@ngxviewbuilder/runtime 0.12.1 → 0.12.2

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 (47) hide show
  1. package/fesm2022/{ngxviewbuilder-runtime-autocomplete-element-D1-b60Yg.mjs → ngxviewbuilder-runtime-autocomplete-element-DWbMobho.mjs} +1 -1
  2. package/fesm2022/{ngxviewbuilder-runtime-avatar-element-BZGgAqHX.mjs → ngxviewbuilder-runtime-avatar-element-98vFX6ZL.mjs} +1 -1
  3. package/fesm2022/{ngxviewbuilder-runtime-badge-element-DwLNvH9z.mjs → ngxviewbuilder-runtime-badge-element-WdHbUp_X.mjs} +1 -1
  4. package/fesm2022/{ngxviewbuilder-runtime-breadcrumbs-element-lBOlvfwd.mjs → ngxviewbuilder-runtime-breadcrumbs-element-qlHbgWfh.mjs} +1 -1
  5. package/fesm2022/{ngxviewbuilder-runtime-button-element-m24BQTuL.mjs → ngxviewbuilder-runtime-button-element-BWI56rGB.mjs} +1 -1
  6. package/fesm2022/{ngxviewbuilder-runtime-chart-element-BSWuWpXQ.mjs → ngxviewbuilder-runtime-chart-element-wN98hSa2.mjs} +1 -1
  7. package/fesm2022/{ngxviewbuilder-runtime-checkbox-element-CuDort0j.mjs → ngxviewbuilder-runtime-checkbox-element-yAUJgMY7.mjs} +1 -1
  8. package/fesm2022/{ngxviewbuilder-runtime-column-q9jO7OA7.mjs → ngxviewbuilder-runtime-column-CEOo23I_.mjs} +1 -1
  9. package/fesm2022/{ngxviewbuilder-runtime-custom-html-element-B2TQNPbK.mjs → ngxviewbuilder-runtime-custom-html-element-D7ezjkGw.mjs} +1 -1
  10. package/fesm2022/{ngxviewbuilder-runtime-date-range-element-DYtVuNvd.mjs → ngxviewbuilder-runtime-date-range-element-kRoWWvXf.mjs} +1 -1
  11. package/fesm2022/{ngxviewbuilder-runtime-datepicker-element-Dx9ryU_V.mjs → ngxviewbuilder-runtime-datepicker-element-Co2_JHM2.mjs} +1 -1
  12. package/fesm2022/{ngxviewbuilder-runtime-divider-element-D4828e5R.mjs → ngxviewbuilder-runtime-divider-element-Bit-YRpc.mjs} +1 -1
  13. package/fesm2022/{ngxviewbuilder-runtime-element-wrapper-BUzRnWUH.mjs → ngxviewbuilder-runtime-element-wrapper-D0lfZvuW.mjs} +1 -1
  14. package/fesm2022/{ngxviewbuilder-runtime-file-upload-element-Bx_JJxsl.mjs → ngxviewbuilder-runtime-file-upload-element-B1sGgTAJ.mjs} +1 -1
  15. package/fesm2022/{ngxviewbuilder-runtime-icon-element-xkaer6fW.mjs → ngxviewbuilder-runtime-icon-element-BBV3IriU.mjs} +1 -1
  16. package/fesm2022/{ngxviewbuilder-runtime-iframe-element-DG-YEOXe.mjs → ngxviewbuilder-runtime-iframe-element-DAKlSTTJ.mjs} +1 -1
  17. package/fesm2022/{ngxviewbuilder-runtime-image-element-sl9NYRt4.mjs → ngxviewbuilder-runtime-image-element-Co9eNt6D.mjs} +1 -1
  18. package/fesm2022/{ngxviewbuilder-runtime-list-box-element-BslR4TlH.mjs → ngxviewbuilder-runtime-list-box-element-BkqVfq4H.mjs} +1 -1
  19. package/fesm2022/{ngxviewbuilder-runtime-list-grid-element-vbn5afuD.mjs → ngxviewbuilder-runtime-list-grid-element-BsVooLf9.mjs} +1 -1
  20. package/fesm2022/{ngxviewbuilder-runtime-message-card-element-DV1boKqd.mjs → ngxviewbuilder-runtime-message-card-element-DOlB-FAw.mjs} +1 -1
  21. package/fesm2022/{ngxviewbuilder-runtime-multi-select-element-DO_dk2mB.mjs → ngxviewbuilder-runtime-multi-select-element-5YHKOX69.mjs} +1 -1
  22. package/fesm2022/{ngxviewbuilder-runtime-number-element-BZouLH-5.mjs → ngxviewbuilder-runtime-number-element-MNO3T8kR.mjs} +1 -1
  23. package/fesm2022/{ngxviewbuilder-runtime-number-stepper-element-WzMSnzXR.mjs → ngxviewbuilder-runtime-number-stepper-element-Jl6DZNAb.mjs} +1 -1
  24. package/fesm2022/{ngxviewbuilder-runtime-nvb-select-xpsQ0a-_.mjs → ngxviewbuilder-runtime-nvb-select-DuPHFQk6.mjs} +1 -1
  25. package/fesm2022/{ngxviewbuilder-runtime-page-title-element-BgA2xImq.mjs → ngxviewbuilder-runtime-page-title-element-BdfBrnaW.mjs} +1 -1
  26. package/fesm2022/{ngxviewbuilder-runtime-phone-input-element-wJDjqRGH.mjs → ngxviewbuilder-runtime-phone-input-element-BDZkscMD.mjs} +1 -1
  27. package/fesm2022/{ngxviewbuilder-runtime-progress-bar-element-Bdr0kdSH.mjs → ngxviewbuilder-runtime-progress-bar-element-Dg7Y6-jq.mjs} +1 -1
  28. package/fesm2022/{ngxviewbuilder-runtime-radio-element-KF9kHkJV.mjs → ngxviewbuilder-runtime-radio-element-xscwN_Hs.mjs} +1 -1
  29. package/fesm2022/{ngxviewbuilder-runtime-rich-text-element-CGJRHzNG.mjs → ngxviewbuilder-runtime-rich-text-element-DAl3vSxG.mjs} +1 -1
  30. package/fesm2022/{ngxviewbuilder-runtime-router-outlet-element-DcIc0_OQ.mjs → ngxviewbuilder-runtime-router-outlet-element-BpGv-kkh.mjs} +1 -1
  31. package/fesm2022/{ngxviewbuilder-runtime-select-button-element-DM0If-wo.mjs → ngxviewbuilder-runtime-select-button-element-BPH_N-fd.mjs} +1 -1
  32. package/fesm2022/{ngxviewbuilder-runtime-select-element-kOJtgDmJ.mjs → ngxviewbuilder-runtime-select-element-B_FOlIzR.mjs} +1 -1
  33. package/fesm2022/{ngxviewbuilder-runtime-signature-pad-element-BDSkjOm4.mjs → ngxviewbuilder-runtime-signature-pad-element-BxZMh4-H.mjs} +1 -1
  34. package/fesm2022/{ngxviewbuilder-runtime-single-checkbox-element-CCLuAW3g.mjs → ngxviewbuilder-runtime-single-checkbox-element-DZiHDP6i.mjs} +1 -1
  35. package/fesm2022/{ngxviewbuilder-runtime-slider-element-DA0m8geD.mjs → ngxviewbuilder-runtime-slider-element-NBbgW-1w.mjs} +1 -1
  36. package/fesm2022/{ngxviewbuilder-runtime-spacer-element-D4KgGuYS.mjs → ngxviewbuilder-runtime-spacer-element-BGJ-ObOf.mjs} +1 -1
  37. package/fesm2022/{ngxviewbuilder-runtime-stats-card-element-Bwt5GL25.mjs → ngxviewbuilder-runtime-stats-card-element-DUxzXyTC.mjs} +1 -1
  38. package/fesm2022/{ngxviewbuilder-runtime-table-element-C0Pcf-Do.mjs → ngxviewbuilder-runtime-table-element-yvDWlU-z.mjs} +1 -1
  39. package/fesm2022/{ngxviewbuilder-runtime-text-element-CVntVjD5.mjs → ngxviewbuilder-runtime-text-element-C9W3pPu7.mjs} +1 -1
  40. package/fesm2022/{ngxviewbuilder-runtime-textarea-element-DkNUQ3Xk.mjs → ngxviewbuilder-runtime-textarea-element-55rqT93w.mjs} +1 -1
  41. package/fesm2022/{ngxviewbuilder-runtime-time-picker-element-CKVMQjZ2.mjs → ngxviewbuilder-runtime-time-picker-element-C1p0lG_4.mjs} +1 -1
  42. package/fesm2022/{ngxviewbuilder-runtime-toast-element-C5TyVsu-.mjs → ngxviewbuilder-runtime-toast-element-Dc8tFqFS.mjs} +1 -1
  43. package/fesm2022/{ngxviewbuilder-runtime-toggle-switch-element-NcB3kYta.mjs → ngxviewbuilder-runtime-toggle-switch-element-DEmC69ye.mjs} +1 -1
  44. package/fesm2022/{ngxviewbuilder-runtime-video-element-D_5W6_Rh.mjs → ngxviewbuilder-runtime-video-element-COR0eePU.mjs} +1 -1
  45. package/fesm2022/ngxviewbuilder-runtime.mjs +1 -1
  46. package/package.json +1 -1
  47. package/types/ngxviewbuilder-runtime.d.ts +6 -0
@@ -1 +1 @@
1
- import{t as S}from"./ngxviewbuilder-runtime-rolldown-runtime-DpJrqANO.mjs";import{c as k,g as I,n as y,on as P,t as w}from"./ngxviewbuilder-runtime-dynamic-text.pipe-BUJ4fCqt.mjs";import{ht as D,r as M,rt as z,s as N,t as _}from"./ngxviewbuilder-runtime-element-wrapper-BUzRnWUH.mjs";import*as p from"@angular/core";import{ChangeDetectionStrategy as R,ChangeDetectorRef as T,Component as U,ViewChild as C,inject as c,input as E,signal as u}from"@angular/core";import{NgClass as x}from"@angular/common";import{get as B}from"lodash-es";import{firstValueFrom as b}from"rxjs";import{DomSanitizer as A}from"@angular/platform-browser";var O=S({FileUploadElement:()=>h});var h=class g{model=E.required(...ngDevMode?[{debugName:"model"}]:[]);tid=M(this.model,"nvb-file-upload","file-upload");fileInput;isDragOver=u(false,...ngDevMode?[{debugName:"isDragOver"}]:[]);requestInFlight=u(false,...ngDevMode?[{debugName:"requestInFlight"}]:[]);previewItems=u([],...ngDevMode?[{debugName:"previewItems"}]:[]);previewOpen=u(false,...ngDevMode?[{debugName:"previewOpen"}]:[]);previewUrl=u("",...ngDevMode?[{debugName:"previewUrl"}]:[]);previewKind=u(null,...ngDevMode?[{debugName:"previewKind"}]:[]);previewName=u("",...ngDevMode?[{debugName:"previewName"}]:[]);previewFrameUrl=u(null,...ngDevMode?[{debugName:"previewFrameUrl"}]:[]);elementActionService=c(z);dataSourceService=c(k);dataService=c(P);eventService=c(I);ngxViewBuilderApiService=c(N);cdr=c(T);sanitizer=c(A);markupSecurityService=c(D);previewObjectUrl=null;activePreviewResource=null;onPropertyChangedHandler=e=>{const t=String(this.model()?.dataPath??"").trim();if(!t)return;if(String(e?.payload?.elementNameOrPath??"").trim()!==t)return;this.cdr.markForCheck()};ngOnInit(){this.syncPreviewFromModelValue();this.eventService.afterPropertyChanged.add(this.onPropertyChangedHandler)}ngOnDestroy(){this.closePreview();this.eventService.afterPropertyChanged.remove(this.onPropertyChangedHandler)}openPicker(){if(this.isInteractionLocked())return;this.fileInput?.nativeElement.click()}onFileInputChange(e){if(this.isInteractionLocked())return;const t=e.target;const i=t?.files?Array.from(t.files):[];this.applyFiles(i);if(t)t.value=""}onDragOver(e){if(this.isInteractionLocked())return;e.preventDefault();this.isDragOver.set(true)}onDragLeave(e){if(this.isInteractionLocked())return;e.preventDefault();this.isDragOver.set(false)}onDrop(e){if(this.isInteractionLocked())return;e.preventDefault();this.isDragOver.set(false);const t=e.dataTransfer?.files?Array.from(e.dataTransfer.files):[];this.applyFiles(t)}onEntryActivate(e,t){t.preventDefault();t.stopPropagation();if(this.canPreviewEntry(e)){this.previewFileAsync(e);return}if(this.canDownload(e))this.downloadFileAsync(e)}removeFile(e,t){t.preventDefault();t.stopPropagation();if(this.isInteractionLocked())return;this.removeFileAsync(e)}downloadFile(e,t){t.preventDefault();t.stopPropagation();if(this.isInteractionLocked())return;this.downloadFileAsync(e)}previewFile(e,t){t.preventDefault();t.stopPropagation();if(this.isInteractionLocked())return;this.previewFileAsync(e)}clearFiles(e){e?.preventDefault();e?.stopPropagation();if(this.isInteractionLocked())return;this.closePreview();this.previewItems.set([]);this.model().setFiles([]);this.emitChangeActions()}closePreview(e){e?.preventDefault();e?.stopPropagation();this.previewOpen.set(false);this.previewUrl.set("");this.previewKind.set(null);this.previewName.set("");this.previewFrameUrl.set(null);this.activePreviewResource=null;if(this.previewObjectUrl){URL.revokeObjectURL(this.previewObjectUrl);this.previewObjectUrl=null}}formatSize(e){const t=Number(e);if(!Number.isFinite(t)||t<0)return"0 B";if(t<1024)return`${t} B`;if(t<1048576)return`${(t/1024).toFixed(1)} KB`;return`${(t/1048576).toFixed(1)} MB`}resolveDisplayMode(){const e=String(this.model().displayMode??"modern").trim().toLowerCase();if(e==="compact"||e==="grid")return e;return"modern"}resolveStatusText(e){if(e.status==="pending")return this.isBase64Mode()?"Reading file...":"Uploading...";if(e.status==="error")return e.errorMessage||"Upload failed";return""}canOpenEntry(e){return this.canPreviewEntry(e)||this.canDownload(e)}canDownload(e){if(e.localFile||e.meta.base64)return true;if(!String(this.model().downloadDataSourceName??"").trim())return false;return Boolean(this.resolveMetaKey(e.meta))}canPreviewEntry(e){if(!this.model().showPreview)return false;return this.resolvePreviewKind(e.meta)!==null&&this.canDownload(e)}async applyFiles(e){if(this.isInteractionLocked())return;const t=Boolean(this.model().multiple);const i=t?[...this.previewItems()]:[];const n=this.normalizeFiles(e,i.length);if(n.length===0)return;const r=t?[...i]:[];const o=this.isBase64Mode();const a=!o&&String(this.model().uploadDataSourceName??"").trim().length>0;const l=n.map((s,v)=>this.createPreviewEntry(this.createLocalMeta(s),s,a||o?"pending":"ready","",`${Date.now()}-${v}-${s.name}`));r.push(...l);this.commitPreviewEntries(r);this.emitChangeActions();this.ngxViewBuilderApiService.notifyFileUploadFilesAdded({elementName:this.model().name,elementDataPath:this.model().dataPath,element:this.model(),files:r.map(s=>s.meta),addedFiles:l.map(s=>s.meta)});if(o){await this.encodeEntries(l);return}if(!a)return;this.requestInFlight.set(true);let d=false;try{for(const s of l){const v=s.localFile;if(!v)continue;try{const m=await this.uploadFileIfNeeded(v);const f=this.updatePreviewEntry(s.id,F=>({...F,meta:m,iconName:this.resolveFileTypeIcon(m),status:"ready",errorMessage:""}));d=d||f}catch{const m=this.updatePreviewEntry(s.id,f=>({...f,status:"error",errorMessage:"Upload failed"}));d=d||m}}}finally{this.requestInFlight.set(false)}if(d)this.emitChangeActions()}async encodeEntries(e){let t=false;for(const i of e){const n=i.localFile;if(!n)continue;try{const r=await this.readFileAsBase64(n);t=this.updatePreviewEntry(i.id,o=>({...o,meta:{...o.meta,base64:r},status:"ready",errorMessage:""}))||t}catch{t=this.updatePreviewEntry(i.id,r=>({...r,status:"error",errorMessage:"Could not read the file"}))||t}}if(t)this.emitChangeActions()}readFileAsBase64(e){return new Promise((t,i)=>{const n=new FileReader;n.onload=()=>{const r=String(n.result??"");const o=r.indexOf(",");t(o>=0?r.slice(o+1):r)};n.onerror=()=>i(n.error??new Error("Could not read the file."));n.readAsDataURL(e)})}isBase64Mode(){return this.model().storageMode!=="server"}async removeFileAsync(e){const t=[...this.previewItems()];if(e<0||e>=t.length)return;const i=t[e];const n=this.resolveMetaKey(i.meta);const r=String(this.model().deleteDataSourceName??"").trim();if(r&&n){if(!await this.deleteFileFromServer(i.meta,r,n))return}t.splice(e,1);this.previewItems.set(t);this.model().setFiles(t.map(o=>o.meta));if(this.previewOpen()&&this.previewName()===this.resolveMetaName(i.meta))this.closePreview();this.emitChangeActions();this.ngxViewBuilderApiService.notifyFileUploadFileRemoved({elementName:this.model().name,elementDataPath:this.model().dataPath,element:this.model(),files:t.map(o=>o.meta),removedFile:i.meta,removedIndex:e})}async downloadFileAsync(e){const t=await this.resolveEntryResource(e);if(!t)return;this.downloadResource(t)}async previewFileAsync(e){const t=this.resolvePreviewKind(e.meta);if(!this.model().showPreview||!t){await this.downloadFileAsync(e);return}const i=await this.resolveEntryResource(e);if(!i)return;this.openPreview(t,i)}async resolveEntryResource(e){const t=this.resolveMetaKey(e.meta);if(t){const i=await this.fetchRemoteEntryResource(e,t);if(i)return i}if(e.localFile)return this.createResourceFromBlob(e.localFile,this.resolveMetaName(e.meta),this.resolveMetaType(e.meta)||e.localFile.type);if(e.meta.base64){const i=this.decodeBase64(e.meta.base64,this.resolveMetaType(e.meta));if(i)return this.createResourceFromBlob(i,this.resolveMetaName(e.meta),this.resolveMetaType(e.meta))}if(e.meta.raw){const i=await this.resolveResourceFromUnknown(e.meta.raw,this.resolveMetaName(e.meta),this.resolveMetaType(e.meta));if(i)return i}return null}async fetchRemoteEntryResource(e,t){const i=String(this.model().downloadDataSourceName??"").trim();if(!i)return null;const n=this.dataSourceService.getSource(i);if(!n)return null;const r=this.buildRuntimeContext(e.meta,t,e.localFile??void 0);const o=this.resolveSourceMethod(n,"GET");const a=this.resolveSourceUrl(n,r);if(!a)return null;this.requestInFlight.set(true);try{const l=o==="GET"?void 0:this.resolveSourcePayload(n,r,{[this.model().fileKeyField]:t});const d=await b(this.dataSourceService.request(o,a,l,{responseType:"blob",observeResponse:true}));return await this.resolveHttpDownloadResponse(d,this.resolveMetaName(e.meta),this.resolveMetaType(e.meta))}catch{return null}finally{this.requestInFlight.set(false)}}async uploadFileIfNeeded(e){const t=String(this.model().uploadDataSourceName??"").trim();if(!t)return this.createLocalMeta(e);const i=this.dataSourceService.getSource(t);if(!i)return this.createLocalMeta(e);const n=this.buildRuntimeContext(this.createLocalMeta(e),void 0,e);const r=this.resolveSourceMethod(i,"POST");const o=this.resolveSourceUrl(i,n);if(!o)return this.createLocalMeta(e);const a=new FormData;const l=String(this.model().uploadFormFieldName??"file").trim()||"file";a.append(l,e,e.name);const d=await b(this.dataSourceService.request(r,o,a));const s=this.extractFirstRecord(d);if(s)return this.createMetaFromRecord(s,e);return this.createLocalMeta(e)}async deleteFileFromServer(e,t,i){const n=this.dataSourceService.getSource(t);if(!n)return false;const r=this.buildRuntimeContext(e,i);const o=this.resolveSourceMethod(n,"DELETE");const a=this.resolveSourceUrl(n,r);if(!a)return false;const l=o==="GET"?void 0:this.resolveSourcePayload(n,r,{[this.model().fileKeyField]:i,fileKey:i,filKey:i,key:i,fil_key:i,id:i,fileId:i,uuid:i});this.requestInFlight.set(true);try{await b(this.dataSourceService.request(o,a,l));return true}catch{return false}finally{this.requestInFlight.set(false)}}normalizeFiles(e,t=0){if(!Array.isArray(e)||e.length===0)return[];const i=Number(this.model()?.maxFiles??1);const n=Number.isFinite(i)&&i>0?Math.floor(i):1;if(!this.model().multiple)return this.filterByMaxFileSize([e[0]]);const r=Math.max(0,Math.floor(Number(t)||0));const o=Math.max(0,n-r);if(o<=0)return[];return this.filterByMaxFileSize(e).slice(0,o)}filterByMaxFileSize(e){const t=Number(this.model()["maxFileSizeMb"]);if(!Number.isFinite(t)||t<=0)return e;const i=t*1024*1024;return e.filter(n=>Number(n?.size??0)<=i)}commitPreviewEntries(e){const t=[...e];this.previewItems.set(t);this.model().setFiles(t.map(i=>i.meta))}updatePreviewEntry(e,t){let i=false;const n=this.previewItems().map(r=>{if(r.id!==e)return r;i=true;return t(r)});if(!i)return false;this.commitPreviewEntries(n);return true}syncPreviewFromModelValue(){const e=this.extractRecords(this.model().value);if(e.length===0){this.previewItems.set([]);return}this.previewItems.set(e.map((t,i)=>this.createPreviewEntry(this.createMetaFromRecord(t),null,"ready","",`saved-${i}`)))}createPreviewEntry(e,t,i,n,r){return{id:r,meta:e,iconName:this.resolveFileTypeIcon(e),status:i,localFile:t,errorMessage:n}}createLocalMeta(e){return{name:e.name,size:e.size,type:e.type,lastModified:e.lastModified}}createMetaFromRecord(e,t){const i=this.readRecordString(e,[this.model().fileNameField,"name","fileName","fil_name"])||t?.name||"file";const n=this.readRecordString(e,[this.model().fileTypeField,"type","contentType","mimeType","fil_content_type"])||t?.type||"";const r=this.readRecordNumber(e,[this.model().fileSizeField,"size","fil_size"])??Number(t?.size??0);const o=this.readRecordString(e,[this.model().fileKeyField,"fileKey","filKey","key","fil_key","id","fileId","uuid"])||void 0;const a=this.readRecordNumber(e,["lastModified"])??Number(t?.lastModified??0);const l=typeof e["base64"]==="string"?e["base64"].trim():"";return{name:i,type:n,size:Number.isFinite(r)&&r>=0?r:0,lastModified:Number.isFinite(a)&&a>=0?a:0,fileKey:o,...l?{base64:l}:{},raw:{...e}}}resolveFileTypeIcon(e){const t=String(e?.type??"").trim().toLowerCase();const i=this.resolveFileExtension(e?.name);if(t.startsWith("image/")||["jpg","jpeg","png","gif","webp","bmp","svg"].includes(i))return"image";if(t.includes("pdf")||i==="pdf")return"picture_as_pdf";if(t.includes("spreadsheet")||t.includes("excel")||t.includes("csv")||["csv","xls","xlsx","ods"].includes(i))return"table_view";if(t.includes("word")||t.includes("opendocument.text")||["doc","docx","rtf","odt"].includes(i))return"draft";if(t.startsWith("video/")||["mp4","mov","avi","mkv","webm"].includes(i))return"smart_display";if(t.includes("html")||t.includes("xml")||t.includes("json")||t.includes("javascript")||t.includes("typescript")||t.includes("css")||t.includes("text/")||["txt","json","xml","html","htm","js","ts","css","md","yml","yaml"].includes(i))return"html";if(t.includes("zip")||t.includes("compressed")||["zip","rar","7z","tar","gz"].includes(i))return"extension";return"description"}resolvePreviewKind(e){const t=String(e?.type??"").trim().toLowerCase();const i=this.resolveFileExtension(e?.name);if(t.startsWith("image/")||["jpg","jpeg","png","gif","webp","bmp","svg"].includes(i))return"image";if(t.includes("pdf")||i==="pdf")return"pdf";return null}resolveFileExtension(e){const t=String(e??"").trim().toLowerCase();if(!t)return"";const i=t.lastIndexOf(".");if(i<0||i===t.length-1)return"";return t.slice(i+1)}resolveMetaKey(e){const t=String(e?.fileKey??"").trim();if(t)return t;if(!e?.raw||typeof e.raw!=="object")return"";return this.readRecordString(e.raw,[this.model().fileKeyField,"fileKey","filKey","key","fil_key","id","fileId","uuid"])}resolveMetaName(e){return String(e?.name??"").trim()||"file"}resolveMetaType(e){return String(e?.type??"").trim()||"application/octet-stream"}buildRuntimeContext(e,t,i){const n={value:this.model().value,files:this.model().value,file:i,fileMeta:e?.raw??e,fileRow:e?.raw??e,fileName:this.resolveMetaName(e),fileType:this.resolveMetaType(e),fileSize:Number(e?.size??0),item:e?.raw??e,row:e?.raw??e};if(t){n[this.model().fileKeyField]=t;n["fileKey"]=t;n["filKey"]=t;n["fil_key"]=t;n["key"]=t;n["id"]=t;n["fileId"]=t;n["uuid"]=t}const r=String(this.model().name??"").trim();if(r)n[r]=this.model().value;return n}resolveSourceMethod(e,t){return String(e?.params?.["method"]??t).trim().toUpperCase()||t}resolveSourceUrl(e,t){const i=String(e?.params?.["url"]??"").trim();if(!i)return"";return i.replace(/\{([^}]+)\}/g,(n,r)=>{const o=this.resolveContextValue(String(r??"").trim(),t);return encodeURIComponent(this.serializeForUrl(o))})}resolveSourcePayload(e,t,i){const n=e?.params?.["body"]??e?.params?.["payload"];if(n===null||n===void 0)return i;const r=this.normalizePayloadTemplate(n);if(r===void 0)return i;return this.replacePayloadPlaceholders(r,t)}normalizePayloadTemplate(e){if(typeof e!=="string")return e;const t=e.trim();if(!t)return;if(/^\{[^{}]+\}$/.test(t))return t;if(!t.startsWith("{")&&!t.startsWith("["))return e;try{return JSON.parse(t)}catch{return e}}replacePayloadPlaceholders(e,t){if(typeof e==="string"){const i=e.match(/^\{([^}]+)\}$/);if(i){const n=String(i[1]??"").trim();return this.resolveContextValue(n,t)}return e.replace(/\{([^}]+)\}/g,(n,r)=>{const o=this.resolveContextValue(String(r??"").trim(),t);return this.serializeForUrl(o)})}if(Array.isArray(e))return e.map(i=>this.replacePayloadPlaceholders(i,t));if(e&&typeof e==="object"){const i=e;const n={};Object.keys(i).forEach(r=>{n[r]=this.replacePayloadPlaceholders(i[r],t)});return n}return e}resolveContextValue(e,t){const i=String(e??"").trim().replace(/^\{/,"").replace(/\}$/,"");if(!i)return;const n=B(t,i);if(n!==void 0)return n;return this.dataService.getValue(i)}serializeForUrl(e){if(Array.isArray(e))return e.length>0?String(e[0]??""):"";if(e===null||e===void 0)return"";return String(e)}extractFirstRecord(e){const t=this.extractRecords(e);return t.length>0?t[0]:null}extractRecords(e,t=0){if(t>4||e===null||e===void 0)return[];if(Array.isArray(e))return e.filter(r=>r&&typeof r==="object"&&!Array.isArray(r)).map(r=>r);if(!e||typeof e!=="object")return[];const i=e;const n=Object.keys(i).filter(r=>/^\d+$/.test(r));if(n.length>0)return n.sort((r,o)=>Number(r)-Number(o)).map(r=>i[r]).filter(r=>r&&typeof r==="object"&&!Array.isArray(r)).map(r=>r);for(const r of["data","items","rows","result","value"]){if(i[r]===void 0)continue;const o=this.extractRecords(i[r],t+1);if(o.length>0)return o}return[i]}readRecordString(e,t){for(const i of t){const n=String(i??"").trim();if(!n)continue;const r=e[n];if(r===null||r===void 0)continue;const o=String(r).trim();if(o)return o}return""}readRecordNumber(e,t){for(const i of t){const n=String(i??"").trim();if(!n)continue;const r=e[n];if(r===null||r===void 0||r==="")continue;const o=Number(r);if(Number.isFinite(o))return o}return null}async resolveHttpDownloadResponse(e,t,i){const n=e.body;if(!(n instanceof Blob))return null;const r=e.headers.get("content-type");const o=e.headers.get("content-disposition");const a=String(r||n.type||i||"application/octet-stream");const l=this.parseContentDispositionFileName(o)||t||"file";if(this.shouldUseBlobAsFile(a,o))return this.createResourceFromBlob(n,l,a);const d=await n.text();const s=this.parseStructuredDownloadPayload(d);const v=await this.resolveResourceFromUnknown(s,l,a);if(v)return v;return this.createResourceFromBlob(n,l,a)}shouldUseBlobAsFile(e,t){const i=String(e??"").trim().toLowerCase();if(String(t??"").trim().toLowerCase().includes("attachment"))return true;if(!i)return true;if(i.startsWith("image/")||i.includes("pdf")||i.includes("octet-stream")||i.includes("zip")||i.includes("excel")||i.includes("spreadsheet")||i.includes("msword")||i.includes("officedocument"))return true;return!(i.includes("json")||i.startsWith("text/")||i.includes("javascript")||i.includes("xml"))}parseStructuredDownloadPayload(e){const t=String(e??"").trim();if(!t)return null;if(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]"))try{return JSON.parse(t)}catch{return t}return t}async resolveResourceFromUnknown(e,t,i){if(e===null||e===void 0)return null;if(e instanceof Blob)return this.createResourceFromBlob(e,t,e.type||i);if(e instanceof ArrayBuffer)return this.createResourceFromBlob(new Blob([e],{type:i}),t,i);if(e instanceof Uint8Array)return this.createResourceFromBlob(new Blob([e.slice()],{type:i}),t,i);if(typeof e==="string")return await this.resolveResourceFromString(e,t,i);if(typeof e==="object"){const n=e;const r=this.readRecordString(n,["fileName","name",this.model().fileNameField])||t;const o=this.readRecordString(n,["contentType","type",this.model().fileTypeField])||i;const a=this.markupSecurityService.sanitizeFileUrl(this.readRecordString(n,["url","downloadUrl","href","src","previewUrl"])||"");if(a)return{fileName:r||t||"file",contentType:o||i||"application/octet-stream",sourceUrl:a,revokeOnDispose:false};const l=n["content"]??n["data"]??n["base64"]??n["blob"]??n["file"]??n["result"]??null;if(l!==null&&l!==void 0&&l!==e)return this.resolveResourceFromUnknown(l,r,o)}return null}async resolveResourceFromString(e,t,i){const n=String(e??"").trim();if(!n)return null;if(/^(https?:|blob:|data:)/i.test(n)){const a=this.markupSecurityService.sanitizeFileUrl(n);if(!a)return null;return{fileName:t||"file",contentType:i||this.resolveContentTypeFromUrl(a),sourceUrl:a,revokeOnDispose:false}}const r=this.parseStructuredDownloadPayload(n);if(r!==n)return this.resolveResourceFromUnknown(r,t,i);const o=this.createBlobFromBase64(n,i);if(o)return this.createResourceFromBlob(o,t,i||o.type);return this.createResourceFromBlob(new Blob([n],{type:i||"text/plain;charset=utf-8"}),t,i||"text/plain;charset=utf-8")}decodeBase64(e,t){try{const i=String(e??"");const n=atob(i.slice(i.indexOf(",")+1).replace(/\s+/g,""));const r=new Uint8Array(n.length);for(let o=0;o<n.length;o+=1)r[o]=n.charCodeAt(o);return new Blob([r],{type:t||"application/octet-stream"})}catch{return null}}createBlobFromBase64(e,t){const i=String(e??"").replace(/\s+/g,"");if(!this.isProbableBase64(i))return null;try{const n=atob(i);const r=new Uint8Array(n.length);for(let o=0;o<n.length;o+=1)r[o]=n.charCodeAt(o);return new Blob([r],{type:t||"application/octet-stream"})}catch{return null}}isProbableBase64(e){if(!e||e.length<16||e.length%4!==0)return false;return/^[A-Za-z0-9+/]+={0,2}$/.test(e)}resolveContentTypeFromUrl(e){const t=String(e??"").trim();if(t.startsWith("data:")){const i=t.match(/^data:([^;,]+)[;,]/i);if(i?.[1])return i[1]}return"application/octet-stream"}createResourceFromBlob(e,t,i){const n=String(i||e.type||"").trim();const r=/html|xml|svg|javascript|ecmascript/i.test(n)?"application/octet-stream":n||"application/octet-stream";const o=e.type===r?e:new Blob([e],{type:r});const a=URL.createObjectURL(o);return{fileName:t||"file",contentType:r,sourceUrl:a,revokeOnDispose:true}}openPreview(e,t){const i=this.markupSecurityService.sanitizeFileUrl(t.sourceUrl);if(!i)return;t={...t,sourceUrl:i};this.closePreview();this.previewKind.set(e);this.previewName.set(t.fileName);this.previewUrl.set(t.sourceUrl);this.previewFrameUrl.set(e==="pdf"?this.sanitizer.bypassSecurityTrustResourceUrl(t.sourceUrl):null);this.previewOpen.set(true);this.activePreviewResource=t;if(t.revokeOnDispose)this.previewObjectUrl=t.sourceUrl}downloadPreview(e){e.preventDefault();e.stopPropagation();if(!this.activePreviewResource)return;this.downloadResource(this.activePreviewResource)}downloadResource(e){this.triggerLinkDownload(e.sourceUrl,e.fileName);if(e.revokeOnDispose)setTimeout(()=>{URL.revokeObjectURL(e.sourceUrl)},1e3)}parseContentDispositionFileName(e){const t=String(e??"").trim();if(!t)return"";const i=t.match(/filename\*\s*=\s*UTF-8''([^;]+)/i);if(i?.[1])try{return decodeURIComponent(i[1].trim().replace(/^"|"$/g,""))}catch{return i[1].trim().replace(/^"|"$/g,"")}const n=t.match(/filename\s*=\s*("?)([^";]+)\1/i);return String(n?.[2]??"").trim()}triggerLinkDownload(e,t){const i=this.markupSecurityService.sanitizeFileUrl(e);if(!i)return;const n=document.createElement("a");n.href=i;n.download=t||"file";n.target="_blank";n.rel="noopener";document.body.appendChild(n);n.click();document.body.removeChild(n)}emitChangeActions(){const e={value:this.model().value,files:this.model().value,item:null,row:null};const t=String(this.model().name??"").trim();if(t)e[t]=this.model().value;this.elementActionService.runActions(this.model(),this.model().events??[],"change",e)}isInteractionLocked(){const e=this.model();if(!e)return false;if(this.requestInFlight())return true;if(Boolean(e["__pfInteractionLocked"]))return true;return Boolean(e.disabled)||Boolean(e.readOnly)}static ɵfac=p.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.2.1",ngImport:p,type:g,deps:[],target:p.ɵɵFactoryTarget.Component});static ɵcmp=p.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.2.1",type:g,isStandalone:true,selector:"file-upload-element",inputs:{model:{classPropertyName:"model",publicName:"model",isSignal:true,isRequired:true,transformFunction:null}},viewQueries:[{propertyName:"fileInput",first:true,predicate:["fileInput"],descendants:true}],ngImport:p,template:"<element-wrapper [model]=\"model()\" #fieldWrapper=\"elementWrapper\">\n <section class=\"nvb-file-upload-wrap\" [attr.data-testid]=\"tid('root')\">\n <input\n #fileInput\n [id]=\"fieldWrapper.controlId()\"\n type=\"file\"\n [accept]=\"model().accept\"\n [multiple]=\"model().multiple\"\n hidden\n [attr.aria-describedby]=\"fieldWrapper.describedByIds(fieldWrapper.partId('dropzone-hint'))\"\n [attr.aria-errormessage]=\"fieldWrapper.isInvalid() ? fieldWrapper.errorId() : null\"\n [attr.aria-invalid]=\"fieldWrapper.isInvalid() ? 'true' : null\"\n [attr.aria-required]=\"model().required ? 'true' : null\"\n [attr.data-testid]=\"tid('input')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"onFileInputChange($event)\"\n />\n\n <div\n class=\"nvb-file-upload\"\n [ngClass]=\"{\n 'nvb-file-upload--drag-over': isDragOver(),\n 'nvb-file-upload--compact': resolveDisplayMode() === 'compact',\n 'nvb-file-upload--modern': resolveDisplayMode() === 'modern',\n 'nvb-file-upload--grid': resolveDisplayMode() === 'grid',\n }\"\n (click)=\"openPicker()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-labelledby]=\"fieldWrapper.hasLabelText() ? fieldWrapper.labelId() : null\"\n [attr.aria-label]=\"\n fieldWrapper.hasLabelText() ? null : (model().dropzoneText | dynamicText: model())\n \"\n [attr.aria-describedby]=\"fieldWrapper.describedByIds(fieldWrapper.partId('dropzone-hint'))\"\n [attr.data-testid]=\"tid('dropzone')\"\n (keydown.enter)=\"openPicker()\"\n (keydown.space)=\"openPicker(); $event.preventDefault()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n >\n <span class=\"material-symbols-outlined nvb-file-upload__icon\">upload_file</span>\n <p class=\"nvb-file-upload__label\">{{ model().dropzoneText | dynamicText: model() }}</p>\n\n @if (model().accept) {\n <p class=\"nvb-file-upload__accept\">{{ model().accept }}</p>\n }\n <span [id]=\"fieldWrapper.partId('dropzone-hint')\" class=\"nvb-sr-only\">\n {{ 'files.dropzoneHint' | uiT: 'Drag files here or press Enter to choose files.' }}\n </span>\n </div>\n\n @if (previewItems().length > 0) {\n <ul\n class=\"nvb-file-upload__list\"\n [ngClass]=\"{\n 'nvb-file-upload__list--compact': resolveDisplayMode() === 'compact',\n 'nvb-file-upload__list--modern': resolveDisplayMode() === 'modern',\n 'nvb-file-upload__list--grid': resolveDisplayMode() === 'grid',\n }\"\n >\n @for (entry of previewItems(); track entry.id; let itemIndex = $index) {\n <li\n [ngClass]=\"{\n 'nvb-file-upload__list-item--pending': entry.status === 'pending',\n 'nvb-file-upload__list-item--error': entry.status === 'error',\n }\"\n >\n <button\n type=\"button\"\n class=\"nvb-file-upload__entry-main\"\n [class.nvb-file-upload__entry-main--interactive]=\"canOpenEntry(entry)\"\n [disabled]=\"!canOpenEntry(entry)\"\n [attr.aria-label]=\"entry.meta.name\"\n [attr.data-testid]=\"tid('entry', itemIndex)\"\n (click)=\"onEntryActivate(entry, $event)\"\n >\n <div class=\"nvb-file-upload__thumb\" [attr.data-file-icon]=\"entry.iconName\">\n <span class=\"material-symbols-outlined\">{{ entry.iconName }}</span>\n </div>\n\n <div class=\"nvb-file-upload__entry-content\">\n <p class=\"nvb-file-upload__entry-name\">{{ entry.meta.name }}</p>\n <p class=\"nvb-file-upload__entry-meta\">\n {{ entry.meta.type || ('files.unknownType' | uiT: 'unknown') }}\n <span>&bull;</span>\n {{ formatSize(entry.meta.size) }}\n </p>\n\n @if (resolveStatusText(entry); as statusText) {\n @if (statusText) {\n <p class=\"nvb-file-upload__entry-status\">{{ statusText | uiT: statusText }}</p>\n }\n }\n </div>\n </button>\n\n <div class=\"nvb-file-upload__entry-actions\">\n @if (canPreviewEntry(entry)) {\n <button\n type=\"button\"\n class=\"nvb-file-upload__icon-action\"\n [disabled]=\"requestInFlight()\"\n (click)=\"previewFile(entry, $event)\"\n [attr.aria-label]=\"'files.preview' | uiT: 'Preview'\"\n [attr.data-testid]=\"tid('preview', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">visibility</span>\n </button>\n }\n\n @if (canDownload(entry)) {\n <button\n type=\"button\"\n class=\"nvb-file-upload__icon-action\"\n [disabled]=\"requestInFlight()\"\n (click)=\"downloadFile(entry, $event)\"\n [attr.aria-label]=\"'files.download' | uiT: 'Download'\"\n [attr.data-testid]=\"tid('download', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">download</span>\n </button>\n }\n\n <button\n type=\"button\"\n class=\"nvb-file-upload__remove\"\n [disabled]=\"requestInFlight()\"\n (click)=\"removeFile(itemIndex, $event)\"\n [attr.aria-label]=\"'files.remove' | uiT: 'Remove'\"\n [attr.data-testid]=\"tid('remove', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </div>\n </li>\n }\n </ul>\n }\n </section>\n\n @if (previewOpen()) {\n <div\n class=\"nvb-file-upload__preview-backdrop\"\n [attr.data-testid]=\"tid('preview-backdrop')\"\n (click)=\"closePreview()\"\n >\n <div\n class=\"nvb-file-upload__preview-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"file-upload-preview-title\"\n [attr.data-testid]=\"tid('preview-dialog')\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"nvb-file-upload__preview-header\">\n <p class=\"nvb-file-upload__preview-title\" id=\"file-upload-preview-title\">\n {{ previewName() }}\n </p>\n <div class=\"nvb-file-upload__preview-header-actions\">\n <button\n type=\"button\"\n class=\"nvb-file-upload__preview-action\"\n (click)=\"downloadPreview($event)\"\n [attr.aria-label]=\"'files.download' | uiT: 'Download'\"\n [attr.data-testid]=\"tid('preview-download')\"\n >\n <span class=\"material-symbols-outlined\">download</span>\n <span>{{ 'files.download' | uiT: 'Download' }}</span>\n </button>\n <button\n type=\"button\"\n class=\"nvb-file-upload__preview-close\"\n (click)=\"closePreview($event)\"\n [attr.aria-label]=\"'files.closePreview' | uiT: 'Close preview'\"\n [attr.data-testid]=\"tid('preview-close')\"\n >\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </div>\n </div>\n\n <div class=\"nvb-file-upload__preview-body\">\n @if (previewKind() === 'image') {\n <img [src]=\"previewUrl()\" [alt]=\"previewName()\" />\n } @else if (previewKind() === 'pdf') {\n <iframe [src]=\"previewFrameUrl()\" [attr.title]=\"previewName()\"></iframe>\n }\n </div>\n </div>\n </div>\n }\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-file-upload-wrap{width:100%;display:grid;gap:10px}.nvb-file-upload{border:1px dashed var(--nvb-color-neutral-400);border-radius:var(--nvb-card-radius);background:var(--nvb-color-neutral-050);min-height:110px;display:grid;justify-items:center;align-content:center;gap:6px;text-align:center;cursor:pointer;padding:14px;transition:border-color .16s ease,background-color .16s ease,box-shadow .16s ease}.nvb-file-upload:hover,.nvb-file-upload--drag-over{border-color:var(--nvb-color-primary-500);background:color-mix(in oklab,var(--nvb-color-primary-500) 12%,var(--nvb-color-surface-mix-target, white))}.nvb-file-upload--compact{min-height:88px;padding:10px}.nvb-file-upload--modern{box-shadow:var(--nvb-card-shadow)}.nvb-file-upload--grid{min-height:124px}.nvb-file-upload__icon{font-size:26px;color:var(--nvb-color-primary-600)}.nvb-file-upload__label{margin:0;font-size:13px;color:var(--nvb-color-neutral-700);line-height:1.4;white-space:pre-wrap}.nvb-file-upload__accept{margin:0;font-size:11px;color:var(--nvb-color-neutral-500);line-height:1.35;word-break:break-word}.nvb-file-upload__list{list-style:none;margin:0;padding:0}.nvb-file-upload__list--compact,.nvb-file-upload__list--modern{display:grid;gap:8px}.nvb-file-upload__list--grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.nvb-file-upload__list li{display:flex;align-items:center;justify-content:space-between;gap:10px;border:1px solid var(--nvb-color-neutral-300);border-radius:var(--nvb-control-radius);background:var(--nvb-color-neutral-000);padding:8px 10px}.nvb-file-upload__list--grid li{min-height:148px;align-items:stretch;flex-direction:column;justify-content:space-between}.nvb-file-upload__list-item--pending{border-color:color-mix(in oklab,var(--nvb-color-primary-500) 30%,var(--nvb-color-neutral-300))}.nvb-file-upload__list-item--error{border-color:color-mix(in oklab,var(--nvb-color-danger-500, #dc2626) 35%,var(--nvb-color-neutral-300))}.nvb-file-upload__entry-main{border:none;background:transparent;padding:0;display:flex;align-items:center;gap:10px;min-width:0;text-align:left;width:100%}.nvb-file-upload__entry-main:disabled{cursor:default}.nvb-file-upload__entry-main--interactive{cursor:pointer}.nvb-file-upload__list--grid .nvb-file-upload__entry-main{flex-direction:column;align-items:flex-start}.nvb-file-upload__thumb{width:40px;height:40px;border-radius:var(--nvb-control-radius);border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-100);display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.nvb-file-upload__list--grid .nvb-file-upload__thumb{width:48px;height:48px}.nvb-file-upload__thumb span.material-symbols-outlined{font-size:22px;color:var(--nvb-color-neutral-600)}.nvb-file-upload__entry-content{min-width:0;display:grid;gap:3px}.nvb-file-upload__entry-name,.nvb-file-upload__entry-meta,.nvb-file-upload__entry-status,.nvb-file-upload__preview-title{margin:0;line-height:1.35}.nvb-file-upload__entry-name{font-size:12px;color:var(--nvb-color-neutral-800);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:280px}.nvb-file-upload__list--grid .nvb-file-upload__entry-name{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;max-width:none}.nvb-file-upload__entry-meta{font-size:11px;color:var(--nvb-color-neutral-500);display:inline-flex;align-items:center;gap:4px;flex-wrap:wrap}.nvb-file-upload__entry-status{font-size:11px;color:var(--nvb-color-primary-600)}.nvb-file-upload__list-item--error .nvb-file-upload__entry-status{color:var(--nvb-color-danger-600, #b91c1c)}.nvb-file-upload__entry-actions{display:inline-flex;align-items:center;gap:4px;flex:0 0 auto}.nvb-file-upload__list--grid .nvb-file-upload__entry-actions{width:100%;justify-content:flex-end}.nvb-file-upload__icon-action,.nvb-file-upload__remove,.nvb-file-upload__preview-close{border:1px solid transparent;background:transparent;color:var(--nvb-color-neutral-500);width:32px;height:32px;border-radius:var(--nvb-control-radius);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.nvb-file-upload__icon-action:hover,.nvb-file-upload__remove:hover,.nvb-file-upload__preview-close:hover{background:var(--nvb-color-neutral-100);color:var(--nvb-color-neutral-900)}.nvb-file-upload__icon-action:focus-visible,.nvb-file-upload__remove:focus-visible,.nvb-file-upload__preview-close:focus-visible{outline:0;box-shadow:var(--nvb-focus-ring)}.nvb-file-upload__icon-action:disabled,.nvb-file-upload__remove:disabled{cursor:not-allowed;opacity:.55}.nvb-file-upload__icon-action span,.nvb-file-upload__remove span,.nvb-file-upload__preview-close span{font-size:18px}.nvb-file-upload__preview-backdrop{position:fixed;inset:0;z-index:1000;background:#0f172a5c;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px);display:flex;align-items:center;justify-content:center;padding:20px}.nvb-file-upload__preview-dialog{width:min(1440px,100%);max-width:100%;max-height:calc(100vh - 32px);min-height:min(88vh,960px);background:var(--nvb-color-neutral-000);border:1px solid var(--nvb-color-neutral-200);border-radius:var(--nvb-dialog-radius);overflow:hidden;display:grid;grid-template-rows:auto minmax(0,1fr);box-shadow:var(--nvb-shadow-16);outline:0}.nvb-file-upload__preview-header{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:20px 24px 12px;border-bottom:1px solid var(--nvb-color-neutral-200)}.nvb-file-upload__preview-title{margin:0;font-size:16px;line-height:22px;font-weight:600;color:var(--nvb-color-neutral-900);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nvb-file-upload__preview-header-actions{display:inline-flex;align-items:center;gap:8px}.nvb-file-upload__preview-action{border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000);color:var(--nvb-color-neutral-800);min-height:32px;border-radius:var(--nvb-button-radius);padding:0 12px;display:inline-flex;align-items:center;gap:6px;cursor:pointer;font-size:13px;font-weight:600;line-height:20px;transition:background-color .16s ease,border-color .16s ease,color .16s ease}.nvb-file-upload__preview-action:hover{background:var(--nvb-color-neutral-050);border-color:var(--nvb-color-neutral-400)}.nvb-file-upload__preview-action span.material-symbols-outlined{font-size:18px}.nvb-file-upload__preview-body{min-height:0;overflow:auto;background:#0f172a;padding:12px;display:flex;align-items:center;justify-content:center}.nvb-file-upload__preview-body img{display:block;max-width:100%;max-height:calc(100vh - 140px);object-fit:contain;height:auto;margin:0 auto}.nvb-file-upload__preview-body iframe{display:block;width:100%;min-height:calc(100vh - 140px);border:none;background:var(--nvb-color-neutral-000)}\n"],dependencies:[{kind:"component",type:_,selector:"element-wrapper",inputs:["model","controlIdInput","labelForInput","groupRole","showTextWrapperInput"],exportAs:["elementWrapper"]},{kind:"directive",type:x,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"pipe",type:w,name:"dynamicText"},{kind:"pipe",type:y,name:"uiT"}],changeDetection:p.ChangeDetectionStrategy.OnPush})};p.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.2.1",ngImport:p,type:h,decorators:[{type:U,args:[{selector:"file-upload-element",changeDetection:R.OnPush,imports:[_,x,w,y],template:"<element-wrapper [model]=\"model()\" #fieldWrapper=\"elementWrapper\">\n <section class=\"nvb-file-upload-wrap\" [attr.data-testid]=\"tid('root')\">\n <input\n #fileInput\n [id]=\"fieldWrapper.controlId()\"\n type=\"file\"\n [accept]=\"model().accept\"\n [multiple]=\"model().multiple\"\n hidden\n [attr.aria-describedby]=\"fieldWrapper.describedByIds(fieldWrapper.partId('dropzone-hint'))\"\n [attr.aria-errormessage]=\"fieldWrapper.isInvalid() ? fieldWrapper.errorId() : null\"\n [attr.aria-invalid]=\"fieldWrapper.isInvalid() ? 'true' : null\"\n [attr.aria-required]=\"model().required ? 'true' : null\"\n [attr.data-testid]=\"tid('input')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"onFileInputChange($event)\"\n />\n\n <div\n class=\"nvb-file-upload\"\n [ngClass]=\"{\n 'nvb-file-upload--drag-over': isDragOver(),\n 'nvb-file-upload--compact': resolveDisplayMode() === 'compact',\n 'nvb-file-upload--modern': resolveDisplayMode() === 'modern',\n 'nvb-file-upload--grid': resolveDisplayMode() === 'grid',\n }\"\n (click)=\"openPicker()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-labelledby]=\"fieldWrapper.hasLabelText() ? fieldWrapper.labelId() : null\"\n [attr.aria-label]=\"\n fieldWrapper.hasLabelText() ? null : (model().dropzoneText | dynamicText: model())\n \"\n [attr.aria-describedby]=\"fieldWrapper.describedByIds(fieldWrapper.partId('dropzone-hint'))\"\n [attr.data-testid]=\"tid('dropzone')\"\n (keydown.enter)=\"openPicker()\"\n (keydown.space)=\"openPicker(); $event.preventDefault()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n >\n <span class=\"material-symbols-outlined nvb-file-upload__icon\">upload_file</span>\n <p class=\"nvb-file-upload__label\">{{ model().dropzoneText | dynamicText: model() }}</p>\n\n @if (model().accept) {\n <p class=\"nvb-file-upload__accept\">{{ model().accept }}</p>\n }\n <span [id]=\"fieldWrapper.partId('dropzone-hint')\" class=\"nvb-sr-only\">\n {{ 'files.dropzoneHint' | uiT: 'Drag files here or press Enter to choose files.' }}\n </span>\n </div>\n\n @if (previewItems().length > 0) {\n <ul\n class=\"nvb-file-upload__list\"\n [ngClass]=\"{\n 'nvb-file-upload__list--compact': resolveDisplayMode() === 'compact',\n 'nvb-file-upload__list--modern': resolveDisplayMode() === 'modern',\n 'nvb-file-upload__list--grid': resolveDisplayMode() === 'grid',\n }\"\n >\n @for (entry of previewItems(); track entry.id; let itemIndex = $index) {\n <li\n [ngClass]=\"{\n 'nvb-file-upload__list-item--pending': entry.status === 'pending',\n 'nvb-file-upload__list-item--error': entry.status === 'error',\n }\"\n >\n <button\n type=\"button\"\n class=\"nvb-file-upload__entry-main\"\n [class.nvb-file-upload__entry-main--interactive]=\"canOpenEntry(entry)\"\n [disabled]=\"!canOpenEntry(entry)\"\n [attr.aria-label]=\"entry.meta.name\"\n [attr.data-testid]=\"tid('entry', itemIndex)\"\n (click)=\"onEntryActivate(entry, $event)\"\n >\n <div class=\"nvb-file-upload__thumb\" [attr.data-file-icon]=\"entry.iconName\">\n <span class=\"material-symbols-outlined\">{{ entry.iconName }}</span>\n </div>\n\n <div class=\"nvb-file-upload__entry-content\">\n <p class=\"nvb-file-upload__entry-name\">{{ entry.meta.name }}</p>\n <p class=\"nvb-file-upload__entry-meta\">\n {{ entry.meta.type || ('files.unknownType' | uiT: 'unknown') }}\n <span>&bull;</span>\n {{ formatSize(entry.meta.size) }}\n </p>\n\n @if (resolveStatusText(entry); as statusText) {\n @if (statusText) {\n <p class=\"nvb-file-upload__entry-status\">{{ statusText | uiT: statusText }}</p>\n }\n }\n </div>\n </button>\n\n <div class=\"nvb-file-upload__entry-actions\">\n @if (canPreviewEntry(entry)) {\n <button\n type=\"button\"\n class=\"nvb-file-upload__icon-action\"\n [disabled]=\"requestInFlight()\"\n (click)=\"previewFile(entry, $event)\"\n [attr.aria-label]=\"'files.preview' | uiT: 'Preview'\"\n [attr.data-testid]=\"tid('preview', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">visibility</span>\n </button>\n }\n\n @if (canDownload(entry)) {\n <button\n type=\"button\"\n class=\"nvb-file-upload__icon-action\"\n [disabled]=\"requestInFlight()\"\n (click)=\"downloadFile(entry, $event)\"\n [attr.aria-label]=\"'files.download' | uiT: 'Download'\"\n [attr.data-testid]=\"tid('download', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">download</span>\n </button>\n }\n\n <button\n type=\"button\"\n class=\"nvb-file-upload__remove\"\n [disabled]=\"requestInFlight()\"\n (click)=\"removeFile(itemIndex, $event)\"\n [attr.aria-label]=\"'files.remove' | uiT: 'Remove'\"\n [attr.data-testid]=\"tid('remove', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </div>\n </li>\n }\n </ul>\n }\n </section>\n\n @if (previewOpen()) {\n <div\n class=\"nvb-file-upload__preview-backdrop\"\n [attr.data-testid]=\"tid('preview-backdrop')\"\n (click)=\"closePreview()\"\n >\n <div\n class=\"nvb-file-upload__preview-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"file-upload-preview-title\"\n [attr.data-testid]=\"tid('preview-dialog')\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"nvb-file-upload__preview-header\">\n <p class=\"nvb-file-upload__preview-title\" id=\"file-upload-preview-title\">\n {{ previewName() }}\n </p>\n <div class=\"nvb-file-upload__preview-header-actions\">\n <button\n type=\"button\"\n class=\"nvb-file-upload__preview-action\"\n (click)=\"downloadPreview($event)\"\n [attr.aria-label]=\"'files.download' | uiT: 'Download'\"\n [attr.data-testid]=\"tid('preview-download')\"\n >\n <span class=\"material-symbols-outlined\">download</span>\n <span>{{ 'files.download' | uiT: 'Download' }}</span>\n </button>\n <button\n type=\"button\"\n class=\"nvb-file-upload__preview-close\"\n (click)=\"closePreview($event)\"\n [attr.aria-label]=\"'files.closePreview' | uiT: 'Close preview'\"\n [attr.data-testid]=\"tid('preview-close')\"\n >\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </div>\n </div>\n\n <div class=\"nvb-file-upload__preview-body\">\n @if (previewKind() === 'image') {\n <img [src]=\"previewUrl()\" [alt]=\"previewName()\" />\n } @else if (previewKind() === 'pdf') {\n <iframe [src]=\"previewFrameUrl()\" [attr.title]=\"previewName()\"></iframe>\n }\n </div>\n </div>\n </div>\n }\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-file-upload-wrap{width:100%;display:grid;gap:10px}.nvb-file-upload{border:1px dashed var(--nvb-color-neutral-400);border-radius:var(--nvb-card-radius);background:var(--nvb-color-neutral-050);min-height:110px;display:grid;justify-items:center;align-content:center;gap:6px;text-align:center;cursor:pointer;padding:14px;transition:border-color .16s ease,background-color .16s ease,box-shadow .16s ease}.nvb-file-upload:hover,.nvb-file-upload--drag-over{border-color:var(--nvb-color-primary-500);background:color-mix(in oklab,var(--nvb-color-primary-500) 12%,var(--nvb-color-surface-mix-target, white))}.nvb-file-upload--compact{min-height:88px;padding:10px}.nvb-file-upload--modern{box-shadow:var(--nvb-card-shadow)}.nvb-file-upload--grid{min-height:124px}.nvb-file-upload__icon{font-size:26px;color:var(--nvb-color-primary-600)}.nvb-file-upload__label{margin:0;font-size:13px;color:var(--nvb-color-neutral-700);line-height:1.4;white-space:pre-wrap}.nvb-file-upload__accept{margin:0;font-size:11px;color:var(--nvb-color-neutral-500);line-height:1.35;word-break:break-word}.nvb-file-upload__list{list-style:none;margin:0;padding:0}.nvb-file-upload__list--compact,.nvb-file-upload__list--modern{display:grid;gap:8px}.nvb-file-upload__list--grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.nvb-file-upload__list li{display:flex;align-items:center;justify-content:space-between;gap:10px;border:1px solid var(--nvb-color-neutral-300);border-radius:var(--nvb-control-radius);background:var(--nvb-color-neutral-000);padding:8px 10px}.nvb-file-upload__list--grid li{min-height:148px;align-items:stretch;flex-direction:column;justify-content:space-between}.nvb-file-upload__list-item--pending{border-color:color-mix(in oklab,var(--nvb-color-primary-500) 30%,var(--nvb-color-neutral-300))}.nvb-file-upload__list-item--error{border-color:color-mix(in oklab,var(--nvb-color-danger-500, #dc2626) 35%,var(--nvb-color-neutral-300))}.nvb-file-upload__entry-main{border:none;background:transparent;padding:0;display:flex;align-items:center;gap:10px;min-width:0;text-align:left;width:100%}.nvb-file-upload__entry-main:disabled{cursor:default}.nvb-file-upload__entry-main--interactive{cursor:pointer}.nvb-file-upload__list--grid .nvb-file-upload__entry-main{flex-direction:column;align-items:flex-start}.nvb-file-upload__thumb{width:40px;height:40px;border-radius:var(--nvb-control-radius);border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-100);display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.nvb-file-upload__list--grid .nvb-file-upload__thumb{width:48px;height:48px}.nvb-file-upload__thumb span.material-symbols-outlined{font-size:22px;color:var(--nvb-color-neutral-600)}.nvb-file-upload__entry-content{min-width:0;display:grid;gap:3px}.nvb-file-upload__entry-name,.nvb-file-upload__entry-meta,.nvb-file-upload__entry-status,.nvb-file-upload__preview-title{margin:0;line-height:1.35}.nvb-file-upload__entry-name{font-size:12px;color:var(--nvb-color-neutral-800);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:280px}.nvb-file-upload__list--grid .nvb-file-upload__entry-name{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;max-width:none}.nvb-file-upload__entry-meta{font-size:11px;color:var(--nvb-color-neutral-500);display:inline-flex;align-items:center;gap:4px;flex-wrap:wrap}.nvb-file-upload__entry-status{font-size:11px;color:var(--nvb-color-primary-600)}.nvb-file-upload__list-item--error .nvb-file-upload__entry-status{color:var(--nvb-color-danger-600, #b91c1c)}.nvb-file-upload__entry-actions{display:inline-flex;align-items:center;gap:4px;flex:0 0 auto}.nvb-file-upload__list--grid .nvb-file-upload__entry-actions{width:100%;justify-content:flex-end}.nvb-file-upload__icon-action,.nvb-file-upload__remove,.nvb-file-upload__preview-close{border:1px solid transparent;background:transparent;color:var(--nvb-color-neutral-500);width:32px;height:32px;border-radius:var(--nvb-control-radius);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.nvb-file-upload__icon-action:hover,.nvb-file-upload__remove:hover,.nvb-file-upload__preview-close:hover{background:var(--nvb-color-neutral-100);color:var(--nvb-color-neutral-900)}.nvb-file-upload__icon-action:focus-visible,.nvb-file-upload__remove:focus-visible,.nvb-file-upload__preview-close:focus-visible{outline:0;box-shadow:var(--nvb-focus-ring)}.nvb-file-upload__icon-action:disabled,.nvb-file-upload__remove:disabled{cursor:not-allowed;opacity:.55}.nvb-file-upload__icon-action span,.nvb-file-upload__remove span,.nvb-file-upload__preview-close span{font-size:18px}.nvb-file-upload__preview-backdrop{position:fixed;inset:0;z-index:1000;background:#0f172a5c;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px);display:flex;align-items:center;justify-content:center;padding:20px}.nvb-file-upload__preview-dialog{width:min(1440px,100%);max-width:100%;max-height:calc(100vh - 32px);min-height:min(88vh,960px);background:var(--nvb-color-neutral-000);border:1px solid var(--nvb-color-neutral-200);border-radius:var(--nvb-dialog-radius);overflow:hidden;display:grid;grid-template-rows:auto minmax(0,1fr);box-shadow:var(--nvb-shadow-16);outline:0}.nvb-file-upload__preview-header{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:20px 24px 12px;border-bottom:1px solid var(--nvb-color-neutral-200)}.nvb-file-upload__preview-title{margin:0;font-size:16px;line-height:22px;font-weight:600;color:var(--nvb-color-neutral-900);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nvb-file-upload__preview-header-actions{display:inline-flex;align-items:center;gap:8px}.nvb-file-upload__preview-action{border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000);color:var(--nvb-color-neutral-800);min-height:32px;border-radius:var(--nvb-button-radius);padding:0 12px;display:inline-flex;align-items:center;gap:6px;cursor:pointer;font-size:13px;font-weight:600;line-height:20px;transition:background-color .16s ease,border-color .16s ease,color .16s ease}.nvb-file-upload__preview-action:hover{background:var(--nvb-color-neutral-050);border-color:var(--nvb-color-neutral-400)}.nvb-file-upload__preview-action span.material-symbols-outlined{font-size:18px}.nvb-file-upload__preview-body{min-height:0;overflow:auto;background:#0f172a;padding:12px;display:flex;align-items:center;justify-content:center}.nvb-file-upload__preview-body img{display:block;max-width:100%;max-height:calc(100vh - 140px);object-fit:contain;height:auto;margin:0 auto}.nvb-file-upload__preview-body iframe{display:block;width:100%;min-height:calc(100vh - 140px);border:none;background:var(--nvb-color-neutral-000)}\n"]}]}],propDecorators:{model:[{type:p.Input,args:[{isSignal:true,alias:"model",required:true}]}],fileInput:[{type:C,args:["fileInput"]}]}});export{O as n,h as t};
1
+ import{t as S}from"./ngxviewbuilder-runtime-rolldown-runtime-DpJrqANO.mjs";import{c as k,g as I,n as y,on as P,t as w}from"./ngxviewbuilder-runtime-dynamic-text.pipe-BUJ4fCqt.mjs";import{ht as D,r as M,rt as z,s as N,t as _}from"./ngxviewbuilder-runtime-element-wrapper-D0lfZvuW.mjs";import*as p from"@angular/core";import{ChangeDetectionStrategy as R,ChangeDetectorRef as T,Component as U,ViewChild as C,inject as c,input as E,signal as u}from"@angular/core";import{NgClass as x}from"@angular/common";import{get as B}from"lodash-es";import{firstValueFrom as b}from"rxjs";import{DomSanitizer as A}from"@angular/platform-browser";var O=S({FileUploadElement:()=>h});var h=class g{model=E.required(...ngDevMode?[{debugName:"model"}]:[]);tid=M(this.model,"nvb-file-upload","file-upload");fileInput;isDragOver=u(false,...ngDevMode?[{debugName:"isDragOver"}]:[]);requestInFlight=u(false,...ngDevMode?[{debugName:"requestInFlight"}]:[]);previewItems=u([],...ngDevMode?[{debugName:"previewItems"}]:[]);previewOpen=u(false,...ngDevMode?[{debugName:"previewOpen"}]:[]);previewUrl=u("",...ngDevMode?[{debugName:"previewUrl"}]:[]);previewKind=u(null,...ngDevMode?[{debugName:"previewKind"}]:[]);previewName=u("",...ngDevMode?[{debugName:"previewName"}]:[]);previewFrameUrl=u(null,...ngDevMode?[{debugName:"previewFrameUrl"}]:[]);elementActionService=c(z);dataSourceService=c(k);dataService=c(P);eventService=c(I);ngxViewBuilderApiService=c(N);cdr=c(T);sanitizer=c(A);markupSecurityService=c(D);previewObjectUrl=null;activePreviewResource=null;onPropertyChangedHandler=e=>{const t=String(this.model()?.dataPath??"").trim();if(!t)return;if(String(e?.payload?.elementNameOrPath??"").trim()!==t)return;this.cdr.markForCheck()};ngOnInit(){this.syncPreviewFromModelValue();this.eventService.afterPropertyChanged.add(this.onPropertyChangedHandler)}ngOnDestroy(){this.closePreview();this.eventService.afterPropertyChanged.remove(this.onPropertyChangedHandler)}openPicker(){if(this.isInteractionLocked())return;this.fileInput?.nativeElement.click()}onFileInputChange(e){if(this.isInteractionLocked())return;const t=e.target;const i=t?.files?Array.from(t.files):[];this.applyFiles(i);if(t)t.value=""}onDragOver(e){if(this.isInteractionLocked())return;e.preventDefault();this.isDragOver.set(true)}onDragLeave(e){if(this.isInteractionLocked())return;e.preventDefault();this.isDragOver.set(false)}onDrop(e){if(this.isInteractionLocked())return;e.preventDefault();this.isDragOver.set(false);const t=e.dataTransfer?.files?Array.from(e.dataTransfer.files):[];this.applyFiles(t)}onEntryActivate(e,t){t.preventDefault();t.stopPropagation();if(this.canPreviewEntry(e)){this.previewFileAsync(e);return}if(this.canDownload(e))this.downloadFileAsync(e)}removeFile(e,t){t.preventDefault();t.stopPropagation();if(this.isInteractionLocked())return;this.removeFileAsync(e)}downloadFile(e,t){t.preventDefault();t.stopPropagation();if(this.isInteractionLocked())return;this.downloadFileAsync(e)}previewFile(e,t){t.preventDefault();t.stopPropagation();if(this.isInteractionLocked())return;this.previewFileAsync(e)}clearFiles(e){e?.preventDefault();e?.stopPropagation();if(this.isInteractionLocked())return;this.closePreview();this.previewItems.set([]);this.model().setFiles([]);this.emitChangeActions()}closePreview(e){e?.preventDefault();e?.stopPropagation();this.previewOpen.set(false);this.previewUrl.set("");this.previewKind.set(null);this.previewName.set("");this.previewFrameUrl.set(null);this.activePreviewResource=null;if(this.previewObjectUrl){URL.revokeObjectURL(this.previewObjectUrl);this.previewObjectUrl=null}}formatSize(e){const t=Number(e);if(!Number.isFinite(t)||t<0)return"0 B";if(t<1024)return`${t} B`;if(t<1048576)return`${(t/1024).toFixed(1)} KB`;return`${(t/1048576).toFixed(1)} MB`}resolveDisplayMode(){const e=String(this.model().displayMode??"modern").trim().toLowerCase();if(e==="compact"||e==="grid")return e;return"modern"}resolveStatusText(e){if(e.status==="pending")return this.isBase64Mode()?"Reading file...":"Uploading...";if(e.status==="error")return e.errorMessage||"Upload failed";return""}canOpenEntry(e){return this.canPreviewEntry(e)||this.canDownload(e)}canDownload(e){if(e.localFile||e.meta.base64)return true;if(!String(this.model().downloadDataSourceName??"").trim())return false;return Boolean(this.resolveMetaKey(e.meta))}canPreviewEntry(e){if(!this.model().showPreview)return false;return this.resolvePreviewKind(e.meta)!==null&&this.canDownload(e)}async applyFiles(e){if(this.isInteractionLocked())return;const t=Boolean(this.model().multiple);const i=t?[...this.previewItems()]:[];const n=this.normalizeFiles(e,i.length);if(n.length===0)return;const r=t?[...i]:[];const o=this.isBase64Mode();const a=!o&&String(this.model().uploadDataSourceName??"").trim().length>0;const l=n.map((s,v)=>this.createPreviewEntry(this.createLocalMeta(s),s,a||o?"pending":"ready","",`${Date.now()}-${v}-${s.name}`));r.push(...l);this.commitPreviewEntries(r);this.emitChangeActions();this.ngxViewBuilderApiService.notifyFileUploadFilesAdded({elementName:this.model().name,elementDataPath:this.model().dataPath,element:this.model(),files:r.map(s=>s.meta),addedFiles:l.map(s=>s.meta)});if(o){await this.encodeEntries(l);return}if(!a)return;this.requestInFlight.set(true);let d=false;try{for(const s of l){const v=s.localFile;if(!v)continue;try{const m=await this.uploadFileIfNeeded(v);const f=this.updatePreviewEntry(s.id,F=>({...F,meta:m,iconName:this.resolveFileTypeIcon(m),status:"ready",errorMessage:""}));d=d||f}catch{const m=this.updatePreviewEntry(s.id,f=>({...f,status:"error",errorMessage:"Upload failed"}));d=d||m}}}finally{this.requestInFlight.set(false)}if(d)this.emitChangeActions()}async encodeEntries(e){let t=false;for(const i of e){const n=i.localFile;if(!n)continue;try{const r=await this.readFileAsBase64(n);t=this.updatePreviewEntry(i.id,o=>({...o,meta:{...o.meta,base64:r},status:"ready",errorMessage:""}))||t}catch{t=this.updatePreviewEntry(i.id,r=>({...r,status:"error",errorMessage:"Could not read the file"}))||t}}if(t)this.emitChangeActions()}readFileAsBase64(e){return new Promise((t,i)=>{const n=new FileReader;n.onload=()=>{const r=String(n.result??"");const o=r.indexOf(",");t(o>=0?r.slice(o+1):r)};n.onerror=()=>i(n.error??new Error("Could not read the file."));n.readAsDataURL(e)})}isBase64Mode(){return this.model().storageMode!=="server"}async removeFileAsync(e){const t=[...this.previewItems()];if(e<0||e>=t.length)return;const i=t[e];const n=this.resolveMetaKey(i.meta);const r=String(this.model().deleteDataSourceName??"").trim();if(r&&n){if(!await this.deleteFileFromServer(i.meta,r,n))return}t.splice(e,1);this.previewItems.set(t);this.model().setFiles(t.map(o=>o.meta));if(this.previewOpen()&&this.previewName()===this.resolveMetaName(i.meta))this.closePreview();this.emitChangeActions();this.ngxViewBuilderApiService.notifyFileUploadFileRemoved({elementName:this.model().name,elementDataPath:this.model().dataPath,element:this.model(),files:t.map(o=>o.meta),removedFile:i.meta,removedIndex:e})}async downloadFileAsync(e){const t=await this.resolveEntryResource(e);if(!t)return;this.downloadResource(t)}async previewFileAsync(e){const t=this.resolvePreviewKind(e.meta);if(!this.model().showPreview||!t){await this.downloadFileAsync(e);return}const i=await this.resolveEntryResource(e);if(!i)return;this.openPreview(t,i)}async resolveEntryResource(e){const t=this.resolveMetaKey(e.meta);if(t){const i=await this.fetchRemoteEntryResource(e,t);if(i)return i}if(e.localFile)return this.createResourceFromBlob(e.localFile,this.resolveMetaName(e.meta),this.resolveMetaType(e.meta)||e.localFile.type);if(e.meta.base64){const i=this.decodeBase64(e.meta.base64,this.resolveMetaType(e.meta));if(i)return this.createResourceFromBlob(i,this.resolveMetaName(e.meta),this.resolveMetaType(e.meta))}if(e.meta.raw){const i=await this.resolveResourceFromUnknown(e.meta.raw,this.resolveMetaName(e.meta),this.resolveMetaType(e.meta));if(i)return i}return null}async fetchRemoteEntryResource(e,t){const i=String(this.model().downloadDataSourceName??"").trim();if(!i)return null;const n=this.dataSourceService.getSource(i);if(!n)return null;const r=this.buildRuntimeContext(e.meta,t,e.localFile??void 0);const o=this.resolveSourceMethod(n,"GET");const a=this.resolveSourceUrl(n,r);if(!a)return null;this.requestInFlight.set(true);try{const l=o==="GET"?void 0:this.resolveSourcePayload(n,r,{[this.model().fileKeyField]:t});const d=await b(this.dataSourceService.request(o,a,l,{responseType:"blob",observeResponse:true}));return await this.resolveHttpDownloadResponse(d,this.resolveMetaName(e.meta),this.resolveMetaType(e.meta))}catch{return null}finally{this.requestInFlight.set(false)}}async uploadFileIfNeeded(e){const t=String(this.model().uploadDataSourceName??"").trim();if(!t)return this.createLocalMeta(e);const i=this.dataSourceService.getSource(t);if(!i)return this.createLocalMeta(e);const n=this.buildRuntimeContext(this.createLocalMeta(e),void 0,e);const r=this.resolveSourceMethod(i,"POST");const o=this.resolveSourceUrl(i,n);if(!o)return this.createLocalMeta(e);const a=new FormData;const l=String(this.model().uploadFormFieldName??"file").trim()||"file";a.append(l,e,e.name);const d=await b(this.dataSourceService.request(r,o,a));const s=this.extractFirstRecord(d);if(s)return this.createMetaFromRecord(s,e);return this.createLocalMeta(e)}async deleteFileFromServer(e,t,i){const n=this.dataSourceService.getSource(t);if(!n)return false;const r=this.buildRuntimeContext(e,i);const o=this.resolveSourceMethod(n,"DELETE");const a=this.resolveSourceUrl(n,r);if(!a)return false;const l=o==="GET"?void 0:this.resolveSourcePayload(n,r,{[this.model().fileKeyField]:i,fileKey:i,filKey:i,key:i,fil_key:i,id:i,fileId:i,uuid:i});this.requestInFlight.set(true);try{await b(this.dataSourceService.request(o,a,l));return true}catch{return false}finally{this.requestInFlight.set(false)}}normalizeFiles(e,t=0){if(!Array.isArray(e)||e.length===0)return[];const i=Number(this.model()?.maxFiles??1);const n=Number.isFinite(i)&&i>0?Math.floor(i):1;if(!this.model().multiple)return this.filterByMaxFileSize([e[0]]);const r=Math.max(0,Math.floor(Number(t)||0));const o=Math.max(0,n-r);if(o<=0)return[];return this.filterByMaxFileSize(e).slice(0,o)}filterByMaxFileSize(e){const t=Number(this.model()["maxFileSizeMb"]);if(!Number.isFinite(t)||t<=0)return e;const i=t*1024*1024;return e.filter(n=>Number(n?.size??0)<=i)}commitPreviewEntries(e){const t=[...e];this.previewItems.set(t);this.model().setFiles(t.map(i=>i.meta))}updatePreviewEntry(e,t){let i=false;const n=this.previewItems().map(r=>{if(r.id!==e)return r;i=true;return t(r)});if(!i)return false;this.commitPreviewEntries(n);return true}syncPreviewFromModelValue(){const e=this.extractRecords(this.model().value);if(e.length===0){this.previewItems.set([]);return}this.previewItems.set(e.map((t,i)=>this.createPreviewEntry(this.createMetaFromRecord(t),null,"ready","",`saved-${i}`)))}createPreviewEntry(e,t,i,n,r){return{id:r,meta:e,iconName:this.resolveFileTypeIcon(e),status:i,localFile:t,errorMessage:n}}createLocalMeta(e){return{name:e.name,size:e.size,type:e.type,lastModified:e.lastModified}}createMetaFromRecord(e,t){const i=this.readRecordString(e,[this.model().fileNameField,"name","fileName","fil_name"])||t?.name||"file";const n=this.readRecordString(e,[this.model().fileTypeField,"type","contentType","mimeType","fil_content_type"])||t?.type||"";const r=this.readRecordNumber(e,[this.model().fileSizeField,"size","fil_size"])??Number(t?.size??0);const o=this.readRecordString(e,[this.model().fileKeyField,"fileKey","filKey","key","fil_key","id","fileId","uuid"])||void 0;const a=this.readRecordNumber(e,["lastModified"])??Number(t?.lastModified??0);const l=typeof e["base64"]==="string"?e["base64"].trim():"";return{name:i,type:n,size:Number.isFinite(r)&&r>=0?r:0,lastModified:Number.isFinite(a)&&a>=0?a:0,fileKey:o,...l?{base64:l}:{},raw:{...e}}}resolveFileTypeIcon(e){const t=String(e?.type??"").trim().toLowerCase();const i=this.resolveFileExtension(e?.name);if(t.startsWith("image/")||["jpg","jpeg","png","gif","webp","bmp","svg"].includes(i))return"image";if(t.includes("pdf")||i==="pdf")return"picture_as_pdf";if(t.includes("spreadsheet")||t.includes("excel")||t.includes("csv")||["csv","xls","xlsx","ods"].includes(i))return"table_view";if(t.includes("word")||t.includes("opendocument.text")||["doc","docx","rtf","odt"].includes(i))return"draft";if(t.startsWith("video/")||["mp4","mov","avi","mkv","webm"].includes(i))return"smart_display";if(t.includes("html")||t.includes("xml")||t.includes("json")||t.includes("javascript")||t.includes("typescript")||t.includes("css")||t.includes("text/")||["txt","json","xml","html","htm","js","ts","css","md","yml","yaml"].includes(i))return"html";if(t.includes("zip")||t.includes("compressed")||["zip","rar","7z","tar","gz"].includes(i))return"extension";return"description"}resolvePreviewKind(e){const t=String(e?.type??"").trim().toLowerCase();const i=this.resolveFileExtension(e?.name);if(t.startsWith("image/")||["jpg","jpeg","png","gif","webp","bmp","svg"].includes(i))return"image";if(t.includes("pdf")||i==="pdf")return"pdf";return null}resolveFileExtension(e){const t=String(e??"").trim().toLowerCase();if(!t)return"";const i=t.lastIndexOf(".");if(i<0||i===t.length-1)return"";return t.slice(i+1)}resolveMetaKey(e){const t=String(e?.fileKey??"").trim();if(t)return t;if(!e?.raw||typeof e.raw!=="object")return"";return this.readRecordString(e.raw,[this.model().fileKeyField,"fileKey","filKey","key","fil_key","id","fileId","uuid"])}resolveMetaName(e){return String(e?.name??"").trim()||"file"}resolveMetaType(e){return String(e?.type??"").trim()||"application/octet-stream"}buildRuntimeContext(e,t,i){const n={value:this.model().value,files:this.model().value,file:i,fileMeta:e?.raw??e,fileRow:e?.raw??e,fileName:this.resolveMetaName(e),fileType:this.resolveMetaType(e),fileSize:Number(e?.size??0),item:e?.raw??e,row:e?.raw??e};if(t){n[this.model().fileKeyField]=t;n["fileKey"]=t;n["filKey"]=t;n["fil_key"]=t;n["key"]=t;n["id"]=t;n["fileId"]=t;n["uuid"]=t}const r=String(this.model().name??"").trim();if(r)n[r]=this.model().value;return n}resolveSourceMethod(e,t){return String(e?.params?.["method"]??t).trim().toUpperCase()||t}resolveSourceUrl(e,t){const i=String(e?.params?.["url"]??"").trim();if(!i)return"";return i.replace(/\{([^}]+)\}/g,(n,r)=>{const o=this.resolveContextValue(String(r??"").trim(),t);return encodeURIComponent(this.serializeForUrl(o))})}resolveSourcePayload(e,t,i){const n=e?.params?.["body"]??e?.params?.["payload"];if(n===null||n===void 0)return i;const r=this.normalizePayloadTemplate(n);if(r===void 0)return i;return this.replacePayloadPlaceholders(r,t)}normalizePayloadTemplate(e){if(typeof e!=="string")return e;const t=e.trim();if(!t)return;if(/^\{[^{}]+\}$/.test(t))return t;if(!t.startsWith("{")&&!t.startsWith("["))return e;try{return JSON.parse(t)}catch{return e}}replacePayloadPlaceholders(e,t){if(typeof e==="string"){const i=e.match(/^\{([^}]+)\}$/);if(i){const n=String(i[1]??"").trim();return this.resolveContextValue(n,t)}return e.replace(/\{([^}]+)\}/g,(n,r)=>{const o=this.resolveContextValue(String(r??"").trim(),t);return this.serializeForUrl(o)})}if(Array.isArray(e))return e.map(i=>this.replacePayloadPlaceholders(i,t));if(e&&typeof e==="object"){const i=e;const n={};Object.keys(i).forEach(r=>{n[r]=this.replacePayloadPlaceholders(i[r],t)});return n}return e}resolveContextValue(e,t){const i=String(e??"").trim().replace(/^\{/,"").replace(/\}$/,"");if(!i)return;const n=B(t,i);if(n!==void 0)return n;return this.dataService.getValue(i)}serializeForUrl(e){if(Array.isArray(e))return e.length>0?String(e[0]??""):"";if(e===null||e===void 0)return"";return String(e)}extractFirstRecord(e){const t=this.extractRecords(e);return t.length>0?t[0]:null}extractRecords(e,t=0){if(t>4||e===null||e===void 0)return[];if(Array.isArray(e))return e.filter(r=>r&&typeof r==="object"&&!Array.isArray(r)).map(r=>r);if(!e||typeof e!=="object")return[];const i=e;const n=Object.keys(i).filter(r=>/^\d+$/.test(r));if(n.length>0)return n.sort((r,o)=>Number(r)-Number(o)).map(r=>i[r]).filter(r=>r&&typeof r==="object"&&!Array.isArray(r)).map(r=>r);for(const r of["data","items","rows","result","value"]){if(i[r]===void 0)continue;const o=this.extractRecords(i[r],t+1);if(o.length>0)return o}return[i]}readRecordString(e,t){for(const i of t){const n=String(i??"").trim();if(!n)continue;const r=e[n];if(r===null||r===void 0)continue;const o=String(r).trim();if(o)return o}return""}readRecordNumber(e,t){for(const i of t){const n=String(i??"").trim();if(!n)continue;const r=e[n];if(r===null||r===void 0||r==="")continue;const o=Number(r);if(Number.isFinite(o))return o}return null}async resolveHttpDownloadResponse(e,t,i){const n=e.body;if(!(n instanceof Blob))return null;const r=e.headers.get("content-type");const o=e.headers.get("content-disposition");const a=String(r||n.type||i||"application/octet-stream");const l=this.parseContentDispositionFileName(o)||t||"file";if(this.shouldUseBlobAsFile(a,o))return this.createResourceFromBlob(n,l,a);const d=await n.text();const s=this.parseStructuredDownloadPayload(d);const v=await this.resolveResourceFromUnknown(s,l,a);if(v)return v;return this.createResourceFromBlob(n,l,a)}shouldUseBlobAsFile(e,t){const i=String(e??"").trim().toLowerCase();if(String(t??"").trim().toLowerCase().includes("attachment"))return true;if(!i)return true;if(i.startsWith("image/")||i.includes("pdf")||i.includes("octet-stream")||i.includes("zip")||i.includes("excel")||i.includes("spreadsheet")||i.includes("msword")||i.includes("officedocument"))return true;return!(i.includes("json")||i.startsWith("text/")||i.includes("javascript")||i.includes("xml"))}parseStructuredDownloadPayload(e){const t=String(e??"").trim();if(!t)return null;if(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]"))try{return JSON.parse(t)}catch{return t}return t}async resolveResourceFromUnknown(e,t,i){if(e===null||e===void 0)return null;if(e instanceof Blob)return this.createResourceFromBlob(e,t,e.type||i);if(e instanceof ArrayBuffer)return this.createResourceFromBlob(new Blob([e],{type:i}),t,i);if(e instanceof Uint8Array)return this.createResourceFromBlob(new Blob([e.slice()],{type:i}),t,i);if(typeof e==="string")return await this.resolveResourceFromString(e,t,i);if(typeof e==="object"){const n=e;const r=this.readRecordString(n,["fileName","name",this.model().fileNameField])||t;const o=this.readRecordString(n,["contentType","type",this.model().fileTypeField])||i;const a=this.markupSecurityService.sanitizeFileUrl(this.readRecordString(n,["url","downloadUrl","href","src","previewUrl"])||"");if(a)return{fileName:r||t||"file",contentType:o||i||"application/octet-stream",sourceUrl:a,revokeOnDispose:false};const l=n["content"]??n["data"]??n["base64"]??n["blob"]??n["file"]??n["result"]??null;if(l!==null&&l!==void 0&&l!==e)return this.resolveResourceFromUnknown(l,r,o)}return null}async resolveResourceFromString(e,t,i){const n=String(e??"").trim();if(!n)return null;if(/^(https?:|blob:|data:)/i.test(n)){const a=this.markupSecurityService.sanitizeFileUrl(n);if(!a)return null;return{fileName:t||"file",contentType:i||this.resolveContentTypeFromUrl(a),sourceUrl:a,revokeOnDispose:false}}const r=this.parseStructuredDownloadPayload(n);if(r!==n)return this.resolveResourceFromUnknown(r,t,i);const o=this.createBlobFromBase64(n,i);if(o)return this.createResourceFromBlob(o,t,i||o.type);return this.createResourceFromBlob(new Blob([n],{type:i||"text/plain;charset=utf-8"}),t,i||"text/plain;charset=utf-8")}decodeBase64(e,t){try{const i=String(e??"");const n=atob(i.slice(i.indexOf(",")+1).replace(/\s+/g,""));const r=new Uint8Array(n.length);for(let o=0;o<n.length;o+=1)r[o]=n.charCodeAt(o);return new Blob([r],{type:t||"application/octet-stream"})}catch{return null}}createBlobFromBase64(e,t){const i=String(e??"").replace(/\s+/g,"");if(!this.isProbableBase64(i))return null;try{const n=atob(i);const r=new Uint8Array(n.length);for(let o=0;o<n.length;o+=1)r[o]=n.charCodeAt(o);return new Blob([r],{type:t||"application/octet-stream"})}catch{return null}}isProbableBase64(e){if(!e||e.length<16||e.length%4!==0)return false;return/^[A-Za-z0-9+/]+={0,2}$/.test(e)}resolveContentTypeFromUrl(e){const t=String(e??"").trim();if(t.startsWith("data:")){const i=t.match(/^data:([^;,]+)[;,]/i);if(i?.[1])return i[1]}return"application/octet-stream"}createResourceFromBlob(e,t,i){const n=String(i||e.type||"").trim();const r=/html|xml|svg|javascript|ecmascript/i.test(n)?"application/octet-stream":n||"application/octet-stream";const o=e.type===r?e:new Blob([e],{type:r});const a=URL.createObjectURL(o);return{fileName:t||"file",contentType:r,sourceUrl:a,revokeOnDispose:true}}openPreview(e,t){const i=this.markupSecurityService.sanitizeFileUrl(t.sourceUrl);if(!i)return;t={...t,sourceUrl:i};this.closePreview();this.previewKind.set(e);this.previewName.set(t.fileName);this.previewUrl.set(t.sourceUrl);this.previewFrameUrl.set(e==="pdf"?this.sanitizer.bypassSecurityTrustResourceUrl(t.sourceUrl):null);this.previewOpen.set(true);this.activePreviewResource=t;if(t.revokeOnDispose)this.previewObjectUrl=t.sourceUrl}downloadPreview(e){e.preventDefault();e.stopPropagation();if(!this.activePreviewResource)return;this.downloadResource(this.activePreviewResource)}downloadResource(e){this.triggerLinkDownload(e.sourceUrl,e.fileName);if(e.revokeOnDispose)setTimeout(()=>{URL.revokeObjectURL(e.sourceUrl)},1e3)}parseContentDispositionFileName(e){const t=String(e??"").trim();if(!t)return"";const i=t.match(/filename\*\s*=\s*UTF-8''([^;]+)/i);if(i?.[1])try{return decodeURIComponent(i[1].trim().replace(/^"|"$/g,""))}catch{return i[1].trim().replace(/^"|"$/g,"")}const n=t.match(/filename\s*=\s*("?)([^";]+)\1/i);return String(n?.[2]??"").trim()}triggerLinkDownload(e,t){const i=this.markupSecurityService.sanitizeFileUrl(e);if(!i)return;const n=document.createElement("a");n.href=i;n.download=t||"file";n.target="_blank";n.rel="noopener";document.body.appendChild(n);n.click();document.body.removeChild(n)}emitChangeActions(){const e={value:this.model().value,files:this.model().value,item:null,row:null};const t=String(this.model().name??"").trim();if(t)e[t]=this.model().value;this.elementActionService.runActions(this.model(),this.model().events??[],"change",e)}isInteractionLocked(){const e=this.model();if(!e)return false;if(this.requestInFlight())return true;if(Boolean(e["__pfInteractionLocked"]))return true;return Boolean(e.disabled)||Boolean(e.readOnly)}static ɵfac=p.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.2.1",ngImport:p,type:g,deps:[],target:p.ɵɵFactoryTarget.Component});static ɵcmp=p.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.2.1",type:g,isStandalone:true,selector:"file-upload-element",inputs:{model:{classPropertyName:"model",publicName:"model",isSignal:true,isRequired:true,transformFunction:null}},viewQueries:[{propertyName:"fileInput",first:true,predicate:["fileInput"],descendants:true}],ngImport:p,template:"<element-wrapper [model]=\"model()\" #fieldWrapper=\"elementWrapper\">\n <section class=\"nvb-file-upload-wrap\" [attr.data-testid]=\"tid('root')\">\n <input\n #fileInput\n [id]=\"fieldWrapper.controlId()\"\n type=\"file\"\n [accept]=\"model().accept\"\n [multiple]=\"model().multiple\"\n hidden\n [attr.aria-describedby]=\"fieldWrapper.describedByIds(fieldWrapper.partId('dropzone-hint'))\"\n [attr.aria-errormessage]=\"fieldWrapper.isInvalid() ? fieldWrapper.errorId() : null\"\n [attr.aria-invalid]=\"fieldWrapper.isInvalid() ? 'true' : null\"\n [attr.aria-required]=\"model().required ? 'true' : null\"\n [attr.data-testid]=\"tid('input')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"onFileInputChange($event)\"\n />\n\n <div\n class=\"nvb-file-upload\"\n [ngClass]=\"{\n 'nvb-file-upload--drag-over': isDragOver(),\n 'nvb-file-upload--compact': resolveDisplayMode() === 'compact',\n 'nvb-file-upload--modern': resolveDisplayMode() === 'modern',\n 'nvb-file-upload--grid': resolveDisplayMode() === 'grid',\n }\"\n (click)=\"openPicker()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-labelledby]=\"fieldWrapper.hasLabelText() ? fieldWrapper.labelId() : null\"\n [attr.aria-label]=\"\n fieldWrapper.hasLabelText() ? null : (model().dropzoneText | dynamicText: model())\n \"\n [attr.aria-describedby]=\"fieldWrapper.describedByIds(fieldWrapper.partId('dropzone-hint'))\"\n [attr.data-testid]=\"tid('dropzone')\"\n (keydown.enter)=\"openPicker()\"\n (keydown.space)=\"openPicker(); $event.preventDefault()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n >\n <span class=\"material-symbols-outlined nvb-file-upload__icon\">upload_file</span>\n <p class=\"nvb-file-upload__label\">{{ model().dropzoneText | dynamicText: model() }}</p>\n\n @if (model().accept) {\n <p class=\"nvb-file-upload__accept\">{{ model().accept }}</p>\n }\n <span [id]=\"fieldWrapper.partId('dropzone-hint')\" class=\"nvb-sr-only\">\n {{ 'files.dropzoneHint' | uiT: 'Drag files here or press Enter to choose files.' }}\n </span>\n </div>\n\n @if (previewItems().length > 0) {\n <ul\n class=\"nvb-file-upload__list\"\n [ngClass]=\"{\n 'nvb-file-upload__list--compact': resolveDisplayMode() === 'compact',\n 'nvb-file-upload__list--modern': resolveDisplayMode() === 'modern',\n 'nvb-file-upload__list--grid': resolveDisplayMode() === 'grid',\n }\"\n >\n @for (entry of previewItems(); track entry.id; let itemIndex = $index) {\n <li\n [ngClass]=\"{\n 'nvb-file-upload__list-item--pending': entry.status === 'pending',\n 'nvb-file-upload__list-item--error': entry.status === 'error',\n }\"\n >\n <button\n type=\"button\"\n class=\"nvb-file-upload__entry-main\"\n [class.nvb-file-upload__entry-main--interactive]=\"canOpenEntry(entry)\"\n [disabled]=\"!canOpenEntry(entry)\"\n [attr.aria-label]=\"entry.meta.name\"\n [attr.data-testid]=\"tid('entry', itemIndex)\"\n (click)=\"onEntryActivate(entry, $event)\"\n >\n <div class=\"nvb-file-upload__thumb\" [attr.data-file-icon]=\"entry.iconName\">\n <span class=\"material-symbols-outlined\">{{ entry.iconName }}</span>\n </div>\n\n <div class=\"nvb-file-upload__entry-content\">\n <p class=\"nvb-file-upload__entry-name\">{{ entry.meta.name }}</p>\n <p class=\"nvb-file-upload__entry-meta\">\n {{ entry.meta.type || ('files.unknownType' | uiT: 'unknown') }}\n <span>&bull;</span>\n {{ formatSize(entry.meta.size) }}\n </p>\n\n @if (resolveStatusText(entry); as statusText) {\n @if (statusText) {\n <p class=\"nvb-file-upload__entry-status\">{{ statusText | uiT: statusText }}</p>\n }\n }\n </div>\n </button>\n\n <div class=\"nvb-file-upload__entry-actions\">\n @if (canPreviewEntry(entry)) {\n <button\n type=\"button\"\n class=\"nvb-file-upload__icon-action\"\n [disabled]=\"requestInFlight()\"\n (click)=\"previewFile(entry, $event)\"\n [attr.aria-label]=\"'files.preview' | uiT: 'Preview'\"\n [attr.data-testid]=\"tid('preview', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">visibility</span>\n </button>\n }\n\n @if (canDownload(entry)) {\n <button\n type=\"button\"\n class=\"nvb-file-upload__icon-action\"\n [disabled]=\"requestInFlight()\"\n (click)=\"downloadFile(entry, $event)\"\n [attr.aria-label]=\"'files.download' | uiT: 'Download'\"\n [attr.data-testid]=\"tid('download', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">download</span>\n </button>\n }\n\n <button\n type=\"button\"\n class=\"nvb-file-upload__remove\"\n [disabled]=\"requestInFlight()\"\n (click)=\"removeFile(itemIndex, $event)\"\n [attr.aria-label]=\"'files.remove' | uiT: 'Remove'\"\n [attr.data-testid]=\"tid('remove', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </div>\n </li>\n }\n </ul>\n }\n </section>\n\n @if (previewOpen()) {\n <div\n class=\"nvb-file-upload__preview-backdrop\"\n [attr.data-testid]=\"tid('preview-backdrop')\"\n (click)=\"closePreview()\"\n >\n <div\n class=\"nvb-file-upload__preview-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"file-upload-preview-title\"\n [attr.data-testid]=\"tid('preview-dialog')\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"nvb-file-upload__preview-header\">\n <p class=\"nvb-file-upload__preview-title\" id=\"file-upload-preview-title\">\n {{ previewName() }}\n </p>\n <div class=\"nvb-file-upload__preview-header-actions\">\n <button\n type=\"button\"\n class=\"nvb-file-upload__preview-action\"\n (click)=\"downloadPreview($event)\"\n [attr.aria-label]=\"'files.download' | uiT: 'Download'\"\n [attr.data-testid]=\"tid('preview-download')\"\n >\n <span class=\"material-symbols-outlined\">download</span>\n <span>{{ 'files.download' | uiT: 'Download' }}</span>\n </button>\n <button\n type=\"button\"\n class=\"nvb-file-upload__preview-close\"\n (click)=\"closePreview($event)\"\n [attr.aria-label]=\"'files.closePreview' | uiT: 'Close preview'\"\n [attr.data-testid]=\"tid('preview-close')\"\n >\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </div>\n </div>\n\n <div class=\"nvb-file-upload__preview-body\">\n @if (previewKind() === 'image') {\n <img [src]=\"previewUrl()\" [alt]=\"previewName()\" />\n } @else if (previewKind() === 'pdf') {\n <iframe [src]=\"previewFrameUrl()\" [attr.title]=\"previewName()\"></iframe>\n }\n </div>\n </div>\n </div>\n }\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-file-upload-wrap{width:100%;display:grid;gap:10px}.nvb-file-upload{border:1px dashed var(--nvb-color-neutral-400);border-radius:var(--nvb-card-radius);background:var(--nvb-color-neutral-050);min-height:110px;display:grid;justify-items:center;align-content:center;gap:6px;text-align:center;cursor:pointer;padding:14px;transition:border-color .16s ease,background-color .16s ease,box-shadow .16s ease}.nvb-file-upload:hover,.nvb-file-upload--drag-over{border-color:var(--nvb-color-primary-500);background:color-mix(in oklab,var(--nvb-color-primary-500) 12%,var(--nvb-color-surface-mix-target, white))}.nvb-file-upload--compact{min-height:88px;padding:10px}.nvb-file-upload--modern{box-shadow:var(--nvb-card-shadow)}.nvb-file-upload--grid{min-height:124px}.nvb-file-upload__icon{font-size:26px;color:var(--nvb-color-primary-600)}.nvb-file-upload__label{margin:0;font-size:13px;color:var(--nvb-color-neutral-700);line-height:1.4;white-space:pre-wrap}.nvb-file-upload__accept{margin:0;font-size:11px;color:var(--nvb-color-neutral-500);line-height:1.35;word-break:break-word}.nvb-file-upload__list{list-style:none;margin:0;padding:0}.nvb-file-upload__list--compact,.nvb-file-upload__list--modern{display:grid;gap:8px}.nvb-file-upload__list--grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.nvb-file-upload__list li{display:flex;align-items:center;justify-content:space-between;gap:10px;border:1px solid var(--nvb-color-neutral-300);border-radius:var(--nvb-control-radius);background:var(--nvb-color-neutral-000);padding:8px 10px}.nvb-file-upload__list--grid li{min-height:148px;align-items:stretch;flex-direction:column;justify-content:space-between}.nvb-file-upload__list-item--pending{border-color:color-mix(in oklab,var(--nvb-color-primary-500) 30%,var(--nvb-color-neutral-300))}.nvb-file-upload__list-item--error{border-color:color-mix(in oklab,var(--nvb-color-danger-500, #dc2626) 35%,var(--nvb-color-neutral-300))}.nvb-file-upload__entry-main{border:none;background:transparent;padding:0;display:flex;align-items:center;gap:10px;min-width:0;text-align:left;width:100%}.nvb-file-upload__entry-main:disabled{cursor:default}.nvb-file-upload__entry-main--interactive{cursor:pointer}.nvb-file-upload__list--grid .nvb-file-upload__entry-main{flex-direction:column;align-items:flex-start}.nvb-file-upload__thumb{width:40px;height:40px;border-radius:var(--nvb-control-radius);border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-100);display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.nvb-file-upload__list--grid .nvb-file-upload__thumb{width:48px;height:48px}.nvb-file-upload__thumb span.material-symbols-outlined{font-size:22px;color:var(--nvb-color-neutral-600)}.nvb-file-upload__entry-content{min-width:0;display:grid;gap:3px}.nvb-file-upload__entry-name,.nvb-file-upload__entry-meta,.nvb-file-upload__entry-status,.nvb-file-upload__preview-title{margin:0;line-height:1.35}.nvb-file-upload__entry-name{font-size:12px;color:var(--nvb-color-neutral-800);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:280px}.nvb-file-upload__list--grid .nvb-file-upload__entry-name{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;max-width:none}.nvb-file-upload__entry-meta{font-size:11px;color:var(--nvb-color-neutral-500);display:inline-flex;align-items:center;gap:4px;flex-wrap:wrap}.nvb-file-upload__entry-status{font-size:11px;color:var(--nvb-color-primary-600)}.nvb-file-upload__list-item--error .nvb-file-upload__entry-status{color:var(--nvb-color-danger-600, #b91c1c)}.nvb-file-upload__entry-actions{display:inline-flex;align-items:center;gap:4px;flex:0 0 auto}.nvb-file-upload__list--grid .nvb-file-upload__entry-actions{width:100%;justify-content:flex-end}.nvb-file-upload__icon-action,.nvb-file-upload__remove,.nvb-file-upload__preview-close{border:1px solid transparent;background:transparent;color:var(--nvb-color-neutral-500);width:32px;height:32px;border-radius:var(--nvb-control-radius);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.nvb-file-upload__icon-action:hover,.nvb-file-upload__remove:hover,.nvb-file-upload__preview-close:hover{background:var(--nvb-color-neutral-100);color:var(--nvb-color-neutral-900)}.nvb-file-upload__icon-action:focus-visible,.nvb-file-upload__remove:focus-visible,.nvb-file-upload__preview-close:focus-visible{outline:0;box-shadow:var(--nvb-focus-ring)}.nvb-file-upload__icon-action:disabled,.nvb-file-upload__remove:disabled{cursor:not-allowed;opacity:.55}.nvb-file-upload__icon-action span,.nvb-file-upload__remove span,.nvb-file-upload__preview-close span{font-size:18px}.nvb-file-upload__preview-backdrop{position:fixed;inset:0;z-index:1000;background:#0f172a5c;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px);display:flex;align-items:center;justify-content:center;padding:20px}.nvb-file-upload__preview-dialog{width:min(1440px,100%);max-width:100%;max-height:calc(100vh - 32px);min-height:min(88vh,960px);background:var(--nvb-color-neutral-000);border:1px solid var(--nvb-color-neutral-200);border-radius:var(--nvb-dialog-radius);overflow:hidden;display:grid;grid-template-rows:auto minmax(0,1fr);box-shadow:var(--nvb-shadow-16);outline:0}.nvb-file-upload__preview-header{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:20px 24px 12px;border-bottom:1px solid var(--nvb-color-neutral-200)}.nvb-file-upload__preview-title{margin:0;font-size:16px;line-height:22px;font-weight:600;color:var(--nvb-color-neutral-900);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nvb-file-upload__preview-header-actions{display:inline-flex;align-items:center;gap:8px}.nvb-file-upload__preview-action{border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000);color:var(--nvb-color-neutral-800);min-height:32px;border-radius:var(--nvb-button-radius);padding:0 12px;display:inline-flex;align-items:center;gap:6px;cursor:pointer;font-size:13px;font-weight:600;line-height:20px;transition:background-color .16s ease,border-color .16s ease,color .16s ease}.nvb-file-upload__preview-action:hover{background:var(--nvb-color-neutral-050);border-color:var(--nvb-color-neutral-400)}.nvb-file-upload__preview-action span.material-symbols-outlined{font-size:18px}.nvb-file-upload__preview-body{min-height:0;overflow:auto;background:#0f172a;padding:12px;display:flex;align-items:center;justify-content:center}.nvb-file-upload__preview-body img{display:block;max-width:100%;max-height:calc(100vh - 140px);object-fit:contain;height:auto;margin:0 auto}.nvb-file-upload__preview-body iframe{display:block;width:100%;min-height:calc(100vh - 140px);border:none;background:var(--nvb-color-neutral-000)}\n"],dependencies:[{kind:"component",type:_,selector:"element-wrapper",inputs:["model","controlIdInput","labelForInput","groupRole","showTextWrapperInput"],exportAs:["elementWrapper"]},{kind:"directive",type:x,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"pipe",type:w,name:"dynamicText"},{kind:"pipe",type:y,name:"uiT"}],changeDetection:p.ChangeDetectionStrategy.OnPush})};p.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.2.1",ngImport:p,type:h,decorators:[{type:U,args:[{selector:"file-upload-element",changeDetection:R.OnPush,imports:[_,x,w,y],template:"<element-wrapper [model]=\"model()\" #fieldWrapper=\"elementWrapper\">\n <section class=\"nvb-file-upload-wrap\" [attr.data-testid]=\"tid('root')\">\n <input\n #fileInput\n [id]=\"fieldWrapper.controlId()\"\n type=\"file\"\n [accept]=\"model().accept\"\n [multiple]=\"model().multiple\"\n hidden\n [attr.aria-describedby]=\"fieldWrapper.describedByIds(fieldWrapper.partId('dropzone-hint'))\"\n [attr.aria-errormessage]=\"fieldWrapper.isInvalid() ? fieldWrapper.errorId() : null\"\n [attr.aria-invalid]=\"fieldWrapper.isInvalid() ? 'true' : null\"\n [attr.aria-required]=\"model().required ? 'true' : null\"\n [attr.data-testid]=\"tid('input')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"onFileInputChange($event)\"\n />\n\n <div\n class=\"nvb-file-upload\"\n [ngClass]=\"{\n 'nvb-file-upload--drag-over': isDragOver(),\n 'nvb-file-upload--compact': resolveDisplayMode() === 'compact',\n 'nvb-file-upload--modern': resolveDisplayMode() === 'modern',\n 'nvb-file-upload--grid': resolveDisplayMode() === 'grid',\n }\"\n (click)=\"openPicker()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-labelledby]=\"fieldWrapper.hasLabelText() ? fieldWrapper.labelId() : null\"\n [attr.aria-label]=\"\n fieldWrapper.hasLabelText() ? null : (model().dropzoneText | dynamicText: model())\n \"\n [attr.aria-describedby]=\"fieldWrapper.describedByIds(fieldWrapper.partId('dropzone-hint'))\"\n [attr.data-testid]=\"tid('dropzone')\"\n (keydown.enter)=\"openPicker()\"\n (keydown.space)=\"openPicker(); $event.preventDefault()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n >\n <span class=\"material-symbols-outlined nvb-file-upload__icon\">upload_file</span>\n <p class=\"nvb-file-upload__label\">{{ model().dropzoneText | dynamicText: model() }}</p>\n\n @if (model().accept) {\n <p class=\"nvb-file-upload__accept\">{{ model().accept }}</p>\n }\n <span [id]=\"fieldWrapper.partId('dropzone-hint')\" class=\"nvb-sr-only\">\n {{ 'files.dropzoneHint' | uiT: 'Drag files here or press Enter to choose files.' }}\n </span>\n </div>\n\n @if (previewItems().length > 0) {\n <ul\n class=\"nvb-file-upload__list\"\n [ngClass]=\"{\n 'nvb-file-upload__list--compact': resolveDisplayMode() === 'compact',\n 'nvb-file-upload__list--modern': resolveDisplayMode() === 'modern',\n 'nvb-file-upload__list--grid': resolveDisplayMode() === 'grid',\n }\"\n >\n @for (entry of previewItems(); track entry.id; let itemIndex = $index) {\n <li\n [ngClass]=\"{\n 'nvb-file-upload__list-item--pending': entry.status === 'pending',\n 'nvb-file-upload__list-item--error': entry.status === 'error',\n }\"\n >\n <button\n type=\"button\"\n class=\"nvb-file-upload__entry-main\"\n [class.nvb-file-upload__entry-main--interactive]=\"canOpenEntry(entry)\"\n [disabled]=\"!canOpenEntry(entry)\"\n [attr.aria-label]=\"entry.meta.name\"\n [attr.data-testid]=\"tid('entry', itemIndex)\"\n (click)=\"onEntryActivate(entry, $event)\"\n >\n <div class=\"nvb-file-upload__thumb\" [attr.data-file-icon]=\"entry.iconName\">\n <span class=\"material-symbols-outlined\">{{ entry.iconName }}</span>\n </div>\n\n <div class=\"nvb-file-upload__entry-content\">\n <p class=\"nvb-file-upload__entry-name\">{{ entry.meta.name }}</p>\n <p class=\"nvb-file-upload__entry-meta\">\n {{ entry.meta.type || ('files.unknownType' | uiT: 'unknown') }}\n <span>&bull;</span>\n {{ formatSize(entry.meta.size) }}\n </p>\n\n @if (resolveStatusText(entry); as statusText) {\n @if (statusText) {\n <p class=\"nvb-file-upload__entry-status\">{{ statusText | uiT: statusText }}</p>\n }\n }\n </div>\n </button>\n\n <div class=\"nvb-file-upload__entry-actions\">\n @if (canPreviewEntry(entry)) {\n <button\n type=\"button\"\n class=\"nvb-file-upload__icon-action\"\n [disabled]=\"requestInFlight()\"\n (click)=\"previewFile(entry, $event)\"\n [attr.aria-label]=\"'files.preview' | uiT: 'Preview'\"\n [attr.data-testid]=\"tid('preview', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">visibility</span>\n </button>\n }\n\n @if (canDownload(entry)) {\n <button\n type=\"button\"\n class=\"nvb-file-upload__icon-action\"\n [disabled]=\"requestInFlight()\"\n (click)=\"downloadFile(entry, $event)\"\n [attr.aria-label]=\"'files.download' | uiT: 'Download'\"\n [attr.data-testid]=\"tid('download', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">download</span>\n </button>\n }\n\n <button\n type=\"button\"\n class=\"nvb-file-upload__remove\"\n [disabled]=\"requestInFlight()\"\n (click)=\"removeFile(itemIndex, $event)\"\n [attr.aria-label]=\"'files.remove' | uiT: 'Remove'\"\n [attr.data-testid]=\"tid('remove', itemIndex)\"\n >\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </div>\n </li>\n }\n </ul>\n }\n </section>\n\n @if (previewOpen()) {\n <div\n class=\"nvb-file-upload__preview-backdrop\"\n [attr.data-testid]=\"tid('preview-backdrop')\"\n (click)=\"closePreview()\"\n >\n <div\n class=\"nvb-file-upload__preview-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"file-upload-preview-title\"\n [attr.data-testid]=\"tid('preview-dialog')\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"nvb-file-upload__preview-header\">\n <p class=\"nvb-file-upload__preview-title\" id=\"file-upload-preview-title\">\n {{ previewName() }}\n </p>\n <div class=\"nvb-file-upload__preview-header-actions\">\n <button\n type=\"button\"\n class=\"nvb-file-upload__preview-action\"\n (click)=\"downloadPreview($event)\"\n [attr.aria-label]=\"'files.download' | uiT: 'Download'\"\n [attr.data-testid]=\"tid('preview-download')\"\n >\n <span class=\"material-symbols-outlined\">download</span>\n <span>{{ 'files.download' | uiT: 'Download' }}</span>\n </button>\n <button\n type=\"button\"\n class=\"nvb-file-upload__preview-close\"\n (click)=\"closePreview($event)\"\n [attr.aria-label]=\"'files.closePreview' | uiT: 'Close preview'\"\n [attr.data-testid]=\"tid('preview-close')\"\n >\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </div>\n </div>\n\n <div class=\"nvb-file-upload__preview-body\">\n @if (previewKind() === 'image') {\n <img [src]=\"previewUrl()\" [alt]=\"previewName()\" />\n } @else if (previewKind() === 'pdf') {\n <iframe [src]=\"previewFrameUrl()\" [attr.title]=\"previewName()\"></iframe>\n }\n </div>\n </div>\n </div>\n }\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-file-upload-wrap{width:100%;display:grid;gap:10px}.nvb-file-upload{border:1px dashed var(--nvb-color-neutral-400);border-radius:var(--nvb-card-radius);background:var(--nvb-color-neutral-050);min-height:110px;display:grid;justify-items:center;align-content:center;gap:6px;text-align:center;cursor:pointer;padding:14px;transition:border-color .16s ease,background-color .16s ease,box-shadow .16s ease}.nvb-file-upload:hover,.nvb-file-upload--drag-over{border-color:var(--nvb-color-primary-500);background:color-mix(in oklab,var(--nvb-color-primary-500) 12%,var(--nvb-color-surface-mix-target, white))}.nvb-file-upload--compact{min-height:88px;padding:10px}.nvb-file-upload--modern{box-shadow:var(--nvb-card-shadow)}.nvb-file-upload--grid{min-height:124px}.nvb-file-upload__icon{font-size:26px;color:var(--nvb-color-primary-600)}.nvb-file-upload__label{margin:0;font-size:13px;color:var(--nvb-color-neutral-700);line-height:1.4;white-space:pre-wrap}.nvb-file-upload__accept{margin:0;font-size:11px;color:var(--nvb-color-neutral-500);line-height:1.35;word-break:break-word}.nvb-file-upload__list{list-style:none;margin:0;padding:0}.nvb-file-upload__list--compact,.nvb-file-upload__list--modern{display:grid;gap:8px}.nvb-file-upload__list--grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.nvb-file-upload__list li{display:flex;align-items:center;justify-content:space-between;gap:10px;border:1px solid var(--nvb-color-neutral-300);border-radius:var(--nvb-control-radius);background:var(--nvb-color-neutral-000);padding:8px 10px}.nvb-file-upload__list--grid li{min-height:148px;align-items:stretch;flex-direction:column;justify-content:space-between}.nvb-file-upload__list-item--pending{border-color:color-mix(in oklab,var(--nvb-color-primary-500) 30%,var(--nvb-color-neutral-300))}.nvb-file-upload__list-item--error{border-color:color-mix(in oklab,var(--nvb-color-danger-500, #dc2626) 35%,var(--nvb-color-neutral-300))}.nvb-file-upload__entry-main{border:none;background:transparent;padding:0;display:flex;align-items:center;gap:10px;min-width:0;text-align:left;width:100%}.nvb-file-upload__entry-main:disabled{cursor:default}.nvb-file-upload__entry-main--interactive{cursor:pointer}.nvb-file-upload__list--grid .nvb-file-upload__entry-main{flex-direction:column;align-items:flex-start}.nvb-file-upload__thumb{width:40px;height:40px;border-radius:var(--nvb-control-radius);border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-100);display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.nvb-file-upload__list--grid .nvb-file-upload__thumb{width:48px;height:48px}.nvb-file-upload__thumb span.material-symbols-outlined{font-size:22px;color:var(--nvb-color-neutral-600)}.nvb-file-upload__entry-content{min-width:0;display:grid;gap:3px}.nvb-file-upload__entry-name,.nvb-file-upload__entry-meta,.nvb-file-upload__entry-status,.nvb-file-upload__preview-title{margin:0;line-height:1.35}.nvb-file-upload__entry-name{font-size:12px;color:var(--nvb-color-neutral-800);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:280px}.nvb-file-upload__list--grid .nvb-file-upload__entry-name{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;max-width:none}.nvb-file-upload__entry-meta{font-size:11px;color:var(--nvb-color-neutral-500);display:inline-flex;align-items:center;gap:4px;flex-wrap:wrap}.nvb-file-upload__entry-status{font-size:11px;color:var(--nvb-color-primary-600)}.nvb-file-upload__list-item--error .nvb-file-upload__entry-status{color:var(--nvb-color-danger-600, #b91c1c)}.nvb-file-upload__entry-actions{display:inline-flex;align-items:center;gap:4px;flex:0 0 auto}.nvb-file-upload__list--grid .nvb-file-upload__entry-actions{width:100%;justify-content:flex-end}.nvb-file-upload__icon-action,.nvb-file-upload__remove,.nvb-file-upload__preview-close{border:1px solid transparent;background:transparent;color:var(--nvb-color-neutral-500);width:32px;height:32px;border-radius:var(--nvb-control-radius);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.nvb-file-upload__icon-action:hover,.nvb-file-upload__remove:hover,.nvb-file-upload__preview-close:hover{background:var(--nvb-color-neutral-100);color:var(--nvb-color-neutral-900)}.nvb-file-upload__icon-action:focus-visible,.nvb-file-upload__remove:focus-visible,.nvb-file-upload__preview-close:focus-visible{outline:0;box-shadow:var(--nvb-focus-ring)}.nvb-file-upload__icon-action:disabled,.nvb-file-upload__remove:disabled{cursor:not-allowed;opacity:.55}.nvb-file-upload__icon-action span,.nvb-file-upload__remove span,.nvb-file-upload__preview-close span{font-size:18px}.nvb-file-upload__preview-backdrop{position:fixed;inset:0;z-index:1000;background:#0f172a5c;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px);display:flex;align-items:center;justify-content:center;padding:20px}.nvb-file-upload__preview-dialog{width:min(1440px,100%);max-width:100%;max-height:calc(100vh - 32px);min-height:min(88vh,960px);background:var(--nvb-color-neutral-000);border:1px solid var(--nvb-color-neutral-200);border-radius:var(--nvb-dialog-radius);overflow:hidden;display:grid;grid-template-rows:auto minmax(0,1fr);box-shadow:var(--nvb-shadow-16);outline:0}.nvb-file-upload__preview-header{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:20px 24px 12px;border-bottom:1px solid var(--nvb-color-neutral-200)}.nvb-file-upload__preview-title{margin:0;font-size:16px;line-height:22px;font-weight:600;color:var(--nvb-color-neutral-900);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nvb-file-upload__preview-header-actions{display:inline-flex;align-items:center;gap:8px}.nvb-file-upload__preview-action{border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000);color:var(--nvb-color-neutral-800);min-height:32px;border-radius:var(--nvb-button-radius);padding:0 12px;display:inline-flex;align-items:center;gap:6px;cursor:pointer;font-size:13px;font-weight:600;line-height:20px;transition:background-color .16s ease,border-color .16s ease,color .16s ease}.nvb-file-upload__preview-action:hover{background:var(--nvb-color-neutral-050);border-color:var(--nvb-color-neutral-400)}.nvb-file-upload__preview-action span.material-symbols-outlined{font-size:18px}.nvb-file-upload__preview-body{min-height:0;overflow:auto;background:#0f172a;padding:12px;display:flex;align-items:center;justify-content:center}.nvb-file-upload__preview-body img{display:block;max-width:100%;max-height:calc(100vh - 140px);object-fit:contain;height:auto;margin:0 auto}.nvb-file-upload__preview-body iframe{display:block;width:100%;min-height:calc(100vh - 140px);border:none;background:var(--nvb-color-neutral-000)}\n"]}]}],propDecorators:{model:[{type:p.Input,args:[{isSignal:true,alias:"model",required:true}]}],fileInput:[{type:C,args:["fileInput"]}]}});export{O as n,h as t};
@@ -1 +1 @@
1
- import{o as l,r as d,rt as m,t as a}from"./ngxviewbuilder-runtime-element-wrapper-BUzRnWUH.mjs";import*as n from"@angular/core";import{ChangeDetectionStrategy as v,Component as g,computed as o,inject as b,input as u}from"@angular/core";import{NgClass as s,NgStyle as c}from"@angular/common";var p=class r{model=u.required(...ngDevMode?[{debugName:"model"}]:[]);tid=d(this.model,"nvb-icon","icon");elementActionService=b(m);iconName=o(()=>{return String(this.model()?.iconName??"").trim()||"star"},...ngDevMode?[{debugName:"iconName"}]:[]);iconStyle=o(()=>{const e=this.resolveSize(this.model()?.iconSize,24);const t=String(this.model()?.iconColor??"").trim();return{width:`${e+18}px`,height:`${e+18}px`,color:t||"var(--nvb-color-neutral-700)","font-size":`${e}px`}},...ngDevMode?[{debugName:"iconStyle"}]:[]);previewStyle=o(()=>{const e=this.resolveSize(this.model()?.previewSize,64);const t=String(this.model()?.iconColor??"").trim();return{width:`${e+20}px`,height:`${e+20}px`,color:t||"var(--nvb-color-neutral-700)","font-size":`${e}px`}},...ngDevMode?[{debugName:"previewStyle"}]:[]);onIconClick(e){e.preventDefault();e.stopPropagation();const t={value:this.iconName(),item:null,row:null};const i=String(this.model().name??"").trim();if(i)t[i]=this.iconName();this.elementActionService.runActions(this.model(),this.model().events??[],"click",t)}resolveSize(e,t){const i=Number(e);if(!Number.isFinite(i)||i<=0)return t;return Math.floor(i)}static ɵfac=n.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.2.1",ngImport:n,type:r,deps:[],target:n.ɵɵFactoryTarget.Component});static ɵcmp=n.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.2.1",type:r,isStandalone:true,selector:"icon-element",inputs:{model:{classPropertyName:"model",publicName:"model",isSignal:true,isRequired:true,transformFunction:null}},ngImport:n,template:"<element-wrapper [model]=\"model()\">\n <section class=\"nvb-icon-wrap\" [attr.data-testid]=\"tid('root')\">\n <button [attr.data-testid]=\"tid('icon')\"\n type=\"button\"\n class=\"nvb-icon\"\n [ngClass]=\"{ 'nvb-icon--filled': model().filled }\"\n [ngStyle]=\"iconStyle()\"\n (click)=\"onIconClick($event)\"\n >\n <nvb-icon [name]=\"iconName()\"></nvb-icon>\n </button>\n\n @if (model().showPreview) {\n <div class=\"nvb-icon__preview\" [ngStyle]=\"previewStyle()\">\n <nvb-icon [name]=\"iconName()\"></nvb-icon>\n </div>\n }\n </section>\n</element-wrapper>\n",styles:[':host{display:block;width:100%}.nvb-icon-wrap{width:100%;display:inline-flex;align-items:center;gap:10px;flex-wrap:wrap}.nvb-icon,.nvb-icon__preview{border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000);border-radius:var(--nvb-radius-lg);display:inline-flex;align-items:center;justify-content:center}.nvb-icon{cursor:pointer;min-width:42px;min-height:42px;padding:0}.nvb-icon span,.nvb-icon__preview span{line-height:1}.nvb-icon--filled span{font-variation-settings:"FILL" 1,"wght" 400,"GRAD" 0,"opsz" 24}\n'],dependencies:[{kind:"component",type:a,selector:"element-wrapper",inputs:["model","controlIdInput","labelForInput","groupRole","showTextWrapperInput"],exportAs:["elementWrapper"]},{kind:"directive",type:s,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:c,selector:"[ngStyle]",inputs:["ngStyle"]},{kind:"component",type:l,selector:"nvb-icon",inputs:["name","svg","ariaLabel"]}],changeDetection:n.ChangeDetectionStrategy.OnPush})};n.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.2.1",ngImport:n,type:p,decorators:[{type:g,args:[{selector:"icon-element",changeDetection:v.OnPush,imports:[a,s,c,l],template:"<element-wrapper [model]=\"model()\">\n <section class=\"nvb-icon-wrap\" [attr.data-testid]=\"tid('root')\">\n <button [attr.data-testid]=\"tid('icon')\"\n type=\"button\"\n class=\"nvb-icon\"\n [ngClass]=\"{ 'nvb-icon--filled': model().filled }\"\n [ngStyle]=\"iconStyle()\"\n (click)=\"onIconClick($event)\"\n >\n <nvb-icon [name]=\"iconName()\"></nvb-icon>\n </button>\n\n @if (model().showPreview) {\n <div class=\"nvb-icon__preview\" [ngStyle]=\"previewStyle()\">\n <nvb-icon [name]=\"iconName()\"></nvb-icon>\n </div>\n }\n </section>\n</element-wrapper>\n",styles:[':host{display:block;width:100%}.nvb-icon-wrap{width:100%;display:inline-flex;align-items:center;gap:10px;flex-wrap:wrap}.nvb-icon,.nvb-icon__preview{border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000);border-radius:var(--nvb-radius-lg);display:inline-flex;align-items:center;justify-content:center}.nvb-icon{cursor:pointer;min-width:42px;min-height:42px;padding:0}.nvb-icon span,.nvb-icon__preview span{line-height:1}.nvb-icon--filled span{font-variation-settings:"FILL" 1,"wght" 400,"GRAD" 0,"opsz" 24}\n']}]}],propDecorators:{model:[{type:n.Input,args:[{isSignal:true,alias:"model",required:true}]}]}});export{p as IconElement};
1
+ import{o as l,r as d,rt as m,t as a}from"./ngxviewbuilder-runtime-element-wrapper-D0lfZvuW.mjs";import*as n from"@angular/core";import{ChangeDetectionStrategy as v,Component as g,computed as o,inject as b,input as u}from"@angular/core";import{NgClass as s,NgStyle as c}from"@angular/common";var p=class r{model=u.required(...ngDevMode?[{debugName:"model"}]:[]);tid=d(this.model,"nvb-icon","icon");elementActionService=b(m);iconName=o(()=>{return String(this.model()?.iconName??"").trim()||"star"},...ngDevMode?[{debugName:"iconName"}]:[]);iconStyle=o(()=>{const e=this.resolveSize(this.model()?.iconSize,24);const t=String(this.model()?.iconColor??"").trim();return{width:`${e+18}px`,height:`${e+18}px`,color:t||"var(--nvb-color-neutral-700)","font-size":`${e}px`}},...ngDevMode?[{debugName:"iconStyle"}]:[]);previewStyle=o(()=>{const e=this.resolveSize(this.model()?.previewSize,64);const t=String(this.model()?.iconColor??"").trim();return{width:`${e+20}px`,height:`${e+20}px`,color:t||"var(--nvb-color-neutral-700)","font-size":`${e}px`}},...ngDevMode?[{debugName:"previewStyle"}]:[]);onIconClick(e){e.preventDefault();e.stopPropagation();const t={value:this.iconName(),item:null,row:null};const i=String(this.model().name??"").trim();if(i)t[i]=this.iconName();this.elementActionService.runActions(this.model(),this.model().events??[],"click",t)}resolveSize(e,t){const i=Number(e);if(!Number.isFinite(i)||i<=0)return t;return Math.floor(i)}static ɵfac=n.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.2.1",ngImport:n,type:r,deps:[],target:n.ɵɵFactoryTarget.Component});static ɵcmp=n.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.2.1",type:r,isStandalone:true,selector:"icon-element",inputs:{model:{classPropertyName:"model",publicName:"model",isSignal:true,isRequired:true,transformFunction:null}},ngImport:n,template:"<element-wrapper [model]=\"model()\">\n <section class=\"nvb-icon-wrap\" [attr.data-testid]=\"tid('root')\">\n <button [attr.data-testid]=\"tid('icon')\"\n type=\"button\"\n class=\"nvb-icon\"\n [ngClass]=\"{ 'nvb-icon--filled': model().filled }\"\n [ngStyle]=\"iconStyle()\"\n (click)=\"onIconClick($event)\"\n >\n <nvb-icon [name]=\"iconName()\"></nvb-icon>\n </button>\n\n @if (model().showPreview) {\n <div class=\"nvb-icon__preview\" [ngStyle]=\"previewStyle()\">\n <nvb-icon [name]=\"iconName()\"></nvb-icon>\n </div>\n }\n </section>\n</element-wrapper>\n",styles:[':host{display:block;width:100%}.nvb-icon-wrap{width:100%;display:inline-flex;align-items:center;gap:10px;flex-wrap:wrap}.nvb-icon,.nvb-icon__preview{border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000);border-radius:var(--nvb-radius-lg);display:inline-flex;align-items:center;justify-content:center}.nvb-icon{cursor:pointer;min-width:42px;min-height:42px;padding:0}.nvb-icon span,.nvb-icon__preview span{line-height:1}.nvb-icon--filled span{font-variation-settings:"FILL" 1,"wght" 400,"GRAD" 0,"opsz" 24}\n'],dependencies:[{kind:"component",type:a,selector:"element-wrapper",inputs:["model","controlIdInput","labelForInput","groupRole","showTextWrapperInput"],exportAs:["elementWrapper"]},{kind:"directive",type:s,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:c,selector:"[ngStyle]",inputs:["ngStyle"]},{kind:"component",type:l,selector:"nvb-icon",inputs:["name","svg","ariaLabel"]}],changeDetection:n.ChangeDetectionStrategy.OnPush})};n.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.2.1",ngImport:n,type:p,decorators:[{type:g,args:[{selector:"icon-element",changeDetection:v.OnPush,imports:[a,s,c,l],template:"<element-wrapper [model]=\"model()\">\n <section class=\"nvb-icon-wrap\" [attr.data-testid]=\"tid('root')\">\n <button [attr.data-testid]=\"tid('icon')\"\n type=\"button\"\n class=\"nvb-icon\"\n [ngClass]=\"{ 'nvb-icon--filled': model().filled }\"\n [ngStyle]=\"iconStyle()\"\n (click)=\"onIconClick($event)\"\n >\n <nvb-icon [name]=\"iconName()\"></nvb-icon>\n </button>\n\n @if (model().showPreview) {\n <div class=\"nvb-icon__preview\" [ngStyle]=\"previewStyle()\">\n <nvb-icon [name]=\"iconName()\"></nvb-icon>\n </div>\n }\n </section>\n</element-wrapper>\n",styles:[':host{display:block;width:100%}.nvb-icon-wrap{width:100%;display:inline-flex;align-items:center;gap:10px;flex-wrap:wrap}.nvb-icon,.nvb-icon__preview{border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000);border-radius:var(--nvb-radius-lg);display:inline-flex;align-items:center;justify-content:center}.nvb-icon{cursor:pointer;min-width:42px;min-height:42px;padding:0}.nvb-icon span,.nvb-icon__preview span{line-height:1}.nvb-icon--filled span{font-variation-settings:"FILL" 1,"wght" 400,"GRAD" 0,"opsz" 24}\n']}]}],propDecorators:{model:[{type:n.Input,args:[{isSignal:true,alias:"model",required:true}]}]}});export{p as IconElement};
@@ -1 +1 @@
1
- import{t as i}from"./ngxviewbuilder-runtime-rolldown-runtime-DpJrqANO.mjs";import{n as a,t}from"./ngxviewbuilder-runtime-dynamic-text.pipe-BUJ4fCqt.mjs";import{ht as m,r as d,t as l}from"./ngxviewbuilder-runtime-element-wrapper-BUzRnWUH.mjs";import*as e from"@angular/core";import{ChangeDetectionStrategy as s,Component as c,inject as p,input as u}from"@angular/core";var f=i({IframeElement:()=>r});var r=class n{model=u.required(...ngDevMode?[{debugName:"model"}]:[]);tid=d(this.model,"nvb-iframe","iframe");markupSecurityService=p(m);resolveIframeSrc(o){return this.markupSecurityService.sanitizeIframeUrl(o)}static ɵfac=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.2.1",ngImport:e,type:n,deps:[],target:e.ɵɵFactoryTarget.Component});static ɵcmp=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.2.1",type:n,isStandalone:true,selector:"iframe-element",inputs:{model:{classPropertyName:"model",publicName:"model",isSignal:true,isRequired:true,transformFunction:null}},ngImport:e,template:"<element-wrapper [model]=\"model()\">\n <section class=\"nvb-iframe\" [attr.data-testid]=\"tid('root')\">\n @let iframeSrc = (model().src | dynamicText: model()).trim();\n @if (iframeSrc) {\n @if (resolveIframeSrc(iframeSrc); as safeIframeSrc) {\n <iframe\n class=\"nvb-iframe__frame\"\n [attr.src]=\"safeIframeSrc\"\n [title]=\"(model().title | dynamicText: model()) || ('iframe.titleDefault' | uiT: 'Embedded content')\"\n [style.height]=\"model().frameHeight || '360px'\"\n [style.border-width]=\"model().borderless ? '0' : '1px'\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [attr.referrerpolicy]=\"model().referrerPolicy || null\"\n [attr.allow]=\"model().allow || null\"\n [attr.sandbox]=\"model().sandbox || null\"\n [attr.allowfullscreen]=\"model().allowFullscreen ? '' : null\"\n ></iframe>\n } @else {\n <div class=\"nvb-iframe__empty\">\n {{ 'iframe.blocked' | uiT: 'Blocked insecure iframe source.' }}\n </div>\n }\n } @else {\n <div class=\"nvb-iframe__empty\">{{ 'iframe.noSource' | uiT: 'No iframe source configured.' }}</div>\n }\n </section>\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-iframe{width:100%}.nvb-iframe__frame{width:100%;min-height:220px;border-radius:var(--nvb-radius-lg);border-style:solid;border-color:var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000)}.nvb-iframe__empty{min-height:160px;display:grid;place-items:center;padding:18px;border:1px dashed var(--nvb-color-neutral-300);border-radius:var(--nvb-radius-lg);color:var(--nvb-color-neutral-500);background:color-mix(in oklch,var(--nvb-color-neutral-000) 92%,var(--nvb-color-neutral-100));text-align:center}\n"],dependencies:[{kind:"component",type:l,selector:"element-wrapper",inputs:["model","controlIdInput","labelForInput","groupRole","showTextWrapperInput"],exportAs:["elementWrapper"]},{kind:"pipe",type:t,name:"dynamicText"},{kind:"pipe",type:a,name:"uiT"}],changeDetection:e.ChangeDetectionStrategy.OnPush})};e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.2.1",ngImport:e,type:r,decorators:[{type:c,args:[{selector:"iframe-element",changeDetection:s.OnPush,imports:[l,t,a],template:"<element-wrapper [model]=\"model()\">\n <section class=\"nvb-iframe\" [attr.data-testid]=\"tid('root')\">\n @let iframeSrc = (model().src | dynamicText: model()).trim();\n @if (iframeSrc) {\n @if (resolveIframeSrc(iframeSrc); as safeIframeSrc) {\n <iframe\n class=\"nvb-iframe__frame\"\n [attr.src]=\"safeIframeSrc\"\n [title]=\"(model().title | dynamicText: model()) || ('iframe.titleDefault' | uiT: 'Embedded content')\"\n [style.height]=\"model().frameHeight || '360px'\"\n [style.border-width]=\"model().borderless ? '0' : '1px'\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [attr.referrerpolicy]=\"model().referrerPolicy || null\"\n [attr.allow]=\"model().allow || null\"\n [attr.sandbox]=\"model().sandbox || null\"\n [attr.allowfullscreen]=\"model().allowFullscreen ? '' : null\"\n ></iframe>\n } @else {\n <div class=\"nvb-iframe__empty\">\n {{ 'iframe.blocked' | uiT: 'Blocked insecure iframe source.' }}\n </div>\n }\n } @else {\n <div class=\"nvb-iframe__empty\">{{ 'iframe.noSource' | uiT: 'No iframe source configured.' }}</div>\n }\n </section>\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-iframe{width:100%}.nvb-iframe__frame{width:100%;min-height:220px;border-radius:var(--nvb-radius-lg);border-style:solid;border-color:var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000)}.nvb-iframe__empty{min-height:160px;display:grid;place-items:center;padding:18px;border:1px dashed var(--nvb-color-neutral-300);border-radius:var(--nvb-radius-lg);color:var(--nvb-color-neutral-500);background:color-mix(in oklch,var(--nvb-color-neutral-000) 92%,var(--nvb-color-neutral-100));text-align:center}\n"]}]}],propDecorators:{model:[{type:e.Input,args:[{isSignal:true,alias:"model",required:true}]}]}});export{f as n,r as t};
1
+ import{t as i}from"./ngxviewbuilder-runtime-rolldown-runtime-DpJrqANO.mjs";import{n as a,t}from"./ngxviewbuilder-runtime-dynamic-text.pipe-BUJ4fCqt.mjs";import{ht as m,r as d,t as l}from"./ngxviewbuilder-runtime-element-wrapper-D0lfZvuW.mjs";import*as e from"@angular/core";import{ChangeDetectionStrategy as s,Component as c,inject as p,input as u}from"@angular/core";var f=i({IframeElement:()=>r});var r=class n{model=u.required(...ngDevMode?[{debugName:"model"}]:[]);tid=d(this.model,"nvb-iframe","iframe");markupSecurityService=p(m);resolveIframeSrc(o){return this.markupSecurityService.sanitizeIframeUrl(o)}static ɵfac=e.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.2.1",ngImport:e,type:n,deps:[],target:e.ɵɵFactoryTarget.Component});static ɵcmp=e.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.2.1",type:n,isStandalone:true,selector:"iframe-element",inputs:{model:{classPropertyName:"model",publicName:"model",isSignal:true,isRequired:true,transformFunction:null}},ngImport:e,template:"<element-wrapper [model]=\"model()\">\n <section class=\"nvb-iframe\" [attr.data-testid]=\"tid('root')\">\n @let iframeSrc = (model().src | dynamicText: model()).trim();\n @if (iframeSrc) {\n @if (resolveIframeSrc(iframeSrc); as safeIframeSrc) {\n <iframe\n class=\"nvb-iframe__frame\"\n [attr.src]=\"safeIframeSrc\"\n [title]=\"(model().title | dynamicText: model()) || ('iframe.titleDefault' | uiT: 'Embedded content')\"\n [style.height]=\"model().frameHeight || '360px'\"\n [style.border-width]=\"model().borderless ? '0' : '1px'\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [attr.referrerpolicy]=\"model().referrerPolicy || null\"\n [attr.allow]=\"model().allow || null\"\n [attr.sandbox]=\"model().sandbox || null\"\n [attr.allowfullscreen]=\"model().allowFullscreen ? '' : null\"\n ></iframe>\n } @else {\n <div class=\"nvb-iframe__empty\">\n {{ 'iframe.blocked' | uiT: 'Blocked insecure iframe source.' }}\n </div>\n }\n } @else {\n <div class=\"nvb-iframe__empty\">{{ 'iframe.noSource' | uiT: 'No iframe source configured.' }}</div>\n }\n </section>\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-iframe{width:100%}.nvb-iframe__frame{width:100%;min-height:220px;border-radius:var(--nvb-radius-lg);border-style:solid;border-color:var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000)}.nvb-iframe__empty{min-height:160px;display:grid;place-items:center;padding:18px;border:1px dashed var(--nvb-color-neutral-300);border-radius:var(--nvb-radius-lg);color:var(--nvb-color-neutral-500);background:color-mix(in oklch,var(--nvb-color-neutral-000) 92%,var(--nvb-color-neutral-100));text-align:center}\n"],dependencies:[{kind:"component",type:l,selector:"element-wrapper",inputs:["model","controlIdInput","labelForInput","groupRole","showTextWrapperInput"],exportAs:["elementWrapper"]},{kind:"pipe",type:t,name:"dynamicText"},{kind:"pipe",type:a,name:"uiT"}],changeDetection:e.ChangeDetectionStrategy.OnPush})};e.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.2.1",ngImport:e,type:r,decorators:[{type:c,args:[{selector:"iframe-element",changeDetection:s.OnPush,imports:[l,t,a],template:"<element-wrapper [model]=\"model()\">\n <section class=\"nvb-iframe\" [attr.data-testid]=\"tid('root')\">\n @let iframeSrc = (model().src | dynamicText: model()).trim();\n @if (iframeSrc) {\n @if (resolveIframeSrc(iframeSrc); as safeIframeSrc) {\n <iframe\n class=\"nvb-iframe__frame\"\n [attr.src]=\"safeIframeSrc\"\n [title]=\"(model().title | dynamicText: model()) || ('iframe.titleDefault' | uiT: 'Embedded content')\"\n [style.height]=\"model().frameHeight || '360px'\"\n [style.border-width]=\"model().borderless ? '0' : '1px'\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [attr.referrerpolicy]=\"model().referrerPolicy || null\"\n [attr.allow]=\"model().allow || null\"\n [attr.sandbox]=\"model().sandbox || null\"\n [attr.allowfullscreen]=\"model().allowFullscreen ? '' : null\"\n ></iframe>\n } @else {\n <div class=\"nvb-iframe__empty\">\n {{ 'iframe.blocked' | uiT: 'Blocked insecure iframe source.' }}\n </div>\n }\n } @else {\n <div class=\"nvb-iframe__empty\">{{ 'iframe.noSource' | uiT: 'No iframe source configured.' }}</div>\n }\n </section>\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-iframe{width:100%}.nvb-iframe__frame{width:100%;min-height:220px;border-radius:var(--nvb-radius-lg);border-style:solid;border-color:var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-000)}.nvb-iframe__empty{min-height:160px;display:grid;place-items:center;padding:18px;border:1px dashed var(--nvb-color-neutral-300);border-radius:var(--nvb-radius-lg);color:var(--nvb-color-neutral-500);background:color-mix(in oklch,var(--nvb-color-neutral-000) 92%,var(--nvb-color-neutral-100));text-align:center}\n"]}]}],propDecorators:{model:[{type:e.Input,args:[{isSignal:true,alias:"model",required:true}]}]}});export{f as n,r as t};
@@ -1 +1 @@
1
- import{t as c}from"./ngxviewbuilder-runtime-rolldown-runtime-DpJrqANO.mjs";import{n as l,t as o}from"./ngxviewbuilder-runtime-dynamic-text.pipe-BUJ4fCqt.mjs";import{ht as p,r as g,t as s}from"./ngxviewbuilder-runtime-element-wrapper-BUzRnWUH.mjs";import*as t from"@angular/core";import{ChangeDetectionStrategy as v,Component as b,computed as u,inject as h,input as f,signal as m}from"@angular/core";import{NgStyle as d}from"@angular/common";var y=c({ImageElement:()=>a});var a=class r{model=f.required(...ngDevMode?[{debugName:"model"}]:[]);tid=g(this.model,"nvb-image","image");markupSecurityService=h(p);previewOpen=m(false,...ngDevMode?[{debugName:"previewOpen"}]:[]);previewSrc=m("",...ngDevMode?[{debugName:"previewSrc"}]:[]);resolveSafeLinkUrl(e){const i=String(e??"").trim();if(!i)return null;return this.markupSecurityService.sanitizeNavigationUrl(i)}get resolvedLinkUrl(){const e=String(this.model().linkUrl??"").trim();if(!e)return null;return this.markupSecurityService.sanitizeNavigationUrl(e)}imageFrameStyle=u(()=>{const e=this.resolveHeight();const i=this.resolveAspectRatio();const n=this.normalizeSize(this.model()?.radius,"8px");return{...e?{height:e}:{},...i?{"aspect-ratio":i}:{},"border-radius":n,...this.model()?.borderless?{border:"0"}:{},...this.model()?.shadow?{"box-shadow":"0 12px 28px rgba(15, 23, 42, 0.14)"}:{},...String(this.model()?.backgroundColor??"").trim()?{background:String(this.model()?.backgroundColor??"").trim()}:{}}},...ngDevMode?[{debugName:"imageFrameStyle"}]:[]);onImageClick(e,i){i.preventDefault();i.stopPropagation();if(!this.model().showPreview||!e||this.resolvedLinkUrl)return;this.previewSrc.set(e);this.previewOpen.set(true)}closePreview(e){e?.preventDefault();e?.stopPropagation();this.previewOpen.set(false);this.previewSrc.set("")}resolveFit(){const e=String(this.model()?.fit??"cover").trim().toLowerCase();if(e==="contain"||e==="fill"||e==="none")return e;return"cover"}resolveObjectPosition(){return String(this.model()?.objectPosition??"").trim()||"center center"}resolveCaptionAlign(){const e=String(this.model()?.captionAlign??"left").trim().toLowerCase();if(e==="center"||e==="right")return e;return"left"}resolveHeight(){if(this.resolveAspectRatio())return null;return this.normalizeSize(this.model()?.imageHeight,"220px")}resolveAspectRatio(){const e=String(this.model()?.aspectRatio??"auto").trim();if(!e||e.toLowerCase()==="auto")return null;return e}normalizeSize(e,i){const n=String(e??"").trim();if(!n)return i;if(/^-?\d+(\.\d+)?$/.test(n))return`${n}px`;return n}static ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.2.1",ngImport:t,type:r,deps:[],target:t.ɵɵFactoryTarget.Component});static ɵcmp=t.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.2.1",type:r,isStandalone:true,selector:"image-element",inputs:{model:{classPropertyName:"model",publicName:"model",isSignal:true,isRequired:true,transformFunction:null}},ngImport:t,template:"<element-wrapper [model]=\"model()\">\n @let dynamicImageSrc = (model().src | dynamicText: model()).trim();\n @let imageSrc = (model().srcFile ?? '').trim() || dynamicImageSrc;\n @let imageAlt = (model().alt | dynamicText: model()) || ('image.altDefault' | uiT: 'Image');\n @let imageTitle = (model().title | dynamicText: model()).trim();\n @let caption = (model().caption | dynamicText: model()).trim();\n @let linkUrl = resolveSafeLinkUrl((model().linkUrl | dynamicText: model()).trim());\n @let openInNewTab = model().openInNewTab;\n\n <figure class=\"nvb-image-wrap\" [attr.data-testid]=\"tid('root')\">\n <div class=\"nvb-image\" [ngStyle]=\"imageFrameStyle()\">\n @if (imageSrc) {\n @if (linkUrl) {\n <a [attr.data-testid]=\"tid('link')\"\n class=\"nvb-image__media nvb-image__media--link\"\n [href]=\"linkUrl\"\n [attr.target]=\"openInNewTab ? '_blank' : null\"\n [attr.rel]=\"openInNewTab ? 'noopener noreferrer' : null\"\n [attr.aria-label]=\"imageAlt\"\n >\n <img\n class=\"nvb-image__img\"\n [src]=\"imageSrc\"\n [alt]=\"imageAlt\"\n [attr.title]=\"imageTitle || null\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [style.object-fit]=\"resolveFit()\"\n [style.object-position]=\"resolveObjectPosition()\"\n />\n </a>\n } @else {\n <div class=\"nvb-image__media\">\n <img [attr.data-testid]=\"tid('image')\"\n class=\"nvb-image__img\"\n [src]=\"imageSrc\"\n [alt]=\"imageAlt\"\n [attr.title]=\"imageTitle || null\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [style.object-fit]=\"resolveFit()\"\n [style.object-position]=\"resolveObjectPosition()\"\n (click)=\"onImageClick(imageSrc, $event)\"\n />\n </div>\n }\n } @else {\n <div class=\"nvb-image__placeholder\">\n <span class=\"material-symbols-outlined\">image</span>\n <p>{{ 'image.noSource' | uiT: 'No image source' }}</p>\n </div>\n }\n </div>\n\n @if (caption) {\n <figcaption class=\"nvb-image__caption\" [style.text-align]=\"resolveCaptionAlign()\">\n {{ caption }}\n </figcaption>\n }\n </figure>\n\n @if (previewOpen()) {\n <div [attr.data-testid]=\"tid('close-preview')\" class=\"nvb-image-preview\" (click)=\"closePreview()\">\n <button [attr.data-testid]=\"tid('close')\" type=\"button\" class=\"nvb-image-preview__close\" (click)=\"closePreview($event)\">\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n <img [src]=\"previewSrc()\" [alt]=\"imageAlt\" />\n </div>\n }\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-image-wrap{width:100%;margin:0;display:grid;gap:8px}.nvb-image{width:100%;min-height:64px;border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-050);border-radius:var(--nvb-radius-lg);overflow:hidden;position:relative}.nvb-image__media{display:block;width:100%;height:100%;min-height:inherit}.nvb-image__media--link{text-decoration:none;color:inherit}.nvb-image__img{width:100%;height:100%;display:block;cursor:pointer}.nvb-image__placeholder{min-height:64px;display:grid;justify-items:center;align-content:center;gap:4px;color:var(--nvb-color-neutral-500);font-size:12px;padding:16px}.nvb-image__placeholder p{margin:0}.nvb-image__placeholder span{font-size:22px}.nvb-image__caption{margin:0;font-size:13px;line-height:1.5;color:var(--nvb-color-neutral-600)}.nvb-image-preview{position:fixed;inset:0;background:#000000b8;z-index:1300;display:grid;place-items:center;padding:20px}.nvb-image-preview img{max-width:min(100%,1100px);max-height:calc(100vh - 60px);border-radius:var(--nvb-radius-lg);box-shadow:0 16px 32px #0000004d;background:#fff}.nvb-image-preview__close{position:absolute;top:12px;right:12px;width:36px;height:36px;border:none;border-radius:var(--nvb-radius-lg);background:#ffffff2e;color:#fff;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.nvb-image-preview__close span{font-size:20px}\n"],dependencies:[{kind:"component",type:s,selector:"element-wrapper",inputs:["model","controlIdInput","labelForInput","groupRole","showTextWrapperInput"],exportAs:["elementWrapper"]},{kind:"directive",type:d,selector:"[ngStyle]",inputs:["ngStyle"]},{kind:"pipe",type:o,name:"dynamicText"},{kind:"pipe",type:l,name:"uiT"}],changeDetection:t.ChangeDetectionStrategy.OnPush})};t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.2.1",ngImport:t,type:a,decorators:[{type:b,args:[{selector:"image-element",changeDetection:v.OnPush,imports:[s,d,o,l],template:"<element-wrapper [model]=\"model()\">\n @let dynamicImageSrc = (model().src | dynamicText: model()).trim();\n @let imageSrc = (model().srcFile ?? '').trim() || dynamicImageSrc;\n @let imageAlt = (model().alt | dynamicText: model()) || ('image.altDefault' | uiT: 'Image');\n @let imageTitle = (model().title | dynamicText: model()).trim();\n @let caption = (model().caption | dynamicText: model()).trim();\n @let linkUrl = resolveSafeLinkUrl((model().linkUrl | dynamicText: model()).trim());\n @let openInNewTab = model().openInNewTab;\n\n <figure class=\"nvb-image-wrap\" [attr.data-testid]=\"tid('root')\">\n <div class=\"nvb-image\" [ngStyle]=\"imageFrameStyle()\">\n @if (imageSrc) {\n @if (linkUrl) {\n <a [attr.data-testid]=\"tid('link')\"\n class=\"nvb-image__media nvb-image__media--link\"\n [href]=\"linkUrl\"\n [attr.target]=\"openInNewTab ? '_blank' : null\"\n [attr.rel]=\"openInNewTab ? 'noopener noreferrer' : null\"\n [attr.aria-label]=\"imageAlt\"\n >\n <img\n class=\"nvb-image__img\"\n [src]=\"imageSrc\"\n [alt]=\"imageAlt\"\n [attr.title]=\"imageTitle || null\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [style.object-fit]=\"resolveFit()\"\n [style.object-position]=\"resolveObjectPosition()\"\n />\n </a>\n } @else {\n <div class=\"nvb-image__media\">\n <img [attr.data-testid]=\"tid('image')\"\n class=\"nvb-image__img\"\n [src]=\"imageSrc\"\n [alt]=\"imageAlt\"\n [attr.title]=\"imageTitle || null\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [style.object-fit]=\"resolveFit()\"\n [style.object-position]=\"resolveObjectPosition()\"\n (click)=\"onImageClick(imageSrc, $event)\"\n />\n </div>\n }\n } @else {\n <div class=\"nvb-image__placeholder\">\n <span class=\"material-symbols-outlined\">image</span>\n <p>{{ 'image.noSource' | uiT: 'No image source' }}</p>\n </div>\n }\n </div>\n\n @if (caption) {\n <figcaption class=\"nvb-image__caption\" [style.text-align]=\"resolveCaptionAlign()\">\n {{ caption }}\n </figcaption>\n }\n </figure>\n\n @if (previewOpen()) {\n <div [attr.data-testid]=\"tid('close-preview')\" class=\"nvb-image-preview\" (click)=\"closePreview()\">\n <button [attr.data-testid]=\"tid('close')\" type=\"button\" class=\"nvb-image-preview__close\" (click)=\"closePreview($event)\">\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n <img [src]=\"previewSrc()\" [alt]=\"imageAlt\" />\n </div>\n }\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-image-wrap{width:100%;margin:0;display:grid;gap:8px}.nvb-image{width:100%;min-height:64px;border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-050);border-radius:var(--nvb-radius-lg);overflow:hidden;position:relative}.nvb-image__media{display:block;width:100%;height:100%;min-height:inherit}.nvb-image__media--link{text-decoration:none;color:inherit}.nvb-image__img{width:100%;height:100%;display:block;cursor:pointer}.nvb-image__placeholder{min-height:64px;display:grid;justify-items:center;align-content:center;gap:4px;color:var(--nvb-color-neutral-500);font-size:12px;padding:16px}.nvb-image__placeholder p{margin:0}.nvb-image__placeholder span{font-size:22px}.nvb-image__caption{margin:0;font-size:13px;line-height:1.5;color:var(--nvb-color-neutral-600)}.nvb-image-preview{position:fixed;inset:0;background:#000000b8;z-index:1300;display:grid;place-items:center;padding:20px}.nvb-image-preview img{max-width:min(100%,1100px);max-height:calc(100vh - 60px);border-radius:var(--nvb-radius-lg);box-shadow:0 16px 32px #0000004d;background:#fff}.nvb-image-preview__close{position:absolute;top:12px;right:12px;width:36px;height:36px;border:none;border-radius:var(--nvb-radius-lg);background:#ffffff2e;color:#fff;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.nvb-image-preview__close span{font-size:20px}\n"]}]}],propDecorators:{model:[{type:t.Input,args:[{isSignal:true,alias:"model",required:true}]}]}});export{y as n,a as t};
1
+ import{t as c}from"./ngxviewbuilder-runtime-rolldown-runtime-DpJrqANO.mjs";import{n as l,t as o}from"./ngxviewbuilder-runtime-dynamic-text.pipe-BUJ4fCqt.mjs";import{ht as p,r as g,t as s}from"./ngxviewbuilder-runtime-element-wrapper-D0lfZvuW.mjs";import*as t from"@angular/core";import{ChangeDetectionStrategy as v,Component as b,computed as u,inject as h,input as f,signal as m}from"@angular/core";import{NgStyle as d}from"@angular/common";var y=c({ImageElement:()=>a});var a=class r{model=f.required(...ngDevMode?[{debugName:"model"}]:[]);tid=g(this.model,"nvb-image","image");markupSecurityService=h(p);previewOpen=m(false,...ngDevMode?[{debugName:"previewOpen"}]:[]);previewSrc=m("",...ngDevMode?[{debugName:"previewSrc"}]:[]);resolveSafeLinkUrl(e){const i=String(e??"").trim();if(!i)return null;return this.markupSecurityService.sanitizeNavigationUrl(i)}get resolvedLinkUrl(){const e=String(this.model().linkUrl??"").trim();if(!e)return null;return this.markupSecurityService.sanitizeNavigationUrl(e)}imageFrameStyle=u(()=>{const e=this.resolveHeight();const i=this.resolveAspectRatio();const n=this.normalizeSize(this.model()?.radius,"8px");return{...e?{height:e}:{},...i?{"aspect-ratio":i}:{},"border-radius":n,...this.model()?.borderless?{border:"0"}:{},...this.model()?.shadow?{"box-shadow":"0 12px 28px rgba(15, 23, 42, 0.14)"}:{},...String(this.model()?.backgroundColor??"").trim()?{background:String(this.model()?.backgroundColor??"").trim()}:{}}},...ngDevMode?[{debugName:"imageFrameStyle"}]:[]);onImageClick(e,i){i.preventDefault();i.stopPropagation();if(!this.model().showPreview||!e||this.resolvedLinkUrl)return;this.previewSrc.set(e);this.previewOpen.set(true)}closePreview(e){e?.preventDefault();e?.stopPropagation();this.previewOpen.set(false);this.previewSrc.set("")}resolveFit(){const e=String(this.model()?.fit??"cover").trim().toLowerCase();if(e==="contain"||e==="fill"||e==="none")return e;return"cover"}resolveObjectPosition(){return String(this.model()?.objectPosition??"").trim()||"center center"}resolveCaptionAlign(){const e=String(this.model()?.captionAlign??"left").trim().toLowerCase();if(e==="center"||e==="right")return e;return"left"}resolveHeight(){if(this.resolveAspectRatio())return null;return this.normalizeSize(this.model()?.imageHeight,"220px")}resolveAspectRatio(){const e=String(this.model()?.aspectRatio??"auto").trim();if(!e||e.toLowerCase()==="auto")return null;return e}normalizeSize(e,i){const n=String(e??"").trim();if(!n)return i;if(/^-?\d+(\.\d+)?$/.test(n))return`${n}px`;return n}static ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.2.1",ngImport:t,type:r,deps:[],target:t.ɵɵFactoryTarget.Component});static ɵcmp=t.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.2.1",type:r,isStandalone:true,selector:"image-element",inputs:{model:{classPropertyName:"model",publicName:"model",isSignal:true,isRequired:true,transformFunction:null}},ngImport:t,template:"<element-wrapper [model]=\"model()\">\n @let dynamicImageSrc = (model().src | dynamicText: model()).trim();\n @let imageSrc = (model().srcFile ?? '').trim() || dynamicImageSrc;\n @let imageAlt = (model().alt | dynamicText: model()) || ('image.altDefault' | uiT: 'Image');\n @let imageTitle = (model().title | dynamicText: model()).trim();\n @let caption = (model().caption | dynamicText: model()).trim();\n @let linkUrl = resolveSafeLinkUrl((model().linkUrl | dynamicText: model()).trim());\n @let openInNewTab = model().openInNewTab;\n\n <figure class=\"nvb-image-wrap\" [attr.data-testid]=\"tid('root')\">\n <div class=\"nvb-image\" [ngStyle]=\"imageFrameStyle()\">\n @if (imageSrc) {\n @if (linkUrl) {\n <a [attr.data-testid]=\"tid('link')\"\n class=\"nvb-image__media nvb-image__media--link\"\n [href]=\"linkUrl\"\n [attr.target]=\"openInNewTab ? '_blank' : null\"\n [attr.rel]=\"openInNewTab ? 'noopener noreferrer' : null\"\n [attr.aria-label]=\"imageAlt\"\n >\n <img\n class=\"nvb-image__img\"\n [src]=\"imageSrc\"\n [alt]=\"imageAlt\"\n [attr.title]=\"imageTitle || null\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [style.object-fit]=\"resolveFit()\"\n [style.object-position]=\"resolveObjectPosition()\"\n />\n </a>\n } @else {\n <div class=\"nvb-image__media\">\n <img [attr.data-testid]=\"tid('image')\"\n class=\"nvb-image__img\"\n [src]=\"imageSrc\"\n [alt]=\"imageAlt\"\n [attr.title]=\"imageTitle || null\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [style.object-fit]=\"resolveFit()\"\n [style.object-position]=\"resolveObjectPosition()\"\n (click)=\"onImageClick(imageSrc, $event)\"\n />\n </div>\n }\n } @else {\n <div class=\"nvb-image__placeholder\">\n <span class=\"material-symbols-outlined\">image</span>\n <p>{{ 'image.noSource' | uiT: 'No image source' }}</p>\n </div>\n }\n </div>\n\n @if (caption) {\n <figcaption class=\"nvb-image__caption\" [style.text-align]=\"resolveCaptionAlign()\">\n {{ caption }}\n </figcaption>\n }\n </figure>\n\n @if (previewOpen()) {\n <div [attr.data-testid]=\"tid('close-preview')\" class=\"nvb-image-preview\" (click)=\"closePreview()\">\n <button [attr.data-testid]=\"tid('close')\" type=\"button\" class=\"nvb-image-preview__close\" (click)=\"closePreview($event)\">\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n <img [src]=\"previewSrc()\" [alt]=\"imageAlt\" />\n </div>\n }\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-image-wrap{width:100%;margin:0;display:grid;gap:8px}.nvb-image{width:100%;min-height:64px;border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-050);border-radius:var(--nvb-radius-lg);overflow:hidden;position:relative}.nvb-image__media{display:block;width:100%;height:100%;min-height:inherit}.nvb-image__media--link{text-decoration:none;color:inherit}.nvb-image__img{width:100%;height:100%;display:block;cursor:pointer}.nvb-image__placeholder{min-height:64px;display:grid;justify-items:center;align-content:center;gap:4px;color:var(--nvb-color-neutral-500);font-size:12px;padding:16px}.nvb-image__placeholder p{margin:0}.nvb-image__placeholder span{font-size:22px}.nvb-image__caption{margin:0;font-size:13px;line-height:1.5;color:var(--nvb-color-neutral-600)}.nvb-image-preview{position:fixed;inset:0;background:#000000b8;z-index:1300;display:grid;place-items:center;padding:20px}.nvb-image-preview img{max-width:min(100%,1100px);max-height:calc(100vh - 60px);border-radius:var(--nvb-radius-lg);box-shadow:0 16px 32px #0000004d;background:#fff}.nvb-image-preview__close{position:absolute;top:12px;right:12px;width:36px;height:36px;border:none;border-radius:var(--nvb-radius-lg);background:#ffffff2e;color:#fff;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.nvb-image-preview__close span{font-size:20px}\n"],dependencies:[{kind:"component",type:s,selector:"element-wrapper",inputs:["model","controlIdInput","labelForInput","groupRole","showTextWrapperInput"],exportAs:["elementWrapper"]},{kind:"directive",type:d,selector:"[ngStyle]",inputs:["ngStyle"]},{kind:"pipe",type:o,name:"dynamicText"},{kind:"pipe",type:l,name:"uiT"}],changeDetection:t.ChangeDetectionStrategy.OnPush})};t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.2.1",ngImport:t,type:a,decorators:[{type:b,args:[{selector:"image-element",changeDetection:v.OnPush,imports:[s,d,o,l],template:"<element-wrapper [model]=\"model()\">\n @let dynamicImageSrc = (model().src | dynamicText: model()).trim();\n @let imageSrc = (model().srcFile ?? '').trim() || dynamicImageSrc;\n @let imageAlt = (model().alt | dynamicText: model()) || ('image.altDefault' | uiT: 'Image');\n @let imageTitle = (model().title | dynamicText: model()).trim();\n @let caption = (model().caption | dynamicText: model()).trim();\n @let linkUrl = resolveSafeLinkUrl((model().linkUrl | dynamicText: model()).trim());\n @let openInNewTab = model().openInNewTab;\n\n <figure class=\"nvb-image-wrap\" [attr.data-testid]=\"tid('root')\">\n <div class=\"nvb-image\" [ngStyle]=\"imageFrameStyle()\">\n @if (imageSrc) {\n @if (linkUrl) {\n <a [attr.data-testid]=\"tid('link')\"\n class=\"nvb-image__media nvb-image__media--link\"\n [href]=\"linkUrl\"\n [attr.target]=\"openInNewTab ? '_blank' : null\"\n [attr.rel]=\"openInNewTab ? 'noopener noreferrer' : null\"\n [attr.aria-label]=\"imageAlt\"\n >\n <img\n class=\"nvb-image__img\"\n [src]=\"imageSrc\"\n [alt]=\"imageAlt\"\n [attr.title]=\"imageTitle || null\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [style.object-fit]=\"resolveFit()\"\n [style.object-position]=\"resolveObjectPosition()\"\n />\n </a>\n } @else {\n <div class=\"nvb-image__media\">\n <img [attr.data-testid]=\"tid('image')\"\n class=\"nvb-image__img\"\n [src]=\"imageSrc\"\n [alt]=\"imageAlt\"\n [attr.title]=\"imageTitle || null\"\n [attr.loading]=\"model().loading || 'lazy'\"\n [style.object-fit]=\"resolveFit()\"\n [style.object-position]=\"resolveObjectPosition()\"\n (click)=\"onImageClick(imageSrc, $event)\"\n />\n </div>\n }\n } @else {\n <div class=\"nvb-image__placeholder\">\n <span class=\"material-symbols-outlined\">image</span>\n <p>{{ 'image.noSource' | uiT: 'No image source' }}</p>\n </div>\n }\n </div>\n\n @if (caption) {\n <figcaption class=\"nvb-image__caption\" [style.text-align]=\"resolveCaptionAlign()\">\n {{ caption }}\n </figcaption>\n }\n </figure>\n\n @if (previewOpen()) {\n <div [attr.data-testid]=\"tid('close-preview')\" class=\"nvb-image-preview\" (click)=\"closePreview()\">\n <button [attr.data-testid]=\"tid('close')\" type=\"button\" class=\"nvb-image-preview__close\" (click)=\"closePreview($event)\">\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n <img [src]=\"previewSrc()\" [alt]=\"imageAlt\" />\n </div>\n }\n</element-wrapper>\n",styles:[":host{display:block;width:100%}.nvb-image-wrap{width:100%;margin:0;display:grid;gap:8px}.nvb-image{width:100%;min-height:64px;border:1px solid var(--nvb-color-neutral-300);background:var(--nvb-color-neutral-050);border-radius:var(--nvb-radius-lg);overflow:hidden;position:relative}.nvb-image__media{display:block;width:100%;height:100%;min-height:inherit}.nvb-image__media--link{text-decoration:none;color:inherit}.nvb-image__img{width:100%;height:100%;display:block;cursor:pointer}.nvb-image__placeholder{min-height:64px;display:grid;justify-items:center;align-content:center;gap:4px;color:var(--nvb-color-neutral-500);font-size:12px;padding:16px}.nvb-image__placeholder p{margin:0}.nvb-image__placeholder span{font-size:22px}.nvb-image__caption{margin:0;font-size:13px;line-height:1.5;color:var(--nvb-color-neutral-600)}.nvb-image-preview{position:fixed;inset:0;background:#000000b8;z-index:1300;display:grid;place-items:center;padding:20px}.nvb-image-preview img{max-width:min(100%,1100px);max-height:calc(100vh - 60px);border-radius:var(--nvb-radius-lg);box-shadow:0 16px 32px #0000004d;background:#fff}.nvb-image-preview__close{position:absolute;top:12px;right:12px;width:36px;height:36px;border:none;border-radius:var(--nvb-radius-lg);background:#ffffff2e;color:#fff;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.nvb-image-preview__close span{font-size:20px}\n"]}]}],propDecorators:{model:[{type:t.Input,args:[{isSignal:true,alias:"model",required:true}]}]}});export{y as n,a as t};
@@ -1 +1 @@
1
- import{t as p}from"./ngxviewbuilder-runtime-rolldown-runtime-DpJrqANO.mjs";import{an as v,g as u,on as x}from"./ngxviewbuilder-runtime-dynamic-text.pipe-BUJ4fCqt.mjs";import{r as h,rt as g,t as m}from"./ngxviewbuilder-runtime-element-wrapper-BUzRnWUH.mjs";import*as i from"@angular/core";import{ChangeDetectionStrategy as _,Component as f,Injector as y,computed as s,effect as k,inject as r,input as w,signal as l}from"@angular/core";var S=p({ListBoxElement:()=>d});var d=class c{model=w.required(...ngDevMode?[{debugName:"model"}]:[]);tid=h(this.model,"nvb-list-box","list-box");selectedValues=l(new Set,...ngDevMode?[{debugName:"selectedValues"}]:[]);dataSourceLoaded=l(false,...ngDevMode?[{debugName:"dataSourceLoaded"}]:[]);isEditorView=l(v.isEditor(),...ngDevMode?[{debugName:"isEditorView"}]:[]);dataVersion=l(0,...ngDevMode?[{debugName:"dataVersion"}]:[]);isMultiple=s(()=>this.model()?.selectionMode==="multiple",...ngDevMode?[{debugName:"isMultiple"}]:[]);visibleOptions=s(()=>{this.dataVersion();return this.model()?.options??[]},...ngDevMode?[{debugName:"visibleOptions"}]:[]);dataSourceLoading=s(()=>Boolean(this.model().dataSource)&&!this.dataSourceLoaded()&&!this.isEditorView(),...ngDevMode?[{debugName:"dataSourceLoading"}]:[]);injector=r(y);dataService=r(x);eventService=r(u);elementActionService=r(g);onDataSourceLoadedHandler=()=>{this.dataSourceLoaded.set(true);this.dataVersion.update(e=>e+1)};onDataValueChangedHandler=()=>{this.dataVersion.update(e=>e+1)};ngOnInit(){const e=!this.model().dataSource||!!this.model().dataSourceLoaded;this.dataSourceLoaded.set(e);this.isEditorView.set(v.isEditor());this.model().afterDataSourceLoad.add(this.onDataSourceLoadedHandler);this.dataService.onValueChanged.add(this.onDataValueChangedHandler);this.eventService.afterPropertyChanged.add(this.onDataValueChangedHandler);this.syncFromValue(this.model()?.value);k(()=>{const t=String(this.model()?.dataPath??"").trim();if(!t)return;const n=this.dataService.getValue(t);if(!Object.is(this.model().value,n))this.model().value=n;this.syncFromValue(this.model()?.value)},{injector:this.injector})}ngOnDestroy(){this.model().afterDataSourceLoad.remove(this.onDataSourceLoadedHandler);this.dataService.onValueChanged.remove(this.onDataValueChangedHandler);this.eventService.afterPropertyChanged.remove(this.onDataValueChangedHandler)}isSelected(e){return this.selectedValues().has(String(e?.value??""))}onItemClick(e,t){t.preventDefault();if(this.isInteractionLocked())return;const n=String(e?.value??"");const o=new Set(this.selectedValues());if(this.isMultiple())o.has(n)?o.delete(n):o.add(n);else if(o.has(n))o.clear();else{o.clear();o.add(n)}this.selectedValues.set(o);const a=this.isMultiple()?Array.from(o):Array.from(o)[0]??null;this.model().value=a;const b=String(this.model().dataPath??"").trim();if(b)this.dataService.setValue(b,a);this.runActions("change",e)}onItemKeydown(e,t){if(t.key==="Enter"||t.key===" "){t.preventDefault();this.onItemClick(e,t)}}syncFromValue(e){if(Array.isArray(e))this.selectedValues.set(new Set(e.map(t=>String(t))));else if(e!==null&&e!==void 0&&e!=="")this.selectedValues.set(new Set([String(e)]));else this.selectedValues.set(new Set)}runActions(e,t){const n=this.model().value;const o=String(this.model().name??"").trim();const a={value:n,item:t??null,row:null};if(o)a[o]=n;this.elementActionService.runActions(this.model(),this.model().events??[],e,a)}isInteractionLocked(){const e=this.model();if(!e)return false;if(Boolean(e["__pfInteractionLocked"]))return true;return this.dataSourceLoading()||Boolean(e.disabled)||Boolean(e.readOnly)}static ɵfac=i.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.2.1",ngImport:i,type:c,deps:[],target:i.ɵɵFactoryTarget.Component});static ɵcmp=i.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.2.1",type:c,isStandalone:true,selector:"list-box-element",inputs:{model:{classPropertyName:"model",publicName:"model",isSignal:true,isRequired:true,transformFunction:null}},ngImport:i,template:"<element-wrapper [model]=\"model()\" #fieldWrapper=\"elementWrapper\">\n <div\n class=\"nvb-list-box\"\n [class.nvb-list-box--disabled]=\"model().disabled\"\n [class.nvb-list-box--readonly]=\"model().readOnly\"\n [class.nvb-list-box--multiple]=\"isMultiple()\"\n [style.max-height.px]=\"model().maxHeight\"\n role=\"listbox\"\n [attr.aria-multiselectable]=\"isMultiple() ? 'true' : 'false'\"\n [attr.aria-labelledby]=\"fieldWrapper.labelId()\"\n [attr.aria-describedby]=\"fieldWrapper.describedByIds()\"\n [attr.aria-required]=\"model().required ? 'true' : null\"\n [attr.aria-invalid]=\"fieldWrapper.isInvalid() ? 'true' : null\"\n [attr.aria-busy]=\"dataSourceLoading() ? 'true' : null\"\n [attr.data-testid]=\"tid('root')\"\n >\n @if (dataSourceLoading()) {\n <div class=\"nvb-list-box__loading\" aria-live=\"polite\">\n <span class=\"nvb-list-box__loading-item\"></span>\n <span class=\"nvb-list-box__loading-item\"></span>\n <span class=\"nvb-list-box__loading-item\"></span>\n </div>\n } @else if (visibleOptions().length === 0) {\n <div class=\"nvb-list-box__empty\">{{ model().placeholder || 'No items' }}</div>\n } @else {\n @for (option of visibleOptions(); track option.value) {\n <div\n class=\"nvb-list-box__item\"\n [class.nvb-list-box__item--selected]=\"isSelected(option)\"\n [class.nvb-list-box__item--disabled]=\"model().disabled || model().readOnly\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected(option)\"\n tabindex=\"0\"\n [attr.data-testid]=\"tid('item', option.value)\"\n (click)=\"onItemClick(option, $event)\"\n (keydown)=\"onItemKeydown(option, $event)\"\n >\n @if (isMultiple()) {\n <span class=\"nvb-list-box__check\" aria-hidden=\"true\">\n @if (isSelected(option)) {\n <span class=\"material-symbols-outlined\">check</span>\n }\n </span>\n }\n <span class=\"nvb-list-box__label\">{{ option.label }}</span>\n </div>\n }\n }\n </div>\n</element-wrapper>\n",styles:['@charset "UTF-8";:host{display:block;width:100%}.nvb-list-box{border:1px solid var(--nvb-color-neutral-300);border-radius:var(--nvb-radius-md);overflow-y:auto;background:var(--nvb-color-neutral-000);width:100%;max-height:240px;transition:border-color .16s ease}.nvb-list-box:focus-within{border-color:var(--nvb-color-primary-500);box-shadow:var(--nvb-focus-ring, 0 0 0 3px color-mix(in oklab, var(--nvb-color-primary-500) 18%, transparent))}.nvb-list-box--disabled{background:var(--nvb-color-neutral-050, #f8fafc);opacity:.6;pointer-events:none}.nvb-list-box--readonly{background:var(--nvb-color-neutral-050, #f8fafc);pointer-events:none}.nvb-list-box__empty{padding:14px 16px;color:var(--nvb-color-neutral-400);font-size:13px;text-align:center}.nvb-list-box__loading{display:flex;flex-direction:column;gap:1px;padding:4px 0}.nvb-list-box__loading-item{display:block;height:36px;background:linear-gradient(90deg,color-mix(in oklab,var(--nvb-color-neutral-100) 86%,var(--nvb-color-neutral-000)) 25%,var(--nvb-color-neutral-200) 50%,color-mix(in oklab,var(--nvb-color-neutral-100) 86%,var(--nvb-color-neutral-000)) 75%);background-size:200% 100%;animation:nvb-listbox-shimmer 1.35s ease-in-out infinite}@keyframes nvb-listbox-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.nvb-list-box__item{display:flex;align-items:center;gap:8px;padding:9px 14px;cursor:pointer;font-size:14px;color:var(--nvb-color-neutral-800);-webkit-user-select:none;user-select:none;transition:background-color .1s ease,color .1s ease;border-bottom:1px solid var(--nvb-color-neutral-100);outline:0}.nvb-list-box__item:last-child{border-bottom:0}.nvb-list-box__item:hover:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 5%,var(--nvb-color-surface-mix-target, white))}.nvb-list-box__item:focus-visible:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 8%,var(--nvb-color-surface-mix-target, white));box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--nvb-color-primary-500) 40%,transparent)}.nvb-list-box__item--selected{background:color-mix(in oklab,var(--nvb-color-primary-500) 8%,var(--nvb-color-surface-mix-target, white));color:var(--nvb-color-primary-700);font-weight:600}.nvb-list-box__item--selected:hover:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 12%,var(--nvb-color-surface-mix-target, white))}.nvb-list-box__item--disabled{opacity:.45;cursor:not-allowed}.nvb-list-box__check{width:16px;height:16px;border:1.5px solid var(--nvb-color-neutral-400);border-radius:var(--nvb-radius-sm);flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:var(--nvb-color-neutral-000);transition:border-color .1s ease,background-color .1s ease}.nvb-list-box__item--selected .nvb-list-box__check{border-color:var(--nvb-color-primary-500);background:var(--nvb-color-primary-500)}.nvb-list-box__check .material-symbols-outlined{font-size:12px;color:var(--nvb-color-neutral-000);line-height:1}.nvb-list-box__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n'],dependencies:[{kind:"component",type:m,selector:"element-wrapper",inputs:["model","controlIdInput","labelForInput","groupRole","showTextWrapperInput"],exportAs:["elementWrapper"]}],changeDetection:i.ChangeDetectionStrategy.OnPush})};i.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.2.1",ngImport:i,type:d,decorators:[{type:f,args:[{selector:"list-box-element",changeDetection:_.OnPush,imports:[m],template:"<element-wrapper [model]=\"model()\" #fieldWrapper=\"elementWrapper\">\n <div\n class=\"nvb-list-box\"\n [class.nvb-list-box--disabled]=\"model().disabled\"\n [class.nvb-list-box--readonly]=\"model().readOnly\"\n [class.nvb-list-box--multiple]=\"isMultiple()\"\n [style.max-height.px]=\"model().maxHeight\"\n role=\"listbox\"\n [attr.aria-multiselectable]=\"isMultiple() ? 'true' : 'false'\"\n [attr.aria-labelledby]=\"fieldWrapper.labelId()\"\n [attr.aria-describedby]=\"fieldWrapper.describedByIds()\"\n [attr.aria-required]=\"model().required ? 'true' : null\"\n [attr.aria-invalid]=\"fieldWrapper.isInvalid() ? 'true' : null\"\n [attr.aria-busy]=\"dataSourceLoading() ? 'true' : null\"\n [attr.data-testid]=\"tid('root')\"\n >\n @if (dataSourceLoading()) {\n <div class=\"nvb-list-box__loading\" aria-live=\"polite\">\n <span class=\"nvb-list-box__loading-item\"></span>\n <span class=\"nvb-list-box__loading-item\"></span>\n <span class=\"nvb-list-box__loading-item\"></span>\n </div>\n } @else if (visibleOptions().length === 0) {\n <div class=\"nvb-list-box__empty\">{{ model().placeholder || 'No items' }}</div>\n } @else {\n @for (option of visibleOptions(); track option.value) {\n <div\n class=\"nvb-list-box__item\"\n [class.nvb-list-box__item--selected]=\"isSelected(option)\"\n [class.nvb-list-box__item--disabled]=\"model().disabled || model().readOnly\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected(option)\"\n tabindex=\"0\"\n [attr.data-testid]=\"tid('item', option.value)\"\n (click)=\"onItemClick(option, $event)\"\n (keydown)=\"onItemKeydown(option, $event)\"\n >\n @if (isMultiple()) {\n <span class=\"nvb-list-box__check\" aria-hidden=\"true\">\n @if (isSelected(option)) {\n <span class=\"material-symbols-outlined\">check</span>\n }\n </span>\n }\n <span class=\"nvb-list-box__label\">{{ option.label }}</span>\n </div>\n }\n }\n </div>\n</element-wrapper>\n",styles:['@charset "UTF-8";:host{display:block;width:100%}.nvb-list-box{border:1px solid var(--nvb-color-neutral-300);border-radius:var(--nvb-radius-md);overflow-y:auto;background:var(--nvb-color-neutral-000);width:100%;max-height:240px;transition:border-color .16s ease}.nvb-list-box:focus-within{border-color:var(--nvb-color-primary-500);box-shadow:var(--nvb-focus-ring, 0 0 0 3px color-mix(in oklab, var(--nvb-color-primary-500) 18%, transparent))}.nvb-list-box--disabled{background:var(--nvb-color-neutral-050, #f8fafc);opacity:.6;pointer-events:none}.nvb-list-box--readonly{background:var(--nvb-color-neutral-050, #f8fafc);pointer-events:none}.nvb-list-box__empty{padding:14px 16px;color:var(--nvb-color-neutral-400);font-size:13px;text-align:center}.nvb-list-box__loading{display:flex;flex-direction:column;gap:1px;padding:4px 0}.nvb-list-box__loading-item{display:block;height:36px;background:linear-gradient(90deg,color-mix(in oklab,var(--nvb-color-neutral-100) 86%,var(--nvb-color-neutral-000)) 25%,var(--nvb-color-neutral-200) 50%,color-mix(in oklab,var(--nvb-color-neutral-100) 86%,var(--nvb-color-neutral-000)) 75%);background-size:200% 100%;animation:nvb-listbox-shimmer 1.35s ease-in-out infinite}@keyframes nvb-listbox-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.nvb-list-box__item{display:flex;align-items:center;gap:8px;padding:9px 14px;cursor:pointer;font-size:14px;color:var(--nvb-color-neutral-800);-webkit-user-select:none;user-select:none;transition:background-color .1s ease,color .1s ease;border-bottom:1px solid var(--nvb-color-neutral-100);outline:0}.nvb-list-box__item:last-child{border-bottom:0}.nvb-list-box__item:hover:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 5%,var(--nvb-color-surface-mix-target, white))}.nvb-list-box__item:focus-visible:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 8%,var(--nvb-color-surface-mix-target, white));box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--nvb-color-primary-500) 40%,transparent)}.nvb-list-box__item--selected{background:color-mix(in oklab,var(--nvb-color-primary-500) 8%,var(--nvb-color-surface-mix-target, white));color:var(--nvb-color-primary-700);font-weight:600}.nvb-list-box__item--selected:hover:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 12%,var(--nvb-color-surface-mix-target, white))}.nvb-list-box__item--disabled{opacity:.45;cursor:not-allowed}.nvb-list-box__check{width:16px;height:16px;border:1.5px solid var(--nvb-color-neutral-400);border-radius:var(--nvb-radius-sm);flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:var(--nvb-color-neutral-000);transition:border-color .1s ease,background-color .1s ease}.nvb-list-box__item--selected .nvb-list-box__check{border-color:var(--nvb-color-primary-500);background:var(--nvb-color-primary-500)}.nvb-list-box__check .material-symbols-outlined{font-size:12px;color:var(--nvb-color-neutral-000);line-height:1}.nvb-list-box__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n']}]}],propDecorators:{model:[{type:i.Input,args:[{isSignal:true,alias:"model",required:true}]}]}});export{S as n,d as t};
1
+ import{t as p}from"./ngxviewbuilder-runtime-rolldown-runtime-DpJrqANO.mjs";import{an as v,g as u,on as x}from"./ngxviewbuilder-runtime-dynamic-text.pipe-BUJ4fCqt.mjs";import{r as h,rt as g,t as m}from"./ngxviewbuilder-runtime-element-wrapper-D0lfZvuW.mjs";import*as i from"@angular/core";import{ChangeDetectionStrategy as _,Component as f,Injector as y,computed as s,effect as k,inject as r,input as w,signal as l}from"@angular/core";var S=p({ListBoxElement:()=>d});var d=class c{model=w.required(...ngDevMode?[{debugName:"model"}]:[]);tid=h(this.model,"nvb-list-box","list-box");selectedValues=l(new Set,...ngDevMode?[{debugName:"selectedValues"}]:[]);dataSourceLoaded=l(false,...ngDevMode?[{debugName:"dataSourceLoaded"}]:[]);isEditorView=l(v.isEditor(),...ngDevMode?[{debugName:"isEditorView"}]:[]);dataVersion=l(0,...ngDevMode?[{debugName:"dataVersion"}]:[]);isMultiple=s(()=>this.model()?.selectionMode==="multiple",...ngDevMode?[{debugName:"isMultiple"}]:[]);visibleOptions=s(()=>{this.dataVersion();return this.model()?.options??[]},...ngDevMode?[{debugName:"visibleOptions"}]:[]);dataSourceLoading=s(()=>Boolean(this.model().dataSource)&&!this.dataSourceLoaded()&&!this.isEditorView(),...ngDevMode?[{debugName:"dataSourceLoading"}]:[]);injector=r(y);dataService=r(x);eventService=r(u);elementActionService=r(g);onDataSourceLoadedHandler=()=>{this.dataSourceLoaded.set(true);this.dataVersion.update(e=>e+1)};onDataValueChangedHandler=()=>{this.dataVersion.update(e=>e+1)};ngOnInit(){const e=!this.model().dataSource||!!this.model().dataSourceLoaded;this.dataSourceLoaded.set(e);this.isEditorView.set(v.isEditor());this.model().afterDataSourceLoad.add(this.onDataSourceLoadedHandler);this.dataService.onValueChanged.add(this.onDataValueChangedHandler);this.eventService.afterPropertyChanged.add(this.onDataValueChangedHandler);this.syncFromValue(this.model()?.value);k(()=>{const t=String(this.model()?.dataPath??"").trim();if(!t)return;const n=this.dataService.getValue(t);if(!Object.is(this.model().value,n))this.model().value=n;this.syncFromValue(this.model()?.value)},{injector:this.injector})}ngOnDestroy(){this.model().afterDataSourceLoad.remove(this.onDataSourceLoadedHandler);this.dataService.onValueChanged.remove(this.onDataValueChangedHandler);this.eventService.afterPropertyChanged.remove(this.onDataValueChangedHandler)}isSelected(e){return this.selectedValues().has(String(e?.value??""))}onItemClick(e,t){t.preventDefault();if(this.isInteractionLocked())return;const n=String(e?.value??"");const o=new Set(this.selectedValues());if(this.isMultiple())o.has(n)?o.delete(n):o.add(n);else if(o.has(n))o.clear();else{o.clear();o.add(n)}this.selectedValues.set(o);const a=this.isMultiple()?Array.from(o):Array.from(o)[0]??null;this.model().value=a;const b=String(this.model().dataPath??"").trim();if(b)this.dataService.setValue(b,a);this.runActions("change",e)}onItemKeydown(e,t){if(t.key==="Enter"||t.key===" "){t.preventDefault();this.onItemClick(e,t)}}syncFromValue(e){if(Array.isArray(e))this.selectedValues.set(new Set(e.map(t=>String(t))));else if(e!==null&&e!==void 0&&e!=="")this.selectedValues.set(new Set([String(e)]));else this.selectedValues.set(new Set)}runActions(e,t){const n=this.model().value;const o=String(this.model().name??"").trim();const a={value:n,item:t??null,row:null};if(o)a[o]=n;this.elementActionService.runActions(this.model(),this.model().events??[],e,a)}isInteractionLocked(){const e=this.model();if(!e)return false;if(Boolean(e["__pfInteractionLocked"]))return true;return this.dataSourceLoading()||Boolean(e.disabled)||Boolean(e.readOnly)}static ɵfac=i.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.2.1",ngImport:i,type:c,deps:[],target:i.ɵɵFactoryTarget.Component});static ɵcmp=i.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.2.1",type:c,isStandalone:true,selector:"list-box-element",inputs:{model:{classPropertyName:"model",publicName:"model",isSignal:true,isRequired:true,transformFunction:null}},ngImport:i,template:"<element-wrapper [model]=\"model()\" #fieldWrapper=\"elementWrapper\">\n <div\n class=\"nvb-list-box\"\n [class.nvb-list-box--disabled]=\"model().disabled\"\n [class.nvb-list-box--readonly]=\"model().readOnly\"\n [class.nvb-list-box--multiple]=\"isMultiple()\"\n [style.max-height.px]=\"model().maxHeight\"\n role=\"listbox\"\n [attr.aria-multiselectable]=\"isMultiple() ? 'true' : 'false'\"\n [attr.aria-labelledby]=\"fieldWrapper.labelId()\"\n [attr.aria-describedby]=\"fieldWrapper.describedByIds()\"\n [attr.aria-required]=\"model().required ? 'true' : null\"\n [attr.aria-invalid]=\"fieldWrapper.isInvalid() ? 'true' : null\"\n [attr.aria-busy]=\"dataSourceLoading() ? 'true' : null\"\n [attr.data-testid]=\"tid('root')\"\n >\n @if (dataSourceLoading()) {\n <div class=\"nvb-list-box__loading\" aria-live=\"polite\">\n <span class=\"nvb-list-box__loading-item\"></span>\n <span class=\"nvb-list-box__loading-item\"></span>\n <span class=\"nvb-list-box__loading-item\"></span>\n </div>\n } @else if (visibleOptions().length === 0) {\n <div class=\"nvb-list-box__empty\">{{ model().placeholder || 'No items' }}</div>\n } @else {\n @for (option of visibleOptions(); track option.value) {\n <div\n class=\"nvb-list-box__item\"\n [class.nvb-list-box__item--selected]=\"isSelected(option)\"\n [class.nvb-list-box__item--disabled]=\"model().disabled || model().readOnly\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected(option)\"\n tabindex=\"0\"\n [attr.data-testid]=\"tid('item', option.value)\"\n (click)=\"onItemClick(option, $event)\"\n (keydown)=\"onItemKeydown(option, $event)\"\n >\n @if (isMultiple()) {\n <span class=\"nvb-list-box__check\" aria-hidden=\"true\">\n @if (isSelected(option)) {\n <span class=\"material-symbols-outlined\">check</span>\n }\n </span>\n }\n <span class=\"nvb-list-box__label\">{{ option.label }}</span>\n </div>\n }\n }\n </div>\n</element-wrapper>\n",styles:['@charset "UTF-8";:host{display:block;width:100%}.nvb-list-box{border:1px solid var(--nvb-color-neutral-300);border-radius:var(--nvb-radius-md);overflow-y:auto;background:var(--nvb-color-neutral-000);width:100%;max-height:240px;transition:border-color .16s ease}.nvb-list-box:focus-within{border-color:var(--nvb-color-primary-500);box-shadow:var(--nvb-focus-ring, 0 0 0 3px color-mix(in oklab, var(--nvb-color-primary-500) 18%, transparent))}.nvb-list-box--disabled{background:var(--nvb-color-neutral-050, #f8fafc);opacity:.6;pointer-events:none}.nvb-list-box--readonly{background:var(--nvb-color-neutral-050, #f8fafc);pointer-events:none}.nvb-list-box__empty{padding:14px 16px;color:var(--nvb-color-neutral-400);font-size:13px;text-align:center}.nvb-list-box__loading{display:flex;flex-direction:column;gap:1px;padding:4px 0}.nvb-list-box__loading-item{display:block;height:36px;background:linear-gradient(90deg,color-mix(in oklab,var(--nvb-color-neutral-100) 86%,var(--nvb-color-neutral-000)) 25%,var(--nvb-color-neutral-200) 50%,color-mix(in oklab,var(--nvb-color-neutral-100) 86%,var(--nvb-color-neutral-000)) 75%);background-size:200% 100%;animation:nvb-listbox-shimmer 1.35s ease-in-out infinite}@keyframes nvb-listbox-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.nvb-list-box__item{display:flex;align-items:center;gap:8px;padding:9px 14px;cursor:pointer;font-size:14px;color:var(--nvb-color-neutral-800);-webkit-user-select:none;user-select:none;transition:background-color .1s ease,color .1s ease;border-bottom:1px solid var(--nvb-color-neutral-100);outline:0}.nvb-list-box__item:last-child{border-bottom:0}.nvb-list-box__item:hover:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 5%,var(--nvb-color-surface-mix-target, white))}.nvb-list-box__item:focus-visible:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 8%,var(--nvb-color-surface-mix-target, white));box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--nvb-color-primary-500) 40%,transparent)}.nvb-list-box__item--selected{background:color-mix(in oklab,var(--nvb-color-primary-500) 8%,var(--nvb-color-surface-mix-target, white));color:var(--nvb-color-primary-700);font-weight:600}.nvb-list-box__item--selected:hover:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 12%,var(--nvb-color-surface-mix-target, white))}.nvb-list-box__item--disabled{opacity:.45;cursor:not-allowed}.nvb-list-box__check{width:16px;height:16px;border:1.5px solid var(--nvb-color-neutral-400);border-radius:var(--nvb-radius-sm);flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:var(--nvb-color-neutral-000);transition:border-color .1s ease,background-color .1s ease}.nvb-list-box__item--selected .nvb-list-box__check{border-color:var(--nvb-color-primary-500);background:var(--nvb-color-primary-500)}.nvb-list-box__check .material-symbols-outlined{font-size:12px;color:var(--nvb-color-neutral-000);line-height:1}.nvb-list-box__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n'],dependencies:[{kind:"component",type:m,selector:"element-wrapper",inputs:["model","controlIdInput","labelForInput","groupRole","showTextWrapperInput"],exportAs:["elementWrapper"]}],changeDetection:i.ChangeDetectionStrategy.OnPush})};i.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.2.1",ngImport:i,type:d,decorators:[{type:f,args:[{selector:"list-box-element",changeDetection:_.OnPush,imports:[m],template:"<element-wrapper [model]=\"model()\" #fieldWrapper=\"elementWrapper\">\n <div\n class=\"nvb-list-box\"\n [class.nvb-list-box--disabled]=\"model().disabled\"\n [class.nvb-list-box--readonly]=\"model().readOnly\"\n [class.nvb-list-box--multiple]=\"isMultiple()\"\n [style.max-height.px]=\"model().maxHeight\"\n role=\"listbox\"\n [attr.aria-multiselectable]=\"isMultiple() ? 'true' : 'false'\"\n [attr.aria-labelledby]=\"fieldWrapper.labelId()\"\n [attr.aria-describedby]=\"fieldWrapper.describedByIds()\"\n [attr.aria-required]=\"model().required ? 'true' : null\"\n [attr.aria-invalid]=\"fieldWrapper.isInvalid() ? 'true' : null\"\n [attr.aria-busy]=\"dataSourceLoading() ? 'true' : null\"\n [attr.data-testid]=\"tid('root')\"\n >\n @if (dataSourceLoading()) {\n <div class=\"nvb-list-box__loading\" aria-live=\"polite\">\n <span class=\"nvb-list-box__loading-item\"></span>\n <span class=\"nvb-list-box__loading-item\"></span>\n <span class=\"nvb-list-box__loading-item\"></span>\n </div>\n } @else if (visibleOptions().length === 0) {\n <div class=\"nvb-list-box__empty\">{{ model().placeholder || 'No items' }}</div>\n } @else {\n @for (option of visibleOptions(); track option.value) {\n <div\n class=\"nvb-list-box__item\"\n [class.nvb-list-box__item--selected]=\"isSelected(option)\"\n [class.nvb-list-box__item--disabled]=\"model().disabled || model().readOnly\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected(option)\"\n tabindex=\"0\"\n [attr.data-testid]=\"tid('item', option.value)\"\n (click)=\"onItemClick(option, $event)\"\n (keydown)=\"onItemKeydown(option, $event)\"\n >\n @if (isMultiple()) {\n <span class=\"nvb-list-box__check\" aria-hidden=\"true\">\n @if (isSelected(option)) {\n <span class=\"material-symbols-outlined\">check</span>\n }\n </span>\n }\n <span class=\"nvb-list-box__label\">{{ option.label }}</span>\n </div>\n }\n }\n </div>\n</element-wrapper>\n",styles:['@charset "UTF-8";:host{display:block;width:100%}.nvb-list-box{border:1px solid var(--nvb-color-neutral-300);border-radius:var(--nvb-radius-md);overflow-y:auto;background:var(--nvb-color-neutral-000);width:100%;max-height:240px;transition:border-color .16s ease}.nvb-list-box:focus-within{border-color:var(--nvb-color-primary-500);box-shadow:var(--nvb-focus-ring, 0 0 0 3px color-mix(in oklab, var(--nvb-color-primary-500) 18%, transparent))}.nvb-list-box--disabled{background:var(--nvb-color-neutral-050, #f8fafc);opacity:.6;pointer-events:none}.nvb-list-box--readonly{background:var(--nvb-color-neutral-050, #f8fafc);pointer-events:none}.nvb-list-box__empty{padding:14px 16px;color:var(--nvb-color-neutral-400);font-size:13px;text-align:center}.nvb-list-box__loading{display:flex;flex-direction:column;gap:1px;padding:4px 0}.nvb-list-box__loading-item{display:block;height:36px;background:linear-gradient(90deg,color-mix(in oklab,var(--nvb-color-neutral-100) 86%,var(--nvb-color-neutral-000)) 25%,var(--nvb-color-neutral-200) 50%,color-mix(in oklab,var(--nvb-color-neutral-100) 86%,var(--nvb-color-neutral-000)) 75%);background-size:200% 100%;animation:nvb-listbox-shimmer 1.35s ease-in-out infinite}@keyframes nvb-listbox-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.nvb-list-box__item{display:flex;align-items:center;gap:8px;padding:9px 14px;cursor:pointer;font-size:14px;color:var(--nvb-color-neutral-800);-webkit-user-select:none;user-select:none;transition:background-color .1s ease,color .1s ease;border-bottom:1px solid var(--nvb-color-neutral-100);outline:0}.nvb-list-box__item:last-child{border-bottom:0}.nvb-list-box__item:hover:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 5%,var(--nvb-color-surface-mix-target, white))}.nvb-list-box__item:focus-visible:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 8%,var(--nvb-color-surface-mix-target, white));box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--nvb-color-primary-500) 40%,transparent)}.nvb-list-box__item--selected{background:color-mix(in oklab,var(--nvb-color-primary-500) 8%,var(--nvb-color-surface-mix-target, white));color:var(--nvb-color-primary-700);font-weight:600}.nvb-list-box__item--selected:hover:not(.nvb-list-box__item--disabled){background:color-mix(in oklab,var(--nvb-color-primary-500) 12%,var(--nvb-color-surface-mix-target, white))}.nvb-list-box__item--disabled{opacity:.45;cursor:not-allowed}.nvb-list-box__check{width:16px;height:16px;border:1.5px solid var(--nvb-color-neutral-400);border-radius:var(--nvb-radius-sm);flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:var(--nvb-color-neutral-000);transition:border-color .1s ease,background-color .1s ease}.nvb-list-box__item--selected .nvb-list-box__check{border-color:var(--nvb-color-primary-500);background:var(--nvb-color-primary-500)}.nvb-list-box__check .material-symbols-outlined{font-size:12px;color:var(--nvb-color-neutral-000);line-height:1}.nvb-list-box__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n']}]}],propDecorators:{model:[{type:i.Input,args:[{isSignal:true,alias:"model",required:true}]}]}});export{S as n,d as t};