@sinequa/atomic-angular 0.1.39 → 0.1.43

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,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, Component, Injectable, inject, HostBinding, InjectionToken, computed, signal, effect, assertInInjectionContext, runInInjectionContext, Injector, EventEmitter, Inject, viewChild, ElementRef, afterNextRender, untracked, linkedSignal, model, DestroyRef, Directive, Renderer2, HostListener, contentChildren, contentChild, TemplateRef, Pipe, ChangeDetectorRef, LOCALE_ID, Optional, forwardRef, afterEveryRender, Output, viewChildren, ViewContainerRef } from '@angular/core';
3
- import { DropdownComponent, DropdownContentComponent, ButtonComponent, MenuComponent, MenuContentComponent, MenuItemComponent, BadgeComponent, DialogComponent, DialogHeaderComponent, DialogTitleComponent, DialogContentComponent, DialogFooterComponent, ListItemComponent, InputComponent, cn, SwitchComponent, DialogService, TabsComponent, TabComponent, searchVariants, SearchIconComponent, XMarkIConComponent, PopoverContentComponent, HorizontalDividerComponent, PopoverComponent, ChevronRightIconComponent, LoadingCircleIconComponent, CircleCheckIconComponent, CardComponent, CardHeaderComponent, CardContentComponent, CardFooterComponent, VerticalDividerComponent } from '@sinequa/ui';
2
+ import { input, output, Component, Injectable, inject, HostBinding, InjectionToken, computed, signal, effect, assertInInjectionContext, runInInjectionContext, Injector, EventEmitter, Inject, viewChild, ElementRef, afterNextRender, untracked, linkedSignal, model, DestroyRef, Directive, Renderer2, HostListener, contentChildren, contentChild, TemplateRef, Pipe, ChangeDetectorRef, LOCALE_ID, Optional, afterEveryRender, Output, viewChildren, ViewContainerRef } from '@angular/core';
3
+ import { DropdownComponent, DropdownContentComponent, ButtonComponent, MenuComponent, MenuContentComponent, MenuItemComponent, BadgeComponent, DialogComponent, DialogHeaderComponent, DialogTitleComponent, DialogContentComponent, DialogFooterComponent, ListItemComponent, InputComponent, cn, SwitchComponent, DialogService, TabsComponent, TabComponent, searchVariants, SearchIcon, XMarkIConComponent, PopoverContentComponent, HorizontalDividerComponent, PopoverComponent, ChevronRightIconComponent, LoadingCircleIconComponent, CircleCheckIconComponent, CardComponent, CardHeaderComponent, CardContentComponent, CardFooterComponent, VerticalDividerComponent } from '@sinequa/ui';
4
4
  import { BehaviorSubject, Subscription, catchError, EMPTY, firstValueFrom, map, Subject, of, tap, throwError, from, forkJoin, filter, shareReplay, fromEvent, switchMap, debounceTime } from 'rxjs';
5
5
  import { ActivatedRoute, Router, NavigationEnd, RouterLink, RouterModule } from '@angular/router';
6
6
  import { signalStore, signalStoreFeature, withState, withMethods, patchState, getState, withComputed } from '@ngrx/signals';
@@ -12,7 +12,7 @@ import { Location, DatePipe, DATE_PIPE_DEFAULT_TIMEZONE, DATE_PIPE_DEFAULT_OPTIO
12
12
  import { TranslocoPipe, provideTranslocoScope, TranslocoService } from '@jsverse/transloco';
13
13
  import { cva } from 'class-variance-authority';
14
14
  import * as i1 from '@angular/forms';
15
- import { FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule, FormGroup, FormControl, NonNullableFormBuilder } from '@angular/forms';
15
+ import { FormsModule, ReactiveFormsModule, FormGroup, FormControl, NonNullableFormBuilder } from '@angular/forms';
16
16
  import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
17
17
  import highlightWords from 'highlight-words';
18
18
  import { catchError as catchError$1 } from 'rxjs/operators';
@@ -2173,19 +2173,7 @@ class ApplicationService {
2173
2173
  const firstQuery = queriesMap[0];
2174
2174
  // We need to create a route path object for each tab in the first query
2175
2175
  // if the query has no tabs, we create a route with the query name as the tab name
2176
- const firstQueryConfig = {
2177
- name: firstQuery.name,
2178
- tabs: (firstQuery.tabSearch.tabs && firstQuery.tabSearch.tabs.length
2179
- ? firstQuery.tabSearch.tabs
2180
- : [{
2181
- name: firstQuery.name,
2182
- display: firstQuery.name,
2183
- value: firstQuery.name,
2184
- isDefault: false,
2185
- excludedIndices: [],
2186
- icon: ''
2187
- }])
2188
- };
2176
+ const firstQueryConfig = { name: firstQuery.name, tabs: firstQuery.tabSearch.tabs || [{ name: firstQuery.name }] };
2189
2177
  // We need to remove the current search route from the router config
2190
2178
  // the route exists in the router config because it was created in the app-routing.module.ts and we need it
2191
2179
  // to be able to navigate to the search page. We will recreate it with the new tabs
@@ -2420,7 +2408,7 @@ class AuditService {
2420
2408
  // Second event triggered when we come back
2421
2409
  document.addEventListener('visibilitychange', () => {
2422
2410
  if (document.visibilityState === 'visible') {
2423
- this.notify({ type: 'Navigation_Return' });
2411
+ this.notify({ type: "Navigation_Return" /* AuditEventType.Navigation_Return */ });
2424
2412
  }
2425
2413
  }, { once: true });
2426
2414
  }
@@ -2771,7 +2759,7 @@ class PreviewService {
2771
2759
  close(id, query) {
2772
2760
  const detail = this.getAuditPreviewDetail(id, query);
2773
2761
  const auditEvent = {
2774
- type: "Preview_Close",
2762
+ type: "Preview_Close" /* AuditEventType.Preview_Close */,
2775
2763
  detail
2776
2764
  };
2777
2765
  Audit.notify(auditEvent);
@@ -4637,7 +4625,7 @@ class ExportService {
4637
4625
  exportedColumns: exportedColumns,
4638
4626
  selection: (selection ?? []).length > 0 ? selection : undefined,
4639
4627
  $auditRecord: {
4640
- type: "Search_ExportCSV",
4628
+ type: "Search_ExportCSV" /* AuditEventType.Search_ExportCSV */,
4641
4629
  detail: {
4642
4630
  resultid: results ? results.id : undefined
4643
4631
  }
@@ -5465,6 +5453,7 @@ class OverflowManagerDirective {
5465
5453
  direction = input('horizontal', ...(ngDevMode ? [{ debugName: "direction" }] : []));
5466
5454
  count = output();
5467
5455
  el = inject(ElementRef).nativeElement;
5456
+ destroyRef = inject(DestroyRef);
5468
5457
  resizeObserver = new ResizeObserver(() => this.countItems());
5469
5458
  countSub;
5470
5459
  _lastCount;
@@ -5479,10 +5468,11 @@ class OverflowManagerDirective {
5479
5468
  });
5480
5469
  // listens to the count output and toggles the visibility of the items
5481
5470
  this.countSub = this.count.subscribe(count => this.toggleToCount(count));
5482
- }
5483
- ngOnDestroy() {
5484
- this.countSub?.unsubscribe();
5485
- this.countSub = undefined;
5471
+ this.destroyRef.onDestroy(() => {
5472
+ this.resizeObserver.disconnect();
5473
+ this.countSub?.unsubscribe();
5474
+ this.countSub = undefined;
5475
+ });
5486
5476
  }
5487
5477
  /**
5488
5478
  * Counts the number of items that can fit before the stop element.
@@ -5895,15 +5885,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.2", ngImpor
5895
5885
  }] });
5896
5886
 
5897
5887
  class OperatorPipe {
5888
+ transloco = inject(TranslocoService);
5889
+ lastTransformedValue = null;
5890
+ cdr = inject(ChangeDetectorRef);
5891
+ destroyRef = inject(DestroyRef);
5898
5892
  transform(filter) {
5893
+ this.transloco.langChanges$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(locale => {
5894
+ const transformedValue = this.transformFilter(filter, locale);
5895
+ if (transformedValue !== this.lastTransformedValue) {
5896
+ this.lastTransformedValue = transformedValue;
5897
+ this.cdr.markForCheck();
5898
+ }
5899
+ });
5900
+ return this.lastTransformedValue || this.transformFilter(filter);
5901
+ }
5902
+ transformFilter(filter, locale) {
5899
5903
  let op = this.transformOperator(filter?.operator);
5900
5904
  if (filter?.operator === 'between') {
5901
- return `> ${filter.start} ≤ ${filter.end}`;
5905
+ const { start, end } = filter;
5906
+ if (!start || !end) {
5907
+ return 'bad date range';
5908
+ }
5909
+ return `> ${new Intl.DateTimeFormat(locale).format(new Date(start))} ≤ ${new Intl.DateTimeFormat(locale).format(new Date(end))}`;
5902
5910
  }
5903
5911
  if (filter?.operator === 'and') {
5904
- return filter.display ?? filter.value ?? '';
5912
+ const value = filter?.display ?? filter?.value ?? '';
5913
+ const date = new Date(value);
5914
+ if (isNaN(date.getTime())) {
5915
+ return value;
5916
+ }
5917
+ else {
5918
+ return new Intl.DateTimeFormat(locale).format(date);
5919
+ }
5920
+ }
5921
+ const date = new Date(filter?.value || '');
5922
+ if (isNaN(date.getTime())) {
5923
+ return `${op} ${filter?.value || ''}`;
5924
+ }
5925
+ else {
5926
+ return `${op} ${new Intl.DateTimeFormat(locale).format(date)}`;
5905
5927
  }
5906
- return `${op} ${filter?.value || ''}`;
5907
5928
  }
5908
5929
  transformOperator(operator) {
5909
5930
  switch (operator) {
@@ -5924,14 +5945,14 @@ class OperatorPipe {
5924
5945
  }
5925
5946
  }
5926
5947
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.2", ngImport: i0, type: OperatorPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
5927
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.2", ngImport: i0, type: OperatorPipe, isStandalone: true, name: "operator" });
5948
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.2", ngImport: i0, type: OperatorPipe, isStandalone: true, name: "operator", pure: false });
5928
5949
  }
5929
5950
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.2", ngImport: i0, type: OperatorPipe, decorators: [{
5930
5951
  type: Pipe,
5931
5952
  args: [{
5932
5953
  name: 'operator',
5933
5954
  standalone: true,
5934
- pure: true
5955
+ pure: false
5935
5956
  }]
5936
5957
  }] });
5937
5958
 
@@ -6328,10 +6349,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.2", ngImpor
6328
6349
 
6329
6350
  class SearchInputComponent {
6330
6351
  cn = cn;
6331
- searchElement = viewChild('search', ...(ngDevMode ? [{ debugName: "searchElement" }] : []));
6332
- onFocus = output();
6333
- onBlur = output();
6352
+ searchInput = viewChild.required('search');
6353
+ /**
6354
+ * Emits an event when an element is selected or deselected.
6355
+ *
6356
+ * @remarks
6357
+ * The event payload is either the selected HTMLElement or `null` if the selection is cleared.
6358
+ *
6359
+ * @eventProperty
6360
+ */
6334
6361
  onSelected = output();
6362
+ /**
6363
+ * A required form control for handling string input in the search component.
6364
+ *
6365
+ * This control is initialized using the `input.required` method, ensuring that
6366
+ * the associated input field is mandatory and will enforce validation for non-empty values.
6367
+ *
6368
+ * @remarks
6369
+ * This is typically used to bind to an Angular form input element, providing
6370
+ * reactive form validation and value tracking.
6371
+ *
6372
+ * @type FormControl<string>
6373
+ */
6374
+ control = input.required(...(ngDevMode ? [{ debugName: "control" }] : []));
6335
6375
  controls = input.required(...(ngDevMode ? [{ debugName: "controls" }] : []));
6336
6376
  keyboardNavigatorOptions = input({
6337
6377
  name: 'searchInputKeyboardNavigator',
@@ -6352,37 +6392,20 @@ class SearchInputComponent {
6352
6392
  variants = computed(() => {
6353
6393
  return searchVariants({ variant: this.variant(), class: this.class() });
6354
6394
  }, ...(ngDevMode ? [{ debugName: "variants" }] : []));
6355
- clearSearch(e) {
6356
- const searchEl = this.searchElement()?.nativeElement;
6357
- if (searchEl) {
6358
- searchEl.value = '';
6359
- searchEl.focus();
6360
- }
6361
- this.onChange('');
6362
- }
6363
- /* ControlValueAccessor */
6364
- onChange = () => { };
6365
- onTouched = () => { };
6366
- writeValue(value) {
6367
- const searchEl = this.searchElement()?.nativeElement;
6368
- if (searchEl) {
6369
- searchEl.value = value;
6370
- }
6395
+ onInput(event) {
6396
+ const inputElement = event.target;
6397
+ this.control().setValue(inputElement.value);
6398
+ this.control().markAsDirty();
6399
+ this.control().markAsTouched();
6371
6400
  }
6372
- registerOnChange(fn) {
6373
- this.onChange = fn;
6374
- }
6375
- registerOnTouched(fn) {
6376
- this.onTouched = fn;
6401
+ clearSearch(e) {
6402
+ e.stopImmediatePropagation();
6403
+ this.control().reset();
6404
+ this.control().updateValueAndValidity();
6405
+ this.searchInput()?.nativeElement.focus();
6377
6406
  }
6378
6407
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.2", ngImport: i0, type: SearchInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6379
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.1.2", type: SearchInputComponent, isStandalone: true, selector: "SearchInput", inputs: { controls: { classPropertyName: "controls", publicName: "controls", isSignal: true, isRequired: true, transformFunction: null }, keyboardNavigatorOptions: { classPropertyName: "keyboardNavigatorOptions", publicName: "keyboardNavigatorOptions", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hotkey: { classPropertyName: "hotkey", publicName: "hotkey", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onFocus: "onFocus", onBlur: "onBlur", onSelected: "onSelected" }, host: { properties: { "class": "cn(variants(), disabled() && 'pointer-events-none opacity-50')" } }, providers: [
6380
- {
6381
- provide: NG_VALUE_ACCESSOR,
6382
- useExisting: forwardRef(() => SearchInputComponent),
6383
- multi: true
6384
- }
6385
- ], viewQueries: [{ propertyName: "searchElement", first: true, predicate: ["search"], descendants: true, isSignal: true }], ngImport: i0, template: `
6408
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.1.2", type: SearchInputComponent, isStandalone: true, selector: "SearchInput", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null }, controls: { classPropertyName: "controls", publicName: "controls", isSignal: true, isRequired: true, transformFunction: null }, keyboardNavigatorOptions: { classPropertyName: "keyboardNavigatorOptions", publicName: "keyboardNavigatorOptions", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hotkey: { classPropertyName: "hotkey", publicName: "hotkey", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelected: "onSelected" }, host: { properties: { "class": "cn(variants(), disabled() && 'pointer-events-none opacity-50')" } }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["search"], descendants: true, isSignal: true }], ngImport: i0, template: `
6386
6409
  <SearchIcon class="text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within:rotate-90" />
6387
6410
  <input
6388
6411
  #search
@@ -6396,25 +6419,26 @@ class SearchInputComponent {
6396
6419
  aria-controls="{{ controls() }}"
6397
6420
  [keyboardNavigator]="keyboardNavigatorOptions()"
6398
6421
  [placeholder]="placeholder()"
6422
+ [value]="control().value || ''"
6399
6423
  [attr.aria-keyshortcuts]="hotkey()"
6400
- (onFocus)="onFocus.emit()"
6401
- (onBlur)="onBlur.emit()"
6402
6424
  (onSelected)="onSelected.emit($event)"
6403
- (input)="onChange(search.value)" />
6425
+ (input)="onInput($event)" />
6404
6426
 
6405
6427
  <button
6406
6428
  variant="icon"
6429
+ [tabindex]="control().value ? 0 : -1"
6407
6430
  class="text-foreground peer-not-placeholder-shown:rotate-90 peer-not-placeholder-shown:cursor-pointer peer-not-placeholder-shown:opacity-100 mr-1 rotate-0 transform opacity-0 transition-[rotate,opacity] duration-500 peer-placeholder-shown:pointer-events-none"
6431
+ (keydown.enter)="clearSearch($event)"
6408
6432
  (click)="clearSearch($event)">
6409
- <XMark class="size-4" />
6433
+ <XMark class="size-4" aria-hidden="true" />
6410
6434
  </button>
6411
6435
 
6412
6436
  <ng-content />
6413
- `, isInline: true, styles: [":host input[type=search]::-ms-clear,:host input[type=search]::-ms-reveal{appearance:none;width:0;height:0}:host input[type=search]::-webkit-search-decoration,:host input[type=search]::-webkit-search-cancel-button,:host input[type=search]::-webkit-search-results-button,:host input[type=search]::-webkit-search-results-decoration{appearance:none}\n"], dependencies: [{ kind: "component", type: SearchIconComponent, selector: "SearchIcon", inputs: ["class", "width", "height"] }, { kind: "component", type: XMarkIConComponent, selector: "XMark, xmark, x-mark", inputs: ["class", "width", "height"] }, { kind: "directive", type: KeyboardNavigatorDirective, selector: "input[role=\"combobox\"]", inputs: ["keyboardNavigator", "aria-controls"], outputs: ["onFocus", "onBlur", "onSelected"] }] });
6437
+ `, isInline: true, styles: [":host input[type=search]::-ms-clear,:host input[type=search]::-ms-reveal{appearance:none;width:0;height:0}:host input[type=search]::-webkit-search-decoration,:host input[type=search]::-webkit-search-cancel-button,:host input[type=search]::-webkit-search-results-button,:host input[type=search]::-webkit-search-results-decoration{appearance:none}\n"], dependencies: [{ kind: "component", type: SearchIcon, selector: "SearchIcon", inputs: ["class", "width", "height"] }, { kind: "component", type: XMarkIConComponent, selector: "XMark, xmark, x-mark", inputs: ["class", "width", "height"] }, { kind: "directive", type: KeyboardNavigatorDirective, selector: "input[role=\"combobox\"]", inputs: ["keyboardNavigator", "aria-controls"], outputs: ["onFocus", "onBlur", "onSelected"] }] });
6414
6438
  }
6415
6439
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.2", ngImport: i0, type: SearchInputComponent, decorators: [{
6416
6440
  type: Component,
6417
- args: [{ selector: 'SearchInput', standalone: true, imports: [SearchIconComponent, XMarkIConComponent, KeyboardNavigatorDirective], template: `
6441
+ args: [{ selector: 'SearchInput', standalone: true, imports: [SearchIcon, XMarkIConComponent, KeyboardNavigatorDirective], template: `
6418
6442
  <SearchIcon class="text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within:rotate-90" />
6419
6443
  <input
6420
6444
  #search
@@ -6428,29 +6452,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.2", ngImpor
6428
6452
  aria-controls="{{ controls() }}"
6429
6453
  [keyboardNavigator]="keyboardNavigatorOptions()"
6430
6454
  [placeholder]="placeholder()"
6455
+ [value]="control().value || ''"
6431
6456
  [attr.aria-keyshortcuts]="hotkey()"
6432
- (onFocus)="onFocus.emit()"
6433
- (onBlur)="onBlur.emit()"
6434
6457
  (onSelected)="onSelected.emit($event)"
6435
- (input)="onChange(search.value)" />
6458
+ (input)="onInput($event)" />
6436
6459
 
6437
6460
  <button
6438
6461
  variant="icon"
6462
+ [tabindex]="control().value ? 0 : -1"
6439
6463
  class="text-foreground peer-not-placeholder-shown:rotate-90 peer-not-placeholder-shown:cursor-pointer peer-not-placeholder-shown:opacity-100 mr-1 rotate-0 transform opacity-0 transition-[rotate,opacity] duration-500 peer-placeholder-shown:pointer-events-none"
6464
+ (keydown.enter)="clearSearch($event)"
6440
6465
  (click)="clearSearch($event)">
6441
- <XMark class="size-4" />
6466
+ <XMark class="size-4" aria-hidden="true" />
6442
6467
  </button>
6443
6468
 
6444
6469
  <ng-content />
6445
6470
  `, host: {
6446
6471
  '[class]': "cn(variants(), disabled() && 'pointer-events-none opacity-50')"
6447
- }, providers: [
6448
- {
6449
- provide: NG_VALUE_ACCESSOR,
6450
- useExisting: forwardRef(() => SearchInputComponent),
6451
- multi: true
6452
- }
6453
- ], styles: [":host input[type=search]::-ms-clear,:host input[type=search]::-ms-reveal{appearance:none;width:0;height:0}:host input[type=search]::-webkit-search-decoration,:host input[type=search]::-webkit-search-cancel-button,:host input[type=search]::-webkit-search-results-button,:host input[type=search]::-webkit-search-results-decoration{appearance:none}\n"] }]
6472
+ }, styles: [":host input[type=search]::-ms-clear,:host input[type=search]::-ms-reveal{appearance:none;width:0;height:0}:host input[type=search]::-webkit-search-decoration,:host input[type=search]::-webkit-search-cancel-button,:host input[type=search]::-webkit-search-results-button,:host input[type=search]::-webkit-search-results-decoration{appearance:none}\n"] }]
6454
6473
  }] });
6455
6474
 
6456
6475
  class SortSelectorComponent {
@@ -9443,7 +9462,7 @@ class DateComponent extends AggregationComponent {
9443
9462
  this.updateForm(this.queryParamsStore.getFilter({ field: this.aggregation()?.column, name: this.aggregation()?.name }));
9444
9463
  });
9445
9464
  this.form.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(changes => {
9446
- this.validSelection.set(!!changes.option && (changes.option !== 'custom-range' || (changes.customRange?.from !== null && changes.customRange?.to !== null)));
9465
+ this.validSelection.set(!!changes.option && (changes.option !== 'custom-range' || changes.customRange?.from !== null || changes.customRange?.to !== null));
9447
9466
  });
9448
9467
  }
9449
9468
  aggregation = computed(() => {