# rn-data-gallery URL: /docs/native/docyrus/data-gallery Card gallery for React Native — a TanStack-table-driven FlashList of rich cards (5 variants, 8 field slots, cover styles, density, responsive columns) with toolbar, search, selection bar and paging. API-aligned with the web DataGallery. ## Installation ```bash pnpm dlx @docyrus/cli add @docyrus/rn-data-gallery ``` **Dependencies:** - [@tanstack/react-table](https://www.npmjs.com/package/@tanstack/react-table) - [@shopify/flash-list](https://www.npmjs.com/package/@shopify/flash-list) - [tailwind-variants](https://www.npmjs.com/package/tailwind-variants) `DataGallery` renders the rows of a TanStack table as cards. `useDataGallery` owns the table, the display config and the search state; spread its result onto ` ); } ``` ### Interaction model - Tap a card → `onCardClick(record, rowIndex)`. - Long-press a card → toggle its selection (when row selection is enabled). While cards are selected a bottom selection bar shows the count, **Select all**, your `actions` and a clear button (web: floating `ActionBar`). - Pull to refresh → `onRefresh`; reaching the end → `onEndReached` (infinite paging). - The column count follows `displayConfig.columnCount`, clamped so each card is at least `minCardWidth` wide — one column on phones, more on tablets. ## API Reference ### useDataGallery `useDataGallery(options: UseDataGalleryProps)` accepts every TanStack `TableOptions` (except `pageCount` / `getCoreRowModel`) plus: | Option | Type | Default | Description | |--------|------|---------|-------------| | `data` | `TData[]` | — | Rows (required). | | `columns` | `ColumnDef[]` | — | Columns (required). `meta.cell` drives value rendering. | | `displayConfig` | `Partial` | `DEFAULT_DATA_GALLERY_DISPLAY_CONFIG` | Initial display config (re-hydrated when the prop identity changes). | | `onDisplayConfigChange` | `(config: DataGalleryDisplayConfig) => void` | — | Fires on every display change. | | `enableGrouping` | `boolean` | `false` | Grouping pipeline. | | `enableSearch` | `boolean` | `false` | Client-side global filter from the search input. | | `onSearch` | `(query: string) => void` | — | Debounced (200 ms) search callback (server keyword filtering). | | `minCardWidth` | `number` | `260` | Card width floor for the column clamp. | | `pagingMode` | `'virtual-scroll' \| 'standard'` | `'virtual-scroll'` | `'standard'` adds the paging footer. | | `pageSize` | `number` | `24` | Initial page size (standard paging). | | `initialState` | `InitialTableState` | — | Initial sorting / filters / visibility / order / pinning / grouping / selection / global filter. | | `meta` | `TableMeta` | — | Table meta (formatters, …). | | `dir` | `'ltr' \| 'rtl'` | `'ltr'` | Accepted for parity; ignored (RN uses `I18nManager`). | | `estimatedCardHeight` / `overscan` | `number` | — | Accepted for parity; ignored (FlashList measures cards). | Return value (`UseDataGalleryReturn`): | Field | Type | Description | |-------|------|-------------| | `table` / `tableMeta` | `Table` / `TableMeta` | TanStack table + meta. | | `displayConfig` / `setDisplayConfig` | `DataGalleryDisplayConfig` / `(updater) => void` | Display state. | | `enableSearch`, `searchQuery`, `setSearchQuery` | — | Search state (setter debounces the filter). | | `onClearFilters` / `hasActiveFilters` | `() => void` / `boolean` | Reset column filters + search. | | `selectedRowCount` / `getSelectedRows` | `number` / `() => TData[]` | Selection. | | `columnsPerRow` / `containerWidth` / `onContainerLayout` | `number` / `number` / `(event) => void` | **Native.** Measured layout (replaces web `containerRef` / `virtualizer`). | | `minCardWidth`, `dir`, `pagingMode` | — | Echoed options. | ### DataGallery | Prop | Type | Default | Description | |------|------|---------|-------------| | `table` | `Table` | — | From the hook (required). | | `tableMeta` | `TableMeta` | — | From the hook (required). | | `displayConfig` | `DataGalleryDisplayConfig` | — | From the hook (required). | | `onClearFilters` | `() => void` | — | Empty-state "reset them" action. | | `hasActiveFilters` | `boolean` | `false` | Switches the empty-state copy. | | `selectedRowCount` / `getSelectedRows` / `columnsPerRow` | — | — | Accepted from the hook spread (selection is read from the table state; columns are measured). | | `onContainerLayout` | `(event: LayoutChangeEvent) => void` | — | **Native.** Keeps the hook's `columnsPerRow` in sync. | | `minCardWidth` | `number` | `260` | Card width floor for the column clamp. | | `pagingMode` | `'virtual-scroll' \| 'standard'` | `'virtual-scroll'` | `'standard'` renders `DataGridPaginationFooter`. | | `height` | `number \| 'auto'` | `'auto'` | dp height, or fill the parent. | | `cardConfig` | `DataGalleryCardConfig` | — | Slot bindings + render hooks. | | `actions` | `DataGalleryAction[]` | — | Selection-bar actions. | | `onCardClick` | `(record: TData, rowIndex: number) => void` | — | Card tap. | | `onAdd` / `addLabel` | `() => void` / `string` | — / `'Add card'` | "+ Add card" action after the cards. | | `isReloading` | `boolean` | `false` | Background refetch indicator. | | `startContent` / `endContent` | `ReactNode` | — | Slots above / below the cards. | | `onRefresh` | `() => void` | — | **Native.** Pull-to-refresh. | | `refreshing` | `boolean` | `isReloading` | **Native.** Pull-to-refresh spinner. | | `onEndReached` | `() => void` | — | **Native.** Infinite paging. | | `emptyText` | `string` | — | **Native.** Empty-state title override. | | `dir` | `'ltr' \| 'rtl'` | — | Accepted for parity. | | `className` | `string` | — | Root classes. | `DataGalleryAction`: `key?`, `label`, `icon?: ReactNode`, `variant?: 'default' | 'destructive'`, `onAction?(rows)`, `render?(rows)`. ### DataGalleryToolbar | Prop | Type | Default | Description | |------|------|---------|-------------| | `table` | `Table` | — | Required. | | `displayConfig` / `onDisplayConfigChange` | config / updater | — | Required — drives the display menu. | | `cardConfig` / `onCardConfigChange` | `DataGalleryCardConfigSerializable` / updater | — | Card field bindings (card-config menu). | | `searchQuery` / `onSearchQueryChange` | `string` / `(value) => void` | `''` | Search input (shown when `onSearchQueryChange` is set). | | `enableSearch` | `boolean` | `true` | Search input. | | `enableFilter` | `boolean` | `true` | `DataGridFilterMenu`. | | `enableSort` | `boolean` | `true` | `DataGridSortMenu`. | | `enableGroup` | `boolean` | `false` | `DataGridGroupMenu`. | | `enableDisplay` | `boolean` | `true` | `DataGalleryDisplayMenu`. | | `enableCardConfig` | `boolean` | `false` | `DataGalleryCardConfigMenu`. | | `enableView` | `boolean` | `false` | `DataGridViewMenu` (local saved views). | | `viewStorageKey` | `string` | — | Saved-view namespace. | | `disabled` | `boolean` | `false` | Disable every control. | | `startContent` / `endContent` | `ReactNode` | — | Slots. | | `onAdd` / `addLabel` | `() => void` / `string` | — / `'Add'` | Add button. | | `className` | `string` | — | Root classes. | ### DataGallerySearch | Prop | Type | Default | Description | |------|------|---------|-------------| | `value` | `string` | — | Current value. | | `onChange` | `(value: string) => void` | — | Change handler (debounce upstream). | | `placeholder` | `string` | `'Search...'` | Placeholder. | | `disabled` | `boolean` | `false` | Disable the input. | | `className` | `string` | — | Classes. | ### DataGalleryCard | Prop | Type | Description | |------|------|-------------| | `row` / `table` / `tableMeta` | TanStack | Row to render. | | `cardConfig` | `DataGalleryCardConfig` | Slots + render hooks. | | `displayConfig` | `DataGalleryDisplayConfig` | Display config. | | `enableSelection` | `boolean` | Long-press toggles selection + checkbox. | | `onCardClick` | `(record, rowIndex) => void` | Card tap. | | `className` | `string` | **Native.** Card classes. | ### DataGalleryDisplayConfig | Field | Type | Default | |-------|------|---------| | `columnCount` | `'flex' \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | `'flex'` | | `cardSize` | `'full' \| 'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| '3xl' \| '4xl'` | `'full'` | | `density` | `'compact' \| 'comfortable'` | `'comfortable'` | | `coverStyle` | `'none' \| 'top-sm' \| 'top-md' \| 'top-lg' \| 'left'` | `'top-md'` | | `layoutOrientation` | `'vertical' \| 'horizontal'` | `'vertical'` | | `showFieldLabels` / `showCardHeader` / `showCardFooter` | `boolean` | `true` / `true` / `false` | | `cardVariant` | `'detailed' \| 'compact' \| 'media' \| 'profile' \| 'product'` | `'detailed'` | ### DataGalleryCardConfig Serializable slots (`DataGalleryCardConfigSerializable`): `titleField`, `descriptionField`, `subtitleField`, `avatarField`, `coverImageField`, `badgeField`, `timelineField` (column ids), `bodyFields`, `footerFields` (column id arrays), `variant`. Render hooks: `renderCard({ record, rowIndex, isSelected, onToggleSelected })`, `renderCover({ record, value })`, `renderAvatar({ record, value })`, `renderBadge({ record, value })`, `renderTimeline({ record, value })`, `renderActions({ record, rowIndex })`. ## Components | Component | Description | |-----------|-------------| | `DataGallery` | FlashList card gallery. | | `DataGalleryToolbar` | Search + scrollable menu chips. | | `DataGallerySearch` | Search input. | | `DataGalleryCard` | Card engine (shared with the grid's gallery mode). | | `DataGalleryCardField` | One labelled field value inside a card. | | `DataGalleryDisplayMenu` | Display sheet (variant, columns, size, density, cover, toggles). | | `DataGalleryCardConfigMenu` | Card slot bindings sheet. | | `DataGallerySkeleton` / `DataGallerySkeletonGrid` / `DataGallerySkeletonToolbar` | Loading placeholders. | ## Exports | Export | Kind | |--------|------| | `useDataGallery` | Hook | | `resolveColumnsPerRow`, `resolveImageUrl`, `resolveCardLayout`, `resolveBodyFields`, `getCardSizePx`, `getCoverHeightPx`, `getCellValue`, `getRawCellValue`, `getCellOpts`, `getColumnLabel`, `detectCardConfigFromFields` | Helpers | | `SYSTEM_AUDIT_SLUGS`, `VARIANT_DISPLAY_PRESETS`, `VARIANT_VISUAL_DEFAULTS`, `DEFAULT_GAP`, `DEFAULT_MIN_CARD_WIDTH` | Constants | | `DATA_GALLERY_DEFAULT_PAGE_SIZE`, `DATA_GALLERY_PAGE_SIZE_OPTIONS`, `DEFAULT_DATA_GALLERY_DISPLAY_CONFIG`, `isSavedDataGalleryView` | Constants / guards | ## Type Exports | Type | Description | |------|-------------| | `UseDataGalleryProps` / `UseDataGalleryReturn` | Hook options / return. | | `DataGalleryProps`, `DataGalleryToolbarProps`, `DataGallerySearchProps`, `DataGalleryCardProps`, `DataGalleryCardFieldProps`, `DataGalleryDisplayMenuProps`, `DataGalleryCardConfigMenuProps`, `DataGallerySkeleton*Props` | Component props. | | `DataGalleryAction` | Selection-bar action. | | `DataGalleryCardConfig`, `DataGalleryCardConfigSerializable` | Card configuration. | | `DataGalleryDisplayConfig`, `DataGalleryCardVariant`, `DataGalleryColumnCount`, `DataGalleryCardSize`, `DataGalleryCoverStyle`, `DataGalleryLayoutOrientation`, `DataGalleryDensity`, `DataGalleryPagingMode` | Display unions. | | `SavedDataGalleryView` | Saved view shape. | ## Native deltas - FlashList with `numColumns` replaces `@tanstack/react-virtual`; the width is measured with `onLayout` (web: `ResizeObserver`). `containerRef` / `virtualizer` are gone; `dir`, `estimatedCardHeight`, `overscan` are accepted and ignored. - Long-press selects (no hover checkbox); the selection bar is the grid's bottom bar. - Toolbar = search on top + one horizontally scrollable row of chips opening bottom sheets. - Additions: `onRefresh` / `refreshing`, `onEndReached`, `emptyText`, `onContainerLayout`. ## Translation keys `ui.dataGallery.addCard`, `add`, `searchPlaceholder`, `emptyTitle`, `emptyDescription`, `emptyFilteredTitle`, `emptyFilteredHint`, `clearFilters` (web keys), plus the grid's `ui.dataGrid.selectAll` / `clearSelection` for the selection bar.