WheelPickerGroupNew

A coordinated row of `WheelPicker` instances that share layout, emit a composite values record, and report when every wheel has come to rest.

Import

import { WheelPicker, WheelPickerGroup } from 'heroui-native-pro';

Anatomy

<WheelPickerGroup>
  <WheelPicker name="..." items={[...]} />
  <WheelPicker name="..." items={[...]} />
  <WheelPickerGroup.Indicator />
  <WheelPickerGroup.Mask />
</WheelPickerGroup>
  • WheelPickerGroup: Root container. Owns a shared controllable values record keyed by each child wheel's name, broadcasts itemHeight / visibleCount to the group, coordinates cross-wheel scroll syncing, and cascades animation="disable-all" to all child wheels. Child wheels nested in the group automatically receive flex-1 so they distribute the row evenly.
  • WheelPickerGroup.Indicator: Optional shared selection band spanning every wheel at the center of the group viewport. Replaces the per-wheel indicator when a WheelPicker is nested in the group.
  • WheelPickerGroup.Mask: Optional top / bottom fade overlays spanning the full group viewport.

Usage

Basic usage

Compose a row of WheelPicker instances inside the group. Each child wheel declares a unique name and the group keys the shared values record by that name.

const [values, setValues] = useState({ currency: 'USD', amount: 100 });

<WheelPickerGroup values={values} onValuesChange={setValues}>
  <WheelPicker name="currency" items={CURRENCY_ITEMS} />
  <WheelPicker name="amount" items={AMOUNT_ITEMS} />
  <WheelPickerGroup.Indicator />
  <WheelPickerGroup.Mask />
</WheelPickerGroup>;

Uncontrolled

Pass defaultValues to seed the initial selections without managing external state.

<WheelPickerGroup
  defaultValues={{ currency: 'USD', amount: 100 }}
  onValuesChange={(next) => console.log(next)}
>
  <WheelPicker name="currency" items={CURRENCY_ITEMS} />
  <WheelPicker name="amount" items={AMOUNT_ITEMS} />
  <WheelPickerGroup.Indicator />
  <WheelPickerGroup.Mask />
</WheelPickerGroup>

Item height and visible count

itemHeight and visibleCount are set on the group and shared across every wheel. visibleCount must be odd.

<WheelPickerGroup
  defaultValues={{ currency: 'USD', amount: 100 }}
  itemHeight={56}
  visibleCount={5}
>
  <WheelPicker name="currency" items={CURRENCY_ITEMS} />
  <WheelPicker name="amount" items={AMOUNT_ITEMS} />
  <WheelPickerGroup.Indicator />
  <WheelPickerGroup.Mask />
</WheelPickerGroup>

Custom indicator

Style the shared selection band via classNames on WheelPickerGroup.Indicator, or pass any children for decorative content rendered inside the highlight slot (patterns, gradients, icons). The indicator spans every wheel column. Pair with overflow-hidden on the highlight when the children should be clipped to the rounded corners.

<WheelPickerGroup defaultValues={{ currency: 'USD', amount: 100 }}>
  <WheelPicker name="currency" items={CURRENCY_ITEMS} />
  <WheelPicker name="amount" items={AMOUNT_ITEMS} />
  <WheelPickerGroup.Indicator
    classNames={{
      highlight: 'bg-accent-soft border border-accent/15 overflow-hidden',
    }}
  >
    <MyIndicatorPattern />
  </WheelPickerGroup.Indicator>
  <WheelPickerGroup.Mask />
</WheelPickerGroup>

Custom mask color

Override the fade color when the group sits on a non-background surface. Combine with height (number or percentage) to control how far the fade extends.

const overlayColor = useThemeColor('overlay');

<WheelPickerGroup defaultValues={{ currency: 'USD', amount: 100 }}>
  <WheelPicker name="currency" items={CURRENCY_ITEMS} />
  <WheelPicker name="amount" items={AMOUNT_ITEMS} />
  <WheelPickerGroup.Indicator />
  <WheelPickerGroup.Mask color={overlayColor} height="75%" />
</WheelPickerGroup>;

Commit on rest

onValuesCommit fires exactly once after every wheel in the group has come to rest. Use it to commit a composite selection without listening to intermediate scroll updates.

<WheelPickerGroup
  defaultValues={{ currency: 'USD', amount: 100 }}
  onValuesCommit={(next) => submitOrder(next)}
>
  <WheelPicker name="currency" items={CURRENCY_ITEMS} />
  <WheelPicker name="amount" items={AMOUNT_ITEMS} />
  <WheelPickerGroup.Indicator />
  <WheelPickerGroup.Mask />
</WheelPickerGroup>

Disable animations

Pass animation="disable-all" on the group to cascade the disabled state to every child wheel (rows snap without fading or scaling, and any animated descendants of a child wheel are also disabled).

<WheelPickerGroup
  defaultValues={{ currency: 'USD', amount: 100 }}
  animation="disable-all"
>
  <WheelPicker name="currency" items={CURRENCY_ITEMS} />
  <WheelPicker name="amount" items={AMOUNT_ITEMS} />
  <WheelPickerGroup.Indicator />
  <WheelPickerGroup.Mask />
</WheelPickerGroup>

Disabled

Block interaction and dim the group with isDisabled. Each child wheel can still set its own isDisabled independently.

<WheelPickerGroup
  defaultValues={{ currency: 'USD', amount: 100 }}
  isDisabled
>
  <WheelPicker name="currency" items={CURRENCY_ITEMS} />
  <WheelPicker name="amount" items={AMOUNT_ITEMS} />
  <WheelPickerGroup.Indicator />
  <WheelPickerGroup.Mask />
</WheelPickerGroup>

Example

import { WheelPicker, WheelPickerGroup } from 'heroui-native-pro';
import { useState } from 'react';
import { Text, View } from 'react-native';

const CURRENCY_ITEMS = [
  { value: 'USD', label: 'USD' },
  { value: 'EUR', label: 'EUR' },
  { value: 'GBP', label: 'GBP' },
  { value: 'JPY', label: 'JPY' },
  { value: 'CAD', label: 'CAD' },
];

const AMOUNT_ITEMS = [50, 100, 200, 500, 1000, 2500, 5000].map((amount) => ({
  value: amount,
  label: String(amount),
}));

export default function TransferAmountPicker() {
  const [values, setValues] = useState<Record<string, unknown>>({
    currency: 'USD',
    amount: 500,
  });

  return (
    <View className="flex-1 items-center justify-center px-5">
      <View className="items-center gap-6">
        <View className="items-center gap-1">
          <Text className="text-xs text-muted uppercase tracking-wider">
            Send
          </Text>
          <Text className="text-3xl font-bold text-foreground tabular-nums">
            {String(values.currency)} {String(values.amount)}
          </Text>
        </View>
        <View className="w-[280px]">
          <WheelPickerGroup values={values} onValuesChange={setValues}>
            <WheelPicker name="currency" items={CURRENCY_ITEMS} />
            <WheelPicker name="amount" items={AMOUNT_ITEMS} />
            <WheelPickerGroup.Indicator />
            <WheelPickerGroup.Mask />
          </WheelPickerGroup>
        </View>
      </View>
    </View>
  );
}

API Reference

WheelPickerGroup

proptypedefaultdescription
childrenReact.ReactNode-Compound children. Typically a sequence of WheelPicker instances, optionally accompanied by WheelPickerGroup.Indicator and Mask
valuesWheelPickerGroupValues-Controlled values record. Keyed by each child wheel's name
defaultValuesWheelPickerGroupValues-Uncontrolled initial values record. Keyed by each child wheel's name
itemHeightnumber44Pixel height of a single row, shared by all child wheels
visibleCountnumber5Number of visible rows, shared by all child wheels. Must be odd
isDisabledbooleanfalseDisables interaction for the whole group. Each child wheel may also be disabled locally
classNamestring-Additional CSS classes for the root container
onValuesChange(values: WheelPickerGroupValues) => void-Fires when any wheel's value changes — during scroll, on tap-to-focus, and on imperative scrolls. Not fired on external values updates
onValuesCommit(values: WheelPickerGroupValues) => void-Fires exactly once after every wheel in the group has come to rest
animationWheelPickerGroupRootAnimation-Animation configuration. Cascades disable-all to every child wheel
refWheelPickerGroupRootRef-Forwarded to the underlying root View
...ViewPropsOmit<ViewProps, 'children'>-All standard React Native View props are supported

WheelPickerGroupValues

Shared values record exchanged with the group through values, defaultValues, and onValuesChange / onValuesCommit.

keytypedescription
[name]unknownOne entry per child wheel, keyed by the wheel's name prop. The value type is unknown to allow heterogeneous wheels

WheelPickerGroupRootAnimation

Animation configuration for the group root. The group has no animated styles of its own — this prop only controls the disable-all cascade to every child wheel.

  • "disable-all": Disable all animations including children (cascades to every child WheelPicker)
  • undefined: Use default animations

WheelPickerGroup.Indicator

proptypedefaultdescription
childrenReact.ReactNode-Optional content rendered inside the indicator's highlight slot (patterns, gradients, icons). Pair with overflow-hidden on the highlight so the content is clipped to the rounded corners
classNamestring-Additional CSS classes for the indicator container
classNamesElementSlots<WheelPickerGroupIndicatorSlots>-Additional CSS classes for individual indicator slots
stylesPartial<Record<WheelPickerGroupIndicatorSlots, ViewStyle>>-Inline styles for individual indicator slots
...ViewPropsViewProps-All standard React Native View props are supported

ElementSlots<WheelPickerGroupIndicatorSlots>

slotdescription
wrapperAbsolutely-positioned band centered on the group viewport
highlightFilled rectangle rendered inside the wrapper

styles

slottypedescription
wrapperViewStyleInline style for the indicator wrapper
highlightViewStyleInline style for the indicator highlight

WheelPickerGroup.Mask

proptypedefaultdescription
colorstringuseThemeColor('background')Solid color the gradient fades from. Accepts any RN color string. Falls back to the theme background color when omitted
heightnumber | string"100%"Height of each mask half. number = raw pixels; percentage scales the default fade height (((visibleCount - 1) / 4) * itemHeight)
classNamestring-Additional CSS classes applied to both mask halves
classNamesElementSlots<WheelPickerGroupMaskSlots>-Additional CSS classes for individual mask slots
stylesPartial<Record<WheelPickerGroupMaskSlots, ViewStyle>>-Inline styles for individual mask slots
...ViewPropsOmit<ViewProps, 'children'>-All standard React Native View props are supported

ElementSlots<WheelPickerGroupMaskSlots>

slotdescription
topTop fade overlay
bottomBottom fade overlay

styles

slottypedescription
topViewStyleInline style for the top fade overlay
bottomViewStyleInline style for the bottom fade overlay

Hooks

useWheelPickerGroup

Hook to access the WheelPickerGroup context. Must be used within a WheelPickerGroup component.

import { useWheelPickerGroup } from 'heroui-native-pro';

const { itemHeight, visibleCount, getValue, setValue } = useWheelPickerGroup();

Returns: WheelPickerGroupContextValue

propertytypedescription
itemHeightnumberResolved row height shared across the group's wheels
visibleCountnumberNumber of visible rows shared across the group's wheels
isDisabledbooleanWhether the group as a whole is disabled
getValue(name: string) => unknownRead the current value for the wheel identified by name
setValue(name: string, value: unknown) => voidWrite the value for the wheel identified by name. Merges into the group's values record
notifyScrollState(isScrolling: boolean) => voidNotify the group that one of its wheels has started or stopped scrolling. Used internally by child wheels
isAnyWheelScrolling() => booleanReturns true while at least one wheel in the group is scrolling

On this page