web-mojo 2.6.4 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/admin-models.cjs.js +1 -1
- package/dist/admin-models.es.js +1 -1
- package/dist/admin.cjs.js +1 -1
- package/dist/admin.es.js +1 -1
- package/dist/auth.cjs.js +1 -1
- package/dist/auth.es.js +1 -1
- package/dist/charts.cjs.js +1 -1
- package/dist/charts.es.js +1 -1
- package/dist/chunks/ChatView-B76p_4u8.js +2 -0
- package/dist/chunks/ChatView-B76p_4u8.js.map +1 -0
- package/dist/chunks/ChatView-CC4SaAGA.js +2 -0
- package/dist/chunks/ChatView-CC4SaAGA.js.map +1 -0
- package/dist/chunks/{ContextMenu-3_bOvSwa.js → ContextMenu-B6u-y5X8.js} +2 -2
- package/dist/chunks/ContextMenu-B6u-y5X8.js.map +1 -0
- package/dist/chunks/{ContextMenu-xjj8Quls.js → ContextMenu-DkIc9twn.js} +2 -2
- package/dist/chunks/ContextMenu-DkIc9twn.js.map +1 -0
- package/dist/chunks/{DataView-CdyrhKrD.js → DataView-CnbbvE5S.js} +2 -2
- package/dist/chunks/{DataView-CdyrhKrD.js.map → DataView-CnbbvE5S.js.map} +1 -1
- package/dist/chunks/{DataView-B7XoPBZd.js → DataView-CvXW1Ewe.js} +2 -2
- package/dist/chunks/{DataView-B7XoPBZd.js.map → DataView-CvXW1Ewe.js.map} +1 -1
- package/dist/chunks/FormView-BMjKplJy.js +2 -0
- package/dist/chunks/FormView-BMjKplJy.js.map +1 -0
- package/dist/chunks/FormView-geCsNsn1.js +2 -0
- package/dist/chunks/FormView-geCsNsn1.js.map +1 -0
- package/dist/chunks/ListView-B6cE3WKB.js +2 -0
- package/dist/chunks/ListView-B6cE3WKB.js.map +1 -0
- package/dist/chunks/ListView-DXfD53sU.js +2 -0
- package/dist/chunks/ListView-DXfD53sU.js.map +1 -0
- package/dist/chunks/{MetricsCountryMapView-9e2t5sfH.js → MetricsCountryMapView-BuFNN1Ey.js} +2 -2
- package/dist/chunks/{MetricsCountryMapView-9e2t5sfH.js.map → MetricsCountryMapView-BuFNN1Ey.js.map} +1 -1
- package/dist/chunks/{MetricsCountryMapView-ki6auFBe.js → MetricsCountryMapView-Dse3HsUv.js} +2 -2
- package/dist/chunks/{MetricsCountryMapView-ki6auFBe.js.map → MetricsCountryMapView-Dse3HsUv.js.map} +1 -1
- package/dist/chunks/{Modal-Bbn-54-6.js → Modal-BmXvplWi.js} +3 -3
- package/dist/chunks/Modal-BmXvplWi.js.map +1 -0
- package/dist/chunks/{Modal-BRmaTaWa.js → Modal-DRrfsnNP.js} +3 -3
- package/dist/chunks/Modal-DRrfsnNP.js.map +1 -0
- package/dist/chunks/Passkeys-D2LFSJpQ.js +2 -0
- package/dist/chunks/Passkeys-D2LFSJpQ.js.map +1 -0
- package/dist/chunks/Passkeys-vneS9ywK.js +2 -0
- package/dist/chunks/Passkeys-vneS9ywK.js.map +1 -0
- package/dist/chunks/{TokenManager-qlmZ7eW3.js → TokenManager-DBwv-cF4.js} +2 -2
- package/dist/chunks/{TokenManager-qlmZ7eW3.js.map → TokenManager-DBwv-cF4.js.map} +1 -1
- package/dist/chunks/{TokenManager-BkW1MQ1m.js → TokenManager-DXtiygmr.js} +2 -2
- package/dist/chunks/{TokenManager-BkW1MQ1m.js.map → TokenManager-DXtiygmr.js.map} +1 -1
- package/dist/chunks/User-DJHaSCL9.js +2 -0
- package/dist/chunks/User-DJHaSCL9.js.map +1 -0
- package/dist/chunks/User-ao-iRfPc.js +2 -0
- package/dist/chunks/User-ao-iRfPc.js.map +1 -0
- package/dist/chunks/{UserProfileView-Dbei45vn.js → UserProfileView-DRpHVJtE.js} +2 -2
- package/dist/chunks/{UserProfileView-Dbei45vn.js.map → UserProfileView-DRpHVJtE.js.map} +1 -1
- package/dist/chunks/{UserProfileView-OcqSynHt.js → UserProfileView-DtIBSw3O.js} +2 -2
- package/dist/chunks/{UserProfileView-OcqSynHt.js.map → UserProfileView-DtIBSw3O.js.map} +1 -1
- package/dist/chunks/{WebApp-CIhrSvuV.js → WebApp-7COAyECf.js} +2 -2
- package/dist/chunks/{WebApp-CIhrSvuV.js.map → WebApp-7COAyECf.js.map} +1 -1
- package/dist/chunks/{WebApp-DAviV-_c.js → WebApp-CSvy-GUm.js} +2 -2
- package/dist/chunks/{WebApp-DAviV-_c.js.map → WebApp-CSvy-GUm.js.map} +1 -1
- package/dist/chunks/{admin-models-BBmATRhV.js → admin-models-DHXtrq87.js} +2 -2
- package/dist/chunks/{admin-models-BBmATRhV.js.map → admin-models-DHXtrq87.js.map} +1 -1
- package/dist/chunks/{admin-models-C-SHgZGn.js → admin-models-vhiH86Tq.js} +2 -2
- package/dist/chunks/{admin-models-C-SHgZGn.js.map → admin-models-vhiH86Tq.js.map} +1 -1
- package/dist/chunks/{exportChart-2I2hxr7t.js → exportChart-B1pjkCdm.js} +2 -2
- package/dist/chunks/{exportChart-2I2hxr7t.js.map → exportChart-B1pjkCdm.js.map} +1 -1
- package/dist/chunks/{exportChart-B5optjiT.js → exportChart-Vq4_f06o.js} +2 -2
- package/dist/chunks/{exportChart-B5optjiT.js.map → exportChart-Vq4_f06o.js.map} +1 -1
- package/dist/chunks/{index-B543iMCu.js → index-Bj5AxsEG.js} +2 -2
- package/dist/chunks/{index-B543iMCu.js.map → index-Bj5AxsEG.js.map} +1 -1
- package/dist/chunks/{index-C6reyIyu.js → index-DrmdnYWO.js} +2 -2
- package/dist/chunks/{index-C6reyIyu.js.map → index-DrmdnYWO.js.map} +1 -1
- package/dist/chunks/{version-D_d_sDRM.js → version-CSb8B3nS.js} +2 -2
- package/dist/chunks/{version-D_d_sDRM.js.map → version-CSb8B3nS.js.map} +1 -1
- package/dist/chunks/{version-DWWDfVB9.js → version-_kAV0pF7.js} +2 -2
- package/dist/chunks/{version-DWWDfVB9.js.map → version-_kAV0pF7.js.map} +1 -1
- package/dist/docit.cjs.js +1 -1
- package/dist/docit.es.js +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -1
- package/dist/lightbox.cjs.js +1 -1
- package/dist/lightbox.es.js +1 -1
- package/dist/map.cjs.js +1 -1
- package/dist/map.es.js +1 -1
- package/dist/timeline.cjs.js +1 -1
- package/dist/timeline.es.js +1 -1
- package/dist/user-profile.cjs.js +1 -1
- package/dist/user-profile.es.js +1 -1
- package/dist/web-mojo.lite.iife.js +1406 -43
- package/dist/web-mojo.lite.iife.js.map +1 -1
- package/dist/web-mojo.lite.iife.min.js +336 -95
- package/dist/web-mojo.lite.iife.min.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/ChatView-C1Vc-P_O.js +0 -2
- package/dist/chunks/ChatView-C1Vc-P_O.js.map +0 -1
- package/dist/chunks/ChatView-Cv6kH3MO.js +0 -2
- package/dist/chunks/ChatView-Cv6kH3MO.js.map +0 -1
- package/dist/chunks/ContextMenu-3_bOvSwa.js.map +0 -1
- package/dist/chunks/ContextMenu-xjj8Quls.js.map +0 -1
- package/dist/chunks/FormView-BE4qZvNA.js +0 -2
- package/dist/chunks/FormView-BE4qZvNA.js.map +0 -1
- package/dist/chunks/FormView-BqR4x5nz.js +0 -2
- package/dist/chunks/FormView-BqR4x5nz.js.map +0 -1
- package/dist/chunks/ListView-BF442PdR.js +0 -2
- package/dist/chunks/ListView-BF442PdR.js.map +0 -1
- package/dist/chunks/ListView-DqfZmgXS.js +0 -2
- package/dist/chunks/ListView-DqfZmgXS.js.map +0 -1
- package/dist/chunks/Modal-BRmaTaWa.js.map +0 -1
- package/dist/chunks/Modal-Bbn-54-6.js.map +0 -1
- package/dist/chunks/Passkeys-B_bxdIVa.js +0 -2
- package/dist/chunks/Passkeys-B_bxdIVa.js.map +0 -1
- package/dist/chunks/Passkeys-LRaiCx3H.js +0 -2
- package/dist/chunks/Passkeys-LRaiCx3H.js.map +0 -1
- package/dist/chunks/User-B7jwnBx2.js +0 -2
- package/dist/chunks/User-B7jwnBx2.js.map +0 -1
- package/dist/chunks/User-Dbw_wZAz.js +0 -2
- package/dist/chunks/User-Dbw_wZAz.js.map +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{V as t,C as e,a as i}from"./User-DJHaSCL9.js";import{a as s}from"./Modal-BmXvplWi.js";import{F as n}from"./FormView-geCsNsn1.js";class SegmentControl extends t{constructor(t={}){const{options:e=[],value:i,size:s="sm",ariaLabel:n="Segment control",...o}=t;super({tagName:"div",className:"segment-control",...o}),this.items=e,this.value=void 0!==i?i:e[0]&&e[0].value,this.size="md"===s?"":"sm",this.ariaLabel=n,this.template=()=>this._buildTemplate()}_buildTemplate(){const t=this.size?`btn-group-${this.size}`:"",e=this.items.map(t=>{const e=t.value===this.value,i=e?"btn btn-primary":"btn btn-outline-secondary",s=t.icon?`<i class="bi ${this.escapeHtml(t.icon)} me-1"></i>`:"";return`<button type="button"\n class="${i}"\n data-action="select"\n data-value="${this.escapeHtml(String(t.value))}"\n ${e?'aria-pressed="true"':'aria-pressed="false"'}>${s}${this.escapeHtml(t.label)}</button>`}).join("");return`<div class="btn-group ${t}" role="group" aria-label="${this.escapeHtml(this.ariaLabel)}">${e}</div>`}async onActionSelect(t,e){const i=e.dataset.value;if(i===this.value)return;const s=this.value;this.value=i,this._paintActive(),this.emit("change",{value:i,previous:s})}_paintActive(){this.element&&this.element.querySelectorAll("button[data-value]").forEach(t=>{const e=t.dataset.value===String(this.value);t.classList.toggle("btn-primary",e),t.classList.toggle("btn-outline-secondary",!e),t.setAttribute("aria-pressed",e?"true":"false")})}setValue(t,{silent:e=!1}={}){const i=this.items.find(e=>String(e.value)===String(t));if(!i)return!1;const s=this.value;return i.value===s||(this.value=i.value,this._paintActive(),e||this.emit("change",{value:this.value,previous:s})),!0}getValue(){return this.value}}const o={exact:{display:"is",description:"Exact match"},in:{display:"in",description:"Match any of the values (comma-separated)"},not:{display:"is not",description:"Does not match"},not_in:{display:"not in",description:"Does not match any of the values"},gt:{display:">",description:"Greater than"},gte:{display:">=",description:"Greater than or equal to"},lt:{display:"<",description:"Less than"},lte:{display:"<=",description:"Less than or equal to"},contains:{display:"contains",description:"Contains substring (case-sensitive)"},icontains:{display:"contains",description:"Contains substring (case-insensitive)"},startswith:{display:"starts with",description:"Starts with substring (case-sensitive)"},istartswith:{display:"starts with",description:"Starts with substring (case-insensitive)"},endswith:{display:"ends with",description:"Ends with substring (case-sensitive)"},iendswith:{display:"ends with",description:"Ends with substring (case-insensitive)"},isnull:{display:t=>"true"===t||!0===t?"is null":"is not null",description:"Check if value is null or not"},range:{display:"between",description:"Between two values (comma-separated)"}};function a(t){if(!t||"string"!=typeof t)return{field:t,lookup:null};const e=t.split("__");if(1===e.length)return{field:t,lookup:null};const i=e[e.length-1];return o[i]?{field:e.slice(0,-1).join("__"),lookup:i}:{field:t,lookup:null}}function l(t,e,i){if(!t||null==e)return"";const{field:s,lookup:n}=a(t),l=o[n];if(e&&"object"==typeof e&&!Array.isArray(e)){const t=void 0!==e.start&&null!==e.start&&""!==e.start,s=void 0!==e.end&&null!==e.end&&""!==e.end;return t||s?t&&s?`${i} between '${e.start}' and '${e.end}'`:t?`${i} from '${e.start}'`:`${i} until '${e.end}'`:`${i} is '${JSON.stringify(e)}'`}const r=Array.isArray(e)?e.join(","):String(e);if(!n||"exact"===n)return`${i} is '${r}'`;if("in"===n||"not_in"===n){const t=r.split(",").map(t=>t.trim()).filter(t=>t);if(0===t.length)return`${i} ${l.display}`;const e=t.map(t=>`'${t}'`).join(", ");return`${i} ${l.display} ${e}`}if("range"===n){const t=r.split(",").map(t=>t.trim()).filter(t=>t);return 2===t.length?`${i} between '${t[0]}' and '${t[1]}'`:`${i} ${l.display} '${r}'`}return"isnull"===n?`${i} ${"function"==typeof l.display?l.display(r):l.display}`:l?`${i} ${l.display} '${r}'`:`${i} is '${r}'`}const r={LOOKUPS:o,parseFilterKey:a,formatFilterDisplay:l,getLookupDescription:function(t){const e=o[t];return e?e.description:"Exact match"},isValidLookup:function(t){return t&&o.hasOwnProperty(t)},getAvailableLookups:function(){return Object.keys(o)},buildFilterKey:function(t,e=null){return t?e?`${t}__${e}`:t:""}};class ListViewItem extends t{constructor(t={}){super({className:"list-view-item",...t}),this.selected=!1,this.index=t.index??0,this.listView=t.listView??null,this.clickable=!0===t.clickable,this.clickable&&this.element&&this.addClass("clickable"),this.template||(this.template='\n <div class="list-item-content" data-action="select">\n {{#model}}\n {{#id}}<span class="item-id">{{id}}</span>{{/id}}\n {{#name}}<span class="item-name">{{name}}</span>{{/name}}\n {{#title}}<span class="item-title">{{title}}</span>{{/title}}\n {{#label}}<span class="item-label">{{label}}</span>{{/label}}\n {{#description}}<p class="item-description">{{description}}</p>{{/description}}\n {{/model}}\n {{^model}}\n <span class="item-empty">No data</span>\n {{/model}}\n </div>\n ')}async onActionSelect(t,e){t.stopPropagation(),this.selected?this.deselect():this.select()}async onActionView(t,e){t.stopPropagation(),this._emitRowEvent("row:view",t)}async onActionEdit(t,e){t.stopPropagation(),this._emitRowEvent("row:edit",t)}async onActionDelete(t,e){t.stopPropagation(),this._emitRowEvent("row:delete",t)}_emitRowEvent(t,e){const i={item:this,model:this.model,index:this.index,event:e,data:this.model?.toJSON?this.model.toJSON():this.model};this.emit(t,i),this.listView&&this.listView.emit(t,i)}select(){this.selected||(this.selected=!0,this.addClass("selected"),this.emit("item:select",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:select",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}))}deselect(){this.selected&&(this.selected=!1,this.removeClass("selected"),this.emit("item:deselect",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:deselect",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}))}async onAfterRender(){await super.onAfterRender(),this.clickable&&this.element&&(this.addClass("clickable"),this._wireClickableHandler()),this.listView?.rowStripe&&"function"==typeof this.listView._applyRowStripe&&this.listView._applyRowStripe(this)}_wireClickableHandler(){!this._clickableHandler&&this.element&&(this._clickableHandler=t=>{if(t.target?.closest?.("[data-action]"))return;const e=t.target?.tagName;"INPUT"!==e&&"TEXTAREA"!==e&&"SELECT"!==e&&(this.emit("item:click",{item:this,model:this.model,index:this.index,action:"row-click",event:t,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:click",{item:this,model:this.model,index:this.index,action:"row-click",event:t,data:this.model?.toJSON?this.model.toJSON():this.model}))},this.element.addEventListener("click",this._clickableHandler))}async onActionDefault(t,e,i){this.emit("item:click",{item:this,model:this.model,index:this.index,action:t,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:click",{item:this,model:this.model,index:this.index,action:t,data:this.model?.toJSON?this.model.toJSON():this.model})}setIndex(t){return this.index=t,this.element.setAttribute("data-index",t),this}setSelected(t){return t?this.select():this.deselect(),this}async destroy(){this._clickableHandler&&this.element&&(this.element.removeEventListener("click",this._clickableHandler),this._clickableHandler=null),this.listView=null,await super.destroy()}}class ListGroupHeaderView extends t{constructor(t={}){super({tagName:t.tagName||"div",className:t.className||"list-group-header",...t}),this.key=t.key??"",this.index=t.index??0,this.colspan=t.colspan??1,this.template||(this.template="{{key}}")}}class ListView extends t{static GROUP_HEADER_STYLES=["banner","mark","band","rule"];static ROW_STRIPE_TOKENS=["danger","warning","success","info","primary","secondary"];static _warnedMinifiedClasses=/* @__PURE__ */new WeakSet;constructor(t={}){super({className:t.className||"list-view",...t}),this.collection=null,this.itemViews=/* @__PURE__ */new Map,this.selectedItems=/* @__PURE__ */new Set,this.itemTemplate=t.itemTemplate||null,this.itemClass=t.itemClass||ListViewItem,this.selectionMode=t.selectionMode||"none",this.emptyMessage=t.emptyMessage||"No items to display",this.loading=!1,this.isEmpty=!0,this.searchable=!0===t.searchable,this.filterable=!0===t.filterable,this.paginated=!0===t.paginated;let e=t.paginationMode;e||(e=this.paginated?"more":"none"),this.paginationMode=e,this.searchPlacement=t.searchPlacement||"toolbar",this.searchPlaceholder=t.searchPlaceholder||"Search...",this.sortOptions=Array.isArray(t.sortOptions)?t.sortOptions:[],this.filters={},this.additionalFilters=t.filters||[],this.hideActivePills=!0===t.hideActivePills,this.hideActivePillNames=t.hideActivePillNames||[],this.title=t.title||null,this.eyebrow=t.eyebrow||null,this.showRefresh=!1!==t.showRefresh,this.toolbarButtons=t.toolbarButtons||[],this.toolbarRight=t.toolbarRight||null,this._toolbarRightMounted=!1,this.dayRangeFilter=this._normalizeDayRangeFilter(t.dayRangeFilter),this.dayRangeControl=null,this.filterPresets=this._normalizeFilterPresets(t.filterPresets),this.exportOptions=t.exportOptions||null,this.exportSource=t.exportSource||"remote",this.persistSelection=void 0===t.persistSelection?"more"===this.paginationMode:!0===t.persistSelection,this.onItemClick="function"==typeof t.onItemClick?t.onItemClick:null,this.clickAction=t.clickAction||"none",this.itemView=t.itemView,this.addForm=t.addForm,this.editForm=t.editForm,this.deleteTemplate=t.deleteTemplate,this.formDialogConfig=t.formDialogConfig||{},this.viewDialogOptions=t.viewDialogOptions||{},this.fetchOnView=!1!==t.fetchOnView,this.clickable=!0===t.clickable||!!this.onItemClick||this.clickAction&&"none"!==this.clickAction,this.rowStripe="function"==typeof t.rowStripe?t.rowStripe:null,this.groupBy="function"==typeof t.groupBy||"string"==typeof t.groupBy?t.groupBy:null,this.groupHeaderTemplate=t.groupHeaderTemplate||null,this.groupHeaderLabel="function"==typeof t.groupHeaderLabel?t.groupHeaderLabel:null,this.groupHeaderClass=t.groupHeaderClass||ListGroupHeaderView,this.groupHeaderStyle=ListView.GROUP_HEADER_STYLES.includes(t.groupHeaderStyle)?t.groupHeaderStyle:"banner",this.groupHeaderViews=/* @__PURE__ */new Map,this._renderOrder=[],this.emptyState=this._normalizeEmptyState(t.emptyState),this.loadingStyle="spinner"===t.loadingStyle||"default"===t.loadingStyle?"spinner":"skeleton",this.showResultCount=!0===t.showResultCount,this._autoRefreshMs=this._normalizeAutoRefresh(t.autoRefresh),this._autoRefreshTimer=null,this._autoRefreshPaused=!1,this._autoRefreshHandlers=null,this.autoRefreshIndicator=!1!==t.autoRefreshIndicator,this._autoRefreshPulseTimer=null,this.persistState=!0===t.persistState,this.persistKey=t.persistKey||null,this.loadingMore=!1,this._isToolbarEnabled()||"none"!==this.paginationMode?this.template=this.buildListTemplate():this.template||(this.template=this._defaultBareTemplate())}async onInit(){const t=this.persistState&&this.options.collection&&this.options.collection.params?Object.keys(this.options.collection.params):[];this._initCollection(this.options.collection||this.options.Collection),this.persistState&&(this._restorePersistedState(t),this.on("params-changed",()=>this._savePersistedState())),this.dayRangeFilter&&(this._seedDayRangeParams(),this.dayRangeControl=new SegmentControl({containerId:"toolbar-day-range",options:this.dayRangeFilter.options,value:this.dayRangeFilter.value,ariaLabel:this.dayRangeFilter.ariaLabel}),this.dayRangeControl.on("change",this._onDayRangeChange,this),this.addChild(this.dayRangeControl))}async onAfterMount(){await super.onAfterMount(),!this.collection||!this.options.fetchOnMount&&this.collection.lastFetchTime||this.collection.fetch(),this._startAutoRefresh()}async onBeforeUnmount(){await super.onBeforeUnmount(),this._stopAutoRefresh()}async onBeforeRender(){this.searchValue=this.getActiveFilters().search||"",this.hasMore=this._computeHasMore(),this.skeletonHtml="skeleton"===this.loadingStyle&&this.loading?this._buildSkeletonHtml():"",this.emptyStateHtml=this.emptyState&&this.isEmpty&&!this.loading?this._buildEmptyStateHtml():""}async onAfterRender(){if(await super.onAfterRender(),this.toolbarRight&&!this._toolbarRightMounted&&(this.toolbarRight.containerId="toolbar-right",this.addChild(this.toolbarRight),await this.toolbarRight.render(),this._toolbarRightMounted=!0),this._toolbarRightMounted&&this.toolbarRight&&!this.element?.contains(this.toolbarRight.element)&&(this._toolbarRightMounted=!1),this.paginated&&"pages"===this.paginationMode&&this.collection){const t=this.collection.meta?.count||this.collection.length(),e=this.collection.params?.start||0,i=this.collection.params?.size||10,s=Math.min(e+i,t),n=this.element.querySelector('[data-value="start"]'),o=this.element.querySelector('[data-value="end"]'),a=this.element.querySelector('[data-value="total"]');n&&(n.textContent=0===t?0:e+1),o&&(o.textContent=s),a&&(a.textContent=t);const l=this.element.querySelector('[data-change-action="page-size"]');l&&(l.value=i),this.renderPagination()}this._isToolbarEnabled()&&(this.updateFilterPills(),this.renderFilterPresets(),this.setupSearchClearListener())}_defaultBareTemplate(){return`\n ${this._hasFeedbackFeature()?this._buildFeedbackStyles():""}\n <div class="list-view-container">\n {{#loading}}\n ${this._loadingContent('<div class="list-loading">\n <div class="spinner-border spinner-border-sm" role="status">\n <span class="visually-hidden">Loading...</span>\n </div>\n Loading...\n </div>')}\n {{/loading}}\n {{^loading}}\n {{#isEmpty}}\n ${this._emptyContent('<div class="list-empty">\n {{emptyMessage}}\n </div>')}\n {{/isEmpty}}\n {{^isEmpty}}\n <div class="list-items" data-container="items"></div>\n {{/isEmpty}}\n {{/loading}}\n </div>\n `}buildListTemplate(){const t=this.buildToolbarTemplate(),e="more"===this.paginationMode?this.buildShowMoreTemplate():"",i="pages"===this.paginationMode?this.buildPaginationTemplate():"";return`\n <div class="list-view-wrapper">\n ${this._hasFeedbackFeature()?this._buildFeedbackStyles():""}\n ${t}\n <div class="list-view-container">\n {{#loading}}\n ${this._loadingContent('<div class="list-loading text-center py-4">\n <div class="spinner-border spinner-border-sm" role="status">\n <span class="visually-hidden">Loading...</span>\n </div>\n Loading...\n </div>')}\n {{/loading}}\n {{^loading}}\n {{#isEmpty}}\n ${this._emptyContent('<div class="list-empty text-center py-4 text-muted">\n {{emptyMessage}}\n </div>')}\n {{/isEmpty}}\n {{^isEmpty}}\n <div class="list-items" data-container="items"></div>\n {{/isEmpty}}\n {{/loading}}\n </div>\n ${e}\n ${i}\n </div>\n `}_isToolbarEnabled(){return!!(this.title||this.eyebrow||this.searchable||this.filterable&&this._hasAnyFilters()||this.sortOptions&&this.sortOptions.length>0||this.toolbarRight||this.dayRangeFilter||this.filterPresets&&this.filterPresets.length>0||this.toolbarButtons&&this.toolbarButtons.length>0||this._autoRefreshIndicatorEnabled()||this.options.showAdd||this.options.showExport)}_autoRefreshIndicatorEnabled(){return this._autoRefreshMs>0&&!1!==this.autoRefreshIndicator}_hasAnyFilters(){return this.filters&&Object.keys(this.filters).length>0||this.additionalFilters&&this.additionalFilters.length>0}buildToolbarTemplate(){if(!this._isToolbarEnabled())return"";const t=this._buildTitleBlockTemplate(),e=this.toolbarRight?'<div data-container="toolbar-right"></div>':"",i=this.dayRangeFilter?'<div data-container="toolbar-day-range"></div>':"",s=this.sortOptions&&this.sortOptions.length>0?this.buildSortDropdownTemplate():"",n=this.filterPresets&&this.filterPresets.length>0,o=n&&this._presetsInline(),a=o?'<div data-container="filter-presets" class="preset-segment-slot"></div>':"",l=n&&!o?'<div data-container="filter-presets" class="preset-scroll mt-3"></div>':"",r=n?this._buildPresetStyle():"",c=this._autoRefreshIndicatorEnabled(),d=c?this._buildAutoRefreshIndicatorSlot():"";return`\n <div class="table-action-buttons mb-3">\n ${r}\n ${c?this._buildAutoRefreshIndicatorStyle():""}\n <div class="d-flex align-items-center gap-3 flex-wrap">\n ${t}\n \n <div class="d-flex align-items-center gap-2 flex-wrap ${t?"ms-auto":""}">\n ${this.buildActionButtonsTemplate()}\n ${d}\n ${s}\n ${this.filterable?this.buildFilterDropdownTemplate():""}\n ${this.searchable&&"toolbar"===this.searchPlacement?this.buildSearchTemplate():""}\n ${a}\n ${i}\n ${e}\n </div>\n \n </div>\n ${l}\n <div data-container="filter-pills"></div>\n </div>\n `}_buildTitleBlockTemplate(){return this.title||this.eyebrow?'<div class="rs-table-title-block">{{#eyebrow}}<div class="text-body-secondary text-uppercase small fw-semibold rs-table-eyebrow" style="letter-spacing: 0.05em; line-height: 1.2;">{{eyebrow}}</div>{{/eyebrow}}{{#title}}<h5 class="mb-0 rs-table-title">{{title}}</h5>{{/title}}</div>':""}buildActionButtonsTemplate(){const t=[];if(this.showRefresh&&t.push('\n <button class="btn btn-sm btn-outline-secondary btn-refresh"\n data-action="refresh"\n title="Refresh">\n <i class="bi bi-arrow-clockwise"></i>\n </button>\n '),this.options.showAdd){const e=this.escapeHtml(this.options.addButtonLabel||"Add"),i=this.escapeHtml(this.options.addButtonIcon||"bi bi-plus-circle");t.push(`\n <button class="btn btn-sm btn-success btn-add"\n data-action="add"\n title="${e}">\n <i class="${i} me-1"></i>\n <span class="d-none d-lg-inline">${e}</span>\n </button>\n `)}if(this.options.showExport){const e=this.exportOptions||[{format:"csv",label:"Export as CSV",icon:"bi bi-file-earmark-spreadsheet"},{format:"json",label:"Export as JSON",icon:"bi bi-file-earmark-code"}];if(e.length>1){const i=e.map(t=>`\n <li>\n <a class="dropdown-item" href="#" data-action="export"\n data-format="${this.escapeHtml(t.format)}">\n <i class="${this.escapeHtml(t.icon||"bi bi-file-earmark-arrow-down")} me-2"></i>\n ${this.escapeHtml(t.label)}\n </a>\n </li>\n `).join("");t.push(`\n <div class="dropdown">\n <button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button"\n data-bs-toggle="dropdown" aria-expanded="false" title="Export">\n <i class="bi bi-download me-1"></i>\n <span class="d-none d-lg-inline">Export</span>\n </button>\n <ul class="dropdown-menu">${i}</ul>\n </div>\n `)}else{const i=1===e.length?e[0].format:"json";t.push(`\n <button class="btn btn-sm btn-outline-secondary btn-export"\n data-action="export"\n data-format="${this.escapeHtml(i)}"\n title="Export">\n <i class="bi bi-download me-1"></i>\n <span class="d-none d-lg-inline">Export</span>\n </button>\n `)}}return this.toolbarButtons&&this.toolbarButtons.length>0&&this.toolbarButtons.forEach((e,i)=>{const{label:s="Button",icon:n="",action:o="",handler:a=null,variant:l="outline-secondary",title:r=s,className:c="",permissions:d=null}=e;if(d&&!this.checkPermissions(d))return;const h=this.escapeHtml(n),m=this.escapeHtml(s),u=this.escapeHtml(r),p=this.escapeHtml(l),f=this.escapeHtml(c),g=this.escapeHtml(o),b=n?`<i class="${h} me-1"></i>`:"",y=`<span class="d-none d-lg-inline">${m}</span>`;let w="";a?w=`data-action="custom-toolbar-button" data-button-index="${i}"`:o&&(w=`data-action="${g}"`);const v=`btn btn-sm btn-${p} ${f}`.trim();t.push(`\n <button class="${v}" ${w} title="${u}">\n ${b}${y}\n </button>\n `)}),t.join("")}buildSearchTemplate(){return`\n <div class="flex-grow-1" style="max-width: 400px;">\n <div class="input-group input-group-sm">\n <span class="input-group-text">\n <i class="bi bi-search"></i>\n </span>\n <input type="search"\n class="form-control"\n placeholder="${this.escapeHtml(this.searchPlaceholder)}"\n data-filter="search"\n data-change-action="apply-search"\n value="{{searchValue}}"\n aria-label="Search">\n {{#searchValue}}\n <button class="btn btn-outline-secondary" type="button"\n data-action="clear-search"\n title="Clear search">\n <i class="bi bi-x"></i>\n </button>\n {{/searchValue}}\n </div>\n </div>\n `}buildSortDropdownTemplate(){const t=this.collection?.params?.sort||"";return`\n <div class="dropdown">\n <button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button"\n data-bs-toggle="dropdown" aria-expanded="false">\n <i class="bi bi-sort-down me-1"></i>\n <span class="d-none d-lg-inline">Sort</span>\n </button>\n <ul class="dropdown-menu dropdown-menu-end">\n ${this.sortOptions.map(e=>{const i=`${"desc"===e.dir?"-":""}${e.key}`;return`\n <li><a class="dropdown-item ${t===i?"active":""}" href="#"\n data-action="sort-option" data-sort="${this.escapeHtml(i)}">\n ${this.escapeHtml(e.label||e.key)}\n </a></li>\n `}).join("")}\n ${t?'\n <li><hr class="dropdown-divider"></li>\n <li><a class="dropdown-item" href="#" data-action="sort-option" data-sort="">\n <i class="bi bi-x-circle me-1"></i>Clear sort\n </a></li>\n ':""}\n </ul>\n </div>\n `}buildFilterDropdownTemplate(){return this._hasAnyFilters()?`\n <div class="dropdown">\n <button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button"\n data-bs-toggle="dropdown" aria-expanded="false">\n <i class="bi bi-filter me-1"></i>\n <span class="d-none d-lg-inline">Add Filter</span>\n </button>\n <div class="dropdown-menu" style="min-width: 250px;">\n ${this.buildFilterList()}\n </div>\n </div>\n `:""}buildFilterList(){const t=this.getAllAvailableFilters(),e=this.getActiveFilters();return 0===t.length?'<div class="dropdown-item-text text-muted">No filters available</div>':`\n ${t.map(t=>{const i=Object.prototype.hasOwnProperty.call(e,t.key),s=i?"active":"",n=this.getFilterIcon(t.type||t.config?.type);return`\n <button class="dropdown-item ${s}"\n data-action="add-filter"\n data-filter-key="${this.escapeHtml(t.key)}">\n <i class="bi bi-${this.escapeHtml(n)} me-2"></i>\n ${this.escapeHtml(t.label||t.key)}\n ${i?'<i class="bi bi-check-circle ms-auto"></i>':""}\n </button>\n `}).join("")}\n ${Object.keys(e).length>0?'\n <div class="dropdown-divider"></div>\n <button class="dropdown-item text-danger" data-action="clear-all-filters">\n <i class="bi bi-x-circle me-2"></i>Clear All Filters\n </button>\n ':""}\n `}buildActivePills(){const t=this.showResultCount?this._buildResultCountSummary():"";if(this.hideActivePills)return t?this._wrapPillRow(t):"";const e=this.getActiveFilters(),i=e.search&&""!==e.search.toString().trim();let s=Object.entries(e).filter(([t,e])=>e&&""!==e.toString().trim()&&"search"!==t);return this.hideActivePillNames&&this.hideActivePillNames.length>0&&(s=s.filter(([t])=>!this.hideActivePillNames.includes(t))),0!==s.length||i?`\n <div class="row mt-2">\n <div class="col-12">\n <div class="d-flex flex-wrap align-items-center">\n ${t}${s.map(([t,e])=>{const{field:i}=a(t),s=this.getFilterLabel(i),n=this.escapeHtml(l(t,e,s)),o=this.escapeHtml(t);return`\n <span class="badge bg-primary me-1 mb-1 py-1 px-2 position-relative" style="font-size: 0.75rem;">\n <i class="bi bi-filter me-1" style="font-size: 0.65rem;"></i>\n\n <button type="button" class="btn btn-link p-0 ms-1 list-filter-pill-text"\n style="font-size: 0.65rem; line-height: 1; text-decoration: none;"\n data-action="edit-filter"\n data-filter="${o}"\n title="Edit filter">\n ${n}\n </button>\n\n <button type="button" class="btn-close ms-1"\n style="font-size: 0.6rem; width: 0.5rem; height: 0.5rem;"\n data-action="remove-filter"\n data-filter="${o}"\n title="Remove filter">\n </button>\n </span>\n `}).join("")}\n ${s.length>1||s.length>0&&i||0===s.length&&i?'\n <button class="btn btn-sm btn-outline-secondary mb-1 py-0 px-2" style="font-size: 0.75rem;" data-action="clear-all-filters">\n <i class="bi bi-x-circle me-1" style="font-size: 0.7rem;"></i>\n <small>Clear All</small>\n </button>\n ':""}\n </div>\n </div>\n </div>\n `:t?this._wrapPillRow(t):""}_wrapPillRow(t){return`\n <div class="row mt-2">\n <div class="col-12">\n <div class="d-flex flex-wrap align-items-center">\n ${t}\n </div>\n </div>\n </div>\n `}buildPaginationTemplate(){return'\n <div class="table-status-bar mt-3">\n <div class="d-flex flex-column flex-lg-row justify-content-center justify-content-lg-between align-items-center gap-3">\n <div class="d-flex flex-column flex-sm-row align-items-center gap-2 gap-sm-3 text-center text-lg-start">\n <span class="text-muted">\n Showing <span data-value="start">0</span> to <span data-value="end">0</span>\n of <span data-value="total">0</span> entries\n </span>\n <div class="d-flex align-items-center">\n <label class="form-label me-2 mb-0">Show:</label>\n <select class="form-select form-select-sm" style="width: auto;" data-change-action="page-size">\n <option value="5">5</option>\n <option value="10">10</option>\n <option value="25">25</option>\n <option value="50">50</option>\n <option value="100">100</option>\n </select>\n </div>\n </div>\n <nav aria-label="List pagination">\n <ul class="pagination pagination-sm mb-0 justify-content-center" data-container="pagination"></ul>\n </nav>\n </div>\n </div>\n '}buildShowMoreTemplate(){return'\n {{#hasMore}}\n <div class="list-show-more-row text-center mt-3">\n <button class="btn btn-outline-secondary btn-sm" data-action="show-more"\n {{#loadingMore}}disabled{{/loadingMore}}>\n {{#loadingMore}}\n <span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>\n Loading…\n {{/loadingMore}}\n {{^loadingMore}}\n <i class="bi bi-arrow-down-circle me-1"></i>Show more\n {{/loadingMore}}\n </button>\n </div>\n {{/hasMore}}\n '}_normalizeEmptyState(t){if(!t||"object"!=typeof t)return null;let e=null;return t.action&&"object"==typeof t.action&&t.action.action&&(e={label:t.action.label||"Action",action:t.action.action,icon:t.action.icon||null}),{icon:t.icon||"inbox",title:t.title||null,message:t.message||null,action:e}}_hasFeedbackFeature(){return!!this.emptyState||"skeleton"===this.loadingStyle||this.showResultCount}_loadingContent(t){return"skeleton"===this.loadingStyle?"{{{skeletonHtml}}}":t}_emptyContent(t){return this.emptyState?"{{{emptyStateHtml}}}":t}_skeletonRowCount(){const t=this.collection?.params?.size,e="number"==typeof t&&t>0?t:5;return Math.min(e,8)}_buildSkeletonHtml(){const t=this._skeletonRowCount();let e="";for(let i=0;i<t;i++)e+='<div class="list-skeleton-card"><span class="skeleton-line w-40"></span><span class="skeleton-line w-90"></span><span class="skeleton-line w-60"></span></div>';return`<div class="list-skeleton" aria-hidden="true">${e}</div>`}_buildEmptyStateHtml(){const t=this.emptyState;if(!t)return"";const e=Object.keys(this.getActiveFilters()).length;let i,s,n,o;if(e>0)i="funnel",s="No results match your filters",n=`No items match the ${e} active ${1===e?"filter":"filters"}. Try widening or removing a filter.`,o='<button class="btn btn-outline-primary" data-action="clear-all-filters"><i class="bi bi-x-circle me-1"></i>Clear filters</button>';else if(i=t.icon||"inbox",s=t.title||this.emptyMessage,n=t.message||"",t.action){const e=t.action.icon?`<i class="bi ${this.escapeHtml(t.action.icon)} me-1"></i>`:"";o=`<button class="btn btn-primary" data-action="${this.escapeHtml(t.action.action)}">${e}${this.escapeHtml(t.action.label)}</button>`}else o="";const a=s?`<div class="empty-state-title h6">${this.escapeHtml(s)}</div>`:"",l=n?`<p class="empty-state-message">${this.escapeHtml(n)}</p>`:"";return`\n <div class="table-empty-state">\n <span class="empty-state-icon"><i class="bi bi-${this.escapeHtml(i)}"></i></span>\n ${a}\n ${l}\n ${o}\n </div>\n `}_buildResultCountSummary(){if(!this.showResultCount||!this.collection)return"";const t=this.collection.meta||{},e="number"==typeof t.count?t.count:null;if(null===e)return"";const i=this.collection.length(),s=t=>Number(t).toLocaleString(),n=Object.keys(this.getActiveFilters()).length>0?' <span class="count-filtered">· filtered</span>':"";return`<span class="result-count-summary me-2 mb-1">Showing <strong>${s(i)}</strong> of <strong>${s(e)}</strong>${n}</span>`}_buildFeedbackStyles(){return'\n <style>\n .table-empty-state { text-align: center; padding: 3rem 1.5rem; }\n .table-empty-state .empty-state-icon {\n display: inline-flex; align-items: center; justify-content: center;\n width: 4rem; height: 4rem; border-radius: 50%;\n margin-bottom: 1rem; font-size: 1.75rem;\n background: var(--bs-secondary-bg);\n color: var(--bs-secondary-color);\n border: 1px solid var(--bs-border-color);\n }\n .table-empty-state .empty-state-title {\n font-weight: 600; color: var(--bs-emphasis-color); margin-bottom: 0.35rem;\n }\n .table-empty-state .empty-state-message {\n color: var(--bs-secondary-color); max-width: 26rem; margin: 0 auto 1.25rem;\n }\n\n .skeleton-line {\n display: block; height: 0.85rem; border-radius: 0.35rem;\n background-color: var(--bs-secondary-bg);\n background-image: linear-gradient(90deg,\n rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.06) 50%, rgba(0, 0, 0, 0) 100%);\n background-size: 200% 100%; background-repeat: no-repeat;\n animation: mojo-skeleton-shimmer 1.4s ease-in-out infinite;\n }\n [data-bs-theme="dark"] .skeleton-line {\n background-image: linear-gradient(90deg,\n rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.07) 50%, rgba(255, 255, 255, 0) 100%);\n }\n .skeleton-line.w-90 { width: 90%; }\n .skeleton-line.w-75 { width: 75%; }\n .skeleton-line.w-60 { width: 60%; }\n .skeleton-line.w-40 { width: 40%; }\n .skeleton-line.w-25 { width: 25%; }\n .skeleton-line.skeleton-pill { height: 1.35rem; width: 4rem; border-radius: 999px; }\n .list-skeleton-card {\n display: flex; flex-direction: column; gap: 0.5rem;\n padding: 0.85rem 1rem; margin-bottom: 0.5rem;\n border: 1px solid var(--bs-border-color-translucent);\n border-radius: 0.5rem;\n }\n @keyframes mojo-skeleton-shimmer {\n 0% { background-position: 150% 0; }\n 100% { background-position: -50% 0; }\n }\n @media (prefers-reduced-motion: reduce) {\n .skeleton-line { animation: none; }\n }\n\n .result-count-summary { font-size: 0.8rem; color: var(--bs-secondary-color); }\n .result-count-summary strong { color: var(--bs-emphasis-color); font-weight: 600; }\n .result-count-summary .count-filtered { color: var(--bs-primary); }\n </style>\n '}_initCollection(t){if(t)if(t instanceof e)this.setCollection(t);else if("function"==typeof t){const e=new t;this.setCollection(e)}else if(Array.isArray(t)){const i=new e(t);this.setCollection(i)}}_normalizeDayRangeFilter(t){if(!t)return null;const e={field:"created",value:"7d",options:[{value:"1d",label:"1d"},{value:"7d",label:"7d"},{value:"30d",label:"30d"},{value:"90d",label:"90d"}],ariaLabel:"Time range"};return!0===t?e:{...e,...t}}_dayRangeDays(t){const e=/^(\d+)d$/.exec(String(t||""));return e?parseInt(e[1],10):null}_seedDayRangeParams(){if(!this.dayRangeFilter||!this.collection)return;const t=this._dayRangeDays(this.dayRangeFilter.value);if(null==t)return;const e=Math.floor(Date.now()/1e3)-86400*t;this.collection.params[`${this.dayRangeFilter.field}__gte`]=e}async _onDayRangeChange({value:t,previous:e}){const i=this.dayRangeFilter?.field||"created",s=this._dayRangeDays(t);let n={};if(null!=s&&this.collection){const t=Math.floor(Date.now()/1e3)-86400*s;this.collection.params[`${i}__gte`]=t,this.collection.params.start=0,n={[`${i}__gte`]:t}}if(this.emit("range:change",{field:i,value:t,previous:e,params:n}),this.emit("params-changed"),this.collection?.restEnabled)try{await this.collection.fetch()}catch(o){console.error("Failed to fetch day-range data:",o),await this.render()}else await this.render()}getRange(){return this.dayRangeControl?.getValue()??null}setRange(t,{silent:e=!1}={}){if(!this.dayRangeControl)return!1;const i=this.dayRangeControl.getValue();return!!this.dayRangeControl.setValue(t,{silent:!0})&&(e||this._onDayRangeChange({value:t,previous:i}),!0)}_normalizeFilterPresets(t){if(!Array.isArray(t)||0===t.length)return[];const e=/* @__PURE__ */new Set,i=[];return t.forEach(t=>{t&&t.key&&(e.has(t.key)?console.warn(`ListView: duplicate filterPresets key '${t.key}' — ignoring the later one.`):(e.add(t.key),i.push({key:t.key,label:t.label||t.key,icon:t.icon||null,params:t.params&&"object"==typeof t.params?t.params:{},description:t.description||null})))}),i}_presetsInline(){return this.filterPresets.length<=4}_getPreset(t){return this.filterPresets.find(e=>e.key===t)||null}_resolvePresetParams(t){const e={},i=t?.params||{};return Object.keys(i).forEach(t=>{const s=i[t];if("@me"===s){const i=this.getApp()?.activeUser?.id;if(null==i)return;e[t]=i}else e[t]=s}),e}_presetMatches(t){const e=this._resolvePresetParams(t),i=Object.keys(e);if(0===i.length)return!1;const s=this.getActiveFilters();return i.every(t=>{const i=e[t];if(Array.isArray(i)){if(0===i.length)return!0;const{field:e}=a(t);if(1===i.length)return void 0!==s[e]&&String(s[e])===String(i[0]);const n=s[`${e}__in`];return void 0!==n&&String(n)===i.join(",")}return void 0!==s[t]&&String(s[t])===String(i)})}_clearPresetParams(t){const e=this._resolvePresetParams(t);Object.keys(e).forEach(t=>this.setFilter(t,null))}getActivePreset(){if(!this.filterPresets||0===this.filterPresets.length)return null;let t=null,e=-1;for(const i of this.filterPresets){if(!this._presetMatches(i))continue;const s=Object.keys(this._resolvePresetParams(i)).length;s>e&&(t=i,e=s)}return t}async applyPreset(t){const e=this._getPreset(t);if(!e)return!1;const i=this.getActivePreset();if(i&&i.key===e.key)return await this.clearPreset(),!0;i&&this._clearPresetParams(i);const s=this._resolvePresetParams(e);return Object.keys(s).forEach(t=>this.setFilter(t,s[t])),await this.applyFilters(),this.renderFilterPresets(),this.emit("preset:change",{key:e.key,params:s}),!0}async clearPreset(){const t=this.getActivePreset();t&&(this._clearPresetParams(t),await this.applyFilters()),this.renderFilterPresets(),this.emit("preset:change",null)}async onActionApplyPreset(t,e){t&&"function"==typeof t.preventDefault&&t.preventDefault();const i=e?.getAttribute("data-preset-key");i&&await this.applyPreset(i)}renderFilterPresets(){if(!this.filterPresets||0===this.filterPresets.length)return;const t=this.element?.querySelector('[data-container="filter-presets"]');t&&(t.innerHTML=this._buildPresetSegment())}_buildPresetSegment(){const t=this.getActivePreset(),e=t?t.key:null;return`<div class="btn-group btn-group-sm preset-segment" role="group" aria-label="Filter presets">${this.filterPresets.map(t=>{const i=t.key===e,s=i?"btn btn-primary":"btn btn-outline-secondary",n=t.icon?`<i class="bi ${this.escapeHtml(t.icon)}"></i> `:"",o=t.description?` title="${this.escapeHtml(t.description)}"`:"";return`<button type="button"\n class="${s}"\n data-action="apply-preset"\n data-preset-key="${this.escapeHtml(t.key)}"\n aria-pressed="${i?"true":"false"}"${o}>${n}${this.escapeHtml(t.label)}</button>`}).join("")}</div>`}_buildPresetStyle(){return'\n <style>\n .preset-segment .btn {\n --bs-btn-padding-y: 0.25rem;\n --bs-btn-padding-x: 0.6rem;\n font-size: 0.8125rem;\n font-weight: 500;\n }\n .preset-segment .btn .bi { font-size: 0.8rem; }\n\n /* Touch: bump the tap target only on coarse pointers — desktop stays compact. */\n @media (pointer: coarse) {\n .preset-segment .btn {\n --bs-btn-padding-y: 0.5rem;\n --bs-btn-padding-x: 0.85rem;\n }\n }\n\n /* 5+ presets: own row, scroll horizontally instead of wrapping. */\n .preset-scroll {\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: thin;\n padding-bottom: 0.2rem;\n }\n .preset-scroll .btn-group { flex-wrap: nowrap; }\n .preset-scroll .btn { white-space: nowrap; }\n .preset-scroll::-webkit-scrollbar { height: 6px; }\n .preset-scroll::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.15);\n border-radius: 999px;\n }\n [data-bs-theme="dark"] .preset-scroll::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.12);\n }\n </style>\n '}_buildAutoRefreshIndicatorSlot(){const t=`Auto-refresh: ${Math.round(this._autoRefreshMs/1e3)}s`;return`<span class="mojo-autorefresh-indicator" data-autorefresh-indicator title="${this.escapeHtml(t)}">\n <i class="bi bi-arrow-repeat" aria-hidden="true"></i>\n <span class="visually-hidden">${this.escapeHtml(t)}</span>\n </span>`}_buildAutoRefreshIndicatorStyle(){return"\n <style>\n .mojo-autorefresh-indicator {\n display: inline-flex;\n align-items: center;\n color: var(--bs-secondary-color);\n font-size: 0.9rem;\n line-height: 1;\n }\n .mojo-autorefresh-indicator .bi { display: block; }\n .mojo-autorefresh-indicator.is-refreshing .bi {\n animation: mojo-autorefresh-spin 0.6s ease;\n }\n @keyframes mojo-autorefresh-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n @media (prefers-reduced-motion: reduce) {\n .mojo-autorefresh-indicator.is-refreshing .bi { animation: none; }\n }\n </style>\n "}_pulseAutoRefreshIndicator(){const t=this.element?.querySelector("[data-autorefresh-indicator]");t&&(t.classList.add("is-refreshing"),this._autoRefreshPulseTimer&&clearTimeout(this._autoRefreshPulseTimer),this._autoRefreshPulseTimer=setTimeout(()=>{t.classList.remove("is-refreshing"),this._autoRefreshPulseTimer=null},600))}setCollection(t){return this.collection===t||(this.collection&&(this.collection.off("add",this._onModelsAdded,this),this.collection.off("remove",this._onModelsRemoved,this),this.collection.off("reset",this._onCollectionReset,this),this.collection.off("fetch:start",this._onFetchStart,this),this.collection.off("fetch:end",this._onFetchEnd,this)),this.collection=t,this.options.defaultQuery&&!this.options.collectionParams&&(this.collection.params={...this.collection.params,...this.options.defaultQuery}),this.options.collectionParams&&(this.collection.params={...this.collection.params,...this.options.collectionParams}),this.options.pageSize&&this.collection&&(this.collection.params={...this.collection.params,size:this.options.pageSize}),this.collection&&(this.collection.on("add",this._onModelsAdded,this),this.collection.on("remove",this._onModelsRemoved,this),this.collection.on("reset",this._onCollectionReset,this),this.collection.on("fetch:start",this._onFetchStart,this),this.collection.on("fetch:end",this._onFetchEnd,this),!this.collection.restEnabled||this.collection.lastFetchTime||this.collection.options?.preloaded?this._buildItems():this.loading=!0)),this}async _renderChildren(){await super._renderChildren();const t=this.getChildElement("items");if(!t)return;const e=[];if(this._renderOrder.length>0)for(const i of this._renderOrder)t.appendChild(i.view.element),e.push(Promise.resolve(i.view.render(!1)).catch(()=>{}));else this.forEachItem(i=>{t.appendChild(i.element),e.push(Promise.resolve(i.render(!1)).catch(()=>{}))});await Promise.all(e)}_buildItems(){if(this._clearItems(),!this.collection||this.collection.isEmpty())return this.isEmpty=!0,void this.emit("list:empty");this.isEmpty=!1,this.collection.forEach((t,e)=>{this._createItemView(t,e)}),this._applyPersistedSelections(),this._buildGroupHeaders(),this.emit("list:loaded",{count:this.collection.length()}),this.isMounted()&&this.render()}_buildGroupHeaders(){if(this.groupHeaderViews.forEach(t=>this.removeChild(t.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,!this.groupBy||!this.collection||this.collection.isEmpty())return;const t="function"==typeof this.groupBy?this.groupBy:t=>t.get(this.groupBy);let e,i=!1;this.collection.forEach((s,n)=>{const o=this.itemViews.get(s.id);if(!o)return;let a;try{a=t(s)}catch(l){console.warn("ListView: groupBy resolver threw — treating as ungrouped tail",l),a=null}if(a&&(!i||a!==e)){const t=this._createGroupHeaderView(s,a,n);this._renderOrder.push({type:"header",view:t}),e=a,i=!0}this._renderOrder.push({type:"item",view:o})})}_rebuildGroupHeaders(){this._buildGroupHeaders()}_createGroupHeaderView(t,e,i){const s=this.groupHeaderLabel?this.groupHeaderLabel(e):e,n=new this.groupHeaderClass({template:this.groupHeaderTemplate||this._defaultGroupHeaderTemplate(),model:t,key:s,index:i,...this._groupHeaderViewOptions(t,e,i)});return this.groupHeaderViews.set(n.id,n),n}_groupHeaderViewOptions(t,e,i){return{className:`list-group-header list-group-header--${this.groupHeaderStyle}`}}_defaultGroupHeaderTemplate(){return"{{key}}"}_createItemView(t,e){if(this.itemViews.has(t.id))return this.itemViews.get(t.id);const i=new this.itemClass({model:t,index:e,listView:this,template:this.itemTemplate,clickable:this.clickable});return this.itemViews.set(t.id,i),this._wireItemViewListeners(i),i}_wireItemViewListeners(t){t.on("item:select",this._onItemSelect.bind(this)),t.on("item:deselect",this._onItemDeselect.bind(this)),t.on("item:click",t=>{"row-click"===t.action&&(this.emit("row:click",t),this._dispatchRowClick(t))}),t.on("row:click",t=>{this._dispatchRowClick(t)}),t.on("row:view",this._onRowView.bind(this)),t.on("row:edit",this._onRowEdit.bind(this)),t.on("row:delete",this._onRowDelete.bind(this))}_dispatchRowClick(t){return"function"==typeof this.options.onRowClick?this.options.onRowClick(t.model,t.event):"function"==typeof this.clickAction?this.clickAction(t.model,t.event):this.onItemClick?this.onItemClick(t.model,t.event):"view"===this.clickAction?this._onRowView(t):"edit"===this.clickAction?this._onRowEdit(t):void("select"===this.clickAction&&(this.selectedItems.has(t.model.id)?this.deselectItem(t.model.id):this.selectItem(t.model.id)))}_applyPersistedSelections(){this.persistSelection&&0!==this.selectedItems.size&&this.itemViews.forEach((t,e)=>{this.selectedItems.has(e)&&!t.selected&&(t.selected=!0,t.element&&t.addClass("selected"))})}_clearItems(){this.forEachItem(t=>{this.removeChild(t.id)}),this.itemViews.clear(),this.groupHeaderViews.forEach(t=>this.removeChild(t.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,this.persistSelection||this.selectedItems.clear()}_onModelsAdded(t){const{models:e}=t;e.forEach(t=>{const e=this.collection.models.indexOf(t);this._createItemView(t,e)}),this._applyPersistedSelections(),this.groupBy&&this._rebuildGroupHeaders(),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render()}_onModelsRemoved(t){const{models:e}=t;e.forEach(t=>{const e=this.itemViews.get(t.id);e&&(this.removeChild(e.id),this.itemViews.delete(t.id),this.selectedItems.delete(t.id))}),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render(),this.isEmpty&&this.emit("list:empty")}_onCollectionReset(t){this._buildItems()}_onFetchStart(){this.loading=!0,this.loadingMore||this.isMounted()&&this.render()}_onFetchEnd(){this.loading=!1,this.loadingMore||this.isMounted()&&this.render()}_onItemSelect(t){const{model:e,item:i}=t;"none"!==this.selectionMode?("single"===this.selectionMode&&(this.itemViews.forEach((t,i)=>{i!==e.id&&t.selected&&t.deselect()}),this.selectedItems.clear()),this.selectedItems.add(e.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:i,model:e})):i.deselect()}_onItemDeselect(t){const{model:e}=t;this.selectedItems.delete(e.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:t.item,model:e})}getSelectedItems(){const t=[];return this.selectedItems.forEach(e=>{const i=this.itemViews.get(e);i&&t.push({view:i,model:i.model,data:i.model?.toJSON?i.model.toJSON():i.model})}),t}forEachItem(t,e){if("function"!=typeof t)throw new TypeError("Callback must be a function");let i=0;return this.itemViews.forEach(s=>{t.call(e,s,s.model,i++)}),this}clearSelection(){this.forEachItem(t=>{t.selected&&t.deselect()}),this.selectedItems.clear(),this.emit("selection:change",{selected:[]})}selectItem(t){const e=this.itemViews.get(t);return e&&e.select(),this}deselectItem(t){const e=this.itemViews.get(t);return e&&e.deselect(),this}setItemTemplate(t,e=!1){return this.itemTemplate=t,e&&this.itemViews.size>0&&this.forEachItem(e=>{e.setTemplate(t),e.isMounted()&&e.render()}),this}async refresh(){if(this.collection&&this.collection.restEnabled)return await this.collection.fetch();this._buildItems()}_stripeClassFor(t){if(!this.rowStripe||!t)return null;let e;try{e=this.rowStripe(t)}catch(i){return console.warn("ListView: rowStripe callback threw — treating as no stripe",i),null}return null==e||""===e||"string"!=typeof e?null:ListView.ROW_STRIPE_TOKENS.includes(e)?`list-row-stripe-${e}`:e}_applyRowStripe(t){if(!t||!t.element)return;const e=t.element.classList;for(const n of Array.from(e))n.startsWith("list-row-stripe")&&e.remove(n);const i=this._stripeClassFor(t.model);if(i)try{e.add(i)}catch(s){console.warn("ListView: rowStripe returned an invalid class name, skipping",i,s)}}refreshStripes(){return this.rowStripe?(this.forEachItem(t=>this._applyRowStripe(t)),this):this}async _onRowView(t){if(this.emit("row:view",t),this.options.onItemView)return void(await this.options.onItemView(t.model,t.event));if(this.fetchOnView)try{s.loading(),await t.model.fetch()}catch(i){return s.hideLoading(!0),void s.showError(i?.data?.error||i?.message||"Failed to load item details")}finally{s.hideLoading(!0)}const e=this.getItemViewClass(t.model);if(e){const i=new e({model:t.model,collection:this.collection});await s.dialog({header:!1,body:i,size:"lg",centered:!1,...this.getFormDialogConfig(this.getModelClass(t.model)),...e.DIALOG_OPTIONS,...this.viewDialogOptions})}else await s.data({title:`View ${this.getModelName(t.model)} #${t.model.id}`,model:t.model})}async _onRowEdit(t){if(this.emit("row:edit",t),this.options.onItemEdit)return void(await this.options.onItemEdit(t.model,t.event));const e=this.getModelClass(t.model);let i=this.getEditFormConfig(e);if(i){i.fields||(i={title:`Edit ${this.getModelName(t.model)}`,fields:i});const n=await s.modelForm({model:t.model,...i,...this.getFormDialogConfig(e)});if(!n)return;if(!n.success||!n?.result?.data.status)return void s.showError(n?.result?.data?.error||n?.result?.message||"An error occurred")}else{const e=await s.dialog({title:`Edit ${this.getModelName(t.model)} #${t.model.id}`,body:new n({model:t.model,fields:this.options.formFields||[]})});if(e){const i=await t.model.save(e);if(!i.data?.status)return void s.showError(i.data.error||"An error occurred");await this.refresh()}}}async _onRowDelete(t){if(this.emit("row:delete",t),this.options.onItemDelete)return void(await this.options.onItemDelete(t.model,t.event));const e=this.getModelClass(t.model),i=this.deleteTemplate||e?.DELETE_TEMPLATE||'Are you sure you want to delete this {{name||"item"}}?',n=this.renderTemplateString(i,t.model);await s.confirm({message:n||"Are you sure you want to delete this item?",title:"Confirm Delete",confirmText:"Delete",confirmClass:"btn-danger"})&&(await t.model.destroy(),this.collection?.restEnabled?this.collection.fetch():this._buildItems())}async onActionAdd(t,e){if(this.options.onAdd)return this.emit("list:add",{event:t}),void(await this.options.onAdd(t));this.emit("list:add",{event:t});const i=this.getModelClass();if(!i)return void console.warn("Cannot determine Model class for add operation");let o=this.getAddFormConfig(i);if(o){const t=new i;o.fields||(o={title:`Add ${this.getModelName()}`,fields:o});const e=await s.form({model:t,...o,...this.getFormDialogConfig(i)});if(e){this.options.addRequiresActiveGroup&&(e.group=this.getApp().activeGroup.id),this.options.addRequiresActiveUser&&(e.user=this.getApp().activeUser.id),this.options.addFormDefaults&&Object.assign(e,this.options.addFormDefaults);const i=await t.save(e);if(!i?.data.status)return void s.showError(i?.data.error||"An error occurred");this.collection&&this.collection.add(t),await this.refresh()}}else{const t=new i,e=await s.dialog({title:`Add ${this.getModelName()}`,body:new n({model:t,fields:this.options.formFields||[]})});if(e){const i=await t.save(e);if(!i?.data.status)return void s.showError(i.data.error||"An error occurred");this.collection&&this.collection.add(t),await this.refresh()}}}async onActionExport(t,e){const i=e.getAttribute("data-format")||"json";this.emit("list:export",{format:i,source:this.exportSource,event:t}),"remote"===this.exportSource?this.collection?await this.collection.download(i):console.warn("ListView: Cannot export from remote without a collection."):this.options.onExport?await this.options.onExport(this.collection?.toJSON()||[],i):console.warn("ListView: onExport handler not implemented for local export.")}getModelClass(t){return this.collection?.ModelClass?this.collection.ModelClass:this.collection?.model?this.collection.model:t?.constructor?t.constructor:null}getModelName(t){const e=this.getModelClass(t);if(!e)return"Item";if(e.MODEL_NAME)return e.MODEL_NAME;const i=(e.name||"").replace(/Model$/,"");return/^[A-Z][A-Za-z0-9]{2,}$/.test(i)?i:(ListView._warnedMinifiedClasses.has(e)||(ListView._warnedMinifiedClasses.add(e),console.warn(`ListView.getModelName: class name '${i}' looks minified — set a static MODEL_NAME on the model class for user-facing dialog titles. Falling back to 'Item'.`)),"Item")}getItemViewClass(t){if(this.itemView)return this.itemView;const e=this.getModelClass(t);return e?.VIEW_CLASS?e.VIEW_CLASS:null}getAddFormConfig(t){return this.addForm||t?.ADD_FORM||this.editForm||t?.EDIT_FORM}getEditFormConfig(t){return this.editForm||t?.EDIT_FORM||this.addForm||t?.ADD_FORM}getFormDialogConfig(t){return{...t?.FORM_DIALOG_CONFIG,...this.formDialogConfig}}renderTemplateString(t,e){return t?i.render(t,e):""}async onActionRefresh(t,e){await this.refresh()}async onActionApplySearch(t,e){const i=e.value.trim();this.collection&&(this.setFilter("search",i),this.collection.params.start=0,this.collection.restEnabled?await this.collection.fetch():await this.render()),this.updateFilterPills(),this.emit("list:search",{searchTerm:i}),this.emit("params-changed")}async onActionClearSearch(t,e){this.setFilter("search",null),this.collection&&(this.collection.params.start=0,this.collection.restEnabled&&await this.collection.fetch()),await this.render(),this.updateFilterPills(),this.emit("list:search",{searchTerm:""}),this.emit("params-changed")}setupSearchClearListener(){this.element&&this.element.querySelectorAll('input[type="search"][data-filter="search"]').forEach(t=>{t.addEventListener("input",t=>{""===t.target.value&&this.getActiveFilters().search&&this.onActionClearSearch(t,t.target)})})}updateFilterPills(){const t=this.element?.querySelector('[data-container="filter-pills"]');t&&(t.innerHTML=this.buildActivePills())}updateSearchInputs(t){const e=this.element?.querySelectorAll('[data-filter="search"]');e&&e.forEach(e=>{e.value=t||""})}renderPagination(){const t=this.element.querySelector('[data-container="pagination"]');if(!t||!this.collection)return;const e=this.collection.meta?.count||this.collection.length(),i=this.collection.params?.size||10,s=this.collection.params?.start||0,n=Math.floor(s/i)+1,o=Math.ceil(e/i);if(o<=1)return void(t.innerHTML="");const a=n>1?n-1:o,l=n<o?n+1:1,r=[];r.push(`\n <li class="page-item">\n <a class="page-link" href="#" data-action="page" data-page="${a}">\n <i class="bi bi-chevron-left"></i>\n </a>\n </li>\n `);const c=/* @__PURE__ */new Set([1,o]);for(let m=n-1;m<=n+1;m++)m>=1&&m<=o&&c.add(m);const d=Array.from(c).sort((t,e)=>t-e);let h=0;for(const m of d)h&&m-h>1&&r.push('<li class="page-item disabled"><span class="page-link">…</span></li>'),r.push(`\n <li class="page-item ${m===n?"active":""}">\n <a class="page-link" href="#" data-action="page" data-page="${m}">${m}</a>\n </li>\n `),h=m;r.push(`\n <li class="page-item">\n <a class="page-link" href="#" data-action="page" data-page="${l}">\n <i class="bi bi-chevron-right"></i>\n </a>\n </li>\n `),t.innerHTML=r.join("")}async onActionPage(t,e){t.preventDefault();const i=parseInt(e.getAttribute("data-page"),10),s=this.collection.params?.size||10,n=this.collection.meta?.count||this.collection.length(),o=Math.max(1,Math.ceil(n/s));let a=isNaN(i)?1:i;a<1&&(a=o),a>o&&(a=1),this.collection.setParams({...this.collection.params,start:(a-1)*s}),this.collection.restEnabled?await this.collection.fetch():this.render(),this.emit("list:page",{page:a,event:t}),this.emit("params-changed")}async onChangePageSize(t,e){const i=parseInt(e.value,10);this.collection&&(this.collection.setParams({...this.collection.params,start:0,size:i}),this.collection.restEnabled&&await this.collection.fetch(),this.render()),this.emit("list:pagesize",{size:i}),this.emit("params-changed")}_computeHasMore(){if("more"!==this.paginationMode)return!1;if(!this.collection)return!1;const t=this.collection.meta?.count;return"number"==typeof t&&this.collection.length()<t}async onActionShowMore(t,e){if(!this.loadingMore)if(this.collection&&"function"==typeof this.collection.fetchMore){this.loadingMore=!0,this.isMounted()&&await this.render();try{const t=await this.collection.fetchMore();this.emit("list:show-more",{response:t})}catch(i){console.error("ListView: fetchMore failed",i)}finally{this.loadingMore=!1,this.isMounted()&&await this.render()}}else console.warn("ListView: collection does not support fetchMore()")}async onActionSortOption(t,e){t.preventDefault();const i=e.getAttribute("data-sort");this.collection&&(this.collection.setParams({...this.collection.params,sort:i||void 0,start:0}),this.collection.restEnabled?await this.collection.fetch():this.render()),this.emit("list:sort",{sort:i}),this.emit("params-changed")}async onActionCustomToolbarButton(t,e){const i=parseInt(e.getAttribute("data-button-index"),10),s=this.toolbarButtons[i];s&&"function"==typeof s.handler&&await s.handler.call(this,t,e)}async onActionAddFilter(t,e){const i=e.getAttribute("data-filter-key"),n=this.getFilterConfig(i),o=this.getActiveFilters()[i];if(!n)return void console.warn("No filter config found for key:",i);const a=await s.form({title:`${void 0!==o&&""!==o?"Edit":"Add"} ${this.getFilterLabel(i)} Filter`,size:"md",fields:[this.buildFilterDialogField(n,o,i)]});if(a){const t=this.extractFilterValue(n,a);this.setFilter(i,t),await this.applyFilters()}}async onActionEditFilter(t,e){const i=e.getAttribute("data-filter"),{field:n}=a(i),o=this.getFilterConfig(n)||this.getFilterConfig(i),l=this.getActiveFilters(),r=l[i]||l[n];if(!o)return void console.warn("No filter config found for key:",i,"or field:",n);const c={filter_value:r};if("daterange"===o.type&&r&&"object"==typeof r){const t=o.startName||"dr_start",e=o.endName||"dr_end";c[t]=r.start||"",c[e]=r.end||""}const d=await s.form({title:`Edit ${this.getFilterLabel(n)} Filter`,size:"md",data:c,fields:[this.buildFilterDialogField(o,r,n)]});if(d){const t=this.extractFilterValue(o,d);this.setFilter(i,t),await this.applyFilters()}}async onActionRemoveFilter(t,e){const i=e.getAttribute("data-filter"),{field:s}=a(i);this.setFilter(i,null),"search"===i&&this.updateSearchInputs(""),this.collection?.restEnabled&&await this.collection.fetch(),this.render(),this.updateFilterPills(),this.emit("filter:remove",{key:i,field:s}),this.emit("params-changed")}async onActionClearAllFilters(t,e){if(!this.collection)return;const{start:i,size:s,sort:n}=this.collection.params,o={start:i,size:s};n&&(o.sort=n),Array.isArray(this.hideActivePillNames)&&this.hideActivePillNames.length>0&&this.hideActivePillNames.forEach(t=>{void 0!==this.collection.params[t]&&(o[t]=this.collection.params[t]);const e=this.getFilterConfig(t);if(e&&"daterange"===e.type){const t=e.startName||"dr_start",i=e.endName||"dr_end",s=e.fieldName||"dr_field";void 0!==this.collection.params[t]&&(o[t]=this.collection.params[t]),void 0!==this.collection.params[i]&&(o[i]=this.collection.params[i]),void 0!==this.collection.params[s]&&(o[s]=this.collection.params[s])}}),this.collection.params=o,this.updateSearchInputs(""),this.collection.restEnabled&&await this.collection.fetch(),this.render(),this.updateFilterPills(),this.emit("filters:clear"),this.emit("params-changed")}async applyFilters(){if(this.collection&&(this.collection.params.start=0),this.collection?.restEnabled)try{await this.collection.fetch(),await this.render()}catch(t){console.error("Failed to fetch filtered data:",t),await this.render()}else await this.render();this.updateFilterPills(),this.emit("params-changed")}getActiveFilters(){if(!this.collection?.params)return{};const{start:t,size:e,sort:i,...s}=this.collection.params,n={},o=/* @__PURE__ */new Set;return this.getAllAvailableFilters().forEach(t=>{if("daterange"===t.config?.type){const e=t.key,i=t.config.startName||"dr_start",a=t.config.endName||"dr_end",l=t.config.fieldName||"dr_field";s[l]===e&&(s[i]||s[a])&&(n[e]={start:s[i]||"",end:s[a]||""},o.add(i),o.add(a),o.add(l))}}),Object.keys(s).forEach(t=>{o.has(t)||(n[t]=s[t])}),Object.keys(n).forEach(t=>{const e=`${t}__in`;Object.prototype.hasOwnProperty.call(n,e)&&delete n[t]}),n}setFilter(t,e){if(!this.collection)return;const i=this.getFilterConfig(t);if(i&&"daterange"===i.type){const s=i.startName||"dr_start",n=i.endName||"dr_end",o=i.fieldName||"dr_field";delete this.collection.params[s],delete this.collection.params[n],delete this.collection.params[o],e&&"object"==typeof e&&(e.start||e.end)&&(e.start&&(this.collection.params[s]=e.start),e.end&&(this.collection.params[n]=e.end),this.collection.params[o]=t)}else{const{field:i}=a(t);if(delete this.collection.params[t],delete this.collection.params[i],delete this.collection.params[`${i}__in`],!e||Array.isArray(e)&&0===e.length)return;Array.isArray(e)?1===e.length?this.collection.params[i]=e[0]:this.collection.params[`${i}__in`]=e.join(","):this.collection.params[t]=e}}getAllAvailableFilters(){const t=[];return Object.entries(this.filters||{}).forEach(([e,i])=>{t.push({key:e,label:i.label||e,type:i.type,config:i})}),this.additionalFilters&&Array.isArray(this.additionalFilters)&&this.additionalFilters.forEach(e=>{t.push({key:e.name||e.key,label:e.label,type:e.type,config:e})}),t}getFilterConfig(t){if(this.filters&&this.filters[t])return this.filters[t];if(this.additionalFilters&&Array.isArray(this.additionalFilters)){const e=this.additionalFilters.find(e=>(e.name||e.key)===t);if(e)return e}return null}getFilterLabel(t){if("search"===t)return"Search";const e=this.filters?.[t];if(e&&e.label)return e.label;const i=this.additionalFilters?.find(e=>(e.name||e.key)===t);return i&&i.label?i.label:t.charAt(0).toUpperCase()+t.slice(1)}getFilterIcon(t){return{text:"search",select:"funnel",date:"calendar",daterange:"calendar-range",number:"123",boolean:"toggle-on"}[t]||"filter"}buildFilterDialogField(t,e,i){const{name:s,value:n,...o}=t,a={...o,name:"filter_value",label:o.label,value:e,placeholder:o.placeholder||o.placeHolder};if("daterange"===t.type){if(a.startName=a.startName||"dr_start",a.endName=a.endName||"dr_end",a.fieldName=a.fieldName||"dr_field",a.format=a.format||"YYYY-MM-DD",a.displayFormat=a.displayFormat||"MMM DD, YYYY",a.separator=a.separator||" to ",a.label=a.label||"Date Range",e&&"object"==typeof e){const t=t=>{if(!t&&0!==t)return"";if(t instanceof Date&&!isNaN(t))return t.toISOString().slice(0,10);const e=String(t).trim();if(!e)return"";if(/^-?\d+$/.test(e)){const t=Number(e),i=e.length<=10?1e3*t:t,s=new Date(i);if(!isNaN(s))return s.toISOString().slice(0,10)}const i=new Date(e);return isNaN(i)?e:i.toISOString().slice(0,10)};a.startDate=t(e.start||e.from||e.begin||""),a.endDate=t(e.end||e.to||e.finish||"")}}else if("multiselect"===t.type){let i=[];e&&(Array.isArray(e)?i=e:"string"==typeof e&&(i=e.split(",").map(t=>t.trim()).filter(t=>t))),a.value=i,a.placeholder||a.placeHolder||(t.placeholder||t.placeHolder?a.placeholder=t.placeholder||t.placeHolder:t.label&&(a.placeholder=`Select ${t.label}...`))}else if("boolean"===t.type||"switch"===t.type||"toggle"===t.type){a.type="select";const i=null!=e&&""!==e?e:t.defaultValue,s=!0===i?"true":!1===i?"false":null==i?"":String(i);a.value=s;const n=t.trueLabel||"True",o=t.falseLabel||"False";a.options=[{value:"true",text:n},{value:"false",text:o}],a.placeholder||a.placeHolder||(a.placeholder=t.label?`Filter by ${t.label}…`:"Select…")}return a}extractFilterValue(t,e){if("daterange"===t.type){const i=t.startName||"dr_start",s=t.endName||"dr_end";return{start:e[i],end:e[s]}}return t.type,e.filter_value}setTitle(t){this.title=t||null;const e=this.element?.querySelector(".rs-table-title");e&&(e.textContent=this.title||"")}setEyebrow(t){this.eyebrow=t||null;const e=this.element?.querySelector(".rs-table-eyebrow");e&&(e.textContent=this.eyebrow||"")}escapeHtml(t){return null==t?"":String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}_normalizeAutoRefresh(t){return"number"!=typeof t||!isFinite(t)||t<=0?0:1e3*Math.max(5,t)}_startAutoRefresh(){this._autoRefreshMs&&(this._autoRefreshTimer||(this._autoRefreshPaused=this._autoRefreshDocHidden(),this._bindAutoRefreshListeners(),this._autoRefreshTimer=setInterval(()=>this._autoRefreshTick(),this._autoRefreshMs)))}_stopAutoRefresh(){this._autoRefreshTimer&&(clearInterval(this._autoRefreshTimer),this._autoRefreshTimer=null),this._autoRefreshPulseTimer&&(clearTimeout(this._autoRefreshPulseTimer),this._autoRefreshPulseTimer=null),this._unbindAutoRefreshListeners(),this._autoRefreshPaused=!1}_bindAutoRefreshListeners(){if(this._autoRefreshHandlers)return;const t=()=>{this._autoRefreshPaused=!0},e=()=>{this._autoRefreshPaused=!1,this._autoRefreshResume()},i=()=>{const t=this._autoRefreshDocHidden();this._autoRefreshPaused=t,t||this._autoRefreshResume()};this._autoRefreshHandlers={onBlur:t,onFocus:e,onVisibility:i},"undefined"!=typeof window&&(window.addEventListener("blur",t),window.addEventListener("focus",e)),"undefined"!=typeof document&&document.addEventListener("visibilitychange",i)}_unbindAutoRefreshListeners(){const t=this._autoRefreshHandlers;t&&("undefined"!=typeof window&&(window.removeEventListener("blur",t.onBlur),window.removeEventListener("focus",t.onFocus)),"undefined"!=typeof document&&document.removeEventListener("visibilitychange",t.onVisibility),this._autoRefreshHandlers=null)}_autoRefreshDocHidden(){return"undefined"!=typeof document&&("hidden"===document.visibilityState||!0===document.hidden)}_autoRefreshResume(){this._autoRefreshTimer&&this._autoRefreshTick()}_autoRefreshTick(){this.isMounted()?this._autoRefreshShouldSkip()||this.collection&&this.collection.restEnabled&&Promise.resolve(this.collection.fetch()).then(()=>this._pulseAutoRefreshIndicator()).catch(t=>{console.warn("ListView autoRefresh: fetch failed",t)}):this._stopAutoRefresh()}_autoRefreshShouldSkip(){return!!this._autoRefreshPaused||!!this._autoRefreshDocHidden()||!!(this.selectedItems&&this.selectedItems.size>0)}_persistStorageKey(){return`mojo:tableview:${this.persistKey||this._defaultPersistKey()}`}_defaultPersistKey(){return`${"undefined"!=typeof window&&window.location&&window.location.pathname||""}::${this.collection&&this.collection.endpoint||""}`}_persistStorage(){try{const t="undefined"!=typeof globalThis?globalThis.localStorage:null;if(t&&"function"==typeof t.getItem)return t}catch(t){}return null}_readPersistedState(){const t=this._persistStorage();if(!t)return null;let e,i;try{e=t.getItem(this._persistStorageKey())}catch(s){return null}if(!e)return null;try{i=JSON.parse(e)}catch(s){return this._clearPersistedStorage(),null}return i&&"object"==typeof i&&1===i.v?i:(this._clearPersistedStorage(),null)}_writePersistedState(t){const e=this._persistStorage();if(e)try{e.setItem(this._persistStorageKey(),JSON.stringify(t))}catch(i){}}_clearPersistedStorage(){const t=this._persistStorage();if(t)try{t.removeItem(this._persistStorageKey())}catch(e){}}_restorePersistedState(t=[]){if(!this.persistState||!this.collection)return;const e=this._readPersistedState();if(!e)return;const i=this.collection.params||(this.collection.params={}),s=new Set(t);if(s.delete("start"),s.delete("size"),void 0===e.sort||s.has("sort")||(i.sort=e.sort),void 0!==e.size&&(i.size=e.size),void 0!==e.dayRange&&this.dayRangeFilter){const t=this.dayRangeFilter.field||"created";s.has(`${t}__gte`)||(this.dayRangeFilter.value=e.dayRange)}e.filters&&"object"==typeof e.filters&&Object.keys(e.filters).forEach(t=>{s.has(t)||(i[t]=e.filters[t])}),"function"==typeof this._restoreHiddenColumns&&this._restoreHiddenColumns(e.hidden)}_savePersistedState(){if(!this.persistState)return;const t=this.collection&&this.collection.params||{},e=this.dayRangeFilter?`${this.dayRangeFilter.field||"created"}__gte`:null,i={};Object.keys(t).forEach(s=>{if("start"===s||"size"===s||"sort"===s)return;if(e&&s===e)return;const n=t[s];null!=n&&""!==n&&(i[s]=n)});const s={v:1};if(void 0!==t.sort&&(s.sort=t.sort),void 0!==t.size&&(s.size=t.size),this.dayRangeControl&&"function"==typeof this.dayRangeControl.getValue?s.dayRange=this.dayRangeControl.getValue():this.dayRangeFilter&&(s.dayRange=this.dayRangeFilter.value),Object.keys(i).length>0&&(s.filters=i),"function"==typeof this._getHiddenColumnKeys){const t=this._getHiddenColumnKeys();t&&t.length>0&&(s.hidden=t)}this._writePersistedState(s)}clearPersistedState(){this._clearPersistedStorage(),"function"==typeof this._onClearPersistedState&&this._onClearPersistedState()}async destroy(){this._stopAutoRefresh(),this.collection&&(this.collection.off("add",this._onModelsAdded,this),this.collection.off("remove",this._onModelsRemoved,this),this.collection.off("reset",this._onCollectionReset,this),this.collection.off("fetch:start",this._onFetchStart,this),this.collection.off("fetch:end",this._onFetchEnd,this)),this._clearItems(),await super.destroy()}}export{r as D,ListViewItem as L,SegmentControl as S,ListView as a,o as b,ListGroupHeaderView as c,l as f,a as p};
|
|
2
|
+
//# sourceMappingURL=ListView-B6cE3WKB.js.map
|