@acorex/platform 21.0.0-next.63 → 21.0.0-next.64

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 { signal, computed, Injectable, InjectionToken, inject, ElementRef, effect, untracked, Injector, ChangeDetectorRef, ViewChild, Input, ChangeDetectionStrategy, Component, EventEmitter, Output, input, output, ViewContainerRef, Directive, NgModule } from '@angular/core';
2
+ import { signal, computed, Injectable, InjectionToken, inject, ElementRef, effect, untracked, EventEmitter, Injector, ChangeDetectorRef, ViewChild, Input, Output, ChangeDetectionStrategy, Component, input, output, ViewContainerRef, Directive, NgModule } from '@angular/core';
3
3
  import { convertArrayToDataSource, AXDataSource } from '@acorex/cdk/common';
4
4
  import { AXPContextStore, AXPDataSourceDefinitionProviderService, extractValue, AXPExpressionEvaluatorService, getSmart } from '@acorex/platform/core';
5
5
  export { normalizeDefinitionCategories } from '@acorex/platform/core';
@@ -1163,6 +1163,9 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1163
1163
  this.pendingEvaluations = new Set();
1164
1164
  this.changeDetectionScheduled = false;
1165
1165
  this.MAX_CACHE_SIZE = 1000; // Limit cache size to prevent memory leaks
1166
+ /** When true, header click cycles sort (handled by parent; synced with list sort state). */
1167
+ this.sortEnabled = false;
1168
+ this.sortToggle = new EventEmitter();
1166
1169
  this.injector = inject(Injector);
1167
1170
  this.cdr = inject(ChangeDetectorRef);
1168
1171
  }
@@ -1210,6 +1213,23 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1210
1213
  getHeaderTextAlign() {
1211
1214
  return this.resolveAlignForSide('header');
1212
1215
  }
1216
+ getHeaderJustifyContent() {
1217
+ const align = this.getHeaderTextAlign();
1218
+ if (align === 'center') {
1219
+ return 'center';
1220
+ }
1221
+ if (align === 'end') {
1222
+ return 'flex-end';
1223
+ }
1224
+ return 'flex-start';
1225
+ }
1226
+ onHeaderClick(event) {
1227
+ if (!this.sortEnabled) {
1228
+ return;
1229
+ }
1230
+ event.stopPropagation();
1231
+ this.sortToggle.emit(event);
1232
+ }
1213
1233
  /**
1214
1234
  * When true, the cell body uses flex so `justify-content` can place content on the main axis.
1215
1235
  */
@@ -1289,8 +1309,14 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1289
1309
  });
1290
1310
  this.width = this.mergedOptions().width === 'auto' ? 'auto' : this.customWidth ? this.customWidth : (this.mergedOptions().width ?? '200px');
1291
1311
  this.allowResizing = this.mergedOptions().allowResizing || true;
1312
+ this.allowSorting = this.sortEnabled;
1292
1313
  this.cdr.detectChanges();
1293
1314
  }
1315
+ ngOnChanges() {
1316
+ this.allowSorting = this.sortEnabled;
1317
+ this.sortOrder = this.headerSortDirection;
1318
+ this.sortIndex = this.headerSortPriority;
1319
+ }
1294
1320
  //#region ---- Performance Optimization Methods ----
1295
1321
  /**
1296
1322
  * Check if options contain any expressions that need evaluation
@@ -1453,12 +1479,34 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1453
1479
  return rowInjector;
1454
1480
  }
1455
1481
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWidgetColumnRendererComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1456
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPWidgetColumnRendererComponent, isStandalone: false, selector: "axp-widget-column-renderer", inputs: { caption: "caption", customExpandIcon: "customExpandIcon", customCollapseIcon: "customCollapseIcon", customWidth: "customWidth", node: "node", footerTemplate: "footerTemplate", expandHandler: "expandHandler", cellTemplate: "cellTemplate", headerTemplate: "headerTemplate" }, providers: [
1482
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPWidgetColumnRendererComponent, isStandalone: false, selector: "axp-widget-column-renderer", inputs: { caption: "caption", customExpandIcon: "customExpandIcon", customCollapseIcon: "customCollapseIcon", customWidth: "customWidth", node: "node", footerTemplate: "footerTemplate", expandHandler: "expandHandler", sortEnabled: "sortEnabled", headerSortDirection: "headerSortDirection", headerSortPriority: "headerSortPriority", cellTemplate: "cellTemplate", headerTemplate: "headerTemplate" }, outputs: { sortToggle: "sortToggle" }, providers: [
1457
1483
  AXPWidgetCoreService,
1458
1484
  { provide: AXDataTableColumnComponent, useExisting: AXPWidgetColumnRendererComponent },
1459
- ], viewQueries: [{ propertyName: "_contentFooterTemplate", first: true, predicate: ["footer"], descendants: true }, { propertyName: "_contentCellTemplate", first: true, predicate: ["cell"], descendants: true }, { propertyName: "_contentHeaderTemplate", first: true, predicate: ["header"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
1485
+ ], viewQueries: [{ propertyName: "_contentFooterTemplate", first: true, predicate: ["footer"], descendants: true }, { propertyName: "_contentCellTemplate", first: true, predicate: ["cell"], descendants: true }, { propertyName: "_contentHeaderTemplate", first: true, predicate: ["header"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
1460
1486
  <ng-template #header>
1461
- <div class="ax-w-full" [style.text-align]="getHeaderTextAlign()">{{ caption | translate | async }}</div>
1487
+ <div
1488
+ class="axp-widget-column-header ax-w-full ax-flex ax-items-center ax-gap-1 ax-select-none"
1489
+ [class.axp-widget-column-header--sortable]="sortEnabled"
1490
+ [style.justify-content]="getHeaderJustifyContent()"
1491
+ (click)="onHeaderClick($event)"
1492
+ >
1493
+ <span class="axp-widget-column-header__caption ax-truncate">{{ caption | translate | async }}</span>
1494
+ @if (sortEnabled) {
1495
+ <span class="axp-widget-column-header__sort ax-flex ax-items-center ax-gap-0.5 ax-shrink-0">
1496
+ @if (headerSortPriority !== undefined && headerSortPriority > 1) {
1497
+ <span class="axp-widget-column-header__sort-priority ax-text-xs ax-opacity-70">{{ headerSortPriority }}</span>
1498
+ }
1499
+ <i
1500
+ class="fa-solid fa-arrow-up-long ax-text-neutral-400"
1501
+ [class.ax-text-primary]="headerSortDirection === 'asc'"
1502
+ ></i>
1503
+ <i
1504
+ class="fa-solid fa-arrow-down-long ax-text-neutral-400"
1505
+ [class.ax-text-primary]="headerSortDirection === 'desc'"
1506
+ ></i>
1507
+ </span>
1508
+ }
1509
+ </div>
1462
1510
  </ng-template>
1463
1511
  <ng-template #cell let-row>
1464
1512
  <div
@@ -1495,15 +1543,35 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1495
1543
  </div>
1496
1544
  </ng-template>
1497
1545
  <ng-template #footer></ng-template>
1498
- `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1546
+ `, isInline: true, styles: [".axp-widget-column-header--sortable{cursor:pointer}.axp-widget-column-header__caption{min-width:0}.axp-widget-column-header__sort{opacity:0;transition:opacity .15s ease}.axp-widget-column-header--sortable:hover .axp-widget-column-header__sort,.axp-widget-column-header--sortable:focus-within .axp-widget-column-header__sort{opacity:1}.axp-widget-column-header__sort-priority{line-height:1}:host-context(.ax-data-table-head-cell.ax-interactive:hover) .axp-widget-column-header__sort,:host-context(.ax-data-table-head-cell.ax-interactive:focus-within) .axp-widget-column-header__sort{opacity:1}\n"], dependencies: [{ kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1499
1547
  }
1500
1548
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWidgetColumnRendererComponent, decorators: [{
1501
1549
  type: Component,
1502
- args: [{
1503
- selector: 'axp-widget-column-renderer',
1504
- template: `
1550
+ args: [{ selector: 'axp-widget-column-renderer', template: `
1505
1551
  <ng-template #header>
1506
- <div class="ax-w-full" [style.text-align]="getHeaderTextAlign()">{{ caption | translate | async }}</div>
1552
+ <div
1553
+ class="axp-widget-column-header ax-w-full ax-flex ax-items-center ax-gap-1 ax-select-none"
1554
+ [class.axp-widget-column-header--sortable]="sortEnabled"
1555
+ [style.justify-content]="getHeaderJustifyContent()"
1556
+ (click)="onHeaderClick($event)"
1557
+ >
1558
+ <span class="axp-widget-column-header__caption ax-truncate">{{ caption | translate | async }}</span>
1559
+ @if (sortEnabled) {
1560
+ <span class="axp-widget-column-header__sort ax-flex ax-items-center ax-gap-0.5 ax-shrink-0">
1561
+ @if (headerSortPriority !== undefined && headerSortPriority > 1) {
1562
+ <span class="axp-widget-column-header__sort-priority ax-text-xs ax-opacity-70">{{ headerSortPriority }}</span>
1563
+ }
1564
+ <i
1565
+ class="fa-solid fa-arrow-up-long ax-text-neutral-400"
1566
+ [class.ax-text-primary]="headerSortDirection === 'asc'"
1567
+ ></i>
1568
+ <i
1569
+ class="fa-solid fa-arrow-down-long ax-text-neutral-400"
1570
+ [class.ax-text-primary]="headerSortDirection === 'desc'"
1571
+ ></i>
1572
+ </span>
1573
+ }
1574
+ </div>
1507
1575
  </ng-template>
1508
1576
  <ng-template #cell let-row>
1509
1577
  <div
@@ -1540,15 +1608,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1540
1608
  </div>
1541
1609
  </ng-template>
1542
1610
  <ng-template #footer></ng-template>
1543
- `,
1544
- providers: [
1611
+ `, providers: [
1545
1612
  AXPWidgetCoreService,
1546
1613
  { provide: AXDataTableColumnComponent, useExisting: AXPWidgetColumnRendererComponent },
1547
- ],
1548
- changeDetection: ChangeDetectionStrategy.OnPush,
1549
- inputs: ['caption'],
1550
- standalone: false,
1551
- }]
1614
+ ], changeDetection: ChangeDetectionStrategy.OnPush, inputs: ['caption'], standalone: false, styles: [".axp-widget-column-header--sortable{cursor:pointer}.axp-widget-column-header__caption{min-width:0}.axp-widget-column-header__sort{opacity:0;transition:opacity .15s ease}.axp-widget-column-header--sortable:hover .axp-widget-column-header__sort,.axp-widget-column-header--sortable:focus-within .axp-widget-column-header__sort{opacity:1}.axp-widget-column-header__sort-priority{line-height:1}:host-context(.ax-data-table-head-cell.ax-interactive:hover) .axp-widget-column-header__sort,:host-context(.ax-data-table-head-cell.ax-interactive:focus-within) .axp-widget-column-header__sort{opacity:1}\n"] }]
1552
1615
  }], propDecorators: { customExpandIcon: [{
1553
1616
  type: Input
1554
1617
  }], customCollapseIcon: [{
@@ -1565,6 +1628,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1565
1628
  args: ['footer']
1566
1629
  }], expandHandler: [{
1567
1630
  type: Input
1631
+ }], sortEnabled: [{
1632
+ type: Input
1633
+ }], headerSortDirection: [{
1634
+ type: Input
1635
+ }], headerSortPriority: [{
1636
+ type: Input
1637
+ }], sortToggle: [{
1638
+ type: Output
1568
1639
  }], cellTemplate: [{
1569
1640
  type: Input
1570
1641
  }], _contentCellTemplate: [{