@yahoo/uds-mobile 2.11.0 → 2.13.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.
Files changed (99) hide show
  1. package/dist/bin/fixtures/dist/index.mjs +0 -10
  2. package/dist/bin/mobile/scripts/utils/configToRNMappings.mjs +2 -0
  3. package/dist/bin/modes/dist/index.mjs +1 -0
  4. package/dist/bin/palette/dist/index.mjs +1 -0
  5. package/dist/components/AndroidBackHandler.js.map +1 -1
  6. package/dist/components/Avatar.js.map +1 -1
  7. package/dist/components/Badge.js.map +1 -1
  8. package/dist/components/Banner/Banner.js.map +1 -1
  9. package/dist/components/Banner/BannerContent.js.map +1 -1
  10. package/dist/components/Banner/BannerDescription.js.map +1 -1
  11. package/dist/components/Banner/BannerTitle.js.map +1 -1
  12. package/dist/components/Banner/utils.js.map +1 -1
  13. package/dist/components/BlurTarget.js.map +1 -1
  14. package/dist/components/BottomSheet/BottomSheet.js.map +1 -1
  15. package/dist/components/BottomSheet/BottomSheetContent.js.map +1 -1
  16. package/dist/components/BottomSheet/BottomSheetDismiss.js.map +1 -1
  17. package/dist/components/BottomSheet/BottomSheetHandle.js.map +1 -1
  18. package/dist/components/BottomSheet/BottomSheetHeader.js.map +1 -1
  19. package/dist/components/BottomSheet/BottomSheetInternalProvider.js.map +1 -1
  20. package/dist/components/BottomSheet/BottomSheetProvider.js.map +1 -1
  21. package/dist/components/BottomSheet/BottomSheetTrigger.js.map +1 -1
  22. package/dist/components/BottomSheet/useBottomSheetDrag.js.map +1 -1
  23. package/dist/components/BottomSheet/useBottomSheetScroll.js.map +1 -1
  24. package/dist/components/BottomSheet/useBottomSheetSnapModel.js.map +1 -1
  25. package/dist/components/BottomSheet/useBottomSheetStore.js.map +1 -1
  26. package/dist/components/BottomSheet/useExpansionMargins.js.map +1 -1
  27. package/dist/components/BottomSheet/useKeyboardAvoidance.js.map +1 -1
  28. package/dist/components/BottomSheet/utils.js.map +1 -1
  29. package/dist/components/Box.js.map +1 -1
  30. package/dist/components/Button.js.map +1 -1
  31. package/dist/components/Checkbox.cjs +10 -15
  32. package/dist/components/Checkbox.d.cts.map +1 -1
  33. package/dist/components/Checkbox.d.ts.map +1 -1
  34. package/dist/components/Checkbox.js +11 -16
  35. package/dist/components/Checkbox.js.map +1 -1
  36. package/dist/components/Chip.js.map +1 -1
  37. package/dist/components/Divider/Divider.js.map +1 -1
  38. package/dist/components/Divider/DividerLabel.js.map +1 -1
  39. package/dist/components/Divider/DividerLine.js.map +1 -1
  40. package/dist/components/Divider/utils.js.map +1 -1
  41. package/dist/components/FormLabel.cjs +31 -0
  42. package/dist/components/FormLabel.d.cts +21 -0
  43. package/dist/components/FormLabel.d.cts.map +1 -0
  44. package/dist/components/FormLabel.d.ts +21 -0
  45. package/dist/components/FormLabel.d.ts.map +1 -0
  46. package/dist/components/FormLabel.js +31 -0
  47. package/dist/components/FormLabel.js.map +1 -0
  48. package/dist/components/HStack.js.map +1 -1
  49. package/dist/components/Icon.js.map +1 -1
  50. package/dist/components/IconButton.js.map +1 -1
  51. package/dist/components/IconSlot.js.map +1 -1
  52. package/dist/components/Image.js.map +1 -1
  53. package/dist/components/Input.js.map +1 -1
  54. package/dist/components/Link.js.map +1 -1
  55. package/dist/components/Pressable.js.map +1 -1
  56. package/dist/components/Radio.cjs +10 -15
  57. package/dist/components/Radio.d.cts.map +1 -1
  58. package/dist/components/Radio.d.ts.map +1 -1
  59. package/dist/components/Radio.js +11 -16
  60. package/dist/components/Radio.js.map +1 -1
  61. package/dist/components/Screen.js.map +1 -1
  62. package/dist/components/Scrim.js.map +1 -1
  63. package/dist/components/Switch.cjs +8 -13
  64. package/dist/components/Switch.d.cts.map +1 -1
  65. package/dist/components/Switch.d.ts.map +1 -1
  66. package/dist/components/Switch.js +8 -13
  67. package/dist/components/Switch.js.map +1 -1
  68. package/dist/components/Tabs/Tab.js.map +1 -1
  69. package/dist/components/Tabs/TabList.js.map +1 -1
  70. package/dist/components/Tabs/TabPanel.js.map +1 -1
  71. package/dist/components/Tabs/Tabs.js.map +1 -1
  72. package/dist/components/Tabs/tabTheme.js.map +1 -1
  73. package/dist/components/Tabs/tabsContexts.js.map +1 -1
  74. package/dist/components/Text.cjs +12 -6
  75. package/dist/components/Text.d.cts +3 -2
  76. package/dist/components/Text.d.cts.map +1 -1
  77. package/dist/components/Text.d.ts +3 -2
  78. package/dist/components/Text.d.ts.map +1 -1
  79. package/dist/components/Text.js +12 -6
  80. package/dist/components/Text.js.map +1 -1
  81. package/dist/components/UDSProvider.js.map +1 -1
  82. package/dist/components/VStack.js.map +1 -1
  83. package/dist/jest/mocks/icons.js.map +1 -1
  84. package/dist/jest/mocks/react-native.js.map +1 -1
  85. package/dist/jest/mocks/reanimated.js.map +1 -1
  86. package/dist/jest/mocks/styles.js.map +1 -1
  87. package/dist/jest/mocks/svg.js.map +1 -1
  88. package/dist/jest/mocks/unistyles.js.map +1 -1
  89. package/dist/jest/setup.js.map +1 -1
  90. package/dist/portal.js.map +1 -1
  91. package/dist/types/dist/index.d.cts +39 -1
  92. package/dist/types/dist/index.d.cts.map +1 -1
  93. package/dist/types/dist/index.d.ts +39 -1
  94. package/dist/types/dist/index.d.ts.map +1 -1
  95. package/generated/styles.cjs +4 -0
  96. package/generated/styles.d.ts +2 -1
  97. package/generated/styles.mjs +4 -0
  98. package/generated/unistyles.d.ts +6 -0
  99. package/package.json +11 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Radio.js","names":["Text","Pressable"],"sources":["../../src/components/Radio.tsx"],"sourcesContent":["import type { RadioVariant, UniversalRadioProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { isValidElement, memo, useCallback, 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 { HStack } from './HStack';\nimport { Pressable } from './Pressable';\nimport { Text } from './Text';\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: 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}: RadioProps) {\n const generatedId = useId();\n const uid = `uds-radio-${generatedId}`;\n\n /* --------------------------------- State ---------------------------------- */\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 = isControlled ? checkedProp : internalChecked;\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 const newChecked = !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: 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 const content =\n typeof label === 'function' ? label() : isValidElement(label) ? label : String(label);\n\n const textContent =\n typeof content === 'string' ? <Text style={radioStyles.text}>{content}</Text> : content;\n\n if (required) {\n return (\n <HStack columnGap=\"1\" alignItems=\"flex-start\">\n {textContent}\n <Text style={radioStyles.text}>*</Text>\n </HStack>\n );\n }\n\n return textContent;\n }, [label, required, 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":";;;;;;;;;;;;AAwCA,MAAM,oBAA6D;CACjE,SAAS;CACT,WAAW;CACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCD,MAAM,QAAQ,KAAK,SAAS,MAAM,EAEhC,OACA,gBAAgB,SAChB,SAAS,cAAc,WACvB,OAAO,MACP,SAAS,aACT,UACA,cAEA,gBACA,UACA,UACA,UACA,KACA,GAAG,aACU;CAEb,MAAM,MAAM,aADQ,OACgB;CAGpC,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,aAA8B,cAAc;AAChD,SAAO,UAAU,YAAY;IAC5B,CAAC,QAAQ,CAAC;CAGb,MAAM,gBAAgB,CAAC;CAGvB,MAAM,gBAAgB,sBAElB,gBACI,WAAW,UAAU,cAAc,OAAO,cAAc,MAAM,qBAAqB,GACnF,cAAc,MACpB,CAAC,SAAS,cAAc,CACzB;CAED,MAAM,qBAAqB,wBAAwB,EACjD,WAAW,CAAC,EAAE,OAAO,cAAc,OAAO,CAAC,EAC5C,EAAE;CAGH,MAAM,cAAc,kBAAkB;AACpC,MAAI,SACF;EAGF,MAAM,aAAa,CAAC;AAEpB,MAAI,CAAC,aACH,oBAAmB,WAAW;AAGhC,aAAW,WAAW;IACrB;EAAC;EAAU;EAAS;EAAc;EAAS,CAAC;CAE/C,MAAM,gBAAgB,kBAAkB;AACtC,aAAW,KAAK;IACf,EAAE,CAAC;CAEN,MAAM,iBAAiB,kBAAkB;AACvC,aAAW,MAAM;IAChB,EAAE,CAAC;CAIN,MAAM,eAAkC,WAAW,kBAAkB,eAAe;AAEpF,aAAY,YAAY;EACtB;EACA,SAAS;EACT,OAAO;EACP;EACD,CAAC;CAEF,MAAM,YAAY,cACV,CAAC,YAAY,MAAM,EAAE,SAAS,WAAW,KAAM,GAAG,CAAC,EACzD,CAAC,YAAY,MAAM,SAAS,CAC7B;CAED,MAAM,gBAAgB,cACd;EACJ,YAAY;EACZ;GACE,YAAY;GACZ,gBAAgB;GAChB,cAAc;GACf;EACD;EACD,EACD,CAAC,YAAY,OAAO,mBAAmB,CACxC;CAGD,MAAM,oBAAoB;CAE1B,MAAM,cAAc,cACZ,CACJ,YAAY,aACZ;EACE,OAAO;EACP,QAAQ;EACR,cAAc;EACf,CACF,EACD,CAAC,YAAY,YAAY,CAC1B;CAGD,MAAM,eAAe,cAAc;AACjC,MAAI,CAAC,MACH,QAAO;EAGT,MAAM,UACJ,OAAO,UAAU,aAAa,OAAO,GAAG,eAAe,MAAM,GAAG,QAAQ,OAAO,MAAM;EAEvF,MAAM,cACJ,OAAO,YAAY,WAAW,oBAACA,QAAD;GAAM,OAAO,YAAY;aAAO;GAAe,CAAA,GAAG;AAElF,MAAI,SACF,QACE,qBAAC,QAAD;GAAQ,WAAU;GAAI,YAAW;aAAjC,CACG,aACD,oBAACA,QAAD;IAAM,OAAO,YAAY;cAAM;IAAQ,CAAA,CAChC;;AAIb,SAAO;IACN;EAAC;EAAO;EAAU,YAAY;EAAK,CAAC;CAEvC,MAAM,YAAY,eACT;EACL;EACA;EACD,GACD,CAAC,UAAU,QAAQ,CACpB;AAGD,QACE,qBAACC,aAAD;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;aAAgB,WAAW,oBAAC,MAAD,EAAM,OAAO,aAAe,CAAA;GAAiB,CAAA,EAE7F,aACS;;EAEd;AAEF,MAAM,cAAc"}
1
+ {"version":3,"file":"Radio.js","names":["Pressable"],"sources":["../../src/components/Radio.tsx"],"sourcesContent":["import type { RadioVariant, UniversalRadioProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { memo, useCallback, 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';\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: 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}: RadioProps) {\n const generatedId = useId();\n const uid = `uds-radio-${generatedId}`;\n\n /* --------------------------------- State ---------------------------------- */\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 = isControlled ? checkedProp : internalChecked;\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 const newChecked = !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: 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":";;;;;;;;;;;AAuCA,MAAM,oBAA6D;CACjE,SAAS;CACT,WAAW;CACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCD,MAAM,QAAQ,KAAK,SAAS,MAAM,EAEhC,OACA,gBAAgB,SAChB,SAAS,cAAc,WACvB,OAAO,MACP,SAAS,aACT,UACA,cAEA,gBACA,UACA,UACA,UACA,KACA,GAAG,aACU;CAEb,MAAM,MAAM,aADQ,OACgB;CAGpC,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,aAA8B,cAAc;EAChD,OAAO,UAAU,YAAY;IAC5B,CAAC,QAAQ,CAAC;CAGb,MAAM,gBAAgB,CAAC;CAGvB,MAAM,gBAAgB,sBAElB,gBACI,WAAW,UAAU,cAAc,OAAO,cAAc,MAAM,qBAAqB,GACnF,cAAc,MACpB,CAAC,SAAS,cAAc,CACzB;CAED,MAAM,qBAAqB,wBAAwB,EACjD,WAAW,CAAC,EAAE,OAAO,cAAc,OAAO,CAAC,EAC5C,EAAE;CAGH,MAAM,cAAc,kBAAkB;EACpC,IAAI,UACF;EAGF,MAAM,aAAa,CAAC;EAEpB,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,eAAkC,WAAW,kBAAkB,eAAe;CAEpF,YAAY,YAAY;EACtB;EACA,SAAS;EACT,OAAO;EACP;EACD,CAAC;CAEF,MAAM,YAAY,cACV,CAAC,YAAY,MAAM,EAAE,SAAS,WAAW,KAAM,GAAG,CAAC,EACzD,CAAC,YAAY,MAAM,SAAS,CAC7B;CAED,MAAM,gBAAgB,cACd;EACJ,YAAY;EACZ;GACE,YAAY;GACZ,gBAAgB;GAChB,cAAc;GACf;EACD;EACD,EACD,CAAC,YAAY,OAAO,mBAAmB,CACxC;CAGD,MAAM,oBAAoB;CAE1B,MAAM,cAAc,cACZ,CACJ,YAAY,aACZ;EACE,OAAO;EACP,QAAQ;EACR,cAAc;EACf,CACF,EACD,CAAC,YAAY,YAAY,CAC1B;CAGD,MAAM,eAAe,cAAc;EACjC,IAAI,CAAC,OACH,OAAO;EAGT,OACE,oBAAC,WAAD;GACE,OAAM;GACN,SAAQ;GACD;GACG;GACV,sBAAsB;GACZ;GACV,OAAO,YAAY;GACnB,CAAA;IAEH;EAAC;EAAO;EAAU;EAAU,YAAY;EAAK,CAAC;CAEjD,MAAM,YAAY,eACT;EACL;EACA;EACD,GACD,CAAC,UAAU,QAAQ,CACpB;CAGD,OACE,qBAACA,aAAD;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;aAAgB,WAAW,oBAAC,MAAD,EAAM,OAAO,aAAe,CAAA;GAAiB,CAAA,EAE7F,aACS;;EAEd;AAEF,MAAM,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"Screen.js","names":["StyleSheet"],"sources":["../../src/components/Screen.tsx"],"sourcesContent":["import type { ReactNode, Ref } from 'react';\nimport { memo, useMemo } from 'react';\nimport type { ScrollViewProps, ViewProps } from 'react-native';\nimport { ScrollView } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport type { StyleProps } from '../../generated/styles';\nimport { styles } from '../../generated/styles';\nimport type { HStackProps } from './HStack';\nimport { HStack } from './HStack';\nimport { VStack } from './VStack';\n\ninterface ScreenProps extends ScrollViewProps {\n /** Ref to the underlying ScrollView */\n ref?: Ref<ScrollView>;\n /** Background color of the screen */\n backgroundColor?: StyleProps['backgroundColor'];\n /** Horizontal padding for screen content */\n spacingHorizontal?: StyleProps['spacingHorizontal'];\n /** Top padding for screen content */\n spacingTop?: StyleProps['spacingTop'];\n /** Gap between child elements */\n gap?: StyleProps['columnGap'];\n /** Content that sticks to the top of the screen when scrolling */\n stickyHeader?: ReactNode;\n /** Props passed to the sticky header container */\n stickyHeaderProps?: HStackProps;\n}\n\n/**\n * **📱 A screen container with safe area handling**\n *\n * @description\n * A scrollable screen component that handles safe area insets and provides\n * consistent padding and background styling. Uses Unistyles' built-in\n * safe area insets via the `rt` runtime object.\n *\n * @category Layout\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Screen } from '@yahoo/uds-mobile/Screen';\n *\n * <Screen backgroundColor=\"primary\" spacingHorizontal=\"6\">\n * <Text>Screen content</Text>\n * </Screen>\n *\n * // With sticky header\n * <Screen\n * stickyHeader={<Text>Header</Text>}\n * stickyHeaderProps={{ backgroundColor: 'secondary' }}\n * >\n * <Text>Content</Text>\n * </Screen>\n * ```\n *\n * @usage\n * - Use as the root component for screens\n * - Use stickyHeader for persistent header content\n * - Content is automatically scrollable\n * - Safe area insets are handled automatically\n *\n * @see {@link VStack} for non-scrollable vertical layouts\n * @see {@link Box} for custom containers\n */\nconst Screen = memo(function Screen({\n children,\n // Background\n backgroundColor = 'primary',\n // Spacing\n spacingHorizontal = '6',\n spacingTop = '6',\n gap,\n // Header\n stickyHeader,\n stickyHeaderProps,\n style,\n ref,\n ...props\n}: ScreenProps) {\n const { style: stickyHeaderStyle, ...stickyHeaderPropsWithoutStyle } = stickyHeaderProps ?? {};\n\n styles.useVariants({\n backgroundColor,\n flex: '1',\n flexDirection: 'column',\n columnGap: gap,\n });\n\n // styles.foundation must be in deps - it returns a new reference when variants change\n const scrollStyles = useMemo(\n () => [styles.foundation as ViewProps['style'], style],\n [styles.foundation, style],\n );\n\n return (\n <VStack backgroundColor=\"primary\" style={screenStyles.wrapper}>\n <ScrollView\n ref={ref}\n style={scrollStyles}\n stickyHeaderIndices={stickyHeader ? [0] : undefined}\n {...props}\n >\n {stickyHeader && (\n <HStack\n spacingHorizontal=\"6\"\n spacingBottom=\"4\"\n backgroundColor=\"primary\"\n justifyContent=\"flex-end\"\n style={stickyHeaderStyle}\n {...stickyHeaderPropsWithoutStyle}\n >\n {stickyHeader}\n </HStack>\n )}\n <VStack flex=\"1\" spacingHorizontal={spacingHorizontal} spacingTop={spacingTop} gap={gap}>\n {children}\n </VStack>\n </ScrollView>\n </VStack>\n );\n});\n\nScreen.displayName = 'Screen';\n\nconst screenStyles = StyleSheet.create((_theme, rt) => ({\n wrapper: {\n flex: 1, // apply insets to the container,\n // so it will add required paddings\n paddingTop: rt.insets.top,\n paddingBottom: rt.insets.bottom,\n paddingLeft: rt.insets.left,\n paddingRight: rt.insets.right,\n },\n}));\n\nexport { Screen, type ScreenProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,MAAM,SAAS,KAAK,SAAS,OAAO,EAClC,UAEA,kBAAkB,WAElB,oBAAoB,KACpB,aAAa,KACb,KAEA,cACA,mBACA,OACA,KACA,GAAG,SACW;CACd,MAAM,EAAE,OAAO,mBAAmB,GAAG,kCAAkC,qBAAqB,EAAE;AAE9F,QAAO,YAAY;EACjB;EACA,MAAM;EACN,eAAe;EACf,WAAW;EACZ,CAAC;CAGF,MAAM,eAAe,cACb,CAAC,OAAO,YAAkC,MAAM,EACtD,CAAC,OAAO,YAAY,MAAM,CAC3B;AAED,QACE,oBAAC,QAAD;EAAQ,iBAAgB;EAAU,OAAO,aAAa;YACpD,qBAAC,YAAD;GACO;GACL,OAAO;GACP,qBAAqB,eAAe,CAAC,EAAE,GAAG,KAAA;GAC1C,GAAI;aAJN,CAMG,gBACC,oBAAC,QAAD;IACE,mBAAkB;IAClB,eAAc;IACd,iBAAgB;IAChB,gBAAe;IACf,OAAO;IACP,GAAI;cAEH;IACM,CAAA,EAEX,oBAAC,QAAD;IAAQ,MAAK;IAAuB;IAA+B;IAAiB;IACjF;IACM,CAAA,CACE;;EACN,CAAA;EAEX;AAEF,OAAO,cAAc;AAErB,MAAM,eAAeA,aAAW,QAAQ,QAAQ,QAAQ,EACtD,SAAS;CACP,MAAM;CAEN,YAAY,GAAG,OAAO;CACtB,eAAe,GAAG,OAAO;CACzB,aAAa,GAAG,OAAO;CACvB,cAAc,GAAG,OAAO;CACzB,EACF,EAAE"}
1
+ {"version":3,"file":"Screen.js","names":["StyleSheet"],"sources":["../../src/components/Screen.tsx"],"sourcesContent":["import type { ReactNode, Ref } from 'react';\nimport { memo, useMemo } from 'react';\nimport type { ScrollViewProps, ViewProps } from 'react-native';\nimport { ScrollView } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport type { StyleProps } from '../../generated/styles';\nimport { styles } from '../../generated/styles';\nimport type { HStackProps } from './HStack';\nimport { HStack } from './HStack';\nimport { VStack } from './VStack';\n\ninterface ScreenProps extends ScrollViewProps {\n /** Ref to the underlying ScrollView */\n ref?: Ref<ScrollView>;\n /** Background color of the screen */\n backgroundColor?: StyleProps['backgroundColor'];\n /** Horizontal padding for screen content */\n spacingHorizontal?: StyleProps['spacingHorizontal'];\n /** Top padding for screen content */\n spacingTop?: StyleProps['spacingTop'];\n /** Gap between child elements */\n gap?: StyleProps['columnGap'];\n /** Content that sticks to the top of the screen when scrolling */\n stickyHeader?: ReactNode;\n /** Props passed to the sticky header container */\n stickyHeaderProps?: HStackProps;\n}\n\n/**\n * **📱 A screen container with safe area handling**\n *\n * @description\n * A scrollable screen component that handles safe area insets and provides\n * consistent padding and background styling. Uses Unistyles' built-in\n * safe area insets via the `rt` runtime object.\n *\n * @category Layout\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Screen } from '@yahoo/uds-mobile/Screen';\n *\n * <Screen backgroundColor=\"primary\" spacingHorizontal=\"6\">\n * <Text>Screen content</Text>\n * </Screen>\n *\n * // With sticky header\n * <Screen\n * stickyHeader={<Text>Header</Text>}\n * stickyHeaderProps={{ backgroundColor: 'secondary' }}\n * >\n * <Text>Content</Text>\n * </Screen>\n * ```\n *\n * @usage\n * - Use as the root component for screens\n * - Use stickyHeader for persistent header content\n * - Content is automatically scrollable\n * - Safe area insets are handled automatically\n *\n * @see {@link VStack} for non-scrollable vertical layouts\n * @see {@link Box} for custom containers\n */\nconst Screen = memo(function Screen({\n children,\n // Background\n backgroundColor = 'primary',\n // Spacing\n spacingHorizontal = '6',\n spacingTop = '6',\n gap,\n // Header\n stickyHeader,\n stickyHeaderProps,\n style,\n ref,\n ...props\n}: ScreenProps) {\n const { style: stickyHeaderStyle, ...stickyHeaderPropsWithoutStyle } = stickyHeaderProps ?? {};\n\n styles.useVariants({\n backgroundColor,\n flex: '1',\n flexDirection: 'column',\n columnGap: gap,\n });\n\n // styles.foundation must be in deps - it returns a new reference when variants change\n const scrollStyles = useMemo(\n () => [styles.foundation as ViewProps['style'], style],\n [styles.foundation, style],\n );\n\n return (\n <VStack backgroundColor=\"primary\" style={screenStyles.wrapper}>\n <ScrollView\n ref={ref}\n style={scrollStyles}\n stickyHeaderIndices={stickyHeader ? [0] : undefined}\n {...props}\n >\n {stickyHeader && (\n <HStack\n spacingHorizontal=\"6\"\n spacingBottom=\"4\"\n backgroundColor=\"primary\"\n justifyContent=\"flex-end\"\n style={stickyHeaderStyle}\n {...stickyHeaderPropsWithoutStyle}\n >\n {stickyHeader}\n </HStack>\n )}\n <VStack flex=\"1\" spacingHorizontal={spacingHorizontal} spacingTop={spacingTop} gap={gap}>\n {children}\n </VStack>\n </ScrollView>\n </VStack>\n );\n});\n\nScreen.displayName = 'Screen';\n\nconst screenStyles = StyleSheet.create((_theme, rt) => ({\n wrapper: {\n flex: 1, // apply insets to the container,\n // so it will add required paddings\n paddingTop: rt.insets.top,\n paddingBottom: rt.insets.bottom,\n paddingLeft: rt.insets.left,\n paddingRight: rt.insets.right,\n },\n}));\n\nexport { Screen, type ScreenProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,MAAM,SAAS,KAAK,SAAS,OAAO,EAClC,UAEA,kBAAkB,WAElB,oBAAoB,KACpB,aAAa,KACb,KAEA,cACA,mBACA,OACA,KACA,GAAG,SACW;CACd,MAAM,EAAE,OAAO,mBAAmB,GAAG,kCAAkC,qBAAqB,EAAE;CAE9F,OAAO,YAAY;EACjB;EACA,MAAM;EACN,eAAe;EACf,WAAW;EACZ,CAAC;CAGF,MAAM,eAAe,cACb,CAAC,OAAO,YAAkC,MAAM,EACtD,CAAC,OAAO,YAAY,MAAM,CAC3B;CAED,OACE,oBAAC,QAAD;EAAQ,iBAAgB;EAAU,OAAO,aAAa;YACpD,qBAAC,YAAD;GACO;GACL,OAAO;GACP,qBAAqB,eAAe,CAAC,EAAE,GAAG,KAAA;GAC1C,GAAI;aAJN,CAMG,gBACC,oBAAC,QAAD;IACE,mBAAkB;IAClB,eAAc;IACd,iBAAgB;IAChB,gBAAe;IACf,OAAO;IACP,GAAI;cAEH;IACM,CAAA,EAEX,oBAAC,QAAD;IAAQ,MAAK;IAAuB;IAA+B;IAAiB;IACjF;IACM,CAAA,CACE;;EACN,CAAA;EAEX;AAEF,OAAO,cAAc;AAErB,MAAM,eAAeA,aAAW,QAAQ,QAAQ,QAAQ,EACtD,SAAS;CACP,MAAM;CAEN,YAAY,GAAG,OAAO;CACtB,eAAe,GAAG,OAAO;CACzB,aAAa,GAAG,OAAO;CACvB,cAAc,GAAG,OAAO;CACzB,EACF,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"Scrim.js","names":[],"sources":["../../src/components/Scrim.tsx"],"sourcesContent":["import type { RefObject } from 'react';\nimport { memo, useCallback } from 'react';\nimport { Platform, StyleSheet, View } from 'react-native';\nimport { Gesture, GestureDetector } from 'react-native-gesture-handler';\nimport type { SharedValue } from 'react-native-reanimated';\nimport Animated, { interpolate, runOnJS, useAnimatedStyle } from 'react-native-reanimated';\n\nimport { scrimStyles } from '../../generated/styles';\nimport { Box } from './Box';\n\ninterface ScrimRootTokens {\n backgroundColor?: string;\n backgroundBlurRadius?: number;\n opacity?: number;\n}\n\ninterface ScrimProps {\n /** Animated translateY position of the overlaying content (UI-thread shared value). */\n translateY: SharedValue<number>;\n /** `translateY` value when the content is at its open position. */\n openTranslateY: number;\n /** `translateY` value when the content is fully closed / off-screen. */\n closedTranslateY: number;\n /** Whether tapping the scrim dismisses the content. */\n dismissible: boolean;\n /** Callback invoked when the scrim is tapped and `dismissible` is `true`. */\n onDismiss: () => void;\n /** Ref to a `<BlurTarget>` view for Android backdrop blur. Not needed on iOS. */\n blurTarget?: RefObject<View | null>;\n}\n\n/**\n * Semi-transparent backdrop for modal overlays.\n *\n * Reads `backgroundColor` and `opacity` from the configurator's scrim tokens.\n * Opacity is interpolated between 0 (closed) and the token value (open) based\n * on the content's current `translateY` position.\n *\n * @example\n * ```tsx\n * <Scrim\n * translateY={translateY}\n * openTranslateY={openY}\n * closedTranslateY={closedY}\n * dismissible\n * onDismiss={handleDismiss}\n * />\n * ```\n */\nconst Scrim = memo(function Scrim({\n translateY,\n openTranslateY,\n closedTranslateY,\n dismissible,\n onDismiss,\n blurTarget,\n}: ScrimProps) {\n scrimStyles.useVariants({});\n const scrimTokens = StyleSheet.flatten(scrimStyles.root) as ScrimRootTokens;\n const targetColor = scrimTokens.backgroundColor ?? 'rgba(0, 0, 0, 1)';\n const targetOpacity = scrimTokens.opacity ?? 0.2;\n const blurIntensity = scrimTokens.backgroundBlurRadius ?? 0;\n // iOS blur works without a target; Android requires a blurTarget ref.\n const showBlur = blurIntensity > 0 && (Platform.OS === 'ios' || blurTarget != null);\n\n const handleDismiss = useCallback(() => {\n onDismiss();\n }, [onDismiss]);\n\n const animatedColorStyle = useAnimatedStyle(() => {\n const opacity = interpolate(\n translateY.value,\n [openTranslateY, closedTranslateY],\n [targetOpacity, 0],\n 'clamp',\n );\n\n return { opacity };\n });\n\n // Blur needs its own opacity animation (1 → 0) separate from the color overlay.\n // On iOS, UIVisualEffectView breaks if its parent rests at a fractional opacity.\n const animatedBlurStyle = useAnimatedStyle(() => {\n const opacity = interpolate(\n translateY.value,\n [openTranslateY, closedTranslateY],\n [1, 0],\n 'clamp',\n );\n\n return { opacity };\n });\n\n // Tap gesture on scrim for dismissal.\n const tapGesture = Gesture.Tap()\n .enabled(dismissible)\n .onEnd(() => {\n 'worklet';\n runOnJS(handleDismiss)();\n });\n\n return (\n <GestureDetector gesture={tapGesture}>\n <View style={internalStyles.scrim}>\n {showBlur && (\n <Animated.View style={[StyleSheet.absoluteFill, animatedBlurStyle]}>\n <Box style={StyleSheet.absoluteFill} blur={blurIntensity} blurTarget={blurTarget} />\n </Animated.View>\n )}\n <Animated.View\n style={[StyleSheet.absoluteFill, { backgroundColor: targetColor }, animatedColorStyle]}\n />\n </View>\n </GestureDetector>\n );\n});\n\nconst internalStyles = StyleSheet.create({\n scrim: {\n ...StyleSheet.absoluteFill,\n },\n});\n\nexport { Scrim };\nexport type { ScrimProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,MAAM,QAAQ,KAAK,SAAS,MAAM,EAChC,YACA,gBACA,kBACA,aACA,WACA,cACa;AACb,aAAY,YAAY,EAAE,CAAC;CAC3B,MAAM,cAAc,WAAW,QAAQ,YAAY,KAAK;CACxD,MAAM,cAAc,YAAY,mBAAmB;CACnD,MAAM,gBAAgB,YAAY,WAAW;CAC7C,MAAM,gBAAgB,YAAY,wBAAwB;CAE1D,MAAM,WAAW,gBAAgB,MAAM,SAAS,OAAO,SAAS,cAAc;CAE9E,MAAM,gBAAgB,kBAAkB;AACtC,aAAW;IACV,CAAC,UAAU,CAAC;CAEf,MAAM,qBAAqB,uBAAuB;AAQhD,SAAO,EAAE,SAPO,YACd,WAAW,OACX,CAAC,gBAAgB,iBAAiB,EAClC,CAAC,eAAe,EAAE,EAClB,QAGc,EAAE;GAClB;CAIF,MAAM,oBAAoB,uBAAuB;AAQ/C,SAAO,EAAE,SAPO,YACd,WAAW,OACX,CAAC,gBAAgB,iBAAiB,EAClC,CAAC,GAAG,EAAE,EACN,QAGc,EAAE;GAClB;AAUF,QACE,oBAAC,iBAAD;EAAiB,SARA,QAAQ,KAAK,CAC7B,QAAQ,YAAY,CACpB,YAAY;AACX;AACA,WAAQ,cAAc,EAAE;IAIU;YAClC,qBAAC,MAAD;GAAM,OAAO,eAAe;aAA5B,CACG,YACC,oBAAC,SAAS,MAAV;IAAe,OAAO,CAAC,WAAW,cAAc,kBAAkB;cAChE,oBAAC,KAAD;KAAK,OAAO,WAAW;KAAc,MAAM;KAA2B;KAAc,CAAA;IACtE,CAAA,EAElB,oBAAC,SAAS,MAAV,EACE,OAAO;IAAC,WAAW;IAAc,EAAE,iBAAiB,aAAa;IAAE;IAAmB,EACtF,CAAA,CACG;;EACS,CAAA;EAEpB;AAEF,MAAM,iBAAiB,WAAW,OAAO,EACvC,OAAO,EACL,GAAG,WAAW,cACf,EACF,CAAC"}
1
+ {"version":3,"file":"Scrim.js","names":[],"sources":["../../src/components/Scrim.tsx"],"sourcesContent":["import type { RefObject } from 'react';\nimport { memo, useCallback } from 'react';\nimport { Platform, StyleSheet, View } from 'react-native';\nimport { Gesture, GestureDetector } from 'react-native-gesture-handler';\nimport type { SharedValue } from 'react-native-reanimated';\nimport Animated, { interpolate, runOnJS, useAnimatedStyle } from 'react-native-reanimated';\n\nimport { scrimStyles } from '../../generated/styles';\nimport { Box } from './Box';\n\ninterface ScrimRootTokens {\n backgroundColor?: string;\n backgroundBlurRadius?: number;\n opacity?: number;\n}\n\ninterface ScrimProps {\n /** Animated translateY position of the overlaying content (UI-thread shared value). */\n translateY: SharedValue<number>;\n /** `translateY` value when the content is at its open position. */\n openTranslateY: number;\n /** `translateY` value when the content is fully closed / off-screen. */\n closedTranslateY: number;\n /** Whether tapping the scrim dismisses the content. */\n dismissible: boolean;\n /** Callback invoked when the scrim is tapped and `dismissible` is `true`. */\n onDismiss: () => void;\n /** Ref to a `<BlurTarget>` view for Android backdrop blur. Not needed on iOS. */\n blurTarget?: RefObject<View | null>;\n}\n\n/**\n * Semi-transparent backdrop for modal overlays.\n *\n * Reads `backgroundColor` and `opacity` from the configurator's scrim tokens.\n * Opacity is interpolated between 0 (closed) and the token value (open) based\n * on the content's current `translateY` position.\n *\n * @example\n * ```tsx\n * <Scrim\n * translateY={translateY}\n * openTranslateY={openY}\n * closedTranslateY={closedY}\n * dismissible\n * onDismiss={handleDismiss}\n * />\n * ```\n */\nconst Scrim = memo(function Scrim({\n translateY,\n openTranslateY,\n closedTranslateY,\n dismissible,\n onDismiss,\n blurTarget,\n}: ScrimProps) {\n scrimStyles.useVariants({});\n const scrimTokens = StyleSheet.flatten(scrimStyles.root) as ScrimRootTokens;\n const targetColor = scrimTokens.backgroundColor ?? 'rgba(0, 0, 0, 1)';\n const targetOpacity = scrimTokens.opacity ?? 0.2;\n const blurIntensity = scrimTokens.backgroundBlurRadius ?? 0;\n // iOS blur works without a target; Android requires a blurTarget ref.\n const showBlur = blurIntensity > 0 && (Platform.OS === 'ios' || blurTarget != null);\n\n const handleDismiss = useCallback(() => {\n onDismiss();\n }, [onDismiss]);\n\n const animatedColorStyle = useAnimatedStyle(() => {\n const opacity = interpolate(\n translateY.value,\n [openTranslateY, closedTranslateY],\n [targetOpacity, 0],\n 'clamp',\n );\n\n return { opacity };\n });\n\n // Blur needs its own opacity animation (1 → 0) separate from the color overlay.\n // On iOS, UIVisualEffectView breaks if its parent rests at a fractional opacity.\n const animatedBlurStyle = useAnimatedStyle(() => {\n const opacity = interpolate(\n translateY.value,\n [openTranslateY, closedTranslateY],\n [1, 0],\n 'clamp',\n );\n\n return { opacity };\n });\n\n // Tap gesture on scrim for dismissal.\n const tapGesture = Gesture.Tap()\n .enabled(dismissible)\n .onEnd(() => {\n 'worklet';\n runOnJS(handleDismiss)();\n });\n\n return (\n <GestureDetector gesture={tapGesture}>\n <View style={internalStyles.scrim}>\n {showBlur && (\n <Animated.View style={[StyleSheet.absoluteFill, animatedBlurStyle]}>\n <Box style={StyleSheet.absoluteFill} blur={blurIntensity} blurTarget={blurTarget} />\n </Animated.View>\n )}\n <Animated.View\n style={[StyleSheet.absoluteFill, { backgroundColor: targetColor }, animatedColorStyle]}\n />\n </View>\n </GestureDetector>\n );\n});\n\nconst internalStyles = StyleSheet.create({\n scrim: {\n ...StyleSheet.absoluteFill,\n },\n});\n\nexport { Scrim };\nexport type { ScrimProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,MAAM,QAAQ,KAAK,SAAS,MAAM,EAChC,YACA,gBACA,kBACA,aACA,WACA,cACa;CACb,YAAY,YAAY,EAAE,CAAC;CAC3B,MAAM,cAAc,WAAW,QAAQ,YAAY,KAAK;CACxD,MAAM,cAAc,YAAY,mBAAmB;CACnD,MAAM,gBAAgB,YAAY,WAAW;CAC7C,MAAM,gBAAgB,YAAY,wBAAwB;CAE1D,MAAM,WAAW,gBAAgB,MAAM,SAAS,OAAO,SAAS,cAAc;CAE9E,MAAM,gBAAgB,kBAAkB;EACtC,WAAW;IACV,CAAC,UAAU,CAAC;CAEf,MAAM,qBAAqB,uBAAuB;EAQhD,OAAO,EAAE,SAPO,YACd,WAAW,OACX,CAAC,gBAAgB,iBAAiB,EAClC,CAAC,eAAe,EAAE,EAClB,QAGc,EAAE;GAClB;CAIF,MAAM,oBAAoB,uBAAuB;EAQ/C,OAAO,EAAE,SAPO,YACd,WAAW,OACX,CAAC,gBAAgB,iBAAiB,EAClC,CAAC,GAAG,EAAE,EACN,QAGc,EAAE;GAClB;CAUF,OACE,oBAAC,iBAAD;EAAiB,SARA,QAAQ,KAAK,CAC7B,QAAQ,YAAY,CACpB,YAAY;AACX;GACA,QAAQ,cAAc,EAAE;IAIU;YAClC,qBAAC,MAAD;GAAM,OAAO,eAAe;aAA5B,CACG,YACC,oBAAC,SAAS,MAAV;IAAe,OAAO,CAAC,WAAW,cAAc,kBAAkB;cAChE,oBAAC,KAAD;KAAK,OAAO,WAAW;KAAc,MAAM;KAA2B;KAAc,CAAA;IACtE,CAAA,EAElB,oBAAC,SAAS,MAAV,EACE,OAAO;IAAC,WAAW;IAAc,EAAE,iBAAiB,aAAa;IAAE;IAAmB,EACtF,CAAA,CACG;;EACS,CAAA;EAEpB;AAEF,MAAM,iBAAiB,WAAW,OAAO,EACvC,OAAO,EACL,GAAG,WAAW,cACf,EACF,CAAC"}
@@ -2,8 +2,7 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
4
4
  const require_components_IconSlot = require("./IconSlot.cjs");
5
- const require_components_Text = require("./Text.cjs");
6
- const require_components_HStack = require("./HStack.cjs");
5
+ const require_components_FormLabel = require("./FormLabel.cjs");
7
6
  let react = require("react");
8
7
  let react_native = require("react-native");
9
8
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -104,17 +103,13 @@ const Switch = (0, react.memo)(function Switch({ isOn: isOnProp, defaultIsOn = f
104
103
  ], [generated_styles.switchStyles.handle, animatedHandleStyle]);
105
104
  const accessibilityLabel = typeof label === "string" ? label : void 0;
106
105
  const resolvedAccessibilityHint = accessibilityHint ?? "Double tap to toggle";
107
- const resolvedLabel = typeof label === "function" ? label() : label;
108
- const labelContent = resolvedLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_components_HStack.HStack, {
109
- gap: "2",
110
- alignItems: "center",
111
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Text.Text, {
112
- style: generated_styles.switchStyles.text,
113
- children: resolvedLabel
114
- }), required && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Text.Text, {
115
- color: "alert",
116
- children: "*"
117
- })]
106
+ const labelContent = label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_FormLabel.FormLabel, {
107
+ color: "inherit",
108
+ variant: "inherit",
109
+ label,
110
+ required,
111
+ showRequiredAsterisk: required,
112
+ style: generated_styles.switchStyles.text
118
113
  });
119
114
  const a11yValue = (0, react.useMemo)(() => ({ text: isOn ? "On" : "Off" }), [isOn]);
120
115
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.Pressable, {
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.d.cts","names":[],"sources":["../../src/components/Switch.tsx"],"mappings":";;;;;;;;UAeU,WAAA,SAAoB,IAAA,CAAK,SAAA,YAAqB,oBAAA,CAAqB,YAAA;;EAE3E,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,IAAY,KAAA;;EAEZ,QAAA;EAN2E;EAQ3E,QAAA;EANM;EAQN,iBAAA,GAAoB,kBAAA;AAAA;;;;;;;;;;;;;;;;;;;AAAkB;;;;;;;;;;;;;;;cA2ClC,MAAA,EAAM,OAAA,CAAA,oBAAA,CAAA,WAAA"}
1
+ {"version":3,"file":"Switch.d.cts","names":[],"sources":["../../src/components/Switch.tsx"],"mappings":";;;;;;;;UAcU,WAAA,SAAoB,IAAA,CAAK,SAAA,YAAqB,oBAAA,CAAqB,YAAA;;EAE3E,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,IAAY,KAAA;;EAEZ,QAAA;EAN2E;EAQ3E,QAAA;EANM;EAQN,iBAAA,GAAoB,kBAAA;AAAA;;;;;;;;;;;;;;;;;;;AAAkB;;;;;;;;;;;;;;;cA2ClC,MAAA,EAAM,OAAA,CAAA,oBAAA,CAAA,WAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.d.ts","names":[],"sources":["../../src/components/Switch.tsx"],"mappings":";;;;;;;;UAeU,WAAA,SAAoB,IAAA,CAAK,SAAA,YAAqB,oBAAA,CAAqB,YAAA;;EAE3E,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,IAAY,KAAA;;EAEZ,QAAA;EAN2E;EAQ3E,QAAA;EANM;EAQN,iBAAA,GAAoB,kBAAA;AAAA;;;;;;;;;;;;;;;;;;;AAAkB;;;;;;;;;;;;;;;cA2ClC,MAAA,EAAM,OAAA,CAAA,oBAAA,CAAA,WAAA"}
1
+ {"version":3,"file":"Switch.d.ts","names":[],"sources":["../../src/components/Switch.tsx"],"mappings":";;;;;;;;UAcU,WAAA,SAAoB,IAAA,CAAK,SAAA,YAAqB,oBAAA,CAAqB,YAAA;;EAE3E,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,IAAY,KAAA;;EAEZ,QAAA;EAN2E;EAQ3E,QAAA;EANM;EAQN,iBAAA,GAAoB,kBAAA;AAAA;;;;;;;;;;;;;;;;;;;AAAkB;;;;;;;;;;;;;;;cA2ClC,MAAA,EAAM,OAAA,CAAA,oBAAA,CAAA,WAAA"}
@@ -1,7 +1,6 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
2
  import { IconSlot } from "./IconSlot.js";
3
- import { Text as Text$1 } from "./Text.js";
4
- import { HStack } from "./HStack.js";
3
+ import { FormLabel } from "./FormLabel.js";
5
4
  import { memo, useCallback, useEffect, useMemo, useState } from "react";
6
5
  import { AccessibilityInfo, Pressable } from "react-native";
7
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -101,17 +100,13 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
101
100
  ], [switchStyles.handle, animatedHandleStyle]);
102
101
  const accessibilityLabel = typeof label === "string" ? label : void 0;
103
102
  const resolvedAccessibilityHint = accessibilityHint ?? "Double tap to toggle";
104
- const resolvedLabel = typeof label === "function" ? label() : label;
105
- const labelContent = resolvedLabel && /* @__PURE__ */ jsxs(HStack, {
106
- gap: "2",
107
- alignItems: "center",
108
- children: [/* @__PURE__ */ jsx(Text$1, {
109
- style: switchStyles.text,
110
- children: resolvedLabel
111
- }), required && /* @__PURE__ */ jsx(Text$1, {
112
- color: "alert",
113
- children: "*"
114
- })]
103
+ const labelContent = label && /* @__PURE__ */ jsx(FormLabel, {
104
+ color: "inherit",
105
+ variant: "inherit",
106
+ label,
107
+ required,
108
+ showRequiredAsterisk: required,
109
+ style: switchStyles.text
115
110
  });
116
111
  const a11yValue = useMemo(() => ({ text: isOn ? "On" : "Off" }), [isOn]);
117
112
  return /* @__PURE__ */ jsxs(Pressable, {
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.js","names":["Text","StyleSheet"],"sources":["../../src/components/Switch.tsx"],"sourcesContent":["import type { SwitchSize, UniversalSwitchProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport type { AccessibilityProps, StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { AccessibilityInfo, Pressable } from 'react-native';\nimport Animated, { useAnimatedStyle, useDerivedValue, withTiming } from 'react-native-reanimated';\nimport { StyleSheet } from 'react-native-unistyles';\nimport { useAnimatedVariantColor } from 'react-native-unistyles/reanimated';\n\nimport { switchStyles } from '../../generated/styles';\nimport { HStack } from './HStack';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\nimport { Text } from './Text';\n\ninterface SwitchProps extends Omit<ViewProps, 'style'>, UniversalSwitchProps<IconSlotType> {\n /** Ref to the underlying View */\n ref?: Ref<View>;\n /** Callback when the switch value changes */\n onChange?: (value: boolean) => void;\n /** Whether the switch is disabled */\n disabled?: boolean;\n /** Whether the switch is required (shows asterisk with label) */\n required?: boolean;\n /** Accessibility hint describing what happens when activated */\n accessibilityHint?: AccessibilityProps['accessibilityHint'];\n}\n\nconst HANDLE_TRAVEL: Record<SwitchSize, number> = {\n md: 20,\n sm: 12,\n};\n\nconst ANIMATION_DURATION = 120;\n\n/**\n * **Switch component for toggling options**\n *\n * @description\n * A switch (also called a toggle) is a binary on/off input control.\n * It allows users to pick between two clearly opposite choices.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Switch } from '@yahoo/uds-mobile/Switch';\n *\n * <Switch label=\"Notifications\" />\n * <Switch isOn={enabled} onChange={setEnabled} label=\"Dark mode\" />\n * <Switch onIcon=\"Check\" offIcon=\"Cross\" label=\"Sync\" />\n * ```\n *\n * @usage\n * - Settings: For toggling preferences on/off\n * - Feature flags: For enabling/disabling features\n * - Immediate effect toggles (no submit button needed)\n *\n * @accessibility\n * - Sets `accessibilityRole=\"switch\"` automatically\n * - Announces on/off state to screen readers\n * - Respects system reduce motion preference\n * - Supports `reduceMotion` prop to disable animations\n *\n * @see {@link Checkbox} for forms with submit actions\n * @see {@link Radio} for single-select options\n */\nconst Switch = memo(function Switch({\n isOn: isOnProp,\n defaultIsOn = false,\n onChange,\n label,\n labelPosition = 'start',\n size = 'md',\n onIcon,\n offIcon,\n disabled = false,\n required,\n accessibilityHint,\n reduceMotion = false,\n ref,\n ...viewProps\n}: SwitchProps) {\n const isControlled = isOnProp !== undefined;\n const [internalIsOn, setInternalIsOn] = useState(defaultIsOn);\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n const isOn = isControlled ? isOnProp : internalIsOn;\n\n // Check system reduced motion preference\n useEffect(() => {\n const checkReducedMotion = async () => {\n const isReduceMotionEnabled = await AccessibilityInfo.isReduceMotionEnabled();\n setPrefersReducedMotion(isReduceMotionEnabled);\n };\n checkReducedMotion();\n\n const subscription = AccessibilityInfo.addEventListener(\n 'reduceMotionChanged',\n setPrefersReducedMotion,\n );\n return () => subscription.remove();\n }, []);\n\n const shouldReduceMotion = reduceMotion || prefersReducedMotion;\n const animationDuration = shouldReduceMotion ? 0 : ANIMATION_DURATION;\n\n const progress = useDerivedValue(\n () => withTiming(isOn ? 1 : 0, { duration: animationDuration }),\n [isOn, animationDuration],\n );\n\n const travelDistance = HANDLE_TRAVEL[size];\n\n const handlePress = useCallback(() => {\n if (disabled) {\n return;\n }\n\n const newValue = !isOn;\n\n if (!isControlled) {\n setInternalIsOn(newValue);\n }\n\n onChange?.(newValue);\n }, [disabled, isOn, isControlled, onChange]);\n\n switchStyles.useVariants({\n size,\n variant: isOn ? 'on' : 'off',\n });\n\n // Get animated track color from design tokens (changes when variant changes)\n const trackBackgroundColor = useAnimatedVariantColor(switchStyles.switch, 'backgroundColor');\n\n const animatedTrackStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n backgroundColor: withTiming(trackBackgroundColor.value, { duration: animationDuration }),\n };\n });\n\n const animatedHandleStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n transform: [{ translateX: progress.value * travelDistance }],\n };\n });\n\n const rootStyle: StyleProp<ViewStyle> = useMemo(\n () => [switchStyles.root, switchStaticStyles.root({ disabled })],\n [switchStyles.root, disabled],\n );\n\n const trackStyle: StyleProp<ViewStyle> = useMemo(\n () => [switchStyles.switch, switchStaticStyles.track, animatedTrackStyle],\n [switchStyles.switch, animatedTrackStyle],\n );\n\n const handleStyle: StyleProp<ViewStyle> = useMemo(\n () => [switchStyles.handle, switchStaticStyles.handle, animatedHandleStyle],\n [switchStyles.handle, animatedHandleStyle],\n );\n\n const accessibilityLabel = typeof label === 'string' ? label : undefined;\n const resolvedAccessibilityHint = accessibilityHint ?? 'Double tap to toggle';\n\n const resolvedLabel = typeof label === 'function' ? label() : label;\n const labelContent = resolvedLabel && (\n <HStack gap=\"2\" alignItems=\"center\">\n <Text style={switchStyles.text}>{resolvedLabel}</Text>\n {required && <Text color=\"alert\">*</Text>}\n </HStack>\n );\n\n const a11yValue = useMemo(() => ({ text: isOn ? 'On' : 'Off' }), [isOn]);\n\n return (\n <Pressable\n ref={ref}\n onPress={handlePress}\n disabled={disabled}\n accessible\n accessibilityRole=\"switch\"\n accessibilityState={{ checked: isOn, disabled }}\n accessibilityLabel={accessibilityLabel}\n accessibilityHint={resolvedAccessibilityHint}\n accessibilityValue={a11yValue}\n {...viewProps}\n style={rootStyle}\n >\n {labelPosition === 'start' && labelContent}\n\n <Animated.View style={trackStyle} importantForAccessibility=\"no-hide-descendants\">\n <Animated.View style={handleStyle}>\n {onIcon && isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot icon={onIcon} variant=\"fill\" style={switchStyles.handleIcon} />\n </Animated.View>\n )}\n {offIcon && !isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot icon={offIcon} variant=\"fill\" style={switchStyles.handleIcon} />\n </Animated.View>\n )}\n </Animated.View>\n </Animated.View>\n\n {labelPosition === 'end' && labelContent}\n </Pressable>\n );\n});\n\nSwitch.displayName = 'Switch';\n\nconst switchStaticStyles = StyleSheet.create((theme) => ({\n handle: {\n borderRadius: theme.borderRadius.full,\n alignItems: 'center',\n justifyContent: 'center',\n },\n iconContainer: {\n position: 'absolute',\n alignItems: 'center',\n justifyContent: 'center',\n },\n track: {\n justifyContent: 'center',\n borderRadius: theme.borderRadius.full,\n },\n root: ({ disabled }: { disabled: boolean }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n alignSelf: 'flex-start',\n opacity: disabled ? 0.5 : 1,\n }),\n}));\n\nexport { Switch, type SwitchProps };\n"],"mappings":"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"}
1
+ {"version":3,"file":"Switch.js","names":["StyleSheet"],"sources":["../../src/components/Switch.tsx"],"sourcesContent":["import type { SwitchSize, UniversalSwitchProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport type { AccessibilityProps, StyleProp, View, ViewProps, ViewStyle } from 'react-native';\nimport { AccessibilityInfo, Pressable } from 'react-native';\nimport Animated, { useAnimatedStyle, useDerivedValue, withTiming } from 'react-native-reanimated';\nimport { StyleSheet } from 'react-native-unistyles';\nimport { useAnimatedVariantColor } from 'react-native-unistyles/reanimated';\n\nimport { switchStyles } from '../../generated/styles';\nimport { FormLabel } from './FormLabel';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\n\ninterface SwitchProps extends Omit<ViewProps, 'style'>, UniversalSwitchProps<IconSlotType> {\n /** Ref to the underlying View */\n ref?: Ref<View>;\n /** Callback when the switch value changes */\n onChange?: (value: boolean) => void;\n /** Whether the switch is disabled */\n disabled?: boolean;\n /** Whether the switch is required (shows asterisk with label) */\n required?: boolean;\n /** Accessibility hint describing what happens when activated */\n accessibilityHint?: AccessibilityProps['accessibilityHint'];\n}\n\nconst HANDLE_TRAVEL: Record<SwitchSize, number> = {\n md: 20,\n sm: 12,\n};\n\nconst ANIMATION_DURATION = 120;\n\n/**\n * **Switch component for toggling options**\n *\n * @description\n * A switch (also called a toggle) is a binary on/off input control.\n * It allows users to pick between two clearly opposite choices.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Switch } from '@yahoo/uds-mobile/Switch';\n *\n * <Switch label=\"Notifications\" />\n * <Switch isOn={enabled} onChange={setEnabled} label=\"Dark mode\" />\n * <Switch onIcon=\"Check\" offIcon=\"Cross\" label=\"Sync\" />\n * ```\n *\n * @usage\n * - Settings: For toggling preferences on/off\n * - Feature flags: For enabling/disabling features\n * - Immediate effect toggles (no submit button needed)\n *\n * @accessibility\n * - Sets `accessibilityRole=\"switch\"` automatically\n * - Announces on/off state to screen readers\n * - Respects system reduce motion preference\n * - Supports `reduceMotion` prop to disable animations\n *\n * @see {@link Checkbox} for forms with submit actions\n * @see {@link Radio} for single-select options\n */\nconst Switch = memo(function Switch({\n isOn: isOnProp,\n defaultIsOn = false,\n onChange,\n label,\n labelPosition = 'start',\n size = 'md',\n onIcon,\n offIcon,\n disabled = false,\n required,\n accessibilityHint,\n reduceMotion = false,\n ref,\n ...viewProps\n}: SwitchProps) {\n const isControlled = isOnProp !== undefined;\n const [internalIsOn, setInternalIsOn] = useState(defaultIsOn);\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n const isOn = isControlled ? isOnProp : internalIsOn;\n\n // Check system reduced motion preference\n useEffect(() => {\n const checkReducedMotion = async () => {\n const isReduceMotionEnabled = await AccessibilityInfo.isReduceMotionEnabled();\n setPrefersReducedMotion(isReduceMotionEnabled);\n };\n checkReducedMotion();\n\n const subscription = AccessibilityInfo.addEventListener(\n 'reduceMotionChanged',\n setPrefersReducedMotion,\n );\n return () => subscription.remove();\n }, []);\n\n const shouldReduceMotion = reduceMotion || prefersReducedMotion;\n const animationDuration = shouldReduceMotion ? 0 : ANIMATION_DURATION;\n\n const progress = useDerivedValue(\n () => withTiming(isOn ? 1 : 0, { duration: animationDuration }),\n [isOn, animationDuration],\n );\n\n const travelDistance = HANDLE_TRAVEL[size];\n\n const handlePress = useCallback(() => {\n if (disabled) {\n return;\n }\n\n const newValue = !isOn;\n\n if (!isControlled) {\n setInternalIsOn(newValue);\n }\n\n onChange?.(newValue);\n }, [disabled, isOn, isControlled, onChange]);\n\n switchStyles.useVariants({\n size,\n variant: isOn ? 'on' : 'off',\n });\n\n // Get animated track color from design tokens (changes when variant changes)\n const trackBackgroundColor = useAnimatedVariantColor(switchStyles.switch, 'backgroundColor');\n\n const animatedTrackStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n backgroundColor: withTiming(trackBackgroundColor.value, { duration: animationDuration }),\n };\n });\n\n const animatedHandleStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n transform: [{ translateX: progress.value * travelDistance }],\n };\n });\n\n const rootStyle: StyleProp<ViewStyle> = useMemo(\n () => [switchStyles.root, switchStaticStyles.root({ disabled })],\n [switchStyles.root, disabled],\n );\n\n const trackStyle: StyleProp<ViewStyle> = useMemo(\n () => [switchStyles.switch, switchStaticStyles.track, animatedTrackStyle],\n [switchStyles.switch, animatedTrackStyle],\n );\n\n const handleStyle: StyleProp<ViewStyle> = useMemo(\n () => [switchStyles.handle, switchStaticStyles.handle, animatedHandleStyle],\n [switchStyles.handle, animatedHandleStyle],\n );\n\n const accessibilityLabel = typeof label === 'string' ? label : undefined;\n const resolvedAccessibilityHint = accessibilityHint ?? 'Double tap to toggle';\n\n const labelContent = label && (\n <FormLabel\n color=\"inherit\"\n variant=\"inherit\"\n label={label}\n required={required}\n showRequiredAsterisk={required}\n style={switchStyles.text}\n />\n );\n\n const a11yValue = useMemo(() => ({ text: isOn ? 'On' : 'Off' }), [isOn]);\n\n return (\n <Pressable\n ref={ref}\n onPress={handlePress}\n disabled={disabled}\n accessible\n accessibilityRole=\"switch\"\n accessibilityState={{ checked: isOn, disabled }}\n accessibilityLabel={accessibilityLabel}\n accessibilityHint={resolvedAccessibilityHint}\n accessibilityValue={a11yValue}\n {...viewProps}\n style={rootStyle}\n >\n {labelPosition === 'start' && labelContent}\n\n <Animated.View style={trackStyle} importantForAccessibility=\"no-hide-descendants\">\n <Animated.View style={handleStyle}>\n {onIcon && isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot icon={onIcon} variant=\"fill\" style={switchStyles.handleIcon} />\n </Animated.View>\n )}\n {offIcon && !isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot icon={offIcon} variant=\"fill\" style={switchStyles.handleIcon} />\n </Animated.View>\n )}\n </Animated.View>\n </Animated.View>\n\n {labelPosition === 'end' && labelContent}\n </Pressable>\n );\n});\n\nSwitch.displayName = 'Switch';\n\nconst switchStaticStyles = StyleSheet.create((theme) => ({\n handle: {\n borderRadius: theme.borderRadius.full,\n alignItems: 'center',\n justifyContent: 'center',\n },\n iconContainer: {\n position: 'absolute',\n alignItems: 'center',\n justifyContent: 'center',\n },\n track: {\n justifyContent: 'center',\n borderRadius: theme.borderRadius.full,\n },\n root: ({ disabled }: { disabled: boolean }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n alignSelf: 'flex-start',\n opacity: disabled ? 0.5 : 1,\n }),\n}));\n\nexport { Switch, type SwitchProps };\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tab.js","names":["RNText","Pressable"],"sources":["../../../src/components/Tabs/Tab.tsx"],"sourcesContent":["import type { UniversalTabProps } from '@yahoo/uds-types';\nimport type { ReactElement, ReactNode } from 'react';\nimport { memo, useCallback, useEffect, useId, useMemo, useState } from 'react';\nimport type { LayoutChangeEvent, PressableProps, TextStyle, ViewStyle } from 'react-native';\nimport { Text as RNText, View } from 'react-native';\n// eslint-disable-next-line uds/no-use-unistyles -- theme.components path lookups for tab layers\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport type { StyleProps } from '../../../generated/styles';\nimport type { IconSlotType } from '../IconSlot';\nimport { IconSlot } from '../IconSlot';\nimport { Pressable } from '../Pressable';\nimport { useTabSelectionContext, useTabsVisualContext } from './tabsContexts';\nimport { getMergedTabLayerStyle, getTabLayerStyle } from './tabTheme';\n\nconst PRIMARY_TAB_UNDERLINE_HEIGHT = 2;\n\ninterface TabProps\n extends\n Omit<PressableProps, 'children' | 'style' | 'disabled' | 'onPress'>,\n Omit<UniversalTabProps, 'asChild' | 'className' | 'startIcon' | 'endIcon'> {\n children: UniversalTabProps['children'];\n startIcon?: IconSlotType;\n endIcon?: IconSlotType;\n style?: ViewStyle;\n}\n\nconst CLEAR_SELECTION_CHROME: ViewStyle = {\n backgroundColor: 'transparent',\n borderWidth: 0,\n borderColor: 'transparent',\n shadowOpacity: 0,\n elevation: 0,\n boxShadow: [],\n};\n\nfunction TabLabel({ style, children }: { style: TextStyle; children: ReactNode }) {\n if (typeof children === 'string' || typeof children === 'number') {\n return <RNText style={style}>{children}</RNText>;\n }\n return children as ReactElement;\n}\n\n/**\n * **⚙️ Tab**\n *\n * @description\n * A single selectable tab. Must be used inside {@link TabList} within {@link Tabs}.\n *\n * @category Navigation\n * @platform mobile\n */\nconst Tab = memo(function Tab({\n value,\n children,\n startIcon,\n endIcon,\n disabled,\n style,\n ...pressableRest\n}: TabProps) {\n const generatedId = useId();\n const uid = value ?? `uds-tab-${generatedId}`;\n const { variant: visualVariant, reduceMotion } = useTabsVisualContext();\n const { selectedId, setSelectedId, registerTab, unregisterTab, setTabLayout } =\n useTabSelectionContext();\n const { theme } = useUnistyles();\n const [pressed, setPressed] = useState(false);\n\n const selected = !disabled && selectedId === uid;\n const active: 'on' | 'off' = selected ? 'on' : 'off';\n const interaction: 'rest' | 'pressed' = pressed ? 'pressed' : 'rest';\n\n useEffect(() => {\n registerTab(uid);\n return () => {\n unregisterTab(uid);\n };\n }, [uid, registerTab, unregisterTab]);\n\n const rootBase = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'root', interaction) as ViewStyle,\n [theme, visualVariant, active, interaction],\n );\n const textStyle = useMemo(\n () =>\n getMergedTabLayerStyle(theme, visualVariant, active, 'rootText', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n const iconStyle = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'icon', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n\n const iconColor = ((): StyleProps['color'] | undefined => {\n const c = iconStyle?.color;\n if (c === undefined || c === null) {\n return undefined;\n }\n return c as StyleProps['color'];\n })();\n\n /** Inactive primary tabs use transparent underline tokens on web; RN has no CSS vars for that layer. */\n const showPrimaryPerTabUnderline = visualVariant === 'primary' && !(selected && !reduceMotion);\n\n const primaryUnderlineColor = useMemo(() => {\n if (visualVariant !== 'primary') {\n return undefined;\n }\n if (selected && reduceMotion) {\n const onText = getTabLayerStyle(theme, 'primary', 'on', 'rootText', 'rest') as TextStyle;\n const c = onText.color;\n if (typeof c === 'string') {\n return c;\n }\n }\n return 'transparent';\n }, [visualVariant, selected, reduceMotion, theme]);\n\n const rootStyle = useMemo((): ViewStyle => {\n const base: ViewStyle = {\n ...rootBase,\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n zIndex: 1,\n position: 'relative',\n };\n if (selected && !reduceMotion) {\n return { ...base, ...CLEAR_SELECTION_CHROME };\n }\n return base;\n }, [rootBase, selected, reduceMotion]);\n\n const onLayout = useCallback(\n (e: LayoutChangeEvent) => {\n setTabLayout(uid, e.nativeEvent.layout);\n },\n [uid, setTabLayout],\n );\n\n const onPress = useCallback(() => {\n if (disabled) {\n return;\n }\n setSelectedId(uid);\n }, [disabled, setSelectedId, uid]);\n\n return (\n <Pressable\n accessibilityRole=\"tab\"\n accessibilityState={{ selected, disabled: !!disabled }}\n disabled={disabled}\n onPress={onPress}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n onLayout={onLayout}\n style={[rootStyle, style]}\n {...pressableRest}\n >\n {startIcon ? (\n <IconSlot\n icon={startIcon}\n size=\"sm\"\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n <TabLabel style={textStyle}>{children}</TabLabel>\n {endIcon ? (\n <IconSlot\n icon={endIcon}\n size=\"sm\"\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n {showPrimaryPerTabUnderline &&\n primaryUnderlineColor &&\n primaryUnderlineColor !== 'transparent' ? (\n <View\n accessibilityElementsHidden\n importantForAccessibility=\"no-hide-descendants\"\n pointerEvents=\"none\"\n style={{\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n height: PRIMARY_TAB_UNDERLINE_HEIGHT,\n backgroundColor: primaryUnderlineColor,\n }}\n />\n ) : null}\n </Pressable>\n );\n});\n\nTab.displayName = 'Tab';\n\nexport { Tab };\nexport type { TabProps };\n"],"mappings":"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"}
1
+ {"version":3,"file":"Tab.js","names":["RNText","Pressable"],"sources":["../../../src/components/Tabs/Tab.tsx"],"sourcesContent":["import type { UniversalTabProps } from '@yahoo/uds-types';\nimport type { ReactElement, ReactNode } from 'react';\nimport { memo, useCallback, useEffect, useId, useMemo, useState } from 'react';\nimport type { LayoutChangeEvent, PressableProps, TextStyle, ViewStyle } from 'react-native';\nimport { Text as RNText, View } from 'react-native';\n// eslint-disable-next-line uds/no-use-unistyles -- theme.components path lookups for tab layers\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport type { StyleProps } from '../../../generated/styles';\nimport type { IconSlotType } from '../IconSlot';\nimport { IconSlot } from '../IconSlot';\nimport { Pressable } from '../Pressable';\nimport { useTabSelectionContext, useTabsVisualContext } from './tabsContexts';\nimport { getMergedTabLayerStyle, getTabLayerStyle } from './tabTheme';\n\nconst PRIMARY_TAB_UNDERLINE_HEIGHT = 2;\n\ninterface TabProps\n extends\n Omit<PressableProps, 'children' | 'style' | 'disabled' | 'onPress'>,\n Omit<UniversalTabProps, 'asChild' | 'className' | 'startIcon' | 'endIcon'> {\n children: UniversalTabProps['children'];\n startIcon?: IconSlotType;\n endIcon?: IconSlotType;\n style?: ViewStyle;\n}\n\nconst CLEAR_SELECTION_CHROME: ViewStyle = {\n backgroundColor: 'transparent',\n borderWidth: 0,\n borderColor: 'transparent',\n shadowOpacity: 0,\n elevation: 0,\n boxShadow: [],\n};\n\nfunction TabLabel({ style, children }: { style: TextStyle; children: ReactNode }) {\n if (typeof children === 'string' || typeof children === 'number') {\n return <RNText style={style}>{children}</RNText>;\n }\n return children as ReactElement;\n}\n\n/**\n * **⚙️ Tab**\n *\n * @description\n * A single selectable tab. Must be used inside {@link TabList} within {@link Tabs}.\n *\n * @category Navigation\n * @platform mobile\n */\nconst Tab = memo(function Tab({\n value,\n children,\n startIcon,\n endIcon,\n disabled,\n style,\n ...pressableRest\n}: TabProps) {\n const generatedId = useId();\n const uid = value ?? `uds-tab-${generatedId}`;\n const { variant: visualVariant, reduceMotion } = useTabsVisualContext();\n const { selectedId, setSelectedId, registerTab, unregisterTab, setTabLayout } =\n useTabSelectionContext();\n const { theme } = useUnistyles();\n const [pressed, setPressed] = useState(false);\n\n const selected = !disabled && selectedId === uid;\n const active: 'on' | 'off' = selected ? 'on' : 'off';\n const interaction: 'rest' | 'pressed' = pressed ? 'pressed' : 'rest';\n\n useEffect(() => {\n registerTab(uid);\n return () => {\n unregisterTab(uid);\n };\n }, [uid, registerTab, unregisterTab]);\n\n const rootBase = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'root', interaction) as ViewStyle,\n [theme, visualVariant, active, interaction],\n );\n const textStyle = useMemo(\n () =>\n getMergedTabLayerStyle(theme, visualVariant, active, 'rootText', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n const iconStyle = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'icon', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n\n const iconColor = ((): StyleProps['color'] | undefined => {\n const c = iconStyle?.color;\n if (c === undefined || c === null) {\n return undefined;\n }\n return c as StyleProps['color'];\n })();\n\n /** Inactive primary tabs use transparent underline tokens on web; RN has no CSS vars for that layer. */\n const showPrimaryPerTabUnderline = visualVariant === 'primary' && !(selected && !reduceMotion);\n\n const primaryUnderlineColor = useMemo(() => {\n if (visualVariant !== 'primary') {\n return undefined;\n }\n if (selected && reduceMotion) {\n const onText = getTabLayerStyle(theme, 'primary', 'on', 'rootText', 'rest') as TextStyle;\n const c = onText.color;\n if (typeof c === 'string') {\n return c;\n }\n }\n return 'transparent';\n }, [visualVariant, selected, reduceMotion, theme]);\n\n const rootStyle = useMemo((): ViewStyle => {\n const base: ViewStyle = {\n ...rootBase,\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n zIndex: 1,\n position: 'relative',\n };\n if (selected && !reduceMotion) {\n return { ...base, ...CLEAR_SELECTION_CHROME };\n }\n return base;\n }, [rootBase, selected, reduceMotion]);\n\n const onLayout = useCallback(\n (e: LayoutChangeEvent) => {\n setTabLayout(uid, e.nativeEvent.layout);\n },\n [uid, setTabLayout],\n );\n\n const onPress = useCallback(() => {\n if (disabled) {\n return;\n }\n setSelectedId(uid);\n }, [disabled, setSelectedId, uid]);\n\n return (\n <Pressable\n accessibilityRole=\"tab\"\n accessibilityState={{ selected, disabled: !!disabled }}\n disabled={disabled}\n onPress={onPress}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n onLayout={onLayout}\n style={[rootStyle, style]}\n {...pressableRest}\n >\n {startIcon ? (\n <IconSlot\n icon={startIcon}\n size=\"sm\"\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n <TabLabel style={textStyle}>{children}</TabLabel>\n {endIcon ? (\n <IconSlot\n icon={endIcon}\n size=\"sm\"\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n {showPrimaryPerTabUnderline &&\n primaryUnderlineColor &&\n primaryUnderlineColor !== 'transparent' ? (\n <View\n accessibilityElementsHidden\n importantForAccessibility=\"no-hide-descendants\"\n pointerEvents=\"none\"\n style={{\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n height: PRIMARY_TAB_UNDERLINE_HEIGHT,\n backgroundColor: primaryUnderlineColor,\n }}\n />\n ) : null}\n </Pressable>\n );\n});\n\nTab.displayName = 'Tab';\n\nexport { Tab };\nexport type { TabProps };\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TabList.js","names":[],"sources":["../../../src/components/Tabs/TabList.tsx"],"sourcesContent":["import type { UniversalTabListProps } from '@yahoo/uds-types';\nimport { memo, useEffect, useMemo } from 'react';\nimport type { ViewProps, ViewStyle } from 'react-native';\nimport { ScrollView, View } from 'react-native';\nimport Animated, {\n Easing,\n useAnimatedStyle,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated';\n// eslint-disable-next-line uds/no-use-unistyles -- theme.components path lookups for tab indicator\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport { tabsStyles } from '../../../generated/styles';\nimport { useTabSelectionContext, useTabsVisualContext } from './tabsContexts';\nimport { getTabLayerStyle } from './tabTheme';\n\nconst TAB_INDICATOR_MS = 240;\nconst TAB_INDICATOR_EASING = Easing.bezier(0.2, 0, 0, 1);\nconst PRIMARY_SLIDE_UNDERLINE_HEIGHT = 2;\n\n/** RN View/ScrollView aria types differ from `React.AriaAttributes` on web; keep parity fields only. */\ninterface TabListProps\n extends Omit<ViewProps, 'children' | 'style'>, Pick<UniversalTabListProps, 'scrollable'> {\n children: UniversalTabListProps['children'];\n style?: ViewStyle;\n}\n\nfunction TabListIndicator({\n visualVariant,\n reduceMotion,\n}: {\n visualVariant: 'primary' | 'secondary';\n reduceMotion: boolean;\n}) {\n const { selectedId, tabLayouts } = useTabSelectionContext();\n const { theme } = useUnistyles();\n const x = useSharedValue(0);\n const y = useSharedValue(0);\n const w = useSharedValue(0);\n const h = useSharedValue(0);\n const opacity = useSharedValue(0);\n\n useEffect(() => {\n if (reduceMotion || !selectedId) {\n opacity.value = withTiming(0, { duration: 120, easing: Easing.out(Easing.quad) });\n return;\n }\n const layout = tabLayouts.get(selectedId);\n if (!layout || layout.width <= 0 || layout.height <= 0) {\n opacity.value = withTiming(0, { duration: 120, easing: Easing.out(Easing.quad) });\n return;\n }\n const timing = { duration: TAB_INDICATOR_MS, easing: TAB_INDICATOR_EASING };\n x.value = withTiming(layout.x, timing);\n y.value = withTiming(layout.y, timing);\n w.value = withTiming(layout.width, timing);\n h.value = withTiming(layout.height, timing);\n opacity.value = withTiming(1, timing);\n }, [selectedId, tabLayouts, reduceMotion, x, y, w, h, opacity]);\n\n const indicatorChrome = useMemo(\n () => getTabLayerStyle(theme, visualVariant, 'on', 'root', 'rest') as ViewStyle,\n [theme, visualVariant],\n );\n\n const primaryAccentColor = useMemo(() => {\n const t = getTabLayerStyle(theme, 'primary', 'on', 'rootText', 'rest') as { color?: string };\n return typeof t.color === 'string' ? t.color : '#7d2eff';\n }, [theme]);\n\n const animatedStyle = useAnimatedStyle(() => ({\n position: 'absolute' as const,\n left: x.value,\n top: y.value,\n width: w.value,\n height: h.value,\n opacity: opacity.value,\n zIndex: 0,\n overflow: 'hidden' as const,\n }));\n\n if (reduceMotion) {\n return null;\n }\n\n /** Primary: sliding accent line at bottom (web uses underline layer, not full pill). */\n if (visualVariant === 'primary') {\n return (\n <Animated.View\n pointerEvents=\"none\"\n style={[animatedStyle, { backgroundColor: 'transparent' }]}\n >\n <View style={{ flex: 1, justifyContent: 'flex-end' }}>\n <View\n style={{\n height: PRIMARY_SLIDE_UNDERLINE_HEIGHT,\n width: '100%',\n backgroundColor: primaryAccentColor,\n }}\n />\n </View>\n </Animated.View>\n );\n }\n\n return (\n <Animated.View pointerEvents=\"none\" style={animatedStyle}>\n <View style={[indicatorChrome, { flex: 1 }]} />\n </Animated.View>\n );\n}\n\n/**\n * **⚙️ TabList**\n *\n * @description\n * Horizontal row of {@link Tab} items. Set `scrollable` when tabs may overflow the viewport.\n *\n * @category Navigation\n * @platform mobile\n */\nconst TabList = memo(function TabList({\n children,\n scrollable = false,\n style,\n accessibilityLabel,\n ...viewProps\n}: TabListProps) {\n const { variant: visualVariant, reduceMotion } = useTabsVisualContext();\n tabsStyles.useVariants({ variant: visualVariant });\n\n const rowStyle: ViewStyle = {\n flexDirection: 'row',\n alignItems: 'center',\n position: 'relative',\n ...tabsStyles.root,\n // Secondary track tokens include horizontal padding; shrink-wrap so inset matches on both ends.\n ...(visualVariant === 'secondary' && !scrollable ? { alignSelf: 'flex-start' as const } : {}),\n };\n\n const row = (\n <View style={rowStyle}>\n <TabListIndicator visualVariant={visualVariant} reduceMotion={reduceMotion} />\n {children}\n </View>\n );\n\n if (scrollable) {\n return (\n <ScrollView\n horizontal\n showsHorizontalScrollIndicator={false}\n accessibilityRole=\"tablist\"\n accessibilityLabel={accessibilityLabel}\n {...viewProps}\n style={style}\n >\n {row}\n </ScrollView>\n );\n }\n\n return (\n <View\n accessibilityRole=\"tablist\"\n accessibilityLabel={accessibilityLabel}\n style={style}\n {...viewProps}\n >\n {row}\n </View>\n );\n});\n\nTabList.displayName = 'TabList';\n\nexport { TabList };\nexport type { TabListProps };\n"],"mappings":"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"}
1
+ {"version":3,"file":"TabList.js","names":[],"sources":["../../../src/components/Tabs/TabList.tsx"],"sourcesContent":["import type { UniversalTabListProps } from '@yahoo/uds-types';\nimport { memo, useEffect, useMemo } from 'react';\nimport type { ViewProps, ViewStyle } from 'react-native';\nimport { ScrollView, View } from 'react-native';\nimport Animated, {\n Easing,\n useAnimatedStyle,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated';\n// eslint-disable-next-line uds/no-use-unistyles -- theme.components path lookups for tab indicator\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport { tabsStyles } from '../../../generated/styles';\nimport { useTabSelectionContext, useTabsVisualContext } from './tabsContexts';\nimport { getTabLayerStyle } from './tabTheme';\n\nconst TAB_INDICATOR_MS = 240;\nconst TAB_INDICATOR_EASING = Easing.bezier(0.2, 0, 0, 1);\nconst PRIMARY_SLIDE_UNDERLINE_HEIGHT = 2;\n\n/** RN View/ScrollView aria types differ from `React.AriaAttributes` on web; keep parity fields only. */\ninterface TabListProps\n extends Omit<ViewProps, 'children' | 'style'>, Pick<UniversalTabListProps, 'scrollable'> {\n children: UniversalTabListProps['children'];\n style?: ViewStyle;\n}\n\nfunction TabListIndicator({\n visualVariant,\n reduceMotion,\n}: {\n visualVariant: 'primary' | 'secondary';\n reduceMotion: boolean;\n}) {\n const { selectedId, tabLayouts } = useTabSelectionContext();\n const { theme } = useUnistyles();\n const x = useSharedValue(0);\n const y = useSharedValue(0);\n const w = useSharedValue(0);\n const h = useSharedValue(0);\n const opacity = useSharedValue(0);\n\n useEffect(() => {\n if (reduceMotion || !selectedId) {\n opacity.value = withTiming(0, { duration: 120, easing: Easing.out(Easing.quad) });\n return;\n }\n const layout = tabLayouts.get(selectedId);\n if (!layout || layout.width <= 0 || layout.height <= 0) {\n opacity.value = withTiming(0, { duration: 120, easing: Easing.out(Easing.quad) });\n return;\n }\n const timing = { duration: TAB_INDICATOR_MS, easing: TAB_INDICATOR_EASING };\n x.value = withTiming(layout.x, timing);\n y.value = withTiming(layout.y, timing);\n w.value = withTiming(layout.width, timing);\n h.value = withTiming(layout.height, timing);\n opacity.value = withTiming(1, timing);\n }, [selectedId, tabLayouts, reduceMotion, x, y, w, h, opacity]);\n\n const indicatorChrome = useMemo(\n () => getTabLayerStyle(theme, visualVariant, 'on', 'root', 'rest') as ViewStyle,\n [theme, visualVariant],\n );\n\n const primaryAccentColor = useMemo(() => {\n const t = getTabLayerStyle(theme, 'primary', 'on', 'rootText', 'rest') as { color?: string };\n return typeof t.color === 'string' ? t.color : '#7d2eff';\n }, [theme]);\n\n const animatedStyle = useAnimatedStyle(() => ({\n position: 'absolute' as const,\n left: x.value,\n top: y.value,\n width: w.value,\n height: h.value,\n opacity: opacity.value,\n zIndex: 0,\n overflow: 'hidden' as const,\n }));\n\n if (reduceMotion) {\n return null;\n }\n\n /** Primary: sliding accent line at bottom (web uses underline layer, not full pill). */\n if (visualVariant === 'primary') {\n return (\n <Animated.View\n pointerEvents=\"none\"\n style={[animatedStyle, { backgroundColor: 'transparent' }]}\n >\n <View style={{ flex: 1, justifyContent: 'flex-end' }}>\n <View\n style={{\n height: PRIMARY_SLIDE_UNDERLINE_HEIGHT,\n width: '100%',\n backgroundColor: primaryAccentColor,\n }}\n />\n </View>\n </Animated.View>\n );\n }\n\n return (\n <Animated.View pointerEvents=\"none\" style={animatedStyle}>\n <View style={[indicatorChrome, { flex: 1 }]} />\n </Animated.View>\n );\n}\n\n/**\n * **⚙️ TabList**\n *\n * @description\n * Horizontal row of {@link Tab} items. Set `scrollable` when tabs may overflow the viewport.\n *\n * @category Navigation\n * @platform mobile\n */\nconst TabList = memo(function TabList({\n children,\n scrollable = false,\n style,\n accessibilityLabel,\n ...viewProps\n}: TabListProps) {\n const { variant: visualVariant, reduceMotion } = useTabsVisualContext();\n tabsStyles.useVariants({ variant: visualVariant });\n\n const rowStyle: ViewStyle = {\n flexDirection: 'row',\n alignItems: 'center',\n position: 'relative',\n ...tabsStyles.root,\n // Secondary track tokens include horizontal padding; shrink-wrap so inset matches on both ends.\n ...(visualVariant === 'secondary' && !scrollable ? { alignSelf: 'flex-start' as const } : {}),\n };\n\n const row = (\n <View style={rowStyle}>\n <TabListIndicator visualVariant={visualVariant} reduceMotion={reduceMotion} />\n {children}\n </View>\n );\n\n if (scrollable) {\n return (\n <ScrollView\n horizontal\n showsHorizontalScrollIndicator={false}\n accessibilityRole=\"tablist\"\n accessibilityLabel={accessibilityLabel}\n {...viewProps}\n style={style}\n >\n {row}\n </ScrollView>\n );\n }\n\n return (\n <View\n accessibilityRole=\"tablist\"\n accessibilityLabel={accessibilityLabel}\n style={style}\n {...viewProps}\n >\n {row}\n </View>\n );\n});\n\nTabList.displayName = 'TabList';\n\nexport { TabList };\nexport type { TabListProps };\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TabPanel.js","names":[],"sources":["../../../src/components/Tabs/TabPanel.tsx"],"sourcesContent":["import type { UniversalTabPanelProps } from '@yahoo/uds-types';\nimport { memo } from 'react';\nimport type { ViewProps, ViewStyle } from 'react-native';\nimport { View } from 'react-native';\n\nimport { useTabSelectionContext } from './tabsContexts';\n\ninterface TabPanelProps\n extends Omit<UniversalTabPanelProps, 'className'>, Omit<ViewProps, 'style' | 'children'> {\n children: UniversalTabPanelProps['children'];\n style?: ViewStyle;\n}\n\n/**\n * **⚙️ TabPanel**\n *\n * @description\n * Content associated with a tab id. Only the panel whose `tabId` matches the current\n * selection is rendered.\n *\n * @category Navigation\n * @platform mobile\n */\nconst TabPanel = memo(function TabPanel({ tabId, children, style, ...viewProps }: TabPanelProps) {\n const { selectedId } = useTabSelectionContext();\n\n if (selectedId !== tabId) {\n return null;\n }\n\n return (\n <View accessibilityRole=\"none\" style={style} {...viewProps}>\n {children}\n </View>\n );\n});\n\nTabPanel.displayName = 'TabPanel';\n\nexport { TabPanel };\nexport type { TabPanelProps };\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,MAAM,WAAW,KAAK,SAAS,SAAS,EAAE,OAAO,UAAU,OAAO,GAAG,aAA4B;CAC/F,MAAM,EAAE,eAAe,wBAAwB;AAE/C,KAAI,eAAe,MACjB,QAAO;AAGT,QACE,oBAAC,MAAD;EAAM,mBAAkB;EAAc;EAAO,GAAI;EAC9C;EACI,CAAA;EAET;AAEF,SAAS,cAAc"}
1
+ {"version":3,"file":"TabPanel.js","names":[],"sources":["../../../src/components/Tabs/TabPanel.tsx"],"sourcesContent":["import type { UniversalTabPanelProps } from '@yahoo/uds-types';\nimport { memo } from 'react';\nimport type { ViewProps, ViewStyle } from 'react-native';\nimport { View } from 'react-native';\n\nimport { useTabSelectionContext } from './tabsContexts';\n\ninterface TabPanelProps\n extends Omit<UniversalTabPanelProps, 'className'>, Omit<ViewProps, 'style' | 'children'> {\n children: UniversalTabPanelProps['children'];\n style?: ViewStyle;\n}\n\n/**\n * **⚙️ TabPanel**\n *\n * @description\n * Content associated with a tab id. Only the panel whose `tabId` matches the current\n * selection is rendered.\n *\n * @category Navigation\n * @platform mobile\n */\nconst TabPanel = memo(function TabPanel({ tabId, children, style, ...viewProps }: TabPanelProps) {\n const { selectedId } = useTabSelectionContext();\n\n if (selectedId !== tabId) {\n return null;\n }\n\n return (\n <View accessibilityRole=\"none\" style={style} {...viewProps}>\n {children}\n </View>\n );\n});\n\nTabPanel.displayName = 'TabPanel';\n\nexport { TabPanel };\nexport type { TabPanelProps };\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,MAAM,WAAW,KAAK,SAAS,SAAS,EAAE,OAAO,UAAU,OAAO,GAAG,aAA4B;CAC/F,MAAM,EAAE,eAAe,wBAAwB;CAE/C,IAAI,eAAe,OACjB,OAAO;CAGT,OACE,oBAAC,MAAD;EAAM,mBAAkB;EAAc;EAAO,GAAI;EAC9C;EACI,CAAA;EAET;AAEF,SAAS,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.js","names":[],"sources":["../../../src/components/Tabs/Tabs.tsx"],"sourcesContent":["import type { UniversalTabsProps } from '@yahoo/uds-types';\nimport { memo, useMemo } from 'react';\n\nimport { TabSelectionContext, TabsVisualContext, useTabSelectionState } from './tabsContexts';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- alias for doc extraction / parity with web\ninterface TabsProps extends UniversalTabsProps {}\n\n/**\n * **⚙️ Tabs**\n *\n * @description\n * Organizes content into sections with a tab list and tab panels. Supports `primary` and\n * `secondary` variants. When `reduceMotion` is false, a sliding indicator animates between\n * tabs (240ms, cubic-bezier(0.2, 0, 0, 1)) to match web UDS.\n *\n * @category Navigation\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Tabs, TabList, Tab, TabPanel } from '@yahoo/uds-mobile/Tabs';\n *\n * <Tabs variant=\"primary\" defaultSelectedId=\"home\">\n * <TabList accessibilityLabel=\"Main\">\n * <Tab value=\"home\">Home</Tab>\n * <Tab value=\"about\">About</Tab>\n * </TabList>\n * <TabPanel tabId=\"home\">Home content</TabPanel>\n * <TabPanel tabId=\"about\">About content</TabPanel>\n * </Tabs>\n * ```\n */\nconst Tabs = memo(function Tabs({\n children,\n variant = 'primary',\n reduceMotion = false,\n defaultSelectedId,\n selectedId,\n onSelectionChange,\n}: TabsProps) {\n const visual = useMemo(() => ({ variant, reduceMotion }), [variant, reduceMotion]);\n const selection = useTabSelectionState({\n defaultSelectedId,\n selectedId,\n onSelectionChange,\n });\n\n return (\n <TabsVisualContext.Provider value={visual}>\n <TabSelectionContext.Provider value={selection}>{children}</TabSelectionContext.Provider>\n </TabsVisualContext.Provider>\n );\n});\n\nTabs.displayName = 'Tabs';\n\nexport { Tabs };\nexport type { TabsProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAM,OAAO,KAAK,SAAS,KAAK,EAC9B,UACA,UAAU,WACV,eAAe,OACf,mBACA,YACA,qBACY;CACZ,MAAM,SAAS,eAAe;EAAE;EAAS;EAAc,GAAG,CAAC,SAAS,aAAa,CAAC;CAClF,MAAM,YAAY,qBAAqB;EACrC;EACA;EACA;EACD,CAAC;AAEF,QACE,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO;YACjC,oBAAC,oBAAoB,UAArB;GAA8B,OAAO;GAAY;GAAwC,CAAA;EAC9D,CAAA;EAE/B;AAEF,KAAK,cAAc"}
1
+ {"version":3,"file":"Tabs.js","names":[],"sources":["../../../src/components/Tabs/Tabs.tsx"],"sourcesContent":["import type { UniversalTabsProps } from '@yahoo/uds-types';\nimport { memo, useMemo } from 'react';\n\nimport { TabSelectionContext, TabsVisualContext, useTabSelectionState } from './tabsContexts';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- alias for doc extraction / parity with web\ninterface TabsProps extends UniversalTabsProps {}\n\n/**\n * **⚙️ Tabs**\n *\n * @description\n * Organizes content into sections with a tab list and tab panels. Supports `primary` and\n * `secondary` variants. When `reduceMotion` is false, a sliding indicator animates between\n * tabs (240ms, cubic-bezier(0.2, 0, 0, 1)) to match web UDS.\n *\n * @category Navigation\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Tabs, TabList, Tab, TabPanel } from '@yahoo/uds-mobile/Tabs';\n *\n * <Tabs variant=\"primary\" defaultSelectedId=\"home\">\n * <TabList accessibilityLabel=\"Main\">\n * <Tab value=\"home\">Home</Tab>\n * <Tab value=\"about\">About</Tab>\n * </TabList>\n * <TabPanel tabId=\"home\">Home content</TabPanel>\n * <TabPanel tabId=\"about\">About content</TabPanel>\n * </Tabs>\n * ```\n */\nconst Tabs = memo(function Tabs({\n children,\n variant = 'primary',\n reduceMotion = false,\n defaultSelectedId,\n selectedId,\n onSelectionChange,\n}: TabsProps) {\n const visual = useMemo(() => ({ variant, reduceMotion }), [variant, reduceMotion]);\n const selection = useTabSelectionState({\n defaultSelectedId,\n selectedId,\n onSelectionChange,\n });\n\n return (\n <TabsVisualContext.Provider value={visual}>\n <TabSelectionContext.Provider value={selection}>{children}</TabSelectionContext.Provider>\n </TabsVisualContext.Provider>\n );\n});\n\nTabs.displayName = 'Tabs';\n\nexport { Tabs };\nexport type { TabsProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAM,OAAO,KAAK,SAAS,KAAK,EAC9B,UACA,UAAU,WACV,eAAe,OACf,mBACA,YACA,qBACY;CACZ,MAAM,SAAS,eAAe;EAAE;EAAS;EAAc,GAAG,CAAC,SAAS,aAAa,CAAC;CAClF,MAAM,YAAY,qBAAqB;EACrC;EACA;EACA;EACD,CAAC;CAEF,OACE,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO;YACjC,oBAAC,oBAAoB,UAArB;GAA8B,OAAO;GAAY;GAAwC,CAAA;EAC9D,CAAA;EAE/B;AAEF,KAAK,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"tabTheme.js","names":[],"sources":["../../../src/components/Tabs/tabTheme.ts"],"sourcesContent":["import type { UniversalTabsVariant } from '@yahoo/uds-types';\nimport type { TextStyle, ViewStyle } from 'react-native';\n\ntype TabActiveState = 'on' | 'off';\ntype TabLayer = 'root' | 'rootText' | 'icon';\ntype InteractionState = 'rest' | 'pressed';\n\nfunction tabComponentPath(\n visual: UniversalTabsVariant,\n active: TabActiveState,\n layer: TabLayer,\n state: InteractionState,\n): string {\n const layerKey = layer === 'rootText' ? 'rootText' : layer;\n return `tab/variant/${visual}/active/${active}/${layerKey}/${state}`;\n}\n\n/** Default tab dimensions / spacing from tokens (`tab/size/default/...`). */\nexport function getTabSizeLayerStyle(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n theme: { components: Record<string, any> },\n layer: 'root' | 'rootText' | 'icon',\n): ViewStyle | TextStyle {\n const path = `tab/size/default/${layer}/rest`;\n const s = theme.components[path];\n return s && typeof s === 'object' ? s : {};\n}\n\n/** Variant + interaction layer (active on/off, pressed/rest). */\nexport function getTabLayerStyle(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n theme: { components: Record<string, any> },\n visual: UniversalTabsVariant,\n active: TabActiveState,\n layer: TabLayer,\n state: InteractionState,\n): ViewStyle | TextStyle {\n const path = tabComponentPath(visual, active, layer, state);\n const s = theme.components[path];\n return s && typeof s === 'object' ? s : {};\n}\n\n/** Size tokens + variant state (matches web stacking size + variant classes). */\nexport function getMergedTabLayerStyle(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n theme: { components: Record<string, any> },\n visual: UniversalTabsVariant,\n active: TabActiveState,\n layer: TabLayer,\n state: InteractionState,\n): ViewStyle | TextStyle {\n const sizeKey = layer === 'rootText' ? 'rootText' : layer === 'icon' ? 'icon' : 'root';\n return {\n ...(getTabSizeLayerStyle(theme, sizeKey) as object),\n ...(getTabLayerStyle(theme, visual, active, layer, state) as object),\n } as ViewStyle;\n}\n"],"mappings":";;AAOA,SAAS,iBACP,QACA,QACA,OACA,OACQ;AAER,QAAO,eAAe,OAAO,UAAU,OAAO,GAD7B,UAAU,aAAa,aAAa,MACK,GAAG;;;AAI/D,SAAgB,qBAEd,OACA,OACuB;CACvB,MAAM,OAAO,oBAAoB,MAAM;CACvC,MAAM,IAAI,MAAM,WAAW;AAC3B,QAAO,KAAK,OAAO,MAAM,WAAW,IAAI,EAAE;;;AAI5C,SAAgB,iBAEd,OACA,QACA,QACA,OACA,OACuB;CACvB,MAAM,OAAO,iBAAiB,QAAQ,QAAQ,OAAO,MAAM;CAC3D,MAAM,IAAI,MAAM,WAAW;AAC3B,QAAO,KAAK,OAAO,MAAM,WAAW,IAAI,EAAE;;;AAI5C,SAAgB,uBAEd,OACA,QACA,QACA,OACA,OACuB;AAEvB,QAAO;EACL,GAAI,qBAAqB,OAFX,UAAU,aAAa,aAAa,UAAU,SAAS,SAAS,OAEtC;EACxC,GAAI,iBAAiB,OAAO,QAAQ,QAAQ,OAAO,MAAM;EAC1D"}
1
+ {"version":3,"file":"tabTheme.js","names":[],"sources":["../../../src/components/Tabs/tabTheme.ts"],"sourcesContent":["import type { UniversalTabsVariant } from '@yahoo/uds-types';\nimport type { TextStyle, ViewStyle } from 'react-native';\n\ntype TabActiveState = 'on' | 'off';\ntype TabLayer = 'root' | 'rootText' | 'icon';\ntype InteractionState = 'rest' | 'pressed';\n\nfunction tabComponentPath(\n visual: UniversalTabsVariant,\n active: TabActiveState,\n layer: TabLayer,\n state: InteractionState,\n): string {\n const layerKey = layer === 'rootText' ? 'rootText' : layer;\n return `tab/variant/${visual}/active/${active}/${layerKey}/${state}`;\n}\n\n/** Default tab dimensions / spacing from tokens (`tab/size/default/...`). */\nexport function getTabSizeLayerStyle(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n theme: { components: Record<string, any> },\n layer: 'root' | 'rootText' | 'icon',\n): ViewStyle | TextStyle {\n const path = `tab/size/default/${layer}/rest`;\n const s = theme.components[path];\n return s && typeof s === 'object' ? s : {};\n}\n\n/** Variant + interaction layer (active on/off, pressed/rest). */\nexport function getTabLayerStyle(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n theme: { components: Record<string, any> },\n visual: UniversalTabsVariant,\n active: TabActiveState,\n layer: TabLayer,\n state: InteractionState,\n): ViewStyle | TextStyle {\n const path = tabComponentPath(visual, active, layer, state);\n const s = theme.components[path];\n return s && typeof s === 'object' ? s : {};\n}\n\n/** Size tokens + variant state (matches web stacking size + variant classes). */\nexport function getMergedTabLayerStyle(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n theme: { components: Record<string, any> },\n visual: UniversalTabsVariant,\n active: TabActiveState,\n layer: TabLayer,\n state: InteractionState,\n): ViewStyle | TextStyle {\n const sizeKey = layer === 'rootText' ? 'rootText' : layer === 'icon' ? 'icon' : 'root';\n return {\n ...(getTabSizeLayerStyle(theme, sizeKey) as object),\n ...(getTabLayerStyle(theme, visual, active, layer, state) as object),\n } as ViewStyle;\n}\n"],"mappings":";;AAOA,SAAS,iBACP,QACA,QACA,OACA,OACQ;CAER,OAAO,eAAe,OAAO,UAAU,OAAO,GAD7B,UAAU,aAAa,aAAa,MACK,GAAG;;;AAI/D,SAAgB,qBAEd,OACA,OACuB;CACvB,MAAM,OAAO,oBAAoB,MAAM;CACvC,MAAM,IAAI,MAAM,WAAW;CAC3B,OAAO,KAAK,OAAO,MAAM,WAAW,IAAI,EAAE;;;AAI5C,SAAgB,iBAEd,OACA,QACA,QACA,OACA,OACuB;CACvB,MAAM,OAAO,iBAAiB,QAAQ,QAAQ,OAAO,MAAM;CAC3D,MAAM,IAAI,MAAM,WAAW;CAC3B,OAAO,KAAK,OAAO,MAAM,WAAW,IAAI,EAAE;;;AAI5C,SAAgB,uBAEd,OACA,QACA,QACA,OACA,OACuB;CAEvB,OAAO;EACL,GAAI,qBAAqB,OAFX,UAAU,aAAa,aAAa,UAAU,SAAS,SAAS,OAEtC;EACxC,GAAI,iBAAiB,OAAO,QAAQ,QAAQ,OAAO,MAAM;EAC1D"}
@@ -1 +1 @@
1
- {"version":3,"file":"tabsContexts.js","names":[],"sources":["../../../src/components/Tabs/tabsContexts.tsx"],"sourcesContent":["import type { UniversalTabsVariant } from '@yahoo/uds-types';\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';\nimport type { LayoutRectangle } from 'react-native';\n\nexport interface TabsVisualContextValue {\n variant: UniversalTabsVariant;\n reduceMotion: boolean;\n}\n\nexport const TabsVisualContext = createContext<TabsVisualContextValue>({\n variant: 'primary',\n reduceMotion: false,\n});\n\nexport function useTabsVisualContext(): TabsVisualContextValue {\n return useContext(TabsVisualContext);\n}\n\nexport interface TabSelectionContextValue {\n selectedId: string | null | undefined;\n setSelectedId: (id: string) => void;\n registerTab: (id: string) => void;\n unregisterTab: (id: string) => void;\n tabLayouts: ReadonlyMap<string, LayoutRectangle>;\n setTabLayout: (id: string, layout: LayoutRectangle) => void;\n clearTabLayout: (id: string) => void;\n}\n\nexport const TabSelectionContext = createContext<TabSelectionContextValue | null>(null);\n\nexport function useTabSelectionContext(): TabSelectionContextValue {\n const ctx = useContext(TabSelectionContext);\n if (!ctx) {\n throw new Error('Tab components must be used within <Tabs>');\n }\n return ctx;\n}\n\nexport function useTabSelectionState({\n defaultSelectedId,\n selectedId: selectedIdProp,\n onSelectionChange,\n}: {\n defaultSelectedId?: string;\n selectedId?: string | null;\n onSelectionChange?: (selectedId: string | null | undefined) => void;\n}): TabSelectionContextValue {\n const isControlled = selectedIdProp !== undefined;\n const [internalSelectedId, setInternalSelectedId] = useState<string | null>(\n defaultSelectedId ?? null,\n );\n const [registeredIds, setRegisteredIds] = useState<string[]>([]);\n const [tabLayouts, setTabLayouts] = useState<Map<string, LayoutRectangle>>(() => new Map());\n\n const selectedId = isControlled ? selectedIdProp : internalSelectedId;\n\n const setSelectedId = useCallback(\n (id: string) => {\n if (!isControlled) {\n setInternalSelectedId(id);\n }\n onSelectionChange?.(id);\n },\n [isControlled, onSelectionChange],\n );\n\n const registerTab = useCallback((id: string) => {\n setRegisteredIds((prev) => (prev.includes(id) ? prev : [...prev, id]));\n }, []);\n\n const unregisterTab = useCallback((id: string) => {\n setRegisteredIds((prev) => prev.filter((x) => x !== id));\n setTabLayouts((prev) => {\n const next = new Map(prev);\n next.delete(id);\n return next;\n });\n }, []);\n\n const setTabLayout = useCallback((id: string, layout: LayoutRectangle) => {\n setTabLayouts((prev) => {\n const cur = prev.get(id);\n if (\n cur &&\n cur.x === layout.x &&\n cur.y === layout.y &&\n cur.width === layout.width &&\n cur.height === layout.height\n ) {\n return prev;\n }\n const next = new Map(prev);\n next.set(id, layout);\n return next;\n });\n }, []);\n\n const clearTabLayout = useCallback((id: string) => {\n setTabLayouts((prev) => {\n if (!prev.has(id)) {\n return prev;\n }\n const next = new Map(prev);\n next.delete(id);\n return next;\n });\n }, []);\n\n useEffect(() => {\n if (isControlled || defaultSelectedId !== undefined) {\n return;\n }\n if (internalSelectedId !== null) {\n return;\n }\n if (registeredIds.length === 0) {\n return;\n }\n setInternalSelectedId(registeredIds[0]!);\n }, [isControlled, defaultSelectedId, internalSelectedId, registeredIds]);\n\n return useMemo(\n () => ({\n selectedId,\n setSelectedId,\n registerTab,\n unregisterTab,\n tabLayouts,\n setTabLayout,\n clearTabLayout,\n }),\n [\n selectedId,\n setSelectedId,\n registerTab,\n unregisterTab,\n tabLayouts,\n setTabLayout,\n clearTabLayout,\n ],\n );\n}\n"],"mappings":";;;AASA,MAAa,oBAAoB,cAAsC;CACrE,SAAS;CACT,cAAc;CACf,CAAC;AAEF,SAAgB,uBAA+C;AAC7D,QAAO,WAAW,kBAAkB;;AAatC,MAAa,sBAAsB,cAA+C,KAAK;AAEvF,SAAgB,yBAAmD;CACjE,MAAM,MAAM,WAAW,oBAAoB;AAC3C,KAAI,CAAC,IACH,OAAM,IAAI,MAAM,4CAA4C;AAE9D,QAAO;;AAGT,SAAgB,qBAAqB,EACnC,mBACA,YAAY,gBACZ,qBAK2B;CAC3B,MAAM,eAAe,mBAAmB,KAAA;CACxC,MAAM,CAAC,oBAAoB,yBAAyB,SAClD,qBAAqB,KACtB;CACD,MAAM,CAAC,eAAe,oBAAoB,SAAmB,EAAE,CAAC;CAChE,MAAM,CAAC,YAAY,iBAAiB,+BAA6C,IAAI,KAAK,CAAC;CAE3F,MAAM,aAAa,eAAe,iBAAiB;CAEnD,MAAM,gBAAgB,aACnB,OAAe;AACd,MAAI,CAAC,aACH,uBAAsB,GAAG;AAE3B,sBAAoB,GAAG;IAEzB,CAAC,cAAc,kBAAkB,CAClC;CAED,MAAM,cAAc,aAAa,OAAe;AAC9C,oBAAkB,SAAU,KAAK,SAAS,GAAG,GAAG,OAAO,CAAC,GAAG,MAAM,GAAG,CAAE;IACrE,EAAE,CAAC;CAEN,MAAM,gBAAgB,aAAa,OAAe;AAChD,oBAAkB,SAAS,KAAK,QAAQ,MAAM,MAAM,GAAG,CAAC;AACxD,iBAAe,SAAS;GACtB,MAAM,OAAO,IAAI,IAAI,KAAK;AAC1B,QAAK,OAAO,GAAG;AACf,UAAO;IACP;IACD,EAAE,CAAC;CAEN,MAAM,eAAe,aAAa,IAAY,WAA4B;AACxE,iBAAe,SAAS;GACtB,MAAM,MAAM,KAAK,IAAI,GAAG;AACxB,OACE,OACA,IAAI,MAAM,OAAO,KACjB,IAAI,MAAM,OAAO,KACjB,IAAI,UAAU,OAAO,SACrB,IAAI,WAAW,OAAO,OAEtB,QAAO;GAET,MAAM,OAAO,IAAI,IAAI,KAAK;AAC1B,QAAK,IAAI,IAAI,OAAO;AACpB,UAAO;IACP;IACD,EAAE,CAAC;CAEN,MAAM,iBAAiB,aAAa,OAAe;AACjD,iBAAe,SAAS;AACtB,OAAI,CAAC,KAAK,IAAI,GAAG,CACf,QAAO;GAET,MAAM,OAAO,IAAI,IAAI,KAAK;AAC1B,QAAK,OAAO,GAAG;AACf,UAAO;IACP;IACD,EAAE,CAAC;AAEN,iBAAgB;AACd,MAAI,gBAAgB,sBAAsB,KAAA,EACxC;AAEF,MAAI,uBAAuB,KACzB;AAEF,MAAI,cAAc,WAAW,EAC3B;AAEF,wBAAsB,cAAc,GAAI;IACvC;EAAC;EAAc;EAAmB;EAAoB;EAAc,CAAC;AAExE,QAAO,eACE;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF"}
1
+ {"version":3,"file":"tabsContexts.js","names":[],"sources":["../../../src/components/Tabs/tabsContexts.tsx"],"sourcesContent":["import type { UniversalTabsVariant } from '@yahoo/uds-types';\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';\nimport type { LayoutRectangle } from 'react-native';\n\nexport interface TabsVisualContextValue {\n variant: UniversalTabsVariant;\n reduceMotion: boolean;\n}\n\nexport const TabsVisualContext = createContext<TabsVisualContextValue>({\n variant: 'primary',\n reduceMotion: false,\n});\n\nexport function useTabsVisualContext(): TabsVisualContextValue {\n return useContext(TabsVisualContext);\n}\n\nexport interface TabSelectionContextValue {\n selectedId: string | null | undefined;\n setSelectedId: (id: string) => void;\n registerTab: (id: string) => void;\n unregisterTab: (id: string) => void;\n tabLayouts: ReadonlyMap<string, LayoutRectangle>;\n setTabLayout: (id: string, layout: LayoutRectangle) => void;\n clearTabLayout: (id: string) => void;\n}\n\nexport const TabSelectionContext = createContext<TabSelectionContextValue | null>(null);\n\nexport function useTabSelectionContext(): TabSelectionContextValue {\n const ctx = useContext(TabSelectionContext);\n if (!ctx) {\n throw new Error('Tab components must be used within <Tabs>');\n }\n return ctx;\n}\n\nexport function useTabSelectionState({\n defaultSelectedId,\n selectedId: selectedIdProp,\n onSelectionChange,\n}: {\n defaultSelectedId?: string;\n selectedId?: string | null;\n onSelectionChange?: (selectedId: string | null | undefined) => void;\n}): TabSelectionContextValue {\n const isControlled = selectedIdProp !== undefined;\n const [internalSelectedId, setInternalSelectedId] = useState<string | null>(\n defaultSelectedId ?? null,\n );\n const [registeredIds, setRegisteredIds] = useState<string[]>([]);\n const [tabLayouts, setTabLayouts] = useState<Map<string, LayoutRectangle>>(() => new Map());\n\n const selectedId = isControlled ? selectedIdProp : internalSelectedId;\n\n const setSelectedId = useCallback(\n (id: string) => {\n if (!isControlled) {\n setInternalSelectedId(id);\n }\n onSelectionChange?.(id);\n },\n [isControlled, onSelectionChange],\n );\n\n const registerTab = useCallback((id: string) => {\n setRegisteredIds((prev) => (prev.includes(id) ? prev : [...prev, id]));\n }, []);\n\n const unregisterTab = useCallback((id: string) => {\n setRegisteredIds((prev) => prev.filter((x) => x !== id));\n setTabLayouts((prev) => {\n const next = new Map(prev);\n next.delete(id);\n return next;\n });\n }, []);\n\n const setTabLayout = useCallback((id: string, layout: LayoutRectangle) => {\n setTabLayouts((prev) => {\n const cur = prev.get(id);\n if (\n cur &&\n cur.x === layout.x &&\n cur.y === layout.y &&\n cur.width === layout.width &&\n cur.height === layout.height\n ) {\n return prev;\n }\n const next = new Map(prev);\n next.set(id, layout);\n return next;\n });\n }, []);\n\n const clearTabLayout = useCallback((id: string) => {\n setTabLayouts((prev) => {\n if (!prev.has(id)) {\n return prev;\n }\n const next = new Map(prev);\n next.delete(id);\n return next;\n });\n }, []);\n\n useEffect(() => {\n if (isControlled || defaultSelectedId !== undefined) {\n return;\n }\n if (internalSelectedId !== null) {\n return;\n }\n if (registeredIds.length === 0) {\n return;\n }\n setInternalSelectedId(registeredIds[0]!);\n }, [isControlled, defaultSelectedId, internalSelectedId, registeredIds]);\n\n return useMemo(\n () => ({\n selectedId,\n setSelectedId,\n registerTab,\n unregisterTab,\n tabLayouts,\n setTabLayout,\n clearTabLayout,\n }),\n [\n selectedId,\n setSelectedId,\n registerTab,\n unregisterTab,\n tabLayouts,\n setTabLayout,\n clearTabLayout,\n ],\n );\n}\n"],"mappings":";;;AASA,MAAa,oBAAoB,cAAsC;CACrE,SAAS;CACT,cAAc;CACf,CAAC;AAEF,SAAgB,uBAA+C;CAC7D,OAAO,WAAW,kBAAkB;;AAatC,MAAa,sBAAsB,cAA+C,KAAK;AAEvF,SAAgB,yBAAmD;CACjE,MAAM,MAAM,WAAW,oBAAoB;CAC3C,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,4CAA4C;CAE9D,OAAO;;AAGT,SAAgB,qBAAqB,EACnC,mBACA,YAAY,gBACZ,qBAK2B;CAC3B,MAAM,eAAe,mBAAmB,KAAA;CACxC,MAAM,CAAC,oBAAoB,yBAAyB,SAClD,qBAAqB,KACtB;CACD,MAAM,CAAC,eAAe,oBAAoB,SAAmB,EAAE,CAAC;CAChE,MAAM,CAAC,YAAY,iBAAiB,+BAA6C,IAAI,KAAK,CAAC;CAE3F,MAAM,aAAa,eAAe,iBAAiB;CAEnD,MAAM,gBAAgB,aACnB,OAAe;EACd,IAAI,CAAC,cACH,sBAAsB,GAAG;EAE3B,oBAAoB,GAAG;IAEzB,CAAC,cAAc,kBAAkB,CAClC;CAED,MAAM,cAAc,aAAa,OAAe;EAC9C,kBAAkB,SAAU,KAAK,SAAS,GAAG,GAAG,OAAO,CAAC,GAAG,MAAM,GAAG,CAAE;IACrE,EAAE,CAAC;CAEN,MAAM,gBAAgB,aAAa,OAAe;EAChD,kBAAkB,SAAS,KAAK,QAAQ,MAAM,MAAM,GAAG,CAAC;EACxD,eAAe,SAAS;GACtB,MAAM,OAAO,IAAI,IAAI,KAAK;GAC1B,KAAK,OAAO,GAAG;GACf,OAAO;IACP;IACD,EAAE,CAAC;CAEN,MAAM,eAAe,aAAa,IAAY,WAA4B;EACxE,eAAe,SAAS;GACtB,MAAM,MAAM,KAAK,IAAI,GAAG;GACxB,IACE,OACA,IAAI,MAAM,OAAO,KACjB,IAAI,MAAM,OAAO,KACjB,IAAI,UAAU,OAAO,SACrB,IAAI,WAAW,OAAO,QAEtB,OAAO;GAET,MAAM,OAAO,IAAI,IAAI,KAAK;GAC1B,KAAK,IAAI,IAAI,OAAO;GACpB,OAAO;IACP;IACD,EAAE,CAAC;CAEN,MAAM,iBAAiB,aAAa,OAAe;EACjD,eAAe,SAAS;GACtB,IAAI,CAAC,KAAK,IAAI,GAAG,EACf,OAAO;GAET,MAAM,OAAO,IAAI,IAAI,KAAK;GAC1B,KAAK,OAAO,GAAG;GACf,OAAO;IACP;IACD,EAAE,CAAC;CAEN,gBAAgB;EACd,IAAI,gBAAgB,sBAAsB,KAAA,GACxC;EAEF,IAAI,uBAAuB,MACzB;EAEF,IAAI,cAAc,WAAW,GAC3B;EAEF,sBAAsB,cAAc,GAAI;IACvC;EAAC;EAAc;EAAmB;EAAoB;EAAc,CAAC;CAExE,OAAO,eACE;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF"}
@@ -36,14 +36,20 @@ let generated_styles = require("../../generated/styles");
36
36
  *
37
37
  * @see {@link Link} for interactive text links
38
38
  */
39
- const Text = (0, react.memo)(function Text({ color = "primary", variant = "body1", fontFamily = variant, fontSize = variant, fontWeight, lineHeight = variant, letterSpacing = variant, textAlign, textTransform, textDecorationLine, style, backgroundColor, borderRadius, borderTopStartRadius, borderTopEndRadius, borderBottomStartRadius, borderBottomEndRadius, borderColor, borderStartColor, borderEndColor, borderTopColor, borderBottomColor, borderWidth, borderVerticalWidth, borderHorizontalWidth, borderStartWidth, borderEndWidth, borderTopWidth, borderBottomWidth, spacing, spacingHorizontal, spacingVertical, spacingBottom, spacingEnd, spacingStart, spacingTop, offset, offsetVertical, offsetHorizontal, offsetBottom, offsetEnd, offsetStart, offsetTop, flexShrink, verticalAlign, height, minHeight, maxHeight, width, minWidth, maxWidth, dangerouslySetColor, ref, ...props }) {
39
+ const Text = (0, react.memo)(function Text({ color = "primary", variant = "body1", fontFamily, fontSize, fontWeight, lineHeight, letterSpacing, textAlign, textTransform, textDecorationLine, style, backgroundColor, borderRadius, borderTopStartRadius, borderTopEndRadius, borderBottomStartRadius, borderBottomEndRadius, borderColor, borderStartColor, borderEndColor, borderTopColor, borderBottomColor, borderWidth, borderVerticalWidth, borderHorizontalWidth, borderStartWidth, borderEndWidth, borderTopWidth, borderBottomWidth, spacing, spacingHorizontal, spacingVertical, spacingBottom, spacingEnd, spacingStart, spacingTop, offset, offsetVertical, offsetHorizontal, offsetBottom, offsetEnd, offsetStart, offsetTop, flexShrink, verticalAlign, height, minHeight, maxHeight, width, minWidth, maxWidth, dangerouslySetColor, ref, ...props }) {
40
+ const resolvedColor = color === "inherit" ? void 0 : color;
41
+ const resolvedVariant = variant === "inherit" ? void 0 : variant;
42
+ const resolvedFontFamily = fontFamily ?? resolvedVariant;
43
+ const resolvedFontSize = fontSize ?? resolvedVariant;
44
+ const resolvedLineHeight = lineHeight ?? resolvedVariant;
45
+ const resolvedLetterSpacing = letterSpacing ?? resolvedVariant;
40
46
  generated_styles.styles.useVariants({
41
- color,
42
- fontFamily,
43
- fontSize,
47
+ color: resolvedColor,
48
+ fontFamily: resolvedFontFamily,
49
+ fontSize: resolvedFontSize,
44
50
  fontWeight,
45
- lineHeight,
46
- letterSpacing,
51
+ lineHeight: resolvedLineHeight,
52
+ letterSpacing: resolvedLetterSpacing,
47
53
  textAlign,
48
54
  textTransform,
49
55
  backgroundColor,
@@ -6,14 +6,15 @@ import { StyleProps } from "../../generated/styles";
6
6
 
7
7
  //#region src/components/Text.d.ts
8
8
  type TextVariant = Exclude<StyleProps['fontFamily'], 'sans' | 'sans-alt' | 'serif' | 'serif-alt' | 'mono' | 'icons'>;
9
+ type TextVariantProp = TextVariant | 'inherit';
9
10
  type TextDecorationLine = 'none' | 'underline' | 'line-through' | 'underline line-through';
10
11
  interface TextProps extends TextProps$1 {
11
12
  /** Ref to the underlying Text element */
12
13
  ref?: Ref<Text$1>;
13
14
  /** Text color from the theme palette */
14
- color?: StyleProps['color'];
15
+ color?: StyleProps['color'] | 'inherit';
15
16
  /** Typography variant - sets fontSize, lineHeight, letterSpacing, and fontFamily together */
16
- variant?: TextVariant;
17
+ variant?: TextVariantProp;
17
18
  /** Override the fontFamily independently */
18
19
  fontFamily?: StyleProps['fontFamily'];
19
20
  /** Override the fontSize independently */
@@ -1 +1 @@
1
- {"version":3,"file":"Text.d.cts","names":[],"sources":["../../src/components/Text.tsx"],"mappings":";;;;;;;KASK,WAAA,GAAc,OAAA,CACjB,UAAA;AAAA,KAMG,kBAAA;AAAA,UAEK,SAAA,SAAkB,WAAA;EATZ;EAWd,GAAA,GAAM,GAAA,CAAI,MAAA;EAXO;EAajB,KAAA,GAAQ,UAAA;EANL;EAQH,OAAA,GAAU,WAAA;;EAEV,UAAA,GAAa,UAAA;EAVQ;EAYrB,QAAA,GAAW,UAAA;EAVO;EAYlB,UAAA,GAAa,UAAA;EAVH;EAYV,UAAA,GAAa,UAAA;EAVL;EAYR,aAAA,GAAgB,UAAA;EARH;EAUb,SAAA,GAAY,UAAA;EANC;EAQb,aAAA,GAAgB,UAAA;EAJA;EAMhB,kBAAA,GAAqB,kBAAA;EAErB,eAAA,GAAkB,UAAA;EAElB,YAAA,GAAe,UAAA;EACf,oBAAA,GAAuB,UAAA;EACvB,kBAAA,GAAqB,UAAA;EACrB,uBAAA,GAA0B,UAAA;EAC1B,qBAAA,GAAwB,UAAA;EACxB,WAAA,GAAc,UAAA;EACd,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,WAAA,GAAc,UAAA;EACd,mBAAA,GAAsB,UAAA;EACtB,qBAAA,GAAwB,UAAA;EACxB,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EAEpB,OAAA,GAAU,UAAA;EACV,iBAAA,GAAoB,UAAA;EACpB,eAAA,GAAkB,UAAA;EAClB,aAAA,GAAgB,UAAA;EAChB,UAAA,GAAa,UAAA;EACb,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EAEb,MAAA,GAAS,UAAA;EACT,cAAA,GAAiB,UAAA;EACjB,gBAAA,GAAmB,UAAA;EACnB,YAAA,GAAe,UAAA;EACf,SAAA,GAAY,UAAA;EACZ,WAAA,GAAc,UAAA;EACd,SAAA,GAAY,UAAA;EAEZ,UAAA,GAAa,UAAA;EAEb,aAAA,GAAgB,SAAA;EAEhB,MAAA;EACA,KAAA;EACA,SAAA;EACA,SAAA;EACA,QAAA;EACA,QAAA;EAEA,mBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiCI,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"Text.d.cts","names":[],"sources":["../../src/components/Text.tsx"],"mappings":";;;;;;;KASK,WAAA,GAAc,OAAA,CACjB,UAAA;AAAA,KAGG,eAAA,GAAkB,WAAA;AAAA,KAIlB,kBAAA;AAAA,UAEK,SAAA,SAAkB,WAAA;;EAE1B,GAAA,GAAM,GAAA,CAAI,MAAA;EAXA;EAaV,KAAA,GAAQ,UAAA;EAVU;EAYlB,OAAA,GAAU,eAAA;EAZW;EAcrB,UAAA,GAAa,UAAA;EAVV;EAYH,QAAA,GAAW,UAAA;;EAEX,UAAA,GAAa,UAAA;EAdQ;EAgBrB,UAAA,GAAa,UAAA;EAdK;EAgBlB,aAAA,GAAgB,UAAA;EAdN;EAgBV,SAAA,GAAY,UAAA;EAdJ;EAgBR,aAAA,GAAgB,UAAA;EAZH;EAcb,kBAAA,GAAqB,kBAAA;EAErB,eAAA,GAAkB,UAAA;EAElB,YAAA,GAAe,UAAA;EACf,oBAAA,GAAuB,UAAA;EACvB,kBAAA,GAAqB,UAAA;EACrB,uBAAA,GAA0B,UAAA;EAC1B,qBAAA,GAAwB,UAAA;EACxB,WAAA,GAAc,UAAA;EACd,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,WAAA,GAAc,UAAA;EACd,mBAAA,GAAsB,UAAA;EACtB,qBAAA,GAAwB,UAAA;EACxB,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EAEpB,OAAA,GAAU,UAAA;EACV,iBAAA,GAAoB,UAAA;EACpB,eAAA,GAAkB,UAAA;EAClB,aAAA,GAAgB,UAAA;EAChB,UAAA,GAAa,UAAA;EACb,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EAEb,MAAA,GAAS,UAAA;EACT,cAAA,GAAiB,UAAA;EACjB,gBAAA,GAAmB,UAAA;EACnB,YAAA,GAAe,UAAA;EACf,SAAA,GAAY,UAAA;EACZ,WAAA,GAAc,UAAA;EACd,SAAA,GAAY,UAAA;EAEZ,UAAA,GAAa,UAAA;EAEb,aAAA,GAAgB,SAAA;EAEhB,MAAA;EACA,KAAA;EACA,SAAA;EACA,SAAA;EACA,QAAA;EACA,QAAA;EAEA,mBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiCI,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
@@ -6,14 +6,15 @@ import { StyleProps } from "../../generated/styles";
6
6
 
7
7
  //#region src/components/Text.d.ts
8
8
  type TextVariant = Exclude<StyleProps['fontFamily'], 'sans' | 'sans-alt' | 'serif' | 'serif-alt' | 'mono' | 'icons'>;
9
+ type TextVariantProp = TextVariant | 'inherit';
9
10
  type TextDecorationLine = 'none' | 'underline' | 'line-through' | 'underline line-through';
10
11
  interface TextProps extends TextProps$1 {
11
12
  /** Ref to the underlying Text element */
12
13
  ref?: Ref<Text$1>;
13
14
  /** Text color from the theme palette */
14
- color?: StyleProps['color'];
15
+ color?: StyleProps['color'] | 'inherit';
15
16
  /** Typography variant - sets fontSize, lineHeight, letterSpacing, and fontFamily together */
16
- variant?: TextVariant;
17
+ variant?: TextVariantProp;
17
18
  /** Override the fontFamily independently */
18
19
  fontFamily?: StyleProps['fontFamily'];
19
20
  /** Override the fontSize independently */
@@ -1 +1 @@
1
- {"version":3,"file":"Text.d.ts","names":[],"sources":["../../src/components/Text.tsx"],"mappings":";;;;;;;KASK,WAAA,GAAc,OAAA,CACjB,UAAA;AAAA,KAMG,kBAAA;AAAA,UAEK,SAAA,SAAkB,WAAA;EATZ;EAWd,GAAA,GAAM,GAAA,CAAI,MAAA;EAXO;EAajB,KAAA,GAAQ,UAAA;EANL;EAQH,OAAA,GAAU,WAAA;;EAEV,UAAA,GAAa,UAAA;EAVQ;EAYrB,QAAA,GAAW,UAAA;EAVO;EAYlB,UAAA,GAAa,UAAA;EAVH;EAYV,UAAA,GAAa,UAAA;EAVL;EAYR,aAAA,GAAgB,UAAA;EARH;EAUb,SAAA,GAAY,UAAA;EANC;EAQb,aAAA,GAAgB,UAAA;EAJA;EAMhB,kBAAA,GAAqB,kBAAA;EAErB,eAAA,GAAkB,UAAA;EAElB,YAAA,GAAe,UAAA;EACf,oBAAA,GAAuB,UAAA;EACvB,kBAAA,GAAqB,UAAA;EACrB,uBAAA,GAA0B,UAAA;EAC1B,qBAAA,GAAwB,UAAA;EACxB,WAAA,GAAc,UAAA;EACd,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,WAAA,GAAc,UAAA;EACd,mBAAA,GAAsB,UAAA;EACtB,qBAAA,GAAwB,UAAA;EACxB,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EAEpB,OAAA,GAAU,UAAA;EACV,iBAAA,GAAoB,UAAA;EACpB,eAAA,GAAkB,UAAA;EAClB,aAAA,GAAgB,UAAA;EAChB,UAAA,GAAa,UAAA;EACb,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EAEb,MAAA,GAAS,UAAA;EACT,cAAA,GAAiB,UAAA;EACjB,gBAAA,GAAmB,UAAA;EACnB,YAAA,GAAe,UAAA;EACf,SAAA,GAAY,UAAA;EACZ,WAAA,GAAc,UAAA;EACd,SAAA,GAAY,UAAA;EAEZ,UAAA,GAAa,UAAA;EAEb,aAAA,GAAgB,SAAA;EAEhB,MAAA;EACA,KAAA;EACA,SAAA;EACA,SAAA;EACA,QAAA;EACA,QAAA;EAEA,mBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiCI,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"Text.d.ts","names":[],"sources":["../../src/components/Text.tsx"],"mappings":";;;;;;;KASK,WAAA,GAAc,OAAA,CACjB,UAAA;AAAA,KAGG,eAAA,GAAkB,WAAA;AAAA,KAIlB,kBAAA;AAAA,UAEK,SAAA,SAAkB,WAAA;;EAE1B,GAAA,GAAM,GAAA,CAAI,MAAA;EAXA;EAaV,KAAA,GAAQ,UAAA;EAVU;EAYlB,OAAA,GAAU,eAAA;EAZW;EAcrB,UAAA,GAAa,UAAA;EAVV;EAYH,QAAA,GAAW,UAAA;;EAEX,UAAA,GAAa,UAAA;EAdQ;EAgBrB,UAAA,GAAa,UAAA;EAdK;EAgBlB,aAAA,GAAgB,UAAA;EAdN;EAgBV,SAAA,GAAY,UAAA;EAdJ;EAgBR,aAAA,GAAgB,UAAA;EAZH;EAcb,kBAAA,GAAqB,kBAAA;EAErB,eAAA,GAAkB,UAAA;EAElB,YAAA,GAAe,UAAA;EACf,oBAAA,GAAuB,UAAA;EACvB,kBAAA,GAAqB,UAAA;EACrB,uBAAA,GAA0B,UAAA;EAC1B,qBAAA,GAAwB,UAAA;EACxB,WAAA,GAAc,UAAA;EACd,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,WAAA,GAAc,UAAA;EACd,mBAAA,GAAsB,UAAA;EACtB,qBAAA,GAAwB,UAAA;EACxB,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EAEpB,OAAA,GAAU,UAAA;EACV,iBAAA,GAAoB,UAAA;EACpB,eAAA,GAAkB,UAAA;EAClB,aAAA,GAAgB,UAAA;EAChB,UAAA,GAAa,UAAA;EACb,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EAEb,MAAA,GAAS,UAAA;EACT,cAAA,GAAiB,UAAA;EACjB,gBAAA,GAAmB,UAAA;EACnB,YAAA,GAAe,UAAA;EACf,SAAA,GAAY,UAAA;EACZ,WAAA,GAAc,UAAA;EACd,SAAA,GAAY,UAAA;EAEZ,UAAA,GAAa,UAAA;EAEb,aAAA,GAAgB,SAAA;EAEhB,MAAA;EACA,KAAA;EACA,SAAA;EACA,SAAA;EACA,QAAA;EACA,QAAA;EAEA,mBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiCI,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
@@ -34,14 +34,20 @@ import { styles } from "../../generated/styles";
34
34
  *
35
35
  * @see {@link Link} for interactive text links
36
36
  */
37
- const Text = memo(function Text({ color = "primary", variant = "body1", fontFamily = variant, fontSize = variant, fontWeight, lineHeight = variant, letterSpacing = variant, textAlign, textTransform, textDecorationLine, style, backgroundColor, borderRadius, borderTopStartRadius, borderTopEndRadius, borderBottomStartRadius, borderBottomEndRadius, borderColor, borderStartColor, borderEndColor, borderTopColor, borderBottomColor, borderWidth, borderVerticalWidth, borderHorizontalWidth, borderStartWidth, borderEndWidth, borderTopWidth, borderBottomWidth, spacing, spacingHorizontal, spacingVertical, spacingBottom, spacingEnd, spacingStart, spacingTop, offset, offsetVertical, offsetHorizontal, offsetBottom, offsetEnd, offsetStart, offsetTop, flexShrink, verticalAlign, height, minHeight, maxHeight, width, minWidth, maxWidth, dangerouslySetColor, ref, ...props }) {
37
+ const Text = memo(function Text({ color = "primary", variant = "body1", fontFamily, fontSize, fontWeight, lineHeight, letterSpacing, textAlign, textTransform, textDecorationLine, style, backgroundColor, borderRadius, borderTopStartRadius, borderTopEndRadius, borderBottomStartRadius, borderBottomEndRadius, borderColor, borderStartColor, borderEndColor, borderTopColor, borderBottomColor, borderWidth, borderVerticalWidth, borderHorizontalWidth, borderStartWidth, borderEndWidth, borderTopWidth, borderBottomWidth, spacing, spacingHorizontal, spacingVertical, spacingBottom, spacingEnd, spacingStart, spacingTop, offset, offsetVertical, offsetHorizontal, offsetBottom, offsetEnd, offsetStart, offsetTop, flexShrink, verticalAlign, height, minHeight, maxHeight, width, minWidth, maxWidth, dangerouslySetColor, ref, ...props }) {
38
+ const resolvedColor = color === "inherit" ? void 0 : color;
39
+ const resolvedVariant = variant === "inherit" ? void 0 : variant;
40
+ const resolvedFontFamily = fontFamily ?? resolvedVariant;
41
+ const resolvedFontSize = fontSize ?? resolvedVariant;
42
+ const resolvedLineHeight = lineHeight ?? resolvedVariant;
43
+ const resolvedLetterSpacing = letterSpacing ?? resolvedVariant;
38
44
  styles.useVariants({
39
- color,
40
- fontFamily,
41
- fontSize,
45
+ color: resolvedColor,
46
+ fontFamily: resolvedFontFamily,
47
+ fontSize: resolvedFontSize,
42
48
  fontWeight,
43
- lineHeight,
44
- letterSpacing,
49
+ lineHeight: resolvedLineHeight,
50
+ letterSpacing: resolvedLetterSpacing,
45
51
  textAlign,
46
52
  textTransform,
47
53
  backgroundColor,