Skip to content

Commit f77ce69

Browse files
authored
Merge pull request #1073 from objectstack-ai/copilot/upgrade-record-picker-solution
2 parents 8bb67c5 + 7b0765c commit f77ce69

File tree

9 files changed

+1489
-135
lines changed

9 files changed

+1489
-135
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- **RecordPickerDialog Component** (`@object-ui/fields`): New enterprise-grade record selection dialog with multi-column table display, pagination, search, column sorting with `$orderby`, keyboard navigation (Arrow keys + Enter), loading/error/empty states, and single/multi-select support. Responsive layout with mobile-friendly width. Provides the foundation for Salesforce-style Lookup experience.
13+
- **LookupField Popover Typeahead** (`@object-ui/fields`): Level 1 quick-select upgraded from Dialog to Popover for inline typeahead experience (anchored dropdown, not modal). Includes "Show All Results" footer button that opens the full RecordPickerDialog (Level 2).
14+
- **LookupFieldMetadata Schema Enhancement** (`@object-ui/types`): Added `lookup_columns`, `description_field`, `lookup_page_size`, `lookup_filters` to `LookupFieldMetadata`. New `LookupColumnDef` interface with `type` hint for cell formatting. New `LookupFilterDef` interface for base filter configuration.
15+
1016
### Changed
1117

1218
- **@objectstack v3.2.6 Upgrade**: Upgraded all `@objectstack/*` packages from `^3.2.5` to `^3.2.6` across 13 package.json files (43 references)

ROADMAP.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ ObjectUI is a universal Server-Driven UI (SDUI) engine built on React + Tailwind
134134
- [x] Lookup field dynamic DataSource loading — popup fetches records via `DataSource.find()` with `$search` debounce, loading/error/empty states
135135
- [x] Lookup field context DataSource — reads DataSource from SchemaRendererContext so forms work without explicit prop
136136
- [x] Lookup field UX polish — arrow key navigation, description field display, quick-create entry, ARIA listbox roles
137+
- [x] Enterprise Record Picker — `RecordPickerDialog` component with multi-column table, pagination, search; LookupField two-level interaction (quick-select + "Show All Results" → full picker); `lookup_columns` / `lookup_page_size` schema config
137138
- [ ] Form conditional logic with branching
138139
- [ ] Multi-page forms with progress indicator
139140

content/docs/fields/lookup.mdx

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ interface LookupFieldSchema {
7373
7474
// Quick-create callback (shown when no results found)
7575
onCreateNew?: (searchQuery: string) => void;
76+
77+
// === Record Picker Configuration (Enterprise) ===
78+
79+
// Columns to show in the Record Picker dialog table.
80+
// Accepts field names or { field, label, width } objects.
81+
// When omitted, auto-infers from reference_field.
82+
lookup_columns?: Array<string | { field: string; label?: string; width?: string }>;
83+
84+
// Custom page size for the Record Picker dialog (default: 10)
85+
lookup_page_size?: number;
7686
}
7787
7888
interface LookupOption {
@@ -106,6 +116,41 @@ The popup will:
106116
2. Send `$search` queries with 300ms debounce as the user types
107117
3. Show loading spinner, error state with retry, and empty state
108118
4. Display "Showing X of Y" when more records exist than the page size
119+
5. Show a **"Show All Results"** button to open the full Record Picker dialog
120+
121+
## Record Picker Dialog (Enterprise)
122+
123+
When more results are available than displayed in the quick-select popup, a **"Show All Results"** button opens the full **RecordPickerDialog** — an enterprise-grade record selection experience.
124+
125+
```plaintext
126+
// Configure the Record Picker with lookup_columns
127+
{
128+
type: 'lookup',
129+
name: 'order',
130+
label: 'Order',
131+
reference_to: 'orders',
132+
reference_field: 'order_number',
133+
description_field: 'customer_name',
134+
lookup_columns: [
135+
{ field: 'order_number', label: 'Order #' },
136+
{ field: 'customer_name', label: 'Customer' },
137+
{ field: 'total_amount', label: 'Amount' },
138+
{ field: 'status', label: 'Status' },
139+
],
140+
lookup_page_size: 15,
141+
}
142+
```
143+
144+
The Record Picker dialog provides:
145+
- **Multi-column table** with configurable columns via `lookup_columns`
146+
- **Search** with debounced server-side querying
147+
- **Column sorting** via clickable headers (sends `$orderby` to DataSource)
148+
- **Pagination** with page-by-page navigation
149+
- **Keyboard navigation** — Arrow keys to move between rows, Enter/Space to select
150+
- **Single/Multi-select** with visual check indicators and confirmation flow
151+
- **Responsive layout** — Mobile-friendly width (95vw on small screens)
152+
- **Loading, error, and empty states**
153+
- Auto-inferred columns from `reference_field` when `lookup_columns` is not set
109154

110155
## Lookup vs Master-Detail
111156

@@ -133,12 +178,19 @@ import { LookupCellRenderer } from '@object-ui/fields';
133178

134179
## Features
135180

181+
- **Two-Level Interaction**: Popover typeahead (Level 1) + full Record Picker dialog (Level 2)
182+
- **Record Picker Dialog**: Enterprise-grade table with multi-column, pagination, search, sorting
183+
- **Inline Popover**: Level 1 opens as anchored dropdown (non-modal) for fast typeahead
184+
- **Column Sorting**: Clickable column headers with `$orderby` server-side sort
136185
- **Dynamic DataSource Loading**: Automatically fetches records from referenced objects
137186
- **Search**: Debounced type-ahead search with `$search` parameter
138-
- **Multi-Select**: Support for multiple references
139-
- **Keyboard Navigation**: Arrow keys to navigate, Enter to select
187+
- **Multi-Select**: Support for multiple references with confirmation flow
188+
- **Keyboard Navigation**: Arrow keys to navigate rows, Enter to select in both levels
189+
- **Responsive**: Mobile-friendly width, adapts to screen size
140190
- **Loading/Error/Empty States**: Friendly feedback for all states
141191
- **Secondary Field Display**: Show description/subtitle per option
142192
- **Quick-Create Entry**: Optional "Create new" button when no results
143-
- **Pagination Hint**: Shows total count when more results available
193+
- **Configurable Columns**: `lookup_columns` for multi-column picker display
194+
- **Base Filters**: `lookup_filters` to restrict selectable records
195+
- **Pagination**: Page-by-page navigation in Record Picker dialog
144196
- **Backward Compatible**: Falls back to static options when no DataSource

packages/fields/src/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,6 +1327,7 @@ export * from './widgets/PasswordField';
13271327
export * from './widgets/TextAreaField';
13281328
export * from './widgets/RichTextField';
13291329
export * from './widgets/LookupField';
1330+
export * from './widgets/RecordPickerDialog';
13301331
export * from './widgets/FileField';
13311332
export * from './widgets/ImageField';
13321333
export * from './widgets/LocationField';

0 commit comments

Comments
 (0)