@transferwise/components 46.140.1 → 46.142.0
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/avatarLayout/AvatarLayout.js +15 -1
- package/build/avatarLayout/AvatarLayout.js.map +1 -1
- package/build/avatarLayout/AvatarLayout.mjs +15 -1
- package/build/avatarLayout/AvatarLayout.mjs.map +1 -1
- package/build/avatarView/AvatarView.js +6 -2
- package/build/avatarView/AvatarView.js.map +1 -1
- package/build/avatarView/AvatarView.mjs +6 -2
- package/build/avatarView/AvatarView.mjs.map +1 -1
- package/build/avatarView/Dot.js +8 -0
- package/build/avatarView/Dot.js.map +1 -1
- package/build/avatarView/Dot.mjs +8 -0
- package/build/avatarView/Dot.mjs.map +1 -1
- package/build/avatarWrapper/AvatarWrapper.js +3 -4
- package/build/avatarWrapper/AvatarWrapper.js.map +1 -1
- package/build/avatarWrapper/AvatarWrapper.mjs +4 -5
- package/build/avatarWrapper/AvatarWrapper.mjs.map +1 -1
- package/build/button/LegacyButton.js.map +1 -1
- package/build/button/LegacyButton.mjs.map +1 -1
- package/build/common/circle/Circle.js +6 -2
- package/build/common/circle/Circle.js.map +1 -1
- package/build/common/circle/Circle.mjs +6 -2
- package/build/common/circle/Circle.mjs.map +1 -1
- package/build/common/hooks/useHasIntersected/useHasIntersected.js +6 -4
- package/build/common/hooks/useHasIntersected/useHasIntersected.js.map +1 -1
- package/build/common/hooks/useHasIntersected/useHasIntersected.mjs +6 -4
- package/build/common/hooks/useHasIntersected/useHasIntersected.mjs.map +1 -1
- package/build/common/liveRegion/LiveRegion.js +4 -1
- package/build/common/liveRegion/LiveRegion.js.map +1 -1
- package/build/common/liveRegion/LiveRegion.mjs +4 -1
- package/build/common/liveRegion/LiveRegion.mjs.map +1 -1
- package/build/dateInput/DateInput.js +10 -10
- package/build/dateInput/DateInput.js.map +1 -1
- package/build/dateInput/DateInput.mjs +10 -10
- package/build/dateInput/DateInput.mjs.map +1 -1
- package/build/dateLookup/monthCalendar/table/MonthCalendarTable.js +1 -1
- package/build/dateLookup/monthCalendar/table/MonthCalendarTable.js.map +1 -1
- package/build/dateLookup/monthCalendar/table/MonthCalendarTable.mjs +1 -1
- package/build/dateLookup/monthCalendar/table/MonthCalendarTable.mjs.map +1 -1
- package/build/dateLookup/yearCalendar/table/YearCalendarTable.js +1 -1
- package/build/dateLookup/yearCalendar/table/YearCalendarTable.js.map +1 -1
- package/build/dateLookup/yearCalendar/table/YearCalendarTable.mjs +1 -1
- package/build/dateLookup/yearCalendar/table/YearCalendarTable.mjs.map +1 -1
- package/build/expressiveMoneyInput/ExpressiveMoneyInput.js.map +1 -1
- package/build/expressiveMoneyInput/ExpressiveMoneyInput.mjs.map +1 -1
- package/build/expressiveMoneyInput/amountInput/AmountInput.js +18 -12
- package/build/expressiveMoneyInput/amountInput/AmountInput.js.map +1 -1
- package/build/expressiveMoneyInput/amountInput/AmountInput.mjs +19 -13
- package/build/expressiveMoneyInput/amountInput/AmountInput.mjs.map +1 -1
- package/build/expressiveMoneyInput/hooks/useInputStyle.js +8 -6
- package/build/expressiveMoneyInput/hooks/useInputStyle.js.map +1 -1
- package/build/expressiveMoneyInput/hooks/useInputStyle.mjs +9 -7
- package/build/expressiveMoneyInput/hooks/useInputStyle.mjs.map +1 -1
- package/build/field/Field.js +63 -32
- package/build/field/Field.js.map +1 -1
- package/build/field/Field.messages.js +14 -0
- package/build/field/Field.messages.js.map +1 -0
- package/build/field/Field.messages.mjs +10 -0
- package/build/field/Field.messages.mjs.map +1 -0
- package/build/field/Field.mjs +65 -34
- package/build/field/Field.mjs.map +1 -1
- package/build/header/Header.js +1 -1
- package/build/header/Header.js.map +1 -1
- package/build/header/Header.mjs +1 -1
- package/build/header/Header.mjs.map +1 -1
- package/build/i18n/en.json +1 -0
- package/build/i18n/en.json.js +1 -0
- package/build/i18n/en.json.js.map +1 -1
- package/build/i18n/en.json.mjs +1 -0
- package/build/i18n/en.json.mjs.map +1 -1
- package/build/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.js.map +1 -1
- package/build/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.mjs.map +1 -1
- package/build/inputs/SelectInput/Options/SelectInputOptions.js +34 -22
- package/build/inputs/SelectInput/Options/SelectInputOptions.js.map +1 -1
- package/build/inputs/SelectInput/Options/SelectInputOptions.mjs +35 -23
- package/build/inputs/SelectInput/Options/SelectInputOptions.mjs.map +1 -1
- package/build/inputs/SelectInput/Popover/SelectInputPopover.js.map +1 -1
- package/build/inputs/SelectInput/Popover/SelectInputPopover.mjs.map +1 -1
- package/build/inputs/SelectInput/SelectInput.js +8 -6
- package/build/inputs/SelectInput/SelectInput.js.map +1 -1
- package/build/inputs/SelectInput/SelectInput.mjs +9 -7
- package/build/inputs/SelectInput/SelectInput.mjs.map +1 -1
- package/build/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.js.map +1 -1
- package/build/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.mjs.map +1 -1
- package/build/inputs/TextArea.js +5 -0
- package/build/inputs/TextArea.js.map +1 -1
- package/build/inputs/TextArea.mjs +6 -1
- package/build/inputs/TextArea.mjs.map +1 -1
- package/build/inputs/contexts.js +16 -0
- package/build/inputs/contexts.js.map +1 -1
- package/build/inputs/contexts.mjs +16 -2
- package/build/inputs/contexts.mjs.map +1 -1
- package/build/main.css +42 -8
- package/build/nudge/Nudge.js +31 -15
- package/build/nudge/Nudge.js.map +1 -1
- package/build/nudge/Nudge.mjs +32 -16
- package/build/nudge/Nudge.mjs.map +1 -1
- package/build/phoneNumberInput/PhoneNumberInput.js +9 -12
- package/build/phoneNumberInput/PhoneNumberInput.js.map +1 -1
- package/build/phoneNumberInput/PhoneNumberInput.mjs +9 -12
- package/build/phoneNumberInput/PhoneNumberInput.mjs.map +1 -1
- package/build/promoCard/PromoCardGroup.js +34 -16
- package/build/promoCard/PromoCardGroup.js.map +1 -1
- package/build/promoCard/PromoCardGroup.mjs +35 -17
- package/build/promoCard/PromoCardGroup.mjs.map +1 -1
- package/build/segmentedControl/SegmentedControl.js +6 -1
- package/build/segmentedControl/SegmentedControl.js.map +1 -1
- package/build/segmentedControl/SegmentedControl.mjs +7 -2
- package/build/segmentedControl/SegmentedControl.mjs.map +1 -1
- package/build/styles/avatarView/AvatarView.css +4 -4
- package/build/styles/avatarView/Dot.css +4 -4
- package/build/styles/css/neptune.css +15 -1
- package/build/styles/expressiveMoneyInput/ExpressiveMoneyInput.css +2 -0
- package/build/styles/expressiveMoneyInput/amountInput/AmountInput.css +2 -0
- package/build/styles/field/Field.css +19 -3
- package/build/styles/main.css +42 -8
- package/build/styles/styles/less/neptune.css +15 -1
- package/build/tabs/Tabs.js +1 -1
- package/build/tabs/Tabs.js.map +1 -1
- package/build/tabs/Tabs.mjs +1 -1
- package/build/tabs/Tabs.mjs.map +1 -1
- package/build/tooltip/Tooltip.js +6 -3
- package/build/tooltip/Tooltip.js.map +1 -1
- package/build/tooltip/Tooltip.mjs +6 -3
- package/build/tooltip/Tooltip.mjs.map +1 -1
- package/build/types/avatarView/AvatarView.d.ts +1 -1
- package/build/types/avatarView/AvatarView.d.ts.map +1 -1
- package/build/types/avatarView/Dot.d.ts.map +1 -1
- package/build/types/avatarWrapper/AvatarWrapper.d.ts.map +1 -1
- package/build/types/common/circle/Circle.d.ts +1 -1
- package/build/types/common/circle/Circle.d.ts.map +1 -1
- package/build/types/common/hooks/useHasIntersected/useHasIntersected.d.ts.map +1 -1
- package/build/types/common/liveRegion/LiveRegion.d.ts.map +1 -1
- package/build/types/dateLookup/monthCalendar/table/MonthCalendarTable.d.ts.map +1 -1
- package/build/types/expressiveMoneyInput/ExpressiveMoneyInput.d.ts.map +1 -1
- package/build/types/expressiveMoneyInput/amountInput/AmountInput.d.ts.map +1 -1
- package/build/types/expressiveMoneyInput/hooks/useInputStyle.d.ts +2 -2
- package/build/types/expressiveMoneyInput/hooks/useInputStyle.d.ts.map +1 -1
- package/build/types/expressiveMoneyInput/hooks/useSelectionRange.d.ts.map +1 -1
- package/build/types/field/Field.d.ts.map +1 -1
- package/build/types/field/Field.messages.d.ts +8 -0
- package/build/types/field/Field.messages.d.ts.map +1 -0
- package/build/types/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.d.ts.map +1 -1
- package/build/types/inputs/SelectInput/Options/SelectInputOptions.d.ts.map +1 -1
- package/build/types/inputs/SelectInput/Popover/SelectInputPopover.d.ts.map +1 -1
- package/build/types/inputs/SelectInput/SelectInput.d.ts.map +1 -1
- package/build/types/inputs/TextArea.d.ts.map +1 -1
- package/build/types/inputs/contexts.d.ts +6 -0
- package/build/types/inputs/contexts.d.ts.map +1 -1
- package/build/types/nudge/Nudge.d.ts.map +1 -1
- package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
- package/build/types/promoCard/PromoCardGroup.d.ts.map +1 -1
- package/build/types/segmentedControl/SegmentedControl.d.ts.map +1 -1
- package/build/types/test-utils/index.d.ts +2 -0
- package/build/types/test-utils/index.d.ts.map +1 -1
- package/build/types/tooltip/Tooltip.d.ts.map +1 -1
- package/build/types/uploadInput/UploadInput.d.ts.map +1 -1
- package/build/uploadInput/UploadInput.js +29 -25
- package/build/uploadInput/UploadInput.js.map +1 -1
- package/build/uploadInput/UploadInput.mjs +29 -25
- package/build/uploadInput/UploadInput.mjs.map +1 -1
- package/package.json +3 -3
- package/src/avatarLayout/AvatarLayout.story.tsx +1 -1
- package/src/avatarLayout/AvatarLayout.tsx +4 -0
- package/src/avatarView/AvatarView.css +4 -4
- package/src/avatarView/AvatarView.story.tsx +17 -13
- package/src/avatarView/AvatarView.tsx +5 -1
- package/src/avatarView/Dot.css +4 -4
- package/src/avatarView/Dot.less +6 -6
- package/src/avatarView/Dot.tsx +2 -0
- package/src/avatarWrapper/AvatarWrapper.test.tsx +33 -3
- package/src/avatarWrapper/AvatarWrapper.tsx +5 -6
- package/src/button/LegacyButton.tsx +1 -1
- package/src/button/_stories/Button.test.story.tsx +3 -3
- package/src/common/circle/Circle.tsx +5 -1
- package/src/common/hooks/useContainerSize.test.tsx +1 -1
- package/src/common/hooks/useHasIntersected/useHasIntersected.ts +12 -4
- package/src/common/liveRegion/LiveRegion.tsx +5 -2
- package/src/dateInput/DateInput.tsx +10 -10
- package/src/dateLookup/monthCalendar/table/MonthCalendarTable.tsx +1 -5
- package/src/dateLookup/yearCalendar/table/YearCalendarTable.tsx +1 -1
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.css +2 -0
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.test.story.tsx +43 -0
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.tsx +1 -1
- package/src/expressiveMoneyInput/amountInput/AmountInput.css +2 -0
- package/src/expressiveMoneyInput/amountInput/AmountInput.less +2 -0
- package/src/expressiveMoneyInput/amountInput/AmountInput.tsx +23 -16
- package/src/expressiveMoneyInput/hooks/useInputStyle.ts +20 -8
- package/src/expressiveMoneyInput/hooks/useSelectionRange.ts +2 -0
- package/src/field/Field.css +19 -3
- package/src/field/Field.less +17 -3
- package/src/field/Field.messages.ts +8 -0
- package/src/field/Field.story.tsx +5 -1
- package/src/field/Field.test.tsx +90 -0
- package/src/field/Field.tsx +84 -37
- package/src/header/Header.tsx +2 -2
- package/src/i18n/en.json +1 -0
- package/src/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.tsx +4 -0
- package/src/inputs/SelectInput/Options/SelectInputOptions.tsx +43 -27
- package/src/inputs/SelectInput/Popover/SelectInputPopover.tsx +4 -0
- package/src/inputs/SelectInput/SelectInput.tsx +21 -15
- package/src/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.tsx +1 -1
- package/src/inputs/TextArea.story.tsx +97 -0
- package/src/inputs/TextArea.test.story.tsx +142 -0
- package/src/inputs/TextArea.tsx +7 -2
- package/src/inputs/contexts.tsx +18 -1
- package/src/main.css +42 -8
- package/src/nudge/Nudge.tsx +29 -20
- package/src/phoneNumberInput/PhoneNumberInput.test.tsx +16 -0
- package/src/phoneNumberInput/PhoneNumberInput.tsx +11 -13
- package/src/promoCard/PromoCard.story.tsx +3 -3
- package/src/promoCard/PromoCardGroup.tsx +39 -21
- package/src/segmentedControl/SegmentedControl.test.tsx +25 -0
- package/src/segmentedControl/SegmentedControl.tsx +7 -1
- package/src/select/Select.story.tsx +1 -1
- package/src/styles/less/core/_typography.less +28 -6
- package/src/styles/less/neptune.css +15 -1
- package/src/tabs/Tabs.tsx +1 -1
- package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.story.tsx +1 -0
- package/src/tooltip/Tooltip.tsx +3 -0
- package/src/uploadInput/UploadInput.test.tsx +19 -0
- package/src/uploadInput/UploadInput.tsx +28 -24
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { clsx } from 'clsx';
|
|
2
|
-
import React__default, { useState,
|
|
2
|
+
import React__default, { useState, useEffect, useMemo } from 'react';
|
|
3
3
|
import { PromoCardContext } from './PromoCardContext.mjs';
|
|
4
4
|
import { jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
@@ -12,8 +12,40 @@ const PromoCardGroup = ({
|
|
|
12
12
|
onChange = () => {},
|
|
13
13
|
testId
|
|
14
14
|
}) => {
|
|
15
|
-
const [
|
|
16
|
-
|
|
15
|
+
const [promoCardState, setPromoCardState] = useState({
|
|
16
|
+
defaultChecked,
|
|
17
|
+
state: defaultChecked
|
|
18
|
+
});
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (promoCardState.defaultChecked !== defaultChecked) {
|
|
21
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect -- Syncing defaultChecked prop to internal state
|
|
22
|
+
setPromoCardState({
|
|
23
|
+
defaultChecked,
|
|
24
|
+
state: defaultChecked
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}, [defaultChecked, promoCardState.defaultChecked]);
|
|
28
|
+
const {
|
|
29
|
+
state
|
|
30
|
+
} = promoCardState;
|
|
31
|
+
const setState = newState => setPromoCardState(prev => ({
|
|
32
|
+
...prev,
|
|
33
|
+
state: newState
|
|
34
|
+
}));
|
|
35
|
+
// Derive container role from children
|
|
36
|
+
const containerRole = useMemo(() => {
|
|
37
|
+
// Collect an array of types from the children PromoCard components
|
|
38
|
+
const types = React__default.Children.map(children, child => {
|
|
39
|
+
if (/*#__PURE__*/React__default.isValidElement(child) && child.props.type) {
|
|
40
|
+
return child.props.type;
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
})?.filter(type => type !== null && type !== undefined) ?? [];
|
|
44
|
+
// Check if all types are the same
|
|
45
|
+
const allTypesAreTheSame = types.every(type => type === types[0]);
|
|
46
|
+
// If all types are the same and the type is 'radio', return 'radiogroup'
|
|
47
|
+
return allTypesAreTheSame && types[0] === 'radio' ? 'radiogroup' : null;
|
|
48
|
+
}, [children]);
|
|
17
49
|
/**
|
|
18
50
|
* The context value for the PromoCardGroup.
|
|
19
51
|
*
|
|
@@ -44,20 +76,6 @@ const PromoCardGroup = ({
|
|
|
44
76
|
'data-testid': testId,
|
|
45
77
|
role: containerRole // Add the role attribute here
|
|
46
78
|
};
|
|
47
|
-
useEffect(() => {
|
|
48
|
-
setState(defaultChecked);
|
|
49
|
-
// Collect an array of types from the children PromoCard components
|
|
50
|
-
const types = React__default.Children.map(children, child => {
|
|
51
|
-
if (/*#__PURE__*/React__default.isValidElement(child) && child.props.type) {
|
|
52
|
-
return child.props.type;
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
55
|
-
})?.filter(type => type !== null && type !== undefined) ?? [];
|
|
56
|
-
// Check if all types are the same
|
|
57
|
-
const allTypesAreTheSame = types.every(type => type === types[0]);
|
|
58
|
-
// If all types are the same and the type is 'radio', set the container role
|
|
59
|
-
setContainerRole(allTypesAreTheSame && types[0] === 'radio' ? 'radiogroup' : null);
|
|
60
|
-
}, [defaultChecked, children]);
|
|
61
79
|
return /*#__PURE__*/jsx(PromoCardContext.Provider, {
|
|
62
80
|
value: contextValue,
|
|
63
81
|
children: /*#__PURE__*/jsx("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PromoCardGroup.mjs","sources":["../../src/promoCard/PromoCardGroup.tsx"],"sourcesContent":["import { clsx } from 'clsx';\nimport React, { FunctionComponent, ReactNode, useState, useEffect, useMemo } from 'react';\n\nimport { PromoCardProps } from './PromoCard';\nimport PromoCardContext from './PromoCardContext';\n\nexport type AriaRoleRadioGroup = 'radiogroup';\n\nexport interface PromoCardGroupProps {\n /**\n * Optional class name(s) to add to the group container.\n */\n className?: string;\n /**\n * The PromoCard components to display inside the group.\n */\n children: ReactNode;\n /**\n * The default checked for the group.\n */\n defaultChecked?: string;\n /**\n * Optional ID to add to the group container.\n */\n id?: string;\n /**\n * Whether the group is disabled or not.\n */\n isDisabled?: boolean;\n /**\n * Optional label to display above the group.\n */\n label?: string;\n /**\n * Optional function to call when the group value changes.\n */\n onChange?: (value: string) => void;\n /**\n * Optional ID to add to the group container for testing purposes.\n */\n testId?: string;\n}\n\n/**\n * PromoCardGroup component.\n *\n * A PromoCardGroup is a container for PromoCard components that allows the user to select one or more\n * cards from a group. It can be used to display a set of related options, and can be customized with\n * various props to suit different use cases.\n *\n * @param {ReactNode} children - The PromoCard components to display inside the group.\n * @param {string} className - Optional class name(s) to add to the group container.\n * @param {string} defaultChecked - The default value for the group.\n * @param {string} id - Optional ID to add to the group container.\n * @param {boolean} isDisabled=false - Whether the group is disabled or not.\n * @param {string} label - Optional label to display above the group.\n * @param {Function} onChange - Optional function to call when the group value changes.\n * @param {string} testId - Optional ID to add to the group container for testing purposes.\n * @returns {React.JSX.Element} - The PromoCardGroup component.\n */\nconst PromoCardGroup: FunctionComponent<PromoCardGroupProps> = ({\n children,\n className,\n defaultChecked = '',\n id,\n isDisabled = false,\n onChange = () => {},\n testId,\n}) => {\n const [
|
|
1
|
+
{"version":3,"file":"PromoCardGroup.mjs","sources":["../../src/promoCard/PromoCardGroup.tsx"],"sourcesContent":["import { clsx } from 'clsx';\nimport React, { FunctionComponent, ReactNode, useState, useEffect, useMemo } from 'react';\n\nimport { PromoCardProps } from './PromoCard';\nimport PromoCardContext from './PromoCardContext';\n\nexport type AriaRoleRadioGroup = 'radiogroup';\n\nexport interface PromoCardGroupProps {\n /**\n * Optional class name(s) to add to the group container.\n */\n className?: string;\n /**\n * The PromoCard components to display inside the group.\n */\n children: ReactNode;\n /**\n * The default checked for the group.\n */\n defaultChecked?: string;\n /**\n * Optional ID to add to the group container.\n */\n id?: string;\n /**\n * Whether the group is disabled or not.\n */\n isDisabled?: boolean;\n /**\n * Optional label to display above the group.\n */\n label?: string;\n /**\n * Optional function to call when the group value changes.\n */\n onChange?: (value: string) => void;\n /**\n * Optional ID to add to the group container for testing purposes.\n */\n testId?: string;\n}\n\n/**\n * PromoCardGroup component.\n *\n * A PromoCardGroup is a container for PromoCard components that allows the user to select one or more\n * cards from a group. It can be used to display a set of related options, and can be customized with\n * various props to suit different use cases.\n *\n * @param {ReactNode} children - The PromoCard components to display inside the group.\n * @param {string} className - Optional class name(s) to add to the group container.\n * @param {string} defaultChecked - The default value for the group.\n * @param {string} id - Optional ID to add to the group container.\n * @param {boolean} isDisabled=false - Whether the group is disabled or not.\n * @param {string} label - Optional label to display above the group.\n * @param {Function} onChange - Optional function to call when the group value changes.\n * @param {string} testId - Optional ID to add to the group container for testing purposes.\n * @returns {React.JSX.Element} - The PromoCardGroup component.\n */\nconst PromoCardGroup: FunctionComponent<PromoCardGroupProps> = ({\n children,\n className,\n defaultChecked = '',\n id,\n isDisabled = false,\n onChange = () => {},\n testId,\n}) => {\n const [promoCardState, setPromoCardState] = useState<{\n defaultChecked: string;\n state: string;\n }>({\n defaultChecked,\n state: defaultChecked,\n });\n\n useEffect(() => {\n if (promoCardState.defaultChecked !== defaultChecked) {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- Syncing defaultChecked prop to internal state\n setPromoCardState({\n defaultChecked,\n state: defaultChecked,\n });\n }\n }, [defaultChecked, promoCardState.defaultChecked]);\n\n const { state } = promoCardState;\n const setState = (newState: string) =>\n setPromoCardState((prev) => ({ ...prev, state: newState }));\n\n // Derive container role from children\n const containerRole = useMemo(() => {\n // Collect an array of types from the children PromoCard components\n const types =\n React.Children.map(children, (child) => {\n if (React.isValidElement<PromoCardProps>(child) && child.props.type) {\n return child.props.type;\n }\n return null;\n })?.filter((type): type is 'radio' | 'checkbox' => type !== null && type !== undefined) ?? [];\n\n // Check if all types are the same\n const allTypesAreTheSame = types.every((type) => type === types[0]);\n\n // If all types are the same and the type is 'radio', return 'radiogroup'\n return allTypesAreTheSame && types[0] === 'radio' ? 'radiogroup' : null;\n }, [children]);\n\n /**\n * The context value for the PromoCardGroup.\n *\n * The context value is an object that contains the current state of the\n * group, whether the group is disabled or not, and a function to call when\n * the group value changes. This value is used to provide context to child\n * PromoCard components, allowing them to interact with the group and update\n * its state.\n */\n const contextValue = useMemo(() => {\n const handleOnChange = (value: string) => {\n setState(value);\n onChange(value);\n };\n\n return { state, isDisabled, onChange: handleOnChange };\n }, [state, isDisabled, onChange]);\n\n const commonClasses = clsx(\n {\n 'np-CardGroup': true,\n 'is-disabled': isDisabled,\n },\n className,\n );\n\n const commonProps = {\n className: commonClasses,\n id,\n 'data-testid': testId,\n role: containerRole as AriaRoleRadioGroup | undefined, // Add the role attribute here\n };\n\n return (\n <PromoCardContext.Provider value={contextValue}>\n <div {...commonProps}>{children}</div>\n </PromoCardContext.Provider>\n );\n};\n\nexport default React.memo(PromoCardGroup);\n"],"names":["PromoCardGroup","children","className","defaultChecked","id","isDisabled","onChange","testId","promoCardState","setPromoCardState","useState","state","useEffect","setState","newState","prev","containerRole","useMemo","types","React","Children","map","child","isValidElement","props","type","filter","undefined","allTypesAreTheSame","every","contextValue","handleOnChange","value","commonClasses","clsx","commonProps","role","_jsx","PromoCardContext","Provider","memo"],"mappings":"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"}
|
|
@@ -37,6 +37,7 @@ const SegmentedControl = ({
|
|
|
37
37
|
segments,
|
|
38
38
|
onChange
|
|
39
39
|
}) => {
|
|
40
|
+
const isMountedRef = React.useRef(false);
|
|
40
41
|
const [animate, setAnimate] = React.useState(false);
|
|
41
42
|
const segmentsRef = React.useRef(null);
|
|
42
43
|
if (segments.length > 3) {
|
|
@@ -60,7 +61,11 @@ const SegmentedControl = ({
|
|
|
60
61
|
}
|
|
61
62
|
};
|
|
62
63
|
React.useEffect(() => {
|
|
63
|
-
|
|
64
|
+
if (isMountedRef.current) {
|
|
65
|
+
setAnimate(true);
|
|
66
|
+
} else {
|
|
67
|
+
isMountedRef.current = true;
|
|
68
|
+
}
|
|
64
69
|
updateSegmentPosition();
|
|
65
70
|
const handleWindowSizeChange = () => {
|
|
66
71
|
setAnimate(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SegmentedControl.js","sources":["../../src/segmentedControl/SegmentedControl.tsx"],"sourcesContent":["import { clsx } from 'clsx';\nimport { createRef, useEffect, useRef, useState } from 'react';\n\nimport Body from '../body';\nimport { Typography } from '../common';\n\ntype SegmentBase = { id: string; label: string; value: string };\n\ntype Segment = SegmentBase & { controls?: never };\ntype SegmentWithControls = SegmentBase & { controls: string };\n\nexport type Segments = readonly Segment[] | readonly SegmentWithControls[];\n\ntype SegmentedControlPropsBase = {\n name: string;\n value: string;\n mode: 'input' | 'view';\n onChange: (value: string) => void;\n};\n\ntype SegmentedControlViewProps = {\n mode: 'view';\n segments: readonly SegmentWithControls[];\n};\n\ntype SegmentedControlInputProps = {\n mode: 'input';\n segments: readonly Segment[];\n};\n\nexport type SegmentedControlProps = SegmentedControlPropsBase &\n (SegmentedControlViewProps | SegmentedControlInputProps);\n\nconst SegmentedControl = ({\n name,\n value,\n mode = 'input',\n segments,\n onChange,\n}: SegmentedControlProps) => {\n const [animate, setAnimate] = useState(false);\n\n const segmentsRef = useRef<HTMLDivElement>(null);\n\n if (segments.length > 3) {\n throw new Error(\n 'SegmentedControl only supports up to 3 segments. Please refer to: https://wise.design/components/segmented-control',\n );\n }\n\n const segmentsWithRefs = segments.map((segment) => ({\n ...segment,\n ref: createRef<HTMLLabelElement | HTMLButtonElement>(),\n }));\n\n const updateSegmentPosition = () => {\n const selectedSegmentRef = segmentsWithRefs.find((segment) => segment.value === value)?.ref;\n\n // We grab the active segments style object from the ref\n // and set the css variables to the selected segments width and x position.\n // This is so we can animate the highlight to the selected segment\n if (selectedSegmentRef?.current && segmentsRef.current) {\n const { style } = segmentsRef.current;\n style.setProperty('--segment-highlight-width', `${selectedSegmentRef.current.offsetWidth}px`);\n style.setProperty('--segment-highlight-x', `${selectedSegmentRef.current.offsetLeft}px`);\n }\n };\n\n useEffect(() => {\n setAnimate(true);\n updateSegmentPosition();\n\n const handleWindowSizeChange = () => {\n setAnimate(false);\n updateSegmentPosition();\n };\n\n window.addEventListener('resize', handleWindowSizeChange);\n return () => {\n window.removeEventListener('resize', handleWindowSizeChange);\n };\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [segmentsWithRefs, value]);\n\n return (\n <div\n ref={segmentsRef}\n data-testid=\"segmented-control\"\n className={clsx('segmented-control', {\n 'segmented-control--input': mode === 'input',\n })}\n >\n <div\n className={clsx('segmented-control__segments', {\n 'segmented-control__segments--no-animate': !animate,\n })}\n role={mode !== 'input' ? 'tablist' : undefined}\n >\n {segmentsWithRefs.map((segment) => {\n const onSelect = () => {\n setAnimate(true);\n onChange(segment.value);\n };\n return mode === 'input' ? (\n <label\n ref={segment.ref as React.MutableRefObject<HTMLLabelElement | null>}\n key={segment.id}\n htmlFor={segment.id}\n className={clsx('segmented-control__segment', {\n 'segmented-control__selected-segment': value === segment.value,\n })}\n >\n <input\n type=\"radio\"\n className=\"segmented-control__radio-input\"\n id={segment.id}\n name={name}\n value={segment.value}\n checked={value === segment.value}\n onChange={onSelect}\n />\n <Body\n className=\"segmented-control__text\"\n as=\"span\"\n type={\n value === segment.value ? Typography.BODY_DEFAULT_BOLD : Typography.BODY_DEFAULT\n }\n >\n {segment.label}\n </Body>\n </label>\n ) : (\n <button\n ref={segment.ref as React.MutableRefObject<HTMLButtonElement | null>}\n key={segment.id}\n type=\"button\"\n role=\"tab\"\n id={segment.id}\n aria-controls={segment.controls}\n aria-selected={value === segment.value}\n className={clsx('segmented-control__segment', 'segmented-control__button', {\n 'segmented-control__selected-segment': value === segment.value,\n })}\n onClick={onSelect}\n >\n <Body\n as=\"span\"\n className=\"segmented-control__text\"\n type={\n value === segment.value ? Typography.BODY_DEFAULT_BOLD : Typography.BODY_DEFAULT\n }\n >\n {segment.label}\n </Body>\n </button>\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default SegmentedControl;\n"],"names":["SegmentedControl","name","value","mode","segments","onChange","animate","setAnimate","useState","segmentsRef","
|
|
1
|
+
{"version":3,"file":"SegmentedControl.js","sources":["../../src/segmentedControl/SegmentedControl.tsx"],"sourcesContent":["import { clsx } from 'clsx';\nimport { createRef, useEffect, useRef, useState } from 'react';\n\nimport Body from '../body';\nimport { Typography } from '../common';\n\ntype SegmentBase = { id: string; label: string; value: string };\n\ntype Segment = SegmentBase & { controls?: never };\ntype SegmentWithControls = SegmentBase & { controls: string };\n\nexport type Segments = readonly Segment[] | readonly SegmentWithControls[];\n\ntype SegmentedControlPropsBase = {\n name: string;\n value: string;\n mode: 'input' | 'view';\n onChange: (value: string) => void;\n};\n\ntype SegmentedControlViewProps = {\n mode: 'view';\n segments: readonly SegmentWithControls[];\n};\n\ntype SegmentedControlInputProps = {\n mode: 'input';\n segments: readonly Segment[];\n};\n\nexport type SegmentedControlProps = SegmentedControlPropsBase &\n (SegmentedControlViewProps | SegmentedControlInputProps);\n\nconst SegmentedControl = ({\n name,\n value,\n mode = 'input',\n segments,\n onChange,\n}: SegmentedControlProps) => {\n const isMountedRef = useRef(false);\n const [animate, setAnimate] = useState(false);\n\n const segmentsRef = useRef<HTMLDivElement>(null);\n\n if (segments.length > 3) {\n throw new Error(\n 'SegmentedControl only supports up to 3 segments. Please refer to: https://wise.design/components/segmented-control',\n );\n }\n\n const segmentsWithRefs = segments.map((segment) => ({\n ...segment,\n ref: createRef<HTMLLabelElement | HTMLButtonElement>(),\n }));\n\n const updateSegmentPosition = () => {\n const selectedSegmentRef = segmentsWithRefs.find((segment) => segment.value === value)?.ref;\n\n // We grab the active segments style object from the ref\n // and set the css variables to the selected segments width and x position.\n // This is so we can animate the highlight to the selected segment\n if (selectedSegmentRef?.current && segmentsRef.current) {\n const { style } = segmentsRef.current;\n style.setProperty('--segment-highlight-width', `${selectedSegmentRef.current.offsetWidth}px`);\n style.setProperty('--segment-highlight-x', `${selectedSegmentRef.current.offsetLeft}px`);\n }\n };\n\n useEffect(() => {\n if (isMountedRef.current) {\n setAnimate(true);\n } else {\n isMountedRef.current = true;\n }\n\n updateSegmentPosition();\n\n const handleWindowSizeChange = () => {\n setAnimate(false);\n updateSegmentPosition();\n };\n\n window.addEventListener('resize', handleWindowSizeChange);\n return () => {\n window.removeEventListener('resize', handleWindowSizeChange);\n };\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [segmentsWithRefs, value]);\n\n return (\n <div\n ref={segmentsRef}\n data-testid=\"segmented-control\"\n className={clsx('segmented-control', {\n 'segmented-control--input': mode === 'input',\n })}\n >\n <div\n className={clsx('segmented-control__segments', {\n 'segmented-control__segments--no-animate': !animate,\n })}\n role={mode !== 'input' ? 'tablist' : undefined}\n >\n {segmentsWithRefs.map((segment) => {\n const onSelect = () => {\n setAnimate(true);\n onChange(segment.value);\n };\n return mode === 'input' ? (\n <label\n ref={segment.ref as React.MutableRefObject<HTMLLabelElement | null>}\n key={segment.id}\n htmlFor={segment.id}\n className={clsx('segmented-control__segment', {\n 'segmented-control__selected-segment': value === segment.value,\n })}\n >\n <input\n type=\"radio\"\n className=\"segmented-control__radio-input\"\n id={segment.id}\n name={name}\n value={segment.value}\n checked={value === segment.value}\n onChange={onSelect}\n />\n <Body\n className=\"segmented-control__text\"\n as=\"span\"\n type={\n value === segment.value ? Typography.BODY_DEFAULT_BOLD : Typography.BODY_DEFAULT\n }\n >\n {segment.label}\n </Body>\n </label>\n ) : (\n <button\n ref={segment.ref as React.MutableRefObject<HTMLButtonElement | null>}\n key={segment.id}\n type=\"button\"\n role=\"tab\"\n id={segment.id}\n aria-controls={segment.controls}\n aria-selected={value === segment.value}\n className={clsx('segmented-control__segment', 'segmented-control__button', {\n 'segmented-control__selected-segment': value === segment.value,\n })}\n onClick={onSelect}\n >\n <Body\n as=\"span\"\n className=\"segmented-control__text\"\n type={\n value === segment.value ? Typography.BODY_DEFAULT_BOLD : Typography.BODY_DEFAULT\n }\n >\n {segment.label}\n </Body>\n </button>\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default SegmentedControl;\n"],"names":["SegmentedControl","name","value","mode","segments","onChange","isMountedRef","useRef","animate","setAnimate","useState","segmentsRef","length","Error","segmentsWithRefs","map","segment","ref","createRef","updateSegmentPosition","selectedSegmentRef","find","current","style","setProperty","offsetWidth","offsetLeft","useEffect","handleWindowSizeChange","window","addEventListener","removeEventListener","_jsx","className","clsx","children","role","undefined","onSelect","_jsxs","htmlFor","id","type","checked","Body","as","Typography","BODY_DEFAULT_BOLD","BODY_DEFAULT","label","controls","onClick"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { clsx } from 'clsx';
|
|
2
|
-
import {
|
|
2
|
+
import { useRef, useState, createRef, useEffect } from 'react';
|
|
3
3
|
import Body from '../body/Body.mjs';
|
|
4
4
|
import '../common/theme.mjs';
|
|
5
5
|
import '../common/direction.mjs';
|
|
@@ -33,6 +33,7 @@ const SegmentedControl = ({
|
|
|
33
33
|
segments,
|
|
34
34
|
onChange
|
|
35
35
|
}) => {
|
|
36
|
+
const isMountedRef = useRef(false);
|
|
36
37
|
const [animate, setAnimate] = useState(false);
|
|
37
38
|
const segmentsRef = useRef(null);
|
|
38
39
|
if (segments.length > 3) {
|
|
@@ -56,7 +57,11 @@ const SegmentedControl = ({
|
|
|
56
57
|
}
|
|
57
58
|
};
|
|
58
59
|
useEffect(() => {
|
|
59
|
-
|
|
60
|
+
if (isMountedRef.current) {
|
|
61
|
+
setAnimate(true);
|
|
62
|
+
} else {
|
|
63
|
+
isMountedRef.current = true;
|
|
64
|
+
}
|
|
60
65
|
updateSegmentPosition();
|
|
61
66
|
const handleWindowSizeChange = () => {
|
|
62
67
|
setAnimate(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SegmentedControl.mjs","sources":["../../src/segmentedControl/SegmentedControl.tsx"],"sourcesContent":["import { clsx } from 'clsx';\nimport { createRef, useEffect, useRef, useState } from 'react';\n\nimport Body from '../body';\nimport { Typography } from '../common';\n\ntype SegmentBase = { id: string; label: string; value: string };\n\ntype Segment = SegmentBase & { controls?: never };\ntype SegmentWithControls = SegmentBase & { controls: string };\n\nexport type Segments = readonly Segment[] | readonly SegmentWithControls[];\n\ntype SegmentedControlPropsBase = {\n name: string;\n value: string;\n mode: 'input' | 'view';\n onChange: (value: string) => void;\n};\n\ntype SegmentedControlViewProps = {\n mode: 'view';\n segments: readonly SegmentWithControls[];\n};\n\ntype SegmentedControlInputProps = {\n mode: 'input';\n segments: readonly Segment[];\n};\n\nexport type SegmentedControlProps = SegmentedControlPropsBase &\n (SegmentedControlViewProps | SegmentedControlInputProps);\n\nconst SegmentedControl = ({\n name,\n value,\n mode = 'input',\n segments,\n onChange,\n}: SegmentedControlProps) => {\n const [animate, setAnimate] = useState(false);\n\n const segmentsRef = useRef<HTMLDivElement>(null);\n\n if (segments.length > 3) {\n throw new Error(\n 'SegmentedControl only supports up to 3 segments. Please refer to: https://wise.design/components/segmented-control',\n );\n }\n\n const segmentsWithRefs = segments.map((segment) => ({\n ...segment,\n ref: createRef<HTMLLabelElement | HTMLButtonElement>(),\n }));\n\n const updateSegmentPosition = () => {\n const selectedSegmentRef = segmentsWithRefs.find((segment) => segment.value === value)?.ref;\n\n // We grab the active segments style object from the ref\n // and set the css variables to the selected segments width and x position.\n // This is so we can animate the highlight to the selected segment\n if (selectedSegmentRef?.current && segmentsRef.current) {\n const { style } = segmentsRef.current;\n style.setProperty('--segment-highlight-width', `${selectedSegmentRef.current.offsetWidth}px`);\n style.setProperty('--segment-highlight-x', `${selectedSegmentRef.current.offsetLeft}px`);\n }\n };\n\n useEffect(() => {\n setAnimate(true);\n updateSegmentPosition();\n\n const handleWindowSizeChange = () => {\n setAnimate(false);\n updateSegmentPosition();\n };\n\n window.addEventListener('resize', handleWindowSizeChange);\n return () => {\n window.removeEventListener('resize', handleWindowSizeChange);\n };\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [segmentsWithRefs, value]);\n\n return (\n <div\n ref={segmentsRef}\n data-testid=\"segmented-control\"\n className={clsx('segmented-control', {\n 'segmented-control--input': mode === 'input',\n })}\n >\n <div\n className={clsx('segmented-control__segments', {\n 'segmented-control__segments--no-animate': !animate,\n })}\n role={mode !== 'input' ? 'tablist' : undefined}\n >\n {segmentsWithRefs.map((segment) => {\n const onSelect = () => {\n setAnimate(true);\n onChange(segment.value);\n };\n return mode === 'input' ? (\n <label\n ref={segment.ref as React.MutableRefObject<HTMLLabelElement | null>}\n key={segment.id}\n htmlFor={segment.id}\n className={clsx('segmented-control__segment', {\n 'segmented-control__selected-segment': value === segment.value,\n })}\n >\n <input\n type=\"radio\"\n className=\"segmented-control__radio-input\"\n id={segment.id}\n name={name}\n value={segment.value}\n checked={value === segment.value}\n onChange={onSelect}\n />\n <Body\n className=\"segmented-control__text\"\n as=\"span\"\n type={\n value === segment.value ? Typography.BODY_DEFAULT_BOLD : Typography.BODY_DEFAULT\n }\n >\n {segment.label}\n </Body>\n </label>\n ) : (\n <button\n ref={segment.ref as React.MutableRefObject<HTMLButtonElement | null>}\n key={segment.id}\n type=\"button\"\n role=\"tab\"\n id={segment.id}\n aria-controls={segment.controls}\n aria-selected={value === segment.value}\n className={clsx('segmented-control__segment', 'segmented-control__button', {\n 'segmented-control__selected-segment': value === segment.value,\n })}\n onClick={onSelect}\n >\n <Body\n as=\"span\"\n className=\"segmented-control__text\"\n type={\n value === segment.value ? Typography.BODY_DEFAULT_BOLD : Typography.BODY_DEFAULT\n }\n >\n {segment.label}\n </Body>\n </button>\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default SegmentedControl;\n"],"names":["SegmentedControl","name","value","mode","segments","onChange","animate","setAnimate","useState","segmentsRef","
|
|
1
|
+
{"version":3,"file":"SegmentedControl.mjs","sources":["../../src/segmentedControl/SegmentedControl.tsx"],"sourcesContent":["import { clsx } from 'clsx';\nimport { createRef, useEffect, useRef, useState } from 'react';\n\nimport Body from '../body';\nimport { Typography } from '../common';\n\ntype SegmentBase = { id: string; label: string; value: string };\n\ntype Segment = SegmentBase & { controls?: never };\ntype SegmentWithControls = SegmentBase & { controls: string };\n\nexport type Segments = readonly Segment[] | readonly SegmentWithControls[];\n\ntype SegmentedControlPropsBase = {\n name: string;\n value: string;\n mode: 'input' | 'view';\n onChange: (value: string) => void;\n};\n\ntype SegmentedControlViewProps = {\n mode: 'view';\n segments: readonly SegmentWithControls[];\n};\n\ntype SegmentedControlInputProps = {\n mode: 'input';\n segments: readonly Segment[];\n};\n\nexport type SegmentedControlProps = SegmentedControlPropsBase &\n (SegmentedControlViewProps | SegmentedControlInputProps);\n\nconst SegmentedControl = ({\n name,\n value,\n mode = 'input',\n segments,\n onChange,\n}: SegmentedControlProps) => {\n const isMountedRef = useRef(false);\n const [animate, setAnimate] = useState(false);\n\n const segmentsRef = useRef<HTMLDivElement>(null);\n\n if (segments.length > 3) {\n throw new Error(\n 'SegmentedControl only supports up to 3 segments. Please refer to: https://wise.design/components/segmented-control',\n );\n }\n\n const segmentsWithRefs = segments.map((segment) => ({\n ...segment,\n ref: createRef<HTMLLabelElement | HTMLButtonElement>(),\n }));\n\n const updateSegmentPosition = () => {\n const selectedSegmentRef = segmentsWithRefs.find((segment) => segment.value === value)?.ref;\n\n // We grab the active segments style object from the ref\n // and set the css variables to the selected segments width and x position.\n // This is so we can animate the highlight to the selected segment\n if (selectedSegmentRef?.current && segmentsRef.current) {\n const { style } = segmentsRef.current;\n style.setProperty('--segment-highlight-width', `${selectedSegmentRef.current.offsetWidth}px`);\n style.setProperty('--segment-highlight-x', `${selectedSegmentRef.current.offsetLeft}px`);\n }\n };\n\n useEffect(() => {\n if (isMountedRef.current) {\n setAnimate(true);\n } else {\n isMountedRef.current = true;\n }\n\n updateSegmentPosition();\n\n const handleWindowSizeChange = () => {\n setAnimate(false);\n updateSegmentPosition();\n };\n\n window.addEventListener('resize', handleWindowSizeChange);\n return () => {\n window.removeEventListener('resize', handleWindowSizeChange);\n };\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [segmentsWithRefs, value]);\n\n return (\n <div\n ref={segmentsRef}\n data-testid=\"segmented-control\"\n className={clsx('segmented-control', {\n 'segmented-control--input': mode === 'input',\n })}\n >\n <div\n className={clsx('segmented-control__segments', {\n 'segmented-control__segments--no-animate': !animate,\n })}\n role={mode !== 'input' ? 'tablist' : undefined}\n >\n {segmentsWithRefs.map((segment) => {\n const onSelect = () => {\n setAnimate(true);\n onChange(segment.value);\n };\n return mode === 'input' ? (\n <label\n ref={segment.ref as React.MutableRefObject<HTMLLabelElement | null>}\n key={segment.id}\n htmlFor={segment.id}\n className={clsx('segmented-control__segment', {\n 'segmented-control__selected-segment': value === segment.value,\n })}\n >\n <input\n type=\"radio\"\n className=\"segmented-control__radio-input\"\n id={segment.id}\n name={name}\n value={segment.value}\n checked={value === segment.value}\n onChange={onSelect}\n />\n <Body\n className=\"segmented-control__text\"\n as=\"span\"\n type={\n value === segment.value ? Typography.BODY_DEFAULT_BOLD : Typography.BODY_DEFAULT\n }\n >\n {segment.label}\n </Body>\n </label>\n ) : (\n <button\n ref={segment.ref as React.MutableRefObject<HTMLButtonElement | null>}\n key={segment.id}\n type=\"button\"\n role=\"tab\"\n id={segment.id}\n aria-controls={segment.controls}\n aria-selected={value === segment.value}\n className={clsx('segmented-control__segment', 'segmented-control__button', {\n 'segmented-control__selected-segment': value === segment.value,\n })}\n onClick={onSelect}\n >\n <Body\n as=\"span\"\n className=\"segmented-control__text\"\n type={\n value === segment.value ? Typography.BODY_DEFAULT_BOLD : Typography.BODY_DEFAULT\n }\n >\n {segment.label}\n </Body>\n </button>\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default SegmentedControl;\n"],"names":["SegmentedControl","name","value","mode","segments","onChange","isMountedRef","useRef","animate","setAnimate","useState","segmentsRef","length","Error","segmentsWithRefs","map","segment","ref","createRef","updateSegmentPosition","selectedSegmentRef","find","current","style","setProperty","offsetWidth","offsetLeft","useEffect","handleWindowSizeChange","window","addEventListener","removeEventListener","_jsx","className","clsx","children","role","undefined","onSelect","_jsxs","htmlFor","id","type","checked","Body","as","Typography","BODY_DEFAULT_BOLD","BODY_DEFAULT","label","controls","onClick"],"mappings":"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"}
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
display: inline-block;
|
|
5
5
|
}
|
|
6
6
|
.np-dot-mask {
|
|
7
|
-
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
8
|
-
mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
9
|
-
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
10
|
-
mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
7
|
+
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
8
|
+
mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
9
|
+
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
10
|
+
mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
11
11
|
}
|
|
12
12
|
.np-dot-badge {
|
|
13
13
|
position: absolute;
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
display: inline-block;
|
|
5
5
|
}
|
|
6
6
|
.np-dot-mask {
|
|
7
|
-
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
8
|
-
mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
9
|
-
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
10
|
-
mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
7
|
+
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
8
|
+
mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
9
|
+
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
10
|
+
mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
11
11
|
}
|
|
12
12
|
.np-dot-badge {
|
|
13
13
|
position: absolute;
|
|
@@ -3238,7 +3238,16 @@ 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
|
|
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 {
|
|
3242
3251
|
font-family: 'Wise Sans', 'Inter', sans-serif;
|
|
3243
3252
|
font-family: var(--font-family-display);
|
|
3244
3253
|
font-synthesis: none;
|
|
@@ -3285,9 +3294,14 @@ a,
|
|
|
3285
3294
|
* of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
|
|
3286
3295
|
* font files are browser-cached and we carried over to launchpad, where it causes issues
|
|
3287
3296
|
* 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.
|
|
3288
3300
|
*/
|
|
3289
3301
|
font-family: 'Inter', Helvetica, Arial, sans-serif;
|
|
3290
3302
|
font-family: var(--font-family-regular);
|
|
3303
|
+
line-height: 1.2;
|
|
3304
|
+
line-height: var(--line-height-title);
|
|
3291
3305
|
}
|
|
3292
3306
|
|
|
3293
3307
|
/* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
flex-grow: 1;
|
|
22
22
|
text-align: right;
|
|
23
23
|
background-color: transparent;
|
|
24
|
+
line-height: inherit;
|
|
24
25
|
}
|
|
25
26
|
.wds-amount-input-input:focus-visible {
|
|
26
27
|
outline: none;
|
|
@@ -29,6 +30,7 @@
|
|
|
29
30
|
flex-grow: 0;
|
|
30
31
|
display: flex;
|
|
31
32
|
align-items: center;
|
|
33
|
+
line-height: inherit;
|
|
32
34
|
}
|
|
33
35
|
.wds-currency-selector:disabled {
|
|
34
36
|
opacity: 1 !important;
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
flex-grow: 1;
|
|
22
22
|
text-align: right;
|
|
23
23
|
background-color: transparent;
|
|
24
|
+
line-height: inherit;
|
|
24
25
|
}
|
|
25
26
|
.wds-amount-input-input:focus-visible {
|
|
26
27
|
outline: none;
|
|
@@ -29,4 +30,5 @@
|
|
|
29
30
|
flex-grow: 0;
|
|
30
31
|
display: flex;
|
|
31
32
|
align-items: center;
|
|
33
|
+
line-height: inherit;
|
|
32
34
|
}
|
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
.np-field-control
|
|
2
|
-
.np-field__prompt {
|
|
1
|
+
.np-field-control {
|
|
3
2
|
margin-top: 4px;
|
|
4
3
|
margin-top: var(--size-4);
|
|
5
4
|
}
|
|
5
|
+
.np-field-validation {
|
|
6
|
+
display: flex;
|
|
7
|
+
align-items: flex-start;
|
|
8
|
+
margin-top: 4px;
|
|
9
|
+
margin-top: var(--size-4);
|
|
10
|
+
gap: 8px;
|
|
11
|
+
gap: var(--size-8);
|
|
12
|
+
}
|
|
13
|
+
.np-field-textarea-char-counter {
|
|
14
|
+
min-width: 55px;
|
|
15
|
+
text-align: right;
|
|
16
|
+
margin-left: auto;
|
|
17
|
+
padding: 4px 0;
|
|
18
|
+
padding: var(--size-4) 0;
|
|
19
|
+
color: #768e9c;
|
|
20
|
+
color: var(--color-content-tertiary);
|
|
21
|
+
}
|
|
6
22
|
.np-field .form-group--typeahead[class],
|
|
7
23
|
.np-field .np-checkbox-label[class] {
|
|
8
24
|
margin-bottom: 0;
|
|
9
25
|
}
|
|
10
|
-
.np-field:has(.wds-radio-group) .np-
|
|
26
|
+
.np-field:has(.wds-radio-group) .np-field-validation {
|
|
11
27
|
margin-top: 12px;
|
|
12
28
|
margin-top: var(--size-12);
|
|
13
29
|
}
|
package/build/styles/main.css
CHANGED
|
@@ -3238,7 +3238,16 @@ 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
|
|
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 {
|
|
3242
3251
|
font-family: 'Wise Sans', 'Inter', sans-serif;
|
|
3243
3252
|
font-family: var(--font-family-display);
|
|
3244
3253
|
font-synthesis: none;
|
|
@@ -3285,9 +3294,14 @@ a,
|
|
|
3285
3294
|
* of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
|
|
3286
3295
|
* font files are browser-cached and we carried over to launchpad, where it causes issues
|
|
3287
3296
|
* 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.
|
|
3288
3300
|
*/
|
|
3289
3301
|
font-family: 'Inter', Helvetica, Arial, sans-serif;
|
|
3290
3302
|
font-family: var(--font-family-regular);
|
|
3303
|
+
line-height: 1.2;
|
|
3304
|
+
line-height: var(--line-height-title);
|
|
3291
3305
|
}
|
|
3292
3306
|
|
|
3293
3307
|
/* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
|
|
@@ -26633,10 +26647,10 @@ a[data-toggle="tooltip"] {
|
|
|
26633
26647
|
}
|
|
26634
26648
|
|
|
26635
26649
|
.np-dot-mask {
|
|
26636
|
-
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
26637
|
-
mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
26638
|
-
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
26639
|
-
mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
26650
|
+
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
26651
|
+
mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
26652
|
+
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
26653
|
+
mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black calc(var(--np-dot-size) / 2 + var(--np-dot-offset) + 0.5px));
|
|
26640
26654
|
}
|
|
26641
26655
|
|
|
26642
26656
|
.np-dot-badge {
|
|
@@ -29935,18 +29949,36 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
|
|
|
29935
29949
|
stroke-dasharray: var(--wds-list-item-spotlight-strokeDashSize) var(--wds-list-item-spotlight-strokeDashSize);
|
|
29936
29950
|
}
|
|
29937
29951
|
|
|
29938
|
-
.np-field-control
|
|
29939
|
-
.np-field__prompt {
|
|
29952
|
+
.np-field-control {
|
|
29940
29953
|
margin-top: 4px;
|
|
29941
29954
|
margin-top: var(--size-4);
|
|
29942
29955
|
}
|
|
29943
29956
|
|
|
29957
|
+
.np-field-validation {
|
|
29958
|
+
display: flex;
|
|
29959
|
+
align-items: flex-start;
|
|
29960
|
+
margin-top: 4px;
|
|
29961
|
+
margin-top: var(--size-4);
|
|
29962
|
+
gap: 8px;
|
|
29963
|
+
gap: var(--size-8);
|
|
29964
|
+
}
|
|
29965
|
+
|
|
29966
|
+
.np-field-textarea-char-counter {
|
|
29967
|
+
min-width: 55px;
|
|
29968
|
+
text-align: right;
|
|
29969
|
+
margin-left: auto;
|
|
29970
|
+
padding: 4px 0;
|
|
29971
|
+
padding: var(--size-4) 0;
|
|
29972
|
+
color: #768e9c;
|
|
29973
|
+
color: var(--color-content-tertiary);
|
|
29974
|
+
}
|
|
29975
|
+
|
|
29944
29976
|
.np-field .form-group--typeahead[class],
|
|
29945
29977
|
.np-field .np-checkbox-label[class] {
|
|
29946
29978
|
margin-bottom: 0;
|
|
29947
29979
|
}
|
|
29948
29980
|
|
|
29949
|
-
.np-field:has(.wds-radio-group) .np-
|
|
29981
|
+
.np-field:has(.wds-radio-group) .np-field-validation {
|
|
29950
29982
|
margin-top: 12px;
|
|
29951
29983
|
margin-top: var(--size-12);
|
|
29952
29984
|
}
|
|
@@ -31052,6 +31084,7 @@ button.np-link {
|
|
|
31052
31084
|
flex-grow: 1;
|
|
31053
31085
|
text-align: right;
|
|
31054
31086
|
background-color: transparent;
|
|
31087
|
+
line-height: inherit;
|
|
31055
31088
|
}
|
|
31056
31089
|
|
|
31057
31090
|
.wds-amount-input-input:focus-visible {
|
|
@@ -31062,6 +31095,7 @@ button.np-link {
|
|
|
31062
31095
|
flex-grow: 0;
|
|
31063
31096
|
display: flex;
|
|
31064
31097
|
align-items: center;
|
|
31098
|
+
line-height: inherit;
|
|
31065
31099
|
}
|
|
31066
31100
|
|
|
31067
31101
|
.wds-currency-selector:disabled {
|
|
@@ -3238,7 +3238,16 @@ 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
|
|
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 {
|
|
3242
3251
|
font-family: 'Wise Sans', 'Inter', sans-serif;
|
|
3243
3252
|
font-family: var(--font-family-display);
|
|
3244
3253
|
font-synthesis: none;
|
|
@@ -3285,9 +3294,14 @@ a,
|
|
|
3285
3294
|
* of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
|
|
3286
3295
|
* font files are browser-cached and we carried over to launchpad, where it causes issues
|
|
3287
3296
|
* 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.
|
|
3288
3300
|
*/
|
|
3289
3301
|
font-family: 'Inter', Helvetica, Arial, sans-serif;
|
|
3290
3302
|
font-family: var(--font-family-regular);
|
|
3303
|
+
line-height: 1.2;
|
|
3304
|
+
line-height: var(--line-height-title);
|
|
3291
3305
|
}
|
|
3292
3306
|
|
|
3293
3307
|
/* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
|
package/build/tabs/Tabs.js
CHANGED