@object-ui/plugin-grid 0.5.0 → 2.0.0

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.
@@ -1,9 +1,9 @@
1
- (function(A,j){typeof exports=="object"&&typeof module<"u"?j(exports,require("react"),require("@object-ui/core"),require("@object-ui/react"),require("@object-ui/fields"),require("@object-ui/components"),require("lucide-react"),require("react-dom")):typeof define=="function"&&define.amd?define(["exports","react","@object-ui/core","@object-ui/react","@object-ui/fields","@object-ui/components","lucide-react","react-dom"],j):(A=typeof globalThis<"u"?globalThis:A||self,j(A.ObjectUIPluginGrid={},A.React,A.core,A.react,A.fields,A.components,A.lucideReact,A.ReactDOM))})(this,(function(A,j,re,X,pe,P,Z,be){"use strict";function ve(t){const a=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const e in t)if(e!=="default"){const s=Object.getOwnPropertyDescriptor(t,e);Object.defineProperty(a,e,s.get?s:{enumerable:!0,get:()=>t[e]})}}return a.default=t,Object.freeze(a)}const U=ve(j);var G={exports:{}},W={};var ie;function ye(){if(ie)return W;ie=1;var t=Symbol.for("react.transitional.element"),a=Symbol.for("react.fragment");function e(s,n,i){var o=null;if(i!==void 0&&(o=""+i),n.key!==void 0&&(o=""+n.key),"key"in n){i={};for(var l in n)l!=="key"&&(i[l]=n[l])}else i=n;return n=i.ref,{$$typeof:t,type:s,key:o,ref:n!==void 0?n:null,props:i}}return W.Fragment=a,W.jsx=e,W.jsxs=e,W}var L={};var oe;function Ee(){return oe||(oe=1,process.env.NODE_ENV!=="production"&&(function(){function t(r){if(r==null)return null;if(typeof r=="function")return r.$$typeof===ee?null:r.displayName||r.name||null;if(typeof r=="string")return r;switch(r){case _:return"Fragment";case p:return"Profiler";case z:return"StrictMode";case B:return"Suspense";case N:return"SuspenseList";case q:return"Activity"}if(typeof r=="object")switch(typeof r.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),r.$$typeof){case g:return"Portal";case k:return r.displayName||"Context";case C:return(r._context.displayName||"Context")+".Consumer";case D:var u=r.render;return r=r.displayName,r||(r=u.displayName||u.name||"",r=r!==""?"ForwardRef("+r+")":"ForwardRef"),r;case H:return u=r.displayName||null,u!==null?u:t(r.type)||"Memo";case V:u=r._payload,r=r._init;try{return t(r(u))}catch{}}return null}function a(r){return""+r}function e(r){try{a(r);var u=!1}catch{u=!0}if(u){u=console;var x=u.error,w=typeof Symbol=="function"&&Symbol.toStringTag&&r[Symbol.toStringTag]||r.constructor.name||"Object";return x.call(u,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",w),a(r)}}function s(r){if(r===_)return"<>";if(typeof r=="object"&&r!==null&&r.$$typeof===V)return"<...>";try{var u=t(r);return u?"<"+u+">":"<...>"}catch{return"<...>"}}function n(){var r=Y.A;return r===null?null:r.getOwner()}function i(){return Error("react-stack-top-frame")}function o(r){if(J.call(r,"key")){var u=Object.getOwnPropertyDescriptor(r,"key").get;if(u&&u.isReactWarning)return!1}return r.key!==void 0}function l(r,u){function x(){M||(M=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",u))}x.isReactWarning=!0,Object.defineProperty(r,"key",{get:x,configurable:!0})}function f(){var r=t(this.type);return R[r]||(R[r]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),r=this.props.ref,r!==void 0?r:null}function v(r,u,x,w,K,ne){var O=x.ref;return r={$$typeof:T,type:r,key:u,props:x,_owner:w},(O!==void 0?O:null)!==null?Object.defineProperty(r,"ref",{enumerable:!1,get:f}):Object.defineProperty(r,"ref",{enumerable:!1,value:null}),r._store={},Object.defineProperty(r._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(r,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(r,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:K}),Object.defineProperty(r,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:ne}),Object.freeze&&(Object.freeze(r.props),Object.freeze(r)),r}function d(r,u,x,w,K,ne){var O=u.children;if(O!==void 0)if(w)if(te(O)){for(w=0;w<O.length;w++)S(O[w]);Object.freeze&&Object.freeze(O)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else S(O);if(J.call(u,"key")){O=t(r);var $=Object.keys(u).filter(function(De){return De!=="key"});w=0<$.length?"{key: someKey, "+$.join(": ..., ")+": ...}":"{key: someKey}",I[O+w]||($=0<$.length?"{"+$.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
1
+ (function(A,R){typeof exports=="object"&&typeof module<"u"?R(exports,require("react"),require("@object-ui/core"),require("@object-ui/react"),require("@object-ui/fields"),require("@object-ui/components"),require("lucide-react"),require("react-dom")):typeof define=="function"&&define.amd?define(["exports","react","@object-ui/core","@object-ui/react","@object-ui/fields","@object-ui/components","lucide-react","react-dom"],R):(A=typeof globalThis<"u"?globalThis:A||self,R(A.ObjectUIPluginGrid={},A.React,A.core,A.react,A.fields,A.components,A.lucideReact,A.ReactDOM))})(this,(function(A,R,he,B,me,q,de,Ce){"use strict";function _e(n){const a=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const e in n)if(e!=="default"){const s=Object.getOwnPropertyDescriptor(n,e);Object.defineProperty(a,e,s.get?s:{enumerable:!0,get:()=>n[e]})}}return a.default=n,Object.freeze(a)}const le=_e(R);var ae={exports:{}},Q={};var pe;function Ae(){if(pe)return Q;pe=1;var n=Symbol.for("react.transitional.element"),a=Symbol.for("react.fragment");function e(s,t,i){var o=null;if(i!==void 0&&(o=""+i),t.key!==void 0&&(o=""+t.key),"key"in t){i={};for(var l in t)l!=="key"&&(i[l]=t[l])}else i=t;return t=i.ref,{$$typeof:n,type:s,key:o,ref:t!==void 0?t:null,props:i}}return Q.Fragment=a,Q.jsx=e,Q.jsxs=e,Q}var ee={};var ge;function Re(){return ge||(ge=1,process.env.NODE_ENV!=="production"&&(function(){function n(r){if(r==null)return null;if(typeof r=="function")return r.$$typeof===U?null:r.displayName||r.name||null;if(typeof r=="string")return r;switch(r){case w:return"Fragment";case O:return"Profiler";case z:return"StrictMode";case Y:return"Suspense";case $:return"SuspenseList";case J:return"Activity"}if(typeof r=="object")switch(typeof r.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),r.$$typeof){case v:return"Portal";case M:return r.displayName||"Context";case F:return(r._context.displayName||"Context")+".Consumer";case C:var h=r.render;return r=r.displayName,r||(r=h.displayName||h.name||"",r=r!==""?"ForwardRef("+r+")":"ForwardRef"),r;case L:return h=r.displayName||null,h!==null?h:n(r.type)||"Memo";case I:h=r._payload,r=r._init;try{return n(r(h))}catch{}}return null}function a(r){return""+r}function e(r){try{a(r);var h=!1}catch{h=!0}if(h){h=console;var y=h.error,S=typeof Symbol=="function"&&Symbol.toStringTag&&r[Symbol.toStringTag]||r.constructor.name||"Object";return y.call(h,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",S),a(r)}}function s(r){if(r===w)return"<>";if(typeof r=="object"&&r!==null&&r.$$typeof===I)return"<...>";try{var h=n(r);return h?"<"+h+">":"<...>"}catch{return"<...>"}}function t(){var r=K.A;return r===null?null:r.getOwner()}function i(){return Error("react-stack-top-frame")}function o(r){if(te.call(r,"key")){var h=Object.getOwnPropertyDescriptor(r,"key").get;if(h&&h.isReactWarning)return!1}return r.key!==void 0}function l(r,h){function y(){ce||(ce=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",h))}y.isReactWarning=!0,Object.defineProperty(r,"key",{get:y,configurable:!0})}function p(){var r=n(this.type);return ne[r]||(ne[r]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),r=this.props.ref,r!==void 0?r:null}function g(r,h,y,S,G,Z){var f=y.ref;return r={$$typeof:_,type:r,key:h,props:y,_owner:S},(f!==void 0?f:null)!==null?Object.defineProperty(r,"ref",{enumerable:!1,get:p}):Object.defineProperty(r,"ref",{enumerable:!1,value:null}),r._store={},Object.defineProperty(r._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(r,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(r,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:G}),Object.defineProperty(r,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:Z}),Object.freeze&&(Object.freeze(r.props),Object.freeze(r)),r}function m(r,h,y,S,G,Z){var f=h.children;if(f!==void 0)if(S)if(D(f)){for(S=0;S<f.length;S++)E(f[S]);Object.freeze&&Object.freeze(f)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else E(f);if(te.call(h,"key")){f=n(r);var x=Object.keys(h).filter(function(j){return j!=="key"});S=0<x.length?"{key: someKey, "+x.join(": ..., ")+": ...}":"{key: someKey}",ue[f+S]||(x=0<x.length?"{"+x.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
2
2
  let props = %s;
3
3
  <%s {...props} />
4
4
  React keys must be passed directly to JSX without using spread:
5
5
  let props = %s;
6
- <%s key={someKey} {...props} />`,w,O,$,O),I[O+w]=!0)}if(O=null,x!==void 0&&(e(x),O=""+x),o(u)&&(e(u.key),O=""+u.key),"key"in u){x={};for(var se in u)se!=="key"&&(x[se]=u[se])}else x=u;return O&&l(x,typeof r=="function"?r.displayName||r.name||"Unknown":r),v(r,O,x,n(),K,ne)}function S(r){c(r)?r._store&&(r._store.validated=1):typeof r=="object"&&r!==null&&r.$$typeof===V&&(r._payload.status==="fulfilled"?c(r._payload.value)&&r._payload.value._store&&(r._payload.value._store.validated=1):r._store&&(r._store.validated=1))}function c(r){return typeof r=="object"&&r!==null&&r.$$typeof===T}var m=j,T=Symbol.for("react.transitional.element"),g=Symbol.for("react.portal"),_=Symbol.for("react.fragment"),z=Symbol.for("react.strict_mode"),p=Symbol.for("react.profiler"),C=Symbol.for("react.consumer"),k=Symbol.for("react.context"),D=Symbol.for("react.forward_ref"),B=Symbol.for("react.suspense"),N=Symbol.for("react.suspense_list"),H=Symbol.for("react.memo"),V=Symbol.for("react.lazy"),q=Symbol.for("react.activity"),ee=Symbol.for("react.client.reference"),Y=m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,J=Object.prototype.hasOwnProperty,te=Array.isArray,E=console.createTask?console.createTask:function(){return null};m={react_stack_bottom_frame:function(r){return r()}};var M,R={},y=m.react_stack_bottom_frame.bind(m,i)(),h=E(s(i)),I={};L.Fragment=_,L.jsx=function(r,u,x){var w=1e4>Y.recentlyCreatedOwnerStacks++;return d(r,u,x,!1,w?Error("react-stack-top-frame"):y,w?E(s(r)):h)},L.jsxs=function(r,u,x){var w=1e4>Y.recentlyCreatedOwnerStacks++;return d(r,u,x,!0,w?Error("react-stack-top-frame"):y,w?E(s(r)):h)}})()),L}var le;function xe(){return le||(le=1,process.env.NODE_ENV==="production"?G.exports=ye():G.exports=Ee()),G.exports}var b=xe();function Se(t){return t.data?Array.isArray(t.data)?{provider:"value",items:t.data}:t.data:t.staticData?{provider:"value",items:t.staticData}:t.objectName?{provider:"object",object:t.objectName}:null}function ae(t){if(!(!t||t.length===0))return typeof t[0]=="object"&&t[0]!==null,t}const ce=({schema:t,dataSource:a,onEdit:e,onDelete:s,onRowSelect:n,onRowClick:i,...o})=>{const[l,f]=j.useState([]),[v,d]=j.useState(!0),[S,c]=j.useState(null),[m,T]=j.useState(null),g=o.data,_=X.useDataScope(t.bind),z=Se(t),p=j.useMemo(()=>g&&Array.isArray(g)?{provider:"value",items:g}:_&&Array.isArray(_)?{provider:"value",items:_}:z,[JSON.stringify(z),_,g]),C=p?.provider==="value";j.useEffect(()=>{C&&p?.provider==="value"&&(f(E=>{const M=p.items;return JSON.stringify(E)!==JSON.stringify(M)?M:E}),d(!1))},[C,p]),j.useEffect(()=>{const E=async()=>{try{if(!a)throw new Error("DataSource required");const R=p?.provider==="object"&&"object"in p?p.object:t.objectName;if(!R)throw new Error("Object name required for object provider");const y=await a.getObjectSchema(R);T(y)}catch(R){c(R)}},M=ae(t.columns)||t.fields;C&&M?T({name:t.objectName,fields:{}}):t.objectName&&!C&&a&&E()},[t.objectName,t.columns,t.fields,a,C,p]);const k=j.useCallback(()=>{const E=ae(t.columns);if(E){if(E.length>0&&typeof E[0]=="object"&&E[0]!==null){const y=E[0];if("accessorKey"in y)return E;if("field"in y)return E.filter(h=>h?.field&&typeof h.field=="string").map(h=>({header:h.label||h.field.charAt(0).toUpperCase()+h.field.slice(1).replace(/_/g," "),accessorKey:h.field,...h.width&&{width:h.width},...h.align&&{align:h.align},sortable:h.sortable!==!1}))}return E.filter(y=>typeof y=="string"&&y.trim().length>0).map(y=>({header:m?.fields?.[y]?.label||y.charAt(0).toUpperCase()+y.slice(1).replace(/_/g," "),accessorKey:y}))}if(C){const y=p?.provider==="value"?p.items:[];if(y.length>0)return(t.fields||Object.keys(y[0])).map(I=>({header:I.charAt(0).toUpperCase()+I.slice(1).replace(/_/g," "),accessorKey:I}))}if(!m)return[];const M=[];return(t.fields||Object.keys(m.fields||{})).forEach(y=>{const h=m.fields?.[y];if(!h||h.permissions&&h.permissions.read===!1)return;const I=pe.getCellRenderer(h.type);M.push({header:h.label||y,accessorKey:y,cell:r=>b.jsx(I,{value:r,field:h}),sortable:h.sortable!==!1})}),M},[m,t.fields,t.columns,p,C]),D=j.useCallback(async()=>{if(!(C||!a)){d(!0);try{const E=p?.provider==="object"&&"object"in p?p.object:t.objectName;if(!E)throw new Error("Object name required for data fetching");const R={$select:(()=>{if(t.fields)return t.fields;if(t.columns&&Array.isArray(t.columns))return t.columns.map(h=>typeof h=="string"?h:h.field)})(),$top:t.pagination?.pageSize||t.pageSize||50};t.filter&&Array.isArray(t.filter)?R.$filter=t.filter:"defaultFilters"in t&&t.defaultFilters&&(R.$filter=t.defaultFilters),t.sort?typeof t.sort=="string"?R.$orderby=t.sort:Array.isArray(t.sort)&&(R.$orderby=t.sort.map(h=>`${h.field} ${h.order}`).join(", ")):"defaultSort"in t&&t.defaultSort&&(R.$orderby=`${t.defaultSort.field} ${t.defaultSort.order}`);const y=await a.find(E,R);f(y.data||[])}catch(E){c(E)}finally{d(!1)}}},[t,a,C,p]);if(j.useEffect(()=>{(m||C)&&D()},[m,C,D]),S)return b.jsxs("div",{className:"p-4 border border-red-300 bg-red-50 rounded-md",children:[b.jsx("h3",{className:"text-red-800 font-semibold",children:"Error loading grid"}),b.jsx("p",{className:"text-red-600 text-sm mt-1",children:S.message})]});if(v&&l.length===0)return b.jsxs("div",{className:"p-8 text-center",children:[b.jsx("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"}),b.jsx("p",{className:"mt-2 text-sm text-gray-600",children:"Loading grid..."})]});const B=k(),N="operations"in t?t.operations:void 0,H=N&&(N.update||N.delete),V=H?[...B,{header:"Actions",accessorKey:"_actions",cell:(E,M)=>b.jsxs(P.DropdownMenu,{children:[b.jsx(P.DropdownMenuTrigger,{asChild:!0,children:b.jsxs(P.Button,{variant:"ghost",size:"icon",className:"h-8 w-8",children:[b.jsx(Z.MoreVertical,{className:"h-4 w-4"}),b.jsx("span",{className:"sr-only",children:"Open menu"})]})}),b.jsxs(P.DropdownMenuContent,{align:"end",children:[N?.update&&e&&b.jsxs(P.DropdownMenuItem,{onClick:()=>e(M),children:[b.jsx(Z.Edit,{className:"mr-2 h-4 w-4"}),"Edit"]}),N?.delete&&s&&b.jsxs(P.DropdownMenuItem,{onClick:()=>s(M),children:[b.jsx(Z.Trash2,{className:"mr-2 h-4 w-4"}),"Delete"]})]})]}),sortable:!1}]:B;let q=!1;t.selection?.type?q=t.selection.type==="none"?!1:t.selection.type:t.selectable!==void 0&&(q=t.selectable);const ee=t.pagination!==void 0?!0:t.showPagination!==void 0?t.showPagination:!0,Y=t.pagination?.pageSize||t.pageSize||10,J=t.searchableFields!==void 0?t.searchableFields.length>0:t.showSearch!==void 0?t.showSearch:!0,te={type:"data-table",caption:t.label||t.title,columns:V,data:l,pagination:ee,pageSize:Y,searchable:J,selectable:q,sortable:!0,exportable:N?.export,rowActions:H,resizableColumns:t.resizable??t.resizableColumns??!0,reorderableColumns:t.reorderableColumns??!1,className:t.className,onSelectionChange:n,onRowClick:i};return b.jsx(X.SchemaRenderer,{schema:te})};function F(t,a,e){let s=e.initialDeps??[],n,i=!0;function o(){var l,f,v;let d;e.key&&((l=e.debug)!=null&&l.call(e))&&(d=Date.now());const S=t();if(!(S.length!==s.length||S.some((T,g)=>s[g]!==T)))return n;s=S;let m;if(e.key&&((f=e.debug)!=null&&f.call(e))&&(m=Date.now()),n=a(...S),e.key&&((v=e.debug)!=null&&v.call(e))){const T=Math.round((Date.now()-d)*100)/100,g=Math.round((Date.now()-m)*100)/100,_=g/16,z=(p,C)=>{for(p=String(p);p.length<C;)p=" "+p;return p};console.info(`%c⏱ ${z(g,5)} /${z(T,5)} ms`,`
6
+ <%s key={someKey} {...props} />`,S,f,x,f),ue[f+S]=!0)}if(f=null,y!==void 0&&(e(y),f=""+y),o(h)&&(e(h.key),f=""+h.key),"key"in h){y={};for(var N in h)N!=="key"&&(y[N]=h[N])}else y=h;return f&&l(y,typeof r=="function"?r.displayName||r.name||"Unknown":r),g(r,f,y,t(),G,Z)}function E(r){u(r)?r._store&&(r._store.validated=1):typeof r=="object"&&r!==null&&r.$$typeof===I&&(r._payload.status==="fulfilled"?u(r._payload.value)&&r._payload.value._store&&(r._payload.value._store.validated=1):r._store&&(r._store.validated=1))}function u(r){return typeof r=="object"&&r!==null&&r.$$typeof===_}var b=R,_=Symbol.for("react.transitional.element"),v=Symbol.for("react.portal"),w=Symbol.for("react.fragment"),z=Symbol.for("react.strict_mode"),O=Symbol.for("react.profiler"),F=Symbol.for("react.consumer"),M=Symbol.for("react.context"),C=Symbol.for("react.forward_ref"),Y=Symbol.for("react.suspense"),$=Symbol.for("react.suspense_list"),L=Symbol.for("react.memo"),I=Symbol.for("react.lazy"),J=Symbol.for("react.activity"),U=Symbol.for("react.client.reference"),K=b.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,te=Object.prototype.hasOwnProperty,D=Array.isArray,X=console.createTask?console.createTask:function(){return null};b={react_stack_bottom_frame:function(r){return r()}};var ce,ne={},V=b.react_stack_bottom_frame.bind(b,i)(),se=X(s(i)),ue={};ee.Fragment=w,ee.jsx=function(r,h,y){var S=1e4>K.recentlyCreatedOwnerStacks++;return m(r,h,y,!1,S?Error("react-stack-top-frame"):V,S?X(s(r)):se)},ee.jsxs=function(r,h,y){var S=1e4>K.recentlyCreatedOwnerStacks++;return m(r,h,y,!0,S?Error("react-stack-top-frame"):V,S?X(s(r)):se)}})()),ee}var be;function Te(){return be||(be=1,process.env.NODE_ENV==="production"?ae.exports=Ae():ae.exports=Re()),ae.exports}var c=Te();function Ne(n){return n.data?Array.isArray(n.data)?{provider:"value",items:n.data}:n.data:n.staticData?{provider:"value",items:n.staticData}:n.objectName?{provider:"object",object:n.objectName}:null}function ve(n){if(!(!n||n.length===0))return typeof n[0]=="object"&&n[0]!==null,n}const ye=({schema:n,dataSource:a,onEdit:e,onDelete:s,onRowSelect:t,onRowClick:i,onCellChange:o,onRowSave:l,onBatchSave:p,...g})=>{const[m,E]=R.useState([]),[u,b]=R.useState(!0),[_,v]=R.useState(null),[w,z]=R.useState(null),O=g.data,F=B.useDataScope(n.bind),M=Ne(n),C=R.useMemo(()=>O&&Array.isArray(O)?{provider:"value",items:O}:F&&Array.isArray(F)?{provider:"value",items:F}:M,[JSON.stringify(M),F,O]),Y=C?.provider==="value",$=C?.provider==="object"&&C&&"object"in C?C.object:n.objectName,L=n.fields,I=n.columns,J=n.filter,U=n.sort,K=n.pagination,te=n.pageSize;R.useEffect(()=>{Y&&C?.provider==="value"&&(E(f=>{const x=C.items;return JSON.stringify(f)!==JSON.stringify(x)?x:f}),b(!1))},[Y,C]),R.useEffect(()=>{if(Y)return;let f=!1;return(async()=>{b(!0),v(null);try{let N=null;if((ve(I)||L)&&$)N={name:$,fields:{}};else if($&&a){const d=await a.getObjectSchema($);if(f)return;N=d}else throw $?new Error("DataSource required"):new Error("Object name required for data fetching");if(f||z(N),a&&$){const k={$select:(()=>{if(L)return L;if(I&&Array.isArray(I))return I.map(T=>typeof T=="string"?T:T.field)})(),$top:K?.pageSize||te||50};J&&Array.isArray(J)?k.$filter=J:n.defaultFilters&&(k.$filter=n.defaultFilters),U?typeof U=="string"?k.$orderby=U:Array.isArray(U)&&(k.$orderby=U.map(T=>`${T.field} ${T.order}`).join(", ")):n.defaultSort&&(k.$orderby=`${n.defaultSort.field} ${n.defaultSort.order}`);const W=await a.find($,k);if(f)return;E(W.data||[])}}catch(N){f||v(N)}finally{f||b(!1)}})(),()=>{f=!0}},[$,L,I,J,U,K,te,a,Y,C]);const D=B.useNavigationOverlay({navigation:n.navigation,objectName:n.objectName,onNavigate:n.onNavigate,onRowClick:i}),{execute:X}=B.useAction(),ce=R.useCallback(()=>{const f=ve(I);if(f){if(f.length>0&&typeof f[0]=="object"&&f[0]!==null){const j=f[0];if("accessorKey"in j)return f;if("field"in j)return f.filter(d=>d?.field&&typeof d.field=="string"&&!d.hidden).map(d=>{const k=d.label||d.field.charAt(0).toUpperCase()+d.field.slice(1).replace(/_/g," ");let W;const T=d.type?me.getCellRenderer(d.type):null;return d.link&&d.action?W=(P,re)=>{const ie=T?c.jsx(T,{value:P,field:{name:d.field,type:d.type||"text"}}):String(P??"");return c.jsx("button",{type:"button",className:"text-primary underline-offset-4 hover:underline cursor-pointer bg-transparent border-none p-0 text-left font-inherit",onClick:oe=>{oe.stopPropagation(),D.handleClick(re)},children:ie})}:d.link?W=(P,re)=>{const ie=T?c.jsx(T,{value:P,field:{name:d.field,type:d.type||"text"}}):String(P??"");return c.jsx("button",{type:"button",className:"text-primary underline-offset-4 hover:underline cursor-pointer bg-transparent border-none p-0 text-left font-inherit",onClick:oe=>{oe.stopPropagation(),D.handleClick(re)},children:ie})}:d.action?W=(P,re)=>{const ie=T?c.jsx(T,{value:P,field:{name:d.field,type:d.type||"text"}}):String(P??"");return c.jsx("button",{type:"button",className:"text-primary underline-offset-4 hover:underline cursor-pointer bg-transparent border-none p-0 text-left font-inherit",onClick:oe=>{oe.stopPropagation(),X({type:d.action,params:{record:re,field:d.field,value:P}})},children:ie})}:T&&(W=P=>c.jsx(T,{value:P,field:{name:d.field,type:d.type||"text"}})),{header:k,accessorKey:d.field,...d.width&&{width:d.width},...d.align&&{align:d.align},sortable:d.sortable!==!1,...d.resizable!==void 0&&{resizable:d.resizable},...d.wrap!==void 0&&{wrap:d.wrap},...W&&{cell:W}}})}return f.filter(j=>typeof j=="string"&&j.trim().length>0).map(j=>({header:w?.fields?.[j]?.label||j.charAt(0).toUpperCase()+j.slice(1).replace(/_/g," "),accessorKey:j}))}if(Y){const j=C?.provider==="value"?C.items:[];if(j.length>0)return(L||Object.keys(j[0])).map(k=>({header:k.charAt(0).toUpperCase()+k.slice(1).replace(/_/g," "),accessorKey:k}))}if(!w)return[];const x=[];return(L||Object.keys(w.fields||{})).forEach(j=>{const d=w.fields?.[j];if(!d||d.permissions&&d.permissions.read===!1)return;const k=me.getCellRenderer(d.type);x.push({header:d.label||j,accessorKey:j,cell:W=>c.jsx(k,{value:W,field:d}),sortable:d.sortable!==!1})}),x},[w,L,I,C,Y,D.handleClick,X]);if(_)return c.jsxs("div",{className:"p-4 border border-red-300 bg-red-50 rounded-md",children:[c.jsx("h3",{className:"text-red-800 font-semibold",children:"Error loading grid"}),c.jsx("p",{className:"text-red-600 text-sm mt-1",children:_.message})]});if(u&&m.length===0)return c.jsxs("div",{className:"p-8 text-center",children:[c.jsx("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"}),c.jsx("p",{className:"mt-2 text-sm text-gray-600",children:"Loading grid..."})]});const ne=ce(),V="operations"in n?n.operations:void 0,se=V&&(V.update||V.delete),ue=se?[...ne,{header:"Actions",accessorKey:"_actions",cell:(f,x)=>c.jsxs(q.DropdownMenu,{children:[c.jsx(q.DropdownMenuTrigger,{asChild:!0,children:c.jsxs(q.Button,{variant:"ghost",size:"icon",className:"h-8 w-8",children:[c.jsx(de.MoreVertical,{className:"h-4 w-4"}),c.jsx("span",{className:"sr-only",children:"Open menu"})]})}),c.jsxs(q.DropdownMenuContent,{align:"end",children:[V?.update&&e&&c.jsxs(q.DropdownMenuItem,{onClick:()=>e(x),children:[c.jsx(de.Edit,{className:"mr-2 h-4 w-4"}),"Edit"]}),V?.delete&&s&&c.jsxs(q.DropdownMenuItem,{onClick:()=>s(x),children:[c.jsx(de.Trash2,{className:"mr-2 h-4 w-4"}),"Delete"]})]})]}),sortable:!1}]:ne;let r=!1;n.selection?.type?r=n.selection.type==="none"?!1:n.selection.type:n.selectable!==void 0&&(r=n.selectable);const h=n.pagination!==void 0?!0:n.showPagination!==void 0?n.showPagination:!0,y=n.pagination?.pageSize||n.pageSize||10,S=n.searchableFields!==void 0?n.searchableFields.length>0:n.showSearch!==void 0?n.showSearch:!0,G={type:"data-table",caption:n.label||n.title,columns:ue,data:m,pagination:h,pageSize:y,searchable:S,selectable:r,sortable:!0,exportable:V?.export,rowActions:se,resizableColumns:n.resizable??n.resizableColumns??!0,reorderableColumns:n.reorderableColumns??!1,editable:n.editable??!1,className:n.className,onSelectionChange:t,onRowClick:D.handleClick,onCellChange:o,onRowSave:l,onBatchSave:p},Z=n.label?`${n.label} Detail`:n.objectName?`${n.objectName.charAt(0).toUpperCase()+n.objectName.slice(1)} Detail`:"Record Detail";return D.isOverlay&&D.mode==="split"?c.jsx(q.NavigationOverlay,{...D,title:Z,mainContent:c.jsx(B.SchemaRenderer,{schema:G}),children:f=>c.jsx("div",{className:"space-y-3",children:Object.entries(f).map(([x,N])=>c.jsxs("div",{className:"flex flex-col",children:[c.jsx("span",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wide",children:x.replace(/_/g," ")}),c.jsx("span",{className:"text-sm",children:String(N??"—")})]},x))})}):c.jsxs(c.Fragment,{children:[c.jsx(B.SchemaRenderer,{schema:G}),D.isOverlay&&c.jsx(q.NavigationOverlay,{...D,title:Z,children:f=>c.jsx("div",{className:"space-y-3",children:Object.entries(f).map(([x,N])=>c.jsxs("div",{className:"flex flex-col",children:[c.jsx("span",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wide",children:x.replace(/_/g," ")}),c.jsx("span",{className:"text-sm",children:String(N??"—")})]},x))})})]})};function H(n,a,e){let s=e.initialDeps??[],t,i=!0;function o(){var l,p,g;let m;e.key&&((l=e.debug)!=null&&l.call(e))&&(m=Date.now());const E=n();if(!(E.length!==s.length||E.some((_,v)=>s[v]!==_)))return t;s=E;let b;if(e.key&&((p=e.debug)!=null&&p.call(e))&&(b=Date.now()),t=a(...E),e.key&&((g=e.debug)!=null&&g.call(e))){const _=Math.round((Date.now()-m)*100)/100,v=Math.round((Date.now()-b)*100)/100,w=v/16,z=(O,F)=>{for(O=String(O);O.length<F;)O=" "+O;return O};console.info(`%c⏱ ${z(v,5)} /${z(_,5)} ms`,`
7
7
  font-size: .6rem;
8
8
  font-weight: bold;
9
- color: hsl(${Math.max(0,Math.min(120-120*_,120))}deg 100% 31%);`,e?.key)}return e?.onChange&&!(i&&e.skipInitialOnChange)&&e.onChange(n),i=!1,n}return o.updateDeps=l=>{s=l},o}function ue(t,a){if(t===void 0)throw new Error("Unexpected undefined");return t}const we=(t,a)=>Math.abs(t-a)<1.01,Oe=(t,a,e)=>{let s;return function(...n){t.clearTimeout(s),s=t.setTimeout(()=>a.apply(this,n),e)}},de=t=>{const{offsetWidth:a,offsetHeight:e}=t;return{width:a,height:e}},je=t=>t,_e=t=>{const a=Math.max(t.startIndex-t.overscan,0),e=Math.min(t.endIndex+t.overscan,t.count-1),s=[];for(let n=a;n<=e;n++)s.push(n);return s},Ce=(t,a)=>{const e=t.scrollElement;if(!e)return;const s=t.targetWindow;if(!s)return;const n=o=>{const{width:l,height:f}=o;a({width:Math.round(l),height:Math.round(f)})};if(n(de(e)),!s.ResizeObserver)return()=>{};const i=new s.ResizeObserver(o=>{const l=()=>{const f=o[0];if(f?.borderBoxSize){const v=f.borderBoxSize[0];if(v){n({width:v.inlineSize,height:v.blockSize});return}}n(de(e))};t.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(l):l()});return i.observe(e,{box:"border-box"}),()=>{i.unobserve(e)}},fe={passive:!0},he=typeof window>"u"?!0:"onscrollend"in window,Te=(t,a)=>{const e=t.scrollElement;if(!e)return;const s=t.targetWindow;if(!s)return;let n=0;const i=t.options.useScrollendEvent&&he?()=>{}:Oe(s,()=>{a(n,!1)},t.options.isScrollingResetDelay),o=d=>()=>{const{horizontal:S,isRtl:c}=t.options;n=S?e.scrollLeft*(c&&-1||1):e.scrollTop,i(),a(n,d)},l=o(!0),f=o(!1);e.addEventListener("scroll",l,fe);const v=t.options.useScrollendEvent&&he;return v&&e.addEventListener("scrollend",f,fe),()=>{e.removeEventListener("scroll",l),v&&e.removeEventListener("scrollend",f)}},Ae=(t,a,e)=>{if(a?.borderBoxSize){const s=a.borderBoxSize[0];if(s)return Math.round(s[e.options.horizontal?"inlineSize":"blockSize"])}return t[e.options.horizontal?"offsetWidth":"offsetHeight"]},Re=(t,{adjustments:a=0,behavior:e},s)=>{var n,i;const o=t+a;(i=(n=s.scrollElement)==null?void 0:n.scrollTo)==null||i.call(n,{[s.options.horizontal?"left":"top"]:o,behavior:e})};class Me{constructor(a){this.unsubs=[],this.scrollElement=null,this.targetWindow=null,this.isScrolling=!1,this.currentScrollToIndex=null,this.measurementsCache=[],this.itemSizeCache=new Map,this.laneAssignments=new Map,this.pendingMeasuredCacheIndexes=[],this.prevLanes=void 0,this.lanesChangedFlag=!1,this.lanesSettling=!1,this.scrollRect=null,this.scrollOffset=null,this.scrollDirection=null,this.scrollAdjustments=0,this.elementsCache=new Map,this.observer=(()=>{let e=null;const s=()=>e||(!this.targetWindow||!this.targetWindow.ResizeObserver?null:e=new this.targetWindow.ResizeObserver(n=>{n.forEach(i=>{const o=()=>{this._measureElement(i.target,i)};this.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(o):o()})}));return{disconnect:()=>{var n;(n=s())==null||n.disconnect(),e=null},observe:n=>{var i;return(i=s())==null?void 0:i.observe(n,{box:"border-box"})},unobserve:n=>{var i;return(i=s())==null?void 0:i.unobserve(n)}}})(),this.range=null,this.setOptions=e=>{Object.entries(e).forEach(([s,n])=>{typeof n>"u"&&delete e[s]}),this.options={debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:je,rangeExtractor:_e,onChange:()=>{},measureElement:Ae,initialRect:{width:0,height:0},scrollMargin:0,gap:0,indexAttribute:"data-index",initialMeasurementsCache:[],lanes:1,isScrollingResetDelay:150,enabled:!0,isRtl:!1,useScrollendEvent:!1,useAnimationFrameWithResizeObserver:!1,...e}},this.notify=e=>{var s,n;(n=(s=this.options).onChange)==null||n.call(s,this,e)},this.maybeNotify=F(()=>(this.calculateRange(),[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]),e=>{this.notify(e)},{key:process.env.NODE_ENV!=="production"&&"maybeNotify",debug:()=>this.options.debug,initialDeps:[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]}),this.cleanup=()=>{this.unsubs.filter(Boolean).forEach(e=>e()),this.unsubs=[],this.observer.disconnect(),this.scrollElement=null,this.targetWindow=null},this._didMount=()=>()=>{this.cleanup()},this._willUpdate=()=>{var e;const s=this.options.enabled?this.options.getScrollElement():null;if(this.scrollElement!==s){if(this.cleanup(),!s){this.maybeNotify();return}this.scrollElement=s,this.scrollElement&&"ownerDocument"in this.scrollElement?this.targetWindow=this.scrollElement.ownerDocument.defaultView:this.targetWindow=((e=this.scrollElement)==null?void 0:e.window)??null,this.elementsCache.forEach(n=>{this.observer.observe(n)}),this.unsubs.push(this.options.observeElementRect(this,n=>{this.scrollRect=n,this.maybeNotify()})),this.unsubs.push(this.options.observeElementOffset(this,(n,i)=>{this.scrollAdjustments=0,this.scrollDirection=i?this.getScrollOffset()<n?"forward":"backward":null,this.scrollOffset=n,this.isScrolling=i,this.maybeNotify()})),this._scrollToOffset(this.getScrollOffset(),{adjustments:void 0,behavior:void 0})}},this.getSize=()=>this.options.enabled?(this.scrollRect=this.scrollRect??this.options.initialRect,this.scrollRect[this.options.horizontal?"width":"height"]):(this.scrollRect=null,0),this.getScrollOffset=()=>this.options.enabled?(this.scrollOffset=this.scrollOffset??(typeof this.options.initialOffset=="function"?this.options.initialOffset():this.options.initialOffset),this.scrollOffset):(this.scrollOffset=null,0),this.getFurthestMeasurement=(e,s)=>{const n=new Map,i=new Map;for(let o=s-1;o>=0;o--){const l=e[o];if(n.has(l.lane))continue;const f=i.get(l.lane);if(f==null||l.end>f.end?i.set(l.lane,l):l.end<f.end&&n.set(l.lane,!0),n.size===this.options.lanes)break}return i.size===this.options.lanes?Array.from(i.values()).sort((o,l)=>o.end===l.end?o.index-l.index:o.end-l.end)[0]:void 0},this.getMeasurementOptions=F(()=>[this.options.count,this.options.paddingStart,this.options.scrollMargin,this.options.getItemKey,this.options.enabled,this.options.lanes],(e,s,n,i,o,l)=>(this.prevLanes!==void 0&&this.prevLanes!==l&&(this.lanesChangedFlag=!0),this.prevLanes=l,this.pendingMeasuredCacheIndexes=[],{count:e,paddingStart:s,scrollMargin:n,getItemKey:i,enabled:o,lanes:l}),{key:!1}),this.getMeasurements=F(()=>[this.getMeasurementOptions(),this.itemSizeCache],({count:e,paddingStart:s,scrollMargin:n,getItemKey:i,enabled:o,lanes:l},f)=>{if(!o)return this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),[];if(this.laneAssignments.size>e)for(const c of this.laneAssignments.keys())c>=e&&this.laneAssignments.delete(c);this.lanesChangedFlag&&(this.lanesChangedFlag=!1,this.lanesSettling=!0,this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),this.pendingMeasuredCacheIndexes=[]),this.measurementsCache.length===0&&!this.lanesSettling&&(this.measurementsCache=this.options.initialMeasurementsCache,this.measurementsCache.forEach(c=>{this.itemSizeCache.set(c.key,c.size)}));const v=this.lanesSettling?0:this.pendingMeasuredCacheIndexes.length>0?Math.min(...this.pendingMeasuredCacheIndexes):0;this.pendingMeasuredCacheIndexes=[],this.lanesSettling&&this.measurementsCache.length===e&&(this.lanesSettling=!1);const d=this.measurementsCache.slice(0,v),S=new Array(l).fill(void 0);for(let c=0;c<v;c++){const m=d[c];m&&(S[m.lane]=c)}for(let c=v;c<e;c++){const m=i(c),T=this.laneAssignments.get(c);let g,_;if(T!==void 0&&this.options.lanes>1){g=T;const k=S[g],D=k!==void 0?d[k]:void 0;_=D?D.end+this.options.gap:s+n}else{const k=this.options.lanes===1?d[c-1]:this.getFurthestMeasurement(d,c);_=k?k.end+this.options.gap:s+n,g=k?k.lane:c%this.options.lanes,this.options.lanes>1&&this.laneAssignments.set(c,g)}const z=f.get(m),p=typeof z=="number"?z:this.options.estimateSize(c),C=_+p;d[c]={index:c,start:_,size:p,end:C,key:m,lane:g},S[g]=c}return this.measurementsCache=d,d},{key:process.env.NODE_ENV!=="production"&&"getMeasurements",debug:()=>this.options.debug}),this.calculateRange=F(()=>[this.getMeasurements(),this.getSize(),this.getScrollOffset(),this.options.lanes],(e,s,n,i)=>this.range=e.length>0&&s>0?ze({measurements:e,outerSize:s,scrollOffset:n,lanes:i}):null,{key:process.env.NODE_ENV!=="production"&&"calculateRange",debug:()=>this.options.debug}),this.getVirtualIndexes=F(()=>{let e=null,s=null;const n=this.calculateRange();return n&&(e=n.startIndex,s=n.endIndex),this.maybeNotify.updateDeps([this.isScrolling,e,s]),[this.options.rangeExtractor,this.options.overscan,this.options.count,e,s]},(e,s,n,i,o)=>i===null||o===null?[]:e({startIndex:i,endIndex:o,overscan:s,count:n}),{key:process.env.NODE_ENV!=="production"&&"getVirtualIndexes",debug:()=>this.options.debug}),this.indexFromElement=e=>{const s=this.options.indexAttribute,n=e.getAttribute(s);return n?parseInt(n,10):(console.warn(`Missing attribute name '${s}={index}' on measured element.`),-1)},this._measureElement=(e,s)=>{const n=this.indexFromElement(e),i=this.measurementsCache[n];if(!i)return;const o=i.key,l=this.elementsCache.get(o);l!==e&&(l&&this.observer.unobserve(l),this.observer.observe(e),this.elementsCache.set(o,e)),e.isConnected&&this.resizeItem(n,this.options.measureElement(e,s,this))},this.resizeItem=(e,s)=>{const n=this.measurementsCache[e];if(!n)return;const i=this.itemSizeCache.get(n.key)??n.size,o=s-i;o!==0&&((this.shouldAdjustScrollPositionOnItemSizeChange!==void 0?this.shouldAdjustScrollPositionOnItemSizeChange(n,o,this):n.start<this.getScrollOffset()+this.scrollAdjustments)&&(process.env.NODE_ENV!=="production"&&this.options.debug&&console.info("correction",o),this._scrollToOffset(this.getScrollOffset(),{adjustments:this.scrollAdjustments+=o,behavior:void 0})),this.pendingMeasuredCacheIndexes.push(n.index),this.itemSizeCache=new Map(this.itemSizeCache.set(n.key,s)),this.notify(!1))},this.measureElement=e=>{if(!e){this.elementsCache.forEach((s,n)=>{s.isConnected||(this.observer.unobserve(s),this.elementsCache.delete(n))});return}this._measureElement(e,void 0)},this.getVirtualItems=F(()=>[this.getVirtualIndexes(),this.getMeasurements()],(e,s)=>{const n=[];for(let i=0,o=e.length;i<o;i++){const l=e[i],f=s[l];n.push(f)}return n},{key:process.env.NODE_ENV!=="production"&&"getVirtualItems",debug:()=>this.options.debug}),this.getVirtualItemForOffset=e=>{const s=this.getMeasurements();if(s.length!==0)return ue(s[me(0,s.length-1,n=>ue(s[n]).start,e)])},this.getMaxScrollOffset=()=>{if(!this.scrollElement)return 0;if("scrollHeight"in this.scrollElement)return this.options.horizontal?this.scrollElement.scrollWidth-this.scrollElement.clientWidth:this.scrollElement.scrollHeight-this.scrollElement.clientHeight;{const e=this.scrollElement.document.documentElement;return this.options.horizontal?e.scrollWidth-this.scrollElement.innerWidth:e.scrollHeight-this.scrollElement.innerHeight}},this.getOffsetForAlignment=(e,s,n=0)=>{if(!this.scrollElement)return 0;const i=this.getSize(),o=this.getScrollOffset();s==="auto"&&(s=e>=o+i?"end":"start"),s==="center"?e+=(n-i)/2:s==="end"&&(e-=i);const l=this.getMaxScrollOffset();return Math.max(Math.min(l,e),0)},this.getOffsetForIndex=(e,s="auto")=>{e=Math.max(0,Math.min(e,this.options.count-1));const n=this.measurementsCache[e];if(!n)return;const i=this.getSize(),o=this.getScrollOffset();if(s==="auto")if(n.end>=o+i-this.options.scrollPaddingEnd)s="end";else if(n.start<=o+this.options.scrollPaddingStart)s="start";else return[o,s];if(s==="end"&&e===this.options.count-1)return[this.getMaxScrollOffset(),s];const l=s==="end"?n.end+this.options.scrollPaddingEnd:n.start-this.options.scrollPaddingStart;return[this.getOffsetForAlignment(l,s,n.size),s]},this.isDynamicMode=()=>this.elementsCache.size>0,this.scrollToOffset=(e,{align:s="start",behavior:n}={})=>{n==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getOffsetForAlignment(e,s),{adjustments:void 0,behavior:n})},this.scrollToIndex=(e,{align:s="auto",behavior:n}={})=>{n==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),e=Math.max(0,Math.min(e,this.options.count-1)),this.currentScrollToIndex=e;let i=0;const o=10,l=v=>{if(!this.targetWindow)return;const d=this.getOffsetForIndex(e,v);if(!d){console.warn("Failed to get offset for index:",e);return}const[S,c]=d;this._scrollToOffset(S,{adjustments:void 0,behavior:n}),this.targetWindow.requestAnimationFrame(()=>{const m=()=>{if(this.currentScrollToIndex!==e)return;const T=this.getScrollOffset(),g=this.getOffsetForIndex(e,c);if(!g){console.warn("Failed to get offset for index:",e);return}we(g[0],T)||f(c)};this.isDynamicMode()?this.targetWindow.requestAnimationFrame(m):m()})},f=v=>{this.targetWindow&&this.currentScrollToIndex===e&&(i++,i<o?(process.env.NODE_ENV!=="production"&&this.options.debug&&console.info("Schedule retry",i,o),this.targetWindow.requestAnimationFrame(()=>l(v))):console.warn(`Failed to scroll to index ${e} after ${o} attempts.`))};l(s)},this.scrollBy=(e,{behavior:s}={})=>{s==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getScrollOffset()+e,{adjustments:void 0,behavior:s})},this.getTotalSize=()=>{var e;const s=this.getMeasurements();let n;if(s.length===0)n=this.options.paddingStart;else if(this.options.lanes===1)n=((e=s[s.length-1])==null?void 0:e.end)??0;else{const i=Array(this.options.lanes).fill(null);let o=s.length-1;for(;o>=0&&i.some(l=>l===null);){const l=s[o];i[l.lane]===null&&(i[l.lane]=l.end),o--}n=Math.max(...i.filter(l=>l!==null))}return Math.max(n-this.options.scrollMargin+this.options.paddingEnd,0)},this._scrollToOffset=(e,{adjustments:s,behavior:n})=>{this.options.scrollToFn(e,{behavior:n,adjustments:s},this)},this.measure=()=>{this.itemSizeCache=new Map,this.laneAssignments=new Map,this.notify(!1)},this.setOptions(a)}}const me=(t,a,e,s)=>{for(;t<=a;){const n=(t+a)/2|0,i=e(n);if(i<s)t=n+1;else if(i>s)a=n-1;else return n}return t>0?t-1:0};function ze({measurements:t,outerSize:a,scrollOffset:e,lanes:s}){const n=t.length-1,i=f=>t[f].start;if(t.length<=s)return{startIndex:0,endIndex:n};let o=me(0,n,i,e),l=o;if(s===1)for(;l<n&&t[l].end<e+a;)l++;else if(s>1){const f=Array(s).fill(0);for(;l<n&&f.some(d=>d<e+a);){const d=t[l];f[d.lane]=d.end,l++}const v=Array(s).fill(e+a);for(;o>=0&&v.some(d=>d>=e);){const d=t[o];v[d.lane]=d.start,o--}o=Math.max(0,o-o%s),l=Math.min(n,l+(s-1-l%s))}return{startIndex:o,endIndex:l}}const ge=typeof document<"u"?U.useLayoutEffect:U.useEffect;function ke({useFlushSync:t=!0,...a}){const e=U.useReducer(()=>({}),{})[1],s={...a,onChange:(i,o)=>{var l;t&&o?be.flushSync(e):e(),(l=a.onChange)==null||l.call(a,i,o)}},[n]=U.useState(()=>new Me(s));return n.setOptions(s),ge(()=>n._didMount(),[]),ge(()=>n._willUpdate()),n}function Ne(t){return ke({observeElementRect:Ce,observeElementOffset:Te,scrollToFn:Re,...t})}const Ie=({data:t,columns:a,rowHeight:e=40,height:s=600,className:n="",headerClassName:i="",rowClassName:o,onRowClick:l,overscan:f=5})=>{const v=j.useRef(null),d=Ne({count:t.length,getScrollElement:()=>v.current,estimateSize:()=>e,overscan:f}),S=d.getVirtualItems();return b.jsxs("div",{className:n,children:[b.jsx("div",{className:`grid border-b sticky top-0 bg-background z-10 ${i}`,style:{gridTemplateColumns:a.map(c=>c.width||"1fr").join(" ")},children:a.map((c,m)=>b.jsx("div",{className:`px-4 py-2 font-semibold text-sm ${c.align==="center"?"text-center":c.align==="right"?"text-right":"text-left"}`,children:c.header},m))}),b.jsx("div",{ref:v,className:"overflow-auto",style:{height:typeof s=="number"?`${s}px`:s,contain:"strict"},children:b.jsx("div",{style:{height:`${d.getTotalSize()}px`,width:"100%",position:"relative"},children:S.map(c=>{const m=t[c.index],T=typeof o=="function"?o(m,c.index):o||"";return b.jsx("div",{className:`grid border-b hover:bg-muted/50 cursor-pointer ${T}`,style:{position:"absolute",top:0,left:0,width:"100%",height:`${c.size}px`,transform:`translateY(${c.start}px)`,gridTemplateColumns:a.map(g=>g.width||"1fr").join(" ")},onClick:()=>l?.(m,c.index),children:a.map((g,_)=>{const z=m[g.accessorKey],p=g.cell?g.cell(z,m):z;return b.jsx("div",{className:`px-4 py-2 text-sm flex items-center ${g.align==="center"?"text-center justify-center":g.align==="right"?"text-right justify-end":"text-left justify-start"}`,children:p},_)})},c.key)})})}),b.jsxs("div",{className:"px-4 py-2 text-xs text-muted-foreground border-t",children:["Showing ",S.length," of ",t.length," rows (virtual scrolling enabled)"]})]})},Q=({schema:t,...a})=>{const{dataSource:e}=X.useSchemaContext()||{};return b.jsx(ce,{schema:t,dataSource:e,...a})};re.ComponentRegistry.register("object-grid",Q,{namespace:"plugin-grid",label:"Object Grid",category:"plugin"}),re.ComponentRegistry.register("grid",Q,{namespace:"view",label:"Data Grid",category:"view"}),A.ObjectGrid=ce,A.ObjectGridRenderer=Q,A.VirtualGrid=Ie,Object.defineProperty(A,Symbol.toStringTag,{value:"Module"})}));
9
+ color: hsl(${Math.max(0,Math.min(120-120*w,120))}deg 100% 31%);`,e?.key)}return e?.onChange&&!(i&&e.skipInitialOnChange)&&e.onChange(t),i=!1,t}return o.updateDeps=l=>{s=l},o}function xe(n,a){if(n===void 0)throw new Error("Unexpected undefined");return n}const ke=(n,a)=>Math.abs(n-a)<1.01,ze=(n,a,e)=>{let s;return function(...t){n.clearTimeout(s),s=n.setTimeout(()=>a.apply(this,t),e)}},Ee=n=>{const{offsetWidth:a,offsetHeight:e}=n;return{width:a,height:e}},Me=n=>n,Ie=n=>{const a=Math.max(n.startIndex-n.overscan,0),e=Math.min(n.endIndex+n.overscan,n.count-1),s=[];for(let t=a;t<=e;t++)s.push(t);return s},De=(n,a)=>{const e=n.scrollElement;if(!e)return;const s=n.targetWindow;if(!s)return;const t=o=>{const{width:l,height:p}=o;a({width:Math.round(l),height:Math.round(p)})};if(t(Ee(e)),!s.ResizeObserver)return()=>{};const i=new s.ResizeObserver(o=>{const l=()=>{const p=o[0];if(p?.borderBoxSize){const g=p.borderBoxSize[0];if(g){t({width:g.inlineSize,height:g.blockSize});return}}t(Ee(e))};n.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(l):l()});return i.observe(e,{box:"border-box"}),()=>{i.unobserve(e)}},Se={passive:!0},je=typeof window>"u"?!0:"onscrollend"in window,Pe=(n,a)=>{const e=n.scrollElement;if(!e)return;const s=n.targetWindow;if(!s)return;let t=0;const i=n.options.useScrollendEvent&&je?()=>{}:ze(s,()=>{a(t,!1)},n.options.isScrollingResetDelay),o=m=>()=>{const{horizontal:E,isRtl:u}=n.options;t=E?e.scrollLeft*(u&&-1||1):e.scrollTop,i(),a(t,m)},l=o(!0),p=o(!1);e.addEventListener("scroll",l,Se);const g=n.options.useScrollendEvent&&je;return g&&e.addEventListener("scrollend",p,Se),()=>{e.removeEventListener("scroll",l),g&&e.removeEventListener("scrollend",p)}},Fe=(n,a,e)=>{if(a?.borderBoxSize){const s=a.borderBoxSize[0];if(s)return Math.round(s[e.options.horizontal?"inlineSize":"blockSize"])}return n[e.options.horizontal?"offsetWidth":"offsetHeight"]},$e=(n,{adjustments:a=0,behavior:e},s)=>{var t,i;const o=n+a;(i=(t=s.scrollElement)==null?void 0:t.scrollTo)==null||i.call(t,{[s.options.horizontal?"left":"top"]:o,behavior:e})};class We{constructor(a){this.unsubs=[],this.scrollElement=null,this.targetWindow=null,this.isScrolling=!1,this.currentScrollToIndex=null,this.measurementsCache=[],this.itemSizeCache=new Map,this.laneAssignments=new Map,this.pendingMeasuredCacheIndexes=[],this.prevLanes=void 0,this.lanesChangedFlag=!1,this.lanesSettling=!1,this.scrollRect=null,this.scrollOffset=null,this.scrollDirection=null,this.scrollAdjustments=0,this.elementsCache=new Map,this.observer=(()=>{let e=null;const s=()=>e||(!this.targetWindow||!this.targetWindow.ResizeObserver?null:e=new this.targetWindow.ResizeObserver(t=>{t.forEach(i=>{const o=()=>{this._measureElement(i.target,i)};this.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(o):o()})}));return{disconnect:()=>{var t;(t=s())==null||t.disconnect(),e=null},observe:t=>{var i;return(i=s())==null?void 0:i.observe(t,{box:"border-box"})},unobserve:t=>{var i;return(i=s())==null?void 0:i.unobserve(t)}}})(),this.range=null,this.setOptions=e=>{Object.entries(e).forEach(([s,t])=>{typeof t>"u"&&delete e[s]}),this.options={debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:Me,rangeExtractor:Ie,onChange:()=>{},measureElement:Fe,initialRect:{width:0,height:0},scrollMargin:0,gap:0,indexAttribute:"data-index",initialMeasurementsCache:[],lanes:1,isScrollingResetDelay:150,enabled:!0,isRtl:!1,useScrollendEvent:!1,useAnimationFrameWithResizeObserver:!1,...e}},this.notify=e=>{var s,t;(t=(s=this.options).onChange)==null||t.call(s,this,e)},this.maybeNotify=H(()=>(this.calculateRange(),[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]),e=>{this.notify(e)},{key:process.env.NODE_ENV!=="production"&&"maybeNotify",debug:()=>this.options.debug,initialDeps:[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]}),this.cleanup=()=>{this.unsubs.filter(Boolean).forEach(e=>e()),this.unsubs=[],this.observer.disconnect(),this.scrollElement=null,this.targetWindow=null},this._didMount=()=>()=>{this.cleanup()},this._willUpdate=()=>{var e;const s=this.options.enabled?this.options.getScrollElement():null;if(this.scrollElement!==s){if(this.cleanup(),!s){this.maybeNotify();return}this.scrollElement=s,this.scrollElement&&"ownerDocument"in this.scrollElement?this.targetWindow=this.scrollElement.ownerDocument.defaultView:this.targetWindow=((e=this.scrollElement)==null?void 0:e.window)??null,this.elementsCache.forEach(t=>{this.observer.observe(t)}),this.unsubs.push(this.options.observeElementRect(this,t=>{this.scrollRect=t,this.maybeNotify()})),this.unsubs.push(this.options.observeElementOffset(this,(t,i)=>{this.scrollAdjustments=0,this.scrollDirection=i?this.getScrollOffset()<t?"forward":"backward":null,this.scrollOffset=t,this.isScrolling=i,this.maybeNotify()})),this._scrollToOffset(this.getScrollOffset(),{adjustments:void 0,behavior:void 0})}},this.getSize=()=>this.options.enabled?(this.scrollRect=this.scrollRect??this.options.initialRect,this.scrollRect[this.options.horizontal?"width":"height"]):(this.scrollRect=null,0),this.getScrollOffset=()=>this.options.enabled?(this.scrollOffset=this.scrollOffset??(typeof this.options.initialOffset=="function"?this.options.initialOffset():this.options.initialOffset),this.scrollOffset):(this.scrollOffset=null,0),this.getFurthestMeasurement=(e,s)=>{const t=new Map,i=new Map;for(let o=s-1;o>=0;o--){const l=e[o];if(t.has(l.lane))continue;const p=i.get(l.lane);if(p==null||l.end>p.end?i.set(l.lane,l):l.end<p.end&&t.set(l.lane,!0),t.size===this.options.lanes)break}return i.size===this.options.lanes?Array.from(i.values()).sort((o,l)=>o.end===l.end?o.index-l.index:o.end-l.end)[0]:void 0},this.getMeasurementOptions=H(()=>[this.options.count,this.options.paddingStart,this.options.scrollMargin,this.options.getItemKey,this.options.enabled,this.options.lanes],(e,s,t,i,o,l)=>(this.prevLanes!==void 0&&this.prevLanes!==l&&(this.lanesChangedFlag=!0),this.prevLanes=l,this.pendingMeasuredCacheIndexes=[],{count:e,paddingStart:s,scrollMargin:t,getItemKey:i,enabled:o,lanes:l}),{key:!1}),this.getMeasurements=H(()=>[this.getMeasurementOptions(),this.itemSizeCache],({count:e,paddingStart:s,scrollMargin:t,getItemKey:i,enabled:o,lanes:l},p)=>{if(!o)return this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),[];if(this.laneAssignments.size>e)for(const u of this.laneAssignments.keys())u>=e&&this.laneAssignments.delete(u);this.lanesChangedFlag&&(this.lanesChangedFlag=!1,this.lanesSettling=!0,this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),this.pendingMeasuredCacheIndexes=[]),this.measurementsCache.length===0&&!this.lanesSettling&&(this.measurementsCache=this.options.initialMeasurementsCache,this.measurementsCache.forEach(u=>{this.itemSizeCache.set(u.key,u.size)}));const g=this.lanesSettling?0:this.pendingMeasuredCacheIndexes.length>0?Math.min(...this.pendingMeasuredCacheIndexes):0;this.pendingMeasuredCacheIndexes=[],this.lanesSettling&&this.measurementsCache.length===e&&(this.lanesSettling=!1);const m=this.measurementsCache.slice(0,g),E=new Array(l).fill(void 0);for(let u=0;u<g;u++){const b=m[u];b&&(E[b.lane]=u)}for(let u=g;u<e;u++){const b=i(u),_=this.laneAssignments.get(u);let v,w;if(_!==void 0&&this.options.lanes>1){v=_;const M=E[v],C=M!==void 0?m[M]:void 0;w=C?C.end+this.options.gap:s+t}else{const M=this.options.lanes===1?m[u-1]:this.getFurthestMeasurement(m,u);w=M?M.end+this.options.gap:s+t,v=M?M.lane:u%this.options.lanes,this.options.lanes>1&&this.laneAssignments.set(u,v)}const z=p.get(b),O=typeof z=="number"?z:this.options.estimateSize(u),F=w+O;m[u]={index:u,start:w,size:O,end:F,key:b,lane:v},E[v]=u}return this.measurementsCache=m,m},{key:process.env.NODE_ENV!=="production"&&"getMeasurements",debug:()=>this.options.debug}),this.calculateRange=H(()=>[this.getMeasurements(),this.getSize(),this.getScrollOffset(),this.options.lanes],(e,s,t,i)=>this.range=e.length>0&&s>0?Le({measurements:e,outerSize:s,scrollOffset:t,lanes:i}):null,{key:process.env.NODE_ENV!=="production"&&"calculateRange",debug:()=>this.options.debug}),this.getVirtualIndexes=H(()=>{let e=null,s=null;const t=this.calculateRange();return t&&(e=t.startIndex,s=t.endIndex),this.maybeNotify.updateDeps([this.isScrolling,e,s]),[this.options.rangeExtractor,this.options.overscan,this.options.count,e,s]},(e,s,t,i,o)=>i===null||o===null?[]:e({startIndex:i,endIndex:o,overscan:s,count:t}),{key:process.env.NODE_ENV!=="production"&&"getVirtualIndexes",debug:()=>this.options.debug}),this.indexFromElement=e=>{const s=this.options.indexAttribute,t=e.getAttribute(s);return t?parseInt(t,10):(console.warn(`Missing attribute name '${s}={index}' on measured element.`),-1)},this._measureElement=(e,s)=>{const t=this.indexFromElement(e),i=this.measurementsCache[t];if(!i)return;const o=i.key,l=this.elementsCache.get(o);l!==e&&(l&&this.observer.unobserve(l),this.observer.observe(e),this.elementsCache.set(o,e)),e.isConnected&&this.resizeItem(t,this.options.measureElement(e,s,this))},this.resizeItem=(e,s)=>{const t=this.measurementsCache[e];if(!t)return;const i=this.itemSizeCache.get(t.key)??t.size,o=s-i;o!==0&&((this.shouldAdjustScrollPositionOnItemSizeChange!==void 0?this.shouldAdjustScrollPositionOnItemSizeChange(t,o,this):t.start<this.getScrollOffset()+this.scrollAdjustments)&&(process.env.NODE_ENV!=="production"&&this.options.debug&&console.info("correction",o),this._scrollToOffset(this.getScrollOffset(),{adjustments:this.scrollAdjustments+=o,behavior:void 0})),this.pendingMeasuredCacheIndexes.push(t.index),this.itemSizeCache=new Map(this.itemSizeCache.set(t.key,s)),this.notify(!1))},this.measureElement=e=>{if(!e){this.elementsCache.forEach((s,t)=>{s.isConnected||(this.observer.unobserve(s),this.elementsCache.delete(t))});return}this._measureElement(e,void 0)},this.getVirtualItems=H(()=>[this.getVirtualIndexes(),this.getMeasurements()],(e,s)=>{const t=[];for(let i=0,o=e.length;i<o;i++){const l=e[i],p=s[l];t.push(p)}return t},{key:process.env.NODE_ENV!=="production"&&"getVirtualItems",debug:()=>this.options.debug}),this.getVirtualItemForOffset=e=>{const s=this.getMeasurements();if(s.length!==0)return xe(s[we(0,s.length-1,t=>xe(s[t]).start,e)])},this.getMaxScrollOffset=()=>{if(!this.scrollElement)return 0;if("scrollHeight"in this.scrollElement)return this.options.horizontal?this.scrollElement.scrollWidth-this.scrollElement.clientWidth:this.scrollElement.scrollHeight-this.scrollElement.clientHeight;{const e=this.scrollElement.document.documentElement;return this.options.horizontal?e.scrollWidth-this.scrollElement.innerWidth:e.scrollHeight-this.scrollElement.innerHeight}},this.getOffsetForAlignment=(e,s,t=0)=>{if(!this.scrollElement)return 0;const i=this.getSize(),o=this.getScrollOffset();s==="auto"&&(s=e>=o+i?"end":"start"),s==="center"?e+=(t-i)/2:s==="end"&&(e-=i);const l=this.getMaxScrollOffset();return Math.max(Math.min(l,e),0)},this.getOffsetForIndex=(e,s="auto")=>{e=Math.max(0,Math.min(e,this.options.count-1));const t=this.measurementsCache[e];if(!t)return;const i=this.getSize(),o=this.getScrollOffset();if(s==="auto")if(t.end>=o+i-this.options.scrollPaddingEnd)s="end";else if(t.start<=o+this.options.scrollPaddingStart)s="start";else return[o,s];if(s==="end"&&e===this.options.count-1)return[this.getMaxScrollOffset(),s];const l=s==="end"?t.end+this.options.scrollPaddingEnd:t.start-this.options.scrollPaddingStart;return[this.getOffsetForAlignment(l,s,t.size),s]},this.isDynamicMode=()=>this.elementsCache.size>0,this.scrollToOffset=(e,{align:s="start",behavior:t}={})=>{t==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getOffsetForAlignment(e,s),{adjustments:void 0,behavior:t})},this.scrollToIndex=(e,{align:s="auto",behavior:t}={})=>{t==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),e=Math.max(0,Math.min(e,this.options.count-1)),this.currentScrollToIndex=e;let i=0;const o=10,l=g=>{if(!this.targetWindow)return;const m=this.getOffsetForIndex(e,g);if(!m){console.warn("Failed to get offset for index:",e);return}const[E,u]=m;this._scrollToOffset(E,{adjustments:void 0,behavior:t}),this.targetWindow.requestAnimationFrame(()=>{const b=()=>{if(this.currentScrollToIndex!==e)return;const _=this.getScrollOffset(),v=this.getOffsetForIndex(e,u);if(!v){console.warn("Failed to get offset for index:",e);return}ke(v[0],_)||p(u)};this.isDynamicMode()?this.targetWindow.requestAnimationFrame(b):b()})},p=g=>{this.targetWindow&&this.currentScrollToIndex===e&&(i++,i<o?(process.env.NODE_ENV!=="production"&&this.options.debug&&console.info("Schedule retry",i,o),this.targetWindow.requestAnimationFrame(()=>l(g))):console.warn(`Failed to scroll to index ${e} after ${o} attempts.`))};l(s)},this.scrollBy=(e,{behavior:s}={})=>{s==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getScrollOffset()+e,{adjustments:void 0,behavior:s})},this.getTotalSize=()=>{var e;const s=this.getMeasurements();let t;if(s.length===0)t=this.options.paddingStart;else if(this.options.lanes===1)t=((e=s[s.length-1])==null?void 0:e.end)??0;else{const i=Array(this.options.lanes).fill(null);let o=s.length-1;for(;o>=0&&i.some(l=>l===null);){const l=s[o];i[l.lane]===null&&(i[l.lane]=l.end),o--}t=Math.max(...i.filter(l=>l!==null))}return Math.max(t-this.options.scrollMargin+this.options.paddingEnd,0)},this._scrollToOffset=(e,{adjustments:s,behavior:t})=>{this.options.scrollToFn(e,{behavior:t,adjustments:s},this)},this.measure=()=>{this.itemSizeCache=new Map,this.laneAssignments=new Map,this.notify(!1)},this.setOptions(a)}}const we=(n,a,e,s)=>{for(;n<=a;){const t=(n+a)/2|0,i=e(t);if(i<s)n=t+1;else if(i>s)a=t-1;else return t}return n>0?n-1:0};function Le({measurements:n,outerSize:a,scrollOffset:e,lanes:s}){const t=n.length-1,i=p=>n[p].start;if(n.length<=s)return{startIndex:0,endIndex:t};let o=we(0,t,i,e),l=o;if(s===1)for(;l<t&&n[l].end<e+a;)l++;else if(s>1){const p=Array(s).fill(0);for(;l<t&&p.some(m=>m<e+a);){const m=n[l];p[m.lane]=m.end,l++}const g=Array(s).fill(e+a);for(;o>=0&&g.some(m=>m>=e);){const m=n[o];g[m.lane]=m.start,o--}o=Math.max(0,o-o%s),l=Math.min(t,l+(s-1-l%s))}return{startIndex:o,endIndex:l}}const Oe=typeof document<"u"?le.useLayoutEffect:le.useEffect;function Ve({useFlushSync:n=!0,...a}){const e=le.useReducer(()=>({}),{})[1],s={...a,onChange:(i,o)=>{var l;n&&o?Ce.flushSync(e):e(),(l=a.onChange)==null||l.call(a,i,o)}},[t]=le.useState(()=>new We(s));return t.setOptions(s),Oe(()=>t._didMount(),[]),Oe(()=>t._willUpdate()),t}function qe(n){return Ve({observeElementRect:De,observeElementOffset:Pe,scrollToFn:$e,...n})}const Ye=({data:n,columns:a,rowHeight:e=40,height:s=600,className:t="",headerClassName:i="",rowClassName:o,onRowClick:l,overscan:p=5})=>{const g=R.useRef(null),m=qe({count:n.length,getScrollElement:()=>g.current,estimateSize:()=>e,overscan:p}),E=m.getVirtualItems();return c.jsxs("div",{className:t,children:[c.jsx("div",{className:`grid border-b sticky top-0 bg-background z-10 ${i}`,style:{gridTemplateColumns:a.map(u=>u.width||"1fr").join(" ")},children:a.map((u,b)=>c.jsx("div",{className:`px-4 py-2 font-semibold text-sm ${u.align==="center"?"text-center":u.align==="right"?"text-right":"text-left"}`,children:u.header},b))}),c.jsx("div",{ref:g,className:"overflow-auto",style:{height:typeof s=="number"?`${s}px`:s,contain:"strict"},children:c.jsx("div",{style:{height:`${m.getTotalSize()}px`,width:"100%",position:"relative"},children:E.map(u=>{const b=n[u.index],_=typeof o=="function"?o(b,u.index):o||"";return c.jsx("div",{className:`grid border-b hover:bg-muted/50 cursor-pointer ${_}`,style:{position:"absolute",top:0,left:0,width:"100%",height:`${u.size}px`,transform:`translateY(${u.start}px)`,gridTemplateColumns:a.map(v=>v.width||"1fr").join(" ")},onClick:()=>l?.(b,u.index),children:a.map((v,w)=>{const z=b[v.accessorKey],O=v.cell?v.cell(z,b):z;return c.jsx("div",{className:`px-4 py-2 text-sm flex items-center ${v.align==="center"?"text-center justify-center":v.align==="right"?"text-right justify-end":"text-left justify-start"}`,children:O},w)})},u.key)})})}),c.jsxs("div",{className:"px-4 py-2 text-xs text-muted-foreground border-t",children:["Showing ",E.length," of ",n.length," rows (virtual scrolling enabled)"]})]})},fe=({schema:n,...a})=>{const{dataSource:e}=B.useSchemaContext()||{};return c.jsx(ye,{schema:n,dataSource:e,...a})};he.ComponentRegistry.register("object-grid",fe,{namespace:"plugin-grid",label:"Object Grid",category:"plugin",inputs:[{name:"objectName",type:"string",label:"Object Name",required:!0},{name:"columns",type:"array",label:"Columns"},{name:"filters",type:"array",label:"Filters"}]}),he.ComponentRegistry.register("grid",fe,{namespace:"view",label:"Data Grid",category:"view",inputs:[{name:"objectName",type:"string",label:"Object Name",required:!0},{name:"columns",type:"array",label:"Columns"},{name:"filters",type:"array",label:"Filters"}]}),A.ObjectGrid=ye,A.ObjectGridRenderer=fe,A.VirtualGrid=Ye,Object.defineProperty(A,Symbol.toStringTag,{value:"Module"})}));
@@ -8,7 +8,13 @@ export interface ObjectGridProps {
8
8
  onEdit?: (record: any) => void;
9
9
  onDelete?: (record: any) => void;
10
10
  onBulkDelete?: (records: any[]) => void;
11
- onCellChange?: (rowIndex: number, columnKey: string, newValue: any) => void;
11
+ onCellChange?: (rowIndex: number, columnKey: string, newValue: any, row: any) => void;
12
+ onRowSave?: (rowIndex: number, changes: Record<string, any>, row: any) => void | Promise<void>;
13
+ onBatchSave?: (changes: Array<{
14
+ rowIndex: number;
15
+ changes: Record<string, any>;
16
+ row: any;
17
+ }>) => void | Promise<void>;
12
18
  onRowSelect?: (selectedRows: any[]) => void;
13
19
  }
14
20
  export declare const ObjectGrid: React.FC<ObjectGridProps>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/plugin-grid",
3
- "version": "0.5.0",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Grid plugin for Object UI",
@@ -17,11 +17,11 @@
17
17
  "dependencies": {
18
18
  "@tanstack/react-virtual": "^3.11.3",
19
19
  "lucide-react": "^0.563.0",
20
- "@object-ui/components": "0.5.0",
21
- "@object-ui/core": "0.5.0",
22
- "@object-ui/fields": "0.5.0",
23
- "@object-ui/react": "0.5.0",
24
- "@object-ui/types": "0.5.0"
20
+ "@object-ui/components": "2.0.0",
21
+ "@object-ui/core": "2.0.0",
22
+ "@object-ui/fields": "2.0.0",
23
+ "@object-ui/react": "2.0.0",
24
+ "@object-ui/types": "2.0.0"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "react": "^18.0.0 || ^19.0.0",
@@ -29,11 +29,11 @@
29
29
  },
30
30
  "devDependencies": {
31
31
  "@vitejs/plugin-react": "^5.1.3",
32
- "msw": "^2.12.7",
32
+ "msw": "^2.12.9",
33
33
  "typescript": "^5.9.3",
34
34
  "vite": "^7.3.1",
35
35
  "vite-plugin-dts": "^4.5.4",
36
- "@object-ui/data-objectstack": "0.5.0"
36
+ "@object-ui/data-objectstack": "2.0.0"
37
37
  },
38
38
  "scripts": {
39
39
  "build": "vite build",
@@ -0,0 +1,374 @@
1
+ /**
2
+ * ListColumn Extensions Tests
3
+ *
4
+ * Tests for link, action, hidden, type, wrap, and resizable properties
5
+ * on ListColumn when rendered through ObjectGrid → data-table.
6
+ */
7
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
8
+ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
9
+ import '@testing-library/jest-dom';
10
+ import React from 'react';
11
+ import { ObjectGrid } from './ObjectGrid';
12
+ import { registerAllFields } from '@object-ui/fields';
13
+ import { ActionProvider } from '@object-ui/react';
14
+ import type { ListColumn } from '@object-ui/types';
15
+
16
+ registerAllFields();
17
+
18
+ // --- Mock Data ---
19
+ const mockData = [
20
+ { _id: '1', name: 'Alice', email: 'alice@test.com', amount: 1500, status: 'active' },
21
+ { _id: '2', name: 'Bob', email: 'bob@test.com', amount: 2300, status: 'inactive' },
22
+ { _id: '3', name: 'Charlie', email: 'charlie@test.com', amount: 800, status: 'active' },
23
+ ];
24
+
25
+ // --- Helper: Render ObjectGrid with static data and ListColumn[] ---
26
+ function renderGrid(columns: ListColumn[], opts?: { onNavigate?: any; navigation?: any }) {
27
+ const schema: any = {
28
+ type: 'object-grid' as const,
29
+ objectName: 'test_object',
30
+ columns,
31
+ data: { provider: 'value', items: mockData },
32
+ navigation: opts?.navigation,
33
+ onNavigate: opts?.onNavigate,
34
+ };
35
+
36
+ return render(
37
+ <ActionProvider>
38
+ <ObjectGrid schema={schema} />
39
+ </ActionProvider>
40
+ );
41
+ }
42
+
43
+ // =========================================================================
44
+ // 1. Hidden columns
45
+ // =========================================================================
46
+ describe('ListColumn: hidden', () => {
47
+ it('should not render hidden columns', async () => {
48
+ renderGrid([
49
+ { field: 'name', label: 'Name' },
50
+ { field: 'email', label: 'Email', hidden: true },
51
+ { field: 'amount', label: 'Amount' },
52
+ ]);
53
+
54
+ await waitFor(() => {
55
+ expect(screen.getByText('Name')).toBeInTheDocument();
56
+ });
57
+ expect(screen.getByText('Amount')).toBeInTheDocument();
58
+ // Email column should NOT be rendered
59
+ expect(screen.queryByText('Email')).not.toBeInTheDocument();
60
+ expect(screen.queryByText('alice@test.com')).not.toBeInTheDocument();
61
+ });
62
+
63
+ it('should render non-hidden columns normally', async () => {
64
+ renderGrid([
65
+ { field: 'name', label: 'Name', hidden: false },
66
+ { field: 'email', label: 'Email' },
67
+ ]);
68
+
69
+ await waitFor(() => {
70
+ expect(screen.getByText('Name')).toBeInTheDocument();
71
+ });
72
+ expect(screen.getByText('Email')).toBeInTheDocument();
73
+ });
74
+ });
75
+
76
+ // =========================================================================
77
+ // 2. Link columns
78
+ // =========================================================================
79
+ describe('ListColumn: link', () => {
80
+ it('should render link columns as clickable text', async () => {
81
+ renderGrid([
82
+ { field: 'name', label: 'Name', link: true },
83
+ { field: 'email', label: 'Email' },
84
+ ]);
85
+
86
+ await waitFor(() => {
87
+ expect(screen.getByText('Name')).toBeInTheDocument();
88
+ });
89
+
90
+ // The name cells should be rendered as buttons (clickable links)
91
+ const aliceLink = screen.getByRole('button', { name: 'Alice' });
92
+ expect(aliceLink).toBeInTheDocument();
93
+ expect(aliceLink).toHaveClass('text-primary');
94
+
95
+ const bobLink = screen.getByRole('button', { name: 'Bob' });
96
+ expect(bobLink).toBeInTheDocument();
97
+ });
98
+
99
+ it('should trigger navigation when link column is clicked', async () => {
100
+ const onNavigate = vi.fn();
101
+
102
+ renderGrid(
103
+ [
104
+ { field: 'name', label: 'Name', link: true },
105
+ { field: 'email', label: 'Email' },
106
+ ],
107
+ {
108
+ navigation: { mode: 'page' },
109
+ onNavigate,
110
+ }
111
+ );
112
+
113
+ await waitFor(() => {
114
+ expect(screen.getByRole('button', { name: 'Alice' })).toBeInTheDocument();
115
+ });
116
+
117
+ fireEvent.click(screen.getByRole('button', { name: 'Alice' }));
118
+
119
+ expect(onNavigate).toHaveBeenCalledTimes(1);
120
+ expect(onNavigate).toHaveBeenCalledWith('1', 'view');
121
+ });
122
+
123
+ it('should not render non-link columns as buttons', async () => {
124
+ renderGrid([
125
+ { field: 'name', label: 'Name', link: true },
126
+ { field: 'email', label: 'Email' },
127
+ ]);
128
+
129
+ await waitFor(() => {
130
+ expect(screen.getByText('Name')).toBeInTheDocument();
131
+ });
132
+
133
+ // Email values should NOT be buttons
134
+ expect(screen.queryByRole('button', { name: 'alice@test.com' })).not.toBeInTheDocument();
135
+ // But the text should still render
136
+ expect(screen.getByText('alice@test.com')).toBeInTheDocument();
137
+ });
138
+ });
139
+
140
+ // =========================================================================
141
+ // 3. Action columns
142
+ // =========================================================================
143
+ describe('ListColumn: action', () => {
144
+ it('should render action columns as clickable text', async () => {
145
+ renderGrid([
146
+ { field: 'name', label: 'Name' },
147
+ { field: 'status', label: 'Status', action: 'toggleStatus' },
148
+ ]);
149
+
150
+ await waitFor(() => {
151
+ expect(screen.getByText('Name')).toBeInTheDocument();
152
+ });
153
+
154
+ // Status cells should be buttons
155
+ const activeBtn = screen.getAllByRole('button', { name: 'active' });
156
+ expect(activeBtn.length).toBeGreaterThanOrEqual(1);
157
+ expect(activeBtn[0]).toHaveClass('text-primary');
158
+ });
159
+
160
+ it('should execute action when action column is clicked', async () => {
161
+ const actionHandler = vi.fn().mockResolvedValue({ success: true });
162
+
163
+ const schema: any = {
164
+ type: 'object-grid' as const,
165
+ objectName: 'test_object',
166
+ columns: [
167
+ { field: 'name', label: 'Name' },
168
+ { field: 'status', label: 'Status', action: 'toggleStatus' },
169
+ ],
170
+ data: { provider: 'value', items: mockData },
171
+ };
172
+
173
+ render(
174
+ <ActionProvider handlers={{ toggleStatus: actionHandler }}>
175
+ <ObjectGrid schema={schema} />
176
+ </ActionProvider>
177
+ );
178
+
179
+ await waitFor(() => {
180
+ expect(screen.getByText('Name')).toBeInTheDocument();
181
+ });
182
+
183
+ const statusBtns = screen.getAllByRole('button', { name: 'active' });
184
+ fireEvent.click(statusBtns[0]);
185
+
186
+ await waitFor(() => {
187
+ expect(actionHandler).toHaveBeenCalledTimes(1);
188
+ });
189
+ expect(actionHandler).toHaveBeenCalledWith(
190
+ expect.objectContaining({
191
+ type: 'toggleStatus',
192
+ params: expect.objectContaining({
193
+ field: 'status',
194
+ value: 'active',
195
+ record: expect.objectContaining({ _id: '1', name: 'Alice' }),
196
+ }),
197
+ }),
198
+ expect.any(Object) // ActionCtx
199
+ );
200
+ });
201
+ });
202
+
203
+ // =========================================================================
204
+ // 4. Type-based cell rendering
205
+ // =========================================================================
206
+ describe('ListColumn: type', () => {
207
+ it('should use getCellRenderer for typed columns', async () => {
208
+ renderGrid([
209
+ { field: 'name', label: 'Name' },
210
+ { field: 'email', label: 'Email', type: 'email' },
211
+ ]);
212
+
213
+ await waitFor(() => {
214
+ expect(screen.getByText('Name')).toBeInTheDocument();
215
+ });
216
+
217
+ // Email type should render as a mailto link
218
+ const emailLink = screen.getByText('alice@test.com');
219
+ expect(emailLink).toBeInTheDocument();
220
+ // The email cell renderer wraps in an anchor
221
+ expect(emailLink.closest('a')).toHaveAttribute('href', 'mailto:alice@test.com');
222
+ });
223
+
224
+ it('should render boolean type columns correctly', async () => {
225
+ const boolData = [
226
+ { _id: '1', name: 'Alice', active: true },
227
+ { _id: '2', name: 'Bob', active: false },
228
+ ];
229
+
230
+ const schema: any = {
231
+ type: 'object-grid' as const,
232
+ objectName: 'test_object',
233
+ columns: [
234
+ { field: 'name', label: 'Name' },
235
+ { field: 'active', label: 'Active', type: 'boolean' },
236
+ ],
237
+ data: { provider: 'value', items: boolData },
238
+ };
239
+
240
+ render(
241
+ <ActionProvider>
242
+ <ObjectGrid schema={schema} />
243
+ </ActionProvider>
244
+ );
245
+
246
+ await waitFor(() => {
247
+ expect(screen.getByText('Name')).toBeInTheDocument();
248
+ });
249
+
250
+ // Boolean renderer should show check/x icons or text representation
251
+ expect(screen.getByText('Active')).toBeInTheDocument();
252
+ });
253
+ });
254
+
255
+ // =========================================================================
256
+ // 5. Combined: link + type
257
+ // =========================================================================
258
+ describe('ListColumn: link + type', () => {
259
+ it('should render typed content inside a clickable link', async () => {
260
+ const onNavigate = vi.fn();
261
+
262
+ renderGrid(
263
+ [
264
+ { field: 'email', label: 'Email', link: true, type: 'email' },
265
+ { field: 'name', label: 'Name' },
266
+ ],
267
+ {
268
+ navigation: { mode: 'page' },
269
+ onNavigate,
270
+ }
271
+ );
272
+
273
+ await waitFor(() => {
274
+ expect(screen.getByText('Email')).toBeInTheDocument();
275
+ });
276
+
277
+ // Should be a button wrapping the email content
278
+ const emailBtn = screen.getByRole('button', { name: /alice@test.com/ });
279
+ expect(emailBtn).toBeInTheDocument();
280
+ expect(emailBtn).toHaveClass('text-primary');
281
+
282
+ fireEvent.click(emailBtn);
283
+ expect(onNavigate).toHaveBeenCalledWith('1', 'view');
284
+ });
285
+ });
286
+
287
+ // =========================================================================
288
+ // 6. Column properties passthrough
289
+ // =========================================================================
290
+ describe('ListColumn: property passthrough', () => {
291
+ it('should auto-generate header from field name if no label', async () => {
292
+ renderGrid([
293
+ { field: 'first_name' },
294
+ ]);
295
+
296
+ await waitFor(() => {
297
+ // Should convert snake_case to title case
298
+ expect(screen.getByText('First name')).toBeInTheDocument();
299
+ });
300
+ });
301
+
302
+ it('should use label when provided', async () => {
303
+ renderGrid([
304
+ { field: 'name', label: 'Full Name' },
305
+ ]);
306
+
307
+ await waitFor(() => {
308
+ expect(screen.getByText('Full Name')).toBeInTheDocument();
309
+ });
310
+ });
311
+
312
+ it('should handle all columns hidden gracefully', async () => {
313
+ const { container } = renderGrid([
314
+ { field: 'name', hidden: true },
315
+ { field: 'email', hidden: true },
316
+ ]);
317
+
318
+ // Should render without error, just no columns
319
+ await waitFor(() => {
320
+ expect(container).toBeInTheDocument();
321
+ });
322
+ });
323
+ });
324
+
325
+ // =========================================================================
326
+ // 7. Type definitions alignment
327
+ // =========================================================================
328
+ describe('ListColumn type definitions', () => {
329
+ it('should accept link property on ListColumn', () => {
330
+ const col: ListColumn = {
331
+ field: 'name',
332
+ link: true,
333
+ };
334
+ expect(col.link).toBe(true);
335
+ });
336
+
337
+ it('should accept action property on ListColumn', () => {
338
+ const col: ListColumn = {
339
+ field: 'status',
340
+ action: 'toggleStatus',
341
+ };
342
+ expect(col.action).toBe('toggleStatus');
343
+ });
344
+
345
+ it('should accept both link and action together', () => {
346
+ const col: ListColumn = {
347
+ field: 'name',
348
+ link: true,
349
+ action: 'viewDetail',
350
+ };
351
+ expect(col.link).toBe(true);
352
+ expect(col.action).toBe('viewDetail');
353
+ });
354
+
355
+ it('should accept all ListColumn properties', () => {
356
+ const col: ListColumn = {
357
+ field: 'amount',
358
+ label: 'Total Amount',
359
+ width: 150,
360
+ align: 'right',
361
+ hidden: false,
362
+ sortable: true,
363
+ resizable: true,
364
+ wrap: false,
365
+ type: 'currency',
366
+ link: false,
367
+ action: 'editAmount',
368
+ };
369
+ expect(col.field).toBe('amount');
370
+ expect(col.type).toBe('currency');
371
+ expect(col.link).toBe(false);
372
+ expect(col.action).toBe('editAmount');
373
+ });
374
+ });