@yahoo/uds-mobile 2.24.0-beta.4 → 2.24.0-beta.5
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/components/Avatar/AvatarIcon.cjs +8 -2
- package/dist/components/Avatar/AvatarIcon.d.cts.map +1 -1
- package/dist/components/Avatar/AvatarIcon.d.ts.map +1 -1
- package/dist/components/Avatar/AvatarIcon.js +9 -3
- package/dist/components/Avatar/AvatarIcon.js.map +1 -1
- package/dist/components/Avatar/AvatarImage.cjs +9 -2
- package/dist/components/Avatar/AvatarImage.d.cts.map +1 -1
- package/dist/components/Avatar/AvatarImage.d.ts.map +1 -1
- package/dist/components/Avatar/AvatarImage.js +10 -3
- package/dist/components/Avatar/AvatarImage.js.map +1 -1
- package/dist/components/Avatar/AvatarText.cjs +8 -2
- package/dist/components/Avatar/AvatarText.d.cts.map +1 -1
- package/dist/components/Avatar/AvatarText.d.ts.map +1 -1
- package/dist/components/Avatar/AvatarText.js +9 -3
- package/dist/components/Avatar/AvatarText.js.map +1 -1
- package/dist/components/Avatar/types.d.cts +7 -3
- package/dist/components/Avatar/types.d.cts.map +1 -1
- package/dist/components/Avatar/types.d.ts +7 -3
- package/dist/components/Avatar/types.d.ts.map +1 -1
- package/dist/components/Avatar/utils.cjs +9 -6
- package/dist/components/Avatar/utils.d.cts +2 -2
- package/dist/components/Avatar/utils.d.cts.map +1 -1
- package/dist/components/Avatar/utils.d.ts +2 -2
- package/dist/components/Avatar/utils.d.ts.map +1 -1
- package/dist/components/Avatar/utils.js +9 -6
- package/dist/components/Avatar/utils.js.map +1 -1
- package/dist/components/Button.cjs +5 -1
- package/dist/components/Button.d.cts.map +1 -1
- package/dist/components/Button.d.ts.map +1 -1
- package/dist/components/Button.js +5 -1
- package/dist/components/Button.js.map +1 -1
- package/dist/components/Checkbox.cjs +3 -1
- package/dist/components/Checkbox.js +3 -1
- package/dist/components/Checkbox.js.map +1 -1
- package/dist/components/Icon.cjs +2 -2
- package/dist/components/Icon.js +2 -2
- package/dist/components/Icon.js.map +1 -1
- package/dist/components/Input.cjs +54 -18
- package/dist/components/Input.d.cts +5 -0
- package/dist/components/Input.d.cts.map +1 -1
- package/dist/components/Input.d.ts +5 -0
- package/dist/components/Input.d.ts.map +1 -1
- package/dist/components/Input.js +54 -18
- package/dist/components/Input.js.map +1 -1
- package/dist/components/InputHelpText.cjs +6 -1
- package/dist/components/InputHelpText.d.cts +2 -0
- package/dist/components/InputHelpText.d.cts.map +1 -1
- package/dist/components/InputHelpText.d.ts +2 -0
- package/dist/components/InputHelpText.d.ts.map +1 -1
- package/dist/components/InputHelpText.js +6 -1
- package/dist/components/InputHelpText.js.map +1 -1
- package/dist/components/Select/Select.cjs +11 -2
- package/dist/components/Select/Select.d.cts +2 -0
- package/dist/components/Select/Select.d.cts.map +1 -1
- package/dist/components/Select/Select.d.ts +2 -0
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +11 -2
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/SelectItem.cjs +23 -12
- package/dist/components/Select/SelectItem.d.cts.map +1 -1
- package/dist/components/Select/SelectItem.d.ts.map +1 -1
- package/dist/components/Select/SelectItem.js +23 -12
- package/dist/components/Select/SelectItem.js.map +1 -1
- package/dist/components/Select/SelectTrigger.cjs +28 -13
- package/dist/components/Select/SelectTrigger.d.cts.map +1 -1
- package/dist/components/Select/SelectTrigger.d.ts.map +1 -1
- package/dist/components/Select/SelectTrigger.js +28 -13
- package/dist/components/Select/SelectTrigger.js.map +1 -1
- package/dist/components/Select/types.d.cts +2 -0
- package/dist/components/Select/types.d.cts.map +1 -1
- package/dist/components/Select/types.d.ts +2 -0
- package/dist/components/Select/types.d.ts.map +1 -1
- package/dist/components/Switch.cjs +2 -2
- package/dist/components/Switch.d.cts.map +1 -1
- package/dist/components/Switch.d.ts.map +1 -1
- package/dist/components/Switch.js +2 -2
- package/dist/components/Switch.js.map +1 -1
- package/dist/components/Tabs/Tab.cjs +5 -1
- package/dist/components/Tabs/Tab.d.cts.map +1 -1
- package/dist/components/Tabs/Tab.d.ts.map +1 -1
- package/dist/components/Tabs/Tab.js +5 -1
- package/dist/components/Tabs/Tab.js.map +1 -1
- package/dist/components/Text.cjs +4 -0
- package/dist/components/Text.d.cts.map +1 -1
- package/dist/components/Text.d.ts.map +1 -1
- package/dist/components/Text.js +4 -0
- package/dist/components/Text.js.map +1 -1
- package/dist/components/UDSProvider.cjs +1 -1
- package/dist/components/UDSProvider.js +1 -1
- package/dist/fontScaling/FontScalingContext.cjs +14 -0
- package/dist/fontScaling/FontScalingContext.d.cts +7 -1
- package/dist/fontScaling/FontScalingContext.d.cts.map +1 -1
- package/dist/fontScaling/FontScalingContext.d.ts +7 -1
- package/dist/fontScaling/FontScalingContext.d.ts.map +1 -1
- package/dist/fontScaling/FontScalingContext.js +15 -2
- package/dist/fontScaling/FontScalingContext.js.map +1 -1
- package/dist/fontScaling/constants.cjs +33 -0
- package/dist/fontScaling/constants.d.cts +11 -1
- package/dist/fontScaling/constants.d.cts.map +1 -1
- package/dist/fontScaling/constants.d.ts +11 -1
- package/dist/fontScaling/constants.d.ts.map +1 -1
- package/dist/fontScaling/constants.js +33 -1
- package/dist/fontScaling/constants.js.map +1 -1
- package/dist/fontScaling/index.cjs +2 -1
- package/dist/fontScaling/index.d.cts +2 -2
- package/dist/fontScaling/index.d.ts +2 -2
- package/dist/fontScaling/index.js +3 -3
- package/dist/jest/mocks/styles.cjs +13 -1
- package/dist/jest/mocks/styles.d.cts.map +1 -1
- package/dist/jest/mocks/styles.d.ts.map +1 -1
- package/dist/jest/mocks/styles.js +13 -1
- package/dist/jest/mocks/styles.js.map +1 -1
- package/dist/portal.cjs +8 -2
- package/dist/portal.d.cts.map +1 -1
- package/dist/portal.d.ts.map +1 -1
- package/dist/portal.js +8 -2
- package/dist/portal.js.map +1 -1
- package/package.json +1 -1
package/dist/components/Input.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
2
|
import { HStack } from "./HStack.js";
|
|
3
|
+
import { useFontScale } from "../fontScaling/useFontScale.js";
|
|
4
|
+
import { useMaxFontSizeMultiplier } from "../fontScaling/useMaxFontSizeMultiplier.js";
|
|
3
5
|
import { IconSlot } from "./IconSlot.js";
|
|
4
6
|
import { Text as Text$1 } from "./Text.js";
|
|
5
7
|
import { InputHelpText } from "./InputHelpText.js";
|
|
@@ -45,8 +47,10 @@ import { isFunction } from "lodash-es";
|
|
|
45
47
|
* @see {@link Checkbox} for boolean selections
|
|
46
48
|
* @see {@link Radio} for single-select options
|
|
47
49
|
*/
|
|
48
|
-
const Input = memo(function Input({ label, size = "md", startIcon, endIcon, helpText, helperTextIcon, hasError, disabled, readOnly, required, width = "100%", defaultValue, value: controlledValue, onChangeText, onFocus, onBlur, placeholder, placeholderTextColor, ref, ...textInputProps }) {
|
|
50
|
+
const Input = memo(function Input({ label, size = "md", startIcon, endIcon, helpText, helperTextIcon, hasError, disabled, readOnly, required, width = "100%", defaultValue, value: controlledValue, onChangeText, onFocus, onBlur, placeholder, placeholderTextColor, maxFontSizeMultiplier, ref, ...textInputProps }) {
|
|
49
51
|
const uid = `uds-input-${useId()}`;
|
|
52
|
+
const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
|
|
53
|
+
const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);
|
|
50
54
|
const [internalValue, setInternalValue] = useState(defaultValue ?? "");
|
|
51
55
|
const [isFocused, setIsFocused] = useState(false);
|
|
52
56
|
const isControlled = controlledValue !== void 0;
|
|
@@ -76,25 +80,41 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
|
|
|
76
80
|
width,
|
|
77
81
|
opacity: disabled ? .5 : 1
|
|
78
82
|
}], [width, disabled]);
|
|
79
|
-
const inputWrapperStyle = useMemo(() =>
|
|
80
|
-
inputStyles.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
const inputWrapperStyle = useMemo(() => {
|
|
84
|
+
const { gap, paddingVertical } = inputStyles.inputWrapperStatic;
|
|
85
|
+
const scaledMetrics = fontScaleFactor === 1 ? void 0 : {
|
|
86
|
+
...typeof gap === "number" && { gap: Math.round(gap * fontScaleFactor) },
|
|
87
|
+
...typeof paddingVertical === "number" && { paddingVertical: Math.round(paddingVertical * fontScaleFactor) }
|
|
88
|
+
};
|
|
89
|
+
return [
|
|
90
|
+
inputStyles.inputWrapper,
|
|
91
|
+
inputStyles.inputWrapperStatic,
|
|
92
|
+
inputStyles.inputWrapperDynamic,
|
|
93
|
+
scaledMetrics,
|
|
94
|
+
{
|
|
95
|
+
flexDirection: "row",
|
|
96
|
+
alignItems: "center"
|
|
97
|
+
}
|
|
98
|
+
];
|
|
99
|
+
}, [
|
|
100
|
+
fontScaleFactor,
|
|
88
101
|
inputStyles.inputWrapper,
|
|
89
102
|
inputStyles.inputWrapperStatic,
|
|
90
103
|
inputStyles.inputWrapperDynamic
|
|
91
104
|
]);
|
|
92
|
-
const textInputStyle = useMemo(() =>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
105
|
+
const textInputStyle = useMemo(() => {
|
|
106
|
+
const inputHeight = inputStyles.input.height;
|
|
107
|
+
return [
|
|
108
|
+
inputStyles.input,
|
|
109
|
+
typeof inputHeight === "number" ? { height: Math.round(inputHeight * fontScaleFactor) } : void 0,
|
|
110
|
+
{
|
|
111
|
+
flex: 1,
|
|
112
|
+
includeFontPadding: false,
|
|
113
|
+
textAlignVertical: "center",
|
|
114
|
+
paddingVertical: 0
|
|
115
|
+
}
|
|
116
|
+
];
|
|
117
|
+
}, [fontScaleFactor, inputStyles.input]);
|
|
98
118
|
const labelContent = useMemo(() => {
|
|
99
119
|
if (!label) return null;
|
|
100
120
|
const content = isFunction(label) ? label() : label;
|
|
@@ -103,9 +123,11 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
|
|
|
103
123
|
alignItems: "flex-end",
|
|
104
124
|
spacingBottom: "2",
|
|
105
125
|
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
126
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
106
127
|
style: inputStyles.label,
|
|
107
128
|
children: content
|
|
108
129
|
}), required && /* @__PURE__ */ jsx(Text$1, {
|
|
130
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
109
131
|
style: inputStyles.labelRequired,
|
|
110
132
|
children: "*"
|
|
111
133
|
})]
|
|
@@ -113,6 +135,7 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
|
|
|
113
135
|
}, [
|
|
114
136
|
label,
|
|
115
137
|
required,
|
|
138
|
+
resolvedMaxFontSizeMultiplier,
|
|
116
139
|
inputStyles.label,
|
|
117
140
|
inputStyles.labelRequired
|
|
118
141
|
]);
|
|
@@ -121,17 +144,27 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
|
|
|
121
144
|
return /* @__PURE__ */ jsx(IconSlot, {
|
|
122
145
|
icon: startIcon,
|
|
123
146
|
variant: "outline",
|
|
147
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
124
148
|
style: inputStyles.startIcon
|
|
125
149
|
});
|
|
126
|
-
}, [
|
|
150
|
+
}, [
|
|
151
|
+
startIcon,
|
|
152
|
+
resolvedMaxFontSizeMultiplier,
|
|
153
|
+
inputStyles.startIcon
|
|
154
|
+
]);
|
|
127
155
|
const endIconContent = useMemo(() => {
|
|
128
156
|
if (!endIcon) return null;
|
|
129
157
|
return /* @__PURE__ */ jsx(IconSlot, {
|
|
130
158
|
icon: endIcon,
|
|
131
159
|
variant: "outline",
|
|
160
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
132
161
|
style: inputStyles.endIcon
|
|
133
162
|
});
|
|
134
|
-
}, [
|
|
163
|
+
}, [
|
|
164
|
+
endIcon,
|
|
165
|
+
resolvedMaxFontSizeMultiplier,
|
|
166
|
+
inputStyles.endIcon
|
|
167
|
+
]);
|
|
135
168
|
const helpTextContent = useMemo(() => {
|
|
136
169
|
if (!helpText) return null;
|
|
137
170
|
const content = isFunction(helpText) ? helpText() : helpText;
|
|
@@ -143,6 +176,7 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
|
|
|
143
176
|
readOnly,
|
|
144
177
|
hasError,
|
|
145
178
|
pressed: isFocused,
|
|
179
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
146
180
|
children: content
|
|
147
181
|
});
|
|
148
182
|
}, [
|
|
@@ -152,6 +186,7 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
|
|
|
152
186
|
helperTextIcon,
|
|
153
187
|
isFocused,
|
|
154
188
|
readOnly,
|
|
189
|
+
resolvedMaxFontSizeMultiplier,
|
|
155
190
|
size,
|
|
156
191
|
valueState
|
|
157
192
|
]);
|
|
@@ -176,6 +211,7 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
|
|
|
176
211
|
placeholder,
|
|
177
212
|
placeholderTextColor: computedPlaceholderColor,
|
|
178
213
|
editable: !disabled && !readOnly,
|
|
214
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
179
215
|
style: textInputStyle,
|
|
180
216
|
accessibilityLabel: typeof label === "string" ? label : void 0,
|
|
181
217
|
accessibilityHint: typeof helpText === "string" ? helpText : void 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.js","names":["Text"],"sources":["../../src/components/Input.tsx"],"sourcesContent":["import type { UniversalInputProps } from '@yahoo/uds-types';\nimport { isFunction } from 'lodash-es';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useId, useMemo, useState } from 'react';\nimport type { TextInputProps } from 'react-native';\nimport { TextInput, View } from 'react-native';\n\nimport { inputStyles } from '../../generated/styles';\nimport type { SizeProps } from '../types';\nimport { HStack } from './HStack';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\nimport { InputHelpText } from './InputHelpText';\nimport { Text } from './Text';\nimport { VStack } from './VStack';\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\ninterface InputProps\n extends\n Omit<UniversalInputProps<IconSlotType>, 'width'>,\n Omit<TextInputProps, 'style' | 'editable'>,\n Pick<SizeProps, 'width'> {\n /** Ref to the underlying TextInput element */\n ref?: Ref<TextInput>;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Input Component */\n/* -------------------------------------------------------------------------- */\n\n/**\n * **📦 An input that allows users to enter text and collect data.**\n *\n * @description\n * An input field is a component that takes text typed into it. It can also serve\n * as a way to display a selection and trigger a dropdown menu. Inputs are interactive\n * elements that users can click, tap, or otherwise engage with to collect data.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Input } from '@yahoo/uds-mobile/Input';\n *\n * <Input label=\"Name\" placeholder=\"Enter your name\" required />\n * <Input label=\"Email\" startIcon=\"Mail\" helpText=\"We'll never share your email\" />\n * <Input label=\"Password\" secureTextEntry hasError helpText=\"Password is required\" />\n * ```\n *\n * @usage\n * - Forms: For collecting data like names, emails, passwords, etc.\n * - Search Bars: Allowing users to enter search queries\n * - Filters/Settings: When users need to specify preferences\n * - Feedback/Comments: Letting users leave reviews or comments\n *\n * @accessibility\n * - Label is automatically associated with the input\n * - Help text is announced as accessibility hint\n * - Error state is communicated to screen readers\n * - Disabled state prevents interaction\n *\n * @see {@link Checkbox} for boolean selections\n * @see {@link Radio} for single-select options\n */\nconst Input = memo(function Input({\n // Input props\n label,\n size = 'md',\n startIcon,\n endIcon,\n helpText,\n helperTextIcon,\n hasError,\n disabled,\n readOnly,\n required,\n // Size props\n width = '100%',\n // TextInput props\n defaultValue,\n value: controlledValue,\n onChangeText,\n onFocus,\n onBlur,\n placeholder,\n placeholderTextColor,\n ref,\n ...textInputProps\n}: InputProps) {\n const generatedId = useId();\n const uid = `uds-input-${generatedId}`;\n\n /* --------------------------------- State ---------------------------------- */\n const [internalValue, setInternalValue] = useState(defaultValue ?? '');\n const [isFocused, setIsFocused] = useState(false);\n\n // Support both controlled and uncontrolled modes\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n const valueState = value ? 'filled' : 'empty';\n\n /* -------------------------------- Handlers -------------------------------- */\n const handleChangeText = useCallback(\n (text: string) => {\n if (!isControlled) {\n setInternalValue(text);\n }\n onChangeText?.(text);\n },\n [isControlled, onChangeText],\n );\n\n const handleFocus = useCallback<NonNullable<TextInputProps['onFocus']>>(\n (e) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n [onFocus],\n );\n\n const handleBlur = useCallback<NonNullable<TextInputProps['onBlur']>>(\n (e) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n [onBlur],\n );\n\n /* --------------------------------- Styles --------------------------------- */\n inputStyles.useVariants({\n size,\n value: valueState,\n pressed: isFocused,\n readonly: readOnly,\n invalid: hasError,\n });\n\n // Get placeholder color from theme styles\n const computedPlaceholderColor = placeholderTextColor ?? inputStyles.inputPlaceholder.color;\n\n const rootStyle = useMemo(() => [{ width, opacity: disabled ? 0.5 : 1 }], [width, disabled]);\n\n // `inputWrapper` carries only background/border colors; the size-axis spacing\n // (`inputWrapperStatic`) and border width/radius (`inputWrapperDynamic`) live\n // on their own layers after the wrapper split. All three must be applied to\n // the wrapper View — matching the web component, which drives the static and\n // dynamic layers via separate variants — or the input loses its padding, gap,\n // and border sizing.\n const inputWrapperStyle = useMemo(\n () => [\n inputStyles.inputWrapper,\n inputStyles.inputWrapperStatic,\n inputStyles.inputWrapperDynamic,\n { flexDirection: 'row' as const, alignItems: 'center' as const },\n ],\n [inputStyles.inputWrapper, inputStyles.inputWrapperStatic, inputStyles.inputWrapperDynamic],\n );\n\n // Android-specific fixes: TextInput on Android has rendering issues with text visibility\n // - includeFontPadding: false removes Android's extra font padding that can clip text\n // - textAlignVertical: 'center' ensures text is vertically centered in the input\n // - paddingVertical: 0 removes default padding that interferes with flex layout\n const textInputStyle = useMemo(\n () => [\n inputStyles.input,\n {\n flex: 1,\n includeFontPadding: false,\n textAlignVertical: 'center' as const,\n paddingVertical: 0,\n },\n ],\n [inputStyles.input],\n );\n\n /* ---------------------------- Render Helpers ------------------------------ */\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n const content = isFunction(label) ? label() : label;\n return (\n <HStack columnGap=\"1\" alignItems=\"flex-end\" spacingBottom=\"2\">\n <Text style={inputStyles.label}>{content}</Text>\n {required && <Text style={inputStyles.labelRequired}>*</Text>}\n </HStack>\n );\n }, [label, required, inputStyles.label, inputStyles.labelRequired]);\n\n const startIconContent = useMemo(() => {\n if (!startIcon) {\n return null;\n }\n return <IconSlot icon={startIcon} variant=\"outline\" style={inputStyles.startIcon} />;\n }, [startIcon, inputStyles.startIcon]);\n\n const endIconContent = useMemo(() => {\n if (!endIcon) {\n return null;\n }\n return <IconSlot icon={endIcon} variant=\"outline\" style={inputStyles.endIcon} />;\n }, [endIcon, inputStyles.endIcon]);\n\n const helpTextContent = useMemo(() => {\n if (!helpText) {\n return null;\n }\n const content = isFunction(helpText) ? helpText() : helpText;\n return (\n <InputHelpText\n startIcon={helperTextIcon}\n size={size}\n isFilled={valueState === 'filled'}\n disabled={disabled}\n readOnly={readOnly}\n hasError={hasError}\n pressed={isFocused}\n >\n {content}\n </InputHelpText>\n );\n }, [disabled, hasError, helpText, helperTextIcon, isFocused, readOnly, size, valueState]);\n\n /* --------------------------------- Render --------------------------------- */\n return (\n <VStack style={rootStyle}>\n {labelContent}\n\n <View\n style={inputWrapperStyle}\n accessible\n accessibilityRole=\"none\"\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n >\n {startIconContent}\n\n <TextInput\n ref={ref}\n nativeID={uid}\n value={value}\n onChangeText={handleChangeText}\n onFocus={handleFocus}\n onBlur={handleBlur}\n placeholder={placeholder}\n placeholderTextColor={computedPlaceholderColor}\n editable={!disabled && !readOnly}\n style={textInputStyle}\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n accessibilityHint={typeof helpText === 'string' ? helpText : undefined}\n accessibilityState={{ disabled }}\n {...textInputProps}\n />\n\n {endIconContent}\n </View>\n\n {helpTextContent}\n </VStack>\n );\n});\n\nInput.displayName = 'Input';\n\nexport { Input, type InputProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEA,MAAM,QAAQ,KAAK,SAAS,MAAM,EAEhC,OACA,OAAO,MACP,WACA,SACA,UACA,gBACA,UACA,UACA,UACA,UAEA,QAAQ,QAER,cACA,OAAO,iBACP,cACA,SACA,QACA,aACA,sBACA,KACA,GAAG,kBACU;CAEb,MAAM,MAAM,aADQ,OACgB;CAGpC,MAAM,CAAC,eAAe,oBAAoB,SAAS,gBAAgB,GAAG;CACtE,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CAGjD,MAAM,eAAe,oBAAoB,KAAA;CACzC,MAAM,QAAQ,eAAe,kBAAkB;CAC/C,MAAM,aAAa,QAAQ,WAAW;CAGtC,MAAM,mBAAmB,aACtB,SAAiB;EAChB,IAAI,CAAC,cACH,iBAAiB,KAAK;EAExB,eAAe,KAAK;IAEtB,CAAC,cAAc,aAAa,CAC7B;CAED,MAAM,cAAc,aACjB,MAAM;EACL,aAAa,KAAK;EAClB,UAAU,EAAE;IAEd,CAAC,QAAQ,CACV;CAED,MAAM,aAAa,aAChB,MAAM;EACL,aAAa,MAAM;EACnB,SAAS,EAAE;IAEb,CAAC,OAAO,CACT;CAGD,YAAY,YAAY;EACtB;EACA,OAAO;EACP,SAAS;EACT,UAAU;EACV,SAAS;EACV,CAAC;CAGF,MAAM,2BAA2B,wBAAwB,YAAY,iBAAiB;CAEtF,MAAM,YAAY,cAAc,CAAC;EAAE;EAAO,SAAS,WAAW,KAAM;EAAG,CAAC,EAAE,CAAC,OAAO,SAAS,CAAC;CAQ5F,MAAM,oBAAoB,cAClB;EACJ,YAAY;EACZ,YAAY;EACZ,YAAY;EACZ;GAAE,eAAe;GAAgB,YAAY;GAAmB;EACjE,EACD;EAAC,YAAY;EAAc,YAAY;EAAoB,YAAY;EAAoB,CAC5F;CAMD,MAAM,iBAAiB,cACf,CACJ,YAAY,OACZ;EACE,MAAM;EACN,oBAAoB;EACpB,mBAAmB;EACnB,iBAAiB;EAClB,CACF,EACD,CAAC,YAAY,MAAM,CACpB;CAGD,MAAM,eAAe,cAAc;EACjC,IAAI,CAAC,OACH,OAAO;EAET,MAAM,UAAU,WAAW,MAAM,GAAG,OAAO,GAAG;EAC9C,OACE,qBAAC,QAAD;GAAQ,WAAU;GAAI,YAAW;GAAW,eAAc;aAA1D,CACE,oBAACA,QAAD;IAAM,OAAO,YAAY;cAAQ;IAAe,CAAA,EAC/C,YAAY,oBAACA,QAAD;IAAM,OAAO,YAAY;cAAe;IAAQ,CAAA,CACtD;;IAEV;EAAC;EAAO;EAAU,YAAY;EAAO,YAAY;EAAc,CAAC;CAEnE,MAAM,mBAAmB,cAAc;EACrC,IAAI,CAAC,WACH,OAAO;EAET,OAAO,oBAAC,UAAD;GAAU,MAAM;GAAW,SAAQ;GAAU,OAAO,YAAY;GAAa,CAAA;IACnF,CAAC,WAAW,YAAY,UAAU,CAAC;CAEtC,MAAM,iBAAiB,cAAc;EACnC,IAAI,CAAC,SACH,OAAO;EAET,OAAO,oBAAC,UAAD;GAAU,MAAM;GAAS,SAAQ;GAAU,OAAO,YAAY;GAAW,CAAA;IAC/E,CAAC,SAAS,YAAY,QAAQ,CAAC;CAElC,MAAM,kBAAkB,cAAc;EACpC,IAAI,CAAC,UACH,OAAO;EAET,MAAM,UAAU,WAAW,SAAS,GAAG,UAAU,GAAG;EACpD,OACE,oBAAC,eAAD;GACE,WAAW;GACL;GACN,UAAU,eAAe;GACf;GACA;GACA;GACV,SAAS;aAER;GACa,CAAA;IAEjB;EAAC;EAAU;EAAU;EAAU;EAAgB;EAAW;EAAU;EAAM;EAAW,CAAC;CAGzF,OACE,qBAAC,QAAD;EAAQ,OAAO;YAAf;GACG;GAED,qBAAC,MAAD;IACE,OAAO;IACP,YAAA;IACA,mBAAkB;IAClB,oBAAoB,OAAO,UAAU,WAAW,QAAQ,KAAA;cAJ1D;KAMG;KAED,oBAAC,WAAD;MACO;MACL,UAAU;MACH;MACP,cAAc;MACd,SAAS;MACT,QAAQ;MACK;MACb,sBAAsB;MACtB,UAAU,CAAC,YAAY,CAAC;MACxB,OAAO;MACP,oBAAoB,OAAO,UAAU,WAAW,QAAQ,KAAA;MACxD,mBAAmB,OAAO,aAAa,WAAW,WAAW,KAAA;MAC7D,oBAAoB,EAAE,UAAU;MAChC,GAAI;MACJ,CAAA;KAED;KACI;;GAEN;GACM;;EAEX;AAEF,MAAM,cAAc"}
|
|
1
|
+
{"version":3,"file":"Input.js","names":["Text"],"sources":["../../src/components/Input.tsx"],"sourcesContent":["import type { UniversalInputProps } from '@yahoo/uds-types';\nimport { isFunction } from 'lodash-es';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useId, useMemo, useState } from 'react';\nimport type { TextInputProps } from 'react-native';\nimport { TextInput, View } from 'react-native';\n\nimport { inputStyles } from '../../generated/styles';\nimport { useFontScale } from '../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../fontScaling/useMaxFontSizeMultiplier';\nimport type { SizeProps } from '../types';\nimport { HStack } from './HStack';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\nimport { InputHelpText } from './InputHelpText';\nimport { Text } from './Text';\nimport { VStack } from './VStack';\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\ninterface InputProps\n extends\n Omit<UniversalInputProps<IconSlotType>, 'width'>,\n Omit<TextInputProps, 'style' | 'editable'>,\n Pick<SizeProps, 'width'> {\n /** Ref to the underlying TextInput element */\n ref?: Ref<TextInput>;\n /**\n * Caps the field text, labels, icons, and geometry at the control scale.\n * Set null to remove the cap. @default 2\n */\n maxFontSizeMultiplier?: number | null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Input Component */\n/* -------------------------------------------------------------------------- */\n\n/**\n * **📦 An input that allows users to enter text and collect data.**\n *\n * @description\n * An input field is a component that takes text typed into it. It can also serve\n * as a way to display a selection and trigger a dropdown menu. Inputs are interactive\n * elements that users can click, tap, or otherwise engage with to collect data.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Input } from '@yahoo/uds-mobile/Input';\n *\n * <Input label=\"Name\" placeholder=\"Enter your name\" required />\n * <Input label=\"Email\" startIcon=\"Mail\" helpText=\"We'll never share your email\" />\n * <Input label=\"Password\" secureTextEntry hasError helpText=\"Password is required\" />\n * ```\n *\n * @usage\n * - Forms: For collecting data like names, emails, passwords, etc.\n * - Search Bars: Allowing users to enter search queries\n * - Filters/Settings: When users need to specify preferences\n * - Feedback/Comments: Letting users leave reviews or comments\n *\n * @accessibility\n * - Label is automatically associated with the input\n * - Help text is announced as accessibility hint\n * - Error state is communicated to screen readers\n * - Disabled state prevents interaction\n *\n * @see {@link Checkbox} for boolean selections\n * @see {@link Radio} for single-select options\n */\nconst Input = memo(function Input({\n // Input props\n label,\n size = 'md',\n startIcon,\n endIcon,\n helpText,\n helperTextIcon,\n hasError,\n disabled,\n readOnly,\n required,\n // Size props\n width = '100%',\n // TextInput props\n defaultValue,\n value: controlledValue,\n onChangeText,\n onFocus,\n onBlur,\n placeholder,\n placeholderTextColor,\n maxFontSizeMultiplier,\n ref,\n ...textInputProps\n}: InputProps) {\n const generatedId = useId();\n const uid = `uds-input-${generatedId}`;\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);\n\n /* --------------------------------- State ---------------------------------- */\n const [internalValue, setInternalValue] = useState(defaultValue ?? '');\n const [isFocused, setIsFocused] = useState(false);\n\n // Support both controlled and uncontrolled modes\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n const valueState = value ? 'filled' : 'empty';\n\n /* -------------------------------- Handlers -------------------------------- */\n const handleChangeText = useCallback(\n (text: string) => {\n if (!isControlled) {\n setInternalValue(text);\n }\n onChangeText?.(text);\n },\n [isControlled, onChangeText],\n );\n\n const handleFocus = useCallback<NonNullable<TextInputProps['onFocus']>>(\n (e) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n [onFocus],\n );\n\n const handleBlur = useCallback<NonNullable<TextInputProps['onBlur']>>(\n (e) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n [onBlur],\n );\n\n /* --------------------------------- Styles --------------------------------- */\n inputStyles.useVariants({\n size,\n value: valueState,\n pressed: isFocused,\n readonly: readOnly,\n invalid: hasError,\n });\n\n // Get placeholder color from theme styles\n const computedPlaceholderColor = placeholderTextColor ?? inputStyles.inputPlaceholder.color;\n\n const rootStyle = useMemo(() => [{ width, opacity: disabled ? 0.5 : 1 }], [width, disabled]);\n\n // `inputWrapper` carries only background/border colors; the size-axis spacing\n // (`inputWrapperStatic`) and border width/radius (`inputWrapperDynamic`) live\n // on their own layers after the wrapper split. All three must be applied to\n // the wrapper View — matching the web component, which drives the static and\n // dynamic layers via separate variants — or the input loses its padding, gap,\n // and border sizing.\n const inputWrapperStyle = useMemo(() => {\n const { gap, paddingVertical } = inputStyles.inputWrapperStatic;\n const scaledMetrics =\n fontScaleFactor === 1\n ? undefined\n : {\n ...(typeof gap === 'number' && { gap: Math.round(gap * fontScaleFactor) }),\n ...(typeof paddingVertical === 'number' && {\n paddingVertical: Math.round(paddingVertical * fontScaleFactor),\n }),\n };\n\n return [\n inputStyles.inputWrapper,\n inputStyles.inputWrapperStatic,\n inputStyles.inputWrapperDynamic,\n scaledMetrics,\n { flexDirection: 'row' as const, alignItems: 'center' as const },\n ];\n }, [\n fontScaleFactor,\n inputStyles.inputWrapper,\n inputStyles.inputWrapperStatic,\n inputStyles.inputWrapperDynamic,\n ]);\n\n // Android-specific fixes: TextInput on Android has rendering issues with text visibility\n // - includeFontPadding: false removes Android's extra font padding that can clip text\n // - textAlignVertical: 'center' ensures text is vertically centered in the input\n // - paddingVertical: 0 removes default padding that interferes with flex layout\n const textInputStyle = useMemo(() => {\n const inputHeight = inputStyles.input.height;\n return [\n inputStyles.input,\n typeof inputHeight === 'number'\n ? { height: Math.round(inputHeight * fontScaleFactor) }\n : undefined,\n {\n flex: 1,\n includeFontPadding: false,\n textAlignVertical: 'center' as const,\n paddingVertical: 0,\n },\n ];\n }, [fontScaleFactor, inputStyles.input]);\n\n /* ---------------------------- Render Helpers ------------------------------ */\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n const content = isFunction(label) ? label() : label;\n return (\n <HStack columnGap=\"1\" alignItems=\"flex-end\" spacingBottom=\"2\">\n <Text maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier} style={inputStyles.label}>\n {content}\n </Text>\n {required && (\n <Text\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={inputStyles.labelRequired}\n >\n *\n </Text>\n )}\n </HStack>\n );\n }, [\n label,\n required,\n resolvedMaxFontSizeMultiplier,\n inputStyles.label,\n inputStyles.labelRequired,\n ]);\n\n const startIconContent = useMemo(() => {\n if (!startIcon) {\n return null;\n }\n return (\n <IconSlot\n icon={startIcon}\n variant=\"outline\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={inputStyles.startIcon}\n />\n );\n }, [startIcon, resolvedMaxFontSizeMultiplier, inputStyles.startIcon]);\n\n const endIconContent = useMemo(() => {\n if (!endIcon) {\n return null;\n }\n return (\n <IconSlot\n icon={endIcon}\n variant=\"outline\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={inputStyles.endIcon}\n />\n );\n }, [endIcon, resolvedMaxFontSizeMultiplier, inputStyles.endIcon]);\n\n const helpTextContent = useMemo(() => {\n if (!helpText) {\n return null;\n }\n const content = isFunction(helpText) ? helpText() : helpText;\n return (\n <InputHelpText\n startIcon={helperTextIcon}\n size={size}\n isFilled={valueState === 'filled'}\n disabled={disabled}\n readOnly={readOnly}\n hasError={hasError}\n pressed={isFocused}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n >\n {content}\n </InputHelpText>\n );\n }, [\n disabled,\n hasError,\n helpText,\n helperTextIcon,\n isFocused,\n readOnly,\n resolvedMaxFontSizeMultiplier,\n size,\n valueState,\n ]);\n\n /* --------------------------------- Render --------------------------------- */\n return (\n <VStack style={rootStyle}>\n {labelContent}\n\n <View\n style={inputWrapperStyle}\n accessible\n accessibilityRole=\"none\"\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n >\n {startIconContent}\n\n <TextInput\n ref={ref}\n nativeID={uid}\n value={value}\n onChangeText={handleChangeText}\n onFocus={handleFocus}\n onBlur={handleBlur}\n placeholder={placeholder}\n placeholderTextColor={computedPlaceholderColor}\n editable={!disabled && !readOnly}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={textInputStyle}\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n accessibilityHint={typeof helpText === 'string' ? helpText : undefined}\n accessibilityState={{ disabled }}\n {...textInputProps}\n />\n\n {endIconContent}\n </View>\n\n {helpTextContent}\n </VStack>\n );\n});\n\nInput.displayName = 'Input';\n\nexport { Input, type InputProps };\n"],"mappings":"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"}
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
require("../_virtual/_rolldown/runtime.cjs");
|
|
4
4
|
const require_components_HStack = require("./HStack.cjs");
|
|
5
|
+
const require_fontScaling_useMaxFontSizeMultiplier = require("../fontScaling/useMaxFontSizeMultiplier.cjs");
|
|
5
6
|
const require_components_IconSlot = require("./IconSlot.cjs");
|
|
6
7
|
const require_components_Text = require("./Text.cjs");
|
|
7
8
|
let react = require("react");
|
|
8
9
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
10
|
let generated_styles = require("../../generated/styles");
|
|
10
11
|
//#region src/components/InputHelpText.tsx
|
|
11
|
-
const InputHelpText = (0, react.memo)(function InputHelpText({ children, startIcon, endIcon, iconProps, size = "md", isFilled = false, disabled: _disabled, readOnly, hasError, pressed, ref, ...hStackProps }) {
|
|
12
|
+
const InputHelpText = (0, react.memo)(function InputHelpText({ children, startIcon, endIcon, iconProps, size = "md", isFilled = false, disabled: _disabled, readOnly, hasError, pressed, maxFontSizeMultiplier, ref, ...hStackProps }) {
|
|
12
13
|
const { style: iconStyle, variant = "outline", ...resolvedIconProps } = iconProps ?? {};
|
|
13
14
|
const value = isFilled ? "filled" : "empty";
|
|
15
|
+
const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
|
|
14
16
|
generated_styles.inputStyles.useVariants({
|
|
15
17
|
size,
|
|
16
18
|
value,
|
|
@@ -30,16 +32,19 @@ const InputHelpText = (0, react.memo)(function InputHelpText({ children, startIc
|
|
|
30
32
|
startIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_IconSlot.IconSlot, {
|
|
31
33
|
icon: startIcon,
|
|
32
34
|
variant,
|
|
35
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
33
36
|
style: resolvedIconStyle,
|
|
34
37
|
...resolvedIconProps
|
|
35
38
|
}),
|
|
36
39
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Text.Text, {
|
|
40
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
37
41
|
style: generated_styles.inputStyles.helperText,
|
|
38
42
|
children
|
|
39
43
|
}),
|
|
40
44
|
endIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_IconSlot.IconSlot, {
|
|
41
45
|
icon: endIcon,
|
|
42
46
|
variant,
|
|
47
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
43
48
|
style: resolvedIconStyle,
|
|
44
49
|
...resolvedIconProps
|
|
45
50
|
})
|
|
@@ -30,6 +30,8 @@ interface InputHelpTextProps extends Omit<HStackProps, 'children' | 'ref'> {
|
|
|
30
30
|
hasError?: boolean;
|
|
31
31
|
/** Whether the associated input is focused or pressed. */
|
|
32
32
|
pressed?: boolean;
|
|
33
|
+
/** Caps helper text and icons at the control scale. Set null to remove the cap. @default 2 */
|
|
34
|
+
maxFontSizeMultiplier?: number | null;
|
|
33
35
|
}
|
|
34
36
|
declare const InputHelpText: _$react.NamedExoticComponent<InputHelpTextProps>;
|
|
35
37
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputHelpText.d.cts","names":[],"sources":["../../src/components/InputHelpText.tsx"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"InputHelpText.d.cts","names":[],"sources":["../../src/components/InputHelpText.tsx"],"mappings":";;;;;;;;;UAcU,kBAAA,SAA2B,IAAA,CAAK,WAAA;;EAExC,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,GAAW,SAAA;;EAEX,SAAA,GAAY,YAAA;EAJF;EAMV,OAAA,GAAU,YAAA;EAJC;EAMX,SAAA,GAAY,IAAA,CAAK,aAAA;EAFP;EAIV,IAAA,GAAO,SAAA;EAFK;EAIZ,QAAA;EAdmC;EAgBnC,QAAA;EAhBuC;EAkBvC,QAAA;EAlBwC;EAoBxC,QAAA;EAlBM;EAoBN,OAAA;EAlBA;EAoBA,qBAAA;AAAA;AAAA,cAGI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}
|
|
@@ -30,6 +30,8 @@ interface InputHelpTextProps extends Omit<HStackProps, 'children' | 'ref'> {
|
|
|
30
30
|
hasError?: boolean;
|
|
31
31
|
/** Whether the associated input is focused or pressed. */
|
|
32
32
|
pressed?: boolean;
|
|
33
|
+
/** Caps helper text and icons at the control scale. Set null to remove the cap. @default 2 */
|
|
34
|
+
maxFontSizeMultiplier?: number | null;
|
|
33
35
|
}
|
|
34
36
|
declare const InputHelpText: _$react.NamedExoticComponent<InputHelpTextProps>;
|
|
35
37
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputHelpText.d.ts","names":[],"sources":["../../src/components/InputHelpText.tsx"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"InputHelpText.d.ts","names":[],"sources":["../../src/components/InputHelpText.tsx"],"mappings":";;;;;;;;;UAcU,kBAAA,SAA2B,IAAA,CAAK,WAAA;;EAExC,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,GAAW,SAAA;;EAEX,SAAA,GAAY,YAAA;EAJF;EAMV,OAAA,GAAU,YAAA;EAJC;EAMX,SAAA,GAAY,IAAA,CAAK,aAAA;EAFP;EAIV,IAAA,GAAO,SAAA;EAFK;EAIZ,QAAA;EAdmC;EAgBnC,QAAA;EAhBuC;EAkBvC,QAAA;EAlBwC;EAoBxC,QAAA;EAlBM;EAoBN,OAAA;EAlBA;EAoBA,qBAAA;AAAA;AAAA,cAGI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
2
|
import { HStack } from "./HStack.js";
|
|
3
|
+
import { useMaxFontSizeMultiplier } from "../fontScaling/useMaxFontSizeMultiplier.js";
|
|
3
4
|
import { IconSlot } from "./IconSlot.js";
|
|
4
5
|
import { Text } from "./Text.js";
|
|
5
6
|
import { memo, useMemo } from "react";
|
|
6
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
8
|
import { inputStyles } from "../../generated/styles";
|
|
8
9
|
//#region src/components/InputHelpText.tsx
|
|
9
|
-
const InputHelpText = memo(function InputHelpText({ children, startIcon, endIcon, iconProps, size = "md", isFilled = false, disabled: _disabled, readOnly, hasError, pressed, ref, ...hStackProps }) {
|
|
10
|
+
const InputHelpText = memo(function InputHelpText({ children, startIcon, endIcon, iconProps, size = "md", isFilled = false, disabled: _disabled, readOnly, hasError, pressed, maxFontSizeMultiplier, ref, ...hStackProps }) {
|
|
10
11
|
const { style: iconStyle, variant = "outline", ...resolvedIconProps } = iconProps ?? {};
|
|
11
12
|
const value = isFilled ? "filled" : "empty";
|
|
13
|
+
const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
|
|
12
14
|
inputStyles.useVariants({
|
|
13
15
|
size,
|
|
14
16
|
value,
|
|
@@ -28,16 +30,19 @@ const InputHelpText = memo(function InputHelpText({ children, startIcon, endIcon
|
|
|
28
30
|
startIcon && /* @__PURE__ */ jsx(IconSlot, {
|
|
29
31
|
icon: startIcon,
|
|
30
32
|
variant,
|
|
33
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
31
34
|
style: resolvedIconStyle,
|
|
32
35
|
...resolvedIconProps
|
|
33
36
|
}),
|
|
34
37
|
/* @__PURE__ */ jsx(Text, {
|
|
38
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
35
39
|
style: inputStyles.helperText,
|
|
36
40
|
children
|
|
37
41
|
}),
|
|
38
42
|
endIcon && /* @__PURE__ */ jsx(IconSlot, {
|
|
39
43
|
icon: endIcon,
|
|
40
44
|
variant,
|
|
45
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
41
46
|
style: resolvedIconStyle,
|
|
42
47
|
...resolvedIconProps
|
|
43
48
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputHelpText.js","names":[],"sources":["../../src/components/InputHelpText.tsx"],"sourcesContent":["import type { InputSize } from '@yahoo/uds-types';\nimport type { ReactNode, Ref } from 'react';\nimport { memo, useMemo } from 'react';\nimport type { View } from 'react-native';\n\nimport { inputStyles } from '../../generated/styles';\nimport type { HStackProps } from './HStack';\nimport { HStack } from './HStack';\nimport type { IconSlotProps, IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\nimport type { TextProps } from './Text';\nimport { Text } from './Text';\n\ninterface InputHelpTextProps extends Omit<HStackProps, 'children' | 'ref'> {\n /** Ref to the underlying root View. */\n ref?: Ref<View>;\n /** Helper text content. */\n children?: ReactNode;\n /** Icon to render before the help text. */\n startIcon?: IconSlotType;\n /** Icon to render after the help text. */\n endIcon?: IconSlotType;\n /** Props to apply to both helper icons. */\n iconProps?: Omit<IconSlotProps, 'icon' | 'ref'>;\n /** Input size used to resolve configured helper text styles. */\n size?: InputSize;\n /** Whether the associated input has a value. */\n isFilled?: boolean;\n /** Whether the associated input is disabled. */\n disabled?: boolean;\n /** Whether the associated input is read-only. */\n readOnly?: boolean;\n /** Whether the associated input has a validation error. */\n hasError?: boolean;\n /** Whether the associated input is focused or pressed. */\n pressed?: boolean;\n}\n\nconst InputHelpText = memo(function InputHelpText({\n children,\n startIcon,\n endIcon,\n iconProps,\n size = 'md',\n isFilled = false,\n disabled: _disabled,\n readOnly,\n hasError,\n pressed,\n ref,\n ...hStackProps\n}: InputHelpTextProps) {\n const { style: iconStyle, variant = 'outline', ...resolvedIconProps } = iconProps ?? {};\n const value = isFilled ? 'filled' : 'empty';\n\n inputStyles.useVariants({\n size,\n value,\n pressed,\n readonly: readOnly,\n invalid: hasError,\n });\n\n const resolvedIconStyle = useMemo(\n () => [inputStyles.helperIcon, iconStyle],\n [iconStyle, inputStyles.helperIcon],\n );\n\n if (children === null || children === undefined || children === false) {\n return null;\n }\n\n return (\n <HStack ref={ref} columnGap=\"1\" alignItems=\"center\" spacingTop=\"2\" {...hStackProps}>\n {startIcon && (\n <IconSlot\n icon={startIcon}\n variant={variant}\n style={resolvedIconStyle}\n {...resolvedIconProps}\n />\n )}\n\n <Text
|
|
1
|
+
{"version":3,"file":"InputHelpText.js","names":[],"sources":["../../src/components/InputHelpText.tsx"],"sourcesContent":["import type { InputSize } from '@yahoo/uds-types';\nimport type { ReactNode, Ref } from 'react';\nimport { memo, useMemo } from 'react';\nimport type { View } from 'react-native';\n\nimport { inputStyles } from '../../generated/styles';\nimport { useMaxFontSizeMultiplier } from '../fontScaling/useMaxFontSizeMultiplier';\nimport type { HStackProps } from './HStack';\nimport { HStack } from './HStack';\nimport type { IconSlotProps, IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\nimport type { TextProps } from './Text';\nimport { Text } from './Text';\n\ninterface InputHelpTextProps extends Omit<HStackProps, 'children' | 'ref'> {\n /** Ref to the underlying root View. */\n ref?: Ref<View>;\n /** Helper text content. */\n children?: ReactNode;\n /** Icon to render before the help text. */\n startIcon?: IconSlotType;\n /** Icon to render after the help text. */\n endIcon?: IconSlotType;\n /** Props to apply to both helper icons. */\n iconProps?: Omit<IconSlotProps, 'icon' | 'ref'>;\n /** Input size used to resolve configured helper text styles. */\n size?: InputSize;\n /** Whether the associated input has a value. */\n isFilled?: boolean;\n /** Whether the associated input is disabled. */\n disabled?: boolean;\n /** Whether the associated input is read-only. */\n readOnly?: boolean;\n /** Whether the associated input has a validation error. */\n hasError?: boolean;\n /** Whether the associated input is focused or pressed. */\n pressed?: boolean;\n /** Caps helper text and icons at the control scale. Set null to remove the cap. @default 2 */\n maxFontSizeMultiplier?: number | null;\n}\n\nconst InputHelpText = memo(function InputHelpText({\n children,\n startIcon,\n endIcon,\n iconProps,\n size = 'md',\n isFilled = false,\n disabled: _disabled,\n readOnly,\n hasError,\n pressed,\n maxFontSizeMultiplier,\n ref,\n ...hStackProps\n}: InputHelpTextProps) {\n const { style: iconStyle, variant = 'outline', ...resolvedIconProps } = iconProps ?? {};\n const value = isFilled ? 'filled' : 'empty';\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n\n inputStyles.useVariants({\n size,\n value,\n pressed,\n readonly: readOnly,\n invalid: hasError,\n });\n\n const resolvedIconStyle = useMemo(\n () => [inputStyles.helperIcon, iconStyle],\n [iconStyle, inputStyles.helperIcon],\n );\n\n if (children === null || children === undefined || children === false) {\n return null;\n }\n\n return (\n <HStack ref={ref} columnGap=\"1\" alignItems=\"center\" spacingTop=\"2\" {...hStackProps}>\n {startIcon && (\n <IconSlot\n icon={startIcon}\n variant={variant}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={resolvedIconStyle}\n {...resolvedIconProps}\n />\n )}\n\n <Text\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={inputStyles.helperText as TextProps['style']}\n >\n {children}\n </Text>\n\n {endIcon && (\n <IconSlot\n icon={endIcon}\n variant={variant}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={resolvedIconStyle}\n {...resolvedIconProps}\n />\n )}\n </HStack>\n );\n});\n\nInputHelpText.displayName = 'InputHelpText';\n\nexport { InputHelpText, type InputHelpTextProps };\n"],"mappings":";;;;;;;;;AAyCA,MAAM,gBAAgB,KAAK,SAAS,cAAc,EAChD,UACA,WACA,SACA,WACA,OAAO,MACP,WAAW,OACX,UAAU,WACV,UACA,UACA,SACA,uBACA,KACA,GAAG,eACkB;CACrB,MAAM,EAAE,OAAO,WAAW,UAAU,WAAW,GAAG,sBAAsB,aAAa,EAAE;CACvF,MAAM,QAAQ,WAAW,WAAW;CACpC,MAAM,gCACJ,yBAAyB,WAAW,sBAAsB,IAAI;CAEhE,YAAY,YAAY;EACtB;EACA;EACA;EACA,UAAU;EACV,SAAS;EACV,CAAC;CAEF,MAAM,oBAAoB,cAClB,CAAC,YAAY,YAAY,UAAU,EACzC,CAAC,WAAW,YAAY,WAAW,CACpC;CAED,IAAI,aAAa,QAAQ,aAAa,KAAA,KAAa,aAAa,OAC9D,OAAO;CAGT,OACE,qBAAC,QAAD;EAAa;EAAK,WAAU;EAAI,YAAW;EAAS,YAAW;EAAI,GAAI;YAAvE;GACG,aACC,oBAAC,UAAD;IACE,MAAM;IACG;IACT,uBAAuB;IACvB,OAAO;IACP,GAAI;IACJ,CAAA;GAGJ,oBAAC,MAAD;IACE,uBAAuB;IACvB,OAAO,YAAY;IAElB;IACI,CAAA;GAEN,WACC,oBAAC,UAAD;IACE,MAAM;IACG;IACT,uBAAuB;IACvB,OAAO;IACP,GAAI;IACJ,CAAA;GAEG;;EAEX;AAEF,cAAc,cAAc"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
require("../../_virtual/_rolldown/runtime.cjs");
|
|
4
4
|
const require_components_HStack = require("../HStack.cjs");
|
|
5
|
+
const require_fontScaling_useMaxFontSizeMultiplier = require("../../fontScaling/useMaxFontSizeMultiplier.cjs");
|
|
5
6
|
const require_components_Text = require("../Text.cjs");
|
|
6
7
|
const require_components_InputHelpText = require("../InputHelpText.cjs");
|
|
7
8
|
const require_components_VStack = require("../VStack.cjs");
|
|
@@ -35,8 +36,9 @@ let lodash_es = require("lodash-es");
|
|
|
35
36
|
* </Select>
|
|
36
37
|
* ```
|
|
37
38
|
*/
|
|
38
|
-
const Select = (0, react.memo)(function Select({ label, helpText, helperTextIcon, placeholder, size = "md", disabled, required, hasError, readOnly, width = "100%", reduceMotion = false, startIcon, endIcon, value: valueProp, defaultValue = "", onChange, children, testID }) {
|
|
39
|
+
const Select = (0, react.memo)(function Select({ label, helpText, helperTextIcon, placeholder, size = "md", disabled, required, hasError, readOnly, width = "100%", maxFontSizeMultiplier, reduceMotion = false, startIcon, endIcon, value: valueProp, defaultValue = "", onChange, children, testID }) {
|
|
39
40
|
const uid = `uds-select-${(0, react.useId)()}`;
|
|
41
|
+
const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
|
|
40
42
|
const triggerRef = (0, react.useRef)(null);
|
|
41
43
|
const [triggerRect, setTriggerRect] = (0, react.useState)(null);
|
|
42
44
|
const [highlightedValue, setHighlightedValue] = (0, react.useState)(null);
|
|
@@ -73,7 +75,8 @@ const Select = (0, react.memo)(function Select({ label, helpText, helperTextIcon
|
|
|
73
75
|
width,
|
|
74
76
|
reduceMotion,
|
|
75
77
|
placeholder,
|
|
76
|
-
uid
|
|
78
|
+
uid,
|
|
79
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier
|
|
77
80
|
}), [
|
|
78
81
|
disabled,
|
|
79
82
|
hasError,
|
|
@@ -81,6 +84,7 @@ const Select = (0, react.memo)(function Select({ label, helpText, helperTextIcon
|
|
|
81
84
|
readOnly,
|
|
82
85
|
reduceMotion,
|
|
83
86
|
required,
|
|
87
|
+
resolvedMaxFontSizeMultiplier,
|
|
84
88
|
size,
|
|
85
89
|
uid,
|
|
86
90
|
width
|
|
@@ -133,9 +137,11 @@ const Select = (0, react.memo)(function Select({ label, helpText, helperTextIcon
|
|
|
133
137
|
alignItems: "flex-end",
|
|
134
138
|
spacingBottom: "2",
|
|
135
139
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Text.Text, {
|
|
140
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
136
141
|
style: generated_styles.inputStyles.label,
|
|
137
142
|
children: content
|
|
138
143
|
}), required && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Text.Text, {
|
|
144
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
139
145
|
style: generated_styles.inputStyles.labelRequired,
|
|
140
146
|
children: "*"
|
|
141
147
|
})]
|
|
@@ -143,6 +149,7 @@ const Select = (0, react.memo)(function Select({ label, helpText, helperTextIcon
|
|
|
143
149
|
}, [
|
|
144
150
|
label,
|
|
145
151
|
required,
|
|
152
|
+
resolvedMaxFontSizeMultiplier,
|
|
146
153
|
generated_styles.inputStyles.label,
|
|
147
154
|
generated_styles.inputStyles.labelRequired
|
|
148
155
|
]);
|
|
@@ -157,6 +164,7 @@ const Select = (0, react.memo)(function Select({ label, helpText, helperTextIcon
|
|
|
157
164
|
readOnly,
|
|
158
165
|
hasError,
|
|
159
166
|
pressed: open,
|
|
167
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
160
168
|
children: content
|
|
161
169
|
});
|
|
162
170
|
}, [
|
|
@@ -166,6 +174,7 @@ const Select = (0, react.memo)(function Select({ label, helpText, helperTextIcon
|
|
|
166
174
|
helperTextIcon,
|
|
167
175
|
open,
|
|
168
176
|
readOnly,
|
|
177
|
+
resolvedMaxFontSizeMultiplier,
|
|
169
178
|
size,
|
|
170
179
|
valueState
|
|
171
180
|
]);
|
|
@@ -16,6 +16,8 @@ interface SelectProps extends Omit<UniversalSelectProps<IconSlotType>, 'width'>
|
|
|
16
16
|
onChange?: (value: string) => void;
|
|
17
17
|
/** Container width. @default '100%' */
|
|
18
18
|
width?: number | `${number}%` | '100%';
|
|
19
|
+
/** Caps text, icons, and field geometry at the control scale. Set null to remove the cap. @default 2 */
|
|
20
|
+
maxFontSizeMultiplier?: number | null;
|
|
19
21
|
children?: ReactNode;
|
|
20
22
|
testID?: string;
|
|
21
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.d.cts","names":[],"sources":["../../../src/components/Select/Select.tsx"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"Select.d.cts","names":[],"sources":["../../../src/components/Select/Select.tsx"],"mappings":";;;;;;;UAkBU,WAAA,SAAoB,IAAA,CAAK,oBAAA,CAAqB,YAAA;;EAEtD,WAAA;EAFQ;EAIR,KAAA;;EAEA,YAAA;EANiC;EAQjC,QAAA,IAAY,KAAA;EARgB;EAU5B,KAAA;EAVgC;EAYhC,qBAAA;EACA,QAAA,GAAW,SAAA;EACX,MAAA;AAAA;;;;;;;;;;;;AAAM;;;;;;;;;;;cAyBF,MAAA,EAAM,OAAA,CAAA,oBAAA,CAAA,WAAA"}
|
|
@@ -16,6 +16,8 @@ interface SelectProps extends Omit<UniversalSelectProps<IconSlotType>, 'width'>
|
|
|
16
16
|
onChange?: (value: string) => void;
|
|
17
17
|
/** Container width. @default '100%' */
|
|
18
18
|
width?: number | `${number}%` | '100%';
|
|
19
|
+
/** Caps text, icons, and field geometry at the control scale. Set null to remove the cap. @default 2 */
|
|
20
|
+
maxFontSizeMultiplier?: number | null;
|
|
19
21
|
children?: ReactNode;
|
|
20
22
|
testID?: string;
|
|
21
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.d.ts","names":[],"sources":["../../../src/components/Select/Select.tsx"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"Select.d.ts","names":[],"sources":["../../../src/components/Select/Select.tsx"],"mappings":";;;;;;;UAkBU,WAAA,SAAoB,IAAA,CAAK,oBAAA,CAAqB,YAAA;;EAEtD,WAAA;EAFQ;EAIR,KAAA;;EAEA,YAAA;EANiC;EAQjC,QAAA,IAAY,KAAA;EARgB;EAU5B,KAAA;EAVgC;EAYhC,qBAAA;EACA,QAAA,GAAW,SAAA;EACX,MAAA;AAAA;;;;;;;;;;;;AAAM;;;;;;;;;;;cAyBF,MAAA,EAAM,OAAA,CAAA,oBAAA,CAAA,WAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
2
|
import { HStack } from "../HStack.js";
|
|
3
|
+
import { useMaxFontSizeMultiplier } from "../../fontScaling/useMaxFontSizeMultiplier.js";
|
|
3
4
|
import { Text } from "../Text.js";
|
|
4
5
|
import { InputHelpText } from "../InputHelpText.js";
|
|
5
6
|
import { VStack } from "../VStack.js";
|
|
@@ -33,8 +34,9 @@ import { isFunction } from "lodash-es";
|
|
|
33
34
|
* </Select>
|
|
34
35
|
* ```
|
|
35
36
|
*/
|
|
36
|
-
const Select = memo(function Select({ label, helpText, helperTextIcon, placeholder, size = "md", disabled, required, hasError, readOnly, width = "100%", reduceMotion = false, startIcon, endIcon, value: valueProp, defaultValue = "", onChange, children, testID }) {
|
|
37
|
+
const Select = memo(function Select({ label, helpText, helperTextIcon, placeholder, size = "md", disabled, required, hasError, readOnly, width = "100%", maxFontSizeMultiplier, reduceMotion = false, startIcon, endIcon, value: valueProp, defaultValue = "", onChange, children, testID }) {
|
|
37
38
|
const uid = `uds-select-${useId()}`;
|
|
39
|
+
const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
|
|
38
40
|
const triggerRef = useRef(null);
|
|
39
41
|
const [triggerRect, setTriggerRect] = useState(null);
|
|
40
42
|
const [highlightedValue, setHighlightedValue] = useState(null);
|
|
@@ -71,7 +73,8 @@ const Select = memo(function Select({ label, helpText, helperTextIcon, placehold
|
|
|
71
73
|
width,
|
|
72
74
|
reduceMotion,
|
|
73
75
|
placeholder,
|
|
74
|
-
uid
|
|
76
|
+
uid,
|
|
77
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier
|
|
75
78
|
}), [
|
|
76
79
|
disabled,
|
|
77
80
|
hasError,
|
|
@@ -79,6 +82,7 @@ const Select = memo(function Select({ label, helpText, helperTextIcon, placehold
|
|
|
79
82
|
readOnly,
|
|
80
83
|
reduceMotion,
|
|
81
84
|
required,
|
|
85
|
+
resolvedMaxFontSizeMultiplier,
|
|
82
86
|
size,
|
|
83
87
|
uid,
|
|
84
88
|
width
|
|
@@ -131,9 +135,11 @@ const Select = memo(function Select({ label, helpText, helperTextIcon, placehold
|
|
|
131
135
|
alignItems: "flex-end",
|
|
132
136
|
spacingBottom: "2",
|
|
133
137
|
children: [/* @__PURE__ */ jsx(Text, {
|
|
138
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
134
139
|
style: inputStyles.label,
|
|
135
140
|
children: content
|
|
136
141
|
}), required && /* @__PURE__ */ jsx(Text, {
|
|
142
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
137
143
|
style: inputStyles.labelRequired,
|
|
138
144
|
children: "*"
|
|
139
145
|
})]
|
|
@@ -141,6 +147,7 @@ const Select = memo(function Select({ label, helpText, helperTextIcon, placehold
|
|
|
141
147
|
}, [
|
|
142
148
|
label,
|
|
143
149
|
required,
|
|
150
|
+
resolvedMaxFontSizeMultiplier,
|
|
144
151
|
inputStyles.label,
|
|
145
152
|
inputStyles.labelRequired
|
|
146
153
|
]);
|
|
@@ -155,6 +162,7 @@ const Select = memo(function Select({ label, helpText, helperTextIcon, placehold
|
|
|
155
162
|
readOnly,
|
|
156
163
|
hasError,
|
|
157
164
|
pressed: open,
|
|
165
|
+
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
158
166
|
children: content
|
|
159
167
|
});
|
|
160
168
|
}, [
|
|
@@ -164,6 +172,7 @@ const Select = memo(function Select({ label, helpText, helperTextIcon, placehold
|
|
|
164
172
|
helperTextIcon,
|
|
165
173
|
open,
|
|
166
174
|
readOnly,
|
|
175
|
+
resolvedMaxFontSizeMultiplier,
|
|
167
176
|
size,
|
|
168
177
|
valueState
|
|
169
178
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.js","names":[],"sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import type { UniversalSelectProps } from '@yahoo/uds-types';\nimport { isFunction } from 'lodash-es';\nimport type { ReactNode } from 'react';\nimport { memo, useCallback, useId, useMemo, useRef, useState } from 'react';\nimport type { View } from 'react-native';\n\nimport { inputStyles } from '../../../generated/styles';\nimport { HStack } from '../HStack';\nimport type { IconSlotType } from '../IconSlot';\nimport { InputHelpText } from '../InputHelpText';\nimport { useControllableState } from '../internal/Overlay';\nimport { Text } from '../Text';\nimport { VStack } from '../VStack';\nimport { SelectContext, SelectFieldContext } from './selectContext';\nimport { SelectTrigger } from './SelectTrigger';\nimport type { SelectContextValue, SelectFieldContextValue } from './types';\n\ninterface SelectProps extends Omit<UniversalSelectProps<IconSlotType>, 'width'> {\n /** Placeholder text shown when no value is selected. */\n placeholder?: string;\n /** Selected value for controlled usage. */\n value?: string;\n /** Initial value for uncontrolled usage. @default '' */\n defaultValue?: string;\n /** Called when the selected value changes. */\n onChange?: (value: string) => void;\n /** Container width. @default '100%' */\n width?: number | `${number}%` | '100%';\n children?: ReactNode;\n testID?: string;\n}\n\n/**\n * **⚙️ A composable Select component**\n *\n * @description\n * Select lets users pick one value from a list. Compose with `SelectContent` and\n * `SelectItem`, similar to `Tabs` with `TabList` and `Tab`.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Select, SelectContent, SelectItem } from '@yahoo/uds-mobile/Select';\n *\n * <Select label=\"Country\" placeholder=\"Select a country\" defaultValue=\"us\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"ca\">Canada</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nconst Select = memo(function Select({\n label,\n helpText,\n helperTextIcon,\n placeholder,\n size = 'md',\n disabled,\n required,\n hasError,\n readOnly,\n width = '100%',\n reduceMotion = false,\n startIcon,\n endIcon,\n value: valueProp,\n defaultValue = '',\n onChange,\n children,\n testID,\n}: SelectProps) {\n const generatedId = useId();\n const uid = `uds-select-${generatedId}`;\n const triggerRef = useRef<View | null>(null);\n const [triggerRect, setTriggerRect] = useState<SelectContextValue['triggerRect']>(null);\n const [highlightedValue, setHighlightedValue] = useState<string | null>(null);\n const itemsRef = useRef(new Map<string, string>());\n const [, setItemsVersion] = useState(0);\n\n const [value, setValue] = useControllableState({\n value: valueProp,\n defaultValue,\n onChange,\n });\n\n const [open, setOpen] = useControllableState({\n defaultValue: false,\n onChange: (nextOpen) => {\n if (!nextOpen) {\n setHighlightedValue(null);\n }\n },\n });\n\n const registerItem = useCallback((itemValue: string, itemLabel: string) => {\n if (itemsRef.current.get(itemValue) === itemLabel) {\n return;\n }\n\n itemsRef.current.set(itemValue, itemLabel);\n setItemsVersion((version) => version + 1);\n }, []);\n\n const unregisterItem = useCallback((itemValue: string) => {\n if (!itemsRef.current.has(itemValue)) {\n return;\n }\n\n itemsRef.current.delete(itemValue);\n setItemsVersion((version) => version + 1);\n }, []);\n\n const getItemLabel = useCallback((itemValue: string) => itemsRef.current.get(itemValue), []);\n\n const fieldContext = useMemo<SelectFieldContextValue>(\n () => ({\n size,\n disabled,\n readOnly,\n required,\n hasError,\n width,\n reduceMotion,\n placeholder,\n uid,\n }),\n [disabled
|
|
1
|
+
{"version":3,"file":"Select.js","names":[],"sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import type { UniversalSelectProps } from '@yahoo/uds-types';\nimport { isFunction } from 'lodash-es';\nimport type { ReactNode } from 'react';\nimport { memo, useCallback, useId, useMemo, useRef, useState } from 'react';\nimport type { View } from 'react-native';\n\nimport { inputStyles } from '../../../generated/styles';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport { HStack } from '../HStack';\nimport type { IconSlotType } from '../IconSlot';\nimport { InputHelpText } from '../InputHelpText';\nimport { useControllableState } from '../internal/Overlay';\nimport { Text } from '../Text';\nimport { VStack } from '../VStack';\nimport { SelectContext, SelectFieldContext } from './selectContext';\nimport { SelectTrigger } from './SelectTrigger';\nimport type { SelectContextValue, SelectFieldContextValue } from './types';\n\ninterface SelectProps extends Omit<UniversalSelectProps<IconSlotType>, 'width'> {\n /** Placeholder text shown when no value is selected. */\n placeholder?: string;\n /** Selected value for controlled usage. */\n value?: string;\n /** Initial value for uncontrolled usage. @default '' */\n defaultValue?: string;\n /** Called when the selected value changes. */\n onChange?: (value: string) => void;\n /** Container width. @default '100%' */\n width?: number | `${number}%` | '100%';\n /** Caps text, icons, and field geometry at the control scale. Set null to remove the cap. @default 2 */\n maxFontSizeMultiplier?: number | null;\n children?: ReactNode;\n testID?: string;\n}\n\n/**\n * **⚙️ A composable Select component**\n *\n * @description\n * Select lets users pick one value from a list. Compose with `SelectContent` and\n * `SelectItem`, similar to `Tabs` with `TabList` and `Tab`.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Select, SelectContent, SelectItem } from '@yahoo/uds-mobile/Select';\n *\n * <Select label=\"Country\" placeholder=\"Select a country\" defaultValue=\"us\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"ca\">Canada</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nconst Select = memo(function Select({\n label,\n helpText,\n helperTextIcon,\n placeholder,\n size = 'md',\n disabled,\n required,\n hasError,\n readOnly,\n width = '100%',\n maxFontSizeMultiplier,\n reduceMotion = false,\n startIcon,\n endIcon,\n value: valueProp,\n defaultValue = '',\n onChange,\n children,\n testID,\n}: SelectProps) {\n const generatedId = useId();\n const uid = `uds-select-${generatedId}`;\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n const triggerRef = useRef<View | null>(null);\n const [triggerRect, setTriggerRect] = useState<SelectContextValue['triggerRect']>(null);\n const [highlightedValue, setHighlightedValue] = useState<string | null>(null);\n const itemsRef = useRef(new Map<string, string>());\n const [, setItemsVersion] = useState(0);\n\n const [value, setValue] = useControllableState({\n value: valueProp,\n defaultValue,\n onChange,\n });\n\n const [open, setOpen] = useControllableState({\n defaultValue: false,\n onChange: (nextOpen) => {\n if (!nextOpen) {\n setHighlightedValue(null);\n }\n },\n });\n\n const registerItem = useCallback((itemValue: string, itemLabel: string) => {\n if (itemsRef.current.get(itemValue) === itemLabel) {\n return;\n }\n\n itemsRef.current.set(itemValue, itemLabel);\n setItemsVersion((version) => version + 1);\n }, []);\n\n const unregisterItem = useCallback((itemValue: string) => {\n if (!itemsRef.current.has(itemValue)) {\n return;\n }\n\n itemsRef.current.delete(itemValue);\n setItemsVersion((version) => version + 1);\n }, []);\n\n const getItemLabel = useCallback((itemValue: string) => itemsRef.current.get(itemValue), []);\n\n const fieldContext = useMemo<SelectFieldContextValue>(\n () => ({\n size,\n disabled,\n readOnly,\n required,\n hasError,\n width,\n reduceMotion,\n placeholder,\n uid,\n maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,\n }),\n [\n disabled,\n hasError,\n placeholder,\n readOnly,\n reduceMotion,\n required,\n resolvedMaxFontSizeMultiplier,\n size,\n uid,\n width,\n ],\n );\n\n const contextValue = useMemo<SelectContextValue>(\n () => ({\n value,\n setValue,\n open,\n setOpen,\n triggerRef,\n triggerRect,\n setTriggerRect,\n registerItem,\n unregisterItem,\n getItemLabel,\n highlightedValue,\n setHighlightedValue,\n field: fieldContext,\n reduceMotion,\n }),\n [\n fieldContext,\n getItemLabel,\n highlightedValue,\n open,\n reduceMotion,\n registerItem,\n setOpen,\n setValue,\n triggerRect,\n unregisterItem,\n value,\n ],\n );\n\n const hasValue = value.length > 0;\n const valueState = hasValue ? 'filled' : 'empty';\n\n inputStyles.useVariants({\n size,\n value: valueState,\n pressed: open,\n readonly: readOnly,\n invalid: hasError,\n });\n\n const rootStyle = useMemo(() => [{ width, opacity: disabled ? 0.5 : 1 }], [disabled, width]);\n\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n\n const content = isFunction(label) ? label() : label;\n return (\n <HStack columnGap=\"1\" alignItems=\"flex-end\" spacingBottom=\"2\">\n <Text maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier} style={inputStyles.label}>\n {content}\n </Text>\n {required && (\n <Text\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={inputStyles.labelRequired}\n >\n *\n </Text>\n )}\n </HStack>\n );\n }, [\n label,\n required,\n resolvedMaxFontSizeMultiplier,\n inputStyles.label,\n inputStyles.labelRequired,\n ]);\n\n const helpTextContent = useMemo(() => {\n if (!helpText) {\n return null;\n }\n\n const content = isFunction(helpText) ? helpText() : helpText;\n return (\n <InputHelpText\n startIcon={helperTextIcon}\n size={size}\n isFilled={valueState === 'filled'}\n disabled={disabled}\n readOnly={readOnly}\n hasError={hasError}\n pressed={open}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n >\n {content}\n </InputHelpText>\n );\n }, [\n disabled,\n hasError,\n helpText,\n helperTextIcon,\n open,\n readOnly,\n resolvedMaxFontSizeMultiplier,\n size,\n valueState,\n ]);\n\n return (\n <SelectContext.Provider value={contextValue}>\n <SelectFieldContext.Provider value={fieldContext}>\n <VStack testID={testID} style={rootStyle}>\n {labelContent}\n\n <SelectTrigger startIcon={startIcon} endIcon={endIcon} />\n\n {helpTextContent}\n\n {children}\n </VStack>\n </SelectFieldContext.Provider>\n </SelectContext.Provider>\n );\n});\n\nSelect.displayName = 'Select';\n\nexport { Select, type SelectProps };\n"],"mappings":"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"}
|