@ah-oh/ao-workspaces-design-system 0.0.47 → 0.0.49

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,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, inject, signal, Injectable, makeEnvironmentProviders, input, ChangeDetectionStrategy, computed, model, forwardRef, output, DestroyRef, ElementRef, HostListener, viewChild, TemplateRef, Directive, contentChildren, effect, ViewContainerRef, ViewChild, InjectionToken, ApplicationRef, Injector, EnvironmentInjector, createComponent, untracked, Optional, SkipSelf, NgModule, EventEmitter, PLATFORM_ID, Output, Input, Inject, viewChildren } from '@angular/core';
2
+ import { Component, inject, signal, Injectable, makeEnvironmentProviders, input, ChangeDetectionStrategy, computed, model, forwardRef, output, DestroyRef, ElementRef, HostListener, viewChild, TemplateRef, Directive, contentChildren, effect, ViewContainerRef, ViewChild, InjectionToken, ApplicationRef, Injector, EnvironmentInjector, createComponent, runInInjectionContext, untracked, Optional, SkipSelf, NgModule, EventEmitter, PLATFORM_ID, Output, Input, Inject, viewChildren } from '@angular/core';
3
3
  import { DOCUMENT, NgTemplateOutlet, isPlatformBrowser, DatePipe } from '@angular/common';
4
4
  import * as i2 from '@angular/common/http';
5
5
  import { withInterceptors, HttpParams, HttpHeaders, HttpRequest, HttpResponse, HttpClient } from '@angular/common/http';
@@ -9,7 +9,7 @@ import { ReactiveFormsModule, NG_VALUE_ACCESSOR, FormsModule, FormControl, Valid
9
9
  import * as phosphorIcons from '@ng-icons/phosphor-icons/regular';
10
10
  import { phosphorLockSimple, phosphorWarning, phosphorCaretDown, phosphorSquare, phosphorCheckSquare, phosphorMinusSquare, phosphorCaretLeft, phosphorCaretRight, phosphorCalendarBlank, phosphorDotsThreeVertical, phosphorPlus, phosphorTrash, phosphorDatabase, phosphorMagnifyingGlass, phosphorFunnel, phosphorArrowsDownUp, phosphorCaretUp, phosphorPencilSimple, phosphorEye, phosphorArrowClockwise, phosphorArrowCounterClockwise, phosphorMinus, phosphorLink, phosphorCodeBlock, phosphorQuotes, phosphorListNumbers, phosphorListBullets, phosphorTextHThree, phosphorTextHTwo, phosphorTextHOne, phosphorCode, phosphorTextStrikethrough, phosphorTextItalic, phosphorTextB, phosphorCheck, phosphorX, phosphorSparkle, phosphorMicrophone, phosphorArrowRight, phosphorBell, phosphorBookOpenText, phosphorTestTube, phosphorPaperPlaneRight, phosphorClockCounterClockwise, phosphorSignOut, phosphorRobot, phosphorPuzzlePiece, phosphorGearSix, phosphorPenNib, phosphorTreeStructure, phosphorSquaresFour } from '@ng-icons/phosphor-icons/regular';
11
11
  import { takeUntilDestroyed, toSignal, toObservable } from '@angular/core/rxjs-interop';
12
- import { Subject, debounceTime, BehaviorSubject, map as map$1, catchError, of, tap, takeUntil, firstValueFrom, filter as filter$1, distinctUntilChanged, switchMap, timer, fromEvent } from 'rxjs';
12
+ import { Subject, debounceTime, BehaviorSubject, map as map$1, catchError, of, tap, takeUntil, throttleTime, asyncScheduler, switchMap, firstValueFrom, filter as filter$1, distinctUntilChanged, timer, fromEvent } from 'rxjs';
13
13
  import { Editor } from '@tiptap/core';
14
14
  import Link from '@tiptap/extension-link';
15
15
  import Placeholder from '@tiptap/extension-placeholder';
@@ -21,7 +21,7 @@ import { Product, AccessRole } from '@ah-oh/ao-workspaces-types';
21
21
  import * as i1$1 from '@angular/router';
22
22
  import { NavigationEnd, Router } from '@angular/router';
23
23
  import RecordRTC from 'recordrtc';
24
- import { filter, map, throttleTime } from 'rxjs/operators';
24
+ import { filter, map, throttleTime as throttleTime$1 } from 'rxjs/operators';
25
25
  import { ENTER, COMMA } from '@angular/cdk/keycodes';
26
26
  import { MarkdownComponent } from 'ngx-markdown';
27
27
  import { CdkMenu, CdkMenuItem } from '@angular/cdk/menu';
@@ -2767,16 +2767,19 @@ class TabsComponent {
2767
2767
  activeTab = model('', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
2768
2768
  tabChange = output();
2769
2769
  panels = contentChildren(TabPanelComponent, ...(ngDevMode ? [{ debugName: "panels" }] : /* istanbul ignore next */ []));
2770
- constructor() {
2771
- effect(() => {
2772
- const panelList = this.panels();
2773
- const currentActiveTab = untracked(() => this.activeTab());
2774
- if (panelList.length > 0 && !currentActiveTab) {
2775
- const firstEnabled = panelList.find((p) => !p.disabled());
2776
- if (firstEnabled) {
2777
- this.activeTab.set(firstEnabled.id());
2770
+ injector = inject(Injector);
2771
+ ngAfterViewInit() {
2772
+ runInInjectionContext(this.injector, () => {
2773
+ effect(() => {
2774
+ const panelList = this.panels();
2775
+ const currentActiveTab = untracked(() => this.activeTab());
2776
+ if (panelList.length > 0 && !currentActiveTab) {
2777
+ const firstEnabled = panelList.find(p => !p.disabled());
2778
+ if (firstEnabled) {
2779
+ this.activeTab.set(firstEnabled.id());
2780
+ }
2778
2781
  }
2779
- }
2782
+ });
2780
2783
  });
2781
2784
  }
2782
2785
  selectTab(panel) {
@@ -2788,19 +2791,17 @@ class TabsComponent {
2788
2791
  this.tabChange.emit({ previousTabId, currentTabId: panel.id() });
2789
2792
  }
2790
2793
  onKeydown(event, currentPanel) {
2791
- const enabledPanels = this.panels().filter((p) => !p.disabled());
2792
- const currentIndex = enabledPanels.findIndex((p) => p.id() === currentPanel.id());
2794
+ const enabledPanels = this.panels().filter(p => !p.disabled());
2795
+ const currentIndex = enabledPanels.findIndex(p => p.id() === currentPanel.id());
2793
2796
  if (currentIndex === -1)
2794
2797
  return;
2795
2798
  let targetIndex = null;
2796
2799
  switch (event.key) {
2797
2800
  case 'ArrowLeft':
2798
- targetIndex =
2799
- currentIndex > 0 ? currentIndex - 1 : enabledPanels.length - 1;
2801
+ targetIndex = currentIndex > 0 ? currentIndex - 1 : enabledPanels.length - 1;
2800
2802
  break;
2801
2803
  case 'ArrowRight':
2802
- targetIndex =
2803
- currentIndex < enabledPanels.length - 1 ? currentIndex + 1 : 0;
2804
+ targetIndex = currentIndex < enabledPanels.length - 1 ? currentIndex + 1 : 0;
2804
2805
  break;
2805
2806
  case 'Home':
2806
2807
  targetIndex = 0;
@@ -2828,7 +2829,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
2828
2829
  args: [{ selector: 'ao-tabs', imports: [NgTemplateOutlet, IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2829
2830
  class: 'ao-tabs',
2830
2831
  }, template: "<div class=\"ao-tabs__header\" role=\"tablist\">\n @for (panel of panels(); track panel.id()) {\n <button\n class=\"ao-tabs__tab\"\n role=\"tab\"\n type=\"button\"\n [class.ao-tabs__tab--active]=\"panel.id() === activeTab()\"\n [class.ao-tabs__tab--disabled]=\"panel.disabled()\"\n [attr.aria-selected]=\"panel.id() === activeTab()\"\n [attr.aria-controls]=\"'panel-' + panel.id()\"\n [attr.aria-disabled]=\"panel.disabled()\"\n [attr.data-tab-id]=\"panel.id()\"\n [attr.tabindex]=\"panel.id() === activeTab() ? 0 : -1\"\n [disabled]=\"panel.disabled()\"\n (click)=\"selectTab(panel)\"\n (keydown)=\"onKeydown($event, panel)\"\n >\n @if (panel.icon()) {\n <ao-icon [svg]=\"panel.icon()!\" size=\"sm\" />\n }\n {{ panel.label() }}\n </button>\n }\n</div>\n<div class=\"ao-tabs__content\">\n @for (panel of panels(); track panel.id()) {\n <div\n class=\"ao-tabs__panel\"\n role=\"tabpanel\"\n [id]=\"'panel-' + panel.id()\"\n [attr.aria-labelledby]=\"panel.id()\"\n [class.ao-tabs__panel--active]=\"panel.id() === activeTab()\"\n [attr.hidden]=\"panel.id() !== activeTab() ? true : null\"\n >\n @if (panel.id() === activeTab()) {\n <ng-container [ngTemplateOutlet]=\"panel.panelContent()\" />\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}.ao-tabs__header{display:flex;gap:20px;border-bottom:1px solid #e9e9e9}.ao-tabs__tab{font-size:13px;font-weight:700;line-height:19.5px;letter-spacing:0;position:relative;display:inline-flex;align-items:center;gap:5px;padding:10px 5px;background:transparent;border:none;color:#212121;cursor:pointer;transition:color .2s ease}.ao-tabs__tab:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:3px;background:transparent;transition:background-color .2s ease}.ao-tabs__tab:hover:not(:disabled){color:#ff004d}.ao-tabs__tab:focus-visible{outline:2px solid #ff004d;outline-offset:2px}.ao-tabs__tab--active{color:#ff004d}.ao-tabs__tab--active:after{background:#ff004d}.ao-tabs__tab--disabled{color:#909090;cursor:not-allowed}.ao-tabs__content{padding-top:15px}.ao-tabs__panel[hidden]{display:none}\n"] }]
2831
- }], ctorParameters: () => [], propDecorators: { activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }, { type: i0.Output, args: ["activeTabChange"] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }], panels: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TabPanelComponent), { isSignal: true }] }] } });
2832
+ }], propDecorators: { activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }, { type: i0.Output, args: ["activeTabChange"] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }], panels: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TabPanelComponent), { isSignal: true }] }] } });
2832
2833
 
2833
2834
  class SideNavComponent {
2834
2835
  items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
@@ -5971,7 +5972,7 @@ const ROBIN_SEARCH_APP_NAME = new InjectionToken('ROBIN_SEARCH_APP_NAME', {
5971
5972
  providedIn: 'root',
5972
5973
  factory: () => 'unknown',
5973
5974
  });
5974
- const QUICK_DEBOUNCE_MS = 200;
5975
+ const QUICK_THROTTLE_MS = 200;
5975
5976
  class RobinSearchService {
5976
5977
  http = inject(HttpClient);
5977
5978
  baseUrl = inject(ROBIN_API_BASE_URL);
@@ -5983,8 +5984,12 @@ class RobinSearchService {
5983
5984
  resultGroups = signal([], ...(ngDevMode ? [{ debugName: "resultGroups" }] : /* istanbul ignore next */ []));
5984
5985
  pageSuggestion = signal(null, ...(ngDevMode ? [{ debugName: "pageSuggestion" }] : /* istanbul ignore next */ []));
5985
5986
  aiSuggestions = signal([], ...(ngDevMode ? [{ debugName: "aiSuggestions" }] : /* istanbul ignore next */ []));
5986
- debounceHandle = null;
5987
- requestSeq = 0;
5987
+ quickSearchInput$ = new Subject();
5988
+ constructor() {
5989
+ this.quickSearchInput$
5990
+ .pipe(throttleTime(QUICK_THROTTLE_MS, asyncScheduler, { leading: true, trailing: true }), switchMap(({ query, type }) => this.fetchQuickSearch(query, type)))
5991
+ .subscribe((outcome) => this.applyQuickSearchOutcome(outcome));
5992
+ }
5988
5993
  async loadRecommendedFilters() {
5989
5994
  try {
5990
5995
  const params = new HttpParams().set('appName', this.appName);
@@ -5998,9 +6003,6 @@ class RobinSearchService {
5998
6003
  }
5999
6004
  search(query, type) {
6000
6005
  this.query.set(query);
6001
- if (this.debounceHandle !== null) {
6002
- clearTimeout(this.debounceHandle);
6003
- }
6004
6006
  if (!query.trim()) {
6005
6007
  this.resultGroups.set([]);
6006
6008
  this.pageSuggestion.set(null);
@@ -6010,9 +6012,7 @@ class RobinSearchService {
6010
6012
  return;
6011
6013
  }
6012
6014
  this.loading.set(true);
6013
- this.debounceHandle = setTimeout(() => {
6014
- void this.runQuickSearch(query, type);
6015
- }, QUICK_DEBOUNCE_MS);
6015
+ this.quickSearchInput$.next({ query, type });
6016
6016
  }
6017
6017
  async loadFull(query, type, date) {
6018
6018
  let params = new HttpParams().set('q', query).set('appName', this.appName);
@@ -6040,35 +6040,35 @@ class RobinSearchService {
6040
6040
  this.loading.set(false);
6041
6041
  }
6042
6042
  }
6043
- async runQuickSearch(query, type) {
6044
- const seq = ++this.requestSeq;
6043
+ fetchQuickSearch(query, type) {
6045
6044
  let params = new HttpParams().set('q', query).set('appName', this.appName);
6046
6045
  if (type)
6047
6046
  params = params.set('type', type);
6048
- try {
6049
- const payload = await firstValueFrom(this.http.get(this.url('/search/quick'), { params }));
6050
- if (seq !== this.requestSeq)
6051
- return;
6052
- const safe = payload ?? {};
6053
- this.resultGroups.set(safe.groups ?? []);
6054
- this.pageSuggestion.set(safe.pageSuggestion ?? null);
6055
- this.aiSuggestions.set(safe.aiSuggestions ?? []);
6056
- this.error.set(null);
6057
- }
6058
- catch (err) {
6059
- if (seq !== this.requestSeq)
6060
- return;
6047
+ return this.http
6048
+ .get(this.url('/search/quick'), { params })
6049
+ .pipe(map$1((payload) => ({ query, payload, failed: false })), catchError((err) => {
6061
6050
  console.warn('[RobinSearch] quickSearch failed', err);
6051
+ return of({ query, payload: null, failed: true });
6052
+ }));
6053
+ }
6054
+ applyQuickSearchOutcome(outcome) {
6055
+ if (this.query() !== outcome.query) {
6056
+ return;
6057
+ }
6058
+ if (outcome.failed) {
6062
6059
  this.error.set('Suche fehlgeschlagen');
6063
6060
  this.resultGroups.set([]);
6064
6061
  this.pageSuggestion.set(null);
6065
6062
  this.aiSuggestions.set([]);
6066
6063
  }
6067
- finally {
6068
- if (seq === this.requestSeq) {
6069
- this.loading.set(false);
6070
- }
6064
+ else {
6065
+ const safe = outcome.payload ?? {};
6066
+ this.resultGroups.set(safe.groups ?? []);
6067
+ this.pageSuggestion.set(safe.pageSuggestion ?? null);
6068
+ this.aiSuggestions.set(safe.aiSuggestions ?? []);
6069
+ this.error.set(null);
6071
6070
  }
6071
+ this.loading.set(false);
6072
6072
  }
6073
6073
  url(path) {
6074
6074
  return `${this.baseUrl}${path}`;
@@ -6079,7 +6079,7 @@ class RobinSearchService {
6079
6079
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: RobinSearchService, decorators: [{
6080
6080
  type: Injectable,
6081
6081
  args: [{ providedIn: 'root' }]
6082
- }] });
6082
+ }], ctorParameters: () => [] });
6083
6083
 
6084
6084
  class LogoMenuComponent {
6085
6085
  workspaceNavbarService = inject(WorkspaceNavbarService);
@@ -7184,7 +7184,7 @@ class WorkspaceNavbarComponent {
7184
7184
  ngAfterViewInit() {
7185
7185
  if (isPlatformBrowser(this.platformId)) {
7186
7186
  fromEvent(window, 'scroll', { passive: true })
7187
- .pipe(throttleTime(50), takeUntilDestroyed(this.destroyRef))
7187
+ .pipe(throttleTime$1(50), takeUntilDestroyed(this.destroyRef))
7188
7188
  .subscribe(() => {
7189
7189
  const scrollY = window.scrollY ?? window.pageYOffset ?? 0;
7190
7190
  if (scrollY <= this.scrollThreshold) {