index.mjs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. "use client";
  2. // src/radio-group.tsx
  3. import * as React2 from "react";
  4. import { composeEventHandlers as composeEventHandlers2 } from "@radix-ui/primitive";
  5. import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
  6. import { createContextScope as createContextScope2 } from "@radix-ui/react-context";
  7. import { Primitive as Primitive2 } from "@radix-ui/react-primitive";
  8. import * as RovingFocusGroup from "@radix-ui/react-roving-focus";
  9. import { createRovingFocusGroupScope } from "@radix-ui/react-roving-focus";
  10. import { useControllableState } from "@radix-ui/react-use-controllable-state";
  11. import { useDirection } from "@radix-ui/react-direction";
  12. // src/radio.tsx
  13. import * as React from "react";
  14. import { composeEventHandlers } from "@radix-ui/primitive";
  15. import { useComposedRefs } from "@radix-ui/react-compose-refs";
  16. import { createContextScope } from "@radix-ui/react-context";
  17. import { useSize } from "@radix-ui/react-use-size";
  18. import { usePrevious } from "@radix-ui/react-use-previous";
  19. import { Presence } from "@radix-ui/react-presence";
  20. import { Primitive } from "@radix-ui/react-primitive";
  21. import { jsx, jsxs } from "react/jsx-runtime";
  22. var RADIO_NAME = "Radio";
  23. var [createRadioContext, createRadioScope] = createContextScope(RADIO_NAME);
  24. var [RadioProvider, useRadioContext] = createRadioContext(RADIO_NAME);
  25. var Radio = React.forwardRef(
  26. (props, forwardedRef) => {
  27. const {
  28. __scopeRadio,
  29. name,
  30. checked = false,
  31. required,
  32. disabled,
  33. value = "on",
  34. onCheck,
  35. form,
  36. ...radioProps
  37. } = props;
  38. const [button, setButton] = React.useState(null);
  39. const composedRefs = useComposedRefs(forwardedRef, (node) => setButton(node));
  40. const hasConsumerStoppedPropagationRef = React.useRef(false);
  41. const isFormControl = button ? form || !!button.closest("form") : true;
  42. return /* @__PURE__ */ jsxs(RadioProvider, { scope: __scopeRadio, checked, disabled, children: [
  43. /* @__PURE__ */ jsx(
  44. Primitive.button,
  45. {
  46. type: "button",
  47. role: "radio",
  48. "aria-checked": checked,
  49. "data-state": getState(checked),
  50. "data-disabled": disabled ? "" : void 0,
  51. disabled,
  52. value,
  53. ...radioProps,
  54. ref: composedRefs,
  55. onClick: composeEventHandlers(props.onClick, (event) => {
  56. if (!checked) onCheck?.();
  57. if (isFormControl) {
  58. hasConsumerStoppedPropagationRef.current = event.isPropagationStopped();
  59. if (!hasConsumerStoppedPropagationRef.current) event.stopPropagation();
  60. }
  61. })
  62. }
  63. ),
  64. isFormControl && /* @__PURE__ */ jsx(
  65. RadioBubbleInput,
  66. {
  67. control: button,
  68. bubbles: !hasConsumerStoppedPropagationRef.current,
  69. name,
  70. value,
  71. checked,
  72. required,
  73. disabled,
  74. form,
  75. style: { transform: "translateX(-100%)" }
  76. }
  77. )
  78. ] });
  79. }
  80. );
  81. Radio.displayName = RADIO_NAME;
  82. var INDICATOR_NAME = "RadioIndicator";
  83. var RadioIndicator = React.forwardRef(
  84. (props, forwardedRef) => {
  85. const { __scopeRadio, forceMount, ...indicatorProps } = props;
  86. const context = useRadioContext(INDICATOR_NAME, __scopeRadio);
  87. return /* @__PURE__ */ jsx(Presence, { present: forceMount || context.checked, children: /* @__PURE__ */ jsx(
  88. Primitive.span,
  89. {
  90. "data-state": getState(context.checked),
  91. "data-disabled": context.disabled ? "" : void 0,
  92. ...indicatorProps,
  93. ref: forwardedRef
  94. }
  95. ) });
  96. }
  97. );
  98. RadioIndicator.displayName = INDICATOR_NAME;
  99. var BUBBLE_INPUT_NAME = "RadioBubbleInput";
  100. var RadioBubbleInput = React.forwardRef(
  101. ({
  102. __scopeRadio,
  103. control,
  104. checked,
  105. bubbles = true,
  106. ...props
  107. }, forwardedRef) => {
  108. const ref = React.useRef(null);
  109. const composedRefs = useComposedRefs(ref, forwardedRef);
  110. const prevChecked = usePrevious(checked);
  111. const controlSize = useSize(control);
  112. React.useEffect(() => {
  113. const input = ref.current;
  114. if (!input) return;
  115. const inputProto = window.HTMLInputElement.prototype;
  116. const descriptor = Object.getOwnPropertyDescriptor(
  117. inputProto,
  118. "checked"
  119. );
  120. const setChecked = descriptor.set;
  121. if (prevChecked !== checked && setChecked) {
  122. const event = new Event("click", { bubbles });
  123. setChecked.call(input, checked);
  124. input.dispatchEvent(event);
  125. }
  126. }, [prevChecked, checked, bubbles]);
  127. return /* @__PURE__ */ jsx(
  128. Primitive.input,
  129. {
  130. type: "radio",
  131. "aria-hidden": true,
  132. defaultChecked: checked,
  133. ...props,
  134. tabIndex: -1,
  135. ref: composedRefs,
  136. style: {
  137. ...props.style,
  138. ...controlSize,
  139. position: "absolute",
  140. pointerEvents: "none",
  141. opacity: 0,
  142. margin: 0
  143. }
  144. }
  145. );
  146. }
  147. );
  148. RadioBubbleInput.displayName = BUBBLE_INPUT_NAME;
  149. function getState(checked) {
  150. return checked ? "checked" : "unchecked";
  151. }
  152. // src/radio-group.tsx
  153. import { jsx as jsx2 } from "react/jsx-runtime";
  154. var ARROW_KEYS = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"];
  155. var RADIO_GROUP_NAME = "RadioGroup";
  156. var [createRadioGroupContext, createRadioGroupScope] = createContextScope2(RADIO_GROUP_NAME, [
  157. createRovingFocusGroupScope,
  158. createRadioScope
  159. ]);
  160. var useRovingFocusGroupScope = createRovingFocusGroupScope();
  161. var useRadioScope = createRadioScope();
  162. var [RadioGroupProvider, useRadioGroupContext] = createRadioGroupContext(RADIO_GROUP_NAME);
  163. var RadioGroup = React2.forwardRef(
  164. (props, forwardedRef) => {
  165. const {
  166. __scopeRadioGroup,
  167. name,
  168. defaultValue,
  169. value: valueProp,
  170. required = false,
  171. disabled = false,
  172. orientation,
  173. dir,
  174. loop = true,
  175. onValueChange,
  176. ...groupProps
  177. } = props;
  178. const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeRadioGroup);
  179. const direction = useDirection(dir);
  180. const [value, setValue] = useControllableState({
  181. prop: valueProp,
  182. defaultProp: defaultValue ?? null,
  183. onChange: onValueChange,
  184. caller: RADIO_GROUP_NAME
  185. });
  186. return /* @__PURE__ */ jsx2(
  187. RadioGroupProvider,
  188. {
  189. scope: __scopeRadioGroup,
  190. name,
  191. required,
  192. disabled,
  193. value,
  194. onValueChange: setValue,
  195. children: /* @__PURE__ */ jsx2(
  196. RovingFocusGroup.Root,
  197. {
  198. asChild: true,
  199. ...rovingFocusGroupScope,
  200. orientation,
  201. dir: direction,
  202. loop,
  203. children: /* @__PURE__ */ jsx2(
  204. Primitive2.div,
  205. {
  206. role: "radiogroup",
  207. "aria-required": required,
  208. "aria-orientation": orientation,
  209. "data-disabled": disabled ? "" : void 0,
  210. dir: direction,
  211. ...groupProps,
  212. ref: forwardedRef
  213. }
  214. )
  215. }
  216. )
  217. }
  218. );
  219. }
  220. );
  221. RadioGroup.displayName = RADIO_GROUP_NAME;
  222. var ITEM_NAME = "RadioGroupItem";
  223. var RadioGroupItem = React2.forwardRef(
  224. (props, forwardedRef) => {
  225. const { __scopeRadioGroup, disabled, ...itemProps } = props;
  226. const context = useRadioGroupContext(ITEM_NAME, __scopeRadioGroup);
  227. const isDisabled = context.disabled || disabled;
  228. const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeRadioGroup);
  229. const radioScope = useRadioScope(__scopeRadioGroup);
  230. const ref = React2.useRef(null);
  231. const composedRefs = useComposedRefs2(forwardedRef, ref);
  232. const checked = context.value === itemProps.value;
  233. const isArrowKeyPressedRef = React2.useRef(false);
  234. React2.useEffect(() => {
  235. const handleKeyDown = (event) => {
  236. if (ARROW_KEYS.includes(event.key)) {
  237. isArrowKeyPressedRef.current = true;
  238. }
  239. };
  240. const handleKeyUp = () => isArrowKeyPressedRef.current = false;
  241. document.addEventListener("keydown", handleKeyDown);
  242. document.addEventListener("keyup", handleKeyUp);
  243. return () => {
  244. document.removeEventListener("keydown", handleKeyDown);
  245. document.removeEventListener("keyup", handleKeyUp);
  246. };
  247. }, []);
  248. return /* @__PURE__ */ jsx2(
  249. RovingFocusGroup.Item,
  250. {
  251. asChild: true,
  252. ...rovingFocusGroupScope,
  253. focusable: !isDisabled,
  254. active: checked,
  255. children: /* @__PURE__ */ jsx2(
  256. Radio,
  257. {
  258. disabled: isDisabled,
  259. required: context.required,
  260. checked,
  261. ...radioScope,
  262. ...itemProps,
  263. name: context.name,
  264. ref: composedRefs,
  265. onCheck: () => context.onValueChange(itemProps.value),
  266. onKeyDown: composeEventHandlers2((event) => {
  267. if (event.key === "Enter") event.preventDefault();
  268. }),
  269. onFocus: composeEventHandlers2(itemProps.onFocus, () => {
  270. if (isArrowKeyPressedRef.current) ref.current?.click();
  271. })
  272. }
  273. )
  274. }
  275. );
  276. }
  277. );
  278. RadioGroupItem.displayName = ITEM_NAME;
  279. var INDICATOR_NAME2 = "RadioGroupIndicator";
  280. var RadioGroupIndicator = React2.forwardRef(
  281. (props, forwardedRef) => {
  282. const { __scopeRadioGroup, ...indicatorProps } = props;
  283. const radioScope = useRadioScope(__scopeRadioGroup);
  284. return /* @__PURE__ */ jsx2(RadioIndicator, { ...radioScope, ...indicatorProps, ref: forwardedRef });
  285. }
  286. );
  287. RadioGroupIndicator.displayName = INDICATOR_NAME2;
  288. var Root2 = RadioGroup;
  289. var Item2 = RadioGroupItem;
  290. var Indicator = RadioGroupIndicator;
  291. export {
  292. Indicator,
  293. Item2 as Item,
  294. RadioGroup,
  295. RadioGroupIndicator,
  296. RadioGroupItem,
  297. Root2 as Root,
  298. createRadioGroupScope
  299. };
  300. //# sourceMappingURL=index.mjs.map