@transferwise/components 0.0.0-experimental-8b2286f → 0.0.0-experimental-1fefde6
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/expressiveMoneyInput/amountInput/AmountInput.js +1 -1
- package/build/expressiveMoneyInput/amountInput/AmountInput.js.map +1 -1
- package/build/expressiveMoneyInput/amountInput/AmountInput.mjs +1 -1
- package/build/expressiveMoneyInput/amountInput/AmountInput.mjs.map +1 -1
- package/build/main.css +1 -17
- package/build/styles/css/neptune.css +1 -15
- package/build/styles/expressiveMoneyInput/ExpressiveMoneyInput.css +0 -2
- package/build/styles/expressiveMoneyInput/amountInput/AmountInput.css +0 -2
- package/build/styles/main.css +1 -17
- package/build/styles/styles/less/neptune.css +1 -15
- package/package.json +4 -4
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.css +0 -2
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.test.story.tsx +0 -43
- package/src/expressiveMoneyInput/amountInput/AmountInput.css +0 -2
- package/src/expressiveMoneyInput/amountInput/AmountInput.less +0 -2
- package/src/expressiveMoneyInput/amountInput/AmountInput.tsx +1 -1
- package/src/main.css +1 -17
- package/src/styles/less/core/_typography.less +6 -28
- package/src/styles/less/neptune.css +1 -15
|
@@ -225,7 +225,7 @@ const AmountInput = ({
|
|
|
225
225
|
return /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
226
226
|
className: "wds-amount-input-container",
|
|
227
227
|
children: /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
228
|
-
className: clsx.clsx('wds-amount-input-input-container', 'np-text-display-large
|
|
228
|
+
className: clsx.clsx('wds-amount-input-input-container', 'np-text-display-large'),
|
|
229
229
|
style: style,
|
|
230
230
|
children: [/*#__PURE__*/jsxRuntime.jsx("input", {
|
|
231
231
|
ref: ref,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AmountInput.js","sources":["../../../src/expressiveMoneyInput/amountInput/AmountInput.tsx"],"sourcesContent":["import { formatAmount } from '@transferwise/formatting';\nimport { clsx } from 'clsx';\nimport { AnimatePresence } from 'framer-motion';\nimport { type ChangeEvent, type KeyboardEvent, useEffect, useMemo, useRef, useState } from 'react';\nimport { useIntl } from 'react-intl';\n\nimport { Props as ExpressiveMoneyInputProps } from '../ExpressiveMoneyInput';\nimport { AnimatedNumber } from '../animatedNumber/AnimatedNumber';\nimport { useFocus } from '../hooks/useFocus';\nimport { useInputStyle } from '../hooks/useInputStyle';\nimport {\n getDecimalCount,\n getDecimalSeparator,\n getEnteredDecimalsCount,\n getFormattedString,\n getGroupSeparator,\n getUnformattedNumber,\n isAllowedInputKey,\n isInputPossiblyOverflowing,\n} from './utils';\n\ntype Props = {\n id: string;\n describedById?: string;\n amount?: number | null;\n currency: string;\n autoFocus?: boolean;\n onChange: (amount: number | null) => void;\n onFocusChange?: (focused: boolean) => void;\n} & Pick<ExpressiveMoneyInputProps, 'loading'>;\n\nexport const AmountInput = ({\n id,\n describedById,\n amount,\n currency,\n autoFocus,\n onChange,\n onFocusChange,\n loading,\n}: Props) => {\n const intl = useIntl();\n const { focus, setFocus, visualFocus, setVisualFocus } = useFocus();\n\n const [value, setValue] = useState<string>(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n const numericValue = useMemo(() => {\n return getUnformattedNumber({\n value,\n currency,\n locale: intl.locale,\n });\n }, [value, currency, intl.locale]);\n\n const valueWithFullDecimals = useMemo(() => {\n return getFormattedString({\n value: numericValue ?? 0,\n currency,\n locale: intl.locale,\n alwaysShowDecimals: true,\n });\n }, [numericValue, currency, intl.locale]);\n\n const ref = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (autoFocus) {\n ref.current?.focus();\n }\n }, []);\n\n const placeholder = getPlaceholder(currency, intl.locale);\n const groupSeparator = getGroupSeparator(currency, intl.locale);\n const decimalSeparator = getDecimalSeparator(currency, intl.locale);\n const maxDecimalCount = getDecimalCount(currency, intl.locale);\n\n const decimalPart = getDecimalPart(value, decimalSeparator);\n const decimalMode = decimalSeparator && value.includes(decimalSeparator);\n\n useEffect(() => {\n if (!focus) {\n setValue(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [amount]);\n\n useEffect(() => {\n onFocusChange?.(visualFocus);\n }, [visualFocus]);\n\n const shouldReformatAfterUserInput = (newValue: string) => {\n // don't reformat if formatting would wipe out user's input\n if (reformatValue(newValue) === '') {\n return false;\n }\n\n const endsWithDecimalSeparator = decimalSeparator && newValue.endsWith(decimalSeparator);\n const endsWithGroupSeparator = groupSeparator && newValue.endsWith(groupSeparator);\n\n // if the user has entered a seperator to the end, formatting would delete it\n if (endsWithDecimalSeparator || endsWithGroupSeparator) {\n return false;\n }\n\n const containsDecimalSeparator = decimalSeparator && newValue.includes(decimalSeparator);\n\n if (containsDecimalSeparator) {\n const enteredDecimalsCount = getEnteredDecimalsCount(newValue, decimalSeparator);\n // don't reformat until user has entered all the allowed decimals\n // for example, we don't want 1.1 to be reformatted to 1.10 immediately\n if (enteredDecimalsCount < maxDecimalCount) {\n return false;\n }\n }\n\n return true;\n };\n\n const reformatValue = (newValue: string) => {\n const unformattedValue = getUnformattedNumber({\n value: newValue,\n currency,\n locale: intl.locale,\n });\n const formattedValue = unformattedValue\n ? getFormattedString({\n value: unformattedValue,\n currency,\n locale: intl.locale,\n })\n : '';\n return formattedValue;\n };\n\n const handleChange = (newValue: string) => {\n const oldCursorPosition = ref.current?.selectionStart ?? 0;\n\n const newFormattedString = shouldReformatAfterUserInput(newValue)\n ? reformatValue(newValue)\n : newValue;\n setValue(newFormattedString);\n\n const newNumber = getUnformattedNumber({\n value: newFormattedString,\n currency,\n locale: intl.locale,\n });\n\n if (newNumber !== numericValue) {\n if (numericValue || newNumber) {\n onChange(newNumber);\n }\n }\n\n const newCursorPosition = oldCursorPosition + (newFormattedString.length - newValue.length);\n requestAnimationFrame(() => {\n ref?.current?.setSelectionRange(newCursorPosition, newCursorPosition);\n });\n };\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n\n const clipboardData = e.clipboardData?.getData('text/plain');\n if (!clipboardData) {\n return;\n }\n\n // need to sanitise the pasted value otherwise other validation logic will ignore the input entirely\n const sanitisedValue = reformatValue(clipboardData);\n\n handleChange(sanitisedValue);\n };\n\n const handleBlur = () => {\n setFocus(false);\n setValue(reformatValue(value));\n };\n\n const handleBackspace = (e: KeyboardEvent<HTMLInputElement>) => {\n const input = e.target as HTMLInputElement;\n // using the updated selection range after the backspace key has been processed, instead of the current selection range in state\n const { value: currentValue, selectionStart, selectionEnd } = input;\n\n if (selectionStart === selectionEnd && selectionStart && selectionStart > 0) {\n const charBeforeCursor = currentValue[selectionStart - 1];\n\n // if the user deletes a thousands separator, remove the digit before it as well\n if (charBeforeCursor === groupSeparator) {\n e.preventDefault();\n const beforeCursor = currentValue.slice(0, selectionStart - 2);\n const afterCursor = currentValue.slice(selectionStart);\n const newValue = `${beforeCursor}${afterCursor}`;\n input.setSelectionRange(beforeCursor.length, beforeCursor.length);\n handleChange(newValue);\n }\n }\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n setFocus(true);\n if (!isAllowedInputKey(e)) {\n e.preventDefault();\n }\n\n if (e.key === 'Backspace') {\n handleBackspace(e);\n }\n };\n\n const isAllowedInput = (e: ChangeEvent<HTMLInputElement>) => {\n const hasMultipleDecimalSeparators =\n decimalSeparator && e.target.value.split(decimalSeparator).length > 2;\n if (hasMultipleDecimalSeparators) {\n return false;\n }\n\n const newNumericValue = getUnformattedNumber({\n value: e.target.value,\n currency,\n locale: intl.locale,\n });\n const maxLength = Number.MAX_SAFE_INTEGER.toString().length;\n if (String(newNumericValue).length > maxLength) {\n return false;\n }\n\n return true;\n };\n\n const addonContent = useMemo((): string | null | undefined => {\n // because we're using a separate \"addon\" element for the placeholder decimals, there is a possibility that the input itself will become scrollable\n // and the decimals will appear on top of the input. Safest thing to do is to just hide the addon if there is not enough room\n if (isInputPossiblyOverflowing({ ref, value })) {\n return null;\n }\n if (!decimalSeparator || !value) {\n return null;\n }\n\n // if the user has typed a decimal separator, show the full decimal part as a placeholder\n // this returns a string even if there is no content, typing should replace the placeholder immediately without animation\n // otherwise there is an ugly animation when going from 1.23 to 1.2 due to AnimatePresence\n if (focus && decimalMode) {\n // reuse getDecimalPart\n const fullDecimalPart = getDecimalPart(valueWithFullDecimals, decimalSeparator);\n // show only the characters that are not already displayed by the input\n return fullDecimalPart?.slice(decimalPart?.length);\n }\n\n // in unfocused state, always show the full decimal part unless the user has already entered decimals\n if (!focus && !decimalMode) {\n const [_, decimalPlaceholder] = placeholder.split(decimalSeparator);\n return decimalSeparator + decimalPlaceholder;\n }\n\n return null;\n }, [\n decimalMode,\n decimalPart?.length,\n decimalSeparator,\n focus,\n placeholder,\n value,\n valueWithFullDecimals,\n ]);\n\n const style = useInputStyle({\n // whenever decimals are shown, we need to account for the full decimal part for the font size calculation\n value: addonContent ? valueWithFullDecimals : value,\n focus: visualFocus,\n inputElement: ref.current,\n loading,\n });\n\n return (\n <div className=\"wds-amount-input-container\">\n <div\n className={clsx('wds-amount-input-input-container', 'np-text-display-large--forced')}\n style={style}\n >\n <input\n ref={ref}\n className=\"wds-amount-input-input\"\n id={id}\n autoComplete=\"off\"\n inputMode=\"decimal\"\n value={value}\n type=\"text\"\n placeholder={placeholder}\n aria-describedby={describedById}\n /* without this, the input tries to keep an aspect ratio and doesn't respect CSS width rules */\n size={1}\n onChange={(e) => {\n if (isAllowedInput(e)) {\n handleChange(e.target.value);\n }\n }}\n onBlurCapture={() => handleBlur()}\n onPaste={(e) => handlePaste(e)}\n onFocus={() => {\n setFocus(true);\n }}\n onBlur={() => {\n setTimeout(() => setVisualFocus(false), 30);\n }}\n onKeyDown={(e) => handleKeyDown(e)}\n />\n <AnimatePresence initial={false}>\n {addonContent !== null && (\n <AnimatedNumber\n className={clsx(\n 'wds-amount-input-placeholder',\n visualFocus && 'wds-amount-input-placeholder-focus',\n )}\n onClick={() => ref.current?.focus()}\n >\n {addonContent}\n </AnimatedNumber>\n )}\n </AnimatePresence>\n </div>\n </div>\n );\n};\n\nconst getPlaceholder = (currency: string, locale: string) => {\n return formatAmount(0, currency, locale, { alwaysShowDecimals: true });\n};\n\nconst getDecimalPart = (value: string, decimalSeparator: string | null) => {\n if (!value || !decimalSeparator) {\n return undefined;\n }\n\n const [_, decimalPart] = value.split(decimalSeparator);\n return decimalPart ?? undefined;\n};\n"],"names":["AmountInput","id","describedById","amount","currency","autoFocus","onChange","onFocusChange","loading","intl","useIntl","focus","setFocus","visualFocus","setVisualFocus","useFocus","value","setValue","useState","getFormattedString","locale","numericValue","useMemo","getUnformattedNumber","valueWithFullDecimals","alwaysShowDecimals","ref","useRef","useEffect","current","placeholder","getPlaceholder","groupSeparator","getGroupSeparator","decimalSeparator","getDecimalSeparator","maxDecimalCount","getDecimalCount","decimalPart","getDecimalPart","decimalMode","includes","shouldReformatAfterUserInput","newValue","reformatValue","endsWithDecimalSeparator","endsWith","endsWithGroupSeparator","containsDecimalSeparator","enteredDecimalsCount","getEnteredDecimalsCount","unformattedValue","formattedValue","handleChange","oldCursorPosition","selectionStart","newFormattedString","newNumber","newCursorPosition","length","requestAnimationFrame","setSelectionRange","handlePaste","e","preventDefault","clipboardData","getData","sanitisedValue","handleBlur","handleBackspace","input","target","currentValue","selectionEnd","charBeforeCursor","beforeCursor","slice","afterCursor","handleKeyDown","isAllowedInputKey","key","isAllowedInput","hasMultipleDecimalSeparators","split","newNumericValue","maxLength","Number","MAX_SAFE_INTEGER","toString","String","addonContent","isInputPossiblyOverflowing","fullDecimalPart","_","decimalPlaceholder","style","useInputStyle","inputElement","_jsx","className","children","_jsxs","clsx","autoComplete","inputMode","type","size","onBlurCapture","onPaste","onFocus","onBlur","setTimeout","onKeyDown","AnimatePresence","initial","AnimatedNumber","onClick","formatAmount","undefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AmountInput.js","sources":["../../../src/expressiveMoneyInput/amountInput/AmountInput.tsx"],"sourcesContent":["import { formatAmount } from '@transferwise/formatting';\nimport { clsx } from 'clsx';\nimport { AnimatePresence } from 'framer-motion';\nimport { type ChangeEvent, type KeyboardEvent, useEffect, useMemo, useRef, useState } from 'react';\nimport { useIntl } from 'react-intl';\n\nimport { Props as ExpressiveMoneyInputProps } from '../ExpressiveMoneyInput';\nimport { AnimatedNumber } from '../animatedNumber/AnimatedNumber';\nimport { useFocus } from '../hooks/useFocus';\nimport { useInputStyle } from '../hooks/useInputStyle';\nimport {\n getDecimalCount,\n getDecimalSeparator,\n getEnteredDecimalsCount,\n getFormattedString,\n getGroupSeparator,\n getUnformattedNumber,\n isAllowedInputKey,\n isInputPossiblyOverflowing,\n} from './utils';\n\ntype Props = {\n id: string;\n describedById?: string;\n amount?: number | null;\n currency: string;\n autoFocus?: boolean;\n onChange: (amount: number | null) => void;\n onFocusChange?: (focused: boolean) => void;\n} & Pick<ExpressiveMoneyInputProps, 'loading'>;\n\nexport const AmountInput = ({\n id,\n describedById,\n amount,\n currency,\n autoFocus,\n onChange,\n onFocusChange,\n loading,\n}: Props) => {\n const intl = useIntl();\n const { focus, setFocus, visualFocus, setVisualFocus } = useFocus();\n\n const [value, setValue] = useState<string>(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n const numericValue = useMemo(() => {\n return getUnformattedNumber({\n value,\n currency,\n locale: intl.locale,\n });\n }, [value, currency, intl.locale]);\n\n const valueWithFullDecimals = useMemo(() => {\n return getFormattedString({\n value: numericValue ?? 0,\n currency,\n locale: intl.locale,\n alwaysShowDecimals: true,\n });\n }, [numericValue, currency, intl.locale]);\n\n const ref = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (autoFocus) {\n ref.current?.focus();\n }\n }, []);\n\n const placeholder = getPlaceholder(currency, intl.locale);\n const groupSeparator = getGroupSeparator(currency, intl.locale);\n const decimalSeparator = getDecimalSeparator(currency, intl.locale);\n const maxDecimalCount = getDecimalCount(currency, intl.locale);\n\n const decimalPart = getDecimalPart(value, decimalSeparator);\n const decimalMode = decimalSeparator && value.includes(decimalSeparator);\n\n useEffect(() => {\n if (!focus) {\n setValue(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [amount]);\n\n useEffect(() => {\n onFocusChange?.(visualFocus);\n }, [visualFocus]);\n\n const shouldReformatAfterUserInput = (newValue: string) => {\n // don't reformat if formatting would wipe out user's input\n if (reformatValue(newValue) === '') {\n return false;\n }\n\n const endsWithDecimalSeparator = decimalSeparator && newValue.endsWith(decimalSeparator);\n const endsWithGroupSeparator = groupSeparator && newValue.endsWith(groupSeparator);\n\n // if the user has entered a seperator to the end, formatting would delete it\n if (endsWithDecimalSeparator || endsWithGroupSeparator) {\n return false;\n }\n\n const containsDecimalSeparator = decimalSeparator && newValue.includes(decimalSeparator);\n\n if (containsDecimalSeparator) {\n const enteredDecimalsCount = getEnteredDecimalsCount(newValue, decimalSeparator);\n // don't reformat until user has entered all the allowed decimals\n // for example, we don't want 1.1 to be reformatted to 1.10 immediately\n if (enteredDecimalsCount < maxDecimalCount) {\n return false;\n }\n }\n\n return true;\n };\n\n const reformatValue = (newValue: string) => {\n const unformattedValue = getUnformattedNumber({\n value: newValue,\n currency,\n locale: intl.locale,\n });\n const formattedValue = unformattedValue\n ? getFormattedString({\n value: unformattedValue,\n currency,\n locale: intl.locale,\n })\n : '';\n return formattedValue;\n };\n\n const handleChange = (newValue: string) => {\n const oldCursorPosition = ref.current?.selectionStart ?? 0;\n\n const newFormattedString = shouldReformatAfterUserInput(newValue)\n ? reformatValue(newValue)\n : newValue;\n setValue(newFormattedString);\n\n const newNumber = getUnformattedNumber({\n value: newFormattedString,\n currency,\n locale: intl.locale,\n });\n\n if (newNumber !== numericValue) {\n if (numericValue || newNumber) {\n onChange(newNumber);\n }\n }\n\n const newCursorPosition = oldCursorPosition + (newFormattedString.length - newValue.length);\n requestAnimationFrame(() => {\n ref?.current?.setSelectionRange(newCursorPosition, newCursorPosition);\n });\n };\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n\n const clipboardData = e.clipboardData?.getData('text/plain');\n if (!clipboardData) {\n return;\n }\n\n // need to sanitise the pasted value otherwise other validation logic will ignore the input entirely\n const sanitisedValue = reformatValue(clipboardData);\n\n handleChange(sanitisedValue);\n };\n\n const handleBlur = () => {\n setFocus(false);\n setValue(reformatValue(value));\n };\n\n const handleBackspace = (e: KeyboardEvent<HTMLInputElement>) => {\n const input = e.target as HTMLInputElement;\n // using the updated selection range after the backspace key has been processed, instead of the current selection range in state\n const { value: currentValue, selectionStart, selectionEnd } = input;\n\n if (selectionStart === selectionEnd && selectionStart && selectionStart > 0) {\n const charBeforeCursor = currentValue[selectionStart - 1];\n\n // if the user deletes a thousands separator, remove the digit before it as well\n if (charBeforeCursor === groupSeparator) {\n e.preventDefault();\n const beforeCursor = currentValue.slice(0, selectionStart - 2);\n const afterCursor = currentValue.slice(selectionStart);\n const newValue = `${beforeCursor}${afterCursor}`;\n input.setSelectionRange(beforeCursor.length, beforeCursor.length);\n handleChange(newValue);\n }\n }\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n setFocus(true);\n if (!isAllowedInputKey(e)) {\n e.preventDefault();\n }\n\n if (e.key === 'Backspace') {\n handleBackspace(e);\n }\n };\n\n const isAllowedInput = (e: ChangeEvent<HTMLInputElement>) => {\n const hasMultipleDecimalSeparators =\n decimalSeparator && e.target.value.split(decimalSeparator).length > 2;\n if (hasMultipleDecimalSeparators) {\n return false;\n }\n\n const newNumericValue = getUnformattedNumber({\n value: e.target.value,\n currency,\n locale: intl.locale,\n });\n const maxLength = Number.MAX_SAFE_INTEGER.toString().length;\n if (String(newNumericValue).length > maxLength) {\n return false;\n }\n\n return true;\n };\n\n const addonContent = useMemo((): string | null | undefined => {\n // because we're using a separate \"addon\" element for the placeholder decimals, there is a possibility that the input itself will become scrollable\n // and the decimals will appear on top of the input. Safest thing to do is to just hide the addon if there is not enough room\n if (isInputPossiblyOverflowing({ ref, value })) {\n return null;\n }\n if (!decimalSeparator || !value) {\n return null;\n }\n\n // if the user has typed a decimal separator, show the full decimal part as a placeholder\n // this returns a string even if there is no content, typing should replace the placeholder immediately without animation\n // otherwise there is an ugly animation when going from 1.23 to 1.2 due to AnimatePresence\n if (focus && decimalMode) {\n // reuse getDecimalPart\n const fullDecimalPart = getDecimalPart(valueWithFullDecimals, decimalSeparator);\n // show only the characters that are not already displayed by the input\n return fullDecimalPart?.slice(decimalPart?.length);\n }\n\n // in unfocused state, always show the full decimal part unless the user has already entered decimals\n if (!focus && !decimalMode) {\n const [_, decimalPlaceholder] = placeholder.split(decimalSeparator);\n return decimalSeparator + decimalPlaceholder;\n }\n\n return null;\n }, [\n decimalMode,\n decimalPart?.length,\n decimalSeparator,\n focus,\n placeholder,\n value,\n valueWithFullDecimals,\n ]);\n\n const style = useInputStyle({\n // whenever decimals are shown, we need to account for the full decimal part for the font size calculation\n value: addonContent ? valueWithFullDecimals : value,\n focus: visualFocus,\n inputElement: ref.current,\n loading,\n });\n\n return (\n <div className=\"wds-amount-input-container\">\n <div\n className={clsx('wds-amount-input-input-container', 'np-text-display-large')}\n style={style}\n >\n <input\n ref={ref}\n className=\"wds-amount-input-input\"\n id={id}\n autoComplete=\"off\"\n inputMode=\"decimal\"\n value={value}\n type=\"text\"\n placeholder={placeholder}\n aria-describedby={describedById}\n /* without this, the input tries to keep an aspect ratio and doesn't respect CSS width rules */\n size={1}\n onChange={(e) => {\n if (isAllowedInput(e)) {\n handleChange(e.target.value);\n }\n }}\n onBlurCapture={() => handleBlur()}\n onPaste={(e) => handlePaste(e)}\n onFocus={() => {\n setFocus(true);\n }}\n onBlur={() => {\n setTimeout(() => setVisualFocus(false), 30);\n }}\n onKeyDown={(e) => handleKeyDown(e)}\n />\n <AnimatePresence initial={false}>\n {addonContent !== null && (\n <AnimatedNumber\n className={clsx(\n 'wds-amount-input-placeholder',\n visualFocus && 'wds-amount-input-placeholder-focus',\n )}\n onClick={() => ref.current?.focus()}\n >\n {addonContent}\n </AnimatedNumber>\n )}\n </AnimatePresence>\n </div>\n </div>\n );\n};\n\nconst getPlaceholder = (currency: string, locale: string) => {\n return formatAmount(0, currency, locale, { alwaysShowDecimals: true });\n};\n\nconst getDecimalPart = (value: string, decimalSeparator: string | null) => {\n if (!value || !decimalSeparator) {\n return undefined;\n }\n\n const [_, decimalPart] = value.split(decimalSeparator);\n return decimalPart ?? undefined;\n};\n"],"names":["AmountInput","id","describedById","amount","currency","autoFocus","onChange","onFocusChange","loading","intl","useIntl","focus","setFocus","visualFocus","setVisualFocus","useFocus","value","setValue","useState","getFormattedString","locale","numericValue","useMemo","getUnformattedNumber","valueWithFullDecimals","alwaysShowDecimals","ref","useRef","useEffect","current","placeholder","getPlaceholder","groupSeparator","getGroupSeparator","decimalSeparator","getDecimalSeparator","maxDecimalCount","getDecimalCount","decimalPart","getDecimalPart","decimalMode","includes","shouldReformatAfterUserInput","newValue","reformatValue","endsWithDecimalSeparator","endsWith","endsWithGroupSeparator","containsDecimalSeparator","enteredDecimalsCount","getEnteredDecimalsCount","unformattedValue","formattedValue","handleChange","oldCursorPosition","selectionStart","newFormattedString","newNumber","newCursorPosition","length","requestAnimationFrame","setSelectionRange","handlePaste","e","preventDefault","clipboardData","getData","sanitisedValue","handleBlur","handleBackspace","input","target","currentValue","selectionEnd","charBeforeCursor","beforeCursor","slice","afterCursor","handleKeyDown","isAllowedInputKey","key","isAllowedInput","hasMultipleDecimalSeparators","split","newNumericValue","maxLength","Number","MAX_SAFE_INTEGER","toString","String","addonContent","isInputPossiblyOverflowing","fullDecimalPart","_","decimalPlaceholder","style","useInputStyle","inputElement","_jsx","className","children","_jsxs","clsx","autoComplete","inputMode","type","size","onBlurCapture","onPaste","onFocus","onBlur","setTimeout","onKeyDown","AnimatePresence","initial","AnimatedNumber","onClick","formatAmount","undefined"],"mappings":"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"}
|
|
@@ -223,7 +223,7 @@ const AmountInput = ({
|
|
|
223
223
|
return /*#__PURE__*/jsx("div", {
|
|
224
224
|
className: "wds-amount-input-container",
|
|
225
225
|
children: /*#__PURE__*/jsxs("div", {
|
|
226
|
-
className: clsx('wds-amount-input-input-container', 'np-text-display-large
|
|
226
|
+
className: clsx('wds-amount-input-input-container', 'np-text-display-large'),
|
|
227
227
|
style: style,
|
|
228
228
|
children: [/*#__PURE__*/jsx("input", {
|
|
229
229
|
ref: ref,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AmountInput.mjs","sources":["../../../src/expressiveMoneyInput/amountInput/AmountInput.tsx"],"sourcesContent":["import { formatAmount } from '@transferwise/formatting';\nimport { clsx } from 'clsx';\nimport { AnimatePresence } from 'framer-motion';\nimport { type ChangeEvent, type KeyboardEvent, useEffect, useMemo, useRef, useState } from 'react';\nimport { useIntl } from 'react-intl';\n\nimport { Props as ExpressiveMoneyInputProps } from '../ExpressiveMoneyInput';\nimport { AnimatedNumber } from '../animatedNumber/AnimatedNumber';\nimport { useFocus } from '../hooks/useFocus';\nimport { useInputStyle } from '../hooks/useInputStyle';\nimport {\n getDecimalCount,\n getDecimalSeparator,\n getEnteredDecimalsCount,\n getFormattedString,\n getGroupSeparator,\n getUnformattedNumber,\n isAllowedInputKey,\n isInputPossiblyOverflowing,\n} from './utils';\n\ntype Props = {\n id: string;\n describedById?: string;\n amount?: number | null;\n currency: string;\n autoFocus?: boolean;\n onChange: (amount: number | null) => void;\n onFocusChange?: (focused: boolean) => void;\n} & Pick<ExpressiveMoneyInputProps, 'loading'>;\n\nexport const AmountInput = ({\n id,\n describedById,\n amount,\n currency,\n autoFocus,\n onChange,\n onFocusChange,\n loading,\n}: Props) => {\n const intl = useIntl();\n const { focus, setFocus, visualFocus, setVisualFocus } = useFocus();\n\n const [value, setValue] = useState<string>(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n const numericValue = useMemo(() => {\n return getUnformattedNumber({\n value,\n currency,\n locale: intl.locale,\n });\n }, [value, currency, intl.locale]);\n\n const valueWithFullDecimals = useMemo(() => {\n return getFormattedString({\n value: numericValue ?? 0,\n currency,\n locale: intl.locale,\n alwaysShowDecimals: true,\n });\n }, [numericValue, currency, intl.locale]);\n\n const ref = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (autoFocus) {\n ref.current?.focus();\n }\n }, []);\n\n const placeholder = getPlaceholder(currency, intl.locale);\n const groupSeparator = getGroupSeparator(currency, intl.locale);\n const decimalSeparator = getDecimalSeparator(currency, intl.locale);\n const maxDecimalCount = getDecimalCount(currency, intl.locale);\n\n const decimalPart = getDecimalPart(value, decimalSeparator);\n const decimalMode = decimalSeparator && value.includes(decimalSeparator);\n\n useEffect(() => {\n if (!focus) {\n setValue(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [amount]);\n\n useEffect(() => {\n onFocusChange?.(visualFocus);\n }, [visualFocus]);\n\n const shouldReformatAfterUserInput = (newValue: string) => {\n // don't reformat if formatting would wipe out user's input\n if (reformatValue(newValue) === '') {\n return false;\n }\n\n const endsWithDecimalSeparator = decimalSeparator && newValue.endsWith(decimalSeparator);\n const endsWithGroupSeparator = groupSeparator && newValue.endsWith(groupSeparator);\n\n // if the user has entered a seperator to the end, formatting would delete it\n if (endsWithDecimalSeparator || endsWithGroupSeparator) {\n return false;\n }\n\n const containsDecimalSeparator = decimalSeparator && newValue.includes(decimalSeparator);\n\n if (containsDecimalSeparator) {\n const enteredDecimalsCount = getEnteredDecimalsCount(newValue, decimalSeparator);\n // don't reformat until user has entered all the allowed decimals\n // for example, we don't want 1.1 to be reformatted to 1.10 immediately\n if (enteredDecimalsCount < maxDecimalCount) {\n return false;\n }\n }\n\n return true;\n };\n\n const reformatValue = (newValue: string) => {\n const unformattedValue = getUnformattedNumber({\n value: newValue,\n currency,\n locale: intl.locale,\n });\n const formattedValue = unformattedValue\n ? getFormattedString({\n value: unformattedValue,\n currency,\n locale: intl.locale,\n })\n : '';\n return formattedValue;\n };\n\n const handleChange = (newValue: string) => {\n const oldCursorPosition = ref.current?.selectionStart ?? 0;\n\n const newFormattedString = shouldReformatAfterUserInput(newValue)\n ? reformatValue(newValue)\n : newValue;\n setValue(newFormattedString);\n\n const newNumber = getUnformattedNumber({\n value: newFormattedString,\n currency,\n locale: intl.locale,\n });\n\n if (newNumber !== numericValue) {\n if (numericValue || newNumber) {\n onChange(newNumber);\n }\n }\n\n const newCursorPosition = oldCursorPosition + (newFormattedString.length - newValue.length);\n requestAnimationFrame(() => {\n ref?.current?.setSelectionRange(newCursorPosition, newCursorPosition);\n });\n };\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n\n const clipboardData = e.clipboardData?.getData('text/plain');\n if (!clipboardData) {\n return;\n }\n\n // need to sanitise the pasted value otherwise other validation logic will ignore the input entirely\n const sanitisedValue = reformatValue(clipboardData);\n\n handleChange(sanitisedValue);\n };\n\n const handleBlur = () => {\n setFocus(false);\n setValue(reformatValue(value));\n };\n\n const handleBackspace = (e: KeyboardEvent<HTMLInputElement>) => {\n const input = e.target as HTMLInputElement;\n // using the updated selection range after the backspace key has been processed, instead of the current selection range in state\n const { value: currentValue, selectionStart, selectionEnd } = input;\n\n if (selectionStart === selectionEnd && selectionStart && selectionStart > 0) {\n const charBeforeCursor = currentValue[selectionStart - 1];\n\n // if the user deletes a thousands separator, remove the digit before it as well\n if (charBeforeCursor === groupSeparator) {\n e.preventDefault();\n const beforeCursor = currentValue.slice(0, selectionStart - 2);\n const afterCursor = currentValue.slice(selectionStart);\n const newValue = `${beforeCursor}${afterCursor}`;\n input.setSelectionRange(beforeCursor.length, beforeCursor.length);\n handleChange(newValue);\n }\n }\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n setFocus(true);\n if (!isAllowedInputKey(e)) {\n e.preventDefault();\n }\n\n if (e.key === 'Backspace') {\n handleBackspace(e);\n }\n };\n\n const isAllowedInput = (e: ChangeEvent<HTMLInputElement>) => {\n const hasMultipleDecimalSeparators =\n decimalSeparator && e.target.value.split(decimalSeparator).length > 2;\n if (hasMultipleDecimalSeparators) {\n return false;\n }\n\n const newNumericValue = getUnformattedNumber({\n value: e.target.value,\n currency,\n locale: intl.locale,\n });\n const maxLength = Number.MAX_SAFE_INTEGER.toString().length;\n if (String(newNumericValue).length > maxLength) {\n return false;\n }\n\n return true;\n };\n\n const addonContent = useMemo((): string | null | undefined => {\n // because we're using a separate \"addon\" element for the placeholder decimals, there is a possibility that the input itself will become scrollable\n // and the decimals will appear on top of the input. Safest thing to do is to just hide the addon if there is not enough room\n if (isInputPossiblyOverflowing({ ref, value })) {\n return null;\n }\n if (!decimalSeparator || !value) {\n return null;\n }\n\n // if the user has typed a decimal separator, show the full decimal part as a placeholder\n // this returns a string even if there is no content, typing should replace the placeholder immediately without animation\n // otherwise there is an ugly animation when going from 1.23 to 1.2 due to AnimatePresence\n if (focus && decimalMode) {\n // reuse getDecimalPart\n const fullDecimalPart = getDecimalPart(valueWithFullDecimals, decimalSeparator);\n // show only the characters that are not already displayed by the input\n return fullDecimalPart?.slice(decimalPart?.length);\n }\n\n // in unfocused state, always show the full decimal part unless the user has already entered decimals\n if (!focus && !decimalMode) {\n const [_, decimalPlaceholder] = placeholder.split(decimalSeparator);\n return decimalSeparator + decimalPlaceholder;\n }\n\n return null;\n }, [\n decimalMode,\n decimalPart?.length,\n decimalSeparator,\n focus,\n placeholder,\n value,\n valueWithFullDecimals,\n ]);\n\n const style = useInputStyle({\n // whenever decimals are shown, we need to account for the full decimal part for the font size calculation\n value: addonContent ? valueWithFullDecimals : value,\n focus: visualFocus,\n inputElement: ref.current,\n loading,\n });\n\n return (\n <div className=\"wds-amount-input-container\">\n <div\n className={clsx('wds-amount-input-input-container', 'np-text-display-large--forced')}\n style={style}\n >\n <input\n ref={ref}\n className=\"wds-amount-input-input\"\n id={id}\n autoComplete=\"off\"\n inputMode=\"decimal\"\n value={value}\n type=\"text\"\n placeholder={placeholder}\n aria-describedby={describedById}\n /* without this, the input tries to keep an aspect ratio and doesn't respect CSS width rules */\n size={1}\n onChange={(e) => {\n if (isAllowedInput(e)) {\n handleChange(e.target.value);\n }\n }}\n onBlurCapture={() => handleBlur()}\n onPaste={(e) => handlePaste(e)}\n onFocus={() => {\n setFocus(true);\n }}\n onBlur={() => {\n setTimeout(() => setVisualFocus(false), 30);\n }}\n onKeyDown={(e) => handleKeyDown(e)}\n />\n <AnimatePresence initial={false}>\n {addonContent !== null && (\n <AnimatedNumber\n className={clsx(\n 'wds-amount-input-placeholder',\n visualFocus && 'wds-amount-input-placeholder-focus',\n )}\n onClick={() => ref.current?.focus()}\n >\n {addonContent}\n </AnimatedNumber>\n )}\n </AnimatePresence>\n </div>\n </div>\n );\n};\n\nconst getPlaceholder = (currency: string, locale: string) => {\n return formatAmount(0, currency, locale, { alwaysShowDecimals: true });\n};\n\nconst getDecimalPart = (value: string, decimalSeparator: string | null) => {\n if (!value || !decimalSeparator) {\n return undefined;\n }\n\n const [_, decimalPart] = value.split(decimalSeparator);\n return decimalPart ?? undefined;\n};\n"],"names":["AmountInput","id","describedById","amount","currency","autoFocus","onChange","onFocusChange","loading","intl","useIntl","focus","setFocus","visualFocus","setVisualFocus","useFocus","value","setValue","useState","getFormattedString","locale","numericValue","useMemo","getUnformattedNumber","valueWithFullDecimals","alwaysShowDecimals","ref","useRef","useEffect","current","placeholder","getPlaceholder","groupSeparator","getGroupSeparator","decimalSeparator","getDecimalSeparator","maxDecimalCount","getDecimalCount","decimalPart","getDecimalPart","decimalMode","includes","shouldReformatAfterUserInput","newValue","reformatValue","endsWithDecimalSeparator","endsWith","endsWithGroupSeparator","containsDecimalSeparator","enteredDecimalsCount","getEnteredDecimalsCount","unformattedValue","formattedValue","handleChange","oldCursorPosition","selectionStart","newFormattedString","newNumber","newCursorPosition","length","requestAnimationFrame","setSelectionRange","handlePaste","e","preventDefault","clipboardData","getData","sanitisedValue","handleBlur","handleBackspace","input","target","currentValue","selectionEnd","charBeforeCursor","beforeCursor","slice","afterCursor","handleKeyDown","isAllowedInputKey","key","isAllowedInput","hasMultipleDecimalSeparators","split","newNumericValue","maxLength","Number","MAX_SAFE_INTEGER","toString","String","addonContent","isInputPossiblyOverflowing","fullDecimalPart","_","decimalPlaceholder","style","useInputStyle","inputElement","_jsx","className","children","_jsxs","clsx","autoComplete","inputMode","type","size","onBlurCapture","onPaste","onFocus","onBlur","setTimeout","onKeyDown","AnimatePresence","initial","AnimatedNumber","onClick","formatAmount","undefined"],"mappings":";;;;;;;;;;;AA+BO,MAAMA,WAAW,GAAGA,CAAC;EAC1BC,EAAE;EACFC,aAAa;EACbC,MAAM;EACNC,QAAQ;EACRC,SAAS;EACTC,QAAQ;EACRC,aAAa;AACbC,EAAAA;AAAO,CACD,KAAI;AACV,EAAA,MAAMC,IAAI,GAAGC,OAAO,EAAE;EACtB,MAAM;IAAEC,KAAK;IAAEC,QAAQ;IAAEC,WAAW;AAAEC,IAAAA;GAAgB,GAAGC,QAAQ,EAAE;EAEnE,MAAM,CAACC,KAAK,EAAEC,QAAQ,CAAC,GAAGC,QAAQ,CAChCf,MAAM,GACFgB,kBAAkB,CAAC;AACjBH,IAAAA,KAAK,EAAEb,MAAM;IACbC,QAAQ;IACRgB,MAAM,EAAEX,IAAI,CAACW;GACd,CAAC,GACF,EAAE,CACP;AACD,EAAA,MAAMC,YAAY,GAAGC,OAAO,CAAC,MAAK;AAChC,IAAA,OAAOC,oBAAoB,CAAC;MAC1BP,KAAK;MACLZ,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW;AACd,KAAA,CAAC;EACJ,CAAC,EAAE,CAACJ,KAAK,EAAEZ,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC,CAAC;AAElC,EAAA,MAAMI,qBAAqB,GAAGF,OAAO,CAAC,MAAK;AACzC,IAAA,OAAOH,kBAAkB,CAAC;MACxBH,KAAK,EAAEK,YAAY,IAAI,CAAC;MACxBjB,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW,MAAM;AACnBK,MAAAA,kBAAkB,EAAE;AACrB,KAAA,CAAC;EACJ,CAAC,EAAE,CAACJ,YAAY,EAAEjB,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC,CAAC;AAEzC,EAAA,MAAMM,GAAG,GAAGC,MAAM,CAAmB,IAAI,CAAC;AAE1CC,EAAAA,SAAS,CAAC,MAAK;AACb,IAAA,IAAIvB,SAAS,EAAE;AACbqB,MAAAA,GAAG,CAACG,OAAO,EAAElB,KAAK,EAAE;AACtB,IAAA;EACF,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMmB,WAAW,GAAGC,cAAc,CAAC3B,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC;EACzD,MAAMY,cAAc,GAAGC,iBAAiB,CAAC7B,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC;EAC/D,MAAMc,gBAAgB,GAAGC,mBAAmB,CAAC/B,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC;EACnE,MAAMgB,eAAe,GAAGC,eAAe,CAACjC,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC;AAE9D,EAAA,MAAMkB,WAAW,GAAGC,cAAc,CAACvB,KAAK,EAAEkB,gBAAgB,CAAC;EAC3D,MAAMM,WAAW,GAAGN,gBAAgB,IAAIlB,KAAK,CAACyB,QAAQ,CAACP,gBAAgB,CAAC;AAExEN,EAAAA,SAAS,CAAC,MAAK;IACb,IAAI,CAACjB,KAAK,EAAE;AACVM,MAAAA,QAAQ,CACNd,MAAM,GACFgB,kBAAkB,CAAC;AACjBH,QAAAA,KAAK,EAAEb,MAAM;QACbC,QAAQ;QACRgB,MAAM,EAAEX,IAAI,CAACW;OACd,CAAC,GACF,EAAE,CACP;AACH,IAAA;AACA;AACF,EAAA,CAAC,EAAE,CAACjB,MAAM,CAAC,CAAC;AAEZyB,EAAAA,SAAS,CAAC,MAAK;IACbrB,aAAa,GAAGM,WAAW,CAAC;AAC9B,EAAA,CAAC,EAAE,CAACA,WAAW,CAAC,CAAC;EAEjB,MAAM6B,4BAA4B,GAAIC,QAAgB,IAAI;AACxD;AACA,IAAA,IAAIC,aAAa,CAACD,QAAQ,CAAC,KAAK,EAAE,EAAE;AAClC,MAAA,OAAO,KAAK;AACd,IAAA;IAEA,MAAME,wBAAwB,GAAGX,gBAAgB,IAAIS,QAAQ,CAACG,QAAQ,CAACZ,gBAAgB,CAAC;IACxF,MAAMa,sBAAsB,GAAGf,cAAc,IAAIW,QAAQ,CAACG,QAAQ,CAACd,cAAc,CAAC;AAElF;IACA,IAAIa,wBAAwB,IAAIE,sBAAsB,EAAE;AACtD,MAAA,OAAO,KAAK;AACd,IAAA;IAEA,MAAMC,wBAAwB,GAAGd,gBAAgB,IAAIS,QAAQ,CAACF,QAAQ,CAACP,gBAAgB,CAAC;AAExF,IAAA,IAAIc,wBAAwB,EAAE;AAC5B,MAAA,MAAMC,oBAAoB,GAAGC,uBAAuB,CAACP,QAAQ,EAAET,gBAAgB,CAAC;AAChF;AACA;MACA,IAAIe,oBAAoB,GAAGb,eAAe,EAAE;AAC1C,QAAA,OAAO,KAAK;AACd,MAAA;AACF,IAAA;AAEA,IAAA,OAAO,IAAI;EACb,CAAC;EAED,MAAMQ,aAAa,GAAID,QAAgB,IAAI;IACzC,MAAMQ,gBAAgB,GAAG5B,oBAAoB,CAAC;AAC5CP,MAAAA,KAAK,EAAE2B,QAAQ;MACfvC,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW;AACd,KAAA,CAAC;AACF,IAAA,MAAMgC,cAAc,GAAGD,gBAAgB,GACnChC,kBAAkB,CAAC;AACjBH,MAAAA,KAAK,EAAEmC,gBAAgB;MACvB/C,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW;KACd,CAAC,GACF,EAAE;AACN,IAAA,OAAOgC,cAAc;EACvB,CAAC;EAED,MAAMC,YAAY,GAAIV,QAAgB,IAAI;IACxC,MAAMW,iBAAiB,GAAG5B,GAAG,CAACG,OAAO,EAAE0B,cAAc,IAAI,CAAC;AAE1D,IAAA,MAAMC,kBAAkB,GAAGd,4BAA4B,CAACC,QAAQ,CAAC,GAC7DC,aAAa,CAACD,QAAQ,CAAC,GACvBA,QAAQ;IACZ1B,QAAQ,CAACuC,kBAAkB,CAAC;IAE5B,MAAMC,SAAS,GAAGlC,oBAAoB,CAAC;AACrCP,MAAAA,KAAK,EAAEwC,kBAAkB;MACzBpD,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW;AACd,KAAA,CAAC;IAEF,IAAIqC,SAAS,KAAKpC,YAAY,EAAE;MAC9B,IAAIA,YAAY,IAAIoC,SAAS,EAAE;QAC7BnD,QAAQ,CAACmD,SAAS,CAAC;AACrB,MAAA;AACF,IAAA;IAEA,MAAMC,iBAAiB,GAAGJ,iBAAiB,IAAIE,kBAAkB,CAACG,MAAM,GAAGhB,QAAQ,CAACgB,MAAM,CAAC;AAC3FC,IAAAA,qBAAqB,CAAC,MAAK;MACzBlC,GAAG,EAAEG,OAAO,EAAEgC,iBAAiB,CAACH,iBAAiB,EAAEA,iBAAiB,CAAC;AACvE,IAAA,CAAC,CAAC;EACJ,CAAC;EAED,MAAMI,WAAW,GAAIC,CAAyC,IAAI;IAChEA,CAAC,CAACC,cAAc,EAAE;IAElB,MAAMC,aAAa,GAAGF,CAAC,CAACE,aAAa,EAAEC,OAAO,CAAC,YAAY,CAAC;IAC5D,IAAI,CAACD,aAAa,EAAE;AAClB,MAAA;AACF,IAAA;AAEA;AACA,IAAA,MAAME,cAAc,GAAGvB,aAAa,CAACqB,aAAa,CAAC;IAEnDZ,YAAY,CAACc,cAAc,CAAC;EAC9B,CAAC;EAED,MAAMC,UAAU,GAAGA,MAAK;IACtBxD,QAAQ,CAAC,KAAK,CAAC;AACfK,IAAAA,QAAQ,CAAC2B,aAAa,CAAC5B,KAAK,CAAC,CAAC;EAChC,CAAC;EAED,MAAMqD,eAAe,GAAIN,CAAkC,IAAI;AAC7D,IAAA,MAAMO,KAAK,GAAGP,CAAC,CAACQ,MAA0B;AAC1C;IACA,MAAM;AAAEvD,MAAAA,KAAK,EAAEwD,YAAY;MAAEjB,cAAc;AAAEkB,MAAAA;AAAY,KAAE,GAAGH,KAAK;IAEnE,IAAIf,cAAc,KAAKkB,YAAY,IAAIlB,cAAc,IAAIA,cAAc,GAAG,CAAC,EAAE;AAC3E,MAAA,MAAMmB,gBAAgB,GAAGF,YAAY,CAACjB,cAAc,GAAG,CAAC,CAAC;AAEzD;MACA,IAAImB,gBAAgB,KAAK1C,cAAc,EAAE;QACvC+B,CAAC,CAACC,cAAc,EAAE;QAClB,MAAMW,YAAY,GAAGH,YAAY,CAACI,KAAK,CAAC,CAAC,EAAErB,cAAc,GAAG,CAAC,CAAC;AAC9D,QAAA,MAAMsB,WAAW,GAAGL,YAAY,CAACI,KAAK,CAACrB,cAAc,CAAC;AACtD,QAAA,MAAMZ,QAAQ,GAAG,CAAA,EAAGgC,YAAY,CAAA,EAAGE,WAAW,CAAA,CAAE;QAChDP,KAAK,CAACT,iBAAiB,CAACc,YAAY,CAAChB,MAAM,EAAEgB,YAAY,CAAChB,MAAM,CAAC;QACjEN,YAAY,CAACV,QAAQ,CAAC;AACxB,MAAA;AACF,IAAA;EACF,CAAC;EAED,MAAMmC,aAAa,GAAIf,CAAkC,IAAI;IAC3DnD,QAAQ,CAAC,IAAI,CAAC;AACd,IAAA,IAAI,CAACmE,iBAAiB,CAAChB,CAAC,CAAC,EAAE;MACzBA,CAAC,CAACC,cAAc,EAAE;AACpB,IAAA;AAEA,IAAA,IAAID,CAAC,CAACiB,GAAG,KAAK,WAAW,EAAE;MACzBX,eAAe,CAACN,CAAC,CAAC;AACpB,IAAA;EACF,CAAC;EAED,MAAMkB,cAAc,GAAIlB,CAAgC,IAAI;AAC1D,IAAA,MAAMmB,4BAA4B,GAChChD,gBAAgB,IAAI6B,CAAC,CAACQ,MAAM,CAACvD,KAAK,CAACmE,KAAK,CAACjD,gBAAgB,CAAC,CAACyB,MAAM,GAAG,CAAC;AACvE,IAAA,IAAIuB,4BAA4B,EAAE;AAChC,MAAA,OAAO,KAAK;AACd,IAAA;IAEA,MAAME,eAAe,GAAG7D,oBAAoB,CAAC;AAC3CP,MAAAA,KAAK,EAAE+C,CAAC,CAACQ,MAAM,CAACvD,KAAK;MACrBZ,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW;AACd,KAAA,CAAC;IACF,MAAMiE,SAAS,GAAGC,MAAM,CAACC,gBAAgB,CAACC,QAAQ,EAAE,CAAC7B,MAAM;IAC3D,IAAI8B,MAAM,CAACL,eAAe,CAAC,CAACzB,MAAM,GAAG0B,SAAS,EAAE;AAC9C,MAAA,OAAO,KAAK;AACd,IAAA;AAEA,IAAA,OAAO,IAAI;EACb,CAAC;AAED,EAAA,MAAMK,YAAY,GAAGpE,OAAO,CAAC,MAAgC;AAC3D;AACA;AACA,IAAA,IAAIqE,0BAA0B,CAAC;MAAEjE,GAAG;AAAEV,MAAAA;AAAK,KAAE,CAAC,EAAE;AAC9C,MAAA,OAAO,IAAI;AACb,IAAA;AACA,IAAA,IAAI,CAACkB,gBAAgB,IAAI,CAAClB,KAAK,EAAE;AAC/B,MAAA,OAAO,IAAI;AACb,IAAA;AAEA;AACA;AACA;IACA,IAAIL,KAAK,IAAI6B,WAAW,EAAE;AACxB;AACA,MAAA,MAAMoD,eAAe,GAAGrD,cAAc,CAACf,qBAAqB,EAAEU,gBAAgB,CAAC;AAC/E;AACA,MAAA,OAAO0D,eAAe,EAAEhB,KAAK,CAACtC,WAAW,EAAEqB,MAAM,CAAC;AACpD,IAAA;AAEA;AACA,IAAA,IAAI,CAAChD,KAAK,IAAI,CAAC6B,WAAW,EAAE;MAC1B,MAAM,CAACqD,CAAC,EAAEC,kBAAkB,CAAC,GAAGhE,WAAW,CAACqD,KAAK,CAACjD,gBAAgB,CAAC;MACnE,OAAOA,gBAAgB,GAAG4D,kBAAkB;AAC9C,IAAA;AAEA,IAAA,OAAO,IAAI;AACb,EAAA,CAAC,EAAE,CACDtD,WAAW,EACXF,WAAW,EAAEqB,MAAM,EACnBzB,gBAAgB,EAChBvB,KAAK,EACLmB,WAAW,EACXd,KAAK,EACLQ,qBAAqB,CACtB,CAAC;EAEF,MAAMuE,KAAK,GAAGC,aAAa,CAAC;AAC1B;AACAhF,IAAAA,KAAK,EAAE0E,YAAY,GAAGlE,qBAAqB,GAAGR,KAAK;AACnDL,IAAAA,KAAK,EAAEE,WAAW;IAClBoF,YAAY,EAAEvE,GAAG,CAACG,OAAO;AACzBrB,IAAAA;AACD,GAAA,CAAC;AAEF,EAAA,oBACE0F,GAAA,CAAA,KAAA,EAAA;AAAKC,IAAAA,SAAS,EAAC,4BAA4B;AAAAC,IAAAA,QAAA,eACzCC,IAAA,CAAA,KAAA,EAAA;AACEF,MAAAA,SAAS,EAAEG,IAAI,CAAC,kCAAkC,EAAE,+BAA+B,CAAE;AACrFP,MAAAA,KAAK,EAAEA,KAAM;AAAAK,MAAAA,QAAA,gBAEbF,GAAA,CAAA,OAAA,EAAA;AACExE,QAAAA,GAAG,EAAEA,GAAI;AACTyE,QAAAA,SAAS,EAAC,wBAAwB;AAClClG,QAAAA,EAAE,EAAEA,EAAG;AACPsG,QAAAA,YAAY,EAAC,KAAK;AAClBC,QAAAA,SAAS,EAAC,SAAS;AACnBxF,QAAAA,KAAK,EAAEA,KAAM;AACbyF,QAAAA,IAAI,EAAC,MAAM;AACX3E,QAAAA,WAAW,EAAEA,WAAY;QACzB,kBAAA,EAAkB5B;AAClB;AACAwG,QAAAA,IAAI,EAAE,CAAE;QACRpG,QAAQ,EAAGyD,CAAC,IAAI;AACd,UAAA,IAAIkB,cAAc,CAAClB,CAAC,CAAC,EAAE;AACrBV,YAAAA,YAAY,CAACU,CAAC,CAACQ,MAAM,CAACvD,KAAK,CAAC;AAC9B,UAAA;QACF,CAAE;AACF2F,QAAAA,aAAa,EAAEA,MAAMvC,UAAU,EAAG;AAClCwC,QAAAA,OAAO,EAAG7C,CAAC,IAAKD,WAAW,CAACC,CAAC,CAAE;QAC/B8C,OAAO,EAAEA,MAAK;UACZjG,QAAQ,CAAC,IAAI,CAAC;QAChB,CAAE;QACFkG,MAAM,EAAEA,MAAK;UACXC,UAAU,CAAC,MAAMjG,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QAC7C,CAAE;AACFkG,QAAAA,SAAS,EAAGjD,CAAC,IAAKe,aAAa,CAACf,CAAC;AAAE,OAAA,CAErC,eAAAmC,GAAA,CAACe,eAAe,EAAA;AAACC,QAAAA,OAAO,EAAE,KAAM;AAAAd,QAAAA,QAAA,EAC7BV,YAAY,KAAK,IAAI,iBACpBQ,GAAA,CAACiB,cAAc,EAAA;UACbhB,SAAS,EAAEG,IAAI,CACb,8BAA8B,EAC9BzF,WAAW,IAAI,oCAAoC,CACnD;UACFuG,OAAO,EAAEA,MAAM1F,GAAG,CAACG,OAAO,EAAElB,KAAK,EAAG;AAAAyF,UAAAA,QAAA,EAEnCV;SACa;AACjB,OACc,CACnB;KAAK;AACP,GAAK,CAAC;AAEV;AAEA,MAAM3D,cAAc,GAAGA,CAAC3B,QAAgB,EAAEgB,MAAc,KAAI;AAC1D,EAAA,OAAOiG,YAAY,CAAC,CAAC,EAAEjH,QAAQ,EAAEgB,MAAM,EAAE;AAAEK,IAAAA,kBAAkB,EAAE;AAAI,GAAE,CAAC;AACxE,CAAC;AAED,MAAMc,cAAc,GAAGA,CAACvB,KAAa,EAAEkB,gBAA+B,KAAI;AACxE,EAAA,IAAI,CAAClB,KAAK,IAAI,CAACkB,gBAAgB,EAAE;AAC/B,IAAA,OAAOoF,SAAS;AAClB,EAAA;EAEA,MAAM,CAACzB,CAAC,EAAEvD,WAAW,CAAC,GAAGtB,KAAK,CAACmE,KAAK,CAACjD,gBAAgB,CAAC;EACtD,OAAOI,WAAW,IAAIgF,SAAS;AACjC,CAAC;;;;"}
|
|
1
|
+
{"version":3,"file":"AmountInput.mjs","sources":["../../../src/expressiveMoneyInput/amountInput/AmountInput.tsx"],"sourcesContent":["import { formatAmount } from '@transferwise/formatting';\nimport { clsx } from 'clsx';\nimport { AnimatePresence } from 'framer-motion';\nimport { type ChangeEvent, type KeyboardEvent, useEffect, useMemo, useRef, useState } from 'react';\nimport { useIntl } from 'react-intl';\n\nimport { Props as ExpressiveMoneyInputProps } from '../ExpressiveMoneyInput';\nimport { AnimatedNumber } from '../animatedNumber/AnimatedNumber';\nimport { useFocus } from '../hooks/useFocus';\nimport { useInputStyle } from '../hooks/useInputStyle';\nimport {\n getDecimalCount,\n getDecimalSeparator,\n getEnteredDecimalsCount,\n getFormattedString,\n getGroupSeparator,\n getUnformattedNumber,\n isAllowedInputKey,\n isInputPossiblyOverflowing,\n} from './utils';\n\ntype Props = {\n id: string;\n describedById?: string;\n amount?: number | null;\n currency: string;\n autoFocus?: boolean;\n onChange: (amount: number | null) => void;\n onFocusChange?: (focused: boolean) => void;\n} & Pick<ExpressiveMoneyInputProps, 'loading'>;\n\nexport const AmountInput = ({\n id,\n describedById,\n amount,\n currency,\n autoFocus,\n onChange,\n onFocusChange,\n loading,\n}: Props) => {\n const intl = useIntl();\n const { focus, setFocus, visualFocus, setVisualFocus } = useFocus();\n\n const [value, setValue] = useState<string>(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n const numericValue = useMemo(() => {\n return getUnformattedNumber({\n value,\n currency,\n locale: intl.locale,\n });\n }, [value, currency, intl.locale]);\n\n const valueWithFullDecimals = useMemo(() => {\n return getFormattedString({\n value: numericValue ?? 0,\n currency,\n locale: intl.locale,\n alwaysShowDecimals: true,\n });\n }, [numericValue, currency, intl.locale]);\n\n const ref = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (autoFocus) {\n ref.current?.focus();\n }\n }, []);\n\n const placeholder = getPlaceholder(currency, intl.locale);\n const groupSeparator = getGroupSeparator(currency, intl.locale);\n const decimalSeparator = getDecimalSeparator(currency, intl.locale);\n const maxDecimalCount = getDecimalCount(currency, intl.locale);\n\n const decimalPart = getDecimalPart(value, decimalSeparator);\n const decimalMode = decimalSeparator && value.includes(decimalSeparator);\n\n useEffect(() => {\n if (!focus) {\n setValue(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [amount]);\n\n useEffect(() => {\n onFocusChange?.(visualFocus);\n }, [visualFocus]);\n\n const shouldReformatAfterUserInput = (newValue: string) => {\n // don't reformat if formatting would wipe out user's input\n if (reformatValue(newValue) === '') {\n return false;\n }\n\n const endsWithDecimalSeparator = decimalSeparator && newValue.endsWith(decimalSeparator);\n const endsWithGroupSeparator = groupSeparator && newValue.endsWith(groupSeparator);\n\n // if the user has entered a seperator to the end, formatting would delete it\n if (endsWithDecimalSeparator || endsWithGroupSeparator) {\n return false;\n }\n\n const containsDecimalSeparator = decimalSeparator && newValue.includes(decimalSeparator);\n\n if (containsDecimalSeparator) {\n const enteredDecimalsCount = getEnteredDecimalsCount(newValue, decimalSeparator);\n // don't reformat until user has entered all the allowed decimals\n // for example, we don't want 1.1 to be reformatted to 1.10 immediately\n if (enteredDecimalsCount < maxDecimalCount) {\n return false;\n }\n }\n\n return true;\n };\n\n const reformatValue = (newValue: string) => {\n const unformattedValue = getUnformattedNumber({\n value: newValue,\n currency,\n locale: intl.locale,\n });\n const formattedValue = unformattedValue\n ? getFormattedString({\n value: unformattedValue,\n currency,\n locale: intl.locale,\n })\n : '';\n return formattedValue;\n };\n\n const handleChange = (newValue: string) => {\n const oldCursorPosition = ref.current?.selectionStart ?? 0;\n\n const newFormattedString = shouldReformatAfterUserInput(newValue)\n ? reformatValue(newValue)\n : newValue;\n setValue(newFormattedString);\n\n const newNumber = getUnformattedNumber({\n value: newFormattedString,\n currency,\n locale: intl.locale,\n });\n\n if (newNumber !== numericValue) {\n if (numericValue || newNumber) {\n onChange(newNumber);\n }\n }\n\n const newCursorPosition = oldCursorPosition + (newFormattedString.length - newValue.length);\n requestAnimationFrame(() => {\n ref?.current?.setSelectionRange(newCursorPosition, newCursorPosition);\n });\n };\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n\n const clipboardData = e.clipboardData?.getData('text/plain');\n if (!clipboardData) {\n return;\n }\n\n // need to sanitise the pasted value otherwise other validation logic will ignore the input entirely\n const sanitisedValue = reformatValue(clipboardData);\n\n handleChange(sanitisedValue);\n };\n\n const handleBlur = () => {\n setFocus(false);\n setValue(reformatValue(value));\n };\n\n const handleBackspace = (e: KeyboardEvent<HTMLInputElement>) => {\n const input = e.target as HTMLInputElement;\n // using the updated selection range after the backspace key has been processed, instead of the current selection range in state\n const { value: currentValue, selectionStart, selectionEnd } = input;\n\n if (selectionStart === selectionEnd && selectionStart && selectionStart > 0) {\n const charBeforeCursor = currentValue[selectionStart - 1];\n\n // if the user deletes a thousands separator, remove the digit before it as well\n if (charBeforeCursor === groupSeparator) {\n e.preventDefault();\n const beforeCursor = currentValue.slice(0, selectionStart - 2);\n const afterCursor = currentValue.slice(selectionStart);\n const newValue = `${beforeCursor}${afterCursor}`;\n input.setSelectionRange(beforeCursor.length, beforeCursor.length);\n handleChange(newValue);\n }\n }\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n setFocus(true);\n if (!isAllowedInputKey(e)) {\n e.preventDefault();\n }\n\n if (e.key === 'Backspace') {\n handleBackspace(e);\n }\n };\n\n const isAllowedInput = (e: ChangeEvent<HTMLInputElement>) => {\n const hasMultipleDecimalSeparators =\n decimalSeparator && e.target.value.split(decimalSeparator).length > 2;\n if (hasMultipleDecimalSeparators) {\n return false;\n }\n\n const newNumericValue = getUnformattedNumber({\n value: e.target.value,\n currency,\n locale: intl.locale,\n });\n const maxLength = Number.MAX_SAFE_INTEGER.toString().length;\n if (String(newNumericValue).length > maxLength) {\n return false;\n }\n\n return true;\n };\n\n const addonContent = useMemo((): string | null | undefined => {\n // because we're using a separate \"addon\" element for the placeholder decimals, there is a possibility that the input itself will become scrollable\n // and the decimals will appear on top of the input. Safest thing to do is to just hide the addon if there is not enough room\n if (isInputPossiblyOverflowing({ ref, value })) {\n return null;\n }\n if (!decimalSeparator || !value) {\n return null;\n }\n\n // if the user has typed a decimal separator, show the full decimal part as a placeholder\n // this returns a string even if there is no content, typing should replace the placeholder immediately without animation\n // otherwise there is an ugly animation when going from 1.23 to 1.2 due to AnimatePresence\n if (focus && decimalMode) {\n // reuse getDecimalPart\n const fullDecimalPart = getDecimalPart(valueWithFullDecimals, decimalSeparator);\n // show only the characters that are not already displayed by the input\n return fullDecimalPart?.slice(decimalPart?.length);\n }\n\n // in unfocused state, always show the full decimal part unless the user has already entered decimals\n if (!focus && !decimalMode) {\n const [_, decimalPlaceholder] = placeholder.split(decimalSeparator);\n return decimalSeparator + decimalPlaceholder;\n }\n\n return null;\n }, [\n decimalMode,\n decimalPart?.length,\n decimalSeparator,\n focus,\n placeholder,\n value,\n valueWithFullDecimals,\n ]);\n\n const style = useInputStyle({\n // whenever decimals are shown, we need to account for the full decimal part for the font size calculation\n value: addonContent ? valueWithFullDecimals : value,\n focus: visualFocus,\n inputElement: ref.current,\n loading,\n });\n\n return (\n <div className=\"wds-amount-input-container\">\n <div\n className={clsx('wds-amount-input-input-container', 'np-text-display-large')}\n style={style}\n >\n <input\n ref={ref}\n className=\"wds-amount-input-input\"\n id={id}\n autoComplete=\"off\"\n inputMode=\"decimal\"\n value={value}\n type=\"text\"\n placeholder={placeholder}\n aria-describedby={describedById}\n /* without this, the input tries to keep an aspect ratio and doesn't respect CSS width rules */\n size={1}\n onChange={(e) => {\n if (isAllowedInput(e)) {\n handleChange(e.target.value);\n }\n }}\n onBlurCapture={() => handleBlur()}\n onPaste={(e) => handlePaste(e)}\n onFocus={() => {\n setFocus(true);\n }}\n onBlur={() => {\n setTimeout(() => setVisualFocus(false), 30);\n }}\n onKeyDown={(e) => handleKeyDown(e)}\n />\n <AnimatePresence initial={false}>\n {addonContent !== null && (\n <AnimatedNumber\n className={clsx(\n 'wds-amount-input-placeholder',\n visualFocus && 'wds-amount-input-placeholder-focus',\n )}\n onClick={() => ref.current?.focus()}\n >\n {addonContent}\n </AnimatedNumber>\n )}\n </AnimatePresence>\n </div>\n </div>\n );\n};\n\nconst getPlaceholder = (currency: string, locale: string) => {\n return formatAmount(0, currency, locale, { alwaysShowDecimals: true });\n};\n\nconst getDecimalPart = (value: string, decimalSeparator: string | null) => {\n if (!value || !decimalSeparator) {\n return undefined;\n }\n\n const [_, decimalPart] = value.split(decimalSeparator);\n return decimalPart ?? undefined;\n};\n"],"names":["AmountInput","id","describedById","amount","currency","autoFocus","onChange","onFocusChange","loading","intl","useIntl","focus","setFocus","visualFocus","setVisualFocus","useFocus","value","setValue","useState","getFormattedString","locale","numericValue","useMemo","getUnformattedNumber","valueWithFullDecimals","alwaysShowDecimals","ref","useRef","useEffect","current","placeholder","getPlaceholder","groupSeparator","getGroupSeparator","decimalSeparator","getDecimalSeparator","maxDecimalCount","getDecimalCount","decimalPart","getDecimalPart","decimalMode","includes","shouldReformatAfterUserInput","newValue","reformatValue","endsWithDecimalSeparator","endsWith","endsWithGroupSeparator","containsDecimalSeparator","enteredDecimalsCount","getEnteredDecimalsCount","unformattedValue","formattedValue","handleChange","oldCursorPosition","selectionStart","newFormattedString","newNumber","newCursorPosition","length","requestAnimationFrame","setSelectionRange","handlePaste","e","preventDefault","clipboardData","getData","sanitisedValue","handleBlur","handleBackspace","input","target","currentValue","selectionEnd","charBeforeCursor","beforeCursor","slice","afterCursor","handleKeyDown","isAllowedInputKey","key","isAllowedInput","hasMultipleDecimalSeparators","split","newNumericValue","maxLength","Number","MAX_SAFE_INTEGER","toString","String","addonContent","isInputPossiblyOverflowing","fullDecimalPart","_","decimalPlaceholder","style","useInputStyle","inputElement","_jsx","className","children","_jsxs","clsx","autoComplete","inputMode","type","size","onBlurCapture","onPaste","onFocus","onBlur","setTimeout","onKeyDown","AnimatePresence","initial","AnimatedNumber","onClick","formatAmount","undefined"],"mappings":"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"}
|
package/build/main.css
CHANGED
|
@@ -3238,16 +3238,7 @@ a,
|
|
|
3238
3238
|
.np-text-display-extra-large,
|
|
3239
3239
|
.np-text-display-large,
|
|
3240
3240
|
.np-text-display-medium,
|
|
3241
|
-
.np-text-display-small
|
|
3242
|
-
.display-1--forced,
|
|
3243
|
-
.display-2--forced,
|
|
3244
|
-
.display-3--forced,
|
|
3245
|
-
.display-4--forced,
|
|
3246
|
-
.display-5--forced,
|
|
3247
|
-
.np-text-display-extra-large--forced,
|
|
3248
|
-
.np-text-display-large--forced,
|
|
3249
|
-
.np-text-display-medium--forced,
|
|
3250
|
-
.np-text-display-small--forced {
|
|
3241
|
+
.np-text-display-small {
|
|
3251
3242
|
font-family: 'Wise Sans', 'Inter', sans-serif;
|
|
3252
3243
|
font-family: var(--font-family-display);
|
|
3253
3244
|
font-synthesis: none;
|
|
@@ -3294,14 +3285,9 @@ a,
|
|
|
3294
3285
|
* of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
|
|
3295
3286
|
* font files are browser-cached and we carried over to launchpad, where it causes issues
|
|
3296
3287
|
* for unsupported locales, especially those that share glyphs, like Japanese and Chinese.
|
|
3297
|
-
* There are exceptions for small UI parts where Wise Sans is fine or expected — e.g. the
|
|
3298
|
-
* numeric input of ExpressiveMoneyInput.
|
|
3299
|
-
* Add `--forced` BEM modifier to the original class name to guarantee it.
|
|
3300
3288
|
*/
|
|
3301
3289
|
font-family: 'Inter', Helvetica, Arial, sans-serif;
|
|
3302
3290
|
font-family: var(--font-family-regular);
|
|
3303
|
-
line-height: 1.2;
|
|
3304
|
-
line-height: var(--line-height-title);
|
|
3305
3291
|
}
|
|
3306
3292
|
|
|
3307
3293
|
/* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
|
|
@@ -31066,7 +31052,6 @@ button.np-link {
|
|
|
31066
31052
|
flex-grow: 1;
|
|
31067
31053
|
text-align: right;
|
|
31068
31054
|
background-color: transparent;
|
|
31069
|
-
line-height: inherit;
|
|
31070
31055
|
}
|
|
31071
31056
|
|
|
31072
31057
|
.wds-amount-input-input:focus-visible {
|
|
@@ -31077,7 +31062,6 @@ button.np-link {
|
|
|
31077
31062
|
flex-grow: 0;
|
|
31078
31063
|
display: flex;
|
|
31079
31064
|
align-items: center;
|
|
31080
|
-
line-height: inherit;
|
|
31081
31065
|
}
|
|
31082
31066
|
|
|
31083
31067
|
.wds-currency-selector:disabled {
|
|
@@ -3238,16 +3238,7 @@ a,
|
|
|
3238
3238
|
.np-text-display-extra-large,
|
|
3239
3239
|
.np-text-display-large,
|
|
3240
3240
|
.np-text-display-medium,
|
|
3241
|
-
.np-text-display-small
|
|
3242
|
-
.display-1--forced,
|
|
3243
|
-
.display-2--forced,
|
|
3244
|
-
.display-3--forced,
|
|
3245
|
-
.display-4--forced,
|
|
3246
|
-
.display-5--forced,
|
|
3247
|
-
.np-text-display-extra-large--forced,
|
|
3248
|
-
.np-text-display-large--forced,
|
|
3249
|
-
.np-text-display-medium--forced,
|
|
3250
|
-
.np-text-display-small--forced {
|
|
3241
|
+
.np-text-display-small {
|
|
3251
3242
|
font-family: 'Wise Sans', 'Inter', sans-serif;
|
|
3252
3243
|
font-family: var(--font-family-display);
|
|
3253
3244
|
font-synthesis: none;
|
|
@@ -3294,14 +3285,9 @@ a,
|
|
|
3294
3285
|
* of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
|
|
3295
3286
|
* font files are browser-cached and we carried over to launchpad, where it causes issues
|
|
3296
3287
|
* for unsupported locales, especially those that share glyphs, like Japanese and Chinese.
|
|
3297
|
-
* There are exceptions for small UI parts where Wise Sans is fine or expected — e.g. the
|
|
3298
|
-
* numeric input of ExpressiveMoneyInput.
|
|
3299
|
-
* Add `--forced` BEM modifier to the original class name to guarantee it.
|
|
3300
3288
|
*/
|
|
3301
3289
|
font-family: 'Inter', Helvetica, Arial, sans-serif;
|
|
3302
3290
|
font-family: var(--font-family-regular);
|
|
3303
|
-
line-height: 1.2;
|
|
3304
|
-
line-height: var(--line-height-title);
|
|
3305
3291
|
}
|
|
3306
3292
|
|
|
3307
3293
|
/* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
flex-grow: 1;
|
|
22
22
|
text-align: right;
|
|
23
23
|
background-color: transparent;
|
|
24
|
-
line-height: inherit;
|
|
25
24
|
}
|
|
26
25
|
.wds-amount-input-input:focus-visible {
|
|
27
26
|
outline: none;
|
|
@@ -30,7 +29,6 @@
|
|
|
30
29
|
flex-grow: 0;
|
|
31
30
|
display: flex;
|
|
32
31
|
align-items: center;
|
|
33
|
-
line-height: inherit;
|
|
34
32
|
}
|
|
35
33
|
.wds-currency-selector:disabled {
|
|
36
34
|
opacity: 1 !important;
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
flex-grow: 1;
|
|
22
22
|
text-align: right;
|
|
23
23
|
background-color: transparent;
|
|
24
|
-
line-height: inherit;
|
|
25
24
|
}
|
|
26
25
|
.wds-amount-input-input:focus-visible {
|
|
27
26
|
outline: none;
|
|
@@ -30,5 +29,4 @@
|
|
|
30
29
|
flex-grow: 0;
|
|
31
30
|
display: flex;
|
|
32
31
|
align-items: center;
|
|
33
|
-
line-height: inherit;
|
|
34
32
|
}
|
package/build/styles/main.css
CHANGED
|
@@ -3238,16 +3238,7 @@ a,
|
|
|
3238
3238
|
.np-text-display-extra-large,
|
|
3239
3239
|
.np-text-display-large,
|
|
3240
3240
|
.np-text-display-medium,
|
|
3241
|
-
.np-text-display-small
|
|
3242
|
-
.display-1--forced,
|
|
3243
|
-
.display-2--forced,
|
|
3244
|
-
.display-3--forced,
|
|
3245
|
-
.display-4--forced,
|
|
3246
|
-
.display-5--forced,
|
|
3247
|
-
.np-text-display-extra-large--forced,
|
|
3248
|
-
.np-text-display-large--forced,
|
|
3249
|
-
.np-text-display-medium--forced,
|
|
3250
|
-
.np-text-display-small--forced {
|
|
3241
|
+
.np-text-display-small {
|
|
3251
3242
|
font-family: 'Wise Sans', 'Inter', sans-serif;
|
|
3252
3243
|
font-family: var(--font-family-display);
|
|
3253
3244
|
font-synthesis: none;
|
|
@@ -3294,14 +3285,9 @@ a,
|
|
|
3294
3285
|
* of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
|
|
3295
3286
|
* font files are browser-cached and we carried over to launchpad, where it causes issues
|
|
3296
3287
|
* for unsupported locales, especially those that share glyphs, like Japanese and Chinese.
|
|
3297
|
-
* There are exceptions for small UI parts where Wise Sans is fine or expected — e.g. the
|
|
3298
|
-
* numeric input of ExpressiveMoneyInput.
|
|
3299
|
-
* Add `--forced` BEM modifier to the original class name to guarantee it.
|
|
3300
3288
|
*/
|
|
3301
3289
|
font-family: 'Inter', Helvetica, Arial, sans-serif;
|
|
3302
3290
|
font-family: var(--font-family-regular);
|
|
3303
|
-
line-height: 1.2;
|
|
3304
|
-
line-height: var(--line-height-title);
|
|
3305
3291
|
}
|
|
3306
3292
|
|
|
3307
3293
|
/* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
|
|
@@ -31066,7 +31052,6 @@ button.np-link {
|
|
|
31066
31052
|
flex-grow: 1;
|
|
31067
31053
|
text-align: right;
|
|
31068
31054
|
background-color: transparent;
|
|
31069
|
-
line-height: inherit;
|
|
31070
31055
|
}
|
|
31071
31056
|
|
|
31072
31057
|
.wds-amount-input-input:focus-visible {
|
|
@@ -31077,7 +31062,6 @@ button.np-link {
|
|
|
31077
31062
|
flex-grow: 0;
|
|
31078
31063
|
display: flex;
|
|
31079
31064
|
align-items: center;
|
|
31080
|
-
line-height: inherit;
|
|
31081
31065
|
}
|
|
31082
31066
|
|
|
31083
31067
|
.wds-currency-selector:disabled {
|
|
@@ -3238,16 +3238,7 @@ a,
|
|
|
3238
3238
|
.np-text-display-extra-large,
|
|
3239
3239
|
.np-text-display-large,
|
|
3240
3240
|
.np-text-display-medium,
|
|
3241
|
-
.np-text-display-small
|
|
3242
|
-
.display-1--forced,
|
|
3243
|
-
.display-2--forced,
|
|
3244
|
-
.display-3--forced,
|
|
3245
|
-
.display-4--forced,
|
|
3246
|
-
.display-5--forced,
|
|
3247
|
-
.np-text-display-extra-large--forced,
|
|
3248
|
-
.np-text-display-large--forced,
|
|
3249
|
-
.np-text-display-medium--forced,
|
|
3250
|
-
.np-text-display-small--forced {
|
|
3241
|
+
.np-text-display-small {
|
|
3251
3242
|
font-family: 'Wise Sans', 'Inter', sans-serif;
|
|
3252
3243
|
font-family: var(--font-family-display);
|
|
3253
3244
|
font-synthesis: none;
|
|
@@ -3294,14 +3285,9 @@ a,
|
|
|
3294
3285
|
* of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
|
|
3295
3286
|
* font files are browser-cached and we carried over to launchpad, where it causes issues
|
|
3296
3287
|
* for unsupported locales, especially those that share glyphs, like Japanese and Chinese.
|
|
3297
|
-
* There are exceptions for small UI parts where Wise Sans is fine or expected — e.g. the
|
|
3298
|
-
* numeric input of ExpressiveMoneyInput.
|
|
3299
|
-
* Add `--forced` BEM modifier to the original class name to guarantee it.
|
|
3300
3288
|
*/
|
|
3301
3289
|
font-family: 'Inter', Helvetica, Arial, sans-serif;
|
|
3302
3290
|
font-family: var(--font-family-regular);
|
|
3303
|
-
line-height: 1.2;
|
|
3304
|
-
line-height: var(--line-height-title);
|
|
3305
3291
|
}
|
|
3306
3292
|
|
|
3307
3293
|
/* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@transferwise/components",
|
|
3
|
-
"version": "0.0.0-experimental-
|
|
3
|
+
"version": "0.0.0-experimental-1fefde6",
|
|
4
4
|
"description": "Neptune React components",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -91,9 +91,9 @@
|
|
|
91
91
|
"storybook-addon-tag-badges": "^3.1.0",
|
|
92
92
|
"storybook-addon-test-codegen": "^3.0.1",
|
|
93
93
|
"@transferwise/less-config": "3.1.2",
|
|
94
|
-
"@transferwise/neptune-css": "
|
|
95
|
-
"@wise/
|
|
96
|
-
"@wise/
|
|
94
|
+
"@transferwise/neptune-css": "14.27.1",
|
|
95
|
+
"@wise/wds-configs": "0.0.0",
|
|
96
|
+
"@wise/components-theming": "1.10.2"
|
|
97
97
|
},
|
|
98
98
|
"peerDependencies": {
|
|
99
99
|
"@transferwise/icons": "^3 || ^4",
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
flex-grow: 1;
|
|
22
22
|
text-align: right;
|
|
23
23
|
background-color: transparent;
|
|
24
|
-
line-height: inherit;
|
|
25
24
|
}
|
|
26
25
|
.wds-amount-input-input:focus-visible {
|
|
27
26
|
outline: none;
|
|
@@ -30,7 +29,6 @@
|
|
|
30
29
|
flex-grow: 0;
|
|
31
30
|
display: flex;
|
|
32
31
|
align-items: center;
|
|
33
|
-
line-height: inherit;
|
|
34
32
|
}
|
|
35
33
|
.wds-currency-selector:disabled {
|
|
36
34
|
opacity: 1 !important;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
2
|
-
import { fn } from 'storybook/test';
|
|
3
2
|
import ExpressiveMoneyInput, { Props as ExpressiveMoneyInputProps } from './ExpressiveMoneyInput';
|
|
4
3
|
|
|
5
4
|
const meta: Meta<typeof ExpressiveMoneyInput> = {
|
|
@@ -22,45 +21,3 @@ export const WithAutofocus: Story = {
|
|
|
22
21
|
autoFocus: true,
|
|
23
22
|
},
|
|
24
23
|
};
|
|
25
|
-
|
|
26
|
-
const locales = [
|
|
27
|
-
{ lang: 'en', label: 'English', currency: 'GBP' },
|
|
28
|
-
{ lang: 'cs', label: 'Czech', currency: 'CZK' },
|
|
29
|
-
{ lang: 'de', label: 'German', currency: 'EUR' },
|
|
30
|
-
{ lang: 'es', label: 'Spanish', currency: 'EUR' },
|
|
31
|
-
{ lang: 'fr', label: 'French', currency: 'EUR' },
|
|
32
|
-
{ lang: 'hu', label: 'Hungarian', currency: 'HUF', supportsDecimals: false },
|
|
33
|
-
{ lang: 'id', label: 'Indonesian', currency: 'IDR', supportsDecimals: false },
|
|
34
|
-
{ lang: 'it', label: 'Italian', currency: 'EUR' },
|
|
35
|
-
{ lang: 'ja', label: 'Japanese', currency: 'JPY', supportsDecimals: false },
|
|
36
|
-
{ lang: 'nl', label: 'Dutch', currency: 'EUR' },
|
|
37
|
-
{ lang: 'pl', label: 'Polish', currency: 'PLN' },
|
|
38
|
-
{ lang: 'pt', label: 'Portuguese', currency: 'EUR' },
|
|
39
|
-
{ lang: 'ro', label: 'Romanian', currency: 'RON' },
|
|
40
|
-
{ lang: 'ru', label: 'Russian', currency: 'RUB' },
|
|
41
|
-
{ lang: 'th', label: 'Thai', currency: 'THB' },
|
|
42
|
-
{ lang: 'tr', label: 'Turkish', currency: 'TRY' },
|
|
43
|
-
{ lang: 'uk', label: 'Ukrainian', currency: 'UAH' },
|
|
44
|
-
{ lang: 'zh-CN', label: 'Simplified Chinese', currency: 'CNY' },
|
|
45
|
-
{ lang: 'zh-HK', label: 'Traditional Chinese', currency: 'HKD' },
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Verifies that the .wds-text-display--forced class correctly overrides locale-specific
|
|
50
|
-
* font restrictions (ja, zh-HK, zh-CN, th) so amounts render in Wise Sans across all
|
|
51
|
-
* supported locales. Each row represents a different language context.
|
|
52
|
-
*/
|
|
53
|
-
export const LocaleFontOverride = () => (
|
|
54
|
-
<>
|
|
55
|
-
{locales.map(({ lang, label, currency, supportsDecimals = true }) => (
|
|
56
|
-
<div key={lang} lang={lang} className="m-b-4">
|
|
57
|
-
<ExpressiveMoneyInput
|
|
58
|
-
label={`${label} locale (${lang})`}
|
|
59
|
-
currency={currency}
|
|
60
|
-
amount={supportsDecimals ? 1234.56 : 123456}
|
|
61
|
-
onAmountChange={fn()}
|
|
62
|
-
/>
|
|
63
|
-
</div>
|
|
64
|
-
))}
|
|
65
|
-
</>
|
|
66
|
-
);
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
flex-grow: 1;
|
|
22
22
|
text-align: right;
|
|
23
23
|
background-color: transparent;
|
|
24
|
-
line-height: inherit;
|
|
25
24
|
}
|
|
26
25
|
.wds-amount-input-input:focus-visible {
|
|
27
26
|
outline: none;
|
|
@@ -30,5 +29,4 @@
|
|
|
30
29
|
flex-grow: 0;
|
|
31
30
|
display: flex;
|
|
32
31
|
align-items: center;
|
|
33
|
-
line-height: inherit;
|
|
34
32
|
}
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
flex-grow: 1;
|
|
30
30
|
text-align: right;
|
|
31
31
|
background-color: transparent;
|
|
32
|
-
line-height: inherit;
|
|
33
32
|
|
|
34
33
|
&:focus-visible {
|
|
35
34
|
outline: none;
|
|
@@ -40,6 +39,5 @@
|
|
|
40
39
|
flex-grow: 0;
|
|
41
40
|
display: flex;
|
|
42
41
|
align-items: center;
|
|
43
|
-
line-height: inherit;
|
|
44
42
|
}
|
|
45
43
|
}
|
|
@@ -291,7 +291,7 @@ export const AmountInput = ({
|
|
|
291
291
|
return (
|
|
292
292
|
<div className="wds-amount-input-container">
|
|
293
293
|
<div
|
|
294
|
-
className={clsx('wds-amount-input-input-container', 'np-text-display-large
|
|
294
|
+
className={clsx('wds-amount-input-input-container', 'np-text-display-large')}
|
|
295
295
|
style={style}
|
|
296
296
|
>
|
|
297
297
|
<input
|
package/src/main.css
CHANGED
|
@@ -3238,16 +3238,7 @@ a,
|
|
|
3238
3238
|
.np-text-display-extra-large,
|
|
3239
3239
|
.np-text-display-large,
|
|
3240
3240
|
.np-text-display-medium,
|
|
3241
|
-
.np-text-display-small
|
|
3242
|
-
.display-1--forced,
|
|
3243
|
-
.display-2--forced,
|
|
3244
|
-
.display-3--forced,
|
|
3245
|
-
.display-4--forced,
|
|
3246
|
-
.display-5--forced,
|
|
3247
|
-
.np-text-display-extra-large--forced,
|
|
3248
|
-
.np-text-display-large--forced,
|
|
3249
|
-
.np-text-display-medium--forced,
|
|
3250
|
-
.np-text-display-small--forced {
|
|
3241
|
+
.np-text-display-small {
|
|
3251
3242
|
font-family: 'Wise Sans', 'Inter', sans-serif;
|
|
3252
3243
|
font-family: var(--font-family-display);
|
|
3253
3244
|
font-synthesis: none;
|
|
@@ -3294,14 +3285,9 @@ a,
|
|
|
3294
3285
|
* of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
|
|
3295
3286
|
* font files are browser-cached and we carried over to launchpad, where it causes issues
|
|
3296
3287
|
* for unsupported locales, especially those that share glyphs, like Japanese and Chinese.
|
|
3297
|
-
* There are exceptions for small UI parts where Wise Sans is fine or expected — e.g. the
|
|
3298
|
-
* numeric input of ExpressiveMoneyInput.
|
|
3299
|
-
* Add `--forced` BEM modifier to the original class name to guarantee it.
|
|
3300
3288
|
*/
|
|
3301
3289
|
font-family: 'Inter', Helvetica, Arial, sans-serif;
|
|
3302
3290
|
font-family: var(--font-family-regular);
|
|
3303
|
-
line-height: 1.2;
|
|
3304
|
-
line-height: var(--line-height-title);
|
|
3305
3291
|
}
|
|
3306
3292
|
|
|
3307
3293
|
/* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
|
|
@@ -31066,7 +31052,6 @@ button.np-link {
|
|
|
31066
31052
|
flex-grow: 1;
|
|
31067
31053
|
text-align: right;
|
|
31068
31054
|
background-color: transparent;
|
|
31069
|
-
line-height: inherit;
|
|
31070
31055
|
}
|
|
31071
31056
|
|
|
31072
31057
|
.wds-amount-input-input:focus-visible {
|
|
@@ -31077,7 +31062,6 @@ button.np-link {
|
|
|
31077
31062
|
flex-grow: 0;
|
|
31078
31063
|
display: flex;
|
|
31079
31064
|
align-items: center;
|
|
31080
|
-
line-height: inherit;
|
|
31081
31065
|
}
|
|
31082
31066
|
|
|
31083
31067
|
.wds-currency-selector:disabled {
|
|
@@ -8,17 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
/* DEPRECATED: use .np-text-*-title instead */
|
|
10
10
|
/* stylelint-disable-next-line selector-list-comma-newline-after */
|
|
11
|
-
.h1,
|
|
12
|
-
.h2,
|
|
13
|
-
.h3,
|
|
14
|
-
.h4,
|
|
15
|
-
.h5,
|
|
16
|
-
.h6,
|
|
17
|
-
.title-1,
|
|
18
|
-
.title-2,
|
|
19
|
-
.title-3,
|
|
20
|
-
.title-4,
|
|
21
|
-
.title-5,
|
|
11
|
+
.h1, .h2, .h3, .h4, .h5, .h6, .title-1, .title-2, .title-3, .title-4, .title-5,
|
|
22
12
|
h1,
|
|
23
13
|
h2,
|
|
24
14
|
h3,
|
|
@@ -124,12 +114,8 @@ h6,
|
|
|
124
114
|
|
|
125
115
|
/* DEPRECATED: use .np-text-body-default instead */
|
|
126
116
|
/* stylelint-disable-next-line selector-list-comma-newline-after */
|
|
127
|
-
.body-2,
|
|
128
|
-
|
|
129
|
-
.small,
|
|
130
|
-
.tiny,
|
|
131
|
-
body,
|
|
132
|
-
small,
|
|
117
|
+
.body-2, .body-3, .small, .tiny,
|
|
118
|
+
body, small,
|
|
133
119
|
.np-text-body-default {
|
|
134
120
|
font-size: var(--font-size-14);
|
|
135
121
|
line-height: 155%;
|
|
@@ -153,8 +139,7 @@ small,
|
|
|
153
139
|
|
|
154
140
|
/* DEPRECATED: use .np-text-body-large instead */
|
|
155
141
|
/* stylelint-disable-next-line selector-list-comma-newline-after */
|
|
156
|
-
.body-1,
|
|
157
|
-
.value,
|
|
142
|
+
.body-1, .value,
|
|
158
143
|
.np-text-body-large {
|
|
159
144
|
font-weight: var(--font-weight-regular);
|
|
160
145
|
font-size: var(--font-size-16);
|
|
@@ -219,11 +204,8 @@ a,
|
|
|
219
204
|
.np-text-display-large,
|
|
220
205
|
.np-text-display-medium,
|
|
221
206
|
.np-text-display-small {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
font-family: var(--font-family-display);
|
|
225
|
-
font-synthesis: none;
|
|
226
|
-
}
|
|
207
|
+
font-family: var(--font-family-display);
|
|
208
|
+
font-synthesis: none;
|
|
227
209
|
|
|
228
210
|
:lang(ja) &,
|
|
229
211
|
:lang(th) &,
|
|
@@ -234,12 +216,8 @@ a,
|
|
|
234
216
|
* of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
|
|
235
217
|
* font files are browser-cached and we carried over to launchpad, where it causes issues
|
|
236
218
|
* for unsupported locales, especially those that share glyphs, like Japanese and Chinese.
|
|
237
|
-
* There are exceptions for small UI parts where Wise Sans is fine or expected — e.g. the
|
|
238
|
-
* numeric input of ExpressiveMoneyInput.
|
|
239
|
-
* Add `--forced` BEM modifier to the original class name to guarantee it.
|
|
240
219
|
*/
|
|
241
220
|
font-family: var(--font-family-regular);
|
|
242
|
-
line-height: var(--line-height-title);
|
|
243
221
|
}
|
|
244
222
|
}
|
|
245
223
|
|
|
@@ -3238,16 +3238,7 @@ a,
|
|
|
3238
3238
|
.np-text-display-extra-large,
|
|
3239
3239
|
.np-text-display-large,
|
|
3240
3240
|
.np-text-display-medium,
|
|
3241
|
-
.np-text-display-small
|
|
3242
|
-
.display-1--forced,
|
|
3243
|
-
.display-2--forced,
|
|
3244
|
-
.display-3--forced,
|
|
3245
|
-
.display-4--forced,
|
|
3246
|
-
.display-5--forced,
|
|
3247
|
-
.np-text-display-extra-large--forced,
|
|
3248
|
-
.np-text-display-large--forced,
|
|
3249
|
-
.np-text-display-medium--forced,
|
|
3250
|
-
.np-text-display-small--forced {
|
|
3241
|
+
.np-text-display-small {
|
|
3251
3242
|
font-family: 'Wise Sans', 'Inter', sans-serif;
|
|
3252
3243
|
font-family: var(--font-family-display);
|
|
3253
3244
|
font-synthesis: none;
|
|
@@ -3294,14 +3285,9 @@ a,
|
|
|
3294
3285
|
* of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
|
|
3295
3286
|
* font files are browser-cached and we carried over to launchpad, where it causes issues
|
|
3296
3287
|
* for unsupported locales, especially those that share glyphs, like Japanese and Chinese.
|
|
3297
|
-
* There are exceptions for small UI parts where Wise Sans is fine or expected — e.g. the
|
|
3298
|
-
* numeric input of ExpressiveMoneyInput.
|
|
3299
|
-
* Add `--forced` BEM modifier to the original class name to guarantee it.
|
|
3300
3288
|
*/
|
|
3301
3289
|
font-family: 'Inter', Helvetica, Arial, sans-serif;
|
|
3302
3290
|
font-family: var(--font-family-regular);
|
|
3303
|
-
line-height: 1.2;
|
|
3304
|
-
line-height: var(--line-height-title);
|
|
3305
3291
|
}
|
|
3306
3292
|
|
|
3307
3293
|
/* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
|