@ankhorage/zora 4.4.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +1 -1
  3. package/dist/components/radio/RadioGroup.d.ts +1 -3
  4. package/dist/components/radio/RadioGroup.d.ts.map +1 -1
  5. package/dist/components/radio/RadioGroup.js +52 -40
  6. package/dist/components/radio/RadioGroup.js.map +1 -1
  7. package/dist/components/radio/RadioOptionControl.d.ts +15 -0
  8. package/dist/components/radio/RadioOptionControl.d.ts.map +1 -0
  9. package/dist/components/radio/RadioOptionControl.js +105 -0
  10. package/dist/components/radio/RadioOptionControl.js.map +1 -0
  11. package/dist/components/radio/handleRadioOptionKeyDown.d.ts +13 -0
  12. package/dist/components/radio/handleRadioOptionKeyDown.d.ts.map +1 -0
  13. package/dist/components/radio/handleRadioOptionKeyDown.js +22 -0
  14. package/dist/components/radio/handleRadioOptionKeyDown.js.map +1 -0
  15. package/dist/components/radio/meta.d.ts +38 -3
  16. package/dist/components/radio/meta.d.ts.map +1 -1
  17. package/dist/components/radio/meta.js +28 -3
  18. package/dist/components/radio/meta.js.map +1 -1
  19. package/dist/components/radio/resolveRadioOptionColors.d.ts +10 -0
  20. package/dist/components/radio/resolveRadioOptionColors.d.ts.map +1 -0
  21. package/dist/components/radio/resolveRadioOptionColors.js +27 -0
  22. package/dist/components/radio/resolveRadioOptionColors.js.map +1 -0
  23. package/dist/components/radio/types.d.ts +12 -2
  24. package/dist/components/radio/types.d.ts.map +1 -1
  25. package/dist/components/radio/types.js.map +1 -1
  26. package/dist/constants/keyboard.d.ts +3 -0
  27. package/dist/constants/keyboard.d.ts.map +1 -0
  28. package/dist/constants/keyboard.js +8 -0
  29. package/dist/constants/keyboard.js.map +1 -0
  30. package/dist/index.d.ts +0 -12
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +0 -6
  33. package/dist/index.js.map +1 -1
  34. package/dist/metadata/componentMeta.d.ts.map +1 -1
  35. package/dist/metadata/componentMeta.js +0 -12
  36. package/dist/metadata/componentMeta.js.map +1 -1
  37. package/dist/registry.d.ts.map +1 -1
  38. package/dist/registry.js +0 -12
  39. package/dist/registry.js.map +1 -1
  40. package/package.json +1 -1
  41. package/src/audit.test.ts +0 -29
  42. package/src/components/radio/RadioGroup.test.ts +13 -9
  43. package/src/components/radio/RadioGroup.tsx +85 -111
  44. package/src/components/radio/RadioOptionControl.tsx +192 -0
  45. package/src/components/radio/handleRadioOptionKeyDown.test.ts +47 -0
  46. package/src/components/radio/handleRadioOptionKeyDown.ts +37 -0
  47. package/src/components/radio/meta.ts +28 -3
  48. package/src/components/radio/resolveRadioOptionColors.test.ts +29 -0
  49. package/src/components/radio/resolveRadioOptionColors.ts +37 -0
  50. package/src/components/radio/types.ts +10 -2
  51. package/src/constants/keyboard.ts +7 -0
  52. package/src/index.ts +0 -23
  53. package/src/interactionPolicy.test.ts +0 -17
  54. package/src/metadata/componentMeta.test.ts +1 -0
  55. package/src/metadata/componentMeta.ts +0 -12
  56. package/src/registry.ts +0 -12
  57. package/src/showcaseCoverage.test.ts +0 -6
  58. package/src/theme/themeScopeStructure.test.ts +0 -4
  59. package/dist/components/drawer/Drawer.d.ts +0 -7
  60. package/dist/components/drawer/Drawer.d.ts.map +0 -1
  61. package/dist/components/drawer/Drawer.js +0 -36
  62. package/dist/components/drawer/Drawer.js.map +0 -1
  63. package/dist/components/drawer/index.d.ts +0 -3
  64. package/dist/components/drawer/index.d.ts.map +0 -1
  65. package/dist/components/drawer/index.js +0 -2
  66. package/dist/components/drawer/index.js.map +0 -1
  67. package/dist/components/drawer/meta.d.ts +0 -9
  68. package/dist/components/drawer/meta.d.ts.map +0 -1
  69. package/dist/components/drawer/meta.js +0 -9
  70. package/dist/components/drawer/meta.js.map +0 -1
  71. package/dist/components/drawer/types.d.ts +0 -10
  72. package/dist/components/drawer/types.d.ts.map +0 -1
  73. package/dist/components/drawer/types.js +0 -2
  74. package/dist/components/drawer/types.js.map +0 -1
  75. package/dist/components/navigation-item/NavigationItem.d.ts +0 -7
  76. package/dist/components/navigation-item/NavigationItem.d.ts.map +0 -1
  77. package/dist/components/navigation-item/NavigationItem.js +0 -21
  78. package/dist/components/navigation-item/NavigationItem.js.map +0 -1
  79. package/dist/components/navigation-item/index.d.ts +0 -3
  80. package/dist/components/navigation-item/index.d.ts.map +0 -1
  81. package/dist/components/navigation-item/index.js +0 -2
  82. package/dist/components/navigation-item/index.js.map +0 -1
  83. package/dist/components/navigation-item/meta.d.ts +0 -9
  84. package/dist/components/navigation-item/meta.d.ts.map +0 -1
  85. package/dist/components/navigation-item/meta.js +0 -9
  86. package/dist/components/navigation-item/meta.js.map +0 -1
  87. package/dist/components/navigation-item/types.d.ts +0 -23
  88. package/dist/components/navigation-item/types.d.ts.map +0 -1
  89. package/dist/components/navigation-item/types.js +0 -2
  90. package/dist/components/navigation-item/types.js.map +0 -1
  91. package/dist/components/navigation-list/NavigationList.d.ts +0 -7
  92. package/dist/components/navigation-list/NavigationList.d.ts.map +0 -1
  93. package/dist/components/navigation-list/NavigationList.js +0 -29
  94. package/dist/components/navigation-list/NavigationList.js.map +0 -1
  95. package/dist/components/navigation-list/index.d.ts +0 -3
  96. package/dist/components/navigation-list/index.d.ts.map +0 -1
  97. package/dist/components/navigation-list/index.js +0 -2
  98. package/dist/components/navigation-list/index.js.map +0 -1
  99. package/dist/components/navigation-list/meta.d.ts +0 -9
  100. package/dist/components/navigation-list/meta.d.ts.map +0 -1
  101. package/dist/components/navigation-list/meta.js +0 -9
  102. package/dist/components/navigation-list/meta.js.map +0 -1
  103. package/dist/components/navigation-list/types.d.ts +0 -15
  104. package/dist/components/navigation-list/types.d.ts.map +0 -1
  105. package/dist/components/navigation-list/types.js +0 -2
  106. package/dist/components/navigation-list/types.js.map +0 -1
  107. package/dist/internal/resolveZoraNavigationItems.d.ts +0 -65
  108. package/dist/internal/resolveZoraNavigationItems.d.ts.map +0 -1
  109. package/dist/internal/resolveZoraNavigationItems.js +0 -56
  110. package/dist/internal/resolveZoraNavigationItems.js.map +0 -1
  111. package/dist/patterns/responsive-panel/ResponsivePanel.d.ts +0 -16
  112. package/dist/patterns/responsive-panel/ResponsivePanel.d.ts.map +0 -1
  113. package/dist/patterns/responsive-panel/ResponsivePanel.js +0 -101
  114. package/dist/patterns/responsive-panel/ResponsivePanel.js.map +0 -1
  115. package/dist/patterns/responsive-panel/index.d.ts +0 -3
  116. package/dist/patterns/responsive-panel/index.d.ts.map +0 -1
  117. package/dist/patterns/responsive-panel/index.js +0 -3
  118. package/dist/patterns/responsive-panel/index.js.map +0 -1
  119. package/dist/patterns/responsive-panel/meta.d.ts +0 -9
  120. package/dist/patterns/responsive-panel/meta.d.ts.map +0 -1
  121. package/dist/patterns/responsive-panel/meta.js +0 -9
  122. package/dist/patterns/responsive-panel/meta.js.map +0 -1
  123. package/dist/patterns/responsive-panel/types.d.ts +0 -23
  124. package/dist/patterns/responsive-panel/types.d.ts.map +0 -1
  125. package/dist/patterns/responsive-panel/types.js +0 -2
  126. package/dist/patterns/responsive-panel/types.js.map +0 -1
  127. package/dist/patterns/zora-drawer-content/ZoraDrawerContent.d.ts +0 -9
  128. package/dist/patterns/zora-drawer-content/ZoraDrawerContent.d.ts.map +0 -1
  129. package/dist/patterns/zora-drawer-content/ZoraDrawerContent.js +0 -31
  130. package/dist/patterns/zora-drawer-content/ZoraDrawerContent.js.map +0 -1
  131. package/dist/patterns/zora-drawer-content/index.d.ts +0 -3
  132. package/dist/patterns/zora-drawer-content/index.d.ts.map +0 -1
  133. package/dist/patterns/zora-drawer-content/index.js +0 -2
  134. package/dist/patterns/zora-drawer-content/index.js.map +0 -1
  135. package/dist/patterns/zora-drawer-content/meta.d.ts +0 -9
  136. package/dist/patterns/zora-drawer-content/meta.d.ts.map +0 -1
  137. package/dist/patterns/zora-drawer-content/meta.js +0 -9
  138. package/dist/patterns/zora-drawer-content/meta.js.map +0 -1
  139. package/dist/patterns/zora-drawer-content/types.d.ts +0 -15
  140. package/dist/patterns/zora-drawer-content/types.d.ts.map +0 -1
  141. package/dist/patterns/zora-drawer-content/types.js +0 -2
  142. package/dist/patterns/zora-drawer-content/types.js.map +0 -1
  143. package/dist/patterns/zora-tab-bar/ZoraTabBar.d.ts +0 -9
  144. package/dist/patterns/zora-tab-bar/ZoraTabBar.d.ts.map +0 -1
  145. package/dist/patterns/zora-tab-bar/ZoraTabBar.js +0 -89
  146. package/dist/patterns/zora-tab-bar/ZoraTabBar.js.map +0 -1
  147. package/dist/patterns/zora-tab-bar/index.d.ts +0 -3
  148. package/dist/patterns/zora-tab-bar/index.d.ts.map +0 -1
  149. package/dist/patterns/zora-tab-bar/index.js +0 -2
  150. package/dist/patterns/zora-tab-bar/index.js.map +0 -1
  151. package/dist/patterns/zora-tab-bar/meta.d.ts +0 -9
  152. package/dist/patterns/zora-tab-bar/meta.d.ts.map +0 -1
  153. package/dist/patterns/zora-tab-bar/meta.js +0 -9
  154. package/dist/patterns/zora-tab-bar/meta.js.map +0 -1
  155. package/dist/patterns/zora-tab-bar/types.d.ts +0 -19
  156. package/dist/patterns/zora-tab-bar/types.d.ts.map +0 -1
  157. package/dist/patterns/zora-tab-bar/types.js +0 -2
  158. package/dist/patterns/zora-tab-bar/types.js.map +0 -1
  159. package/src/components/drawer/Drawer.tsx +0 -59
  160. package/src/components/drawer/index.ts +0 -2
  161. package/src/components/drawer/meta.ts +0 -10
  162. package/src/components/drawer/types.ts +0 -17
  163. package/src/components/navigation-item/NavigationItem.tsx +0 -41
  164. package/src/components/navigation-item/index.ts +0 -6
  165. package/src/components/navigation-item/meta.ts +0 -10
  166. package/src/components/navigation-item/types.ts +0 -26
  167. package/src/components/navigation-list/NavigationList.tsx +0 -68
  168. package/src/components/navigation-list/index.ts +0 -2
  169. package/src/components/navigation-list/meta.ts +0 -10
  170. package/src/components/navigation-list/types.ts +0 -17
  171. package/src/internal/resolveZoraNavigationItems.test.ts +0 -174
  172. package/src/internal/resolveZoraNavigationItems.ts +0 -157
  173. package/src/navigationExports.test.ts +0 -15
  174. package/src/patterns/responsive-panel/ResponsivePanel.tsx +0 -172
  175. package/src/patterns/responsive-panel/index.ts +0 -2
  176. package/src/patterns/responsive-panel/meta.ts +0 -10
  177. package/src/patterns/responsive-panel/types.ts +0 -25
  178. package/src/patterns/zora-drawer-content/ZoraDrawerContent.tsx +0 -60
  179. package/src/patterns/zora-drawer-content/index.ts +0 -2
  180. package/src/patterns/zora-drawer-content/meta.ts +0 -10
  181. package/src/patterns/zora-drawer-content/types.ts +0 -20
  182. package/src/patterns/zora-tab-bar/ZoraTabBar.tsx +0 -157
  183. package/src/patterns/zora-tab-bar/index.ts +0 -2
  184. package/src/patterns/zora-tab-bar/meta.ts +0 -10
  185. package/src/patterns/zora-tab-bar/types.ts +0 -18
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 44914bc: Remove obsolete navigation and UI chrome APIs now owned by `@ankhorage/navigator`: `Drawer`,
8
+ `NavigationItem`, `NavigationList`, `ResponsivePanel`, `ZoraDrawerContent`, and `ZoraTabBar`.
9
+
10
+ ## 4.5.0
11
+
12
+ ### Minor Changes
13
+
14
+ - f53e341: Add SVG icon options, equal-width columns and content orientation to RadioGroup. Support local initial selection through defaultValue, accessible icon radio controls on web and native, and a directly insertable Radio button group blueprint for Studio.
15
+
3
16
  ## 4.4.1
4
17
 
5
18
  ### Patch Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # ZORA
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v4.2.2](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v4.5.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.
9
9
 
@@ -1,7 +1,5 @@
1
1
  import React from 'react';
2
2
  import type { RadioGroupProps } from './types';
3
- /***
4
- * Renders a group of radio options for selecting a single value.
5
- */
3
+ /*** Present one controlled single-choice group as inline radios or icon radio options. */
6
4
  export declare const RadioGroup: <TValue extends string>(props: RadioGroupProps<TValue>) => React.ReactElement | null;
7
5
  //# sourceMappingURL=RadioGroup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RadioGroup.d.ts","sourceRoot":"","sources":["../../../src/components/radio/RadioGroup.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,KAAK,EAAoB,eAAe,EAAE,MAAM,SAAS,CAAC;AA6DjE;;GAEG;AACH,eAAO,MAAM,UAAU,GA3DE,MAAM,SAAS,MAAM,8DA2De,CAAC"}
1
+ {"version":3,"file":"RadioGroup.d.ts","sourceRoot":"","sources":["../../../src/components/radio/RadioGroup.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,0FAA0F;AAC1F,eAAO,MAAM,UAAU,GAGE,MAAM,SAAS,MAAM,8DAHe,CAAC"}
@@ -1,58 +1,70 @@
1
- import { Radio, useTheme } from '@ankhorage/surface';
1
+ import { Radio } from '@ankhorage/surface';
2
2
  import React from 'react';
3
- import { View } from 'react-native';
3
+ import { StyleSheet, View } from 'react-native';
4
4
  import { Stack } from '../../foundation';
5
5
  import { useZoraThemeRecipe } from '../../theme/useZoraThemeRecipe';
6
6
  import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
7
7
  import { Text } from '../text';
8
+ import { RadioOptionControl } from './RadioOptionControl';
8
9
  import { resolveRadioGroupThemeRecipe } from './resolveRadioGroupThemeRecipe';
9
- /***
10
- * Resolves the themed radio-group presentation within the active ZORA scope.
11
- */
12
- function RadioGroupInner({ themeId: _themeId, mode: _mode, value, onValueChange, options, orientation = 'vertical', gap, presentation = 'inline', color, size, invalid = false, readOnly = false, disabled = false, testID, interactionPolicy, }) {
13
- const isHorizontal = orientation === 'horizontal';
10
+ /*** Present one controlled single-choice group as inline radios or icon radio options. */
11
+ export const RadioGroup = withZoraThemeScope(RadioGroupInner);
12
+ /*** Resolve shared presentation once and preserve a single interaction boundary per option. */
13
+ function RadioGroupInner({ themeId: _themeId, mode: _mode, ...props }) {
14
+ const [localValue, setLocalValue] = React.useState(props.defaultValue);
15
+ const onValueChange = (next) => {
16
+ if (props.value === undefined)
17
+ setLocalValue(next);
18
+ props.onValueChange?.(next);
19
+ };
20
+ const selectedProps = { ...props, value: props.value ?? localValue, onValueChange };
14
21
  const themeFields = useZoraThemeRecipe('RadioGroup');
15
- const recipe = resolveRadioGroupThemeRecipe({ gap, color, size, themeFields });
16
- return (<View testID={testID} accessibilityRole="radiogroup" style={{
17
- flexDirection: isHorizontal ? 'row' : 'column',
18
- flexWrap: isHorizontal ? 'wrap' : 'nowrap',
19
- }}>
20
- <Stack direction={isHorizontal ? 'row' : 'column'} gap={recipe.gap} wrap={isHorizontal ? 'wrap' : 'nowrap'}>
21
- {options.map((option) => (<RadioGroupItem key={option.value} option={option} checked={value === option.value} disabled={disabled || option.disabled === true} invalid={invalid} readOnly={readOnly} size={recipe.size} color={recipe.color} orientation={orientation} presentation={presentation} onSelect={onValueChange} interactionPolicy={interactionPolicy}/>))}
22
+ const recipe = resolveRadioGroupThemeRecipe({ ...props, themeFields });
23
+ if (props.presentation !== 'card')
24
+ return <RadioGroupInline {...selectedProps} {...recipe}/>;
25
+ const columns = props.columns ?? (props.orientation === 'horizontal' ? Math.max(1, props.options.length) : 1);
26
+ const rows = Array.from({ length: Math.ceil(props.options.length / columns) }, (_, index) => props.options.slice(index * columns, (index + 1) * columns));
27
+ return (<View testID={props.testID} accessibilityRole="radiogroup">
28
+ <Stack gap={recipe.gap}>
29
+ {rows.map((options, index) => (<Stack key={index} direction="row" gap={recipe.gap}>
30
+ {options.map((option) => (<View key={option.value} style={styles.option}>
31
+ <RadioGroupItem {...selectedProps} {...recipe} option={option}/>
32
+ </View>))}
33
+ {Array.from({ length: columns - options.length }, (_, slot) => (<View key={`empty-${slot}`} style={styles.option}/>))}
34
+ </Stack>))}
22
35
  </Stack>
23
36
  </View>);
24
37
  }
25
- /***
26
- * Renders a group of radio options for selecting a single value.
27
- */
28
- export const RadioGroup = withZoraThemeScope(RadioGroupInner);
29
- /***
30
- * Renders one option through the single Surface Radio interaction boundary.
31
- */
32
- function RadioGroupItem({ option, checked, disabled, invalid, readOnly, size, color, orientation, presentation, onSelect, interactionPolicy, }) {
33
- const { theme } = useTheme();
34
- const passive = interactionPolicy === 'passive';
35
- const isCard = presentation === 'card';
36
- return (<Radio interactionPolicy={interactionPolicy} checked={checked} disabled={disabled} invalid={invalid} readOnly={readOnly} size={size} color={color} testID={option.testID} bg={isCard
37
- ? checked
38
- ? theme.semantics.selection.background
39
- : theme.semantics.surface.default
40
- : undefined} borderColor={isCard
41
- ? checked
42
- ? theme.semantics.selection.border
43
- : theme.semantics.border.default
44
- : undefined} borderWidth={isCard ? 1 : undefined} p={isCard ? 'm' : undefined} radius={isCard ? 'l' : undefined} width={isCard && orientation === 'vertical' ? '100%' : undefined} onCheckedChange={(nextChecked) => {
45
- if (passive)
46
- return;
47
- if (nextChecked)
48
- onSelect(option.value);
49
- }}>
38
+ /*** Preserve ordinary radio wrapping independently of the icon-option grid. */
39
+ function RadioGroupInline(props) {
40
+ return (<View testID={props.testID} accessibilityRole="radiogroup">
41
+ <Stack direction={props.orientation === 'horizontal' ? 'row' : 'column'} gap={props.gap} wrap="wrap">
42
+ {props.options.map((option) => (<RadioGroupItem key={option.value} {...props} option={option}/>))}
43
+ </Stack>
44
+ </View>);
45
+ }
46
+ /*** Delegate icon options to their composed radio boundary and ordinary options to Surface Radio. */
47
+ function RadioGroupItem(props) {
48
+ const { option, value, onValueChange, interactionPolicy, color, size } = props;
49
+ const checked = value === option.value;
50
+ const inactive = props.disabled === true || option.disabled === true;
51
+ const readOnly = props.readOnly === true;
52
+ const invalid = props.invalid === true;
53
+ const onSelect = () => {
54
+ if (!inactive && !readOnly && interactionPolicy !== 'passive' && !checked)
55
+ onValueChange?.(option.value);
56
+ };
57
+ if (props.presentation === 'card') {
58
+ return (<RadioOptionControl {...props} checked={checked} disabled={inactive} readOnly={readOnly} invalid={invalid} layout={props.contentOrientation ?? 'horizontal'} onSelect={onSelect}/>);
59
+ }
60
+ return (<Radio checked={checked} disabled={inactive} readOnly={readOnly} invalid={invalid} interactionPolicy={interactionPolicy} color={color} size={size} testID={option.testID} onCheckedChange={onSelect}>
50
61
  <Stack gap="xs">
51
- <Text weight={isCard ? 'semiBold' : undefined}>{option.label}</Text>
62
+ <Text>{option.label}</Text>
52
63
  {option.description ? (<Text emphasis="muted" variant="caption">
53
64
  {option.description}
54
65
  </Text>) : null}
55
66
  </Stack>
56
67
  </Radio>);
57
68
  }
69
+ const styles = StyleSheet.create({ option: { flex: 1, minWidth: 0 } });
58
70
  //# sourceMappingURL=RadioGroup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RadioGroup.js","sourceRoot":"","sources":["../../../src/components/radio/RadioGroup.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Radio, useTheme } from '@ankhorage/surface';\nimport React from 'react';\nimport { View } from 'react-native';\n\nimport { Stack } from '../../foundation';\nimport { useZoraThemeRecipe } from '../../theme/useZoraThemeRecipe';\nimport { withZoraThemeScope } from '../../theme/withZoraThemeScope';\nimport { Text } from '../text';\nimport { resolveRadioGroupThemeRecipe } from './resolveRadioGroupThemeRecipe';\nimport type { RadioGroupOption, RadioGroupProps } from './types';\n\n/***\n * Resolves the themed radio-group presentation within the active ZORA scope.\n */\nfunction RadioGroupInner<TValue extends string>({\n themeId: _themeId,\n mode: _mode,\n value,\n onValueChange,\n options,\n orientation = 'vertical',\n gap,\n presentation = 'inline',\n color,\n size,\n invalid = false,\n readOnly = false,\n disabled = false,\n testID,\n interactionPolicy,\n}: RadioGroupProps<TValue>) {\n const isHorizontal = orientation === 'horizontal';\n const themeFields = useZoraThemeRecipe('RadioGroup');\n const recipe = resolveRadioGroupThemeRecipe({ gap, color, size, themeFields });\n\n return (\n <View\n testID={testID}\n accessibilityRole=\"radiogroup\"\n style={{\n flexDirection: isHorizontal ? 'row' : 'column',\n flexWrap: isHorizontal ? 'wrap' : 'nowrap',\n }}\n >\n <Stack\n direction={isHorizontal ? 'row' : 'column'}\n gap={recipe.gap}\n wrap={isHorizontal ? 'wrap' : 'nowrap'}\n >\n {options.map((option) => (\n <RadioGroupItem\n key={option.value}\n option={option}\n checked={value === option.value}\n disabled={disabled || option.disabled === true}\n invalid={invalid}\n readOnly={readOnly}\n size={recipe.size}\n color={recipe.color}\n orientation={orientation}\n presentation={presentation}\n onSelect={onValueChange}\n interactionPolicy={interactionPolicy}\n />\n ))}\n </Stack>\n </View>\n );\n}\n\n/***\n * Renders a group of radio options for selecting a single value.\n */\nexport const RadioGroup = withZoraThemeScope(RadioGroupInner);\n\n/***\n * Renders one option through the single Surface Radio interaction boundary.\n */\nfunction RadioGroupItem<TValue extends string>({\n option,\n checked,\n disabled,\n invalid,\n readOnly,\n size,\n color,\n orientation,\n presentation,\n onSelect,\n interactionPolicy,\n}: {\n option: RadioGroupOption<TValue>;\n checked: boolean;\n disabled: boolean;\n invalid: boolean;\n readOnly: boolean;\n size: NonNullable<RadioGroupProps<TValue>['size']>;\n color: NonNullable<RadioGroupProps<TValue>['color']>;\n orientation: NonNullable<RadioGroupProps<TValue>['orientation']>;\n presentation: NonNullable<RadioGroupProps<TValue>['presentation']>;\n onSelect: (value: TValue) => void;\n interactionPolicy: RadioGroupProps<TValue>['interactionPolicy'];\n}) {\n const { theme } = useTheme();\n const passive = interactionPolicy === 'passive';\n const isCard = presentation === 'card';\n\n return (\n <Radio\n interactionPolicy={interactionPolicy}\n checked={checked}\n disabled={disabled}\n invalid={invalid}\n readOnly={readOnly}\n size={size}\n color={color}\n testID={option.testID}\n bg={\n isCard\n ? checked\n ? theme.semantics.selection.background\n : theme.semantics.surface.default\n : undefined\n }\n borderColor={\n isCard\n ? checked\n ? theme.semantics.selection.border\n : theme.semantics.border.default\n : undefined\n }\n borderWidth={isCard ? 1 : undefined}\n p={isCard ? 'm' : undefined}\n radius={isCard ? 'l' : undefined}\n width={isCard && orientation === 'vertical' ? '100%' : undefined}\n onCheckedChange={(nextChecked) => {\n if (passive) return;\n if (nextChecked) onSelect(option.value);\n }}\n >\n <Stack gap=\"xs\">\n <Text weight={isCard ? 'semiBold' : undefined}>{option.label}</Text>\n {option.description ? (\n <Text emphasis=\"muted\" variant=\"caption\">\n {option.description}\n </Text>\n ) : null}\n </Stack>\n </Radio>\n );\n}\n"]}
1
+ {"version":3,"file":"RadioGroup.js","sourceRoot":"","sources":["../../../src/components/radio/RadioGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAG9E,0FAA0F;AAC1F,MAAM,CAAC,MAAM,UAAU,GAAG,kBAAkB,CAAC,eAAe,CAAC,CAAC;AAE9D,+FAA+F;AAC/F,SAAS,eAAe,CAAwB,EAC9C,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAE,KAAK,EACX,GAAG,KAAK,EACgB;IACxB,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACvE,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,EAAE;QACrC,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,aAAa,CAAC,IAAI,CAAC,CAAC;QACnD,KAAK,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC;IACF,MAAM,aAAa,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,UAAU,EAAE,aAAa,EAAE,CAAC;IACpF,MAAM,WAAW,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,4BAA4B,CAAC,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;IACvE,IAAI,KAAK,CAAC,YAAY,KAAK,MAAM;QAAE,OAAO,CAAC,gBAAgB,CAAC,IAAI,aAAa,CAAC,CAAC,IAAI,MAAM,CAAC,EAAG,CAAC;IAC9F,MAAM,OAAO,GACX,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChG,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAC1F,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,OAAO,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAC5D,CAAC;IACF,OAAO,CACL,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,YAAY,CACxD;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACrB;QAAA,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAC5B,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD;YAAA,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACvB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAC5C;gBAAA,CAAC,cAAc,CAAC,IAAI,aAAa,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAChE;cAAA,EAAE,IAAI,CAAC,CACR,CAAC,CACF;YAAA,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAC7D,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAG,CACrD,CAAC,CACJ;UAAA,EAAE,KAAK,CAAC,CACT,CAAC,CACJ;MAAA,EAAE,KAAK,CACT;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,SAAS,gBAAgB,CAAwB,KAA8B;IAC7E,OAAO,CACL,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,YAAY,CACxD;MAAA,CAAC,KAAK,CACJ,SAAS,CAAC,CAAC,KAAK,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CACjE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CACf,IAAI,CAAC,MAAM,CAEX;QAAA,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAC7B,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAG,CACjE,CAAC,CACJ;MAAA,EAAE,KAAK,CACT;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC;AAED,qGAAqG;AACrG,SAAS,cAAc,CACrB,KAEC;IAED,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAC/E,MAAM,OAAO,GAAG,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC;IACvC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC;IACrE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC;IACvC,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,iBAAiB,KAAK,SAAS,IAAI,CAAC,OAAO;YACvE,aAAa,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC,CAAC;IACF,IAAI,KAAK,CAAC,YAAY,KAAK,MAAM,EAAE,CAAC;QAClC,OAAO,CACL,CAAC,kBAAkB,CACjB,IAAI,KAAK,CAAC,CACV,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,MAAM,CAAC,CAAC,KAAK,CAAC,kBAAkB,IAAI,YAAY,CAAC,CACjD,QAAQ,CAAC,CAAC,QAAQ,CAAC,EACnB,CACH,CAAC;IACJ,CAAC;IACD,OAAO,CACL,CAAC,KAAK,CACJ,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,IAAI,CAAC,CAAC,IAAI,CAAC,CACX,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CACtB,eAAe,CAAC,CAAC,QAAQ,CAAC,CAE1B;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CACb;QAAA,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,CAC1B;QAAA,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CACpB,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CACtC;YAAA,CAAC,MAAM,CAAC,WAAW,CACrB;UAAA,EAAE,IAAI,CAAC,CACR,CAAC,CAAC,CAAC,IAAI,CACV;MAAA,EAAE,KAAK,CACT;IAAA,EAAE,KAAK,CAAC,CACT,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC","sourcesContent":["import { Radio } from '@ankhorage/surface';\nimport React from 'react';\nimport { StyleSheet, View } from 'react-native';\n\nimport { Stack } from '../../foundation';\nimport { useZoraThemeRecipe } from '../../theme/useZoraThemeRecipe';\nimport { withZoraThemeScope } from '../../theme/withZoraThemeScope';\nimport { Text } from '../text';\nimport { RadioOptionControl } from './RadioOptionControl';\nimport { resolveRadioGroupThemeRecipe } from './resolveRadioGroupThemeRecipe';\nimport type { RadioGroupProps } from './types';\n\n/*** Present one controlled single-choice group as inline radios or icon radio options. */\nexport const RadioGroup = withZoraThemeScope(RadioGroupInner);\n\n/*** Resolve shared presentation once and preserve a single interaction boundary per option. */\nfunction RadioGroupInner<TValue extends string>({\n themeId: _themeId,\n mode: _mode,\n ...props\n}: RadioGroupProps<TValue>) {\n const [localValue, setLocalValue] = React.useState(props.defaultValue);\n const onValueChange = (next: TValue) => {\n if (props.value === undefined) setLocalValue(next);\n props.onValueChange?.(next);\n };\n const selectedProps = { ...props, value: props.value ?? localValue, onValueChange };\n const themeFields = useZoraThemeRecipe('RadioGroup');\n const recipe = resolveRadioGroupThemeRecipe({ ...props, themeFields });\n if (props.presentation !== 'card') return <RadioGroupInline {...selectedProps} {...recipe} />;\n const columns =\n props.columns ?? (props.orientation === 'horizontal' ? Math.max(1, props.options.length) : 1);\n const rows = Array.from({ length: Math.ceil(props.options.length / columns) }, (_, index) =>\n props.options.slice(index * columns, (index + 1) * columns),\n );\n return (\n <View testID={props.testID} accessibilityRole=\"radiogroup\">\n <Stack gap={recipe.gap}>\n {rows.map((options, index) => (\n <Stack key={index} direction=\"row\" gap={recipe.gap}>\n {options.map((option) => (\n <View key={option.value} style={styles.option}>\n <RadioGroupItem {...selectedProps} {...recipe} option={option} />\n </View>\n ))}\n {Array.from({ length: columns - options.length }, (_, slot) => (\n <View key={`empty-${slot}`} style={styles.option} />\n ))}\n </Stack>\n ))}\n </Stack>\n </View>\n );\n}\n\n/*** Preserve ordinary radio wrapping independently of the icon-option grid. */\nfunction RadioGroupInline<TValue extends string>(props: RadioGroupProps<TValue>) {\n return (\n <View testID={props.testID} accessibilityRole=\"radiogroup\">\n <Stack\n direction={props.orientation === 'horizontal' ? 'row' : 'column'}\n gap={props.gap}\n wrap=\"wrap\"\n >\n {props.options.map((option) => (\n <RadioGroupItem key={option.value} {...props} option={option} />\n ))}\n </Stack>\n </View>\n );\n}\n\n/*** Delegate icon options to their composed radio boundary and ordinary options to Surface Radio. */\nfunction RadioGroupItem<TValue extends string>(\n props: RadioGroupProps<TValue> & {\n option: RadioGroupProps<TValue>['options'][number];\n },\n) {\n const { option, value, onValueChange, interactionPolicy, color, size } = props;\n const checked = value === option.value;\n const inactive = props.disabled === true || option.disabled === true;\n const readOnly = props.readOnly === true;\n const invalid = props.invalid === true;\n const onSelect = () => {\n if (!inactive && !readOnly && interactionPolicy !== 'passive' && !checked)\n onValueChange?.(option.value);\n };\n if (props.presentation === 'card') {\n return (\n <RadioOptionControl\n {...props}\n checked={checked}\n disabled={inactive}\n readOnly={readOnly}\n invalid={invalid}\n layout={props.contentOrientation ?? 'horizontal'}\n onSelect={onSelect}\n />\n );\n }\n return (\n <Radio\n checked={checked}\n disabled={inactive}\n readOnly={readOnly}\n invalid={invalid}\n interactionPolicy={interactionPolicy}\n color={color}\n size={size}\n testID={option.testID}\n onCheckedChange={onSelect}\n >\n <Stack gap=\"xs\">\n <Text>{option.label}</Text>\n {option.description ? (\n <Text emphasis=\"muted\" variant=\"caption\">\n {option.description}\n </Text>\n ) : null}\n </Stack>\n </Radio>\n );\n}\n\nconst styles = StyleSheet.create({ option: { flex: 1, minWidth: 0 } });\n"]}
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import type { RadioGroupProps } from './types';
3
+ /*** Render a selectable icon radio option with one accessible radio target and a trailing check. */
4
+ export declare function RadioOptionControl<TValue extends string>(props: RadioOptionControlProps<TValue>): React.JSX.Element;
5
+ interface RadioOptionControlProps<TValue extends string> extends Pick<RadioGroupProps<TValue>, 'color' | 'size' | 'interactionPolicy'> {
6
+ option: RadioGroupProps<TValue>['options'][number];
7
+ checked: boolean;
8
+ disabled: boolean;
9
+ readOnly: boolean;
10
+ invalid: boolean;
11
+ layout: 'horizontal' | 'vertical';
12
+ onSelect: () => void;
13
+ }
14
+ export {};
15
+ //# sourceMappingURL=RadioOptionControl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RadioOptionControl.d.ts","sourceRoot":"","sources":["../../../src/components/radio/RadioOptionControl.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,oGAAoG;AACpG,wBAAgB,kBAAkB,CAAC,MAAM,SAAS,MAAM,EAAE,KAAK,EAAE,uBAAuB,CAAC,MAAM,CAAC,qBAuC/F;AAqCD,UAAU,uBAAuB,CAAC,MAAM,SAAS,MAAM,CAAE,SAAQ,IAAI,CACnE,eAAe,CAAC,MAAM,CAAC,EACvB,OAAO,GAAG,MAAM,GAAG,mBAAmB,CACvC;IACC,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IACnD,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,YAAY,GAAG,UAAU,CAAC;IAClC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB"}
@@ -0,0 +1,105 @@
1
+ import { useTheme } from '@ankhorage/surface';
2
+ import React from 'react';
3
+ import { Platform, Pressable, StyleSheet, View } from 'react-native';
4
+ import { Icon } from '../icon';
5
+ import { Text } from '../text';
6
+ import { handleRadioOptionKeyDown, } from './handleRadioOptionKeyDown';
7
+ import { resolveRadioOptionColors } from './resolveRadioOptionColors';
8
+ /*** Render a selectable icon radio option with one accessible radio target and a trailing check. */
9
+ export function RadioOptionControl(props) {
10
+ const { theme } = useTheme();
11
+ const { option, checked, disabled, readOnly, interactionPolicy, onSelect } = props;
12
+ const colors = resolveRadioOptionColors(theme, props);
13
+ const [focused, setFocused] = React.useState(false);
14
+ const keyboardProps = Platform.OS === 'web' && !readOnly && !disabled && interactionPolicy !== 'passive'
15
+ ? {
16
+ onKeyDown: (event) => handleRadioOptionKeyDown(event, onSelect),
17
+ }
18
+ : {};
19
+ const controlStyle = {
20
+ flex: 1,
21
+ width: '100%',
22
+ minHeight: props.size === 'l' ? 84 : 44,
23
+ borderWidth: checked || focused ? 2 : 1,
24
+ borderColor: focused ? theme.semantics.border.focus : checked ? colors.accent : colors.border,
25
+ borderRadius: theme.radii.l,
26
+ backgroundColor: colors.surface,
27
+ };
28
+ return (<Pressable {...keyboardProps} accessibilityRole="radio" accessibilityState={{ checked, disabled }} aria-checked={checked} aria-disabled={disabled} aria-readonly={readOnly} disabled={disabled} onPress={readOnly || interactionPolicy === 'passive' ? undefined : onSelect} onFocus={() => setFocused(true)} onBlur={() => setFocused(false)} testID={option.testID} style={controlStyle}>
29
+ {(state) => <RadioOptionControlBody {...props} pressed={state.pressed}/>}
30
+ </Pressable>);
31
+ }
32
+ /*** Arrange the icon, label and passive indicator within the native radio press target. */
33
+ function RadioOptionControlBody(props) {
34
+ const { theme } = useTheme();
35
+ const colors = resolveRadioOptionColors(theme, props);
36
+ const contentStyle = {
37
+ padding: props.size === 's' ? theme.spacing.s : props.size === 'm' ? 12 : theme.spacing.m,
38
+ gap: props.layout === 'vertical' || !props.option.iconSource ? theme.spacing.s : theme.spacing.m,
39
+ ...(!props.option.iconSource ? { flexDirection: 'row-reverse' } : {}),
40
+ opacity: props.disabled ? 0.5 : props.pressed ? 0.7 : 1,
41
+ };
42
+ return (<View style={[
43
+ styles.content,
44
+ props.layout === 'vertical' ? styles.vertical : styles.horizontal,
45
+ contentStyle,
46
+ ]}>
47
+ <RadioOptionControlContent {...props}/>
48
+ {props.option.iconSource || props.checked ? (<View style={props.layout === 'vertical' ? styles.corner : undefined}>
49
+ <RadioOptionControlIndicator checked={props.checked} accent={colors.accent} onAccent={colors.onAccent}/>
50
+ </View>) : null}
51
+ </View>);
52
+ }
53
+ /*** Keep decoration passive while allowing labels to wrap at narrow widths and large text sizes. */
54
+ function RadioOptionControlContent({ option, layout, size, color, invalid, disabled, }) {
55
+ const { theme } = useTheme();
56
+ const colors = resolveRadioOptionColors(theme, { color, invalid, disabled });
57
+ return (<>
58
+ {option.iconSource ? (<View accessibilityElementsHidden importantForAccessibility="no-hide-descendants">
59
+ <Icon source={option.iconSource} size={size === 'l' ? 36 : 28} color={colors.accent}/>
60
+ </View>) : null}
61
+ <View style={layout === 'horizontal' ? styles.label : styles.centerLabel}>
62
+ <Text variant={size === 'l' ? 'body' : 'bodySmall'} weight="semiBold" align={layout === 'vertical' || !option.iconSource ? 'center' : 'left'}>
63
+ {option.label}
64
+ </Text>
65
+ {option.description ? (<Text emphasis="muted" variant="bodySmall" align={layout === 'vertical' || !option.iconSource ? 'center' : 'left'}>
66
+ {option.description}
67
+ </Text>) : null}
68
+ </View>
69
+ </>);
70
+ }
71
+ /*** Draw a passive check using themed geometry without requiring an application media asset. */
72
+ function RadioOptionControlIndicator({ checked, accent, onAccent, }) {
73
+ const indicatorStyle = { backgroundColor: checked ? accent : 'transparent' };
74
+ return (<View accessibilityElementsHidden importantForAccessibility="no-hide-descendants" style={[styles.indicator, indicatorStyle]}>
75
+ {checked ? <View style={[styles.check, { borderColor: onAccent }]}/> : null}
76
+ </View>);
77
+ }
78
+ const styles = StyleSheet.create({
79
+ content: { gap: 16, flex: 1, minWidth: 0 },
80
+ horizontal: { flexDirection: 'row', alignItems: 'center' },
81
+ vertical: {
82
+ flexDirection: 'column',
83
+ alignItems: 'center',
84
+ justifyContent: 'center',
85
+ paddingTop: 24,
86
+ },
87
+ label: { flex: 1, minWidth: 0, gap: 4 },
88
+ centerLabel: { alignSelf: 'stretch', gap: 4 },
89
+ corner: { position: 'absolute', right: 8, top: 8 },
90
+ indicator: {
91
+ width: 24,
92
+ height: 24,
93
+ borderRadius: 12,
94
+ alignItems: 'center',
95
+ justifyContent: 'center',
96
+ },
97
+ check: {
98
+ width: 7,
99
+ height: 12,
100
+ borderRightWidth: 2.5,
101
+ borderBottomWidth: 2.5,
102
+ transform: [{ rotate: '45deg' }, { translateY: -2 }],
103
+ },
104
+ });
105
+ //# sourceMappingURL=RadioOptionControl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RadioOptionControl.js","sourceRoot":"","sources":["../../../src/components/radio/RadioOptionControl.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useTheme } from '@ankhorage/surface';\nimport React from 'react';\nimport { Platform, Pressable, StyleSheet, View } from 'react-native';\n\nimport { Icon } from '../icon';\nimport { Text } from '../text';\nimport {\n handleRadioOptionKeyDown,\n type RadioOptionKeyboardTarget,\n} from './handleRadioOptionKeyDown';\nimport { resolveRadioOptionColors } from './resolveRadioOptionColors';\nimport type { RadioGroupProps } from './types';\n\n/*** Render a selectable icon radio option with one accessible radio target and a trailing check. */\nexport function RadioOptionControl<TValue extends string>(props: RadioOptionControlProps<TValue>) {\n const { theme } = useTheme();\n const { option, checked, disabled, readOnly, interactionPolicy, onSelect } = props;\n const colors = resolveRadioOptionColors(theme, props);\n const [focused, setFocused] = React.useState(false);\n const keyboardProps =\n Platform.OS === 'web' && !readOnly && !disabled && interactionPolicy !== 'passive'\n ? {\n onKeyDown: (event: React.KeyboardEvent<RadioOptionKeyboardTarget>) =>\n handleRadioOptionKeyDown(event, onSelect),\n }\n : {};\n const controlStyle = {\n flex: 1,\n width: '100%' as const,\n minHeight: props.size === 'l' ? 84 : 44,\n borderWidth: checked || focused ? 2 : 1,\n borderColor: focused ? theme.semantics.border.focus : checked ? colors.accent : colors.border,\n borderRadius: theme.radii.l,\n backgroundColor: colors.surface,\n };\n return (\n <Pressable\n {...keyboardProps}\n accessibilityRole=\"radio\"\n accessibilityState={{ checked, disabled }}\n aria-checked={checked}\n aria-disabled={disabled}\n aria-readonly={readOnly}\n disabled={disabled}\n onPress={readOnly || interactionPolicy === 'passive' ? undefined : onSelect}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n testID={option.testID}\n style={controlStyle}\n >\n {(state) => <RadioOptionControlBody {...props} pressed={state.pressed} />}\n </Pressable>\n );\n}\n\n/*** Arrange the icon, label and passive indicator within the native radio press target. */\nfunction RadioOptionControlBody<TValue extends string>(\n props: RadioOptionControlProps<TValue> & { pressed: boolean },\n) {\n const { theme } = useTheme();\n const colors = resolveRadioOptionColors(theme, props);\n const contentStyle = {\n padding: props.size === 's' ? theme.spacing.s : props.size === 'm' ? 12 : theme.spacing.m,\n gap:\n props.layout === 'vertical' || !props.option.iconSource ? theme.spacing.s : theme.spacing.m,\n ...(!props.option.iconSource ? { flexDirection: 'row-reverse' as const } : {}),\n opacity: props.disabled ? 0.5 : props.pressed ? 0.7 : 1,\n };\n return (\n <View\n style={[\n styles.content,\n props.layout === 'vertical' ? styles.vertical : styles.horizontal,\n contentStyle,\n ]}\n >\n <RadioOptionControlContent {...props} />\n {props.option.iconSource || props.checked ? (\n <View style={props.layout === 'vertical' ? styles.corner : undefined}>\n <RadioOptionControlIndicator\n checked={props.checked}\n accent={colors.accent}\n onAccent={colors.onAccent}\n />\n </View>\n ) : null}\n </View>\n );\n}\n\ninterface RadioOptionControlProps<TValue extends string> extends Pick<\n RadioGroupProps<TValue>,\n 'color' | 'size' | 'interactionPolicy'\n> {\n option: RadioGroupProps<TValue>['options'][number];\n checked: boolean;\n disabled: boolean;\n readOnly: boolean;\n invalid: boolean;\n layout: 'horizontal' | 'vertical';\n onSelect: () => void;\n}\n\n/*** Keep decoration passive while allowing labels to wrap at narrow widths and large text sizes. */\nfunction RadioOptionControlContent<TValue extends string>({\n option,\n layout,\n size,\n color,\n invalid,\n disabled,\n}: RadioOptionControlProps<TValue>) {\n const { theme } = useTheme();\n const colors = resolveRadioOptionColors(theme, { color, invalid, disabled });\n return (\n <>\n {option.iconSource ? (\n <View accessibilityElementsHidden importantForAccessibility=\"no-hide-descendants\">\n <Icon source={option.iconSource} size={size === 'l' ? 36 : 28} color={colors.accent} />\n </View>\n ) : null}\n <View style={layout === 'horizontal' ? styles.label : styles.centerLabel}>\n <Text\n variant={size === 'l' ? 'body' : 'bodySmall'}\n weight=\"semiBold\"\n align={layout === 'vertical' || !option.iconSource ? 'center' : 'left'}\n >\n {option.label}\n </Text>\n {option.description ? (\n <Text\n emphasis=\"muted\"\n variant=\"bodySmall\"\n align={layout === 'vertical' || !option.iconSource ? 'center' : 'left'}\n >\n {option.description}\n </Text>\n ) : null}\n </View>\n </>\n );\n}\n\n/*** Draw a passive check using themed geometry without requiring an application media asset. */\nfunction RadioOptionControlIndicator({\n checked,\n accent,\n onAccent,\n}: {\n checked: boolean;\n accent: string;\n onAccent: string;\n}) {\n const indicatorStyle = { backgroundColor: checked ? accent : 'transparent' };\n return (\n <View\n accessibilityElementsHidden\n importantForAccessibility=\"no-hide-descendants\"\n style={[styles.indicator, indicatorStyle]}\n >\n {checked ? <View style={[styles.check, { borderColor: onAccent }]} /> : null}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n content: { gap: 16, flex: 1, minWidth: 0 },\n horizontal: { flexDirection: 'row', alignItems: 'center' },\n vertical: {\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n paddingTop: 24,\n },\n label: { flex: 1, minWidth: 0, gap: 4 },\n centerLabel: { alignSelf: 'stretch', gap: 4 },\n corner: { position: 'absolute', right: 8, top: 8 },\n indicator: {\n width: 24,\n height: 24,\n borderRadius: 12,\n alignItems: 'center',\n justifyContent: 'center',\n },\n check: {\n width: 7,\n height: 12,\n borderRightWidth: 2.5,\n borderBottomWidth: 2.5,\n transform: [{ rotate: '45deg' }, { translateY: -2 }],\n },\n});\n"]}
@@ -0,0 +1,13 @@
1
+ import type { KeyboardEvent } from 'react';
2
+ /*** Support Space and directional navigation for web radio options without affecting native presses. */
3
+ export declare function handleRadioOptionKeyDown(event: KeyboardEvent<RadioOptionKeyboardTarget>, select: () => void): void;
4
+ /** Minimal web target contract keeps the native build independent of DOM ambient libraries. */
5
+ export interface RadioOptionKeyboardTarget {
6
+ closest(selector: string): {
7
+ querySelectorAll(selector: string): ArrayLike<RadioOptionKeyboardTarget>;
8
+ } | null;
9
+ getAttribute(name: string): string | null;
10
+ focus(): void;
11
+ click(): void;
12
+ }
13
+ //# sourceMappingURL=handleRadioOptionKeyDown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handleRadioOptionKeyDown.d.ts","sourceRoot":"","sources":["../../../src/components/radio/handleRadioOptionKeyDown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAI3C,wGAAwG;AACxG,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,aAAa,CAAC,yBAAyB,CAAC,EAC/C,MAAM,EAAE,MAAM,IAAI,GACjB,IAAI,CAkBN;AAED,+FAA+F;AAC/F,MAAM,WAAW,yBAAyB;IACxC,OAAO,CACL,QAAQ,EAAE,MAAM,GACf;QAAE,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC,yBAAyB,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC;IACvF,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC1C,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,IAAI,IAAI,CAAC;CACf"}
@@ -0,0 +1,22 @@
1
+ import { DIRECTION_MODIFIERS } from '../../constants/keyboard';
2
+ /*** Support Space and directional navigation for web radio options without affecting native presses. */
3
+ export function handleRadioOptionKeyDown(event, select) {
4
+ if (event.key === ' ') {
5
+ event.preventDefault();
6
+ select();
7
+ return;
8
+ }
9
+ const direction = DIRECTION_MODIFIERS.get(event.key);
10
+ if (direction === undefined)
11
+ return;
12
+ const group = event.currentTarget.closest('[role="radiogroup"]');
13
+ const options = Array.from(group?.querySelectorAll('[role="radio"]') ?? []).filter((option) => option.getAttribute('aria-disabled') !== 'true');
14
+ const index = options.indexOf(event.currentTarget);
15
+ if (index < 0 || options.length === 0)
16
+ return;
17
+ event.preventDefault();
18
+ const next = options.at((index + direction + options.length) % options.length);
19
+ next?.focus();
20
+ next?.click();
21
+ }
22
+ //# sourceMappingURL=handleRadioOptionKeyDown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handleRadioOptionKeyDown.js","sourceRoot":"","sources":["../../../src/components/radio/handleRadioOptionKeyDown.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,wGAAwG;AACxG,MAAM,UAAU,wBAAwB,CACtC,KAA+C,EAC/C,MAAkB;IAElB,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;QACtB,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,MAAM,EAAE,CAAC;QACT,OAAO;IACT,CAAC;IACD,MAAM,SAAS,GAAG,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrD,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO;IACpC,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAChF,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,eAAe,CAAC,KAAK,MAAM,CAC5D,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACnD,IAAI,KAAK,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC9C,KAAK,CAAC,cAAc,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/E,IAAI,EAAE,KAAK,EAAE,CAAC;IACd,IAAI,EAAE,KAAK,EAAE,CAAC;AAChB,CAAC","sourcesContent":["import type { KeyboardEvent } from 'react';\n\nimport { DIRECTION_MODIFIERS } from '../../constants/keyboard';\n\n/*** Support Space and directional navigation for web radio options without affecting native presses. */\nexport function handleRadioOptionKeyDown(\n event: KeyboardEvent<RadioOptionKeyboardTarget>,\n select: () => void,\n): void {\n if (event.key === ' ') {\n event.preventDefault();\n select();\n return;\n }\n const direction = DIRECTION_MODIFIERS.get(event.key);\n if (direction === undefined) return;\n const group = event.currentTarget.closest('[role=\"radiogroup\"]');\n const options = Array.from(group?.querySelectorAll('[role=\"radio\"]') ?? []).filter(\n (option) => option.getAttribute('aria-disabled') !== 'true',\n );\n const index = options.indexOf(event.currentTarget);\n if (index < 0 || options.length === 0) return;\n event.preventDefault();\n const next = options.at((index + direction + options.length) % options.length);\n next?.focus();\n next?.click();\n}\n\n/** Minimal web target contract keeps the native build independent of DOM ambient libraries. */\nexport interface RadioOptionKeyboardTarget {\n closest(\n selector: string,\n ): { querySelectorAll(selector: string): ArrayLike<RadioOptionKeyboardTarget> } | null;\n getAttribute(name: string): string | null;\n focus(): void;\n click(): void;\n}\n"]}
@@ -13,9 +13,9 @@ export declare const radioGroupMeta: {
13
13
  readonly directManifestNode: true;
14
14
  readonly allowedChildren: readonly [];
15
15
  readonly blueprint: {
16
- readonly label: "Radio group";
16
+ readonly label: "Radio button group";
17
17
  readonly defaultProps: {
18
- readonly value: "option-b";
18
+ readonly defaultValue: "option-b";
19
19
  readonly options: readonly [{
20
20
  readonly value: "option-a";
21
21
  readonly label: "First option";
@@ -30,7 +30,7 @@ export declare const radioGroupMeta: {
30
30
  readonly description: "Supporting detail";
31
31
  }];
32
32
  readonly orientation: "vertical";
33
- readonly presentation: "inline";
33
+ readonly presentation: "card";
34
34
  readonly invalid: false;
35
35
  readonly readOnly: false;
36
36
  readonly disabled: false;
@@ -85,6 +85,14 @@ export declare const radioGroupMeta: {
85
85
  };
86
86
  };
87
87
  readonly props: {
88
+ readonly defaultValue: {
89
+ readonly type: "string";
90
+ readonly category: "State";
91
+ readonly label: "Initial value";
92
+ readonly authoring: {
93
+ readonly authority: "instance";
94
+ };
95
+ };
88
96
  readonly value: {
89
97
  readonly type: "string";
90
98
  readonly category: "State";
@@ -118,6 +126,14 @@ export declare const radioGroupMeta: {
118
126
  readonly category: "Content";
119
127
  readonly label: "Description";
120
128
  };
129
+ }, {
130
+ readonly key: "iconSource";
131
+ readonly schema: {
132
+ readonly type: "media";
133
+ readonly category: "Content";
134
+ readonly label: "Icon";
135
+ readonly mediaKinds: readonly ["image"];
136
+ };
121
137
  }, {
122
138
  readonly key: "disabled";
123
139
  readonly schema: {
@@ -162,6 +178,25 @@ export declare const radioGroupMeta: {
162
178
  readonly authority: "instance";
163
179
  };
164
180
  };
181
+ readonly contentOrientation: {
182
+ readonly type: "enum";
183
+ readonly category: "Layout";
184
+ readonly label: "Option content orientation";
185
+ readonly enum: readonly ["horizontal", "vertical"];
186
+ readonly default: "horizontal";
187
+ readonly authoring: {
188
+ readonly authority: "instance";
189
+ };
190
+ };
191
+ readonly columns: {
192
+ readonly type: "enum";
193
+ readonly category: "Layout";
194
+ readonly label: "Option columns";
195
+ readonly enum: readonly [1, 2, 3, 4];
196
+ readonly authoring: {
197
+ readonly authority: "instance";
198
+ };
199
+ };
165
200
  readonly color: {
166
201
  readonly type: "enum";
167
202
  readonly category: "Style";
@@ -1 +1 @@
1
- {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../../src/components/radio/meta.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,SAAS;;;;;;;CAOgB,CAAC;AAEvC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsKW,CAAC"}
1
+ {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../../src/components/radio/meta.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,SAAS;;;;;;;CAOgB,CAAC;AAEvC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+LW,CAAC"}
@@ -19,16 +19,16 @@ export const radioGroupMeta = {
19
19
  directManifestNode: true,
20
20
  allowedChildren: [],
21
21
  blueprint: {
22
- label: 'Radio group',
22
+ label: 'Radio button group',
23
23
  defaultProps: {
24
- value: 'option-b',
24
+ defaultValue: 'option-b',
25
25
  options: [
26
26
  { value: 'option-a', label: 'First option', description: 'Supporting detail' },
27
27
  { value: 'option-b', label: 'Second option', description: 'Supporting detail' },
28
28
  { value: 'option-c', label: 'Third option', description: 'Supporting detail' },
29
29
  ],
30
30
  orientation: 'vertical',
31
- presentation: 'inline',
31
+ presentation: 'card',
32
32
  invalid: false,
33
33
  readOnly: false,
34
34
  disabled: false,
@@ -71,6 +71,12 @@ export const radioGroupMeta = {
71
71
  },
72
72
  },
73
73
  props: {
74
+ defaultValue: {
75
+ type: 'string',
76
+ category: 'State',
77
+ label: 'Initial value',
78
+ authoring: { authority: 'instance' },
79
+ },
74
80
  value: {
75
81
  type: 'string',
76
82
  category: 'State',
@@ -106,6 +112,10 @@ export const radioGroupMeta = {
106
112
  label: 'Description',
107
113
  },
108
114
  },
115
+ {
116
+ key: 'iconSource',
117
+ schema: { type: 'media', category: 'Content', label: 'Icon', mediaKinds: ['image'] },
118
+ },
109
119
  {
110
120
  key: 'disabled',
111
121
  schema: {
@@ -141,6 +151,21 @@ export const radioGroupMeta = {
141
151
  default: 'inline',
142
152
  authoring: { authority: 'instance' },
143
153
  },
154
+ contentOrientation: {
155
+ type: 'enum',
156
+ category: 'Layout',
157
+ label: 'Option content orientation',
158
+ enum: ['horizontal', 'vertical'],
159
+ default: 'horizontal',
160
+ authoring: { authority: 'instance' },
161
+ },
162
+ columns: {
163
+ type: 'enum',
164
+ category: 'Layout',
165
+ label: 'Option columns',
166
+ enum: [1, 2, 3, 4],
167
+ authoring: { authority: 'instance' },
168
+ },
144
169
  color: {
145
170
  type: 'enum',
146
171
  category: 'Style',