@tamagui/radio-group 1.96.0 → 1.97.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 (69) hide show
  1. package/dist/cjs/RadioGroup.js +23 -248
  2. package/dist/cjs/RadioGroup.js.map +1 -1
  3. package/dist/cjs/RadioGroup.native.js +25 -336
  4. package/dist/cjs/RadioGroup.native.js.map +2 -2
  5. package/dist/cjs/RadioGroupStyledContext.js +25 -0
  6. package/dist/cjs/RadioGroupStyledContext.js.map +6 -0
  7. package/dist/cjs/RadioGroupStyledContext.native.js +29 -0
  8. package/dist/cjs/RadioGroupStyledContext.native.js.map +6 -0
  9. package/dist/cjs/createRadioGroup.js +107 -0
  10. package/dist/cjs/createRadioGroup.js.map +6 -0
  11. package/dist/cjs/createRadioGroup.native.js +171 -0
  12. package/dist/cjs/createRadioGroup.native.js.map +6 -0
  13. package/dist/cjs/index.js +15 -1
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/cjs/index.native.js +19 -2
  16. package/dist/cjs/index.native.js.map +2 -2
  17. package/dist/esm/RadioGroup.js +20 -248
  18. package/dist/esm/RadioGroup.js.map +1 -1
  19. package/dist/esm/RadioGroup.mjs +19 -240
  20. package/dist/esm/RadioGroup.native.js +20 -334
  21. package/dist/esm/RadioGroup.native.js.map +2 -2
  22. package/dist/esm/RadioGroupStyledContext.js +9 -0
  23. package/dist/esm/RadioGroupStyledContext.js.map +6 -0
  24. package/dist/esm/RadioGroupStyledContext.mjs +6 -0
  25. package/dist/esm/RadioGroupStyledContext.native.js +9 -0
  26. package/dist/esm/RadioGroupStyledContext.native.js.map +6 -0
  27. package/dist/esm/createRadioGroup.js +104 -0
  28. package/dist/esm/createRadioGroup.js.map +6 -0
  29. package/dist/esm/createRadioGroup.mjs +131 -0
  30. package/dist/esm/createRadioGroup.native.js +155 -0
  31. package/dist/esm/createRadioGroup.native.js.map +6 -0
  32. package/dist/esm/index.js +16 -0
  33. package/dist/esm/index.js.map +1 -1
  34. package/dist/esm/index.mjs +11 -1
  35. package/dist/esm/index.native.js +12 -0
  36. package/dist/esm/index.native.js.map +2 -2
  37. package/dist/jsx/RadioGroup.js +20 -248
  38. package/dist/jsx/RadioGroup.js.map +1 -1
  39. package/dist/jsx/RadioGroup.mjs +19 -240
  40. package/dist/jsx/RadioGroup.native.js +20 -334
  41. package/dist/jsx/RadioGroup.native.js.map +2 -2
  42. package/dist/jsx/RadioGroupStyledContext.js +9 -0
  43. package/dist/jsx/RadioGroupStyledContext.js.map +6 -0
  44. package/dist/jsx/RadioGroupStyledContext.mjs +6 -0
  45. package/dist/jsx/RadioGroupStyledContext.native.js +9 -0
  46. package/dist/jsx/RadioGroupStyledContext.native.js.map +6 -0
  47. package/dist/jsx/createRadioGroup.js +104 -0
  48. package/dist/jsx/createRadioGroup.js.map +6 -0
  49. package/dist/jsx/createRadioGroup.mjs +131 -0
  50. package/dist/jsx/createRadioGroup.native.js +155 -0
  51. package/dist/jsx/createRadioGroup.native.js.map +6 -0
  52. package/dist/jsx/index.js +16 -0
  53. package/dist/jsx/index.js.map +1 -1
  54. package/dist/jsx/index.mjs +11 -1
  55. package/dist/jsx/index.native.js +12 -0
  56. package/dist/jsx/index.native.js.map +2 -2
  57. package/package.json +14 -14
  58. package/src/RadioGroup.tsx +22 -432
  59. package/src/RadioGroupStyledContext.tsx +7 -0
  60. package/src/createRadioGroup.tsx +201 -0
  61. package/src/index.ts +15 -0
  62. package/types/RadioGroup.d.ts +7 -224
  63. package/types/RadioGroup.d.ts.map +1 -1
  64. package/types/RadioGroupStyledContext.d.ts +6 -0
  65. package/types/RadioGroupStyledContext.d.ts.map +1 -0
  66. package/types/createRadioGroup.d.ts +979 -0
  67. package/types/createRadioGroup.d.ts.map +1 -0
  68. package/types/index.d.ts +949 -0
  69. package/types/index.d.ts.map +1 -1
@@ -1,120 +1,10 @@
1
- // forked from Radix UI
2
- // https://github.com/radix-ui/primitives/blob/main/packages/react/radio-group/src/RadioGroup.tsx
3
-
4
- import { useComposedRefs } from '@tamagui/compose-refs'
5
- import { isWeb } from '@tamagui/constants'
6
- import type { GetProps } from '@tamagui/core'
7
1
  import { getVariableValue, styled } from '@tamagui/core'
8
- import type { Scope } from '@tamagui/create-context'
9
- import { createContextScope } from '@tamagui/create-context'
10
- import { registerFocusable } from '@tamagui/focusable'
11
2
  import { getSize } from '@tamagui/get-token'
12
- import { composeEventHandlers, withStaticProperties } from '@tamagui/helpers'
13
- import { useLabelContext } from '@tamagui/label'
14
- import { RovingFocusGroup } from '@tamagui/roving-focus'
15
3
  import { ThemeableStack } from '@tamagui/stacks'
16
- import { useControllableState } from '@tamagui/use-controllable-state'
17
- import { usePrevious } from '@tamagui/use-previous'
18
- import * as React from 'react'
19
- import type { View } from 'react-native'
20
-
21
- const RADIO_GROUP_NAME = 'RadioGroup'
22
-
23
- const ARROW_KEYS = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']
24
-
25
- const [createRadioGroupContext, createRadioGroupScope] =
26
- createContextScope(RADIO_GROUP_NAME)
27
- type RadioGroupContextValue = {
28
- value?: string
29
- disabled?: boolean
30
- required?: boolean
31
- onChange?: (value: string) => void
32
- name?: string
33
- native?: boolean
34
- accentColor?: string
35
- }
36
- const [RadioGroupProvider, useRadioGroupContext] =
37
- createRadioGroupContext<RadioGroupContextValue>(RADIO_GROUP_NAME)
38
-
39
- const getState = (checked: boolean) => {
40
- return checked ? 'checked' : 'unchecked'
41
- }
42
-
43
- /* -------------------------------------------------------------------------
44
- * RadioIndicator
45
- * ------------------------------------------------------------------------ */
46
-
47
- const RADIO_GROUP_INDICATOR_NAME = 'RadioGroupIndicator'
48
-
49
- const RadioIndicatorFrame = styled(ThemeableStack, {
50
- name: RADIO_GROUP_INDICATOR_NAME,
51
-
52
- variants: {
53
- unstyled: {
54
- false: {
55
- width: '33%',
56
- height: '33%',
57
- borderRadius: 1000,
58
- backgroundColor: '$color',
59
- pressTheme: true,
60
- },
61
- },
62
- } as const,
63
-
64
- defaultVariants: {
65
- unstyled: process.env.TAMAGUI_HEADLESS === '1' ? true : false,
66
- },
67
- })
68
-
69
- type RadioIndicatorProps = GetProps<typeof RadioIndicatorFrame> & {
70
- forceMount?: boolean
71
- unstyled?: boolean
72
- }
73
-
74
- type RadioIndicatorElement = TamaguiElement
75
-
76
- const RadioIndicator = RadioIndicatorFrame.extractable(
77
- React.forwardRef<RadioIndicatorElement, RadioIndicatorProps>(
78
- (props: ScopedRadioGroupItemProps<RadioIndicatorProps>, forwardedRef) => {
79
- const { __scopeRadioGroupItem, forceMount, disabled, ...indicatorProps } = props
80
- const { checked } = useRadioGroupItemContext(
81
- RADIO_GROUP_INDICATOR_NAME,
82
- __scopeRadioGroupItem
83
- )
84
-
85
- if (forceMount || checked) {
86
- return (
87
- <RadioIndicatorFrame
88
- data-state={getState(checked)}
89
- data-disabled={disabled ? '' : undefined}
90
- {...indicatorProps}
91
- ref={forwardedRef}
92
- />
93
- )
94
- }
95
-
96
- return null
97
- }
98
- )
99
- )
100
-
101
- RadioIndicator.displayName = RADIO_GROUP_INDICATOR_NAME
102
-
103
- /* -------------------------------------------------------------------------
104
- * RadioGroupItem
105
- * ------------------------------------------------------------------------ */
106
4
 
107
5
  const RADIO_GROUP_ITEM_NAME = 'RadioGroupItem'
108
6
 
109
- type RadioGroupItemContextValue = {
110
- checked: boolean
111
- disabled?: boolean
112
- }
113
-
114
- const [RadioGroupItemProvider, useRadioGroupItemContext] =
115
- createRadioGroupContext<RadioGroupItemContextValue>(RADIO_GROUP_NAME)
116
-
117
- const RadioGroupItemFrame = styled(ThemeableStack, {
7
+ export const RadioGroupItemFrame = styled(ThemeableStack, {
118
8
  name: RADIO_GROUP_ITEM_NAME,
119
9
  tag: 'button',
120
10
 
@@ -189,260 +79,35 @@ const RadioGroupItemFrame = styled(ThemeableStack, {
189
79
  } as const,
190
80
 
191
81
  defaultVariants: {
192
- unstyled: process.env.TAMAGUI_HEADLESS === '1' ? true : false,
82
+ unstyled: process.env.TAMAGUI_HEADLESS === '1',
193
83
  },
194
84
  })
195
85
 
196
- type RadioGroupItemProps = GetProps<typeof RadioGroupItemFrame> & {
197
- value: string
198
- id?: string
199
- labelledBy?: string
200
- disabled?: boolean
201
- }
202
-
203
- type RadioGroupItemElement = HTMLButtonElement
204
-
205
- type ScopedRadioGroupItemProps<P> = P & {
206
- __scopeRadioGroupItem?: Scope
207
- }
208
-
209
- const RadioGroupItem = RadioGroupItemFrame.extractable(
210
- React.forwardRef<RadioGroupItemElement, RadioGroupItemProps>(
211
- (props: ScopedProps<RadioGroupItemProps>, forwardedRef) => {
212
- const {
213
- __scopeRadioGroup,
214
- value,
215
- labelledBy: ariaLabelledby,
216
- disabled: itemDisabled,
217
- ...itemProps
218
- } = props
219
- const {
220
- value: groupValue,
221
- disabled,
222
- required,
223
- onChange,
224
- name,
225
- native,
226
- accentColor,
227
- } = useRadioGroupContext(RADIO_GROUP_ITEM_NAME, __scopeRadioGroup)
228
- const [button, setButton] = React.useState<HTMLButtonElement | null>(null)
229
- const hasConsumerStoppedPropagationRef = React.useRef(false)
230
- const ref = React.useRef<HTMLButtonElement>(null)
231
- const composedRefs = useComposedRefs(forwardedRef, (node) => setButton(node), ref)
232
- const isArrowKeyPressedRef = React.useRef(false)
233
-
234
- const isFormControl = isWeb
235
- ? button
236
- ? Boolean(button.closest('form'))
237
- : true
238
- : false
239
-
240
- const checked = groupValue === value
241
-
242
- const labelId = useLabelContext(button)
243
- const labelledBy = ariaLabelledby || labelId
244
-
245
- React.useEffect(() => {
246
- if (isWeb) {
247
- const handleKeyDown = (event: KeyboardEvent) => {
248
- if (ARROW_KEYS.includes(event.key)) {
249
- isArrowKeyPressedRef.current = true
250
- }
251
- }
252
- const handleKeyUp = () => {
253
- isArrowKeyPressedRef.current = false
254
- }
255
- document.addEventListener('keydown', handleKeyDown)
256
- document.addEventListener('keyup', handleKeyUp)
257
- return () => {
258
- document.removeEventListener('keydown', handleKeyDown)
259
- document.removeEventListener('keyup', handleKeyUp)
260
- }
261
- }
262
- }, [])
263
-
264
- if (process.env.TAMAGUI_TARGET === 'native') {
265
- React.useEffect(() => {
266
- if (!props.id) return
267
- if (disabled) return
268
-
269
- return registerFocusable(props.id, {
270
- focusAndSelect: () => {
271
- onChange?.(value)
272
- },
273
- focus: () => {},
274
- })
275
- }, [props.id, value, disabled])
276
- }
277
-
278
- const isDisabled = disabled || itemDisabled
279
-
280
- return (
281
- <RadioGroupItemProvider checked={checked} scope={__scopeRadioGroup}>
282
- {isWeb && native ? (
283
- <BubbleInput
284
- control={button}
285
- bubbles={!hasConsumerStoppedPropagationRef.current}
286
- name={name}
287
- value={value}
288
- checked={checked}
289
- required={required}
290
- disabled={isDisabled}
291
- id={props.id}
292
- accentColor={accentColor}
293
- />
294
- ) : (
295
- <>
296
- <RovingFocusGroup.Item
297
- __scopeRovingFocusGroup={RADIO_GROUP_NAME}
298
- asChild="except-style"
299
- focusable={!isDisabled}
300
- active={checked}
301
- >
302
- <RadioGroupItemFrame
303
- // theme={checked ? 'active' : undefined}
304
- data-state={getState(checked)}
305
- data-disabled={isDisabled ? '' : undefined}
306
- role="radio"
307
- aria-labelledby={labelledBy}
308
- aria-checked={checked}
309
- aria-required={required}
310
- disabled={isDisabled}
311
- ref={composedRefs}
312
- {...(isWeb && {
313
- type: 'button',
314
- value: value,
315
- })}
316
- // allow them to override all but the handlers that already compose:
317
- {...itemProps}
318
- onPress={composeEventHandlers(props.onPress as any, (event) => {
319
- if (!checked) {
320
- onChange?.(value)
321
- }
322
-
323
- if (isFormControl) {
324
- hasConsumerStoppedPropagationRef.current =
325
- event.isPropagationStopped()
326
- // if radio is in a form, stop propagation from the button so that we only propagate
327
- // one click event (from the input). We propagate changes from an input so that native
328
- // form validation works and form events reflect radio updates.
329
- if (!hasConsumerStoppedPropagationRef.current)
330
- event.stopPropagation()
331
- }
332
- })}
333
- {...(isWeb && {
334
- onKeyDown: composeEventHandlers(
335
- (props as React.HTMLProps<HTMLButtonElement>).onKeyDown,
336
- (event) => {
337
- // According to WAI ARIA, Checkboxes don't activate on enter keypress
338
- if (event.key === 'Enter') event.preventDefault()
339
- }
340
- ),
341
- onFocus: composeEventHandlers(itemProps.onFocus, () => {
342
- /**
343
- * Our `RovingFocusGroup` will focus the radio when navigating with arrow keys
344
- * and we need to "check" it in that case. We click it to "check" it (instead
345
- * of updating `context.value`) so that the radio change event fires.
346
- */
347
- if (isArrowKeyPressedRef.current) {
348
- ;(ref.current as HTMLButtonElement)?.click()
349
- }
350
- }),
351
- })}
352
- />
353
- </RovingFocusGroup.Item>
354
- {isFormControl && (
355
- <BubbleInput
356
- isHidden
357
- control={button}
358
- bubbles={!hasConsumerStoppedPropagationRef.current}
359
- name={name}
360
- value={value}
361
- checked={checked}
362
- required={required}
363
- disabled={isDisabled}
364
- />
365
- )}
366
- </>
367
- )}
368
- </RadioGroupItemProvider>
369
- )
370
- }
371
- )
372
- )
373
-
374
- /* -------------------------------------------------------------------------
375
- * BubbleInput
376
- * ------------------------------------------------------------------------ */
377
-
378
- interface BubbleInputProps extends Omit<React.HTMLProps<HTMLInputElement>, 'checked'> {
379
- checked: boolean
380
- control: HTMLElement | null
381
- bubbles: boolean
382
- isHidden?: boolean
383
- accentColor?: string
384
- }
385
-
386
- const BubbleInput = (props: BubbleInputProps) => {
387
- const { checked, bubbles = true, control, isHidden, accentColor, ...inputProps } = props
388
- const ref = React.useRef<HTMLInputElement>(null)
389
- const prevChecked = usePrevious(checked)
390
-
391
- // Bubble checked change to parents (e.g form change event)
392
- React.useEffect(() => {
393
- const input = ref.current!
394
- const inputProto = window.HTMLInputElement.prototype
395
- const descriptor = Object.getOwnPropertyDescriptor(
396
- inputProto,
397
- 'checked'
398
- ) as PropertyDescriptor
399
- const setChecked = descriptor.set
400
- if (prevChecked !== checked && setChecked) {
401
- const event = new Event('click', { bubbles })
402
- setChecked.call(input, checked)
403
- input.dispatchEvent(event)
404
- }
405
- }, [prevChecked, checked, bubbles])
406
-
407
- return (
408
- <input
409
- type="radio"
410
- defaultChecked={checked}
411
- {...inputProps}
412
- tabIndex={-1}
413
- ref={ref}
414
- aria-hidden={isHidden}
415
- style={{
416
- ...(isHidden
417
- ? {
418
- // ...controlSize,
419
- position: 'absolute',
420
- pointerEvents: 'none',
421
- opacity: 0,
422
- margin: 0,
423
- }
424
- : {
425
- appearance: 'auto',
426
- accentColor,
427
- }),
428
-
429
- ...props.style,
430
- }}
431
- />
432
- )
433
- }
86
+ const RADIO_GROUP_INDICATOR_NAME = 'RadioGroupIndicator'
434
87
 
435
- /* -------------------------------------------------------------------------
436
- * RadioGroup
437
- * ----------------------------------------------------------------------- */
88
+ export const RadioGroupIndicatorFrame = styled(ThemeableStack, {
89
+ name: RADIO_GROUP_INDICATOR_NAME,
438
90
 
439
- type ScopedProps<P> = P & { __scopeRadioGroup?: Scope }
91
+ variants: {
92
+ unstyled: {
93
+ false: {
94
+ width: '33%',
95
+ height: '33%',
96
+ borderRadius: 1000,
97
+ backgroundColor: '$color',
98
+ pressTheme: true,
99
+ },
100
+ },
101
+ } as const,
440
102
 
441
- type TamaguiElement = HTMLElement | View
103
+ defaultVariants: {
104
+ unstyled: process.env.TAMAGUI_HEADLESS === '1',
105
+ },
106
+ })
442
107
 
443
- type RadioGroupElement = TamaguiElement
108
+ const RADIO_GROUP_NAME = 'RadioGroup'
444
109
 
445
- const RadioGroupFrame = styled(ThemeableStack, {
110
+ export const RadioGroupFrame = styled(ThemeableStack, {
446
111
  name: RADIO_GROUP_NAME,
447
112
 
448
113
  variants: {
@@ -458,78 +123,3 @@ const RadioGroupFrame = styled(ThemeableStack, {
458
123
  },
459
124
  } as const,
460
125
  })
461
-
462
- type RadioGroupProps = GetProps<typeof RadioGroupFrame> & {
463
- value?: string
464
- defaultValue?: string
465
- onValueChange?: (value: string) => void
466
- required?: boolean
467
- disabled?: boolean
468
- name?: string
469
- native?: boolean
470
- accentColor?: string
471
- }
472
-
473
- const RadioGroup = withStaticProperties(
474
- RadioGroupFrame.extractable(
475
- React.forwardRef<RadioGroupElement, RadioGroupProps>(
476
- (props: ScopedProps<RadioGroupProps>, forwardedRef) => {
477
- const {
478
- __scopeRadioGroup,
479
- value: valueProp,
480
- defaultValue,
481
- onValueChange,
482
- disabled = false,
483
- required = false,
484
- name,
485
- orientation,
486
- native,
487
- accentColor,
488
- ...radioGroupProps
489
- } = props
490
- const [value, setValue] = useControllableState({
491
- prop: valueProp,
492
- defaultProp: defaultValue!,
493
- onChange: onValueChange,
494
- })
495
-
496
- return (
497
- <RadioGroupProvider
498
- scope={__scopeRadioGroup}
499
- value={value}
500
- required={required}
501
- onChange={setValue}
502
- disabled={disabled}
503
- name={name}
504
- native={native}
505
- accentColor={accentColor}
506
- >
507
- <RovingFocusGroup
508
- __scopeRovingFocusGroup={RADIO_GROUP_NAME}
509
- orientation={orientation as any}
510
- loop={true}
511
- >
512
- <RadioGroupFrame
513
- role="radiogroup"
514
- aria-orientation={orientation}
515
- ref={forwardedRef}
516
- orientation={orientation}
517
- data-disabled={disabled ? '' : undefined}
518
- {...radioGroupProps}
519
- />
520
- </RovingFocusGroup>
521
- </RadioGroupProvider>
522
- )
523
- }
524
- )
525
- ),
526
- {
527
- Indicator: RadioIndicator,
528
- Item: RadioGroupItem,
529
- }
530
- )
531
-
532
- RadioGroup.displayName = RADIO_GROUP_NAME
533
-
534
- export { createRadioGroupScope, RadioGroup }
535
- export type { RadioGroupProps, RadioGroupItemProps }
@@ -0,0 +1,7 @@
1
+ import type { SizeTokens } from '@tamagui/core'
2
+ import { createStyledContext } from '@tamagui/core'
3
+
4
+ export const RadioGroupStyledContext = createStyledContext({
5
+ size: '$true' as SizeTokens,
6
+ scaleIcon: 1,
7
+ })
@@ -0,0 +1,201 @@
1
+ import type {
2
+ RadioGroupContextValue,
3
+ RadioGroupItemContextValue,
4
+ } from '@tamagui/radio-headless'
5
+ import type { GetProps } from '@tamagui/core'
6
+ import { isWeb, withStaticProperties } from '@tamagui/core'
7
+
8
+ import {
9
+ RadioGroupFrame,
10
+ RadioGroupIndicatorFrame,
11
+ RadioGroupItemFrame,
12
+ } from './RadioGroup'
13
+
14
+ const ensureContext = (x: any) => {
15
+ if (!x.context) {
16
+ x.context = RadioGroupContext
17
+ }
18
+ }
19
+
20
+ type RadioIndicatorProps = GetProps<typeof RadioGroupIndicatorFrame> & {
21
+ forceMount?: boolean
22
+ unstyled?: boolean
23
+ }
24
+
25
+ import {
26
+ useRadioGroup,
27
+ useRadioGroupItem,
28
+ useRadioGroupItemIndicator,
29
+ } from '@tamagui/radio-headless'
30
+ import { RovingFocusGroup } from '@tamagui/roving-focus'
31
+ import { createContext } from 'react'
32
+ const RadioGroupContext = createContext<RadioGroupContextValue>({})
33
+ const RadioGroupItemContext = createContext<RadioGroupItemContextValue>({
34
+ checked: false,
35
+ disabled: false,
36
+ })
37
+
38
+ export type RadioGroupItemProps = GetProps<typeof RadioGroupItemFrame> & {
39
+ value: string
40
+ id?: string
41
+ labelledBy?: string
42
+ disabled?: boolean
43
+ }
44
+
45
+ export type RadioGroupProps = GetProps<typeof RadioGroupFrame> & {
46
+ value?: string
47
+ defaultValue?: string
48
+ onValueChange?: (value: string) => void
49
+ required?: boolean
50
+ disabled?: boolean
51
+ name?: string
52
+ native?: boolean
53
+ accentColor?: string
54
+ }
55
+
56
+ type RadioGroupComponent = (props: RadioGroupProps) => any
57
+
58
+ type RadioGroupIndicatorComponent = (props: RadioIndicatorProps) => any
59
+
60
+ type RadioGroupItemComponent = (props: RadioGroupItemProps) => any
61
+
62
+ export function createRadioGroup<
63
+ F extends RadioGroupComponent,
64
+ D extends RadioGroupIndicatorComponent,
65
+ I extends RadioGroupItemComponent,
66
+ >(createProps: { disableActiveTheme?: boolean; Frame?: F; Indicator?: D; Item?: I }) {
67
+ const {
68
+ disableActiveTheme,
69
+ Frame = RadioGroupFrame,
70
+ Indicator = RadioGroupIndicatorFrame,
71
+ Item = RadioGroupItemFrame,
72
+ } = createProps as any as {
73
+ disableActiveTheme?: boolean
74
+ Frame: typeof RadioGroupFrame
75
+ Indicator: typeof RadioGroupIndicatorFrame
76
+ Item: typeof RadioGroupItemFrame
77
+ }
78
+
79
+ ensureContext(Frame)
80
+ ensureContext(Indicator)
81
+ ensureContext(Item)
82
+
83
+ type RadioGroupProps = GetProps<typeof RadioGroupFrame> & {
84
+ value?: string
85
+ defaultValue?: string
86
+ onValueChange?: (value: string) => void
87
+ required?: boolean
88
+ disabled?: boolean
89
+ name?: string
90
+ native?: boolean
91
+ accentColor?: string
92
+ }
93
+
94
+ const RadioGroupImp = Frame.styleable<RadioGroupProps>((props, ref) => {
95
+ const {
96
+ value,
97
+ defaultValue,
98
+ onValueChange,
99
+ required = false,
100
+ disabled = false,
101
+ name,
102
+ native,
103
+ accentColor,
104
+ orientation = 'vertical',
105
+ ...rest
106
+ } = props
107
+
108
+ const { providerValue, frameAttrs, rovingFocusGroupAttrs } = useRadioGroup({
109
+ orientation,
110
+ name,
111
+ defaultValue,
112
+ value,
113
+ onValueChange,
114
+ required,
115
+ disabled,
116
+ native,
117
+ accentColor,
118
+ })
119
+
120
+ return (
121
+ <RadioGroupContext.Provider value={providerValue}>
122
+ <RovingFocusGroup {...rovingFocusGroupAttrs}>
123
+ <RadioGroupFrame {...frameAttrs} ref={ref} {...rest} />
124
+ </RovingFocusGroup>
125
+ </RadioGroupContext.Provider>
126
+ )
127
+ })
128
+
129
+ const RadioGroupItemImp = Item.styleable<RadioGroupItemProps>((props, ref) => {
130
+ const {
131
+ value,
132
+ labelledBy,
133
+ onPress,
134
+ //@ts-expect-error
135
+ onKeyDown,
136
+ disabled,
137
+ id,
138
+ ...rest
139
+ } = props
140
+
141
+ const {
142
+ providerValue,
143
+ bubbleInput,
144
+ rovingFocusGroupAttrs,
145
+ frameAttrs,
146
+ isFormControl,
147
+ native,
148
+ } = useRadioGroupItem({
149
+ radioGroupContext: RadioGroupContext,
150
+ value,
151
+ id,
152
+ labelledBy,
153
+ disabled,
154
+ onPress: onPress!,
155
+ onKeyDown,
156
+ })
157
+
158
+ return (
159
+ <RadioGroupItemContext.Provider value={providerValue}>
160
+ {isWeb && native ? (
161
+ bubbleInput
162
+ ) : (
163
+ <>
164
+ <RovingFocusGroup.Item {...rovingFocusGroupAttrs}>
165
+ <RadioGroupItemFrame {...frameAttrs} ref={ref} {...rest} />
166
+ </RovingFocusGroup.Item>
167
+ {isFormControl && bubbleInput}
168
+ </>
169
+ )}
170
+ </RadioGroupItemContext.Provider>
171
+ )
172
+ })
173
+
174
+ RadioGroupItemImp.displayName = 'RadioGroupItem'
175
+
176
+ const RadioIndicator = Indicator.styleable<RadioIndicatorProps>(
177
+ (props: RadioIndicatorProps, forwardedRef) => {
178
+ const { forceMount, disabled, ...indicatorProps } = props
179
+ const { checked, ...useIndicatorRest } = useRadioGroupItemIndicator({
180
+ radioGroupItemContext: RadioGroupItemContext,
181
+ disabled,
182
+ })
183
+
184
+ if (forceMount || checked) {
185
+ return <Indicator {...useIndicatorRest} ref={forwardedRef} {...indicatorProps} />
186
+ }
187
+
188
+ return null
189
+ }
190
+ )
191
+
192
+ RadioIndicator.displayName = 'RadioIndicator'
193
+
194
+ const RadioGroup = withStaticProperties(RadioGroupImp, {
195
+ Item: RadioGroupItemImp,
196
+ Indicator: RadioIndicator,
197
+ })
198
+ RadioGroup.displayName = 'RadioGroup'
199
+
200
+ return RadioGroup
201
+ }
package/src/index.ts CHANGED
@@ -1 +1,16 @@
1
+ import {
2
+ RadioGroupFrame,
3
+ RadioGroupIndicatorFrame,
4
+ RadioGroupItemFrame,
5
+ } from './RadioGroup'
6
+ import { createRadioGroup } from './createRadioGroup'
7
+
8
+ export * from './createRadioGroup'
1
9
  export * from './RadioGroup'
10
+ export * from './RadioGroupStyledContext'
11
+
12
+ export const RadioGroup = createRadioGroup({
13
+ Frame: RadioGroupFrame,
14
+ Indicator: RadioGroupIndicatorFrame,
15
+ Item: RadioGroupItemFrame,
16
+ })