Skip to content

Commit 6f59880

Browse files
Copilothotlong
andcommitted
feat: add RecordPickerDialog and upgrade LookupField with two-level interaction
- Add lookup_columns, description_field, lookup_page_size to LookupFieldMetadata type - Add LookupColumnDef interface for column configuration - Create RecordPickerDialog component with multi-column table, pagination, search - Upgrade LookupField with "Show All Results" button to open RecordPickerDialog - Export RecordPickerDialog from @object-ui/fields Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 8db7016 commit 6f59880

5 files changed

Lines changed: 533 additions & 4 deletions

File tree

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';

packages/fields/src/widgets/LookupField.tsx

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ import {
99
Input,
1010
Badge
1111
} from '@object-ui/components';
12-
import { Search, X, Loader2, AlertCircle, Plus } from 'lucide-react';
12+
import { Search, X, Loader2, AlertCircle, Plus, TableProperties } from 'lucide-react';
1313
import { FieldWidgetProps } from './types';
14-
import type { DataSource, QueryParams } from '@object-ui/types';
14+
import type { DataSource, QueryParams, LookupColumnDef } from '@object-ui/types';
15+
import { RecordPickerDialog } from './RecordPickerDialog';
1516

1617
export interface LookupOption {
1718
value: string | number;
@@ -20,7 +21,7 @@ export interface LookupOption {
2021
[key: string]: any;
2122
}
2223

23-
/** Default page size for lookup data fetching */
24+
/** Page size for the quick-select popover typeahead */
2425
const LOOKUP_PAGE_SIZE = 50;
2526

2627
/**
@@ -99,6 +100,10 @@ export function LookupField({ value, onChange, field, readonly, ...props }: Fiel
99100
// ObjectStack convention uses `reference`; types define `reference_to` — support both
100101
const referenceTo: string | undefined = fieldMeta?.reference_to || fieldMeta?.reference;
101102

103+
// Enterprise Record Picker configuration
104+
const lookupColumns: Array<string | LookupColumnDef> | undefined = fieldMeta?.lookup_columns;
105+
const lookupPageSize: number | undefined = fieldMeta?.lookup_page_size;
106+
102107
// Resolve DataSource: explicit prop > field-level > wrapper field > SchemaRendererContext > none
103108
const ctx = useContext(SchemaRendererContext);
104109
const contextDataSource = ctx?.dataSource ?? null;
@@ -111,6 +116,9 @@ export function LookupField({ value, onChange, field, readonly, ...props }: Fiel
111116
const onCreateNew: ((searchQuery: string) => void) | undefined =
112117
(props as any).onCreateNew ?? lookupField?.onCreateNew;
113118

119+
// State for the full Record Picker dialog (Level 2)
120+
const [isPickerOpen, setIsPickerOpen] = useState(false);
121+
114122
// Determine which options to display
115123
const allOptions = hasDataSource ? fetchedOptions : staticOptions;
116124

@@ -458,9 +466,24 @@ export function LookupField({ value, onChange, field, readonly, ...props }: Fiel
458466
{/* Show total count when fetched from DataSource */}
459467
{hasDataSource && totalCount > filteredOptions.length && (
460468
<p className="text-xs text-muted-foreground text-center py-2">
461-
Showing {filteredOptions.length} of {totalCount} results. Refine your search to find more.
469+
Showing {filteredOptions.length} of {totalCount} results.
462470
</p>
463471
)}
472+
{/* "Show All Results" button — opens the full Record Picker (Level 2) */}
473+
{hasDataSource && totalCount > filteredOptions.length && (
474+
<button
475+
type="button"
476+
className="w-full text-center px-3 py-2 rounded-md text-sm font-medium text-primary hover:bg-accent flex items-center justify-center gap-1.5"
477+
onClick={() => {
478+
setIsOpen(false);
479+
setIsPickerOpen(true);
480+
}}
481+
data-testid="show-all-results"
482+
>
483+
<TableProperties className="size-3.5" />
484+
Show All Results ({totalCount})
485+
</button>
486+
)}
464487
{/* Quick-create entry (below results) */}
465488
{onCreateNew && (
466489
<button
@@ -482,6 +505,24 @@ export function LookupField({ value, onChange, field, readonly, ...props }: Fiel
482505
</div>
483506
</DialogContent>
484507
</Dialog>
508+
509+
{/* Level 2: Full Record Picker Dialog */}
510+
{hasDataSource && dataSource && referenceTo && (
511+
<RecordPickerDialog
512+
open={isPickerOpen}
513+
onOpenChange={setIsPickerOpen}
514+
title={lookupField?.label || 'Select'}
515+
multiple={multiple}
516+
dataSource={dataSource}
517+
objectName={referenceTo}
518+
columns={lookupColumns}
519+
displayField={displayField}
520+
idField={idField}
521+
pageSize={lookupPageSize}
522+
value={value}
523+
onSelect={onChange}
524+
/>
525+
)}
485526
</div>
486527
);
487528
}

0 commit comments

Comments
 (0)