@react-aria/radio 3.8.2 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/import.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import {mergeProps as $4vDl6$mergeProps, filterDOMProps as $4vDl6$filterDOMProps, useFormReset as $4vDl6$useFormReset, useId as $4vDl6$useId} from "@react-aria/utils";
2
2
  import {useFocusable as $4vDl6$useFocusable, getFocusableTreeWalker as $4vDl6$getFocusableTreeWalker} from "@react-aria/focus";
3
+ import {useFormValidation as $4vDl6$useFormValidation} from "@react-aria/form";
3
4
  import {usePress as $4vDl6$usePress, useFocusWithin as $4vDl6$useFocusWithin} from "@react-aria/interactions";
4
5
  import {useField as $4vDl6$useField} from "@react-aria/label";
5
6
  import {useLocale as $4vDl6$useLocale} from "@react-aria/i18n";
@@ -35,9 +36,8 @@ import {useLocale as $4vDl6$useLocale} from "@react-aria/i18n";
35
36
  * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
36
37
  * OF ANY KIND, either express or implied. See the License for the specific language
37
38
  * governing permissions and limitations under the License.
38
- */ const $884aeceb3d67f00f$export$3b7b268d09480394 = new WeakMap();
39
- const $884aeceb3d67f00f$export$8e8b214e06dd397d = new WeakMap();
40
- const $884aeceb3d67f00f$export$61c8d3f0151e21b2 = new WeakMap();
39
+ */ const $884aeceb3d67f00f$export$37b65e5b5444d35c = new WeakMap();
40
+
41
41
 
42
42
 
43
43
 
@@ -56,6 +56,13 @@ function $0d5c49892c1215da$export$37b0961d2f4751e2(props, state, ref) {
56
56
  let { pressProps: pressProps, isPressed: isPressed } = (0, $4vDl6$usePress)({
57
57
  isDisabled: isDisabled
58
58
  });
59
+ // iOS does not toggle radios if you drag off and back onto the label, so handle it ourselves.
60
+ let { pressProps: labelProps, isPressed: isLabelPressed } = (0, $4vDl6$usePress)({
61
+ isDisabled: isDisabled,
62
+ onPress () {
63
+ state.setSelectedValue(value);
64
+ }
65
+ });
59
66
  let { focusableProps: focusableProps } = (0, $4vDl6$useFocusable)((0, $4vDl6$mergeProps)(props, {
60
67
  onFocus: ()=>state.setLastFocusedValue(value)
61
68
  }), ref);
@@ -68,26 +75,34 @@ function $0d5c49892c1215da$export$37b0961d2f4751e2(props, state, ref) {
68
75
  if (state.selectedValue === value) tabIndex = 0;
69
76
  } else if (state.lastFocusedValue === value || state.lastFocusedValue == null) tabIndex = 0;
70
77
  if (isDisabled) tabIndex = undefined;
78
+ let { name: name, descriptionId: descriptionId, errorMessageId: errorMessageId, validationBehavior: validationBehavior } = (0, $884aeceb3d67f00f$export$37b65e5b5444d35c).get(state);
71
79
  (0, $4vDl6$useFormReset)(ref, state.selectedValue, state.setSelectedValue);
80
+ (0, $4vDl6$useFormValidation)({
81
+ validationBehavior: validationBehavior
82
+ }, state, ref);
72
83
  return {
84
+ labelProps: (0, $4vDl6$mergeProps)(labelProps, {
85
+ onClick: (e)=>e.preventDefault()
86
+ }),
73
87
  inputProps: (0, $4vDl6$mergeProps)(domProps, {
74
88
  ...interactions,
75
89
  type: "radio",
76
- name: (0, $884aeceb3d67f00f$export$3b7b268d09480394).get(state),
90
+ name: name,
77
91
  tabIndex: tabIndex,
78
92
  disabled: isDisabled,
93
+ required: state.isRequired && validationBehavior === "native",
79
94
  checked: checked,
80
95
  value: value,
81
96
  onChange: onChange,
82
97
  "aria-describedby": [
83
98
  props["aria-describedby"],
84
- state.isInvalid ? (0, $884aeceb3d67f00f$export$61c8d3f0151e21b2).get(state) : null,
85
- (0, $884aeceb3d67f00f$export$8e8b214e06dd397d).get(state)
99
+ state.isInvalid ? errorMessageId : null,
100
+ descriptionId
86
101
  ].filter(Boolean).join(" ") || undefined
87
102
  }),
88
103
  isDisabled: isDisabled,
89
104
  isSelected: checked,
90
- isPressed: isPressed
105
+ isPressed: isPressed || isLabelPressed
91
106
  };
92
107
  }
93
108
 
@@ -109,16 +124,17 @@ function $0d5c49892c1215da$export$37b0961d2f4751e2(props, state, ref) {
109
124
 
110
125
 
111
126
  function $430f30ed08ec25fa$export$62b9571f283ff5c2(props, state) {
112
- let { name: name, isReadOnly: isReadOnly, isRequired: isRequired, isDisabled: isDisabled, orientation: orientation = "vertical" } = props;
127
+ let { name: name, isReadOnly: isReadOnly, isRequired: isRequired, isDisabled: isDisabled, orientation: orientation = "vertical", validationBehavior: validationBehavior = "aria" } = props;
113
128
  let { direction: direction } = (0, $4vDl6$useLocale)();
129
+ let { isInvalid: isInvalid, validationErrors: validationErrors, validationDetails: validationDetails } = state.displayValidation;
114
130
  let { labelProps: labelProps, fieldProps: fieldProps, descriptionProps: descriptionProps, errorMessageProps: errorMessageProps } = (0, $4vDl6$useField)({
115
131
  ...props,
116
132
  // Radio group is not an HTML input element so it
117
133
  // shouldn't be labeled by a <label> element.
118
- labelElementType: "span"
134
+ labelElementType: "span",
135
+ isInvalid: state.isInvalid,
136
+ errorMessage: props.errorMessage || validationErrors
119
137
  });
120
- (0, $884aeceb3d67f00f$export$8e8b214e06dd397d).set(state, descriptionProps.id);
121
- (0, $884aeceb3d67f00f$export$61c8d3f0151e21b2).set(state, errorMessageProps.id);
122
138
  let domProps = (0, $4vDl6$filterDOMProps)(props, {
123
139
  labelable: true
124
140
  });
@@ -126,9 +142,13 @@ function $430f30ed08ec25fa$export$62b9571f283ff5c2(props, state) {
126
142
  // there is no selection. This allows tabbing into the group from either
127
143
  // direction to go to the first or last radio.
128
144
  let { focusWithinProps: focusWithinProps } = (0, $4vDl6$useFocusWithin)({
129
- onBlurWithin () {
145
+ onBlurWithin (e) {
146
+ var _props_onBlur;
147
+ (_props_onBlur = props.onBlur) === null || _props_onBlur === void 0 ? void 0 : _props_onBlur.call(props, e);
130
148
  if (!state.selectedValue) state.setLastFocusedValue(null);
131
- }
149
+ },
150
+ onFocusWithin: props.onFocus,
151
+ onFocusWithinChange: props.onFocusChange
132
152
  });
133
153
  let onKeyDown = (e)=>{
134
154
  let nextDir;
@@ -175,7 +195,12 @@ function $430f30ed08ec25fa$export$62b9571f283ff5c2(props, state) {
175
195
  }
176
196
  };
177
197
  let groupName = (0, $4vDl6$useId)(name);
178
- (0, $884aeceb3d67f00f$export$3b7b268d09480394).set(state, groupName);
198
+ (0, $884aeceb3d67f00f$export$37b65e5b5444d35c).set(state, {
199
+ name: groupName,
200
+ descriptionId: descriptionProps.id,
201
+ errorMessageId: errorMessageProps.id,
202
+ validationBehavior: validationBehavior
203
+ });
179
204
  return {
180
205
  radioGroupProps: (0, $4vDl6$mergeProps)(domProps, {
181
206
  // https://www.w3.org/TR/wai-aria-1.2/#radiogroup
@@ -192,7 +217,10 @@ function $430f30ed08ec25fa$export$62b9571f283ff5c2(props, state) {
192
217
  }),
193
218
  labelProps: labelProps,
194
219
  descriptionProps: descriptionProps,
195
- errorMessageProps: errorMessageProps
220
+ errorMessageProps: errorMessageProps,
221
+ isInvalid: isInvalid,
222
+ validationErrors: validationErrors,
223
+ validationDetails: validationDetails
196
224
  };
197
225
  }
198
226
 
package/dist/main.js CHANGED
@@ -1,9 +1,11 @@
1
1
  var $fMEGB$reactariautils = require("@react-aria/utils");
2
2
  var $fMEGB$reactariafocus = require("@react-aria/focus");
3
+ var $fMEGB$reactariaform = require("@react-aria/form");
3
4
  var $fMEGB$reactariainteractions = require("@react-aria/interactions");
4
5
  var $fMEGB$reactarialabel = require("@react-aria/label");
5
6
  var $fMEGB$reactariai18n = require("@react-aria/i18n");
6
7
 
8
+
7
9
  function $parcel$export(e, n, v, s) {
8
10
  Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
9
11
  }
@@ -41,9 +43,8 @@ $parcel$export(module.exports, "useRadioGroup", () => $dfcade00a56a6317$export$6
41
43
  * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
42
44
  * OF ANY KIND, either express or implied. See the License for the specific language
43
45
  * governing permissions and limitations under the License.
44
- */ const $eeb149278aae5c67$export$3b7b268d09480394 = new WeakMap();
45
- const $eeb149278aae5c67$export$8e8b214e06dd397d = new WeakMap();
46
- const $eeb149278aae5c67$export$61c8d3f0151e21b2 = new WeakMap();
46
+ */ const $eeb149278aae5c67$export$37b65e5b5444d35c = new WeakMap();
47
+
47
48
 
48
49
 
49
50
 
@@ -62,6 +63,13 @@ function $e184702b1b7f1863$export$37b0961d2f4751e2(props, state, ref) {
62
63
  let { pressProps: pressProps, isPressed: isPressed } = (0, $fMEGB$reactariainteractions.usePress)({
63
64
  isDisabled: isDisabled
64
65
  });
66
+ // iOS does not toggle radios if you drag off and back onto the label, so handle it ourselves.
67
+ let { pressProps: labelProps, isPressed: isLabelPressed } = (0, $fMEGB$reactariainteractions.usePress)({
68
+ isDisabled: isDisabled,
69
+ onPress () {
70
+ state.setSelectedValue(value);
71
+ }
72
+ });
65
73
  let { focusableProps: focusableProps } = (0, $fMEGB$reactariafocus.useFocusable)((0, $fMEGB$reactariautils.mergeProps)(props, {
66
74
  onFocus: ()=>state.setLastFocusedValue(value)
67
75
  }), ref);
@@ -74,26 +82,34 @@ function $e184702b1b7f1863$export$37b0961d2f4751e2(props, state, ref) {
74
82
  if (state.selectedValue === value) tabIndex = 0;
75
83
  } else if (state.lastFocusedValue === value || state.lastFocusedValue == null) tabIndex = 0;
76
84
  if (isDisabled) tabIndex = undefined;
85
+ let { name: name, descriptionId: descriptionId, errorMessageId: errorMessageId, validationBehavior: validationBehavior } = (0, $eeb149278aae5c67$export$37b65e5b5444d35c).get(state);
77
86
  (0, $fMEGB$reactariautils.useFormReset)(ref, state.selectedValue, state.setSelectedValue);
87
+ (0, $fMEGB$reactariaform.useFormValidation)({
88
+ validationBehavior: validationBehavior
89
+ }, state, ref);
78
90
  return {
91
+ labelProps: (0, $fMEGB$reactariautils.mergeProps)(labelProps, {
92
+ onClick: (e)=>e.preventDefault()
93
+ }),
79
94
  inputProps: (0, $fMEGB$reactariautils.mergeProps)(domProps, {
80
95
  ...interactions,
81
96
  type: "radio",
82
- name: (0, $eeb149278aae5c67$export$3b7b268d09480394).get(state),
97
+ name: name,
83
98
  tabIndex: tabIndex,
84
99
  disabled: isDisabled,
100
+ required: state.isRequired && validationBehavior === "native",
85
101
  checked: checked,
86
102
  value: value,
87
103
  onChange: onChange,
88
104
  "aria-describedby": [
89
105
  props["aria-describedby"],
90
- state.isInvalid ? (0, $eeb149278aae5c67$export$61c8d3f0151e21b2).get(state) : null,
91
- (0, $eeb149278aae5c67$export$8e8b214e06dd397d).get(state)
106
+ state.isInvalid ? errorMessageId : null,
107
+ descriptionId
92
108
  ].filter(Boolean).join(" ") || undefined
93
109
  }),
94
110
  isDisabled: isDisabled,
95
111
  isSelected: checked,
96
- isPressed: isPressed
112
+ isPressed: isPressed || isLabelPressed
97
113
  };
98
114
  }
99
115
 
@@ -115,16 +131,17 @@ function $e184702b1b7f1863$export$37b0961d2f4751e2(props, state, ref) {
115
131
 
116
132
 
117
133
  function $dfcade00a56a6317$export$62b9571f283ff5c2(props, state) {
118
- let { name: name, isReadOnly: isReadOnly, isRequired: isRequired, isDisabled: isDisabled, orientation: orientation = "vertical" } = props;
134
+ let { name: name, isReadOnly: isReadOnly, isRequired: isRequired, isDisabled: isDisabled, orientation: orientation = "vertical", validationBehavior: validationBehavior = "aria" } = props;
119
135
  let { direction: direction } = (0, $fMEGB$reactariai18n.useLocale)();
136
+ let { isInvalid: isInvalid, validationErrors: validationErrors, validationDetails: validationDetails } = state.displayValidation;
120
137
  let { labelProps: labelProps, fieldProps: fieldProps, descriptionProps: descriptionProps, errorMessageProps: errorMessageProps } = (0, $fMEGB$reactarialabel.useField)({
121
138
  ...props,
122
139
  // Radio group is not an HTML input element so it
123
140
  // shouldn't be labeled by a <label> element.
124
- labelElementType: "span"
141
+ labelElementType: "span",
142
+ isInvalid: state.isInvalid,
143
+ errorMessage: props.errorMessage || validationErrors
125
144
  });
126
- (0, $eeb149278aae5c67$export$8e8b214e06dd397d).set(state, descriptionProps.id);
127
- (0, $eeb149278aae5c67$export$61c8d3f0151e21b2).set(state, errorMessageProps.id);
128
145
  let domProps = (0, $fMEGB$reactariautils.filterDOMProps)(props, {
129
146
  labelable: true
130
147
  });
@@ -132,9 +149,13 @@ function $dfcade00a56a6317$export$62b9571f283ff5c2(props, state) {
132
149
  // there is no selection. This allows tabbing into the group from either
133
150
  // direction to go to the first or last radio.
134
151
  let { focusWithinProps: focusWithinProps } = (0, $fMEGB$reactariainteractions.useFocusWithin)({
135
- onBlurWithin () {
152
+ onBlurWithin (e) {
153
+ var _props_onBlur;
154
+ (_props_onBlur = props.onBlur) === null || _props_onBlur === void 0 ? void 0 : _props_onBlur.call(props, e);
136
155
  if (!state.selectedValue) state.setLastFocusedValue(null);
137
- }
156
+ },
157
+ onFocusWithin: props.onFocus,
158
+ onFocusWithinChange: props.onFocusChange
138
159
  });
139
160
  let onKeyDown = (e)=>{
140
161
  let nextDir;
@@ -181,7 +202,12 @@ function $dfcade00a56a6317$export$62b9571f283ff5c2(props, state) {
181
202
  }
182
203
  };
183
204
  let groupName = (0, $fMEGB$reactariautils.useId)(name);
184
- (0, $eeb149278aae5c67$export$3b7b268d09480394).set(state, groupName);
205
+ (0, $eeb149278aae5c67$export$37b65e5b5444d35c).set(state, {
206
+ name: groupName,
207
+ descriptionId: descriptionProps.id,
208
+ errorMessageId: errorMessageProps.id,
209
+ validationBehavior: validationBehavior
210
+ });
185
211
  return {
186
212
  radioGroupProps: (0, $fMEGB$reactariautils.mergeProps)(domProps, {
187
213
  // https://www.w3.org/TR/wai-aria-1.2/#radiogroup
@@ -198,7 +224,10 @@ function $dfcade00a56a6317$export$62b9571f283ff5c2(props, state) {
198
224
  }),
199
225
  labelProps: labelProps,
200
226
  descriptionProps: descriptionProps,
201
- errorMessageProps: errorMessageProps
227
+ errorMessageProps: errorMessageProps,
228
+ isInvalid: isInvalid,
229
+ validationErrors: validationErrors,
230
+ validationDetails: validationDetails
202
231
  };
203
232
  }
204
233
 
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-aria/radio/src/index.ts","packages/@react-aria/radio/src/useRadio.ts","packages/@react-aria/radio/src/utils.ts","packages/@react-aria/radio/src/useRadioGroup.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport {useRadio} from './useRadio';\nexport {useRadioGroup} from './useRadioGroup';\nexport type {AriaRadioGroupProps, AriaRadioProps} from '@react-types/radio';\nexport type {Orientation} from '@react-types/shared';\nexport type {RadioAria} from './useRadio';\nexport type {RadioGroupAria} from './useRadioGroup';\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaRadioProps} from '@react-types/radio';\nimport {filterDOMProps, mergeProps, useFormReset} from '@react-aria/utils';\nimport {InputHTMLAttributes, RefObject} from 'react';\nimport {radioGroupDescriptionIds, radioGroupErrorMessageIds, radioGroupNames} from './utils';\nimport {RadioGroupState} from '@react-stately/radio';\nimport {useFocusable} from '@react-aria/focus';\nimport {usePress} from '@react-aria/interactions';\n\nexport interface RadioAria {\n /** Props for the input element. */\n inputProps: InputHTMLAttributes<HTMLInputElement>,\n /** Whether the radio is disabled. */\n isDisabled: boolean,\n /** Whether the radio is currently selected. */\n isSelected: boolean,\n /** Whether the radio is in a pressed state. */\n isPressed: boolean\n}\n\n/**\n * Provides the behavior and accessibility implementation for an individual\n * radio button in a radio group.\n * @param props - Props for the radio.\n * @param state - State for the radio group, as returned by `useRadioGroupState`.\n * @param ref - Ref to the HTML input element.\n */\nexport function useRadio(props: AriaRadioProps, state: RadioGroupState, ref: RefObject<HTMLInputElement>): RadioAria {\n let {\n value,\n children,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby\n } = props;\n\n const isDisabled = props.isDisabled || state.isDisabled;\n\n let hasChildren = children != null;\n let hasAriaLabel = ariaLabel != null || ariaLabelledby != null;\n if (!hasChildren && !hasAriaLabel) {\n console.warn('If you do not provide children, you must specify an aria-label for accessibility');\n }\n\n let checked = state.selectedValue === value;\n\n let onChange = (e) => {\n e.stopPropagation();\n state.setSelectedValue(value);\n };\n\n let {pressProps, isPressed} = usePress({\n isDisabled\n });\n\n let {focusableProps} = useFocusable(mergeProps(props, {\n onFocus: () => state.setLastFocusedValue(value)\n }), ref);\n let interactions = mergeProps(pressProps, focusableProps);\n let domProps = filterDOMProps(props, {labelable: true});\n let tabIndex = -1;\n if (state.selectedValue != null) {\n if (state.selectedValue === value) {\n tabIndex = 0;\n }\n } else if (state.lastFocusedValue === value || state.lastFocusedValue == null) {\n tabIndex = 0;\n }\n if (isDisabled) {\n tabIndex = undefined;\n }\n\n useFormReset(ref, state.selectedValue, state.setSelectedValue);\n\n return {\n inputProps: mergeProps(domProps, {\n ...interactions,\n type: 'radio',\n name: radioGroupNames.get(state),\n tabIndex,\n disabled: isDisabled,\n checked,\n value,\n onChange,\n 'aria-describedby': [\n props['aria-describedby'],\n state.isInvalid ? radioGroupErrorMessageIds.get(state) : null,\n radioGroupDescriptionIds.get(state)\n ].filter(Boolean).join(' ') || undefined\n }),\n isDisabled,\n isSelected: checked,\n isPressed\n };\n}\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {RadioGroupState} from '@react-stately/radio';\n\nexport const radioGroupNames = new WeakMap<RadioGroupState, string>();\nexport const radioGroupDescriptionIds = new WeakMap<RadioGroupState, string>();\nexport const radioGroupErrorMessageIds = new WeakMap<RadioGroupState, string>();\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaRadioGroupProps} from '@react-types/radio';\nimport {DOMAttributes} from '@react-types/shared';\nimport {filterDOMProps, mergeProps, useId} from '@react-aria/utils';\nimport {getFocusableTreeWalker} from '@react-aria/focus';\nimport {radioGroupDescriptionIds, radioGroupErrorMessageIds, radioGroupNames} from './utils';\nimport {RadioGroupState} from '@react-stately/radio';\nimport {useField} from '@react-aria/label';\nimport {useFocusWithin} from '@react-aria/interactions';\nimport {useLocale} from '@react-aria/i18n';\n\nexport interface RadioGroupAria {\n /** Props for the radio group wrapper element. */\n radioGroupProps: DOMAttributes,\n /** Props for the radio group's visible label (if any). */\n labelProps: DOMAttributes,\n /** Props for the radio group description element, if any. */\n descriptionProps: DOMAttributes,\n /** Props for the radio group error message element, if any. */\n errorMessageProps: DOMAttributes\n}\n\n/**\n * Provides the behavior and accessibility implementation for a radio group component.\n * Radio groups allow users to select a single item from a list of mutually exclusive options.\n * @param props - Props for the radio group.\n * @param state - State for the radio group, as returned by `useRadioGroupState`.\n */\nexport function useRadioGroup(props: AriaRadioGroupProps, state: RadioGroupState): RadioGroupAria {\n let {\n name,\n isReadOnly,\n isRequired,\n isDisabled,\n orientation = 'vertical'\n } = props;\n let {direction} = useLocale();\n\n let {labelProps, fieldProps, descriptionProps, errorMessageProps} = useField({\n ...props,\n // Radio group is not an HTML input element so it\n // shouldn't be labeled by a <label> element.\n labelElementType: 'span'\n });\n radioGroupDescriptionIds.set(state, descriptionProps.id);\n radioGroupErrorMessageIds.set(state, errorMessageProps.id);\n\n let domProps = filterDOMProps(props, {labelable: true});\n\n // When the radio group loses focus, reset the focusable radio to null if\n // there is no selection. This allows tabbing into the group from either\n // direction to go to the first or last radio.\n let {focusWithinProps} = useFocusWithin({\n onBlurWithin() {\n if (!state.selectedValue) {\n state.setLastFocusedValue(null);\n }\n }\n });\n\n let onKeyDown = (e) => {\n let nextDir;\n switch (e.key) {\n case 'ArrowRight':\n if (direction === 'rtl' && orientation !== 'vertical') {\n nextDir = 'prev';\n } else {\n nextDir = 'next';\n }\n break;\n case 'ArrowLeft':\n if (direction === 'rtl' && orientation !== 'vertical') {\n nextDir = 'next';\n } else {\n nextDir = 'prev';\n }\n break;\n case 'ArrowDown':\n nextDir = 'next';\n break;\n case 'ArrowUp':\n nextDir = 'prev';\n break;\n default:\n return;\n }\n e.preventDefault();\n let walker = getFocusableTreeWalker(e.currentTarget, {from: e.target});\n let nextElem;\n if (nextDir === 'next') {\n nextElem = walker.nextNode();\n if (!nextElem) {\n walker.currentNode = e.currentTarget;\n nextElem = walker.firstChild();\n }\n } else {\n nextElem = walker.previousNode();\n if (!nextElem) {\n walker.currentNode = e.currentTarget;\n nextElem = walker.lastChild();\n }\n }\n if (nextElem) {\n // Call focus on nextElem so that keyboard navigation scrolls the radio into view\n nextElem.focus();\n state.setSelectedValue(nextElem.value);\n }\n };\n\n let groupName = useId(name);\n radioGroupNames.set(state, groupName);\n\n return {\n radioGroupProps: mergeProps(domProps, {\n // https://www.w3.org/TR/wai-aria-1.2/#radiogroup\n role: 'radiogroup',\n onKeyDown,\n 'aria-invalid': state.isInvalid || undefined,\n 'aria-errormessage': props['aria-errormessage'],\n 'aria-readonly': isReadOnly || undefined,\n 'aria-required': isRequired || undefined,\n 'aria-disabled': isDisabled || undefined,\n 'aria-orientation': orientation,\n ...fieldProps,\n ...focusWithinProps\n }),\n labelProps,\n descriptionProps,\n errorMessageProps\n };\n}\n"],"names":[],"version":3,"file":"main.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-aria/radio/src/index.ts","packages/@react-aria/radio/src/useRadio.ts","packages/@react-aria/radio/src/utils.ts","packages/@react-aria/radio/src/useRadioGroup.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport {useRadio} from './useRadio';\nexport {useRadioGroup} from './useRadioGroup';\nexport type {AriaRadioGroupProps, AriaRadioProps} from '@react-types/radio';\nexport type {Orientation} from '@react-types/shared';\nexport type {RadioAria} from './useRadio';\nexport type {RadioGroupAria} from './useRadioGroup';\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaRadioProps} from '@react-types/radio';\nimport {filterDOMProps, mergeProps, useFormReset} from '@react-aria/utils';\nimport {InputHTMLAttributes, LabelHTMLAttributes, RefObject} from 'react';\nimport {radioGroupData} from './utils';\nimport {RadioGroupState} from '@react-stately/radio';\nimport {useFocusable} from '@react-aria/focus';\nimport {useFormValidation} from '@react-aria/form';\nimport {usePress} from '@react-aria/interactions';\n\nexport interface RadioAria {\n /** Props for the label wrapper element. */\n labelProps: LabelHTMLAttributes<HTMLLabelElement>,\n /** Props for the input element. */\n inputProps: InputHTMLAttributes<HTMLInputElement>,\n /** Whether the radio is disabled. */\n isDisabled: boolean,\n /** Whether the radio is currently selected. */\n isSelected: boolean,\n /** Whether the radio is in a pressed state. */\n isPressed: boolean\n}\n\n/**\n * Provides the behavior and accessibility implementation for an individual\n * radio button in a radio group.\n * @param props - Props for the radio.\n * @param state - State for the radio group, as returned by `useRadioGroupState`.\n * @param ref - Ref to the HTML input element.\n */\nexport function useRadio(props: AriaRadioProps, state: RadioGroupState, ref: RefObject<HTMLInputElement>): RadioAria {\n let {\n value,\n children,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby\n } = props;\n\n const isDisabled = props.isDisabled || state.isDisabled;\n\n let hasChildren = children != null;\n let hasAriaLabel = ariaLabel != null || ariaLabelledby != null;\n if (!hasChildren && !hasAriaLabel) {\n console.warn('If you do not provide children, you must specify an aria-label for accessibility');\n }\n\n let checked = state.selectedValue === value;\n\n let onChange = (e) => {\n e.stopPropagation();\n state.setSelectedValue(value);\n };\n\n let {pressProps, isPressed} = usePress({\n isDisabled\n });\n\n // iOS does not toggle radios if you drag off and back onto the label, so handle it ourselves.\n let {pressProps: labelProps, isPressed: isLabelPressed} = usePress({\n isDisabled,\n onPress() {\n state.setSelectedValue(value);\n }\n });\n\n let {focusableProps} = useFocusable(mergeProps(props, {\n onFocus: () => state.setLastFocusedValue(value)\n }), ref);\n let interactions = mergeProps(pressProps, focusableProps);\n let domProps = filterDOMProps(props, {labelable: true});\n let tabIndex: number | undefined = -1;\n if (state.selectedValue != null) {\n if (state.selectedValue === value) {\n tabIndex = 0;\n }\n } else if (state.lastFocusedValue === value || state.lastFocusedValue == null) {\n tabIndex = 0;\n }\n if (isDisabled) {\n tabIndex = undefined;\n }\n\n let {name, descriptionId, errorMessageId, validationBehavior} = radioGroupData.get(state)!;\n useFormReset(ref, state.selectedValue, state.setSelectedValue);\n useFormValidation({validationBehavior}, state, ref);\n\n return {\n labelProps: mergeProps(labelProps, {onClick: e => e.preventDefault()}),\n inputProps: mergeProps(domProps, {\n ...interactions,\n type: 'radio',\n name,\n tabIndex,\n disabled: isDisabled,\n required: state.isRequired && validationBehavior === 'native',\n checked,\n value,\n onChange,\n 'aria-describedby': [\n props['aria-describedby'],\n state.isInvalid ? errorMessageId : null,\n descriptionId\n ].filter(Boolean).join(' ') || undefined\n }),\n isDisabled,\n isSelected: checked,\n isPressed: isPressed || isLabelPressed\n };\n}\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {RadioGroupState} from '@react-stately/radio';\n\ninterface RadioGroupData {\n name: string,\n descriptionId: string | undefined,\n errorMessageId: string | undefined,\n validationBehavior: 'aria' | 'native'\n}\n\nexport const radioGroupData = new WeakMap<RadioGroupState, RadioGroupData>();\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaRadioGroupProps} from '@react-types/radio';\nimport {DOMAttributes, ValidationResult} from '@react-types/shared';\nimport {filterDOMProps, mergeProps, useId} from '@react-aria/utils';\nimport {getFocusableTreeWalker} from '@react-aria/focus';\nimport {radioGroupData} from './utils';\nimport {RadioGroupState} from '@react-stately/radio';\nimport {useField} from '@react-aria/label';\nimport {useFocusWithin} from '@react-aria/interactions';\nimport {useLocale} from '@react-aria/i18n';\n\nexport interface RadioGroupAria extends ValidationResult {\n /** Props for the radio group wrapper element. */\n radioGroupProps: DOMAttributes,\n /** Props for the radio group's visible label (if any). */\n labelProps: DOMAttributes,\n /** Props for the radio group description element, if any. */\n descriptionProps: DOMAttributes,\n /** Props for the radio group error message element, if any. */\n errorMessageProps: DOMAttributes\n}\n\n/**\n * Provides the behavior and accessibility implementation for a radio group component.\n * Radio groups allow users to select a single item from a list of mutually exclusive options.\n * @param props - Props for the radio group.\n * @param state - State for the radio group, as returned by `useRadioGroupState`.\n */\nexport function useRadioGroup(props: AriaRadioGroupProps, state: RadioGroupState): RadioGroupAria {\n let {\n name,\n isReadOnly,\n isRequired,\n isDisabled,\n orientation = 'vertical',\n validationBehavior = 'aria'\n } = props;\n let {direction} = useLocale();\n\n let {isInvalid, validationErrors, validationDetails} = state.displayValidation;\n let {labelProps, fieldProps, descriptionProps, errorMessageProps} = useField({\n ...props,\n // Radio group is not an HTML input element so it\n // shouldn't be labeled by a <label> element.\n labelElementType: 'span',\n isInvalid: state.isInvalid,\n errorMessage: props.errorMessage || validationErrors\n });\n\n let domProps = filterDOMProps(props, {labelable: true});\n\n // When the radio group loses focus, reset the focusable radio to null if\n // there is no selection. This allows tabbing into the group from either\n // direction to go to the first or last radio.\n let {focusWithinProps} = useFocusWithin({\n onBlurWithin(e) {\n props.onBlur?.(e);\n if (!state.selectedValue) {\n state.setLastFocusedValue(null);\n }\n },\n onFocusWithin: props.onFocus,\n onFocusWithinChange: props.onFocusChange\n });\n\n let onKeyDown = (e) => {\n let nextDir;\n switch (e.key) {\n case 'ArrowRight':\n if (direction === 'rtl' && orientation !== 'vertical') {\n nextDir = 'prev';\n } else {\n nextDir = 'next';\n }\n break;\n case 'ArrowLeft':\n if (direction === 'rtl' && orientation !== 'vertical') {\n nextDir = 'next';\n } else {\n nextDir = 'prev';\n }\n break;\n case 'ArrowDown':\n nextDir = 'next';\n break;\n case 'ArrowUp':\n nextDir = 'prev';\n break;\n default:\n return;\n }\n e.preventDefault();\n let walker = getFocusableTreeWalker(e.currentTarget, {from: e.target});\n let nextElem;\n if (nextDir === 'next') {\n nextElem = walker.nextNode();\n if (!nextElem) {\n walker.currentNode = e.currentTarget;\n nextElem = walker.firstChild();\n }\n } else {\n nextElem = walker.previousNode();\n if (!nextElem) {\n walker.currentNode = e.currentTarget;\n nextElem = walker.lastChild();\n }\n }\n if (nextElem) {\n // Call focus on nextElem so that keyboard navigation scrolls the radio into view\n nextElem.focus();\n state.setSelectedValue(nextElem.value);\n }\n };\n\n let groupName = useId(name);\n radioGroupData.set(state, {\n name: groupName,\n descriptionId: descriptionProps.id,\n errorMessageId: errorMessageProps.id,\n validationBehavior\n });\n\n return {\n radioGroupProps: mergeProps(domProps, {\n // https://www.w3.org/TR/wai-aria-1.2/#radiogroup\n role: 'radiogroup',\n onKeyDown,\n 'aria-invalid': state.isInvalid || undefined,\n 'aria-errormessage': props['aria-errormessage'],\n 'aria-readonly': isReadOnly || undefined,\n 'aria-required': isRequired || undefined,\n 'aria-disabled': isDisabled || undefined,\n 'aria-orientation': orientation,\n ...fieldProps,\n ...focusWithinProps\n }),\n labelProps,\n descriptionProps,\n errorMessageProps,\n isInvalid,\n validationErrors,\n validationDetails\n };\n}\n"],"names":[],"version":3,"file":"main.js.map"}
package/dist/module.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import {mergeProps as $4vDl6$mergeProps, filterDOMProps as $4vDl6$filterDOMProps, useFormReset as $4vDl6$useFormReset, useId as $4vDl6$useId} from "@react-aria/utils";
2
2
  import {useFocusable as $4vDl6$useFocusable, getFocusableTreeWalker as $4vDl6$getFocusableTreeWalker} from "@react-aria/focus";
3
+ import {useFormValidation as $4vDl6$useFormValidation} from "@react-aria/form";
3
4
  import {usePress as $4vDl6$usePress, useFocusWithin as $4vDl6$useFocusWithin} from "@react-aria/interactions";
4
5
  import {useField as $4vDl6$useField} from "@react-aria/label";
5
6
  import {useLocale as $4vDl6$useLocale} from "@react-aria/i18n";
@@ -35,9 +36,8 @@ import {useLocale as $4vDl6$useLocale} from "@react-aria/i18n";
35
36
  * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
36
37
  * OF ANY KIND, either express or implied. See the License for the specific language
37
38
  * governing permissions and limitations under the License.
38
- */ const $884aeceb3d67f00f$export$3b7b268d09480394 = new WeakMap();
39
- const $884aeceb3d67f00f$export$8e8b214e06dd397d = new WeakMap();
40
- const $884aeceb3d67f00f$export$61c8d3f0151e21b2 = new WeakMap();
39
+ */ const $884aeceb3d67f00f$export$37b65e5b5444d35c = new WeakMap();
40
+
41
41
 
42
42
 
43
43
 
@@ -56,6 +56,13 @@ function $0d5c49892c1215da$export$37b0961d2f4751e2(props, state, ref) {
56
56
  let { pressProps: pressProps, isPressed: isPressed } = (0, $4vDl6$usePress)({
57
57
  isDisabled: isDisabled
58
58
  });
59
+ // iOS does not toggle radios if you drag off and back onto the label, so handle it ourselves.
60
+ let { pressProps: labelProps, isPressed: isLabelPressed } = (0, $4vDl6$usePress)({
61
+ isDisabled: isDisabled,
62
+ onPress () {
63
+ state.setSelectedValue(value);
64
+ }
65
+ });
59
66
  let { focusableProps: focusableProps } = (0, $4vDl6$useFocusable)((0, $4vDl6$mergeProps)(props, {
60
67
  onFocus: ()=>state.setLastFocusedValue(value)
61
68
  }), ref);
@@ -68,26 +75,34 @@ function $0d5c49892c1215da$export$37b0961d2f4751e2(props, state, ref) {
68
75
  if (state.selectedValue === value) tabIndex = 0;
69
76
  } else if (state.lastFocusedValue === value || state.lastFocusedValue == null) tabIndex = 0;
70
77
  if (isDisabled) tabIndex = undefined;
78
+ let { name: name, descriptionId: descriptionId, errorMessageId: errorMessageId, validationBehavior: validationBehavior } = (0, $884aeceb3d67f00f$export$37b65e5b5444d35c).get(state);
71
79
  (0, $4vDl6$useFormReset)(ref, state.selectedValue, state.setSelectedValue);
80
+ (0, $4vDl6$useFormValidation)({
81
+ validationBehavior: validationBehavior
82
+ }, state, ref);
72
83
  return {
84
+ labelProps: (0, $4vDl6$mergeProps)(labelProps, {
85
+ onClick: (e)=>e.preventDefault()
86
+ }),
73
87
  inputProps: (0, $4vDl6$mergeProps)(domProps, {
74
88
  ...interactions,
75
89
  type: "radio",
76
- name: (0, $884aeceb3d67f00f$export$3b7b268d09480394).get(state),
90
+ name: name,
77
91
  tabIndex: tabIndex,
78
92
  disabled: isDisabled,
93
+ required: state.isRequired && validationBehavior === "native",
79
94
  checked: checked,
80
95
  value: value,
81
96
  onChange: onChange,
82
97
  "aria-describedby": [
83
98
  props["aria-describedby"],
84
- state.isInvalid ? (0, $884aeceb3d67f00f$export$61c8d3f0151e21b2).get(state) : null,
85
- (0, $884aeceb3d67f00f$export$8e8b214e06dd397d).get(state)
99
+ state.isInvalid ? errorMessageId : null,
100
+ descriptionId
86
101
  ].filter(Boolean).join(" ") || undefined
87
102
  }),
88
103
  isDisabled: isDisabled,
89
104
  isSelected: checked,
90
- isPressed: isPressed
105
+ isPressed: isPressed || isLabelPressed
91
106
  };
92
107
  }
93
108
 
@@ -109,16 +124,17 @@ function $0d5c49892c1215da$export$37b0961d2f4751e2(props, state, ref) {
109
124
 
110
125
 
111
126
  function $430f30ed08ec25fa$export$62b9571f283ff5c2(props, state) {
112
- let { name: name, isReadOnly: isReadOnly, isRequired: isRequired, isDisabled: isDisabled, orientation: orientation = "vertical" } = props;
127
+ let { name: name, isReadOnly: isReadOnly, isRequired: isRequired, isDisabled: isDisabled, orientation: orientation = "vertical", validationBehavior: validationBehavior = "aria" } = props;
113
128
  let { direction: direction } = (0, $4vDl6$useLocale)();
129
+ let { isInvalid: isInvalid, validationErrors: validationErrors, validationDetails: validationDetails } = state.displayValidation;
114
130
  let { labelProps: labelProps, fieldProps: fieldProps, descriptionProps: descriptionProps, errorMessageProps: errorMessageProps } = (0, $4vDl6$useField)({
115
131
  ...props,
116
132
  // Radio group is not an HTML input element so it
117
133
  // shouldn't be labeled by a <label> element.
118
- labelElementType: "span"
134
+ labelElementType: "span",
135
+ isInvalid: state.isInvalid,
136
+ errorMessage: props.errorMessage || validationErrors
119
137
  });
120
- (0, $884aeceb3d67f00f$export$8e8b214e06dd397d).set(state, descriptionProps.id);
121
- (0, $884aeceb3d67f00f$export$61c8d3f0151e21b2).set(state, errorMessageProps.id);
122
138
  let domProps = (0, $4vDl6$filterDOMProps)(props, {
123
139
  labelable: true
124
140
  });
@@ -126,9 +142,13 @@ function $430f30ed08ec25fa$export$62b9571f283ff5c2(props, state) {
126
142
  // there is no selection. This allows tabbing into the group from either
127
143
  // direction to go to the first or last radio.
128
144
  let { focusWithinProps: focusWithinProps } = (0, $4vDl6$useFocusWithin)({
129
- onBlurWithin () {
145
+ onBlurWithin (e) {
146
+ var _props_onBlur;
147
+ (_props_onBlur = props.onBlur) === null || _props_onBlur === void 0 ? void 0 : _props_onBlur.call(props, e);
130
148
  if (!state.selectedValue) state.setLastFocusedValue(null);
131
- }
149
+ },
150
+ onFocusWithin: props.onFocus,
151
+ onFocusWithinChange: props.onFocusChange
132
152
  });
133
153
  let onKeyDown = (e)=>{
134
154
  let nextDir;
@@ -175,7 +195,12 @@ function $430f30ed08ec25fa$export$62b9571f283ff5c2(props, state) {
175
195
  }
176
196
  };
177
197
  let groupName = (0, $4vDl6$useId)(name);
178
- (0, $884aeceb3d67f00f$export$3b7b268d09480394).set(state, groupName);
198
+ (0, $884aeceb3d67f00f$export$37b65e5b5444d35c).set(state, {
199
+ name: groupName,
200
+ descriptionId: descriptionProps.id,
201
+ errorMessageId: errorMessageProps.id,
202
+ validationBehavior: validationBehavior
203
+ });
179
204
  return {
180
205
  radioGroupProps: (0, $4vDl6$mergeProps)(domProps, {
181
206
  // https://www.w3.org/TR/wai-aria-1.2/#radiogroup
@@ -192,7 +217,10 @@ function $430f30ed08ec25fa$export$62b9571f283ff5c2(props, state) {
192
217
  }),
193
218
  labelProps: labelProps,
194
219
  descriptionProps: descriptionProps,
195
- errorMessageProps: errorMessageProps
220
+ errorMessageProps: errorMessageProps,
221
+ isInvalid: isInvalid,
222
+ validationErrors: validationErrors,
223
+ validationDetails: validationDetails
196
224
  };
197
225
  }
198
226
 
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-aria/radio/src/index.ts","packages/@react-aria/radio/src/useRadio.ts","packages/@react-aria/radio/src/utils.ts","packages/@react-aria/radio/src/useRadioGroup.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport {useRadio} from './useRadio';\nexport {useRadioGroup} from './useRadioGroup';\nexport type {AriaRadioGroupProps, AriaRadioProps} from '@react-types/radio';\nexport type {Orientation} from '@react-types/shared';\nexport type {RadioAria} from './useRadio';\nexport type {RadioGroupAria} from './useRadioGroup';\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaRadioProps} from '@react-types/radio';\nimport {filterDOMProps, mergeProps, useFormReset} from '@react-aria/utils';\nimport {InputHTMLAttributes, RefObject} from 'react';\nimport {radioGroupDescriptionIds, radioGroupErrorMessageIds, radioGroupNames} from './utils';\nimport {RadioGroupState} from '@react-stately/radio';\nimport {useFocusable} from '@react-aria/focus';\nimport {usePress} from '@react-aria/interactions';\n\nexport interface RadioAria {\n /** Props for the input element. */\n inputProps: InputHTMLAttributes<HTMLInputElement>,\n /** Whether the radio is disabled. */\n isDisabled: boolean,\n /** Whether the radio is currently selected. */\n isSelected: boolean,\n /** Whether the radio is in a pressed state. */\n isPressed: boolean\n}\n\n/**\n * Provides the behavior and accessibility implementation for an individual\n * radio button in a radio group.\n * @param props - Props for the radio.\n * @param state - State for the radio group, as returned by `useRadioGroupState`.\n * @param ref - Ref to the HTML input element.\n */\nexport function useRadio(props: AriaRadioProps, state: RadioGroupState, ref: RefObject<HTMLInputElement>): RadioAria {\n let {\n value,\n children,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby\n } = props;\n\n const isDisabled = props.isDisabled || state.isDisabled;\n\n let hasChildren = children != null;\n let hasAriaLabel = ariaLabel != null || ariaLabelledby != null;\n if (!hasChildren && !hasAriaLabel) {\n console.warn('If you do not provide children, you must specify an aria-label for accessibility');\n }\n\n let checked = state.selectedValue === value;\n\n let onChange = (e) => {\n e.stopPropagation();\n state.setSelectedValue(value);\n };\n\n let {pressProps, isPressed} = usePress({\n isDisabled\n });\n\n let {focusableProps} = useFocusable(mergeProps(props, {\n onFocus: () => state.setLastFocusedValue(value)\n }), ref);\n let interactions = mergeProps(pressProps, focusableProps);\n let domProps = filterDOMProps(props, {labelable: true});\n let tabIndex = -1;\n if (state.selectedValue != null) {\n if (state.selectedValue === value) {\n tabIndex = 0;\n }\n } else if (state.lastFocusedValue === value || state.lastFocusedValue == null) {\n tabIndex = 0;\n }\n if (isDisabled) {\n tabIndex = undefined;\n }\n\n useFormReset(ref, state.selectedValue, state.setSelectedValue);\n\n return {\n inputProps: mergeProps(domProps, {\n ...interactions,\n type: 'radio',\n name: radioGroupNames.get(state),\n tabIndex,\n disabled: isDisabled,\n checked,\n value,\n onChange,\n 'aria-describedby': [\n props['aria-describedby'],\n state.isInvalid ? radioGroupErrorMessageIds.get(state) : null,\n radioGroupDescriptionIds.get(state)\n ].filter(Boolean).join(' ') || undefined\n }),\n isDisabled,\n isSelected: checked,\n isPressed\n };\n}\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {RadioGroupState} from '@react-stately/radio';\n\nexport const radioGroupNames = new WeakMap<RadioGroupState, string>();\nexport const radioGroupDescriptionIds = new WeakMap<RadioGroupState, string>();\nexport const radioGroupErrorMessageIds = new WeakMap<RadioGroupState, string>();\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaRadioGroupProps} from '@react-types/radio';\nimport {DOMAttributes} from '@react-types/shared';\nimport {filterDOMProps, mergeProps, useId} from '@react-aria/utils';\nimport {getFocusableTreeWalker} from '@react-aria/focus';\nimport {radioGroupDescriptionIds, radioGroupErrorMessageIds, radioGroupNames} from './utils';\nimport {RadioGroupState} from '@react-stately/radio';\nimport {useField} from '@react-aria/label';\nimport {useFocusWithin} from '@react-aria/interactions';\nimport {useLocale} from '@react-aria/i18n';\n\nexport interface RadioGroupAria {\n /** Props for the radio group wrapper element. */\n radioGroupProps: DOMAttributes,\n /** Props for the radio group's visible label (if any). */\n labelProps: DOMAttributes,\n /** Props for the radio group description element, if any. */\n descriptionProps: DOMAttributes,\n /** Props for the radio group error message element, if any. */\n errorMessageProps: DOMAttributes\n}\n\n/**\n * Provides the behavior and accessibility implementation for a radio group component.\n * Radio groups allow users to select a single item from a list of mutually exclusive options.\n * @param props - Props for the radio group.\n * @param state - State for the radio group, as returned by `useRadioGroupState`.\n */\nexport function useRadioGroup(props: AriaRadioGroupProps, state: RadioGroupState): RadioGroupAria {\n let {\n name,\n isReadOnly,\n isRequired,\n isDisabled,\n orientation = 'vertical'\n } = props;\n let {direction} = useLocale();\n\n let {labelProps, fieldProps, descriptionProps, errorMessageProps} = useField({\n ...props,\n // Radio group is not an HTML input element so it\n // shouldn't be labeled by a <label> element.\n labelElementType: 'span'\n });\n radioGroupDescriptionIds.set(state, descriptionProps.id);\n radioGroupErrorMessageIds.set(state, errorMessageProps.id);\n\n let domProps = filterDOMProps(props, {labelable: true});\n\n // When the radio group loses focus, reset the focusable radio to null if\n // there is no selection. This allows tabbing into the group from either\n // direction to go to the first or last radio.\n let {focusWithinProps} = useFocusWithin({\n onBlurWithin() {\n if (!state.selectedValue) {\n state.setLastFocusedValue(null);\n }\n }\n });\n\n let onKeyDown = (e) => {\n let nextDir;\n switch (e.key) {\n case 'ArrowRight':\n if (direction === 'rtl' && orientation !== 'vertical') {\n nextDir = 'prev';\n } else {\n nextDir = 'next';\n }\n break;\n case 'ArrowLeft':\n if (direction === 'rtl' && orientation !== 'vertical') {\n nextDir = 'next';\n } else {\n nextDir = 'prev';\n }\n break;\n case 'ArrowDown':\n nextDir = 'next';\n break;\n case 'ArrowUp':\n nextDir = 'prev';\n break;\n default:\n return;\n }\n e.preventDefault();\n let walker = getFocusableTreeWalker(e.currentTarget, {from: e.target});\n let nextElem;\n if (nextDir === 'next') {\n nextElem = walker.nextNode();\n if (!nextElem) {\n walker.currentNode = e.currentTarget;\n nextElem = walker.firstChild();\n }\n } else {\n nextElem = walker.previousNode();\n if (!nextElem) {\n walker.currentNode = e.currentTarget;\n nextElem = walker.lastChild();\n }\n }\n if (nextElem) {\n // Call focus on nextElem so that keyboard navigation scrolls the radio into view\n nextElem.focus();\n state.setSelectedValue(nextElem.value);\n }\n };\n\n let groupName = useId(name);\n radioGroupNames.set(state, groupName);\n\n return {\n radioGroupProps: mergeProps(domProps, {\n // https://www.w3.org/TR/wai-aria-1.2/#radiogroup\n role: 'radiogroup',\n onKeyDown,\n 'aria-invalid': state.isInvalid || undefined,\n 'aria-errormessage': props['aria-errormessage'],\n 'aria-readonly': isReadOnly || undefined,\n 'aria-required': isRequired || undefined,\n 'aria-disabled': isDisabled || undefined,\n 'aria-orientation': orientation,\n ...fieldProps,\n ...focusWithinProps\n }),\n labelProps,\n descriptionProps,\n errorMessageProps\n };\n}\n"],"names":[],"version":3,"file":"module.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-aria/radio/src/index.ts","packages/@react-aria/radio/src/useRadio.ts","packages/@react-aria/radio/src/utils.ts","packages/@react-aria/radio/src/useRadioGroup.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport {useRadio} from './useRadio';\nexport {useRadioGroup} from './useRadioGroup';\nexport type {AriaRadioGroupProps, AriaRadioProps} from '@react-types/radio';\nexport type {Orientation} from '@react-types/shared';\nexport type {RadioAria} from './useRadio';\nexport type {RadioGroupAria} from './useRadioGroup';\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaRadioProps} from '@react-types/radio';\nimport {filterDOMProps, mergeProps, useFormReset} from '@react-aria/utils';\nimport {InputHTMLAttributes, LabelHTMLAttributes, RefObject} from 'react';\nimport {radioGroupData} from './utils';\nimport {RadioGroupState} from '@react-stately/radio';\nimport {useFocusable} from '@react-aria/focus';\nimport {useFormValidation} from '@react-aria/form';\nimport {usePress} from '@react-aria/interactions';\n\nexport interface RadioAria {\n /** Props for the label wrapper element. */\n labelProps: LabelHTMLAttributes<HTMLLabelElement>,\n /** Props for the input element. */\n inputProps: InputHTMLAttributes<HTMLInputElement>,\n /** Whether the radio is disabled. */\n isDisabled: boolean,\n /** Whether the radio is currently selected. */\n isSelected: boolean,\n /** Whether the radio is in a pressed state. */\n isPressed: boolean\n}\n\n/**\n * Provides the behavior and accessibility implementation for an individual\n * radio button in a radio group.\n * @param props - Props for the radio.\n * @param state - State for the radio group, as returned by `useRadioGroupState`.\n * @param ref - Ref to the HTML input element.\n */\nexport function useRadio(props: AriaRadioProps, state: RadioGroupState, ref: RefObject<HTMLInputElement>): RadioAria {\n let {\n value,\n children,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby\n } = props;\n\n const isDisabled = props.isDisabled || state.isDisabled;\n\n let hasChildren = children != null;\n let hasAriaLabel = ariaLabel != null || ariaLabelledby != null;\n if (!hasChildren && !hasAriaLabel) {\n console.warn('If you do not provide children, you must specify an aria-label for accessibility');\n }\n\n let checked = state.selectedValue === value;\n\n let onChange = (e) => {\n e.stopPropagation();\n state.setSelectedValue(value);\n };\n\n let {pressProps, isPressed} = usePress({\n isDisabled\n });\n\n // iOS does not toggle radios if you drag off and back onto the label, so handle it ourselves.\n let {pressProps: labelProps, isPressed: isLabelPressed} = usePress({\n isDisabled,\n onPress() {\n state.setSelectedValue(value);\n }\n });\n\n let {focusableProps} = useFocusable(mergeProps(props, {\n onFocus: () => state.setLastFocusedValue(value)\n }), ref);\n let interactions = mergeProps(pressProps, focusableProps);\n let domProps = filterDOMProps(props, {labelable: true});\n let tabIndex: number | undefined = -1;\n if (state.selectedValue != null) {\n if (state.selectedValue === value) {\n tabIndex = 0;\n }\n } else if (state.lastFocusedValue === value || state.lastFocusedValue == null) {\n tabIndex = 0;\n }\n if (isDisabled) {\n tabIndex = undefined;\n }\n\n let {name, descriptionId, errorMessageId, validationBehavior} = radioGroupData.get(state)!;\n useFormReset(ref, state.selectedValue, state.setSelectedValue);\n useFormValidation({validationBehavior}, state, ref);\n\n return {\n labelProps: mergeProps(labelProps, {onClick: e => e.preventDefault()}),\n inputProps: mergeProps(domProps, {\n ...interactions,\n type: 'radio',\n name,\n tabIndex,\n disabled: isDisabled,\n required: state.isRequired && validationBehavior === 'native',\n checked,\n value,\n onChange,\n 'aria-describedby': [\n props['aria-describedby'],\n state.isInvalid ? errorMessageId : null,\n descriptionId\n ].filter(Boolean).join(' ') || undefined\n }),\n isDisabled,\n isSelected: checked,\n isPressed: isPressed || isLabelPressed\n };\n}\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {RadioGroupState} from '@react-stately/radio';\n\ninterface RadioGroupData {\n name: string,\n descriptionId: string | undefined,\n errorMessageId: string | undefined,\n validationBehavior: 'aria' | 'native'\n}\n\nexport const radioGroupData = new WeakMap<RadioGroupState, RadioGroupData>();\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaRadioGroupProps} from '@react-types/radio';\nimport {DOMAttributes, ValidationResult} from '@react-types/shared';\nimport {filterDOMProps, mergeProps, useId} from '@react-aria/utils';\nimport {getFocusableTreeWalker} from '@react-aria/focus';\nimport {radioGroupData} from './utils';\nimport {RadioGroupState} from '@react-stately/radio';\nimport {useField} from '@react-aria/label';\nimport {useFocusWithin} from '@react-aria/interactions';\nimport {useLocale} from '@react-aria/i18n';\n\nexport interface RadioGroupAria extends ValidationResult {\n /** Props for the radio group wrapper element. */\n radioGroupProps: DOMAttributes,\n /** Props for the radio group's visible label (if any). */\n labelProps: DOMAttributes,\n /** Props for the radio group description element, if any. */\n descriptionProps: DOMAttributes,\n /** Props for the radio group error message element, if any. */\n errorMessageProps: DOMAttributes\n}\n\n/**\n * Provides the behavior and accessibility implementation for a radio group component.\n * Radio groups allow users to select a single item from a list of mutually exclusive options.\n * @param props - Props for the radio group.\n * @param state - State for the radio group, as returned by `useRadioGroupState`.\n */\nexport function useRadioGroup(props: AriaRadioGroupProps, state: RadioGroupState): RadioGroupAria {\n let {\n name,\n isReadOnly,\n isRequired,\n isDisabled,\n orientation = 'vertical',\n validationBehavior = 'aria'\n } = props;\n let {direction} = useLocale();\n\n let {isInvalid, validationErrors, validationDetails} = state.displayValidation;\n let {labelProps, fieldProps, descriptionProps, errorMessageProps} = useField({\n ...props,\n // Radio group is not an HTML input element so it\n // shouldn't be labeled by a <label> element.\n labelElementType: 'span',\n isInvalid: state.isInvalid,\n errorMessage: props.errorMessage || validationErrors\n });\n\n let domProps = filterDOMProps(props, {labelable: true});\n\n // When the radio group loses focus, reset the focusable radio to null if\n // there is no selection. This allows tabbing into the group from either\n // direction to go to the first or last radio.\n let {focusWithinProps} = useFocusWithin({\n onBlurWithin(e) {\n props.onBlur?.(e);\n if (!state.selectedValue) {\n state.setLastFocusedValue(null);\n }\n },\n onFocusWithin: props.onFocus,\n onFocusWithinChange: props.onFocusChange\n });\n\n let onKeyDown = (e) => {\n let nextDir;\n switch (e.key) {\n case 'ArrowRight':\n if (direction === 'rtl' && orientation !== 'vertical') {\n nextDir = 'prev';\n } else {\n nextDir = 'next';\n }\n break;\n case 'ArrowLeft':\n if (direction === 'rtl' && orientation !== 'vertical') {\n nextDir = 'next';\n } else {\n nextDir = 'prev';\n }\n break;\n case 'ArrowDown':\n nextDir = 'next';\n break;\n case 'ArrowUp':\n nextDir = 'prev';\n break;\n default:\n return;\n }\n e.preventDefault();\n let walker = getFocusableTreeWalker(e.currentTarget, {from: e.target});\n let nextElem;\n if (nextDir === 'next') {\n nextElem = walker.nextNode();\n if (!nextElem) {\n walker.currentNode = e.currentTarget;\n nextElem = walker.firstChild();\n }\n } else {\n nextElem = walker.previousNode();\n if (!nextElem) {\n walker.currentNode = e.currentTarget;\n nextElem = walker.lastChild();\n }\n }\n if (nextElem) {\n // Call focus on nextElem so that keyboard navigation scrolls the radio into view\n nextElem.focus();\n state.setSelectedValue(nextElem.value);\n }\n };\n\n let groupName = useId(name);\n radioGroupData.set(state, {\n name: groupName,\n descriptionId: descriptionProps.id,\n errorMessageId: errorMessageProps.id,\n validationBehavior\n });\n\n return {\n radioGroupProps: mergeProps(domProps, {\n // https://www.w3.org/TR/wai-aria-1.2/#radiogroup\n role: 'radiogroup',\n onKeyDown,\n 'aria-invalid': state.isInvalid || undefined,\n 'aria-errormessage': props['aria-errormessage'],\n 'aria-readonly': isReadOnly || undefined,\n 'aria-required': isRequired || undefined,\n 'aria-disabled': isDisabled || undefined,\n 'aria-orientation': orientation,\n ...fieldProps,\n ...focusWithinProps\n }),\n labelProps,\n descriptionProps,\n errorMessageProps,\n isInvalid,\n validationErrors,\n validationDetails\n };\n}\n"],"names":[],"version":3,"file":"module.js.map"}
package/dist/types.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import { AriaRadioProps, AriaRadioGroupProps } from "@react-types/radio";
2
- import { InputHTMLAttributes, RefObject } from "react";
2
+ import { InputHTMLAttributes, LabelHTMLAttributes, RefObject } from "react";
3
3
  import { RadioGroupState } from "@react-stately/radio";
4
- import { DOMAttributes } from "@react-types/shared";
4
+ import { DOMAttributes, ValidationResult } from "@react-types/shared";
5
5
  export interface RadioAria {
6
+ /** Props for the label wrapper element. */
7
+ labelProps: LabelHTMLAttributes<HTMLLabelElement>;
6
8
  /** Props for the input element. */
7
9
  inputProps: InputHTMLAttributes<HTMLInputElement>;
8
10
  /** Whether the radio is disabled. */
@@ -20,7 +22,7 @@ export interface RadioAria {
20
22
  * @param ref - Ref to the HTML input element.
21
23
  */
22
24
  export function useRadio(props: AriaRadioProps, state: RadioGroupState, ref: RefObject<HTMLInputElement>): RadioAria;
23
- export interface RadioGroupAria {
25
+ export interface RadioGroupAria extends ValidationResult {
24
26
  /** Props for the radio group wrapper element. */
25
27
  radioGroupProps: DOMAttributes;
26
28
  /** Props for the radio group's visible label (if any). */
@@ -1 +1 @@
1
- {"mappings":";;;;ACoBA;IACE,mCAAmC;IACnC,UAAU,EAAE,oBAAoB,gBAAgB,CAAC,CAAC;IAClD,qCAAqC;IACrC,UAAU,EAAE,OAAO,CAAC;IACpB,+CAA+C;IAC/C,UAAU,EAAE,OAAO,CAAC;IACpB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;GAMG;AACH,yBAAyB,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,gBAAgB,CAAC,GAAG,SAAS,CAkEnH;AClFD;IACE,iDAAiD;IACjD,eAAe,EAAE,aAAa,CAAC;IAC/B,0DAA0D;IAC1D,UAAU,EAAE,aAAa,CAAC;IAC1B,6DAA6D;IAC7D,gBAAgB,EAAE,aAAa,CAAC;IAChC,+DAA+D;IAC/D,iBAAiB,EAAE,aAAa,CAAA;CACjC;AAED;;;;;GAKG;AACH,8BAA8B,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,eAAe,GAAG,cAAc,CAsGhG;AChID,YAAY,EAAC,mBAAmB,EAAE,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAC5E,YAAY,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC","sources":["packages/@react-aria/radio/src/packages/@react-aria/radio/src/utils.ts","packages/@react-aria/radio/src/packages/@react-aria/radio/src/useRadio.ts","packages/@react-aria/radio/src/packages/@react-aria/radio/src/useRadioGroup.ts","packages/@react-aria/radio/src/packages/@react-aria/radio/src/index.ts","packages/@react-aria/radio/src/index.ts"],"sourcesContent":[null,null,null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport {useRadio} from './useRadio';\nexport {useRadioGroup} from './useRadioGroup';\nexport type {AriaRadioGroupProps, AriaRadioProps} from '@react-types/radio';\nexport type {Orientation} from '@react-types/shared';\nexport type {RadioAria} from './useRadio';\nexport type {RadioGroupAria} from './useRadioGroup';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
1
+ {"mappings":";;;;ACqBA;IACE,2CAA2C;IAC3C,UAAU,EAAE,oBAAoB,gBAAgB,CAAC,CAAC;IAClD,mCAAmC;IACnC,UAAU,EAAE,oBAAoB,gBAAgB,CAAC,CAAC;IAClD,qCAAqC;IACrC,UAAU,EAAE,OAAO,CAAC;IACpB,+CAA+C;IAC/C,UAAU,EAAE,OAAO,CAAC;IACpB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;GAMG;AACH,yBAAyB,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,gBAAgB,CAAC,GAAG,SAAS,CA8EnH;ACjGD,+BAAgC,SAAQ,gBAAgB;IACtD,iDAAiD;IACjD,eAAe,EAAE,aAAa,CAAC;IAC/B,0DAA0D;IAC1D,UAAU,EAAE,aAAa,CAAC;IAC1B,6DAA6D;IAC7D,gBAAgB,EAAE,aAAa,CAAC;IAChC,+DAA+D;IAC/D,iBAAiB,EAAE,aAAa,CAAA;CACjC;AAED;;;;;GAKG;AACH,8BAA8B,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,eAAe,GAAG,cAAc,CAmHhG;AC7ID,YAAY,EAAC,mBAAmB,EAAE,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAC5E,YAAY,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC","sources":["packages/@react-aria/radio/src/packages/@react-aria/radio/src/utils.ts","packages/@react-aria/radio/src/packages/@react-aria/radio/src/useRadio.ts","packages/@react-aria/radio/src/packages/@react-aria/radio/src/useRadioGroup.ts","packages/@react-aria/radio/src/packages/@react-aria/radio/src/index.ts","packages/@react-aria/radio/src/index.ts"],"sourcesContent":[null,null,null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport {useRadio} from './useRadio';\nexport {useRadioGroup} from './useRadioGroup';\nexport type {AriaRadioGroupProps, AriaRadioProps} from '@react-types/radio';\nexport type {Orientation} from '@react-types/shared';\nexport type {RadioAria} from './useRadio';\nexport type {RadioGroupAria} from './useRadioGroup';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-aria/radio",
3
- "version": "3.8.2",
3
+ "version": "3.10.0",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -22,14 +22,15 @@
22
22
  "url": "https://github.com/adobe/react-spectrum"
23
23
  },
24
24
  "dependencies": {
25
- "@react-aria/focus": "^3.14.3",
26
- "@react-aria/i18n": "^3.8.4",
27
- "@react-aria/interactions": "^3.19.1",
28
- "@react-aria/label": "^3.7.2",
29
- "@react-aria/utils": "^3.21.1",
30
- "@react-stately/radio": "^3.9.1",
31
- "@react-types/radio": "^3.5.2",
32
- "@react-types/shared": "^3.21.0",
25
+ "@react-aria/focus": "^3.16.0",
26
+ "@react-aria/form": "^3.0.1",
27
+ "@react-aria/i18n": "^3.10.0",
28
+ "@react-aria/interactions": "^3.20.1",
29
+ "@react-aria/label": "^3.7.4",
30
+ "@react-aria/utils": "^3.23.0",
31
+ "@react-stately/radio": "^3.10.1",
32
+ "@react-types/radio": "^3.7.0",
33
+ "@react-types/shared": "^3.22.0",
33
34
  "@swc/helpers": "^0.5.0"
34
35
  },
35
36
  "peerDependencies": {
@@ -38,5 +39,5 @@
38
39
  "publishConfig": {
39
40
  "access": "public"
40
41
  },
41
- "gitHead": "3ecf62dcceea437cb12df1851636dd491bb6591c"
42
+ "gitHead": "86b38c87868ce7f262e0df905e5ac4eb2653791d"
42
43
  }
package/src/useRadio.ts CHANGED
@@ -12,13 +12,16 @@
12
12
 
13
13
  import {AriaRadioProps} from '@react-types/radio';
14
14
  import {filterDOMProps, mergeProps, useFormReset} from '@react-aria/utils';
15
- import {InputHTMLAttributes, RefObject} from 'react';
16
- import {radioGroupDescriptionIds, radioGroupErrorMessageIds, radioGroupNames} from './utils';
15
+ import {InputHTMLAttributes, LabelHTMLAttributes, RefObject} from 'react';
16
+ import {radioGroupData} from './utils';
17
17
  import {RadioGroupState} from '@react-stately/radio';
18
18
  import {useFocusable} from '@react-aria/focus';
19
+ import {useFormValidation} from '@react-aria/form';
19
20
  import {usePress} from '@react-aria/interactions';
20
21
 
21
22
  export interface RadioAria {
23
+ /** Props for the label wrapper element. */
24
+ labelProps: LabelHTMLAttributes<HTMLLabelElement>,
22
25
  /** Props for the input element. */
23
26
  inputProps: InputHTMLAttributes<HTMLInputElement>,
24
27
  /** Whether the radio is disabled. */
@@ -63,12 +66,20 @@ export function useRadio(props: AriaRadioProps, state: RadioGroupState, ref: Ref
63
66
  isDisabled
64
67
  });
65
68
 
69
+ // iOS does not toggle radios if you drag off and back onto the label, so handle it ourselves.
70
+ let {pressProps: labelProps, isPressed: isLabelPressed} = usePress({
71
+ isDisabled,
72
+ onPress() {
73
+ state.setSelectedValue(value);
74
+ }
75
+ });
76
+
66
77
  let {focusableProps} = useFocusable(mergeProps(props, {
67
78
  onFocus: () => state.setLastFocusedValue(value)
68
79
  }), ref);
69
80
  let interactions = mergeProps(pressProps, focusableProps);
70
81
  let domProps = filterDOMProps(props, {labelable: true});
71
- let tabIndex = -1;
82
+ let tabIndex: number | undefined = -1;
72
83
  if (state.selectedValue != null) {
73
84
  if (state.selectedValue === value) {
74
85
  tabIndex = 0;
@@ -80,26 +91,30 @@ export function useRadio(props: AriaRadioProps, state: RadioGroupState, ref: Ref
80
91
  tabIndex = undefined;
81
92
  }
82
93
 
94
+ let {name, descriptionId, errorMessageId, validationBehavior} = radioGroupData.get(state)!;
83
95
  useFormReset(ref, state.selectedValue, state.setSelectedValue);
96
+ useFormValidation({validationBehavior}, state, ref);
84
97
 
85
98
  return {
99
+ labelProps: mergeProps(labelProps, {onClick: e => e.preventDefault()}),
86
100
  inputProps: mergeProps(domProps, {
87
101
  ...interactions,
88
102
  type: 'radio',
89
- name: radioGroupNames.get(state),
103
+ name,
90
104
  tabIndex,
91
105
  disabled: isDisabled,
106
+ required: state.isRequired && validationBehavior === 'native',
92
107
  checked,
93
108
  value,
94
109
  onChange,
95
110
  'aria-describedby': [
96
111
  props['aria-describedby'],
97
- state.isInvalid ? radioGroupErrorMessageIds.get(state) : null,
98
- radioGroupDescriptionIds.get(state)
112
+ state.isInvalid ? errorMessageId : null,
113
+ descriptionId
99
114
  ].filter(Boolean).join(' ') || undefined
100
115
  }),
101
116
  isDisabled,
102
117
  isSelected: checked,
103
- isPressed
118
+ isPressed: isPressed || isLabelPressed
104
119
  };
105
120
  }
@@ -11,16 +11,16 @@
11
11
  */
12
12
 
13
13
  import {AriaRadioGroupProps} from '@react-types/radio';
14
- import {DOMAttributes} from '@react-types/shared';
14
+ import {DOMAttributes, ValidationResult} from '@react-types/shared';
15
15
  import {filterDOMProps, mergeProps, useId} from '@react-aria/utils';
16
16
  import {getFocusableTreeWalker} from '@react-aria/focus';
17
- import {radioGroupDescriptionIds, radioGroupErrorMessageIds, radioGroupNames} from './utils';
17
+ import {radioGroupData} from './utils';
18
18
  import {RadioGroupState} from '@react-stately/radio';
19
19
  import {useField} from '@react-aria/label';
20
20
  import {useFocusWithin} from '@react-aria/interactions';
21
21
  import {useLocale} from '@react-aria/i18n';
22
22
 
23
- export interface RadioGroupAria {
23
+ export interface RadioGroupAria extends ValidationResult {
24
24
  /** Props for the radio group wrapper element. */
25
25
  radioGroupProps: DOMAttributes,
26
26
  /** Props for the radio group's visible label (if any). */
@@ -43,18 +43,20 @@ export function useRadioGroup(props: AriaRadioGroupProps, state: RadioGroupState
43
43
  isReadOnly,
44
44
  isRequired,
45
45
  isDisabled,
46
- orientation = 'vertical'
46
+ orientation = 'vertical',
47
+ validationBehavior = 'aria'
47
48
  } = props;
48
49
  let {direction} = useLocale();
49
50
 
51
+ let {isInvalid, validationErrors, validationDetails} = state.displayValidation;
50
52
  let {labelProps, fieldProps, descriptionProps, errorMessageProps} = useField({
51
53
  ...props,
52
54
  // Radio group is not an HTML input element so it
53
55
  // shouldn't be labeled by a <label> element.
54
- labelElementType: 'span'
56
+ labelElementType: 'span',
57
+ isInvalid: state.isInvalid,
58
+ errorMessage: props.errorMessage || validationErrors
55
59
  });
56
- radioGroupDescriptionIds.set(state, descriptionProps.id);
57
- radioGroupErrorMessageIds.set(state, errorMessageProps.id);
58
60
 
59
61
  let domProps = filterDOMProps(props, {labelable: true});
60
62
 
@@ -62,11 +64,14 @@ export function useRadioGroup(props: AriaRadioGroupProps, state: RadioGroupState
62
64
  // there is no selection. This allows tabbing into the group from either
63
65
  // direction to go to the first or last radio.
64
66
  let {focusWithinProps} = useFocusWithin({
65
- onBlurWithin() {
67
+ onBlurWithin(e) {
68
+ props.onBlur?.(e);
66
69
  if (!state.selectedValue) {
67
70
  state.setLastFocusedValue(null);
68
71
  }
69
- }
72
+ },
73
+ onFocusWithin: props.onFocus,
74
+ onFocusWithinChange: props.onFocusChange
70
75
  });
71
76
 
72
77
  let onKeyDown = (e) => {
@@ -119,7 +124,12 @@ export function useRadioGroup(props: AriaRadioGroupProps, state: RadioGroupState
119
124
  };
120
125
 
121
126
  let groupName = useId(name);
122
- radioGroupNames.set(state, groupName);
127
+ radioGroupData.set(state, {
128
+ name: groupName,
129
+ descriptionId: descriptionProps.id,
130
+ errorMessageId: errorMessageProps.id,
131
+ validationBehavior
132
+ });
123
133
 
124
134
  return {
125
135
  radioGroupProps: mergeProps(domProps, {
@@ -137,6 +147,9 @@ export function useRadioGroup(props: AriaRadioGroupProps, state: RadioGroupState
137
147
  }),
138
148
  labelProps,
139
149
  descriptionProps,
140
- errorMessageProps
150
+ errorMessageProps,
151
+ isInvalid,
152
+ validationErrors,
153
+ validationDetails
141
154
  };
142
155
  }
package/src/utils.ts CHANGED
@@ -12,6 +12,11 @@
12
12
 
13
13
  import {RadioGroupState} from '@react-stately/radio';
14
14
 
15
- export const radioGroupNames = new WeakMap<RadioGroupState, string>();
16
- export const radioGroupDescriptionIds = new WeakMap<RadioGroupState, string>();
17
- export const radioGroupErrorMessageIds = new WeakMap<RadioGroupState, string>();
15
+ interface RadioGroupData {
16
+ name: string,
17
+ descriptionId: string | undefined,
18
+ errorMessageId: string | undefined,
19
+ validationBehavior: 'aria' | 'native'
20
+ }
21
+
22
+ export const radioGroupData = new WeakMap<RadioGroupState, RadioGroupData>();