@elderbyte/ngx-starter 18.2.0-beta4 → 18.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@ import { Pipe, LOCALE_ID, Inject, NgModule, Optional, SkipSelf, Directive, Outpu
5
5
  import * as i1 from '@angular/platform-browser';
6
6
  import { Duration, Period, TemporalQueries, LocalTime, Instant, LocalDate, nativeJs, ZoneId, DateTimeFormatter, convert, ZonedDateTime, Temporal } from '@js-joda/core';
7
7
  import { LoggerFactory } from '@elderbyte/ts-logger';
8
- import { timer, defer, ReplaySubject, concat, finalize, exhaustMap, BehaviorSubject, Subject, switchMap, of, combineLatest, EMPTY, merge, throwError, forkJoin, mergeWith, Observable, zip, mergeMap as mergeMap$1, fromEvent, skipUntil, combineLatestWith as combineLatestWith$1, NEVER } from 'rxjs';
8
+ import { timer, defer, ReplaySubject, concat, finalize, exhaustMap, BehaviorSubject, Subject, switchMap, of, combineLatest, EMPTY, merge, throwError, forkJoin, mergeWith, Observable, from, toArray, zip, mergeMap as mergeMap$1, fromEvent, skipUntil, combineLatestWith as combineLatestWith$1, NEVER } from 'rxjs';
9
9
  import { tap, takeUntil, takeWhile, map, filter, distinctUntilChanged, debounceTime, catchError, first, take, switchMap as switchMap$1, mergeMap, expand, reduce, startWith, skip, delay, share, combineLatestWith, skipWhile, timeout } from 'rxjs/operators';
10
10
  import * as i1$2 from '@angular/common/http';
11
11
  import { HttpParams, HttpEventType, HttpRequest, HttpClient, HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
@@ -36,6 +36,7 @@ import { MatAutocompleteTrigger, MatAutocomplete, MatAutocompleteModule } from '
36
36
  import * as i1$7 from '@angular/material/chips';
37
37
  import { MatChipGrid, MatChipRow, MatChipRemove, MatChipInput, MatChipsModule, MatChip, MatChipAvatar, MatChipSet, MatChipTrailingIcon, MatChipListbox, MatChipOption } from '@angular/material/chips';
38
38
  import { MatInput, MatInputModule } from '@angular/material/input';
39
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
39
40
  import { MatList, MatListSubheaderCssMatStyler, MatListItem, MatListModule } from '@angular/material/list';
40
41
  import { MatProgressBar, MatProgressBarModule } from '@angular/material/progress-bar';
41
42
  import * as i1$5 from '@angular/material/snack-bar';
@@ -50,7 +51,6 @@ import * as i1$6 from '@angular/material/dialog';
50
51
  import { MatDialogClose, MAT_DIALOG_DATA, MatDialogConfig, MatDialogModule } from '@angular/material/dialog';
51
52
  import { MatMenuTrigger, MatMenu, MatMenuItem, MatMenuModule } from '@angular/material/menu';
52
53
  import { MatTooltipModule, MatTooltip } from '@angular/material/tooltip';
53
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
54
54
  import { MatPaginator, MatPaginatorIntl, MatPaginatorModule } from '@angular/material/paginator';
55
55
  import { MatColumnDef, MatRowDef, MatTable, MatHeaderCellDef, MatHeaderCell, MatCellDef, MatCell, MatFooterCellDef, MatFooterCell, MatHeaderRowDef, MatHeaderRow, MatRow, MatFooterRowDef, MatFooterRow, MatTableModule } from '@angular/material/table';
56
56
  import * as i1$8 from '@angular/cdk/table';
@@ -9715,6 +9715,100 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.4", ngImpor
9715
9715
  }]
9716
9716
  }] });
9717
9717
 
9718
+ /***************************************************************************
9719
+ * *
9720
+ * FileSystem API *
9721
+ * *
9722
+ **************************************************************************/
9723
+ /**
9724
+ * Holds experimental features of the browser `File System API`. No typescript lint checks
9725
+ * are performed here!
9726
+ */
9727
+ class FileSystemApi {
9728
+ /***************************************************************************
9729
+ * *
9730
+ * DataTransferItem *
9731
+ * *
9732
+ **************************************************************************/
9733
+ static isGetAsFileSystemHandleSupported(transferItem) {
9734
+ // @ts-ignore
9735
+ return transferItem.getAsFileSystemHandle !== undefined;
9736
+ }
9737
+ /**
9738
+ * Returns an FileSystemHandle Observable of the given DataTransferItem. The FileSystemHandle can only be accessed in the `dragstart`
9739
+ * or `drop` event. Otherwise, it will return null!
9740
+ */
9741
+ static getAsFileSystemHandle(transferItem) {
9742
+ // @ts-ignore
9743
+ return from(transferItem.getAsFileSystemHandle());
9744
+ }
9745
+ /***************************************************************************
9746
+ * *
9747
+ * File Picker *
9748
+ * *
9749
+ **************************************************************************/
9750
+ static isFileSystemSupported() {
9751
+ return 'showOpenFilePicker' in window;
9752
+ }
9753
+ static openFilePicker(pickerOpts) {
9754
+ try {
9755
+ // @ts-ignore
9756
+ return from(window.showOpenFilePicker(pickerOpts));
9757
+ }
9758
+ catch (e) {
9759
+ return throwError(() => new Error(e));
9760
+ }
9761
+ }
9762
+ /***************************************************************************
9763
+ * *
9764
+ * Directory Picker *
9765
+ * *
9766
+ **************************************************************************/
9767
+ static isDirectoryPickerSupported() {
9768
+ return 'showDirectoryPicker' in window;
9769
+ }
9770
+ static openDirectoryPicker(pickerOpts) {
9771
+ try {
9772
+ // @ts-ignore
9773
+ return from(window.showDirectoryPicker(pickerOpts));
9774
+ }
9775
+ catch (e) {
9776
+ return throwError(() => new Error(e));
9777
+ }
9778
+ }
9779
+ /***************************************************************************
9780
+ * *
9781
+ * FileSystemDirectoryHandle *
9782
+ * *
9783
+ **************************************************************************/
9784
+ static getHandlesFromDirectory(dirHandle) {
9785
+ return from(FileSystemApi.getHandlesFromDirectoryAsync(dirHandle));
9786
+ }
9787
+ static buildRelativeParent(fileOrDirHandle, rootDirectory) {
9788
+ if (rootDirectory == null) {
9789
+ return of(undefined);
9790
+ }
9791
+ const relativeParents$ = from(rootDirectory.resolve(fileOrDirHandle));
9792
+ return relativeParents$.pipe(map(parents => {
9793
+ // path/to/folder/file.jpg
9794
+ const path = parents;
9795
+ // root/path/to/folder/file.jpg
9796
+ path.unshift(rootDirectory.name);
9797
+ // root/path/to/folder
9798
+ path.pop();
9799
+ return path.join('/');
9800
+ }));
9801
+ }
9802
+ static async getHandlesFromDirectoryAsync(dirHandle) {
9803
+ const handles = [];
9804
+ // @ts-ignore
9805
+ for await (const handle of dirHandle.values()) {
9806
+ handles.push(handle);
9807
+ }
9808
+ return handles;
9809
+ }
9810
+ }
9811
+
9718
9812
  /**
9719
9813
  * Represents a file and the relative path where the user has selected it.
9720
9814
  * This is useful if the user has selected a folder and files
@@ -9729,26 +9823,24 @@ class FileEntry {
9729
9823
  * which is also supported by this method.
9730
9824
  */
9731
9825
  static ofFile(file) {
9732
- let relativeParent = null;
9733
- if (file.webkitRelativePath) {
9734
- if (file.webkitRelativePath.endsWith(file.name)) {
9735
- const nameStart = file.webkitRelativePath.length - file.name.length;
9736
- relativeParent = file.webkitRelativePath.substring(0, nameStart);
9737
- }
9738
- else {
9739
- relativeParent = file.webkitRelativePath;
9740
- }
9741
- }
9742
- return FileEntry.relativeFile(file, relativeParent);
9826
+ return FileEntry.relativeFile(file, this.buildRelativeParent(file));
9827
+ }
9828
+ /**
9829
+ * Creates an Observable of a File Entry by resolving its FileSystemFileHandle.
9830
+ * @param fileHandle
9831
+ * @param rootDirectory is needed to build a relative parent. Additionally useful for requesting permissions
9832
+ */
9833
+ static ofFileHandle(fileHandle, rootDirectory) {
9834
+ return from(fileHandle.getFile()).pipe(combineLatestWith(FileSystemApi.buildRelativeParent(fileHandle, rootDirectory)), map(([file, relativeParent]) => FileEntry.relativeFile(file, relativeParent, fileHandle, rootDirectory)));
9743
9835
  }
9744
9836
  /**
9745
9837
  * Creates a file Entry with a relative parent path
9746
9838
  */
9747
- static relativeFile(file, relativeParent) {
9839
+ static relativeFile(file, relativeParent, fileHandle, rootDirectoryHandle) {
9748
9840
  if (relativeParent && relativeParent.endsWith('/')) {
9749
9841
  relativeParent = relativeParent.substring(0, relativeParent.length - 1);
9750
9842
  }
9751
- return new FileEntry(file, relativeParent);
9843
+ return new FileEntry(file, relativeParent, fileHandle, rootDirectoryHandle);
9752
9844
  }
9753
9845
  static toFileMap(entries) {
9754
9846
  const map = new Map();
@@ -9768,9 +9860,11 @@ class FileEntry {
9768
9860
  * Contains the relative path from the selected folder
9769
9861
  * to this file. Only relevant if the user has selected a folder.
9770
9862
  */
9771
- relativeParent) {
9863
+ relativeParent, fileHandle, rootDirectoryHandle) {
9772
9864
  this.file = file;
9773
9865
  this.relativeParent = relativeParent;
9866
+ this.fileHandle = fileHandle;
9867
+ this.rootDirectoryHandle = rootDirectoryHandle;
9774
9868
  this.relativePath = FileEntry.buildRelativePath(relativeParent, file);
9775
9869
  }
9776
9870
  /***************************************************************************
@@ -9789,42 +9883,46 @@ class FileEntry {
9789
9883
  return file.name;
9790
9884
  }
9791
9885
  }
9886
+ static buildRelativeParent(file) {
9887
+ let relativeParent = null;
9888
+ if (file.webkitRelativePath) {
9889
+ if (file.webkitRelativePath.endsWith(file.name)) {
9890
+ const nameStart = file.webkitRelativePath.length - file.name.length;
9891
+ relativeParent = file.webkitRelativePath.substring(0, nameStart);
9892
+ }
9893
+ else {
9894
+ relativeParent = file.webkitRelativePath;
9895
+ }
9896
+ }
9897
+ return relativeParent;
9898
+ }
9792
9899
  }
9793
9900
 
9794
- class ElderFileSelectDirective {
9901
+ class ElderFileSelectInput {
9795
9902
  /***************************************************************************
9796
9903
  * *
9797
9904
  * Constructor *
9798
9905
  * *
9799
9906
  **************************************************************************/
9800
- constructor(el, renderer) {
9801
- this.el = el;
9907
+ constructor(renderer, el) {
9802
9908
  this.renderer = renderer;
9909
+ this.el = el;
9803
9910
  /***************************************************************************
9804
9911
  * *
9805
9912
  * Fields *
9806
9913
  * *
9807
9914
  **************************************************************************/
9808
9915
  this.logger = LoggerFactory.getLogger(this.constructor.name);
9809
- this.elderFileSelectChange = new EventEmitter();
9810
- this.elderSingleFileSelectChange = new EventEmitter();
9811
- }
9812
- /***************************************************************************
9813
- * *
9814
- * Life Cycle *
9815
- * *
9816
- **************************************************************************/
9817
- ngOnInit() {
9818
- this.createFileSelect();
9819
- }
9820
- ngOnDestroy() {
9821
- this.removeFileSelect();
9916
+ this._filesSelected = new Subject;
9822
9917
  }
9823
9918
  /***************************************************************************
9824
9919
  * *
9825
9920
  * Properties *
9826
9921
  * *
9827
9922
  **************************************************************************/
9923
+ get filesSelected() {
9924
+ return this._filesSelected;
9925
+ }
9828
9926
  set elderFileSelect(value) {
9829
9927
  this._accept = value;
9830
9928
  if (this._fileInput) {
@@ -9837,11 +9935,6 @@ class ElderFileSelectDirective {
9837
9935
  this.renderer.setProperty(this._fileInput, 'multiple', value);
9838
9936
  }
9839
9937
  }
9840
- /**
9841
- * Allow the user to select a directory. All files that are recursively contained are selected.
9842
- * However, the user will no longer be able to select individual files if this is enabled.
9843
- * @param value
9844
- */
9845
9938
  set elderFileSelectDirectory(value) {
9846
9939
  this._directory = coerceBooleanProperty(value);
9847
9940
  if (this._fileInput) {
@@ -9854,17 +9947,6 @@ class ElderFileSelectDirective {
9854
9947
  * Public API *
9855
9948
  * *
9856
9949
  **************************************************************************/
9857
- onClick(event) {
9858
- this.openFileSelectDialog();
9859
- }
9860
- openFileSelectDialog() {
9861
- this._fileInput.click();
9862
- }
9863
- /***************************************************************************
9864
- * *
9865
- * Private methods *
9866
- * *
9867
- **************************************************************************/
9868
9950
  /**
9869
9951
  * <input type="file"
9870
9952
  * hidden #fileInput
@@ -9888,7 +9970,9 @@ class ElderFileSelectDirective {
9888
9970
  this.renderer.setAttribute(this._fileInput, 'webkitdirectory', 'true');
9889
9971
  this.renderer.setAttribute(this._fileInput, 'directory', 'true');
9890
9972
  }
9891
- this._unlisten = this.renderer.listen(this._fileInput, 'change', event => this.fileInputChanged(event));
9973
+ this._unlisten = this.renderer.listen(this._fileInput, 'change', event => {
9974
+ this.fileInputChanged(this._fileInput.files);
9975
+ });
9892
9976
  }
9893
9977
  removeFileSelect() {
9894
9978
  if (this._unlisten) {
@@ -9900,26 +9984,24 @@ class ElderFileSelectDirective {
9900
9984
  this._fileInput = null;
9901
9985
  }
9902
9986
  }
9903
- fileInputChanged(event) {
9904
- const fileList = this._fileInput.files;
9987
+ openFileSelectDialog() {
9988
+ this._fileInput.click();
9989
+ }
9990
+ /***************************************************************************
9991
+ * *
9992
+ * Private methods *
9993
+ * *
9994
+ **************************************************************************/
9995
+ fileInputChanged(fileList) {
9905
9996
  const files = this.toFileEntries(fileList);
9906
9997
  this.logger.debug('fileInputChanged, files:', files);
9907
- this.emitFileList(files);
9908
9998
  this.clearFileList();
9999
+ this._filesSelected.next(files);
9909
10000
  }
9910
10001
  clearFileList() {
9911
10002
  // not nice but works
9912
10003
  this._fileInput.value = null;
9913
10004
  }
9914
- emitFileList(files) {
9915
- if (files.length > 0) {
9916
- this.elderFileSelectChange.next(files);
9917
- this.elderSingleFileSelectChange.emit(files[0].file);
9918
- }
9919
- else {
9920
- this.logger.warn('User did not select any File or the Folder was empty.');
9921
- }
9922
- }
9923
10005
  toFileEntries(fileList) {
9924
10006
  const files = [];
9925
10007
  for (const key in fileList) {
@@ -9929,7 +10011,175 @@ class ElderFileSelectDirective {
9929
10011
  }
9930
10012
  return files;
9931
10013
  }
9932
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.4", ngImport: i0, type: ElderFileSelectDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive }); }
10014
+ }
10015
+
10016
+ class FileListingSystemHandle {
10017
+ /***************************************************************************
10018
+ * *
10019
+ * Public methods *
10020
+ * *
10021
+ **************************************************************************/
10022
+ /**
10023
+ * Creates a File Entry Array Observable by resolving its FileSystemHandle.
10024
+ * @returns An `Observable<FileEntry[]>` with the FileSystemFileHandle included
10025
+ */
10026
+ static listFiles(handle, rootDirectory) {
10027
+ switch (handle.kind) {
10028
+ case 'file':
10029
+ return FileEntry.ofFileHandle(handle, rootDirectory).pipe(toArray());
10030
+ case 'directory':
10031
+ return FileListingSystemHandle.listFilesRecursive(handle, rootDirectory);
10032
+ }
10033
+ }
10034
+ /***************************************************************************
10035
+ * *
10036
+ * Private methods *
10037
+ * *
10038
+ **************************************************************************/
10039
+ static listFilesRecursive(dirHandle, rootDirectory) {
10040
+ return FileSystemApi.getHandlesFromDirectory(dirHandle).pipe(map(handles => FileListingSystemHandle.listFilesOfEach(handles, rootDirectory ? rootDirectory : dirHandle)), switchMap(fileEntriesArray$ => zip(fileEntriesArray$)), map(fileEntriesArray => fileEntriesArray.flat()));
10041
+ }
10042
+ static listFilesOfEach(handles, rootDirectory) {
10043
+ return handles.map(fileOrDirHandle => FileListingSystemHandle.listFiles(fileOrDirHandle, rootDirectory));
10044
+ }
10045
+ }
10046
+
10047
+ class ElderFileSelectDirective {
10048
+ /***************************************************************************
10049
+ * *
10050
+ * Constructor *
10051
+ * *
10052
+ **************************************************************************/
10053
+ constructor(renderer, el, destroyRef) {
10054
+ this.renderer = renderer;
10055
+ this.el = el;
10056
+ this.destroyRef = destroyRef;
10057
+ /***************************************************************************
10058
+ * *
10059
+ * Fields *
10060
+ * *
10061
+ **************************************************************************/
10062
+ this.logger = LoggerFactory.getLogger(this.constructor.name);
10063
+ this.elderFileSelectChange = new EventEmitter();
10064
+ this.elderSingleFileSelectChange = new EventEmitter();
10065
+ this._useDirectoryPicker = false;
10066
+ this._legacyInput = new ElderFileSelectInput(this.renderer, this.el);
10067
+ }
10068
+ /***************************************************************************
10069
+ * *
10070
+ * Life Cycle *
10071
+ * *
10072
+ **************************************************************************/
10073
+ ngOnInit() {
10074
+ if (!FileSystemApi.isFileSystemSupported() || !FileSystemApi.isDirectoryPickerSupported()) {
10075
+ this.logger.warn('showOpenFilePicker or showDirectoryPicker is not supported for this browser, falling back to legacy file picker');
10076
+ this._legacyInput.createFileSelect();
10077
+ this._legacyInput.filesSelected.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
10078
+ next: multiFileChange => this.pushFileChanges(multiFileChange)
10079
+ });
10080
+ }
10081
+ }
10082
+ ngOnDestroy() {
10083
+ this._legacyInput.removeFileSelect();
10084
+ }
10085
+ /***************************************************************************
10086
+ * *
10087
+ * Properties *
10088
+ * *
10089
+ **************************************************************************/
10090
+ set elderFileSelect(value) {
10091
+ this._filePickerOptions = {
10092
+ excludeAcceptAllOptions: true,
10093
+ id: this._filePickerOptions?.id,
10094
+ multiple: this._filePickerOptions?.multiple,
10095
+ startIn: this._filePickerOptions?.startIn,
10096
+ types: [this.buildTypeOption(value)]
10097
+ };
10098
+ this._legacyInput.elderFileSelect = value;
10099
+ }
10100
+ buildTypeOption(value) {
10101
+ if (this.isFileExtension(value)) {
10102
+ return {
10103
+ accept: {
10104
+ '*/*': value.trim()
10105
+ .replace(/\s+/g, '')
10106
+ .split(',')
10107
+ }
10108
+ };
10109
+ }
10110
+ else if (this.isMimeType(value)) {
10111
+ return {
10112
+ accept: { [value]: [] }
10113
+ };
10114
+ }
10115
+ return null;
10116
+ }
10117
+ isFileExtension(input) {
10118
+ const regex = new RegExp(/^(\.\w+)(, ?\.\w+)*$/);
10119
+ return regex.test(input);
10120
+ }
10121
+ isMimeType(input) {
10122
+ const regex = new RegExp(/^.+\/.+$/);
10123
+ return regex.test(input);
10124
+ }
10125
+ set elderFileSelectMultiple(value) {
10126
+ this._filePickerOptions = {
10127
+ excludeAcceptAllOptions: this._filePickerOptions?.excludeAcceptAllOptions,
10128
+ id: this._filePickerOptions?.id,
10129
+ multiple: coerceBooleanProperty(value),
10130
+ startIn: this._filePickerOptions?.startIn,
10131
+ types: this._filePickerOptions?.types
10132
+ };
10133
+ this._legacyInput.elderFileSelectMultiple = value;
10134
+ }
10135
+ /**
10136
+ * Allow the user to select a directory. All files that are recursively contained are selected.
10137
+ * However, the user will no longer be able to select individual files if this is enabled.
10138
+ * @param value
10139
+ */
10140
+ set elderFileSelectDirectory(value) {
10141
+ this._useDirectoryPicker = coerceBooleanProperty(value);
10142
+ this._legacyInput.elderFileSelectDirectory = value;
10143
+ }
10144
+ /***************************************************************************
10145
+ * *
10146
+ * Public API *
10147
+ * *
10148
+ **************************************************************************/
10149
+ onClick(event) {
10150
+ if (!this._useDirectoryPicker && FileSystemApi.isFileSystemSupported()) {
10151
+ this.openFilePicker(this._filePickerOptions).subscribe({
10152
+ next: multiFileChange => this.pushFileChanges(multiFileChange)
10153
+ });
10154
+ }
10155
+ else if (this._useDirectoryPicker && FileSystemApi.isDirectoryPickerSupported()) {
10156
+ this.openDirectoryPicker(this._directoryPickerOptions).subscribe({
10157
+ next: multiFileChange => this.pushFileChanges(multiFileChange)
10158
+ });
10159
+ }
10160
+ else {
10161
+ this._legacyInput.openFileSelectDialog();
10162
+ }
10163
+ }
10164
+ /***************************************************************************
10165
+ * *
10166
+ * Private methods *
10167
+ * *
10168
+ **************************************************************************/
10169
+ pushFileChanges(multiFileChange) {
10170
+ this.elderFileSelectChange.next(multiFileChange);
10171
+ const file = multiFileChange[0]?.file;
10172
+ if (file) {
10173
+ this.elderSingleFileSelectChange.next(file);
10174
+ }
10175
+ }
10176
+ openFilePicker(pickerOpts) {
10177
+ return FileSystemApi.openFilePicker(pickerOpts).pipe(switchMap(files => combineLatest(files.map(file => FileEntry.ofFileHandle(file)))));
10178
+ }
10179
+ openDirectoryPicker(pickerOpts) {
10180
+ return FileSystemApi.openDirectoryPicker(pickerOpts).pipe(switchMap(dir => FileListingSystemHandle.listFiles(dir)));
10181
+ }
10182
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.4", ngImport: i0, type: ElderFileSelectDirective, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.DestroyRef }], target: i0.ɵɵFactoryTarget.Directive }); }
9933
10183
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.4", type: ElderFileSelectDirective, isStandalone: true, selector: "[elderFileSelect]", inputs: { elderFileSelect: "elderFileSelect", elderFileSelectMultiple: "elderFileSelectMultiple", elderFileSelectDirectory: "elderFileSelectDirectory" }, outputs: { elderFileSelectChange: "elderFileSelectChange", elderSingleFileSelectChange: "elderSingleFileSelectChange" }, host: { listeners: { "click": "onClick($event)" } }, ngImport: i0 }); }
9934
10184
  }
9935
10185
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.4", ngImport: i0, type: ElderFileSelectDirective, decorators: [{
@@ -9938,7 +10188,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.4", ngImpor
9938
10188
  selector: '[elderFileSelect]',
9939
10189
  standalone: true
9940
10190
  }]
9941
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { elderFileSelectChange: [{
10191
+ }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.DestroyRef }], propDecorators: { elderFileSelectChange: [{
9942
10192
  type: Output
9943
10193
  }], elderSingleFileSelectChange: [{
9944
10194
  type: Output
@@ -10058,70 +10308,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.4", ngImpor
10058
10308
  type: Input
10059
10309
  }] } });
10060
10310
 
10061
- class FileListingRx {
10311
+ class FileListingWebkit {
10312
+ /***************************************************************************
10313
+ * *
10314
+ * Constructor *
10315
+ * *
10316
+ **************************************************************************/
10062
10317
  constructor() {
10063
- this.log = LoggerFactory.getLogger(this.constructor.name);
10064
10318
  }
10065
- static { this.INSTANCE = new FileListingRx(); }
10066
10319
  /***************************************************************************
10067
10320
  * *
10068
- * Public API *
10321
+ * Public methods *
10069
10322
  * *
10070
10323
  **************************************************************************/
10071
- toFileList(transferItemList) {
10072
- const obs = [];
10073
- for (let i = 0; i < transferItemList.length; i++) {
10074
- const transferItem = transferItemList[i];
10075
- const entry = transferItem.webkitGetAsEntry();
10076
- if (entry) {
10077
- obs.push(this.listFilesRecursive(entry));
10078
- }
10079
- else {
10080
- const itemAsFile = transferItem.getAsFile();
10081
- if (itemAsFile) {
10082
- obs.push(of([FileEntry.ofFile(itemAsFile)]));
10083
- }
10084
- else {
10085
- if (transferItem.kind == 'file') {
10086
- obs.push(of([
10087
- FileEntry.ofFile(new File([], '', {
10088
- type: transferItem.type
10089
- }))
10090
- ]));
10091
- }
10092
- else {
10093
- this.log.warn('Could not handle DataTransferItem!', transferItem);
10094
- }
10095
- }
10096
- }
10097
- }
10098
- return zip(obs).pipe(map(files => files.flat()));
10099
- }
10100
- listFilesRecursive(entry) {
10101
- return this.listFilesRecursiveAsync(entry, null);
10324
+ static listFilesRecursive(entry) {
10325
+ return FileListingWebkit.listFilesRecursiveAsync(entry, null);
10102
10326
  }
10103
10327
  /***************************************************************************
10104
10328
  * *
10105
10329
  * Private methods *
10106
10330
  * *
10107
10331
  **************************************************************************/
10108
- listFilesRecursiveAsync(entry, parent) {
10332
+ static listFilesRecursiveAsync(entry, parent) {
10109
10333
  if (entry.isDirectory) {
10110
10334
  const directoryEntry = entry;
10111
- return this.readEntries(directoryEntry).pipe(mergeMap$1(entries => zip(entries.map(entry => this.listFilesRecursiveAsync(entry, directoryEntry)))), map(files => files.flat()));
10335
+ return FileListingWebkit.readEntries(directoryEntry).pipe(mergeMap$1(entries => zip(entries.map(entry => this.listFilesRecursiveAsync(entry, directoryEntry)))), map(files => files.flat()));
10112
10336
  }
10113
10337
  else if (entry.isFile) {
10114
10338
  const fileEntry = entry;
10115
- return this.observableFile(fileEntry, parent).pipe(map(file => [file]));
10339
+ return FileListingWebkit.observableFile(fileEntry, parent).pipe(map(file => [file]));
10116
10340
  }
10117
10341
  else {
10118
10342
  return EMPTY;
10119
10343
  }
10120
10344
  }
10121
- observableFile(fileEntry, parent) {
10345
+ static observableFile(fileEntry, parent) {
10122
10346
  return new Observable(observer => {
10123
10347
  fileEntry.file(file => {
10124
- observer.next(FileEntry.relativeFile(file, this.trimStaringSlash(parent?.fullPath)));
10348
+ observer.next(FileEntry.relativeFile(file, FileListingWebkit.trimStaringSlash(parent?.fullPath)));
10125
10349
  observer.complete();
10126
10350
  }, err => {
10127
10351
  observer.error(err);
@@ -10129,7 +10353,7 @@ class FileListingRx {
10129
10353
  });
10130
10354
  });
10131
10355
  }
10132
- trimStaringSlash(path) {
10356
+ static trimStaringSlash(path) {
10133
10357
  if (path) {
10134
10358
  if (path.startsWith('/')) {
10135
10359
  path = path.substring(1);
@@ -10137,12 +10361,12 @@ class FileListingRx {
10137
10361
  }
10138
10362
  return path;
10139
10363
  }
10140
- readEntries(directoryEntry) {
10364
+ static readEntries(directoryEntry) {
10141
10365
  return new Observable(observer => {
10142
- this.consumeReaderToCompletion(observer, directoryEntry.createReader());
10366
+ FileListingWebkit.consumeReaderToCompletion(observer, directoryEntry.createReader());
10143
10367
  });
10144
10368
  }
10145
- consumeReaderToCompletion(observer, directoryReader) {
10369
+ static consumeReaderToCompletion(observer, directoryReader) {
10146
10370
  directoryReader.readEntries(entries => {
10147
10371
  if (entries && entries.length > 0) {
10148
10372
  observer.next(entries);
@@ -10158,6 +10382,63 @@ class FileListingRx {
10158
10382
  }
10159
10383
  }
10160
10384
 
10385
+ class FileListingRx {
10386
+ constructor() {
10387
+ this.log = LoggerFactory.getLogger(this.constructor.name);
10388
+ }
10389
+ static { this.INSTANCE = new FileListingRx(); }
10390
+ /***************************************************************************
10391
+ * *
10392
+ * Public API *
10393
+ * *
10394
+ **************************************************************************/
10395
+ toFileList(transferItemList) {
10396
+ const obs = [];
10397
+ for (let i = 0; i < transferItemList.length; i++) {
10398
+ const transferItem = transferItemList[i];
10399
+ obs.push(this.resolveTransferItem(transferItem));
10400
+ }
10401
+ return zip(obs).pipe(map(files => files.flat()));
10402
+ }
10403
+ /***************************************************************************
10404
+ * *
10405
+ * Private methods *
10406
+ * *
10407
+ **************************************************************************/
10408
+ resolveTransferItem(transferItem) {
10409
+ if (FileSystemApi.isGetAsFileSystemHandleSupported(transferItem)) {
10410
+ return FileSystemApi.getAsFileSystemHandle(transferItem).pipe(switchMap(handle => handle ? FileListingSystemHandle.listFiles(handle) : this.legacyFileListing(transferItem)));
10411
+ }
10412
+ return this.legacyFileListing(transferItem);
10413
+ }
10414
+ legacyFileListing(transferItem) {
10415
+ const entry = transferItem.webkitGetAsEntry();
10416
+ if (entry) {
10417
+ return FileListingWebkit.listFilesRecursive(entry);
10418
+ }
10419
+ return this.fallbackFileListing(transferItem);
10420
+ }
10421
+ fallbackFileListing(transferItem) {
10422
+ const itemAsFile = transferItem.getAsFile();
10423
+ if (itemAsFile) {
10424
+ return of([FileEntry.ofFile(itemAsFile)]);
10425
+ }
10426
+ else {
10427
+ if (transferItem.kind == 'file') {
10428
+ return of([
10429
+ FileEntry.ofFile(new File([], '', {
10430
+ type: transferItem.type
10431
+ }))
10432
+ ]);
10433
+ }
10434
+ else {
10435
+ this.log.warn('Could not handle DataTransferItem!', transferItem);
10436
+ return of([]);
10437
+ }
10438
+ }
10439
+ }
10440
+ }
10441
+
10161
10442
  class ElderFileDropZoneDirective {
10162
10443
  /***************************************************************************
10163
10444
  * *