web-mojo 2.5.5 → 2.5.6

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/admin.cjs.js +1 -1
  3. package/dist/admin.cjs.js.map +1 -1
  4. package/dist/admin.es.js +1 -1
  5. package/dist/admin.es.js.map +1 -1
  6. package/dist/auth.cjs.js +1 -1
  7. package/dist/auth.es.js +1 -1
  8. package/dist/charts.cjs.js +1 -1
  9. package/dist/charts.es.js +1 -1
  10. package/dist/chunks/ChatView-3d50GW02.js +2 -0
  11. package/dist/chunks/ChatView-3d50GW02.js.map +1 -0
  12. package/dist/chunks/ChatView-C27ckVwL.js +2 -0
  13. package/dist/chunks/ChatView-C27ckVwL.js.map +1 -0
  14. package/dist/chunks/{ListView-BxxGqz7q.js → ListView-C-jiqALE.js} +2 -2
  15. package/dist/chunks/{ListView-Wpby1PCA.js.map → ListView-C-jiqALE.js.map} +1 -1
  16. package/dist/chunks/{ListView-Wpby1PCA.js → ListView-zpCxyyjq.js} +2 -2
  17. package/dist/chunks/{ListView-BxxGqz7q.js.map → ListView-zpCxyyjq.js.map} +1 -1
  18. package/dist/chunks/{Passkeys-C2VoBjDn.js → Passkeys-B4bndv5b.js} +2 -2
  19. package/dist/chunks/{Passkeys-C2VoBjDn.js.map → Passkeys-B4bndv5b.js.map} +1 -1
  20. package/dist/chunks/{Passkeys-eZrcSyHX.js → Passkeys-CIhIxwb2.js} +2 -2
  21. package/dist/chunks/{Passkeys-eZrcSyHX.js.map → Passkeys-CIhIxwb2.js.map} +1 -1
  22. package/dist/chunks/{UserProfileView-CXJKMGy6.js → UserProfileView-B_HnFtsf.js} +2 -2
  23. package/dist/chunks/{UserProfileView-CXJKMGy6.js.map → UserProfileView-B_HnFtsf.js.map} +1 -1
  24. package/dist/chunks/{UserProfileView-D3MGkVVN.js → UserProfileView-DugtA_qG.js} +2 -2
  25. package/dist/chunks/{UserProfileView-D3MGkVVN.js.map → UserProfileView-DugtA_qG.js.map} +1 -1
  26. package/dist/chunks/{index-Dc0tdf4C.js → index-D-bZ5zeg.js} +2 -2
  27. package/dist/chunks/{index-Dc0tdf4C.js.map → index-D-bZ5zeg.js.map} +1 -1
  28. package/dist/chunks/{index-51V5UL7N.js → index-D-gO-M9M.js} +2 -2
  29. package/dist/chunks/{index-51V5UL7N.js.map → index-D-gO-M9M.js.map} +1 -1
  30. package/dist/chunks/{version-b3ZqvsDw.js → version-B1TH_fkK.js} +2 -2
  31. package/dist/chunks/{version-b3ZqvsDw.js.map → version-B1TH_fkK.js.map} +1 -1
  32. package/dist/chunks/{version-CcV-NTY8.js → version-DlfxFCfQ.js} +2 -2
  33. package/dist/chunks/{version-CcV-NTY8.js.map → version-DlfxFCfQ.js.map} +1 -1
  34. package/dist/docit.cjs.js +1 -1
  35. package/dist/docit.es.js +1 -1
  36. package/dist/index.cjs.js +1 -1
  37. package/dist/index.es.js +1 -1
  38. package/dist/lightbox.cjs.js +1 -1
  39. package/dist/lightbox.es.js +1 -1
  40. package/dist/timeline.cjs.js +1 -1
  41. package/dist/timeline.es.js +1 -1
  42. package/dist/user-profile.cjs.js +1 -1
  43. package/dist/user-profile.es.js +1 -1
  44. package/dist/web-mojo.lite.iife.js +8 -0
  45. package/dist/web-mojo.lite.iife.js.map +1 -1
  46. package/dist/web-mojo.lite.iife.min.js +1 -1
  47. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  48. package/package.json +1 -1
  49. package/dist/chunks/ChatView-Ctjijnsd.js +0 -2
  50. package/dist/chunks/ChatView-Ctjijnsd.js.map +0 -1
  51. package/dist/chunks/ChatView-cPwjzX7r.js +0 -2
  52. package/dist/chunks/ChatView-cPwjzX7r.js.map +0 -1
@@ -1581,7 +1581,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1581
1581
  </button>
1582
1582
  </div>
1583
1583
  {{/hasMore}}
1584
- `}_initCollection(e){if(!e){console.log("Collection not provided");return}if(e instanceof le)this.setCollection(e);else if(typeof e=="function"){const t=new e;this.setCollection(t)}else if(Array.isArray(e)){const t=new le(e);this.setCollection(t)}}_normalizeDayRangeFilter(e){if(!e)return null;const t={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 e===!0?t:{...t,...e}}_dayRangeDays(e){const t=/^(\d+)d$/.exec(String(e||""));return t?parseInt(t[1],10):null}_seedDayRangeParams(){if(!this.dayRangeFilter||!this.collection)return;const e=this._dayRangeDays(this.dayRangeFilter.value);if(e==null)return;const t=Math.floor(Date.now()/1e3)-e*86400;this.collection.params[`${this.dayRangeFilter.field}__gte`]=t}async _onDayRangeChange({value:e,previous:t}){const s=this.dayRangeFilter?.field||"created",i=this._dayRangeDays(e);let r={};if(i!=null&&this.collection){const n=Math.floor(Date.now()/1e3)-i*86400;this.collection.params[`${s}__gte`]=n,this.collection.params.start=0,r={[`${s}__gte`]:n}}if(this.emit("range:change",{field:s,value:e,previous:t,params:r}),this.emit("params-changed"),this.collection?.restEnabled)try{await this.collection.fetch()}catch(n){console.error("Failed to fetch day-range data:",n),await this.render()}else await this.render()}getRange(){return this.dayRangeControl?.getValue()??null}setRange(e,{silent:t=!1}={}){if(!this.dayRangeControl)return!1;const s=this.dayRangeControl.getValue();return this.dayRangeControl.setValue(e,{silent:!0})?(t||this._onDayRangeChange({value:e,previous:s}),!0):!1}setCollection(e){return this.collection===e?this:(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=e,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.loading=!0:this._buildItems()),this)}async _renderChildren(){await super._renderChildren();const e=this.getChildElement("items");if(!e)return;const t=[];if(this._renderOrder.length>0)for(const s of this._renderOrder)e.appendChild(s.view.element),t.push(Promise.resolve(s.view.render(!1)).catch(()=>{}));else this.forEachItem(s=>{e.appendChild(s.element),t.push(Promise.resolve(s.render(!1)).catch(()=>{}))});await Promise.all(t)}_buildItems(){if(this._clearItems(),!this.collection||this.collection.isEmpty()){this.isEmpty=!0,this.emit("list:empty");return}this.isEmpty=!1,this.collection.forEach((e,t)=>{this._createItemView(e,t)}),this._applyPersistedSelections(),this._buildGroupHeaders(),this.emit("list:loaded",{count:this.collection.length()}),this.isMounted()&&this.render()}_buildGroupHeaders(){if(this.groupHeaderViews.forEach(i=>this.removeChild(i.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,!this.groupBy||!this.collection||this.collection.isEmpty())return;const e=typeof this.groupBy=="function"?this.groupBy:i=>i.get(this.groupBy);let t,s=!1;this.collection.forEach((i,r)=>{const n=this.itemViews.get(i.id);if(!n)return;let a;try{a=e(i)}catch(o){console.warn("ListView: groupBy resolver threw — treating as ungrouped tail",o),a=null}if(a&&(!s||a!==t)){const o=this._createGroupHeaderView(i,a,r);this._renderOrder.push({type:"header",view:o}),t=a,s=!0}this._renderOrder.push({type:"item",view:n})})}_rebuildGroupHeaders(){this._buildGroupHeaders()}_createGroupHeaderView(e,t,s){const i=this.groupHeaderLabel?this.groupHeaderLabel(t):t,r=new this.groupHeaderClass({template:this.groupHeaderTemplate||this._defaultGroupHeaderTemplate(),model:e,key:i,index:s,...this._groupHeaderViewOptions(e,t,s)});return this.groupHeaderViews.set(r.id,r),r}_groupHeaderViewOptions(e,t,s){return{className:`list-group-header list-group-header--${this.groupHeaderStyle}`}}_defaultGroupHeaderTemplate(){return"{{key}}"}_createItemView(e,t){if(this.itemViews.has(e.id))return this.itemViews.get(e.id);const s=new this.itemClass({model:e,index:t,listView:this,template:this.itemTemplate,clickable:this.clickable});return this.itemViews.set(e.id,s),this._wireItemViewListeners(s),s}_wireItemViewListeners(e){e.on("item:select",this._onItemSelect.bind(this)),e.on("item:deselect",this._onItemDeselect.bind(this)),e.on("item:click",t=>{t.action==="row-click"&&(this.emit("row:click",t),this._dispatchRowClick(t))}),e.on("row:click",t=>{this._dispatchRowClick(t)}),e.on("row:view",this._onRowView.bind(this)),e.on("row:edit",this._onRowEdit.bind(this)),e.on("row:delete",this._onRowDelete.bind(this))}_dispatchRowClick(e){if(typeof this.options.onRowClick=="function")return this.options.onRowClick(e.model,e.event);if(typeof this.clickAction=="function")return this.clickAction(e.model,e.event);if(this.onItemClick)return this.onItemClick(e.model,e.event);if(this.clickAction==="view")return this._onRowView(e);if(this.clickAction==="edit")return this._onRowEdit(e);this.clickAction==="select"&&(this.selectedItems.has(e.model.id)?this.deselectItem(e.model.id):this.selectItem(e.model.id))}_applyPersistedSelections(){!this.persistSelection||this.selectedItems.size===0||this.itemViews.forEach((e,t)=>{this.selectedItems.has(t)&&!e.selected&&(e.selected=!0,e.element&&e.addClass("selected"))})}_clearItems(){this.forEachItem(e=>{this.removeChild(e.id)}),this.itemViews.clear(),this.groupHeaderViews.forEach(e=>this.removeChild(e.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,this.persistSelection||this.selectedItems.clear()}_onModelsAdded(e){const{models:t}=e;t.forEach(s=>{const i=this.collection.models.indexOf(s);this._createItemView(s,i)}),this._applyPersistedSelections(),this.groupBy&&this._rebuildGroupHeaders(),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render()}_onModelsRemoved(e){const{models:t}=e;t.forEach(s=>{const i=this.itemViews.get(s.id);i&&(this.removeChild(i.id),this.itemViews.delete(s.id),this.selectedItems.delete(s.id))}),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render(),this.isEmpty&&this.emit("list:empty")}_onCollectionReset(e){this._buildItems()}_onFetchStart(){this.loading=!0,!this.loadingMore&&this.isMounted()&&this.render()}_onFetchEnd(){this.loading=!1,!this.loadingMore&&this.isMounted()&&this.render()}_onItemSelect(e){const{model:t,item:s}=e;if(this.selectionMode==="none"){s.deselect();return}this.selectionMode==="single"&&(this.itemViews.forEach((i,r)=>{r!==t.id&&i.selected&&i.deselect()}),this.selectedItems.clear()),this.selectedItems.add(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:s,model:t})}_onItemDeselect(e){const{model:t}=e;this.selectedItems.delete(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:e.item,model:t})}getSelectedItems(){const e=[];return this.selectedItems.forEach(t=>{const s=this.itemViews.get(t);s&&e.push({view:s,model:s.model,data:s.model?.toJSON?s.model.toJSON():s.model})}),e}forEachItem(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");let s=0;return this.itemViews.forEach(i=>{e.call(t,i,i.model,s++)}),this}clearSelection(){this.forEachItem(e=>{e.selected&&e.deselect()}),this.selectedItems.clear(),this.emit("selection:change",{selected:[]})}selectItem(e){const t=this.itemViews.get(e);return t&&t.select(),this}deselectItem(e){const t=this.itemViews.get(e);return t&&t.deselect(),this}setItemTemplate(e,t=!1){return this.itemTemplate=e,t&&this.itemViews.size>0&&this.forEachItem(s=>{s.setTemplate(e),s.isMounted()&&s.render()}),this}async refresh(){if(this.collection&&this.collection.restEnabled)return await this.collection.fetch();this._buildItems()}_stripeClassFor(e){if(!this.rowStripe||!e)return null;let t;try{t=this.rowStripe(e)}catch(s){return console.warn("ListView: rowStripe callback threw — treating as no stripe",s),null}return t==null||t===""||typeof t!="string"?null:he.ROW_STRIPE_TOKENS.includes(t)?`list-row-stripe-${t}`:t}_applyRowStripe(e){if(!e||!e.element)return;const t=e.element.classList;for(const i of Array.from(t))i.startsWith("list-row-stripe")&&t.remove(i);const s=this._stripeClassFor(e.model);if(s)try{t.add(s)}catch(i){console.warn("ListView: rowStripe returned an invalid class name, skipping",s,i)}}refreshStripes(){return this.rowStripe?(this.forEachItem(e=>this._applyRowStripe(e)),this):this}async _onRowView(e){if(this.emit("row:view",e),this.options.onItemView){await this.options.onItemView(e.model,e.event);return}if(this.fetchOnView)try{w.loading(),await e.model.fetch()}catch(s){w.hideLoading(!0),w.showError(s?.data?.error||s?.message||"Failed to load item details");return}finally{w.hideLoading(!0)}const t=this.getItemViewClass(e.model);if(t){const s=new t({model:e.model,collection:this.collection});await w.dialog({header:!1,body:s,size:"lg",centered:!1,...this.getFormDialogConfig(this.getModelClass(e.model)),...this.viewDialogOptions})}else await w.data({title:`View ${this.getModelName(e.model)} #${e.model.id}`,model:e.model})}async _onRowEdit(e){if(this.emit("row:edit",e),this.options.onItemEdit){await this.options.onItemEdit(e.model,e.event);return}const t=this.getModelClass(e.model);let s=this.getEditFormConfig(t);if(s){s.fields||(s={title:`Edit ${this.getModelName(e.model)}`,fields:s});const i=await w.modelForm({model:e.model,...s,...this.getFormDialogConfig(t)});if(!i)return;if(!i.success||!i?.result?.data.status){w.showError(i?.result?.data?.error||i?.result?.message||"An error occurred");return}}else{const i=await w.dialog({title:`Edit ${this.getModelName(e.model)} #${e.model.id}`,body:new ee({model:e.model,fields:this.options.formFields||[]})});if(i){const r=await e.model.save(i);if(!r.data?.status){w.showError(r.data.error||"An error occurred");return}await this.refresh()}}}async _onRowDelete(e){if(this.emit("row:delete",e),this.options.onItemDelete){await this.options.onItemDelete(e.model,e.event);return}const t=this.getModelClass(e.model),s=this.deleteTemplate||t?.DELETE_TEMPLATE||'Are you sure you want to delete this {{name||"item"}}?',i=this.renderTemplateString(s,e.model);await w.confirm({message:i||"Are you sure you want to delete this item?",title:"Confirm Delete",confirmText:"Delete",confirmClass:"btn-danger"})&&(await e.model.destroy(),this.collection?.restEnabled?this.collection.fetch():this._buildItems())}async onActionAdd(e,t){if(this.options.onAdd){this.emit("list:add",{event:e}),await this.options.onAdd(e);return}this.emit("list:add",{event:e});const s=this.getModelClass();if(!s){console.warn("Cannot determine Model class for add operation");return}let i=this.getAddFormConfig(s);if(i){const r=new s;i.fields||(i={title:`Add ${this.getModelName()}`,fields:i});const n=await w.form({model:r,...i,...this.getFormDialogConfig(s)});if(n){this.options.addRequiresActiveGroup&&(n.group=this.getApp().activeGroup.id),this.options.addRequiresActiveUser&&(n.user=this.getApp().activeUser.id),this.options.addFormDefaults&&Object.assign(n,this.options.addFormDefaults);const a=await r.save(n);if(!a?.data.status){w.showError(a?.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}else{const r=new s,n=await w.dialog({title:`Add ${this.getModelName()}`,body:new ee({model:r,fields:this.options.formFields||[]})});if(n){const a=await r.save(n);if(!a?.data.status){w.showError(a.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}}async onActionExport(e,t){const s=t.getAttribute("data-format")||"json";this.emit("list:export",{format:s,source:this.exportSource,event:e}),this.exportSource==="remote"?this.collection?await this.collection.download(s):console.warn("ListView: Cannot export from remote without a collection."):this.options.onExport?await this.options.onExport(this.collection?.toJSON()||[],s):console.warn("ListView: onExport handler not implemented for local export.")}getModelClass(e){return this.collection?.ModelClass?this.collection.ModelClass:this.collection?.model?this.collection.model:e?.constructor?e.constructor:null}getModelName(e){const t=this.getModelClass(e);return t&&(t.MODEL_NAME||t.name.replace(/Model$/,""))||"Item"}getItemViewClass(e){if(this.itemView)return this.itemView;const t=this.getModelClass(e);return t?.VIEW_CLASS?t.VIEW_CLASS:null}getAddFormConfig(e){return this.addForm||e?.ADD_FORM||this.editForm||e?.EDIT_FORM}getEditFormConfig(e){return this.editForm||e?.EDIT_FORM||this.addForm||e?.ADD_FORM}getFormDialogConfig(e){return{...e?.FORM_DIALOG_CONFIG,...this.formDialogConfig}}renderTemplateString(e,t){return e?D.render(e,t):""}async onActionRefresh(e,t){await this.refresh()}async onActionApplySearch(e,t){const s=t.value.trim();this.collection&&(this.setFilter("search",s),this.collection.params.start=0,this.collection.restEnabled?await this.collection.fetch():await this.render()),this.updateFilterPills(),this.emit("list:search",{searchTerm:s}),this.emit("params-changed")}async onActionClearSearch(e,t){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(){if(!this.element)return;this.element.querySelectorAll('input[type="search"][data-filter="search"]').forEach(t=>{t.addEventListener("input",s=>{s.target.value===""&&this.getActiveFilters().search&&this.onActionClearSearch(s,s.target)})})}updateFilterPills(){const e=this.element?.querySelector('[data-container="filter-pills"]');e&&(e.innerHTML=this.buildActivePills())}updateSearchInputs(e){const t=this.element?.querySelectorAll('[data-filter="search"]');t&&t.forEach(s=>{s.value=e||""})}renderPagination(){const e=this.element.querySelector('[data-container="pagination"]');if(!e||!this.collection)return;const t=this.collection.meta?.count||this.collection.length(),s=this.collection.params?.size||10,i=this.collection.params?.start||0,r=Math.floor(i/s)+1,n=Math.ceil(t/s);if(n<=1){e.innerHTML="";return}const a=r>1?r-1:n,o=r<n?r+1:1,l=[];l.push(`
1584
+ `}_initCollection(e){if(!e){console.log("Collection not provided");return}if(e instanceof le)this.setCollection(e);else if(typeof e=="function"){const t=new e;this.setCollection(t)}else if(Array.isArray(e)){const t=new le(e);this.setCollection(t)}}_normalizeDayRangeFilter(e){if(!e)return null;const t={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 e===!0?t:{...t,...e}}_dayRangeDays(e){const t=/^(\d+)d$/.exec(String(e||""));return t?parseInt(t[1],10):null}_seedDayRangeParams(){if(!this.dayRangeFilter||!this.collection)return;const e=this._dayRangeDays(this.dayRangeFilter.value);if(e==null)return;const t=Math.floor(Date.now()/1e3)-e*86400;this.collection.params[`${this.dayRangeFilter.field}__gte`]=t}async _onDayRangeChange({value:e,previous:t}){const s=this.dayRangeFilter?.field||"created",i=this._dayRangeDays(e);let r={};if(i!=null&&this.collection){const n=Math.floor(Date.now()/1e3)-i*86400;this.collection.params[`${s}__gte`]=n,this.collection.params.start=0,r={[`${s}__gte`]:n}}if(this.emit("range:change",{field:s,value:e,previous:t,params:r}),this.emit("params-changed"),this.collection?.restEnabled)try{await this.collection.fetch()}catch(n){console.error("Failed to fetch day-range data:",n),await this.render()}else await this.render()}getRange(){return this.dayRangeControl?.getValue()??null}setRange(e,{silent:t=!1}={}){if(!this.dayRangeControl)return!1;const s=this.dayRangeControl.getValue();return this.dayRangeControl.setValue(e,{silent:!0})?(t||this._onDayRangeChange({value:e,previous:s}),!0):!1}setCollection(e){return this.collection===e?this:(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=e,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.loading=!0:this._buildItems()),this)}async _renderChildren(){await super._renderChildren();const e=this.getChildElement("items");if(!e)return;const t=[];if(this._renderOrder.length>0)for(const s of this._renderOrder)e.appendChild(s.view.element),t.push(Promise.resolve(s.view.render(!1)).catch(()=>{}));else this.forEachItem(s=>{e.appendChild(s.element),t.push(Promise.resolve(s.render(!1)).catch(()=>{}))});await Promise.all(t)}_buildItems(){if(this._clearItems(),!this.collection||this.collection.isEmpty()){this.isEmpty=!0,this.emit("list:empty");return}this.isEmpty=!1,this.collection.forEach((e,t)=>{this._createItemView(e,t)}),this._applyPersistedSelections(),this._buildGroupHeaders(),this.emit("list:loaded",{count:this.collection.length()}),this.isMounted()&&this.render()}_buildGroupHeaders(){if(this.groupHeaderViews.forEach(i=>this.removeChild(i.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,!this.groupBy||!this.collection||this.collection.isEmpty())return;const e=typeof this.groupBy=="function"?this.groupBy:i=>i.get(this.groupBy);let t,s=!1;this.collection.forEach((i,r)=>{const n=this.itemViews.get(i.id);if(!n)return;let a;try{a=e(i)}catch(o){console.warn("ListView: groupBy resolver threw — treating as ungrouped tail",o),a=null}if(a&&(!s||a!==t)){const o=this._createGroupHeaderView(i,a,r);this._renderOrder.push({type:"header",view:o}),t=a,s=!0}this._renderOrder.push({type:"item",view:n})})}_rebuildGroupHeaders(){this._buildGroupHeaders()}_createGroupHeaderView(e,t,s){const i=this.groupHeaderLabel?this.groupHeaderLabel(t):t,r=new this.groupHeaderClass({template:this.groupHeaderTemplate||this._defaultGroupHeaderTemplate(),model:e,key:i,index:s,...this._groupHeaderViewOptions(e,t,s)});return this.groupHeaderViews.set(r.id,r),r}_groupHeaderViewOptions(e,t,s){return{className:`list-group-header list-group-header--${this.groupHeaderStyle}`}}_defaultGroupHeaderTemplate(){return"{{key}}"}_createItemView(e,t){if(this.itemViews.has(e.id))return this.itemViews.get(e.id);const s=new this.itemClass({model:e,index:t,listView:this,template:this.itemTemplate,clickable:this.clickable});return this.itemViews.set(e.id,s),this._wireItemViewListeners(s),s}_wireItemViewListeners(e){e.on("item:select",this._onItemSelect.bind(this)),e.on("item:deselect",this._onItemDeselect.bind(this)),e.on("item:click",t=>{t.action==="row-click"&&(this.emit("row:click",t),this._dispatchRowClick(t))}),e.on("row:click",t=>{this._dispatchRowClick(t)}),e.on("row:view",this._onRowView.bind(this)),e.on("row:edit",this._onRowEdit.bind(this)),e.on("row:delete",this._onRowDelete.bind(this))}_dispatchRowClick(e){if(typeof this.options.onRowClick=="function")return this.options.onRowClick(e.model,e.event);if(typeof this.clickAction=="function")return this.clickAction(e.model,e.event);if(this.onItemClick)return this.onItemClick(e.model,e.event);if(this.clickAction==="view")return this._onRowView(e);if(this.clickAction==="edit")return this._onRowEdit(e);this.clickAction==="select"&&(this.selectedItems.has(e.model.id)?this.deselectItem(e.model.id):this.selectItem(e.model.id))}_applyPersistedSelections(){!this.persistSelection||this.selectedItems.size===0||this.itemViews.forEach((e,t)=>{this.selectedItems.has(t)&&!e.selected&&(e.selected=!0,e.element&&e.addClass("selected"))})}_clearItems(){this.forEachItem(e=>{this.removeChild(e.id)}),this.itemViews.clear(),this.groupHeaderViews.forEach(e=>this.removeChild(e.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,this.persistSelection||this.selectedItems.clear()}_onModelsAdded(e){const{models:t}=e;t.forEach(s=>{const i=this.collection.models.indexOf(s);this._createItemView(s,i)}),this._applyPersistedSelections(),this.groupBy&&this._rebuildGroupHeaders(),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render()}_onModelsRemoved(e){const{models:t}=e;t.forEach(s=>{const i=this.itemViews.get(s.id);i&&(this.removeChild(i.id),this.itemViews.delete(s.id),this.selectedItems.delete(s.id))}),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render(),this.isEmpty&&this.emit("list:empty")}_onCollectionReset(e){this._buildItems()}_onFetchStart(){this.loading=!0,!this.loadingMore&&this.isMounted()&&this.render()}_onFetchEnd(){this.loading=!1,!this.loadingMore&&this.isMounted()&&this.render()}_onItemSelect(e){const{model:t,item:s}=e;if(this.selectionMode==="none"){s.deselect();return}this.selectionMode==="single"&&(this.itemViews.forEach((i,r)=>{r!==t.id&&i.selected&&i.deselect()}),this.selectedItems.clear()),this.selectedItems.add(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:s,model:t})}_onItemDeselect(e){const{model:t}=e;this.selectedItems.delete(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:e.item,model:t})}getSelectedItems(){const e=[];return this.selectedItems.forEach(t=>{const s=this.itemViews.get(t);s&&e.push({view:s,model:s.model,data:s.model?.toJSON?s.model.toJSON():s.model})}),e}forEachItem(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");let s=0;return this.itemViews.forEach(i=>{e.call(t,i,i.model,s++)}),this}clearSelection(){this.forEachItem(e=>{e.selected&&e.deselect()}),this.selectedItems.clear(),this.emit("selection:change",{selected:[]})}selectItem(e){const t=this.itemViews.get(e);return t&&t.select(),this}deselectItem(e){const t=this.itemViews.get(e);return t&&t.deselect(),this}setItemTemplate(e,t=!1){return this.itemTemplate=e,t&&this.itemViews.size>0&&this.forEachItem(s=>{s.setTemplate(e),s.isMounted()&&s.render()}),this}async refresh(){if(this.collection&&this.collection.restEnabled)return await this.collection.fetch();this._buildItems()}_stripeClassFor(e){if(!this.rowStripe||!e)return null;let t;try{t=this.rowStripe(e)}catch(s){return console.warn("ListView: rowStripe callback threw — treating as no stripe",s),null}return t==null||t===""||typeof t!="string"?null:he.ROW_STRIPE_TOKENS.includes(t)?`list-row-stripe-${t}`:t}_applyRowStripe(e){if(!e||!e.element)return;const t=e.element.classList;for(const i of Array.from(t))i.startsWith("list-row-stripe")&&t.remove(i);const s=this._stripeClassFor(e.model);if(s)try{t.add(s)}catch(i){console.warn("ListView: rowStripe returned an invalid class name, skipping",s,i)}}refreshStripes(){return this.rowStripe?(this.forEachItem(e=>this._applyRowStripe(e)),this):this}async _onRowView(e){if(this.emit("row:view",e),this.options.onItemView){await this.options.onItemView(e.model,e.event);return}if(this.fetchOnView)try{w.loading(),await e.model.fetch()}catch(s){w.hideLoading(!0),w.showError(s?.data?.error||s?.message||"Failed to load item details");return}finally{w.hideLoading(!0)}const t=this.getItemViewClass(e.model);if(t){const s=new t({model:e.model,collection:this.collection});await w.dialog({header:!1,body:s,size:"lg",centered:!1,...this.getFormDialogConfig(this.getModelClass(e.model)),...t.DIALOG_OPTIONS,...this.viewDialogOptions})}else await w.data({title:`View ${this.getModelName(e.model)} #${e.model.id}`,model:e.model})}async _onRowEdit(e){if(this.emit("row:edit",e),this.options.onItemEdit){await this.options.onItemEdit(e.model,e.event);return}const t=this.getModelClass(e.model);let s=this.getEditFormConfig(t);if(s){s.fields||(s={title:`Edit ${this.getModelName(e.model)}`,fields:s});const i=await w.modelForm({model:e.model,...s,...this.getFormDialogConfig(t)});if(!i)return;if(!i.success||!i?.result?.data.status){w.showError(i?.result?.data?.error||i?.result?.message||"An error occurred");return}}else{const i=await w.dialog({title:`Edit ${this.getModelName(e.model)} #${e.model.id}`,body:new ee({model:e.model,fields:this.options.formFields||[]})});if(i){const r=await e.model.save(i);if(!r.data?.status){w.showError(r.data.error||"An error occurred");return}await this.refresh()}}}async _onRowDelete(e){if(this.emit("row:delete",e),this.options.onItemDelete){await this.options.onItemDelete(e.model,e.event);return}const t=this.getModelClass(e.model),s=this.deleteTemplate||t?.DELETE_TEMPLATE||'Are you sure you want to delete this {{name||"item"}}?',i=this.renderTemplateString(s,e.model);await w.confirm({message:i||"Are you sure you want to delete this item?",title:"Confirm Delete",confirmText:"Delete",confirmClass:"btn-danger"})&&(await e.model.destroy(),this.collection?.restEnabled?this.collection.fetch():this._buildItems())}async onActionAdd(e,t){if(this.options.onAdd){this.emit("list:add",{event:e}),await this.options.onAdd(e);return}this.emit("list:add",{event:e});const s=this.getModelClass();if(!s){console.warn("Cannot determine Model class for add operation");return}let i=this.getAddFormConfig(s);if(i){const r=new s;i.fields||(i={title:`Add ${this.getModelName()}`,fields:i});const n=await w.form({model:r,...i,...this.getFormDialogConfig(s)});if(n){this.options.addRequiresActiveGroup&&(n.group=this.getApp().activeGroup.id),this.options.addRequiresActiveUser&&(n.user=this.getApp().activeUser.id),this.options.addFormDefaults&&Object.assign(n,this.options.addFormDefaults);const a=await r.save(n);if(!a?.data.status){w.showError(a?.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}else{const r=new s,n=await w.dialog({title:`Add ${this.getModelName()}`,body:new ee({model:r,fields:this.options.formFields||[]})});if(n){const a=await r.save(n);if(!a?.data.status){w.showError(a.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}}async onActionExport(e,t){const s=t.getAttribute("data-format")||"json";this.emit("list:export",{format:s,source:this.exportSource,event:e}),this.exportSource==="remote"?this.collection?await this.collection.download(s):console.warn("ListView: Cannot export from remote without a collection."):this.options.onExport?await this.options.onExport(this.collection?.toJSON()||[],s):console.warn("ListView: onExport handler not implemented for local export.")}getModelClass(e){return this.collection?.ModelClass?this.collection.ModelClass:this.collection?.model?this.collection.model:e?.constructor?e.constructor:null}getModelName(e){const t=this.getModelClass(e);return t&&(t.MODEL_NAME||t.name.replace(/Model$/,""))||"Item"}getItemViewClass(e){if(this.itemView)return this.itemView;const t=this.getModelClass(e);return t?.VIEW_CLASS?t.VIEW_CLASS:null}getAddFormConfig(e){return this.addForm||e?.ADD_FORM||this.editForm||e?.EDIT_FORM}getEditFormConfig(e){return this.editForm||e?.EDIT_FORM||this.addForm||e?.ADD_FORM}getFormDialogConfig(e){return{...e?.FORM_DIALOG_CONFIG,...this.formDialogConfig}}renderTemplateString(e,t){return e?D.render(e,t):""}async onActionRefresh(e,t){await this.refresh()}async onActionApplySearch(e,t){const s=t.value.trim();this.collection&&(this.setFilter("search",s),this.collection.params.start=0,this.collection.restEnabled?await this.collection.fetch():await this.render()),this.updateFilterPills(),this.emit("list:search",{searchTerm:s}),this.emit("params-changed")}async onActionClearSearch(e,t){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(){if(!this.element)return;this.element.querySelectorAll('input[type="search"][data-filter="search"]').forEach(t=>{t.addEventListener("input",s=>{s.target.value===""&&this.getActiveFilters().search&&this.onActionClearSearch(s,s.target)})})}updateFilterPills(){const e=this.element?.querySelector('[data-container="filter-pills"]');e&&(e.innerHTML=this.buildActivePills())}updateSearchInputs(e){const t=this.element?.querySelectorAll('[data-filter="search"]');t&&t.forEach(s=>{s.value=e||""})}renderPagination(){const e=this.element.querySelector('[data-container="pagination"]');if(!e||!this.collection)return;const t=this.collection.meta?.count||this.collection.length(),s=this.collection.params?.size||10,i=this.collection.params?.start||0,r=Math.floor(i/s)+1,n=Math.ceil(t/s);if(n<=1){e.innerHTML="";return}const a=r>1?r-1:n,o=r<n?r+1:1,l=[];l.push(`
1585
1585
  <li class="page-item">
1586
1586
  <a class="page-link" href="#" data-action="page" data-page="${a}">
1587
1587
  <i class="bi bi-chevron-left"></i>