@sinequa/atomic-angular 0.3.8 → 0.3.15

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.
@@ -1544,7 +1544,7 @@ class QueryService {
1544
1544
  transloco = inject(TranslocoService);
1545
1545
  API_URL = `${globalConfig.backendUrl}/api/v1`;
1546
1546
  // Represents the last result of a search operation with getResult().
1547
- result = {};
1547
+ result = signal({}, ...(ngDevMode ? [{ debugName: "result" }] : []));
1548
1548
  audit;
1549
1549
  /**
1550
1550
  * Performs a search query.
@@ -1558,20 +1558,21 @@ class QueryService {
1558
1558
  // if audit is set, always use it
1559
1559
  // if this.audit is set and audit is not set use this.audit
1560
1560
  // if this.audit is not set and audit is not set use default audit
1561
- const newAudit = audit ?? this.audit ?? { type: 'Search_Text', detail: { querytext: q?.text } };
1561
+ const newAudit = audit ?? this.audit ?? { type: "Search_Text", detail: { querytext: q?.text } };
1562
1562
  const $auditRecord = { auditEvents: [newAudit] };
1563
1563
  this.audit = undefined; // reset this.audit after using it
1564
+ this.result.set({}); // reset results for new search
1564
1565
  const { app } = globalConfig;
1565
1566
  const currentQuery = q ?? this.queryParamsStore.getQuery();
1566
1567
  const query = includeQueryParams ? { ...this.queryParamsStore.getQuery(), ...currentQuery } : currentQuery;
1567
1568
  // Check if the search query is empty and if empty searches are allowed
1568
1569
  // If not allowed, return an empty result
1569
1570
  // basket overrides this rule
1570
- if (!query.basket && query.action !== 'open') {
1571
- const allowEmptySearch = this.appStore.allowEmptySearch(query?.name || '');
1572
- if (allowEmptySearch === false && query?.text === '') {
1573
- warn('QueryService.search: Empty search query is not allowed. Returning empty result.');
1574
- notify.warning(this.transloco.translate('searches.emptySearch'));
1571
+ if (!query.basket && query.action !== "open") {
1572
+ const allowEmptySearch = this.appStore.allowEmptySearch(query?.name || "");
1573
+ if (allowEmptySearch === false && query?.text === "") {
1574
+ warn("QueryService.search: Empty search query is not allowed. Returning empty result.");
1575
+ notify.warning(this.transloco.translate("searches.emptySearch"));
1575
1576
  return of({ records: [] });
1576
1577
  }
1577
1578
  }
@@ -1580,8 +1581,8 @@ class QueryService {
1580
1581
  query,
1581
1582
  $auditRecord
1582
1583
  };
1583
- return this.http.post(this.API_URL + '/query', body).pipe(catchError(err => {
1584
- error('queryService.getResults failure - error: ', err);
1584
+ return this.http.post(this.API_URL + "/query", body).pipe(catchError((err) => {
1585
+ error("queryService.getResults failure - error: ", err);
1585
1586
  return of({});
1586
1587
  }), map((result) => {
1587
1588
  // update $hasMore flag
@@ -1599,19 +1600,21 @@ class QueryService {
1599
1600
  }
1600
1601
  });
1601
1602
  return result;
1602
- }), map(result => {
1603
- result.records?.map((article) => Object.assign(article, { value: article.title, type: 'default' }));
1603
+ }), map((result) => {
1604
+ result.records?.map((article) => Object.assign(article, { value: article.title, type: "default" }));
1604
1605
  return result;
1605
- }), map(result => {
1606
+ }), map((result) => {
1606
1607
  const r = {
1607
1608
  ...result,
1608
- nextPage: result.page !== undefined && result.page < Math.ceil(result.rowCount / result.pageSize) ? result.page + 1 : undefined,
1609
+ nextPage: result.page !== undefined && result.page < Math.ceil(result.rowCount / result.pageSize)
1610
+ ? result.page + 1
1611
+ : undefined,
1609
1612
  previousPage: result.page !== undefined && result.page > 1 ? result.page - 1 : undefined
1610
1613
  };
1611
1614
  return r;
1612
- }), tap(response => {
1613
- this.result = response;
1614
- info('queryService.getResults success - data: ', response);
1615
+ }), tap((response) => {
1616
+ this.result.set(response);
1617
+ info("queryService.getResults success - data: ", response);
1615
1618
  }));
1616
1619
  }
1617
1620
  /**
@@ -1622,7 +1625,7 @@ class QueryService {
1622
1625
  * @returns An Observable that emits an array of Result objects.
1623
1626
  */
1624
1627
  bulkSearch(q, audit) {
1625
- const { app = '' } = globalConfig;
1628
+ const { app = "" } = globalConfig;
1626
1629
  const body = {
1627
1630
  methods: [],
1628
1631
  propagateErrors: true,
@@ -1630,15 +1633,15 @@ class QueryService {
1630
1633
  };
1631
1634
  for (const query of q) {
1632
1635
  body.methods.push({
1633
- method: 'query',
1636
+ method: "query",
1634
1637
  app,
1635
1638
  query
1636
1639
  });
1637
1640
  }
1638
- return this.http.post(this.API_URL + '/multi', body).pipe(catchError(err => {
1639
- error('queryService.bulkSearch failure - error: ', err);
1641
+ return this.http.post(this.API_URL + "/multi", body).pipe(catchError((err) => {
1642
+ error("queryService.bulkSearch failure - error: ", err);
1640
1643
  return EMPTY;
1641
- }), map(response => {
1644
+ }), map((response) => {
1642
1645
  // update $hasMore flag
1643
1646
  response.results.forEach((result) => {
1644
1647
  result.aggregations.forEach((agg) => {
@@ -1656,11 +1659,13 @@ class QueryService {
1656
1659
  });
1657
1660
  });
1658
1661
  return response.results;
1659
- }), map(results => {
1660
- results.forEach(result => result.records?.map((article) => Object.assign(article, { value: article.title, type: 'default' })));
1662
+ }), map((results) => {
1663
+ results.forEach((result) => {
1664
+ result.records?.map((article) => Object.assign(article, { value: article.title, type: "default" }));
1665
+ });
1661
1666
  return results;
1662
- }), map(results => {
1663
- return results.map(result => {
1667
+ }), map((results) => {
1668
+ return results.map((result) => {
1664
1669
  const r = {
1665
1670
  ...result,
1666
1671
  nextPage: result.page < Math.ceil(result.rowCount / result.pageSize) ? result.page + 1 : undefined,
@@ -1670,8 +1675,8 @@ class QueryService {
1670
1675
  });
1671
1676
  }),
1672
1677
  // map(response => ResultsSchema.parse(response) as T),
1673
- tap(response => {
1674
- info('queryService.bulkSearch success - data: ', response);
1678
+ tap((response) => {
1679
+ info("queryService.bulkSearch success - data: ", response);
1675
1680
  }));
1676
1681
  }
1677
1682
  /**
@@ -1681,21 +1686,21 @@ class QueryService {
1681
1686
  */
1682
1687
  gotoPage(page) {
1683
1688
  const audit = {
1684
- type: 'Search_GotoPage',
1689
+ type: "Search_GotoPage",
1685
1690
  detail: {
1686
1691
  page: page,
1687
- fromresultid: this.result ? this.result.id : null
1692
+ fromresultid: this.result()?.id ?? null
1688
1693
  }
1689
1694
  };
1690
1695
  this.queryParamsStore.patch({ page }, audit);
1691
1696
  }
1692
1697
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: QueryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1693
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: QueryService, providedIn: 'root' });
1698
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: QueryService, providedIn: "root" });
1694
1699
  }
1695
1700
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: QueryService, decorators: [{
1696
1701
  type: Injectable,
1697
1702
  args: [{
1698
- providedIn: 'root'
1703
+ providedIn: "root"
1699
1704
  }]
1700
1705
  }] });
1701
1706
 
@@ -3443,7 +3448,7 @@ class PreviewService {
3443
3448
  const query = this.queryParamsStore.getQuery();
3444
3449
  try {
3445
3450
  const detail = this.getAuditPreviewDetail(article.id, query);
3446
- const result = this.queryService.result;
3451
+ const result = this.queryService.result();
3447
3452
  this.auditService.notifyDocument("Click_ResultLink", article, result || detail.resultid || "", {
3448
3453
  querytext: detail.querytext,
3449
3454
  querylang: detail.querylang,
@@ -3573,7 +3578,7 @@ class PreviewService {
3573
3578
  this.sendMessage({ action: "highlight", highlights });
3574
3579
  }
3575
3580
  getAuditPreviewDetail(id, q) {
3576
- const results = this.queryService.result;
3581
+ const results = this.queryService.result();
3577
3582
  const queryLanguage = results?.queryAnalysis?.queryLanguage ||
3578
3583
  q?.questionLanguage ||
3579
3584
  (q.name && this.appStore.getQueryByName(q.name)?.questionLanguage) ||
@@ -4570,7 +4575,14 @@ function withQueryParamsFeatures() {
4570
4575
  * @returns Query The constructed query object.
4571
4576
  */
4572
4577
  getQuery() {
4573
- const { filters: allFilters = [], sort, tab, basket, text: queryText = "", name = appStore.getDefaultQuery()?.name || "_query", spellingCorrectionMode } = getState(store);
4578
+ const { filters: allFilters = [], sort, tab, basket, text: queryText = "", spellingCorrectionMode } = getState(store);
4579
+ // check if a query name is defined
4580
+ // if not, try to get it from the route data or from the default query in the app store
4581
+ let { name } = getState(store);
4582
+ if (!name) {
4583
+ const routeData = route.snapshot.firstChild?.children[0]?.data;
4584
+ name = routeData ? routeData["queryName"] : appStore.getDefaultQuery()?.name || "";
4585
+ }
4574
4586
  let text = queryText;
4575
4587
  // remove concepts filters from the query to add them in the query expression
4576
4588
  const [conceptsFilters] = allFilters.filter((f) => f.field === "concepts");
@@ -6742,6 +6754,15 @@ class NavbarTabsComponent {
6742
6754
  * This works only if tabSearch is enabled in the administration panel.
6743
6755
  */
6744
6756
  showCount = input(true, ...(ngDevMode ? [{ debugName: "showCount", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
6757
+ /**
6758
+ * The base path for the search routes.
6759
+ * This value is provided as an input property and defaults to "search".
6760
+ *
6761
+ * @remarks
6762
+ * This path is used to find the corresponding route configuration and its children
6763
+ * to populate the tabs in the navbar.
6764
+ */
6765
+ path = input("search", ...(ngDevMode ? [{ debugName: "path" }] : []));
6745
6766
  searchText = computed(() => {
6746
6767
  const state = getState(this.queryParamsStore);
6747
6768
  return state.text || "";
@@ -6762,8 +6783,9 @@ class NavbarTabsComponent {
6762
6783
  }, ...(ngDevMode ? [{ debugName: "currentPath" }] : []));
6763
6784
  // create tabs from the search routes
6764
6785
  tabs = computed(() => {
6786
+ const result = this.queryService.result();
6765
6787
  const r = this.router.config
6766
- .find((item) => item.path === "search")
6788
+ .find((item) => item.path === this.path())
6767
6789
  ?.children?.filter((c) => c.path !== "**")
6768
6790
  .map((child) => {
6769
6791
  const data = child.data;
@@ -6771,11 +6793,14 @@ class NavbarTabsComponent {
6771
6793
  display: data?.display || child.path || "",
6772
6794
  wsQueryTab: data?.wsQueryTab || child.path || "",
6773
6795
  path: child.path || "",
6774
- routerLink: `/search/${child.path}`,
6796
+ routerLink: `/${this.path()}/${child.path}`,
6775
6797
  icon: data?.icon || "",
6776
6798
  queryName: data?.queryName,
6799
+ // get the count from the last search result if showCount is true and queryName matches
6777
6800
  count: this.showCount()
6778
- ? this.queryService.result?.tabs?.find((tab) => tab.name === (data?.wsQueryTab || child.path))?.count
6801
+ ? result.queryName === data?.queryName
6802
+ ? result.tabs?.find((tab) => tab.name === (data?.wsQueryTab || child.path))?.count
6803
+ : undefined
6779
6804
  : undefined
6780
6805
  };
6781
6806
  }) ?? [];
@@ -6787,7 +6812,7 @@ class NavbarTabsComponent {
6787
6812
  this.drawerStack.closeAll();
6788
6813
  }
6789
6814
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NavbarTabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6790
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NavbarTabsComponent, isStandalone: true, selector: "navbar-tabs", inputs: { showCount: { classPropertyName: "showCount", publicName: "showCount", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
6815
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: NavbarTabsComponent, isStandalone: true, selector: "navbar-tabs", inputs: { showCount: { classPropertyName: "showCount", publicName: "showCount", isSignal: true, isRequired: false, transformFunction: null }, path: { classPropertyName: "path", publicName: "path", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
6791
6816
  <!-- do not display the tabs if there are no tabs -->
6792
6817
  @if (tabs().length > 0) {
6793
6818
  <div overflowManager class="relative col-span-2 col-start-2 row-start-2 flex" (count)="visibleTabCount.set($event)">
@@ -6931,7 +6956,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
6931
6956
  }
6932
6957
  `
6933
6958
  }]
6934
- }], propDecorators: { showCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCount", required: false }] }] } });
6959
+ }], propDecorators: { showCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCount", required: false }] }], path: [{ type: i0.Input, args: [{ isSignal: true, alias: "path", required: false }] }] } });
6935
6960
 
6936
6961
  class NoResultComponent {
6937
6962
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NoResultComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -7068,7 +7093,7 @@ class PreviewNavigator {
7068
7093
  <button
7069
7094
  variant="ghost"
7070
7095
  size="icon"
7071
- class="dark:text-background dark:hover:bg-background/10"
7096
+ class="dark:text-white dark:hover:bg-background/10"
7072
7097
  aria-label="Page précédente"
7073
7098
  (click)="preview.firstPage()"
7074
7099
  [disabled]="isFirst()">
@@ -7077,19 +7102,19 @@ class PreviewNavigator {
7077
7102
  <button
7078
7103
  variant="ghost"
7079
7104
  size="icon"
7080
- class="dark:text-background dark:hover:bg-background/10"
7105
+ class="dark:text-white dark:hover:bg-background/10"
7081
7106
  aria-label="Page précédente"
7082
7107
  (click)="preview.prevPage()"
7083
7108
  [disabled]="isFirst()">
7084
7109
  <chevron-left />
7085
7110
  </button>
7086
7111
 
7087
- <div class="dark:text-background inline-flex items-center gap-1 px-1 tabular-nums">
7112
+ <div class="dark:text-white inline-flex items-center gap-1 px-1 tabular-nums">
7088
7113
  <input
7089
7114
  #page
7090
7115
  type="text"
7091
7116
  decoration="outline"
7092
- class="dark:hover:bg-background/10 dark:text-background dark:border-foreground w-14 py-0.5 text-center invalid:bg-red-200"
7117
+ class="dark:hover:bg-background/10 dark:text-white dark:border-foreground w-14 py-0.5 text-center invalid:bg-red-200"
7093
7118
  [min]="1"
7094
7119
  [max]="total() || 1"
7095
7120
  [value]="current()"
@@ -7104,7 +7129,7 @@ class PreviewNavigator {
7104
7129
  <button
7105
7130
  variant="ghost"
7106
7131
  size="icon"
7107
- class="dark:text-background dark:hover:bg-background/10"
7132
+ class="dark:text-white dark:hover:bg-background/10"
7108
7133
  aria-label="Page suivante"
7109
7134
  (click)="preview.nextPage()"
7110
7135
  [disabled]="isLast()">
@@ -7113,7 +7138,7 @@ class PreviewNavigator {
7113
7138
  <button
7114
7139
  variant="ghost"
7115
7140
  size="icon"
7116
- class="dark:text-background dark:hover:bg-background/10"
7141
+ class="dark:text-white dark:hover:bg-background/10"
7117
7142
  aria-label="Page suivante"
7118
7143
  (click)="preview.lastPage()"
7119
7144
  [disabled]="isLast()">
@@ -7137,7 +7162,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
7137
7162
  <button
7138
7163
  variant="ghost"
7139
7164
  size="icon"
7140
- class="dark:text-background dark:hover:bg-background/10"
7165
+ class="dark:text-white dark:hover:bg-background/10"
7141
7166
  aria-label="Page précédente"
7142
7167
  (click)="preview.firstPage()"
7143
7168
  [disabled]="isFirst()">
@@ -7146,19 +7171,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
7146
7171
  <button
7147
7172
  variant="ghost"
7148
7173
  size="icon"
7149
- class="dark:text-background dark:hover:bg-background/10"
7174
+ class="dark:text-white dark:hover:bg-background/10"
7150
7175
  aria-label="Page précédente"
7151
7176
  (click)="preview.prevPage()"
7152
7177
  [disabled]="isFirst()">
7153
7178
  <chevron-left />
7154
7179
  </button>
7155
7180
 
7156
- <div class="dark:text-background inline-flex items-center gap-1 px-1 tabular-nums">
7181
+ <div class="dark:text-white inline-flex items-center gap-1 px-1 tabular-nums">
7157
7182
  <input
7158
7183
  #page
7159
7184
  type="text"
7160
7185
  decoration="outline"
7161
- class="dark:hover:bg-background/10 dark:text-background dark:border-foreground w-14 py-0.5 text-center invalid:bg-red-200"
7186
+ class="dark:hover:bg-background/10 dark:text-white dark:border-foreground w-14 py-0.5 text-center invalid:bg-red-200"
7162
7187
  [min]="1"
7163
7188
  [max]="total() || 1"
7164
7189
  [value]="current()"
@@ -7173,7 +7198,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
7173
7198
  <button
7174
7199
  variant="ghost"
7175
7200
  size="icon"
7176
- class="dark:text-background dark:hover:bg-background/10"
7201
+ class="dark:text-white dark:hover:bg-background/10"
7177
7202
  aria-label="Page suivante"
7178
7203
  (click)="preview.nextPage()"
7179
7204
  [disabled]="isLast()">
@@ -7182,7 +7207,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
7182
7207
  <button
7183
7208
  variant="ghost"
7184
7209
  size="icon"
7185
- class="dark:text-background dark:hover:bg-background/10"
7210
+ class="dark:text-white dark:hover:bg-background/10"
7186
7211
  aria-label="Page suivante"
7187
7212
  (click)="preview.lastPage()"
7188
7213
  [disabled]="isLast()">
@@ -10666,6 +10691,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
10666
10691
 
10667
10692
  class AggregationComponent {
10668
10693
  cn = cn;
10694
+ searchInput = viewChild("searchInput", ...(ngDevMode ? [{ debugName: "searchInput" }] : []));
10669
10695
  /* stores */
10670
10696
  aggregationsStore = inject(AggregationsStore);
10671
10697
  queryParamsStore = inject(QueryParamsStore);
@@ -10824,6 +10850,14 @@ class AggregationComponent {
10824
10850
  effect(() => {
10825
10851
  sessionStorage.removeItem(`agg-${this.column()}`);
10826
10852
  });
10853
+ effect(() => {
10854
+ // focus the search input when expanded
10855
+ if (this.searchInput()?.nativeElement && this.expanded() !== null) {
10856
+ setTimeout(() => {
10857
+ this.searchInput()?.nativeElement.focus();
10858
+ }, 0);
10859
+ }
10860
+ });
10827
10861
  effect(async () => {
10828
10862
  if (this.debouncedSearchText() === "" || this.aggregation() === null) {
10829
10863
  this.suggests.set([]);
@@ -11268,7 +11302,7 @@ class AggregationComponent {
11268
11302
  });
11269
11303
  }
11270
11304
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AggregationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11271
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: AggregationComponent, isStandalone: true, selector: "Aggregation, aggregation", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, showFiltersCount: { classPropertyName: "showFiltersCount", publicName: "showFiltersCount", isSignal: true, isRequired: false, transformFunction: null }, searchText: { classPropertyName: "searchText", publicName: "searchText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect", searchText: "searchTextChange" }, host: { properties: { "class": "cn(\"block h-[inherit] max-h-[inherit]\",class())" } }, ngImport: i0, template: "<details (toggle)=\"onToggle($event)\" [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\n <summary [class.cursor-pointer]=\"collapsible() && !isEmpty()\" [class.text-muted-foreground]=\"isEmpty()\"\n class=\"m-0 mt-1 flex gap-1 h-8 w-full select-none items-center pl-1 font-semibold\" (click)=\"onHeaderClick($event)\">\n <ng-content select=\"label\">\n @if (aggregation()?.icon) {\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\n }\n <span class=\"grow\">{{ aggregation()?.display | syslang | transloco }}</span>\n </ng-content>\n\n @if (showFiltersCount() && filtersCount() > 0) {\n <!-- count -->\n <Badge size=\"xs\" class=\"ml-1 pb-0.5\">\n {{ filtersCount() }}\n </Badge>\n }\n <!-- apply filter block -->\n @if (!isCollapsed()) {\n <ButtonGroup>\n @if (hasFilters()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.clearFilters' | transloco\"\n [attr.aria-label]=\"'filters.clearFilters' | transloco\" (click)=\"$event.stopPropagation(); clear()\">\n <i class=\"fa-fw far fa-filter-circle-xmark\"></i>\n </button>\n }\n @if (selection()) {\n <button variant=\"outline\" size=\"xs\" [attr.title]=\"'filters.applyFilters' | transloco\"\n [attr.aria-label]=\"'filters.applyFilters' | transloco\" (click)=\"$event.stopPropagation(); apply()\" class=\"px-1 h-4\">\n <FilterIcon class=\"size-4\"/>\n {{ 'filters.apply' | transloco }}\n </button>\n }\n\n <!-- select / unselect all -->\n @if (isAllSelected()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.unselectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.unselectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); unselectAll()\">\n <i class=\"fa-fw far fa-check-square\"></i>\n </button>\n } @else {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.selectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.selectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); selectAll()\">\n <i class=\"fa-fw far fa-square\"></i>\n </button>\n }\n </ButtonGroup>\n }\n\n @if (collapsible()) {\n <button variant=\"none\" title=\"Open/Close\"\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\n <chevronright />\n </button>\n }\n </summary>\n\n <!-- content wrapper -->\n @if (aggregation()?.searchable && items().length) {\n <InputGroup class=\"group/item mt-1\">\n <input input-group type=\"text\" [attr.placeholder]=\"'search' | transloco\" [(ngModel)]=\"searchText\" class=\"mt-1\"/>\n <InputGroupAddon>\n <SearchIcon class=\"text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within/item:rotate-90\" />\n </InputGroupAddon>\n </InputGroup>\n <!-- <input type=\"text\" [placeholder]=\"'search' | transloco\" [(ngModel)]=\"searchText\" class=\"mt-1\" /> -->\n }\n\n <ul class=\"scrollbar-thin max-h-[calc(var(--height,100%)-100px)] snap-y snap-start overflow-auto\" role=\"list\"\n [attr.aria-label]=\"aggregation()?.display | syslang | transloco\">\n @for (item of items(); track $index) {\n <AggregationItem [node]=\"item\" [path]=\"[]\" [field]=\"aggregation()?.column\" (onSelect)=\"select()\"\n (onOpen)=\"open($event)\" (onFilter)=\"quickFilter($event)\" />\n }\n </ul>\n @if (aggregation()?.$hasMore && this.searchedItems().length === 0) {\n <button decoration=\"underline\" class=\"mt-1 flex w-full justify-center\" [attr.aria-label]=\"'loadMore' | transloco\"\n (click)=\"loadMore()\">\n {{ 'loadMore' | transloco }}\n </button>\n }\n</details>\n", styles: ["AggregationItem:has(+AggregationItem){margin-bottom:var(--agg-item-gap, 0)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: ButtonComponent, selector: "button,a[role=\"button\"]", inputs: ["class", "variant", "decoration", "size"] }, { kind: "component", type: AggregationItemComponent, selector: "aggregation-item, AggregationItem, aggregationitem", inputs: ["node", "path", "field"], outputs: ["onSelect", "onOpen", "onFilter"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "component", type: ChevronRightIcon, selector: "chevron-right, ChevronRight, chevronright, ChevronRightIcon", inputs: ["class"] }, { kind: "directive", type: ButtonGroup, selector: "button-group, ButtonGroup", inputs: ["class", "orientation"] }, { kind: "directive", type: InputGroupInput, selector: "input[input-group]", inputs: ["class", "type", "placeholder", "disabled"] }, { kind: "directive", type: InputGroupComponent, selector: "input-group, inputgroup, InputGroup", inputs: ["class"] }, { kind: "directive", type: InputGroupAddonComponent, selector: "input-group-addon, inputgroupaddon, InputGroupAddon", inputs: ["class", "align"] }, { kind: "component", type: SearchIcon, selector: "SearchIcon", inputs: ["class"] }, { kind: "component", type: FilterIcon, selector: "filter-icon, FilterIcon", inputs: ["class"] }, { kind: "pipe", type: SyslangPipe, name: "syslang" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
11305
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: AggregationComponent, isStandalone: true, selector: "Aggregation, aggregation", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, showFiltersCount: { classPropertyName: "showFiltersCount", publicName: "showFiltersCount", isSignal: true, isRequired: false, transformFunction: null }, searchText: { classPropertyName: "searchText", publicName: "searchText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect", searchText: "searchTextChange" }, host: { properties: { "class": "cn(\"block h-[inherit] max-h-[inherit]\",class())" } }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<details (toggle)=\"onToggle($event)\" [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\n <summary [class.cursor-pointer]=\"collapsible() && !isEmpty()\" [class.text-muted-foreground]=\"isEmpty()\"\n class=\"m-0 mt-1 flex gap-1 h-8 w-full select-none items-center pl-1 font-semibold\" (click)=\"onHeaderClick($event)\">\n <ng-content select=\"label\">\n @if (aggregation()?.icon) {\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\n }\n <span class=\"grow\">{{ aggregation()?.display | syslang | transloco }}</span>\n </ng-content>\n\n @if (showFiltersCount() && filtersCount() > 0) {\n <!-- count -->\n <Badge size=\"xs\" class=\"ml-1 pb-0.5\">\n {{ filtersCount() }}\n </Badge>\n }\n <!-- apply filter block -->\n @if (!isCollapsed()) {\n <ButtonGroup>\n @if (hasFilters()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.clearFilters' | transloco\"\n [attr.aria-label]=\"'filters.clearFilters' | transloco\" (click)=\"$event.stopPropagation(); clear()\">\n <i class=\"fa-fw far fa-filter-circle-xmark\"></i>\n </button>\n }\n @if (selection()) {\n <button variant=\"primary\" size=\"xs\" [attr.title]=\"'filters.applyFilters' | transloco\"\n [attr.aria-label]=\"'filters.applyFilters' | transloco\" (click)=\"$event.stopPropagation(); apply()\" class=\"px-1 h-4\">\n <FilterIcon class=\"size-4\"/>\n {{ 'filters.apply' | transloco }}\n </button>\n }\n\n <!-- select / unselect all -->\n @if (isAllSelected()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.unselectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.unselectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); unselectAll()\">\n <i class=\"fa-fw far fa-check-square\"></i>\n </button>\n } @else {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.selectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.selectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); selectAll()\">\n <i class=\"fa-fw far fa-square\"></i>\n </button>\n }\n </ButtonGroup>\n }\n\n @if (collapsible()) {\n <button variant=\"none\" title=\"Open/Close\"\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\n <chevronright />\n </button>\n }\n </summary>\n\n <!-- content wrapper -->\n @if (aggregation()?.searchable && items().length) {\n <InputGroup class=\"group/item mt-1\">\n <input #searchInput input-group id=\"aggregation-input-{{column()}}\" type=\"text\" [attr.placeholder]=\"'search' | transloco\" [(ngModel)]=\"searchText\" class=\"mt-1\"/>\n <InputGroupAddon>\n <SearchIcon class=\"text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within/item:rotate-90\" />\n </InputGroupAddon>\n </InputGroup>\n }\n\n <ul class=\"scrollbar-thin max-h-[calc(var(--height,100%)-100px)] snap-y snap-start overflow-auto\" role=\"list\"\n [attr.aria-label]=\"aggregation()?.display | syslang | transloco\">\n @for (item of items(); track $index) {\n <AggregationItem [node]=\"item\" [path]=\"[]\" [field]=\"aggregation()?.column\" (onSelect)=\"select()\"\n (onOpen)=\"open($event)\" (onFilter)=\"quickFilter($event)\" />\n }\n </ul>\n @if (aggregation()?.$hasMore && this.searchedItems().length === 0) {\n <button decoration=\"underline\" class=\"mt-1 flex w-full justify-center\" [attr.aria-label]=\"'loadMore' | transloco\"\n (click)=\"loadMore()\">\n {{ 'loadMore' | transloco }}\n </button>\n }\n</details>\n", styles: ["AggregationItem:has(+AggregationItem){margin-bottom:var(--agg-item-gap, 0)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: ButtonComponent, selector: "button,a[role=\"button\"]", inputs: ["class", "variant", "decoration", "size"] }, { kind: "component", type: AggregationItemComponent, selector: "aggregation-item, AggregationItem, aggregationitem", inputs: ["node", "path", "field"], outputs: ["onSelect", "onOpen", "onFilter"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "component", type: ChevronRightIcon, selector: "chevron-right, ChevronRight, chevronright, ChevronRightIcon", inputs: ["class"] }, { kind: "directive", type: ButtonGroup, selector: "button-group, ButtonGroup", inputs: ["class", "orientation"] }, { kind: "directive", type: InputGroupInput, selector: "input[input-group]", inputs: ["class", "type", "placeholder", "disabled"] }, { kind: "directive", type: InputGroupComponent, selector: "input-group, inputgroup, InputGroup", inputs: ["class"] }, { kind: "directive", type: InputGroupAddonComponent, selector: "input-group-addon, inputgroupaddon, InputGroupAddon", inputs: ["class", "align"] }, { kind: "component", type: SearchIcon, selector: "SearchIcon", inputs: ["class"] }, { kind: "component", type: FilterIcon, selector: "filter-icon, FilterIcon", inputs: ["class"] }, { kind: "pipe", type: SyslangPipe, name: "syslang" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
11272
11306
  }
11273
11307
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AggregationComponent, decorators: [{
11274
11308
  type: Component,
@@ -11289,8 +11323,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
11289
11323
  FilterIcon
11290
11324
  ], standalone: true, host: {
11291
11325
  "[class]": 'cn("block h-[inherit] max-h-[inherit]",class())'
11292
- }, template: "<details (toggle)=\"onToggle($event)\" [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\n <summary [class.cursor-pointer]=\"collapsible() && !isEmpty()\" [class.text-muted-foreground]=\"isEmpty()\"\n class=\"m-0 mt-1 flex gap-1 h-8 w-full select-none items-center pl-1 font-semibold\" (click)=\"onHeaderClick($event)\">\n <ng-content select=\"label\">\n @if (aggregation()?.icon) {\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\n }\n <span class=\"grow\">{{ aggregation()?.display | syslang | transloco }}</span>\n </ng-content>\n\n @if (showFiltersCount() && filtersCount() > 0) {\n <!-- count -->\n <Badge size=\"xs\" class=\"ml-1 pb-0.5\">\n {{ filtersCount() }}\n </Badge>\n }\n <!-- apply filter block -->\n @if (!isCollapsed()) {\n <ButtonGroup>\n @if (hasFilters()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.clearFilters' | transloco\"\n [attr.aria-label]=\"'filters.clearFilters' | transloco\" (click)=\"$event.stopPropagation(); clear()\">\n <i class=\"fa-fw far fa-filter-circle-xmark\"></i>\n </button>\n }\n @if (selection()) {\n <button variant=\"outline\" size=\"xs\" [attr.title]=\"'filters.applyFilters' | transloco\"\n [attr.aria-label]=\"'filters.applyFilters' | transloco\" (click)=\"$event.stopPropagation(); apply()\" class=\"px-1 h-4\">\n <FilterIcon class=\"size-4\"/>\n {{ 'filters.apply' | transloco }}\n </button>\n }\n\n <!-- select / unselect all -->\n @if (isAllSelected()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.unselectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.unselectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); unselectAll()\">\n <i class=\"fa-fw far fa-check-square\"></i>\n </button>\n } @else {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.selectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.selectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); selectAll()\">\n <i class=\"fa-fw far fa-square\"></i>\n </button>\n }\n </ButtonGroup>\n }\n\n @if (collapsible()) {\n <button variant=\"none\" title=\"Open/Close\"\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\n <chevronright />\n </button>\n }\n </summary>\n\n <!-- content wrapper -->\n @if (aggregation()?.searchable && items().length) {\n <InputGroup class=\"group/item mt-1\">\n <input input-group type=\"text\" [attr.placeholder]=\"'search' | transloco\" [(ngModel)]=\"searchText\" class=\"mt-1\"/>\n <InputGroupAddon>\n <SearchIcon class=\"text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within/item:rotate-90\" />\n </InputGroupAddon>\n </InputGroup>\n <!-- <input type=\"text\" [placeholder]=\"'search' | transloco\" [(ngModel)]=\"searchText\" class=\"mt-1\" /> -->\n }\n\n <ul class=\"scrollbar-thin max-h-[calc(var(--height,100%)-100px)] snap-y snap-start overflow-auto\" role=\"list\"\n [attr.aria-label]=\"aggregation()?.display | syslang | transloco\">\n @for (item of items(); track $index) {\n <AggregationItem [node]=\"item\" [path]=\"[]\" [field]=\"aggregation()?.column\" (onSelect)=\"select()\"\n (onOpen)=\"open($event)\" (onFilter)=\"quickFilter($event)\" />\n }\n </ul>\n @if (aggregation()?.$hasMore && this.searchedItems().length === 0) {\n <button decoration=\"underline\" class=\"mt-1 flex w-full justify-center\" [attr.aria-label]=\"'loadMore' | transloco\"\n (click)=\"loadMore()\">\n {{ 'loadMore' | transloco }}\n </button>\n }\n</details>\n", styles: ["AggregationItem:has(+AggregationItem){margin-bottom:var(--agg-item-gap, 0)}\n"] }]
11293
- }], ctorParameters: () => [], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], showFiltersCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFiltersCount", required: false }] }], searchText: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchText", required: false }] }, { type: i0.Output, args: ["searchTextChange"] }] } });
11326
+ }, template: "<details (toggle)=\"onToggle($event)\" [attr.open]=\"expanded()\" [attr.name]=\"id()\" class=\"group space-y-2\">\n <summary [class.cursor-pointer]=\"collapsible() && !isEmpty()\" [class.text-muted-foreground]=\"isEmpty()\"\n class=\"m-0 mt-1 flex gap-1 h-8 w-full select-none items-center pl-1 font-semibold\" (click)=\"onHeaderClick($event)\">\n <ng-content select=\"label\">\n @if (aggregation()?.icon) {\n <i class=\"fa-fw {{ aggregation()?.icon }} mr-1\" aria-hidden=\"true\"></i>\n }\n <span class=\"grow\">{{ aggregation()?.display | syslang | transloco }}</span>\n </ng-content>\n\n @if (showFiltersCount() && filtersCount() > 0) {\n <!-- count -->\n <Badge size=\"xs\" class=\"ml-1 pb-0.5\">\n {{ filtersCount() }}\n </Badge>\n }\n <!-- apply filter block -->\n @if (!isCollapsed()) {\n <ButtonGroup>\n @if (hasFilters()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.clearFilters' | transloco\"\n [attr.aria-label]=\"'filters.clearFilters' | transloco\" (click)=\"$event.stopPropagation(); clear()\">\n <i class=\"fa-fw far fa-filter-circle-xmark\"></i>\n </button>\n }\n @if (selection()) {\n <button variant=\"primary\" size=\"xs\" [attr.title]=\"'filters.applyFilters' | transloco\"\n [attr.aria-label]=\"'filters.applyFilters' | transloco\" (click)=\"$event.stopPropagation(); apply()\" class=\"px-1 h-4\">\n <FilterIcon class=\"size-4\"/>\n {{ 'filters.apply' | transloco }}\n </button>\n }\n\n <!-- select / unselect all -->\n @if (isAllSelected()) {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.unselectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.unselectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); unselectAll()\">\n <i class=\"fa-fw far fa-check-square\"></i>\n </button>\n } @else {\n <button variant=\"outline\" size=\"icon\" class=\"size-6\" [attr.title]=\"'filters.selectAllFilters' | transloco\"\n [attr.aria-label]=\"'filters.selectAllFilters' | transloco\" (click)=\"$event.stopPropagation(); selectAll()\">\n <i class=\"fa-fw far fa-square\"></i>\n </button>\n }\n </ButtonGroup>\n }\n\n @if (collapsible()) {\n <button variant=\"none\" title=\"Open/Close\"\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\n <chevronright />\n </button>\n }\n </summary>\n\n <!-- content wrapper -->\n @if (aggregation()?.searchable && items().length) {\n <InputGroup class=\"group/item mt-1\">\n <input #searchInput input-group id=\"aggregation-input-{{column()}}\" type=\"text\" [attr.placeholder]=\"'search' | transloco\" [(ngModel)]=\"searchText\" class=\"mt-1\"/>\n <InputGroupAddon>\n <SearchIcon class=\"text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within/item:rotate-90\" />\n </InputGroupAddon>\n </InputGroup>\n }\n\n <ul class=\"scrollbar-thin max-h-[calc(var(--height,100%)-100px)] snap-y snap-start overflow-auto\" role=\"list\"\n [attr.aria-label]=\"aggregation()?.display | syslang | transloco\">\n @for (item of items(); track $index) {\n <AggregationItem [node]=\"item\" [path]=\"[]\" [field]=\"aggregation()?.column\" (onSelect)=\"select()\"\n (onOpen)=\"open($event)\" (onFilter)=\"quickFilter($event)\" />\n }\n </ul>\n @if (aggregation()?.$hasMore && this.searchedItems().length === 0) {\n <button decoration=\"underline\" class=\"mt-1 flex w-full justify-center\" [attr.aria-label]=\"'loadMore' | transloco\"\n (click)=\"loadMore()\">\n {{ 'loadMore' | transloco }}\n </button>\n }\n</details>\n", styles: ["AggregationItem:has(+AggregationItem){margin-bottom:var(--agg-item-gap, 0)}\n"] }]
11327
+ }], ctorParameters: () => [], propDecorators: { searchInput: [{ type: i0.ViewChild, args: ["searchInput", { isSignal: true }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], showFiltersCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFiltersCount", required: false }] }], searchText: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchText", required: false }] }, { type: i0.Output, args: ["searchTextChange"] }] } });
11294
11328
 
11295
11329
  /**
11296
11330
  * Injection token that indicates whether custom date ranges are allowed.
@@ -11627,7 +11661,8 @@ class FilterButtonComponent {
11627
11661
  [variant]="variant()"
11628
11662
  class="group-open:border-foreground/50 group-open:border"
11629
11663
  [attr.data-disabled]="filter().disabled"
11630
- [disabled]="filter().disabled || null">
11664
+ [disabled]="filter().disabled || null"
11665
+ >
11631
11666
  <!-- display the filter icon if set -->
11632
11667
  @if (filter().icon) {
11633
11668
  <i class="fa-fw {{ filter().icon }} " aria-hidden="true"></i>
@@ -11651,11 +11686,12 @@ class FilterButtonComponent {
11651
11686
  }
11652
11687
  </button>
11653
11688
 
11654
- <PopoverContent
11689
+ <PopoverContent #contentRef="popoverContent"
11655
11690
  class="min-w-fit w-max max-w-[90vw]"
11656
11691
  [position]="position()"
11657
11692
  [offset]="offset()"
11658
11693
  >
11694
+ @if(contentRef.isVisible) {
11659
11695
  @if (isDate(filter().column)) {
11660
11696
  <DateFilter
11661
11697
  class="*:details-content:[--height:19lh] w-max max-w-80"
@@ -11671,9 +11707,10 @@ class FilterButtonComponent {
11671
11707
  [column]="filter().column"
11672
11708
  id="filter-{{ filter().column }}" />
11673
11709
  }
11710
+ }
11674
11711
  </PopoverContent>
11675
11712
  </Popover>
11676
- `, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button,a[role=\"button\"]", inputs: ["class", "variant", "decoration", "size"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["position", "keepOpen", "class", "offset"] }, { kind: "component", type: AggregationComponent, selector: "Aggregation, aggregation", inputs: ["class", "id", "name", "column", "collapsible", "collapsed", "searchable", "showFiltersCount", "searchText"], outputs: ["onSelect", "searchTextChange"] }, { kind: "component", type: DateComponent, selector: "date-filter,DateFilter", inputs: ["title", "displayEmptyDistributionIntervals"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "pipe", type: OperatorPipe, name: "operator" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: SyslangPipe, name: "syslang" }] });
11713
+ `, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button,a[role=\"button\"]", inputs: ["class", "variant", "decoration", "size"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["position", "keepOpen", "class", "offset"], exportAs: ["popoverContent"] }, { kind: "component", type: AggregationComponent, selector: "Aggregation, aggregation", inputs: ["class", "id", "name", "column", "collapsible", "collapsed", "searchable", "showFiltersCount", "searchText"], outputs: ["onSelect", "searchTextChange"] }, { kind: "component", type: DateComponent, selector: "date-filter,DateFilter", inputs: ["title", "displayEmptyDistributionIntervals"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "pipe", type: OperatorPipe, name: "operator" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: SyslangPipe, name: "syslang" }] });
11677
11714
  }
11678
11715
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterButtonComponent, decorators: [{
11679
11716
  type: Component,
@@ -11697,7 +11734,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
11697
11734
  [variant]="variant()"
11698
11735
  class="group-open:border-foreground/50 group-open:border"
11699
11736
  [attr.data-disabled]="filter().disabled"
11700
- [disabled]="filter().disabled || null">
11737
+ [disabled]="filter().disabled || null"
11738
+ >
11701
11739
  <!-- display the filter icon if set -->
11702
11740
  @if (filter().icon) {
11703
11741
  <i class="fa-fw {{ filter().icon }} " aria-hidden="true"></i>
@@ -11721,11 +11759,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
11721
11759
  }
11722
11760
  </button>
11723
11761
 
11724
- <PopoverContent
11762
+ <PopoverContent #contentRef="popoverContent"
11725
11763
  class="min-w-fit w-max max-w-[90vw]"
11726
11764
  [position]="position()"
11727
11765
  [offset]="offset()"
11728
11766
  >
11767
+ @if(contentRef.isVisible) {
11729
11768
  @if (isDate(filter().column)) {
11730
11769
  <DateFilter
11731
11770
  class="*:details-content:[--height:19lh] w-max max-w-80"
@@ -11741,6 +11780,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
11741
11780
  [column]="filter().column"
11742
11781
  id="filter-{{ filter().column }}" />
11743
11782
  }
11783
+ }
11744
11784
  </PopoverContent>
11745
11785
  </Popover>
11746
11786
  `,
@@ -11928,11 +11968,13 @@ class MoreButtonComponent {
11928
11968
  }
11929
11969
  </button>
11930
11970
 
11931
- <PopoverContent [position]="position()" class="min-w-max">
11971
+ <PopoverContent #contentRef="popoverContent" [position]="position()" class="min-w-max">
11972
+ @if(contentRef.isVisible) {
11932
11973
  <More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" class="block h-full w-full max-w-80 [--height:55vh] min-w-40 overflow-hidden" />
11974
+ }
11933
11975
  </PopoverContent>
11934
11976
  </Popover>
11935
- `, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button,a[role=\"button\"]", inputs: ["class", "variant", "decoration", "size"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["position", "keepOpen", "class", "offset"] }, { kind: "component", type: MoreComponent, selector: "more, More", inputs: ["count", "includedFilters", "excludedFilters", "aggregations"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
11977
+ `, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button,a[role=\"button\"]", inputs: ["class", "variant", "decoration", "size"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["position", "keepOpen", "class", "offset"], exportAs: ["popoverContent"] }, { kind: "component", type: MoreComponent, selector: "more, More", inputs: ["count", "includedFilters", "excludedFilters", "aggregations"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
11936
11978
  }
11937
11979
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MoreButtonComponent, decorators: [{
11938
11980
  type: Component,
@@ -11956,8 +11998,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
11956
11998
  }
11957
11999
  </button>
11958
12000
 
11959
- <PopoverContent [position]="position()" class="min-w-max">
12001
+ <PopoverContent #contentRef="popoverContent" [position]="position()" class="min-w-max">
12002
+ @if(contentRef.isVisible) {
11960
12003
  <More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" class="block h-full w-full max-w-80 [--height:55vh] min-w-40 overflow-hidden" />
12004
+ }
11961
12005
  </PopoverContent>
11962
12006
  </Popover>
11963
12007
  `
@@ -12412,22 +12456,26 @@ class MultiSelectLabelsComponent {
12412
12456
  labelsField = input(...(ngDevMode ? [undefined, { debugName: "labelsField" }] : []));
12413
12457
  anchor = signal(`--${guid()}`, ...(ngDevMode ? [{ debugName: "anchor" }] : []));
12414
12458
  suggestedLabels = signal([], ...(ngDevMode ? [{ debugName: "suggestedLabels" }] : []));
12415
- labelInput = model('', ...(ngDevMode ? [{ debugName: "labelInput" }] : []));
12459
+ labelInput = model("", ...(ngDevMode ? [{ debugName: "labelInput" }] : []));
12416
12460
  debouncedLabelInput = debouncedSignal(this.labelInput, DEBOUNCE_DELAY);
12417
- popover = viewChild('LabelsPopover', ...(ngDevMode ? [{ debugName: "popover" }] : []));
12461
+ popover = viewChild("LabelsPopover", ...(ngDevMode ? [{ debugName: "popover" }] : []));
12418
12462
  popoverElement = computed(() => this.popover()?.nativeElement, ...(ngDevMode ? [{ debugName: "popoverElement" }] : []));
12419
12463
  labels = signal([], ...(ngDevMode ? [{ debugName: "labels" }] : []));
12464
+ hasError = signal(false, ...(ngDevMode ? [{ debugName: "hasError" }] : []));
12420
12465
  id = signal(`labels-form-${guid()}`, ...(ngDevMode ? [{ debugName: "id" }] : []));
12421
12466
  constructor() {
12422
12467
  afterEveryRender(() => {
12423
12468
  this.popoverElement().style.positionAnchor = this.anchor();
12424
12469
  });
12425
12470
  effect(() => {
12426
- if (!this.article())
12471
+ const article = this.article();
12472
+ const labelsField = this.labelsField();
12473
+ if (!article)
12427
12474
  return;
12428
- if (!this.labelsField())
12475
+ if (!labelsField)
12429
12476
  return;
12430
- this.labels.set(this.article()[this.labelsField()] || []);
12477
+ const labels = article[labelsField];
12478
+ this.labels.set(labels || []);
12431
12479
  });
12432
12480
  effect(() => {
12433
12481
  this.fetchLabels(this.debouncedLabelInput(), this.isPublic());
@@ -12445,14 +12493,14 @@ class MultiSelectLabelsComponent {
12445
12493
  event.stopImmediatePropagation();
12446
12494
  if (this.labelInput().length === 0)
12447
12495
  return;
12448
- if (event.key === 'Enter') {
12496
+ if (event.key === "Enter") {
12449
12497
  this.addLabel(this.labelInput(), this.isPublic());
12450
- this.labelInput.set('');
12498
+ this.labelInput.set("");
12451
12499
  }
12452
12500
  }
12453
12501
  async fetchLabels(text, isPublic) {
12454
12502
  const labels = (await withFetch(() => fetchLabels(text, isPublic), this.injector)) || [];
12455
- const unappliedLabels = labels.filter(label => !this.labels().some(l => l === label));
12503
+ const unappliedLabels = labels.filter((label) => !this.labels().some((l) => l === label));
12456
12504
  this.suggestedLabels.set(unappliedLabels);
12457
12505
  unappliedLabels.length ? this.popoverElement().showPopover() : this.popoverElement().hidePopover();
12458
12506
  }
@@ -12470,12 +12518,21 @@ class MultiSelectLabelsComponent {
12470
12518
  * @returns A promise that resolves once the label has been added and the article updated.
12471
12519
  */
12472
12520
  async addLabel(label, isPublic) {
12473
- const currentLabels = this.labels();
12474
- this.labels.set([...currentLabels, label]);
12475
- await labels.add([label], [this.article().id], isPublic);
12476
- this.updateArticleWithLabels();
12477
- this.labelInput.set('');
12478
- this.suggestedLabels.set([]);
12521
+ this.hasError.set(false);
12522
+ const article = this.article();
12523
+ if (!article)
12524
+ return;
12525
+ try {
12526
+ await labels.add([label], [article.id], isPublic);
12527
+ const currentLabels = this.labels();
12528
+ this.labels.set([...currentLabels, label]);
12529
+ this.updateArticleWithLabels();
12530
+ this.labelInput.set("");
12531
+ this.suggestedLabels.set([]);
12532
+ }
12533
+ catch {
12534
+ this.hasError.set(true);
12535
+ }
12479
12536
  }
12480
12537
  /**
12481
12538
  * Removes a label from the current list of labels and updates the associated article.
@@ -12485,9 +12542,18 @@ class MultiSelectLabelsComponent {
12485
12542
  * @returns A promise that resolves once the label is removed and the article is updated.
12486
12543
  */
12487
12544
  async removeLabel(label, isPublic) {
12488
- this.labels.set(this.labels().filter(l => l !== label));
12489
- await labels.remove([label], [this.article().id], isPublic);
12490
- this.updateArticleWithLabels();
12545
+ this.hasError.set(false);
12546
+ const article = this.article();
12547
+ if (!article)
12548
+ return;
12549
+ try {
12550
+ await labels.remove([label], [article.id], isPublic);
12551
+ this.labels.set(this.labels().filter((l) => l !== label));
12552
+ this.updateArticleWithLabels();
12553
+ }
12554
+ catch {
12555
+ this.hasError.set(true);
12556
+ }
12491
12557
  }
12492
12558
  /**
12493
12559
  * Updates the article object by assigning the current labels to the specified labels field.
@@ -12499,13 +12565,18 @@ class MultiSelectLabelsComponent {
12499
12565
  * Ensure that `this.article`, `this.labelsField`, and `this.labels` return valid values
12500
12566
  * before invoking this method to avoid runtime errors.
12501
12567
  *
12502
- * @throws {TypeError} If `this.article` or `this.labelsField` returns `undefined`.
12503
12568
  */
12504
12569
  updateArticleWithLabels() {
12505
- this.article()[this.labelsField()] = this.labels();
12570
+ const article = this.article();
12571
+ const labelsField = this.labelsField();
12572
+ if (!article)
12573
+ return;
12574
+ if (!labelsField)
12575
+ return;
12576
+ article[labelsField] = this.labels();
12506
12577
  }
12507
12578
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MultiSelectLabelsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12508
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: MultiSelectLabelsComponent, isStandalone: true, selector: "multiselect-labels, multiselectlabels, MultiSelectLabels", inputs: { article: { classPropertyName: "article", publicName: "article", isSignal: true, isRequired: false, transformFunction: null }, isPublic: { classPropertyName: "isPublic", publicName: "isPublic", isSignal: true, isRequired: false, transformFunction: null }, allowModification: { classPropertyName: "allowModification", publicName: "allowModification", isSignal: true, isRequired: false, transformFunction: null }, labelsField: { classPropertyName: "labelsField", publicName: "labelsField", isSignal: true, isRequired: false, transformFunction: null }, labelInput: { classPropertyName: "labelInput", publicName: "labelInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { article: "articleChange", labelInput: "labelInputChange" }, viewQueries: [{ propertyName: "popover", first: true, predicate: ["LabelsPopover"], descendants: true, isSignal: true }], ngImport: i0, template: `
12579
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: MultiSelectLabelsComponent, isStandalone: true, selector: "multiselect-labels, multiselectlabels, MultiSelectLabels", inputs: { article: { classPropertyName: "article", publicName: "article", isSignal: true, isRequired: false, transformFunction: null }, isPublic: { classPropertyName: "isPublic", publicName: "isPublic", isSignal: true, isRequired: false, transformFunction: null }, allowModification: { classPropertyName: "allowModification", publicName: "allowModification", isSignal: true, isRequired: false, transformFunction: null }, labelsField: { classPropertyName: "labelsField", publicName: "labelsField", isSignal: true, isRequired: false, transformFunction: null }, labelInput: { classPropertyName: "labelInput", publicName: "labelInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { article: "articleChange", labelInput: "labelInputChange" }, providers: [provideTranslocoScope("labels")], viewQueries: [{ propertyName: "popover", first: true, predicate: ["LabelsPopover"], descendants: true, isSignal: true }], ngImport: i0, template: `
12509
12580
  <div class="anchor" [ngStyle]="{ 'anchor-name': anchor() }">
12510
12581
  <label [htmlFor]="id()" class="font-semibold">{{ (isPublic() ? 'labels.publicLabels' : 'labels.privateLabels') | transloco }}</label>
12511
12582
  <input
@@ -12542,11 +12613,16 @@ class MultiSelectLabelsComponent {
12542
12613
  </Badge>
12543
12614
  }
12544
12615
  </div>
12616
+ @if (hasError()) {
12617
+ <div class="p-4 w-full bg-destructive/20 border-destructive">
12618
+ {{ 'labels.error' | transloco }}
12619
+ </div>
12620
+ }
12545
12621
  `, isInline: true, styles: [".anchor:has(.popover:popover-open){z-index:var(--z-menu, 1000);border-radius:var(--radius) var(--radius) 0 0}.anchor .popover::backdrop{background-color:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.popover{width:anchor-size(width);top:anchor(bottom);left:anchor(left)}@supports (-moz-appearance: none){.popover{margin:calc(33.3333333333vh + 30px) 25vw;width:50vw}}@supports (background: -webkit-named-image(i)){.popover{margin:calc(33.3333333333vh + 30px) 25vw;width:50vw}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: InputComponent, selector: "input[type=\"text\"], input[type=\"email\"], input[type=\"number\"], input[type=\"password\"], input[type=\"tel\"], input[type=\"url\"], input[type=\"time\"]", inputs: ["class", "variant", "decoration"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant"] }, { kind: "directive", type: ListItemComponent, selector: "[role=\"listitem\"], [role=\"option\"]", inputs: ["class", "variant", "decoration"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
12546
12622
  }
12547
12623
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MultiSelectLabelsComponent, decorators: [{
12548
12624
  type: Component,
12549
- args: [{ selector: 'multiselect-labels, multiselectlabels, MultiSelectLabels', standalone: true, imports: [FormsModule, NgStyle, TranslocoPipe, InputComponent, BadgeComponent, ListItemComponent], template: `
12625
+ args: [{ selector: "multiselect-labels, multiselectlabels, MultiSelectLabels", providers: [provideTranslocoScope("labels")], standalone: true, imports: [FormsModule, NgStyle, TranslocoPipe, InputComponent, BadgeComponent, ListItemComponent], template: `
12550
12626
  <div class="anchor" [ngStyle]="{ 'anchor-name': anchor() }">
12551
12627
  <label [htmlFor]="id()" class="font-semibold">{{ (isPublic() ? 'labels.publicLabels' : 'labels.privateLabels') | transloco }}</label>
12552
12628
  <input
@@ -12583,8 +12659,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
12583
12659
  </Badge>
12584
12660
  }
12585
12661
  </div>
12662
+ @if (hasError()) {
12663
+ <div class="p-4 w-full bg-destructive/20 border-destructive">
12664
+ {{ 'labels.error' | transloco }}
12665
+ </div>
12666
+ }
12586
12667
  `, styles: [".anchor:has(.popover:popover-open){z-index:var(--z-menu, 1000);border-radius:var(--radius) var(--radius) 0 0}.anchor .popover::backdrop{background-color:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.popover{width:anchor-size(width);top:anchor(bottom);left:anchor(left)}@supports (-moz-appearance: none){.popover{margin:calc(33.3333333333vh + 30px) 25vw;width:50vw}}@supports (background: -webkit-named-image(i)){.popover{margin:calc(33.3333333333vh + 30px) 25vw;width:50vw}}\n"] }]
12587
- }], ctorParameters: () => [], propDecorators: { article: [{ type: i0.Input, args: [{ isSignal: true, alias: "article", required: false }] }, { type: i0.Output, args: ["articleChange"] }], isPublic: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPublic", required: false }] }], allowModification: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowModification", required: false }] }], labelsField: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelsField", required: false }] }], labelInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelInput", required: false }] }, { type: i0.Output, args: ["labelInputChange"] }], popover: [{ type: i0.ViewChild, args: ['LabelsPopover', { isSignal: true }] }] } });
12668
+ }], ctorParameters: () => [], propDecorators: { article: [{ type: i0.Input, args: [{ isSignal: true, alias: "article", required: false }] }, { type: i0.Output, args: ["articleChange"] }], isPublic: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPublic", required: false }] }], allowModification: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowModification", required: false }] }], labelsField: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelsField", required: false }] }], labelInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelInput", required: false }] }, { type: i0.Output, args: ["labelInputChange"] }], popover: [{ type: i0.ViewChild, args: ["LabelsPopover", { isSignal: true }] }] } });
12588
12669
 
12589
12670
  class LabelsEditDialog {
12590
12671
  destroyRef;