@object-ui/fields 3.1.3 → 3.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/AddressField-B6fPb2Fs.js +3 -0
  2. package/dist/AddressField-Ctsxkj35.cjs +1 -0
  3. package/dist/AutoNumberField-DXIYJfiB.js +3 -0
  4. package/dist/AutoNumberField-f76XU1bR.cjs +1 -0
  5. package/dist/AvatarField-BHpex3Wa.js +3 -0
  6. package/dist/AvatarField-CXOdYavl.cjs +1 -0
  7. package/dist/BooleanField-Bs0urhsx.js +3 -0
  8. package/dist/BooleanField-DeexI_O2.cjs +1 -0
  9. package/dist/CodeField-DDOMH8E8.cjs +1 -0
  10. package/dist/CodeField-tRACqngO.js +3 -0
  11. package/dist/ColorField-Bar6bOJw.js +3 -0
  12. package/dist/ColorField-CM9CxZ9h.cjs +1 -0
  13. package/dist/CurrencyField-CezTX_rA.cjs +1 -0
  14. package/dist/CurrencyField-D4VwXI9k.js +3 -0
  15. package/dist/DateField-DDUllj7w.cjs +1 -0
  16. package/dist/DateField-DjGiK6BH.js +3 -0
  17. package/dist/DateTimeField-DBh-dYdR.js +3 -0
  18. package/dist/DateTimeField-DDqgVN3b.cjs +1 -0
  19. package/dist/EmailField-B-3nY8Pr.cjs +1 -0
  20. package/dist/EmailField-Cp6yJlpH.js +3 -0
  21. package/dist/FileField-C1bcL7tu.cjs +1 -0
  22. package/dist/FileField-DUgt6ai3.js +3 -0
  23. package/dist/FormulaField-BLV1KgkQ.js +3 -0
  24. package/dist/FormulaField-CsbQIZ7S.cjs +1 -0
  25. package/dist/GeolocationField-BbIRH51u.js +3 -0
  26. package/dist/GeolocationField-UFu9VR-x.cjs +1 -0
  27. package/dist/GridField-2m74haE0.cjs +1 -0
  28. package/dist/GridField-O3Jd1NuJ.js +3 -0
  29. package/dist/ImageField-Cna7g6KL.cjs +1 -0
  30. package/dist/ImageField-rc1Nzcvb.js +3 -0
  31. package/dist/LocationField-DpRe9QlH.cjs +1 -0
  32. package/dist/LocationField-QZPPYo0J.js +3 -0
  33. package/dist/LookupField-BX4sK8NG.js +904 -0
  34. package/dist/LookupField-C9rPrHi_.cjs +1 -0
  35. package/dist/MasterDetailField-BXncIT1s.js +3 -0
  36. package/dist/MasterDetailField-TNP2825Z.cjs +1 -0
  37. package/dist/NumberField-DCHTzmDG.js +3 -0
  38. package/dist/NumberField-SqRwbcY8.cjs +1 -0
  39. package/dist/ObjectField-BEUHpn_X.js +3 -0
  40. package/dist/ObjectField-BWZwaFIG.cjs +1 -0
  41. package/dist/PasswordField-BZ_OeQyw.js +3 -0
  42. package/dist/PasswordField-kLp-ZyPm.cjs +1 -0
  43. package/dist/PercentField-B2t2knlc.js +3 -0
  44. package/dist/PercentField-BzhD6tQm.cjs +1 -0
  45. package/dist/PhoneField-CirvuysP.cjs +1 -0
  46. package/dist/PhoneField-CkrCFmcO.js +3 -0
  47. package/dist/QRCodeField-C4OOLCbE.cjs +1 -0
  48. package/dist/QRCodeField-CQoGow8y.js +3 -0
  49. package/dist/RatingField-CZG8SgQ8.cjs +1 -0
  50. package/dist/RatingField-DecDJkou.js +3 -0
  51. package/dist/RichTextField-Bog2i4NN.cjs +1 -0
  52. package/dist/RichTextField-b-8QbNCJ.js +3 -0
  53. package/dist/SelectField-CAa6c0cB.cjs +1 -0
  54. package/dist/SelectField-DMy5IxRc.js +3 -0
  55. package/dist/SignatureField-BvTPE7Dn.js +3 -0
  56. package/dist/SignatureField-jsb-0AYp.cjs +1 -0
  57. package/dist/SliderField-B7WvKFv7.js +3 -0
  58. package/dist/SliderField-DRjEJSxK.cjs +1 -0
  59. package/dist/SummaryField-DA16Edq3.cjs +1 -0
  60. package/dist/SummaryField-DVSVfKmY.js +3 -0
  61. package/dist/TextAreaField--ut87UiB.js +3 -0
  62. package/dist/TextAreaField-Cxp3DFC6.cjs +1 -0
  63. package/dist/TextField-CkEDGbkQ.js +3 -0
  64. package/dist/TextField-aLAzBaLZ.cjs +1 -0
  65. package/dist/TimeField-D0lF0y_I.cjs +1 -0
  66. package/dist/TimeField-DA_S6lQV.js +3 -0
  67. package/dist/UrlField-D0ugmD3f.cjs +1 -0
  68. package/dist/UrlField-DCnXHR1A.js +3 -0
  69. package/dist/UserField-DGlorzyG.cjs +1 -0
  70. package/dist/UserField-V0GmvyGV.js +3 -0
  71. package/dist/VectorField-BSD85ntU.cjs +1 -0
  72. package/dist/VectorField-CVi5yrrc.js +3 -0
  73. package/dist/fields/src/index.d.ts +1 -0
  74. package/dist/fields/src/record-picker-dialog.stories.d.ts +25 -0
  75. package/dist/fields/src/record-picker.test.d.ts +1 -0
  76. package/dist/fields/src/widgets/RecordPickerDialog.d.ts +166 -0
  77. package/dist/fields/src/widgets/_cell-renderer-bridge.d.ts +3 -0
  78. package/dist/index.cjs +4 -9
  79. package/dist/index.js +2229 -2850
  80. package/dist/jsx-runtime-DHCF5ANT.cjs +6 -0
  81. package/dist/jsx-runtime-MxADXuRH.js +189 -0
  82. package/package.json +7 -6
  83. package/src/index.tsx +6 -0
  84. package/src/record-picker-dialog.stories.tsx +160 -0
  85. package/src/record-picker.test.tsx +1696 -0
  86. package/src/widgets/LookupField.tsx +254 -150
  87. package/src/widgets/RecordPickerDialog.tsx +1182 -0
  88. package/src/widgets/_cell-renderer-bridge.ts +19 -0
@@ -0,0 +1 @@
1
+ const e=require(`./jsx-runtime-DHCF5ANT.cjs`);let t=require(`react`);t=e.r(t);let n=require(`@object-ui/components`),r=require(`lucide-react`),i=require(`@object-ui/react`);var a=e.t(),o=10,s=60,ee=5;function c(e){return typeof e==`string`?{field:e}:e}function l(e){return e.replace(/_/g,` `).replace(/([a-z])([A-Z])/g,`$1 $2`).replace(/\b\w/g,e=>e.toUpperCase())}function u(e){let t={};for(let n of e)switch(n.operator){case`eq`:t[n.field]=n.value;break;case`ne`:t[n.field]={$ne:n.value};break;case`gt`:t[n.field]={$gt:n.value};break;case`lt`:t[n.field]={$lt:n.value};break;case`gte`:t[n.field]={$gte:n.value};break;case`lte`:t[n.field]={$lte:n.value};break;case`contains`:t[n.field]={$contains:n.value};break;case`in`:t[n.field]={$in:n.value};break;case`notIn`:t[n.field]={$nin:n.value};break}return t}function te(e,t){let n={};for(let r of t){let t=e[r.field];t==null||t===``||(r.type===`boolean`?n[r.field]=!!t:r.type===`text`?n[r.field]={$contains:t}:n[r.field]=t)}return n}function ne({open:e,onOpenChange:i,title:ne=`Select Record`,multiple:d=!1,dataSource:f,objectName:re,columns:p,displayField:m=`name`,idField:ie=`id`,pageSize:h=o,value:g,onSelect:_,onSelectRecords:v,lookupFilters:y,cellRenderer:b,filterColumns:x,renderFilterBar:S,renderGrid:ae}){let[C,w]=(0,t.useState)([]),[T,E]=(0,t.useState)(!1),[D,O]=(0,t.useState)(null),[k,oe]=(0,t.useState)(0),[A,j]=(0,t.useState)(``),[M,N]=(0,t.useState)(1),P=(0,t.useRef)(null),[F,se]=(0,t.useState)(null),[I,ce]=(0,t.useState)(`asc`),[L,R]=(0,t.useState)(new Set),z=(0,t.useRef)(new Map),[B,V]=(0,t.useState)(-1),H=(0,t.useRef)(null),[le,U]=(0,t.useState)(!1),[W,ue]=(0,t.useState)({}),[de,G]=(0,t.useState)({}),K=(0,t.useRef)(null),[fe,pe]=(0,t.useState)(``),q=(0,t.useMemo)(()=>p&&p.length>0?p.map(c):[{field:m,label:l(m)}],[p,m]),J=(0,t.useMemo)(()=>{if(x&&x.length>0)return x;if(y&&y.length>0)return y.map(e=>{let t=`text`;return typeof e.value==`boolean`?t=`boolean`:Array.isArray(e.value)?t=`select`:typeof e.value==`number`||e.operator===`gt`||e.operator===`lt`||e.operator===`gte`||e.operator===`lte`?t=`number`:(e.operator===`in`||e.operator===`notIn`)&&(t=`select`),{field:e.field,label:l(e.field),type:t,...Array.isArray(e.value)?{options:e.value.map(e=>{if(typeof e==`object`&&e){let t=e;return{label:String(t.name||t.label||t.title||e),value:e}}return{label:String(e),value:e}})}:{}}})},[x,y]),me=(0,t.useMemo)(()=>{let e=y?.length?u(y):{},t=J?.length?te(W,J):{},n={...e,...t};return Object.keys(n).length>0?n:void 0},[y,J,W]),Y=Math.max(1,Math.ceil(k/h)),he=(0,t.useCallback)(async(e,t=1,n,r)=>{if(!(!f||!re)){E(!0),O(null);try{let i={$top:h,$skip:(t-1)*h};e&&e.trim()&&(i.$search=e.trim()),n&&(i.$orderby={[n.field]:n.direction});let a=r===void 0?me:r;a&&Object.keys(a).length>0&&(i.$filter=a);let o=await f.find(re,i),s=o?.data??o??[];w(s),oe(o?.total??s.length),V(-1)}catch(e){O(e instanceof Error?e.message:String(e)),w([])}finally{E(!1)}}},[f,re,h,me]),X=(0,t.useMemo)(()=>F?{field:F,direction:I}:null,[F,I]);(0,t.useEffect)(()=>{e||(j(``),N(1),O(null),w([]),se(null),ce(`asc`),V(-1),U(!1),ue({}),G({}),pe(``),R(new Set(d&&Array.isArray(g)?g:[])),z.current.clear())},[e]),(0,t.useEffect)(()=>{e&&he(A||void 0,M,X)},[e,M,X,me]),(0,t.useEffect)(()=>{e&&d&&R(new Set(Array.isArray(g)?g:[]))},[e,d,g]);let ge=(0,t.useCallback)(e=>{j(e),N(1),P.current&&clearTimeout(P.current),P.current=setTimeout(()=>{he(e||void 0,1,X)},300)},[he,X]);(0,t.useEffect)(()=>()=>{P.current&&clearTimeout(P.current)},[]);let _e=(0,t.useCallback)(e=>{se(t=>t===e?(ce(e=>e===`asc`?`desc`:`asc`),e):(ce(`asc`),e)),N(1)},[]),Z=(0,t.useCallback)(e=>e[ie]??e.id??e._id,[ie]),ve=(0,t.useCallback)(e=>{let t=Z(e);return d?L.has(t):g===t},[d,g,L,Z]),ye=(0,t.useCallback)(e=>{let t=Z(e);d?R(n=>{let r=new Set(n);return r.has(t)?(r.delete(t),z.current.delete(t)):(r.add(t),z.current.set(t,e)),r}):(_(t),v?.([e]),i(!1))},[d,Z,_,v,i]),be=(0,t.useCallback)(()=>{let e=Array.from(L);_(e);let t=e.map(e=>z.current.get(e)).filter(Boolean);v?.(t),i(!1)},[L,_,v,i]),xe=(0,t.useCallback)(()=>{N(e=>Math.max(1,e-1))},[]),Se=(0,t.useCallback)(()=>{N(e=>Math.min(Y,e+1))},[Y]),Ce=(0,t.useCallback)(e=>{if(e.key!==`Enter`)return;let t=parseInt(fe,10);!isNaN(t)&&t>=1&&t<=Y&&N(t),pe(``)},[fe,Y]),we=(0,t.useCallback)(e=>{C.length!==0&&(e.key===`ArrowDown`?(e.preventDefault(),V(e=>Math.min(e+1,C.length-1))):e.key===`ArrowUp`?(e.preventDefault(),V(e=>Math.max(e-1,0))):(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),B>=0&&B<C.length&&ye(C[B])))},[C,B,ye]);(0,t.useEffect)(()=>{if(B>=0&&H.current){let e=H.current.querySelector(`[data-row-index="${B}"]`);e&&typeof e.scrollIntoView==`function`&&e.scrollIntoView({block:`nearest`})}},[B]);let Te=(0,t.useCallback)((e,t)=>{let n=e[t.field];if(t.type&&b){let e=b(t.type);if(e)return(0,a.jsx)(e,{value:n,field:{name:t.field,type:t.type}})}return n==null?``:typeof n==`object`?n.$numberDecimal?String(Number(n.$numberDecimal)):n.$oid?String(n.$oid):n.$date?new Date(n.$date).toLocaleDateString():n.name||n.label?String(n.name||n.label):JSON.stringify(n):typeof n==`boolean`?n?`Yes`:`No`:String(n)},[b]),Ee=(0,t.useCallback)(e=>F===e?I===`asc`?(0,a.jsx)(r.ArrowUp,{className:`ml-1 size-3`}):(0,a.jsx)(r.ArrowDown,{className:`ml-1 size-3`}):(0,a.jsx)(r.ArrowUpDown,{className:`ml-1 size-3 opacity-40`}),[F,I]),De=(0,t.useCallback)((e,t,n)=>{e.preventDefault(),e.stopPropagation(),K.current={field:t,startX:e.clientX,startWidth:n};let r=e=>{if(!K.current)return;let t=e.clientX-K.current.startX,n=Math.max(s,K.current.startWidth+t);G(e=>({...e,[K.current.field]:n}))},i=()=>{K.current=null,document.removeEventListener(`mousemove`,r),document.removeEventListener(`mouseup`,i)};document.addEventListener(`mousemove`,r),document.addEventListener(`mouseup`,i)},[]),Q=(0,t.useCallback)((e,t)=>{ue(n=>({...n,[e]:t})),N(1)},[]),Oe=(0,t.useCallback)(()=>{ue({}),N(1)},[]),$=(0,t.useMemo)(()=>Object.values(W).filter(e=>e!=null&&e!==``).length,[W]),ke=(0,t.useCallback)(e=>{let t=W[e.field],r=e.label||l(e.field);switch(e.type){case`select`:return(0,a.jsxs)(`div`,{className:`space-y-1`,children:[(0,a.jsx)(n.Label,{className:`text-xs text-muted-foreground`,children:r}),(0,a.jsxs)(n.Select,{value:t==null?``:String(t),onValueChange:t=>Q(e.field,t),children:[(0,a.jsx)(n.SelectTrigger,{className:`h-8 text-xs`,children:(0,a.jsx)(n.SelectValue,{placeholder:`Filter ${r}`})}),(0,a.jsx)(n.SelectContent,{children:e.options?.map(e=>(0,a.jsx)(n.SelectItem,{value:String(e.value),children:e.label},String(e.value)))})]})]});case`number`:return(0,a.jsxs)(`div`,{className:`space-y-1`,children:[(0,a.jsx)(n.Label,{className:`text-xs text-muted-foreground`,children:r}),(0,a.jsx)(n.Input,{type:`number`,className:`h-8 text-xs`,value:t??``,placeholder:`Filter ${r}`,onChange:t=>{let n=t.target.value;Q(e.field,n===``?``:Number(n))}})]});case`date`:return(0,a.jsxs)(`div`,{className:`space-y-1`,children:[(0,a.jsx)(n.Label,{className:`text-xs text-muted-foreground`,children:r}),(0,a.jsx)(n.Input,{type:`date`,className:`h-8 text-xs`,value:t??``,onChange:t=>Q(e.field,t.target.value)})]});case`boolean`:return(0,a.jsxs)(`div`,{className:`space-y-1`,children:[(0,a.jsx)(n.Label,{className:`text-xs text-muted-foreground`,children:r}),(0,a.jsxs)(`div`,{className:`flex items-center gap-2 h-8`,children:[(0,a.jsx)(n.Checkbox,{checked:!!t,onCheckedChange:t=>Q(e.field,!!t)}),(0,a.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`Yes`})]})]});default:return(0,a.jsxs)(`div`,{className:`space-y-1`,children:[(0,a.jsx)(n.Label,{className:`text-xs text-muted-foreground`,children:r}),(0,a.jsx)(n.Input,{className:`h-8 text-xs`,value:t??``,placeholder:`Filter ${r}`,onChange:t=>Q(e.field,t.target.value)})]})}},[W,Q]),Ae=(0,t.useCallback)((e,t)=>e?`bg-primary/5 hover:bg-primary/10`:t%2==1?`bg-muted/20 hover:bg-accent/30`:`hover:bg-accent/30`,[]);return(0,a.jsx)(n.Dialog,{open:e,onOpenChange:i,children:(0,a.jsxs)(n.DialogContent,{className:`w-[95vw] sm:max-w-3xl lg:max-w-5xl max-h-[85vh] sm:max-h-[80vh] flex flex-col gap-0`,"data-testid":`record-picker-dialog`,children:[(0,a.jsx)(n.DialogHeader,{children:(0,a.jsxs)(n.DialogTitle,{children:[ne,d&&(0,a.jsx)(`span`,{className:`sr-only`,children:` (multiple selection)`})]})}),(0,a.jsxs)(`div`,{className:`relative rounded-md border bg-muted/30 mb-3`,children:[(0,a.jsx)(r.Search,{className:`absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground`}),(0,a.jsx)(n.Input,{placeholder:`Search...`,value:A,onChange:e=>ge(e.target.value),className:`pl-9 border-0 bg-transparent shadow-none focus-visible:ring-0`,"data-testid":`record-picker-search`}),T&&(0,a.jsx)(r.Loader2,{className:`absolute right-3 top-1/2 -translate-y-1/2 size-4 animate-spin text-muted-foreground`,"data-testid":`record-picker-loading-indicator`})]}),J&&J.length>0&&(0,a.jsx)(`div`,{className:`py-2`,children:S?(0,a.jsx)(`div`,{"data-testid":`record-picker-filter-bar`,children:S({filterColumns:J,values:W,onChange:Q,onClear:Oe,activeCount:$})}):(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(`div`,{className:`flex items-center gap-2`,"data-testid":`record-picker-filter-bar`,children:[(0,a.jsxs)(n.Button,{type:`button`,variant:$>0?`secondary`:`outline`,size:`sm`,className:`gap-1.5 shrink-0`,onClick:()=>U(e=>!e),children:[(0,a.jsx)(r.SlidersHorizontal,{className:`size-3.5`}),`Filters`,$>0&&(0,a.jsx)(`span`,{className:`inline-flex h-5 min-w-[20px] items-center justify-center rounded-full bg-primary/10 px-1 text-xs font-medium text-primary`,children:$})]}),$>0&&(0,a.jsxs)(n.Button,{type:`button`,variant:`ghost`,size:`sm`,className:`gap-1 text-xs`,onClick:Oe,children:[(0,a.jsx)(r.X,{className:`size-3`}),`Clear`]})]}),le&&(0,a.jsx)(`div`,{className:`mt-2 grid gap-3 sm:grid-cols-2 lg:grid-cols-3 border rounded-md p-3 bg-muted/30`,"data-testid":`record-picker-filter-panel`,children:J.map(e=>(0,a.jsx)(`div`,{children:ke(e)},e.field))})]})}),D&&(0,a.jsxs)(`div`,{className:`flex flex-col items-center gap-2 py-4`,role:`alert`,children:[(0,a.jsx)(r.AlertCircle,{className:`size-5 text-destructive`}),(0,a.jsx)(`p`,{className:`text-sm text-destructive`,children:D}),(0,a.jsx)(n.Button,{variant:`outline`,size:`sm`,onClick:()=>he(A||void 0,M,X),type:`button`,children:`Retry`})]}),ae?(0,a.jsx)(`div`,{className:`flex-1 min-h-0`,"data-testid":`record-picker-grid-slot`,children:ae({columns:q,records:C,loading:T,totalCount:k,currentPage:M,pageSize:h,sortField:F,sortDirection:I,onSort:_e,onPageChange:N,onRowClick:ye,isSelected:ve,multiple:d,idField:ie,cellRenderer:b})}):(0,a.jsxs)(a.Fragment,{children:[T&&C.length===0&&!D&&(0,a.jsx)(`div`,{className:`flex-1 overflow-hidden min-h-0 border rounded-md`,role:`status`,"aria-live":`polite`,"data-testid":`record-picker-skeleton`,children:(0,a.jsxs)(n.Table,{children:[(0,a.jsx)(n.TableHeader,{children:(0,a.jsxs)(n.TableRow,{className:`bg-muted/40`,children:[d&&(0,a.jsx)(n.TableHead,{className:`w-10`}),q.map(e=>(0,a.jsx)(n.TableHead,{children:(0,a.jsx)(n.Skeleton,{className:`h-4 w-20`})},e.field))]})}),(0,a.jsx)(n.TableBody,{children:Array.from({length:ee},(e,t)=>(0,a.jsxs)(n.TableRow,{children:[d&&(0,a.jsx)(n.TableCell,{className:`w-10`,children:(0,a.jsx)(n.Skeleton,{className:`size-4 rounded`})}),q.map(e=>(0,a.jsx)(n.TableCell,{children:(0,a.jsx)(n.Skeleton,{className:`h-4 w-full`})},e.field))]},t))})]})}),!T&&!D&&C.length===0&&(0,a.jsx)(`div`,{className:`py-8 text-center`,children:(0,a.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`No records found`})}),!D&&C.length>0&&(0,a.jsxs)(`div`,{className:`relative flex-1 overflow-auto min-h-0 border rounded-md`,tabIndex:0,onKeyDown:we,role:`grid`,"aria-label":`Records`,children:[T&&(0,a.jsx)(`div`,{className:`absolute inset-0 z-10 flex items-center justify-center bg-background/60`,"data-testid":`record-picker-loading-overlay`,children:(0,a.jsx)(r.Loader2,{className:`size-6 animate-spin text-muted-foreground`})}),(0,a.jsxs)(n.Table,{style:Object.keys(de).length>0?{tableLayout:`fixed`}:void 0,children:[(0,a.jsx)(n.TableHeader,{className:`sticky top-0 z-[5] bg-muted/50 [&_tr]:border-b`,"data-testid":`record-picker-sticky-header`,children:(0,a.jsxs)(n.TableRow,{children:[d&&(0,a.jsx)(n.TableHead,{className:`w-10`}),q.map(e=>{let t=de[e.field];return(0,a.jsxs)(n.TableHead,{style:t?{width:`${t}px`,minWidth:`${t}px`}:e.width?{width:e.width}:void 0,className:`cursor-pointer select-none relative group text-xs font-semibold uppercase tracking-wider`,onClick:()=>_e(e.field),"aria-sort":F===e.field?I===`asc`?`ascending`:`descending`:`none`,children:[(0,a.jsxs)(`span`,{className:`inline-flex items-center`,children:[e.label||l(e.field),Ee(e.field)]}),(0,a.jsx)(`span`,{role:`separator`,"aria-orientation":`vertical`,className:`absolute right-0 top-0 bottom-0 w-1 cursor-col-resize opacity-0 group-hover:opacity-100 bg-border hover:bg-primary/50 transition-opacity`,onMouseDown:t=>{let n=t.currentTarget.parentElement?.getBoundingClientRect();De(t,e.field,n?.width??100)},onClick:e=>e.stopPropagation(),"data-testid":`resize-handle-${e.field}`})]},e.field)})]})}),(0,a.jsx)(n.TableBody,{ref:H,children:C.map((e,t)=>{let i=Z(e),o=ve(e),s=t===B;return(0,a.jsxs)(n.TableRow,{"data-row-index":t,className:(0,n.cn)(`cursor-pointer transition-colors`,Ae(o,t),s&&`ring-2 ring-primary ring-inset`),onClick:()=>ye(e),"data-testid":`record-row-${i}`,"aria-selected":o,children:[d&&(0,a.jsx)(n.TableCell,{className:`w-10`,children:o&&(0,a.jsx)(r.Check,{className:`size-4 text-primary`})}),q.map(t=>(0,a.jsx)(n.TableCell,{className:`py-2.5`,children:Te(e,t)},t.field))]},i??t)})})]})]}),!D&&k>0&&(0,a.jsxs)(`div`,{className:`flex items-center justify-between text-sm text-muted-foreground border-t pt-3 mt-2 px-1`,"data-testid":`record-picker-pagination`,children:[(0,a.jsxs)(`span`,{children:[k,` `,k===1?`record`:`records`,Y>1&&` · Page ${M} of ${Y}`]}),Y>1&&(0,a.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,a.jsx)(n.Button,{variant:`outline`,size:`icon`,className:`size-7`,onClick:xe,disabled:M<=1,type:`button`,"aria-label":`Previous page`,children:(0,a.jsx)(r.ChevronLeft,{className:`size-4`})}),(0,a.jsx)(n.Input,{className:`h-7 w-12 text-center text-xs px-1`,placeholder:String(M),value:fe,onChange:e=>pe(e.target.value),onKeyDown:Ce,"aria-label":`Jump to page`,"data-testid":`record-picker-page-jump`}),(0,a.jsx)(n.Button,{variant:`outline`,size:`icon`,className:`size-7`,onClick:Se,disabled:M>=Y,type:`button`,"aria-label":`Next page`,children:(0,a.jsx)(r.ChevronRight,{className:`size-4`})})]})]})]}),d&&(0,a.jsx)(n.DialogFooter,{children:(0,a.jsxs)(`div`,{className:`flex items-center gap-2 w-full justify-between`,children:[(0,a.jsxs)(`span`,{className:`text-sm text-muted-foreground`,children:[L.size,` selected`]}),(0,a.jsxs)(`div`,{className:`flex gap-2`,children:[(0,a.jsx)(n.Button,{variant:`outline`,type:`button`,onClick:()=>i(!1),children:`Cancel`}),(0,a.jsx)(n.Button,{type:`button`,onClick:be,children:`Confirm`})]})]})})]})})}var d;function f(e){d=e}function re(){return d}var p=e.n({LookupField:()=>_}),m=50,ie=i.SchemaRendererContext;function h(e,t,n,r){let i=e[n]??e.id??e._id,a=e[t]??e.label??e.name??String(i),o=r?e[r]:void 0;return{value:i,label:String(a),description:o,...e}}function g(e){return{text:`text`,number:`number`,currency:`number`,percent:`number`,select:`select`,status:`select`,date:`date`,datetime:`date`,boolean:`boolean`}[e]}function _({value:e,onChange:i,field:o,readonly:s,...ee}){let[c,l]=(0,t.useState)(!1),[u,te]=(0,t.useState)(``),[d,f]=(0,t.useState)([]),[p,_]=(0,t.useState)(!1),[v,y]=(0,t.useState)(null),[b,x]=(0,t.useState)(0),S=(0,t.useRef)(null),[ae,C]=(0,t.useState)([]),[w,T]=(0,t.useState)(-1),E=(0,t.useRef)(null),D=o||ee.schema,O=D?.field,k=O&&typeof O==`object`&&(`reference_to`in O||`reference`in O||`type`in O)?O:D,oe=k?.options||[],A=k?.multiple||!1,j=k?.display_field||k?.reference_field||`name`,M=k?.description_field,N=k?.id_field||`id`,P=k?.reference_to||k?.reference,F=k?.lookup_columns,se=k?.lookup_page_size,I=k?.lookup_filters,ce=(0,t.useMemo)(()=>{if(!F)return;let e=[];for(let t of F)if(typeof t==`object`&&t.type){let n=g(t.type);n&&e.push({field:t.field,label:t.label,type:n})}return e.length>0?e:void 0},[F]),L=(0,t.useContext)(ie)?.dataSource??null,R=ee.dataSource??D?.dataSource??k?.dataSource??L,z=R!=null&&typeof R.find==`function`&&!!P,B=ee.onCreateNew??D?.onCreateNew,[V,H]=(0,t.useState)(!1),le=z?d:oe,U=(0,t.useMemo)(()=>{if(z||!u)return le;let e=u.toLowerCase();return le.filter(t=>t.label.toLowerCase().includes(e)||t.description&&t.description.toLowerCase().includes(e))},[z,le,u]);(0,t.useEffect)(()=>{T(-1)},[U.length]);let W=(0,t.useCallback)(async e=>{if(!(!R||!P)){_(!0),y(null);try{let t={$top:m};e&&e.trim()&&(t.$search=e.trim());let n=await R.find(P,t),r=n?.data??n??[];f(r.map(e=>h(e,j,N,M))),x(n?.total??r.length)}catch(e){y(e instanceof Error?e.message:String(e)),f([])}finally{_(!1)}}},[R,P,j,N,M]);(0,t.useEffect)(()=>{c&&z&&W(u||void 0),c||(te(``),y(null),T(-1))},[c]);let ue=(0,t.useCallback)(e=>{te(e),z&&(S.current&&clearTimeout(S.current),S.current=setTimeout(()=>{W(e||void 0)},300))},[z,W]);(0,t.useEffect)(()=>()=>{S.current&&clearTimeout(S.current)},[]);let de=(0,t.useCallback)(e=>oe.find(t=>t.value===e)??d.find(t=>t.value===e)??ae.find(t=>t.value===e),[oe,d,ae]),G=A?(Array.isArray(e)?e:[]).map(de).filter(Boolean):e?[de(e)].filter(Boolean):[],K=(0,t.useCallback)(t=>{if(A){let n=Array.isArray(e)?e:[];n.includes(t.value)?i(n.filter(e=>e!==t.value)):i([...n,t.value])}else i(t.value),l(!1)},[A,e,i]),fe=t=>{i(A?(Array.isArray(e)?e:[]).filter(e=>e!==t):null)},pe=(0,t.useCallback)(e=>{C(e.map(e=>h(e,j,N,M)))},[j,N,M]),q=(0,t.useCallback)(e=>{e.key===`ArrowDown`?(e.preventDefault(),T(e=>e<U.length-1?e+1:e)):e.key===`ArrowUp`?(e.preventDefault(),T(e=>e>0?e-1:0)):e.key===`Enter`&&(e.preventDefault(),w>=0&&w<U.length&&K(U[w]))},[U,w,K]);return(0,t.useEffect)(()=>{w>=0&&E.current&&E.current.querySelector(`[data-lookup-index="${w}"]`)?.scrollIntoView({block:`nearest`})},[w]),s?G.length?A?(0,a.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:G.map((e,t)=>(0,a.jsx)(n.Badge,{variant:`outline`,children:e?.[j]||e?.label},t))}):(0,a.jsx)(`span`,{className:`text-sm`,children:G[0]?.[j]||G[0]?.label}):(0,a.jsx)(`span`,{className:`text-sm`,children:`-`}):(0,a.jsxs)(`div`,{className:`space-y-2`,children:[G.length>0&&(0,a.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:G.map((e,t)=>(0,a.jsxs)(n.Badge,{variant:`outline`,className:`gap-1`,children:[e?.[j]||e?.label,(0,a.jsx)(`button`,{onClick:()=>fe(e?.value),className:`ml-1 hover:text-destructive`,type:`button`,"aria-label":`Remove ${e?.[j]||e?.label}`,children:(0,a.jsx)(r.X,{className:`size-3`})})]},t))}),(0,a.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,a.jsxs)(n.Popover,{open:c,onOpenChange:l,children:[(0,a.jsx)(n.PopoverTrigger,{asChild:!0,children:(0,a.jsxs)(n.Button,{variant:`outline`,className:`min-w-0 flex-1 justify-start text-left font-normal`,type:`button`,children:[(0,a.jsx)(r.Search,{className:`mr-2 size-4`}),G.length===0?D?.placeholder||`Select...`:A?`${G.length} selected`:`Change selection`]})}),(0,a.jsxs)(n.PopoverContent,{className:`w-[var(--radix-popover-trigger-width)] p-0`,align:`start`,children:[(0,a.jsx)(`div`,{className:`p-2`,children:(0,a.jsxs)(`div`,{className:`relative`,children:[(0,a.jsx)(r.Search,{className:`absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground`}),(0,a.jsx)(n.Input,{placeholder:`Search...`,value:u,onChange:e=>ue(e.target.value),onKeyDown:q,className:`w-full pl-9 h-8 text-sm`}),p&&(0,a.jsx)(r.Loader2,{className:`absolute right-3 top-1/2 -translate-y-1/2 size-4 animate-spin text-muted-foreground`,"data-testid":`lookup-loading`})]})}),v&&(0,a.jsxs)(`div`,{className:`flex flex-col items-center gap-2 py-4 px-2`,role:`alert`,children:[(0,a.jsx)(r.AlertCircle,{className:`size-5 text-destructive`}),(0,a.jsx)(`p`,{className:`text-sm text-destructive`,children:v}),(0,a.jsx)(n.Button,{variant:`outline`,size:`sm`,onClick:()=>W(u||void 0),type:`button`,children:`Retry`})]}),p&&U.length===0&&!v&&(0,a.jsxs)(`div`,{className:`flex flex-col items-center gap-2 py-6`,role:`status`,"aria-live":`polite`,children:[(0,a.jsx)(r.Loader2,{className:`size-6 animate-spin text-muted-foreground`}),(0,a.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Loading…`})]}),!v&&!(p&&U.length===0)&&(0,a.jsx)(`div`,{ref:E,className:`max-h-64 overflow-y-auto px-1 pb-1`,role:`listbox`,children:U.length===0?(0,a.jsxs)(`div`,{className:`py-4 text-center`,children:[(0,a.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`No options found`}),B&&(0,a.jsxs)(n.Button,{variant:`ghost`,size:`sm`,className:`mt-2 gap-1`,type:`button`,onClick:()=>{B(u),l(!1)},children:[(0,a.jsx)(r.Plus,{className:`size-4`}),`Create new`]})]}):(0,a.jsxs)(a.Fragment,{children:[U.map((t,r)=>{let i=A?(Array.isArray(e)?e:[]).includes(t.value):e===t.value,o=r===w;return(0,a.jsxs)(`button`,{"data-lookup-index":r,role:`option`,"aria-selected":i,onClick:()=>K(t),className:`w-full text-left px-3 py-2 rounded-md text-sm hover:bg-accent flex items-center justify-between ${o?`bg-accent text-accent-foreground`:i?`bg-accent/50 text-accent-foreground`:``}`,type:`button`,children:[(0,a.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,a.jsx)(`span`,{className:`block truncate`,children:t.label}),t.description&&(0,a.jsx)(`span`,{className:`block truncate text-xs text-muted-foreground`,children:t.description})]}),i&&(0,a.jsx)(n.Badge,{variant:`default`,className:`ml-2 shrink-0`,children:`Selected`})]},t.value)}),z&&b>U.length&&(0,a.jsxs)(`p`,{className:`text-xs text-muted-foreground text-center py-2`,children:[`Showing `,U.length,` of `,b,` results.`]}),z&&b>U.length&&(0,a.jsxs)(`button`,{type:`button`,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`,onClick:()=>{l(!1),H(!0)},"data-testid":`show-all-results`,children:[(0,a.jsx)(r.TableProperties,{className:`size-3.5`}),`Show All Results (`,b,`)`]}),B&&(0,a.jsxs)(`button`,{type:`button`,className:`w-full text-left px-3 py-2 rounded-md text-sm hover:bg-accent flex items-center gap-1.5 text-muted-foreground`,onClick:()=>{B(u),l(!1)},children:[(0,a.jsx)(r.Plus,{className:`size-3.5`}),`Create new`,u?` "${u}"`:``]})]})})]})]}),z&&(0,a.jsx)(n.Button,{variant:`outline`,size:`icon`,className:`shrink-0`,type:`button`,onClick:()=>H(!0),"aria-label":`Browse all records`,title:`Browse all records`,"data-testid":`browse-all-records`,children:(0,a.jsx)(r.TableProperties,{className:`size-4`})})]}),z&&R&&P&&(0,a.jsx)(ne,{open:V,onOpenChange:H,title:D?.label||`Select`,multiple:A,dataSource:R,objectName:P,columns:F,displayField:j,idField:N,pageSize:se,value:e,onSelect:i,onSelectRecords:pe,lookupFilters:I,cellRenderer:re(),filterColumns:ce})]})}Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return ne}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return _}});
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { MasterDetailField as e } from "./index.js";
3
+ export { e as MasterDetailField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.MasterDetailField=e.MasterDetailField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { NumberField as e } from "./index.js";
3
+ export { e as NumberField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.NumberField=e.NumberField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { ObjectField as e } from "./index.js";
3
+ export { e as ObjectField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.ObjectField=e.ObjectField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { PasswordField as e } from "./index.js";
3
+ export { e as PasswordField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.PasswordField=e.PasswordField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { PercentField as e } from "./index.js";
3
+ export { e as PercentField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.PercentField=e.PercentField;
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.PhoneField=e.PhoneField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { PhoneField as e } from "./index.js";
3
+ export { e as PhoneField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.QRCodeField=e.QRCodeField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { QRCodeField as e } from "./index.js";
3
+ export { e as QRCodeField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.RatingField=e.RatingField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { RatingField as e } from "./index.js";
3
+ export { e as RatingField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.RichTextField=e.RichTextField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { RichTextField as e } from "./index.js";
3
+ export { e as RichTextField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.SelectField=e.SelectField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { SelectField as e } from "./index.js";
3
+ export { e as SelectField };
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { SignatureField as e } from "./index.js";
3
+ export { e as SignatureField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.SignatureField=e.SignatureField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { SliderField as e } from "./index.js";
3
+ export { e as SliderField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.SliderField=e.SliderField;
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.SummaryField=e.SummaryField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { SummaryField as e } from "./index.js";
3
+ export { e as SummaryField };
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { TextAreaField as e } from "./index.js";
3
+ export { e as TextAreaField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.TextAreaField=e.TextAreaField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { TextField as e } from "./index.js";
3
+ export { e as TextField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.TextField=e.TextField;
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.TimeField=e.TimeField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { TimeField as e } from "./index.js";
3
+ export { e as TimeField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.UrlField=e.UrlField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { UrlField as e } from "./index.js";
3
+ export { e as UrlField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.UserField=e.UserField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { UserField as e } from "./index.js";
3
+ export { e as UserField };
@@ -0,0 +1 @@
1
+ require(`./jsx-runtime-DHCF5ANT.cjs`);const e=require(`./index.cjs`);exports.VectorField=e.VectorField;
@@ -0,0 +1,3 @@
1
+ import "./jsx-runtime-MxADXuRH.js";
2
+ import { VectorField as e } from "./index.js";
3
+ export { e as VectorField };
@@ -198,6 +198,7 @@ export * from './widgets/PasswordField';
198
198
  export * from './widgets/TextAreaField';
199
199
  export * from './widgets/RichTextField';
200
200
  export * from './widgets/LookupField';
201
+ export * from './widgets/RecordPickerDialog';
201
202
  export * from './widgets/FileField';
202
203
  export * from './widgets/ImageField';
203
204
  export * from './widgets/LocationField';
@@ -0,0 +1,25 @@
1
+ import { StoryObj } from '@storybook/react';
2
+ import { RecordPickerDialog } from './widgets/RecordPickerDialog';
3
+ /**
4
+ * **RecordPickerDialog** — Enterprise-grade record picker for lookup fields.
5
+ *
6
+ * Features: skeleton loading, sticky table header, column sort,
7
+ * keyboard navigation, page jump, inline filter bar, column resize,
8
+ * and responsive layout.
9
+ */
10
+ declare const meta: {
11
+ title: string;
12
+ component: typeof RecordPickerDialog;
13
+ parameters: {
14
+ layout: string;
15
+ };
16
+ tags: string[];
17
+ };
18
+ export default meta;
19
+ type Story = StoryObj<typeof RecordPickerDialog>;
20
+ /** Default single-select dialog with 4 columns, pagination, and search. */
21
+ export declare const Default: Story;
22
+ /** Multi-select mode with confirm/cancel footer. */
23
+ export declare const MultiSelect: Story;
24
+ /** With inline filter columns for interactive filtering. */
25
+ export declare const WithFilters: Story;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,166 @@
1
+ import { default as React } from 'react';
2
+ import { DataSource, LookupColumnDef, LookupFilterDef } from '../../../types/src';
3
+ /**
4
+ * Cell renderer function signature — matches getCellRenderer from @object-ui/fields.
5
+ * Accepts a field type and returns a React component that renders a formatted cell.
6
+ */
7
+ export type CellRendererResolver = (fieldType: string) => React.FC<{
8
+ value: any;
9
+ field: any;
10
+ }>;
11
+ /**
12
+ * Filter column definition used by the inline filter bar.
13
+ * A subset of LookupColumnDef enriched with filter-specific metadata.
14
+ * Compatible with FilterUISchema.filters entries for easy bridging.
15
+ */
16
+ export interface RecordPickerFilterColumn {
17
+ field: string;
18
+ label?: string;
19
+ type: 'text' | 'number' | 'select' | 'date' | 'boolean';
20
+ options?: Array<{
21
+ label: string;
22
+ value: any;
23
+ }>;
24
+ }
25
+ /**
26
+ * Props passed to the custom filter bar renderer (renderFilterBar slot).
27
+ * Allows plugging in FilterUI or any custom component.
28
+ */
29
+ export interface RecordPickerFilterBarProps {
30
+ /** Filter column definitions describing each filterable field */
31
+ filterColumns: RecordPickerFilterColumn[];
32
+ /** Current filter values keyed by field name */
33
+ values: Record<string, any>;
34
+ /** Called when a single filter value changes */
35
+ onChange: (field: string, value: any) => void;
36
+ /** Clear all filter values */
37
+ onClear: () => void;
38
+ /** Number of actively applied filters */
39
+ activeCount: number;
40
+ }
41
+ /**
42
+ * Props passed to the custom grid renderer (renderGrid slot).
43
+ * Allows plugging in ObjectGrid or any compatible table component.
44
+ */
45
+ export interface RecordPickerGridSlotProps {
46
+ /** Resolved column definitions */
47
+ columns: LookupColumnDef[];
48
+ /** Current page of records */
49
+ records: any[];
50
+ /** Whether data is loading */
51
+ loading: boolean;
52
+ /** Total record count across all pages */
53
+ totalCount: number;
54
+ /** Current page number (1-based) */
55
+ currentPage: number;
56
+ /** Records per page */
57
+ pageSize: number;
58
+ /** Current sort field, null if unsorted */
59
+ sortField: string | null;
60
+ /** Current sort direction */
61
+ sortDirection: 'asc' | 'desc';
62
+ /** Called when a column header is clicked to sort */
63
+ onSort: (field: string) => void;
64
+ /** Called when page changes */
65
+ onPageChange: (page: number) => void;
66
+ /** Called when a row is clicked */
67
+ onRowClick: (record: any) => void;
68
+ /** Check if a record is selected */
69
+ isSelected: (record: any) => boolean;
70
+ /** Whether multiple selection is enabled */
71
+ multiple: boolean;
72
+ /** Record ID field name */
73
+ idField: string;
74
+ /** Cell renderer resolver */
75
+ cellRenderer?: CellRendererResolver;
76
+ }
77
+ export interface RecordPickerDialogProps {
78
+ /** Whether the dialog is open */
79
+ open: boolean;
80
+ /** Called when the dialog should close */
81
+ onOpenChange: (open: boolean) => void;
82
+ /** Dialog title */
83
+ title?: string;
84
+ /** Allow multiple selection */
85
+ multiple?: boolean;
86
+ /** DataSource to fetch records from */
87
+ dataSource: DataSource;
88
+ /** Object name to query (e.g. 'customers') */
89
+ objectName: string;
90
+ /** Columns to display. Defaults to [displayField, descriptionField]. */
91
+ columns?: Array<string | LookupColumnDef>;
92
+ /** Primary display field (default: 'name') */
93
+ displayField?: string;
94
+ /** Record id field (default: 'id') */
95
+ idField?: string;
96
+ /** Page size (default: 10) */
97
+ pageSize?: number;
98
+ /** Currently selected value(s) */
99
+ value?: any;
100
+ /** Called when selection changes */
101
+ onSelect: (value: any) => void;
102
+ /**
103
+ * Called with the full record objects corresponding to the selected value(s).
104
+ * Useful for parent components (e.g. LookupField) that need display data
105
+ * (labels, descriptions) for the selected records beyond just their IDs.
106
+ */
107
+ onSelectRecords?: (records: any[]) => void;
108
+ /**
109
+ * Base filters applied to every query.
110
+ * Converted from LookupFieldMetadata.lookup_filters.
111
+ * Restricts which records are selectable (e.g. only active records).
112
+ */
113
+ lookupFilters?: LookupFilterDef[];
114
+ /**
115
+ * Cell renderer resolver function.
116
+ * When provided, columns with a `type` property will be rendered using the
117
+ * resolved cell renderer (e.g. badges for select, formatted currency, etc.).
118
+ * Typically pass `getCellRenderer` from @object-ui/fields.
119
+ */
120
+ cellRenderer?: CellRendererResolver;
121
+ /**
122
+ * Filter bar column definitions.
123
+ * When provided, shows an inline filter bar below the search input.
124
+ * Columns can include type-specific inputs (text, number, select, date, boolean).
125
+ */
126
+ filterColumns?: RecordPickerFilterColumn[];
127
+ /**
128
+ * Custom filter bar renderer slot.
129
+ * When provided, replaces the built-in filter bar with a custom component
130
+ * (e.g. FilterUI from @object-ui/plugin-view).
131
+ * Receives filter state and callbacks via RecordPickerFilterBarProps.
132
+ *
133
+ * @example
134
+ * renderFilterBar={(props) => (
135
+ * <FilterUI
136
+ * schema={{ type: 'filter-ui', filters: props.filterColumns, layout: 'inline' }}
137
+ * onChange={(values) => Object.entries(values).forEach(([k, v]) => props.onChange(k, v))}
138
+ * />
139
+ * )}
140
+ */
141
+ renderFilterBar?: (props: RecordPickerFilterBarProps) => React.ReactNode;
142
+ /**
143
+ * Custom grid renderer slot.
144
+ * When provided, replaces the built-in table with a custom grid component
145
+ * (e.g. ObjectGrid from @object-ui/plugin-grid).
146
+ * Receives data, columns, and interaction callbacks via RecordPickerGridSlotProps.
147
+ *
148
+ * @example
149
+ * renderGrid={(props) => (
150
+ * <ObjectGrid
151
+ * schema={{ type: 'object-grid', objectName, columns: props.columns }}
152
+ * dataSource={dataSource}
153
+ * />
154
+ * )}
155
+ */
156
+ renderGrid?: (props: RecordPickerGridSlotProps) => React.ReactNode;
157
+ }
158
+ /**
159
+ * RecordPickerDialog — Enterprise-grade record selection dialog.
160
+ *
161
+ * Renders records in a table with multi-column display, search,
162
+ * pagination, column sorting, keyboard navigation, loading/error/empty
163
+ * states, and single/multi-select. Responsive: mobile-friendly width
164
+ * via Tailwind breakpoints.
165
+ */
166
+ export declare function RecordPickerDialog({ open, onOpenChange, title, multiple, dataSource, objectName, columns: columnsProp, displayField, idField, pageSize, value, onSelect, onSelectRecords, lookupFilters, cellRenderer, filterColumns, renderFilterBar, renderGrid, }: RecordPickerDialogProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import { CellRendererResolver } from './RecordPickerDialog';
2
+ export declare function setCellRendererResolver(resolver: CellRendererResolver): void;
3
+ export declare function getCellRendererResolver(): CellRendererResolver | undefined;