81 lines
22 KiB
JavaScript
81 lines
22 KiB
JavaScript
import{Component as e,NewState as t,RefreshState as i,Util as o}from"@web/state";import{VirtualScroll as n,State as r}from"@web/base";const l={text:["contains","equals","starts","ends"],textarea:["contains","equals","starts","ends"],number:["=",">","<","between"],date:["=",">","<","between"],select:["contains","equals"],TagsInput:["contains","equals","starts","ends"]},s={contains:"bi-search",equals:"bi-distribute-vertical",starts:"bi-align-start",ends:"bi-align-end","=":"bi-calculator",">":"bi-chevron-right","<":"bi-chevron-left",between:"bi-arrows-expand"};e.register("DataTable",e=>{e.state||(e.state=t({}));const o=e.state;Object.assign(o,{list:[],fields:[],_renderedList:[],prevHeight:0,postHeight:0,_listStartIndex:0,selectedRowCount:0,_originalList:[],sortConfig:{fieldId:null,direction:null},filterConfig:{},activeFieldId:null,activeField:null,activeModes:[],_columnStats:{},_internalUpdate:!1,_appliedHash:"",_fieldsDirty:!1,_masterCellNodes:null});const a=(()=>{let e=!!window.__DT_PERF_MODE__;const t={refreshTime:0,refreshCount:0,scrollCount:0,totalNodes:0};return e&&!window.__statePerformanceTelemetry&&(window.__statePerformanceTelemetry={scanCount:0,reuseCount:0,moveCount:0}),{get stats(){return t},enable:()=>{e=!0},disable:()=>{e=!1},onScroll:()=>{e&&t.scrollCount++},startFrame:()=>{var t,i,o;return e?{start:performance.now(),scan:(null==(t=window.__statePerformanceTelemetry)?void 0:t.scanCount)||0,move:(null==(i=window.__statePerformanceTelemetry)?void 0:i.moveCount)||0,reuse:(null==(o=window.__statePerformanceTelemetry)?void 0:o.reuseCount)||0}:null},endFrame:(i,o)=>{if(!e||!i)return;t.refreshCount++,t.totalNodes+=o;const n=performance.now()-i.start;t.refreshTime+=n;const r=window.__statePerformanceTelemetry;if(r){const e=r.scanCount-i.scan,t=r.moveCount-i.move,l=r.reuseCount-i.reuse;(e>0||n>2)&&console.log(`[DataTable Frame] Time: ${n.toFixed(2)}ms, Scans: ${e}, Moves: ${t}, Reuses: ${l}, Rows: ${o}`)}}}})();o.perf=a.stats;const d=((e,t)=>{let i=null,o=null,n=[];const r=(e,t)=>!!(i&&e>=i.minRow&&e<=i.maxRow&&t>=i.minCol&&t<=i.maxCol)||n.some(i=>e>=i.minRow&&e<=i.maxRow&&t>=i.minCol&&t<=i.maxCol);let l=!1;const s=()=>{if(window.__DT_FEATURES__&&!window.__DT_FEATURES__.selection)return;let o=1/0,s=-1/0;i&&(o=Math.min(o,i.minRow),s=Math.max(s,i.maxRow)),n.forEach(e=>{o=Math.min(o,e.minRow),s=Math.max(s,e.maxRow)});const a=o!==1/0;if(!a&&!l)return;l=a;const d=e.querySelector(".dt-body");d&&d.querySelectorAll(".dt-body-row").forEach(e=>{var i;const n=((null==(i=e._ref)?void 0:i.rIdx)??-1)+t._listStartIndex,l=e.querySelectorAll(".dt-cell");!a||n<o||n>s?l.forEach(e=>e.classList.remove("dt-cell-selected")):l.forEach((e,t)=>{r(n,t)?e.classList.add("dt-cell-selected"):e.classList.remove("dt-cell-selected")})})},a=()=>{let e=0;i&&(e+=i.maxRow-i.minRow+1),n.forEach(t=>e+=t.maxRow-t.minRow+1),t.selectedRowCount=e},d=(e=!1)=>{e||(i=null,o=null,n=[],s(),a())},c=()=>{if(!i)return null;let e=i.minRow,t=i.maxRow,o=i.minCol,r=i.maxCol;return n.forEach(i=>{e=Math.min(e,i.minRow),t=Math.max(t,i.maxRow),o=Math.min(o,i.minCol),r=Math.max(r,i.maxCol)}),{minRow:e,maxRow:t,minCol:o,maxCol:r}};return{applySelectionUI:s,clearAllActive:d,startSelect:(l,c,m)=>{const u=r(l,c),p=i&&(i.minRow!==i.maxRow||i.minCol!==i.maxCol)||n.length>0;m.shiftKey&&o?i={minRow:Math.min(o.row,l),maxRow:Math.max(o.row,l),minCol:Math.min(o.col,c),maxCol:Math.max(o.col,c)}:(!u||m.ctrlKey||m.metaKey?(m.ctrlKey||m.metaKey?i&&!u&&n.push(i):d(),o={row:l,col:c},i={minRow:l,maxRow:l,minCol:c,maxCol:c}):p||(e._potentialCancel={row:l,col:c}),t.isSelecting=!0),s(),a(),e.focus()},updateSelect:(n,r)=>{t.isSelecting&&o&&(i={minRow:Math.min(o.row,n),maxRow:Math.max(o.row,n),minCol:Math.min(o.col,r),maxCol:Math.max(o.col,r)},e._potentialCancel=null,s(),a())},endSelect:()=>{if(e._potentialCancel){const{row:t,col:i}=e._potentialCancel;r(t,i)&&d(),e._potentialCancel=null}t.isSelecting=!1},deleteSelected:()=>{const e=c();if(!e)return;const i=e.minRow,o=e.maxRow,n=t.list.filter((e,t)=>!(t>=i&&t<=o));t.list=n,d()},getSelectionBounds:c,copy:async()=>{const e=c();if(!e)return;const i=t.list.slice(e.minRow,e.maxRow+1).map(i=>t.fields.slice(e.minCol,e.maxCol+1).map(e=>{let t=String(i[e.id]??"");return(t.includes("\t")||t.includes("\n")||t.includes('"'))&&(t='"'+t.replace(/"/g,'""')+'"'),t}).join("\t")).join("\n");await navigator.clipboard.writeText(i)},paste:async()=>{try{const i=await navigator.clipboard.readText();if(!i)return;const o=c();if(!o)return;const n=i.split(/\r?\n/).filter(e=>e.length>0).map(e=>{const t=[];let i="",o=!1;for(let n=0;n<e.length;n++){const r=e[n];'"'===r?o&&'"'===e[n+1]?(i+='"',n++):o=!o:"\t"!==r||o?i+=r:(t.push(i),i="")}return t.push(i),t}),r=o.minRow,l=o.minCol,s=o.maxRow,a=o.maxCol,d=e.querySelector(".dt-body"),m=d?Array.from(d.childNodes).filter(e=>{var t;return null==(t=e.classList)?void 0:t.contains("dt-body-row")}):[];n.forEach((i,o)=>{const n=r+o;if(n>s||n>=t.list.length)return;const d=t.list[n];let c=!1;if(i.forEach((e,i)=>{const o=l+i;if(o>a||o>=t.fields.length)return;const n=t.fields[o];d[n.id]=e,c=!0}),c&&e.refreshNode){const i=m.find(e=>{var i;return((null==(i=e._ref)?void 0:i.rIdx)??-1)+t._listStartIndex===n});i&&e.refreshNode(i)}})}catch(e){console.error("Paste Error:",e)}}}})(e,o),c=((e,t,i)=>{const o=n({itemHeight:40});let r=null;const l=(e=!1)=>{if(!r)return;const n=o.calc(r,t.list);if(n){if(!e&&t.prevHeight===n.prevHeight&&t.postHeight===n.postHeight&&t._listStartIndex===n.listStartIndex&&t._renderedList.length===n.renderedList.length)return;Object.assign(t,{prevHeight:n.prevHeight,postHeight:n.postHeight,_listStartIndex:n.listStartIndex,_renderedList:n.renderedList}),null==i||i(n.renderedList.length,e)}};return{init:()=>{r=e.querySelector(".dt-main")},reset:i=>{t._listStartIndex=0,o.reset(i,r||e),t.list===i&&o.init(i,()=>l(!0))},refresh:l,onScroll:()=>l(!1)}})(e,o,()=>d.applySelectionUI()),m=e.querySelector(".dt-column-menu");m&&(m._thisObj=e),e.onColumnResizing=(t,i)=>e.style.setProperty(`--w-${t.id}`,i.detail.newSize+"px"),e.onColumnResize=(e,t)=>{const i=o.fields.findIndex(t=>t.id===e.id);-1!==i&&(o.fields[i].width=t.detail.newSize,o.fields=[...o.fields])};let u,p=null;e.format=(e,t)=>t.formatter?t.formatter(e,t):null==e?"":"object"==typeof e?JSON.stringify(e):String(e),e.onScroll=()=>{a.onScroll(),c.refresh(),e.hideColumnMenu();const t=e.querySelector(".dt-spacer-prev"),i=e.querySelector(".dt-spacer-post");t&&(t.style.height=(o.prevHeight||0)+"px",t.style.display=o.prevHeight>0?"block":"none"),i&&(i.style.height=(o.postHeight||0)+"px",i.style.display=o.postHeight>0?"block":"none")},e.applySortFilter=(e={})=>{if(o._internalUpdate)return;const t={...o.filterConfig,...e.filters||{}},i=void 0!==e.sort?e.sort?{fieldId:o.activeFieldId,direction:e.sort}:{fieldId:null,direction:null}:o.sortConfig,n=JSON.stringify({s:i,f:t});if(o._appliedHash===n&&!e.force)return;o._internalUpdate=!0;let r=[...o._originalList||[]];Object.keys(t).forEach(e=>{const i=t[e];if(!i)return;const{mode:o="contains",value:n,value2:l,selectedValues:s}=i;if((null==s?void 0:s.length)>0)return void(r=r.filter(t=>s.includes(String(t[e]??""))));if(""===n||null==n)return;const a=String(n).toLowerCase(),d=Number(n),c=Number(l);r=r.filter(t=>{const i=t[e],n=String(i??"").toLowerCase();switch(o){case"contains":default:return n.includes(a);case"equals":return n===a;case"starts":return n.startsWith(a);case"ends":return n.endsWith(a);case">":return Number(i)>d;case"<":return Number(i)<d;case"=":return Number(i)===d;case"between":return Number(i)>=d&&Number(i)<=c}})}),i.fieldId&&i.direction&&r.sort((e,t)=>{let o=e[i.fieldId],n=t[i.fieldId];if(o===n)return 0;const r=o>n?1:-1;return"asc"===i.direction?r:-r}),o._appliedHash=n,o.sortConfig=i,o.list=r,o._internalUpdate=!1},e.showColumnMenu=(t,i)=>{i.stopPropagation();const n=i.currentTarget,r=e.querySelector(".dt-column-menu"),s=t.type||"text";o.activeModes=l[s]||(["boolean","switch","checkbox","radio"].includes(s)?[]:l.text),o.filterConfig[t.id]||(o.filterConfig[t.id]={mode:o.activeModes[0]||"contains",value:"",selectedValues:[]}),o.activeField=t,o.activeFieldId=t.id,r.style.display="block";const a=n.closest(".dt-cell").getBoundingClientRect(),d=e.getBoundingClientRect(),c=r.offsetWidth||260;let m=a.right-d.left-c;m<0&&(m=Math.max(0,a.left-d.left)),r.style.left=m+"px",r.style.top=a.bottom-d.top+5+"px";const u=t=>{r.contains(t.target)||n.contains(t.target)||(e.hideColumnMenu(),e.applySortFilter(),document.removeEventListener("mousedown",u))};document.addEventListener("mousedown",u),setTimeout(()=>{var e;return null==(e=r.querySelector("input"))?void 0:e.focus()},50)},e.toggleSelectedValue=t=>{const i=o.filterConfig[o.activeFieldId];if(!i)return;const n=i.selectedValues.indexOf(t);-1===n?i.selectedValues.push(t):i.selectedValues.splice(n,1),o.filterConfig={...o.filterConfig},e.applySortFilter()},e.filterOnlyThis=t=>{o.filterConfig[o.activeFieldId]={mode:"contains",value:"",selectedValues:[String(t)]},o.filterConfig={...o.filterConfig},e.applySortFilter()},e.hideColumnMenu=()=>{const t=e.querySelector(".dt-column-menu");t&&(t.style.display="none")},e.setSort=t=>{const i=o.sortConfig.direction===t&&o.sortConfig.fieldId===o.activeFieldId?null:t;e.applySortFilter({sort:i})},e.clearColumnSettings=()=>{o.activeFieldId&&(delete o.filterConfig[o.activeFieldId],o.filterConfig={...o.filterConfig},e.applySortFilter())},e._initRow=t=>{var i;const n=null==(i=t._ref)?void 0:i.item;n&&void 0===n._editingF&&Object.defineProperty(n,"_editingF",{set:t=>{null===t&&e.hideEditor(!0)},configurable:!0}),Array.from(t.children).forEach(e=>{const t=parseInt(e.dataset.fidx);isNaN(t)||(e._refExt={f:o.fields[t],fIdx:t})})},o.__watch("fields",t=>{if(!t)return;o._fieldsDirty=!0,e.style.setProperty("--dt-grid-template",t.map(e=>`var(--w-${e.id}, ${e.width||150}px)`).join(" ")),e.style.setProperty("--dt-row-width",t.reduce((e,t)=>e+(t.width||150),0)+"px");let i=0;t.forEach(t=>{"left"===t.pinned&&(e.style.setProperty(`--l-${t.id}`,i+"px"),i+=t.width||150)});let n=0;[...t].reverse().forEach(t=>{"right"===t.pinned&&(e.style.setProperty(`--r-${t.id}`,n+"px"),n+=t.width||150)})}),o.__watch("list",t=>{var i;if(o._fieldsDirty){o._fieldsDirty=!1;const t=null==(i=e.querySelector('.dt-body template[index="rIdx"]'))?void 0:i.content.querySelector('template[as="f"]');if(t){const e=o._masterCellNodes||(o._masterCellNodes=Array.from(t.content.childNodes).map(e=>e.cloneNode(!0)));t.removeAttribute("$each"),t.setAttribute("$if","true"),t.content.textContent="",o.fields.forEach((i,o)=>e.forEach(e=>{const i=e.cloneNode(!0);1===i.nodeType&&(i.dataset.fidx=o),t.content.appendChild(i)}))}}o._internalUpdate||(o._originalList=[...t||[]],setTimeout(()=>{const e={};o.fields.forEach(t=>{const i={};o._originalList.forEach(e=>{const o=e[t.id],n=null==o||""===o?"":String(o);i[n]=(i[n]||0)+1}),e[t.id]=Object.entries(i).sort((e,t)=>t[1]-e[1]).slice(0,20).map(([e,t])=>({val:e,count:t}))}),o._columnStats=e},200)),c.init(),c.reset(t)}),e.editCell=(t,i,o)=>{const n=e.querySelector(".dt-editor-overlay"),l=o.getBoundingClientRect(),s=e.getBoundingClientRect();p=o,Object.assign(n.style,{display:"flex",left:l.left-s.left+"px",top:l.top-s.top+"px",width:("textarea"===i.type||"TagsInput"===i.type?Math.max(l.width,300):l.width)+"px",height:"textarea"===i.type||"TagsInput"===i.type?"auto":l.height+"px"}),r.editingSchema=[{...i,name:i.id,label:""}],r.editingData=t,setTimeout(()=>{var e;return null==(e=n.querySelector("input, textarea, select, .form-control"))?void 0:e.focus()},30)},e.hideEditor=(t=!0)=>{if(u||(u=e.querySelector(".dt-editor-overlay")),u&&"none"!==u.style.display){if(t){const e=u.querySelector("input:focus, select:focus, textarea:focus");e&&e.dispatchEvent(new Event("number"===e.type||"SELECT"===e.tagName?"change":"input",{bubbles:!0})),p&&i(p)}u.style.display="none",r.editingSchema=r.editingData=p=null,e.focus()}},e.onMainMouseDown=t=>{var i;const n=t.target.closest(".dt-cell"),r=null==n?void 0:n.closest(".dt-row");if(!r||r.classList.contains("dt-header-row"))return;const l=n.dataset.fidx?parseInt(n.dataset.fidx):Array.from(r.querySelectorAll(".dt-cell")).indexOf(n),s=(null==(i=r._ref)?void 0:i.rIdx)??Array.from(e.querySelectorAll(".dt-body-row")).indexOf(r);d.startSelect(s+o._listStartIndex,l,t)},e.onMainMouseOver=t=>{var i;if(o.isSelecting){const n=t.target.closest(".dt-cell"),r=null==n?void 0:n.closest(".dt-row");if(r&&!r.classList.contains("dt-header-row")){const t=n.dataset.fidx?parseInt(n.dataset.fidx):Array.from(r.querySelectorAll(".dt-cell")).indexOf(n),l=(null==(i=r._ref)?void 0:i.rIdx)??Array.from(e.querySelectorAll(".dt-body-row")).indexOf(r);d.updateSelect(l+o._listStartIndex,t)}}},e.onMainDblClick=t=>{var i;const n=t.target.closest(".dt-cell"),r=null==n?void 0:n.closest(".dt-row");if(r&&!r.classList.contains("dt-header-row")){const t=null==(i=r._ref)?void 0:i.item,l=n.dataset.fidx?parseInt(n.dataset.fidx):Array.from(r.querySelectorAll(".dt-cell")).indexOf(n);t&&o.fields[l]&&e.editCell(t,o.fields[l],n)}},window.addEventListener("mouseup",d.endSelect),document.addEventListener("mousedown",t=>{const i=e.querySelector(".dt-editor-overlay");"none"===(null==i?void 0:i.style.display)||i.contains(t.target)||e.hideEditor(!0),e.contains(t.target)||(null==i?void 0:i.contains(t.target))||d.clearAllActive()}),o._MODE_ICONS=s},o.makeDom(`
|
|
<!--
|
|
NOTE: For $class and $style directives, ALWAYS use the template literal syntax:
|
|
$class="base-class \${condition ? 'active' : ''}"
|
|
DO NOT use string concatenation like $class="'base-class ' + (condition ? 'active' : '')".
|
|
Since the HTML is wrapped in backticks (``), remember to escape the dollar sign: \${ }
|
|
-->
|
|
<div class="dt-root d-flex flex-column h-100 border bg-body text-body overflow-hidden" style="position:relative; user-select:none; outline: none; min-height: 0" tabindex="0">
|
|
<div class="dt-main flex-grow-1 overflow-auto" $onscroll="this.onScroll()"
|
|
$onmousedown="this.onMainMouseDown(event)" $onmouseover="this.onMainMouseOver(event)" $ondblclick="this.onMainDblClick(event)"
|
|
style="overflow-anchor:none; min-height: 0">
|
|
<div class="dt-header border-bottom bg-light sticky-top" style="z-index:20">
|
|
<div class="dt-header-row fw-bold text-muted small">
|
|
<template $each="this.state?.fields || []">
|
|
<div $data-id="item.id" $class="dt-cell dt-col border-end d-flex align-items-center header-cell \${item.pinned ? 'pinned-' + item.pinned : ''}" $style="(item.pinned ? 'position: sticky; z-index: 11; background-color: inherit; ' : 'position:relative; ') + 'padding: 0; ' + (item.pinned === 'left' ? 'left: var(--l-' + item.id + '); border-right: 1px solid var(--bs-border-color); box-shadow: 2px 0 5px -2px rgba(0,0,0,0.1);' : (item.pinned === 'right' ? 'right: var(--r-' + item.id + '); border-left: 1px solid var(--bs-border-color); box-shadow: -2px 0 5px -2px rgba(0,0,0,0.1);' : ''))">
|
|
<div class="d-flex align-items-center overflow-hidden flex-grow-1 h-100 px-2 cursor-pointer" $onclick="this.showColumnMenu(item, event)">
|
|
<i $if="this.state?.filterConfig?.[item.id] && (this.state.filterConfig[item.id].value || this.state.filterConfig[item.id].selectedValues?.length)" class="bi bi-filter me-1 text-primary"></i>
|
|
<i $if="this.state?.sortConfig?.fieldId === item.id && this.state.sortConfig.direction" $class="bi bi-sort-\${this.state.sortConfig.direction === 'asc' ? 'down' : 'up-alt'} me-1 text-primary"></i>
|
|
<span $text="item.name" class="text-truncate flex-grow-1"></span>
|
|
</div>
|
|
<button class="btn btn-xs btn-link text-muted p-0 border-0 me-1 header-menu-btn" $onclick="this.showColumnMenu(item, event)"><i class="bi bi-chevron-down"></i></button>
|
|
<Resizer $.target="thisNode.parentElement" style="position:absolute; right:0; top:0; bottom:0; width:4px; z-index:10" min="50" max="1000" $onresizing="this.onColumnResizing(item, event)" $onresize="this.onColumnResize(item, event)"></Resizer>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<div class="dt-body" style="position:relative">
|
|
<div class="dt-spacer-prev flex-shrink-0" style="display:none"></div>
|
|
<template $each="this.state?._renderedList || []" key="id" index="rIdx">
|
|
<div class="dt-row dt-body-row border-bottom bg-white" $.="this._initRow(thisNode)">
|
|
<template as="f"><div $class="dt-cell border-end px-2 d-flex align-items-center \${f.pinned ? 'pinned-' + f.pinned : ''}" $style="(f.pinned ? 'position: sticky; z-index: 1; background-color: inherit; ' : '') + (f.pinned === 'left' ? 'left: var(--l-' + f.id + '); border-right: 1px solid var(--bs-border-color); box-shadow: 2px 0 5px -2px rgba(0,0,0,0.1);' : (f.pinned === 'right' ? 'right: var(--r-' + f.id + '); border-left: 1px solid var(--bs-border-color); box-shadow: -2px 0 5px -2px rgba(0,0,0,0.1);' : ''))"><span $text="this.format(item[f.id], f)" class="text-truncate"></span></div></template>
|
|
</div>
|
|
</template>
|
|
<div class="dt-spacer-post flex-shrink-0" style="display:none"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="dt-column-menu border bg-body shadow-lg rounded p-3" style="display:none; position:absolute; z-index:2000; min-width:260px; max-width:320px;">
|
|
<template $if="this.state?.activeFieldId">
|
|
<div class="btn-group w-100 mb-3">
|
|
<button $class="btn btn-sm d-flex align-items-center justify-content-center \${this.state?.sortConfig?.direction === 'asc' && this.state?.sortConfig?.fieldId === this.state?.activeFieldId ? 'btn-primary' : 'btn-outline-secondary border'}" $onclick="this.setSort('asc')"><i class="bi bi-sort-alpha-down me-1"></i> ASC</button>
|
|
<button $class="btn btn-sm d-flex align-items-center justify-content-center \${this.state?.sortConfig?.direction === 'desc' && this.state?.sortConfig?.fieldId === this.state?.activeFieldId ? 'btn-primary' : 'btn-outline-secondary border'}" $onclick="this.setSort('desc')"><i class="bi bi-sort-alpha-up-alt me-1"></i> DESC</button>
|
|
</div>
|
|
|
|
<div $if="this.state?.activeModes?.length" class="dt-filter-tabs d-flex overflow-auto border-bottom bg-light-subtle rounded-top py-1" style="white-space:nowrap; scrollbar-width: none;">
|
|
<template $each="this.state?.activeModes || []" as="m">
|
|
<div $class="px-2 py-1 cursor-pointer fs-5 \${this.state?.filterConfig?.[this.state?.activeFieldId]?.mode === m ? 'text-primary border-bottom border-primary border-2' : 'text-muted'}" $title="m.toUpperCase()" $onclick="this.state.filterConfig[this.state.activeFieldId].mode = m; this.state.filterConfig = {...this.state.filterConfig}">
|
|
<i $class="bi \${this.state?._MODE_ICONS?.[m] || 'bi-filter'}"></i>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
<template $if="this.state?.activeModes?.length">
|
|
<div class="py-2 border-bottom" style="min-height: 48px">
|
|
<input type="text" class="form-control form-control-sm mb-1" $placeholder="(this.state?.filterConfig?.[this.state?.activeFieldId]?.mode || 'Search').toUpperCase() + '...'" $bind="this.state?.filterConfig?.[this.state?.activeFieldId].value" $onkeydown="if(event.key==='Enter'){this.applySortFilter();this.hideColumnMenu();}">
|
|
<input $if="this.state?.filterConfig?.[this.state?.activeFieldId]?.mode === 'between'" type="text" class="form-control form-control-sm" placeholder="And..." $bind="this.state?.filterConfig?.[this.state?.activeFieldId].value2" $onkeydown="if(event.key==='Enter'){this.applySortFilter();this.hideColumnMenu();}">
|
|
</div>
|
|
</template>
|
|
|
|
<div class="mt-3" style="max-height: 200px; overflow-y: auto;">
|
|
<div class="text-muted fw-bold mb-2" style="font-size: 10px; letter-spacing: 0.5px">TOP FREQUENT VALUES</div>
|
|
<template $each="this.state?._columnStats?.[this.state?.activeFieldId] || []">
|
|
<label class="d-flex align-items-center mb-1 small cursor-pointer p-1 rounded-1 menu-item-row" onmouseover="this.style.background='var(--bs-light)'" onmouseout="this.style.background='transparent'">
|
|
<input type="checkbox" class="form-check-input me-2" $checked="this.state?.filterConfig?.[this.state?.activeFieldId]?.selectedValues?.includes(String(item.val))" $onclick="this.toggleSelectedValue(String(item.val))">
|
|
<span class="text-truncate flex-grow-1"><span $text="item.val || '(Empty)'"></span> <span class="text-muted ms-1" style="font-size: 0.7rem" $text="'(' + item.count + ')'"></span></span>
|
|
<button class="btn btn-xs btn-link p-0 text-primary only-btn" style="font-size: 10px; text-decoration: none" $onclick="this.filterOnlyThis(item.val); event.preventDefault(); event.stopPropagation();">Only</button>
|
|
</label>
|
|
</template>
|
|
</div>
|
|
|
|
<div $if="this.state?.filterConfig?.[this.state?.activeFieldId]?.value || this.state?.filterConfig?.[this.state?.activeFieldId]?.selectedValues?.length" class="mt-3 pt-2 border-top text-center">
|
|
<span class="cursor-pointer text-primary small fw-bold" $onclick="this.clearColumnSettings()"><i class="bi bi-x-circle me-1"></i> Clear Filter</span>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
<div class="dt-editor-overlay dt-editor-container" style="display: none; position: absolute; z-index: 1000; background: var(--bs-body-bg); box-shadow: 0 4px 16px rgba(0,0,0,0.25); border: 1px solid var(--bs-primary);"><AutoForm inline class="h-100 w-100" $onsubmit="this.hideEditor(true)"/></div>
|
|
<div class="dt-footer border-top bg-light d-flex align-items-center px-2 py-1 small text-muted" style="height:32px"><span $text="(this.state?.selectedRowCount || 0) + ' / ' + (this.state?.list?.length || 0)"></span></div>
|
|
</div>
|
|
`),o.makeDom("\n<style>\n\tDataTable { display: block; }\n\t.dt-root { font-size: 0.875rem; }\n\t.dt-row, .dt-header-row { display: grid; grid-template-columns: var(--dt-grid-template); width: var(--dt-row-width, max-content); min-width: 100%; height: 40px; contain: paint layout; }\n\t.dt-header-row { background-color: var(--bs-tertiary-bg); border-bottom: 1px solid var(--bs-border-color); }\n\t.dt-cell { background: inherit; white-space: nowrap; flex-shrink: 0; contain: content; }\n\t.dt-cell-selected { background-color: rgba(var(--bs-primary-rgb), 0.15) !important; outline: 1px solid var(--bs-primary); outline-offset: -1px; }\n\t.dt-body-row:hover { background-color: var(--bs-secondary-bg) !important; }\n\t.header-cell .header-menu-btn { opacity: 0; transition: opacity 0.2s; }\n\t.header-cell:hover .header-menu-btn { opacity: 1; }\n\t.dt-column-menu { background-color: var(--bs-body-bg); border: 1px solid var(--bs-primary); box-shadow: 0 10px 40px rgba(0,0,0,0.2) !important; z-index: 2100 !important; }\n\t.btn-xs { padding: 1px 5px; line-height: 1.5; }\n\t.cursor-pointer { cursor: pointer; }\n\t.dt-filter-tabs i { font-size: 1.1rem; }\n\t.dt-filter-tabs div:hover i { color: var(--bs-primary); }\n\t.menu-item-row .only-btn { opacity: 0; }\n\t.menu-item-row:hover .only-btn { opacity: 1; }\n</style>\n"));
|