@dereekb/dbx-web 13.12.5 → 13.12.7

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.
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-web/eslint",
3
- "version": "13.12.5",
3
+ "version": "13.12.7",
4
4
  "peerDependencies": {
5
- "@dereekb/util": "13.12.5",
5
+ "@dereekb/util": "13.12.7",
6
6
  "@typescript-eslint/utils": "8.59.3"
7
7
  },
8
8
  "devDependencies": {
9
9
  "@angular/core": "21.2.11",
10
- "@dereekb/dbx-core": "13.12.5",
11
- "@dereekb/rxjs": "13.12.5",
10
+ "@dereekb/dbx-core": "13.12.7",
11
+ "@dereekb/rxjs": "13.12.7",
12
12
  "@typescript-eslint/parser": "8.59.3",
13
13
  "eslint": "10.4.0",
14
14
  "rxjs": "^7.8.2"
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { Injectable, input, inject, effect, Directive, NgModule, ChangeDetectionStrategy, Component, output, computed, HostListener, forwardRef, InjectionToken, viewChild, ElementRef, makeEnvironmentProviders, ApplicationRef, Injector, EnvironmentInjector, createComponent, DestroyRef, signal, TemplateRef, model, SecurityContext, ViewContainerRef, booleanAttribute, Renderer2 } from '@angular/core';
3
3
  import { asPromise, DASH_CHARACTER_PREFIX_INSTANCE, cssTokenVar, isDefinedAndNotFalse, useIterableOrValue, spaceSeparatedCssClasses, cssClassesSet, objectHasNoKeys, getValueFromGetter, firstValue, filterUndefinedValues, separateValues, splitFront, asDecisionFunction, SLASH_PATH_FILE_TYPE_SEPARATOR, filterMaybeArrayValues, mapIterable, toReadableError, isDefaultReadableError, MS_IN_SECOND, mergeObjects, build, ServerErrorResponse, UnauthorizedServerErrorResponse, makeTimer, MS_IN_MINUTE, toggleTimerRunning, unixDateTimeSecondsNumberForNow, ModelRelationUtility, encodeModelKeyTypePair, safeCompareEquality, addMilliseconds, isPast, asArray, slashPathDetails, mimeTypeForFileExtension, slashPathDirectoryTree, isMaybeNot, isNotFalse, modifier, combineMaps, addModifiers, removeModifiers, applyBestFit, findNext, maybeModifierMapToFunction, makeValuesGroupMap, compareWithMappedValuesFunction, invertMaybeBoolean, splitCommaSeparatedStringToSet, ZIP_FILE_MIME_TYPE, cachedGetter, sortByNumberFunction, JPEG_MIME_TYPES, JPEG_MIME_TYPE, PNG_MIME_TYPE, PDF_MIME_TYPE, sequentialIncrementingNumberStringModelIdFactory, PDF_HEADER, PDF_EOF_MARKER, PDF_ENCRYPT_MARKER } from '@dereekb/util';
4
4
  import * as i1$2 from '@dereekb/dbx-core';
5
- import { completeOnDestroy, clean, AbstractTransitionWatcherDirective, DbxInjectionComponent, dbxActionWorkProgress, AbstractDbxButtonDirective, hasNonTrivialChildNodes, provideDbxButton, DbxCoreButtonModule, createInjectorForInjectionComponentConfig, initInjectionComponent, AbstractDbxActionValueGetterDirective, cleanSubscription, AbstractDbxActionHandlerDirective, FilterSourceDirective, provideActionStoreSource, isClickableFilterPreset, AbstractDbxAnchorDirective, expandClickableAnchorLinkTrees, DbxCoreFilterModule, DbxButton, DbxActionContextStoreSourceInstance, cleanSubscriptionWithLockSet, DBX_INJECTION_COMPONENT_DATA, checkNgContentWrapperHasContent, cleanLoadingContext, DbxActionSourceDirective, DbxActionSuccessHandlerDirective, DbxActionDirective, transformEmptyStringInputToUndefined, isIdleActionState, canTriggerAction, DbxCoreActionModule, DbxActionButtonDirective, onDbxAppAuth, SimpleStorageAccessorFactory, mergeStaticProviders, asSegueRef, AbstractTransitionDirective, DbxRouterService, AbstractIfDirective, isSegueRefActive, anchorTypeForAnchor } from '@dereekb/dbx-core';
5
+ import { completeOnDestroy, clean, AbstractTransitionWatcherDirective, DbxInjectionComponent, dbxActionWorkProgress, AbstractDbxButtonDirective, hasNonTrivialChildNodes, provideDbxButton, DbxCoreButtonModule, createInjectorForInjectionComponentConfig, initInjectionComponent, AbstractDbxActionValueGetterDirective, cleanSubscription, AbstractDbxActionHandlerDirective, FilterSourceDirective, provideActionStoreSource, isClickableFilterPreset, AbstractDbxAnchorDirective, expandClickableAnchorLinkTrees, DbxCoreFilterModule, DbxButton, DbxActionWorkable, provideDbxActionWorkable, DbxActionContextStoreSourceInstance, cleanSubscriptionWithLockSet, DBX_INJECTION_COMPONENT_DATA, checkNgContentWrapperHasContent, cleanLoadingContext, DbxActionSourceDirective, DbxActionSuccessHandlerDirective, DbxActionDirective, transformEmptyStringInputToUndefined, isIdleActionState, canTriggerAction, DbxCoreActionModule, DbxActionButtonDirective, onDbxAppAuth, SimpleStorageAccessorFactory, mergeStaticProviders, asSegueRef, AbstractTransitionDirective, DbxRouterService, AbstractIfDirective, isSegueRefActive, anchorTypeForAnchor } from '@dereekb/dbx-core';
6
6
  import { NgPopoverRef, NgOverlayContainerService } from 'ng-overlay-container';
7
7
  import { of, map, BehaviorSubject, distinctUntilChanged, shareReplay, delay, Subject, first, startWith, filter, throttleTime, skip, defaultIfEmpty, combineLatest, switchMap, delayWhen, timer, asyncScheduler, from, firstValueFrom, mergeMap, race, tap, catchError, distinct, merge, exhaustMap, NEVER } from 'rxjs';
8
8
  import { LockSet, distinctUntilItemsHaveDifferentValues, filterMaybe, skipAllInitialMaybe, maybeValueFromObservableOrValue, switchMapMaybeLoadingContextStream, LoadingStateType, loadingStateType, successResult, valueFromFinishedLoadingState, loadingStateContext, initialize, asObservable, isNot, mapForEach, switchMapMaybe, listLoadingStateContext, isLoadingStateFinishedLoading, startWithBeginLoading, loadingStateFromObs, errorResult, beginLoading, distinctUntilHasDifferentValues } from '@dereekb/rxjs';
@@ -5623,8 +5623,10 @@ function fileAcceptFunction(accept) {
5623
5623
 
5624
5624
  /**
5625
5625
  * Abstract interface for file upload components that can be controlled by the action system (disabled, working, multiple, accept states).
5626
+ *
5627
+ * Extends {@link DbxActionWorkable} (disabled/working), adding upload-specific multiple/accept controls.
5626
5628
  */
5627
- class DbxFileUploadActionCompatable {
5629
+ class DbxFileUploadActionCompatable extends DbxActionWorkable {
5628
5630
  }
5629
5631
  /**
5630
5632
  * Provides a {@link DbxFileUploadActionCompatable} for dependency injection from the given component type.
@@ -5643,7 +5645,8 @@ function provideDbxFileUploadActionCompatable(sourceType) {
5643
5645
  {
5644
5646
  provide: DbxFileUploadActionCompatable,
5645
5647
  useExisting: forwardRef(() => sourceType)
5646
- }
5648
+ },
5649
+ ...provideDbxActionWorkable(sourceType)
5647
5650
  ];
5648
5651
  }
5649
5652
 
@@ -5997,27 +6000,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
5997
6000
  }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], area: [{ type: i0.ViewChild, args: ['area', { ...{ read: DbxFileUploadAreaComponent }, isSignal: true }] }], button: [{ type: i0.ViewChild, args: ['button', { ...{ read: DbxFileUploadButtonComponent }, isSignal: true }] }], buttonStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonStyle", required: false }] }], buttonDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonDisplay", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], clickAreaToUpload: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickAreaToUpload", required: false }] }], filesChanged: [{ type: i0.Output, args: ["filesChanged"] }] } });
5998
6001
 
5999
6002
  /**
6000
- * Syncs the disabled and working states from an ActionContextStoreSource to a {@link DbxFileUploadActionCompatable} component.
6003
+ * Syncs the disabled and working states from an ActionContextStoreSource to a {@link DbxActionWorkable} target.
6004
+ *
6005
+ * The target is any element that provides {@link DbxActionWorkable} -- a {@link DbxFileUploadActionCompatable}
6006
+ * file upload component, or a {@link DbxButton} (e.g. `<dbx-button>`).
6001
6007
  *
6002
6008
  * @example
6003
6009
  * ```html
6004
6010
  * <dbx-file-upload-button dbxFileUploadActionSync (filesChanged)="onFiles($event)"></dbx-file-upload-button>
6005
6011
  * ```
6012
+ *
6013
+ * @example
6014
+ * ```html
6015
+ * <dbx-button dbxFileUploadActionSync></dbx-button>
6016
+ * ```
6006
6017
  */
6007
6018
  class DbxFileUploadActionSyncDirective {
6008
6019
  source = inject(DbxActionContextStoreSourceInstance);
6009
- uploadCompatable = inject(DbxFileUploadActionCompatable);
6020
+ workable = inject(DbxActionWorkable);
6010
6021
  constructor() {
6011
6022
  cleanSubscriptionWithLockSet({
6012
6023
  lockSet: this.source.lockSet,
6013
6024
  sub: this.source.isWorkingOrWorkProgress$.subscribe((working) => {
6014
- this.uploadCompatable.setWorking(working);
6025
+ this.workable.setWorking(working);
6015
6026
  })
6016
6027
  });
6017
6028
  cleanSubscriptionWithLockSet({
6018
6029
  lockSet: this.source.lockSet,
6019
6030
  sub: this.source.isDisabled$.subscribe((disabled) => {
6020
- this.uploadCompatable.setDisabled(disabled);
6031
+ this.workable.setDisabled(disabled);
6021
6032
  })
6022
6033
  });
6023
6034
  }
@@ -18030,6 +18041,7 @@ const DBX_PDF_MERGE_EDITOR_INITIAL_STATE = {
18030
18041
  class DbxPdfMergeEditorStore extends ComponentStore {
18031
18042
  _validator$ = new BehaviorSubject(undefined);
18032
18043
  _outputSizeLimit$ = new BehaviorSubject(undefined);
18044
+ _imageCompression$ = new BehaviorSubject(undefined);
18033
18045
  constructor() {
18034
18046
  super(DBX_PDF_MERGE_EDITOR_INITIAL_STATE);
18035
18047
  }
@@ -18108,6 +18120,10 @@ class DbxPdfMergeEditorStore extends ComponentStore {
18108
18120
  */
18109
18121
  currentMergeOutput$ = combineLatest([this._candidateMergeOutput$, this.sizeLimitValid$]).pipe(map(([blob, sizeLimitValid]) => (sizeLimitValid ? blob : undefined)), shareReplay(1));
18110
18122
  mergeOutput$ = this.currentMergeOutput$.pipe(filterMaybe());
18123
+ /**
18124
+ * Emits the active client-side image-compression config pushed via {@link setImageCompression}, or `undefined` when none is set. Consumed by the editor and its slot uploaders as the middle tier of compression resolution (own `[config]` input → store → {@link DBX_PDF_MERGE_EDITOR_CONFIG} token), letting {@link DbxPdfMergeEditorStoreDirective} supply a store-level default that flows through the upload dialog's bare editor.
18125
+ */
18126
+ imageCompression$ = this._imageCompression$.asObservable();
18111
18127
  /**
18112
18128
  * Returns an observable of entries belonging to the given slot id. The result is filtered from {@link entries$} so the per-slot stream still reflects validation progress and removals.
18113
18129
  *
@@ -18140,6 +18156,14 @@ class DbxPdfMergeEditorStore extends ComponentStore {
18140
18156
  setOutputSizeLimit(maxBytes) {
18141
18157
  this._outputSizeLimit$.next(maxBytes ?? undefined);
18142
18158
  }
18159
+ /**
18160
+ * Sets the store-level client-side image-compression config exposed via {@link imageCompression$}. The editor and its slot uploaders apply it as the middle tier of compression resolution (own `[config]` input → store → {@link DBX_PDF_MERGE_EDITOR_CONFIG} token), so a value pushed here by {@link DbxPdfMergeEditorStoreDirective} reaches the upload dialog's bare editor while a per-input/per-slot override still wins. Pass `null`/`undefined` to clear the store-level default.
18161
+ *
18162
+ * @param config - Image-compression config, or a falsy value to clear the store-level default.
18163
+ */
18164
+ setImageCompression(config) {
18165
+ this._imageCompression$.next(config ?? undefined);
18166
+ }
18143
18167
  // MARK: Updaters
18144
18168
  /**
18145
18169
  * Appends entries (already constructed) or builds them from raw files and appends them to state. Each entry's validation promise starts when the entry is built; {@link entries$} reflects each result as it resolves. When `input` is an object with `files` and `slotId`, the resulting entries are tagged with that slot id. When `input` is `{ entries }`, the entries are appended as-is — use this shape for entries that went through async client-side compression upstream.
@@ -18249,6 +18273,14 @@ class DbxPdfMergeEditorStoreDirective {
18249
18273
  this.store.setOutputSizeLimit(errorBytes);
18250
18274
  }
18251
18275
  });
18276
+ // Push the directive's image-compression config onto the store so it reaches the
18277
+ // upload dialog's bare <dbx-pdf-merge-editor> (which renders with no own [config]).
18278
+ // Only the store directive pushes — the editor reads the store as the middle tier of
18279
+ // its resolution chain (own [config] → store → token) — so the bare editor never
18280
+ // clobbers this value with an empty config.
18281
+ effect(() => {
18282
+ this.store.setImageCompression(this.config()?.imageCompression);
18283
+ });
18252
18284
  }
18253
18285
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxPdfMergeEditorStoreDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
18254
18286
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.11", type: DbxPdfMergeEditorStoreDirective, isStandalone: true, selector: "[dbxPdfMergeEditorStore]", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, outputSizeLimit: { classPropertyName: "outputSizeLimit", publicName: "outputSizeLimit", isSignal: true, isRequired: false, transformFunction: null } }, providers: [DbxPdfMergeEditorStore], exportAs: ["dbxPdfMergeEditorStore"], ngImport: i0 });
@@ -18530,38 +18562,82 @@ class DbxPdfMergeEditorComponent {
18530
18562
  * Single-slot subscription tracker for the deferred Preview path. Replacing the slot cancels any earlier in-flight wait so rapid clicks (or repeated programmatic calls) cannot stack pending dialogs.
18531
18563
  */
18532
18564
  _pendingPreview = cleanSubscription();
18533
- accept = input(DEFAULT_PDF_MERGE_ACCEPT, ...(ngDevMode ? [{ debugName: "accept" }] : /* istanbul ignore next */ []));
18534
- multiple = input(true, ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
18535
- fileName = input(DEFAULT_MERGED_FILE_NAME, ...(ngDevMode ? [{ debugName: "fileName" }] : /* istanbul ignore next */ []));
18536
- showDownloadButton = input(false, ...(ngDevMode ? [{ debugName: "showDownloadButton" }] : /* istanbul ignore next */ []));
18537
- showPreviewButton = input(true, ...(ngDevMode ? [{ debugName: "showPreviewButton" }] : /* istanbul ignore next */ []));
18538
- downloadButton = input(DEFAULT_DOWNLOAD_BUTTON, ...(ngDevMode ? [{ debugName: "downloadButton" }] : /* istanbul ignore next */ []));
18539
- /**
18540
- * When `false`, hides the default "Add files" upload area. Use when projecting one or more {@link DbxPdfMergeEditorFileUploadComponent} slots through `<ng-content>` instead of relying on the unscoped uploader.
18541
- */
18542
- showAddFiles = input(true, ...(ngDevMode ? [{ debugName: "showAddFiles" }] : /* istanbul ignore next */ []));
18543
18565
  /**
18544
- * When `false`, hides the shared {@link DbxPdfMergeListComponent} below the slot content. Useful when each slot displays its owned files inline and you don't want a duplicate unified list.
18566
+ * Individual inputs. Each takes precedence over the matching field on {@link config} (and the workspace-wide token), with defaults applied in the corresponding `*Signal` computed. See {@link DbxPdfMergeEditorConfig} for field docs.
18545
18567
  */
18546
- showFileList = input(true, ...(ngDevMode ? [{ debugName: "showFileList" }] : /* istanbul ignore next */ []));
18568
+ accept = input(...(ngDevMode ? [undefined, { debugName: "accept" }] : /* istanbul ignore next */ []));
18569
+ multiple = input(...(ngDevMode ? [undefined, { debugName: "multiple" }] : /* istanbul ignore next */ []));
18570
+ fileName = input(...(ngDevMode ? [undefined, { debugName: "fileName" }] : /* istanbul ignore next */ []));
18571
+ showDownloadButton = input(...(ngDevMode ? [undefined, { debugName: "showDownloadButton" }] : /* istanbul ignore next */ []));
18572
+ showPreviewButton = input(...(ngDevMode ? [undefined, { debugName: "showPreviewButton" }] : /* istanbul ignore next */ []));
18573
+ downloadButton = input(...(ngDevMode ? [undefined, { debugName: "downloadButton" }] : /* istanbul ignore next */ []));
18574
+ showAddFiles = input(...(ngDevMode ? [undefined, { debugName: "showAddFiles" }] : /* istanbul ignore next */ []));
18575
+ showFileList = input(...(ngDevMode ? [undefined, { debugName: "showFileList" }] : /* istanbul ignore next */ []));
18547
18576
  /**
18548
- * Optional configuration override for image compression and output-size limits. When omitted, falls back to the value provided via {@link DBX_PDF_MERGE_EDITOR_CONFIG} (if any).
18577
+ * Bundles every editor option into one object (see {@link DbxPdfMergeEditorConfig}). Individual inputs override the matching field here, which in turn overrides the workspace-wide {@link DBX_PDF_MERGE_EDITOR_CONFIG} token.
18549
18578
  */
18550
18579
  config = input(...(ngDevMode ? [undefined, { debugName: "config" }] : /* istanbul ignore next */ []));
18551
18580
  entriesChanged = output();
18552
18581
  /**
18553
- * Merged config the editor's own `config` input wins over the workspace-wide token.
18582
+ * Store-level image-compression default pushed by {@link DbxPdfMergeEditorStoreDirective}. Resolved between the editor's own `config` input and the workspace-wide token so a store-level default flows through the upload dialog's bare editor.
18583
+ */
18584
+ storeImageCompressionSignal = toSignal(this.store.imageCompression$, { initialValue: undefined });
18585
+ /**
18586
+ * Merged config — the editor's own `config` input wins over the store-level default (for `imageCompression`), which in turn wins over the workspace-wide token. The individual inputs are resolved on top of this object in the per-field `*Signal` computeds below.
18554
18587
  */
18555
18588
  effectiveConfigSignal = computed(() => {
18556
18589
  const fromInput = this.config();
18557
18590
  const fromToken = this._injectedConfig;
18591
+ const storeImageCompression = this.storeImageCompressionSignal();
18558
18592
  return {
18559
- imageCompression: fromInput?.imageCompression ?? fromToken?.imageCompression ?? null,
18560
- outputSizeLimits: fromInput?.outputSizeLimits ?? fromToken?.outputSizeLimits ?? null
18593
+ imageCompression: fromInput?.imageCompression ?? storeImageCompression ?? fromToken?.imageCompression ?? null,
18594
+ outputSizeLimits: fromInput?.outputSizeLimits ?? fromToken?.outputSizeLimits ?? null,
18595
+ accept: fromInput?.accept ?? fromToken?.accept,
18596
+ multiple: fromInput?.multiple ?? fromToken?.multiple,
18597
+ fileName: fromInput?.fileName ?? fromToken?.fileName,
18598
+ showDownloadButton: fromInput?.showDownloadButton ?? fromToken?.showDownloadButton,
18599
+ showPreviewButton: fromInput?.showPreviewButton ?? fromToken?.showPreviewButton,
18600
+ downloadButton: fromInput?.downloadButton ?? fromToken?.downloadButton,
18601
+ showAddFiles: fromInput?.showAddFiles ?? fromToken?.showAddFiles,
18602
+ showFileList: fromInput?.showFileList ?? fromToken?.showFileList
18561
18603
  };
18562
18604
  }, ...(ngDevMode ? [{ debugName: "effectiveConfigSignal" }] : /* istanbul ignore next */ []));
18563
18605
  imageCompressionConfigSignal = computed(() => this.effectiveConfigSignal().imageCompression, ...(ngDevMode ? [{ debugName: "imageCompressionConfigSignal" }] : /* istanbul ignore next */ []));
18564
18606
  outputSizeLimitsSignal = computed(() => this.effectiveConfigSignal().outputSizeLimits, ...(ngDevMode ? [{ debugName: "outputSizeLimitsSignal" }] : /* istanbul ignore next */ []));
18607
+ // Per-field resolution: dedicated input → config (input/token) → default. The config signal is
18608
+ // read unconditionally at the top of each computed so the computed tracks it on every run.
18609
+ acceptSignal = computed(() => {
18610
+ const config = this.effectiveConfigSignal();
18611
+ return this.accept() ?? config.accept ?? DEFAULT_PDF_MERGE_ACCEPT;
18612
+ }, ...(ngDevMode ? [{ debugName: "acceptSignal" }] : /* istanbul ignore next */ []));
18613
+ multipleSignal = computed(() => {
18614
+ const config = this.effectiveConfigSignal();
18615
+ return this.multiple() ?? config.multiple ?? true;
18616
+ }, ...(ngDevMode ? [{ debugName: "multipleSignal" }] : /* istanbul ignore next */ []));
18617
+ fileNameSignal = computed(() => {
18618
+ const config = this.effectiveConfigSignal();
18619
+ return this.fileName() ?? config.fileName ?? DEFAULT_MERGED_FILE_NAME;
18620
+ }, ...(ngDevMode ? [{ debugName: "fileNameSignal" }] : /* istanbul ignore next */ []));
18621
+ showDownloadButtonSignal = computed(() => {
18622
+ const config = this.effectiveConfigSignal();
18623
+ return this.showDownloadButton() ?? config.showDownloadButton ?? false;
18624
+ }, ...(ngDevMode ? [{ debugName: "showDownloadButtonSignal" }] : /* istanbul ignore next */ []));
18625
+ showPreviewButtonSignal = computed(() => {
18626
+ const config = this.effectiveConfigSignal();
18627
+ return this.showPreviewButton() ?? config.showPreviewButton ?? true;
18628
+ }, ...(ngDevMode ? [{ debugName: "showPreviewButtonSignal" }] : /* istanbul ignore next */ []));
18629
+ downloadButtonSignal = computed(() => {
18630
+ const config = this.effectiveConfigSignal();
18631
+ return this.downloadButton() ?? config.downloadButton ?? DEFAULT_DOWNLOAD_BUTTON;
18632
+ }, ...(ngDevMode ? [{ debugName: "downloadButtonSignal" }] : /* istanbul ignore next */ []));
18633
+ showAddFilesSignal = computed(() => {
18634
+ const config = this.effectiveConfigSignal();
18635
+ return this.showAddFiles() ?? config.showAddFiles ?? true;
18636
+ }, ...(ngDevMode ? [{ debugName: "showAddFilesSignal" }] : /* istanbul ignore next */ []));
18637
+ showFileListSignal = computed(() => {
18638
+ const config = this.effectiveConfigSignal();
18639
+ return this.showFileList() ?? config.showFileList ?? true;
18640
+ }, ...(ngDevMode ? [{ debugName: "showFileListSignal" }] : /* istanbul ignore next */ []));
18565
18641
  warnBytesSignal = computed(() => this.outputSizeLimitsSignal()?.warnBytes, ...(ngDevMode ? [{ debugName: "warnBytesSignal" }] : /* istanbul ignore next */ []));
18566
18642
  errorBytesSignal = computed(() => this.outputSizeLimitsSignal()?.errorBytes, ...(ngDevMode ? [{ debugName: "errorBytesSignal" }] : /* istanbul ignore next */ []));
18567
18643
  hasReadyEntriesSignal = toSignal(this.store.hasReadyEntries$, { initialValue: false });
@@ -18618,8 +18694,8 @@ class DbxPdfMergeEditorComponent {
18618
18694
  }, ...(ngDevMode ? [{ debugName: "formattedErrorLimitSignal" }] : /* istanbul ignore next */ []));
18619
18695
  downloadConfigSignal = computed(() => ({
18620
18696
  blob: this.mergeBlobSignal(),
18621
- fileName: this.fileName(),
18622
- buttonStylePair: this.downloadButton() ?? DEFAULT_DOWNLOAD_BUTTON
18697
+ fileName: this.fileNameSignal(),
18698
+ buttonStylePair: this.downloadButtonSignal()
18623
18699
  }), ...(ngDevMode ? [{ debugName: "downloadConfigSignal" }] : /* istanbul ignore next */ []));
18624
18700
  constructor() {
18625
18701
  this.store.entries$.pipe(takeUntilDestroyed()).subscribe((entries) => this.entriesChanged.emit(entries));
@@ -18662,20 +18738,20 @@ class DbxPdfMergeEditorComponent {
18662
18738
  openPreviewDialog(blob) {
18663
18739
  openPdfPreviewDialog(this._matDialog, {
18664
18740
  blob,
18665
- downloadFileName: this.fileName(),
18741
+ downloadFileName: this.fileNameSignal(),
18666
18742
  width: '90vw',
18667
18743
  maxWidth: '1200px',
18668
18744
  height: '90vh'
18669
18745
  });
18670
18746
  }
18671
18747
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxPdfMergeEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
18672
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: DbxPdfMergeEditorComponent, isStandalone: true, selector: "dbx-pdf-merge-editor", inputs: { accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, showDownloadButton: { classPropertyName: "showDownloadButton", publicName: "showDownloadButton", isSignal: true, isRequired: false, transformFunction: null }, showPreviewButton: { classPropertyName: "showPreviewButton", publicName: "showPreviewButton", isSignal: true, isRequired: false, transformFunction: null }, downloadButton: { classPropertyName: "downloadButton", publicName: "downloadButton", isSignal: true, isRequired: false, transformFunction: null }, showAddFiles: { classPropertyName: "showAddFiles", publicName: "showAddFiles", isSignal: true, isRequired: false, transformFunction: null }, showFileList: { classPropertyName: "showFileList", publicName: "showFileList", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entriesChanged: "entriesChanged" }, host: { classAttribute: "dbx-pdf-merge-editor d-block" }, ngImport: i0, template: "@if (showAddFiles()) {\n <div class=\"dbx-pdf-merge-editor-upload d-block dbx-mb3\">\n <dbx-file-upload [accept]=\"accept()\" [multiple]=\"multiple()\" (filesChanged)=\"onFiles($event)\" [hint]=\"'Drop PDFs or images here, or click to browse'\" [text]=\"'Add files'\" icon=\"upload_file\"></dbx-file-upload>\n </div>\n}\n<ng-content></ng-content>\n@if (showFileList()) {\n <dbx-pdf-merge-list></dbx-pdf-merge-list>\n}\n@switch (outputSizeStateSignal()) {\n @case ('warn') {\n <div class=\"dbx-pdf-merge-editor-size-warning\">\n <mat-icon>warning</mat-icon>\n <span>Merged file is {{ formattedOutputSizeSignal() }} \u2014 above the recommended {{ formattedWarnLimitSignal() }} limit.</span>\n </div>\n }\n @case ('error') {\n <div class=\"dbx-pdf-merge-editor-size-error\">\n <mat-icon>error</mat-icon>\n <span>Merged file is {{ formattedOutputSizeSignal() }}, exceeds the {{ formattedErrorLimitSignal() }} limit. Remove or compress files to continue.</span>\n </div>\n }\n}\n<div class=\"dbx-pdf-merge-editor-actions\">\n <span class=\"dbx-hint dbx-small\">{{ entryCountSignal() }} file(s)</span>\n <span class=\"dbx-spacer\"></span>\n <dbx-button text=\"Clear\" icon=\"delete\" [disabled]=\"entryCountSignal() === 0\" (buttonClick)=\"onClear()\"></dbx-button>\n @if (showPreviewButton()) {\n <dbx-button text=\"Preview\" icon=\"picture_as_pdf\" [disabled]=\"!canMergeSignal()\" (buttonClick)=\"onPreview()\"></dbx-button>\n }\n @if (showDownloadButton() && canMergeSignal()) {\n <dbx-download-blob-button [config]=\"downloadConfigSignal()\"></dbx-download-blob-button>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: DbxButtonComponent, selector: "dbx-button", inputs: ["bar", "type", "buttonStyle", "color", "spinnerColor", "customButtonColor", "customTextColor", "customSpinnerColor", "basic", "tonal", "raised", "stroked", "flat", "iconOnly", "fab", "customContent", "allowClickPropagation", "mode"] }, { kind: "component", type: DbxFileUploadComponent, selector: "dbx-file-upload", inputs: ["config", "buttonStyle", "buttonDisplay", "mode", "text", "icon", "hint", "clickAreaToUpload"], outputs: ["filesChanged"] }, { kind: "component", type: DbxDownloadBlobButtonComponent, selector: "dbx-download-blob-button", inputs: ["config"] }, { kind: "component", type: DbxPdfMergeListComponent, selector: "dbx-pdf-merge-list" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18748
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: DbxPdfMergeEditorComponent, isStandalone: true, selector: "dbx-pdf-merge-editor", inputs: { accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, showDownloadButton: { classPropertyName: "showDownloadButton", publicName: "showDownloadButton", isSignal: true, isRequired: false, transformFunction: null }, showPreviewButton: { classPropertyName: "showPreviewButton", publicName: "showPreviewButton", isSignal: true, isRequired: false, transformFunction: null }, downloadButton: { classPropertyName: "downloadButton", publicName: "downloadButton", isSignal: true, isRequired: false, transformFunction: null }, showAddFiles: { classPropertyName: "showAddFiles", publicName: "showAddFiles", isSignal: true, isRequired: false, transformFunction: null }, showFileList: { classPropertyName: "showFileList", publicName: "showFileList", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entriesChanged: "entriesChanged" }, host: { classAttribute: "dbx-pdf-merge-editor d-block" }, ngImport: i0, template: "@if (showAddFilesSignal()) {\n <div class=\"dbx-pdf-merge-editor-upload d-block dbx-mb3\">\n <dbx-file-upload [accept]=\"acceptSignal()\" [multiple]=\"multipleSignal()\" (filesChanged)=\"onFiles($event)\" [hint]=\"'Drop PDFs or images here, or click to browse'\" [text]=\"'Add files'\" icon=\"upload_file\"></dbx-file-upload>\n </div>\n}\n<ng-content></ng-content>\n@if (showFileListSignal()) {\n <dbx-pdf-merge-list></dbx-pdf-merge-list>\n}\n@switch (outputSizeStateSignal()) {\n @case ('warn') {\n <div class=\"dbx-pdf-merge-editor-size-warning\">\n <mat-icon>warning</mat-icon>\n <span>Merged file is {{ formattedOutputSizeSignal() }} \u2014 above the recommended {{ formattedWarnLimitSignal() }} limit.</span>\n </div>\n }\n @case ('error') {\n <div class=\"dbx-pdf-merge-editor-size-error\">\n <mat-icon>error</mat-icon>\n <span>Merged file is {{ formattedOutputSizeSignal() }}, exceeds the {{ formattedErrorLimitSignal() }} limit. Remove or compress files to continue.</span>\n </div>\n }\n}\n<div class=\"dbx-pdf-merge-editor-actions\">\n <span class=\"dbx-hint dbx-small\">{{ entryCountSignal() }} file(s)</span>\n <span class=\"dbx-spacer\"></span>\n <dbx-button text=\"Clear\" icon=\"delete\" [disabled]=\"entryCountSignal() === 0\" (buttonClick)=\"onClear()\"></dbx-button>\n @if (showPreviewButtonSignal()) {\n <dbx-button text=\"Preview\" icon=\"picture_as_pdf\" [disabled]=\"!canMergeSignal()\" (buttonClick)=\"onPreview()\"></dbx-button>\n }\n @if (showDownloadButtonSignal() && canMergeSignal()) {\n <dbx-download-blob-button [config]=\"downloadConfigSignal()\"></dbx-download-blob-button>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: DbxButtonComponent, selector: "dbx-button", inputs: ["bar", "type", "buttonStyle", "color", "spinnerColor", "customButtonColor", "customTextColor", "customSpinnerColor", "basic", "tonal", "raised", "stroked", "flat", "iconOnly", "fab", "customContent", "allowClickPropagation", "mode"] }, { kind: "component", type: DbxFileUploadComponent, selector: "dbx-file-upload", inputs: ["config", "buttonStyle", "buttonDisplay", "mode", "text", "icon", "hint", "clickAreaToUpload"], outputs: ["filesChanged"] }, { kind: "component", type: DbxDownloadBlobButtonComponent, selector: "dbx-download-blob-button", inputs: ["config"] }, { kind: "component", type: DbxPdfMergeListComponent, selector: "dbx-pdf-merge-list" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18673
18749
  }
18674
18750
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxPdfMergeEditorComponent, decorators: [{
18675
18751
  type: Component,
18676
18752
  args: [{ selector: 'dbx-pdf-merge-editor', host: {
18677
18753
  class: 'dbx-pdf-merge-editor d-block'
18678
- }, imports: [MatIconModule, DbxButtonComponent, DbxFileUploadComponent, DbxDownloadBlobButtonComponent, DbxPdfMergeListComponent], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "@if (showAddFiles()) {\n <div class=\"dbx-pdf-merge-editor-upload d-block dbx-mb3\">\n <dbx-file-upload [accept]=\"accept()\" [multiple]=\"multiple()\" (filesChanged)=\"onFiles($event)\" [hint]=\"'Drop PDFs or images here, or click to browse'\" [text]=\"'Add files'\" icon=\"upload_file\"></dbx-file-upload>\n </div>\n}\n<ng-content></ng-content>\n@if (showFileList()) {\n <dbx-pdf-merge-list></dbx-pdf-merge-list>\n}\n@switch (outputSizeStateSignal()) {\n @case ('warn') {\n <div class=\"dbx-pdf-merge-editor-size-warning\">\n <mat-icon>warning</mat-icon>\n <span>Merged file is {{ formattedOutputSizeSignal() }} \u2014 above the recommended {{ formattedWarnLimitSignal() }} limit.</span>\n </div>\n }\n @case ('error') {\n <div class=\"dbx-pdf-merge-editor-size-error\">\n <mat-icon>error</mat-icon>\n <span>Merged file is {{ formattedOutputSizeSignal() }}, exceeds the {{ formattedErrorLimitSignal() }} limit. Remove or compress files to continue.</span>\n </div>\n }\n}\n<div class=\"dbx-pdf-merge-editor-actions\">\n <span class=\"dbx-hint dbx-small\">{{ entryCountSignal() }} file(s)</span>\n <span class=\"dbx-spacer\"></span>\n <dbx-button text=\"Clear\" icon=\"delete\" [disabled]=\"entryCountSignal() === 0\" (buttonClick)=\"onClear()\"></dbx-button>\n @if (showPreviewButton()) {\n <dbx-button text=\"Preview\" icon=\"picture_as_pdf\" [disabled]=\"!canMergeSignal()\" (buttonClick)=\"onPreview()\"></dbx-button>\n }\n @if (showDownloadButton() && canMergeSignal()) {\n <dbx-download-blob-button [config]=\"downloadConfigSignal()\"></dbx-download-blob-button>\n }\n</div>\n" }]
18754
+ }, imports: [MatIconModule, DbxButtonComponent, DbxFileUploadComponent, DbxDownloadBlobButtonComponent, DbxPdfMergeListComponent], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "@if (showAddFilesSignal()) {\n <div class=\"dbx-pdf-merge-editor-upload d-block dbx-mb3\">\n <dbx-file-upload [accept]=\"acceptSignal()\" [multiple]=\"multipleSignal()\" (filesChanged)=\"onFiles($event)\" [hint]=\"'Drop PDFs or images here, or click to browse'\" [text]=\"'Add files'\" icon=\"upload_file\"></dbx-file-upload>\n </div>\n}\n<ng-content></ng-content>\n@if (showFileListSignal()) {\n <dbx-pdf-merge-list></dbx-pdf-merge-list>\n}\n@switch (outputSizeStateSignal()) {\n @case ('warn') {\n <div class=\"dbx-pdf-merge-editor-size-warning\">\n <mat-icon>warning</mat-icon>\n <span>Merged file is {{ formattedOutputSizeSignal() }} \u2014 above the recommended {{ formattedWarnLimitSignal() }} limit.</span>\n </div>\n }\n @case ('error') {\n <div class=\"dbx-pdf-merge-editor-size-error\">\n <mat-icon>error</mat-icon>\n <span>Merged file is {{ formattedOutputSizeSignal() }}, exceeds the {{ formattedErrorLimitSignal() }} limit. Remove or compress files to continue.</span>\n </div>\n }\n}\n<div class=\"dbx-pdf-merge-editor-actions\">\n <span class=\"dbx-hint dbx-small\">{{ entryCountSignal() }} file(s)</span>\n <span class=\"dbx-spacer\"></span>\n <dbx-button text=\"Clear\" icon=\"delete\" [disabled]=\"entryCountSignal() === 0\" (buttonClick)=\"onClear()\"></dbx-button>\n @if (showPreviewButtonSignal()) {\n <dbx-button text=\"Preview\" icon=\"picture_as_pdf\" [disabled]=\"!canMergeSignal()\" (buttonClick)=\"onPreview()\"></dbx-button>\n }\n @if (showDownloadButtonSignal() && canMergeSignal()) {\n <dbx-download-blob-button [config]=\"downloadConfigSignal()\"></dbx-download-blob-button>\n }\n</div>\n" }]
18679
18755
  }], ctorParameters: () => [], propDecorators: { accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], showDownloadButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDownloadButton", required: false }] }], showPreviewButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPreviewButton", required: false }] }], downloadButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "downloadButton", required: false }] }], showAddFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAddFiles", required: false }] }], showFileList: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFileList", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], entriesChanged: [{ type: i0.Output, args: ["entriesChanged"] }] } });
18680
18756
 
18681
18757
  /**
@@ -18873,9 +18949,16 @@ class DbxPdfMergeEditorFileUploadComponent {
18873
18949
  });
18874
18950
  }
18875
18951
  /**
18876
- * Resolves the active image compression config: per-slot override → workspace-wide DI token. The intermediate ancestor {@link DbxPdfMergeEditorComponent} config is not visible from a slot, so consumers needing per-editor compression should either set the slot's `imageCompression` directly or rely on the injection token.
18952
+ * Store-level image-compression default pushed by {@link DbxPdfMergeEditorStoreDirective}. Resolved between the slot's own override and the workspace-wide token.
18953
+ */
18954
+ storeImageCompressionSignal = toSignal(this.store.imageCompression$, { initialValue: undefined });
18955
+ /**
18956
+ * Resolves the active image compression config: per-slot override → store-level default → workspace-wide DI token. The store tier lets a {@link DbxPdfMergeEditorStoreDirective} `[config]` supply a shared default (e.g. through the upload dialog) while a slot's own `imageCompression` still wins.
18877
18957
  */
18878
- effectiveImageCompressionSignal = computed(() => this.config()?.imageCompression ?? this._injectedConfig?.imageCompression ?? null, ...(ngDevMode ? [{ debugName: "effectiveImageCompressionSignal" }] : /* istanbul ignore next */ []));
18958
+ effectiveImageCompressionSignal = computed(() => {
18959
+ const storeImageCompression = this.storeImageCompressionSignal();
18960
+ return this.config()?.imageCompression ?? storeImageCompression ?? this._injectedConfig?.imageCompression ?? null;
18961
+ }, ...(ngDevMode ? [{ debugName: "effectiveImageCompressionSignal" }] : /* istanbul ignore next */ []));
18879
18962
  async onFiles(event) {
18880
18963
  const accepted = event.matchResult.accepted;
18881
18964
  const ownedCount = this.ownedEntriesSignal().length;