@box/blueprint-web 16.20.0 → 16.20.2
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/dist/lib-esm/accordion/accordion.module.js +1 -1
- package/dist/lib-esm/components.css +471 -415
- package/dist/lib-esm/index.css +471 -415
- package/dist/lib-esm/index.d.ts +1 -0
- package/dist/lib-esm/index.js +1 -0
- package/dist/lib-esm/number-field/constants.d.ts +5 -0
- package/dist/lib-esm/number-field/constants.js +9 -0
- package/dist/lib-esm/number-field/index.d.ts +2 -0
- package/dist/lib-esm/number-field/number-field-control.d.ts +24 -0
- package/dist/lib-esm/number-field/number-field-control.js +82 -0
- package/dist/lib-esm/number-field/number-field.d.ts +9 -0
- package/dist/lib-esm/number-field/number-field.js +140 -0
- package/dist/lib-esm/number-field/number-field.module.js +4 -0
- package/dist/lib-esm/number-field/stepper-button.d.ts +21 -0
- package/dist/lib-esm/number-field/stepper-button.js +41 -0
- package/dist/lib-esm/number-field/types.d.ts +99 -0
- package/package.json +3 -3
package/dist/lib-esm/index.d.ts
CHANGED
|
@@ -39,6 +39,7 @@ export * from './list-item/list-item';
|
|
|
39
39
|
export * from './loading-indicator/loading-indicator';
|
|
40
40
|
export * from './modal';
|
|
41
41
|
export * from './navigation-menu';
|
|
42
|
+
export * from './number-field';
|
|
42
43
|
export * from './page';
|
|
43
44
|
export * from './page-section';
|
|
44
45
|
export * from './password-input';
|
package/dist/lib-esm/index.js
CHANGED
|
@@ -50,6 +50,7 @@ export { LoadingIndicator } from './loading-indicator/loading-indicator.js';
|
|
|
50
50
|
export { AlertModal } from './modal/alert-modal.js';
|
|
51
51
|
export { Modal } from './modal/modal.js';
|
|
52
52
|
export { NavigationMenu } from './navigation-menu/index.js';
|
|
53
|
+
export { NumberField } from './number-field/number-field.js';
|
|
53
54
|
export { Page } from './page/index.js';
|
|
54
55
|
export { PageSection } from './page-section/index.js';
|
|
55
56
|
export { PasswordInput } from './password-input/password-input.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Three digits, the width the design spec draws the control at. */
|
|
2
|
+
declare const NUMBER_FIELD_DEFAULT_MAX = 999;
|
|
3
|
+
/** Non-negative integers only. Also governs what react-aria lets through, keeping the field digits-only. */
|
|
4
|
+
declare const NUMBER_FIELD_FORMAT_OPTIONS: Intl.NumberFormatOptions;
|
|
5
|
+
export { NUMBER_FIELD_DEFAULT_MAX, NUMBER_FIELD_FORMAT_OPTIONS };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Three digits, the width the design spec draws the control at. */
|
|
2
|
+
const NUMBER_FIELD_DEFAULT_MAX = 999;
|
|
3
|
+
/** Non-negative integers only. Also governs what react-aria lets through, keeping the field digits-only. */
|
|
4
|
+
const NUMBER_FIELD_FORMAT_OPTIONS = {
|
|
5
|
+
maximumFractionDigits: 0,
|
|
6
|
+
useGrouping: false
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export { NUMBER_FIELD_DEFAULT_MAX, NUMBER_FIELD_FORMAT_OPTIONS };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type ForwardedRef } from 'react';
|
|
2
|
+
type NumberFieldControlProps = {
|
|
3
|
+
ariaValueMax: number;
|
|
4
|
+
ariaValueMin: number;
|
|
5
|
+
decrementAriaLabel: string;
|
|
6
|
+
hasError: boolean;
|
|
7
|
+
incrementAriaLabel: string;
|
|
8
|
+
inputLength: number;
|
|
9
|
+
inputProps: ComponentPropsWithoutRef<'input'>;
|
|
10
|
+
inputRef: ForwardedRef<HTMLInputElement>;
|
|
11
|
+
isAnimationEnabled: boolean;
|
|
12
|
+
isDecrementDisabled: boolean;
|
|
13
|
+
isDecrementLoading: boolean;
|
|
14
|
+
isIncrementDisabled: boolean;
|
|
15
|
+
isIncrementLoading: boolean;
|
|
16
|
+
labelId: string;
|
|
17
|
+
loadingAriaLabel?: string;
|
|
18
|
+
maxReachedTooltipContent?: string;
|
|
19
|
+
minReachedTooltipContent?: string;
|
|
20
|
+
showDecrementTooltip: boolean;
|
|
21
|
+
showIncrementTooltip: boolean;
|
|
22
|
+
};
|
|
23
|
+
export declare const NumberFieldControl: ({ ariaValueMax, ariaValueMin, decrementAriaLabel, hasError, incrementAriaLabel, inputLength, inputProps, inputRef, isAnimationEnabled, isDecrementDisabled, isDecrementLoading, isIncrementDisabled, isIncrementLoading, labelId, loadingAriaLabel, maxReachedTooltipContent, minReachedTooltipContent, showDecrementTooltip, showIncrementTooltip, }: NumberFieldControlProps) => React.ReactElement;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Minus, Plus } from '@box/blueprint-web-assets/icons/Medium';
|
|
3
|
+
import { useContext } from 'react';
|
|
4
|
+
import { NumberFieldStateContext, useContextProps, InputContext, Group } from 'react-aria-components';
|
|
5
|
+
import { BaseTextInput } from '../primitives/base-text-input/base-text-input.js';
|
|
6
|
+
import { StepperButton } from './stepper-button.js';
|
|
7
|
+
import styles from './number-field.module.js';
|
|
8
|
+
|
|
9
|
+
const NumberFieldControl = ({
|
|
10
|
+
ariaValueMax,
|
|
11
|
+
ariaValueMin,
|
|
12
|
+
decrementAriaLabel,
|
|
13
|
+
hasError,
|
|
14
|
+
incrementAriaLabel,
|
|
15
|
+
inputLength,
|
|
16
|
+
inputProps,
|
|
17
|
+
inputRef,
|
|
18
|
+
isAnimationEnabled,
|
|
19
|
+
isDecrementDisabled,
|
|
20
|
+
isDecrementLoading,
|
|
21
|
+
isIncrementDisabled,
|
|
22
|
+
isIncrementLoading,
|
|
23
|
+
labelId,
|
|
24
|
+
loadingAriaLabel,
|
|
25
|
+
maxReachedTooltipContent,
|
|
26
|
+
minReachedTooltipContent,
|
|
27
|
+
showDecrementTooltip,
|
|
28
|
+
showIncrementTooltip
|
|
29
|
+
}) => {
|
|
30
|
+
const state = useContext(NumberFieldStateContext);
|
|
31
|
+
const [racInputProps, racInputRef] = useContextProps({
|
|
32
|
+
maxLength: inputLength
|
|
33
|
+
}, inputRef, InputContext);
|
|
34
|
+
if (!state) {
|
|
35
|
+
throw new Error('NumberFieldControl must be rendered inside NumberField');
|
|
36
|
+
}
|
|
37
|
+
const decrementLoading = loadingAriaLabel && isDecrementLoading ? {
|
|
38
|
+
loading: true,
|
|
39
|
+
loadingAriaLabel
|
|
40
|
+
} : {};
|
|
41
|
+
const incrementLoading = loadingAriaLabel && isIncrementLoading ? {
|
|
42
|
+
loading: true,
|
|
43
|
+
loadingAriaLabel
|
|
44
|
+
} : {};
|
|
45
|
+
return jsxs(Group, {
|
|
46
|
+
"aria-labelledby": labelId,
|
|
47
|
+
className: styles.control,
|
|
48
|
+
children: [jsx(StepperButton, {
|
|
49
|
+
ariaLabel: decrementAriaLabel,
|
|
50
|
+
className: styles.stepperLeft,
|
|
51
|
+
disabled: isDecrementDisabled,
|
|
52
|
+
icon: Minus,
|
|
53
|
+
onClick: state.decrement,
|
|
54
|
+
showTooltip: showDecrementTooltip,
|
|
55
|
+
tooltipContent: minReachedTooltipContent,
|
|
56
|
+
...decrementLoading
|
|
57
|
+
}), jsx(BaseTextInput, {
|
|
58
|
+
...inputProps,
|
|
59
|
+
...racInputProps,
|
|
60
|
+
ref: racInputRef,
|
|
61
|
+
"aria-valuemax": ariaValueMax,
|
|
62
|
+
"aria-valuemin": ariaValueMin,
|
|
63
|
+
className: styles.input,
|
|
64
|
+
"data-bp-animated": isAnimationEnabled ? 'true' : 'false',
|
|
65
|
+
invalid: hasError,
|
|
66
|
+
label: "",
|
|
67
|
+
// Pinned to the `text` react-aria already sets, since it types this as any input type.
|
|
68
|
+
type: "text"
|
|
69
|
+
}), jsx(StepperButton, {
|
|
70
|
+
ariaLabel: incrementAriaLabel,
|
|
71
|
+
className: styles.stepperRight,
|
|
72
|
+
disabled: isIncrementDisabled,
|
|
73
|
+
icon: Plus,
|
|
74
|
+
onClick: state.increment,
|
|
75
|
+
showTooltip: showIncrementTooltip,
|
|
76
|
+
tooltipContent: maxReachedTooltipContent,
|
|
77
|
+
...incrementLoading
|
|
78
|
+
})]
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export { NumberFieldControl };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type NumberFieldProps } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Numeric form field with a label, a decrement/increment stepper, and optional subtext or error.
|
|
4
|
+
*
|
|
5
|
+
* Formats non-negative whole numbers out of the box; `formatOptions` opens that up to decimals, currency
|
|
6
|
+
* and percent, and doubles as the rule for what may be typed. The control is sized to hold `maxLength`
|
|
7
|
+
* characters and does not grow or shrink with its container.
|
|
8
|
+
*/
|
|
9
|
+
export declare const NumberField: import("react").ForwardRefExoticComponent<NumberFieldProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { NumberField as NumberField$1 } from 'react-aria-components';
|
|
5
|
+
import '../blueprint-configuration-context/blueprint-configuration-context.js';
|
|
6
|
+
import '../blueprint-configuration-context/consts.js';
|
|
7
|
+
import { useBlueprintConfiguration } from '../blueprint-configuration-context/useBlueprintConfiguration.js';
|
|
8
|
+
import { InlineError } from '../primitives/inline-error/inline-error.js';
|
|
9
|
+
import { Text } from '../text/text.js';
|
|
10
|
+
import { useLabelable } from '../util-components/labelable/useLabelable.js';
|
|
11
|
+
import { useUniqueId } from '../utils/useUniqueId.js';
|
|
12
|
+
import { NUMBER_FIELD_FORMAT_OPTIONS, NUMBER_FIELD_DEFAULT_MAX } from './constants.js';
|
|
13
|
+
import { NumberFieldControl } from './number-field-control.js';
|
|
14
|
+
import styles from './number-field.module.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Numeric form field with a label, a decrement/increment stepper, and optional subtext or error.
|
|
18
|
+
*
|
|
19
|
+
* Formats non-negative whole numbers out of the box; `formatOptions` opens that up to decimals, currency
|
|
20
|
+
* and percent, and doubles as the rule for what may be typed. The control is sized to hold `maxLength`
|
|
21
|
+
* characters and does not grow or shrink with its container.
|
|
22
|
+
*/
|
|
23
|
+
const NumberField = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
24
|
+
const {
|
|
25
|
+
className,
|
|
26
|
+
decrementAriaLabel,
|
|
27
|
+
disabled = false,
|
|
28
|
+
error,
|
|
29
|
+
form,
|
|
30
|
+
formatOptions = NUMBER_FIELD_FORMAT_OPTIONS,
|
|
31
|
+
hideLabel = false,
|
|
32
|
+
id,
|
|
33
|
+
incrementAriaLabel,
|
|
34
|
+
label,
|
|
35
|
+
loading = false,
|
|
36
|
+
loadingAriaLabel,
|
|
37
|
+
max = NUMBER_FIELD_DEFAULT_MAX,
|
|
38
|
+
maxLength,
|
|
39
|
+
maxReachedTooltipContent,
|
|
40
|
+
min = 0,
|
|
41
|
+
minReachedTooltipContent,
|
|
42
|
+
name,
|
|
43
|
+
onChange,
|
|
44
|
+
readOnly = false,
|
|
45
|
+
required = false,
|
|
46
|
+
step = 1,
|
|
47
|
+
subtext,
|
|
48
|
+
value,
|
|
49
|
+
'aria-describedby': ariaDescribedByProp,
|
|
50
|
+
...rest
|
|
51
|
+
} = props;
|
|
52
|
+
const uniqueId = useUniqueId('number-field-');
|
|
53
|
+
const inputId = id || uniqueId;
|
|
54
|
+
const labelId = useUniqueId('number-field-label-');
|
|
55
|
+
const subtextId = useUniqueId('number-field-subtext-');
|
|
56
|
+
const inlineErrorId = useUniqueId('number-field-error-');
|
|
57
|
+
const isDecrementLoading = !disabled && (loading === true || loading === 'decrement');
|
|
58
|
+
const isIncrementLoading = !disabled && (loading === true || loading === 'increment');
|
|
59
|
+
const isAnyLoading = isDecrementLoading || isIncrementLoading;
|
|
60
|
+
const isInteractive = !disabled && !readOnly;
|
|
61
|
+
// Hide the error while loading: BaseTextInput suppresses aria-invalid when disabled, so showing
|
|
62
|
+
// InlineError alone would leave an inconsistent a11y state.
|
|
63
|
+
const hasError = !!error && !disabled && !isAnyLoading;
|
|
64
|
+
const hasSubtext = !hasError && !!subtext;
|
|
65
|
+
// Also sizes the control, handed to the stylesheet as `--number-field-digits` below.
|
|
66
|
+
const inputLength = maxLength ?? String(max).length;
|
|
67
|
+
const Label = useLabelable(label, inputId, required);
|
|
68
|
+
// Mirrors TextInput
|
|
69
|
+
const {
|
|
70
|
+
componentsWithAnimationEnabled
|
|
71
|
+
} = useBlueprintConfiguration();
|
|
72
|
+
const isAnimationEnabled = componentsWithAnimationEnabled.includes('TextInput');
|
|
73
|
+
const ariaDescribedBy = clsx(ariaDescribedByProp, {
|
|
74
|
+
[inlineErrorId]: hasError,
|
|
75
|
+
[subtextId]: hasSubtext
|
|
76
|
+
}) || undefined;
|
|
77
|
+
return jsxs(NumberField$1, {
|
|
78
|
+
"aria-describedby": ariaDescribedBy,
|
|
79
|
+
"aria-labelledby": labelId,
|
|
80
|
+
className: clsx(styles.numberField, className),
|
|
81
|
+
formatOptions: formatOptions,
|
|
82
|
+
form: form,
|
|
83
|
+
id: inputId,
|
|
84
|
+
isDisabled: disabled || isAnyLoading,
|
|
85
|
+
isInvalid: hasError,
|
|
86
|
+
isReadOnly: readOnly,
|
|
87
|
+
isRequired: required,
|
|
88
|
+
maxValue: max,
|
|
89
|
+
minValue: min,
|
|
90
|
+
name: name,
|
|
91
|
+
onChange: onChange,
|
|
92
|
+
step: step,
|
|
93
|
+
style: {
|
|
94
|
+
'--number-field-digits': inputLength
|
|
95
|
+
},
|
|
96
|
+
validationBehavior: "native",
|
|
97
|
+
value: value,
|
|
98
|
+
children: [jsx(Label, {
|
|
99
|
+
className: clsx(styles.label, {
|
|
100
|
+
[styles.hidden]: hideLabel
|
|
101
|
+
}),
|
|
102
|
+
hideLabel: hideLabel,
|
|
103
|
+
id: labelId
|
|
104
|
+
}), jsx(NumberFieldControl, {
|
|
105
|
+
ariaValueMax: max,
|
|
106
|
+
ariaValueMin: min,
|
|
107
|
+
decrementAriaLabel: decrementAriaLabel,
|
|
108
|
+
hasError: hasError,
|
|
109
|
+
incrementAriaLabel: incrementAriaLabel,
|
|
110
|
+
inputLength: inputLength,
|
|
111
|
+
inputProps: rest,
|
|
112
|
+
inputRef: forwardedRef,
|
|
113
|
+
isAnimationEnabled: isAnimationEnabled,
|
|
114
|
+
isDecrementDisabled: !isInteractive || value <= min || isAnyLoading && !isDecrementLoading,
|
|
115
|
+
isDecrementLoading: isDecrementLoading,
|
|
116
|
+
isIncrementDisabled: !isInteractive || value >= max || isAnyLoading && !isIncrementLoading,
|
|
117
|
+
isIncrementLoading: isIncrementLoading,
|
|
118
|
+
labelId: labelId,
|
|
119
|
+
loadingAriaLabel: loadingAriaLabel,
|
|
120
|
+
maxReachedTooltipContent: maxReachedTooltipContent,
|
|
121
|
+
minReachedTooltipContent: minReachedTooltipContent,
|
|
122
|
+
showDecrementTooltip: isInteractive && !isAnyLoading && value <= min,
|
|
123
|
+
showIncrementTooltip: isInteractive && !isAnyLoading && value >= max
|
|
124
|
+
}), hasError ? jsx(InlineError, {
|
|
125
|
+
className: styles.inlineError,
|
|
126
|
+
id: inlineErrorId,
|
|
127
|
+
children: error
|
|
128
|
+
}) : hasSubtext && jsx(Text, {
|
|
129
|
+
as: "p",
|
|
130
|
+
className: styles.subtext,
|
|
131
|
+
color: "textOnLightSecondary",
|
|
132
|
+
id: subtextId,
|
|
133
|
+
variant: "caption",
|
|
134
|
+
children: subtext
|
|
135
|
+
})]
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
NumberField.displayName = 'NumberField';
|
|
139
|
+
|
|
140
|
+
export { NumberField };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import '../index.css';
|
|
2
|
+
var styles = {"numberField":"bp_number_field_module_numberField--e9b37","label":"bp_number_field_module_label--e9b37","hidden":"bp_number_field_module_hidden--e9b37","control":"bp_number_field_module_control--e9b37","stepperLeft":"bp_number_field_module_stepperLeft--e9b37","stepperRight":"bp_number_field_module_stepperRight--e9b37","input":"bp_number_field_module_input--e9b37","inlineError":"bp_number_field_module_inlineError--e9b37","subtext":"bp_number_field_module_subtext--e9b37"};
|
|
3
|
+
|
|
4
|
+
export { styles as default };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type RequireAllOrNone } from 'type-fest';
|
|
2
|
+
import { type SvgIconComponent } from '../button/types';
|
|
3
|
+
type StepperLoadingProps = RequireAllOrNone<{
|
|
4
|
+
loading: boolean;
|
|
5
|
+
loadingAriaLabel: string;
|
|
6
|
+
}, 'loading' | 'loadingAriaLabel'>;
|
|
7
|
+
type StepperButtonProps = {
|
|
8
|
+
ariaLabel: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
disabled: boolean;
|
|
11
|
+
icon: SvgIconComponent;
|
|
12
|
+
onClick: () => void;
|
|
13
|
+
showTooltip: boolean;
|
|
14
|
+
tooltipContent?: string;
|
|
15
|
+
} & StepperLoadingProps;
|
|
16
|
+
/**
|
|
17
|
+
* With a boundary tooltip to show, `disabled` gives way to `aria-disabled` so the button stays focusable
|
|
18
|
+
* and hoverable enough to surface it.
|
|
19
|
+
*/
|
|
20
|
+
export declare const StepperButton: ({ ariaLabel, className, disabled, icon, onClick, showTooltip, tooltipContent, ...loadingProps }: StepperButtonProps) => React.ReactElement;
|
|
21
|
+
export type { StepperLoadingProps };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Button } from '../button/button.js';
|
|
3
|
+
import { Tooltip } from '../tooltip/tooltip.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* With a boundary tooltip to show, `disabled` gives way to `aria-disabled` so the button stays focusable
|
|
7
|
+
* and hoverable enough to surface it.
|
|
8
|
+
*/
|
|
9
|
+
const StepperButton = ({
|
|
10
|
+
ariaLabel,
|
|
11
|
+
className,
|
|
12
|
+
disabled,
|
|
13
|
+
icon,
|
|
14
|
+
onClick,
|
|
15
|
+
showTooltip,
|
|
16
|
+
tooltipContent,
|
|
17
|
+
...loadingProps
|
|
18
|
+
}) => {
|
|
19
|
+
const tooltip = showTooltip ? tooltipContent : undefined;
|
|
20
|
+
const button = jsx(Button, {
|
|
21
|
+
...loadingProps,
|
|
22
|
+
accessibleWhenDisabled: !!tooltip,
|
|
23
|
+
"aria-label": ariaLabel,
|
|
24
|
+
className: className,
|
|
25
|
+
disabled: disabled,
|
|
26
|
+
onClick: onClick,
|
|
27
|
+
size: "large",
|
|
28
|
+
startIcon: icon,
|
|
29
|
+
type: "button",
|
|
30
|
+
variant: "secondary"
|
|
31
|
+
});
|
|
32
|
+
if (tooltip) {
|
|
33
|
+
return jsx(Tooltip, {
|
|
34
|
+
content: tooltip,
|
|
35
|
+
children: button
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return button;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export { StepperButton };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type ReactNode } from 'react';
|
|
2
|
+
import { type RequireAllOrNone } from 'type-fest';
|
|
3
|
+
import { type Labelable } from '../util-components/labelable';
|
|
4
|
+
export interface Loading {
|
|
5
|
+
/**
|
|
6
|
+
* Shows a spinner on both steppers, or on just one. The input and the other stepper are disabled while
|
|
7
|
+
* it spins. Requires `loadingAriaLabel`.
|
|
8
|
+
*/
|
|
9
|
+
loading: boolean | 'increment' | 'decrement';
|
|
10
|
+
/** The aria-label for the stepper loading indicators. */
|
|
11
|
+
loadingAriaLabel: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Attributes NumberField sets from its own props, so they cannot be forwarded. `size` is included because
|
|
15
|
+
* the control takes its width from `maxLength`.
|
|
16
|
+
*/
|
|
17
|
+
type ReservedInputAttributes = 'defaultValue' | 'disabled' | 'inputMode' | 'max' | 'min' | 'onBlur' | 'onChange' | 'onKeyDown' | 'pattern' | 'readOnly' | 'required' | 'size' | 'step' | 'type' | 'value';
|
|
18
|
+
/**
|
|
19
|
+
* Remaining props are forwarded to the `<input>`, so the field takes part in native form submission.
|
|
20
|
+
* `className` styles the wrapper holding the label, the control and the subtext.
|
|
21
|
+
*/
|
|
22
|
+
interface NumberFieldBaseProps extends Omit<ComponentPropsWithoutRef<'input'>, ReservedInputAttributes>, Labelable {
|
|
23
|
+
/** Accessible label for the decrement button. */
|
|
24
|
+
decrementAriaLabel: string;
|
|
25
|
+
/**
|
|
26
|
+
* When true, prevents the user from interacting with the field.
|
|
27
|
+
*
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
/** Error message rendered below the control, replacing the subtext and marking the control invalid. */
|
|
32
|
+
error?: ReactNode;
|
|
33
|
+
/**
|
|
34
|
+
* How the value is formatted and, in turn, what may be typed — react-aria parses input with the same
|
|
35
|
+
* options it formats with. Must be a stable reference, so hoist or memoize it.
|
|
36
|
+
*
|
|
37
|
+
* @default { maximumFractionDigits: 0, useGrouping: false }
|
|
38
|
+
*/
|
|
39
|
+
formatOptions?: Intl.NumberFormatOptions;
|
|
40
|
+
/**
|
|
41
|
+
* When true, the label is visually hidden but remains available to assistive technology.
|
|
42
|
+
*
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
hideLabel?: boolean;
|
|
46
|
+
/** Accessible label for the increment button. */
|
|
47
|
+
incrementAriaLabel: string;
|
|
48
|
+
/** The field label rendered above the control. */
|
|
49
|
+
label: Labelable['label'];
|
|
50
|
+
/**
|
|
51
|
+
* The upper bound. Disables the increment button once reached, shows `maxReachedTooltipContent`, and
|
|
52
|
+
* snaps typed commits down to this value.
|
|
53
|
+
*
|
|
54
|
+
* @default 999
|
|
55
|
+
*/
|
|
56
|
+
max?: number;
|
|
57
|
+
/**
|
|
58
|
+
* How many characters the input accepts and is sized to hold. Defaults to the digits of `max`; set it
|
|
59
|
+
* when `formatOptions` needs room for a separator or a sign.
|
|
60
|
+
*/
|
|
61
|
+
maxLength?: number;
|
|
62
|
+
/** Localized tooltip content shown when the increment button is disabled because the value is at max. */
|
|
63
|
+
maxReachedTooltipContent?: string;
|
|
64
|
+
/**
|
|
65
|
+
* The lower bound. Disables the decrement button once reached, shows `minReachedTooltipContent`, and
|
|
66
|
+
* snaps typed commits up to this value.
|
|
67
|
+
*
|
|
68
|
+
* @default 0
|
|
69
|
+
*/
|
|
70
|
+
min?: number;
|
|
71
|
+
/** Localized tooltip content shown when the decrement button is disabled because the value is at min. */
|
|
72
|
+
minReachedTooltipContent?: string;
|
|
73
|
+
/** Called with the new value when a stepper is used, or when the typed draft is committed on blur or Enter. */
|
|
74
|
+
onChange: (value: number) => void;
|
|
75
|
+
/**
|
|
76
|
+
* When true, the value is displayed but cannot be edited and the stepper buttons are inactive.
|
|
77
|
+
*
|
|
78
|
+
* @default false
|
|
79
|
+
*/
|
|
80
|
+
readOnly?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* When true, marks the field as required.
|
|
83
|
+
*
|
|
84
|
+
* @default false
|
|
85
|
+
*/
|
|
86
|
+
required?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* The stepping interval used by the increment and decrement buttons.
|
|
89
|
+
*
|
|
90
|
+
* @default 1
|
|
91
|
+
*/
|
|
92
|
+
step?: number;
|
|
93
|
+
/** Helper text rendered below the control. Not rendered while the field is in its error state. */
|
|
94
|
+
subtext?: string;
|
|
95
|
+
/** The controlled value of the field. Must be used in conjunction with `onChange`. */
|
|
96
|
+
value: number;
|
|
97
|
+
}
|
|
98
|
+
export type NumberFieldProps = NumberFieldBaseProps & RequireAllOrNone<Loading, keyof Loading>;
|
|
99
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@box/blueprint-web",
|
|
3
|
-
"version": "16.20.
|
|
3
|
+
"version": "16.20.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"publishConfig": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@ariakit/react": "0.4.21",
|
|
52
52
|
"@ariakit/react-core": "0.4.21",
|
|
53
|
-
"@box/blueprint-web-assets": "^5.7.
|
|
53
|
+
"@box/blueprint-web-assets": "^5.7.9",
|
|
54
54
|
"@internationalized/date": "^3.12.0",
|
|
55
55
|
"@radix-ui/react-accordion": "1.1.2",
|
|
56
56
|
"@radix-ui/react-checkbox": "1.0.4",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"type-fest": "^3.2.0"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"@box/storybook-utils": "^1.2.
|
|
82
|
+
"@box/storybook-utils": "^1.2.18",
|
|
83
83
|
"@figma/code-connect": "1.4.4",
|
|
84
84
|
"@types/react": "^18.0.0",
|
|
85
85
|
"@types/react-dom": "^18.0.0",
|