@vuu-ui/vuu-table 0.8.22 → 0.8.23-debug

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/esm/index.js CHANGED
@@ -1,3 +1,3734 @@
1
- import{OverflowContainer as hn}from"@vuu-ui/vuu-layout";import{useLayoutEffectSkipFirst as xn}from"@vuu-ui/vuu-utils";import wn from"clsx";import{useCallback as Tn,useRef as Rn,useState as yn}from"react";import rn from"clsx";import{useCallback as ln}from"react";import{jsx as an,jsxs as sn}from"react/jsx-runtime";var Co="vuuColumnHeaderPill",le=({children:e,className:o,column:t,onRemove:r,removable:n,...l})=>{if(n&&typeof r!="function")throw Error("ColumnHeaderPill onRemove prop must be provided if Pill is removable");let s=ln(i=>{i.preventDefault(),i.stopPropagation(),r==null||r(t)},[t,r]);return sn("div",{...l,className:rn(Co,o),children:[e,n?an("span",{className:`${Co}-removeButton`,role:"button","data-icon":"cross",onClick:s}):null]})};import{jsx as Ie,jsxs as un}from"react/jsx-runtime";var vo=({column:e,...o})=>{let{name:t,sorted:r}=e,n=typeof r=="number"?r<0?"arrow-down":"arrow-up":r==="A"?"arrow-up":r==="D"?"arrow-down":void 0;return un(le,{...o,column:e,children:[Ie("span",{className:"vuuGroupColumnPill-label",children:t}),n!==void 0?Ie("span",{"data-icon":n}):null,typeof r=="number"?Ie("span",{className:"vuuSortPosition",children:Math.abs(r)}):null]})};import{jsx as ho,jsxs as cn}from"react/jsx-runtime";var xo=({column:e})=>{if(!e.sorted)return null;let o=typeof e.sorted=="number"?e.sorted<0?"arrow-down":"arrow-up":e.sorted==="A"?"arrow-up":"arrow-down";return cn(le,{column:e,children:[ho("span",{"data-icon":o}),typeof e.sorted=="number"?ho("span",{className:"vuuSortPosition",children:Math.abs(e.sorted)}):null]})};import{useCallback as ze,useRef as mn}from"react";import{jsx as pn}from"react/jsx-runtime";var wo=()=>{},dn="vuuColumnResizerNext",ge=({onDrag:e,onDragEnd:o=wo,onDragStart:t=wo})=>{let r=mn(0),n=ze(i=>{i.stopPropagation&&i.stopPropagation(),i.preventDefault&&i.preventDefault();let a=Math.round(i.clientX),u=a-r.current;r.current=a,u!==0&&e(i,u)},[e]),l=ze(i=>{window.removeEventListener("mouseup",l),window.removeEventListener("mousemove",n),o(i)},[o,n]),s=ze(i=>{t(i),r.current=Math.round(i.clientX),window.addEventListener("mouseup",l),window.addEventListener("mousemove",n),i.stopPropagation&&i.stopPropagation(),i.preventDefault&&i.preventDefault()},[t,n,l]);return pn("div",{className:dn,onMouseDown:s})};import{useCallback as Ne,useRef as bn,useState as fn}from"react";var Ce=({column:e,onResize:o,rootRef:t})=>{let r=bn(0),[n,l]=fn(!1),{name:s}=e,i=Ne(()=>{if(o&&t.current){let{width:c}=t.current.getBoundingClientRect();r.current=Math.round(c),l(!0),o==null||o("begin",s)}},[s,o,t]),a=Ne((c,d)=>{if(t.current&&o){let{width:g}=t.current.getBoundingClientRect(),b=Math.round(g)+d;b!==r.current&&b>0&&(o("resize",s,b),r.current=b)}},[s,o,t]),u=Ne(()=>{o&&(o("end",s,r.current),setTimeout(()=>{l(!1)},80))},[s,o]);return{isResizing:n,onDrag:a,onDragStart:i,onDragEnd:u}};import{getColumnStyle as gn}from"@vuu-ui/vuu-utils";import Cn from"clsx";import{useMemo as vn}from"react";var Y=(e,o,t)=>vn(()=>{let r=Cn(o,{vuuPinFloating:e.pin==="floating",vuuPinLeft:e.pin==="left",vuuPinRight:e.pin==="right",vuuEndPin:t&&e.endPin,[`${o}-editable`]:e.editable,[`${o}-right`]:e.align==="right"}),n=gn(e);return{className:r,style:n}},[e,o,t]);import{jsx as Ke,jsxs as Hn}from"react/jsx-runtime";import{createElement as Mn}from"react";var Fe="vuuTableGroupHeaderCell",Dn=(e,o)=>e===o?e:o,Ve=({column:e,className:o,onMoveColumn:t,onRemoveColumn:r,onResize:n,...l})=>{let s=Rn(null),{isResizing:i,...a}=Ce({column:e,onResize:n,rootRef:s}),[u,c]=yn(e.columns),{className:d,style:g}=Y(e,Fe,!0),b=u.length>1?{removable:!0,onRemove:r}:void 0,C=Tn((h,m)=>{c(v=>{let R=v.slice(),[P]=R.splice(h,1);if(m===-1){let I=R.concat(P);return t==null||t(I),I}else return R.splice(m,0,P),t==null||t(R),R})},[t]);return xn(()=>{c(h=>Dn(h,e.columns))},[e.columns]),Hn("div",{...l,className:wn(d,o,{[`${Fe}-pending`]:e.groupConfirmed===!1}),ref:s,role:"columnheader",style:g,children:[Ke(hn,{allowDragDrop:!0,className:`${Fe}-inner`,height:24,onMoveItem:C,overflowPosition:"start",children:u.map(h=>Mn(vo,{...b,column:h,key:h.key}))}),Ke(le,{column:e,removable:!0,onRemove:r}),e.resizeable!==!1?Ke(ge,{...a}):null]})};import In from"clsx";import{useCallback as zn,useRef as Nn}from"react";import{useContextMenu as Pn}from"@vuu-ui/vuu-popups";import En from"clsx";import{useCallback as To,useRef as Sn,useState as kn}from"react";import{jsx as An}from"react/jsx-runtime";var Ln=e=>{if(e){let{bottom:o,left:t}=e.getBoundingClientRect();return{x:t,y:o+6}}},Ro=({className:e,column:o,...t})=>{let r=Sn(null),[n,l]=kn(!1),[s]=Pn(),i=To(()=>{l(!1)},[]),a=To(u=>{l(!0),s(u,"column-menu",{column:o,ContextMenuProps:{onClose:i,position:Ln(r.current)}})},[o,i,s]);return An("span",{...t,className:En("vuuTable-columnMenu",e,{"vuuTable-columnMenu-open":n}),"data-icon":"more-vert",onClick:a,ref:r})};import{jsx as ie,jsxs as Fn}from"react/jsx-runtime";var ve="vuuTableHeaderCell",yo=({className:e,column:o,onClick:t,onResize:r,...n})=>{var R;let{HeaderCellContentRenderer:l,HeaderCellLabelRenderer:s}=o,i=Nn(null),{isResizing:a,...u}=Ce({column:o,onResize:r,rootRef:i}),c=zn(P=>{!a&&(t==null||t(P))},[a,t]),{className:d,style:g}=Y(o,ve,!0),b=ie(Ro,{column:o}),C=s?ie(s,{className:`${ve}-label`,column:o}):ie("div",{className:`${ve}-label`,children:(R=o.label)!=null?R:o.name}),h=l?[ie(l,{column:o},"content")]:[],m=ie(xo,{column:o}),v=o.align==="right"?[m,C].concat(h).concat(b):[b,C,m].concat(h);return Fn("div",{...n,className:In(d,e,{[`${ve}-resizing`]:a}),onClick:c,ref:i,role:"columnheader",style:g,children:[...v,o.resizeable!==!1?ie(ge,{...u}):null]})};import{MeasuredContainer as li}from"@vuu-ui/vuu-layout";import{ContextMenuProvider as ii}from"@vuu-ui/vuu-popups";import{metadataKeys as ai,useId as si}from"@vuu-ui/vuu-utils";import{useForkRef as ui}from"@salt-ds/core";import Mt from"clsx";import{forwardRef as ci,useRef as mi,useState as di}from"react";import{isGroupColumn as Eo,isJsonColumn as _n,isJsonGroup as Xn,metadataKeys as Qn,isNotHidden as Jn,RowSelected as Yn}from"@vuu-ui/vuu-utils";import Zn from"clsx";import{memo as jn,useCallback as So}from"react";import{isNumericColumn as Kn}from"@vuu-ui/vuu-utils";import{useCallback as Do}from"react";import{jsx as Mo}from"react/jsx-runtime";var Vn="vuuTableCell",Ho=({column:e,columnMap:o,onClick:t,onDataEdited:r,row:n})=>{let{className:l,style:s}=Y(e,Vn),{CellRenderer:i,name:a,valueFormatter:u}=e,c=o[a],d=Do(b=>{if(r){let C=b;return Kn(e)&&typeof b=="string"&&(C=e.serverDataType==="double"?parseFloat(b):parseInt(b)),r==null?void 0:r(n,a,C)}else throw Error("TableCell onDataEdited prop not supplied for an editable cell")},[e,a,r,n]),g=Do(b=>{t==null||t(b,e)},[e,t]);return Mo("div",{className:l,onClick:t?g:void 0,role:"cell",style:s,children:i?Mo(i,{column:e,columnMap:o,onCommit:d,row:n}):u(n[c])})};import{getGroupValueAndOffset as $n,metadataKeys as Gn}from"@vuu-ui/vuu-utils";import{useCallback as Bn}from"react";import On from"clsx";import{jsx as Ge,jsxs as Un}from"react/jsx-runtime";var{IS_LEAF:Wn}=Gn,$e="vuuTableGroupCell",Po=({column:e,onClick:o,row:t})=>{let{columns:r}=e,[n,l]=$n(r,t),{className:s,style:i}=Y(e,$e),a=Bn(d=>{o==null||o(d,e)},[e,o]),u=t[Wn],c=Array(l).fill(0).map((d,g)=>Ge("span",{className:`${$e}-spacer`},g));return Un("div",{className:On(s,"vuuTableCell"),role:"cell",style:i,onClick:u?void 0:a,children:[c,u?null:Ge("span",{className:`${$e}-toggle`,"data-icon":"triangle-right"}),Ge("span",{children:n})]})};import{jsx as Be}from"react/jsx-runtime";import{createElement as tr}from"react";var{IDX:qn,IS_EXPANDED:er,SELECTED:or}=Qn,X="vuuTableRow",Oe=jn(({className:e,columnMap:o,columns:t,highlighted:r,row:n,offset:l,onClick:s,onDataEdited:i,onToggleGroup:a,zebraStripes:u=!1,...c})=>{let{[qn]:d,[er]:g,[or]:b}=n,C=So(E=>{let k=E.shiftKey,F=E.ctrlKey||E.metaKey;s==null||s(n,k,F)},[s,n]),{True:h,First:m,Last:v}=Yn,R=Zn(X,e,{[`${X}-even`]:u&&d%2===0,[`${X}-expanded`]:g,[`${X}-highlighted`]:r,[`${X}-selected`]:b&h,[`${X}-selectedStart`]:b&m,[`${X}-selectedEnd`]:b&v}),P={transform:`translate3d(0px, ${l}px, 0px)`},I=So((E,k)=>{(Eo(k)||Xn(k,n))&&(E.stopPropagation(),a==null||a(n,k))},[a,n]);return tr("div",{...c,key:`row-${n[0]}`,role:"row",className:R,onClick:C,style:P},Be("span",{className:`${X}-selectionDecorator vuuStickyLeft`}),t.filter(Jn).map(E=>{let k=Eo(E),F=_n(E);return Be(k?Po:Ho,{column:E,columnMap:o,onClick:k||F?I:void 0,onDataEdited:i,row:n},E.key)}),Be("span",{className:`${X}-selectionDecorator vuuStickyRight`}))});Oe.displayName="Row";import{useDragDrop as Gl}from"@vuu-ui/vuu-ui-controls";import{applySort as Bl,buildColumnMap as Ol,getIndexFromRowElement as Wl,isGroupColumn as Ul,isJsonGroup as _l,isValidNumber as bt,metadataKeys as Xl,updateColumn as ft,useLayoutEffectSkipFirst as gt}from"@vuu-ui/vuu-utils";import{useCallback as L,useEffect as Ql,useMemo as oo,useState as Ct}from"react";import{isNumericColumn as nr}from"@vuu-ui/vuu-utils";var ko=e=>(o,t)=>{let r=[];return e===void 0||(o==="header"||o==="column-menu")&&(r.push(...rr(t,e)),r.push(...ar(t,e)),r.push(...lr(t,e)),r.push(...ir(t)),r.push({action:"column-settings",icon:"cog",label:"Column Settings",options:t}),r.push({action:"table-settings",icon:"cog",label:"DataGrid Settings",options:t})),r};function rr(e,{sort:{sortDefs:o}}){let{column:t}=e,r=[];if(t===void 0)return r;let n=o.length>0;return t.sorted==="A"?r.push({label:"Reverse Sort (DSC)",action:"sort-dsc",options:e}):t.sorted==="D"?r.push({label:"Reverse Sort (ASC)",action:"sort-asc",options:e}):typeof t.sorted=="number"?(t.sorted>0?r.push({label:"Reverse Sort (DSC)",action:"sort-add-dsc",options:e}):r.push({label:"Reverse Sort (ASC)",action:"sort-add-asc",options:e}),n&&Math.abs(t.sorted)<o.length&&r.push({label:"Remove from sort",action:"sort-remove",options:e}),r.push({label:"New Sort",children:[{label:"Ascending",action:"sort-asc",options:e},{label:"Descending",action:"sort-dsc",options:e}]})):n?(r.push({label:"Add to sort",children:[{label:"Ascending",action:"sort-add-asc",options:e},{label:"Descending",action:"sort-add-dsc",options:e}]}),r.push({label:"New Sort",children:[{label:"Ascending",action:"sort-asc",options:e},{label:"Descending",action:"sort-dsc",options:e}]})):r.push({label:"Sort",children:[{label:"Ascending",action:"sort-asc",options:e},{label:"Descending",action:"sort-dsc",options:e}]}),r}function lr(e,o){let{column:t}=e;if(t===void 0||o.groupBy.length===0)return[];let{name:r,label:n=r}=t;return[{label:`Aggregate ${n}`,children:[{label:"Count",action:"agg-count",options:e},{label:"Distinct",action:"agg-distinct",options:e}].concat(nr(t)?[{label:"Sum",action:"agg-sum",options:e},{label:"Avg",action:"agg-avg",options:e},{label:"High",action:"agg-high",options:e},{label:"Low",action:"agg-low",options:e}]:[])}]}var Xe=(e,o)=>({label:`Pin ${o}`,action:`column-pin-${o}`,options:e}),We=e=>Xe(e,"left"),Ue=e=>Xe(e,"floating"),_e=e=>Xe(e,"right");function ir(e){let{column:o}=e;if(o===void 0)return[];let{pin:t}=o,r=[{label:"Hide column",action:"column-hide",options:e},{label:"Remove column",action:"column-remove",options:e}];return t===void 0?r.push({label:"Pin column",children:[We(e),Ue(e),_e(e)]}):t==="left"?r.push({label:"Unpin column",action:"column-unpin",options:e},{label:"Pin column",children:[Ue(e),_e(e)]}):t==="right"?r.push({label:"Unpin column",action:"column-unpin",options:e},{label:"Pin column",children:[We(e),Ue(e)]}):t==="floating"&&r.push({label:"Unpin column",action:"column-unpin",options:e},{label:"Pin column",children:[We(e),_e(e)]}),r}function ar(e,{groupBy:o}){let{column:t}=e,r=[];if(t===void 0)return r;let{name:n,label:l=n}=t;return o.length===0?r.push({label:`Group by ${l}`,action:"group",options:e}):r.push({label:`Add ${l} to group by`,action:"group-add",options:e}),r}import{removeColumnFromFilter as sr}from"@vuu-ui/vuu-utils";import{addGroupColumn as Lo,addSortColumn as Ao,AggregationType as ur,setAggregations as ae,setSortColumn as Io}from"@vuu-ui/vuu-utils";var cr=(e,o)=>{if(e.filterStruct&&o){let[t,r]=sr(o,e.filterStruct);return{filter:r,filterStruct:t}}else return e},{Average:mr,Count:dr,Distinct:pr,High:br,Low:fr,Sum:gr}=ur,zo=({dataSource:e,onPersistentColumnOperation:o})=>r=>{let n=r.options;if(n.column&&e){let{column:l}=n;switch(r.menuId){case"sort-asc":return e.sort=Io(e.sort,l,"A"),!0;case"sort-dsc":return e.sort=Io(e.sort,l,"D"),!0;case"sort-add-asc":return e.sort=Ao(e.sort,l,"A"),!0;case"sort-add-dsc":return e.sort=Ao(e.sort,l,"D"),!0;case"group":return e.groupBy=Lo(e.groupBy,l),!0;case"group-add":return e.groupBy=Lo(e.groupBy,l),!0;case"column-hide":return o({type:"hideColumns",columns:[l]}),!0;case"column-remove":return e.columns=e.columns.filter(s=>s!==l.name),!0;case"filter-remove-column":return e.filter=cr(e.filter,l),!0;case"remove-filters":return e.filter={filter:""},!0;case"agg-avg":return e.aggregations=ae(e.aggregations,l,mr),!0;case"agg-high":return e.aggregations=ae(e.aggregations,l,br),!0;case"agg-low":return e.aggregations=ae(e.aggregations,l,fr),!0;case"agg-count":return e.aggregations=ae(e.aggregations,l,dr),!0;case"agg-distinct":return e.aggregations=ae(e.aggregations,l,pr),!0;case"agg-sum":return e.aggregations=ae(e.aggregations,l,gr),!0;case"column-pin-floating":return o({type:"pinColumn",column:l,pin:"floating"}),!0;case"column-pin-left":return o({type:"pinColumn",column:l,pin:"left"}),!0;case"column-pin-right":return o({type:"pinColumn",column:l,pin:"right"}),!0;case"column-unpin":return o({type:"pinColumn",column:l,pin:void 0}),!0;case"column-settings":return o({type:"columnSettings",column:l}),!0;case"table-settings":return o({type:"tableSettings"}),!0;default:}}return!1};var No=(e,o)=>{switch(o.type){case"col-size":return{...e,columns:e.columns.map(t=>t.name===o.column.name?{...t,width:o.width}:t)};case"column-prop":return{...e,columns:e.columns.map(t=>t.name===o.column.name?{...t,[o.property]:o.value}:t)};default:return e}};import{isCharacterKey as xr}from"@vuu-ui/vuu-utils";import{useCallback as ee}from"react";var Qe=e=>`.vuuTable-col-headers .vuuTableHeaderCell:nth-child(${e})`,Je=(e,o)=>`.vuuTable-body > [aria-rowindex='${e+1}'] > [role='cell']:nth-child(${o+1})`,Fo=(e,[o,t])=>{var l;let r=o===-1?Qe(t):Je(o,t),n=(l=e.current)==null?void 0:l.querySelector(r);return Cr(n)&&n.querySelector("button")||n},Cr=e=>e.classList.contains("vuuTableCell-editable"),Ko=e=>e.querySelector(".vuuTableInputCell")!==null;function vr(e){if(e){let o=e.ariaRowIndex;if(o!==null)return parseInt(o,10)-1}return-1}var hr=e=>e.closest('[role="row"]'),Vo=e=>vr(hr(e));var $o=({navigate:e})=>{let o=ee(()=>{e()},[e]),t=ee(a=>{let u=a.target,c=u.matches("input")?u:u.querySelector("input");c&&(c.focus(),c.select())},[]),r=ee(a=>{let c=a.target.querySelector("input");c&&(c.focus(),c.select())},[]),n=ee(a=>{let u=a.target;Ko(u)&&(xr(a.key)?t(a):a.key==="Enter"&&r(a))},[t,r]),l=ee(a=>{let u=a.target;(u.matches("input")||u.querySelector("input"))&&(t(a),a.stopPropagation())},[t]),s=ee(a=>{a.target.removeEventListener("vuu-commit",o,!0)},[o]),i=ee(a=>{a.target.addEventListener("vuu-commit",o,!0)},[o]);return{onBlur:s,onDoubleClick:l,onFocus:i,onKeyDown:n}};import{getFullRange as Ze,NULL_RANGE as Go}from"@vuu-ui/vuu-utils";import{useCallback as xe,useEffect as Bo,useMemo as yr,useRef as we,useState as Dr}from"react";import{isRowSelectedLast as wr,metadataKeys as Tr,WindowRange as Rr}from"@vuu-ui/vuu-utils";var{SELECTED:Ye}=Tr,he=class{constructor({from:o,to:t}){this.rowCount=0;this.setRowCount=o=>{o<this.data.length&&(this.data.length=o),this.rowCount=o};this.range=new Rr(o,t),this.data=new Array(Math.max(0,t-o)),this.rowCount=0}add(o){let[t]=o;if(this.isWithinRange(t)){let r=t-this.range.from;if(this.data[r]=o,o[Ye]){let n=this.data[r-1];wr(n)&&(this.data[r-1]=n.slice(),this.data[r-1][Ye]-=4)}}}getAtIndex(o){return this.range.isWithin(o)&&this.data[o-this.range.from]!=null?this.data[o-this.range.from]:void 0}isWithinRange(o){return this.range.isWithin(o)}setRange({from:o,to:t}){if(o!==this.range.from||t!==this.range.to){let[r,n]=this.range.overlap(o,t),l=new Array(Math.max(0,t-o));for(let s=r;s<n;s++){let i=this.getAtIndex(s);if(i){let a=s-o;l[a]=i}}this.data=l,this.range.from=o,this.range.to=t}}getSelectedRows(){return this.data.filter(o=>o[Ye]!==0)}};var Mr=e=>e.type==="vuu-link-created"||e.type==="vuu-link-removed",Oo=({dataSource:e,onFeatureInvocation:o,onSizeChange:t,onSubscribed:r,range:n=Go,renderBufferSize:l=0})=>{let[,s]=Dr(null),i=we([]),a=we(!0),u=we(!1),c=we(Go),d=yr(()=>new he(Ze(n,l)),[]),g=xe(m=>{for(let v of m)d.add(v);i.current=d.data,a.current?s({}):console.log("ignore update as we're not mounted")},[d]),b=xe(m=>{m.type==="subscribed"?r==null||r(m):m.type==="viewport-update"?(typeof m.size=="number"&&(t==null||t(m.size),d.setRowCount(m.size)),m.rows?g(m.rows):typeof m.size=="number"&&(i.current=d.data,u.current=!0)):Mr(m)?o==null||o(m):console.log(`useDataSource unexpected message ${m.type}`)},[d,o,t,r,g]),C=xe(()=>d.getSelectedRows(),[d]);Bo(()=>{var m;return a.current=!0,(m=e.resume)==null||m.call(e),()=>{var v;a.current=!1,(v=e.suspend)==null||v.call(e)}},[e]),Bo(()=>{var m;e.status==="disabled"?(m=e.enable)==null||m.call(e,b):e==null||e.subscribe({range:Ze(n,l)},b)},[e,b,n,l]);let h=xe(m=>{let v=Ze(m,l);d.setRange(v),e.range=c.current=v,e.emit("range",m)},[e,d,l]);return{data:i.current,dataRef:i,getSelectedRows:C,range:c.current,setRange:h}};import{useMemo as Hr,useRef as Pr}from"react";var Wo=e=>{let o=Pr(e);return Hr(()=>o.current,[])};import{getIndexFromRowElement as Er}from"@vuu-ui/vuu-utils";import{useControlled as Sr}from"@salt-ds/core";import{useCallback as W,useEffect as Uo,useRef as Te}from"react";var Qo=new Set(["Home","End","PageUp","PageDown","ArrowDown","ArrowUp"]),je=new Set(Qo);je.add("ArrowLeft");je.add("ArrowRight");var kr=(e,o)=>{switch(o){case"cell":return je.has(e);case"row":return Qo.has(e);default:return!1}},Lr=["Home","End","PageUp","PageDown"],_o=e=>Lr.includes(e),Ar=[-1,-1];function Xo(e,[o,t],r,n){return e==="ArrowUp"?o>-1?[o-1,t]:[o,t]:e==="ArrowDown"?o===-1?[0,t]:o===n-1?[o,t]:[o+1,t]:e==="ArrowRight"?t<r?[o,t+1]:[o,t]:e==="ArrowLeft"?t>1?[o,t-1]:[o,t]:[o,t]}var Jo=({columnCount:e=0,containerRef:o,disableFocus:t=!1,defaultHighlightedIndex:r,disableHighlightOnFocus:n,highlightedIndex:l,navigationStyle:s,requestScroll:i,onHighlight:a,rowCount:u=0,viewportRowCount:c})=>{var y;let d=Te([-1,-1]),g=Te(),b=Te([-1,0]),C=Te(),[h,m]=Sr({controlled:l,default:r,name:"UseKeyboardNavigation"});C.current=h;let v=W((f,x=!1)=>{a==null||a(f),m(f)},[a,m]),R=f=>f==null?void 0:f.closest("[role='columnHeader'],[role='cell']"),P=f=>{var x;if(f.role==="columnHeader")return[-1,parseInt((x=f.dataset.idx)!=null?x:"-1",10)];{let D=f.closest("[role='row']");if(D){let S=Er(D),$=Array.from(D.childNodes).indexOf(f);return[S,$]}}return Ar},I=W(f=>{var x;if(o.current){let D=Fo(o,f);D&&(D!==g.current&&((x=g.current)==null||x.removeAttribute("tabindex"),g.current=D,D.setAttribute("tabindex","0")),console.log(`scroll row ${f[0]}`),i==null||i({type:"scroll-row",rowIndex:f[0]}),D.focus({preventScroll:!0}))}},[o,i]),E=W((f,x,D=!1)=>{let S=[f,x];b.current=S,s==="row"?m(f):I(S),D&&(d.current=S)},[I,s,m]),k=W((f,[x,D])=>new Promise(S=>{let $=x;switch(f){case"PageDown":$=Math.min(u-1,x+c),i==null||i({type:"scroll-page",direction:"down"});break;case"PageUp":$=Math.max(0,x-c),i==null||i({type:"scroll-page",direction:"up"});break;case"Home":$=0,i==null||i({type:"scroll-end",direction:"home"});break;case"End":$=u-1,i==null||i({type:"scroll-end",direction:"end"});break}setTimeout(()=>{S([$,D])},90)}),[i,u,c]),F=W(()=>{var f;if(n!==!0&&(f=o.current)!=null&&f.contains(document.activeElement)){let x=R(document.activeElement);x&&(d.current=P(x),s==="row"&&m(d.current[0]))}},[n,o,s,m]),K=W(async f=>{let[x,D]=_o(f)?await k(f,b.current):Xo(f,b.current,e,u),[S,$]=b.current;(x!==S||D!==$)&&E(x,D,!0)},[e,k,u,E]),V=W(f=>{i==null||i({type:"scroll-row",rowIndex:f})},[i]),B=W(async f=>{let{current:x}=C,[D]=_o(f)?await k(f,[x!=null?x:-1,0]):Xo(f,[x!=null?x:-1,0],e,u);D!==x&&(v(D),V(D))},[e,k,u,V,v]);Uo(()=>{l!==void 0&&l!==-1&&V(l)},[l,V]);let O=W(f=>{u>0&&kr(f.key,s)&&(f.preventDefault(),f.stopPropagation(),s==="row"?B(f.key):K(f.key))},[u,s,B,K]),T=W(f=>{let x=f.target,D=R(x);if(D){let[S,$]=P(D);E(S,$)}},[E]),M=W(()=>{v(-1)},[v]),w=W(f=>{let x=Vo(f.target);x!==-1&&x!==C.current&&v(x)},[v]),N=W(()=>{K("ArrowDown")},[K]),z=((y=o.current)==null?void 0:y.firstChild)!=null;return Uo(()=>{if(z&&g.current===void 0&&!t){let{current:f}=o,x=(f==null?void 0:f.querySelector(Qe(0)))||(f==null?void 0:f.querySelector(Je(0,0)));x&&(x.setAttribute("tabindex","0"),g.current=x)}},[o,t,z]),{highlightedIndexRef:C,navigate:N,onClick:T,onFocus:F,onKeyDown:O,onMouseLeave:s==="row"?M:void 0,onMouseMove:s==="row"?w:void 0}};import{deselectItem as Ir,dispatchMouseEvent as zr,isRowSelected as Nr,metadataKeys as Fr,selectItem as Kr}from"@vuu-ui/vuu-utils";import{useCallback as qe,useRef as Yo}from"react";var{IDX:Vr}=Fr,$r=[],Gr=["Enter"," "],Zo=({highlightedIndexRef:e,selectionKeys:o=Gr,selectionModel:t,onSelect:r,onSelectionChange:n})=>{let l=Yo(-1),s=Yo($r),i=qe(c=>o.includes(c.key),[o]),a=qe((c,d,g)=>{let{[Vr]:b}=c,{current:C}=l,{current:h}=s,v=(Nr(c)?Ir:Kr)(t,h,b,d,g,C);s.current=v,l.current=b,r==null||r(c),n==null||n(v)},[r,n,t]);return{onKeyDown:qe(c=>{if(i(c)){let{current:d}=e;if(d!==void 0&&d!==-1){let g=c.target.querySelector(`[aria-rowindex="${d}"]`);g&&zr(g,"click")}}},[e,i]),onRowClick:a}};import{useContextMenu as Br}from"@vuu-ui/vuu-popups";import{buildColumnMap as Or,getIndexFromRowElement as Wr}from"@vuu-ui/vuu-utils";import{useCallback as Ur}from"react";var _r=[],jo=({columns:e,data:o,dataSource:t,getSelectedRows:r})=>{let[n]=Br();return Ur(s=>{let i=s.target,a=i==null?void 0:i.closest("div[role='cell']"),u=i==null?void 0:i.closest("div[role='row']");if(a&&u){let{selectedRowsCount:c}=t,d=Or(e),g=Wr(u),b=Array.from(u.childNodes).indexOf(a),C=o.find(([m])=>m===g),h=e[b];n(s,"grid",{columnMap:d,columnName:h,row:C,selectedRows:c===0?_r:r(),viewport:t.viewport})}},[e,o,t,r,n])};import{applyFilterToColumns as Xr,applyGroupByToColumns as Qr,applySortToColumns as Jr,getCellRenderer as Yr,getColumnHeaderContentRenderer as Zr,getColumnHeaderLabelRenderer as jr,getColumnLabel as qr,getTableHeadings as el,getValueFormatter as ol,hasValidationRules as tl,isFilteredColumn as nl,isGroupColumn as rl,isPinned as ll,logger as il,metadataKeys as al,replaceColumn as oe,sortPinnedColumns as qo,stripFilterFromColumns as sl,subscribedOnly as ul}from"@vuu-ui/vuu-utils";import{buildValidationChecker as cl}from"@vuu-ui/vuu-ui-controls";import{useReducer as ml}from"react";var{info:eo}=il("useTableModel"),dl=100,pl=al.count,bl=({serverDataType:e})=>e===void 0,et=(e,o)=>{let t=o==null?void 0:o.columns.find(({name:r})=>r===e.name);return t?t.serverDataType:e.serverDataType},fl=["int","long","double"],ot=e=>e===void 0?void 0:fl.includes(e)?"right":"left",tt=e=>e.type==="columnSettings",nt=e=>e.type==="tableSettings",gl=(e,o)=>{switch(eo==null||eo(`TableModelReducer ${o.type}`),o.type){case"init":return lt(o);case"moveColumn":return vl(e,o);case"resizeColumn":return wl(e,o);case"setTableSchema":return Tl(e,o);case"hideColumns":return hl(e,o);case"showColumns":return xl(e,o);case"pinColumn":return Rl(e,o);case"updateColumnProp":return se(e,o);case"tableConfig":return at(e,o);default:return console.log(`unhandled action ${o.type}`),e}},rt=(e,o)=>{let[t,r]=ml(gl,{tableConfig:e,dataSource:o},lt),{columns:n,headings:l,tableConfig:s,...i}=t;return{columns:n,dispatchColumnAction:r,headings:l,tableAttributes:i,tableConfig:s}};function lt({dataSource:e,tableConfig:o}){let{columns:t,...r}=o,{config:n,tableSchema:l}=e,s=t.filter(ul(n==null?void 0:n.columns)).map(it(r,l)),i=s.some(ll)?qo(s):s,a={columns:i,headings:el(i),tableConfig:o,...r};if(n){let{columns:u,...c}=n;a=at(a,{type:"tableConfig",...c})}return a}var Cl=(e,o)=>o==="uppercase"?e.toUpperCase():o==="capitalize"?e[0].toUpperCase()+e.slice(1).toLowerCase():e,it=(e,o)=>(t,r)=>{let{columnDefaultWidth:n=dl,columnFormatHeader:l}=e,s=et(t,o),{align:i=ot(s),key:a,name:u,label:c=qr(t),width:d=n,...g}=t,b={...g,align:i,CellRenderer:Yr(t),HeaderCellContentRenderer:Zr(t),HeaderCellLabelRenderer:jr(t),clientSideEditValidationCheck:tl(t.type)?cl(t.type.renderer.rules):void 0,label:Cl(c,l),key:a!=null?a:r+pl,name:u,originalIdx:r,serverDataType:s,valueFormatter:ol(t,s),width:d};return rl(b)&&(b.columns=b.columns.map(C=>it(e)(C,C.key))),b};function vl(e,{column:o,moveBy:t}){let{columns:r}=e;if(typeof t=="number"){let n=r.indexOf(o),l=r.slice(),[s]=l.splice(n,1);return l.splice(n+t,0,s),{...e,columns:l}}return e}function hl(e,{columns:o}){return o.some(t=>t.hidden!==!0)?o.reduce((t,r)=>r.hidden!==!0?se(t,{type:"updateColumnProp",column:r,hidden:!0}):t,e):e}function xl(e,{columns:o}){return o.some(t=>t.hidden)?o.reduce((t,r)=>r.hidden?se(t,{type:"updateColumnProp",column:r,hidden:!1}):t,e):e}function wl(e,{column:o,phase:t,width:r}){let n="updateColumnProp",l=t!=="end";switch(t){case"begin":return se(e,{type:n,column:o,resizing:l});case"end":return se(e,{type:n,column:o,resizing:l,width:r});case"resize":return se(e,{type:n,column:o,width:r});default:throw Error(`useTableModel.resizeColumn, invalid resizePhase ${t}`)}}function Tl(e,{tableSchema:o}){let{columns:t}=e;if(t.some(bl)){let r=t.map(n=>{var s;let l=et(n,o);return{...n,align:(s=n.align)!=null?s:ot(l),serverDataType:l}});return{...e,columns:r}}else return e}function Rl(e,o){let{columns:t}=e,{column:r,pin:n}=o,l=t.find(s=>s.name===r.name);return l?(t=oe(t,{...l,pin:n}),t=qo(t),{...e,columns:t}):e}function se(e,o){let{columns:t,tableConfig:r}=e,{align:n,column:l,hidden:s,label:i,resizing:a,width:u}=o,c=t.find(d=>d.name===l.name);if(c&&((n==="left"||n==="right")&&(t=oe(t,{...c,align:n})),typeof i=="string"&&(t=oe(t,{...c,label:i})),typeof a=="boolean"&&(t=oe(t,{...c,resizing:a})),typeof s=="boolean"&&(t=oe(t,{...c,hidden:s})),typeof u=="number")){t=oe(t,{...c,width:u});let d=r.columns.find(g=>g.name===l.name);d&&(r={...r,columns:oe(r.columns,{...d,width:u})})}return{...e,columns:t,tableConfig:r}}function at(e,{confirmed:o,filter:t,groupBy:r,sort:n}){let l=r!==void 0,s=typeof(t==null?void 0:t.filter)=="string",i=n&&n.sortDefs.length>0,a=e;return l&&(a={...e,columns:Qr(a.columns,r,o)}),i&&(a={...e,columns:Jr(a.columns,n)}),s?a={...e,columns:Xr(a.columns,t)}:a.columns.some(nl)&&(a={...e,columns:sl(a.columns)}),a}import{getRowElementAtIndex as yl}from"@vuu-ui/vuu-utils";import{useCallback as Q,useEffect as Dl,useImperativeHandle as Ml,useMemo as Hl,useRef as ue}from"react";var st=e=>{let{scrollLeft:o,scrollTop:t}=e,{clientHeight:r,clientWidth:n,scrollHeight:l,scrollWidth:s}=e,i=o/(s-n),a=t/(l-r);return[i,a]},Pl={scrollToIndex:()=>{},scrollToKey:()=>{}},El=[void 0,void 0],Sl=(e,o,t=e.closest(".vuuTable-contentContainer"))=>{if(t){let r=t==null?void 0:t.getBoundingClientRect(),n=r.top+o,l=e.getBoundingClientRect();if(l)return l.bottom>r.bottom?["down",l.bottom-r.bottom]:l.top<n?["up",l.top-n]:El;throw Error("Whats going on, row not found")}else throw Error("Whats going on, scrollbar container not found")},ut=({onAttach:e,onDetach:o})=>{let t=ue(null);return Q(n=>{if(n)t.current=n,e==null||e(n);else if(t.current){let{current:l}=t;t.current=n,o==null||o(l)}},[e,o])},ct=({getRowAtPosition:e,onHorizontalScroll:o,onVerticalScroll:t,scrollingApiRef:r,setRange:n,viewportMeasurements:l})=>{let s=ue(0),i=ue(!1),a=ue({scrollTop:0,scrollLeft:0}),u=ue(null),c=ue(null),{appliedPageSize:d,isVirtualScroll:g,maxScrollContainerScrollHorizontal:b,maxScrollContainerScrollVertical:C,rowCount:h,totalHeaderHeight:m}=l,v=Q((T,M)=>{t==null||t(T,M);let w=e(T);w!==s.current&&(s.current=w,n({from:w,to:w+h+1}))},[e,t,n,h]),R=Q(()=>{let{current:T}=c,{current:M}=u,{current:w}=i;if(w)i.current=!1;else if(T&&M){let[N,z]=st(M),y=Math.round(N*b),f=z*C;T.scrollTo({left:y,top:f,behavior:"auto"})}},[b,C]),P=Q(()=>{let{current:T}=c,{current:M}=u,{current:w}=a;if(T&&M){let{scrollLeft:N,scrollTop:z}=T,[y,f]=st(T);i.current=!0,M.scrollLeft=Math.round(y*b),M.scrollTop=f*C,w.scrollTop!==z&&(w.scrollTop=z,v(z,f)),w.scrollLeft!==N&&(w.scrollLeft=N,o==null||o(N))}},[v,b,C,o]),I=Q(T=>{u.current=T,T.addEventListener("scroll",R,{passive:!0})},[R]),E=Q(T=>{u.current=null,T.removeEventListener("scroll",R)},[R]),k=Q(T=>{c.current=T,T.addEventListener("scroll",P,{passive:!0})},[P]),F=Q(T=>{c.current=null,T.removeEventListener("scroll",P)},[P]),K=ut({onAttach:k,onDetach:F}),V=ut({onAttach:I,onDetach:E}),B=Q(T=>{let{current:M}=c;if(M){let{scrollLeft:w,scrollTop:N}=M;if(i.current=!1,T.type==="scroll-row"){let z=yl(M,T.rowIndex);if(z!==null){let[y,f]=Sl(z,m);if(y&&f)if(g)console.log(`virtual scroll row required ${y} ${f}
2
- first Row ${s.current}`);else{let x=w,D=N;y==="up"||y==="down"?D=Math.min(Math.max(0,N+f),C):x=Math.min(Math.max(0,w+f),b),M.scrollTo({top:D,left:x,behavior:"smooth"})}}}else if(T.type==="scroll-page"){let{direction:z}=T;if(g)console.log("need a virtual page scroll");else{let y=z==="down"?d:-d,f=Math.min(Math.max(0,N+y),C);M.scrollTo({top:f,left:w,behavior:"auto"})}}else if(T.type==="scroll-end"){let{direction:z}=T,y=z==="end"?C:0;M.scrollTo({top:y,left:M.scrollLeft,behavior:"auto"})}}},[d,g,b,C,n,m,h]),O=Hl(()=>({scrollToIndex:T=>{if(u.current){let M=(T-30)*20;u.current.scrollTop=M}},scrollToKey:T=>{console.log(`scrollToKey ${T}`)}}),[]);return Ml(r,()=>u.current?O:Pl,[O]),Dl(()=>{let{current:T}=s,M={from:T,to:T+h+1};n(M)},[n,h]),{scrollbarContainerRef:V,contentContainerRef:K,requestScroll:B}};import{useCallback as kl,useMemo as Re,useRef as mt}from"react";import{actualRowPositioning as Ll,virtualRowPositioning as Al}from"@vuu-ui/vuu-utils";var Il=1e5,zl={appliedPageSize:0,contentHeight:0,contentWidth:0,getRowAtPosition:()=>-1,getRowOffset:()=>-1,horizontalScrollbarHeight:0,isVirtualScroll:!1,maxScrollContainerScrollHorizontal:0,maxScrollContainerScrollVertical:0,pinnedWidthLeft:0,pinnedWidthRight:0,rowCount:0,setPctScrollTop:()=>{},totalHeaderHeight:0,verticalScrollbarWidth:0,viewportBodyHeight:0},Nl=e=>{let o=0,t=0,r=0;for(let n of e){let{hidden:l,pin:s,width:i}=n,a=l?0:i;s==="left"?o+=a:s==="right"?t+=a:r+=a}return{pinnedWidthLeft:o+4,pinnedWidthRight:t+4,unpinnedWidth:r}},dt=({columns:e,headerHeight:o,headings:t,rowCount:r,rowHeight:n,size:l})=>{let s=mt(0),i=n*Math.min(r,Il),a=r*n,u=a-i,{pinnedWidthLeft:c,pinnedWidthRight:d,unpinnedWidth:g}=Re(()=>Nl(e),[e]),b=mt(o);Re(()=>{b.current=o*(1+t.length)},[o,t.length]);let[C,h,m]=Re(()=>u?Al(n,u,s):Ll(n),[u,n]),v=kl(R=>{s.current=R},[]);return Re(()=>{var R;if(l){let{current:P}=b,I=15,E=c+g+d,k=E>l.width?I:0,F=i-(((R=l==null?void 0:l.height)!=null?R:0)-k)+P,K=E-l.width+c,V=(l.height-o)/n,B=Number.isInteger(V)?V:Math.ceil(V),O=l.height-P,T=i>O?I:0;return{appliedPageSize:B*n*(i/a),contentHeight:i,contentWidth:E,getRowAtPosition:h,getRowOffset:C,isVirtualScroll:m,horizontalScrollbarHeight:k,maxScrollContainerScrollHorizontal:K,maxScrollContainerScrollVertical:F,pinnedWidthLeft:c,pinnedWidthRight:d,rowCount:B,setPctScrollTop:v,totalHeaderHeight:P,verticalScrollbarWidth:T,viewportBodyHeight:O}}else return zl},[h,C,o,m,c,g,d,i,n,v,l,a])};import{useLayoutProviderDispatch as Fl}from"@vuu-ui/vuu-layout";import{getCalculatedColumnType as Kl}from"@vuu-ui/vuu-utils";import{useCallback as te,useRef as Vl,useState as $l}from"react";var pt=({availableColumns:e,onAvailableColumnsChange:o,onConfigChange:t,onCreateCalculatedColumn:r,onDataSourceConfigChange:n,tableConfig:l})=>{let s=Fl(),i=Vl(),[a,u]=$l(e),c=te((m,v,R)=>{s({type:"set-props",path:"#context-panel",props:{expanded:!0,content:{type:m,props:R},title:v}})},[s]),d=te(()=>{requestAnimationFrame(()=>{var m;(m=i.current)==null||m.call(i)})},[]),g=te(m=>{let v=a.concat({name:m.name,serverDataType:Kl(m)});u(v),o==null||o(v),requestAnimationFrame(()=>{var R;(R=i.current)==null||R.call(i)}),r(m)},[a,o,r]),b=te(m=>{c("ColumnSettings","Column Settings",{column:m.column,onCancelCreateColumn:d,onConfigChange:t,onCreateCalculatedColumn:g,tableConfig:l,vuuTable:m.vuuTable})},[d,g,t,c,l]),C=te(()=>{b({column:{name:"::",serverDataType:"string"},type:"columnSettings",vuuTable:{module:"SIMUL",table:"instruments"}})},[b]),h=te(m=>{let v=l.columns.find(R=>R.name===m);v&&b({type:"columnSettings",column:v,vuuTable:{module:"SIMUL",table:"instruments"}})},[b,l.columns]);return i.current=te(()=>{c("TableSettings","DataGrid Settings",{availableColumns:a!=null?a:l.columns.map(({name:m,serverDataType:v})=>({name:m,serverDataType:v})),onAddCalculatedColumn:C,onConfigChange:t,onDataSourceConfigChange:n,onNavigateToColumn:h,tableConfig:l})},[a,C,h,t,n,c,l]),{showColumnSettingsPanel:b,showTableSettingsPanel:i.current}};var ye=e=>e,{KEY:Jl,IS_EXPANDED:vt,IS_LEAF:ht}=Xl,Yl={draggable:void 0,onMouseDown:void 0},Zl=()=>Yl,jl=(e,o)=>({...e,columns:e.columns.concat(o)}),xt=({allowDragDrop:e=!1,availableColumns:o,config:t,containerRef:r,dataSource:n,disableFocus:l,headerHeight:s=25,highlightedIndex:i,id:a,navigationStyle:u="cell",onAvailableColumnsChange:c,onConfigChange:d,onDragStart:g,onDrop:b,onFeatureInvocation:C,onHighlight:h,onRowClick:m,onSelect:v,onSelectionChange:R,renderBufferSize:P=0,rowHeight:I=20,scrollingApiRef:E,selectionModel:k,size:F})=>{let[K,V]=Ct(n.size);if(n===void 0)throw Error("no data source provided to Vuu Table");let B=e?Gl:Zl,O=oo(()=>ko(n),[n]),T=L(p=>{V(p)},[]),{columns:M,dispatchColumnAction:w,headings:N,tableAttributes:z,tableConfig:y}=rt(t,n);gt(()=>{w({type:"init",dataSource:n,tableConfig:y})},[y,n,w]);let f=L(p=>{w({type:"init",tableConfig:p,dataSource:n}),d==null||d(ye(p))},[n,w,d]),[x,D]=Ct(),[S,$]=oo(()=>{let p=(H,A)=>{let G=ft(M,H,{width:A});D(G)};return[x!=null?x:M,p]},[M,x]),Pe=oo(()=>Ol(n.columns),[n.columns]),{getRowAtPosition:Ee,getRowOffset:Se,setPctScrollTop:de,...j}=dt({columns:S,headerHeight:s,headings:N,rowCount:K,rowHeight:I,size:F}),pe=Wo({from:0,to:j.rowCount===0?0:j.rowCount+1}),ne=L(({tableSchema:p})=>{p?w({type:"setTableSchema",tableSchema:p}):console.log("subscription message with no schema")},[w]),{data:be,dataRef:_,getSelectedRows:ke,range:Le,setRange:fe}=Oo({dataSource:n,onFeatureInvocation:C,renderBufferSize:P,onSizeChange:T,onSubscribed:ne,range:pe}),q=L(p=>{w({type:"init",tableConfig:p,dataSource:n}),d==null||d(ye(p))},[n,w,d]),kt=L(p=>{n.config={...n.config,...p}},[n]);Ql(()=>{n.on("config",(p,H)=>{w({type:"tableConfig",...p,confirmed:H})})},[n,w]);let Lt=L(p=>{n.columns=n.columns.concat(p.name),f(jl(y,p))},[n,y,f]),ro=L(p=>{let{columns:H}=p,A=H.map(U=>U.name),G={...y,columns:y.columns.map(U=>A.includes(U.name)?{...U,hidden:!0}:U)};f(G)},[y,f]),lo=L(p=>{f({...y,columns:ft(y.columns,{...p.column,pin:p.pin})})},[y,f]),{showColumnSettingsPanel:io,showTableSettingsPanel:ao}=pt({availableColumns:o!=null?o:y.columns.map(({name:p,serverDataType:H="string"})=>({name:p,serverDataType:H})),onAvailableColumnsChange:c,onConfigChange:q,onCreateCalculatedColumn:Lt,onDataSourceConfigChange:kt,tableConfig:y}),At=L(p=>{if(tt(p))io(p);else if(nt(p))ao();else switch(p.type){case"hideColumns":return ro(p);case"pinColumn":return lo(p);default:w(p)}},[w,ro,lo,io,ao]),It=zo({dataSource:n,onPersistentColumnOperation:At}),zt=L((p,H=!1,A)=>{n&&(n.sort=Bl(n.sort,p,H,A))},[n]),Nt=L((p,H,A)=>{let G=S.find(U=>U.name===H);if(G)p==="resize"?bt(A)&&$(H,A):p==="end"?bt(A)&&(w({type:"resizeColumn",phase:p,column:G,width:A}),D(void 0),d==null||d(ye(No(y,{type:"col-size",column:G,width:A})))):(D(void 0),w({type:"resizeColumn",phase:p,column:G,width:A}));else throw Error(`useDataTable.handleColumnResize, column ${H} not found`)},[S,y,w,d,$]),Ft=L((p,H)=>{var U,go;let A=_l(H,p),G=p[Jl];if(p[vt]){if(n.closeTreeNode(G,!0),A){let ce=S.indexOf(H),me=(U=n.getRowsAtDepth)==null?void 0:U.call(n,ce+1);me&&!me.some(re=>re[vt]||re[ht])&&w({type:"hideColumns",columns:S.slice(ce+2)})}}else if(n.openTreeNode(G),A){let ce=(go=n.getChildRows)==null?void 0:go.call(n,G),me=S.indexOf(H)+1,re=[S[me]];ce&&ce.some(Ae=>Ae[ht])&&re.push(S[me+1]),re.some(Ae=>Ae.hidden)&&w({type:"showColumns",columns:re})}},[S,n,w]),Kt=L((p,H)=>{de(H)},[de]),{requestScroll:Vt,...$t}=ct({getRowAtPosition:Ee,rowHeight:I,scrollingApiRef:E,setRange:fe,onVerticalScroll:Kt,viewportMeasurements:j}),{highlightedIndexRef:so,navigate:Gt,onFocus:uo,onKeyDown:co,...Bt}=Jo({columnCount:S.filter(p=>p.hidden!==!0).length,containerRef:r,disableFocus:l,highlightedIndex:i,navigationStyle:u,requestScroll:Vt,rowCount:n==null?void 0:n.size,onHighlight:h,viewportRange:Le,viewportRowCount:j.rowCount}),{onBlur:Ot,onDoubleClick:Wt,onKeyDown:mo,onFocus:po}=$o({navigate:Gt}),Ut=L(p=>{uo(),p.defaultPrevented||po(p)},[po,uo]),_t=jo({columns:S,data:be,dataSource:n,getSelectedRows:ke}),Xt=L(p=>{n.groupBy=p.map(H=>H.name)},[n]),Qt=L(p=>{Ul(p)?n.groupBy=[]:n&&n.groupBy.includes(p.name)&&(n.groupBy=n.groupBy.filter(H=>H!==p.name))},[n]),Jt=L(p=>{n.select(p),R==null||R(p)},[n,R]),{onKeyDown:bo,onRowClick:fo}=Zo({highlightedIndexRef:so,onSelect:v,onSelectionChange:Jt,selectionModel:k}),Yt=L(p=>{co(p),p.defaultPrevented||mo(p),p.defaultPrevented||bo(p)},[co,mo,bo]),Zt=L((p,H,A)=>{fo(p,H,A),m==null||m(p)},[m,fo]);gt(()=>{w({type:"init",tableConfig:t,dataSource:n})},[t,n,w]);let jt=L(p=>{console.log("useTable onMoveColumn",{columns:p});let H={...y,columns:p};w({type:"init",tableConfig:H,dataSource:n}),d==null||d(ye(H))},[n,w,d,y]),qt=L(p=>{b==null||b(p)},[b]),en=L(async(p,H,A)=>n.applyEdit(p,H,A),[n]),on=L(p=>{let{initialDragElement:H}=p,A=Wl(H),G=_.current.find(U=>U[0]===A);G&&p.setPayload(G),g==null||g(p)},[_,g]),{onMouseDown:tn,draggable:nn}=B({allowDragDrop:e,containerRef:r,draggableClassName:"vuuTable",id:a,onDragStart:on,onDrop:qt,orientation:"vertical",itemQuery:".vuuTableRow"});return{...Bt,"aria-rowcount":n.size,draggableRow:nn,onBlur:Ot,onDoubleClick:Wt,onFocus:Ut,onKeyDown:Yt,onMouseDown:tn,columnMap:Pe,columns:S,data:be,getRowOffset:Se,handleContextMenuAction:It,headings:N,highlightedIndex:so.current,menuBuilder:O,onContextMenu:_t,onDataEdited:en,onMoveColumn:jt,onMoveGroupColumn:Xt,onRemoveGroupColumn:Qt,onRowClick:Zt,onSortColumn:zt,onResizeColumn:Nt,onToggleGroup:Ft,scrollProps:$t,tableAttributes:z,tableConfig:y,viewportMeasurements:j}};import{isGroupColumn as ti,isNotHidden as ni}from"@vuu-ui/vuu-utils";import ri from"clsx";import{useDragDrop as ql}from"@vuu-ui/vuu-ui-controls";import{moveColumnTo as to,visibleColumnAtIndex as ei}from"@vuu-ui/vuu-utils";import{useCallback as wt,useRef as oi}from"react";var Tt=({columns:e,onMoveColumn:o,onSortColumn:t,tableConfig:r})=>{let n=oi(null),l=wt((c,d)=>{let g=e[c],b=to(e,g,d),C=({name:R})=>P=>P.name===R,h=b.findIndex(C(g)),m=b[h+1],v=m?r.columns.findIndex(C(m)):-1;d>c&&v!==-1?o(to(r.columns,g,v-1)):o(to(r.columns,g,v))},[e,o,r.columns]),s=wt(c=>{var m;let g=c.target.closest(".vuuTableHeaderCell"),b=parseInt((m=g==null?void 0:g.dataset.index)!=null?m:"-1"),C=ei(e,b),h=c.shiftKey;C&&t(C,h)},[e,t]),{onMouseDown:i,draggable:a,...u}=ql({allowDragDrop:!0,containerRef:n,draggableClassName:"vuuTable",onDrop:l,orientation:"horizontal",itemQuery:".vuuTableHeaderCell"});return{containerRef:n,draggableColumn:a,draggedColumnIndex:u.draggedItemIndex,onClick:s,onMouseDown:i}};import{jsx as De,jsxs as Rt}from"react/jsx-runtime";var yt=({classBase:e="vuuTable",columns:o,headings:t,onMoveColumn:r,onMoveGroupColumn:n,onRemoveGroupColumn:l,onResizeColumn:s,onSortColumn:i,tableConfig:a,tableId:u})=>{let{containerRef:c,draggableColumn:d,draggedColumnIndex:g,onClick:b,onMouseDown:C}=Tt({columns:o,onMoveColumn:r,onSortColumn:i,tableConfig:a});return Rt("div",{className:`${e}-col-headings`,ref:c,children:[t.map((h,m)=>De("div",{className:"vuuTable-heading",children:h.map(({label:v,width:R},P)=>De("div",{className:"vuuTable-headingCell",style:{width:R},children:v},P))},m)),Rt("div",{className:`${e}-col-headers`,role:"row",children:[o.filter(ni).map((h,m)=>ti(h)?De(Ve,{column:h,"data-index":m,onMoveColumn:n,onRemoveColumn:l,onResize:s},h.name):De(yo,{className:ri({"vuuDraggable-dragAway":m===g}),column:h,"data-index":m,id:`${u}-col-${m}`,onClick:b,onMouseDown:C,onResize:s},h.name)),d]})]})};import{jsx as Z,jsxs as Dt}from"react/jsx-runtime";var J="vuuTable",{IDX:pi,RENDER_IDX:bi}=ai,fi=({Row:e=Oe,allowDragDrop:o,availableColumns:t,config:r,containerRef:n,dataSource:l,disableFocus:s=!1,highlightedIndex:i,id:a,navigationStyle:u="cell",onAvailableColumnsChange:c,onConfigChange:d,onDragStart:g,onDrop:b,onFeatureInvocation:C,onHighlight:h,onRowClick:m,onSelect:v,onSelectionChange:R,renderBufferSize:P=5,rowHeight:I=20,scrollingApiRef:E,selectionModel:k="extended",showColumnHeaders:F=!0,headerHeight:K=F?25:0,size:V})=>{let B=si(a),{columnMap:O,columns:T,data:M,draggableRow:w,getRowOffset:N,handleContextMenuAction:z,headings:y,highlightedIndex:f,onDataEdited:x,onMoveColumn:D,onMoveGroupColumn:S,onRemoveGroupColumn:$,onResizeColumn:Pe,onRowClick:Ee,onSortColumn:Se,onToggleGroup:de,menuBuilder:j,scrollProps:pe,tableAttributes:ne,tableConfig:be,viewportMeasurements:_,...ke}=xt({allowDragDrop:o,availableColumns:t,config:r,containerRef:n,dataSource:l,disableFocus:s,headerHeight:K,highlightedIndex:i,id:B,navigationStyle:u,onAvailableColumnsChange:c,onConfigChange:d,onDragStart:g,onDrop:b,onFeatureInvocation:C,onHighlight:h,onRowClick:m,onSelect:v,onSelectionChange:R,renderBufferSize:P,rowHeight:I,scrollingApiRef:E,selectionModel:k,size:V}),Le=Mt(`${J}-contentContainer`,{[`${J}-colLines`]:ne.columnSeparators,[`${J}-rowLines`]:ne.rowSeparators,[`${J}-zebra`]:ne.zebraStripes}),fe={"--content-height":`${_.contentHeight}px`,"--content-width":`${_.contentWidth}px`,"--horizontal-scrollbar-height":`${_.horizontalScrollbarHeight}px`,"--pinned-width-left":`${_.pinnedWidthLeft}px`,"--pinned-width-right":`${_.pinnedWidthRight}px`,"--header-height":`${K}px`,"--row-height":`${I}px`,"--total-header-height":`${_.totalHeaderHeight}px`,"--vertical-scrollbar-width":`${_.verticalScrollbarWidth}px`,"--viewport-body-height":`${_.viewportBodyHeight}px`};return Dt(ii,{menuActionHandler:z,menuBuilder:j,children:[Z("div",{className:`${J}-scrollbarContainer`,ref:pe.scrollbarContainerRef,style:fe,children:Z("div",{className:`${J}-scrollbarContent`})}),Z("div",{className:Le,ref:pe.contentContainerRef,style:fe,children:Dt("div",{...ke,className:`${J}-table`,role:"table",tabIndex:s?void 0:-1,children:[F?Z(yt,{columns:T,headings:y,onMoveColumn:D,onMoveGroupColumn:S,onRemoveGroupColumn:$,onResizeColumn:Pe,onSortColumn:Se,tableConfig:be,tableId:B}):null,Z("div",{className:`${J}-body`,children:M.map(q=>Z(e,{"aria-rowindex":q[0]+1,columnMap:O,columns:T,highlighted:f===q[pi],onClick:Ee,onDataEdited:x,row:q,offset:N(q),onToggleGroup:de,zebraStripes:ne.zebraStripes},q[bi]))})]})}),w]})},um=ci(function({Row:o,allowDragDrop:t,availableColumns:r,className:n,config:l,dataSource:s,disableFocus:i,highlightedIndex:a,id:u,navigationStyle:c,onAvailableColumnsChange:d,onConfigChange:g,onDragStart:b,onDrop:C,onFeatureInvocation:h,onHighlight:m,onRowClick:v,onSelect:R,onSelectionChange:P,renderBufferSize:I,rowHeight:E,scrollingApiRef:k,selectionModel:F,showColumnHeaders:K,headerHeight:V,style:B,...O},T){let M=mi(null),[w,N]=di();if(l===void 0)throw Error("vuu Table requires config prop. Minimum config is list of Column Descriptors");if(s===void 0)throw Error("vuu Table requires dataSource prop");return Z(li,{...O,className:Mt(J,n),id:u,onResize:N,ref:ui(M,T),children:w?Z(fi,{Row:o,allowDragDrop:t,availableColumns:r,config:l,containerRef:M,dataSource:s,disableFocus:i,headerHeight:V,highlightedIndex:a,id:u,navigationStyle:c,onAvailableColumnsChange:d,onConfigChange:g,onDragStart:b,onDrop:C,onFeatureInvocation:h,onHighlight:m,onRowClick:v,onSelect:R,onSelectionChange:P,renderBufferSize:I,rowHeight:E,scrollingApiRef:k,selectionModel:F,showColumnHeaders:K,size:w}):null})});import{memo as gi,useCallback as Ci}from"react";import{CheckboxIcon as vi,WarnCommit as hi}from"@vuu-ui/vuu-ui-controls";import{Checkbox as xi}from"@salt-ds/core";var Me=(e,o)=>e.column===o.column&&e.column.valueFormatter(e.row[e.columnMap[e.column.name]])===o.column.valueFormatter(o.row[o.columnMap[o.column.name]]);import{dispatchCustomEvent as wi,registerComponent as Ti}from"@vuu-ui/vuu-utils";import{jsx as Ht}from"react/jsx-runtime";var Pt=gi(({column:e,columnMap:o,onCommit:t=hi,row:r})=>{let n=o[e.name],l=r[n],s=Ci(i=>async a=>{let u=await t(i);return u===!0&&wi(a.target,"vuu-commit"),u},[t]);return e.editable?Ht(xi,{checked:l,onClick:s(!l)}):Ht(vi,{checked:l,disabled:!0})},Me);Pt.displayName="CheckboxCell";Ti("checkbox-cell",Pt,"cell-renderer",{serverDataType:"boolean"});import{registerComponent as Ri}from"@vuu-ui/vuu-utils";import{Input as yi}from"@salt-ds/core";import{useEditableText as Di}from"@vuu-ui/vuu-ui-controls";import Mi from"clsx";import{jsx as no}from"react/jsx-runtime";var He="vuuTableInputCell",Hi=()=>(console.warn("onCommit handler has not been provided to InputCell cell renderer"),Promise.resolve(!0)),Pi=({column:e,columnMap:o,onCommit:t=Hi,row:r})=>{let n=o[e.name],{align:l="left",clientSideEditValidationCheck:s}=e,{warningMessage:i,...a}=Di({initialValue:r[n],onCommit:t,clientSideEditValidationCheck:s}),u=i&&l==="left"?no("span",{className:`${He}-icon`,"data-icon":"error"}):void 0,c=i&&l==="right"?no("span",{className:`${He}-icon`,"data-icon":"error"}):void 0;return no(yi,{...a,className:Mi(He,{[`${He}-error`]:i!==void 0}),endAdornment:u,startAdornment:c})};Ri("input-cell",Pi,"cell-renderer",{});import{WarnCommit as Ei}from"@vuu-ui/vuu-ui-controls";import{dispatchCustomEvent as Si,isTypeDescriptor as ki,isValueListRenderer as Li,registerComponent as Ai}from"@vuu-ui/vuu-utils";import Ii from"clsx";import{memo as zi,useCallback as Ni}from"react";import{CycleStateButton as Fi}from"@vuu-ui/vuu-ui-controls";import{jsx as $i}from"react/jsx-runtime";var Et="vuuTableToggleCell",Ki=({name:e,type:o})=>{if(ki(o)&&Li(o.renderer))return o.renderer.values;throw Error(`useLookupValues column ${e} has not been configured with a values list`)},Vi=zi(function({column:o,columnMap:t,onCommit:r=Ei,row:n}){let l=Ki(o),s=t[o.name],i=n[s],a=Ni((u,c)=>r(c).then(d=>(d===!0&&Si(u.target,"vuu-commit"),d)),[r]);return $i(Fi,{className:Ii(Et,`${Et}-${o.name}`),onCommit:a,value:i,values:l,variant:"cta",children:i})},Me);Ai("toggle-cell",Vi,"cell-renderer",{});import{useStateRef as Gi}from"@vuu-ui/vuu-ui-controls";import{dispatchMouseEvent as Bi}from"@vuu-ui/vuu-utils";import{useCallback as St,useRef as Oi}from"react";var nd=(e,o)=>{let t=Oi(null),[r,n]=Gi(e),l=St(i=>{var a;if(i.key==="ArrowDown")n((u=-1)=>Math.min(o-1,u+1));else if(i.key==="ArrowUp")n((u=-1)=>Math.max(0,u-1));else if(i.key==="Enter"||i.key===" "){let{current:u}=r,c=(a=t.current)==null?void 0:a.querySelector(`[aria-rowindex="${u}"]`);c&&Bi(c,"click")}},[r,o,n]),s=St(i=>{n(i)},[n]);return{highlightedIndexRef:r,onHighlight:s,onKeyDown:l,tableRef:t}};export{Pt as CheckboxCell,Ve as GroupHeaderCellNext,yo as HeaderCell,Pi as InputCell,um as Table,Ho as TableCell,Po as TableGroupCell,Vi as ToggleCell,Me as dataAndColumnUnchanged,Sl as howFarIsRowOutsideViewport,tt as isShowColumnSettings,nt as isShowTableSettings,Pl as noScrolling,No as updateTableConfig,nd as useControlledTableNavigation,rt as useTableModel,ct as useTableScroll,dt as useTableViewport};
1
+ // src/header-cell/GroupHeaderCellNext.tsx
2
+ import { OverflowContainer } from "@vuu-ui/vuu-ui-controls";
3
+ import { useLayoutEffectSkipFirst } from "@vuu-ui/vuu-utils";
4
+ import cx3 from "clsx";
5
+ import { useCallback as useCallback4, useRef as useRef3, useState as useState2 } from "react";
6
+
7
+ // src/column-header-pill/ColumnHeaderPill.tsx
8
+ import cx from "clsx";
9
+ import { useCallback } from "react";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ var classBase = "vuuColumnHeaderPill";
12
+ var ColumnHeaderPill = ({
13
+ children,
14
+ className,
15
+ column,
16
+ onRemove,
17
+ removable,
18
+ ...htmlAttributes
19
+ }) => {
20
+ if (removable && typeof onRemove !== "function") {
21
+ throw Error(
22
+ "ColumnHeaderPill onRemove prop must be provided if Pill is removable"
23
+ );
24
+ }
25
+ const handleClickRemove = useCallback(
26
+ (evt) => {
27
+ evt.preventDefault();
28
+ evt.stopPropagation();
29
+ onRemove == null ? void 0 : onRemove(column);
30
+ },
31
+ [column, onRemove]
32
+ );
33
+ return /* @__PURE__ */ jsxs("div", { ...htmlAttributes, className: cx(classBase, className), children: [
34
+ children,
35
+ removable ? /* @__PURE__ */ jsx(
36
+ "span",
37
+ {
38
+ className: `${classBase}-removeButton`,
39
+ role: "button",
40
+ "data-icon": "cross",
41
+ onClick: handleClickRemove
42
+ }
43
+ ) : null
44
+ ] });
45
+ };
46
+
47
+ // src/column-header-pill/GroupColumnPill.tsx
48
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
49
+ var GroupColumnPill = ({
50
+ column,
51
+ ...columnHeaderProps
52
+ }) => {
53
+ const { name, sorted } = column;
54
+ const icon = typeof sorted === "number" ? sorted < 0 ? "arrow-down" : "arrow-up" : sorted === "A" ? "arrow-up" : sorted === "D" ? "arrow-down" : void 0;
55
+ return /* @__PURE__ */ jsxs2(ColumnHeaderPill, { ...columnHeaderProps, column, children: [
56
+ /* @__PURE__ */ jsx2("span", { className: "vuuGroupColumnPill-label", children: name }),
57
+ icon !== void 0 ? /* @__PURE__ */ jsx2("span", { "data-icon": icon }) : null,
58
+ typeof sorted === "number" ? /* @__PURE__ */ jsx2("span", { className: "vuuSortPosition", children: Math.abs(sorted) }) : null
59
+ ] });
60
+ };
61
+
62
+ // src/column-header-pill/SortIndicator.tsx
63
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
64
+ var SortIndicator = ({ column }) => {
65
+ if (!column.sorted) {
66
+ return null;
67
+ }
68
+ const icon = typeof column.sorted === "number" ? column.sorted < 0 ? "arrow-down" : "arrow-up" : column.sorted === "A" ? "arrow-up" : "arrow-down";
69
+ return /* @__PURE__ */ jsxs3(ColumnHeaderPill, { column, children: [
70
+ /* @__PURE__ */ jsx3("span", { "data-icon": icon }),
71
+ typeof column.sorted === "number" ? /* @__PURE__ */ jsx3("span", { className: "vuuSortPosition", children: Math.abs(column.sorted) }) : null
72
+ ] });
73
+ };
74
+
75
+ // src/column-resizing/ColumnResizer.tsx
76
+ import { useCallback as useCallback2, useRef } from "react";
77
+ import { jsx as jsx4 } from "react/jsx-runtime";
78
+ var NOOP = () => void 0;
79
+ var baseClass = "vuuColumnResizerNext";
80
+ var ColumnResizer = ({
81
+ onDrag,
82
+ onDragEnd = NOOP,
83
+ onDragStart = NOOP
84
+ }) => {
85
+ const positionRef = useRef({ start: 0, now: 0 });
86
+ const onMouseMove = useCallback2(
87
+ (e) => {
88
+ if (e.stopPropagation) {
89
+ e.stopPropagation();
90
+ }
91
+ if (e.preventDefault) {
92
+ e.preventDefault();
93
+ }
94
+ const { current: position } = positionRef;
95
+ const x = Math.round(e.clientX);
96
+ const moveBy = x - position.now;
97
+ const distanceMoved = position.now - position.start;
98
+ positionRef.current.now = x;
99
+ if (moveBy !== 0) {
100
+ onDrag(e, moveBy, distanceMoved);
101
+ }
102
+ },
103
+ [onDrag]
104
+ );
105
+ const onMouseUp = useCallback2(
106
+ (e) => {
107
+ window.removeEventListener("mouseup", onMouseUp);
108
+ window.removeEventListener("mousemove", onMouseMove);
109
+ const { current: position } = positionRef;
110
+ const distanceMoved = position.now - position.start;
111
+ onDragEnd(e, distanceMoved);
112
+ },
113
+ [onDragEnd, onMouseMove]
114
+ );
115
+ const handleMouseDown = useCallback2(
116
+ (e) => {
117
+ const { current: position } = positionRef;
118
+ onDragStart(e);
119
+ position.now = position.start = Math.round(e.clientX);
120
+ window.addEventListener("mouseup", onMouseUp);
121
+ window.addEventListener("mousemove", onMouseMove);
122
+ if (e.stopPropagation) {
123
+ e.stopPropagation();
124
+ }
125
+ if (e.preventDefault) {
126
+ e.preventDefault();
127
+ }
128
+ },
129
+ [onDragStart, onMouseMove, onMouseUp]
130
+ );
131
+ return /* @__PURE__ */ jsx4("div", { className: baseClass, onMouseDown: handleMouseDown });
132
+ };
133
+
134
+ // src/column-resizing/useTableColumnResize.tsx
135
+ import { useCallback as useCallback3, useRef as useRef2, useState } from "react";
136
+ var useTableColumnResize = ({
137
+ column,
138
+ onResize,
139
+ rootRef
140
+ }) => {
141
+ const widthRef = useRef2({ start: 0, now: 0 });
142
+ const [isResizing, setResizing] = useState(false);
143
+ const { name } = column;
144
+ const handleResizeStart = useCallback3(() => {
145
+ if (onResize && rootRef.current) {
146
+ const { current: width } = widthRef;
147
+ const { width: measuredWidth } = rootRef.current.getBoundingClientRect();
148
+ width.start = width.now = Math.round(measuredWidth);
149
+ setResizing(true);
150
+ onResize == null ? void 0 : onResize("begin", name);
151
+ }
152
+ }, [name, onResize, rootRef]);
153
+ const handleResize = useCallback3(
154
+ (_evt, moveBy, totalDistanceMoved) => {
155
+ if (rootRef.current) {
156
+ if (onResize) {
157
+ const { current: width } = widthRef;
158
+ const newWidth = width.start + totalDistanceMoved;
159
+ if (newWidth !== width.now && newWidth > 0) {
160
+ onResize("resize", name, newWidth);
161
+ width.now = newWidth;
162
+ }
163
+ }
164
+ }
165
+ },
166
+ [name, onResize, rootRef]
167
+ );
168
+ const handleResizeEnd = useCallback3(() => {
169
+ if (onResize) {
170
+ const { current: width } = widthRef;
171
+ onResize("end", name, width.now);
172
+ setTimeout(() => {
173
+ setResizing(false);
174
+ }, 80);
175
+ }
176
+ }, [name, onResize]);
177
+ return {
178
+ isResizing,
179
+ onDrag: handleResize,
180
+ onDragStart: handleResizeStart,
181
+ onDragEnd: handleResizeEnd
182
+ };
183
+ };
184
+
185
+ // src/useCell.ts
186
+ import { getColumnStyle } from "@vuu-ui/vuu-utils";
187
+ import cx2 from "clsx";
188
+ import { useMemo } from "react";
189
+ var useCell = (column, classBase10, isHeader) => (
190
+ // TODO measure perf without the memo, might not be worth the cost
191
+ useMemo(() => {
192
+ const className = cx2(classBase10, {
193
+ vuuPinFloating: column.pin === "floating",
194
+ vuuPinLeft: column.pin === "left",
195
+ vuuPinRight: column.pin === "right",
196
+ vuuEndPin: isHeader && column.endPin,
197
+ // [`${classBase}-resizing`]: column.resizing,
198
+ [`${classBase10}-editable`]: column.editable,
199
+ [`${classBase10}-right`]: column.align === "right"
200
+ });
201
+ const style = getColumnStyle(column);
202
+ return {
203
+ className,
204
+ style
205
+ };
206
+ }, [column, classBase10, isHeader])
207
+ );
208
+
209
+ // src/header-cell/GroupHeaderCellNext.tsx
210
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
211
+ import { createElement } from "react";
212
+ var classBase2 = "vuuTableGroupHeaderCell";
213
+ var switchIfChanged = (columns, newColumns) => {
214
+ if (columns === newColumns) {
215
+ return columns;
216
+ } else {
217
+ return newColumns;
218
+ }
219
+ };
220
+ var GroupHeaderCellNext = ({
221
+ column: groupColumn,
222
+ className: classNameProp,
223
+ onMoveColumn,
224
+ onRemoveColumn,
225
+ onResize,
226
+ ...htmlAttributes
227
+ }) => {
228
+ const rootRef = useRef3(null);
229
+ const { isResizing, ...resizeProps } = useTableColumnResize({
230
+ column: groupColumn,
231
+ onResize,
232
+ rootRef
233
+ });
234
+ const [columns, setColumns] = useState2(groupColumn.columns);
235
+ const { className, style } = useCell(groupColumn, classBase2, true);
236
+ const columnPillProps = columns.length > 1 ? {
237
+ removable: true,
238
+ onRemove: onRemoveColumn
239
+ } : void 0;
240
+ const handleMoveItem = useCallback4(
241
+ (fromIndex, toIndex) => {
242
+ setColumns((cols) => {
243
+ const newCols = cols.slice();
244
+ const [tab] = newCols.splice(fromIndex, 1);
245
+ if (toIndex === -1) {
246
+ const result = newCols.concat(tab);
247
+ onMoveColumn == null ? void 0 : onMoveColumn(result);
248
+ return result;
249
+ } else {
250
+ newCols.splice(toIndex, 0, tab);
251
+ onMoveColumn == null ? void 0 : onMoveColumn(newCols);
252
+ return newCols;
253
+ }
254
+ });
255
+ },
256
+ [onMoveColumn]
257
+ );
258
+ useLayoutEffectSkipFirst(() => {
259
+ setColumns((cols) => switchIfChanged(cols, groupColumn.columns));
260
+ }, [groupColumn.columns]);
261
+ return /* @__PURE__ */ jsxs4(
262
+ "div",
263
+ {
264
+ ...htmlAttributes,
265
+ className: cx3(className, classNameProp, {
266
+ [`${classBase2}-pending`]: groupColumn.groupConfirmed === false
267
+ }),
268
+ ref: rootRef,
269
+ role: "columnheader",
270
+ style,
271
+ children: [
272
+ /* @__PURE__ */ jsx5(
273
+ OverflowContainer,
274
+ {
275
+ allowDragDrop: true,
276
+ className: `${classBase2}-inner`,
277
+ height: 24,
278
+ onMoveItem: handleMoveItem,
279
+ overflowPosition: "start",
280
+ children: columns.map((column) => {
281
+ return /* @__PURE__ */ createElement(
282
+ GroupColumnPill,
283
+ {
284
+ ...columnPillProps,
285
+ column,
286
+ key: column.name
287
+ }
288
+ );
289
+ })
290
+ }
291
+ ),
292
+ /* @__PURE__ */ jsx5(
293
+ ColumnHeaderPill,
294
+ {
295
+ column: groupColumn,
296
+ removable: true,
297
+ onRemove: onRemoveColumn
298
+ }
299
+ ),
300
+ groupColumn.resizeable !== false ? /* @__PURE__ */ jsx5(ColumnResizer, { ...resizeProps }) : null
301
+ ]
302
+ }
303
+ );
304
+ };
305
+
306
+ // src/header-cell/HeaderCell.tsx
307
+ import cx5 from "clsx";
308
+ import { useCallback as useCallback6, useRef as useRef5 } from "react";
309
+
310
+ // src/column-menu/ColumnMenu.tsx
311
+ import { useContextMenu } from "@vuu-ui/vuu-popups";
312
+ import cx4 from "clsx";
313
+ import {
314
+ useCallback as useCallback5,
315
+ useRef as useRef4,
316
+ useState as useState3
317
+ } from "react";
318
+ import { jsx as jsx6 } from "react/jsx-runtime";
319
+ var getPosition = (element) => {
320
+ if (element) {
321
+ const { bottom, left } = element.getBoundingClientRect();
322
+ return { x: left, y: bottom + 6 };
323
+ }
324
+ };
325
+ var ColumnMenu = ({
326
+ className,
327
+ column,
328
+ ...props
329
+ }) => {
330
+ const rootRef = useRef4(null);
331
+ const [menuOpen, setMenuOpen] = useState3(false);
332
+ const [showContextMenu] = useContextMenu();
333
+ const handleMenuClose = useCallback5(() => {
334
+ setMenuOpen(false);
335
+ }, []);
336
+ const showColumnMenu = useCallback5(
337
+ (e) => {
338
+ setMenuOpen(true);
339
+ showContextMenu(e, "column-menu", {
340
+ column,
341
+ ContextMenuProps: {
342
+ onClose: handleMenuClose,
343
+ position: getPosition(rootRef.current)
344
+ }
345
+ });
346
+ },
347
+ [column, handleMenuClose, showContextMenu]
348
+ );
349
+ return /* @__PURE__ */ jsx6(
350
+ "span",
351
+ {
352
+ ...props,
353
+ className: cx4("vuuTable-columnMenu", className, {
354
+ "vuuTable-columnMenu-open": menuOpen
355
+ }),
356
+ "data-icon": "more-vert",
357
+ onClick: showColumnMenu,
358
+ ref: rootRef
359
+ }
360
+ );
361
+ };
362
+
363
+ // src/header-cell/HeaderCell.tsx
364
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
365
+ var classBase3 = "vuuTableHeaderCell";
366
+ var HeaderCell = ({
367
+ className: classNameProp,
368
+ column,
369
+ onClick,
370
+ onResize,
371
+ ...htmlAttributes
372
+ }) => {
373
+ var _a;
374
+ const { HeaderCellContentRenderer, HeaderCellLabelRenderer } = column;
375
+ const rootRef = useRef5(null);
376
+ const { isResizing, ...resizeProps } = useTableColumnResize({
377
+ column,
378
+ onResize,
379
+ rootRef
380
+ });
381
+ const handleClick = useCallback6(
382
+ (evt) => {
383
+ !isResizing && (onClick == null ? void 0 : onClick(evt));
384
+ },
385
+ [isResizing, onClick]
386
+ );
387
+ const { className, style } = useCell(column, classBase3, true);
388
+ const columnMenu = /* @__PURE__ */ jsx7(ColumnMenu, { column });
389
+ const columnLabel = HeaderCellLabelRenderer ? /* @__PURE__ */ jsx7(HeaderCellLabelRenderer, { className: `${classBase3}-label`, column }) : /* @__PURE__ */ jsx7("div", { className: `${classBase3}-label`, children: (_a = column.label) != null ? _a : column.name });
390
+ const columnContent = HeaderCellContentRenderer ? [/* @__PURE__ */ jsx7(HeaderCellContentRenderer, { column }, "content")] : [];
391
+ const sortIndicator = /* @__PURE__ */ jsx7(SortIndicator, { column });
392
+ const headerItems = column.align === "right" ? [sortIndicator, columnLabel].concat(columnContent).concat(columnMenu) : [columnMenu, columnLabel, sortIndicator].concat(columnContent);
393
+ return /* @__PURE__ */ jsxs5(
394
+ "div",
395
+ {
396
+ ...htmlAttributes,
397
+ className: cx5(className, classNameProp, {
398
+ [`${classBase3}-resizing`]: isResizing
399
+ }),
400
+ onClick: handleClick,
401
+ ref: rootRef,
402
+ role: "columnheader",
403
+ style,
404
+ children: [
405
+ ...headerItems,
406
+ column.resizeable !== false ? /* @__PURE__ */ jsx7(ColumnResizer, { ...resizeProps }) : null
407
+ ]
408
+ }
409
+ );
410
+ };
411
+
412
+ // src/Table.tsx
413
+ import { ContextMenuProvider } from "@vuu-ui/vuu-popups";
414
+ import {
415
+ MeasuredContainer
416
+ } from "@vuu-ui/vuu-ui-controls";
417
+ import { metadataKeys as metadataKeys6, useId } from "@vuu-ui/vuu-utils";
418
+ import { useForkRef } from "@salt-ds/core";
419
+ import cx9 from "clsx";
420
+ import {
421
+ forwardRef,
422
+ useRef as useRef15,
423
+ useState as useState8
424
+ } from "react";
425
+
426
+ // src/Row.tsx
427
+ import {
428
+ isGroupColumn,
429
+ isJsonColumn,
430
+ isJsonGroup,
431
+ metadataKeys as metadataKeys2,
432
+ isNotHidden,
433
+ RowSelected
434
+ } from "@vuu-ui/vuu-utils";
435
+ import cx7 from "clsx";
436
+ import { memo, useCallback as useCallback9 } from "react";
437
+
438
+ // src/table-cell/TableCell.tsx
439
+ import { isNumericColumn } from "@vuu-ui/vuu-utils";
440
+ import { useCallback as useCallback7 } from "react";
441
+ import { jsx as jsx8 } from "react/jsx-runtime";
442
+ var classBase4 = "vuuTableCell";
443
+ var TableCell = ({
444
+ column,
445
+ columnMap,
446
+ onClick,
447
+ onDataEdited,
448
+ row
449
+ }) => {
450
+ const { className, style } = useCell(column, classBase4);
451
+ const { CellRenderer, index, name, valueFormatter } = column;
452
+ const dataIdx = columnMap[name];
453
+ const handleDataItemEdited = useCallback7(
454
+ (value) => {
455
+ if (onDataEdited) {
456
+ let typedValue = value;
457
+ if (isNumericColumn(column) && typeof value === "string") {
458
+ typedValue = column.serverDataType === "double" ? parseFloat(value) : parseInt(value);
459
+ }
460
+ return onDataEdited == null ? void 0 : onDataEdited(row, name, typedValue);
461
+ } else {
462
+ throw Error(
463
+ "TableCell onDataEdited prop not supplied for an editable cell"
464
+ );
465
+ }
466
+ },
467
+ [column, name, onDataEdited, row]
468
+ );
469
+ const handleClick = useCallback7(
470
+ (evt) => {
471
+ onClick == null ? void 0 : onClick(evt, column);
472
+ },
473
+ [column, onClick]
474
+ );
475
+ return /* @__PURE__ */ jsx8(
476
+ "div",
477
+ {
478
+ "aria-colindex": index,
479
+ className,
480
+ onClick: onClick ? handleClick : void 0,
481
+ role: "cell",
482
+ style,
483
+ children: CellRenderer ? /* @__PURE__ */ jsx8(
484
+ CellRenderer,
485
+ {
486
+ column,
487
+ columnMap,
488
+ onCommit: handleDataItemEdited,
489
+ row
490
+ }
491
+ ) : valueFormatter(row[dataIdx])
492
+ }
493
+ );
494
+ };
495
+
496
+ // src/table-cell/TableGroupCell.tsx
497
+ import { getGroupValueAndOffset, metadataKeys } from "@vuu-ui/vuu-utils";
498
+ import { useCallback as useCallback8 } from "react";
499
+ import cx6 from "clsx";
500
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
501
+ var { IS_LEAF } = metadataKeys;
502
+ var classBase5 = "vuuTableGroupCell";
503
+ var TableGroupCell = ({
504
+ column,
505
+ columnMap,
506
+ onClick,
507
+ row
508
+ }) => {
509
+ const { columns } = column;
510
+ const [value, offset] = getGroupValueAndOffset(columns, row, columnMap);
511
+ const { className, style } = useCell(column, classBase5);
512
+ const handleClick = useCallback8(
513
+ (evt) => {
514
+ onClick == null ? void 0 : onClick(evt, column);
515
+ },
516
+ [column, onClick]
517
+ );
518
+ const isLeaf = row[IS_LEAF];
519
+ const spacers = Array(offset).fill(0).map((n, i) => /* @__PURE__ */ jsx9("span", { className: `${classBase5}-spacer` }, i));
520
+ return /* @__PURE__ */ jsxs6(
521
+ "div",
522
+ {
523
+ className: cx6(className, "vuuTableCell"),
524
+ role: "cell",
525
+ style,
526
+ onClick: isLeaf ? void 0 : handleClick,
527
+ children: [
528
+ spacers,
529
+ isLeaf ? null : /* @__PURE__ */ jsx9("span", { className: `${classBase5}-toggle`, "data-icon": "triangle-right" }),
530
+ /* @__PURE__ */ jsx9("span", { children: value })
531
+ ]
532
+ }
533
+ );
534
+ };
535
+
536
+ // src/Row.tsx
537
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
538
+ var { IDX, IS_EXPANDED, SELECTED } = metadataKeys2;
539
+ var classBase6 = "vuuTableRow";
540
+ var Row = memo(
541
+ ({
542
+ className: classNameProp,
543
+ columnMap,
544
+ columns,
545
+ highlighted,
546
+ row,
547
+ offset,
548
+ onClick,
549
+ onDataEdited,
550
+ onToggleGroup,
551
+ virtualColSpan = 0,
552
+ zebraStripes = false,
553
+ ...htmlAttributes
554
+ }) => {
555
+ const {
556
+ [IDX]: rowIndex,
557
+ [IS_EXPANDED]: isExpanded,
558
+ [SELECTED]: selectionStatus
559
+ } = row;
560
+ const handleRowClick = useCallback9(
561
+ (evt) => {
562
+ const rangeSelect = evt.shiftKey;
563
+ const keepExistingSelection = evt.ctrlKey || evt.metaKey;
564
+ onClick == null ? void 0 : onClick(row, rangeSelect, keepExistingSelection);
565
+ },
566
+ [onClick, row]
567
+ );
568
+ const { True, First, Last } = RowSelected;
569
+ const className = cx7(classBase6, classNameProp, {
570
+ [`${classBase6}-even`]: zebraStripes && rowIndex % 2 === 0,
571
+ [`${classBase6}-expanded`]: isExpanded,
572
+ [`${classBase6}-highlighted`]: highlighted,
573
+ [`${classBase6}-selected`]: selectionStatus & True,
574
+ [`${classBase6}-selectedStart`]: selectionStatus & First,
575
+ [`${classBase6}-selectedEnd`]: selectionStatus & Last
576
+ });
577
+ const style = { transform: `translate3d(0px, ${offset}px, 0px)` };
578
+ const handleGroupCellClick = useCallback9(
579
+ (evt, column) => {
580
+ if (isGroupColumn(column) || isJsonGroup(column, row, columnMap)) {
581
+ evt.stopPropagation();
582
+ onToggleGroup == null ? void 0 : onToggleGroup(row, column);
583
+ }
584
+ },
585
+ [columnMap, onToggleGroup, row]
586
+ );
587
+ return /* @__PURE__ */ jsxs7(
588
+ "div",
589
+ {
590
+ ...htmlAttributes,
591
+ role: "row",
592
+ className,
593
+ onClick: handleRowClick,
594
+ style,
595
+ children: [
596
+ /* @__PURE__ */ jsx10("span", { className: `${classBase6}-selectionDecorator vuuStickyLeft` }),
597
+ virtualColSpan > 0 ? /* @__PURE__ */ jsx10("div", { className: "vuuTableCell", style: { width: virtualColSpan } }) : null,
598
+ columns.filter(isNotHidden).map((column) => {
599
+ const isGroup = isGroupColumn(column);
600
+ const isJsonCell = isJsonColumn(column);
601
+ const Cell = isGroup ? TableGroupCell : TableCell;
602
+ return /* @__PURE__ */ jsx10(
603
+ Cell,
604
+ {
605
+ column,
606
+ columnMap,
607
+ onClick: isGroup || isJsonCell ? handleGroupCellClick : void 0,
608
+ onDataEdited,
609
+ row
610
+ },
611
+ column.name
612
+ );
613
+ }),
614
+ /* @__PURE__ */ jsx10("span", { className: `${classBase6}-selectionDecorator vuuStickyRight` })
615
+ ]
616
+ }
617
+ );
618
+ }
619
+ );
620
+ Row.displayName = "Row";
621
+
622
+ // src/table-header/TableHeader.tsx
623
+ import { isGroupColumn as isGroupColumn2, isNotHidden as isNotHidden2 } from "@vuu-ui/vuu-utils";
624
+ import cx8 from "clsx";
625
+ import { memo as memo2 } from "react";
626
+
627
+ // src/table-header/useTableHeader.ts
628
+ import {
629
+ useDragDrop
630
+ } from "@vuu-ui/vuu-ui-controls";
631
+ import { moveColumnTo, visibleColumnAtIndex } from "@vuu-ui/vuu-utils";
632
+ import { useCallback as useCallback10, useRef as useRef6 } from "react";
633
+ var useTableHeader = ({
634
+ columns,
635
+ onMoveColumn,
636
+ onSortColumn,
637
+ tableConfig
638
+ }) => {
639
+ const containerRef = useRef6(null);
640
+ const scrollingContainerRef = useRef6(null);
641
+ const setContainerRef = useCallback10((el) => {
642
+ containerRef.current = el;
643
+ if (el) {
644
+ scrollingContainerRef.current = el.closest(".vuuTable-contentContainer");
645
+ } else {
646
+ scrollingContainerRef.current = null;
647
+ }
648
+ }, []);
649
+ const handleDropColumnHeader = useCallback10(
650
+ ({ fromIndex: moveFrom, toIndex: moveTo }) => {
651
+ const column = columns[moveFrom];
652
+ const orderedColumns = moveColumnTo(columns, column, moveTo);
653
+ const ofColumn = ({ name }) => (col) => col.name === name;
654
+ const targetIndex = orderedColumns.findIndex(ofColumn(column));
655
+ const nextColumn = orderedColumns[targetIndex + 1];
656
+ const insertPos = nextColumn ? tableConfig.columns.findIndex(ofColumn(nextColumn)) : -1;
657
+ if (moveTo > moveFrom && insertPos !== -1) {
658
+ onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos - 1));
659
+ } else {
660
+ onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos));
661
+ }
662
+ },
663
+ [columns, onMoveColumn, tableConfig.columns]
664
+ );
665
+ const handleColumnHeaderClick = useCallback10(
666
+ (evt) => {
667
+ var _a;
668
+ const targetElement = evt.target;
669
+ const headerCell = targetElement.closest(
670
+ ".vuuTableHeaderCell"
671
+ );
672
+ const colIdx = parseInt((_a = headerCell == null ? void 0 : headerCell.dataset.index) != null ? _a : "-1");
673
+ const column = visibleColumnAtIndex(columns, colIdx);
674
+ const isAdditive = evt.shiftKey;
675
+ column && onSortColumn(column, isAdditive);
676
+ },
677
+ [columns, onSortColumn]
678
+ );
679
+ const {
680
+ onMouseDown: columnHeaderDragMouseDown,
681
+ draggable: draggableColumn,
682
+ ...dragDropHook
683
+ } = useDragDrop({
684
+ allowDragDrop: true,
685
+ containerRef,
686
+ draggableClassName: `vuuTable`,
687
+ itemQuery: ".vuuTableHeaderCell",
688
+ onDrop: handleDropColumnHeader,
689
+ orientation: "horizontal",
690
+ scrollingContainerRef
691
+ });
692
+ return {
693
+ draggableColumn,
694
+ draggedColumnIndex: dragDropHook.draggedItemIndex,
695
+ onClick: handleColumnHeaderClick,
696
+ onMouseDown: columnHeaderDragMouseDown,
697
+ setContainerRef
698
+ };
699
+ };
700
+
701
+ // src/table-header/TableHeader.tsx
702
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
703
+ var TableHeader = memo2(
704
+ ({
705
+ classBase: classBase10 = "vuuTable",
706
+ columns,
707
+ headings,
708
+ onMoveColumn,
709
+ onMoveGroupColumn,
710
+ onRemoveGroupColumn,
711
+ onResizeColumn,
712
+ onSortColumn,
713
+ tableConfig,
714
+ tableId,
715
+ virtualColSpan = 0
716
+ }) => {
717
+ const {
718
+ draggableColumn,
719
+ draggedColumnIndex,
720
+ onClick,
721
+ onMouseDown,
722
+ setContainerRef
723
+ } = useTableHeader({
724
+ columns,
725
+ onMoveColumn,
726
+ onSortColumn,
727
+ tableConfig
728
+ });
729
+ return /* @__PURE__ */ jsxs8("div", { className: `${classBase10}-col-headings`, ref: setContainerRef, children: [
730
+ headings.map((colHeaders, i) => /* @__PURE__ */ jsx11("div", { className: "vuuTable-heading", children: colHeaders.map(({ label, width }, j) => /* @__PURE__ */ jsx11("div", { className: "vuuTable-headingCell", style: { width }, children: label }, j)) }, i)),
731
+ /* @__PURE__ */ jsxs8("div", { className: `${classBase10}-col-headers`, role: "row", children: [
732
+ virtualColSpan > 0 ? /* @__PURE__ */ jsx11(
733
+ "div",
734
+ {
735
+ role: "cell",
736
+ className: "vuuTableCell",
737
+ style: { width: virtualColSpan }
738
+ }
739
+ ) : null,
740
+ columns.filter(isNotHidden2).map(
741
+ (col, i) => isGroupColumn2(col) ? /* @__PURE__ */ jsx11(
742
+ GroupHeaderCellNext,
743
+ {
744
+ "aria-colindex": col.index,
745
+ column: col,
746
+ "data-index": i,
747
+ onMoveColumn: onMoveGroupColumn,
748
+ onRemoveColumn: onRemoveGroupColumn,
749
+ onResize: onResizeColumn
750
+ },
751
+ col.name
752
+ ) : /* @__PURE__ */ jsx11(
753
+ HeaderCell,
754
+ {
755
+ "aria-colindex": col.index,
756
+ className: cx8({
757
+ "vuuDraggable-dragAway": i === draggedColumnIndex
758
+ }),
759
+ column: col,
760
+ "data-index": i,
761
+ id: `${tableId}-col-${i}`,
762
+ onClick,
763
+ onMouseDown,
764
+ onResize: onResizeColumn
765
+ },
766
+ col.name
767
+ )
768
+ ),
769
+ draggableColumn
770
+ ] })
771
+ ] });
772
+ }
773
+ );
774
+ TableHeader.displayName = "TableHeader";
775
+
776
+ // src/useTable.ts
777
+ import {
778
+ useDragDrop as useDragDrop2
779
+ } from "@vuu-ui/vuu-ui-controls";
780
+ import {
781
+ applySort,
782
+ buildColumnMap as buildColumnMap2,
783
+ getIndexFromRowElement as getIndexFromRowElement3,
784
+ isGroupColumn as isGroupColumn4,
785
+ isJsonGroup as isJsonGroup2,
786
+ isValidNumber,
787
+ metadataKeys as metadataKeys5,
788
+ updateColumn,
789
+ useLayoutEffectSkipFirst as useLayoutEffectSkipFirst2
790
+ } from "@vuu-ui/vuu-utils";
791
+ import {
792
+ useCallback as useCallback19,
793
+ useEffect as useEffect4,
794
+ useMemo as useMemo6,
795
+ useRef as useRef14,
796
+ useState as useState7
797
+ } from "react";
798
+
799
+ // src/context-menu/buildContextMenuDescriptors.ts
800
+ import { isNumericColumn as isNumericColumn2 } from "@vuu-ui/vuu-utils";
801
+ var buildContextMenuDescriptors = (dataSource) => (location, options) => {
802
+ const descriptors = [];
803
+ if (dataSource === void 0) {
804
+ return descriptors;
805
+ }
806
+ if (location === "header" || location === "column-menu") {
807
+ descriptors.push(
808
+ ...buildSortMenuItems(options, dataSource)
809
+ );
810
+ descriptors.push(
811
+ ...buildGroupMenuItems(options, dataSource)
812
+ );
813
+ descriptors.push(
814
+ ...buildAggregationMenuItems(options, dataSource)
815
+ );
816
+ descriptors.push(...buildColumnDisplayMenuItems(options));
817
+ descriptors.push({
818
+ action: "column-settings",
819
+ icon: "cog",
820
+ label: `Column Settings`,
821
+ options
822
+ });
823
+ descriptors.push({
824
+ action: "table-settings",
825
+ icon: "cog",
826
+ label: `DataGrid Settings`,
827
+ options
828
+ });
829
+ }
830
+ return descriptors;
831
+ };
832
+ function buildSortMenuItems(options, { sort: { sortDefs } }) {
833
+ const { column } = options;
834
+ const menuItems = [];
835
+ if (column === void 0) {
836
+ return menuItems;
837
+ }
838
+ const hasSort = sortDefs.length > 0;
839
+ if (column.sorted === "A") {
840
+ menuItems.push({
841
+ label: "Reverse Sort (DSC)",
842
+ action: "sort-dsc",
843
+ options
844
+ });
845
+ } else if (column.sorted === "D") {
846
+ menuItems.push({
847
+ label: "Reverse Sort (ASC)",
848
+ action: "sort-asc",
849
+ options
850
+ });
851
+ } else if (typeof column.sorted === "number") {
852
+ if (column.sorted > 0) {
853
+ menuItems.push({
854
+ label: "Reverse Sort (DSC)",
855
+ action: "sort-add-dsc",
856
+ options
857
+ });
858
+ } else {
859
+ menuItems.push({
860
+ label: "Reverse Sort (ASC)",
861
+ action: "sort-add-asc",
862
+ options
863
+ });
864
+ }
865
+ if (hasSort && Math.abs(column.sorted) < sortDefs.length) {
866
+ menuItems.push({
867
+ label: "Remove from sort",
868
+ action: "sort-remove",
869
+ options
870
+ });
871
+ }
872
+ menuItems.push({
873
+ label: "New Sort",
874
+ children: [
875
+ { label: "Ascending", action: "sort-asc", options },
876
+ { label: "Descending", action: "sort-dsc", options }
877
+ ]
878
+ });
879
+ } else if (hasSort) {
880
+ menuItems.push({
881
+ label: "Add to sort",
882
+ children: [
883
+ { label: "Ascending", action: "sort-add-asc", options },
884
+ { label: "Descending", action: "sort-add-dsc", options }
885
+ ]
886
+ });
887
+ menuItems.push({
888
+ label: "New Sort",
889
+ children: [
890
+ { label: "Ascending", action: "sort-asc", options },
891
+ { label: "Descending", action: "sort-dsc", options }
892
+ ]
893
+ });
894
+ } else {
895
+ menuItems.push({
896
+ label: "Sort",
897
+ children: [
898
+ { label: "Ascending", action: "sort-asc", options },
899
+ { label: "Descending", action: "sort-dsc", options }
900
+ ]
901
+ });
902
+ }
903
+ return menuItems;
904
+ }
905
+ function buildAggregationMenuItems(options, dataSource) {
906
+ const { column } = options;
907
+ if (column === void 0 || dataSource.groupBy.length === 0) {
908
+ return [];
909
+ }
910
+ const { name, label = name } = column;
911
+ return [
912
+ {
913
+ label: `Aggregate ${label}`,
914
+ children: [
915
+ { label: "Count", action: "agg-count", options },
916
+ { label: "Distinct", action: "agg-distinct", options }
917
+ ].concat(
918
+ isNumericColumn2(column) ? [
919
+ { label: "Sum", action: "agg-sum", options },
920
+ { label: "Avg", action: "agg-avg", options },
921
+ { label: "High", action: "agg-high", options },
922
+ { label: "Low", action: "agg-low", options }
923
+ ] : []
924
+ )
925
+ }
926
+ ];
927
+ }
928
+ var pinColumn = (options, pinLocation) => ({
929
+ label: `Pin ${pinLocation}`,
930
+ action: `column-pin-${pinLocation}`,
931
+ options
932
+ });
933
+ var pinLeft = (options) => pinColumn(options, "left");
934
+ var pinFloating = (options) => pinColumn(options, "floating");
935
+ var pinRight = (options) => pinColumn(options, "right");
936
+ function buildColumnDisplayMenuItems(options) {
937
+ const { column } = options;
938
+ if (column === void 0) {
939
+ return [];
940
+ }
941
+ const { pin } = column;
942
+ const menuItems = [
943
+ {
944
+ label: `Hide column`,
945
+ action: "column-hide",
946
+ options
947
+ },
948
+ {
949
+ label: `Remove column`,
950
+ action: "column-remove",
951
+ options
952
+ }
953
+ ];
954
+ if (pin === void 0) {
955
+ menuItems.push({
956
+ label: `Pin column`,
957
+ children: [pinLeft(options), pinFloating(options), pinRight(options)]
958
+ });
959
+ } else if (pin === "left") {
960
+ menuItems.push(
961
+ { label: "Unpin column", action: "column-unpin", options },
962
+ {
963
+ label: `Pin column`,
964
+ children: [pinFloating(options), pinRight(options)]
965
+ }
966
+ );
967
+ } else if (pin === "right") {
968
+ menuItems.push(
969
+ { label: "Unpin column", action: "column-unpin", options },
970
+ {
971
+ label: `Pin column`,
972
+ children: [pinLeft(options), pinFloating(options)]
973
+ }
974
+ );
975
+ } else if (pin === "floating") {
976
+ menuItems.push(
977
+ { label: "Unpin column", action: "column-unpin", options },
978
+ {
979
+ label: `Pin column`,
980
+ children: [pinLeft(options), pinRight(options)]
981
+ }
982
+ );
983
+ }
984
+ return menuItems;
985
+ }
986
+ function buildGroupMenuItems(options, { groupBy }) {
987
+ const { column } = options;
988
+ const menuItems = [];
989
+ if (column === void 0) {
990
+ return menuItems;
991
+ }
992
+ const { name, label = name } = column;
993
+ if (groupBy.length === 0) {
994
+ menuItems.push({
995
+ label: `Group by ${label}`,
996
+ action: "group",
997
+ options
998
+ });
999
+ } else {
1000
+ menuItems.push({
1001
+ label: `Add ${label} to group by`,
1002
+ action: "group-add",
1003
+ options
1004
+ });
1005
+ }
1006
+ return menuItems;
1007
+ }
1008
+
1009
+ // src/context-menu/useHandleTableContextMenu.ts
1010
+ import { removeColumnFromFilter } from "@vuu-ui/vuu-utils";
1011
+ import {
1012
+ addGroupColumn,
1013
+ addSortColumn,
1014
+ AggregationType,
1015
+ setAggregations,
1016
+ setSortColumn
1017
+ } from "@vuu-ui/vuu-utils";
1018
+ var removeFilterColumn = (dataSourceFilter, column) => {
1019
+ if (dataSourceFilter.filterStruct && column) {
1020
+ const [filterStruct, filter] = removeColumnFromFilter(
1021
+ column,
1022
+ dataSourceFilter.filterStruct
1023
+ );
1024
+ return {
1025
+ filter,
1026
+ filterStruct
1027
+ };
1028
+ } else {
1029
+ return dataSourceFilter;
1030
+ }
1031
+ };
1032
+ var { Average, Count, Distinct, High, Low, Sum } = AggregationType;
1033
+ var useHandleTableContextMenu = ({
1034
+ dataSource,
1035
+ onPersistentColumnOperation
1036
+ }) => {
1037
+ const handleContextMenuAction = (action) => {
1038
+ const gridOptions = action.options;
1039
+ if (gridOptions.column && dataSource) {
1040
+ const { column } = gridOptions;
1041
+ switch (action.menuId) {
1042
+ case "sort-asc":
1043
+ return dataSource.sort = setSortColumn(dataSource.sort, column, "A"), true;
1044
+ case "sort-dsc":
1045
+ return dataSource.sort = setSortColumn(dataSource.sort, column, "D"), true;
1046
+ case "sort-add-asc":
1047
+ return dataSource.sort = addSortColumn(dataSource.sort, column, "A"), true;
1048
+ case "sort-add-dsc":
1049
+ return dataSource.sort = addSortColumn(dataSource.sort, column, "D"), true;
1050
+ case "group":
1051
+ return dataSource.groupBy = addGroupColumn(dataSource.groupBy, column), true;
1052
+ case "group-add":
1053
+ return dataSource.groupBy = addGroupColumn(dataSource.groupBy, column), true;
1054
+ case "column-hide":
1055
+ return onPersistentColumnOperation({ type: "hideColumns", columns: [column] }), true;
1056
+ case "column-remove":
1057
+ return dataSource.columns = dataSource.columns.filter((name) => name !== column.name), true;
1058
+ case "filter-remove-column":
1059
+ return dataSource.filter = removeFilterColumn(dataSource.filter, column), true;
1060
+ case "remove-filters":
1061
+ return dataSource.filter = { filter: "" }, true;
1062
+ case "agg-avg":
1063
+ return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Average), true;
1064
+ case "agg-high":
1065
+ return dataSource.aggregations = setAggregations(dataSource.aggregations, column, High), true;
1066
+ case "agg-low":
1067
+ return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Low), true;
1068
+ case "agg-count":
1069
+ return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Count), true;
1070
+ case "agg-distinct":
1071
+ return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Distinct), true;
1072
+ case "agg-sum":
1073
+ return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Sum), true;
1074
+ case "column-pin-floating":
1075
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: "floating" }), true;
1076
+ case "column-pin-left":
1077
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: "left" }), true;
1078
+ case "column-pin-right":
1079
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: "right" }), true;
1080
+ case "column-unpin":
1081
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: void 0 }), true;
1082
+ case "column-settings":
1083
+ return onPersistentColumnOperation({ type: "columnSettings", column }), true;
1084
+ case "table-settings":
1085
+ return onPersistentColumnOperation({ type: "tableSettings" }), true;
1086
+ default:
1087
+ }
1088
+ }
1089
+ return false;
1090
+ };
1091
+ return handleContextMenuAction;
1092
+ };
1093
+
1094
+ // src/table-config.ts
1095
+ var updateTableConfig = (config, action) => {
1096
+ switch (action.type) {
1097
+ case "col-size":
1098
+ return {
1099
+ ...config,
1100
+ columns: config.columns.map(
1101
+ (col) => col.name === action.column.name ? { ...col, width: action.width } : col
1102
+ )
1103
+ };
1104
+ case "column-prop":
1105
+ return {
1106
+ ...config,
1107
+ columns: config.columns.map(
1108
+ (col) => col.name === action.column.name ? { ...col, [action.property]: action.value } : col
1109
+ )
1110
+ };
1111
+ default:
1112
+ return config;
1113
+ }
1114
+ };
1115
+
1116
+ // src/useCellEditing.ts
1117
+ import { isCharacterKey } from "@vuu-ui/vuu-utils";
1118
+ import {
1119
+ useCallback as useCallback11
1120
+ } from "react";
1121
+
1122
+ // src/table-dom-utils.ts
1123
+ var headerCellQuery = (colIdx) => `.vuuTable-col-headers .vuuTableHeaderCell:nth-child(${colIdx})`;
1124
+ var dataCellQuery = (rowIdx, colIdx) => `.vuuTable-body > [aria-rowindex='${rowIdx + 1}'] > [role='cell']:nth-child(${colIdx + 1})`;
1125
+ var getTableCell = (containerRef, [rowIdx, colIdx]) => {
1126
+ var _a;
1127
+ const cssQuery = rowIdx === -1 ? headerCellQuery(colIdx) : dataCellQuery(rowIdx, colIdx);
1128
+ const cell = (_a = containerRef.current) == null ? void 0 : _a.querySelector(
1129
+ cssQuery
1130
+ );
1131
+ if (cellIsEditable(cell)) {
1132
+ const focusableContent = cell.querySelector("button");
1133
+ return focusableContent || cell;
1134
+ } else {
1135
+ return cell;
1136
+ }
1137
+ };
1138
+ var cellIsEditable = (cell) => cell == null ? void 0 : cell.classList.contains("vuuTableCell-editable");
1139
+ var cellIsTextInput = (cell) => cell.querySelector(".vuuTableInputCell") !== null;
1140
+ function getRowIndex(rowEl) {
1141
+ if (rowEl) {
1142
+ const idx = rowEl.ariaRowIndex;
1143
+ if (idx !== null) {
1144
+ return parseInt(idx, 10) - 1;
1145
+ }
1146
+ }
1147
+ return -1;
1148
+ }
1149
+ var closestRow = (el) => el.closest('[role="row"]');
1150
+ var closestRowIndex = (el) => getRowIndex(closestRow(el));
1151
+ var NO_SCROLL_NECESSARY = [void 0, void 0];
1152
+ var howFarIsRowOutsideViewport = (rowEl, totalHeaderHeight, contentContainer = rowEl.closest(".vuuTable-contentContainer")) => {
1153
+ if (contentContainer) {
1154
+ const viewport = contentContainer == null ? void 0 : contentContainer.getBoundingClientRect();
1155
+ const upperBoundary = viewport.top + totalHeaderHeight;
1156
+ const row = rowEl.getBoundingClientRect();
1157
+ if (row) {
1158
+ if (row.bottom > viewport.bottom) {
1159
+ return ["down", row.bottom - viewport.bottom];
1160
+ } else if (row.top < upperBoundary) {
1161
+ return ["up", row.top - upperBoundary];
1162
+ } else {
1163
+ return NO_SCROLL_NECESSARY;
1164
+ }
1165
+ } else {
1166
+ throw Error("Whats going on, row not found");
1167
+ }
1168
+ } else {
1169
+ throw Error("Whats going on, scrollbar container not found");
1170
+ }
1171
+ };
1172
+
1173
+ // src/useCellEditing.ts
1174
+ var useCellEditing = ({ navigate }) => {
1175
+ const commitHandler = useCallback11(() => {
1176
+ navigate();
1177
+ }, [navigate]);
1178
+ const editInput = useCallback11(
1179
+ (evt) => {
1180
+ const cellEl = evt.target;
1181
+ const input = cellEl.matches("input") ? cellEl : cellEl.querySelector("input");
1182
+ if (input) {
1183
+ input.focus();
1184
+ input.select();
1185
+ }
1186
+ },
1187
+ []
1188
+ );
1189
+ const focusInput = useCallback11(
1190
+ (evt) => {
1191
+ const cellEl = evt.target;
1192
+ const input = cellEl.querySelector("input");
1193
+ if (input) {
1194
+ input.focus();
1195
+ input.select();
1196
+ }
1197
+ },
1198
+ []
1199
+ );
1200
+ const handleKeyDown = useCallback11(
1201
+ (e) => {
1202
+ const el = e.target;
1203
+ if (cellIsTextInput(el)) {
1204
+ if (isCharacterKey(e.key)) {
1205
+ editInput(e);
1206
+ } else if (e.key === "Enter") {
1207
+ focusInput(e);
1208
+ }
1209
+ }
1210
+ },
1211
+ [editInput, focusInput]
1212
+ );
1213
+ const handleDoubleClick = useCallback11(
1214
+ (e) => {
1215
+ const el = e.target;
1216
+ if (el.matches("input") || el.querySelector("input")) {
1217
+ editInput(e);
1218
+ e.stopPropagation();
1219
+ }
1220
+ },
1221
+ [editInput]
1222
+ );
1223
+ const handleBlur = useCallback11(
1224
+ (e) => {
1225
+ const el = e.target;
1226
+ el.removeEventListener("vuu-commit", commitHandler, true);
1227
+ },
1228
+ [commitHandler]
1229
+ );
1230
+ const handleFocus = useCallback11(
1231
+ (e) => {
1232
+ const el = e.target;
1233
+ el.addEventListener("vuu-commit", commitHandler, true);
1234
+ },
1235
+ [commitHandler]
1236
+ );
1237
+ return {
1238
+ onBlur: handleBlur,
1239
+ onDoubleClick: handleDoubleClick,
1240
+ onFocus: handleFocus,
1241
+ onKeyDown: handleKeyDown
1242
+ };
1243
+ };
1244
+
1245
+ // src/useDataSource.ts
1246
+ import { getFullRange, NULL_RANGE, rangesAreSame } from "@vuu-ui/vuu-utils";
1247
+ import { useCallback as useCallback12, useEffect, useMemo as useMemo2, useRef as useRef7, useState as useState4 } from "react";
1248
+
1249
+ // src/moving-window.ts
1250
+ import {
1251
+ isRowSelectedLast,
1252
+ metadataKeys as metadataKeys3,
1253
+ WindowRange
1254
+ } from "@vuu-ui/vuu-utils";
1255
+ var { SELECTED: SELECTED2 } = metadataKeys3;
1256
+ var MovingWindow = class {
1257
+ constructor({ from, to }) {
1258
+ this.rowCount = 0;
1259
+ this.setRowCount = (rowCount) => {
1260
+ if (rowCount < this.data.length) {
1261
+ this.data.length = rowCount;
1262
+ }
1263
+ this.rowCount = rowCount;
1264
+ };
1265
+ this.range = new WindowRange(from, to);
1266
+ this.data = new Array(Math.max(0, to - from));
1267
+ this.rowCount = 0;
1268
+ }
1269
+ add(data) {
1270
+ const [index] = data;
1271
+ if (this.isWithinRange(index)) {
1272
+ const internalIndex = index - this.range.from;
1273
+ this.data[internalIndex] = data;
1274
+ if (data[SELECTED2]) {
1275
+ const previousRow = this.data[internalIndex - 1];
1276
+ if (isRowSelectedLast(previousRow)) {
1277
+ this.data[internalIndex - 1] = previousRow.slice();
1278
+ this.data[internalIndex - 1][SELECTED2] -= 4;
1279
+ }
1280
+ }
1281
+ }
1282
+ }
1283
+ getAtIndex(index) {
1284
+ return this.range.isWithin(index) && this.data[index - this.range.from] != null ? this.data[index - this.range.from] : void 0;
1285
+ }
1286
+ isWithinRange(index) {
1287
+ return this.range.isWithin(index);
1288
+ }
1289
+ setRange({ from, to }) {
1290
+ if (from !== this.range.from || to !== this.range.to) {
1291
+ const [overlapFrom, overlapTo] = this.range.overlap(from, to);
1292
+ const newData = new Array(Math.max(0, to - from));
1293
+ for (let i = overlapFrom; i < overlapTo; i++) {
1294
+ const data = this.getAtIndex(i);
1295
+ if (data) {
1296
+ const index = i - from;
1297
+ newData[index] = data;
1298
+ }
1299
+ }
1300
+ this.data = newData;
1301
+ this.range.from = from;
1302
+ this.range.to = to;
1303
+ }
1304
+ }
1305
+ getSelectedRows() {
1306
+ return this.data.filter((row) => row[SELECTED2] !== 0);
1307
+ }
1308
+ };
1309
+
1310
+ // src/useDataSource.ts
1311
+ var isVuuFeatureInvocation = (action) => action.type === "vuu-link-created" || action.type === "vuu-link-removed";
1312
+ var useDataSource = ({
1313
+ dataSource,
1314
+ onFeatureInvocation,
1315
+ onSizeChange,
1316
+ onSubscribed,
1317
+ range = NULL_RANGE,
1318
+ renderBufferSize = 0
1319
+ }) => {
1320
+ const [, forceUpdate] = useState4(null);
1321
+ const data = useRef7([]);
1322
+ const isMounted = useRef7(true);
1323
+ const hasUpdated = useRef7(false);
1324
+ const rangeRef = useRef7(range);
1325
+ const dataWindow = useMemo2(
1326
+ () => new MovingWindow(getFullRange(range, renderBufferSize)),
1327
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1328
+ []
1329
+ );
1330
+ const setData = useCallback12(
1331
+ (updates) => {
1332
+ for (const row of updates) {
1333
+ dataWindow.add(row);
1334
+ }
1335
+ data.current = dataWindow.data;
1336
+ if (isMounted.current) {
1337
+ forceUpdate({});
1338
+ } else {
1339
+ console.log(`ignore update as we're not mounted`);
1340
+ }
1341
+ },
1342
+ [dataWindow]
1343
+ );
1344
+ const datasourceMessageHandler = useCallback12(
1345
+ (message) => {
1346
+ if (message.type === "subscribed") {
1347
+ onSubscribed == null ? void 0 : onSubscribed(message);
1348
+ } else if (message.type === "viewport-update") {
1349
+ if (typeof message.size === "number") {
1350
+ onSizeChange == null ? void 0 : onSizeChange(message.size);
1351
+ dataWindow.setRowCount(message.size);
1352
+ }
1353
+ if (message.rows) {
1354
+ setData(message.rows);
1355
+ } else if (typeof message.size === "number") {
1356
+ data.current = dataWindow.data;
1357
+ hasUpdated.current = true;
1358
+ }
1359
+ } else if (isVuuFeatureInvocation(message)) {
1360
+ onFeatureInvocation == null ? void 0 : onFeatureInvocation(message);
1361
+ } else {
1362
+ console.log(`useDataSource unexpected message ${message.type}`);
1363
+ }
1364
+ },
1365
+ [dataWindow, onFeatureInvocation, onSizeChange, onSubscribed, setData]
1366
+ );
1367
+ const getSelectedRows = useCallback12(() => {
1368
+ return dataWindow.getSelectedRows();
1369
+ }, [dataWindow]);
1370
+ useEffect(() => {
1371
+ var _a;
1372
+ isMounted.current = true;
1373
+ (_a = dataSource.resume) == null ? void 0 : _a.call(dataSource);
1374
+ return () => {
1375
+ var _a2;
1376
+ isMounted.current = false;
1377
+ (_a2 = dataSource.suspend) == null ? void 0 : _a2.call(dataSource);
1378
+ };
1379
+ }, [dataSource]);
1380
+ useEffect(() => {
1381
+ var _a;
1382
+ if (dataSource.status === "disabled") {
1383
+ (_a = dataSource.enable) == null ? void 0 : _a.call(dataSource, datasourceMessageHandler);
1384
+ } else {
1385
+ dataSource == null ? void 0 : dataSource.subscribe(
1386
+ { range: getFullRange(range, renderBufferSize) },
1387
+ datasourceMessageHandler
1388
+ );
1389
+ }
1390
+ }, [dataSource, datasourceMessageHandler, range, renderBufferSize]);
1391
+ const setRange = useCallback12(
1392
+ (range2) => {
1393
+ if (!rangesAreSame(range2, rangeRef.current)) {
1394
+ const fullRange = getFullRange(range2, renderBufferSize);
1395
+ dataWindow.setRange(fullRange);
1396
+ dataSource.range = rangeRef.current = fullRange;
1397
+ dataSource.emit("range", range2);
1398
+ }
1399
+ },
1400
+ [dataSource, dataWindow, renderBufferSize]
1401
+ );
1402
+ return {
1403
+ data: data.current,
1404
+ dataRef: data,
1405
+ getSelectedRows,
1406
+ range: rangeRef.current,
1407
+ setRange
1408
+ };
1409
+ };
1410
+
1411
+ // src/useInitialValue.ts
1412
+ import { useMemo as useMemo3, useRef as useRef8 } from "react";
1413
+ var useInitialValue = (value) => {
1414
+ const ref = useRef8(value);
1415
+ return useMemo3(() => ref.current, []);
1416
+ };
1417
+
1418
+ // src/useKeyboardNavigation.ts
1419
+ import { getIndexFromRowElement } from "@vuu-ui/vuu-utils";
1420
+ import { useControlled } from "@salt-ds/core";
1421
+ import {
1422
+ useCallback as useCallback13,
1423
+ useEffect as useEffect2,
1424
+ useRef as useRef9
1425
+ } from "react";
1426
+ var rowNavigationKeys = /* @__PURE__ */ new Set([
1427
+ "Home",
1428
+ "End",
1429
+ "PageUp",
1430
+ "PageDown",
1431
+ "ArrowDown",
1432
+ "ArrowUp"
1433
+ ]);
1434
+ var cellNavigationKeys = new Set(rowNavigationKeys);
1435
+ cellNavigationKeys.add("ArrowLeft");
1436
+ cellNavigationKeys.add("ArrowRight");
1437
+ var isNavigationKey = (key, navigationStyle) => {
1438
+ switch (navigationStyle) {
1439
+ case "cell":
1440
+ return cellNavigationKeys.has(key);
1441
+ case "row":
1442
+ return rowNavigationKeys.has(key);
1443
+ default:
1444
+ return false;
1445
+ }
1446
+ };
1447
+ var PageKeys = ["Home", "End", "PageUp", "PageDown"];
1448
+ var isPagingKey = (key) => PageKeys.includes(key);
1449
+ var NULL_CELL_POS = [-1, -1];
1450
+ function nextCellPos(key, [rowIdx, colIdx], columnCount, rowCount) {
1451
+ if (key === "ArrowUp") {
1452
+ if (rowIdx > -1) {
1453
+ return [rowIdx - 1, colIdx];
1454
+ } else {
1455
+ return [rowIdx, colIdx];
1456
+ }
1457
+ } else if (key === "ArrowDown") {
1458
+ if (rowIdx === -1) {
1459
+ return [0, colIdx];
1460
+ } else if (rowIdx === rowCount - 1) {
1461
+ return [rowIdx, colIdx];
1462
+ } else {
1463
+ return [rowIdx + 1, colIdx];
1464
+ }
1465
+ } else if (key === "ArrowRight") {
1466
+ if (colIdx < columnCount) {
1467
+ return [rowIdx, colIdx + 1];
1468
+ } else {
1469
+ return [rowIdx, colIdx];
1470
+ }
1471
+ } else if (key === "ArrowLeft") {
1472
+ if (colIdx > 1) {
1473
+ return [rowIdx, colIdx - 1];
1474
+ } else {
1475
+ return [rowIdx, colIdx];
1476
+ }
1477
+ }
1478
+ return [rowIdx, colIdx];
1479
+ }
1480
+ var useKeyboardNavigation = ({
1481
+ columnCount = 0,
1482
+ containerRef,
1483
+ disableFocus = false,
1484
+ defaultHighlightedIndex,
1485
+ disableHighlightOnFocus,
1486
+ highlightedIndex: highlightedIndexProp,
1487
+ navigationStyle,
1488
+ requestScroll,
1489
+ onHighlight,
1490
+ rowCount = 0,
1491
+ viewportRowCount
1492
+ }) => {
1493
+ var _a;
1494
+ const focusedCellPos = useRef9([-1, -1]);
1495
+ const focusableCell = useRef9();
1496
+ const activeCellPos = useRef9([-1, 0]);
1497
+ const highlightedIndexRef = useRef9();
1498
+ const [highlightedIndex, setHighlightedIdx] = useControlled({
1499
+ controlled: highlightedIndexProp,
1500
+ default: defaultHighlightedIndex,
1501
+ name: "UseKeyboardNavigation"
1502
+ });
1503
+ highlightedIndexRef.current = highlightedIndex;
1504
+ const setHighlightedIndex = useCallback13(
1505
+ (idx, fromKeyboard = false) => {
1506
+ onHighlight == null ? void 0 : onHighlight(idx);
1507
+ setHighlightedIdx(idx);
1508
+ if (fromKeyboard) {
1509
+ }
1510
+ },
1511
+ [onHighlight, setHighlightedIdx]
1512
+ );
1513
+ const getFocusedCell = (element) => element == null ? void 0 : element.closest(
1514
+ "[role='columnHeader'],[role='cell']"
1515
+ );
1516
+ const getTableCellPos = (tableCell) => {
1517
+ var _a2;
1518
+ if (tableCell.role === "columnHeader") {
1519
+ const colIdx = parseInt((_a2 = tableCell.dataset.idx) != null ? _a2 : "-1", 10);
1520
+ return [-1, colIdx];
1521
+ } else {
1522
+ const focusedRow = tableCell.closest("[role='row']");
1523
+ if (focusedRow) {
1524
+ const rowIdx = getIndexFromRowElement(focusedRow);
1525
+ const colIdx = Array.from(focusedRow.childNodes).indexOf(tableCell);
1526
+ return [rowIdx, colIdx];
1527
+ }
1528
+ }
1529
+ return NULL_CELL_POS;
1530
+ };
1531
+ const focusCell = useCallback13(
1532
+ (cellPos) => {
1533
+ var _a2;
1534
+ if (containerRef.current) {
1535
+ const activeCell = getTableCell(containerRef, cellPos);
1536
+ if (activeCell) {
1537
+ if (activeCell !== focusableCell.current) {
1538
+ (_a2 = focusableCell.current) == null ? void 0 : _a2.removeAttribute("tabindex");
1539
+ focusableCell.current = activeCell;
1540
+ activeCell.setAttribute("tabindex", "0");
1541
+ }
1542
+ requestScroll == null ? void 0 : requestScroll({ type: "scroll-row", rowIndex: cellPos[0] });
1543
+ activeCell.focus({ preventScroll: true });
1544
+ }
1545
+ }
1546
+ },
1547
+ // TODO we recreate this function whenever viewportRange changes, which will
1548
+ // be often whilst scrolling - store range in a a ref ?
1549
+ [containerRef, requestScroll]
1550
+ );
1551
+ const setActiveCell = useCallback13(
1552
+ (rowIdx, colIdx, fromKeyboard = false) => {
1553
+ const pos = [rowIdx, colIdx];
1554
+ activeCellPos.current = pos;
1555
+ if (navigationStyle === "row") {
1556
+ setHighlightedIdx(rowIdx);
1557
+ } else {
1558
+ focusCell(pos);
1559
+ }
1560
+ if (fromKeyboard) {
1561
+ focusedCellPos.current = pos;
1562
+ }
1563
+ },
1564
+ [focusCell, navigationStyle, setHighlightedIdx]
1565
+ );
1566
+ const nextPageItemIdx = useCallback13(
1567
+ (key, [rowIdx, colIdx]) => new Promise((resolve) => {
1568
+ let newRowIdx = rowIdx;
1569
+ switch (key) {
1570
+ case "PageDown": {
1571
+ newRowIdx = Math.min(rowCount - 1, rowIdx + viewportRowCount);
1572
+ if (newRowIdx !== rowIdx) {
1573
+ requestScroll == null ? void 0 : requestScroll({ type: "scroll-page", direction: "down" });
1574
+ }
1575
+ break;
1576
+ }
1577
+ case "PageUp": {
1578
+ newRowIdx = Math.max(0, rowIdx - viewportRowCount);
1579
+ if (newRowIdx !== rowIdx) {
1580
+ requestScroll == null ? void 0 : requestScroll({ type: "scroll-page", direction: "up" });
1581
+ }
1582
+ break;
1583
+ }
1584
+ case "Home": {
1585
+ newRowIdx = 0;
1586
+ if (newRowIdx !== rowIdx) {
1587
+ requestScroll == null ? void 0 : requestScroll({ type: "scroll-end", direction: "home" });
1588
+ }
1589
+ break;
1590
+ }
1591
+ case "End": {
1592
+ newRowIdx = rowCount - 1;
1593
+ if (newRowIdx !== rowIdx) {
1594
+ requestScroll == null ? void 0 : requestScroll({ type: "scroll-end", direction: "end" });
1595
+ }
1596
+ break;
1597
+ }
1598
+ }
1599
+ setTimeout(() => {
1600
+ resolve([newRowIdx, colIdx]);
1601
+ }, 35);
1602
+ }),
1603
+ [requestScroll, rowCount, viewportRowCount]
1604
+ );
1605
+ const handleFocus = useCallback13(() => {
1606
+ var _a2;
1607
+ if (disableHighlightOnFocus !== true) {
1608
+ if ((_a2 = containerRef.current) == null ? void 0 : _a2.contains(document.activeElement)) {
1609
+ const focusedCell = getFocusedCell(document.activeElement);
1610
+ if (focusedCell) {
1611
+ focusedCellPos.current = getTableCellPos(focusedCell);
1612
+ if (navigationStyle === "row") {
1613
+ setHighlightedIdx(focusedCellPos.current[0]);
1614
+ }
1615
+ }
1616
+ }
1617
+ }
1618
+ }, [
1619
+ disableHighlightOnFocus,
1620
+ containerRef,
1621
+ navigationStyle,
1622
+ setHighlightedIdx
1623
+ ]);
1624
+ const navigateChildItems = useCallback13(
1625
+ async (key) => {
1626
+ const [nextRowIdx, nextColIdx] = isPagingKey(key) ? await nextPageItemIdx(key, activeCellPos.current) : nextCellPos(key, activeCellPos.current, columnCount, rowCount);
1627
+ const [rowIdx, colIdx] = activeCellPos.current;
1628
+ if (nextRowIdx !== rowIdx || nextColIdx !== colIdx) {
1629
+ setActiveCell(nextRowIdx, nextColIdx, true);
1630
+ }
1631
+ },
1632
+ [columnCount, nextPageItemIdx, rowCount, setActiveCell]
1633
+ );
1634
+ const scrollRowIntoViewIfNecessary = useCallback13(
1635
+ (rowIndex) => {
1636
+ requestScroll == null ? void 0 : requestScroll({ type: "scroll-row", rowIndex });
1637
+ },
1638
+ [requestScroll]
1639
+ );
1640
+ const moveHighlightedRow = useCallback13(
1641
+ async (key) => {
1642
+ const { current: highlighted } = highlightedIndexRef;
1643
+ const [nextRowIdx] = isPagingKey(key) ? await nextPageItemIdx(key, [highlighted != null ? highlighted : -1, 0]) : nextCellPos(key, [highlighted != null ? highlighted : -1, 0], columnCount, rowCount);
1644
+ if (nextRowIdx !== highlighted) {
1645
+ setHighlightedIndex(nextRowIdx);
1646
+ scrollRowIntoViewIfNecessary(nextRowIdx);
1647
+ }
1648
+ },
1649
+ [
1650
+ columnCount,
1651
+ nextPageItemIdx,
1652
+ rowCount,
1653
+ scrollRowIntoViewIfNecessary,
1654
+ setHighlightedIndex
1655
+ ]
1656
+ );
1657
+ useEffect2(() => {
1658
+ if (highlightedIndexProp !== void 0 && highlightedIndexProp !== -1) {
1659
+ scrollRowIntoViewIfNecessary(highlightedIndexProp);
1660
+ }
1661
+ }, [highlightedIndexProp, scrollRowIntoViewIfNecessary]);
1662
+ const handleKeyDown = useCallback13(
1663
+ (e) => {
1664
+ if (rowCount > 0 && isNavigationKey(e.key, navigationStyle)) {
1665
+ e.preventDefault();
1666
+ e.stopPropagation();
1667
+ if (navigationStyle === "row") {
1668
+ moveHighlightedRow(e.key);
1669
+ } else {
1670
+ void navigateChildItems(e.key);
1671
+ }
1672
+ }
1673
+ },
1674
+ [rowCount, navigationStyle, moveHighlightedRow, navigateChildItems]
1675
+ );
1676
+ const handleClick = useCallback13(
1677
+ // Might not be a cell e.g the Settings button
1678
+ (evt) => {
1679
+ const target = evt.target;
1680
+ const focusedCell = getFocusedCell(target);
1681
+ if (focusedCell) {
1682
+ const [rowIdx, colIdx] = getTableCellPos(focusedCell);
1683
+ setActiveCell(rowIdx, colIdx);
1684
+ }
1685
+ },
1686
+ [setActiveCell]
1687
+ );
1688
+ const handleMouseLeave = useCallback13(() => {
1689
+ setHighlightedIndex(-1);
1690
+ }, [setHighlightedIndex]);
1691
+ const handleMouseMove = useCallback13(
1692
+ (evt) => {
1693
+ const idx = closestRowIndex(evt.target);
1694
+ if (idx !== -1 && idx !== highlightedIndexRef.current) {
1695
+ setHighlightedIndex(idx);
1696
+ }
1697
+ },
1698
+ [setHighlightedIndex]
1699
+ );
1700
+ const navigate = useCallback13(() => {
1701
+ navigateChildItems("ArrowDown");
1702
+ }, [navigateChildItems]);
1703
+ const fullyRendered = ((_a = containerRef.current) == null ? void 0 : _a.firstChild) != null;
1704
+ useEffect2(() => {
1705
+ if (fullyRendered && focusableCell.current === void 0 && !disableFocus) {
1706
+ const { current: container } = containerRef;
1707
+ const cell = (container == null ? void 0 : container.querySelector(headerCellQuery(0))) || (container == null ? void 0 : container.querySelector(dataCellQuery(0, 0)));
1708
+ if (cell) {
1709
+ cell.setAttribute("tabindex", "0");
1710
+ focusableCell.current = cell;
1711
+ }
1712
+ }
1713
+ }, [containerRef, disableFocus, fullyRendered]);
1714
+ return {
1715
+ highlightedIndexRef,
1716
+ navigate,
1717
+ onClick: handleClick,
1718
+ onFocus: handleFocus,
1719
+ onKeyDown: handleKeyDown,
1720
+ onMouseLeave: navigationStyle === "row" ? handleMouseLeave : void 0,
1721
+ onMouseMove: navigationStyle === "row" ? handleMouseMove : void 0
1722
+ };
1723
+ };
1724
+
1725
+ // src/useSelection.ts
1726
+ import {
1727
+ deselectItem,
1728
+ dispatchMouseEvent,
1729
+ isRowSelected,
1730
+ metadataKeys as metadataKeys4,
1731
+ selectItem
1732
+ } from "@vuu-ui/vuu-utils";
1733
+ import {
1734
+ useCallback as useCallback14,
1735
+ useRef as useRef10
1736
+ } from "react";
1737
+ var { IDX: IDX2 } = metadataKeys4;
1738
+ var NO_SELECTION = [];
1739
+ var defaultSelectionKeys = ["Enter", " "];
1740
+ var useSelection = ({
1741
+ highlightedIndexRef,
1742
+ selectionKeys = defaultSelectionKeys,
1743
+ selectionModel,
1744
+ onSelect,
1745
+ onSelectionChange
1746
+ }) => {
1747
+ selectionModel === "extended" || selectionModel === "checkbox";
1748
+ const lastActiveRef = useRef10(-1);
1749
+ const selectedRef = useRef10(NO_SELECTION);
1750
+ const isSelectionEvent = useCallback14(
1751
+ (evt) => selectionKeys.includes(evt.key),
1752
+ [selectionKeys]
1753
+ );
1754
+ const handleRowClick = useCallback14(
1755
+ (row, rangeSelect, keepExistingSelection) => {
1756
+ const { [IDX2]: idx } = row;
1757
+ const { current: active } = lastActiveRef;
1758
+ const { current: selected } = selectedRef;
1759
+ const selectOperation = isRowSelected(row) ? deselectItem : selectItem;
1760
+ const newSelected = selectOperation(
1761
+ selectionModel,
1762
+ selected,
1763
+ idx,
1764
+ rangeSelect,
1765
+ keepExistingSelection,
1766
+ active
1767
+ );
1768
+ selectedRef.current = newSelected;
1769
+ lastActiveRef.current = idx;
1770
+ onSelect == null ? void 0 : onSelect(row);
1771
+ onSelectionChange == null ? void 0 : onSelectionChange(newSelected);
1772
+ },
1773
+ [onSelect, onSelectionChange, selectionModel]
1774
+ );
1775
+ const handleKeyDown = useCallback14(
1776
+ (e) => {
1777
+ if (isSelectionEvent(e)) {
1778
+ const { current: rowIndex } = highlightedIndexRef;
1779
+ if (rowIndex !== void 0 && rowIndex !== -1) {
1780
+ const rowEl = e.target.querySelector(
1781
+ `[aria-rowindex="${rowIndex}"]`
1782
+ );
1783
+ if (rowEl) {
1784
+ dispatchMouseEvent(rowEl, "click");
1785
+ }
1786
+ }
1787
+ }
1788
+ },
1789
+ [highlightedIndexRef, isSelectionEvent]
1790
+ );
1791
+ return {
1792
+ onKeyDown: handleKeyDown,
1793
+ onRowClick: handleRowClick
1794
+ };
1795
+ };
1796
+
1797
+ // src/useTableContextMenu.ts
1798
+ import { useContextMenu as usePopupContextMenu } from "@vuu-ui/vuu-popups";
1799
+ import { buildColumnMap, getIndexFromRowElement as getIndexFromRowElement2 } from "@vuu-ui/vuu-utils";
1800
+ import { useCallback as useCallback15 } from "react";
1801
+ var NO_ROWS = [];
1802
+ var useTableContextMenu = ({
1803
+ columns,
1804
+ data,
1805
+ dataSource,
1806
+ getSelectedRows
1807
+ }) => {
1808
+ const [showContextMenu] = usePopupContextMenu();
1809
+ const onContextMenu = useCallback15(
1810
+ (evt) => {
1811
+ const target = evt.target;
1812
+ const cellEl = target == null ? void 0 : target.closest("div[role='cell']");
1813
+ const rowEl = target == null ? void 0 : target.closest("div[role='row']");
1814
+ if (cellEl && rowEl) {
1815
+ const { selectedRowsCount } = dataSource;
1816
+ const columnMap = buildColumnMap(columns);
1817
+ const rowIndex = getIndexFromRowElement2(rowEl);
1818
+ const cellIndex = Array.from(rowEl.childNodes).indexOf(cellEl);
1819
+ const row = data.find(([idx]) => idx === rowIndex);
1820
+ const columnName = columns[cellIndex];
1821
+ showContextMenu(evt, "grid", {
1822
+ columnMap,
1823
+ columnName,
1824
+ row,
1825
+ selectedRows: selectedRowsCount === 0 ? NO_ROWS : getSelectedRows(),
1826
+ viewport: dataSource.viewport
1827
+ });
1828
+ }
1829
+ },
1830
+ [columns, data, dataSource, getSelectedRows, showContextMenu]
1831
+ );
1832
+ return onContextMenu;
1833
+ };
1834
+
1835
+ // src/useTableModel.ts
1836
+ import {
1837
+ applyFilterToColumns,
1838
+ applyGroupByToColumns,
1839
+ applySortToColumns,
1840
+ getCellRenderer,
1841
+ getColumnHeaderContentRenderer,
1842
+ getColumnHeaderLabelRenderer,
1843
+ getColumnLabel,
1844
+ getTableHeadings,
1845
+ getValueFormatter,
1846
+ hasValidationRules,
1847
+ isFilteredColumn,
1848
+ isGroupColumn as isGroupColumn3,
1849
+ isPinned,
1850
+ logger,
1851
+ replaceColumn,
1852
+ sortPinnedColumns,
1853
+ stripFilterFromColumns,
1854
+ subscribedOnly
1855
+ } from "@vuu-ui/vuu-utils";
1856
+ import { buildValidationChecker } from "@vuu-ui/vuu-ui-controls";
1857
+ import { useReducer } from "react";
1858
+ var { info } = logger("useTableModel");
1859
+ var DEFAULT_COLUMN_WIDTH = 100;
1860
+ var columnWithoutDataType = ({ serverDataType }) => serverDataType === void 0;
1861
+ var getDataType = (column, tableSchema) => {
1862
+ const schemaColumn = tableSchema == null ? void 0 : tableSchema.columns.find(
1863
+ ({ name }) => name === column.name
1864
+ );
1865
+ if (schemaColumn) {
1866
+ return schemaColumn.serverDataType;
1867
+ } else {
1868
+ return column.serverDataType;
1869
+ }
1870
+ };
1871
+ var numericTypes = ["int", "long", "double"];
1872
+ var getDefaultAlignment = (serverDataType) => serverDataType === void 0 ? void 0 : numericTypes.includes(serverDataType) ? "right" : "left";
1873
+ var isShowColumnSettings = (action) => action.type === "columnSettings";
1874
+ var isShowTableSettings = (action) => action.type === "tableSettings";
1875
+ var columnReducer = (state, action) => {
1876
+ info == null ? void 0 : info(`TableModelReducer ${action.type}`);
1877
+ switch (action.type) {
1878
+ case "init":
1879
+ return init(action);
1880
+ case "moveColumn":
1881
+ return moveColumn(state, action);
1882
+ case "resizeColumn":
1883
+ return resizeColumn(state, action);
1884
+ case "setTableSchema":
1885
+ return setTableSchema(state, action);
1886
+ case "hideColumns":
1887
+ return hideColumns(state, action);
1888
+ case "showColumns":
1889
+ return showColumns(state, action);
1890
+ case "pinColumn":
1891
+ return pinColumn2(state, action);
1892
+ case "updateColumnProp":
1893
+ return updateColumnProp(state, action);
1894
+ case "tableConfig":
1895
+ return updateTableConfig2(state, action);
1896
+ default:
1897
+ console.log(`unhandled action ${action.type}`);
1898
+ return state;
1899
+ }
1900
+ };
1901
+ var useTableModel = (tableConfigProp, dataSource) => {
1902
+ const [state, dispatchColumnAction] = useReducer(columnReducer, { tableConfig: tableConfigProp, dataSource }, init);
1903
+ const { columns, headings, tableConfig, ...tableAttributes } = state;
1904
+ return {
1905
+ columns,
1906
+ dispatchColumnAction,
1907
+ headings,
1908
+ tableAttributes,
1909
+ tableConfig
1910
+ };
1911
+ };
1912
+ function init({ dataSource, tableConfig }) {
1913
+ const { columns, ...tableAttributes } = tableConfig;
1914
+ const { config: dataSourceConfig, tableSchema } = dataSource;
1915
+ const runtimeColumns = columns.filter(subscribedOnly(dataSourceConfig == null ? void 0 : dataSourceConfig.columns)).map(
1916
+ columnDescriptorToRuntimeColumDescriptor(tableAttributes, tableSchema)
1917
+ );
1918
+ const maybePinnedColumns = runtimeColumns.some(isPinned) ? sortPinnedColumns(runtimeColumns) : runtimeColumns;
1919
+ let state = {
1920
+ columns: maybePinnedColumns,
1921
+ headings: getTableHeadings(maybePinnedColumns),
1922
+ tableConfig,
1923
+ ...tableAttributes
1924
+ };
1925
+ if (dataSourceConfig) {
1926
+ const { columns: _, ...rest } = dataSourceConfig;
1927
+ state = updateTableConfig2(state, {
1928
+ type: "tableConfig",
1929
+ ...rest
1930
+ });
1931
+ }
1932
+ return state;
1933
+ }
1934
+ var getLabel = (label, columnFormatHeader) => {
1935
+ if (columnFormatHeader === "uppercase") {
1936
+ return label.toUpperCase();
1937
+ } else if (columnFormatHeader === "capitalize") {
1938
+ return label[0].toUpperCase() + label.slice(1).toLowerCase();
1939
+ }
1940
+ return label;
1941
+ };
1942
+ var columnDescriptorToRuntimeColumDescriptor = (tableAttributes, tableSchema) => (column, index) => {
1943
+ const { columnDefaultWidth = DEFAULT_COLUMN_WIDTH, columnFormatHeader } = tableAttributes;
1944
+ const serverDataType = getDataType(column, tableSchema);
1945
+ const {
1946
+ align = getDefaultAlignment(serverDataType),
1947
+ name,
1948
+ label = getColumnLabel(column),
1949
+ width = columnDefaultWidth,
1950
+ ...rest
1951
+ } = column;
1952
+ const runtimeColumnWithDefaults = {
1953
+ ...rest,
1954
+ align,
1955
+ CellRenderer: getCellRenderer(column),
1956
+ HeaderCellContentRenderer: getColumnHeaderContentRenderer(column),
1957
+ HeaderCellLabelRenderer: getColumnHeaderLabelRenderer(column),
1958
+ clientSideEditValidationCheck: hasValidationRules(column.type) ? buildValidationChecker(column.type.renderer.rules) : void 0,
1959
+ index: index + 1,
1960
+ label: getLabel(label, columnFormatHeader),
1961
+ name,
1962
+ originalIdx: index,
1963
+ serverDataType,
1964
+ valueFormatter: getValueFormatter(column, serverDataType),
1965
+ width
1966
+ };
1967
+ if (isGroupColumn3(runtimeColumnWithDefaults)) {
1968
+ runtimeColumnWithDefaults.columns = runtimeColumnWithDefaults.columns.map(
1969
+ (col) => columnDescriptorToRuntimeColumDescriptor(tableAttributes)(col, index)
1970
+ );
1971
+ }
1972
+ return runtimeColumnWithDefaults;
1973
+ };
1974
+ function moveColumn(state, { column, moveBy }) {
1975
+ const { columns } = state;
1976
+ if (typeof moveBy === "number") {
1977
+ const idx = columns.indexOf(column);
1978
+ const newColumns = columns.slice();
1979
+ const [movedColumns] = newColumns.splice(idx, 1);
1980
+ newColumns.splice(idx + moveBy, 0, movedColumns);
1981
+ return {
1982
+ ...state,
1983
+ columns: newColumns
1984
+ };
1985
+ }
1986
+ return state;
1987
+ }
1988
+ function hideColumns(state, { columns }) {
1989
+ if (columns.some((col) => col.hidden !== true)) {
1990
+ return columns.reduce((s, c) => {
1991
+ if (c.hidden !== true) {
1992
+ return updateColumnProp(s, {
1993
+ type: "updateColumnProp",
1994
+ column: c,
1995
+ hidden: true
1996
+ });
1997
+ } else {
1998
+ return s;
1999
+ }
2000
+ }, state);
2001
+ } else {
2002
+ return state;
2003
+ }
2004
+ }
2005
+ function showColumns(state, { columns }) {
2006
+ if (columns.some((col) => col.hidden)) {
2007
+ return columns.reduce((s, c) => {
2008
+ if (c.hidden) {
2009
+ return updateColumnProp(s, {
2010
+ type: "updateColumnProp",
2011
+ column: c,
2012
+ hidden: false
2013
+ });
2014
+ } else {
2015
+ return s;
2016
+ }
2017
+ }, state);
2018
+ } else {
2019
+ return state;
2020
+ }
2021
+ }
2022
+ function resizeColumn(state, { column, phase, width }) {
2023
+ const type = "updateColumnProp";
2024
+ const resizing = phase !== "end";
2025
+ switch (phase) {
2026
+ case "begin":
2027
+ return updateColumnProp(state, { type, column, resizing });
2028
+ case "end":
2029
+ return updateColumnProp(state, { type, column, resizing, width });
2030
+ case "resize":
2031
+ return updateColumnProp(state, { type, column, width });
2032
+ default:
2033
+ throw Error(`useTableModel.resizeColumn, invalid resizePhase ${phase}`);
2034
+ }
2035
+ }
2036
+ function setTableSchema(state, { tableSchema }) {
2037
+ const { columns } = state;
2038
+ if (columns.some(columnWithoutDataType)) {
2039
+ const cols = columns.map((column) => {
2040
+ var _a;
2041
+ const serverDataType = getDataType(column, tableSchema);
2042
+ return {
2043
+ ...column,
2044
+ align: (_a = column.align) != null ? _a : getDefaultAlignment(serverDataType),
2045
+ serverDataType
2046
+ };
2047
+ });
2048
+ return {
2049
+ ...state,
2050
+ columns: cols
2051
+ };
2052
+ } else {
2053
+ return state;
2054
+ }
2055
+ }
2056
+ function pinColumn2(state, action) {
2057
+ let { columns } = state;
2058
+ const { column, pin } = action;
2059
+ const targetColumn = columns.find((col) => col.name === column.name);
2060
+ if (targetColumn) {
2061
+ columns = replaceColumn(columns, { ...targetColumn, pin });
2062
+ columns = sortPinnedColumns(columns);
2063
+ return {
2064
+ ...state,
2065
+ columns
2066
+ };
2067
+ } else {
2068
+ return state;
2069
+ }
2070
+ }
2071
+ function updateColumnProp(state, action) {
2072
+ let { columns, tableConfig } = state;
2073
+ const { align, column, hidden, label, resizing, width } = action;
2074
+ const targetColumn = columns.find((col) => col.name === column.name);
2075
+ if (targetColumn) {
2076
+ if (align === "left" || align === "right") {
2077
+ columns = replaceColumn(columns, { ...targetColumn, align });
2078
+ }
2079
+ if (typeof label === "string") {
2080
+ columns = replaceColumn(columns, { ...targetColumn, label });
2081
+ }
2082
+ if (typeof resizing === "boolean") {
2083
+ columns = replaceColumn(columns, { ...targetColumn, resizing });
2084
+ }
2085
+ if (typeof hidden === "boolean") {
2086
+ columns = replaceColumn(columns, { ...targetColumn, hidden });
2087
+ }
2088
+ if (typeof width === "number") {
2089
+ columns = replaceColumn(columns, { ...targetColumn, width });
2090
+ const targetConfigColumn = tableConfig.columns.find(
2091
+ (col) => col.name === column.name
2092
+ );
2093
+ if (targetConfigColumn) {
2094
+ tableConfig = {
2095
+ ...tableConfig,
2096
+ columns: replaceColumn(tableConfig.columns, {
2097
+ ...targetConfigColumn,
2098
+ width
2099
+ })
2100
+ };
2101
+ }
2102
+ }
2103
+ }
2104
+ return {
2105
+ ...state,
2106
+ columns,
2107
+ tableConfig
2108
+ };
2109
+ }
2110
+ function updateTableConfig2(state, { confirmed, filter, groupBy, sort }) {
2111
+ const hasGroupBy = groupBy !== void 0;
2112
+ const hasFilter = typeof (filter == null ? void 0 : filter.filter) === "string";
2113
+ const hasSort = sort && sort.sortDefs.length > 0;
2114
+ let result = state;
2115
+ if (hasGroupBy) {
2116
+ result = {
2117
+ ...state,
2118
+ columns: applyGroupByToColumns(result.columns, groupBy, confirmed)
2119
+ };
2120
+ }
2121
+ if (hasSort) {
2122
+ result = {
2123
+ ...state,
2124
+ columns: applySortToColumns(result.columns, sort)
2125
+ };
2126
+ }
2127
+ if (hasFilter) {
2128
+ result = {
2129
+ ...state,
2130
+ columns: applyFilterToColumns(result.columns, filter)
2131
+ };
2132
+ } else if (result.columns.some(isFilteredColumn)) {
2133
+ result = {
2134
+ ...state,
2135
+ columns: stripFilterFromColumns(result.columns)
2136
+ };
2137
+ }
2138
+ return result;
2139
+ }
2140
+
2141
+ // src/useTableScroll.ts
2142
+ import {
2143
+ getColumnsInViewport,
2144
+ getRowElementAtIndex,
2145
+ itemsChanged
2146
+ } from "@vuu-ui/vuu-utils";
2147
+ import {
2148
+ useCallback as useCallback16,
2149
+ useEffect as useEffect3,
2150
+ useImperativeHandle,
2151
+ useMemo as useMemo4,
2152
+ useRef as useRef11,
2153
+ useState as useState5
2154
+ } from "react";
2155
+ var SCROLL_MOVE_CHECK_THRESHOLD = 100;
2156
+ var HORIZONTAL_SCROLL_BUFFER = 200;
2157
+ var getMaxScroll = (container) => {
2158
+ const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;
2159
+ return [scrollWidth - clientWidth, scrollHeight - clientHeight];
2160
+ };
2161
+ var getScrollDirection = (prevScrollPositions, scrollPos) => {
2162
+ if (prevScrollPositions === void 0) {
2163
+ return void 0;
2164
+ } else {
2165
+ const { scrollTop: prevTop } = prevScrollPositions;
2166
+ return scrollPos > prevTop ? "fwd" : "bwd";
2167
+ }
2168
+ };
2169
+ var getPctScroll = (container, currentScrollPos) => {
2170
+ const {
2171
+ clientHeight,
2172
+ clientWidth,
2173
+ scrollHeight,
2174
+ scrollLeft,
2175
+ scrollTop,
2176
+ scrollWidth
2177
+ } = container;
2178
+ const maxScrollLeft = scrollWidth - clientWidth;
2179
+ const pctScrollLeft = scrollLeft / (scrollWidth - clientWidth);
2180
+ const maxScrollTop = scrollHeight - clientHeight;
2181
+ let pctScrollTop = scrollTop / (scrollHeight - clientHeight);
2182
+ const scrollDirection = getScrollDirection(currentScrollPos, scrollTop);
2183
+ if (scrollDirection === "fwd" && pctScrollTop > 0.99) {
2184
+ pctScrollTop = 1;
2185
+ } else if (scrollDirection === "bwd" && pctScrollTop < 0.02) {
2186
+ pctScrollTop = 0;
2187
+ }
2188
+ return [
2189
+ scrollLeft,
2190
+ pctScrollLeft,
2191
+ maxScrollLeft,
2192
+ scrollTop,
2193
+ pctScrollTop,
2194
+ maxScrollTop
2195
+ ];
2196
+ };
2197
+ var noScrolling = {
2198
+ scrollToIndex: () => void 0,
2199
+ scrollToKey: () => void 0
2200
+ };
2201
+ var useCallbackRef = ({
2202
+ onAttach,
2203
+ onDetach
2204
+ }) => {
2205
+ const ref = useRef11(null);
2206
+ const callbackRef = useCallback16(
2207
+ (el) => {
2208
+ if (el) {
2209
+ ref.current = el;
2210
+ onAttach == null ? void 0 : onAttach(el);
2211
+ } else if (ref.current) {
2212
+ const { current: originalRef } = ref;
2213
+ ref.current = el;
2214
+ onDetach == null ? void 0 : onDetach(originalRef);
2215
+ }
2216
+ },
2217
+ [onAttach, onDetach]
2218
+ );
2219
+ return callbackRef;
2220
+ };
2221
+ var useTableScroll = ({
2222
+ columns,
2223
+ getRowAtPosition,
2224
+ onHorizontalScroll,
2225
+ onVerticalScroll,
2226
+ onVerticalScrollInSitu,
2227
+ scrollingApiRef,
2228
+ setRange,
2229
+ viewportMeasurements
2230
+ }) => {
2231
+ const firstRowRef = useRef11(0);
2232
+ const contentContainerScrolledRef = useRef11(false);
2233
+ const contentContainerPosRef = useRef11({
2234
+ scrollTop: 0,
2235
+ scrollLeft: 0
2236
+ });
2237
+ const scrollbarContainerScrolledRef = useRef11(false);
2238
+ const scrollbarContainerPosRef = useRef11({
2239
+ scrollTop: 0,
2240
+ scrollLeft: 0
2241
+ });
2242
+ const scrollbarContainerRef = useRef11(null);
2243
+ const contentContainerRef = useRef11(null);
2244
+ const lastHorizontalScrollCheckPoint = useRef11(0);
2245
+ const {
2246
+ appliedPageSize,
2247
+ isVirtualScroll,
2248
+ rowCount: viewportRowCount,
2249
+ totalHeaderHeight,
2250
+ viewportWidth
2251
+ } = viewportMeasurements;
2252
+ const columnsWithinViewportRef = useRef11([]);
2253
+ const [, forceRefresh] = useState5({});
2254
+ const preSpanRef = useRef11(0);
2255
+ useMemo4(() => {
2256
+ const [visibleColumns, offset] = getColumnsInViewport(
2257
+ columns,
2258
+ contentContainerPosRef.current.scrollLeft,
2259
+ contentContainerPosRef.current.scrollLeft + viewportWidth + HORIZONTAL_SCROLL_BUFFER
2260
+ );
2261
+ preSpanRef.current = offset;
2262
+ columnsWithinViewportRef.current = visibleColumns;
2263
+ }, [viewportWidth, columns]);
2264
+ const handleHorizontalScroll = useCallback16(
2265
+ (scrollLeft) => {
2266
+ contentContainerPosRef.current.scrollLeft = scrollLeft;
2267
+ onHorizontalScroll == null ? void 0 : onHorizontalScroll(scrollLeft);
2268
+ if (Math.abs(scrollLeft - lastHorizontalScrollCheckPoint.current) > SCROLL_MOVE_CHECK_THRESHOLD) {
2269
+ lastHorizontalScrollCheckPoint.current = scrollLeft;
2270
+ const [visibleColumns, pre] = getColumnsInViewport(
2271
+ columns,
2272
+ scrollLeft,
2273
+ scrollLeft + viewportWidth + HORIZONTAL_SCROLL_BUFFER
2274
+ );
2275
+ if (itemsChanged(columnsWithinViewportRef.current, visibleColumns)) {
2276
+ preSpanRef.current = pre;
2277
+ columnsWithinViewportRef.current = visibleColumns;
2278
+ forceRefresh({});
2279
+ }
2280
+ }
2281
+ },
2282
+ [columns, onHorizontalScroll, viewportWidth]
2283
+ );
2284
+ const handleVerticalScroll = useCallback16(
2285
+ (scrollTop, pctScrollTop) => {
2286
+ contentContainerPosRef.current.scrollTop = scrollTop;
2287
+ onVerticalScroll == null ? void 0 : onVerticalScroll(scrollTop, pctScrollTop);
2288
+ const firstRow = getRowAtPosition(scrollTop);
2289
+ if (firstRow !== firstRowRef.current) {
2290
+ firstRowRef.current = firstRow;
2291
+ setRange({ from: firstRow, to: firstRow + viewportRowCount });
2292
+ }
2293
+ onVerticalScrollInSitu == null ? void 0 : onVerticalScrollInSitu(0);
2294
+ },
2295
+ [
2296
+ getRowAtPosition,
2297
+ onVerticalScroll,
2298
+ onVerticalScrollInSitu,
2299
+ setRange,
2300
+ viewportRowCount
2301
+ ]
2302
+ );
2303
+ const handleScrollbarContainerScroll = useCallback16(() => {
2304
+ const { current: contentContainer } = contentContainerRef;
2305
+ const { current: scrollbarContainer } = scrollbarContainerRef;
2306
+ const { current: contentContainerScrolled } = contentContainerScrolledRef;
2307
+ const { current: scrollPos } = scrollbarContainerPosRef;
2308
+ if (contentContainerScrolled) {
2309
+ contentContainerScrolledRef.current = false;
2310
+ } else if (contentContainer && scrollbarContainer) {
2311
+ scrollbarContainerScrolledRef.current = true;
2312
+ const [scrollLeft, pctScrollLeft, , scrollTop, pctScrollTop] = getPctScroll(scrollbarContainer, scrollPos);
2313
+ scrollPos.scrollLeft = scrollLeft;
2314
+ scrollPos.scrollTop = scrollTop;
2315
+ const [maxScrollLeft, maxScrollTop] = getMaxScroll(scrollbarContainer);
2316
+ const contentScrollLeft = Math.round(pctScrollLeft * maxScrollLeft);
2317
+ const contentScrollTop = pctScrollTop * maxScrollTop;
2318
+ contentContainer.scrollTo({
2319
+ left: contentScrollLeft,
2320
+ top: contentScrollTop,
2321
+ behavior: "auto"
2322
+ });
2323
+ }
2324
+ onVerticalScrollInSitu == null ? void 0 : onVerticalScrollInSitu(0);
2325
+ }, [onVerticalScrollInSitu]);
2326
+ const handleContentContainerScroll = useCallback16(() => {
2327
+ const { current: scrollbarContainerScrolled } = scrollbarContainerScrolledRef;
2328
+ const { current: contentContainer } = contentContainerRef;
2329
+ const { current: scrollbarContainer } = scrollbarContainerRef;
2330
+ const { current: scrollPos } = contentContainerPosRef;
2331
+ if (contentContainer && scrollbarContainer) {
2332
+ const [
2333
+ scrollLeft,
2334
+ pctScrollLeft,
2335
+ maxScrollLeft,
2336
+ scrollTop,
2337
+ pctScrollTop,
2338
+ maxScrollTop
2339
+ ] = getPctScroll(contentContainer);
2340
+ contentContainerScrolledRef.current = true;
2341
+ if (scrollbarContainerScrolled) {
2342
+ scrollbarContainerScrolledRef.current = false;
2343
+ } else {
2344
+ scrollbarContainer.scrollLeft = Math.round(
2345
+ pctScrollLeft * maxScrollLeft
2346
+ );
2347
+ scrollbarContainer.scrollTop = pctScrollTop * maxScrollTop;
2348
+ }
2349
+ if (scrollPos.scrollTop !== scrollTop) {
2350
+ handleVerticalScroll(scrollTop, pctScrollTop);
2351
+ }
2352
+ if (scrollPos.scrollLeft !== scrollLeft) {
2353
+ handleHorizontalScroll(scrollLeft);
2354
+ }
2355
+ }
2356
+ }, [handleVerticalScroll, handleHorizontalScroll]);
2357
+ const handleAttachScrollbarContainer = useCallback16(
2358
+ (el) => {
2359
+ scrollbarContainerRef.current = el;
2360
+ el.addEventListener("scroll", handleScrollbarContainerScroll, {
2361
+ passive: true
2362
+ });
2363
+ },
2364
+ [handleScrollbarContainerScroll]
2365
+ );
2366
+ const handleDetachScrollbarContainer = useCallback16(
2367
+ (el) => {
2368
+ scrollbarContainerRef.current = null;
2369
+ el.removeEventListener("scroll", handleScrollbarContainerScroll);
2370
+ },
2371
+ [handleScrollbarContainerScroll]
2372
+ );
2373
+ const handleAttachContentContainer = useCallback16(
2374
+ (el) => {
2375
+ contentContainerRef.current = el;
2376
+ el.addEventListener("scroll", handleContentContainerScroll, {
2377
+ passive: true
2378
+ });
2379
+ },
2380
+ [handleContentContainerScroll]
2381
+ );
2382
+ const handleDetachContentContainer = useCallback16(
2383
+ (el) => {
2384
+ contentContainerRef.current = null;
2385
+ el.removeEventListener("scroll", handleContentContainerScroll);
2386
+ },
2387
+ [handleContentContainerScroll]
2388
+ );
2389
+ const contentContainerCallbackRef = useCallbackRef({
2390
+ onAttach: handleAttachContentContainer,
2391
+ onDetach: handleDetachContentContainer
2392
+ });
2393
+ const scrollbarContainerCallbackRef = useCallbackRef({
2394
+ onAttach: handleAttachScrollbarContainer,
2395
+ onDetach: handleDetachScrollbarContainer
2396
+ });
2397
+ const requestScroll = useCallback16(
2398
+ (scrollRequest) => {
2399
+ const { current: contentContainer } = contentContainerRef;
2400
+ if (contentContainer) {
2401
+ const [maxScrollLeft, maxScrollTop] = getMaxScroll(contentContainer);
2402
+ const { scrollLeft, scrollTop } = contentContainer;
2403
+ contentContainerScrolledRef.current = false;
2404
+ if (scrollRequest.type === "scroll-row") {
2405
+ const activeRow = getRowElementAtIndex(
2406
+ contentContainer,
2407
+ scrollRequest.rowIndex
2408
+ );
2409
+ if (activeRow !== null) {
2410
+ const [direction, distance] = howFarIsRowOutsideViewport(
2411
+ activeRow,
2412
+ totalHeaderHeight
2413
+ );
2414
+ if (direction && distance) {
2415
+ if (isVirtualScroll) {
2416
+ const offset = direction === "down" ? 1 : -1;
2417
+ onVerticalScrollInSitu == null ? void 0 : onVerticalScrollInSitu(offset);
2418
+ const firstRow = firstRowRef.current + offset;
2419
+ firstRowRef.current = firstRow;
2420
+ setRange({
2421
+ from: firstRow,
2422
+ to: firstRow + viewportRowCount
2423
+ });
2424
+ } else {
2425
+ let newScrollLeft = scrollLeft;
2426
+ let newScrollTop = scrollTop;
2427
+ if (direction === "up" || direction === "down") {
2428
+ newScrollTop = Math.min(
2429
+ Math.max(0, scrollTop + distance),
2430
+ maxScrollTop
2431
+ );
2432
+ } else {
2433
+ newScrollLeft = Math.min(
2434
+ Math.max(0, scrollLeft + distance),
2435
+ maxScrollLeft
2436
+ );
2437
+ }
2438
+ contentContainer.scrollTo({
2439
+ top: newScrollTop,
2440
+ left: newScrollLeft,
2441
+ behavior: "smooth"
2442
+ });
2443
+ }
2444
+ }
2445
+ }
2446
+ } else if (scrollRequest.type === "scroll-page") {
2447
+ const { direction } = scrollRequest;
2448
+ if (isVirtualScroll) {
2449
+ const offset = direction === "down" ? viewportRowCount : -viewportRowCount;
2450
+ onVerticalScrollInSitu == null ? void 0 : onVerticalScrollInSitu(offset);
2451
+ const firstRow = firstRowRef.current + offset;
2452
+ firstRowRef.current = firstRow;
2453
+ setRange({ from: firstRow, to: firstRow + viewportRowCount });
2454
+ } else {
2455
+ const scrollBy = direction === "down" ? appliedPageSize : -appliedPageSize;
2456
+ const newScrollTop = Math.min(
2457
+ Math.max(0, scrollTop + scrollBy),
2458
+ maxScrollTop
2459
+ );
2460
+ contentContainer.scrollTo({
2461
+ top: newScrollTop,
2462
+ left: scrollLeft,
2463
+ behavior: "auto"
2464
+ });
2465
+ }
2466
+ } else if (scrollRequest.type === "scroll-end") {
2467
+ const { direction } = scrollRequest;
2468
+ const scrollTo = direction === "end" ? maxScrollTop : 0;
2469
+ contentContainer.scrollTo({
2470
+ top: scrollTo,
2471
+ left: contentContainer.scrollLeft,
2472
+ behavior: "auto"
2473
+ });
2474
+ }
2475
+ }
2476
+ },
2477
+ [
2478
+ appliedPageSize,
2479
+ isVirtualScroll,
2480
+ onVerticalScrollInSitu,
2481
+ setRange,
2482
+ totalHeaderHeight,
2483
+ viewportRowCount
2484
+ ]
2485
+ );
2486
+ const scrollHandles = useMemo4(
2487
+ // TODO not complete yet
2488
+ () => ({
2489
+ scrollToIndex: (rowIndex) => {
2490
+ if (scrollbarContainerRef.current) {
2491
+ const scrollPos = (rowIndex - 30) * 20;
2492
+ scrollbarContainerRef.current.scrollTop = scrollPos;
2493
+ }
2494
+ },
2495
+ scrollToKey: (rowKey) => {
2496
+ console.log(`scrollToKey ${rowKey}`);
2497
+ }
2498
+ }),
2499
+ []
2500
+ );
2501
+ useImperativeHandle(
2502
+ scrollingApiRef,
2503
+ () => {
2504
+ if (scrollbarContainerRef.current) {
2505
+ return scrollHandles;
2506
+ } else {
2507
+ return noScrolling;
2508
+ }
2509
+ },
2510
+ [scrollHandles]
2511
+ );
2512
+ useEffect3(() => {
2513
+ const { current: from } = firstRowRef;
2514
+ const rowRange = { from, to: from + viewportRowCount };
2515
+ setRange(rowRange);
2516
+ }, [setRange, viewportRowCount]);
2517
+ return {
2518
+ columnsWithinViewport: columnsWithinViewportRef.current,
2519
+ /** Ref to be assigned to ScrollbarContainer */
2520
+ scrollbarContainerRef: scrollbarContainerCallbackRef,
2521
+ /** Ref to be assigned to ContentContainer */
2522
+ contentContainerRef: contentContainerCallbackRef,
2523
+ /** Scroll the table */
2524
+ requestScroll,
2525
+ /** number of leading columns not rendered because of virtualization */
2526
+ virtualColSpan: preSpanRef.current
2527
+ };
2528
+ };
2529
+
2530
+ // src/useTableViewport.ts
2531
+ import {
2532
+ actualRowPositioning,
2533
+ measurePinnedColumns,
2534
+ virtualRowPositioning
2535
+ } from "@vuu-ui/vuu-utils";
2536
+ import { useCallback as useCallback17, useMemo as useMemo5, useRef as useRef12 } from "react";
2537
+ var MAX_PIXEL_HEIGHT = 1e7;
2538
+ var UNMEASURED_VIEWPORT = {
2539
+ appliedPageSize: 0,
2540
+ contentHeight: 0,
2541
+ contentWidth: 0,
2542
+ getRowAtPosition: () => -1,
2543
+ getRowOffset: () => -1,
2544
+ horizontalScrollbarHeight: 0,
2545
+ isVirtualScroll: false,
2546
+ pinnedWidthLeft: 0,
2547
+ pinnedWidthRight: 0,
2548
+ rowCount: 0,
2549
+ setInSituRowOffset: () => void 0,
2550
+ setScrollTop: () => void 0,
2551
+ totalHeaderHeight: 0,
2552
+ verticalScrollbarWidth: 0,
2553
+ viewportBodyHeight: 0,
2554
+ viewportWidth: 0
2555
+ };
2556
+ var useTableViewport = ({
2557
+ columns,
2558
+ headerHeight,
2559
+ headings,
2560
+ rowCount,
2561
+ rowHeight,
2562
+ selectionEndSize = 4,
2563
+ size
2564
+ }) => {
2565
+ const inSituRowOffsetRef = useRef12(0);
2566
+ const pctScrollTopRef = useRef12(0);
2567
+ const pixelContentHeight = Math.min(rowHeight * rowCount, MAX_PIXEL_HEIGHT);
2568
+ const virtualContentHeight = rowCount * rowHeight;
2569
+ const virtualisedExtent = virtualContentHeight - pixelContentHeight;
2570
+ const { pinnedWidthLeft, pinnedWidthRight, unpinnedWidth } = useMemo5(
2571
+ () => measurePinnedColumns(columns, selectionEndSize),
2572
+ [columns, selectionEndSize]
2573
+ );
2574
+ const totalHeaderHeightRef = useRef12(headerHeight);
2575
+ useMemo5(() => {
2576
+ totalHeaderHeightRef.current = headerHeight * (1 + headings.length);
2577
+ }, [headerHeight, headings.length]);
2578
+ const [getRowOffset, getRowAtPosition, isVirtualScroll] = useMemo5(() => {
2579
+ if (virtualisedExtent) {
2580
+ const [_getRowOffset, getRowAtPosition2, _isVirtual] = virtualRowPositioning(rowHeight, virtualisedExtent, pctScrollTopRef);
2581
+ const getOffset = (row) => {
2582
+ return _getRowOffset(row, inSituRowOffsetRef.current);
2583
+ };
2584
+ return [getOffset, getRowAtPosition2, _isVirtual];
2585
+ } else {
2586
+ return actualRowPositioning(rowHeight);
2587
+ }
2588
+ }, [virtualisedExtent, rowHeight]);
2589
+ const setScrollTop = useCallback17((_, scrollPct) => {
2590
+ pctScrollTopRef.current = scrollPct;
2591
+ }, []);
2592
+ const setInSituRowOffset = useCallback17((rowIndexOffset) => {
2593
+ if (rowIndexOffset === 0) {
2594
+ inSituRowOffsetRef.current = 0;
2595
+ } else {
2596
+ inSituRowOffsetRef.current = Math.max(
2597
+ 0,
2598
+ inSituRowOffsetRef.current + rowIndexOffset
2599
+ );
2600
+ }
2601
+ }, []);
2602
+ return useMemo5(() => {
2603
+ if (size) {
2604
+ const { current: totalHeaderHeight } = totalHeaderHeightRef;
2605
+ const scrollbarSize = 15;
2606
+ const contentWidth = pinnedWidthLeft + unpinnedWidth + pinnedWidthRight;
2607
+ const horizontalScrollbarHeight = contentWidth > size.width ? scrollbarSize : 0;
2608
+ const visibleRows = (size.height - headerHeight) / rowHeight;
2609
+ const count = Number.isInteger(visibleRows) ? visibleRows : Math.ceil(visibleRows);
2610
+ const viewportBodyHeight = size.height - totalHeaderHeight;
2611
+ const verticalScrollbarWidth = pixelContentHeight > viewportBodyHeight ? scrollbarSize : 0;
2612
+ const appliedPageSize = count * rowHeight * (pixelContentHeight / virtualContentHeight);
2613
+ const viewportWidth = size.width;
2614
+ return {
2615
+ appliedPageSize,
2616
+ contentHeight: pixelContentHeight,
2617
+ contentWidth,
2618
+ getRowAtPosition,
2619
+ getRowOffset,
2620
+ isVirtualScroll,
2621
+ horizontalScrollbarHeight,
2622
+ pinnedWidthLeft,
2623
+ pinnedWidthRight,
2624
+ rowCount: count,
2625
+ setInSituRowOffset,
2626
+ setScrollTop,
2627
+ totalHeaderHeight,
2628
+ verticalScrollbarWidth,
2629
+ viewportBodyHeight,
2630
+ viewportWidth
2631
+ };
2632
+ } else {
2633
+ return UNMEASURED_VIEWPORT;
2634
+ }
2635
+ }, [
2636
+ getRowAtPosition,
2637
+ getRowOffset,
2638
+ headerHeight,
2639
+ isVirtualScroll,
2640
+ pinnedWidthLeft,
2641
+ unpinnedWidth,
2642
+ pinnedWidthRight,
2643
+ pixelContentHeight,
2644
+ rowHeight,
2645
+ setInSituRowOffset,
2646
+ setScrollTop,
2647
+ size,
2648
+ virtualContentHeight
2649
+ ]);
2650
+ };
2651
+
2652
+ // src/useTableAndColumnSettings.ts
2653
+ import { useLayoutProviderDispatch } from "@vuu-ui/vuu-layout";
2654
+ import { getCalculatedColumnType } from "@vuu-ui/vuu-utils";
2655
+ import { useCallback as useCallback18, useRef as useRef13, useState as useState6 } from "react";
2656
+ var useTableAndColumnSettings = ({
2657
+ availableColumns: availableColumnsProps,
2658
+ onAvailableColumnsChange,
2659
+ onConfigChange,
2660
+ onCreateCalculatedColumn,
2661
+ onDataSourceConfigChange,
2662
+ tableConfig
2663
+ }) => {
2664
+ const dispatchLayoutAction = useLayoutProviderDispatch();
2665
+ const showTableSettingsRef = useRef13();
2666
+ const [availableColumns, setAvailableColumns] = useState6(
2667
+ availableColumnsProps
2668
+ );
2669
+ const showContextPanel = useCallback18(
2670
+ (componentType, title, props) => {
2671
+ dispatchLayoutAction({
2672
+ type: "set-props",
2673
+ path: "#context-panel",
2674
+ props: {
2675
+ expanded: true,
2676
+ content: {
2677
+ type: componentType,
2678
+ props
2679
+ },
2680
+ title
2681
+ }
2682
+ });
2683
+ },
2684
+ [dispatchLayoutAction]
2685
+ );
2686
+ const handleCancelCreateColumn = useCallback18(() => {
2687
+ requestAnimationFrame(() => {
2688
+ var _a;
2689
+ (_a = showTableSettingsRef.current) == null ? void 0 : _a.call(showTableSettingsRef);
2690
+ });
2691
+ }, []);
2692
+ const handleCreateCalculatedColumn = useCallback18(
2693
+ (column) => {
2694
+ const newAvailableColumns = availableColumns.concat({
2695
+ name: column.name,
2696
+ serverDataType: getCalculatedColumnType(column)
2697
+ });
2698
+ setAvailableColumns(newAvailableColumns);
2699
+ onAvailableColumnsChange == null ? void 0 : onAvailableColumnsChange(newAvailableColumns);
2700
+ requestAnimationFrame(() => {
2701
+ var _a;
2702
+ (_a = showTableSettingsRef.current) == null ? void 0 : _a.call(showTableSettingsRef);
2703
+ });
2704
+ onCreateCalculatedColumn(column);
2705
+ },
2706
+ [availableColumns, onAvailableColumnsChange, onCreateCalculatedColumn]
2707
+ );
2708
+ const showColumnSettingsPanel = useCallback18(
2709
+ (action) => {
2710
+ showContextPanel("ColumnSettings", "Column Settings", {
2711
+ column: action.column,
2712
+ onCancelCreateColumn: handleCancelCreateColumn,
2713
+ onConfigChange,
2714
+ onCreateCalculatedColumn: handleCreateCalculatedColumn,
2715
+ tableConfig,
2716
+ vuuTable: action.vuuTable
2717
+ });
2718
+ },
2719
+ [
2720
+ handleCancelCreateColumn,
2721
+ handleCreateCalculatedColumn,
2722
+ onConfigChange,
2723
+ showContextPanel,
2724
+ tableConfig
2725
+ ]
2726
+ );
2727
+ const handleAddCalculatedColumn = useCallback18(() => {
2728
+ showColumnSettingsPanel({
2729
+ column: {
2730
+ name: "::",
2731
+ serverDataType: "string"
2732
+ },
2733
+ type: "columnSettings",
2734
+ vuuTable: { module: "SIMUL", table: "instruments" }
2735
+ });
2736
+ }, [showColumnSettingsPanel]);
2737
+ const handleNavigateToColumn = useCallback18(
2738
+ (columnName) => {
2739
+ const column = tableConfig.columns.find((c) => c.name === columnName);
2740
+ if (column) {
2741
+ showColumnSettingsPanel({
2742
+ type: "columnSettings",
2743
+ column,
2744
+ //TODO where do we get this from
2745
+ vuuTable: { module: "SIMUL", table: "instruments" }
2746
+ });
2747
+ }
2748
+ },
2749
+ [showColumnSettingsPanel, tableConfig.columns]
2750
+ );
2751
+ showTableSettingsRef.current = useCallback18(() => {
2752
+ showContextPanel("TableSettings", "DataGrid Settings", {
2753
+ availableColumns: availableColumns != null ? availableColumns : tableConfig.columns.map(({ name, serverDataType }) => ({
2754
+ name,
2755
+ serverDataType
2756
+ })),
2757
+ onAddCalculatedColumn: handleAddCalculatedColumn,
2758
+ onConfigChange,
2759
+ onDataSourceConfigChange,
2760
+ onNavigateToColumn: handleNavigateToColumn,
2761
+ tableConfig
2762
+ });
2763
+ }, [
2764
+ availableColumns,
2765
+ handleAddCalculatedColumn,
2766
+ handleNavigateToColumn,
2767
+ onConfigChange,
2768
+ onDataSourceConfigChange,
2769
+ showContextPanel,
2770
+ tableConfig
2771
+ ]);
2772
+ return {
2773
+ showColumnSettingsPanel,
2774
+ showTableSettingsPanel: showTableSettingsRef.current
2775
+ };
2776
+ };
2777
+
2778
+ // src/useTable.ts
2779
+ var stripInternalProperties = (tableConfig) => {
2780
+ return tableConfig;
2781
+ };
2782
+ var { KEY, IS_EXPANDED: IS_EXPANDED2, IS_LEAF: IS_LEAF2 } = metadataKeys5;
2783
+ var NULL_DRAG_DROP = {
2784
+ draggable: void 0,
2785
+ onMouseDown: void 0
2786
+ };
2787
+ var useNullDragDrop = () => NULL_DRAG_DROP;
2788
+ var addColumn = (tableConfig, column) => ({
2789
+ ...tableConfig,
2790
+ columns: tableConfig.columns.concat(column)
2791
+ });
2792
+ var useTable = ({
2793
+ allowDragDrop = false,
2794
+ availableColumns,
2795
+ config,
2796
+ containerRef,
2797
+ dataSource,
2798
+ disableFocus,
2799
+ headerHeight = 25,
2800
+ highlightedIndex: highlightedIndexProp,
2801
+ id,
2802
+ navigationStyle = "cell",
2803
+ onAvailableColumnsChange,
2804
+ onConfigChange,
2805
+ onDragStart,
2806
+ onDrop,
2807
+ onFeatureInvocation,
2808
+ onHighlight,
2809
+ onRowClick: onRowClickProp,
2810
+ onSelect,
2811
+ onSelectionChange,
2812
+ renderBufferSize = 0,
2813
+ rowHeight = 20,
2814
+ scrollingApiRef,
2815
+ selectionModel,
2816
+ size
2817
+ }) => {
2818
+ const [rowCount, setRowCount] = useState7(dataSource.size);
2819
+ if (dataSource === void 0) {
2820
+ throw Error("no data source provided to Vuu Table");
2821
+ }
2822
+ const useRowDragDrop = allowDragDrop ? useDragDrop2 : useNullDragDrop;
2823
+ const menuBuilder = useMemo6(
2824
+ () => buildContextMenuDescriptors(dataSource),
2825
+ [dataSource]
2826
+ );
2827
+ const onDataRowcountChange = useCallback19((size2) => {
2828
+ setRowCount(size2);
2829
+ }, []);
2830
+ const {
2831
+ columns,
2832
+ dispatchColumnAction,
2833
+ headings,
2834
+ tableAttributes,
2835
+ tableConfig
2836
+ } = useTableModel(config, dataSource);
2837
+ useLayoutEffectSkipFirst2(() => {
2838
+ dispatchColumnAction({
2839
+ type: "init",
2840
+ tableConfig: config,
2841
+ dataSource
2842
+ });
2843
+ }, [config, dataSource, dispatchColumnAction]);
2844
+ const applyTableConfigChange = useCallback19(
2845
+ (config2) => {
2846
+ dispatchColumnAction({
2847
+ type: "init",
2848
+ tableConfig: config2,
2849
+ dataSource
2850
+ });
2851
+ onConfigChange == null ? void 0 : onConfigChange(stripInternalProperties(config2));
2852
+ },
2853
+ [dataSource, dispatchColumnAction, onConfigChange]
2854
+ );
2855
+ const columnMap = useMemo6(
2856
+ () => buildColumnMap2(dataSource.columns),
2857
+ [dataSource.columns]
2858
+ );
2859
+ const onSubscribed = useCallback19(
2860
+ ({ tableSchema }) => {
2861
+ if (tableSchema) {
2862
+ dispatchColumnAction({
2863
+ type: "setTableSchema",
2864
+ tableSchema
2865
+ });
2866
+ } else {
2867
+ console.log("subscription message with no schema");
2868
+ }
2869
+ },
2870
+ [dispatchColumnAction]
2871
+ );
2872
+ const {
2873
+ getRowAtPosition,
2874
+ getRowOffset,
2875
+ setInSituRowOffset: viewportHookSetInSituRowOffset,
2876
+ setScrollTop: viewportHookSetScrollTop,
2877
+ ...viewportMeasurements
2878
+ } = useTableViewport({
2879
+ columns,
2880
+ headerHeight,
2881
+ headings,
2882
+ rowCount,
2883
+ rowHeight,
2884
+ size
2885
+ });
2886
+ const initialRange = useInitialValue({
2887
+ from: 0,
2888
+ to: viewportMeasurements.rowCount
2889
+ });
2890
+ const { data, dataRef, getSelectedRows, range, setRange } = useDataSource({
2891
+ dataSource,
2892
+ // We need to factor this out of Table
2893
+ onFeatureInvocation,
2894
+ renderBufferSize,
2895
+ onSizeChange: onDataRowcountChange,
2896
+ onSubscribed,
2897
+ range: initialRange
2898
+ });
2899
+ const { requestScroll, ...scrollProps } = useTableScroll({
2900
+ columns,
2901
+ getRowAtPosition,
2902
+ rowHeight,
2903
+ scrollingApiRef,
2904
+ setRange,
2905
+ onVerticalScroll: viewportHookSetScrollTop,
2906
+ onVerticalScrollInSitu: viewportHookSetInSituRowOffset,
2907
+ viewportMeasurements
2908
+ });
2909
+ const handleConfigEditedInSettingsPanel = useCallback19(
2910
+ (tableConfig2) => {
2911
+ dispatchColumnAction({
2912
+ type: "init",
2913
+ tableConfig: tableConfig2,
2914
+ dataSource
2915
+ });
2916
+ onConfigChange == null ? void 0 : onConfigChange(stripInternalProperties(tableConfig2));
2917
+ },
2918
+ [dataSource, dispatchColumnAction, onConfigChange]
2919
+ );
2920
+ const handleDataSourceConfigChanged = useCallback19(
2921
+ (dataSourceConfig) => {
2922
+ dataSource.config = {
2923
+ ...dataSource.config,
2924
+ ...dataSourceConfig
2925
+ };
2926
+ },
2927
+ [dataSource]
2928
+ );
2929
+ useEffect4(() => {
2930
+ dataSource.on("config", (config2, confirmed) => {
2931
+ dispatchColumnAction({
2932
+ type: "tableConfig",
2933
+ ...config2,
2934
+ confirmed
2935
+ });
2936
+ });
2937
+ }, [dataSource, dispatchColumnAction]);
2938
+ const handleCreateCalculatedColumn = useCallback19(
2939
+ (column) => {
2940
+ dataSource.columns = dataSource.columns.concat(column.name);
2941
+ applyTableConfigChange(addColumn(tableConfig, column));
2942
+ },
2943
+ [dataSource, tableConfig, applyTableConfigChange]
2944
+ );
2945
+ const hideColumns2 = useCallback19(
2946
+ (action) => {
2947
+ const { columns: columns2 } = action;
2948
+ const hiddenColumns = columns2.map((c) => c.name);
2949
+ const newTableConfig = {
2950
+ ...tableConfig,
2951
+ columns: tableConfig.columns.map(
2952
+ (col) => hiddenColumns.includes(col.name) ? { ...col, hidden: true } : col
2953
+ )
2954
+ };
2955
+ applyTableConfigChange(newTableConfig);
2956
+ },
2957
+ [tableConfig, applyTableConfigChange]
2958
+ );
2959
+ const pinColumn3 = useCallback19(
2960
+ (action) => {
2961
+ applyTableConfigChange({
2962
+ ...tableConfig,
2963
+ columns: updateColumn(tableConfig.columns, {
2964
+ ...action.column,
2965
+ pin: action.pin
2966
+ })
2967
+ });
2968
+ },
2969
+ [tableConfig, applyTableConfigChange]
2970
+ );
2971
+ const { showColumnSettingsPanel, showTableSettingsPanel } = useTableAndColumnSettings({
2972
+ availableColumns: availableColumns != null ? availableColumns : tableConfig.columns.map(({ name, serverDataType = "string" }) => ({
2973
+ name,
2974
+ serverDataType
2975
+ })),
2976
+ onAvailableColumnsChange,
2977
+ onConfigChange: handleConfigEditedInSettingsPanel,
2978
+ onCreateCalculatedColumn: handleCreateCalculatedColumn,
2979
+ onDataSourceConfigChange: handleDataSourceConfigChanged,
2980
+ tableConfig
2981
+ });
2982
+ const onPersistentColumnOperation = useCallback19(
2983
+ (action) => {
2984
+ if (isShowColumnSettings(action)) {
2985
+ showColumnSettingsPanel(action);
2986
+ } else if (isShowTableSettings(action)) {
2987
+ showTableSettingsPanel();
2988
+ } else {
2989
+ switch (action.type) {
2990
+ case "hideColumns":
2991
+ return hideColumns2(action);
2992
+ case "pinColumn":
2993
+ return pinColumn3(action);
2994
+ default:
2995
+ dispatchColumnAction(action);
2996
+ }
2997
+ }
2998
+ },
2999
+ [
3000
+ dispatchColumnAction,
3001
+ hideColumns2,
3002
+ pinColumn3,
3003
+ showColumnSettingsPanel,
3004
+ showTableSettingsPanel
3005
+ ]
3006
+ );
3007
+ const handleContextMenuAction = useHandleTableContextMenu({
3008
+ dataSource,
3009
+ onPersistentColumnOperation
3010
+ });
3011
+ const handleSort = useCallback19(
3012
+ (column, extendSort = false, sortType) => {
3013
+ if (dataSource) {
3014
+ dataSource.sort = applySort(
3015
+ dataSource.sort,
3016
+ column,
3017
+ extendSort,
3018
+ sortType
3019
+ );
3020
+ }
3021
+ },
3022
+ [dataSource]
3023
+ );
3024
+ const resizeCells = useRef14();
3025
+ const onResizeColumn = useCallback19(
3026
+ (phase, columnName, width) => {
3027
+ var _a, _b, _c;
3028
+ const column = columns.find((column2) => column2.name === columnName);
3029
+ if (column) {
3030
+ if (phase === "resize") {
3031
+ (_a = resizeCells.current) == null ? void 0 : _a.forEach((cell) => {
3032
+ cell.style.width = `${width}px`;
3033
+ });
3034
+ } else if (phase === "end") {
3035
+ resizeCells.current = void 0;
3036
+ if (isValidNumber(width)) {
3037
+ dispatchColumnAction({
3038
+ type: "resizeColumn",
3039
+ phase,
3040
+ column,
3041
+ width
3042
+ });
3043
+ onConfigChange == null ? void 0 : onConfigChange(
3044
+ stripInternalProperties(
3045
+ updateTableConfig(tableConfig, {
3046
+ type: "col-size",
3047
+ column,
3048
+ width
3049
+ })
3050
+ )
3051
+ );
3052
+ }
3053
+ } else {
3054
+ const byColIndex = `[aria-colindex='${column.index}']`;
3055
+ resizeCells.current = Array.from(
3056
+ (_c = (_b = containerRef.current) == null ? void 0 : _b.querySelectorAll(
3057
+ `.vuuTableCell${byColIndex},.vuuTableHeaderCell${byColIndex}`
3058
+ )) != null ? _c : []
3059
+ );
3060
+ dispatchColumnAction({
3061
+ type: "resizeColumn",
3062
+ phase,
3063
+ column,
3064
+ width
3065
+ });
3066
+ }
3067
+ } else {
3068
+ throw Error(
3069
+ `useDataTable.handleColumnResize, column ${columnName} not found`
3070
+ );
3071
+ }
3072
+ },
3073
+ [columns, dispatchColumnAction, onConfigChange, tableConfig, containerRef]
3074
+ );
3075
+ const onToggleGroup = useCallback19(
3076
+ (row, column) => {
3077
+ var _a, _b;
3078
+ const isJson = isJsonGroup2(column, row, columnMap);
3079
+ const key = row[KEY];
3080
+ if (row[IS_EXPANDED2]) {
3081
+ dataSource.closeTreeNode(key, true);
3082
+ if (isJson) {
3083
+ const idx = columns.indexOf(column);
3084
+ const rows = (_a = dataSource.getRowsAtDepth) == null ? void 0 : _a.call(dataSource, idx + 1);
3085
+ if (rows && !rows.some((row2) => row2[IS_EXPANDED2] || row2[IS_LEAF2])) {
3086
+ dispatchColumnAction({
3087
+ type: "hideColumns",
3088
+ columns: columns.slice(idx + 2)
3089
+ });
3090
+ }
3091
+ }
3092
+ } else {
3093
+ dataSource.openTreeNode(key);
3094
+ if (isJson) {
3095
+ const childRows = (_b = dataSource.getChildRows) == null ? void 0 : _b.call(dataSource, key);
3096
+ const idx = columns.indexOf(column) + 1;
3097
+ const columnsToShow = [columns[idx]];
3098
+ if (childRows && childRows.some((row2) => row2[IS_LEAF2])) {
3099
+ columnsToShow.push(columns[idx + 1]);
3100
+ }
3101
+ if (columnsToShow.some((col) => col.hidden)) {
3102
+ dispatchColumnAction({
3103
+ type: "showColumns",
3104
+ columns: columnsToShow
3105
+ });
3106
+ }
3107
+ }
3108
+ }
3109
+ },
3110
+ [columnMap, columns, dataSource, dispatchColumnAction]
3111
+ );
3112
+ const {
3113
+ highlightedIndexRef,
3114
+ navigate,
3115
+ onFocus: navigationFocus,
3116
+ onKeyDown: navigationKeyDown,
3117
+ ...containerProps
3118
+ } = useKeyboardNavigation({
3119
+ columnCount: columns.filter((c) => c.hidden !== true).length,
3120
+ containerRef,
3121
+ disableFocus,
3122
+ highlightedIndex: highlightedIndexProp,
3123
+ navigationStyle,
3124
+ requestScroll,
3125
+ rowCount: dataSource == null ? void 0 : dataSource.size,
3126
+ onHighlight,
3127
+ viewportRange: range,
3128
+ viewportRowCount: viewportMeasurements.rowCount
3129
+ });
3130
+ const {
3131
+ onBlur: editingBlur,
3132
+ onDoubleClick: editingDoubleClick,
3133
+ onKeyDown: editingKeyDown,
3134
+ onFocus: editingFocus
3135
+ } = useCellEditing({
3136
+ navigate
3137
+ });
3138
+ const handleFocus = useCallback19(
3139
+ (e) => {
3140
+ navigationFocus();
3141
+ if (!e.defaultPrevented) {
3142
+ editingFocus(e);
3143
+ }
3144
+ },
3145
+ [editingFocus, navigationFocus]
3146
+ );
3147
+ const onContextMenu = useTableContextMenu({
3148
+ columns,
3149
+ data,
3150
+ dataSource,
3151
+ getSelectedRows
3152
+ });
3153
+ const onMoveGroupColumn = useCallback19(
3154
+ (columns2) => {
3155
+ dataSource.groupBy = columns2.map((col) => col.name);
3156
+ },
3157
+ [dataSource]
3158
+ );
3159
+ const onRemoveGroupColumn = useCallback19(
3160
+ (column) => {
3161
+ if (isGroupColumn4(column)) {
3162
+ dataSource.groupBy = [];
3163
+ } else {
3164
+ if (dataSource && dataSource.groupBy.includes(column.name)) {
3165
+ dataSource.groupBy = dataSource.groupBy.filter(
3166
+ (columnName) => columnName !== column.name
3167
+ );
3168
+ }
3169
+ }
3170
+ },
3171
+ [dataSource]
3172
+ );
3173
+ const handleSelectionChange = useCallback19(
3174
+ (selected) => {
3175
+ dataSource.select(selected);
3176
+ onSelectionChange == null ? void 0 : onSelectionChange(selected);
3177
+ },
3178
+ [dataSource, onSelectionChange]
3179
+ );
3180
+ const {
3181
+ onKeyDown: selectionHookKeyDown,
3182
+ onRowClick: selectionHookOnRowClick
3183
+ } = useSelection({
3184
+ highlightedIndexRef,
3185
+ onSelect,
3186
+ onSelectionChange: handleSelectionChange,
3187
+ selectionModel
3188
+ });
3189
+ const handleKeyDown = useCallback19(
3190
+ (e) => {
3191
+ navigationKeyDown(e);
3192
+ if (!e.defaultPrevented) {
3193
+ editingKeyDown(e);
3194
+ }
3195
+ if (!e.defaultPrevented) {
3196
+ selectionHookKeyDown(e);
3197
+ }
3198
+ },
3199
+ [navigationKeyDown, editingKeyDown, selectionHookKeyDown]
3200
+ );
3201
+ const handleRowClick = useCallback19(
3202
+ (row, rangeSelect, keepExistingSelection) => {
3203
+ selectionHookOnRowClick(row, rangeSelect, keepExistingSelection);
3204
+ onRowClickProp == null ? void 0 : onRowClickProp(row);
3205
+ },
3206
+ [onRowClickProp, selectionHookOnRowClick]
3207
+ );
3208
+ const onMoveColumn = useCallback19(
3209
+ (columns2) => {
3210
+ const newTableConfig = {
3211
+ ...tableConfig,
3212
+ columns: columns2
3213
+ };
3214
+ dispatchColumnAction({
3215
+ type: "init",
3216
+ tableConfig: newTableConfig,
3217
+ dataSource
3218
+ });
3219
+ onConfigChange == null ? void 0 : onConfigChange(stripInternalProperties(newTableConfig));
3220
+ },
3221
+ [dataSource, dispatchColumnAction, onConfigChange, tableConfig]
3222
+ );
3223
+ const handleDropRow = useCallback19(
3224
+ (dragDropState) => {
3225
+ onDrop == null ? void 0 : onDrop(dragDropState);
3226
+ },
3227
+ [onDrop]
3228
+ );
3229
+ const handleDataEdited = useCallback19(
3230
+ async (row, columnName, value) => dataSource.applyEdit(row, columnName, value),
3231
+ [dataSource]
3232
+ );
3233
+ const handleDragStartRow = useCallback19(
3234
+ (dragDropState) => {
3235
+ const { initialDragElement } = dragDropState;
3236
+ const rowIndex = getIndexFromRowElement3(initialDragElement);
3237
+ const row = dataRef.current.find((row2) => row2[0] === rowIndex);
3238
+ if (row) {
3239
+ dragDropState.setPayload(row);
3240
+ } else {
3241
+ }
3242
+ onDragStart == null ? void 0 : onDragStart(dragDropState);
3243
+ },
3244
+ [dataRef, onDragStart]
3245
+ );
3246
+ const { onMouseDown: rowDragMouseDown, draggable: draggableRow } = useRowDragDrop({
3247
+ allowDragDrop,
3248
+ containerRef,
3249
+ draggableClassName: `vuuTable`,
3250
+ id,
3251
+ onDragStart: handleDragStartRow,
3252
+ onDrop: handleDropRow,
3253
+ orientation: "vertical",
3254
+ itemQuery: ".vuuTableRow"
3255
+ });
3256
+ return {
3257
+ ...containerProps,
3258
+ "aria-rowcount": dataSource.size,
3259
+ draggableRow,
3260
+ onBlur: editingBlur,
3261
+ onDoubleClick: editingDoubleClick,
3262
+ onFocus: handleFocus,
3263
+ onKeyDown: handleKeyDown,
3264
+ onMouseDown: rowDragMouseDown,
3265
+ columnMap,
3266
+ columns,
3267
+ data,
3268
+ getRowOffset,
3269
+ handleContextMenuAction,
3270
+ headings,
3271
+ highlightedIndex: highlightedIndexRef.current,
3272
+ menuBuilder,
3273
+ onContextMenu,
3274
+ onDataEdited: handleDataEdited,
3275
+ onMoveColumn,
3276
+ onMoveGroupColumn,
3277
+ onRemoveGroupColumn,
3278
+ onRowClick: handleRowClick,
3279
+ onSortColumn: handleSort,
3280
+ onResizeColumn,
3281
+ onToggleGroup,
3282
+ scrollProps,
3283
+ // TODO don't think we need these ...
3284
+ tableAttributes,
3285
+ tableConfig,
3286
+ viewportMeasurements
3287
+ };
3288
+ };
3289
+
3290
+ // src/Table.tsx
3291
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
3292
+ var classBase7 = "vuuTable";
3293
+ var { IDX: IDX3, RENDER_IDX } = metadataKeys6;
3294
+ var TableCore = ({
3295
+ Row: Row2 = Row,
3296
+ allowDragDrop,
3297
+ availableColumns,
3298
+ config,
3299
+ containerRef,
3300
+ dataSource,
3301
+ disableFocus = false,
3302
+ highlightedIndex: highlightedIndexProp,
3303
+ id: idProp,
3304
+ navigationStyle = "cell",
3305
+ onAvailableColumnsChange,
3306
+ onConfigChange,
3307
+ onDragStart,
3308
+ onDrop,
3309
+ onFeatureInvocation,
3310
+ onHighlight,
3311
+ onRowClick: onRowClickProp,
3312
+ onSelect,
3313
+ onSelectionChange,
3314
+ renderBufferSize = 5,
3315
+ rowHeight = 20,
3316
+ scrollingApiRef,
3317
+ selectionModel = "extended",
3318
+ showColumnHeaders = true,
3319
+ headerHeight = showColumnHeaders ? 25 : 0,
3320
+ size
3321
+ }) => {
3322
+ const id = useId(idProp);
3323
+ const {
3324
+ columnMap,
3325
+ columns,
3326
+ data,
3327
+ draggableRow,
3328
+ getRowOffset,
3329
+ handleContextMenuAction,
3330
+ headings,
3331
+ highlightedIndex,
3332
+ onDataEdited,
3333
+ onMoveColumn,
3334
+ onMoveGroupColumn,
3335
+ onRemoveGroupColumn,
3336
+ onResizeColumn,
3337
+ onRowClick,
3338
+ onSortColumn,
3339
+ onToggleGroup,
3340
+ menuBuilder,
3341
+ scrollProps,
3342
+ tableAttributes,
3343
+ tableConfig,
3344
+ viewportMeasurements,
3345
+ ...tableProps
3346
+ } = useTable({
3347
+ allowDragDrop,
3348
+ availableColumns,
3349
+ config,
3350
+ containerRef,
3351
+ dataSource,
3352
+ disableFocus,
3353
+ headerHeight,
3354
+ highlightedIndex: highlightedIndexProp,
3355
+ id,
3356
+ navigationStyle,
3357
+ onAvailableColumnsChange,
3358
+ onConfigChange,
3359
+ onDragStart,
3360
+ onDrop,
3361
+ onFeatureInvocation,
3362
+ onHighlight,
3363
+ onRowClick: onRowClickProp,
3364
+ onSelect,
3365
+ onSelectionChange,
3366
+ renderBufferSize,
3367
+ rowHeight,
3368
+ scrollingApiRef,
3369
+ selectionModel,
3370
+ size
3371
+ });
3372
+ const contentContainerClassName = cx9(`${classBase7}-contentContainer`, {
3373
+ [`${classBase7}-colLines`]: tableAttributes.columnSeparators,
3374
+ [`${classBase7}-rowLines`]: tableAttributes.rowSeparators,
3375
+ [`${classBase7}-zebra`]: tableAttributes.zebraStripes
3376
+ });
3377
+ const cssVariables = {
3378
+ "--content-height": `${viewportMeasurements.contentHeight}px`,
3379
+ "--content-width": `${viewportMeasurements.contentWidth}px`,
3380
+ "--horizontal-scrollbar-height": `${viewportMeasurements.horizontalScrollbarHeight}px`,
3381
+ "--pinned-width-left": `${viewportMeasurements.pinnedWidthLeft}px`,
3382
+ "--pinned-width-right": `${viewportMeasurements.pinnedWidthRight}px`,
3383
+ "--header-height": `${headerHeight}px`,
3384
+ "--row-height": `${rowHeight}px`,
3385
+ "--total-header-height": `${viewportMeasurements.totalHeaderHeight}px`,
3386
+ "--vertical-scrollbar-width": `${viewportMeasurements.verticalScrollbarWidth}px`,
3387
+ "--viewport-body-height": `${viewportMeasurements.viewportBodyHeight}px`
3388
+ };
3389
+ return /* @__PURE__ */ jsxs9(
3390
+ ContextMenuProvider,
3391
+ {
3392
+ menuActionHandler: handleContextMenuAction,
3393
+ menuBuilder,
3394
+ children: [
3395
+ /* @__PURE__ */ jsx12(
3396
+ "div",
3397
+ {
3398
+ className: `${classBase7}-scrollbarContainer`,
3399
+ ref: scrollProps.scrollbarContainerRef,
3400
+ style: cssVariables,
3401
+ children: /* @__PURE__ */ jsx12("div", { className: `${classBase7}-scrollbarContent` })
3402
+ }
3403
+ ),
3404
+ /* @__PURE__ */ jsx12(
3405
+ "div",
3406
+ {
3407
+ className: contentContainerClassName,
3408
+ ref: scrollProps.contentContainerRef,
3409
+ style: cssVariables,
3410
+ children: /* @__PURE__ */ jsxs9(
3411
+ "div",
3412
+ {
3413
+ ...tableProps,
3414
+ className: `${classBase7}-table`,
3415
+ role: "table",
3416
+ tabIndex: disableFocus ? void 0 : -1,
3417
+ children: [
3418
+ showColumnHeaders ? /* @__PURE__ */ jsx12(
3419
+ TableHeader,
3420
+ {
3421
+ columns: scrollProps.columnsWithinViewport,
3422
+ headings,
3423
+ onMoveColumn,
3424
+ onMoveGroupColumn,
3425
+ onRemoveGroupColumn,
3426
+ onResizeColumn,
3427
+ onSortColumn,
3428
+ tableConfig,
3429
+ tableId: id,
3430
+ virtualColSpan: scrollProps.virtualColSpan
3431
+ }
3432
+ ) : null,
3433
+ /* @__PURE__ */ jsx12("div", { className: `${classBase7}-body`, children: data.map((data2) => /* @__PURE__ */ jsx12(
3434
+ Row2,
3435
+ {
3436
+ "aria-rowindex": data2[0] + 1,
3437
+ columnMap,
3438
+ columns: scrollProps.columnsWithinViewport,
3439
+ highlighted: highlightedIndex === data2[IDX3],
3440
+ onClick: onRowClick,
3441
+ onDataEdited,
3442
+ row: data2,
3443
+ offset: getRowOffset(data2),
3444
+ onToggleGroup,
3445
+ virtualColSpan: scrollProps.virtualColSpan,
3446
+ zebraStripes: tableAttributes.zebraStripes
3447
+ },
3448
+ data2[RENDER_IDX]
3449
+ )) })
3450
+ ]
3451
+ }
3452
+ )
3453
+ }
3454
+ ),
3455
+ draggableRow
3456
+ ]
3457
+ }
3458
+ );
3459
+ };
3460
+ var Table = forwardRef(function TableNext({
3461
+ Row: Row2,
3462
+ allowDragDrop,
3463
+ availableColumns,
3464
+ className: classNameProp,
3465
+ config,
3466
+ dataSource,
3467
+ disableFocus,
3468
+ highlightedIndex,
3469
+ id,
3470
+ navigationStyle,
3471
+ onAvailableColumnsChange,
3472
+ onConfigChange,
3473
+ onDragStart,
3474
+ onDrop,
3475
+ onFeatureInvocation,
3476
+ onHighlight,
3477
+ onRowClick,
3478
+ onSelect,
3479
+ onSelectionChange,
3480
+ renderBufferSize,
3481
+ rowHeight,
3482
+ scrollingApiRef,
3483
+ selectionModel,
3484
+ showColumnHeaders,
3485
+ headerHeight,
3486
+ style: styleProp,
3487
+ ...htmlAttributes
3488
+ }, forwardedRef) {
3489
+ const containerRef = useRef15(null);
3490
+ const [size, setSize] = useState8();
3491
+ if (config === void 0) {
3492
+ throw Error(
3493
+ "vuu Table requires config prop. Minimum config is list of Column Descriptors"
3494
+ );
3495
+ }
3496
+ if (dataSource === void 0) {
3497
+ throw Error("vuu Table requires dataSource prop");
3498
+ }
3499
+ return /* @__PURE__ */ jsx12(
3500
+ MeasuredContainer,
3501
+ {
3502
+ ...htmlAttributes,
3503
+ className: cx9(classBase7, classNameProp),
3504
+ id,
3505
+ onResize: setSize,
3506
+ ref: useForkRef(containerRef, forwardedRef),
3507
+ children: size ? /* @__PURE__ */ jsx12(
3508
+ TableCore,
3509
+ {
3510
+ Row: Row2,
3511
+ allowDragDrop,
3512
+ availableColumns,
3513
+ config,
3514
+ containerRef,
3515
+ dataSource,
3516
+ disableFocus,
3517
+ headerHeight,
3518
+ highlightedIndex,
3519
+ id,
3520
+ navigationStyle,
3521
+ onAvailableColumnsChange,
3522
+ onConfigChange,
3523
+ onDragStart,
3524
+ onDrop,
3525
+ onFeatureInvocation,
3526
+ onHighlight,
3527
+ onRowClick,
3528
+ onSelect,
3529
+ onSelectionChange,
3530
+ renderBufferSize,
3531
+ rowHeight,
3532
+ scrollingApiRef,
3533
+ selectionModel,
3534
+ showColumnHeaders,
3535
+ size
3536
+ }
3537
+ ) : null
3538
+ }
3539
+ );
3540
+ });
3541
+
3542
+ // src/cell-renderers/checkbox-cell/CheckboxCell.tsx
3543
+ import { memo as memo3, useCallback as useCallback20 } from "react";
3544
+ import { CheckboxIcon, WarnCommit } from "@vuu-ui/vuu-ui-controls";
3545
+ import { Checkbox } from "@salt-ds/core";
3546
+ import {
3547
+ dataAndColumnUnchanged,
3548
+ dispatchCustomEvent,
3549
+ registerComponent
3550
+ } from "@vuu-ui/vuu-utils";
3551
+ import { jsx as jsx13 } from "react/jsx-runtime";
3552
+ var CheckboxCell = memo3(
3553
+ ({ column, columnMap, onCommit = WarnCommit, row }) => {
3554
+ const dataIdx = columnMap[column.name];
3555
+ const isChecked = row[dataIdx];
3556
+ const handleCommit = useCallback20(
3557
+ (value) => async (evt) => {
3558
+ const res = await onCommit(value);
3559
+ if (res === true) {
3560
+ dispatchCustomEvent(evt.target, "vuu-commit");
3561
+ }
3562
+ return res;
3563
+ },
3564
+ [onCommit]
3565
+ );
3566
+ return column.editable ? /* @__PURE__ */ jsx13(Checkbox, { checked: isChecked, onClick: handleCommit(!isChecked) }) : /* @__PURE__ */ jsx13(CheckboxIcon, { checked: isChecked, disabled: true });
3567
+ },
3568
+ dataAndColumnUnchanged
3569
+ );
3570
+ CheckboxCell.displayName = "CheckboxCell";
3571
+ registerComponent("checkbox-cell", CheckboxCell, "cell-renderer", {
3572
+ serverDataType: "boolean"
3573
+ });
3574
+
3575
+ // src/cell-renderers/input-cell/InputCell.tsx
3576
+ import { registerComponent as registerComponent2 } from "@vuu-ui/vuu-utils";
3577
+ import { Input } from "@salt-ds/core";
3578
+ import { useEditableText } from "@vuu-ui/vuu-ui-controls";
3579
+ import cx10 from "clsx";
3580
+ import { jsx as jsx14 } from "react/jsx-runtime";
3581
+ var classBase8 = "vuuTableInputCell";
3582
+ var WarnCommit2 = () => {
3583
+ console.warn(
3584
+ "onCommit handler has not been provided to InputCell cell renderer"
3585
+ );
3586
+ return Promise.resolve(true);
3587
+ };
3588
+ var InputCell = ({
3589
+ column,
3590
+ columnMap,
3591
+ onCommit = WarnCommit2,
3592
+ row
3593
+ }) => {
3594
+ const dataIdx = columnMap[column.name];
3595
+ const { align = "left", clientSideEditValidationCheck } = column;
3596
+ const { warningMessage, ...editProps } = useEditableText({
3597
+ initialValue: row[dataIdx],
3598
+ onCommit,
3599
+ clientSideEditValidationCheck
3600
+ });
3601
+ const endAdornment = warningMessage && align === "left" ? /* @__PURE__ */ jsx14("span", { className: `${classBase8}-icon`, "data-icon": "error" }) : void 0;
3602
+ const startAdornment = warningMessage && align === "right" ? /* @__PURE__ */ jsx14("span", { className: `${classBase8}-icon`, "data-icon": "error" }) : void 0;
3603
+ return /* @__PURE__ */ jsx14(
3604
+ Input,
3605
+ {
3606
+ ...editProps,
3607
+ className: cx10(classBase8, {
3608
+ [`${classBase8}-error`]: warningMessage !== void 0
3609
+ }),
3610
+ endAdornment,
3611
+ startAdornment
3612
+ }
3613
+ );
3614
+ };
3615
+ registerComponent2("input-cell", InputCell, "cell-renderer", {});
3616
+
3617
+ // src/cell-renderers/toggle-cell/ToggleCell.tsx
3618
+ import { WarnCommit as WarnCommit3 } from "@vuu-ui/vuu-ui-controls";
3619
+ import {
3620
+ dataAndColumnUnchanged as dataAndColumnUnchanged2,
3621
+ dispatchCustomEvent as dispatchCustomEvent2,
3622
+ isTypeDescriptor,
3623
+ isValueListRenderer,
3624
+ registerComponent as registerComponent3
3625
+ } from "@vuu-ui/vuu-utils";
3626
+ import cx11 from "clsx";
3627
+ import { memo as memo4, useCallback as useCallback21 } from "react";
3628
+ import { CycleStateButton } from "@vuu-ui/vuu-ui-controls";
3629
+ import { jsx as jsx15 } from "react/jsx-runtime";
3630
+ var classBase9 = "vuuTableToggleCell";
3631
+ var getValueList = ({ name, type }) => {
3632
+ if (isTypeDescriptor(type) && isValueListRenderer(type.renderer)) {
3633
+ return type.renderer.values;
3634
+ } else {
3635
+ throw Error(
3636
+ `useLookupValues column ${name} has not been configured with a values list`
3637
+ );
3638
+ }
3639
+ };
3640
+ var ToggleCell = memo4(
3641
+ function ToggleCell2({
3642
+ column,
3643
+ columnMap,
3644
+ onCommit = WarnCommit3,
3645
+ row
3646
+ }) {
3647
+ const values = getValueList(column);
3648
+ const dataIdx = columnMap[column.name];
3649
+ const value = row[dataIdx];
3650
+ const handleCommit = useCallback21(
3651
+ (evt, value2) => {
3652
+ return onCommit(value2).then((response) => {
3653
+ if (response === true) {
3654
+ dispatchCustomEvent2(evt.target, "vuu-commit");
3655
+ }
3656
+ return response;
3657
+ });
3658
+ },
3659
+ [onCommit]
3660
+ );
3661
+ return /* @__PURE__ */ jsx15(
3662
+ CycleStateButton,
3663
+ {
3664
+ className: cx11(classBase9, `${classBase9}-${column.name}`),
3665
+ onCommit: handleCommit,
3666
+ value,
3667
+ values,
3668
+ variant: "cta",
3669
+ children: value
3670
+ }
3671
+ );
3672
+ },
3673
+ dataAndColumnUnchanged2
3674
+ );
3675
+ registerComponent3("toggle-cell", ToggleCell, "cell-renderer", {});
3676
+
3677
+ // src/useControlledTableNavigation.ts
3678
+ import { useStateRef } from "@vuu-ui/vuu-ui-controls";
3679
+ import { dispatchMouseEvent as dispatchMouseEvent2 } from "@vuu-ui/vuu-utils";
3680
+ import { useCallback as useCallback22, useRef as useRef16 } from "react";
3681
+ var useControlledTableNavigation = (initialValue, rowCount) => {
3682
+ const tableRef = useRef16(null);
3683
+ const [highlightedIndexRef, setHighlightedIndex] = useStateRef(initialValue);
3684
+ const handleKeyDown = useCallback22(
3685
+ (e) => {
3686
+ var _a;
3687
+ if (e.key === "ArrowDown") {
3688
+ setHighlightedIndex((index = -1) => Math.min(rowCount - 1, index + 1));
3689
+ } else if (e.key === "ArrowUp") {
3690
+ setHighlightedIndex((index = -1) => Math.max(0, index - 1));
3691
+ } else if (e.key === "Enter" || e.key === " ") {
3692
+ const { current: rowIdx } = highlightedIndexRef;
3693
+ const rowEl = (_a = tableRef.current) == null ? void 0 : _a.querySelector(
3694
+ `[aria-rowindex="${rowIdx}"]`
3695
+ );
3696
+ if (rowEl) {
3697
+ dispatchMouseEvent2(rowEl, "click");
3698
+ }
3699
+ }
3700
+ },
3701
+ [highlightedIndexRef, rowCount, setHighlightedIndex]
3702
+ );
3703
+ const handleHighlight = useCallback22(
3704
+ (idx) => {
3705
+ setHighlightedIndex(idx);
3706
+ },
3707
+ [setHighlightedIndex]
3708
+ );
3709
+ return {
3710
+ highlightedIndexRef,
3711
+ onHighlight: handleHighlight,
3712
+ onKeyDown: handleKeyDown,
3713
+ tableRef
3714
+ };
3715
+ };
3716
+ export {
3717
+ CheckboxCell,
3718
+ GroupHeaderCellNext,
3719
+ HeaderCell,
3720
+ InputCell,
3721
+ Table,
3722
+ TableCell,
3723
+ TableGroupCell,
3724
+ ToggleCell,
3725
+ isShowColumnSettings,
3726
+ isShowTableSettings,
3727
+ noScrolling,
3728
+ updateTableConfig,
3729
+ useControlledTableNavigation,
3730
+ useTableModel,
3731
+ useTableScroll,
3732
+ useTableViewport
3733
+ };
3
3734
  //# sourceMappingURL=index.js.map