Lynx/Modules/Gestures/Swiper
@sigx/lynx-gestures · Stable · Component library

Swiper#

A paged horizontal carousel built on a native paging scroll-view. It renders items into page-sized wrappers, writes the live pixel offset into a SharedValue each main-thread frame, supports a controlled index with native scrollTo glide, and emits pageChange.

Import#

TSX
import { Swiper } from '@sigx/lynx-gestures';

Basic usage#

items and renderItem are the only required props — renderItem receives each item and its index and returns the page content. Each item is laid out into a page-sized wrapper.

TSX
import { Swiper } from '@sigx/lynx-gestures';

function Gallery({ photos }: { photos: string[] }) {
    return (
        <Swiper
            items={photos}
            height={480}
            renderItem={(src) => (
                <image src={src} mode="aspectFit" style={{ width: '100%', height: '100%' }} />
            )}
            onPageChange={(e) => console.log('page', e.index)}
        />
    );
}

width defaults to the measured container width, then lynx.SystemInfo.pixelWidth / pixelRatio (fallback 400); height falls back to the measured height then 800. keyExtractor defaults to the array index.

Controlled paging#

Pass a PrimitiveSignal to index for controlled paging — writing the signal glides to that page via native scrollTo, and the swiper writes it back as the user pages. Use initialIndex for an uncontrolled starting page.

TSX
import { Swiper } from '@sigx/lynx-gestures';
import { signal } from '@sigx/reactivity';

function Carousel({ slides }: { slides: string[] }) {
    const index = signal(0);

    return (
        <Swiper
            items={slides}
            index={index}
            height={320}
            renderItem={(label) => (
                <view style={{ justifyContent: 'center', alignItems: 'center' }}>
                    <text>{label}</text>
                </view>
            )}
            onPageChange={(e) => { index.value = e.index; }}
        />
    );
}

Driving indicators from offset#

Pass a SharedValue to offset to read the live main-thread pixel offset and drive dot indicators. The headless useSwiperDot* hooks each return a MainThreadRef you spread onto a dot element and animate one transform channel from that offset.

TSX
import { Swiper, useSwiperDotProgress } from '@sigx/lynx-gestures';
import { useSharedValue } from '@sigx/lynx';

function Gallery({ photos }: { photos: string[] }) {
    const offset = useSharedValue(0);
    const pageWidth = 360;

    return (
        <view>
            <Swiper
                items={photos}
                offset={offset}
                width={pageWidth}
                height={480}
                renderItem={(src) => (
                    <image src={src} mode="aspectFit" style={{ width: '100%', height: '100%' }} />
                )}
            />
            <view style={{ flexDirection: 'row' }}>
                {photos.map((_, i) => (
                    <Dot offset={offset} pageWidth={pageWidth} index={i} />
                ))}
            </view>
        </view>
    );
}

function Dot({ offset, pageWidth, index }: {
    offset: ReturnType<typeof useSharedValue<number>>;
    pageWidth: number;
    index: number;
}) {
    const ref = useSwiperDotProgress({ offset, pageWidth, index });
    return (
        <view
            main-thread:ref={ref}
            style={{ width: '8px', height: '8px', borderRadius: '4px', backgroundColor: 'tomato', opacity: '0' }}
        />
    );
}

For themed, ready-made indicators use SwiperIndicator from @sigx/lynx-zero (also re-exported from @sigx/lynx-daisyui).

Props#

Swiper is generic over the item type T: Swiper<T>(props: SwiperProps<T>).

PropTypeDescription
itemsreadonly T[]Required. The pages to render, one per array element.
renderItem(item: T, index: number) => unknownRequired. Renders the content for each page.
keyExtractor(item: T, index: number) => string | numberStable key per item. Defaults to the array index.
widthnumberPage width in CSS pixels. Defaults to the measured container width, then lynx.SystemInfo.pixelWidth / pixelRatio (fallback 400).
heightnumber | stringPage height. Falls back to the measured height then 800.
indexPrimitiveSignal<number>Controlled current page. Writing it glides via native scrollTo; the swiper writes it back on page change.
initialIndexnumberStarting page when uncontrolled.
offsetSharedValue<number>Live main-thread pixel offset, written each frame — spread into useSwiperDot* hooks.
classstringExtra CSS classes.
styleRecord<string, string | number>Inline styles. Keep structurally stable across renders.

Events#

EventTypeDescription
onPageChange(e: { index: number }) => voidFired when the active page changes.

See also#

  • Usage guide — the full gesture set, end to end.
  • API reference — every export, including the useSwiperDot* indicator hooks, typed.