@object-ui/plugin-grid 3.0.3 → 3.1.1
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.
- package/.turbo/turbo-build.log +6 -6
- package/CHANGELOG.md +12 -0
- package/dist/index.js +2173 -922
- package/dist/index.umd.cjs +9 -3
- package/dist/plugin-grid/src/FormulaBar.d.ts +29 -0
- package/dist/plugin-grid/src/GroupRow.d.ts +23 -0
- package/dist/plugin-grid/src/ImportWizard.d.ts +29 -0
- package/dist/plugin-grid/src/ObjectGrid.d.ts +1 -0
- package/dist/plugin-grid/src/SplitPaneGrid.d.ts +22 -0
- package/dist/plugin-grid/src/components/BulkActionBar.d.ts +12 -0
- package/dist/plugin-grid/src/components/RowActionMenu.d.ts +23 -0
- package/dist/plugin-grid/src/index.d.ts +22 -2
- package/dist/plugin-grid/src/useCellClipboard.d.ts +47 -0
- package/dist/plugin-grid/src/useColumnSummary.d.ts +25 -0
- package/dist/plugin-grid/src/useGradientColor.d.ts +37 -0
- package/dist/plugin-grid/src/useGroupReorder.d.ts +34 -0
- package/dist/plugin-grid/src/useGroupedData.d.ts +24 -3
- package/package.json +10 -10
- package/src/FormulaBar.tsx +151 -0
- package/src/GroupRow.tsx +69 -0
- package/src/ImportWizard.tsx +412 -0
- package/src/ListColumnExtensions.test.tsx +4 -5
- package/src/ObjectGrid.tsx +1002 -139
- package/src/SplitPaneGrid.tsx +120 -0
- package/src/VirtualGrid.tsx +2 -2
- package/src/__tests__/GroupRow.test.tsx +206 -0
- package/src/__tests__/ImportPreview.test.tsx +171 -0
- package/src/__tests__/accessorKey-inference.test.tsx +132 -0
- package/src/__tests__/airtable-style.test.tsx +508 -0
- package/src/__tests__/column-features.test.tsx +490 -0
- package/src/__tests__/grid-export.test.tsx +121 -0
- package/src/__tests__/mobile-card-view.test.tsx +355 -0
- package/src/__tests__/objectdef-enrichment.test.tsx +566 -0
- package/src/__tests__/phase11-features.test.tsx +418 -0
- package/src/__tests__/row-bulk-actions.test.tsx +413 -0
- package/src/__tests__/row-height.test.tsx +160 -0
- package/src/__tests__/useGroupedData.test.ts +165 -0
- package/src/components/BulkActionBar.tsx +66 -0
- package/src/components/RowActionMenu.tsx +91 -0
- package/src/index.tsx +46 -2
- package/src/useCellClipboard.ts +136 -0
- package/src/useColumnSummary.ts +128 -0
- package/src/useGradientColor.ts +103 -0
- package/src/useGroupReorder.ts +123 -0
- package/src/useGroupedData.ts +69 -4
package/dist/index.umd.cjs
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(P,f){typeof exports=="object"&&typeof module<"u"?f(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"],f):(P=typeof globalThis<"u"?globalThis:P||self,f(P.ObjectUIPluginGrid={},P.React,P.core,P.react,P.fields,P.components,P.lucideReact,P.ReactDOM))})(this,(function(P,f,_e,pe,Z,v,F,_t){"use strict";function Tt(e){const o=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(o,t,r.get?r:{enumerable:!0,get:()=>e[t]})}}return o.default=e,Object.freeze(o)}const ze=Tt(f);var Ie={exports:{}},Te={};var Ye;function At(){if(Ye)return Te;Ye=1;var e=Symbol.for("react.transitional.element"),o=Symbol.for("react.fragment");function t(r,n,i){var a=null;if(i!==void 0&&(a=""+i),n.key!==void 0&&(a=""+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:e,type:r,key:a,ref:n!==void 0?n:null,props:i}}return Te.Fragment=o,Te.jsx=t,Te.jsxs=t,Te}var Ae={};var Je;function Mt(){return Je||(Je=1,process.env.NODE_ENV!=="production"&&(function(){function e(u){if(u==null)return null;if(typeof u=="function")return u.$$typeof===de?null:u.displayName||u.name||null;if(typeof u=="string")return u;switch(u){case T:return"Fragment";case I:return"Profiler";case D:return"StrictMode";case J:return"Suspense";case le:return"SuspenseList";case Ee:return"Activity"}if(typeof u=="object")switch(typeof u.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),u.$$typeof){case w:return"Portal";case Y:return u.displayName||"Context";case L:return(u._context.displayName||"Context")+".Consumer";case q:var A=u.render;return u=u.displayName,u||(u=A.displayName||A.name||"",u=u!==""?"ForwardRef("+u+")":"ForwardRef"),u;case Me:return A=u.displayName||null,A!==null?A:e(u.type)||"Memo";case ve:A=u._payload,u=u._init;try{return e(u(A))}catch{}}return null}function o(u){return""+u}function t(u){try{o(u);var A=!1}catch{A=!0}if(A){A=console;var K=A.error,H=typeof Symbol=="function"&&Symbol.toStringTag&&u[Symbol.toStringTag]||u.constructor.name||"Object";return K.call(A,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",H),o(u)}}function r(u){if(u===T)return"<>";if(typeof u=="object"&&u!==null&&u.$$typeof===ve)return"<...>";try{var A=e(u);return A?"<"+A+">":"<...>"}catch{return"<...>"}}function n(){var u=ge.A;return u===null?null:u.getOwner()}function i(){return Error("react-stack-top-frame")}function a(u){if(V.call(u,"key")){var A=Object.getOwnPropertyDescriptor(u,"key").get;if(A&&A.isReactWarning)return!1}return u.key!==void 0}function l(u,A){function K(){ae||(ae=!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)",A))}K.isReactWarning=!0,Object.defineProperty(u,"key",{get:K,configurable:!0})}function p(){var u=e(this.type);return je[u]||(je[u]=!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.")),u=this.props.ref,u!==void 0?u:null}function h(u,A,K,H,we,ee){var R=K.ref;return u={$$typeof:C,type:u,key:A,props:K,_owner:H},(R!==void 0?R:null)!==null?Object.defineProperty(u,"ref",{enumerable:!1,get:p}):Object.defineProperty(u,"ref",{enumerable:!1,value:null}),u._store={},Object.defineProperty(u._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(u,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(u,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:we}),Object.defineProperty(u,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:ee}),Object.freeze&&(Object.freeze(u.props),Object.freeze(u)),u}function d(u,A,K,H,we,ee){var R=A.children;if(R!==void 0)if(H)if(Q(R)){for(H=0;H<R.length;H++)m(R[H]);Object.freeze&&Object.freeze(R)}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 m(R);if(V.call(A,"key")){R=e(u);var X=Object.keys(A).filter(function(me){return me!=="key"});H=0<X.length?"{key: someKey, "+X.join(": ..., ")+": ...}":"{key: someKey}",xe[R+H]||(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} />`,O,N,q,N),ce[N+O]=!0)}if(N=null,w!==void 0&&(e(w),N=""+w),o(h)&&(e(h.key),N=""+h.key),"key"in h){w={};for(var oe in h)oe!=="key"&&(w[oe]=h[oe])}else w=h;return N&&l(w,typeof r=="function"?r.displayName||r.name||"Unknown":r),m(r,N,w,s(),re,ie)}function y(r){u(r)?r._store&&(r._store.validated=1):typeof r=="object"&&r!==null&&r.$$typeof===ee&&(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===E}var d=g,E=Symbol.for("react.transitional.element"),x=Symbol.for("react.portal"),C=Symbol.for("react.fragment"),A=Symbol.for("react.strict_mode"),T=Symbol.for("react.profiler"),$=Symbol.for("react.consumer"),R=Symbol.for("react.context"),K=Symbol.for("react.forward_ref"),M=Symbol.for("react.suspense"),W=Symbol.for("react.suspense_list"),be=Symbol.for("react.memo"),ee=Symbol.for("react.lazy"),te=Symbol.for("react.activity"),ne=Symbol.for("react.client.reference"),se=d.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,D=Object.prototype.hasOwnProperty,U=Array.isArray,L=console.createTask?console.createTask:function(){return null};d={react_stack_bottom_frame:function(r){return r()}};var V,Y={},X=d.react_stack_bottom_frame.bind(d,i)(),G=L(n(i)),ce={};ae.Fragment=C,ae.jsx=function(r,h,w){var O=1e4>se.recentlyCreatedOwnerStacks++;return f(r,h,w,!1,O?Error("react-stack-top-frame"):X,O?L(n(r)):G)},ae.jsxs=function(r,h,w){var O=1e4>se.recentlyCreatedOwnerStacks++;return f(r,h,w,!0,O?Error("react-stack-top-frame"):X,O?L(n(r)):G)}})()),ae}var we;function Ye(){return we||(we=1,process.env.NODE_ENV==="production"?pe.exports=We():pe.exports=Ve()),pe.exports}var a=Ye();function Ge(t){const{onRefresh:c,threshold:e=80,enabled:n=!0}=t,s=g.useRef(null),[i,o]=g.useState(!1),[l,b]=g.useState(0),m=g.useRef(0),f=g.useCallback(d=>{if(!n||i)return;const E=s.current;E&&E.scrollTop===0&&(m.current=d.touches[0].clientY)},[n,i]),y=g.useCallback(d=>{if(!n||i||!m.current)return;const x=d.touches[0].clientY-m.current;x>0&&b(Math.min(x,e*1.5))},[n,i,e]),u=g.useCallback(async()=>{if(!(!n||i)){if(l>=e){o(!0);try{await c()}finally{o(!1)}}b(0),m.current=0}},[n,i,l,e,c]);return g.useEffect(()=>{const d=s.current;if(!(!d||!n))return d.addEventListener("touchstart",f,{passive:!0}),d.addEventListener("touchmove",y,{passive:!0}),d.addEventListener("touchend",u,{passive:!0}),()=>{d.removeEventListener("touchstart",f),d.removeEventListener("touchmove",y),d.removeEventListener("touchend",u)}},[f,y,u,n]),{ref:s,isRefreshing:i,pullDistance:l}}const qe=g.createContext(null);qe.displayName="MobileContext";const Ke={red:"bg-red-100",green:"bg-green-100",blue:"bg-blue-100",yellow:"bg-yellow-100",orange:"bg-orange-100",purple:"bg-purple-100",pink:"bg-pink-100",gray:"bg-gray-100",grey:"bg-gray-100",indigo:"bg-indigo-100",teal:"bg-teal-100",cyan:"bg-cyan-100",amber:"bg-amber-100",lime:"bg-lime-100",emerald:"bg-emerald-100",rose:"bg-rose-100",sky:"bg-sky-100",violet:"bg-violet-100",fuchsia:"bg-fuchsia-100",slate:"bg-slate-100",zinc:"bg-zinc-100",stone:"bg-stone-100",neutral:"bg-neutral-100"};function Ue(t){if(t.startsWith("bg-"))return t;const c=t.toLowerCase().trim();return Ke[c]}function Ce(t){return g.useCallback(c=>{if(!t?.field||!t.colors)return;const e=String(c[t.field]??""),n=t.colors[e];if(n)return Ue(n)},[t?.field,t?.colors])}function Be(t,c){return c.map(e=>String(t[e.field]??"")).join(" / ")}function He(t,c){return c.map(e=>{const n=t[e.field];return n!=null&&n!==""?String(n):"(empty)"}).join(" / ")}function Je(t,c,e){const n=t.localeCompare(c,void 0,{numeric:!0,sensitivity:"base"});return e==="desc"?-n:n}function Oe(t,c){const e=t?.fields,n=!!(e&&e.length>0),[s,i]=g.useState({}),o=g.useMemo(()=>e?e.some(m=>m.collapsed):!1,[e]),l=g.useMemo(()=>{if(!n||!e)return[];const m=new Map,f=[];for(const u of c){const d=Be(u,e);m.has(d)||(m.set(d,{label:He(u,e),rows:[]}),f.push(d)),m.get(d).rows.push(u)}const y=e[0]?.order??"asc";return f.sort((u,d)=>Je(u,d,y)),f.map(u=>{const d=m.get(u),E=u in s?s[u]:o;return{key:u,label:d.label,rows:d.rows,collapsed:E}})},[c,e,n,s,o]),b=g.useCallback(m=>{i(f=>({...f,[m]:f[m]!==void 0?!f[m]:!o}))},[o]);return{groups:l,isGrouped:n,toggleGroup:b}}function Xe(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 Ne(t){if(!(!t||t.length===0))return typeof t[0]=="object"&&t[0]!==null,t}const _e=({schema:t,dataSource:c,onEdit:e,onDelete:n,onRowSelect:s,onRowClick:i,onCellChange:o,onRowSave:l,onBatchSave:b,...m})=>{const[f,y]=g.useState([]),[u,d]=g.useState(!0),[E,x]=g.useState(null),[C,A]=g.useState(null),[T,$]=g.useState(!1),[R,K]=g.useState(0),M=g.useCallback(async()=>{K(v=>v+1)},[]),{ref:W,isRefreshing:be,pullDistance:ee}=Ge({onRefresh:M,enabled:!!c&&!!t.objectName});g.useEffect(()=>{const v=()=>$(window.innerWidth<480);return v(),window.addEventListener("resize",v),()=>window.removeEventListener("resize",v)},[]);const te=m.data,ne=Z.useDataScope(t.bind),se=Xe(t),D=g.useMemo(()=>te&&Array.isArray(te)?{provider:"value",items:te}:ne&&Array.isArray(ne)?{provider:"value",items:ne}:se,[JSON.stringify(se),ne,te]),U=D?.provider==="value",L=D?.provider==="object"&&D&&"object"in D?D.object:t.objectName,V=t.fields,Y=t.columns,X=t.filter,G=t.sort,ce=t.pagination,r=t.pageSize;g.useEffect(()=>{U&&D?.provider==="value"&&(y(v=>{const j=D.items;return JSON.stringify(v)!==JSON.stringify(j)?j:v}),d(!1))},[U,D]),g.useEffect(()=>{if(U)return;let v=!1;return(async()=>{d(!0),x(null);try{let I=null;if((Ne(Y)||V)&&L)I={name:L,fields:{}};else if(L&&c){const p=await c.getObjectSchema(L);if(v)return;I=p}else throw L?new Error("DataSource required"):new Error("Object name required for data fetching");if(v||A(I),c&&L){const P={$select:(()=>{if(V)return V;if(Y&&Array.isArray(Y))return Y.map(z=>typeof z=="string"?z:z.field)})(),$top:ce?.pageSize||r||50};X&&Array.isArray(X)?P.$filter=X:t.defaultFilters&&(P.$filter=t.defaultFilters),G?typeof G=="string"?P.$orderby=G:Array.isArray(G)&&(P.$orderby=G.map(z=>`${z.field} ${z.order}`).join(", ")):t.defaultSort&&(P.$orderby=`${t.defaultSort.field} ${t.defaultSort.order}`);const ue=await c.find(L,P);if(v)return;y(ue.data||[])}}catch(I){v||x(I)}finally{v||d(!1)}})(),()=>{v=!0}},[L,V,Y,X,G,ce,r,c,U,D,R]);const h=Z.useNavigationOverlay({navigation:t.navigation,objectName:t.objectName,onNavigate:t.onNavigate,onRowClick:i}),{execute:w}=Z.useAction(),O=Ce(t.rowColor),{groups:re,isGrouped:ie,toggleGroup:N}=Oe(t.grouping,f),q=g.useCallback(()=>{const v=Ne(Y);if(v){if(v.length>0&&typeof v[0]=="object"&&v[0]!==null){const S=v[0];if("accessorKey"in S)return v;if("field"in S)return v.filter(p=>p?.field&&typeof p.field=="string"&&!p.hidden).map((p,P)=>{const ue=p.label||p.field.charAt(0).toUpperCase()+p.field.slice(1).replace(/_/g," ");let z;const H=p.type?Ee.getCellRenderer(p.type):null;p.link&&p.action?z=(_,de)=>{const fe=H?a.jsx(H,{value:_,field:{name:p.field,type:p.type||"text"}}):_!=null&&_!==""?String(_):a.jsx("span",{className:"text-muted-foreground",children:"-"});return a.jsx("button",{type:"button",className:"text-primary font-medium underline-offset-4 hover:underline cursor-pointer bg-transparent border-none p-0 text-left font-inherit",onClick:he=>{he.stopPropagation(),h.handleClick(de)},children:fe})}:p.link?z=(_,de)=>{const fe=H?a.jsx(H,{value:_,field:{name:p.field,type:p.type||"text"}}):_!=null&&_!==""?String(_):a.jsx("span",{className:"text-muted-foreground",children:"-"});return a.jsx("button",{type:"button",className:"text-primary font-medium underline-offset-4 hover:underline cursor-pointer bg-transparent border-none p-0 text-left font-inherit",onClick:he=>{he.stopPropagation(),h.handleClick(de)},children:fe})}:p.action?z=(_,de)=>{const fe=H?a.jsx(H,{value:_,field:{name:p.field,type:p.type||"text"}}):_!=null&&_!==""?String(_):a.jsx("span",{className:"text-muted-foreground",children:"-"});return a.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:he=>{he.stopPropagation(),w({type:p.action,params:{record:de,field:p.field,value:_}})},children:fe})}:H?z=_=>a.jsx(H,{value:_,field:{name:p.field,type:p.type||"text"}}):z=_=>_!=null&&_!==""?a.jsx("span",{children:String(_)}):a.jsx("span",{className:"text-muted-foreground",children:"-"});const bt=["number","currency","percent"],Fe=p.align||(p.type&&bt.includes(p.type)?"right":void 0),vt=P===0||p.essential===!0;return{header:ue,accessorKey:p.field,...!vt&&{className:"hidden sm:table-cell"},...p.width&&{width:p.width},...Fe&&{align:Fe},sortable:p.sortable!==!1,...p.resizable!==void 0&&{resizable:p.resizable},...p.wrap!==void 0&&{wrap:p.wrap},...z&&{cell:z}}})}return v.filter(S=>typeof S=="string"&&S.trim().length>0).map(S=>({header:C?.fields?.[S]?.label||S.charAt(0).toUpperCase()+S.slice(1).replace(/_/g," "),accessorKey:S}))}if(U){const S=D?.provider==="value"?D.items:[];if(S.length>0)return(V||Object.keys(S[0])).map(P=>({header:P.charAt(0).toUpperCase()+P.slice(1).replace(/_/g," "),accessorKey:P}))}if(!C)return[];const j=[];return(V||Object.keys(C.fields||{})).forEach(S=>{const p=C.fields?.[S];if(!p||p.permissions&&p.permissions.read===!1)return;const P=Ee.getCellRenderer(p.type),ue=["number","currency","percent"];j.push({header:p.label||S,accessorKey:S,...ue.includes(p.type)&&{align:"right"},cell:z=>a.jsx(P,{value:z,field:p}),sortable:p.sortable!==!1})}),j},[C,V,Y,D,U,h.handleClick,w]);if(E)return a.jsxs("div",{className:"p-3 sm:p-4 border border-red-300 bg-red-50 rounded-md",children:[a.jsx("h3",{className:"text-red-800 font-semibold",children:"Error loading grid"}),a.jsx("p",{className:"text-red-600 text-sm mt-1",children:E.message})]});if(u&&f.length===0)return a.jsxs("div",{className:"p-4 sm:p-8 text-center",children:[a.jsx("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"}),a.jsx("p",{className:"mt-2 text-sm text-gray-600",children:"Loading grid..."})]});const oe=q(),B="operations"in t?t.operations:void 0,De=B&&(B.update||B.delete),ft=De?[...oe,{header:"Actions",accessorKey:"_actions",cell:(v,j)=>a.jsxs(F.DropdownMenu,{children:[a.jsx(F.DropdownMenuTrigger,{asChild:!0,children:a.jsxs(F.Button,{variant:"ghost",size:"icon",className:"h-8 w-8 min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0",children:[a.jsx(J.MoreVertical,{className:"h-4 w-4"}),a.jsx("span",{className:"sr-only",children:"Open menu"})]})}),a.jsxs(F.DropdownMenuContent,{align:"end",children:[B?.update&&e&&a.jsxs(F.DropdownMenuItem,{onClick:()=>e(j),children:[a.jsx(J.Edit,{className:"mr-2 h-4 w-4"}),"Edit"]}),B?.delete&&n&&a.jsxs(F.DropdownMenuItem,{onClick:()=>n(j),children:[a.jsx(J.Trash2,{className:"mr-2 h-4 w-4"}),"Delete"]})]})]}),sortable:!1}]:oe;let ve=!1;t.selection?.type?ve=t.selection.type==="none"?!1:t.selection.type:t.selectable!==void 0&&(ve=t.selectable);const ht=t.pagination!==void 0?!0:t.showPagination!==void 0?t.showPagination:!0,mt=t.pagination?.pageSize||t.pageSize||10,pt=t.searchableFields!==void 0?t.searchableFields.length>0:t.showSearch!==void 0?t.showSearch:!0,Ie={type:"data-table",caption:t.label||t.title,columns:ft,data:f,pagination:ht,pageSize:mt,searchable:pt,selectable:ve,sortable:!0,exportable:B?.export,rowActions:De,resizableColumns:t.resizable??t.resizableColumns??!0,reorderableColumns:t.reorderableColumns??!1,editable:t.editable??!1,className:t.className,cellClassName:"px-2 py-1.5 sm:px-3 sm:py-2 md:px-4 md:py-2.5",rowClassName:t.rowColor?(v,j)=>O(v):void 0,onSelectionChange:s,onRowClick:h.handleClick,onCellChange:o,onRowSave:l,onBatchSave:b},gt=v=>({...Ie,caption:void 0,data:v,pagination:!1,searchable:!1}),xe=t.label?`${t.label} Detail`:t.objectName?`${t.objectName.charAt(0).toUpperCase()+t.objectName.slice(1)} Detail`:"Record Detail";if(T&&f.length>0&&!ie){const v=q().filter(j=>j.accessorKey!=="_actions");return a.jsxs(a.Fragment,{children:[a.jsx("div",{className:"space-y-2 p-2",children:f.map((j,I)=>a.jsx("div",{className:"border rounded-lg p-3 bg-card hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation",onClick:()=>h.handleClick(j),children:v.slice(0,4).map(S=>a.jsxs("div",{className:"flex justify-between items-center py-1",children:[a.jsx("span",{className:"text-xs text-muted-foreground",children:S.header}),a.jsx("span",{className:"text-sm font-medium truncate ml-2 text-right",children:S.cell?S.cell(j[S.accessorKey],j):String(j[S.accessorKey]??"—")})]},S.accessorKey))},j.id||j._id||I))}),h.isOverlay&&a.jsx(F.NavigationOverlay,{...h,title:xe,children:j=>a.jsx("div",{className:"space-y-3",children:Object.entries(j).map(([I,S])=>a.jsxs("div",{className:"flex flex-col",children:[a.jsx("span",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wide",children:I.replace(/_/g," ")}),a.jsx("span",{className:"text-sm",children:String(S??"—")})]},I))})})]})}const Pe=ie?a.jsx("div",{className:"space-y-2",children:re.map(v=>a.jsxs("div",{className:"border rounded-md",children:[a.jsxs("button",{type:"button",className:"flex w-full items-center gap-2 px-3 py-2 text-sm font-medium text-left bg-muted/50 hover:bg-muted transition-colors",onClick:()=>N(v.key),children:[v.collapsed?a.jsx(J.ChevronRight,{className:"h-4 w-4 shrink-0"}):a.jsx(J.ChevronDown,{className:"h-4 w-4 shrink-0"}),a.jsx("span",{children:v.label}),a.jsx("span",{className:"ml-auto text-xs text-muted-foreground",children:v.rows.length})]}),!v.collapsed&&a.jsx(Z.SchemaRenderer,{schema:gt(v.rows)})]},v.key))}):a.jsx(Z.SchemaRenderer,{schema:Ie});return h.isOverlay&&h.mode==="split"?a.jsx(F.NavigationOverlay,{...h,title:xe,mainContent:Pe,children:v=>a.jsx("div",{className:"space-y-3",children:Object.entries(v).map(([j,I])=>a.jsxs("div",{className:"flex flex-col",children:[a.jsx("span",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wide",children:j.replace(/_/g," ")}),a.jsx("span",{className:"text-sm",children:String(I??"—")})]},j))})}):a.jsxs("div",{ref:W,className:"relative h-full",children:[ee>0&&a.jsx("div",{className:"flex items-center justify-center text-xs text-muted-foreground",style:{height:ee},children:be?"Refreshing…":"Pull to refresh"}),Pe,h.isOverlay&&a.jsx(F.NavigationOverlay,{...h,title:xe,children:v=>a.jsx("div",{className:"space-y-3",children:Object.entries(v).map(([j,I])=>a.jsxs("div",{className:"flex flex-col",children:[a.jsx("span",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wide",children:j.replace(/_/g," ")}),a.jsx("span",{className:"text-sm",children:String(I??"—")})]},j))})})]})};function Q(t,c,e){let n=e.initialDeps??[],s,i=!0;function o(){var l,b,m;let f;e.key&&((l=e.debug)!=null&&l.call(e))&&(f=Date.now());const y=t();if(!(y.length!==n.length||y.some((E,x)=>n[x]!==E)))return s;n=y;let d;if(e.key&&((b=e.debug)!=null&&b.call(e))&&(d=Date.now()),s=c(...y),e.key&&((m=e.debug)!=null&&m.call(e))){const E=Math.round((Date.now()-f)*100)/100,x=Math.round((Date.now()-d)*100)/100,C=x/16,A=(T,$)=>{for(T=String(T);T.length<$;)T=" "+T;return T};console.info(`%c⏱ ${A(x,5)} /${A(E,5)} ms`,`
|
|
6
|
+
<%s key={someKey} {...props} />`,H,R,X,R),xe[R+H]=!0)}if(R=null,K!==void 0&&(t(K),R=""+K),a(A)&&(t(A.key),R=""+A.key),"key"in A){K={};for(var ue in A)ue!=="key"&&(K[ue]=A[ue])}else K=A;return R&&l(K,typeof u=="function"?u.displayName||u.name||"Unknown":u),h(u,R,K,n(),we,ee)}function m(u){g(u)?u._store&&(u._store.validated=1):typeof u=="object"&&u!==null&&u.$$typeof===ve&&(u._payload.status==="fulfilled"?g(u._payload.value)&&u._payload.value._store&&(u._payload.value._store.validated=1):u._store&&(u._store.validated=1))}function g(u){return typeof u=="object"&&u!==null&&u.$$typeof===C}var b=f,C=Symbol.for("react.transitional.element"),w=Symbol.for("react.portal"),T=Symbol.for("react.fragment"),D=Symbol.for("react.strict_mode"),I=Symbol.for("react.profiler"),L=Symbol.for("react.consumer"),Y=Symbol.for("react.context"),q=Symbol.for("react.forward_ref"),J=Symbol.for("react.suspense"),le=Symbol.for("react.suspense_list"),Me=Symbol.for("react.memo"),ve=Symbol.for("react.lazy"),Ee=Symbol.for("react.activity"),de=Symbol.for("react.client.reference"),ge=b.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,V=Object.prototype.hasOwnProperty,Q=Array.isArray,he=console.createTask?console.createTask:function(){return null};b={react_stack_bottom_frame:function(u){return u()}};var ae,je={},re=b.react_stack_bottom_frame.bind(b,i)(),be=he(r(i)),xe={};Ae.Fragment=T,Ae.jsx=function(u,A,K){var H=1e4>ge.recentlyCreatedOwnerStacks++;return d(u,A,K,!1,H?Error("react-stack-top-frame"):re,H?he(r(u)):be)},Ae.jsxs=function(u,A,K){var H=1e4>ge.recentlyCreatedOwnerStacks++;return d(u,A,K,!0,H?Error("react-stack-top-frame"):re,H?he(r(u)):be)}})()),Ae}var Xe;function Dt(){return Xe||(Xe=1,process.env.NODE_ENV==="production"?Ie.exports=At():Ie.exports=Mt()),Ie.exports}var s=Dt();function Ft(e){const{onRefresh:o,threshold:t=80,enabled:r=!0}=e,n=f.useRef(null),[i,a]=f.useState(!1),[l,p]=f.useState(0),h=f.useRef(0),d=f.useCallback(b=>{if(!r||i)return;const C=n.current;C&&C.scrollTop===0&&(h.current=b.touches[0].clientY)},[r,i]),m=f.useCallback(b=>{if(!r||i||!h.current)return;const w=b.touches[0].clientY-h.current;w>0&&p(Math.min(w,t*1.5))},[r,i,t]),g=f.useCallback(async()=>{if(!r||i)return;const b=l;if(p(0),h.current=0,b>=t){a(!0);try{await o()}finally{a(!1)}}},[r,i,l,t,o]);return f.useEffect(()=>{const b=n.current;if(!(!b||!r))return b.addEventListener("touchstart",d,{passive:!0}),b.addEventListener("touchmove",m,{passive:!0}),b.addEventListener("touchend",g,{passive:!0}),()=>{b.removeEventListener("touchstart",d),b.removeEventListener("touchmove",m),b.removeEventListener("touchend",g)}},[d,m,g,r]),{ref:n,isRefreshing:i,pullDistance:l}}const zt=f.createContext(null);zt.displayName="MobileContext";const It={red:"bg-red-100",green:"bg-green-100",blue:"bg-blue-100",yellow:"bg-yellow-100",orange:"bg-orange-100",purple:"bg-purple-100",pink:"bg-pink-100",gray:"bg-gray-100",grey:"bg-gray-100",indigo:"bg-indigo-100",teal:"bg-teal-100",cyan:"bg-cyan-100",amber:"bg-amber-100",lime:"bg-lime-100",emerald:"bg-emerald-100",rose:"bg-rose-100",sky:"bg-sky-100",violet:"bg-violet-100",fuchsia:"bg-fuchsia-100",slate:"bg-slate-100",zinc:"bg-zinc-100",stone:"bg-stone-100",neutral:"bg-neutral-100"};function Pt(e){if(e.startsWith("bg-"))return e;const o=e.toLowerCase().trim();return It[o]}function Qe(e){return f.useCallback(o=>{if(!e?.field||!e.colors)return;const t=String(o[e.field]??""),r=e.colors[t];if(r)return Pt(r)},[e?.field,e?.colors])}function Lt(e,o){return o.map(t=>String(e[t.field]??"")).join(" / ")}function Rt(e,o){return o.map(t=>{const r=e[t.field];return r!=null&&r!==""?String(r):"(empty)"}).join(" / ")}function $t(e,o){return o.map(({field:t,type:r})=>{const n=e.map(a=>Number(a[t])).filter(a=>Number.isFinite(a));let i;switch(r){case"count":i=n.length;break;case"sum":i=n.reduce((a,l)=>a+l,0);break;case"avg":i=n.length>0?n.reduce((a,l)=>a+l,0)/n.length:0;break;case"min":i=n.length>0?Math.min(...n):0;break;case"max":i=n.length>0?Math.max(...n):0;break;default:i=0}return{field:t,type:r,value:i}})}function Vt(e,o,t){const r=e.localeCompare(o,void 0,{numeric:!0,sensitivity:"base"});return t==="desc"?-r:r}function Ze(e,o,t){const r=e?.fields,n=!!(r&&r.length>0),[i,a]=f.useState({}),l=f.useMemo(()=>r?r.some(d=>d.collapsed):!1,[r]),p=f.useMemo(()=>{if(!n||!r)return[];const d=new Map,m=[];for(const b of o){const C=Lt(b,r);d.has(C)||(d.set(C,{label:Rt(b,r),rows:[]}),m.push(C)),d.get(C).rows.push(b)}const g=r[0]?.order??"asc";return m.sort((b,C)=>Vt(b,C,g)),m.map(b=>{const C=d.get(b),w=b in i?i[b]:l,T=t&&t.length>0?$t(C.rows,t):[];return{key:b,label:C.label,rows:C.rows,collapsed:w,aggregations:T}})},[o,r,n,i,l,t]),h=f.useCallback(d=>{a(m=>({...m,[d]:m[d]!==void 0?!m[d]:!l}))},[l]);return{groups:p,isGrouped:n,toggleGroup:h}}const et=({groupKey:e,label:o,count:t,collapsed:r,aggregations:n,onToggle:i,children:a})=>s.jsxs("div",{className:"border rounded-md","data-testid":`group-row-${e}`,children:[s.jsxs("button",{type:"button",className:"flex w-full items-center gap-2 px-3 py-2 text-sm font-medium text-left bg-muted/50 hover:bg-muted transition-colors",onClick:()=>i(e),"aria-expanded":!r,children:[r?s.jsx(F.ChevronRight,{className:"h-4 w-4 shrink-0"}):s.jsx(F.ChevronDown,{className:"h-4 w-4 shrink-0"}),s.jsx("span",{className:"group-label",children:o}),n&&n.length>0&&s.jsx("span",{className:"ml-2 text-xs text-muted-foreground group-aggregations",children:n.map(l=>s.jsxs("span",{className:"mr-2",children:[l.type,": ",Number.isInteger(l.value)?l.value:l.value.toFixed(2)]},`${l.field}-${l.type}`))}),s.jsxs("span",{className:"ml-auto text-xs text-muted-foreground group-count",children:["(",t,")"]})]}),!r&&a]});function Kt(e){return typeof e=="string"?{type:e}:e}function Bt(e,o){if(o.length===0)return null;switch(e){case"count":return o.length;case"sum":return o.reduce((t,r)=>t+r,0);case"avg":return o.reduce((t,r)=>t+r,0)/o.length;case"min":return Math.min(...o);case"max":return Math.max(...o);default:return null}}function Wt(e,o){if(o===null)return"";const r={count:"Count",sum:"Sum",avg:"Avg",min:"Min",max:"Max"}[e]||e,n=e==="avg"?o.toLocaleString(void 0,{maximumFractionDigits:2}):o.toLocaleString();return`${r}: ${n}`}function tt(e,o){return f.useMemo(()=>{const t=new Map;if(!e||e.length===0||o.length===0)return{summaries:t,hasSummary:!1};for(const r of e){if(!r.summary)continue;const n=Kt(r.summary),i=n.field||r.field,a=[];for(const p of o){const h=p[i];if(h!=null&&typeof h=="number"&&!isNaN(h))a.push(h);else if(h!=null&&typeof h=="string"){const d=parseFloat(h);isNaN(d)||a.push(d)}}let l;if(n.type==="count"){const p=o.filter(h=>h[i]!=null&&h[i]!=="").length;l=p>0?p:null}else l=Bt(n.type,a);t.set(r.field,{field:r.field,value:l,label:Wt(n.type,l)})}return{summaries:t,hasSummary:t.size>0}},[e,o])}function Pe(e){return e.replace(/_/g," ").replace(/\b\w/g,o=>o.toUpperCase())}const st=({row:e,rowActions:o,canEdit:t,canDelete:r,onEdit:n,onDelete:i,onAction:a})=>s.jsxs(v.DropdownMenu,{children:[s.jsx(v.DropdownMenuTrigger,{asChild:!0,children:s.jsxs(v.Button,{variant:"ghost",size:"icon",className:"h-8 w-8 min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0","data-testid":"row-action-trigger",children:[s.jsx(F.MoreVertical,{className:"h-4 w-4"}),s.jsx("span",{className:"sr-only",children:"Open menu"})]})}),s.jsxs(v.DropdownMenuContent,{align:"end",children:[t&&n&&s.jsxs(v.DropdownMenuItem,{onClick:()=>n(e),children:[s.jsx(F.Edit,{className:"mr-2 h-4 w-4"}),"Edit"]}),r&&i&&s.jsxs(v.DropdownMenuItem,{onClick:()=>i(e),children:[s.jsx(F.Trash2,{className:"mr-2 h-4 w-4"}),"Delete"]}),o?.map(l=>s.jsx(v.DropdownMenuItem,{onClick:()=>a?.(l,e),"data-testid":`row-action-${l}`,children:Pe(l)},l))]})]}),We=({selectedRows:e,actions:o,onAction:t,onClearSelection:r})=>!o||o.length===0||e.length===0?null:s.jsxs("div",{className:"border-t px-4 py-1.5 flex items-center gap-2 text-xs bg-primary/5 shrink-0","data-testid":"bulk-actions-bar",children:[s.jsxs("span",{className:"text-muted-foreground font-medium",children:[e.length," selected"]}),s.jsx("div",{className:"flex items-center gap-1 ml-2",children:o.map(n=>s.jsx(v.Button,{variant:"outline",size:"sm",className:"h-6 px-2 text-xs",onClick:()=>t?.(n,e),"data-testid":`bulk-action-${n}`,children:Pe(n)},n))}),s.jsx(v.Button,{variant:"ghost",size:"sm",className:"h-6 px-2 text-xs ml-auto",onClick:r,children:"Clear"})]}),rt={"grid.actions":"Actions","grid.edit":"Edit","grid.delete":"Delete","grid.export":"Export","grid.exportAs":"Export as {{format}}","grid.loading":"Loading grid...","grid.errorLoading":"Error loading grid","grid.pullToRefresh":"Pull to refresh","grid.refreshing":"Refreshing…","grid.openRecord":"Open record"};function qt(){try{const e=pe.useObjectTranslation();return e.t("grid.actions")==="grid.actions"?{t:(t,r)=>{let n=rt[t]||t;if(r)for(const[i,a]of Object.entries(r))n=n.replace(`{{${i}}}`,String(a));return n}}:{t:e.t}}catch{return{t:(e,o)=>{let t=rt[e]||e;if(o)for(const[r,n]of Object.entries(o))t=t.replace(`{{${r}}}`,String(n));return t}}}}function Gt(e){if(e!=null)return typeof e=="string"?e:e.defaultValue||e.key}function Ht(e){return e.data?Array.isArray(e.data)?{provider:"value",items:e.data}:e.data:e.staticData?{provider:"value",items:e.staticData}:e.objectName?{provider:"object",object:e.objectName}:null}function qe(e){if(!(!e||e.length===0))return typeof e[0]=="object"&&e[0]!==null,e}const nt=({schema:e,dataSource:o,onEdit:t,onDelete:r,onRowSelect:n,onRowClick:i,onCellChange:a,onRowSave:l,onBatchSave:p,onAddRecord:h,...d})=>{const[m,g]=f.useState([]),[b,C]=f.useState(!0),[w,T]=f.useState(null),{t:D}=qt(),{fieldLabel:I}=pe.useSafeFieldLabel(),[L,Y]=f.useState(null),[q,J]=f.useState(!1),[le,Me]=f.useState(0),[ve,Ee]=f.useState(!1),[de,ge]=f.useState(e.rowHeight??"compact"),[V,Q]=f.useState([]),he=f.useMemo(()=>e.id?`grid-columns-${e.objectName}-${e.id}`:`grid-columns-${e.objectName}`,[e.objectName,e.id]),[ae,je]=f.useState(()=>{try{const c=localStorage.getItem(he);return c?JSON.parse(c):{}}catch{return{}}}),re=f.useCallback(c=>{je(c);try{localStorage.setItem(he,JSON.stringify(c))}catch(M){console.warn("Failed to persist column state:",M)}},[he]),be=f.useCallback(async()=>{Me(c=>c+1)},[]),{ref:xe,isRefreshing:u,pullDistance:A}=Ft({onRefresh:be,enabled:!!o&&!!e.objectName});f.useEffect(()=>{const c=()=>J(window.innerWidth<480);return c(),window.addEventListener("resize",c),()=>window.removeEventListener("resize",c)},[]);const K=d.data,H=pe.useDataScope(e.bind),we=Ht(e),ee=f.useMemo(()=>K&&Array.isArray(K)?{provider:"value",items:K}:H&&Array.isArray(H)?{provider:"value",items:H}:we,[JSON.stringify(we),H,K]),R=ee?.provider==="value",X=ee?.provider==="object"&&ee&&"object"in ee?ee.object:e.objectName,ue=e.fields,me=e.columns,Le=e.filter,ke=e.sort,pt=e.pagination,gt=e.pageSize;f.useEffect(()=>{R&&ee?.provider==="value"&&(g(c=>{const M=ee.items;return JSON.stringify(c)!==JSON.stringify(M)?M:c}),C(!1))},[R,ee]),f.useEffect(()=>{if(!R||!X||!o)return;let c=!1;return(async()=>{try{const k=await o.getObjectSchema(X);c||Y(k)}catch(k){console.warn(`[ObjectGrid] Failed to fetch objectSchema for inline data (objectName: ${X}):`,k)}})(),()=>{c=!0}},[R,X,o]),f.useEffect(()=>{if(R)return;let c=!1;return(async()=>{C(!0),T(null);try{let k=null;const U=qe(me)||ue;if(X&&o){const te=await o.getObjectSchema(X);if(c)return;k=te}else if(U&&X)k={name:X,fields:{}};else throw X?new Error("DataSource required"):new Error("Object name required for data fetching");if(c||Y(k),o&&X){const j={$select:(()=>{if(ue)return ue;if(me&&Array.isArray(me))return me.map(N=>typeof N=="string"?N:N.field)})(),$top:pt?.pageSize||gt||50};Le&&Array.isArray(Le)?j.$filter=Le:e.defaultFilters&&(j.$filter=e.defaultFilters),ke?typeof ke=="string"?j.$orderby=ke:Array.isArray(ke)&&(j.$orderby=ke.map(N=>`${N.field} ${N.order}`).join(", ")):e.defaultSort&&(j.$orderby=`${e.defaultSort.field} ${e.defaultSort.order}`);const x=_e.buildExpandFields(k?.fields,me??ue);x.length>0&&(j.$expand=x);const S=await o.find(X,j);if(c)return;g(S.data||[])}}catch(k){c||T(k)}finally{c||C(!1)}})(),()=>{c=!0}},[X,ue,me,Le,ke,pt,gt,o,R,ee,le]);const ne=pe.useNavigationOverlay({navigation:e.navigation,objectName:e.objectName,onNavigate:e.onNavigate,onRowClick:i}),{execute:De}=pe.useAction(),Ns=Qe(e.rowColor),Ss=f.useCallback(c=>{const M=e.conditionalFormatting;if(!(!M||M.length===0))for(const k of M){let U=!1;const te=("condition"in k?k.condition:void 0)||("expression"in k?k.expression:void 0)||void 0;if(te)U=_e.evaluatePlainCondition(te,c);else if("field"in k&&"operator"in k&&k.field&&k.operator){const j=k,x=c[j.field];switch(j.operator){case"equals":U=x===j.value;break;case"not_equals":U=x!==j.value;break;case"contains":U=typeof x=="string"&&typeof j.value=="string"&&x.includes(j.value);break;case"greater_than":U=typeof x=="number"&&typeof j.value=="number"&&x>j.value;break;case"less_than":U=typeof x=="number"&&typeof j.value=="number"&&x<j.value;break;case"in":U=Array.isArray(j.value)&&j.value.includes(x);break}}if(U){const j={};return"style"in k&&k.style&&Object.assign(j,k.style),"backgroundColor"in k&&k.backgroundColor&&(j.backgroundColor=k.backgroundColor),"textColor"in k&&k.textColor&&(j.color=k.textColor),"borderColor"in k&&k.borderColor&&(j.borderColor=k.borderColor),j}}},[e.conditionalFormatting]),{groups:Es,isGrouped:xt,toggleGroup:ks}=Ze(e.grouping,m),Os=f.useMemo(()=>{const c=qe(e.columns);if(c&&c.length>0&&typeof c[0]=="object")return c},[e.columns]),{summaries:bt,hasSummary:_s}=tt(Os,m),Re=f.useCallback(()=>{const c=j=>j?{text:s.jsx(F.Type,{className:"h-3.5 w-3.5"}),number:s.jsx(F.Hash,{className:"h-3.5 w-3.5"}),currency:s.jsx(F.Hash,{className:"h-3.5 w-3.5"}),percent:s.jsx(F.Hash,{className:"h-3.5 w-3.5"}),date:s.jsx(F.Calendar,{className:"h-3.5 w-3.5"}),datetime:s.jsx(F.Clock,{className:"h-3.5 w-3.5"}),boolean:s.jsx(F.CheckSquare,{className:"h-3.5 w-3.5"}),user:s.jsx(F.User,{className:"h-3.5 w-3.5"}),select:s.jsx(F.Tag,{className:"h-3.5 w-3.5"})}[j]||s.jsx(F.Type,{className:"h-3.5 w-3.5"}):s.jsx(F.Type,{className:"h-3.5 w-3.5"}),M=j=>{if(j.type)return j.type;const x=j.field.toLowerCase();if(["completed","is_completed","done","active","enabled","archived"].some(O=>x===O||x===`is_${O}`))return"boolean";if(["created_time","modified_time","updated_time","created_at","updated_at","modified_at","last_login","logged_at"].some(O=>x===O||x.endsWith(`_${O}`)))return"datetime";if(["date","due","created","updated","deadline","start","end","expires"].some(O=>x.includes(O))){if(m.length>0){const O=m.find($=>$[j.field]!=null)?.[j.field];if(typeof O=="string"&&!isNaN(Date.parse(O)))return"date"}return"date"}if(["probability","percent","percentage","completion","progress","rate"].some(O=>x.includes(O))&&m.length>0&&typeof m.find($=>$[j.field]!=null)?.[j.field]=="number")return"percent";if(["status","priority","category","stage","type","severity","level"].some(O=>x.includes(O))&&m.length>0){const O=new Set(m.map($=>$[j.field]).filter(Boolean));if(O.size>0&&O.size<=10)return"select"}if(["assignee","owner","author","reporter","creator","user"].some(O=>x.includes(O)))return"user";if(["amount","price","total","revenue","cost","budget","salary"].some(O=>x.includes(O))&&m.length>0&&typeof m.find($=>$[j.field]!=null)?.[j.field]=="number")return"currency";if(m.length>0){const O=m.find($=>$[j.field]!=null)?.[j.field];if(typeof O=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/.test(O))return"datetime"}return null},k=qe(me);if(k){if(k.length>0&&typeof k[0]=="object"&&k[0]!==null){const j=k[0];if("accessorKey"in j)return k.map(x=>{if(x.cell)return x;const S={field:x.accessorKey,label:x.header,type:x.type},N=M(S);if(!N)return x;const z=Z.getCellRenderer(N),E={name:x.accessorKey,type:N};if(N==="select"){const y=Array.from(new Set(m.map(_=>_[x.accessorKey]).filter(Boolean)));E.options=y.map(_=>({value:_,label:Z.humanizeLabel(String(_))}))}return{...x,headerIcon:c(N),cell:y=>s.jsx(z,{value:y,field:E})}});if("field"in j)return k.filter(x=>x?.field&&typeof x.field=="string"&&!x.hidden).map((x,S)=>{const N=Gt(x.label)||x.field.charAt(0).toUpperCase()+x.field.slice(1).replace(/_/g," "),z=e.objectName?I(e.objectName,x.field,N):N;let E;const y=L?.fields?.[x.field],_=x.type||y?.type||M({field:x.field})||null,B=_?Z.getCellRenderer(_):null,O={name:x.field,type:_||"text"};if(y&&(y.label&&(O.label=y.label),y.currency&&(O.currency=y.currency),y.precision!==void 0&&(O.precision=y.precision),y.format&&(O.format=y.format),y.options&&(O.options=y.options)),_==="select"&&!O.options){const G=Array.from(new Set(m.map(ce=>ce[x.field]).filter(Boolean)));O.options=G.map(ce=>({value:ce,label:Z.humanizeLabel(String(ce))}))}x.options&&(O.options=x.options);const $=S===0&&!x.link&&!x.action,se=x.link||$;x.link&&x.action||$&&x.action?E=(G,ce)=>{const Ne=B?s.jsx(B,{value:G,field:O}):G!=null&&G!==""?String(G):s.jsx("span",{className:"text-muted-foreground/50 text-xs italic",children:"—"});return s.jsx("button",{type:"button",className:"text-primary font-medium underline-offset-4 hover:underline cursor-pointer bg-transparent border-none p-0 text-left font-inherit","data-testid":$?"primary-field-link":"link-cell",onClick:Oe=>{Oe.stopPropagation(),ne.handleClick(ce)},children:Ne})}:se?E=(G,ce)=>{const Ne=B?s.jsx(B,{value:G,field:O}):G!=null&&G!==""?String(G):s.jsx("span",{className:"text-muted-foreground/50 text-xs italic",children:"—"});return s.jsx("button",{type:"button",className:"text-primary font-medium underline-offset-4 hover:underline cursor-pointer bg-transparent border-none p-0 text-left font-inherit","data-testid":$?"primary-field-link":"link-cell",onClick:Oe=>{Oe.stopPropagation(),ne.handleClick(ce)},children:Ne})}:x.action?E=(G,ce)=>s.jsx(v.Button,{variant:"outline",size:"sm",className:"h-7 text-xs","data-testid":"action-cell",onClick:Ne=>{Ne.stopPropagation(),De({type:x.action,params:{record:ce,field:x.field,value:G}})},children:Pe(x.action)}):B?E=G=>s.jsx(B,{value:G,field:O}):E=G=>G!=null&&G!==""?s.jsx("span",{children:String(G)}):s.jsx("span",{className:"text-muted-foreground/50 text-xs italic",children:"—"});const fe=x.prefix;if(fe?.field){const G=E,ce=fe.type==="badge"?Z.getCellRenderer("select"):null;E=(Ne,Oe)=>{const Be=Oe[fe.field],Ks=Be!=null&&Be!==""?ce?s.jsx(ce,{value:Be,field:{name:fe.field,type:"select"}}):s.jsx("span",{className:"text-muted-foreground text-xs mr-1.5",children:String(Be)}):null;return s.jsxs("span",{className:"flex items-center gap-1.5",children:[Ks,G(Ne,Oe)]})}}const ie=["number","currency","percent"],oe=_||x.type,ye=x.align||(oe&&ie.includes(oe)?"right":void 0),W=S===0||x.essential===!0;return{header:z,accessorKey:x.field,headerIcon:c(_),...!W&&{className:"hidden sm:table-cell"},...x.width&&{width:x.width},...ye&&{align:ye},sortable:x.sortable!==!1,...x.resizable!==void 0&&{resizable:x.resizable},...x.wrap!==void 0&&{wrap:x.wrap},...E&&{cell:E},...x.pinned&&{pinned:x.pinned}}})}return k.filter(j=>typeof j=="string"&&j.trim().length>0).map((j,x)=>{const S=L?.fields?.[j],z=S?.label||j.charAt(0).toUpperCase()+j.slice(1).replace(/_/g," "),E=e.objectName?I(e.objectName,j,z):z,y=S?.type||M({field:j})||null,_=y?Z.getCellRenderer(y):null,B={name:j,type:y||"text"};if(S&&(S.label&&(B.label=S.label),S.currency&&(B.currency=S.currency),S.precision!==void 0&&(B.precision=S.precision),S.format&&(B.format=S.format),S.options&&(B.options=S.options)),y==="select"&&!B.options){const ie=Array.from(new Set(m.map(oe=>oe[j]).filter(Boolean)));B.options=ie.map(oe=>({value:oe,label:Z.humanizeLabel(String(oe))}))}const $=y&&["number","currency","percent"].includes(y)?"right":void 0,se=x===0;let fe;return se&&_?fe=(ie,oe)=>{const ye=s.jsx(_,{value:ie,field:B});return s.jsx("button",{type:"button",className:"text-primary font-medium underline-offset-4 hover:underline cursor-pointer bg-transparent border-none p-0 text-left font-inherit","data-testid":"primary-field-link",onClick:W=>{W.stopPropagation(),ne.handleClick(oe)},children:ye})}:se?fe=(ie,oe)=>s.jsx("button",{type:"button",className:"text-primary font-medium underline-offset-4 hover:underline cursor-pointer bg-transparent border-none p-0 text-left font-inherit","data-testid":"primary-field-link",onClick:ye=>{ye.stopPropagation(),ne.handleClick(oe)},children:ie!=null&&ie!==""?String(ie):s.jsx("span",{className:"text-muted-foreground/50 text-xs italic",children:"—"})}):_&&(fe=ie=>s.jsx(_,{value:ie,field:B})),{header:E,accessorKey:j,...y&&{headerIcon:c(y)},...$&&{align:$},...fe&&{cell:fe},sortable:S?.sortable!==!1}})}if(R){const j=ee?.provider==="value"?ee.items:[];if(j.length>0)return(ue||Object.keys(j[0])).map(S=>{const N=L?.fields?.[S],z=N?.type||M({field:S})||null,E=z?Z.getCellRenderer(z):null,y=N?.label||S.charAt(0).toUpperCase()+S.slice(1).replace(/_/g," "),_={name:S,type:z||"text"};if(N&&(N.label&&(_.label=N.label),N.currency&&(_.currency=N.currency),N.precision!==void 0&&(_.precision=N.precision),N.format&&(_.format=N.format),N.options&&(_.options=N.options)),z==="select"&&!_.options){const $=Array.from(new Set(m.map(se=>se[S]).filter(Boolean)));_.options=$.map(se=>({value:se,label:Z.humanizeLabel(String(se))}))}const O=z&&["number","currency","percent"].includes(z)?"right":void 0;return{header:y,accessorKey:S,...z&&{headerIcon:c(z)},...O&&{align:O},...E&&{cell:$=>s.jsx(E,{value:$,field:_})},sortable:N?.sortable!==!1}})}if(!L)return[];const U=[];return(ue||Object.keys(L.fields||{})).forEach(j=>{const x=L.fields?.[j];if(!x||x.permissions&&x.permissions.read===!1)return;const S=Z.getCellRenderer(x.type),N=["number","currency","percent"];U.push({header:e.objectName?I(e.objectName,j,x.label||j):x.label||j,accessorKey:j,...N.includes(x.type)&&{align:"right"},cell:z=>s.jsx(S,{value:z,field:x}),sortable:x.sortable!==!1})}),U},[L,ue,me,ee,R,ne.handleClick,De,m,I,e.objectName]),Ts=f.useCallback(c=>{const M=e.exportOptions,k=M?.maxRecords||0,U=M?.includeHeaders!==!1,te=M?.fileNamePrefix||e.objectName||"export",j=k>0?m.slice(0,k):m,x=(N,z)=>{const E=URL.createObjectURL(N),y=document.createElement("a");y.href=E,y.download=z,y.click(),URL.revokeObjectURL(E)},S=N=>{const z=N==null?"":String(N);return z.includes(",")||z.includes('"')||z.includes(`
|
|
7
|
+
`)||z.includes("\r")?`"${z.replace(/"/g,'""')}"`:z};if(c==="csv"){const N=Re().filter(_=>_.accessorKey!=="_actions"),z=N.map(_=>_.accessorKey),E=N.map(_=>_.header),y=[];U&&y.push(E.join(",")),j.forEach(_=>{y.push(z.map(B=>S(_[B])).join(","))}),x(new Blob([y.join(`
|
|
8
|
+
`)],{type:"text/csv;charset=utf-8;"}),`${te}.csv`)}else c==="json"&&x(new Blob([JSON.stringify(j,null,2)],{type:"application/json"}),`${te}.json`);Ee(!1)},[m,e.exportOptions,e.objectName,Re]);if(w)return s.jsxs("div",{className:"p-3 sm:p-4 border border-red-300 bg-red-50 rounded-md",children:[s.jsx("h3",{className:"text-red-800 font-semibold",children:D("grid.errorLoading")}),s.jsx("p",{className:"text-red-600 text-sm mt-1",children:w.message})]});if(b&&m.length===0)return q?s.jsx("div",{className:"space-y-2 p-2",children:[1,2,3].map(c=>s.jsxs("div",{className:"border rounded-lg p-3 bg-card animate-pulse",children:[s.jsx("div",{className:"h-5 bg-muted rounded w-3/4 mb-3"}),s.jsxs("div",{className:"flex items-center justify-between mb-2",children:[s.jsx("div",{className:"h-4 bg-muted rounded w-1/4"}),s.jsx("div",{className:"h-5 bg-muted rounded-full w-20"})]}),s.jsx("div",{className:"h-3 bg-muted rounded w-1/3"})]},c))}):s.jsxs("div",{className:"p-4 sm:p-8 text-center",children:[s.jsx("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-foreground"}),s.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:D("grid.loading")})]});let Fe=[...Re()];if(ae.widths&&(Fe=Fe.map(c=>{const M=ae.widths?.[c.accessorKey];return M?{...c,size:M}:c})),ae.order&&ae.order.length>0){const c=new Map(ae.order.map((M,k)=>[M,k]));Fe.sort((M,k)=>{const U=c.get(M.accessorKey)??1/0,te=c.get(k.accessorKey)??1/0;return U-te})}const Ce="operations"in e?e.operations:void 0,yt=Ce&&(Ce.update||Ce.delete),As=e.rowActions&&e.rowActions.length>0,$e=yt||As?[...Fe,{header:D("grid.actions"),accessorKey:"_actions",cell:(c,M)=>s.jsx(st,{row:M,rowActions:e.rowActions,canEdit:!!(Ce?.update&&t),canDelete:!!(Ce?.delete&&r),onEdit:t,onDelete:r,onAction:(k,U)=>De({type:k,params:{record:U}})}),sortable:!1}]:Fe,He=$e.filter(c=>c.pinned==="left"),vt=$e.filter(c=>c.pinned==="right"),Ms=$e.filter(c=>!c.pinned),jt=He.length>0||vt.length>0,wt="sticky right-0 z-10 bg-background border-l border-border",Ct=jt?[...He,...Ms,...vt.map(c=>({...c,className:[c.className,wt].filter(Boolean).join(" "),cellClassName:[c.cellClassName,wt].filter(Boolean).join(" ")}))]:$e,Ds=jt?He.length:e.frozenColumns??1,Ve=e.batchActions??e.bulkActions,Fs=Ve&&Ve.length>0;let Ke=!1;e.selection?.type?Ke=e.selection.type==="none"?!1:e.selection.type:e.selectable!==void 0?Ke=e.selectable:Fs&&(Ke="multiple");const zs=e.pagination!==void 0?!0:e.showPagination!==void 0?e.showPagination:!0,Is=e.pagination?.pageSize||e.pageSize||10,Ps=e.searchableFields!==void 0?e.searchableFields.length>0:e.showSearch!==void 0?e.showSearch:!0,Nt={type:"data-table",caption:e.label||e.title,columns:Ct,data:m,pagination:zs,pageSize:Is,searchable:Ps,selectable:Ke,sortable:!0,exportable:Ce?.export,rowActions:yt,resizableColumns:e.resizable??e.resizableColumns??!0,reorderableColumns:e.reorderableColumns??!1,editable:e.editable??!1,singleClickEdit:e.singleClickEdit??!0,className:e.className,cellClassName:de==="compact"?"px-3 py-1 text-[13px] leading-tight":de==="short"?"px-3 py-1 text-[13px] leading-normal":de==="tall"?"px-3 py-2.5 text-sm":de==="extra_tall"?"px-3 py-3.5 text-sm leading-relaxed":"px-3 py-1.5 text-[13px] leading-normal",showRowNumbers:!0,showAddRow:!!Ce?.create,onAddRecord:h,rowClassName:e.rowColor?(c,M)=>Ns(c):void 0,rowStyle:e.conditionalFormatting?.length?(c,M)=>Ss(c):void 0,frozenColumns:Ds,onSelectionChange:c=>{Q(c),n?.(c)},onRowClick:ne.handleClick,onCellChange:a,onRowSave:l,onBatchSave:p,onColumnResize:(c,M)=>{re({...ae,widths:{...ae.widths,[c]:M}})},onColumnReorder:c=>{re({...ae,order:c})}},Ls=c=>({...Nt,caption:void 0,data:c,pagination:!1,searchable:!1}),Ue=e.label?`${e.label} Detail`:e.objectName?`${e.objectName.charAt(0).toUpperCase()+e.objectName.slice(1)} Detail`:"Record Detail";if(q&&m.length>0&&!xt){const c=Re().filter(E=>E.accessorKey!=="_actions"),M=new Map;c.forEach(E=>M.set(E.accessorKey,E));const k=c[0],U=["amount","price","total","revenue","cost","value","budget","salary"],te=["stage","status","priority","category","severity","level"],j=["date","due","created","updated","deadline","start","end","expires"],x=["probability","percent","rate","ratio","confidence","score"],S=E=>{const y=(E||"").toLowerCase();return y.includes("won")||y.includes("completed")||y.includes("done")||y.includes("active")?"bg-green-100 text-green-800 border-green-300":y.includes("lost")||y.includes("cancelled")||y.includes("rejected")||y.includes("closed lost")?"bg-red-100 text-red-800 border-red-300":y.includes("negotiation")||y.includes("review")||y.includes("in progress")?"bg-yellow-100 text-yellow-800 border-yellow-300":y.includes("proposal")||y.includes("pending")?"bg-blue-100 text-blue-800 border-blue-300":y.includes("qualification")||y.includes("qualified")?"bg-indigo-100 text-indigo-800 border-indigo-300":y.includes("prospecting")||y.includes("new")||y.includes("open")?"bg-purple-100 text-purple-800 border-purple-300":"bg-muted text-muted-foreground border-border"},N=E=>{const y=(E||"").toLowerCase();return y.includes("won")||y.includes("completed")||y.includes("done")||y.includes("active")?"border-l-green-500":y.includes("lost")||y.includes("cancelled")||y.includes("rejected")?"border-l-red-500":y.includes("negotiation")||y.includes("review")||y.includes("in progress")?"border-l-yellow-500":y.includes("proposal")||y.includes("pending")?"border-l-blue-500":y.includes("qualification")||y.includes("qualified")?"border-l-indigo-500":y.includes("prospecting")||y.includes("new")||y.includes("open")?"border-l-purple-500":"border-l-gray-300"},z=E=>{const y=E.toLowerCase();return U.some(_=>y.includes(_))?"amount":te.some(_=>y.includes(_))?"stage":j.some(_=>y.includes(_))?"date":x.some(_=>y.includes(_))?"percent":"other"};return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"space-y-2 p-2",children:m.map((E,y)=>{const _=c.slice(1,5),B=_.find(W=>z(W.accessorKey)==="amount"),O=_.find(W=>z(W.accessorKey)==="stage"),$=_.filter(W=>z(W.accessorKey)==="date"),se=_.filter(W=>z(W.accessorKey)==="percent"),fe=_.filter(W=>W!==B&&W!==O&&!$.includes(W)&&!se.includes(W)),ie=O?String(E[O.accessorKey]??""):"",oe=ie?N(ie):"",ye=["border rounded-lg p-2.5 bg-card hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation",oe?`border-l-[3px] ${oe}`:""].filter(Boolean).join(" ");return s.jsxs("div",{className:ye,onClick:()=>ne.handleClick(E),children:[k&&s.jsx("div",{className:"font-semibold text-sm truncate mb-1",children:E[k.accessorKey]??"—"}),(B||O)&&s.jsxs("div",{className:"flex items-center justify-between gap-2 mb-1",children:[B&&s.jsx("span",{className:"text-sm tabular-nums font-medium",children:typeof E[B.accessorKey]=="number"?Z.formatCompactCurrency(E[B.accessorKey]):E[B.accessorKey]??"—"}),O&&E[O.accessorKey]&&s.jsx(v.Badge,{variant:"outline",className:`text-xs shrink-0 max-w-[140px] truncate ${S(String(E[O.accessorKey]))}`,children:E[O.accessorKey]})]}),($.length>0||se.length>0)&&s.jsxs("div",{className:"flex items-center justify-between py-0.5 text-xs text-muted-foreground",children:[$[0]&&s.jsx("span",{className:"tabular-nums",children:E[$[0].accessorKey]?Z.formatDate(E[$[0].accessorKey],"short"):"—"}),se[0]&&E[se[0].accessorKey]!=null&&s.jsx("span",{className:"tabular-nums",children:Z.formatPercent(Number(E[se[0].accessorKey]))})]}),$.slice(1).map(W=>s.jsxs("div",{className:"flex justify-between items-center py-0.5",children:[s.jsx("span",{className:"text-xs text-muted-foreground",children:W.header}),s.jsx("span",{className:"text-xs text-muted-foreground tabular-nums",children:E[W.accessorKey]?Z.formatDate(E[W.accessorKey],"short"):"—"})]},W.accessorKey)),fe.map(W=>{const G=E[W.accessorKey];return G==null||G===""?null:s.jsxs("div",{className:"flex justify-between items-center py-0.5",children:[s.jsx("span",{className:"text-xs text-muted-foreground",children:W.header}),s.jsx("span",{className:"text-xs font-medium truncate ml-2 text-right",children:W.cell?W.cell(G,E):String(G)})]},W.accessorKey)})]},E.id||E._id||y)})}),ne.isOverlay&&s.jsx(v.NavigationOverlay,{...ne,title:Ue,children:E=>s.jsx("div",{className:"space-y-3",children:Object.entries(E).map(([y,_])=>s.jsxs("div",{className:"flex flex-col",children:[s.jsx("span",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wide",children:y.replace(/_/g," ")}),s.jsx("span",{className:"text-sm",children:String(_??"—")})]},y))})})]})}const Rs=()=>{ge(c=>c==="compact"?"short":c==="short"?"medium":c==="medium"?"tall":c==="tall"?"extra_tall":"compact")},$s={compact:F.Rows4,short:F.Rows3,medium:F.Rows2,tall:F.AlignJustify,extra_tall:F.AlignJustify}[de],St=e.rowHeight!==void 0,Et=e.exportOptions||St?s.jsxs("div",{className:"flex items-center justify-end gap-1 px-2 py-1",children:[St&&s.jsxs(v.Button,{variant:"ghost",size:"sm",className:"h-7 px-2 text-muted-foreground hover:text-primary text-xs",onClick:Rs,title:`Row height: ${de}`,children:[s.jsx($s,{className:"h-3.5 w-3.5 mr-1.5"}),s.jsx("span",{className:"hidden sm:inline capitalize",children:de})]}),e.exportOptions&&s.jsxs(v.Popover,{open:ve,onOpenChange:Ee,children:[s.jsx(v.PopoverTrigger,{asChild:!0,children:s.jsxs(v.Button,{variant:"ghost",size:"sm",className:"h-7 px-2 text-muted-foreground hover:text-primary text-xs",children:[s.jsx(F.Download,{className:"h-3.5 w-3.5 mr-1.5"}),s.jsx("span",{className:"hidden sm:inline",children:D("grid.export")})]})}),s.jsx(v.PopoverContent,{align:"end",className:"w-48 p-2",children:s.jsx("div",{className:"space-y-1",children:(e.exportOptions.formats||["csv","json"]).map(c=>s.jsxs(v.Button,{variant:"ghost",size:"sm",className:"w-full justify-start h-8 text-xs",onClick:()=>Ts(c),children:[s.jsx(F.Download,{className:"h-3.5 w-3.5 mr-2"}),D("grid.exportAs",{format:c.toUpperCase()})]},c))})})]})]}):null,kt=c=>{const M=["_id","id","created_at","updated_at","created_by","updated_by"],k=Object.entries(c),U=k.filter(([S])=>!M.includes(S)),te=k.filter(([S])=>M.includes(S)&&S!=="_id"&&S!=="id"),j=S=>S.charAt(0).toUpperCase()+S.slice(1).replace(/_/g," "),x=(S,N)=>{if(N==null||N==="")return s.jsx("span",{className:"text-muted-foreground/50 text-sm italic",children:"Empty"});const z=L?.fields?.[S];if(z?.type){const y=Z.getCellRenderer(z.type);if(y)return s.jsx(y,{value:N,field:z})}return typeof N=="boolean"?s.jsx(v.Badge,{variant:N?"default":"outline",children:N?"Yes":"No"}):typeof N=="string"&&!isNaN(Date.parse(N))&&(S.includes("date")||S.includes("_at")||S.includes("time"))?s.jsx("span",{className:"text-sm tabular-nums",children:Z.formatDate(N)}):typeof N=="number"&&["amount","price","total","revenue","cost","value","budget","salary"].some(y=>S.toLowerCase().includes(y))?s.jsx("span",{className:"text-sm tabular-nums font-medium",children:Z.formatCurrency(N)}):s.jsx("span",{className:"text-sm break-words",children:String(N)})};return s.jsxs("div",{className:"space-y-4","data-testid":"record-detail-panel",children:[s.jsx("div",{className:"rounded-lg border bg-card",children:s.jsx("div",{className:"divide-y",children:U.map(([S,N])=>s.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-start gap-1 sm:gap-4 px-4 py-3",children:[s.jsx("span",{className:"text-xs font-medium text-muted-foreground sm:w-1/3 sm:text-right sm:pt-0.5 uppercase tracking-wide shrink-0",children:j(S)}),s.jsx("div",{className:"flex-1 min-w-0",children:x(S,N)})]},S))})}),te.length>0&&s.jsxs("div",{className:"rounded-lg border bg-muted/30",children:[s.jsx("div",{className:"px-4 py-2 border-b",children:s.jsx("span",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wide",children:"System"})}),s.jsx("div",{className:"divide-y divide-border/50",children:te.map(([S,N])=>s.jsxs("div",{className:"flex items-center gap-4 px-4 py-2",children:[s.jsx("span",{className:"text-xs text-muted-foreground w-1/3 text-right shrink-0",children:j(S)}),s.jsx("span",{className:"text-xs text-muted-foreground flex-1 min-w-0 break-words",children:String(N??"")})]},S))})]})]})},Vs=_s?s.jsx("div",{className:"border-t bg-muted/30 px-2 py-1.5","data-testid":"column-summary-footer",children:s.jsx("div",{className:"flex gap-4 text-xs text-muted-foreground font-medium",children:Ct.filter(c=>bt.has(c.accessorKey)).map(c=>{const M=bt.get(c.accessorKey);return s.jsxs("span",{"data-testid":`summary-${c.accessorKey}`,children:[c.header,": ",M.label]},c.accessorKey)})})}):null,Ot=xt?s.jsx("div",{className:"space-y-2",children:Es.map(c=>s.jsx(et,{groupKey:c.key,label:c.label,count:c.rows.length,collapsed:c.collapsed,aggregations:c.aggregations,onToggle:ks,children:s.jsx(pe.SchemaRenderer,{schema:Ls(c.rows)})},c.key))}):s.jsxs(s.Fragment,{children:[s.jsx(pe.SchemaRenderer,{schema:Nt}),Vs]});return ne.isOverlay&&ne.mode==="split"?s.jsx(v.NavigationOverlay,{...ne,title:Ue,mainContent:s.jsxs(s.Fragment,{children:[Et,Ot,s.jsx(We,{selectedRows:V,actions:Ve??[],onAction:(c,M)=>De({type:c,params:{records:M}}),onClearSelection:()=>Q([])})]}),children:c=>kt(c)}):s.jsxs("div",{ref:xe,className:"relative h-full",children:[A>0&&s.jsx("div",{className:"flex items-center justify-center text-xs text-muted-foreground",style:{height:A},children:D(u?"grid.refreshing":"grid.pullToRefresh")}),Et,Ot,s.jsx(We,{selectedRows:V,actions:Ve??[],onAction:(c,M)=>De({type:c,params:{records:M}}),onClearSelection:()=>Q([])}),ne.isOverlay&&s.jsx(v.NavigationOverlay,{...ne,title:Ue,children:c=>kt(c)})]})};function Se(e,o,t){let r=t.initialDeps??[],n,i=!0;function a(){var l,p,h;let d;t.key&&((l=t.debug)!=null&&l.call(t))&&(d=Date.now());const m=e();if(!(m.length!==r.length||m.some((C,w)=>r[w]!==C)))return n;r=m;let b;if(t.key&&((p=t.debug)!=null&&p.call(t))&&(b=Date.now()),n=o(...m),t.key&&((h=t.debug)!=null&&h.call(t))){const C=Math.round((Date.now()-d)*100)/100,w=Math.round((Date.now()-b)*100)/100,T=w/16,D=(I,L)=>{for(I=String(I);I.length<L;)I=" "+I;return I};console.info(`%c⏱ ${D(w,5)} /${D(C,5)} ms`,`
|
|
7
9
|
font-size: .6rem;
|
|
8
10
|
font-weight: bold;
|
|
9
|
-
color: hsl(${Math.max(0,Math.min(120-120*C,120))}deg 100% 31%);`,e?.key)}return e?.onChange&&!(i&&e.skipInitialOnChange)&&e.onChange(s),i=!1,s}return o.updateDeps=l=>{n=l},o}function ke(t,c){if(t===void 0)throw new Error("Unexpected undefined");return t}const Ze=(t,c)=>Math.abs(t-c)<1.01,Qe=(t,c,e)=>{let n;return function(...s){t.clearTimeout(n),n=t.setTimeout(()=>c.apply(this,s),e)}},Te=t=>{const{offsetWidth:c,offsetHeight:e}=t;return{width:c,height:e}},et=t=>t,tt=t=>{const c=Math.max(t.startIndex-t.overscan,0),e=Math.min(t.endIndex+t.overscan,t.count-1),n=[];for(let s=c;s<=e;s++)n.push(s);return n},nt=(t,c)=>{const e=t.scrollElement;if(!e)return;const n=t.targetWindow;if(!n)return;const s=o=>{const{width:l,height:b}=o;c({width:Math.round(l),height:Math.round(b)})};if(s(Te(e)),!n.ResizeObserver)return()=>{};const i=new n.ResizeObserver(o=>{const l=()=>{const b=o[0];if(b?.borderBoxSize){const m=b.borderBoxSize[0];if(m){s({width:m.inlineSize,height:m.blockSize});return}}s(Te(e))};t.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(l):l()});return i.observe(e,{box:"border-box"}),()=>{i.unobserve(e)}},Ae={passive:!0},Me=typeof window>"u"?!0:"onscrollend"in window,st=(t,c)=>{const e=t.scrollElement;if(!e)return;const n=t.targetWindow;if(!n)return;let s=0;const i=t.options.useScrollendEvent&&Me?()=>{}:Qe(n,()=>{c(s,!1)},t.options.isScrollingResetDelay),o=f=>()=>{const{horizontal:y,isRtl:u}=t.options;s=y?e.scrollLeft*(u&&-1||1):e.scrollTop,i(),c(s,f)},l=o(!0),b=o(!1);e.addEventListener("scroll",l,Ae);const m=t.options.useScrollendEvent&&Me;return m&&e.addEventListener("scrollend",b,Ae),()=>{e.removeEventListener("scroll",l),m&&e.removeEventListener("scrollend",b)}},rt=(t,c,e)=>{if(c?.borderBoxSize){const n=c.borderBoxSize[0];if(n)return Math.round(n[e.options.horizontal?"inlineSize":"blockSize"])}return t[e.options.horizontal?"offsetWidth":"offsetHeight"]},it=(t,{adjustments:c=0,behavior:e},n)=>{var s,i;const o=t+c;(i=(s=n.scrollElement)==null?void 0:s.scrollTo)==null||i.call(s,{[n.options.horizontal?"left":"top"]:o,behavior:e})};class ot{constructor(c){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 n=()=>e||(!this.targetWindow||!this.targetWindow.ResizeObserver?null:e=new this.targetWindow.ResizeObserver(s=>{s.forEach(i=>{const o=()=>{this._measureElement(i.target,i)};this.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(o):o()})}));return{disconnect:()=>{var s;(s=n())==null||s.disconnect(),e=null},observe:s=>{var i;return(i=n())==null?void 0:i.observe(s,{box:"border-box"})},unobserve:s=>{var i;return(i=n())==null?void 0:i.unobserve(s)}}})(),this.range=null,this.setOptions=e=>{Object.entries(e).forEach(([n,s])=>{typeof s>"u"&&delete e[n]}),this.options={debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:et,rangeExtractor:tt,onChange:()=>{},measureElement:rt,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 n,s;(s=(n=this.options).onChange)==null||s.call(n,this,e)},this.maybeNotify=Q(()=>(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 n=this.options.enabled?this.options.getScrollElement():null;if(this.scrollElement!==n){if(this.cleanup(),!n){this.maybeNotify();return}this.scrollElement=n,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(s=>{this.observer.observe(s)}),this.unsubs.push(this.options.observeElementRect(this,s=>{this.scrollRect=s,this.maybeNotify()})),this.unsubs.push(this.options.observeElementOffset(this,(s,i)=>{this.scrollAdjustments=0,this.scrollDirection=i?this.getScrollOffset()<s?"forward":"backward":null,this.scrollOffset=s,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,n)=>{const s=new Map,i=new Map;for(let o=n-1;o>=0;o--){const l=e[o];if(s.has(l.lane))continue;const b=i.get(l.lane);if(b==null||l.end>b.end?i.set(l.lane,l):l.end<b.end&&s.set(l.lane,!0),s.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=Q(()=>[this.options.count,this.options.paddingStart,this.options.scrollMargin,this.options.getItemKey,this.options.enabled,this.options.lanes],(e,n,s,i,o,l)=>(this.prevLanes!==void 0&&this.prevLanes!==l&&(this.lanesChangedFlag=!0),this.prevLanes=l,this.pendingMeasuredCacheIndexes=[],{count:e,paddingStart:n,scrollMargin:s,getItemKey:i,enabled:o,lanes:l}),{key:!1}),this.getMeasurements=Q(()=>[this.getMeasurementOptions(),this.itemSizeCache],({count:e,paddingStart:n,scrollMargin:s,getItemKey:i,enabled:o,lanes:l},b)=>{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 m=this.lanesSettling?0:this.pendingMeasuredCacheIndexes.length>0?Math.min(...this.pendingMeasuredCacheIndexes):0;this.pendingMeasuredCacheIndexes=[],this.lanesSettling&&this.measurementsCache.length===e&&(this.lanesSettling=!1);const f=this.measurementsCache.slice(0,m),y=new Array(l).fill(void 0);for(let u=0;u<m;u++){const d=f[u];d&&(y[d.lane]=u)}for(let u=m;u<e;u++){const d=i(u),E=this.laneAssignments.get(u);let x,C;if(E!==void 0&&this.options.lanes>1){x=E;const R=y[x],K=R!==void 0?f[R]:void 0;C=K?K.end+this.options.gap:n+s}else{const R=this.options.lanes===1?f[u-1]:this.getFurthestMeasurement(f,u);C=R?R.end+this.options.gap:n+s,x=R?R.lane:u%this.options.lanes,this.options.lanes>1&&this.laneAssignments.set(u,x)}const A=b.get(d),T=typeof A=="number"?A:this.options.estimateSize(u),$=C+T;f[u]={index:u,start:C,size:T,end:$,key:d,lane:x},y[x]=u}return this.measurementsCache=f,f},{key:process.env.NODE_ENV!=="production"&&"getMeasurements",debug:()=>this.options.debug}),this.calculateRange=Q(()=>[this.getMeasurements(),this.getSize(),this.getScrollOffset(),this.options.lanes],(e,n,s,i)=>this.range=e.length>0&&n>0?lt({measurements:e,outerSize:n,scrollOffset:s,lanes:i}):null,{key:process.env.NODE_ENV!=="production"&&"calculateRange",debug:()=>this.options.debug}),this.getVirtualIndexes=Q(()=>{let e=null,n=null;const s=this.calculateRange();return s&&(e=s.startIndex,n=s.endIndex),this.maybeNotify.updateDeps([this.isScrolling,e,n]),[this.options.rangeExtractor,this.options.overscan,this.options.count,e,n]},(e,n,s,i,o)=>i===null||o===null?[]:e({startIndex:i,endIndex:o,overscan:n,count:s}),{key:process.env.NODE_ENV!=="production"&&"getVirtualIndexes",debug:()=>this.options.debug}),this.indexFromElement=e=>{const n=this.options.indexAttribute,s=e.getAttribute(n);return s?parseInt(s,10):(console.warn(`Missing attribute name '${n}={index}' on measured element.`),-1)},this._measureElement=(e,n)=>{const s=this.indexFromElement(e),i=this.measurementsCache[s];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(s,this.options.measureElement(e,n,this))},this.resizeItem=(e,n)=>{const s=this.measurementsCache[e];if(!s)return;const i=this.itemSizeCache.get(s.key)??s.size,o=n-i;o!==0&&((this.shouldAdjustScrollPositionOnItemSizeChange!==void 0?this.shouldAdjustScrollPositionOnItemSizeChange(s,o,this):s.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(s.index),this.itemSizeCache=new Map(this.itemSizeCache.set(s.key,n)),this.notify(!1))},this.measureElement=e=>{if(!e){this.elementsCache.forEach((n,s)=>{n.isConnected||(this.observer.unobserve(n),this.elementsCache.delete(s))});return}this._measureElement(e,void 0)},this.getVirtualItems=Q(()=>[this.getVirtualIndexes(),this.getMeasurements()],(e,n)=>{const s=[];for(let i=0,o=e.length;i<o;i++){const l=e[i],b=n[l];s.push(b)}return s},{key:process.env.NODE_ENV!=="production"&&"getVirtualItems",debug:()=>this.options.debug}),this.getVirtualItemForOffset=e=>{const n=this.getMeasurements();if(n.length!==0)return ke(n[ze(0,n.length-1,s=>ke(n[s]).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,n,s=0)=>{if(!this.scrollElement)return 0;const i=this.getSize(),o=this.getScrollOffset();n==="auto"&&(n=e>=o+i?"end":"start"),n==="center"?e+=(s-i)/2:n==="end"&&(e-=i);const l=this.getMaxScrollOffset();return Math.max(Math.min(l,e),0)},this.getOffsetForIndex=(e,n="auto")=>{e=Math.max(0,Math.min(e,this.options.count-1));const s=this.measurementsCache[e];if(!s)return;const i=this.getSize(),o=this.getScrollOffset();if(n==="auto")if(s.end>=o+i-this.options.scrollPaddingEnd)n="end";else if(s.start<=o+this.options.scrollPaddingStart)n="start";else return[o,n];if(n==="end"&&e===this.options.count-1)return[this.getMaxScrollOffset(),n];const l=n==="end"?s.end+this.options.scrollPaddingEnd:s.start-this.options.scrollPaddingStart;return[this.getOffsetForAlignment(l,n,s.size),n]},this.isDynamicMode=()=>this.elementsCache.size>0,this.scrollToOffset=(e,{align:n="start",behavior:s}={})=>{s==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getOffsetForAlignment(e,n),{adjustments:void 0,behavior:s})},this.scrollToIndex=(e,{align:n="auto",behavior:s}={})=>{s==="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=m=>{if(!this.targetWindow)return;const f=this.getOffsetForIndex(e,m);if(!f){console.warn("Failed to get offset for index:",e);return}const[y,u]=f;this._scrollToOffset(y,{adjustments:void 0,behavior:s}),this.targetWindow.requestAnimationFrame(()=>{const d=()=>{if(this.currentScrollToIndex!==e)return;const E=this.getScrollOffset(),x=this.getOffsetForIndex(e,u);if(!x){console.warn("Failed to get offset for index:",e);return}Ze(x[0],E)||b(u)};this.isDynamicMode()?this.targetWindow.requestAnimationFrame(d):d()})},b=m=>{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(m))):console.warn(`Failed to scroll to index ${e} after ${o} attempts.`))};l(n)},this.scrollBy=(e,{behavior:n}={})=>{n==="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:n})},this.getTotalSize=()=>{var e;const n=this.getMeasurements();let s;if(n.length===0)s=this.options.paddingStart;else if(this.options.lanes===1)s=((e=n[n.length-1])==null?void 0:e.end)??0;else{const i=Array(this.options.lanes).fill(null);let o=n.length-1;for(;o>=0&&i.some(l=>l===null);){const l=n[o];i[l.lane]===null&&(i[l.lane]=l.end),o--}s=Math.max(...i.filter(l=>l!==null))}return Math.max(s-this.options.scrollMargin+this.options.paddingEnd,0)},this._scrollToOffset=(e,{adjustments:n,behavior:s})=>{this.options.scrollToFn(e,{behavior:s,adjustments:n},this)},this.measure=()=>{this.itemSizeCache=new Map,this.laneAssignments=new Map,this.notify(!1)},this.setOptions(c)}}const ze=(t,c,e,n)=>{for(;t<=c;){const s=(t+c)/2|0,i=e(s);if(i<n)t=s+1;else if(i>n)c=s-1;else return s}return t>0?t-1:0};function lt({measurements:t,outerSize:c,scrollOffset:e,lanes:n}){const s=t.length-1,i=b=>t[b].start;if(t.length<=n)return{startIndex:0,endIndex:s};let o=ze(0,s,i,e),l=o;if(n===1)for(;l<s&&t[l].end<e+c;)l++;else if(n>1){const b=Array(n).fill(0);for(;l<s&&b.some(f=>f<e+c);){const f=t[l];b[f.lane]=f.end,l++}const m=Array(n).fill(e+c);for(;o>=0&&m.some(f=>f>=e);){const f=t[o];m[f.lane]=f.start,o--}o=Math.max(0,o-o%n),l=Math.min(s,l+(n-1-l%n))}return{startIndex:o,endIndex:l}}const Re=typeof document<"u"?me.useLayoutEffect:me.useEffect;function at({useFlushSync:t=!0,...c}){const e=me.useReducer(()=>({}),{})[1],n={...c,onChange:(i,o)=>{var l;t&&o?Le.flushSync(e):e(),(l=c.onChange)==null||l.call(c,i,o)}},[s]=me.useState(()=>new ot(n));return s.setOptions(n),Re(()=>s._didMount(),[]),Re(()=>s._willUpdate()),s}function ct(t){return at({observeElementRect:nt,observeElementOffset:st,scrollToFn:it,...t})}const ut=({data:t,columns:c,rowHeight:e=40,height:n=600,className:s="",headerClassName:i="",rowClassName:o,onRowClick:l,overscan:b=5})=>{const m=g.useRef(null),f=ct({count:t.length,getScrollElement:()=>m.current,estimateSize:()=>e,overscan:b}),y=f.getVirtualItems();return a.jsxs("div",{className:s,children:[a.jsx("div",{className:`grid border-b sticky top-0 bg-background z-10 ${i}`,style:{gridTemplateColumns:c.map(u=>u.width||"1fr").join(" ")},children:c.map((u,d)=>a.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},d))}),a.jsx("div",{ref:m,className:"overflow-auto",style:{height:typeof n=="number"?`${n}px`:n,contain:"strict"},children:a.jsx("div",{style:{height:`${f.getTotalSize()}px`,width:"100%",position:"relative"},children:y.map(u=>{const d=t[u.index],E=typeof o=="function"?o(d,u.index):o||"";return a.jsx("div",{className:`grid border-b hover:bg-muted/50 cursor-pointer ${E}`,style:{position:"absolute",top:0,left:0,width:"100%",height:`${u.size}px`,transform:`translateY(${u.start}px)`,gridTemplateColumns:c.map(x=>x.width||"1fr").join(" ")},onClick:()=>l?.(d,u.index),children:c.map((x,C)=>{const A=d[x.accessorKey],T=x.cell?x.cell(A,d):A;return a.jsx("div",{className:`px-4 py-2 text-sm flex items-center ${x.align==="center"?"text-center justify-center":x.align==="right"?"text-right justify-end":"text-left justify-start"}`,children:T},C)})},u.key)})})}),a.jsxs("div",{className:"px-4 py-2 text-xs text-muted-foreground border-t",children:["Showing ",y.length," of ",t.length," rows (virtual scrolling enabled)"]})]})};function dt({value:t,onSave:c,onCancel:e,validate:n,type:s="text",placeholder:i,editing:o=!1,className:l,disabled:b=!1}){const[m,f]=g.useState(o),[y,u]=g.useState(String(t??"")),[d,E]=g.useState(),[x,C]=g.useState(!1),A=g.useRef(null);g.useEffect(()=>{m||u(String(t??""))},[t,m]),g.useEffect(()=>{m&&A.current&&(A.current.focus(),A.current.select())},[m]);const T=g.useCallback(()=>{b||(f(!0),u(String(t??"")),E(void 0))},[b,t]),$=g.useCallback(()=>{f(!1),u(String(t??"")),E(void 0),e?.()},[t,e]),R=g.useCallback(async()=>{if(n){const W=n(y);if(W){E(W);return}}const M=s==="number"?Number(y):y;C(!0);try{const W=await c(M);if(typeof W=="string"){E(W),C(!1);return}f(!1),E(void 0)}catch(W){E(W?.message||"Save failed")}finally{C(!1)}},[y,n,s,c]),K=g.useCallback(M=>{M.key==="Enter"?(M.preventDefault(),R()):M.key==="Escape"&&(M.preventDefault(),$())},[R,$]);return m?a.jsxs("div",{"data-slot":"inline-editing",className:F.cn("relative flex items-center gap-1",l),children:[a.jsxs("div",{className:"flex-1 relative",children:[a.jsx("input",{ref:A,"data-slot":"inline-editing-input",type:s,value:y,onChange:M=>{u(M.target.value),d&&E(void 0)},onKeyDown:K,placeholder:i,disabled:x,"aria-invalid":!!d,"aria-describedby":d?"inline-editing-error":void 0,className:F.cn("w-full rounded border px-2 py-1 text-sm outline-none transition-colors","focus:ring-2 focus:ring-ring focus:border-input",d?"border-destructive focus:ring-destructive/30":"border-input",x&&"opacity-50")}),d&&a.jsx("p",{id:"inline-editing-error","data-slot":"inline-editing-error",className:"absolute left-0 top-full mt-0.5 text-xs text-destructive",role:"alert",children:d})]}),a.jsx("button",{"data-slot":"inline-editing-save",type:"button",onClick:R,disabled:x,"aria-label":"Save",className:F.cn("inline-flex h-6 w-6 items-center justify-center rounded text-primary hover:bg-primary/10 transition-colors",x&&"opacity-50 cursor-not-allowed"),children:a.jsx(J.Check,{className:"h-3.5 w-3.5"})}),a.jsx("button",{"data-slot":"inline-editing-cancel",type:"button",onClick:$,disabled:x,"aria-label":"Cancel",className:"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive transition-colors",children:a.jsx(J.X,{className:"h-3.5 w-3.5"})})]}):a.jsx("div",{"data-slot":"inline-editing",className:F.cn("group relative cursor-pointer rounded px-2 py-1 hover:bg-muted/50 transition-colors min-h-[1.75rem] flex items-center",b&&"cursor-default opacity-60",l),onClick:T,role:"button",tabIndex:b?-1:0,onKeyDown:M=>{(M.key==="Enter"||M.key===" ")&&(M.preventDefault(),T())},"aria-label":`Edit value: ${String(t??"")}`,children:a.jsx("span",{"data-slot":"inline-editing-display",className:"truncate text-sm",children:t!=null&&String(t)!==""?String(t):a.jsx("span",{className:"text-muted-foreground italic",children:i||"Click to edit"})})})}const ge=({schema:t,...c})=>{const{dataSource:e}=Z.useSchemaContext()||{};return a.jsx(_e,{schema:t,dataSource:e,...c})};ye.ComponentRegistry.register("object-grid",ge,{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"}]}),ye.ComponentRegistry.register("grid",ge,{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"}]}),k.InlineEditing=dt,k.ObjectGrid=_e,k.ObjectGridRenderer=ge,k.VirtualGrid=ut,k.useGroupedData=Oe,k.useRowColor=Ce,Object.defineProperty(k,Symbol.toStringTag,{value:"Module"})}));
|
|
11
|
+
color: hsl(${Math.max(0,Math.min(120-120*T,120))}deg 100% 31%);`,t?.key)}return t?.onChange&&!(i&&t.skipInitialOnChange)&&t.onChange(n),i=!1,n}return a.updateDeps=l=>{r=l},a}function it(e,o){if(e===void 0)throw new Error("Unexpected undefined");return e}const Ut=(e,o)=>Math.abs(e-o)<1.01,Yt=(e,o,t)=>{let r;return function(...n){e.clearTimeout(r),r=e.setTimeout(()=>o.apply(this,n),t)}},ot=e=>{const{offsetWidth:o,offsetHeight:t}=e;return{width:o,height:t}},Jt=e=>e,Xt=e=>{const o=Math.max(e.startIndex-e.overscan,0),t=Math.min(e.endIndex+e.overscan,e.count-1),r=[];for(let n=o;n<=t;n++)r.push(n);return r},Qt=(e,o)=>{const t=e.scrollElement;if(!t)return;const r=e.targetWindow;if(!r)return;const n=a=>{const{width:l,height:p}=a;o({width:Math.round(l),height:Math.round(p)})};if(n(ot(t)),!r.ResizeObserver)return()=>{};const i=new r.ResizeObserver(a=>{const l=()=>{const p=a[0];if(p?.borderBoxSize){const h=p.borderBoxSize[0];if(h){n({width:h.inlineSize,height:h.blockSize});return}}n(ot(t))};e.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(l):l()});return i.observe(t,{box:"border-box"}),()=>{i.unobserve(t)}},lt={passive:!0},at=typeof window>"u"?!0:"onscrollend"in window,Zt=(e,o)=>{const t=e.scrollElement;if(!t)return;const r=e.targetWindow;if(!r)return;let n=0;const i=e.options.useScrollendEvent&&at?()=>{}:Yt(r,()=>{o(n,!1)},e.options.isScrollingResetDelay),a=d=>()=>{const{horizontal:m,isRtl:g}=e.options;n=m?t.scrollLeft*(g&&-1||1):t.scrollTop,i(),o(n,d)},l=a(!0),p=a(!1);t.addEventListener("scroll",l,lt);const h=e.options.useScrollendEvent&&at;return h&&t.addEventListener("scrollend",p,lt),()=>{t.removeEventListener("scroll",l),h&&t.removeEventListener("scrollend",p)}},es=(e,o,t)=>{if(o?.borderBoxSize){const r=o.borderBoxSize[0];if(r)return Math.round(r[t.options.horizontal?"inlineSize":"blockSize"])}return e[t.options.horizontal?"offsetWidth":"offsetHeight"]},ts=(e,{adjustments:o=0,behavior:t},r)=>{var n,i;const a=e+o;(i=(n=r.scrollElement)==null?void 0:n.scrollTo)==null||i.call(n,{[r.options.horizontal?"left":"top"]:a,behavior:t})};class ss{constructor(o){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 t=null;const r=()=>t||(!this.targetWindow||!this.targetWindow.ResizeObserver?null:t=new this.targetWindow.ResizeObserver(n=>{n.forEach(i=>{const a=()=>{this._measureElement(i.target,i)};this.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(a):a()})}));return{disconnect:()=>{var n;(n=r())==null||n.disconnect(),t=null},observe:n=>{var i;return(i=r())==null?void 0:i.observe(n,{box:"border-box"})},unobserve:n=>{var i;return(i=r())==null?void 0:i.unobserve(n)}}})(),this.range=null,this.setOptions=t=>{Object.entries(t).forEach(([r,n])=>{typeof n>"u"&&delete t[r]}),this.options={debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:Jt,rangeExtractor:Xt,onChange:()=>{},measureElement:es,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,...t}},this.notify=t=>{var r,n;(n=(r=this.options).onChange)==null||n.call(r,this,t)},this.maybeNotify=Se(()=>(this.calculateRange(),[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]),t=>{this.notify(t)},{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(t=>t()),this.unsubs=[],this.observer.disconnect(),this.scrollElement=null,this.targetWindow=null},this._didMount=()=>()=>{this.cleanup()},this._willUpdate=()=>{var t;const r=this.options.enabled?this.options.getScrollElement():null;if(this.scrollElement!==r){if(this.cleanup(),!r){this.maybeNotify();return}this.scrollElement=r,this.scrollElement&&"ownerDocument"in this.scrollElement?this.targetWindow=this.scrollElement.ownerDocument.defaultView:this.targetWindow=((t=this.scrollElement)==null?void 0:t.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=(t,r)=>{const n=new Map,i=new Map;for(let a=r-1;a>=0;a--){const l=t[a];if(n.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&&n.set(l.lane,!0),n.size===this.options.lanes)break}return i.size===this.options.lanes?Array.from(i.values()).sort((a,l)=>a.end===l.end?a.index-l.index:a.end-l.end)[0]:void 0},this.getMeasurementOptions=Se(()=>[this.options.count,this.options.paddingStart,this.options.scrollMargin,this.options.getItemKey,this.options.enabled,this.options.lanes],(t,r,n,i,a,l)=>(this.prevLanes!==void 0&&this.prevLanes!==l&&(this.lanesChangedFlag=!0),this.prevLanes=l,this.pendingMeasuredCacheIndexes=[],{count:t,paddingStart:r,scrollMargin:n,getItemKey:i,enabled:a,lanes:l}),{key:!1}),this.getMeasurements=Se(()=>[this.getMeasurementOptions(),this.itemSizeCache],({count:t,paddingStart:r,scrollMargin:n,getItemKey:i,enabled:a,lanes:l},p)=>{if(!a)return this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),[];if(this.laneAssignments.size>t)for(const g of this.laneAssignments.keys())g>=t&&this.laneAssignments.delete(g);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(g=>{this.itemSizeCache.set(g.key,g.size)}));const h=this.lanesSettling?0:this.pendingMeasuredCacheIndexes.length>0?Math.min(...this.pendingMeasuredCacheIndexes):0;this.pendingMeasuredCacheIndexes=[],this.lanesSettling&&this.measurementsCache.length===t&&(this.lanesSettling=!1);const d=this.measurementsCache.slice(0,h),m=new Array(l).fill(void 0);for(let g=0;g<h;g++){const b=d[g];b&&(m[b.lane]=g)}for(let g=h;g<t;g++){const b=i(g),C=this.laneAssignments.get(g);let w,T;if(C!==void 0&&this.options.lanes>1){w=C;const Y=m[w],q=Y!==void 0?d[Y]:void 0;T=q?q.end+this.options.gap:r+n}else{const Y=this.options.lanes===1?d[g-1]:this.getFurthestMeasurement(d,g);T=Y?Y.end+this.options.gap:r+n,w=Y?Y.lane:g%this.options.lanes,this.options.lanes>1&&this.laneAssignments.set(g,w)}const D=p.get(b),I=typeof D=="number"?D:this.options.estimateSize(g),L=T+I;d[g]={index:g,start:T,size:I,end:L,key:b,lane:w},m[w]=g}return this.measurementsCache=d,d},{key:process.env.NODE_ENV!=="production"&&"getMeasurements",debug:()=>this.options.debug}),this.calculateRange=Se(()=>[this.getMeasurements(),this.getSize(),this.getScrollOffset(),this.options.lanes],(t,r,n,i)=>this.range=t.length>0&&r>0?rs({measurements:t,outerSize:r,scrollOffset:n,lanes:i}):null,{key:process.env.NODE_ENV!=="production"&&"calculateRange",debug:()=>this.options.debug}),this.getVirtualIndexes=Se(()=>{let t=null,r=null;const n=this.calculateRange();return n&&(t=n.startIndex,r=n.endIndex),this.maybeNotify.updateDeps([this.isScrolling,t,r]),[this.options.rangeExtractor,this.options.overscan,this.options.count,t,r]},(t,r,n,i,a)=>i===null||a===null?[]:t({startIndex:i,endIndex:a,overscan:r,count:n}),{key:process.env.NODE_ENV!=="production"&&"getVirtualIndexes",debug:()=>this.options.debug}),this.indexFromElement=t=>{const r=this.options.indexAttribute,n=t.getAttribute(r);return n?parseInt(n,10):(console.warn(`Missing attribute name '${r}={index}' on measured element.`),-1)},this._measureElement=(t,r)=>{const n=this.indexFromElement(t),i=this.measurementsCache[n];if(!i)return;const a=i.key,l=this.elementsCache.get(a);l!==t&&(l&&this.observer.unobserve(l),this.observer.observe(t),this.elementsCache.set(a,t)),t.isConnected&&this.resizeItem(n,this.options.measureElement(t,r,this))},this.resizeItem=(t,r)=>{const n=this.measurementsCache[t];if(!n)return;const i=this.itemSizeCache.get(n.key)??n.size,a=r-i;a!==0&&((this.shouldAdjustScrollPositionOnItemSizeChange!==void 0?this.shouldAdjustScrollPositionOnItemSizeChange(n,a,this):n.start<this.getScrollOffset()+this.scrollAdjustments)&&(process.env.NODE_ENV!=="production"&&this.options.debug&&console.info("correction",a),this._scrollToOffset(this.getScrollOffset(),{adjustments:this.scrollAdjustments+=a,behavior:void 0})),this.pendingMeasuredCacheIndexes.push(n.index),this.itemSizeCache=new Map(this.itemSizeCache.set(n.key,r)),this.notify(!1))},this.measureElement=t=>{if(!t){this.elementsCache.forEach((r,n)=>{r.isConnected||(this.observer.unobserve(r),this.elementsCache.delete(n))});return}this._measureElement(t,void 0)},this.getVirtualItems=Se(()=>[this.getVirtualIndexes(),this.getMeasurements()],(t,r)=>{const n=[];for(let i=0,a=t.length;i<a;i++){const l=t[i],p=r[l];n.push(p)}return n},{key:process.env.NODE_ENV!=="production"&&"getVirtualItems",debug:()=>this.options.debug}),this.getVirtualItemForOffset=t=>{const r=this.getMeasurements();if(r.length!==0)return it(r[ct(0,r.length-1,n=>it(r[n]).start,t)])},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 t=this.scrollElement.document.documentElement;return this.options.horizontal?t.scrollWidth-this.scrollElement.innerWidth:t.scrollHeight-this.scrollElement.innerHeight}},this.getOffsetForAlignment=(t,r,n=0)=>{if(!this.scrollElement)return 0;const i=this.getSize(),a=this.getScrollOffset();r==="auto"&&(r=t>=a+i?"end":"start"),r==="center"?t+=(n-i)/2:r==="end"&&(t-=i);const l=this.getMaxScrollOffset();return Math.max(Math.min(l,t),0)},this.getOffsetForIndex=(t,r="auto")=>{t=Math.max(0,Math.min(t,this.options.count-1));const n=this.measurementsCache[t];if(!n)return;const i=this.getSize(),a=this.getScrollOffset();if(r==="auto")if(n.end>=a+i-this.options.scrollPaddingEnd)r="end";else if(n.start<=a+this.options.scrollPaddingStart)r="start";else return[a,r];if(r==="end"&&t===this.options.count-1)return[this.getMaxScrollOffset(),r];const l=r==="end"?n.end+this.options.scrollPaddingEnd:n.start-this.options.scrollPaddingStart;return[this.getOffsetForAlignment(l,r,n.size),r]},this.isDynamicMode=()=>this.elementsCache.size>0,this.scrollToOffset=(t,{align:r="start",behavior:n}={})=>{n==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getOffsetForAlignment(t,r),{adjustments:void 0,behavior:n})},this.scrollToIndex=(t,{align:r="auto",behavior:n}={})=>{n==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),t=Math.max(0,Math.min(t,this.options.count-1)),this.currentScrollToIndex=t;let i=0;const a=10,l=h=>{if(!this.targetWindow)return;const d=this.getOffsetForIndex(t,h);if(!d){console.warn("Failed to get offset for index:",t);return}const[m,g]=d;this._scrollToOffset(m,{adjustments:void 0,behavior:n}),this.targetWindow.requestAnimationFrame(()=>{if(!this.targetWindow)return;const b=()=>{if(this.currentScrollToIndex!==t)return;const C=this.getScrollOffset(),w=this.getOffsetForIndex(t,g);if(!w){console.warn("Failed to get offset for index:",t);return}Ut(w[0],C)||p(g)};this.isDynamicMode()?this.targetWindow.requestAnimationFrame(b):b()})},p=h=>{this.targetWindow&&this.currentScrollToIndex===t&&(i++,i<a?(process.env.NODE_ENV!=="production"&&this.options.debug&&console.info("Schedule retry",i,a),this.targetWindow.requestAnimationFrame(()=>l(h))):console.warn(`Failed to scroll to index ${t} after ${a} attempts.`))};l(r)},this.scrollBy=(t,{behavior:r}={})=>{r==="smooth"&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getScrollOffset()+t,{adjustments:void 0,behavior:r})},this.getTotalSize=()=>{var t;const r=this.getMeasurements();let n;if(r.length===0)n=this.options.paddingStart;else if(this.options.lanes===1)n=((t=r[r.length-1])==null?void 0:t.end)??0;else{const i=Array(this.options.lanes).fill(null);let a=r.length-1;for(;a>=0&&i.some(l=>l===null);){const l=r[a];i[l.lane]===null&&(i[l.lane]=l.end),a--}n=Math.max(...i.filter(l=>l!==null))}return Math.max(n-this.options.scrollMargin+this.options.paddingEnd,0)},this._scrollToOffset=(t,{adjustments:r,behavior:n})=>{this.options.scrollToFn(t,{behavior:n,adjustments:r},this)},this.measure=()=>{this.itemSizeCache=new Map,this.laneAssignments=new Map,this.notify(!1)},this.setOptions(o)}}const ct=(e,o,t,r)=>{for(;e<=o;){const n=(e+o)/2|0,i=t(n);if(i<r)e=n+1;else if(i>r)o=n-1;else return n}return e>0?e-1:0};function rs({measurements:e,outerSize:o,scrollOffset:t,lanes:r}){const n=e.length-1,i=p=>e[p].start;if(e.length<=r)return{startIndex:0,endIndex:n};let a=ct(0,n,i,t),l=a;if(r===1)for(;l<n&&e[l].end<t+o;)l++;else if(r>1){const p=Array(r).fill(0);for(;l<n&&p.some(d=>d<t+o);){const d=e[l];p[d.lane]=d.end,l++}const h=Array(r).fill(t+o);for(;a>=0&&h.some(d=>d>=t);){const d=e[a];h[d.lane]=d.start,a--}a=Math.max(0,a-a%r),l=Math.min(n,l+(r-1-l%r))}return{startIndex:a,endIndex:l}}const dt=typeof document<"u"?ze.useLayoutEffect:ze.useEffect;function ns({useFlushSync:e=!0,...o}){const t=ze.useReducer(()=>({}),{})[1],r={...o,onChange:(i,a)=>{var l;e&&a?_t.flushSync(t):t(),(l=o.onChange)==null||l.call(o,i,a)}},[n]=ze.useState(()=>new ss(r));return n.setOptions(r),dt(()=>n._didMount(),[]),dt(()=>n._willUpdate()),n}function is(e){return ns({observeElementRect:Qt,observeElementOffset:Zt,scrollToFn:ts,...e})}const os=({data:e,columns:o,rowHeight:t=40,height:r=600,className:n="",headerClassName:i="",rowClassName:a,onRowClick:l,overscan:p=5})=>{const h=f.useRef(null),d=is({count:e.length,getScrollElement:()=>h.current,estimateSize:()=>t,overscan:p}),m=d.getVirtualItems();return s.jsxs("div",{className:n,children:[s.jsx("div",{className:`grid border-b sticky top-0 bg-muted/30 z-10 ${i}`,style:{gridTemplateColumns:o.map(g=>g.width||"1fr").join(" ")},children:o.map((g,b)=>s.jsx("div",{className:`px-4 py-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/70 ${g.align==="center"?"text-center":g.align==="right"?"text-right":"text-left"}`,children:g.header},b))}),s.jsx("div",{ref:h,className:"overflow-auto",style:{height:typeof r=="number"?`${r}px`:r,contain:"strict"},children:s.jsx("div",{style:{height:`${d.getTotalSize()}px`,width:"100%",position:"relative"},children:m.map(g=>{const b=e[g.index],C=typeof a=="function"?a(b,g.index):a||"";return s.jsx("div",{className:`grid border-b hover:bg-muted/50 cursor-pointer ${C}`,style:{position:"absolute",top:0,left:0,width:"100%",height:`${g.size}px`,transform:`translateY(${g.start}px)`,gridTemplateColumns:o.map(w=>w.width||"1fr").join(" ")},onClick:()=>l?.(b,g.index),children:o.map((w,T)=>{const D=b[w.accessorKey],I=w.cell?w.cell(D,b):D;return s.jsx("div",{className:`px-4 py-2 text-sm flex items-center ${w.align==="center"?"text-center justify-center":w.align==="right"?"text-right justify-end":"text-left justify-start"}`,children:I},T)})},g.key)})})}),s.jsxs("div",{className:"px-4 py-2 text-xs text-muted-foreground border-t",children:["Showing ",m.length," of ",e.length," rows (virtual scrolling enabled)"]})]})},ls=10;function as(e){const o=[];let t=[],r="",n=!1;for(let i=0;i<e.length;i++){const a=e[i],l=e[i+1];n?a==='"'&&l==='"'?(r+='"',i++):a==='"'?n=!1:r+=a:a==='"'?n=!0:a===","?(t.push(r.trim()),r=""):a===`
|
|
12
|
+
`||a==="\r"&&l===`
|
|
13
|
+
`?(t.push(r.trim()),t.some(p=>p!=="")&&o.push(t),t=[],r="",a==="\r"&&i++):r+=a}return t.push(r.trim()),t.some(i=>i!=="")&&o.push(t),o}function ut(e,o){if(!e)return!0;switch(o){case"number":case"currency":case"percent":return!isNaN(Number(e));case"boolean":return["true","false","1","0","yes","no"].includes(e.toLowerCase());case"date":case"datetime":return!isNaN(Date.parse(e));default:return!0}}function cs(e,o){const t={};return e.forEach((r,n)=>{const i=r.toLowerCase().replace(/[_\s-]/g,""),a=o.find(l=>{const p=l.name.toLowerCase().replace(/[_\s-]/g,""),h=l.label.toLowerCase().replace(/[_\s-]/g,"");return p===i||h===i});a&&(t[n]=a.name)}),t}function ds(e,o,t){const r=[],n={};for(const i of o){const a=e[i.csvIdx]??"";if(i.field.required&&!a){r.push({row:t,field:i.field.name,message:"Required field is empty"});continue}if(a&&!ut(a,i.field.type)){r.push({row:t,field:i.field.name,message:`Invalid ${i.field.type} value: "${a}"`});continue}n[i.field.name]=a}return{record:n,errors:r}}const us=({onFileLoaded:e})=>{const[o,t]=f.useState(!1),[r,n]=f.useState(null),i=f.useCallback(a=>{if(n(null),!a.name.endsWith(".csv")){n("Only CSV files are supported.");return}const l=new FileReader;l.onload=p=>{const h=as(p.target?.result);if(h.length<2){n("File must contain a header row and at least one data row.");return}e(h[0],h.slice(1))},l.readAsText(a)},[e]);return s.jsxs("div",{className:"flex flex-col items-center gap-4 py-6",children:[s.jsxs("div",{className:v.cn("flex w-full flex-col items-center justify-center gap-3 rounded-lg border-2 border-dashed p-10 transition-colors",o?"border-primary bg-primary/5":"border-muted-foreground/25"),onDragOver:a=>{a.preventDefault(),t(!0)},onDragLeave:()=>t(!1),onDrop:a=>{a.preventDefault(),t(!1);const l=a.dataTransfer.files[0];l&&i(l)},children:[s.jsx(F.Upload,{className:"h-10 w-10 text-muted-foreground"}),s.jsx("p",{className:"text-sm text-muted-foreground",children:"Drag & drop a CSV file here, or click to browse"}),s.jsxs("label",{children:[s.jsx("input",{type:"file",accept:".csv",className:"hidden",onChange:a=>{const l=a.target.files?.[0];l&&i(l)}}),s.jsx(v.Button,{variant:"outline",size:"sm",asChild:!0,children:s.jsx("span",{children:"Browse Files"})})]})]}),r&&s.jsxs("p",{className:"flex items-center gap-1 text-sm text-destructive",children:[s.jsx(F.AlertCircle,{className:"h-4 w-4"})," ",r]})]})},fs=({headers:e,fields:o,mapping:t,onMappingChange:r})=>{const n=f.useMemo(()=>new Set(Object.values(t)),[t]),i=f.useCallback((a,l)=>{const p={...t};l==="__skip__"?delete p[a]:p[a]=l,r(p)},[t,r]);return s.jsx("div",{className:"max-h-[360px] overflow-auto",children:s.jsxs(v.Table,{children:[s.jsx(v.TableHeader,{children:s.jsxs(v.TableRow,{children:[s.jsx(v.TableHead,{children:"CSV Column"}),s.jsx(v.TableHead,{children:"Maps To"}),s.jsx(v.TableHead,{className:"w-24 text-center",children:"Status"})]})}),s.jsx(v.TableBody,{children:e.map((a,l)=>s.jsxs(v.TableRow,{children:[s.jsx(v.TableCell,{className:"font-medium",children:a}),s.jsx(v.TableCell,{children:s.jsxs(v.Select,{value:t[l]??"__skip__",onValueChange:p=>i(l,p),children:[s.jsx(v.SelectTrigger,{className:"h-8 w-56",children:s.jsx(v.SelectValue,{placeholder:"Skip column"})}),s.jsxs(v.SelectContent,{children:[s.jsx(v.SelectItem,{value:"__skip__",children:"— Skip —"}),o.map(p=>s.jsxs(v.SelectItem,{value:p.name,disabled:n.has(p.name)&&t[l]!==p.name,children:[p.label,p.required?" *":""]},p.name))]})]})}),s.jsx(v.TableCell,{className:"text-center",children:t[l]?s.jsx(v.Badge,{variant:"default",className:"text-xs",children:"Mapped"}):s.jsx(v.Badge,{variant:"secondary",className:"text-xs",children:"Skipped"})})]},l))})]})})},hs=({headers:e,rows:o,mapping:t,fields:r})=>{const n=f.useMemo(()=>Object.entries(t).map(([p,h])=>({csvIdx:Number(p),header:e[Number(p)],field:r.find(d=>d.name===h)})),[t,e,r]),i=o.slice(0,ls),a=f.useMemo(()=>i.map((p,h)=>{const d={};for(const m of n){const g=p[m.csvIdx]??"";m.field.required&&!g?d[m.csvIdx]="Required":g&&!ut(g,m.field.type)&&(d[m.csvIdx]=`Invalid ${m.field.type}`)}return d}),[i,n]),l=a.filter(p=>Object.keys(p).length>0).length;return s.jsxs("div",{className:"max-h-[360px] overflow-auto",children:[l>0&&s.jsxs("p",{className:"mb-2 flex items-center gap-1 text-xs text-destructive",children:[s.jsx(F.AlertCircle,{className:"h-3.5 w-3.5"})," ",l," row(s) with errors in preview"]}),s.jsxs(v.Table,{children:[s.jsx(v.TableHeader,{children:s.jsxs(v.TableRow,{children:[s.jsx(v.TableHead,{className:"w-12",children:"#"}),n.map(p=>s.jsx(v.TableHead,{children:p.field.label},p.csvIdx))]})}),s.jsx(v.TableBody,{children:i.map((p,h)=>{const d=a[h],m=Object.keys(d).length>0;return s.jsxs(v.TableRow,{className:v.cn(m&&"bg-destructive/5"),children:[s.jsx(v.TableCell,{className:"text-xs text-muted-foreground",children:h+1}),n.map(g=>{const b=p[g.csvIdx]??"",C=d[g.csvIdx];return s.jsx(v.TableCell,{className:v.cn(C&&"text-destructive"),title:C,children:b||s.jsx("span",{className:"text-muted-foreground/50",children:"—"})},g.csvIdx)})]},h)})})]}),s.jsxs("p",{className:"mt-2 text-xs text-muted-foreground",children:["Showing ",i.length," of ",o.length," rows"]})]})},ft=({objectName:e,objectLabel:o,fields:t,dataSource:r,onComplete:n,onCancel:i,open:a,onOpenChange:l,onErrorMode:p="skip"})=>{const[h,d]=f.useState("upload"),[m,g]=f.useState([]),[b,C]=f.useState([]),[w,T]=f.useState({}),[D,I]=f.useState(!1),[L,Y]=f.useState(0),[q,J]=f.useState(null),le=o??e,Me=f.useMemo(()=>{const V=new Set(Object.values(w));return t.filter(Q=>Q.required&&!V.has(Q.name))},[t,w]),ve=f.useCallback((V,Q)=>{g(V),C(Q),T(cs(V,t)),d("mapping")},[t]),Ee=f.useCallback(async()=>{I(!0),Y(0);const V=[];let Q=0,he=0;const ae=Object.entries(w).map(([re,be])=>({csvIdx:Number(re),field:t.find(xe=>xe.name===be)}));for(let re=0;re<b.length;re++){const{record:be,errors:xe}=ds(b[re],ae,re+1);if(xe.length>0){if(he++,V.push(...xe),p==="stop")break}else try{r?.create&&await r.create(e,be),Q++}catch(u){he++;const A=u instanceof Error?u.message:"Failed to create record";if(V.push({row:re+1,field:"",message:A}),p==="stop")break}Y(Math.round((re+1)/b.length*100))}const je={totalRows:b.length,importedRows:Q,skippedRows:he,errors:V};J(je),I(!1),n?.(je)},[b,w,t,r,e,n,p]),de=f.useCallback(()=>{d("upload"),g([]),C([]),T({}),Y(0),J(null)},[]),ge=f.useCallback(()=>{de(),l?.(!1),i?.()},[de,l,i]);return s.jsx(v.Dialog,{open:a,onOpenChange:V=>{V?l?.(V):ge()},children:s.jsxs(v.DialogContent,{className:"sm:max-w-2xl",children:[s.jsxs(v.DialogHeader,{children:[s.jsxs(v.DialogTitle,{className:"flex items-center gap-2",children:[s.jsx(F.FileSpreadsheet,{className:"h-5 w-5"})," Import ",le]}),s.jsxs(v.DialogDescription,{children:[h==="upload"&&"Upload a CSV file to get started.",h==="mapping"&&"Map CSV columns to object fields.",h==="preview"&&"Review data before importing."]})]}),s.jsx("div",{className:"flex items-center justify-center gap-2 text-xs text-muted-foreground",children:["upload","mapping","preview"].map((V,Q)=>s.jsxs(f.Fragment,{children:[Q>0&&s.jsx(F.ArrowRight,{className:"h-3 w-3"}),s.jsxs("span",{className:v.cn("rounded-full px-3 py-1",h===V?"bg-primary text-primary-foreground":"bg-muted"),children:[Q+1,". ",V==="upload"?"Upload":V==="mapping"?"Mapping":"Preview"]})]},V))}),q?s.jsxs("div",{className:"flex flex-col items-center gap-3 py-4",children:[s.jsx(F.CheckCircle2,{className:"h-10 w-10 text-green-500"}),s.jsx("p",{className:"text-lg font-semibold",children:"Import Complete"}),s.jsxs("div",{className:"flex gap-3",children:[s.jsxs(v.Badge,{variant:"default",children:[q.importedRows," imported"]}),q.skippedRows>0&&s.jsxs(v.Badge,{variant:"destructive",children:[q.skippedRows," skipped"]})]}),q.errors.length>0&&s.jsxs("div",{className:"max-h-32 w-full overflow-auto rounded border p-2 text-xs",children:[q.errors.slice(0,10).map((V,Q)=>s.jsxs("p",{className:"text-destructive",children:["Row ",V.row,V.field?` (${V.field})`:"",": ",V.message]},Q)),q.errors.length>10&&s.jsxs("p",{className:"text-muted-foreground",children:["…and ",q.errors.length-10," more errors"]})]})]}):s.jsxs(s.Fragment,{children:[h==="upload"&&s.jsx(us,{onFileLoaded:ve}),h==="mapping"&&s.jsx(fs,{headers:m,fields:t,mapping:w,onMappingChange:T}),h==="preview"&&s.jsx(hs,{headers:m,rows:b,mapping:w,fields:t}),D&&s.jsxs("div",{className:"flex flex-col gap-1",children:[s.jsx(v.Progress,{value:L,className:"h-2"}),s.jsxs("p",{className:"text-center text-xs text-muted-foreground",children:["Importing… ",L,"%"]})]})]}),s.jsx(v.DialogFooter,{className:"gap-2 sm:gap-0",children:q?s.jsx(v.Button,{onClick:ge,children:"Close"}):s.jsxs(s.Fragment,{children:[s.jsxs(v.Button,{variant:"ghost",onClick:ge,disabled:D,children:[s.jsx(F.X,{className:"mr-1 h-4 w-4"})," Cancel"]}),(h==="mapping"||h==="preview")&&s.jsxs(v.Button,{variant:"outline",onClick:()=>d(h==="mapping"?"upload":"mapping"),disabled:D,children:[s.jsx(F.ArrowLeft,{className:"mr-1 h-4 w-4"})," Back"]}),h==="mapping"&&s.jsxs(v.Button,{onClick:()=>d("preview"),disabled:Object.keys(w).length===0||Me.length>0,children:["Next ",s.jsx(F.ArrowRight,{className:"ml-1 h-4 w-4"})]}),h==="preview"&&s.jsx(v.Button,{onClick:Ee,disabled:D,children:D?"Importing…":`Import ${b.length} Rows`})]})})]})})};function ms({value:e,onSave:o,onCancel:t,validate:r,type:n="text",placeholder:i,editing:a=!1,className:l,disabled:p=!1}){const[h,d]=f.useState(a),[m,g]=f.useState(String(e??"")),[b,C]=f.useState(),[w,T]=f.useState(!1),D=f.useRef(null);f.useEffect(()=>{h||g(String(e??""))},[e,h]),f.useEffect(()=>{h&&D.current&&(D.current.focus(),D.current.select())},[h]);const I=f.useCallback(()=>{p||(d(!0),g(String(e??"")),C(void 0))},[p,e]),L=f.useCallback(()=>{d(!1),g(String(e??"")),C(void 0),t?.()},[e,t]),Y=f.useCallback(async()=>{if(r){const le=r(m);if(le){C(le);return}}const J=n==="number"?Number(m):m;T(!0);try{const le=await o(J);if(typeof le=="string"){C(le),T(!1);return}d(!1),C(void 0)}catch(le){C(le?.message||"Save failed")}finally{T(!1)}},[m,r,n,o]),q=f.useCallback(J=>{J.key==="Enter"?(J.preventDefault(),Y()):J.key==="Escape"&&(J.preventDefault(),L())},[Y,L]);return h?s.jsxs("div",{"data-slot":"inline-editing",className:v.cn("relative flex items-center gap-1",l),children:[s.jsxs("div",{className:"flex-1 relative",children:[s.jsx("input",{ref:D,"data-slot":"inline-editing-input",type:n,value:m,onChange:J=>{g(J.target.value),b&&C(void 0)},onKeyDown:q,placeholder:i,disabled:w,"aria-invalid":!!b,"aria-describedby":b?"inline-editing-error":void 0,className:v.cn("w-full rounded border px-2 py-1 text-sm outline-none transition-colors","focus:ring-2 focus:ring-ring focus:border-input",b?"border-destructive focus:ring-destructive/30":"border-input",w&&"opacity-50")}),b&&s.jsx("p",{id:"inline-editing-error","data-slot":"inline-editing-error",className:"absolute left-0 top-full mt-0.5 text-xs text-destructive",role:"alert",children:b})]}),s.jsx("button",{"data-slot":"inline-editing-save",type:"button",onClick:Y,disabled:w,"aria-label":"Save",className:v.cn("inline-flex h-6 w-6 items-center justify-center rounded text-primary hover:bg-primary/10 transition-colors",w&&"opacity-50 cursor-not-allowed"),children:s.jsx(F.Check,{className:"h-3.5 w-3.5"})}),s.jsx("button",{"data-slot":"inline-editing-cancel",type:"button",onClick:L,disabled:w,"aria-label":"Cancel",className:"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive transition-colors",children:s.jsx(F.X,{className:"h-3.5 w-3.5"})})]}):s.jsx("div",{"data-slot":"inline-editing",className:v.cn("group relative cursor-pointer rounded px-2 py-1 hover:bg-muted/50 transition-colors min-h-[1.75rem] flex items-center",p&&"cursor-default opacity-60",l),onClick:I,role:"button",tabIndex:p?-1:0,onKeyDown:J=>{(J.key==="Enter"||J.key===" ")&&(J.preventDefault(),I())},"aria-label":`Edit value: ${String(e??"")}`,children:s.jsx("span",{"data-slot":"inline-editing-display",className:"truncate text-sm",children:e!=null&&String(e)!==""?String(e):s.jsx("span",{className:"text-muted-foreground italic",children:i||"Click to edit"})})})}function ht(e){return{startRow:Math.min(e.startRow,e.endRow),startCol:Math.min(e.startCol,e.endCol),endRow:Math.max(e.startRow,e.endRow),endCol:Math.max(e.startCol,e.endCol)}}function ps({data:e,columns:o,onPaste:t,enabled:r=!0}){const[n,i]=f.useState(null),a=f.useCallback(()=>{if(!r||!n)return;const{startRow:h,startCol:d,endRow:m,endCol:g}=ht(n),b=[];for(let w=h;w<=m;w++){const T=e[w];if(!T)continue;const D=[];for(let I=d;I<=g;I++){const L=o[I];D.push(L?String(T[L]??""):"")}b.push(D.join(" "))}const C=b.join(`
|
|
14
|
+
`);navigator.clipboard.writeText(C)},[r,n,e,o]),l=f.useCallback(()=>{if(!r||!n||!t)return;const{startRow:h,startCol:d}=ht(n);navigator.clipboard.readText().then(m=>{const g=[],b=m.split(`
|
|
15
|
+
`);for(let C=0;C<b.length;C++){const w=b[C].split(" ");for(let T=0;T<w.length;T++){const D=h+C,I=d+T,L=o[I];L&&D<e.length&&g.push({rowIndex:D,field:L,value:w[T]})}}g.length>0&&t(g)})},[r,n,o,e.length,t]),p=f.useCallback(h=>{if(!r)return;const d=h.metaKey||h.ctrlKey;d&&h.key==="c"?(h.preventDefault(),a()):d&&h.key==="v"&&(h.preventDefault(),l())},[r,a,l]);return f.useEffect(()=>{r||i(null)},[r]),{selectedRange:n,setSelectedRange:i,onCopy:a,onPaste:l,onKeyDown:p}}const gs=[{position:0,className:"bg-green-100"},{position:.5,className:"bg-yellow-100"},{position:1,className:"bg-red-100"}];function xs(e,o){let t=1/0,r=-1/0;for(const n of e){const i=Number(n[o]);Number.isFinite(i)&&(i<t&&(t=i),i>r&&(r=i))}return Number.isFinite(t)?[t,r]:[0,0]}function bs(e,o){if(o.length===0)return"";if(o.length===1)return o[0].className;let t=o[0],r=Math.abs(e-t.position);for(let n=1;n<o.length;n++){const i=Math.abs(e-o[n].position);i<r&&(t=o[n],r=i)}return t.className}function ys(e){const{field:o,data:t,min:r,max:n,stops:i=gs}=e,[a,l]=f.useMemo(()=>xs(t,o),[t,o]),p=r??a,h=n??l;return f.useCallback(d=>{const m=Number(d[o]);if(!Number.isFinite(m))return;if(h===p)return i.length>0?i[0].className:void 0;const g=Math.max(0,Math.min(1,(m-p)/(h-p)));return bs(g,i)},[o,p,h,i])}const mt="text/x-group-key";function vs({groupKeys:e}){const[o,t]=f.useState(e),[r,n]=f.useState(null);f.useEffect(()=>{t(d=>{const m=new Set(d),g=new Set(e);if(d.length===e.length&&d.every((w,T)=>w===e[T]))return d;const b=d.filter(w=>g.has(w)),C=e.filter(w=>!m.has(w));return[...b,...C]})},[e]);const i=f.useCallback((d,m)=>{t(g=>{if(d<0||d>=g.length||m<0||m>=g.length||d===m)return g;const b=[...g],[C]=b.splice(d,1);return b.splice(m,0,C),b})},[]),a=f.useCallback((d,m)=>{d.dataTransfer.effectAllowed="move",d.dataTransfer.setData(mt,m),n(m)},[]),l=f.useCallback(d=>{d.preventDefault(),d.dataTransfer.dropEffect="move"},[]),p=f.useCallback((d,m)=>{d.preventDefault();const g=d.dataTransfer.getData(mt);!g||g===m||t(b=>{const C=b.indexOf(g),w=b.indexOf(m);if(C===-1||w===-1)return b;const T=[...b],[D]=T.splice(C,1);return T.splice(w,0,D),T})},[]),h=f.useCallback(()=>{n(null)},[]);return{groupOrder:o,moveGroup:i,onDragStart:a,onDragOver:l,onDrop:p,onDragEnd:h,draggingKey:r}}function js({value:e,onChange:o,onConfirm:t,onCancel:r,activeCell:n,disabled:i=!1,className:a}){const[l,p]=f.useState(!1),[h,d]=f.useState(e),m=f.useRef(null);f.useEffect(()=>{l||d(e)},[e,l]),f.useEffect(()=>{l&&m.current&&(m.current.focus(),m.current.select())},[l]);const g=f.useCallback(()=>{i||(p(!0),d(e))},[i,e]),b=f.useCallback(()=>{p(!1),o?.(h),t?.(h)},[h,o,t]),C=f.useCallback(()=>{p(!1),d(e),r?.()},[e,r]),w=f.useCallback(T=>{T.key==="Enter"?(T.preventDefault(),b()):T.key==="Escape"&&(T.preventDefault(),C())},[b,C]);return s.jsxs("div",{className:v.cn("flex items-center gap-2 border-b border-border bg-muted/30 px-3 py-1.5",a),children:[s.jsx(F.FunctionSquare,{className:"h-4 w-4 shrink-0 text-muted-foreground"}),n&&s.jsx("span",{className:"min-w-[4rem] shrink-0 rounded bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground",children:n}),s.jsx("input",{ref:m,type:"text",value:l?h:e,readOnly:!l,disabled:i,onClick:g,onChange:T=>d(T.target.value),onKeyDown:w,className:v.cn("flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground",l&&"rounded ring-1 ring-ring px-1",i&&"cursor-not-allowed opacity-50")}),l&&s.jsxs("div",{className:"flex items-center gap-1",children:[s.jsx("button",{type:"button",onClick:b,className:"rounded p-0.5 text-green-600 hover:bg-green-100","aria-label":"Confirm",children:s.jsx(F.Check,{className:"h-4 w-4"})}),s.jsx("button",{type:"button",onClick:C,className:"rounded p-0.5 text-red-600 hover:bg-red-100","aria-label":"Cancel",children:s.jsx(F.X,{className:"h-4 w-4"})})]})]})}function ws({frozenWidth:e,onResize:o,minFrozenWidth:t=100,minScrollableWidth:r=200,left:n,right:i,className:a}){const l=f.useRef(null),[p,h]=f.useState(e),d=f.useRef(!1),m=f.useRef(0),g=f.useRef(0),b=o?e:p,C=f.useCallback(w=>{w.preventDefault(),d.current=!0,m.current=w.clientX,g.current=b;const T=I=>{if(!d.current||!l.current)return;const L=l.current.offsetWidth,Y=I.clientX-m.current;let q=g.current+Y;q=Math.max(q,t),q=Math.min(q,L-r),o?o(q):h(q)},D=()=>{d.current=!1,document.removeEventListener("pointermove",T),document.removeEventListener("pointerup",D)};document.addEventListener("pointermove",T),document.addEventListener("pointerup",D)},[b,t,r,o]);return s.jsxs("div",{ref:l,className:v.cn("flex h-full w-full overflow-hidden",a),children:[s.jsx("div",{className:"shrink-0 overflow-auto",style:{width:b},children:n}),s.jsx("div",{role:"separator","aria-orientation":"vertical",onPointerDown:C,className:v.cn("flex w-2 cursor-col-resize items-center justify-center","border-x border-border bg-muted/50 hover:bg-muted","transition-colors"),children:s.jsx(F.GripVertical,{className:"h-4 w-4 text-muted-foreground"})}),s.jsx("div",{className:"min-w-0 flex-1 overflow-auto",children:i})]})}const Ge=({schema:e,...o})=>{const{dataSource:t}=pe.useSchemaContext()||{};return s.jsx(nt,{schema:e,dataSource:t,...o})};_e.ComponentRegistry.register("object-grid",Ge,{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"}]}),_e.ComponentRegistry.register("grid",Ge,{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"}]});const Cs=({schema:e,...o})=>{const{dataSource:t}=pe.useSchemaContext()||{};return s.jsx(ft,{objectName:e.objectName,objectLabel:e.objectLabel,fields:e.fields??[],dataSource:t,...o})};_e.ComponentRegistry.register("import-wizard",Cs,{namespace:"plugin-grid",label:"Import Wizard",category:"plugin",inputs:[{name:"objectName",type:"string",label:"Object Name",required:!0},{name:"fields",type:"array",label:"Fields",required:!0}]}),P.BulkActionBar=We,P.FormulaBar=js,P.GroupRow=et,P.ImportWizard=ft,P.InlineEditing=ms,P.ObjectGrid=nt,P.ObjectGridRenderer=Ge,P.RowActionMenu=st,P.SplitPaneGrid=ws,P.VirtualGrid=os,P.formatActionLabel=Pe,P.useCellClipboard=ps,P.useColumnSummary=tt,P.useGradientColor=ys,P.useGroupReorder=vs,P.useGroupedData=Ze,P.useRowColor=Qe,Object.defineProperty(P,Symbol.toStringTag,{value:"Module"})}));
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
export interface FormulaBarProps {
|
|
9
|
+
/** Current cell value displayed in the bar. */
|
|
10
|
+
value: string;
|
|
11
|
+
/** Called when the user edits the value (controlled input). */
|
|
12
|
+
onChange?: (value: string) => void;
|
|
13
|
+
/** Called when the user confirms the edit (Enter or check button). */
|
|
14
|
+
onConfirm?: (value: string) => void;
|
|
15
|
+
/** Called when the user cancels the edit (Escape or X button). */
|
|
16
|
+
onCancel?: () => void;
|
|
17
|
+
/** Label describing the active cell, e.g. "A1" or "name". */
|
|
18
|
+
activeCell?: string;
|
|
19
|
+
/** Whether editing is disabled. */
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
/** Additional class names. */
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Excel-like formula bar that displays and allows editing of the active cell's
|
|
26
|
+
* value. Press Enter (or the ✓ button) to confirm, Escape (or the ✗ button)
|
|
27
|
+
* to cancel.
|
|
28
|
+
*/
|
|
29
|
+
export declare function FormulaBar({ value, onChange, onConfirm, onCancel, activeCell, disabled, className, }: FormulaBarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { AggregationResult } from './useGroupedData';
|
|
3
|
+
export interface GroupRowProps {
|
|
4
|
+
/** Unique key identifying this group */
|
|
5
|
+
groupKey: string;
|
|
6
|
+
/** Display label for the group (field value or "(empty)") */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Number of rows in this group */
|
|
9
|
+
count: number;
|
|
10
|
+
/** Whether the group is collapsed */
|
|
11
|
+
collapsed: boolean;
|
|
12
|
+
/** Computed aggregation results for this group */
|
|
13
|
+
aggregations?: AggregationResult[];
|
|
14
|
+
/** Callback when the group header is clicked to toggle collapse */
|
|
15
|
+
onToggle: (key: string) => void;
|
|
16
|
+
/** Children to render when not collapsed (the group content) */
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* GroupRow renders a collapsible group header with field value, record count,
|
|
21
|
+
* and optional aggregation summary. Used by ObjectGrid for grouped rendering.
|
|
22
|
+
*/
|
|
23
|
+
export declare const GroupRow: React.FC<GroupRowProps>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface ImportWizardProps {
|
|
3
|
+
objectName: string;
|
|
4
|
+
objectLabel?: string;
|
|
5
|
+
fields: Array<{
|
|
6
|
+
name: string;
|
|
7
|
+
label: string;
|
|
8
|
+
type: string;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
}>;
|
|
11
|
+
dataSource: any;
|
|
12
|
+
onComplete?: (result: ImportResult) => void;
|
|
13
|
+
onCancel?: () => void;
|
|
14
|
+
open?: boolean;
|
|
15
|
+
onOpenChange?: (open: boolean) => void;
|
|
16
|
+
/** Error handling strategy: 'skip' skips invalid rows, 'stop' aborts on first error. @default 'skip' */
|
|
17
|
+
onErrorMode?: 'skip' | 'stop';
|
|
18
|
+
}
|
|
19
|
+
export interface ImportResult {
|
|
20
|
+
totalRows: number;
|
|
21
|
+
importedRows: number;
|
|
22
|
+
skippedRows: number;
|
|
23
|
+
errors: Array<{
|
|
24
|
+
row: number;
|
|
25
|
+
field: string;
|
|
26
|
+
message: string;
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
export declare const ImportWizard: React.FC<ImportWizardProps>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface SplitPaneGridProps {
|
|
3
|
+
/** Initial width (px) of the frozen (left) pane. */
|
|
4
|
+
frozenWidth: number;
|
|
5
|
+
/** Called with the new frozen width while the user drags the divider. */
|
|
6
|
+
onResize?: (frozenWidth: number) => void;
|
|
7
|
+
/** Minimum width (px) allowed for the frozen pane. */
|
|
8
|
+
minFrozenWidth?: number;
|
|
9
|
+
/** Minimum width (px) allowed for the scrollable pane. */
|
|
10
|
+
minScrollableWidth?: number;
|
|
11
|
+
/** Content rendered in the frozen (left) pane. */
|
|
12
|
+
left: React.ReactNode;
|
|
13
|
+
/** Content rendered in the scrollable (right) pane. */
|
|
14
|
+
right: React.ReactNode;
|
|
15
|
+
/** Additional class names for the outer container. */
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Split-pane wrapper that places a resizable vertical divider between a frozen
|
|
20
|
+
* (left) area and a scrollable (right) area. Drag the handle to resize.
|
|
21
|
+
*/
|
|
22
|
+
export declare function SplitPaneGrid({ frozenWidth: frozenWidthProp, onResize, minFrozenWidth, minScrollableWidth, left, right, className, }: SplitPaneGridProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface BulkActionBarProps {
|
|
3
|
+
/** Array of selected row records */
|
|
4
|
+
selectedRows: any[];
|
|
5
|
+
/** Bulk/batch action identifiers */
|
|
6
|
+
actions: string[];
|
|
7
|
+
/** Callback when a bulk action button is clicked */
|
|
8
|
+
onAction?: (action: string, selectedRows: any[]) => void;
|
|
9
|
+
/** Callback to clear selection */
|
|
10
|
+
onClearSelection?: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare const BulkActionBar: React.FC<BulkActionBarProps>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Format an action identifier string into a human-readable label.
|
|
4
|
+
* e.g., 'send_email' → 'Send Email'
|
|
5
|
+
*/
|
|
6
|
+
export declare function formatActionLabel(action: string): string;
|
|
7
|
+
export interface RowActionMenuProps {
|
|
8
|
+
/** The row data record */
|
|
9
|
+
row: any;
|
|
10
|
+
/** Custom row action identifiers */
|
|
11
|
+
rowActions?: string[];
|
|
12
|
+
/** Whether edit operation is available */
|
|
13
|
+
canEdit?: boolean;
|
|
14
|
+
/** Whether delete operation is available */
|
|
15
|
+
canDelete?: boolean;
|
|
16
|
+
/** Callback when edit is clicked */
|
|
17
|
+
onEdit?: (row: any) => void;
|
|
18
|
+
/** Callback when delete is clicked */
|
|
19
|
+
onDelete?: (row: any) => void;
|
|
20
|
+
/** Callback when a custom row action is clicked */
|
|
21
|
+
onAction?: (action: string, row: any) => void;
|
|
22
|
+
}
|
|
23
|
+
export declare const RowActionMenu: React.FC<RowActionMenuProps>;
|
|
@@ -1,14 +1,34 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { ObjectGrid } from './ObjectGrid';
|
|
3
3
|
import { VirtualGrid } from './VirtualGrid';
|
|
4
|
-
|
|
4
|
+
import { ImportWizard } from './ImportWizard';
|
|
5
|
+
export { ObjectGrid, VirtualGrid, ImportWizard };
|
|
5
6
|
export { InlineEditing } from './InlineEditing';
|
|
6
7
|
export { useRowColor } from './useRowColor';
|
|
7
8
|
export { useGroupedData } from './useGroupedData';
|
|
9
|
+
export { GroupRow } from './GroupRow';
|
|
10
|
+
export { RowActionMenu, formatActionLabel } from './components/RowActionMenu';
|
|
11
|
+
export { BulkActionBar } from './components/BulkActionBar';
|
|
12
|
+
export { useCellClipboard } from './useCellClipboard';
|
|
13
|
+
export { useGradientColor } from './useGradientColor';
|
|
14
|
+
export { useGroupReorder } from './useGroupReorder';
|
|
15
|
+
export { useColumnSummary } from './useColumnSummary';
|
|
16
|
+
export { FormulaBar } from './FormulaBar';
|
|
17
|
+
export { SplitPaneGrid } from './SplitPaneGrid';
|
|
8
18
|
export type { ObjectGridProps } from './ObjectGrid';
|
|
9
19
|
export type { VirtualGridProps, VirtualGridColumn } from './VirtualGrid';
|
|
10
20
|
export type { InlineEditingProps } from './InlineEditing';
|
|
11
|
-
export type {
|
|
21
|
+
export type { ImportWizardProps, ImportResult } from './ImportWizard';
|
|
22
|
+
export type { GroupEntry, UseGroupedDataResult, AggregationType, AggregationConfig, AggregationResult } from './useGroupedData';
|
|
23
|
+
export type { GroupRowProps } from './GroupRow';
|
|
24
|
+
export type { RowActionMenuProps } from './components/RowActionMenu';
|
|
25
|
+
export type { BulkActionBarProps } from './components/BulkActionBar';
|
|
26
|
+
export type { CellRange, UseCellClipboardOptions, UseCellClipboardResult } from './useCellClipboard';
|
|
27
|
+
export type { GradientStop, UseGradientColorOptions } from './useGradientColor';
|
|
28
|
+
export type { UseGroupReorderOptions, UseGroupReorderResult } from './useGroupReorder';
|
|
29
|
+
export type { ColumnSummaryConfig, ColumnSummaryResult } from './useColumnSummary';
|
|
30
|
+
export type { FormulaBarProps } from './FormulaBar';
|
|
31
|
+
export type { SplitPaneGridProps } from './SplitPaneGrid';
|
|
12
32
|
export declare const ObjectGridRenderer: React.FC<{
|
|
13
33
|
schema: any;
|
|
14
34
|
[key: string]: any;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
/** A cell range described by start/end row and column indices. */
|
|
9
|
+
export interface CellRange {
|
|
10
|
+
startRow: number;
|
|
11
|
+
startCol: number;
|
|
12
|
+
endRow: number;
|
|
13
|
+
endCol: number;
|
|
14
|
+
}
|
|
15
|
+
export interface UseCellClipboardOptions {
|
|
16
|
+
/** Full data rows currently displayed in the grid. */
|
|
17
|
+
data: Record<string, any>[];
|
|
18
|
+
/** Ordered column keys matching the grid's visible columns. */
|
|
19
|
+
columns: string[];
|
|
20
|
+
/** Callback invoked when pasted values should be applied. */
|
|
21
|
+
onPaste?: (changes: {
|
|
22
|
+
rowIndex: number;
|
|
23
|
+
field: string;
|
|
24
|
+
value: string;
|
|
25
|
+
}[]) => void;
|
|
26
|
+
/** Whether clipboard interaction is enabled. */
|
|
27
|
+
enabled?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface UseCellClipboardResult {
|
|
30
|
+
/** Currently selected cell range (null when nothing is selected). */
|
|
31
|
+
selectedRange: CellRange | null;
|
|
32
|
+
/** Programmatically update the selected range. */
|
|
33
|
+
setSelectedRange: (range: CellRange | null) => void;
|
|
34
|
+
/** Copy handler – reads selected range and writes tab-separated text to clipboard. */
|
|
35
|
+
onCopy: () => void;
|
|
36
|
+
/** Paste handler – reads tab-separated text from clipboard and emits changes. */
|
|
37
|
+
onPaste: () => void;
|
|
38
|
+
/** Keyboard handler to attach to the grid container element. */
|
|
39
|
+
onKeyDown: (e: React.KeyboardEvent) => void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Hook for single-cell and multi-cell copy/paste with Excel-compatible
|
|
43
|
+
* tab-separated format.
|
|
44
|
+
*
|
|
45
|
+
* Attach `onKeyDown` to the grid container to handle Ctrl+C / Ctrl+V.
|
|
46
|
+
*/
|
|
47
|
+
export declare function useCellClipboard({ data, columns, onPaste: onPasteCallback, enabled, }: UseCellClipboardOptions): UseCellClipboardResult;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ListColumn } from '../../types/src';
|
|
2
|
+
/**
|
|
3
|
+
* Summary configuration for a column.
|
|
4
|
+
* Can be a string shorthand (e.g. 'sum') or a full config object.
|
|
5
|
+
*/
|
|
6
|
+
export type ColumnSummaryConfig = string | {
|
|
7
|
+
type: 'count' | 'sum' | 'avg' | 'min' | 'max';
|
|
8
|
+
field?: string;
|
|
9
|
+
};
|
|
10
|
+
export interface ColumnSummaryResult {
|
|
11
|
+
field: string;
|
|
12
|
+
value: number | null;
|
|
13
|
+
label: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Hook to compute column summary/aggregation values.
|
|
17
|
+
*
|
|
18
|
+
* @param columns - Column definitions (may include `summary` config)
|
|
19
|
+
* @param data - Row data array
|
|
20
|
+
* @returns Map of field name to summary result, and a flag if any summaries exist
|
|
21
|
+
*/
|
|
22
|
+
export declare function useColumnSummary(columns: ListColumn[] | undefined, data: any[]): {
|
|
23
|
+
summaries: Map<string, ColumnSummaryResult>;
|
|
24
|
+
hasSummary: boolean;
|
|
25
|
+
};
|