@yahoo/uds-mobile 2.12.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/bin/mobile/scripts/utils/configToRNMappings.mjs +2 -0
- package/dist/components/Checkbox.cjs +10 -15
- package/dist/components/Checkbox.d.cts.map +1 -1
- package/dist/components/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox.js +11 -16
- package/dist/components/Checkbox.js.map +1 -1
- package/dist/components/FormLabel.cjs +31 -0
- package/dist/components/FormLabel.d.cts +21 -0
- package/dist/components/FormLabel.d.cts.map +1 -0
- package/dist/components/FormLabel.d.ts +21 -0
- package/dist/components/FormLabel.d.ts.map +1 -0
- package/dist/components/FormLabel.js +31 -0
- package/dist/components/FormLabel.js.map +1 -0
- package/dist/components/{Radio.cjs → Radio/Radio.cjs} +41 -24
- package/dist/components/{Radio.d.cts → Radio/Radio.d.cts} +2 -2
- package/dist/components/Radio/Radio.d.cts.map +1 -0
- package/dist/components/{Radio.d.ts → Radio/Radio.d.ts} +2 -2
- package/dist/components/Radio/Radio.d.ts.map +1 -0
- package/dist/components/{Radio.js → Radio/Radio.js} +41 -24
- package/dist/components/Radio/Radio.js.map +1 -0
- package/dist/components/Radio/RadioGroup.cjs +84 -0
- package/dist/components/Radio/RadioGroup.d.cts +52 -0
- package/dist/components/Radio/RadioGroup.d.cts.map +1 -0
- package/dist/components/Radio/RadioGroup.d.ts +52 -0
- package/dist/components/Radio/RadioGroup.d.ts.map +1 -0
- package/dist/components/Radio/RadioGroup.js +84 -0
- package/dist/components/Radio/RadioGroup.js.map +1 -0
- package/dist/components/Radio/RadioGroupContext.cjs +12 -0
- package/dist/components/Radio/RadioGroupContext.d.cts +20 -0
- package/dist/components/Radio/RadioGroupContext.d.cts.map +1 -0
- package/dist/components/Radio/RadioGroupContext.d.ts +20 -0
- package/dist/components/Radio/RadioGroupContext.d.ts.map +1 -0
- package/dist/components/Radio/RadioGroupContext.js +11 -0
- package/dist/components/Radio/RadioGroupContext.js.map +1 -0
- package/dist/components/Radio/index.cjs +6 -0
- package/dist/components/Radio/index.d.cts +4 -0
- package/dist/components/Radio/index.d.ts +4 -0
- package/dist/components/Radio/index.js +4 -0
- package/dist/components/Switch.cjs +8 -13
- package/dist/components/Switch.d.cts.map +1 -1
- package/dist/components/Switch.d.ts.map +1 -1
- package/dist/components/Switch.js +8 -13
- package/dist/components/Switch.js.map +1 -1
- package/dist/components/Text.cjs +12 -6
- package/dist/components/Text.d.cts +3 -2
- package/dist/components/Text.d.cts.map +1 -1
- package/dist/components/Text.d.ts +3 -2
- package/dist/components/Text.d.ts.map +1 -1
- package/dist/components/Text.js +12 -6
- package/dist/components/Text.js.map +1 -1
- package/dist/types/dist/index.d.cts +52 -2
- package/dist/types/dist/index.d.cts.map +1 -1
- package/dist/types/dist/index.d.ts +52 -2
- package/dist/types/dist/index.d.ts.map +1 -1
- package/generated/styles.cjs +4 -0
- package/generated/styles.d.ts +2 -1
- package/generated/styles.mjs +4 -0
- package/generated/unistyles.d.ts +6 -0
- package/package.json +25 -5
- package/dist/components/Radio.d.cts.map +0 -1
- package/dist/components/Radio.d.ts.map +0 -1
- package/dist/components/Radio.js.map +0 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
`@yahoo/uds-mobile` brings UDS to React Native. It provides:
|
|
19
19
|
|
|
20
|
-
- **Pre-built Components**: Avatar, Badge, Button, Checkbox, Chip, Divider, Icon, IconButton, Image, Input, Link, Radio, Switch, Tabs, Text, and layout primitives (Box, VStack, HStack, Screen)
|
|
20
|
+
- **Pre-built Components**: Avatar, Badge, Button, Checkbox, Chip, Divider, Icon, IconButton, Image, Input, Link, Radio, RadioGroup, Switch, Tabs, Text, and layout primitives (Box, VStack, HStack, Screen)
|
|
21
21
|
- **Theming**: Full light/dark mode support with automatic system preference detection
|
|
22
22
|
- **Design Token Integration**: Colors, typography, spacing, and motion configs synced from UDS tokens
|
|
23
23
|
- **Animations**: Smooth, physics-based animations using Reanimated with motion parity to web
|
|
@@ -337,6 +337,7 @@ const styles = StyleSheet.create((theme) => ({
|
|
|
337
337
|
| `Link` | Inline text links with icons |
|
|
338
338
|
| `Pressable` | Base pressable component |
|
|
339
339
|
| `Radio` | Radio button with label |
|
|
340
|
+
| `RadioGroup` | Coordinates Radio selection in a group |
|
|
340
341
|
| `Screen` | Screen container with safe area handling |
|
|
341
342
|
| `Switch` | Toggle switch with animations |
|
|
342
343
|
| `Text` | Typography component with variants |
|
|
@@ -698,6 +699,7 @@ import { Input } from '@yahoo/uds-mobile/Input';
|
|
|
698
699
|
import { Link } from '@yahoo/uds-mobile/Link';
|
|
699
700
|
import { Pressable } from '@yahoo/uds-mobile/Pressable';
|
|
700
701
|
import { Radio } from '@yahoo/uds-mobile/Radio';
|
|
702
|
+
import { RadioGroup } from '@yahoo/uds-mobile/RadioGroup';
|
|
701
703
|
import { Screen } from '@yahoo/uds-mobile/Screen';
|
|
702
704
|
import { Switch } from '@yahoo/uds-mobile/Switch';
|
|
703
705
|
import { Text } from '@yahoo/uds-mobile/Text';
|
|
@@ -13,6 +13,7 @@ const PROPERTY_TO_RN_PROPS = {
|
|
|
13
13
|
width: ["width"],
|
|
14
14
|
backgroundColor: ["backgroundColor"],
|
|
15
15
|
color: ["color"],
|
|
16
|
+
labelColor: ["color"],
|
|
16
17
|
borderColor: ["borderColor"],
|
|
17
18
|
borderWidth: ["borderWidth"],
|
|
18
19
|
borderRadius: ["borderRadius"],
|
|
@@ -40,6 +41,7 @@ const PROPERTY_TO_RN_PROPS = {
|
|
|
40
41
|
*/
|
|
41
42
|
const TEXT_ONLY_PROPS = new Set([
|
|
42
43
|
"color",
|
|
44
|
+
"labelColor",
|
|
43
45
|
"textDecorationLine",
|
|
44
46
|
"textVariant"
|
|
45
47
|
]);
|
|
@@ -4,9 +4,8 @@ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
|
4
4
|
const require_index = require("../motion-tokens/dist/index.cjs");
|
|
5
5
|
const require_motion = require("../motion.cjs");
|
|
6
6
|
const require_components_Icon = require("./Icon.cjs");
|
|
7
|
-
const require_components_Text = require("./Text.cjs");
|
|
8
|
-
const require_components_HStack = require("./HStack.cjs");
|
|
9
7
|
const require_components_Pressable = require("./Pressable.cjs");
|
|
8
|
+
const require_components_FormLabel = require("./FormLabel.cjs");
|
|
10
9
|
let react = require("react");
|
|
11
10
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
12
11
|
let generated_styles = require("../../generated/styles");
|
|
@@ -103,23 +102,19 @@ const Checkbox = (0, react.memo)(function Checkbox({ label, labelPosition = "sta
|
|
|
103
102
|
], [generated_styles.checkboxStyles.checkbox, checkboxAnimatedStyle]);
|
|
104
103
|
const labelContent = (0, react.useMemo)(() => {
|
|
105
104
|
if (!label) return null;
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
children: [textContent, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Text.Text, {
|
|
115
|
-
style: generated_styles.checkboxStyles.text,
|
|
116
|
-
children: "*"
|
|
117
|
-
})]
|
|
105
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_FormLabel.FormLabel, {
|
|
106
|
+
color: "inherit",
|
|
107
|
+
variant: "inherit",
|
|
108
|
+
label,
|
|
109
|
+
required,
|
|
110
|
+
showRequiredAsterisk: required,
|
|
111
|
+
hasError,
|
|
112
|
+
style: generated_styles.checkboxStyles.text
|
|
118
113
|
});
|
|
119
|
-
return textContent;
|
|
120
114
|
}, [
|
|
121
115
|
label,
|
|
122
116
|
required,
|
|
117
|
+
hasError,
|
|
123
118
|
generated_styles.checkboxStyles.text
|
|
124
119
|
]);
|
|
125
120
|
const a11yState = (0, react.useMemo)(() => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkbox.d.cts","names":[],"sources":["../../src/components/Checkbox.tsx"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"Checkbox.d.cts","names":[],"sources":["../../src/components/Checkbox.tsx"],"mappings":";;;;;;;UAmBU,aAAA,SAAsB,IAAA,CAAK,SAAA,YAAqB,sBAAA;;EAExD,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,cAAA;;EAEA,QAAA;EAJU;EAMV,QAAA;EAR8B;EAU9B,QAAA,IAAY,OAAA;AAAA;;;;;;;;;;;;;;;AAAgB;;;;;;;;;;;;;;;;;;;;cAqDxB,QAAA,EAAQ,OAAA,CAAA,oBAAA,CAAA,aAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkbox.d.ts","names":[],"sources":["../../src/components/Checkbox.tsx"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"Checkbox.d.ts","names":[],"sources":["../../src/components/Checkbox.tsx"],"mappings":";;;;;;;UAmBU,aAAA,SAAsB,IAAA,CAAK,SAAA,YAAqB,sBAAA;;EAExD,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,cAAA;;EAEA,QAAA;EAJU;EAMV,QAAA;EAR8B;EAU9B,QAAA,IAAY,OAAA;AAAA;;;;;;;;;;;;;;;AAAgB;;;;;;;;;;;;;;;;;;;;cAqDxB,QAAA,EAAQ,OAAA,CAAA,oBAAA,CAAA,aAAA"}
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
import { SCALE_EFFECTS } from "../motion-tokens/dist/index.js";
|
|
3
3
|
import { BUTTON_SPRING_CONFIG } from "../motion.js";
|
|
4
4
|
import { Icon } from "./Icon.js";
|
|
5
|
-
import { Text } from "./Text.js";
|
|
6
|
-
import { HStack } from "./HStack.js";
|
|
7
5
|
import { Pressable } from "./Pressable.js";
|
|
8
|
-
import {
|
|
6
|
+
import { FormLabel } from "./FormLabel.js";
|
|
7
|
+
import { memo, useCallback, useId, useMemo, useState } from "react";
|
|
9
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
9
|
import { checkboxStyles } from "../../generated/styles";
|
|
11
10
|
import Animated, { useAnimatedStyle, useDerivedValue, withSpring } from "react-native-reanimated";
|
|
@@ -100,23 +99,19 @@ const Checkbox = memo(function Checkbox({ label, labelPosition = "start", varian
|
|
|
100
99
|
], [checkboxStyles.checkbox, checkboxAnimatedStyle]);
|
|
101
100
|
const labelContent = useMemo(() => {
|
|
102
101
|
if (!label) return null;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
children: [textContent, /* @__PURE__ */ jsx(Text, {
|
|
112
|
-
style: checkboxStyles.text,
|
|
113
|
-
children: "*"
|
|
114
|
-
})]
|
|
102
|
+
return /* @__PURE__ */ jsx(FormLabel, {
|
|
103
|
+
color: "inherit",
|
|
104
|
+
variant: "inherit",
|
|
105
|
+
label,
|
|
106
|
+
required,
|
|
107
|
+
showRequiredAsterisk: required,
|
|
108
|
+
hasError,
|
|
109
|
+
style: checkboxStyles.text
|
|
115
110
|
});
|
|
116
|
-
return textContent;
|
|
117
111
|
}, [
|
|
118
112
|
label,
|
|
119
113
|
required,
|
|
114
|
+
hasError,
|
|
120
115
|
checkboxStyles.text
|
|
121
116
|
]);
|
|
122
117
|
const a11yState = useMemo(() => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkbox.js","names":[],"sources":["../../src/components/Checkbox.tsx"],"sourcesContent":["import type { CheckboxValue, CheckboxVariant, UniversalCheckboxProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { isValidElement, memo, useCallback, useId, useMemo, useState } from 'react';\nimport type { View, ViewProps } from 'react-native';\nimport Animated, { useAnimatedStyle, useDerivedValue, withSpring } from 'react-native-reanimated';\n\nimport { checkboxStyles } from '../../generated/styles';\nimport { BUTTON_SPRING_CONFIG, SCALE_EFFECTS } from '../motion';\nimport { HStack } from './HStack';\nimport { Icon } from './Icon';\nimport { Pressable } from './Pressable';\nimport { Text } from './Text';\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\n/** Derived from CheckboxValue - maps boolean to 'checked'/'unchecked' string literals */\ntype CheckboxValueState = Exclude<CheckboxValue, boolean> | 'checked' | 'unchecked';\n\ninterface CheckboxProps extends Omit<ViewProps, 'style'>, UniversalCheckboxProps {\n /** Ref to the underlying View */\n ref?: Ref<View>;\n /** Default checked state for uncontrolled mode */\n defaultChecked?: boolean;\n /** Whether the checkbox is disabled */\n disabled?: boolean;\n /** Whether the checkbox is required */\n required?: boolean;\n /** Callback fired when the checked state changes */\n onChange?: (checked: boolean) => void;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Variant Mapping */\n/* -------------------------------------------------------------------------- */\n\n/** All style variants available in the generated styles (includes error variants) */\ntype CheckboxStyleVariant = 'primary' | 'secondary' | 'alert' | 'alert-secondary';\n\nconst VARIANT_ERROR_MAP: Record<CheckboxVariant, CheckboxStyleVariant> = {\n primary: 'alert',\n secondary: 'alert-secondary',\n};\n\n/* -------------------------------------------------------------------------- */\n/* Checkbox Component */\n/* -------------------------------------------------------------------------- */\n\n/**\n * **⚙️ A checkbox component**\n *\n * @description\n * A checkbox component allows users to select one or multiple options from a set.\n * It represents a binary state, typically as checked or unchecked, and optionally\n * includes a third \"indeterminate\" state to indicate partial selection.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Checkbox } from '@yahoo/uds-mobile/Checkbox';\n *\n * <Checkbox label=\"Agree to terms\" />\n * <Checkbox label=\"Subscribe\" checked={true} onChange={setChecked} />\n * <Checkbox label=\"Partial\" checked=\"indeterminate\" />\n * ```\n *\n * @usage\n * - Forms: For selecting options\n * - Settings: For toggling preferences\n * - Filters: For multi-select filtering\n *\n * @accessibility\n * - Sets `accessibilityRole=\"checkbox\"` automatically\n * - Announces checked/unchecked/mixed state\n * - Label is used as accessibility label\n * - Supports `reduceMotion` for users who prefer reduced motion\n *\n * @see {@link Radio} for single-select options\n * @see {@link Switch} for binary toggles\n */\nconst Checkbox = memo(function Checkbox({\n // Checkbox props\n label,\n labelPosition = 'start',\n variant: variantProp = 'primary',\n size = 'md',\n checked: checkedProp,\n hasError,\n reduceMotion,\n // Native props\n defaultChecked,\n disabled,\n required,\n onChange,\n ref,\n ...viewProps\n}: CheckboxProps) {\n const generatedId = useId();\n const uid = `uds-checkbox-${generatedId}`;\n\n /* --------------------------------- State ---------------------------------- */\n const isControlled = checkedProp !== undefined;\n const [internalChecked, setInternalChecked] = useState<CheckboxValue>(\n isControlled ? checkedProp : (defaultChecked ?? false),\n );\n const [pressed, setPressed] = useState(false);\n\n // Use controlled value if provided, otherwise use internal state\n const checked = isControlled ? checkedProp : internalChecked;\n\n /* ------------------------------ Derived Values ---------------------------- */\n const valueState: CheckboxValueState = useMemo(() => {\n if (checked === 'indeterminate') {\n return 'indeterminate';\n }\n return checked ? 'checked' : 'unchecked';\n }, [checked]);\n\n const iconName = valueState === 'indeterminate' ? 'Minus' : 'Check';\n const showIcon = valueState !== 'unchecked';\n\n /* -------------------------------- Animation ------------------------------- */\n const shouldAnimate = !reduceMotion;\n\n // Scale animation for press feedback (disabled when reduceMotion is true)\n const scaleProgress = useDerivedValue(\n () =>\n shouldAnimate\n ? withSpring(pressed ? SCALE_EFFECTS.down : SCALE_EFFECTS.none, BUTTON_SPRING_CONFIG)\n : SCALE_EFFECTS.none, // No scale effect when reduceMotion is true\n [pressed, shouldAnimate],\n );\n\n const checkboxAnimatedStyle = useAnimatedStyle(() => ({\n transform: [{ scale: scaleProgress.value }],\n }));\n\n /* -------------------------------- Handlers -------------------------------- */\n const handlePress = useCallback(() => {\n if (disabled) {\n return;\n }\n\n const newChecked = checked === 'indeterminate' ? true : !checked;\n\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n\n onChange?.(newChecked);\n }, [disabled, checked, isControlled, onChange]);\n\n const handlePressIn = useCallback(() => {\n setPressed(true);\n }, []);\n\n const handlePressOut = useCallback(() => {\n setPressed(false);\n }, []);\n\n /* --------------------------------- Styles --------------------------------- */\n // Compute the style variant (primary/secondary maps to alert variants when hasError)\n const styleVariant: CheckboxStyleVariant = hasError\n ? VARIANT_ERROR_MAP[variantProp]\n : variantProp;\n\n checkboxStyles.useVariants({\n size,\n variant: styleVariant, // primary, secondary, alert, alert-secondary\n value: valueState, // checked, unchecked, indeterminate\n disabled,\n pressed,\n });\n\n const rootStyle = useMemo(\n () => [checkboxStyles.root, { opacity: disabled ? 0.5 : 1 }],\n [checkboxStyles.root, disabled],\n );\n\n const checkboxBoxStyle = useMemo(\n () => [\n checkboxStyles.checkbox,\n { alignItems: 'center' as const, justifyContent: 'center' as const, borderRadius: 4 },\n checkboxAnimatedStyle,\n ],\n [checkboxStyles.checkbox, checkboxAnimatedStyle],\n );\n\n /* ---------------------------- Render Helpers ------------------------------ */\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n\n const content =\n typeof label === 'function' ? label() : isValidElement(label) ? label : String(label);\n\n const textContent =\n typeof content === 'string' ? <Text style={checkboxStyles.text}>{content}</Text> : content;\n\n if (required) {\n return (\n <HStack columnGap=\"1\" alignItems=\"flex-start\">\n {textContent}\n <Text style={checkboxStyles.text}>*</Text>\n </HStack>\n );\n }\n\n return textContent;\n }, [label, required, checkboxStyles.text]);\n\n const a11yState = useMemo(\n () => ({\n disabled,\n checked:\n valueState === 'checked'\n ? true\n : valueState === 'indeterminate'\n ? ('mixed' as const)\n : false,\n }),\n [disabled, valueState],\n );\n\n /* --------------------------------- Render --------------------------------- */\n return (\n <Pressable\n ref={ref}\n nativeID={uid}\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n disabled={disabled}\n flexDirection={labelPosition === 'start' ? 'row' : 'row-reverse'}\n alignItems=\"center\"\n alignSelf=\"flex-start\"\n accessibilityRole=\"checkbox\"\n accessibilityState={a11yState}\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n {...viewProps}\n style={rootStyle}\n >\n <Animated.View style={checkboxBoxStyle}>\n {showIcon && <Icon name={iconName} size=\"sm\" style={checkboxStyles.checkboxIcon} />}\n </Animated.View>\n\n {labelContent}\n </Pressable>\n );\n});\n\nCheckbox.displayName = 'Checkbox';\n\nexport { Checkbox, type CheckboxProps };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Checkbox.js","names":[],"sources":["../../src/components/Checkbox.tsx"],"sourcesContent":["import type { CheckboxValue, CheckboxVariant, UniversalCheckboxProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useId, useMemo, useState } from 'react';\nimport type { View, ViewProps } from 'react-native';\nimport Animated, { useAnimatedStyle, useDerivedValue, withSpring } from 'react-native-reanimated';\n\nimport { checkboxStyles } from '../../generated/styles';\nimport { BUTTON_SPRING_CONFIG, SCALE_EFFECTS } from '../motion';\nimport { FormLabel } from './FormLabel';\nimport { Icon } from './Icon';\nimport { Pressable } from './Pressable';\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\n/** Derived from CheckboxValue - maps boolean to 'checked'/'unchecked' string literals */\ntype CheckboxValueState = Exclude<CheckboxValue, boolean> | 'checked' | 'unchecked';\n\ninterface CheckboxProps extends Omit<ViewProps, 'style'>, UniversalCheckboxProps {\n /** Ref to the underlying View */\n ref?: Ref<View>;\n /** Default checked state for uncontrolled mode */\n defaultChecked?: boolean;\n /** Whether the checkbox is disabled */\n disabled?: boolean;\n /** Whether the checkbox is required */\n required?: boolean;\n /** Callback fired when the checked state changes */\n onChange?: (checked: boolean) => void;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Variant Mapping */\n/* -------------------------------------------------------------------------- */\n\n/** All style variants available in the generated styles (includes error variants) */\ntype CheckboxStyleVariant = 'primary' | 'secondary' | 'alert' | 'alert-secondary';\n\nconst VARIANT_ERROR_MAP: Record<CheckboxVariant, CheckboxStyleVariant> = {\n primary: 'alert',\n secondary: 'alert-secondary',\n};\n\n/* -------------------------------------------------------------------------- */\n/* Checkbox Component */\n/* -------------------------------------------------------------------------- */\n\n/**\n * **⚙️ A checkbox component**\n *\n * @description\n * A checkbox component allows users to select one or multiple options from a set.\n * It represents a binary state, typically as checked or unchecked, and optionally\n * includes a third \"indeterminate\" state to indicate partial selection.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Checkbox } from '@yahoo/uds-mobile/Checkbox';\n *\n * <Checkbox label=\"Agree to terms\" />\n * <Checkbox label=\"Subscribe\" checked={true} onChange={setChecked} />\n * <Checkbox label=\"Partial\" checked=\"indeterminate\" />\n * ```\n *\n * @usage\n * - Forms: For selecting options\n * - Settings: For toggling preferences\n * - Filters: For multi-select filtering\n *\n * @accessibility\n * - Sets `accessibilityRole=\"checkbox\"` automatically\n * - Announces checked/unchecked/mixed state\n * - Label is used as accessibility label\n * - Supports `reduceMotion` for users who prefer reduced motion\n *\n * @see {@link Radio} for single-select options\n * @see {@link Switch} for binary toggles\n */\nconst Checkbox = memo(function Checkbox({\n // Checkbox props\n label,\n labelPosition = 'start',\n variant: variantProp = 'primary',\n size = 'md',\n checked: checkedProp,\n hasError,\n reduceMotion,\n // Native props\n defaultChecked,\n disabled,\n required,\n onChange,\n ref,\n ...viewProps\n}: CheckboxProps) {\n const generatedId = useId();\n const uid = `uds-checkbox-${generatedId}`;\n\n /* --------------------------------- State ---------------------------------- */\n const isControlled = checkedProp !== undefined;\n const [internalChecked, setInternalChecked] = useState<CheckboxValue>(\n isControlled ? checkedProp : (defaultChecked ?? false),\n );\n const [pressed, setPressed] = useState(false);\n\n // Use controlled value if provided, otherwise use internal state\n const checked = isControlled ? checkedProp : internalChecked;\n\n /* ------------------------------ Derived Values ---------------------------- */\n const valueState: CheckboxValueState = useMemo(() => {\n if (checked === 'indeterminate') {\n return 'indeterminate';\n }\n return checked ? 'checked' : 'unchecked';\n }, [checked]);\n\n const iconName = valueState === 'indeterminate' ? 'Minus' : 'Check';\n const showIcon = valueState !== 'unchecked';\n\n /* -------------------------------- Animation ------------------------------- */\n const shouldAnimate = !reduceMotion;\n\n // Scale animation for press feedback (disabled when reduceMotion is true)\n const scaleProgress = useDerivedValue(\n () =>\n shouldAnimate\n ? withSpring(pressed ? SCALE_EFFECTS.down : SCALE_EFFECTS.none, BUTTON_SPRING_CONFIG)\n : SCALE_EFFECTS.none, // No scale effect when reduceMotion is true\n [pressed, shouldAnimate],\n );\n\n const checkboxAnimatedStyle = useAnimatedStyle(() => ({\n transform: [{ scale: scaleProgress.value }],\n }));\n\n /* -------------------------------- Handlers -------------------------------- */\n const handlePress = useCallback(() => {\n if (disabled) {\n return;\n }\n\n const newChecked = checked === 'indeterminate' ? true : !checked;\n\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n\n onChange?.(newChecked);\n }, [disabled, checked, isControlled, onChange]);\n\n const handlePressIn = useCallback(() => {\n setPressed(true);\n }, []);\n\n const handlePressOut = useCallback(() => {\n setPressed(false);\n }, []);\n\n /* --------------------------------- Styles --------------------------------- */\n // Compute the style variant (primary/secondary maps to alert variants when hasError)\n const styleVariant: CheckboxStyleVariant = hasError\n ? VARIANT_ERROR_MAP[variantProp]\n : variantProp;\n\n checkboxStyles.useVariants({\n size,\n variant: styleVariant, // primary, secondary, alert, alert-secondary\n value: valueState, // checked, unchecked, indeterminate\n disabled,\n pressed,\n });\n\n const rootStyle = useMemo(\n () => [checkboxStyles.root, { opacity: disabled ? 0.5 : 1 }],\n [checkboxStyles.root, disabled],\n );\n\n const checkboxBoxStyle = useMemo(\n () => [\n checkboxStyles.checkbox,\n { alignItems: 'center' as const, justifyContent: 'center' as const, borderRadius: 4 },\n checkboxAnimatedStyle,\n ],\n [checkboxStyles.checkbox, checkboxAnimatedStyle],\n );\n\n /* ---------------------------- Render Helpers ------------------------------ */\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n\n return (\n <FormLabel\n color=\"inherit\"\n variant=\"inherit\"\n label={label}\n required={required}\n showRequiredAsterisk={required}\n hasError={hasError}\n style={checkboxStyles.text}\n />\n );\n }, [label, required, hasError, checkboxStyles.text]);\n\n const a11yState = useMemo(\n () => ({\n disabled,\n checked:\n valueState === 'checked'\n ? true\n : valueState === 'indeterminate'\n ? ('mixed' as const)\n : false,\n }),\n [disabled, valueState],\n );\n\n /* --------------------------------- Render --------------------------------- */\n return (\n <Pressable\n ref={ref}\n nativeID={uid}\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n disabled={disabled}\n flexDirection={labelPosition === 'start' ? 'row' : 'row-reverse'}\n alignItems=\"center\"\n alignSelf=\"flex-start\"\n accessibilityRole=\"checkbox\"\n accessibilityState={a11yState}\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n {...viewProps}\n style={rootStyle}\n >\n <Animated.View style={checkboxBoxStyle}>\n {showIcon && <Icon name={iconName} size=\"sm\" style={checkboxStyles.checkboxIcon} />}\n </Animated.View>\n\n {labelContent}\n </Pressable>\n );\n});\n\nCheckbox.displayName = 'Checkbox';\n\nexport { Checkbox, type CheckboxProps };\n"],"mappings":";;;;;;;;;;;AAuCA,MAAM,oBAAmE;CACvE,SAAS;CACT,WAAW;CACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCD,MAAM,WAAW,KAAK,SAAS,SAAS,EAEtC,OACA,gBAAgB,SAChB,SAAS,cAAc,WACvB,OAAO,MACP,SAAS,aACT,UACA,cAEA,gBACA,UACA,UACA,UACA,KACA,GAAG,aACa;CAEhB,MAAM,MAAM,gBADQ,OACmB;CAGvC,MAAM,eAAe,gBAAgB,KAAA;CACrC,MAAM,CAAC,iBAAiB,sBAAsB,SAC5C,eAAe,cAAe,kBAAkB,MACjD;CACD,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAG7C,MAAM,UAAU,eAAe,cAAc;CAG7C,MAAM,aAAiC,cAAc;EACnD,IAAI,YAAY,iBACd,OAAO;EAET,OAAO,UAAU,YAAY;IAC5B,CAAC,QAAQ,CAAC;CAEb,MAAM,WAAW,eAAe,kBAAkB,UAAU;CAC5D,MAAM,WAAW,eAAe;CAGhC,MAAM,gBAAgB,CAAC;CAGvB,MAAM,gBAAgB,sBAElB,gBACI,WAAW,UAAU,cAAc,OAAO,cAAc,MAAM,qBAAqB,GACnF,cAAc,MACpB,CAAC,SAAS,cAAc,CACzB;CAED,MAAM,wBAAwB,wBAAwB,EACpD,WAAW,CAAC,EAAE,OAAO,cAAc,OAAO,CAAC,EAC5C,EAAE;CAGH,MAAM,cAAc,kBAAkB;EACpC,IAAI,UACF;EAGF,MAAM,aAAa,YAAY,kBAAkB,OAAO,CAAC;EAEzD,IAAI,CAAC,cACH,mBAAmB,WAAW;EAGhC,WAAW,WAAW;IACrB;EAAC;EAAU;EAAS;EAAc;EAAS,CAAC;CAE/C,MAAM,gBAAgB,kBAAkB;EACtC,WAAW,KAAK;IACf,EAAE,CAAC;CAEN,MAAM,iBAAiB,kBAAkB;EACvC,WAAW,MAAM;IAChB,EAAE,CAAC;CAIN,MAAM,eAAqC,WACvC,kBAAkB,eAClB;CAEJ,eAAe,YAAY;EACzB;EACA,SAAS;EACT,OAAO;EACP;EACA;EACD,CAAC;CAEF,MAAM,YAAY,cACV,CAAC,eAAe,MAAM,EAAE,SAAS,WAAW,KAAM,GAAG,CAAC,EAC5D,CAAC,eAAe,MAAM,SAAS,CAChC;CAED,MAAM,mBAAmB,cACjB;EACJ,eAAe;EACf;GAAE,YAAY;GAAmB,gBAAgB;GAAmB,cAAc;GAAG;EACrF;EACD,EACD,CAAC,eAAe,UAAU,sBAAsB,CACjD;CAGD,MAAM,eAAe,cAAc;EACjC,IAAI,CAAC,OACH,OAAO;EAGT,OACE,oBAAC,WAAD;GACE,OAAM;GACN,SAAQ;GACD;GACG;GACV,sBAAsB;GACZ;GACV,OAAO,eAAe;GACtB,CAAA;IAEH;EAAC;EAAO;EAAU;EAAU,eAAe;EAAK,CAAC;CAEpD,MAAM,YAAY,eACT;EACL;EACA,SACE,eAAe,YACX,OACA,eAAe,kBACZ,UACD;EACT,GACD,CAAC,UAAU,WAAW,CACvB;CAGD,OACE,qBAAC,WAAD;EACO;EACL,UAAU;EACV,SAAS;EACT,WAAW;EACX,YAAY;EACF;EACV,eAAe,kBAAkB,UAAU,QAAQ;EACnD,YAAW;EACX,WAAU;EACV,mBAAkB;EAClB,oBAAoB;EACpB,oBAAoB,OAAO,UAAU,WAAW,QAAQ,KAAA;EACxD,GAAI;EACJ,OAAO;YAdT,CAgBE,oBAAC,SAAS,MAAV;GAAe,OAAO;aACnB,YAAY,oBAAC,MAAD;IAAM,MAAM;IAAU,MAAK;IAAK,OAAO,eAAe;IAAgB,CAAA;GACrE,CAAA,EAEf,aACS;;EAEd;AAEF,SAAS,cAAc"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
4
|
+
const require_components_Text = require("./Text.cjs");
|
|
5
|
+
let react = require("react");
|
|
6
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
+
let lodash_es = require("lodash-es");
|
|
8
|
+
//#region src/components/FormLabel.tsx
|
|
9
|
+
const FormLabel = (0, react.memo)(function FormLabel({ required, label, children, color = "muted", variant = "label3", hasError = false, showRequiredAsterisk = false, ref, ...textProps }) {
|
|
10
|
+
const contents = (0, react.useMemo)(() => {
|
|
11
|
+
return label ? (0, lodash_es.isFunction)(label) ? label() : label : children;
|
|
12
|
+
}, [children, label]);
|
|
13
|
+
if (!contents) return null;
|
|
14
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_components_Text.Text, {
|
|
15
|
+
ref,
|
|
16
|
+
color,
|
|
17
|
+
variant,
|
|
18
|
+
...textProps,
|
|
19
|
+
children: [contents, required && showRequiredAsterisk && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Text.Text, {
|
|
20
|
+
color: hasError ? "alert" : "inherit",
|
|
21
|
+
variant: "inherit",
|
|
22
|
+
spacingStart: "0.5",
|
|
23
|
+
accessibilityElementsHidden: true,
|
|
24
|
+
importantForAccessibility: "no",
|
|
25
|
+
children: "*"
|
|
26
|
+
})]
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
FormLabel.displayName = "FormLabel";
|
|
30
|
+
//#endregion
|
|
31
|
+
exports.FormLabel = FormLabel;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
import { UniversalFormLabelProps } from "../types/dist/index.cjs";
|
|
3
|
+
import { TextProps } from "./Text.cjs";
|
|
4
|
+
import * as _$react from "react";
|
|
5
|
+
import { ReactNode } from "react";
|
|
6
|
+
|
|
7
|
+
//#region src/components/FormLabel.d.ts
|
|
8
|
+
interface FormLabelProps extends Omit<TextProps, 'children' | 'color' | 'ref' | 'variant'>, Pick<UniversalFormLabelProps, 'hasError' | 'label' | 'required' | 'showRequiredAsterisk'> {
|
|
9
|
+
/** Ref to the underlying Text. */
|
|
10
|
+
ref?: TextProps['ref'];
|
|
11
|
+
/** The label content. Used when the label prop is not provided. */
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
/** Label text color. */
|
|
14
|
+
color?: TextProps['color'] | 'inherit';
|
|
15
|
+
/** Typography variant for the label text. */
|
|
16
|
+
variant?: TextProps['variant'] | 'inherit';
|
|
17
|
+
}
|
|
18
|
+
declare const FormLabel: _$react.NamedExoticComponent<FormLabelProps>;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { FormLabel, type FormLabelProps };
|
|
21
|
+
//# sourceMappingURL=FormLabel.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormLabel.d.cts","names":[],"sources":["../../src/components/FormLabel.tsx"],"mappings":";;;;;;;UAQU,cAAA,SAEN,IAAA,CAAK,SAAA,6CACL,IAAA,CAAK,uBAAA;;EAEP,GAAA,GAAM,SAAA;EALE;EAOR,QAAA,GAAW,SAAA;;EAEX,KAAA,GAAQ,SAAA;EAND;EAQP,OAAA,GAAU,SAAA;AAAA;AAAA,cAGN,SAAA,EAAS,OAAA,CAAA,oBAAA,CAAA,cAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
import { UniversalFormLabelProps } from "../types/dist/index.js";
|
|
3
|
+
import { TextProps } from "./Text.js";
|
|
4
|
+
import * as _$react from "react";
|
|
5
|
+
import { ReactNode } from "react";
|
|
6
|
+
|
|
7
|
+
//#region src/components/FormLabel.d.ts
|
|
8
|
+
interface FormLabelProps extends Omit<TextProps, 'children' | 'color' | 'ref' | 'variant'>, Pick<UniversalFormLabelProps, 'hasError' | 'label' | 'required' | 'showRequiredAsterisk'> {
|
|
9
|
+
/** Ref to the underlying Text. */
|
|
10
|
+
ref?: TextProps['ref'];
|
|
11
|
+
/** The label content. Used when the label prop is not provided. */
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
/** Label text color. */
|
|
14
|
+
color?: TextProps['color'] | 'inherit';
|
|
15
|
+
/** Typography variant for the label text. */
|
|
16
|
+
variant?: TextProps['variant'] | 'inherit';
|
|
17
|
+
}
|
|
18
|
+
declare const FormLabel: _$react.NamedExoticComponent<FormLabelProps>;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { FormLabel, type FormLabelProps };
|
|
21
|
+
//# sourceMappingURL=FormLabel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormLabel.d.ts","names":[],"sources":["../../src/components/FormLabel.tsx"],"mappings":";;;;;;;UAQU,cAAA,SAEN,IAAA,CAAK,SAAA,6CACL,IAAA,CAAK,uBAAA;;EAEP,GAAA,GAAM,SAAA;EALE;EAOR,QAAA,GAAW,SAAA;;EAEX,KAAA,GAAQ,SAAA;EAND;EAQP,OAAA,GAAU,SAAA;AAAA;AAAA,cAGN,SAAA,EAAS,OAAA,CAAA,oBAAA,CAAA,cAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
|
+
import { Text } from "./Text.js";
|
|
3
|
+
import { memo, useMemo } from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { isFunction } from "lodash-es";
|
|
6
|
+
//#region src/components/FormLabel.tsx
|
|
7
|
+
const FormLabel = memo(function FormLabel({ required, label, children, color = "muted", variant = "label3", hasError = false, showRequiredAsterisk = false, ref, ...textProps }) {
|
|
8
|
+
const contents = useMemo(() => {
|
|
9
|
+
return label ? isFunction(label) ? label() : label : children;
|
|
10
|
+
}, [children, label]);
|
|
11
|
+
if (!contents) return null;
|
|
12
|
+
return /* @__PURE__ */ jsxs(Text, {
|
|
13
|
+
ref,
|
|
14
|
+
color,
|
|
15
|
+
variant,
|
|
16
|
+
...textProps,
|
|
17
|
+
children: [contents, required && showRequiredAsterisk && /* @__PURE__ */ jsx(Text, {
|
|
18
|
+
color: hasError ? "alert" : "inherit",
|
|
19
|
+
variant: "inherit",
|
|
20
|
+
spacingStart: "0.5",
|
|
21
|
+
accessibilityElementsHidden: true,
|
|
22
|
+
importantForAccessibility: "no",
|
|
23
|
+
children: "*"
|
|
24
|
+
})]
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
FormLabel.displayName = "FormLabel";
|
|
28
|
+
//#endregion
|
|
29
|
+
export { FormLabel };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=FormLabel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormLabel.js","names":[],"sources":["../../src/components/FormLabel.tsx"],"sourcesContent":["import type { UniversalFormLabelProps } from '@yahoo/uds-types';\nimport { isFunction } from 'lodash-es';\nimport type { ReactNode } from 'react';\nimport { memo, useMemo } from 'react';\n\nimport type { TextProps } from './Text';\nimport { Text } from './Text';\n\ninterface FormLabelProps\n extends\n Omit<TextProps, 'children' | 'color' | 'ref' | 'variant'>,\n Pick<UniversalFormLabelProps, 'hasError' | 'label' | 'required' | 'showRequiredAsterisk'> {\n /** Ref to the underlying Text. */\n ref?: TextProps['ref'];\n /** The label content. Used when the label prop is not provided. */\n children?: ReactNode;\n /** Label text color. */\n color?: TextProps['color'] | 'inherit';\n /** Typography variant for the label text. */\n variant?: TextProps['variant'] | 'inherit';\n}\n\nconst FormLabel = memo(function FormLabel({\n required,\n label,\n children,\n color = 'muted',\n variant = 'label3',\n hasError = false,\n showRequiredAsterisk = false,\n ref,\n ...textProps\n}: FormLabelProps) {\n const contents = useMemo(() => {\n return label ? (isFunction(label) ? label() : label) : children;\n }, [children, label]);\n\n if (!contents) {\n return null;\n }\n\n return (\n <Text ref={ref} color={color} variant={variant} {...textProps}>\n {contents}\n\n {required && showRequiredAsterisk && (\n <Text\n color={hasError ? 'alert' : 'inherit'}\n variant=\"inherit\"\n spacingStart=\"0.5\"\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n >\n *\n </Text>\n )}\n </Text>\n );\n});\n\nFormLabel.displayName = 'FormLabel';\n\nexport { FormLabel, type FormLabelProps };\n"],"mappings":";;;;;;AAsBA,MAAM,YAAY,KAAK,SAAS,UAAU,EACxC,UACA,OACA,UACA,QAAQ,SACR,UAAU,UACV,WAAW,OACX,uBAAuB,OACvB,KACA,GAAG,aACc;CACjB,MAAM,WAAW,cAAc;EAC7B,OAAO,QAAS,WAAW,MAAM,GAAG,OAAO,GAAG,QAAS;IACtD,CAAC,UAAU,MAAM,CAAC;CAErB,IAAI,CAAC,UACH,OAAO;CAGT,OACE,qBAAC,MAAD;EAAW;EAAY;EAAgB;EAAS,GAAI;YAApD,CACG,UAEA,YAAY,wBACX,oBAAC,MAAD;GACE,OAAO,WAAW,UAAU;GAC5B,SAAQ;GACR,cAAa;GACb,6BAAA;GACA,2BAA0B;aAC3B;GAEM,CAAA,CAEJ;;EAET;AAEF,UAAU,cAAc"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const require_runtime = require("
|
|
4
|
-
const require_index = require("
|
|
5
|
-
const require_motion = require("
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
3
|
+
const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
|
|
4
|
+
const require_index = require("../../motion-tokens/dist/index.cjs");
|
|
5
|
+
const require_motion = require("../../motion.cjs");
|
|
6
|
+
const require_components_Pressable = require("../Pressable.cjs");
|
|
7
|
+
const require_components_FormLabel = require("../FormLabel.cjs");
|
|
8
|
+
const require_components_Radio_RadioGroupContext = require("./RadioGroupContext.cjs");
|
|
9
9
|
let react = require("react");
|
|
10
10
|
let react_native = require("react-native");
|
|
11
11
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
12
|
-
let generated_styles = require("
|
|
12
|
+
let generated_styles = require("../../../generated/styles");
|
|
13
13
|
let react_native_reanimated = require("react-native-reanimated");
|
|
14
14
|
react_native_reanimated = require_runtime.__toESM(react_native_reanimated);
|
|
15
|
-
//#region src/components/Radio.tsx
|
|
15
|
+
//#region src/components/Radio/Radio.tsx
|
|
16
16
|
const VARIANT_ERROR_MAP = {
|
|
17
17
|
primary: "alert",
|
|
18
18
|
secondary: "alert-secondary"
|
|
@@ -49,12 +49,24 @@ const VARIANT_ERROR_MAP = {
|
|
|
49
49
|
* @see {@link Checkbox} for multi-select options
|
|
50
50
|
* @see {@link Switch} for binary toggles
|
|
51
51
|
*/
|
|
52
|
-
const Radio = (0, react.memo)(function Radio({ label, labelPosition = "start", variant:
|
|
52
|
+
const Radio = (0, react.memo)(function Radio({ label, labelPosition = "start", variant: variantInput, size: sizeInput, value: valueProp, checked: checkedProp, hasError: hasErrorProp, reduceMotion: reduceMotionProp, defaultChecked, disabled: disabledProp, required, onChange, ref, ...viewProps }) {
|
|
53
53
|
const uid = `uds-radio-${(0, react.useId)()}`;
|
|
54
|
+
const radioGroup = require_components_Radio_RadioGroupContext.useRadioGroupContext();
|
|
55
|
+
const disabled = Boolean(disabledProp || radioGroup?.disabled);
|
|
56
|
+
const hasError = hasErrorProp ?? radioGroup?.hasError;
|
|
57
|
+
const reduceMotion = reduceMotionProp ?? radioGroup?.reduceMotion;
|
|
58
|
+
const size = sizeInput ?? radioGroup?.size ?? "md";
|
|
59
|
+
const variantProp = variantInput ?? radioGroup?.variant ?? "primary";
|
|
60
|
+
const value = valueProp ?? "";
|
|
61
|
+
const isInRadioGroup = radioGroup !== void 0;
|
|
54
62
|
const isControlled = checkedProp !== void 0;
|
|
55
63
|
const [internalChecked, setInternalChecked] = (0, react.useState)(isControlled ? checkedProp : defaultChecked ?? false);
|
|
56
64
|
const [pressed, setPressed] = (0, react.useState)(false);
|
|
57
|
-
const checked = isControlled ? checkedProp : internalChecked;
|
|
65
|
+
const checked = isInRadioGroup ? radioGroup.value === value : isControlled ? checkedProp : internalChecked;
|
|
66
|
+
(0, react.useEffect)(() => {
|
|
67
|
+
if (!__DEV__ || !isInRadioGroup || valueProp) return;
|
|
68
|
+
console.warn("[UDS Mobile] Radio: A Radio rendered inside RadioGroup requires a unique, non-empty value prop.");
|
|
69
|
+
}, [isInRadioGroup, valueProp]);
|
|
58
70
|
const valueState = (0, react.useMemo)(() => {
|
|
59
71
|
return checked ? "checked" : "unchecked";
|
|
60
72
|
}, [checked]);
|
|
@@ -63,14 +75,23 @@ const Radio = (0, react.memo)(function Radio({ label, labelPosition = "start", v
|
|
|
63
75
|
const radioAnimatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({ transform: [{ scale: scaleProgress.value }] }));
|
|
64
76
|
const handlePress = (0, react.useCallback)(() => {
|
|
65
77
|
if (disabled) return;
|
|
78
|
+
if (isInRadioGroup) {
|
|
79
|
+
if (radioGroup.value === value) return;
|
|
80
|
+
radioGroup.setValue(value);
|
|
81
|
+
onChange?.(true);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
66
84
|
const newChecked = !checked;
|
|
67
85
|
if (!isControlled) setInternalChecked(newChecked);
|
|
68
86
|
onChange?.(newChecked);
|
|
69
87
|
}, [
|
|
70
88
|
disabled,
|
|
89
|
+
isInRadioGroup,
|
|
71
90
|
checked,
|
|
72
91
|
isControlled,
|
|
73
|
-
onChange
|
|
92
|
+
onChange,
|
|
93
|
+
radioGroup,
|
|
94
|
+
value
|
|
74
95
|
]);
|
|
75
96
|
const handlePressIn = (0, react.useCallback)(() => {
|
|
76
97
|
setPressed(true);
|
|
@@ -103,23 +124,19 @@ const Radio = (0, react.memo)(function Radio({ label, labelPosition = "start", v
|
|
|
103
124
|
}], [generated_styles.radioStyles.radioCircle]);
|
|
104
125
|
const labelContent = (0, react.useMemo)(() => {
|
|
105
126
|
if (!label) return null;
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
children: [textContent, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Text.Text, {
|
|
115
|
-
style: generated_styles.radioStyles.text,
|
|
116
|
-
children: "*"
|
|
117
|
-
})]
|
|
127
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_FormLabel.FormLabel, {
|
|
128
|
+
color: "inherit",
|
|
129
|
+
variant: "inherit",
|
|
130
|
+
label,
|
|
131
|
+
required,
|
|
132
|
+
showRequiredAsterisk: required,
|
|
133
|
+
hasError,
|
|
134
|
+
style: generated_styles.radioStyles.text
|
|
118
135
|
});
|
|
119
|
-
return textContent;
|
|
120
136
|
}, [
|
|
121
137
|
label,
|
|
122
138
|
required,
|
|
139
|
+
hasError,
|
|
123
140
|
generated_styles.radioStyles.text
|
|
124
141
|
]);
|
|
125
142
|
const a11yState = (0, react.useMemo)(() => ({
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
import { UniversalRadioProps } from "
|
|
2
|
+
import { UniversalRadioProps } from "../../types/dist/index.cjs";
|
|
3
3
|
import * as _$react from "react";
|
|
4
4
|
import { Ref } from "react";
|
|
5
5
|
import { View, ViewProps } from "react-native";
|
|
6
6
|
|
|
7
|
-
//#region src/components/Radio.d.ts
|
|
7
|
+
//#region src/components/Radio/Radio.d.ts
|
|
8
8
|
interface RadioProps extends Omit<ViewProps, 'style'>, UniversalRadioProps {
|
|
9
9
|
/** Ref to the underlying View */
|
|
10
10
|
ref?: Ref<View>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Radio.d.cts","names":[],"sources":["../../../src/components/Radio/Radio.tsx"],"mappings":";;;;;;;UAoBU,UAAA,SAAmB,IAAA,CAAK,SAAA,YAAqB,mBAAA;;EAErD,GAAA,GAAM,GAAA,CAAI,IAAA;EAFS;EAInB,cAAA;EAJgC;EAMhC,QAAA;EAJM;EAMN,QAAA;EARqD;EAUrD,QAAA,IAAY,OAAA;AAAA;;;;;;;;;;;;;;AAAgB;;;;;;;;;;;;;;;;;;;cAmDxB,KAAA,EAAK,OAAA,CAAA,oBAAA,CAAA,UAAA"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
import { UniversalRadioProps } from "
|
|
2
|
+
import { UniversalRadioProps } from "../../types/dist/index.js";
|
|
3
3
|
import * as _$react from "react";
|
|
4
4
|
import { Ref } from "react";
|
|
5
5
|
import { View, ViewProps } from "react-native";
|
|
6
6
|
|
|
7
|
-
//#region src/components/Radio.d.ts
|
|
7
|
+
//#region src/components/Radio/Radio.d.ts
|
|
8
8
|
interface RadioProps extends Omit<ViewProps, 'style'>, UniversalRadioProps {
|
|
9
9
|
/** Ref to the underlying View */
|
|
10
10
|
ref?: Ref<View>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Radio.d.ts","names":[],"sources":["../../../src/components/Radio/Radio.tsx"],"mappings":";;;;;;;UAoBU,UAAA,SAAmB,IAAA,CAAK,SAAA,YAAqB,mBAAA;;EAErD,GAAA,GAAM,GAAA,CAAI,IAAA;EAFS;EAInB,cAAA;EAJgC;EAMhC,QAAA;EAJM;EAMN,QAAA;EARqD;EAUrD,QAAA,IAAY,OAAA;AAAA;;;;;;;;;;;;;;AAAgB;;;;;;;;;;;;;;;;;;;cAmDxB,KAAA,EAAK,OAAA,CAAA,oBAAA,CAAA,UAAA"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
|
-
import { SCALE_EFFECTS } from "
|
|
3
|
-
import { BUTTON_SPRING_CONFIG } from "
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { SCALE_EFFECTS } from "../../motion-tokens/dist/index.js";
|
|
3
|
+
import { BUTTON_SPRING_CONFIG } from "../../motion.js";
|
|
4
|
+
import { Pressable as Pressable$1 } from "../Pressable.js";
|
|
5
|
+
import { FormLabel } from "../FormLabel.js";
|
|
6
|
+
import { useRadioGroupContext } from "./RadioGroupContext.js";
|
|
7
|
+
import { memo, useCallback, useEffect, useId, useMemo, useState } from "react";
|
|
8
8
|
import { View } from "react-native";
|
|
9
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
-
import { radioStyles } from "
|
|
10
|
+
import { radioStyles } from "../../../generated/styles";
|
|
11
11
|
import Animated, { useAnimatedStyle, useDerivedValue, withSpring } from "react-native-reanimated";
|
|
12
|
-
//#region src/components/Radio.tsx
|
|
12
|
+
//#region src/components/Radio/Radio.tsx
|
|
13
13
|
const VARIANT_ERROR_MAP = {
|
|
14
14
|
primary: "alert",
|
|
15
15
|
secondary: "alert-secondary"
|
|
@@ -46,12 +46,24 @@ const VARIANT_ERROR_MAP = {
|
|
|
46
46
|
* @see {@link Checkbox} for multi-select options
|
|
47
47
|
* @see {@link Switch} for binary toggles
|
|
48
48
|
*/
|
|
49
|
-
const Radio = memo(function Radio({ label, labelPosition = "start", variant:
|
|
49
|
+
const Radio = memo(function Radio({ label, labelPosition = "start", variant: variantInput, size: sizeInput, value: valueProp, checked: checkedProp, hasError: hasErrorProp, reduceMotion: reduceMotionProp, defaultChecked, disabled: disabledProp, required, onChange, ref, ...viewProps }) {
|
|
50
50
|
const uid = `uds-radio-${useId()}`;
|
|
51
|
+
const radioGroup = useRadioGroupContext();
|
|
52
|
+
const disabled = Boolean(disabledProp || radioGroup?.disabled);
|
|
53
|
+
const hasError = hasErrorProp ?? radioGroup?.hasError;
|
|
54
|
+
const reduceMotion = reduceMotionProp ?? radioGroup?.reduceMotion;
|
|
55
|
+
const size = sizeInput ?? radioGroup?.size ?? "md";
|
|
56
|
+
const variantProp = variantInput ?? radioGroup?.variant ?? "primary";
|
|
57
|
+
const value = valueProp ?? "";
|
|
58
|
+
const isInRadioGroup = radioGroup !== void 0;
|
|
51
59
|
const isControlled = checkedProp !== void 0;
|
|
52
60
|
const [internalChecked, setInternalChecked] = useState(isControlled ? checkedProp : defaultChecked ?? false);
|
|
53
61
|
const [pressed, setPressed] = useState(false);
|
|
54
|
-
const checked = isControlled ? checkedProp : internalChecked;
|
|
62
|
+
const checked = isInRadioGroup ? radioGroup.value === value : isControlled ? checkedProp : internalChecked;
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (!__DEV__ || !isInRadioGroup || valueProp) return;
|
|
65
|
+
console.warn("[UDS Mobile] Radio: A Radio rendered inside RadioGroup requires a unique, non-empty value prop.");
|
|
66
|
+
}, [isInRadioGroup, valueProp]);
|
|
55
67
|
const valueState = useMemo(() => {
|
|
56
68
|
return checked ? "checked" : "unchecked";
|
|
57
69
|
}, [checked]);
|
|
@@ -60,14 +72,23 @@ const Radio = memo(function Radio({ label, labelPosition = "start", variant: var
|
|
|
60
72
|
const radioAnimatedStyle = useAnimatedStyle(() => ({ transform: [{ scale: scaleProgress.value }] }));
|
|
61
73
|
const handlePress = useCallback(() => {
|
|
62
74
|
if (disabled) return;
|
|
75
|
+
if (isInRadioGroup) {
|
|
76
|
+
if (radioGroup.value === value) return;
|
|
77
|
+
radioGroup.setValue(value);
|
|
78
|
+
onChange?.(true);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
63
81
|
const newChecked = !checked;
|
|
64
82
|
if (!isControlled) setInternalChecked(newChecked);
|
|
65
83
|
onChange?.(newChecked);
|
|
66
84
|
}, [
|
|
67
85
|
disabled,
|
|
86
|
+
isInRadioGroup,
|
|
68
87
|
checked,
|
|
69
88
|
isControlled,
|
|
70
|
-
onChange
|
|
89
|
+
onChange,
|
|
90
|
+
radioGroup,
|
|
91
|
+
value
|
|
71
92
|
]);
|
|
72
93
|
const handlePressIn = useCallback(() => {
|
|
73
94
|
setPressed(true);
|
|
@@ -100,23 +121,19 @@ const Radio = memo(function Radio({ label, labelPosition = "start", variant: var
|
|
|
100
121
|
}], [radioStyles.radioCircle]);
|
|
101
122
|
const labelContent = useMemo(() => {
|
|
102
123
|
if (!label) return null;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
children: [textContent, /* @__PURE__ */ jsx(Text$1, {
|
|
112
|
-
style: radioStyles.text,
|
|
113
|
-
children: "*"
|
|
114
|
-
})]
|
|
124
|
+
return /* @__PURE__ */ jsx(FormLabel, {
|
|
125
|
+
color: "inherit",
|
|
126
|
+
variant: "inherit",
|
|
127
|
+
label,
|
|
128
|
+
required,
|
|
129
|
+
showRequiredAsterisk: required,
|
|
130
|
+
hasError,
|
|
131
|
+
style: radioStyles.text
|
|
115
132
|
});
|
|
116
|
-
return textContent;
|
|
117
133
|
}, [
|
|
118
134
|
label,
|
|
119
135
|
required,
|
|
136
|
+
hasError,
|
|
120
137
|
radioStyles.text
|
|
121
138
|
]);
|
|
122
139
|
const a11yState = useMemo(() => ({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Radio.js","names":["Pressable"],"sources":["../../../src/components/Radio/Radio.tsx"],"sourcesContent":["import type { RadioVariant, UniversalRadioProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useEffect, useId, useMemo, useState } from 'react';\nimport type { ViewProps } from 'react-native';\nimport { View } from 'react-native';\nimport Animated, { useAnimatedStyle, useDerivedValue, withSpring } from 'react-native-reanimated';\n\nimport { radioStyles } from '../../../generated/styles';\nimport { BUTTON_SPRING_CONFIG, SCALE_EFFECTS } from '../../motion';\nimport { FormLabel } from '../FormLabel';\nimport { Pressable } from '../Pressable';\nimport { useRadioGroupContext } from './RadioGroupContext';\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\n/** Derived from RadioValue - maps boolean to 'checked'/'unchecked' string literals */\ntype RadioValueState = 'checked' | 'unchecked';\n\ninterface RadioProps extends Omit<ViewProps, 'style'>, UniversalRadioProps {\n /** Ref to the underlying View */\n ref?: Ref<View>;\n /** Default checked state for uncontrolled mode */\n defaultChecked?: boolean;\n /** Whether the radio is disabled */\n disabled?: boolean;\n /** Whether the radio is required */\n required?: boolean;\n /** Callback fired when the checked state changes */\n onChange?: (checked: boolean) => void;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Variant Mapping */\n/* -------------------------------------------------------------------------- */\n\n/** All style variants available in the generated styles (includes error variants) */\ntype RadioStyleVariant = 'primary' | 'secondary' | 'alert' | 'alert-secondary';\n\nconst VARIANT_ERROR_MAP: Record<RadioVariant, RadioStyleVariant> = {\n primary: 'alert',\n secondary: 'alert-secondary',\n};\n\n/* -------------------------------------------------------------------------- */\n/* Radio Component */\n/* -------------------------------------------------------------------------- */\n\n/**\n * **⚙️ A radio component**\n *\n * @description\n * A radio component allows users to select one option from a set.\n * Unlike checkbox, radio buttons cannot have multiple selected in a group,\n * allowing only one selection at a time.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Radio } from '@yahoo/uds-mobile/Radio';\n *\n * <Radio label=\"Option A\" />\n * <Radio label=\"Option B\" checked={true} onChange={setChecked} />\n * ```\n *\n * @usage\n * - Forms: For selecting a single option from multiple choices\n * - Settings: For toggling between mutually exclusive preferences\n *\n * @accessibility\n * - Sets `accessibilityRole=\"radio\"` automatically\n * - Announces checked/unchecked state\n * - Label is used as accessibility label\n * - Supports `reduceMotion` for users who prefer reduced motion\n *\n * @see {@link Checkbox} for multi-select options\n * @see {@link Switch} for binary toggles\n */\nconst Radio = memo(function Radio({\n // Radio props\n label,\n labelPosition = 'start',\n variant: variantInput,\n size: sizeInput,\n value: valueProp,\n checked: checkedProp,\n hasError: hasErrorProp,\n reduceMotion: reduceMotionProp,\n // Native props\n defaultChecked,\n disabled: disabledProp,\n required,\n onChange,\n ref,\n ...viewProps\n}: RadioProps) {\n const generatedId = useId();\n const uid = `uds-radio-${generatedId}`;\n const radioGroup = useRadioGroupContext();\n\n const disabled = Boolean(disabledProp || radioGroup?.disabled);\n const hasError = hasErrorProp ?? radioGroup?.hasError;\n const reduceMotion = reduceMotionProp ?? radioGroup?.reduceMotion;\n const size = sizeInput ?? radioGroup?.size ?? 'md';\n const variantProp = variantInput ?? radioGroup?.variant ?? 'primary';\n const value = valueProp ?? '';\n\n /* --------------------------------- State ---------------------------------- */\n const isInRadioGroup = radioGroup !== undefined;\n const isControlled = checkedProp !== undefined;\n const [internalChecked, setInternalChecked] = useState<boolean>(\n isControlled ? checkedProp : (defaultChecked ?? false),\n );\n const [pressed, setPressed] = useState(false);\n\n // Use controlled value if provided, otherwise use internal state\n const checked = isInRadioGroup\n ? radioGroup.value === value\n : isControlled\n ? checkedProp\n : internalChecked;\n\n useEffect(() => {\n if (!__DEV__ || !isInRadioGroup || valueProp) {\n return;\n }\n\n console.warn(\n '[UDS Mobile] Radio: A Radio rendered inside RadioGroup requires a unique, non-empty value prop.',\n );\n }, [isInRadioGroup, valueProp]);\n\n /* ------------------------------ Derived Values ---------------------------- */\n const valueState: RadioValueState = useMemo(() => {\n return checked ? 'checked' : 'unchecked';\n }, [checked]);\n\n /* -------------------------------- Animation ------------------------------- */\n const shouldAnimate = !reduceMotion;\n\n // Scale animation for press feedback (disabled when reduceMotion is true)\n const scaleProgress = useDerivedValue(\n () =>\n shouldAnimate\n ? withSpring(pressed ? SCALE_EFFECTS.down : SCALE_EFFECTS.none, BUTTON_SPRING_CONFIG)\n : SCALE_EFFECTS.none, // No scale effect when reduceMotion is true\n [pressed, shouldAnimate],\n );\n\n const radioAnimatedStyle = useAnimatedStyle(() => ({\n transform: [{ scale: scaleProgress.value }],\n }));\n\n /* -------------------------------- Handlers -------------------------------- */\n const handlePress = useCallback(() => {\n if (disabled) {\n return;\n }\n\n if (isInRadioGroup) {\n if (radioGroup.value === value) {\n return;\n }\n\n radioGroup.setValue(value);\n onChange?.(true);\n return;\n }\n\n const newChecked = !checked;\n\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n\n onChange?.(newChecked);\n }, [disabled, isInRadioGroup, checked, isControlled, onChange, radioGroup, value]);\n\n const handlePressIn = useCallback(() => {\n setPressed(true);\n }, []);\n\n const handlePressOut = useCallback(() => {\n setPressed(false);\n }, []);\n\n /* --------------------------------- Styles --------------------------------- */\n // Compute the style variant (primary/secondary maps to alert variants when hasError)\n const styleVariant: RadioStyleVariant = hasError ? VARIANT_ERROR_MAP[variantProp] : variantProp;\n\n radioStyles.useVariants({\n size,\n variant: styleVariant, // primary, secondary, alert, alert-secondary\n value: valueState, // checked, unchecked\n pressed,\n });\n\n const rootStyle = useMemo(\n () => [radioStyles.root, { opacity: disabled ? 0.5 : 1 }],\n [radioStyles.root, disabled],\n );\n\n const radioBoxStyle = useMemo(\n () => [\n radioStyles.radio,\n {\n alignItems: 'center' as const,\n justifyContent: 'center' as const,\n borderRadius: 9999,\n },\n radioAnimatedStyle,\n ],\n [radioStyles.radio, radioAnimatedStyle],\n );\n\n // Inner circle size: fixed 8x8px to match web implementation\n const INNER_CIRCLE_SIZE = 8;\n\n const circleStyle = useMemo(\n () => [\n radioStyles.radioCircle,\n {\n width: INNER_CIRCLE_SIZE,\n height: INNER_CIRCLE_SIZE,\n borderRadius: 9999,\n },\n ],\n [radioStyles.radioCircle],\n );\n\n /* ---------------------------- Render Helpers ------------------------------ */\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n\n return (\n <FormLabel\n color=\"inherit\"\n variant=\"inherit\"\n label={label}\n required={required}\n showRequiredAsterisk={required}\n hasError={hasError}\n style={radioStyles.text}\n />\n );\n }, [label, required, hasError, radioStyles.text]);\n\n const a11yState = useMemo(\n () => ({\n disabled,\n checked,\n }),\n [disabled, checked],\n );\n\n /* --------------------------------- Render --------------------------------- */\n return (\n <Pressable\n ref={ref}\n nativeID={uid}\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n disabled={disabled}\n flexDirection={labelPosition === 'start' ? 'row' : 'row-reverse'}\n alignItems=\"center\"\n alignSelf=\"flex-start\"\n accessibilityRole=\"radio\"\n accessibilityState={a11yState}\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n {...viewProps}\n style={rootStyle}\n >\n <Animated.View style={radioBoxStyle}>{checked && <View style={circleStyle} />}</Animated.View>\n\n {labelContent}\n </Pressable>\n );\n});\n\nRadio.displayName = 'Radio';\n\nexport { Radio, type RadioProps };\n"],"mappings":"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"}
|