reshaped 3.4.6 → 3.4.7
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/CHANGELOG.md +17 -2
- package/dist/bundle.css +1 -1
- package/dist/bundle.d.ts +2 -0
- package/dist/bundle.js +11 -11
- package/dist/components/Autocomplete/Autocomplete.js +25 -8
- package/dist/components/Autocomplete/Autocomplete.module.css +1 -0
- package/dist/components/Autocomplete/tests/Autocomplete.stories.d.ts +15 -1
- package/dist/components/Autocomplete/tests/Autocomplete.stories.js +193 -64
- package/dist/components/Calendar/Calendar.module.css +1 -1
- package/dist/components/Checkbox/Checkbox.js +17 -4
- package/dist/components/Checkbox/Checkbox.module.css +1 -1
- package/dist/components/Checkbox/Checkbox.types.d.ts +1 -0
- package/dist/components/Checkbox/tests/Checkbox.stories.d.ts +1 -0
- package/dist/components/Checkbox/tests/Checkbox.stories.js +40 -0
- package/dist/components/Dismissible/Dismissible.js +1 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +1 -1
- package/dist/components/FormControl/FormControlLabel.js +2 -7
- package/dist/components/NumberField/NumberField.d.ts +6 -0
- package/dist/components/NumberField/NumberField.js +11 -0
- package/dist/components/NumberField/NumberField.module.css +1 -0
- package/dist/components/NumberField/NumberField.types.d.ts +19 -0
- package/dist/components/NumberField/NumberField.types.js +1 -0
- package/dist/components/NumberField/NumberFieldControlled.d.ts +6 -0
- package/dist/components/NumberField/NumberFieldControlled.js +146 -0
- package/dist/components/NumberField/NumberFieldUncontrolled.d.ts +6 -0
- package/dist/components/NumberField/NumberFieldUncontrolled.js +16 -0
- package/dist/components/NumberField/index.d.ts +2 -0
- package/dist/components/NumberField/index.js +1 -0
- package/dist/components/NumberField/tests/NumberField.stories.d.ts +29 -0
- package/dist/components/NumberField/tests/NumberField.stories.js +215 -0
- package/dist/components/PinField/PinField.module.css +1 -1
- package/dist/components/PinField/PinField.types.d.ts +1 -1
- package/dist/components/PinField/PinFieldControlled.js +1 -0
- package/dist/components/PinField/tests/PinField.stories.js +8 -0
- package/dist/components/Radio/Radio.js +11 -4
- package/dist/components/Radio/Radio.module.css +1 -1
- package/dist/components/Radio/Radio.types.d.ts +1 -0
- package/dist/components/Radio/tests/Radio.stories.d.ts +1 -0
- package/dist/components/Radio/tests/Radio.stories.js +31 -0
- package/dist/components/Select/Select.module.css +1 -1
- package/dist/components/Select/Select.types.d.ts +1 -1
- package/dist/components/Select/tests/Select.stories.js +42 -16
- package/dist/components/Switch/Switch.js +10 -4
- package/dist/components/Switch/Switch.module.css +1 -1
- package/dist/components/Switch/Switch.types.d.ts +1 -1
- package/dist/components/Switch/tests/Switch.stories.js +30 -15
- package/dist/components/TextField/TextField.js +1 -1
- package/dist/components/TextField/TextField.module.css +1 -1
- package/dist/components/TextField/TextField.types.d.ts +2 -2
- package/dist/components/TextField/index.d.ts +1 -1
- package/dist/components/TextField/tests/TextField.stories.js +4 -0
- package/dist/hooks/tests/useScrollLock.stories.d.ts +1 -0
- package/dist/hooks/tests/useScrollLock.stories.js +29 -0
- package/dist/icons/ChevronUp.d.ts +2 -0
- package/dist/icons/ChevronUp.js +5 -0
- package/dist/icons/Minus.d.ts +2 -0
- package/dist/icons/Minus.js +3 -0
- package/dist/icons/Plus.d.ts +2 -2
- package/dist/icons/Plus.js +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/utilities/scroll/lock.js +15 -7
- package/dist/utilities/scroll/lockStandard.d.ts +1 -2
- package/dist/utilities/scroll/lockStandard.js +2 -9
- package/package.json +1 -1
- package/dist/components/Autocomplete/tests/Autocomplete.test.stories.d.ts +0 -27
- package/dist/components/Autocomplete/tests/Autocomplete.test.stories.js +0 -86
@@ -0,0 +1,19 @@
|
|
1
|
+
import type { TextFieldBaseProps } from "../TextField";
|
2
|
+
import type * as G from "../../types/global";
|
3
|
+
export type BaseProps = Omit<TextFieldBaseProps, "endSlot" | "onChange"> & {
|
4
|
+
onChange?: G.ChangeHandler<number>;
|
5
|
+
increaseAriaLabel: string;
|
6
|
+
decreaseAriaLabel: string;
|
7
|
+
min?: number;
|
8
|
+
max?: number;
|
9
|
+
step?: number;
|
10
|
+
};
|
11
|
+
export type ControlledProps = BaseProps & {
|
12
|
+
value: number | null;
|
13
|
+
defaultValue?: never;
|
14
|
+
};
|
15
|
+
export type UncontrolledProps = BaseProps & {
|
16
|
+
value?: never;
|
17
|
+
defaultValue?: number;
|
18
|
+
};
|
19
|
+
export type Props = ControlledProps | UncontrolledProps;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,146 @@
|
|
1
|
+
"use client";
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
3
|
+
import React from "react";
|
4
|
+
import Actionable from "../Actionable/index.js";
|
5
|
+
import Icon from "../Icon/index.js";
|
6
|
+
import TextField from "../TextField/index.js";
|
7
|
+
import IconChevronUp from "../../icons/ChevronUp.js";
|
8
|
+
import IconChevronDown from "../../icons/ChevronDown.js";
|
9
|
+
import IconPlus from "../../icons/Plus.js";
|
10
|
+
import IconMinus from "../../icons/Minus.js";
|
11
|
+
import useElementId from "../../hooks/useElementId.js";
|
12
|
+
import useHotkeys from "../../hooks/useHotkeys.js";
|
13
|
+
import * as keys from "../../constants/keys.js";
|
14
|
+
import s from "./NumberField.module.css";
|
15
|
+
import useHandlerRef from "../../hooks/useHandlerRef.js";
|
16
|
+
import { useFormControl } from "../FormControl/index.js";
|
17
|
+
const NumberFieldControlled = (props) => {
|
18
|
+
const { increaseAriaLabel, decreaseAriaLabel, min, max, step = 1, name, value, onChange, ...textFieldProps } = props;
|
19
|
+
const formControl = useFormControl();
|
20
|
+
const id = useElementId(textFieldProps.id);
|
21
|
+
const inputId = formControl?.attributes.id || props.inputAttributes?.id || id;
|
22
|
+
const disabled = formControl?.disabled || props.disabled;
|
23
|
+
const hasError = formControl?.hasError || props.hasError;
|
24
|
+
const increaseDisabled = disabled || (value && max ? value >= max : false);
|
25
|
+
const decreaseDisabled = disabled || (value && min ? value <= min : false);
|
26
|
+
const inputRef = React.useRef(null);
|
27
|
+
const rootRef = React.useRef(null);
|
28
|
+
const [textValue, setTextValue] = React.useState(value?.toString() || "");
|
29
|
+
// Sync value to a ref to handle holding controlss pressed
|
30
|
+
// And changing it without waiting for a rerender
|
31
|
+
const valueRef = React.useRef(value);
|
32
|
+
const onChangeRef = useHandlerRef(onChange);
|
33
|
+
const pressedTimeoutRef = React.useRef(null);
|
34
|
+
const changeIntervalRef = React.useRef(null);
|
35
|
+
const calculateDirectionalChange = React.useCallback((direction) => {
|
36
|
+
const delta = step * direction;
|
37
|
+
const value = valueRef.current;
|
38
|
+
let nextValue = value === null ? delta : value + delta;
|
39
|
+
if (max !== undefined && nextValue > max)
|
40
|
+
nextValue = max;
|
41
|
+
if (min !== undefined && nextValue < min)
|
42
|
+
nextValue = min;
|
43
|
+
// Keep the right precision and avoid JS rounding errors
|
44
|
+
const floatPartLength = value?.toString().split(".")[1]?.length || 0;
|
45
|
+
return Number(nextValue.toFixed(floatPartLength));
|
46
|
+
}, [step, min, max]);
|
47
|
+
const commitValue = React.useCallback((value, options) => {
|
48
|
+
onChangeRef.current?.({ value, name });
|
49
|
+
// Only update the ref here when typing in the input
|
50
|
+
// Otherwise it will be updated when value changes
|
51
|
+
if (!options?.programmatic)
|
52
|
+
valueRef.current = value;
|
53
|
+
}, [name, onChangeRef]);
|
54
|
+
const handleIncrease = React.useCallback(() => {
|
55
|
+
const nextValue = calculateDirectionalChange(1);
|
56
|
+
commitValue(nextValue, { programmatic: true });
|
57
|
+
}, [calculateDirectionalChange, commitValue]);
|
58
|
+
const handleDecrease = React.useCallback(() => {
|
59
|
+
const nextValue = calculateDirectionalChange(-1);
|
60
|
+
commitValue(nextValue, { programmatic: true });
|
61
|
+
}, [calculateDirectionalChange, commitValue]);
|
62
|
+
const handleChange = (args) => {
|
63
|
+
if (!args.value.match(/^(-?)[0-9]*(\.?)[0-9]*$/))
|
64
|
+
return;
|
65
|
+
setTextValue(args.value);
|
66
|
+
const numberValue = parseFloat(args.value);
|
67
|
+
if (isNaN(numberValue))
|
68
|
+
return;
|
69
|
+
commitValue(numberValue);
|
70
|
+
};
|
71
|
+
const handleControlPointerDown = (e, callback) => {
|
72
|
+
if (disabled)
|
73
|
+
return;
|
74
|
+
callback();
|
75
|
+
if (e.pointerType !== "touch") {
|
76
|
+
inputRef.current?.focus();
|
77
|
+
}
|
78
|
+
pressedTimeoutRef.current = setTimeout(() => {
|
79
|
+
changeIntervalRef.current = setInterval(() => {
|
80
|
+
callback();
|
81
|
+
}, 50);
|
82
|
+
}, 500);
|
83
|
+
};
|
84
|
+
const handleControlPointerUp = () => {
|
85
|
+
if (disabled)
|
86
|
+
return;
|
87
|
+
if (pressedTimeoutRef.current) {
|
88
|
+
clearTimeout(pressedTimeoutRef.current);
|
89
|
+
pressedTimeoutRef.current = null;
|
90
|
+
}
|
91
|
+
if (changeIntervalRef.current) {
|
92
|
+
clearTimeout(changeIntervalRef.current);
|
93
|
+
changeIntervalRef.current = null;
|
94
|
+
}
|
95
|
+
};
|
96
|
+
useHotkeys({
|
97
|
+
[keys.UP]: handleIncrease,
|
98
|
+
[keys.DOWN]: handleDecrease,
|
99
|
+
}, [handleIncrease, handleDecrease], {
|
100
|
+
preventDefault: true,
|
101
|
+
ref: rootRef,
|
102
|
+
});
|
103
|
+
React.useEffect(() => {
|
104
|
+
valueRef.current = value;
|
105
|
+
setTextValue(value?.toString() ?? "");
|
106
|
+
}, [value]);
|
107
|
+
const controlsNode = (_jsxs("span", { className: s.controls, children: [_jsxs(Actionable, { className: s.control, disabled: increaseDisabled, disableFocusRing: true, as: "span", attributes: {
|
108
|
+
"aria-label": increaseAriaLabel,
|
109
|
+
"aria-controls": id,
|
110
|
+
role: "button",
|
111
|
+
tabIndex: increaseDisabled ? undefined : -1,
|
112
|
+
onPointerDown: (e) => handleControlPointerDown(e, handleIncrease),
|
113
|
+
onPointerUp: handleControlPointerUp,
|
114
|
+
onPointerLeave: handleControlPointerUp,
|
115
|
+
// Prevent menu from opening on long press
|
116
|
+
onContextMenu: (e) => e.preventDefault(),
|
117
|
+
}, children: [_jsx(Icon, { svg: IconChevronUp, size: 3, className: s["icon--mouse"] }), _jsx(Icon, { svg: IconPlus, size: 4, className: s["icon--touch"] })] }), _jsxs(Actionable, { className: s.control, disabled: decreaseDisabled, disableFocusRing: true, as: "span", attributes: {
|
118
|
+
"aria-label": decreaseAriaLabel,
|
119
|
+
"aria-controls": id,
|
120
|
+
role: "button",
|
121
|
+
tabIndex: decreaseDisabled ? undefined : -1,
|
122
|
+
onPointerDown: (e) => handleControlPointerDown(e, handleDecrease),
|
123
|
+
onPointerUp: handleControlPointerUp,
|
124
|
+
onPointerLeave: handleControlPointerUp,
|
125
|
+
// Prevent menu from opening on long press
|
126
|
+
onContextMenu: (e) => e.preventDefault(),
|
127
|
+
}, children: [_jsx(Icon, { svg: IconChevronDown, size: 3, className: s["icon--mouse"] }), _jsx(Icon, { svg: IconMinus, size: 4, className: s["icon--touch"] })] })] }));
|
128
|
+
return (_jsx(TextField, { attributes: {
|
129
|
+
...textFieldProps.attributes,
|
130
|
+
role: "group",
|
131
|
+
ref: rootRef,
|
132
|
+
}, id: inputId, hasError: hasError, inputAttributes: {
|
133
|
+
...textFieldProps.inputAttributes,
|
134
|
+
ref: inputRef,
|
135
|
+
inputMode: "numeric",
|
136
|
+
autoComplete: "off",
|
137
|
+
autoCorrect: "off",
|
138
|
+
spellCheck: "false",
|
139
|
+
min,
|
140
|
+
max,
|
141
|
+
step,
|
142
|
+
className: s.field,
|
143
|
+
}, ...textFieldProps, disabled: disabled, value: textValue, onChange: handleChange, name: name, endSlot: controlsNode }));
|
144
|
+
};
|
145
|
+
NumberFieldControlled.displayName = "NumberFieldControlled";
|
146
|
+
export default NumberFieldControlled;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
"use client";
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
3
|
+
import React from "react";
|
4
|
+
import NumberFieldControlled from "./NumberFieldControlled.js";
|
5
|
+
const NumberFieldUncontrolled = (props) => {
|
6
|
+
const { defaultValue, onChange } = props;
|
7
|
+
const [value, setValue] = React.useState(defaultValue ?? null);
|
8
|
+
const handleChange = (args) => {
|
9
|
+
setValue(args.value);
|
10
|
+
if (onChange)
|
11
|
+
onChange(args);
|
12
|
+
};
|
13
|
+
return (_jsx(NumberFieldControlled, { ...props, value: value, defaultValue: undefined, onChange: handleChange }));
|
14
|
+
};
|
15
|
+
NumberFieldUncontrolled.displayName = "NumberFieldUncontrolled";
|
16
|
+
export default NumberFieldUncontrolled;
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default } from "./NumberField.js";
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { StoryObj } from "@storybook/react";
|
2
|
+
import { Mock } from "@storybook/test";
|
3
|
+
declare const _default: {
|
4
|
+
title: string;
|
5
|
+
component: {
|
6
|
+
(props: import("./..").NumberFieldProps): import("react").JSX.Element;
|
7
|
+
displayName: string;
|
8
|
+
};
|
9
|
+
parameters: {
|
10
|
+
iframe: {
|
11
|
+
url: string;
|
12
|
+
};
|
13
|
+
};
|
14
|
+
};
|
15
|
+
export default _default;
|
16
|
+
export declare const base: StoryObj;
|
17
|
+
export declare const disabled: StoryObj<{
|
18
|
+
handleChange: Mock;
|
19
|
+
}>;
|
20
|
+
export declare const defaultValue: StoryObj<{
|
21
|
+
handleChange: Mock;
|
22
|
+
}>;
|
23
|
+
export declare const value: StoryObj<{
|
24
|
+
handleChange: Mock;
|
25
|
+
}>;
|
26
|
+
export declare const minMax: StoryObj;
|
27
|
+
export declare const className: StoryObj;
|
28
|
+
export declare const formControl: StoryObj;
|
29
|
+
export declare const valueChanges: StoryObj;
|
@@ -0,0 +1,215 @@
|
|
1
|
+
import { expect, fn, userEvent } from "@storybook/test";
|
2
|
+
import FormControl from "../../FormControl/index.js";
|
3
|
+
import NumberField from "../index.js";
|
4
|
+
import { Example } from "../../../utilities/storybook/index.js";
|
5
|
+
export default {
|
6
|
+
title: "Components/NumberField",
|
7
|
+
component: NumberField,
|
8
|
+
parameters: {
|
9
|
+
iframe: {
|
10
|
+
url: "https://reshaped.so/docs/components/number-field",
|
11
|
+
},
|
12
|
+
},
|
13
|
+
};
|
14
|
+
export const base = {
|
15
|
+
name: "base",
|
16
|
+
render: () => {
|
17
|
+
return (<Example>
|
18
|
+
<Example.Item title="base">
|
19
|
+
<NumberField name="test-name" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" inputAttributes={{ "aria-label": "Label" }}/>
|
20
|
+
</Example.Item>
|
21
|
+
</Example>);
|
22
|
+
},
|
23
|
+
play: async ({ canvas }) => {
|
24
|
+
const input = canvas.getByRole("textbox");
|
25
|
+
const [increaseButton, decreaseButton] = canvas.getAllByRole("button");
|
26
|
+
expect(input).toHaveAttribute("name", "test-name");
|
27
|
+
expect(increaseButton).toHaveAccessibleName("Increase");
|
28
|
+
expect(decreaseButton).toHaveAccessibleName("Decrease");
|
29
|
+
},
|
30
|
+
};
|
31
|
+
export const disabled = {
|
32
|
+
name: "disabled",
|
33
|
+
args: {
|
34
|
+
handleChange: fn(),
|
35
|
+
},
|
36
|
+
render: (args) => (<NumberField name="test-name" onChange={args.handleChange} increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" disabled inputAttributes={{ "aria-label": "Label" }}/>),
|
37
|
+
play: async ({ canvas, args }) => {
|
38
|
+
const input = canvas.getByRole("textbox");
|
39
|
+
const increaseButton = document.querySelector('[aria-label="Increase"]');
|
40
|
+
const decreaseButton = document.querySelector('[aria-label="Decrease"]');
|
41
|
+
expect(input).toBeDisabled();
|
42
|
+
await userEvent.click(increaseButton);
|
43
|
+
expect(args.handleChange).not.toHaveBeenCalled();
|
44
|
+
await userEvent.click(decreaseButton);
|
45
|
+
expect(args.handleChange).not.toHaveBeenCalled();
|
46
|
+
},
|
47
|
+
};
|
48
|
+
export const defaultValue = {
|
49
|
+
name: "defaultValue, uncontrolled",
|
50
|
+
args: {
|
51
|
+
handleChange: fn(),
|
52
|
+
},
|
53
|
+
render: (args) => (<NumberField name="test-name" defaultValue={2} onChange={args.handleChange} increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" inputAttributes={{ "aria-label": "Label" }}/>),
|
54
|
+
play: async ({ canvas, args }) => {
|
55
|
+
const input = canvas.getByRole("textbox");
|
56
|
+
const [increaseButton, decreaseButton] = canvas.getAllByRole("button");
|
57
|
+
expect(input).toHaveValue("2");
|
58
|
+
input.focus();
|
59
|
+
await userEvent.keyboard("3");
|
60
|
+
expect(args.handleChange).toBeCalledTimes(1);
|
61
|
+
expect(args.handleChange).toHaveBeenLastCalledWith({
|
62
|
+
name: "test-name",
|
63
|
+
value: 23,
|
64
|
+
});
|
65
|
+
expect(input).toHaveValue("23");
|
66
|
+
await userEvent.click(increaseButton);
|
67
|
+
expect(args.handleChange).toBeCalledTimes(2);
|
68
|
+
expect(args.handleChange).toHaveBeenLastCalledWith({
|
69
|
+
name: "test-name",
|
70
|
+
value: 24,
|
71
|
+
});
|
72
|
+
expect(input).toHaveValue("24");
|
73
|
+
await userEvent.click(decreaseButton);
|
74
|
+
expect(args.handleChange).toBeCalledTimes(3);
|
75
|
+
expect(args.handleChange).toHaveBeenLastCalledWith({
|
76
|
+
name: "test-name",
|
77
|
+
value: 23,
|
78
|
+
});
|
79
|
+
expect(input).toHaveValue("23");
|
80
|
+
},
|
81
|
+
};
|
82
|
+
export const value = {
|
83
|
+
name: "value, controlled",
|
84
|
+
args: {
|
85
|
+
handleChange: fn(),
|
86
|
+
},
|
87
|
+
render: (args) => (<NumberField name="test-name" value={2} onChange={args.handleChange} increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" inputAttributes={{ "aria-label": "Label" }}/>),
|
88
|
+
play: async ({ canvas, args }) => {
|
89
|
+
const input = canvas.getByRole("textbox");
|
90
|
+
const [increaseButton, decreaseButton] = canvas.getAllByRole("button");
|
91
|
+
expect(input).toHaveValue("2");
|
92
|
+
input.focus();
|
93
|
+
await userEvent.keyboard("3");
|
94
|
+
expect(args.handleChange).toBeCalledTimes(1);
|
95
|
+
expect(args.handleChange).toHaveBeenLastCalledWith({
|
96
|
+
name: "test-name",
|
97
|
+
value: 23,
|
98
|
+
});
|
99
|
+
expect(input).toHaveValue("23");
|
100
|
+
await userEvent.click(increaseButton);
|
101
|
+
expect(args.handleChange).toBeCalledTimes(2);
|
102
|
+
expect(args.handleChange).toHaveBeenLastCalledWith({
|
103
|
+
name: "test-name",
|
104
|
+
value: 24,
|
105
|
+
});
|
106
|
+
expect(input).toHaveValue("23");
|
107
|
+
await userEvent.click(decreaseButton);
|
108
|
+
expect(args.handleChange).toBeCalledTimes(3);
|
109
|
+
expect(args.handleChange).toHaveBeenLastCalledWith({
|
110
|
+
name: "test-name",
|
111
|
+
value: 22,
|
112
|
+
});
|
113
|
+
expect(input).toHaveValue("23");
|
114
|
+
},
|
115
|
+
};
|
116
|
+
export const minMax = {
|
117
|
+
name: "min, max, step",
|
118
|
+
render: () => (<NumberField name="test-name" defaultValue={6} min={5} max={15} step={5} increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" inputAttributes={{ "aria-label": "Label" }}/>),
|
119
|
+
play: async ({ canvas }) => {
|
120
|
+
const input = canvas.getByRole("textbox");
|
121
|
+
const [increaseButton, decreaseButton] = canvas.getAllByRole("button");
|
122
|
+
expect(input).toHaveValue("6");
|
123
|
+
await userEvent.click(increaseButton);
|
124
|
+
expect(input).toHaveValue("11");
|
125
|
+
await userEvent.click(decreaseButton);
|
126
|
+
await userEvent.click(decreaseButton);
|
127
|
+
expect(input).toHaveValue("5");
|
128
|
+
await userEvent.click(increaseButton);
|
129
|
+
await userEvent.click(increaseButton);
|
130
|
+
await userEvent.click(increaseButton);
|
131
|
+
expect(input).toHaveValue("15");
|
132
|
+
},
|
133
|
+
};
|
134
|
+
export const className = {
|
135
|
+
name: "className, attributes",
|
136
|
+
render: () => (<div data-testid="root">
|
137
|
+
<NumberField className="test-classname" attributes={{ id: "test-id" }} name="name" inputAttributes={{ id: "test-input-id", "aria-label": "Label" }} increaseAriaLabel="Increase" decreaseAriaLabel="Decrease"/>
|
138
|
+
</div>),
|
139
|
+
play: async ({ canvas }) => {
|
140
|
+
const root = canvas.getByTestId("root").firstChild;
|
141
|
+
const input = canvas.getByRole("textbox");
|
142
|
+
expect(root).toHaveClass("test-classname");
|
143
|
+
expect(root).toHaveAttribute("id", "test-id");
|
144
|
+
expect(input).toHaveAttribute("id", "test-input-id");
|
145
|
+
},
|
146
|
+
};
|
147
|
+
export const formControl = {
|
148
|
+
name: "test: FormControl",
|
149
|
+
render: () => (<Example>
|
150
|
+
<Example.Item title="FormControl">
|
151
|
+
<FormControl>
|
152
|
+
<FormControl.Label>Label</FormControl.Label>
|
153
|
+
<NumberField name="name" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease"/>
|
154
|
+
<FormControl.Helper>Helper</FormControl.Helper>
|
155
|
+
</FormControl>
|
156
|
+
</Example.Item>
|
157
|
+
|
158
|
+
<Example.Item title="FormControl, disabled">
|
159
|
+
<FormControl disabled>
|
160
|
+
<FormControl.Label>Label</FormControl.Label>
|
161
|
+
<NumberField name="name" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease"/>
|
162
|
+
<FormControl.Helper>Helper</FormControl.Helper>
|
163
|
+
</FormControl>
|
164
|
+
</Example.Item>
|
165
|
+
|
166
|
+
<Example.Item title="FormControl, error">
|
167
|
+
<FormControl hasError>
|
168
|
+
<FormControl.Label>Label</FormControl.Label>
|
169
|
+
<NumberField name="name" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease"/>
|
170
|
+
<FormControl.Error>Error</FormControl.Error>
|
171
|
+
</FormControl>
|
172
|
+
</Example.Item>
|
173
|
+
</Example>),
|
174
|
+
};
|
175
|
+
export const valueChanges = {
|
176
|
+
name: "test: keyboard",
|
177
|
+
render: () => (<Example>
|
178
|
+
<Example.Item title="keyboard">
|
179
|
+
<NumberField name="name" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease"/>
|
180
|
+
</Example.Item>
|
181
|
+
</Example>),
|
182
|
+
play: async ({ canvas }) => {
|
183
|
+
const input = canvas.getByRole("textbox");
|
184
|
+
input.focus();
|
185
|
+
await userEvent.keyboard("-");
|
186
|
+
expect(input).toHaveValue("-");
|
187
|
+
await userEvent.keyboard("1");
|
188
|
+
expect(input).toHaveValue("-1");
|
189
|
+
await userEvent.keyboard("-");
|
190
|
+
expect(input).toHaveValue("-1");
|
191
|
+
await userEvent.keyboard("2");
|
192
|
+
expect(input).toHaveValue("-12");
|
193
|
+
await userEvent.keyboard("{ArrowUp}");
|
194
|
+
expect(input).toHaveValue("-11");
|
195
|
+
await userEvent.keyboard("{ArrowDown}");
|
196
|
+
expect(input).toHaveValue("-12");
|
197
|
+
await userEvent.keyboard(".");
|
198
|
+
expect(input).toHaveValue("-12.");
|
199
|
+
await userEvent.keyboard("3");
|
200
|
+
expect(input).toHaveValue("-12.3");
|
201
|
+
await userEvent.keyboard(".");
|
202
|
+
expect(input).toHaveValue("-12.3");
|
203
|
+
await userEvent.keyboard("-");
|
204
|
+
expect(input).toHaveValue("-12.3");
|
205
|
+
await userEvent.keyboard("{ArrowUp}");
|
206
|
+
await userEvent.keyboard("{ArrowUp}");
|
207
|
+
await userEvent.keyboard("{ArrowUp}");
|
208
|
+
await userEvent.keyboard("{ArrowUp}");
|
209
|
+
await userEvent.keyboard("{ArrowUp}");
|
210
|
+
expect(input).toHaveValue("-7.3");
|
211
|
+
await userEvent.keyboard("{ArrowDown}");
|
212
|
+
expect(input).toHaveValue("-8.3");
|
213
|
+
},
|
214
|
+
};
|
215
|
+
// Value change edge cases
|
@@ -1 +1 @@
|
|
1
|
-
.root{display:inline-flex
|
1
|
+
.root{display:inline-flex}.input,.root{vertical-align:top}.input{background:transparent;border:transparent;caret-color:transparent;color:transparent;font-size:16px;inset:0;outline:none;padding-left:100%;position:absolute}.item{box-sizing:border-box;cursor:text}.item--focused{border-color:var(--rs-color-border-primary);box-shadow:0 0 0 1px var(--rs-color-border-primary)}.item--focused:empty:before{animation:rs-pin-field-caret 1s ease-out infinite;background:var(--rs-color-foreground-neutral);border-radius:999px;content:"";height:var(--rs-font-size-body-2);left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);width:1px}@media (hover:hover){.root:hover .input{pointer-events:none}}@keyframes rs-pin-field-caret{0%,49.9%,to{opacity:1}50%,99.9%{opacity:0}}
|
@@ -11,6 +11,7 @@ import * as keys from "../../constants/keys.js";
|
|
11
11
|
import { regExpNumericChar, regExpAlphabeticChar, regExpAlphaNumericChar, } from "./PinField.constants.js";
|
12
12
|
import s from "./PinField.module.css";
|
13
13
|
const sizeMap = {
|
14
|
+
small: 7,
|
14
15
|
medium: 9,
|
15
16
|
large: 12,
|
16
17
|
xlarge: 14,
|
@@ -40,6 +40,14 @@ export const variant = () => (<Example>
|
|
40
40
|
</Example.Item>
|
41
41
|
</Example>);
|
42
42
|
export const size = () => (<Example>
|
43
|
+
<Example.Item title="size: small">
|
44
|
+
<PinField name="pin" size="small" inputAttributes={{ "aria-label": "Pin" }}/>
|
45
|
+
</Example.Item>
|
46
|
+
|
47
|
+
<Example.Item title="size: medium">
|
48
|
+
<PinField name="pin" size="medium" inputAttributes={{ "aria-label": "Pin" }}/>
|
49
|
+
</Example.Item>
|
50
|
+
|
43
51
|
<Example.Item title="size: large">
|
44
52
|
<PinField name="pin" size="large" inputAttributes={{ "aria-label": "Pin" }}/>
|
45
53
|
</Example.Item>
|
@@ -1,12 +1,13 @@
|
|
1
1
|
"use client";
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
3
|
-
import { classNames } from "../../utilities/helpers.js";
|
3
|
+
import { classNames, responsiveClassNames, responsivePropDependency } from "../../utilities/helpers.js";
|
4
4
|
import HiddenInput from "../_private/HiddenInput/index.js";
|
5
|
+
import Text from "../Text/index.js";
|
5
6
|
import { useRadioGroup } from "../RadioGroup/index.js";
|
6
7
|
import { useFormControl } from "../FormControl/index.js";
|
7
8
|
import s from "./Radio.module.css";
|
8
9
|
const Radio = (props) => {
|
9
|
-
const { children, value, onChange, onFocus, onBlur, className, attributes, inputAttributes } = props;
|
10
|
+
const { children, value, onChange, onFocus, onBlur, size = "medium", className, attributes, inputAttributes, } = props;
|
10
11
|
const formControl = useFormControl();
|
11
12
|
const radioGroup = useRadioGroup();
|
12
13
|
const hasError = formControl?.hasError || props.hasError || radioGroup?.hasError;
|
@@ -14,7 +15,7 @@ const Radio = (props) => {
|
|
14
15
|
const checked = radioGroup ? radioGroup.value === value : props.checked;
|
15
16
|
const defaultChecked = radioGroup ? undefined : props.defaultChecked;
|
16
17
|
const name = radioGroup ? radioGroup.name : props.name;
|
17
|
-
const rootClassName = classNames(s.root, className, hasError && s["--error"], disabled && s["--disabled"]);
|
18
|
+
const rootClassName = classNames(s.root, className, hasError && s["--error"], disabled && s["--disabled"], size && responsiveClassNames(s, "--size", size));
|
18
19
|
const handleChange = (event) => {
|
19
20
|
if (!name)
|
20
21
|
return;
|
@@ -25,7 +26,13 @@ const Radio = (props) => {
|
|
25
26
|
if (radioGroup?.onChange)
|
26
27
|
radioGroup.onChange(changeArgs);
|
27
28
|
};
|
28
|
-
return (_jsxs("label", { ...attributes, className: rootClassName, children: [_jsxs("span", { className: s.field, children: [_jsx(HiddenInput, { className: s.input, type: "radio", checked: checked, defaultChecked: defaultChecked, name: name, disabled: disabled, value: value, onChange: handleChange, onFocus: onFocus, onBlur: onBlur, attributes: inputAttributes }), _jsx("div", { className: s.decorator })] }), children && _jsx(
|
29
|
+
return (_jsxs("label", { ...attributes, className: rootClassName, children: [_jsxs("span", { className: s.field, children: [_jsx(HiddenInput, { className: s.input, type: "radio", checked: checked, defaultChecked: defaultChecked, name: name, disabled: disabled, value: value, onChange: handleChange, onFocus: onFocus, onBlur: onBlur, attributes: inputAttributes }), _jsx("div", { className: s.decorator })] }), children && (_jsx(Text, { as: "span", variant: responsivePropDependency(size, (size) => {
|
30
|
+
if (size === "large")
|
31
|
+
return "body-2";
|
32
|
+
if (size === "small")
|
33
|
+
return "caption-1";
|
34
|
+
return "body-3";
|
35
|
+
}), children: children }))] }));
|
29
36
|
};
|
30
37
|
Radio.displayName = "Radio";
|
31
38
|
export default Radio;
|
@@ -1 +1 @@
|
|
1
|
-
.root{align-items:center;cursor:pointer;display:inline-flex;user-select:none;vertical-align:top;-webkit-tap-highlight-color:transparent}.root:hover .
|
1
|
+
@layer rs.radio.base;@layer rs.radio.error;@layer rs.radio.checked;@layer rs.radio.disabled;@layer rs.radio.base{.root{align-items:center;cursor:pointer;display:inline-flex;gap:var(--rs-radio-gap);user-select:none;vertical-align:top;-webkit-tap-highlight-color:transparent}.root:hover .decorator{background:var(--rs-color-background-neutral-faded)}.field{position:relative}.decorator{background:var(--rs-color-background-elevation-base);border:1px solid var(--rs-color-border-neutral);border-radius:50%;height:var(--rs-radio-line-height);transition:var(--rs-duration-fast) var(--rs-easing-standard);transition-property:background-color,border-color;width:var(--rs-radio-line-height)}.decorator:after{background:var(--rs-color-on-background-primary);border-radius:50%;content:"";height:calc(var(--rs-radio-line-height) * .4);left:50%;opacity:0;position:absolute;top:50%;transform:translate(-50%,-50%) scale(0);transition:var(--rs-duration-fast) var(--rs-easing-standard);transition-property:opacity,transform;width:calc(var(--rs-radio-line-height) * .4)}.--size-small{--rs-radio-line-height:var(--rs-line-height-caption-1);--rs-radio-gap:var(--rs-unit-x1)}.--size-medium{--rs-radio-line-height:var(--rs-line-height-body-3);--rs-radio-gap:var(--rs-unit-x2)}.--size-large{--rs-radio-line-height:var(--rs-line-height-body-2);--rs-radio-gap:var(--rs-unit-x2)}[data-rs-keyboard] .input:focus+.decorator{box-shadow:var(--rs-focus-shadow)}}@layer rs.radio.error{.root.--error .decorator{border-color:var(--rs-color-border-critical)}}@layer rs.radio.checked{.input:checked+.decorator{background:var(--rs-color-background-primary);border-color:var(--rs-color-background-primary)}.input:checked+.decorator:after{opacity:1;transform:translate(-50%,-50%) scale(1)}}@layer rs.radio.disabled{.root.--disabled{color:var(--rs-color-foreground-disabled);cursor:not-allowed}.root.--disabled .decorator{background:var(--rs-color-background-disabled-faded);border-color:var(--rs-color-border-disabled)}.root.--disabled .decorator:after{background-color:var(--rs-color-foreground-disabled)}.root.--disabled .input:checked+.decorator{background:var(--rs-color-background-disabled);border-color:transparent}}@media (--rs-viewport-m ){.--size-small--m{--rs-radio-line-height:var(--rs-line-height-caption-1);--rs-radio-gap:var(--rs-unit-x1)}.--size-medium--m{--rs-radio-line-height:var(--rs-line-height-body-3);--rs-radio-gap:var(--rs-unit-x2)}.--size-large--m{--rs-radio-line-height:var(--rs-line-height-body-2);--rs-radio-gap:var(--rs-unit-x2)}}@media (--rs-viewport-l ){.--size-small--l{--rs-radio-line-height:var(--rs-line-height-caption-1);--rs-radio-gap:var(--rs-unit-x1)}.--size-medium--l{--rs-radio-line-height:var(--rs-line-height-body-3);--rs-radio-gap:var(--rs-unit-x2)}.--size-large--l{--rs-radio-line-height:var(--rs-line-height-body-2);--rs-radio-gap:var(--rs-unit-x2)}}@media (--rs-viewport-xl ){.--size-small--xl{--rs-radio-line-height:var(--rs-line-height-caption-1);--rs-radio-gap:var(--rs-unit-x1)}.--size-medium--xl{--rs-radio-line-height:var(--rs-line-height-body-3);--rs-radio-gap:var(--rs-unit-x2)}.--size-large--xl{--rs-radio-line-height:var(--rs-line-height-body-2);--rs-radio-gap:var(--rs-unit-x2)}}
|
@@ -12,5 +12,6 @@ declare const _default: {
|
|
12
12
|
};
|
13
13
|
export default _default;
|
14
14
|
export declare const selection: () => import("react").JSX.Element;
|
15
|
+
export declare const size: () => import("react").JSX.Element;
|
15
16
|
export declare const error: () => import("react").JSX.Element;
|
16
17
|
export declare const disabled: () => import("react").JSX.Element;
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { Example } from "../../../utilities/storybook/index.js";
|
2
2
|
import Radio from "../index.js";
|
3
|
+
import View from "../../View/index.js";
|
3
4
|
export default {
|
4
5
|
title: "Components/Radio",
|
5
6
|
component: Radio,
|
@@ -28,6 +29,36 @@ export const selection = () => (<Example>
|
|
28
29
|
</Radio>
|
29
30
|
</Example.Item>
|
30
31
|
</Example>);
|
32
|
+
export const size = () => (<Example>
|
33
|
+
<Example.Item title="size: small">
|
34
|
+
<View gap={4} direction="row">
|
35
|
+
<Radio name="animal" value="dog" size="small" defaultChecked>
|
36
|
+
Radio
|
37
|
+
</Radio>
|
38
|
+
</View>
|
39
|
+
</Example.Item>
|
40
|
+
<Example.Item title="size: medium">
|
41
|
+
<View gap={4} direction="row">
|
42
|
+
<Radio name="animal" value="dog" size="medium">
|
43
|
+
Radio
|
44
|
+
</Radio>
|
45
|
+
</View>
|
46
|
+
</Example.Item>
|
47
|
+
<Example.Item title="size: large">
|
48
|
+
<View gap={4} direction="row">
|
49
|
+
<Radio name="animal" value="dog" size="large">
|
50
|
+
Radio
|
51
|
+
</Radio>
|
52
|
+
</View>
|
53
|
+
</Example.Item>
|
54
|
+
<Example.Item title="size: responsive, s: small, m: large">
|
55
|
+
<View gap={4} direction="row">
|
56
|
+
<Radio name="animal" value="dog" size={{ s: "small", m: "large" }}>
|
57
|
+
Radio
|
58
|
+
</Radio>
|
59
|
+
</View>
|
60
|
+
</Example.Item>
|
61
|
+
</Example>);
|
31
62
|
export const error = () => (<Example>
|
32
63
|
<Example.Item title="error">
|
33
64
|
<Radio name="error" value="dog" hasError>
|
@@ -1 +1 @@
|
|
1
|
-
.root{background:var(--rs-color-background-elevation-base);border:1px solid var(--rs-color-border-neutral);display:flex;overflow:hidden;padding:calc(var(--rs-unit-x1) - 1px) 0;position:relative;z-index:0}.root:focus-within{border-color:var(--rs-color-border-primary);box-shadow:0 0 0 1px var(--rs-color-border-primary)}.input{align-items:center;-webkit-appearance:none;appearance:none;background:none;border:0;box-sizing:border-box;color:var(--rs-color-foreground-neutral);cursor:pointer;display:flex;flex-grow:1;font-family:var(--rs-font-family-body);font-weight:var(--rs-font-weight-regular);outline:none;padding-inline-end:calc(var(--rs-select-chevron-size) + var(--rs-select-gap) * 2 + var(--rs-unit-x1));padding-inline-start:var(--rs-select-gap);position:relative;width:100%;z-index:1}.input::-ms-expand{display:none}.slot{align-items:center;display:flex;flex-shrink:0;padding-inline-start:var(--rs-select-gap);position:relative;z-index:5}.input .slot{padding-inline-end:var(--rs-select-gap);padding-inline-start:0}.arrow{color:var(--rs-color-foreground-neutral-faded);display:flex;inset-block-start:50%;inset-inline-end:var(--rs-select-gap);pointer-events:none;position:absolute;transform:translateY(-50%);z-index:5}.--size-
|
1
|
+
.root{background:var(--rs-color-background-elevation-base);border:1px solid var(--rs-color-border-neutral);display:flex;overflow:hidden;padding:calc(var(--rs-unit-x1) - 1px) 0;position:relative;z-index:0}.root:focus-within{border-color:var(--rs-color-border-primary);box-shadow:0 0 0 1px var(--rs-color-border-primary)}.input{align-items:center;-webkit-appearance:none;appearance:none;background:none;border:0;box-sizing:border-box;color:var(--rs-color-foreground-neutral);cursor:pointer;display:flex;flex-grow:1;font-family:var(--rs-font-family-body);font-weight:var(--rs-font-weight-regular);outline:none;padding-inline-end:calc(var(--rs-select-chevron-size) + var(--rs-select-gap) * 2 + var(--rs-unit-x1));padding-inline-start:var(--rs-select-gap);position:relative;width:100%;z-index:1}.input::-ms-expand{display:none}.slot{align-items:center;display:flex;flex-shrink:0;padding-inline-start:var(--rs-select-gap);position:relative;z-index:5}.input .slot{padding-inline-end:var(--rs-select-gap);padding-inline-start:0}.arrow{color:var(--rs-color-foreground-neutral-faded);display:flex;inset-block-start:50%;inset-inline-end:var(--rs-select-gap);pointer-events:none;position:absolute;transform:translateY(-50%);z-index:5}.--size-small{--rs-select-gap:var(--rs-unit-x2);--rs-select-chevron-size:var(--rs-unit-x4);border-radius:var(--rs-radius-small)}.--size-small .input{font-size:var(--rs-font-size-body-3);letter-spacing:var(--rs-letter-spacing-body-3);line-height:var(--rs-line-height-body-3);padding-block:0}.--size-medium{--rs-select-gap:var(--rs-unit-x2);--rs-select-chevron-size:var(--rs-unit-x4);border-radius:var(--rs-radius-small)}.--size-medium .input{font-size:var(--rs-font-size-body-3);letter-spacing:var(--rs-letter-spacing-body-3);line-height:var(--rs-line-height-body-3);padding-block:var(--rs-unit-x1)}.--size-large{--rs-select-gap:var(--rs-unit-x3);--rs-select-chevron-size:var(--rs-unit-x5);border-radius:var(--rs-radius-medium)}.--size-large .input{font-size:var(--rs-font-size-body-2);letter-spacing:var(--rs-letter-spacing-body-2);line-height:var(--rs-line-height-body-2);padding-block:var(--rs-unit-x2)}.--size-xlarge{--rs-select-gap:var(--rs-unit-x4);--rs-select-chevron-size:var(--rs-unit-x5);border-radius:var(--rs-radius-medium)}.--size-xlarge .input{font-size:var(--rs-font-size-body-2);letter-spacing:var(--rs-letter-spacing-body-2);line-height:var(--rs-line-height-body-2);padding-block:var(--rs-unit-x3)}.root.--variant-faded{background:var(--rs-color-background-neutral-faded);border-color:transparent}.root.--variant-faded:focus-within{border-color:var(--rs-color-border-primary)}.root.--variant-headless{background:transparent;border-color:transparent}.root.--variant-headless.--status-error,.root.--variant-headless.--status-error:focus-within,.root.--variant-headless:focus-within{border-color:transparent;box-shadow:none}.root.--status-error{border-color:var(--rs-color-border-critical)}.root.--status-error:focus-within{border-color:var(--rs-color-border-primary)}.root.--placeholder .input{color:var(--rs-color-foreground-neutral-faded)}.root.--disabled{background:var(--rs-color-background-disabled-faded);border-color:var(--rs-color-border-disabled)}.root.--disabled .arrow,.root.--disabled .input{color:var(--rs-color-foreground-disabled);cursor:not-allowed}@media (--rs-viewport-s ) and (hover:none){.input{font-size:var(--rs-font-size-body-2)!important}}@media (--rs-viewport-m ){.--size-small--m{--rs-select-gap:var(--rs-unit-x2);--rs-select-chevron-size:var(--rs-unit-x4);border-radius:var(--rs-radius-small)}.--size-small--m .input{font-size:var(--rs-font-size-body-3);letter-spacing:var(--rs-letter-spacing-body-3);line-height:var(--rs-line-height-body-3);padding-block:0}.--size-medium--m{--rs-select-gap:var(--rs-unit-x2);--rs-select-chevron-size:var(--rs-unit-x4);border-radius:var(--rs-radius-small)}.--size-medium--m .input{font-size:var(--rs-font-size-body-3);letter-spacing:var(--rs-letter-spacing-body-3);line-height:var(--rs-line-height-body-3);padding-block:var(--rs-unit-x1)}.--size-large--m{--rs-select-gap:var(--rs-unit-x3);--rs-select-chevron-size:var(--rs-unit-x5);border-radius:var(--rs-radius-medium)}.--size-large--m .input{font-size:var(--rs-font-size-body-2);letter-spacing:var(--rs-letter-spacing-body-2);line-height:var(--rs-line-height-body-2);padding-block:var(--rs-unit-x2)}.--size-xlarge--m{--rs-select-gap:var(--rs-unit-x4);--rs-select-chevron-size:var(--rs-unit-x5);border-radius:var(--rs-radius-medium)}.--size-xlarge--m .input{font-size:var(--rs-font-size-body-2);letter-spacing:var(--rs-letter-spacing-body-2);line-height:var(--rs-line-height-body-2);padding-block:var(--rs-unit-x3)}}@media (--rs-viewport-l ){.--size-small--l{--rs-select-gap:var(--rs-unit-x2);--rs-select-chevron-size:var(--rs-unit-x4);border-radius:var(--rs-radius-small)}.--size-small--l .input{font-size:var(--rs-font-size-body-3);letter-spacing:var(--rs-letter-spacing-body-3);line-height:var(--rs-line-height-body-3);padding-block:0}.--size-medium--l{--rs-select-gap:var(--rs-unit-x2);--rs-select-chevron-size:var(--rs-unit-x4);border-radius:var(--rs-radius-small)}.--size-medium--l .input{font-size:var(--rs-font-size-body-3);letter-spacing:var(--rs-letter-spacing-body-3);line-height:var(--rs-line-height-body-3);padding-block:var(--rs-unit-x1)}.--size-large--l{--rs-select-gap:var(--rs-unit-x3);--rs-select-chevron-size:var(--rs-unit-x5);border-radius:var(--rs-radius-medium)}.--size-large--l .input{font-size:var(--rs-font-size-body-2);letter-spacing:var(--rs-letter-spacing-body-2);line-height:var(--rs-line-height-body-2);padding-block:var(--rs-unit-x2)}.--size-xlarge--l{--rs-select-gap:var(--rs-unit-x4);--rs-select-chevron-size:var(--rs-unit-x5);border-radius:var(--rs-radius-medium)}.--size-xlarge--l .input{font-size:var(--rs-font-size-body-2);letter-spacing:var(--rs-letter-spacing-body-2);line-height:var(--rs-line-height-body-2);padding-block:var(--rs-unit-x3)}}@media (--rs-viewport-xl ){.--size-small--xl{--rs-select-gap:var(--rs-unit-x2);--rs-select-chevron-size:var(--rs-unit-x4);border-radius:var(--rs-radius-small)}.--size-small--xl .input{font-size:var(--rs-font-size-body-3);letter-spacing:var(--rs-letter-spacing-body-3);line-height:var(--rs-line-height-body-3);padding-block:0}.--size-medium--xl{--rs-select-gap:var(--rs-unit-x2);--rs-select-chevron-size:var(--rs-unit-x4);border-radius:var(--rs-radius-small)}.--size-medium--xl .input{font-size:var(--rs-font-size-body-3);letter-spacing:var(--rs-letter-spacing-body-3);line-height:var(--rs-line-height-body-3);padding-block:var(--rs-unit-x1)}.--size-large--xl{--rs-select-gap:var(--rs-unit-x3);--rs-select-chevron-size:var(--rs-unit-x5);border-radius:var(--rs-radius-medium)}.--size-large--xl .input{font-size:var(--rs-font-size-body-2);letter-spacing:var(--rs-letter-spacing-body-2);line-height:var(--rs-line-height-body-2);padding-block:var(--rs-unit-x2)}.--size-xlarge--xl{--rs-select-gap:var(--rs-unit-x4);--rs-select-chevron-size:var(--rs-unit-x5);border-radius:var(--rs-radius-medium)}.--size-xlarge--xl .input{font-size:var(--rs-font-size-body-2);letter-spacing:var(--rs-letter-spacing-body-2);line-height:var(--rs-line-height-body-2);padding-block:var(--rs-unit-x3)}}
|