@yahoo/uds 3.59.0-beta.1 → 3.59.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/cli/bin/uds-darwin-arm64-baseline +0 -0
  2. package/cli/bin/uds-darwin-x64 +0 -0
  3. package/cli/bin/uds-linux-arm64 +0 -0
  4. package/cli/bin/uds-linux-x64-baseline +0 -0
  5. package/dist/components/Box.d.ts +2 -2
  6. package/dist/components/Box.d.ts.map +1 -1
  7. package/dist/components/Divider/Divider.d.cts +2 -2
  8. package/dist/components/Divider/Divider.d.ts +2 -2
  9. package/dist/components/Divider/DividerCore.d.cts +2 -2
  10. package/dist/components/Divider/DividerCore.d.ts +2 -2
  11. package/dist/components/Divider/DividerInternal.d.cts +2 -2
  12. package/dist/components/Divider/DividerInternal.d.ts +2 -2
  13. package/dist/components/FormLabel.d.ts +2 -2
  14. package/dist/components/HStack.d.ts +2 -2
  15. package/dist/components/Icon.d.ts +2 -2
  16. package/dist/components/Link.d.ts +2 -2
  17. package/dist/components/Text.d.cts +5 -5
  18. package/dist/components/Text.d.cts.map +1 -1
  19. package/dist/components/Text.d.ts +8 -8
  20. package/dist/components/Text.d.ts.map +1 -1
  21. package/dist/components/VStack.d.ts +2 -2
  22. package/dist/components/VStack.d.ts.map +1 -1
  23. package/dist/components/client/AnimateHeightChange.d.cts +2 -2
  24. package/dist/components/client/AnimateHeightChange.d.ts +2 -2
  25. package/dist/components/client/Avatar/Avatar.d.cts +2 -2
  26. package/dist/components/client/Avatar/Avatar.d.cts.map +1 -1
  27. package/dist/components/client/Avatar/Avatar.d.ts +2 -2
  28. package/dist/components/client/Avatar/AvatarIcon.d.cts +2 -2
  29. package/dist/components/client/Avatar/AvatarIcon.d.cts.map +1 -1
  30. package/dist/components/client/Avatar/AvatarIcon.d.ts +2 -2
  31. package/dist/components/client/Avatar/AvatarImage.d.cts +2 -2
  32. package/dist/components/client/Avatar/AvatarImage.d.ts +2 -2
  33. package/dist/components/client/Avatar/AvatarText.d.cts +2 -2
  34. package/dist/components/client/Avatar/AvatarText.d.ts +2 -2
  35. package/dist/components/client/IconButton.d.cts +2 -2
  36. package/dist/components/client/IconButton.d.ts +2 -2
  37. package/dist/components/client/IconButton.d.ts.map +1 -1
  38. package/dist/components/client/Input/Input.d.cts +2 -2
  39. package/dist/components/client/Input/Input.d.ts +2 -2
  40. package/dist/components/client/Input/InputHelpText.d.cts +2 -2
  41. package/dist/components/client/Input/InputHelpText.d.cts.map +1 -1
  42. package/dist/components/client/Input/InputHelpText.d.ts +2 -2
  43. package/dist/components/client/Input/InputHelpTextInternal.d.cts +4 -4
  44. package/dist/components/client/Input/InputHelpTextInternal.d.cts.map +1 -1
  45. package/dist/components/client/Input/InputHelpTextInternal.d.ts +4 -4
  46. package/dist/components/client/Menu/Menu.Content.d.cts +2 -2
  47. package/dist/components/client/Menu/Menu.Content.d.ts +2 -2
  48. package/dist/components/client/Menu/Menu.Divider.d.cts +2 -2
  49. package/dist/components/client/Menu/Menu.Divider.d.ts +2 -2
  50. package/dist/components/client/Menu/Menu.Item.d.cts +2 -2
  51. package/dist/components/client/Menu/Menu.ItemBase.d.cts +2 -2
  52. package/dist/components/client/Menu/Menu.ItemBase.d.ts +2 -2
  53. package/dist/components/client/Menu/Menu.ItemCheckbox.d.cts +2 -2
  54. package/dist/components/client/Menu/Menu.ItemCheckbox.d.ts +2 -2
  55. package/dist/components/client/Menu/Menu.Provider.d.cts +2 -2
  56. package/dist/components/client/Menu/Menu.Provider.d.ts +2 -2
  57. package/dist/components/client/Menu/Menu.Trigger.d.cts +2 -2
  58. package/dist/components/client/Menu/Menu.Trigger.d.ts +2 -2
  59. package/dist/components/client/Pressable.d.cts +2 -2
  60. package/dist/components/client/Pressable.d.ts +2 -2
  61. package/dist/components/client/Pressable.d.ts.map +1 -1
  62. package/dist/components/client/Radio/RadioGroupStore.d.ts +2 -2
  63. package/dist/components/client/SpringMotionConfig.d.cts +3 -3
  64. package/dist/components/client/SpringMotionConfig.d.ts +3 -3
  65. package/dist/components/client/SpringMotionConfig.d.ts.map +1 -1
  66. package/dist/components/experimental/Spinner.d.cts +2 -2
  67. package/dist/components/experimental/Spinner.d.cts.map +1 -1
  68. package/dist/components/experimental/Spinner.d.ts +2 -2
  69. package/dist/components/experimental/Table.d.cts +2 -2
  70. package/dist/components/experimental/Table.d.ts +2 -2
  71. package/dist/components/experimental/client/Accordion.d.cts +2 -2
  72. package/dist/components/experimental/client/Accordion.d.cts.map +1 -1
  73. package/dist/components/experimental/client/Accordion.d.ts +2 -2
  74. package/dist/components/experimental/client/AvoidMotionLibraryProvider.d.cts +2 -2
  75. package/dist/components/experimental/client/AvoidMotionLibraryProvider.d.ts +2 -2
  76. package/dist/components/experimental/client/Modal.d.cts +3 -3
  77. package/dist/components/experimental/client/Modal.d.cts.map +1 -1
  78. package/dist/components/experimental/client/Modal.d.ts +3 -3
  79. package/dist/components/experimental/client/Popover.d.cts +3 -3
  80. package/dist/components/experimental/client/Popover.d.cts.map +1 -1
  81. package/dist/components/experimental/client/Popover.d.ts +3 -3
  82. package/dist/components/experimental/client/Tabs.d.cts +3 -3
  83. package/dist/components/experimental/client/Tabs.d.ts +6 -6
  84. package/dist/components/experimental/client/Toast.d.cts +2 -2
  85. package/dist/components/experimental/client/Toast.d.ts +2 -2
  86. package/dist/providers/ColorModeProvider.d.cts +4 -4
  87. package/dist/providers/ColorModeProvider.d.cts.map +1 -1
  88. package/dist/providers/ColorModeProvider.d.ts +4 -4
  89. package/dist/providers/ColorModeProvider.d.ts.map +1 -1
  90. package/dist/providers/ScaleModeProvider.d.cts +4 -4
  91. package/dist/providers/ScaleModeProvider.d.cts.map +1 -1
  92. package/dist/providers/ScaleModeProvider.d.ts +4 -4
  93. package/dist/providers/ScaleModeProvider.d.ts.map +1 -1
  94. package/dist/providers/ThemeProvider.d.cts +2 -2
  95. package/dist/providers/ThemeProvider.d.cts.map +1 -1
  96. package/dist/providers/ThemeProvider.d.ts +2 -2
  97. package/dist/styles/styler.d.cts +33 -33
  98. package/dist/styles/styler.d.ts +33 -33
  99. package/dist/styles/stylerTypes.d.ts.map +1 -1
  100. package/dist/tailwind/tailwind.config.d.ts +3 -3
  101. package/dist/tailwind/tailwindPlugin.d.ts +3 -3
  102. package/dist/tailwind/utils/getMotionStyles.d.cts +1 -1
  103. package/dist/tailwind/utils/getMotionStyles.d.ts +1 -1
  104. package/dist/tokens/automation/utils/getConfigVariantProperties.d.cts +2 -2
  105. package/dist/tokens/automation/utils/getConfigVariantProperties.d.cts.map +1 -1
  106. package/dist/tokens/automation/utils/getConfigVariantProperties.d.ts +2 -2
  107. package/dist/tokens/automation/utils/getConfigVariantProperties.d.ts.map +1 -1
  108. package/dist/tokens/types.d.cts.map +1 -1
  109. package/dist/tokens/types.d.ts.map +1 -1
  110. package/dist/utils/intersperse.d.cts +2 -2
  111. package/dist/utils/intersperse.d.ts +2 -2
  112. package/package.json +1 -3
  113. package/cli/FlattenButtonVariant.mock.tsx +0 -17
  114. package/src/components/Box.tsx +0 -181
  115. package/src/components/Divider/Divider.tsx +0 -44
  116. package/src/components/Divider/DividerCore.tsx +0 -101
  117. package/src/components/Divider/DividerInternal.tsx +0 -56
  118. package/src/components/Divider/index.ts +0 -1
  119. package/src/components/FormLabel.tsx +0 -66
  120. package/src/components/HStack.tsx +0 -53
  121. package/src/components/Icon.tsx +0 -82
  122. package/src/components/IconSlot.tsx +0 -82
  123. package/src/components/Image.tsx +0 -162
  124. package/src/components/Link.tsx +0 -134
  125. package/src/components/Text.tsx +0 -272
  126. package/src/components/VStack.tsx +0 -53
  127. package/src/components/client/AnimateHeightChange.tsx +0 -50
  128. package/src/components/client/Avatar/Avatar.tsx +0 -31
  129. package/src/components/client/Avatar/AvatarIcon.tsx +0 -103
  130. package/src/components/client/Avatar/AvatarImage.tsx +0 -147
  131. package/src/components/client/Avatar/AvatarText.tsx +0 -88
  132. package/src/components/client/Avatar/index.ts +0 -4
  133. package/src/components/client/Avatar/utils.ts +0 -105
  134. package/src/components/client/Badge.tsx +0 -133
  135. package/src/components/client/Button.tsx +0 -312
  136. package/src/components/client/Checkbox.tsx +0 -377
  137. package/src/components/client/Chip/Chip.tsx +0 -81
  138. package/src/components/client/Chip/ChipBase.tsx +0 -151
  139. package/src/components/client/Chip/ChipButton.tsx +0 -54
  140. package/src/components/client/Chip/ChipDismissible.tsx +0 -90
  141. package/src/components/client/Chip/ChipLink.tsx +0 -60
  142. package/src/components/client/Chip/ChipToggle.tsx +0 -79
  143. package/src/components/client/Chip/index.ts +0 -5
  144. package/src/components/client/IconButton.tsx +0 -198
  145. package/src/components/client/Input/Input.tsx +0 -323
  146. package/src/components/client/Input/InputHelpText.tsx +0 -52
  147. package/src/components/client/Input/InputHelpTextInternal.tsx +0 -81
  148. package/src/components/client/Input/index.ts +0 -2
  149. package/src/components/client/Menu/Menu.Content.tsx +0 -391
  150. package/src/components/client/Menu/Menu.Divider.tsx +0 -102
  151. package/src/components/client/Menu/Menu.Item.tsx +0 -114
  152. package/src/components/client/Menu/Menu.ItemBase.tsx +0 -265
  153. package/src/components/client/Menu/Menu.ItemCheckbox.tsx +0 -197
  154. package/src/components/client/Menu/Menu.Provider.tsx +0 -154
  155. package/src/components/client/Menu/Menu.Trigger.tsx +0 -119
  156. package/src/components/client/Menu/Menu.index.tsx +0 -9
  157. package/src/components/client/Menu/Menu.tsx +0 -2
  158. package/src/components/client/Menu/index.ts +0 -7
  159. package/src/components/client/Menu/utils/transformAriakitPlacement.ts +0 -66
  160. package/src/components/client/Pressable.tsx +0 -194
  161. package/src/components/client/Radio/Radio.tsx +0 -351
  162. package/src/components/client/Radio/RadioGroupProvider.tsx +0 -122
  163. package/src/components/client/Radio/RadioGroupStore.tsx +0 -56
  164. package/src/components/client/Radio/index.ts +0 -2
  165. package/src/components/client/Radio/useRadioGroup.ts +0 -149
  166. package/src/components/client/SpringMotionConfig.tsx +0 -151
  167. package/src/components/client/Switch.tsx +0 -377
  168. package/src/components/client/index.ts +0 -30
  169. package/src/components/client/motionFeatures/domAnimation.ts +0 -2
  170. package/src/components/client/motionFeatures/domMax.ts +0 -2
  171. package/src/components/experimental/Spinner.tsx +0 -30
  172. package/src/components/experimental/Table.mocks.tsx +0 -38
  173. package/src/components/experimental/Table.tsx +0 -239
  174. package/src/components/experimental/client/Accordion.tsx +0 -77
  175. package/src/components/experimental/client/AvoidMotionLibraryProvider.tsx +0 -10
  176. package/src/components/experimental/client/Modal.tsx +0 -68
  177. package/src/components/experimental/client/Popover.tsx +0 -63
  178. package/src/components/experimental/client/SwitchV2.tsx +0 -343
  179. package/src/components/experimental/client/Tabs.tsx +0 -106
  180. package/src/components/experimental/client/Toast.tsx +0 -186
  181. package/src/components/experimental/client/index.ts +0 -15
  182. package/src/components/experimental/index.ts +0 -48
  183. package/src/components/index.ts +0 -41
  184. package/src/defaultTokensConfig.ts +0 -31
  185. package/src/fixtures/index.ts +0 -638
  186. package/src/fixtures/macros/typesToConstants.ts +0 -42
  187. package/src/fixtures/utils/getScaleModeRamp.ts +0 -48
  188. package/src/fixtures/utils/getTailwindAsUdsColors.ts +0 -115
  189. package/src/flags.ts +0 -45
  190. package/src/hooks/useForkRef.ts +0 -34
  191. package/src/hooks/useNestedBorderRadius.ts +0 -138
  192. package/src/hooks/useRtl.ts +0 -64
  193. package/src/index.ts +0 -4
  194. package/src/providers/ColorModeProvider.tsx +0 -21
  195. package/src/providers/ScaleModeProvider.tsx +0 -29
  196. package/src/providers/ThemeProvider.tsx +0 -26
  197. package/src/styles/styler.ts +0 -194
  198. package/src/styles/stylerTypes.ts +0 -81
  199. package/src/styles/toast.css +0 -0
  200. package/src/styles/variants.ts +0 -1351
  201. package/src/tailwind/base/addColorModeVars.ts +0 -23
  202. package/src/tailwind/base/addColorModeVarsV2.ts +0 -57
  203. package/src/tailwind/base/addFontFaceDeclarations.ts +0 -13
  204. package/src/tailwind/base/addFontVars.ts +0 -9
  205. package/src/tailwind/base/addMotionVars.ts +0 -9
  206. package/src/tailwind/base/addScaleModeVars.ts +0 -33
  207. package/src/tailwind/base/types.ts +0 -8
  208. package/src/tailwind/components/getButtonStyles.ts +0 -240
  209. package/src/tailwind/components/getFocusRingStyles.ts +0 -32
  210. package/src/tailwind/components/getGroupedTextStyles.ts +0 -29
  211. package/src/tailwind/components/getHitTargetStyles.ts +0 -23
  212. package/src/tailwind/components/getIconButtonStyles.ts +0 -49
  213. package/src/tailwind/components/getIconStyles.ts +0 -13
  214. package/src/tailwind/components/getInputStyles.ts +0 -20
  215. package/src/tailwind/components/getResponsiveTextStyles.ts +0 -161
  216. package/src/tailwind/components/types.ts +0 -14
  217. package/src/tailwind/components/utils.ts +0 -73
  218. package/src/tailwind/defaultTailwindThemeAsUdsConfig.ts +0 -78
  219. package/src/tailwind/postcss.config.ts +0 -6
  220. package/src/tailwind/purger/index.ts +0 -1
  221. package/src/tailwind/tailwind.config.ts +0 -50
  222. package/src/tailwind/tailwind.d.ts +0 -5
  223. package/src/tailwind/tailwindPlugin.ts +0 -724
  224. package/src/tailwind/theme/getFontFamilyTheme.ts +0 -28
  225. package/src/tailwind/tsMorph.ts +0 -1
  226. package/src/tailwind/uds.css +0 -3
  227. package/src/tailwind/utils/addFontsPlugin.ts +0 -17
  228. package/src/tailwind/utils/getColorModeStyles.ts +0 -21
  229. package/src/tailwind/utils/getFontFaceDeclarations.ts +0 -12
  230. package/src/tailwind/utils/getFontStyles.ts +0 -38
  231. package/src/tailwind/utils/getMotionStyles.ts +0 -35
  232. package/src/tailwind/utils/getScaleModeStyles.ts +0 -23
  233. package/src/tailwind/utils/getShadowPresetValues.ts +0 -133
  234. package/src/tailwind/utils/getShadowStyles.ts +0 -26
  235. package/src/tailwind/utils/getShadowVars.ts +0 -40
  236. package/src/tailwind/utils/index.ts +0 -9
  237. package/src/tokens/automation/configs/avatar.ts +0 -297
  238. package/src/tokens/automation/configs/badge.ts +0 -306
  239. package/src/tokens/automation/configs/checkbox.ts +0 -226
  240. package/src/tokens/automation/configs/chip.ts +0 -521
  241. package/src/tokens/automation/configs/divider.ts +0 -112
  242. package/src/tokens/automation/configs/index.ts +0 -10
  243. package/src/tokens/automation/configs/input.ts +0 -496
  244. package/src/tokens/automation/configs/link.ts +0 -183
  245. package/src/tokens/automation/configs/menu.ts +0 -344
  246. package/src/tokens/automation/configs/radio.ts +0 -225
  247. package/src/tokens/automation/configs/switch.ts +0 -323
  248. package/src/tokens/automation/index.ts +0 -5
  249. package/src/tokens/automation/mapTextVariantFixtureToValue.ts +0 -8
  250. package/src/tokens/automation/properties.ts +0 -433
  251. package/src/tokens/automation/types/ComponentConfig.ts +0 -116
  252. package/src/tokens/automation/types/ComponentDB.ts +0 -1
  253. package/src/tokens/automation/types/ComponentStyles.ts +0 -47
  254. package/src/tokens/automation/types/index.ts +0 -2
  255. package/src/tokens/automation/utils/cartesianProduct.ts +0 -13
  256. package/src/tokens/automation/utils/coalesceConfigVariant.ts +0 -49
  257. package/src/tokens/automation/utils/defaults.ts +0 -29
  258. package/src/tokens/automation/utils/generateKeyFromFlatConfigPath.ts +0 -15
  259. package/src/tokens/automation/utils/generateSchemaKey.ts +0 -29
  260. package/src/tokens/automation/utils/getConfigComponentVariant.ts +0 -28
  261. package/src/tokens/automation/utils/getConfigVariantComponentStatesMatrix.ts +0 -40
  262. package/src/tokens/automation/utils/getConfigVariantProperties.ts +0 -32
  263. package/src/tokens/automation/utils/getConfigVariantPseudoStates.ts +0 -70
  264. package/src/tokens/automation/utils/getConfigVariants.ts +0 -73
  265. package/src/tokens/automation/utils/index.ts +0 -939
  266. package/src/tokens/automation/utils/mapColorFixtureToValue.ts +0 -34
  267. package/src/tokens/automation/utils/subcomponents.ts +0 -13
  268. package/src/tokens/automation/utils/variableData.ts +0 -79
  269. package/src/tokens/automation/utils/variantConfigGuards.ts +0 -17
  270. package/src/tokens/configs/borderRadius.ts +0 -23
  271. package/src/tokens/configs/borderWidth.ts +0 -17
  272. package/src/tokens/configs/button.ts +0 -888
  273. package/src/tokens/configs/colorMode.ts +0 -14
  274. package/src/tokens/configs/font.ts +0 -9
  275. package/src/tokens/configs/iconButton.ts +0 -28
  276. package/src/tokens/configs/motion.ts +0 -135
  277. package/src/tokens/configs/palette.ts +0 -124
  278. package/src/tokens/configs/scaleMode.ts +0 -28
  279. package/src/tokens/configs/shadow.ts +0 -286
  280. package/src/tokens/configs/sizes.ts +0 -23
  281. package/src/tokens/configs/spectrum.ts +0 -729
  282. package/src/tokens/configs/typography.ts +0 -417
  283. package/src/tokens/configs/yosConfig.ts +0 -7651
  284. package/src/tokens/consts/buttonMotionTokens.ts +0 -99
  285. package/src/tokens/consts/cssTokens.ts +0 -110
  286. package/src/tokens/consts/defaultModes.ts +0 -15
  287. package/src/tokens/consts/fontDeclarationsMap.ts +0 -509
  288. package/src/tokens/index.ts +0 -15
  289. package/src/tokens/parseButtonVariants.ts +0 -59
  290. package/src/tokens/parseTokens.ts +0 -122
  291. package/src/tokens/types.ts +0 -1882
  292. package/src/tokens/utils/entries.ts +0 -14
  293. package/src/tokens/utils/fromEntries.ts +0 -11
  294. package/src/tokens/utils/mapValues.ts +0 -15
  295. package/src/types.ts +0 -2
  296. package/src/utils/assertUnreachable.ts +0 -6
  297. package/src/utils/composeRefs.ts +0 -23
  298. package/src/utils/createSlot.tsx +0 -131
  299. package/src/utils/entries.ts +0 -6
  300. package/src/utils/falsyToString.ts +0 -3
  301. package/src/utils/getMotionVar.ts +0 -18
  302. package/src/utils/intersperse.ts +0 -45
  303. package/src/utils/mapValues.ts +0 -15
  304. package/src/utils/mergeSlotProps.ts +0 -70
@@ -1,351 +0,0 @@
1
- import type { RadioSize, RadioVariant, UniversalRadioProps } from '@yahoo/uds/tokens';
2
- import { m, useReducedMotion } from 'motion/react';
3
- import type { ChangeEvent, FocusEvent } from 'react';
4
- import React, { forwardRef, useCallback, useId, useMemo, useRef, useState } from 'react';
5
-
6
- import { cx, getStyles } from '../../../styles/styler';
7
- import { Box } from '../../Box';
8
- import { FormLabel } from '../../FormLabel';
9
- import { SpringMotionConfig } from '../SpringMotionConfig';
10
- import { useRadioGroup } from './useRadioGroup';
11
-
12
- type NativeInputProps = Omit<
13
- React.InputHTMLAttributes<HTMLInputElement>,
14
- 'type' | 'checked' | 'value' | 'size' | 'height' | 'width' | 'color' | 'required'
15
- >;
16
-
17
- interface RadioProps extends NativeInputProps, UniversalRadioProps {
18
- layerClassNames?: {
19
- root?: string;
20
- radio?: string;
21
- label?: string;
22
- };
23
- }
24
-
25
- const RADIO_VARIANTS: RadioVariant[] = ['primary', 'secondary'];
26
- const RADIO_SIZES: RadioSize[] = ['sm', 'md'];
27
-
28
- const VARIANT_ERROR_MAP: Record<RadioVariant, 'alert' | 'alert-secondary'> = {
29
- primary: 'alert',
30
- secondary: 'alert-secondary',
31
- };
32
-
33
- const MotionBox = m.create(Box);
34
-
35
- const hoverTransition = { layoutVariant: 'smooth', layoutSpeed: '3' } as const;
36
- const pressTransition = { layoutVariant: 'veryBouncy', layoutSpeed: '4' } as const;
37
-
38
- /**
39
- * **⚙️️ A Radio.
40
- *
41
- * @componentType Client component
42
- *
43
- * @description
44
- * A radio component allows users to select one or multiple options from a set. Unlike checkbox, radio buttons cannot have multiple selected in a form, allowing only 1 selection in a group. It represents a binary state, typically as selected or unselected.
45
- *
46
- * @see
47
- * Check out the {@link https://uds.build/docs/components/radio Radio Docs} for more info
48
- *
49
- * @usage
50
- * - Forms: Radio
51
- *
52
- * @example
53
- * ```tsx
54
- * 'use client';
55
- * import { Radio } from "@yahoo/uds";
56
- *
57
- * <Radio label="Name" />
58
- *```
59
- *
60
- * @related [Radio](https://uds.build/docs/components/Radio).
61
- **/
62
- const Radio = forwardRef<HTMLInputElement, RadioProps>(function Radio(
63
- {
64
- id,
65
- name: nameProp,
66
- label,
67
- labelPosition = 'start',
68
- variant: variantProp = 'primary',
69
- size = 'md',
70
- reduceMotion: forceReduceMotion,
71
- value: valueProp = '', // Matches HTML
72
- checked: checkedProp,
73
- defaultChecked,
74
- disabled,
75
- hasError,
76
- onChange,
77
- onFocus,
78
- onBlur,
79
- className,
80
- layerClassNames,
81
- ...radioProps
82
- },
83
- parentRef,
84
- ) {
85
- const generatedId = useId();
86
- const uid = id ?? `uds-radio-${generatedId}`;
87
-
88
- const innerRef = useRef<HTMLInputElement | null>(null);
89
-
90
- /**
91
- * State
92
- */
93
- const { name, isControlled, checked, setGroupValue } = useRadioGroup({
94
- name: nameProp,
95
- value: valueProp,
96
- checked: checkedProp,
97
- defaultChecked,
98
- });
99
-
100
- const [isHovered, setIsHovered] = useState(false);
101
- const [isPressed, setIsPressed] = useState(false);
102
-
103
- /**
104
- * Derived values
105
- */
106
- const variant = useMemo(
107
- () => (hasError ? VARIANT_ERROR_MAP[variantProp] : variantProp),
108
- [hasError, variantProp],
109
- );
110
-
111
- const showHoverEffect = useMemo(() => !disabled && isHovered, [disabled, isHovered]);
112
-
113
- const showPressedEffect = useMemo(
114
- () => !disabled && !checked && isPressed,
115
- [checked, disabled, isPressed],
116
- );
117
-
118
- const scale = useMemo(
119
- () => (showPressedEffect ? 0.9 : showHoverEffect ? 1.1 : 1),
120
- [showHoverEffect, showPressedEffect],
121
- );
122
-
123
- const checkOpacity = useMemo(
124
- () => (checked ? (showPressedEffect ? 'opacity-55' : 'opacity-100') : 'opacity-0'),
125
- [checked, showPressedEffect],
126
- );
127
-
128
- const showShadow = useMemo(() => {
129
- const pressedAndUnchecked = showPressedEffect && !checked;
130
- const hoverAndChecked = showHoverEffect && checked;
131
-
132
- return !disabled && (pressedAndUnchecked || hoverAndChecked);
133
- }, [checked, disabled, showHoverEffect, showPressedEffect]);
134
-
135
- const motionAnimate = useMemo(() => ({ scale }), [scale]);
136
-
137
- const motionTransition = useMemo(
138
- () => (isPressed ? pressTransition : hoverTransition),
139
- [isPressed],
140
- );
141
-
142
- /**
143
- * Handlers
144
- */
145
- const handleOnChange = useCallback(
146
- (e: ChangeEvent<HTMLInputElement>) => {
147
- setGroupValue(e.target.value);
148
- onChange?.(e);
149
- },
150
- [onChange, setGroupValue],
151
- );
152
-
153
- const handleFocus = useCallback(
154
- (e: FocusEvent<HTMLInputElement>) => {
155
- onFocus?.(e);
156
- },
157
- [onFocus],
158
- );
159
-
160
- const handleBlur = useCallback(
161
- (e: FocusEvent<HTMLInputElement>) => {
162
- onBlur?.(e);
163
- },
164
- [onBlur],
165
- );
166
-
167
- const handleHoverStart = useCallback(() => {
168
- setIsHovered(true);
169
- }, []);
170
-
171
- const handleHoverEnd = useCallback(() => {
172
- setIsHovered(false);
173
- }, []);
174
-
175
- const handleTapStart = useCallback(() => {
176
- setIsPressed(true);
177
- }, []);
178
-
179
- const handleTapEnd = useCallback(() => {
180
- setIsPressed(false);
181
- }, []);
182
-
183
- // Motion
184
- const prefersReducedMotion = useReducedMotion();
185
- const reduceMotion = forceReduceMotion ? 'always' : 'user';
186
-
187
- const cssAnimationDuration =
188
- prefersReducedMotion || forceReduceMotion ? 'duration-0' : 'duration-120';
189
-
190
- const classNames = {
191
- root: getStyles({
192
- radioSizeRoot: size,
193
- radioVariantValueRoot: checked ? 'checked' : 'unchecked',
194
- radioVariantRoot: variant,
195
- display: 'flex',
196
- flexDirection: labelPosition === 'start' ? 'row' : 'row-reverse',
197
- alignItems: 'center',
198
- className: cx([
199
- {
200
- 'cursor-pointer': !disabled,
201
- 'cursor-default': disabled,
202
- 'opacity-50': disabled,
203
- },
204
-
205
- className,
206
- layerClassNames?.root,
207
- ]),
208
- }),
209
-
210
- radio: getStyles({
211
- radioSizeRadio: size,
212
- radioVariantRadio: variant,
213
- radioVariantValueRadio: checked ? 'checked' : 'unchecked',
214
- className: cx([
215
- 'border',
216
-
217
- 'uds-ring',
218
- 'uds-ring-within',
219
-
220
- cssAnimationDuration,
221
- 'transition-[background-color,border-color]',
222
- 'transition-shadow',
223
-
224
- layerClassNames?.radio,
225
- ]),
226
- }),
227
-
228
- radioCircle: getStyles({
229
- radioVariantRadioCircle: variant,
230
- radioVariantValueRadioCircle: checked ? 'checked' : 'unchecked',
231
- className: cx([
232
- 'pointer-events-none',
233
- 'w-[8px]',
234
- 'h-[8px]',
235
-
236
- // Variant/state specific check opacity override only used when checked.
237
- checkOpacity,
238
-
239
- cssAnimationDuration,
240
- 'transition-opacity',
241
- ]),
242
- }),
243
-
244
- htmlRadio: cx(
245
- // Control the cursor at the top of the component
246
- // and don't let the input override it back to the
247
- // default value.
248
- 'cursor-[inherit]',
249
-
250
- 'absolute',
251
- 'opacity-0',
252
- 'top-1/2',
253
- 'left-1/2',
254
- 'w-[calc(100%+2px)]',
255
- 'h-[calc(100%+2px)]',
256
- 'transform',
257
- 'translate-x-[-50%]',
258
- 'translate-y-[-50%]',
259
- ),
260
-
261
- label: cx(labelPosition === 'start' ? 'text-start' : 'text-end', layerClassNames?.label),
262
- };
263
-
264
- const RootElement = label ? m.label : m.div;
265
-
266
- return (
267
- <SpringMotionConfig reducedMotion={reduceMotion} {...motionTransition}>
268
- <RootElement
269
- className={classNames.root}
270
- data-testid="container"
271
- onHoverStart={handleHoverStart}
272
- onHoverEnd={handleHoverEnd}
273
- onTapStart={handleTapStart}
274
- onTap={handleTapEnd}
275
- onTapCancel={handleTapEnd}
276
- tabIndex={-1}
277
- >
278
- <MotionBox
279
- position="relative"
280
- borderRadius="full"
281
- alignItems="center"
282
- justifyContent="center"
283
- flex="none"
284
- className={classNames.radio}
285
- animate={motionAnimate}
286
- insetShadow={showShadow ? 'lg-invert' : 'none'}
287
- >
288
- <input
289
- type="radio"
290
- // Required for Safari to render a focus ring
291
- tabIndex={0}
292
- // These are standard HTML input props for customization.
293
- {...radioProps}
294
- //
295
- // Provide a ref to the underlying input element for customization.
296
- ref={(ref) => {
297
- // Set internal ref.
298
- innerRef.current = ref;
299
-
300
- // Forward the ref to parent.
301
- if (typeof parentRef === 'function') {
302
- parentRef(ref);
303
- } else if (parentRef !== null) {
304
- parentRef.current = ref;
305
- }
306
- }}
307
- //
308
- // Track focus as a prop for easier styling.
309
- onFocus={handleFocus}
310
- onBlur={handleBlur}
311
- //
312
- // Core props for the Radio.
313
- id={uid}
314
- name={name}
315
- value={valueProp}
316
- disabled={disabled}
317
- aria-invalid={hasError}
318
- onChange={handleOnChange}
319
- {...(isControlled
320
- ? {
321
- checked,
322
- }
323
- : {
324
- defaultChecked,
325
- })}
326
- //
327
- // styles
328
- className={classNames.htmlRadio}
329
- />
330
-
331
- <Box borderRadius="full" className={classNames.radioCircle} />
332
- </MotionBox>
333
-
334
- {label && (
335
- <FormLabel
336
- as="div"
337
- variant="inherit"
338
- color="inherit"
339
- label={label}
340
- className={classNames.label}
341
- />
342
- )}
343
- </RootElement>
344
- </SpringMotionConfig>
345
- );
346
- });
347
-
348
- // Need to re-set this because of the forwardRef wrapper
349
- Radio.displayName = 'Radio';
350
-
351
- export { Radio, RADIO_SIZES, RADIO_VARIANTS, type RadioProps };
@@ -1,122 +0,0 @@
1
- import type { UniversalRadioGroupProps } from '@yahoo/uds/tokens';
2
- import React, { forwardRef, useEffect, useMemo } from 'react';
3
-
4
- import type { DivProps } from '../../../components/Box';
5
- import { createSlot } from '../../../utils/createSlot';
6
- import { RadioGroupContext, RadioGroupStore } from './RadioGroupStore';
7
- import { useRadioGroupName } from './useRadioGroup';
8
-
9
- const Slot = createSlot<React.ComponentType<DivProps>>();
10
-
11
- type NativeDivProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>;
12
-
13
- interface RadioGroupProviderProps extends UniversalRadioGroupProps, NativeDivProps {}
14
-
15
- /**
16
- * A custom RadioGroupStore that extends the default RadioGroupStore to allow for controlled RadioGroups.
17
- */
18
- class RadioGroupProviderStore extends RadioGroupStore {
19
- // The callback to notify the controlled RadioGroup of a value change.
20
- onChangeCb?: (value: string | undefined) => void;
21
-
22
- // Whether the RadioGroup is controlled
23
- isControlled: boolean;
24
-
25
- constructor(name: string, isControlled: boolean) {
26
- super(name);
27
-
28
- this.isControlled = isControlled;
29
- }
30
-
31
- // Overloads the default setValue to notify the controlled RadioGroup of a value change rather than setting the value directly.
32
- setValue(value: string | undefined, force = false) {
33
- // If we are being used inside RadioGroupProvider, we can force the store value to be set (and notify the listeners).
34
- if (!this.isControlled || force) {
35
- super.setValue(value);
36
- return;
37
- }
38
-
39
- this.onChangeCb?.(value);
40
- }
41
- }
42
-
43
- /**
44
- * **⚙️️ A RadioGroup that improves accessibility and provides a central component for state manangement.
45
- *
46
- * @componentType Client component
47
- *
48
- * @description
49
- * Provides a radio group
50
- *
51
- * @see
52
- * Check out the {@link https://uds.build/docs/components/radio Radio Docs} for more info
53
- *
54
- * @usage
55
- * - Forms: RadioGroup
56
- *
57
- * @example
58
- * ```tsx
59
- * 'use client';
60
- * import { RadioGroup } from "@yahoo/uds";
61
- *
62
- * <RadioGroup name="items" value="1">
63
- * <Radio value="1" label="One" />
64
- * <Radio value="2" label="Two" />
65
- * </RadioGroup>
66
- *```
67
- *
68
- * @related [Radio](https://uds.build/docs/components/radio).
69
- **/
70
- const RadioGroupProvider = forwardRef<HTMLDivElement, RadioGroupProviderProps>(
71
- function RadioGroupProvider(
72
- { asChild, name, value: valueProp, defaultValue, onChange, ...props },
73
- ref,
74
- ) {
75
- const isControlled = valueProp !== undefined;
76
- const localName = useRadioGroupName(name);
77
-
78
- // The store for this RadioGroup. Will be created once, memoized and used as the context value.
79
- const store = useMemo(() => {
80
- const s = new RadioGroupProviderStore(localName, isControlled);
81
-
82
- // Set the initial value of the store
83
- s.value = isControlled ? valueProp : defaultValue;
84
-
85
- return s;
86
- }, [defaultValue, isControlled, localName, valueProp]);
87
-
88
- useEffect(() => {
89
- // The store should call the onChange callback when the a change event is emitted.
90
- store.onChangeCb = onChange;
91
- }, [onChange, store]);
92
-
93
- useEffect(() => {
94
- if (!isControlled) {
95
- return;
96
- }
97
-
98
- store.setValue(
99
- valueProp,
100
- true, // Force set the value since we are responding to a controlled prop change.
101
- );
102
- }, [isControlled, store, valueProp]);
103
-
104
- // When the store changes, trigger a change.
105
- useEffect(() => {
106
- return store.onChange((value) => onChange?.(value));
107
- }, [onChange, store]);
108
-
109
- const Comp = asChild ? Slot : 'div';
110
-
111
- return (
112
- <RadioGroupContext.Provider value={store}>
113
- <Comp role="radiogroup" ref={ref} {...props} />
114
- </RadioGroupContext.Provider>
115
- );
116
- },
117
- );
118
-
119
- // Need to re-set this because of the forwardRef wrapper
120
- RadioGroupProvider.displayName = 'RadioGroupProvider';
121
-
122
- export { RadioGroupProvider, type RadioGroupProviderProps };
@@ -1,56 +0,0 @@
1
- import { createContext } from 'react';
2
-
3
- type RadioGroupStoreOnChange = (value: string | undefined) => void;
4
-
5
- /**
6
- * A store for a single RadioGroup. This store is used to manage the state of all Radios within a group.
7
- */
8
- class RadioGroupStore {
9
- // The html name attribute of the RadioGroup.
10
- name: string;
11
-
12
- // The current value of the RadioGroup.
13
- value?: string;
14
-
15
- // A count of the number of active Radios in the group. Used to cleanup stores when all Radios are unmounted.
16
- activeCount = 0;
17
-
18
- // A set of listeners to call when the value of the RadioGroup changes.
19
- #changeListeners = new Set<RadioGroupStoreOnChange>();
20
-
21
- constructor(name: string) {
22
- this.name = name;
23
- }
24
-
25
- // Register a listener to be called when the value of the RadioGroup changes.
26
- onChange(cb: RadioGroupStoreOnChange) {
27
- this.#changeListeners.add(cb);
28
-
29
- // Return a function to remove the listener (used as unmount handler in useEffect).
30
- return () => {
31
- this.#changeListeners.delete(cb);
32
- };
33
- }
34
-
35
- // Set the value of the RadioGroup and notify all listeners.
36
- setValue(value: string | undefined) {
37
- this.value = value;
38
- this.#changeListeners.forEach((cb) => cb(value));
39
- }
40
-
41
- // Create a new store when first encounting a new RadioGroup name.
42
- static findOrCreate(radioGroupStores: Map<string, RadioGroupStore>, name: string) {
43
- let store = radioGroupStores.get(name);
44
-
45
- if (!store) {
46
- store = new RadioGroupStore(name);
47
- radioGroupStores.set(name, store);
48
- }
49
-
50
- return store;
51
- }
52
- }
53
-
54
- const RadioGroupContext = createContext<Map<string, RadioGroupStore> | RadioGroupStore>(new Map());
55
-
56
- export { RadioGroupContext, RadioGroupStore };
@@ -1,2 +0,0 @@
1
- export { Radio, type RadioProps } from './Radio';
2
- export { RadioGroupProvider, type RadioGroupProviderProps } from './RadioGroupProvider';
@@ -1,149 +0,0 @@
1
- import { useCallback, useContext, useEffect, useId, useMemo, useState } from 'react';
2
-
3
- import { RadioGroupContext, RadioGroupStore } from './RadioGroupStore';
4
-
5
- const useRadioGroupName = (name?: string) => {
6
- const uid = useId();
7
- return name ?? `uds-radio-group-${uid}`;
8
- };
9
-
10
- /**
11
- * A hook that connects a single Radio to its RadioGroupStore. If the Radio is used within a RadioGroupProvider,
12
- * it will use the context store. Otherwise, it will use a shared global store across all un-grouped Radios by name.
13
- *
14
- * @param name The name of the Radio which should be shared across the group.
15
- * @param value The value of the Radio.
16
- * @param checked Whether the Radio is checked by its controlled prop.
17
- * @param defaultChecked The uncontrolled default checked state of the Radio.
18
- * @returns The name of the RadioGroup, whether the Radio is controlled, the checked state of the Radio, and a function to set the RadioGroup value.
19
- */
20
- const useRadioGroup = ({
21
- name: radioName,
22
- value: radioValue,
23
- checked: radioIsChecked,
24
- defaultChecked: radioDefaultIsChecked,
25
- }: {
26
- name?: string | undefined;
27
- value: string;
28
- checked?: boolean;
29
- defaultChecked?: boolean;
30
- }): {
31
- name: string;
32
- isControlled: boolean;
33
- checked: boolean | undefined;
34
- setGroupValue: (value: string) => void;
35
- } => {
36
- const ctx = useContext(RadioGroupContext);
37
- const hasRadioGroupProvider = ctx instanceof RadioGroupStore;
38
- const isControlled = radioIsChecked !== undefined || hasRadioGroupProvider;
39
-
40
- // Use either the name passed as a prop on Radio or generate a unique name.
41
- const uniqueName = useRadioGroupName(radioName);
42
-
43
- // Get the Store controlling this Radio.
44
- const store = useMemo(() => {
45
- // Either from RadioGroupProvider
46
- if (hasRadioGroupProvider) {
47
- return ctx;
48
- }
49
-
50
- // Or indexed by name in the global store.
51
- return RadioGroupStore.findOrCreate(ctx, uniqueName);
52
- }, [ctx, hasRadioGroupProvider, uniqueName]);
53
-
54
- // The internal value of the RadioGroup.
55
- const [radioGroupValue, setInternalRadioGroupValue] = useState<string | undefined>(store.value);
56
-
57
- // If the store has a name set, all Radios inside the group should use that name. Otherwise use the Radio's name.
58
- const name = store.name ?? uniqueName;
59
-
60
- // Set the value of the RadioGroup.
61
- const setGroupValue = useCallback(
62
- (value: string) => {
63
- // Notify the store.
64
- store.setValue(value);
65
-
66
- if (isControlled) {
67
- return;
68
- }
69
-
70
- // and optimistically update the internal value.
71
- setInternalRadioGroupValue(value);
72
- },
73
- [isControlled, store],
74
- );
75
-
76
- // Listen for store changes and update the internal value when it changes.
77
- useEffect(() => store.onChange(setInternalRadioGroupValue), [store]);
78
-
79
- useEffect(() => {
80
- // Only update the store if a new Radio in the group has become checked.
81
- if (radioIsChecked !== true) {
82
- return;
83
- }
84
-
85
- setGroupValue(radioValue);
86
- }, [radioIsChecked, radioValue, setGroupValue]);
87
-
88
- // Register with the global store for relating Radios without a RadioGroupProvider.
89
- useEffect(() => {
90
- // Don't need the global store if wrapped in a RadioGroupProvider.
91
- if (hasRadioGroupProvider) {
92
- return;
93
- }
94
-
95
- // Get a store given the RadioGroup name.
96
- const store = RadioGroupStore.findOrCreate(ctx, name);
97
-
98
- // Increment the number of Radios using this store.
99
- store.activeCount += 1;
100
-
101
- // Save the store in the context.
102
- ctx.set(name, store);
103
-
104
- // On unmount.
105
- return () => {
106
- // If this radio is in the store...
107
- const entry = ctx.get(name);
108
-
109
- if (!entry) {
110
- return;
111
- }
112
-
113
- // Decrement the number of Radios using this store.
114
- entry.activeCount -= 1;
115
-
116
- // If there are no more Radios using this store, delete it.
117
- if (entry.activeCount === 0) {
118
- ctx.delete(name);
119
- }
120
- };
121
- }, [ctx, hasRadioGroupProvider, name]);
122
-
123
- // Complicated boolean logic reads better as a IIFE than a ternary.
124
- const checked = (() => {
125
- // If the Radio is controlled by its checked prop AND it's not in a RadioGroupProvider, use the prop.
126
- if (isControlled && !hasRadioGroupProvider) {
127
- return radioIsChecked;
128
- }
129
-
130
- // If the RadioGroup is controlled by a value prop...
131
- if (radioGroupValue !== undefined) {
132
- // The Radio is checked if its value matches the current value of the group.
133
- return radioValue === radioGroupValue;
134
- }
135
-
136
- // Otherwise, we are in an uncontrolled state. If present, our internal value is the defaultChecked prop,
137
- // otherwise we are not checked.
138
- return radioDefaultIsChecked ?? false;
139
- })();
140
-
141
- return {
142
- name,
143
- isControlled,
144
- checked,
145
- setGroupValue,
146
- };
147
- };
148
-
149
- export { useRadioGroup, useRadioGroupName };