@elasticias/ui 0.0.16 → 1.0.1
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.
- package/fesm2022/elasticias-ui.mjs +8057 -2332
- package/fesm2022/elasticias-ui.mjs.map +1 -1
- package/package.json +4 -2
- package/styles/_comptoir.scss +143 -0
- package/styles/_patterns.scss +4090 -0
- package/types/elasticias-ui.d.ts +3246 -189
package/types/elasticias-ui.d.ts
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { PipeTransform, OnInit,
|
|
3
|
-
import { AppUtils } from '@elasticias/utils';
|
|
2
|
+
import { PipeTransform, OnInit, OnChanges, TemplateRef, EventEmitter, AfterContentInit, OnDestroy, SimpleChanges, AfterViewInit } from '@angular/core';
|
|
4
3
|
import { Menu } from 'primeng/menu';
|
|
5
|
-
import
|
|
4
|
+
import * as _elasticias_screens from '@elasticias/screens';
|
|
5
|
+
import { ScreenContext, EfDetailToolbarAction, EfSearchToolbarAction, EfDataCardColumn, EfDataCardSort, EfDateRange, EfDatePresetKey } from '@elasticias/screens';
|
|
6
|
+
export { EfDataCardColumn, EfDataCardColumnAlign, EfDataCardColumnType, EfDataCardSort, EfDataCardSortDirection, EfDatePresetKey, EfDateRange, EfDetailToolbarAction, EfSearchToolbarAction } from '@elasticias/screens';
|
|
7
|
+
import * as _elasticias_core from '@elasticias/core';
|
|
8
|
+
import { EfModule, EfModuleId, EfNavSection, EfNavItem, EfToast, EfToastAction, EfThemeConfigService } from '@elasticias/core';
|
|
6
9
|
import { BlockableUI } from 'primeng/api';
|
|
10
|
+
import { SafeResourceUrl } from '@angular/platform-browser';
|
|
11
|
+
import { ChartConfiguration } from 'chart.js';
|
|
7
12
|
import { ControlValueAccessor, NgControl } from '@angular/forms';
|
|
13
|
+
import { TranslateService } from '@ngx-translate/core';
|
|
8
14
|
import { InputNumber, InputNumberInputEvent } from 'primeng/inputnumber';
|
|
9
15
|
import { Nullable } from 'primeng/ts-helpers';
|
|
10
16
|
import * as _elasticias_ui from '@elasticias/ui';
|
|
11
17
|
import { Table, TableLazyLoadEvent } from 'primeng/table';
|
|
18
|
+
import { Permissions, EmailMetrics, EmailEventRecord, EmailEventKind } from '@elasticias/types';
|
|
12
19
|
import { PrimeNG } from 'primeng/config';
|
|
13
|
-
import { EfThemeConfigService } from '@elasticias/core';
|
|
14
|
-
import { EmailMetrics, EmailEventRecord, EmailEventKind } from '@elasticias/types';
|
|
15
20
|
|
|
16
21
|
/**
|
|
17
22
|
* Merged currency pipe from ERP (AppCurrencyPipe) and Store (CurrencyFormatPipe).
|
|
@@ -30,6 +35,16 @@ declare class TruncatePipe implements PipeTransform {
|
|
|
30
35
|
static ɵpipe: _angular_core.ɵɵPipeDeclaration<TruncatePipe, "truncate", true>;
|
|
31
36
|
}
|
|
32
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Compact human-readable rendering of a number for KPI displays:
|
|
40
|
+
* 1000 → "1 k", 2_500_000 → "2,5 M" (fr-MA locale, decimal comma).
|
|
41
|
+
*/
|
|
42
|
+
declare class EfCompactPipe implements PipeTransform {
|
|
43
|
+
transform(value: number | null | undefined, maxDecimals?: number): string;
|
|
44
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfCompactPipe, never>;
|
|
45
|
+
static ɵpipe: _angular_core.ɵɵPipeDeclaration<EfCompactPipe, "efCompact", true>;
|
|
46
|
+
}
|
|
47
|
+
|
|
33
48
|
declare class EfPriceDisplayComponent {
|
|
34
49
|
readonly amount: _angular_core.InputSignal<number>;
|
|
35
50
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfPriceDisplayComponent, never>;
|
|
@@ -289,6 +304,50 @@ declare class EfOrderSummaryComponent {
|
|
|
289
304
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfOrderSummaryComponent, "ef-order-summary", never, { "orderLines": { "alias": "orderLines"; "required": true; "isSignal": true; }; "countGroupLabels": { "alias": "countGroupLabels"; "required": false; "isSignal": true; }; "legend": { "alias": "legend"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
290
305
|
}
|
|
291
306
|
|
|
307
|
+
/**
|
|
308
|
+
* Presentational shapes for {@link EfChangeHistoryComponent}. Structurally
|
|
309
|
+
* compatible with the backend `ChangeHistoryEntryDto` / `FieldChangeDto` that
|
|
310
|
+
* the NSwag client returns, so a screen can pass them straight through without
|
|
311
|
+
* mapping. Kept lib-local so `@elasticias/ui` stays decoupled from any app's
|
|
312
|
+
* generated API client.
|
|
313
|
+
*/
|
|
314
|
+
interface EfChangeHistoryFieldChange {
|
|
315
|
+
field?: string;
|
|
316
|
+
oldValue?: string | null;
|
|
317
|
+
newValue?: string | null;
|
|
318
|
+
}
|
|
319
|
+
interface EfChangeHistoryEntry {
|
|
320
|
+
/** Standardized operation code: created | updated | status_changed | deleted | note. */
|
|
321
|
+
operation?: string;
|
|
322
|
+
occurredAt?: string | Date | null;
|
|
323
|
+
userId?: string | null;
|
|
324
|
+
userName?: string | null;
|
|
325
|
+
changes?: EfChangeHistoryFieldChange[] | null;
|
|
326
|
+
fromStatus?: string | null;
|
|
327
|
+
toStatus?: string | null;
|
|
328
|
+
note?: string | null;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/** Emitted when the user picks a product (with its active variant) from the menu. */
|
|
332
|
+
interface ProductTypeaheadSelection {
|
|
333
|
+
product: Record<string, unknown>;
|
|
334
|
+
variant: Record<string, unknown> | null;
|
|
335
|
+
unitPrice: number;
|
|
336
|
+
}
|
|
337
|
+
/** A run of result-label text, flagged when it matches the current query. */
|
|
338
|
+
interface HighlightSegment {
|
|
339
|
+
text: string;
|
|
340
|
+
mark: boolean;
|
|
341
|
+
}
|
|
342
|
+
/** Internal view-model for one result row. */
|
|
343
|
+
interface ProductTypeaheadRow {
|
|
344
|
+
key: string;
|
|
345
|
+
product: Record<string, unknown>;
|
|
346
|
+
label: string;
|
|
347
|
+
variants: Record<string, unknown>[];
|
|
348
|
+
segments: HighlightSegment[];
|
|
349
|
+
}
|
|
350
|
+
|
|
292
351
|
/**
|
|
293
352
|
* Reusable order builder component for orders, invoices, and quotes
|
|
294
353
|
* Manages complete order entity with automatic change tracking
|
|
@@ -303,9 +362,10 @@ declare class EfOrderSummaryComponent {
|
|
|
303
362
|
* (orderChanged)="handleOrderChange($event)"
|
|
304
363
|
* />
|
|
305
364
|
*/
|
|
306
|
-
|
|
365
|
+
/** Numeric line columns that support inline click-to-edit. */
|
|
366
|
+
type EditableLineField = 'price' | 'qty' | 'discount' | 'tva';
|
|
367
|
+
declare class EfOrderBuilderComponent implements OnInit {
|
|
307
368
|
rowTrackBy: (_: number, item: OrderLineItem) => string | number;
|
|
308
|
-
protected readonly AppUtils: typeof AppUtils;
|
|
309
369
|
config: _angular_core.InputSignal<DocumentConfig>;
|
|
310
370
|
order: _angular_core.ModelSignal<OrderEntity>;
|
|
311
371
|
products: _angular_core.InputSignal<Record<string, unknown>[]>;
|
|
@@ -317,25 +377,19 @@ declare class EfOrderBuilderComponent implements OnInit, OnDestroy {
|
|
|
317
377
|
backendErrors: _angular_core.InputSignal<{
|
|
318
378
|
[key: string]: string[];
|
|
319
379
|
}>;
|
|
380
|
+
/** Optional change-history entries; when non-empty the Historique rail card renders. */
|
|
381
|
+
auditEntries: _angular_core.InputSignal<EfChangeHistoryEntry[]>;
|
|
320
382
|
openCatalogue: _angular_core.OutputEmitterRef<void>;
|
|
321
383
|
orderChanged: _angular_core.OutputEmitterRef<OrderChangeInfo>;
|
|
322
384
|
orderValidated: _angular_core.OutputEmitterRef<ValidationResult>;
|
|
323
385
|
productsAdded: _angular_core.OutputEmitterRef<OrderLineItem[]>;
|
|
324
386
|
private originalOrder;
|
|
325
|
-
private updateTimeout;
|
|
326
387
|
private initialized;
|
|
327
|
-
|
|
388
|
+
quickAddSelection: _angular_core.WritableSignal<ProductTypeaheadSelection>;
|
|
328
389
|
quickAddPrice: _angular_core.WritableSignal<number>;
|
|
329
390
|
quickAddQuantity: _angular_core.WritableSignal<number>;
|
|
330
391
|
quickAddDisabled: _angular_core.Signal<boolean>;
|
|
331
392
|
orderLines: _angular_core.Signal<OrderLineItem[]>;
|
|
332
|
-
/**
|
|
333
|
-
* Flatten products → one option per active variant for the inline ef-select.
|
|
334
|
-
* Simple products (no variants) get a single row with the product label.
|
|
335
|
-
* Each option exposes `_displayLabel` for `optionLabel` and carries the
|
|
336
|
-
* underlying product/variant references for `onProductSelect`.
|
|
337
|
-
*/
|
|
338
|
-
flattenedProductOptions: _angular_core.Signal<Record<string, unknown>[]>;
|
|
339
393
|
grossTotal: _angular_core.Signal<number>;
|
|
340
394
|
discountTotal: _angular_core.Signal<number>;
|
|
341
395
|
tvaTotal: _angular_core.Signal<number>;
|
|
@@ -344,7 +398,6 @@ declare class EfOrderBuilderComponent implements OnInit, OnDestroy {
|
|
|
344
398
|
locale: _angular_core.Signal<string>;
|
|
345
399
|
hasItems: _angular_core.Signal<boolean>;
|
|
346
400
|
productsSummary: _angular_core.Signal<OrderProductsSummary>;
|
|
347
|
-
hasEditingRow: _angular_core.Signal<boolean>;
|
|
348
401
|
validationResult: _angular_core.Signal<ValidationResult>;
|
|
349
402
|
combinedErrors: _angular_core.Signal<{
|
|
350
403
|
[x: string]: string[];
|
|
@@ -353,19 +406,41 @@ declare class EfOrderBuilderComponent implements OnInit, OnDestroy {
|
|
|
353
406
|
isValid: _angular_core.Signal<boolean>;
|
|
354
407
|
changeInfo: _angular_core.Signal<OrderChangeInfo>;
|
|
355
408
|
hasChanges: _angular_core.Signal<boolean>;
|
|
409
|
+
focusMode: _angular_core.ModelSignal<boolean>;
|
|
410
|
+
railOpen: _angular_core.WritableSignal<boolean>;
|
|
411
|
+
/**
|
|
412
|
+
* Inline cell editing — lines render their numeric values as read-only text
|
|
413
|
+
* until the user clicks a value, which swaps just that cell to an input
|
|
414
|
+
* (V1 behaviour). One cell is editable at a time; blur / Enter / Escape /
|
|
415
|
+
* Tab commits and returns the cell to display.
|
|
416
|
+
*/
|
|
417
|
+
editingCell: _angular_core.WritableSignal<{
|
|
418
|
+
id: OrderLineItem["id"];
|
|
419
|
+
field: EditableLineField;
|
|
420
|
+
}>;
|
|
421
|
+
/** Number of table columns, used for the empty-state colspan. */
|
|
422
|
+
colCount: _angular_core.Signal<number>;
|
|
423
|
+
isEditingCell(item: OrderLineItem, field: EditableLineField): boolean;
|
|
424
|
+
startEditCell(item: OrderLineItem, field: EditableLineField): void;
|
|
425
|
+
stopEditCell(): void;
|
|
426
|
+
onEditCellKeydown(event: KeyboardEvent): void;
|
|
427
|
+
toggleFocus(): void;
|
|
428
|
+
toggleRail(open?: boolean): void;
|
|
429
|
+
hasAudit: _angular_core.Signal<boolean>;
|
|
430
|
+
/** Récap items grouped into columns (column index from reference data). */
|
|
431
|
+
recapColumns: _angular_core.Signal<OrderSummaryItem[][]>;
|
|
356
432
|
constructor();
|
|
357
433
|
ngOnInit(): void;
|
|
358
|
-
|
|
359
|
-
addNewProductRow(): void;
|
|
360
|
-
removeOrderLine(id: number | undefined): void;
|
|
361
|
-
onProductSelect(item: OrderLineItem): void;
|
|
362
|
-
startEditField(item: OrderLineItem, fieldName: string): void;
|
|
363
|
-
stopEditField(item: OrderLineItem): void;
|
|
434
|
+
removeOrderLine(id: string | number | undefined): void;
|
|
364
435
|
onFieldChange(item: OrderLineItem): void;
|
|
365
|
-
saveEditingRow(item: OrderLineItem): void;
|
|
366
436
|
calculateSubtotal(item: OrderLineItem): number;
|
|
367
437
|
handleOpenCatalogue(): void;
|
|
368
|
-
|
|
438
|
+
private readonly typeahead;
|
|
439
|
+
/**
|
|
440
|
+
* Fill the quick-add bar from a typeahead pick. Does NOT add the line —
|
|
441
|
+
* the user reviews price/quantity then clicks "Ajouter" (addQuickProduct).
|
|
442
|
+
*/
|
|
443
|
+
onTypeaheadSelect(selection: ProductTypeaheadSelection): void;
|
|
369
444
|
addQuickProduct(): void;
|
|
370
445
|
addProductsFromCatalogue(selectedProducts: Array<{
|
|
371
446
|
product: Record<string, unknown>;
|
|
@@ -381,7 +456,6 @@ declare class EfOrderBuilderComponent implements OnInit, OnDestroy {
|
|
|
381
456
|
validate(): ValidationResult;
|
|
382
457
|
private updateOrderLines;
|
|
383
458
|
private getCustomerName;
|
|
384
|
-
private productKey;
|
|
385
459
|
getProduct(productId: unknown): Record<string, unknown> | undefined;
|
|
386
460
|
getCustomer(customerId: string): Record<string, unknown> | undefined;
|
|
387
461
|
initializeOrderLines(): void;
|
|
@@ -393,7 +467,63 @@ declare class EfOrderBuilderComponent implements OnInit, OnDestroy {
|
|
|
393
467
|
};
|
|
394
468
|
exportOrder(): OrderEntity;
|
|
395
469
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfOrderBuilderComponent, never>;
|
|
396
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfOrderBuilderComponent, "ef-order-builder", never, { "config": { "alias": "config"; "required": false; "isSignal": true; }; "order": { "alias": "order"; "required": true; "isSignal": true; }; "products": { "alias": "products"; "required": true; "isSignal": true; }; "customers": { "alias": "customers"; "required": true; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "countGroupLabels": { "alias": "countGroupLabels"; "required": false; "isSignal": true; }; "productKeyField": { "alias": "productKeyField"; "required": false; "isSignal": true; }; "backendErrors": { "alias": "backendErrors"; "required": false; "isSignal": true; }; }, { "order": "orderChange"; "openCatalogue": "openCatalogue"; "orderChanged": "orderChanged"; "orderValidated": "orderValidated"; "productsAdded": "productsAdded"; }, never, never, true, never>;
|
|
470
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfOrderBuilderComponent, "ef-order-builder", never, { "config": { "alias": "config"; "required": false; "isSignal": true; }; "order": { "alias": "order"; "required": true; "isSignal": true; }; "products": { "alias": "products"; "required": true; "isSignal": true; }; "customers": { "alias": "customers"; "required": true; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "countGroupLabels": { "alias": "countGroupLabels"; "required": false; "isSignal": true; }; "productKeyField": { "alias": "productKeyField"; "required": false; "isSignal": true; }; "backendErrors": { "alias": "backendErrors"; "required": false; "isSignal": true; }; "auditEntries": { "alias": "auditEntries"; "required": false; "isSignal": true; }; "focusMode": { "alias": "focusMode"; "required": false; "isSignal": true; }; }, { "order": "orderChange"; "openCatalogue": "openCatalogue"; "orderChanged": "orderChanged"; "orderValidated": "orderValidated"; "productsAdded": "productsAdded"; "focusMode": "focusModeChange"; }, never, never, true, never>;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Keyboard-navigable product search. Filters products by display name,
|
|
475
|
+
* highlights the match, exposes per-product variant chips, and emits the
|
|
476
|
+
* chosen product + active variant + unit price. Pure input-driven — no API.
|
|
477
|
+
*
|
|
478
|
+
* @example
|
|
479
|
+
* <ef-product-typeahead
|
|
480
|
+
* [products]="products()"
|
|
481
|
+
* productKeyField="id"
|
|
482
|
+
* placeholderKey="label.search_product"
|
|
483
|
+
* (productSelect)="onPicked($event)" />
|
|
484
|
+
*/
|
|
485
|
+
declare class EfProductTypeaheadComponent {
|
|
486
|
+
products: _angular_core.InputSignal<Record<string, unknown>[]>;
|
|
487
|
+
productKeyField: _angular_core.InputSignal<string>;
|
|
488
|
+
placeholderKey: _angular_core.InputSignal<string>;
|
|
489
|
+
disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
490
|
+
currency: _angular_core.InputSignal<string>;
|
|
491
|
+
locale: _angular_core.InputSignal<string>;
|
|
492
|
+
/**
|
|
493
|
+
* How variants are presented.
|
|
494
|
+
* - `true` (default): compact — one row per product with inline variant
|
|
495
|
+
* chips (e.g. `30ml` / `50ml`); clicking a chip switches the active
|
|
496
|
+
* variant + price.
|
|
497
|
+
* - `false`: V1 expanded — one row per active variant, with the variant
|
|
498
|
+
* title composed into the label (`Name - 30ml`) and its own price.
|
|
499
|
+
*
|
|
500
|
+
* Display-only: the emitted `ProductTypeaheadSelection` (product + chosen
|
|
501
|
+
* variant + unit price) is identical either way.
|
|
502
|
+
*/
|
|
503
|
+
showVariants: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
504
|
+
productSelect: _angular_core.OutputEmitterRef<ProductTypeaheadSelection>;
|
|
505
|
+
query: _angular_core.WritableSignal<string>;
|
|
506
|
+
open: _angular_core.WritableSignal<boolean>;
|
|
507
|
+
highlightedIndex: _angular_core.WritableSignal<number>;
|
|
508
|
+
/** Map of product key -> chosen variant index (defaults to 0). */
|
|
509
|
+
activeVariant: _angular_core.WritableSignal<Record<string, number>>;
|
|
510
|
+
private static norm;
|
|
511
|
+
rows: _angular_core.Signal<ProductTypeaheadRow[]>;
|
|
512
|
+
buildSegments(label: string, query: string): HighlightSegment[];
|
|
513
|
+
onInput(value: string): void;
|
|
514
|
+
moveHighlight(delta: number): void;
|
|
515
|
+
onKeydown(event: KeyboardEvent): void;
|
|
516
|
+
/** Active variant index for a row (defaults to 0). */
|
|
517
|
+
variantIndexOf(row: ProductTypeaheadRow): number;
|
|
518
|
+
variantOf(row: ProductTypeaheadRow): Record<string, unknown> | null;
|
|
519
|
+
priceOf(row: ProductTypeaheadRow): number;
|
|
520
|
+
setActiveVariant(row: ProductTypeaheadRow, index: number): void;
|
|
521
|
+
selectRow(row: ProductTypeaheadRow): void;
|
|
522
|
+
selectHighlighted(): void;
|
|
523
|
+
/** Clear the field after the consumer has consumed the selection. */
|
|
524
|
+
reset(): void;
|
|
525
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfProductTypeaheadComponent, never>;
|
|
526
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfProductTypeaheadComponent, "ef-product-typeahead", never, { "products": { "alias": "products"; "required": true; "isSignal": true; }; "productKeyField": { "alias": "productKeyField"; "required": false; "isSignal": true; }; "placeholderKey": { "alias": "placeholderKey"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "currency": { "alias": "currency"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "showVariants": { "alias": "showVariants"; "required": false; "isSignal": true; }; }, { "productSelect": "productSelect"; }, never, never, true, never>;
|
|
397
527
|
}
|
|
398
528
|
|
|
399
529
|
interface CategoryItem {
|
|
@@ -576,16 +706,106 @@ declare class EfProductCatalogueComponent implements OnChanges {
|
|
|
576
706
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfProductCatalogueComponent, "ef-product-catalogue", never, { "products": { "alias": "products"; "required": false; "isSignal": true; }; "categoryGroups": { "alias": "categoryGroups"; "required": false; "isSignal": true; }; "initialSelectedItems": { "alias": "initialSelectedItems"; "required": false; "isSignal": true; }; "defaultFilters": { "alias": "defaultFilters"; "required": false; "isSignal": true; }; "trackByField": { "alias": "trackByField"; "required": false; "isSignal": true; }; "currencyCode": { "alias": "currencyCode"; "required": false; "isSignal": true; }; "localeCode": { "alias": "localeCode"; "required": false; "isSignal": true; }; }, { "productsValidated": "productsValidated"; }, ["productThumbnailTpl"], never, true, never>;
|
|
577
707
|
}
|
|
578
708
|
|
|
709
|
+
/**
|
|
710
|
+
* Dynamic action descriptor for `ef-dialog`. The dialog renders one
|
|
711
|
+
* `<button class="btn …">` per entry, in array order (left → right);
|
|
712
|
+
* the rightmost entry is the focused / "primary" by convention.
|
|
713
|
+
*
|
|
714
|
+
* When `command` returns a `Promise`, the button auto-toggles
|
|
715
|
+
* `.is-loading` for the duration and the dialog closes when it
|
|
716
|
+
* resolves (unless `dismiss === false`).
|
|
717
|
+
*/
|
|
718
|
+
interface EfDialogAction {
|
|
719
|
+
/** Direct label text. Use `labelKey` for i18n. */
|
|
720
|
+
label?: string;
|
|
721
|
+
/** Translation key for the label — takes precedence over `label`. */
|
|
722
|
+
labelKey?: string;
|
|
723
|
+
/** Visual severity (controls the .btn class). Default: `'ghost'`. */
|
|
724
|
+
severity?: 'primary' | 'ghost' | 'tenant' | 'danger';
|
|
725
|
+
/** PrimeNG icon class (e.g. `'pi pi-trash'`). Optional. */
|
|
726
|
+
icon?: string;
|
|
727
|
+
/** Extra class(es) appended to the footer button — for brand-tinted
|
|
728
|
+
* actions (e.g. `'btn-whatsapp'`) or layout helpers (`'btn-dialog-leading'`)
|
|
729
|
+
* beyond the four standard severities. */
|
|
730
|
+
styleClass?: string;
|
|
731
|
+
/** Click handler. Return a `Promise` to auto-toggle the loading
|
|
732
|
+
* spinner overlay on the button until it settles. */
|
|
733
|
+
command?: () => void | Promise<void>;
|
|
734
|
+
/** Close the dialog after the command resolves. Default: `true`. */
|
|
735
|
+
dismiss?: boolean;
|
|
736
|
+
/** Render the button as disabled. */
|
|
737
|
+
disabled?: boolean;
|
|
738
|
+
/** Render the button as loading (in-flight). Mutated automatically
|
|
739
|
+
* by the dialog when the command returns a Promise. */
|
|
740
|
+
loading?: boolean;
|
|
741
|
+
}
|
|
742
|
+
type EfDialogSeverity = 'default' | 'danger' | 'warn' | 'info' | 'success' | 'tenant';
|
|
743
|
+
type EfDialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
744
|
+
/**
|
|
745
|
+
* Comptoir dialog — wraps PrimeNG `p-dialog` and skins it against the
|
|
746
|
+
* `.es-dialog` patterns lifted from the static prototype
|
|
747
|
+
* (`docs/ux-ui/erp/screens/components.html` § Section 05).
|
|
748
|
+
*
|
|
749
|
+
* **Card design with two rules** — the header has a `border-bottom`,
|
|
750
|
+
* the footer has a `border-top` (`1px var(--rule)`). Header layout:
|
|
751
|
+
* optional severity-tinted icon · title + subtitle · close ✕.
|
|
752
|
+
*
|
|
753
|
+
* **Dynamic actions** — pass an `EfDialogAction[]` via `[actions]`
|
|
754
|
+
* and the footer renders one button per entry, in order. The rightmost
|
|
755
|
+
* is conventionally the primary action; consumers control severity
|
|
756
|
+
* per-entry. Async commands flip the button to `.is-loading` until
|
|
757
|
+
* resolved, then auto-dismiss (unless opted out).
|
|
758
|
+
*
|
|
759
|
+
* ```html
|
|
760
|
+
* <ef-dialog
|
|
761
|
+
* [(visible)]="show"
|
|
762
|
+
* headerKey="orders.delete_confirm"
|
|
763
|
+
* subtitleKey="orders.delete_irreversible"
|
|
764
|
+
* severity="danger"
|
|
765
|
+
* size="md"
|
|
766
|
+
* [actions]="[
|
|
767
|
+
* { labelKey: 'common_cancel', severity: 'ghost' },
|
|
768
|
+
* { labelKey: 'common_delete', severity: 'danger',
|
|
769
|
+
* command: () => this.api.deleteOrder(this.id) }
|
|
770
|
+
* ]"
|
|
771
|
+
* >
|
|
772
|
+
* <div class="es-dialog__highlight">
|
|
773
|
+
* <span class="av tenant">L</span>
|
|
774
|
+
* <div class="body">
|
|
775
|
+
* <div class="nm">SO-2026-198 · Leila Bennani</div>
|
|
776
|
+
* <div class="meta">07 mai · 1 132,00 MAD</div>
|
|
777
|
+
* </div>
|
|
778
|
+
* </div>
|
|
779
|
+
* <p>{{ 'orders.delete_warning' | translate }}</p>
|
|
780
|
+
* </ef-dialog>
|
|
781
|
+
* ```
|
|
782
|
+
*/
|
|
579
783
|
declare class EfDialogComponent {
|
|
580
|
-
|
|
784
|
+
private readonly translate;
|
|
785
|
+
/** Direct header text (not translated). */
|
|
581
786
|
header?: string;
|
|
582
|
-
/** Translation key — takes
|
|
787
|
+
/** Translation key — takes precedence over `header`. */
|
|
583
788
|
headerKey?: string;
|
|
789
|
+
/** Direct subtitle text. */
|
|
790
|
+
subtitle?: string;
|
|
791
|
+
/** Translation key — takes precedence over `subtitle`. */
|
|
792
|
+
subtitleKey?: string;
|
|
584
793
|
visible: boolean;
|
|
585
794
|
modal: boolean;
|
|
586
795
|
closable: boolean;
|
|
587
796
|
draggable: boolean;
|
|
588
797
|
resizable: boolean;
|
|
798
|
+
/** Close the dialog when the user clicks the backdrop mask. */
|
|
799
|
+
dismissableMask: boolean;
|
|
800
|
+
/** Close the dialog on Escape (PrimeNG default = true). */
|
|
801
|
+
closeOnEscape: boolean;
|
|
802
|
+
/** Severity drives the header icon tint (panel itself stays neutral).
|
|
803
|
+
* Pair with `[icon]` to override the default icon-class per severity. */
|
|
804
|
+
severity: EfDialogSeverity;
|
|
805
|
+
/** Header icon class (PrimeNG `pi pi-*`). Overrides the severity default. */
|
|
806
|
+
icon?: string;
|
|
807
|
+
/** Width preset: sm 380 / md 480 (default) / lg 640 / xl 880 / full. */
|
|
808
|
+
size: EfDialogSize;
|
|
589
809
|
style?: {
|
|
590
810
|
[key: string]: string;
|
|
591
811
|
};
|
|
@@ -593,9 +813,22 @@ declare class EfDialogComponent {
|
|
|
593
813
|
position: 'center' | 'top' | 'bottom' | 'left' | 'right' | 'topleft' | 'topright' | 'bottomleft' | 'bottomright';
|
|
594
814
|
appendTo?: string;
|
|
595
815
|
/**
|
|
596
|
-
* Render
|
|
597
|
-
*
|
|
598
|
-
*
|
|
816
|
+
* Render variant.
|
|
817
|
+
* - `'comptoir'` (default) — applies the `.es-dialog` Comptoir skin,
|
|
818
|
+
* custom header (icon + title + subtitle + close), and dynamic-action
|
|
819
|
+
* footer.
|
|
820
|
+
* - `'primeng'` — bare `p-dialog` with its native header (just the
|
|
821
|
+
* `[header]` text + PrimeNG's default close). Use for legacy screens
|
|
822
|
+
* or to dodge the Comptoir skin one-off.
|
|
823
|
+
*/
|
|
824
|
+
variant: 'primeng' | 'comptoir';
|
|
825
|
+
/** Footer actions, rendered left → right. When set (non-empty),
|
|
826
|
+
* takes precedence over `defaultActions`. */
|
|
827
|
+
actions?: EfDialogAction[];
|
|
828
|
+
/**
|
|
829
|
+
* Render a standard cancel + save action footer. Backward-compat
|
|
830
|
+
* shortcut — for richer footers prefer `[actions]`. When false (and
|
|
831
|
+
* no `[actions]` provided), the footer is omitted entirely.
|
|
599
832
|
*/
|
|
600
833
|
defaultActions: boolean;
|
|
601
834
|
saveLabelKey: string;
|
|
@@ -603,31 +836,55 @@ declare class EfDialogComponent {
|
|
|
603
836
|
saveLabel?: string;
|
|
604
837
|
cancelLabel?: string;
|
|
605
838
|
saveIcon: string;
|
|
839
|
+
cancelIcon?: string;
|
|
606
840
|
saveDisabled: boolean;
|
|
607
|
-
saveStyleClass
|
|
608
|
-
cancelStyleClass
|
|
841
|
+
saveStyleClass?: string;
|
|
842
|
+
cancelStyleClass?: string;
|
|
843
|
+
saveSeverity: 'primary' | 'tenant' | 'ghost' | 'danger';
|
|
844
|
+
cancelSeverity: 'primary' | 'tenant' | 'ghost' | 'danger';
|
|
609
845
|
visibleChange: EventEmitter<boolean>;
|
|
610
846
|
showEvent: EventEmitter<void>;
|
|
611
847
|
hideEvent: EventEmitter<void>;
|
|
612
848
|
saveAction: EventEmitter<void>;
|
|
613
849
|
cancelAction: EventEmitter<void>;
|
|
850
|
+
/** Emits for every action in the dynamic `[actions]` footer. The
|
|
851
|
+
* payload includes the action object and its index. */
|
|
852
|
+
actionClick: EventEmitter<{
|
|
853
|
+
action: EfDialogAction;
|
|
854
|
+
index: number;
|
|
855
|
+
}>;
|
|
856
|
+
/** ViewChild ref to the default-action footer template — used in the
|
|
857
|
+
* `'primeng'` variant via [footerTemplate] input. */
|
|
614
858
|
defaultFooterTpl?: TemplateRef<void>;
|
|
859
|
+
/** Severity → default header icon. Override per-instance with `[icon]`. */
|
|
860
|
+
private static readonly SEV_ICONS;
|
|
861
|
+
get effectiveStyleClass(): string;
|
|
862
|
+
get effectiveTitle(): string;
|
|
863
|
+
get effectiveSubtitle(): string;
|
|
864
|
+
get effectiveIcon(): string | null;
|
|
865
|
+
/** True when the dynamic `[actions]` path should render the footer. */
|
|
866
|
+
get useDynamicActions(): boolean;
|
|
867
|
+
/** Whether any kind of footer should render at all. */
|
|
868
|
+
get hasFooter(): boolean;
|
|
869
|
+
actionLabel(a: EfDialogAction): string;
|
|
870
|
+
actionClass(a: EfDialogAction): string;
|
|
871
|
+
handleActionClick(a: EfDialogAction, index: number): void;
|
|
615
872
|
handleVisibleChange(value: boolean): void;
|
|
616
873
|
handleShow(): void;
|
|
617
874
|
handleHide(): void;
|
|
618
|
-
/**
|
|
619
|
-
* Default cancel handler — emits and also closes the dialog. Callers can
|
|
620
|
-
* override behavior via (cancelAction) (close still happens).
|
|
621
|
-
*/
|
|
875
|
+
/** Default cancel — emits and closes. */
|
|
622
876
|
onDefaultCancel(): void;
|
|
877
|
+
/** Default save — emits only (consumer closes after success). */
|
|
623
878
|
onDefaultSave(): void;
|
|
624
879
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfDialogComponent, never>;
|
|
625
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfDialogComponent, "ef-dialog", never, { "header": { "alias": "header"; "required": false; }; "headerKey": { "alias": "headerKey"; "required": false; }; "visible": { "alias": "visible"; "required": false; }; "modal": { "alias": "modal"; "required": false; }; "closable": { "alias": "closable"; "required": false; }; "draggable": { "alias": "draggable"; "required": false; }; "resizable": { "alias": "resizable"; "required": false; }; "style": { "alias": "style"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "position": { "alias": "position"; "required": false; }; "appendTo": { "alias": "appendTo"; "required": false; }; "defaultActions": { "alias": "defaultActions"; "required": false; }; "saveLabelKey": { "alias": "saveLabelKey"; "required": false; }; "cancelLabelKey": { "alias": "cancelLabelKey"; "required": false; }; "saveLabel": { "alias": "saveLabel"; "required": false; }; "cancelLabel": { "alias": "cancelLabel"; "required": false; }; "saveIcon": { "alias": "saveIcon"; "required": false; }; "saveDisabled": { "alias": "saveDisabled"; "required": false; }; "saveStyleClass": { "alias": "saveStyleClass"; "required": false; }; "cancelStyleClass": { "alias": "cancelStyleClass"; "required": false; }; }, { "visibleChange": "visibleChange"; "showEvent": "showEvent"; "hideEvent": "hideEvent"; "saveAction": "saveAction"; "cancelAction": "cancelAction"; }, never, ["*"], true, never>;
|
|
880
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfDialogComponent, "ef-dialog", never, { "header": { "alias": "header"; "required": false; }; "headerKey": { "alias": "headerKey"; "required": false; }; "subtitle": { "alias": "subtitle"; "required": false; }; "subtitleKey": { "alias": "subtitleKey"; "required": false; }; "visible": { "alias": "visible"; "required": false; }; "modal": { "alias": "modal"; "required": false; }; "closable": { "alias": "closable"; "required": false; }; "draggable": { "alias": "draggable"; "required": false; }; "resizable": { "alias": "resizable"; "required": false; }; "dismissableMask": { "alias": "dismissableMask"; "required": false; }; "closeOnEscape": { "alias": "closeOnEscape"; "required": false; }; "severity": { "alias": "severity"; "required": false; }; "icon": { "alias": "icon"; "required": false; }; "size": { "alias": "size"; "required": false; }; "style": { "alias": "style"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "position": { "alias": "position"; "required": false; }; "appendTo": { "alias": "appendTo"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "actions": { "alias": "actions"; "required": false; }; "defaultActions": { "alias": "defaultActions"; "required": false; }; "saveLabelKey": { "alias": "saveLabelKey"; "required": false; }; "cancelLabelKey": { "alias": "cancelLabelKey"; "required": false; }; "saveLabel": { "alias": "saveLabel"; "required": false; }; "cancelLabel": { "alias": "cancelLabel"; "required": false; }; "saveIcon": { "alias": "saveIcon"; "required": false; }; "cancelIcon": { "alias": "cancelIcon"; "required": false; }; "saveDisabled": { "alias": "saveDisabled"; "required": false; }; "saveStyleClass": { "alias": "saveStyleClass"; "required": false; }; "cancelStyleClass": { "alias": "cancelStyleClass"; "required": false; }; "saveSeverity": { "alias": "saveSeverity"; "required": false; }; "cancelSeverity": { "alias": "cancelSeverity"; "required": false; }; }, { "visibleChange": "visibleChange"; "showEvent": "showEvent"; "hideEvent": "hideEvent"; "saveAction": "saveAction"; "cancelAction": "cancelAction"; "actionClick": "actionClick"; }, never, ["*"], true, never>;
|
|
626
881
|
static ngAcceptInputType_visible: unknown;
|
|
627
882
|
static ngAcceptInputType_modal: unknown;
|
|
628
883
|
static ngAcceptInputType_closable: unknown;
|
|
629
884
|
static ngAcceptInputType_draggable: unknown;
|
|
630
885
|
static ngAcceptInputType_resizable: unknown;
|
|
886
|
+
static ngAcceptInputType_dismissableMask: unknown;
|
|
887
|
+
static ngAcceptInputType_closeOnEscape: unknown;
|
|
631
888
|
static ngAcceptInputType_defaultActions: unknown;
|
|
632
889
|
static ngAcceptInputType_saveDisabled: unknown;
|
|
633
890
|
}
|
|
@@ -646,13 +903,44 @@ declare class EfFieldsetComponent {
|
|
|
646
903
|
static ngAcceptInputType_collapsed: unknown;
|
|
647
904
|
}
|
|
648
905
|
|
|
906
|
+
/** PrimeNG severity vocabulary (v1's default). */
|
|
907
|
+
type EfButtonPrimeNGSeverity = 'primary' | 'secondary' | 'success' | 'info' | 'warn' | 'danger' | 'help' | 'contrast';
|
|
908
|
+
/** Comptoir severity vocabulary — maps to `.btn-{name}` rules in
|
|
909
|
+
* `@elasticias/ui/styles/patterns`. `'danger'` renders as
|
|
910
|
+
* `.btn-ghost` with the cancelled-fg tint applied inline. */
|
|
911
|
+
type EfButtonComptoirSeverity = 'primary' | 'tenant' | 'ghost' | 'danger';
|
|
912
|
+
type EfButtonSeverity = EfButtonPrimeNGSeverity | EfButtonComptoirSeverity;
|
|
913
|
+
/**
|
|
914
|
+
* Wrapper button for both v1 (PrimeNG-themed) and V2 (Comptoir-themed)
|
|
915
|
+
* surfaces. `[variant]` picks the rendering path:
|
|
916
|
+
*
|
|
917
|
+
* - `'primeng'` (default) — wraps `<p-button>` with PrimeNG severities
|
|
918
|
+
* (`primary / success / danger / …`). Keeps v1 imports working
|
|
919
|
+
* unchanged.
|
|
920
|
+
*
|
|
921
|
+
* - `'comptoir'` — renders a native `<button class="btn btn-{severity}
|
|
922
|
+
* btn-sm">` against the Comptoir `.btn` pattern. Severities are
|
|
923
|
+
* `'primary' | 'tenant' | 'ghost' | 'danger'`; `'danger'` falls back
|
|
924
|
+
* to `.btn-ghost` with the `--st-cancelled-fg` tint applied inline,
|
|
925
|
+
* matching the prototype's Delete-button styling.
|
|
926
|
+
*
|
|
927
|
+
* Both variants honour `labelKey` (i18n preferred), `icon`,
|
|
928
|
+
* `disabled`, `loading`, `pTooltip` (via `tooltipKey`), and emit the
|
|
929
|
+
* same `clickEvent`.
|
|
930
|
+
*/
|
|
649
931
|
declare class EfButtonComponent {
|
|
650
|
-
/** Direct label text (not translated) */
|
|
932
|
+
/** Direct label text (not translated). */
|
|
651
933
|
label?: string;
|
|
652
|
-
/** Translation key — takes priority over label */
|
|
934
|
+
/** Translation key — takes priority over `label`. */
|
|
653
935
|
labelKey?: string;
|
|
654
936
|
icon?: string;
|
|
655
|
-
|
|
937
|
+
/**
|
|
938
|
+
* Which rendering surface to use. Default `'primeng'` keeps v1
|
|
939
|
+
* consumers unchanged. V2 detail/list screens pass `'comptoir'`
|
|
940
|
+
* to opt into the Comptoir `.btn` styling.
|
|
941
|
+
*/
|
|
942
|
+
variant: 'primeng' | 'comptoir';
|
|
943
|
+
severity: EfButtonSeverity;
|
|
656
944
|
size: 'small' | 'large';
|
|
657
945
|
disabled: boolean;
|
|
658
946
|
rounded: boolean;
|
|
@@ -664,15 +952,33 @@ declare class EfButtonComponent {
|
|
|
664
952
|
type: 'button' | 'submit';
|
|
665
953
|
badge?: string;
|
|
666
954
|
badgeSeverity?: 'success' | 'info' | 'warn' | 'danger' | 'help' | 'primary' | 'secondary' | 'contrast';
|
|
667
|
-
/** Direct tooltip text (not translated)
|
|
955
|
+
/** Direct tooltip text (not translated). Falls back to `label`
|
|
956
|
+
* when neither `tooltip` nor `tooltipKey` is set. */
|
|
668
957
|
tooltip?: string;
|
|
669
|
-
/** Translation key for tooltip — takes priority over tooltip
|
|
958
|
+
/** Translation key for tooltip — takes priority over `tooltip`.
|
|
959
|
+
* Falls back to `labelKey` when not provided, so buttons with
|
|
960
|
+
* visible labels still expose them to screen readers / mobile
|
|
961
|
+
* long-press once the label is hidden by responsive CSS. */
|
|
670
962
|
tooltipKey?: string;
|
|
671
963
|
tooltipPosition: 'top' | 'bottom' | 'left' | 'right';
|
|
964
|
+
/** Resolved tooltip translation key — `tooltipKey` if provided,
|
|
965
|
+
* otherwise `labelKey`. Lets responsive icon-only buttons reuse
|
|
966
|
+
* their label as the tooltip without restating it at every call
|
|
967
|
+
* site. */
|
|
968
|
+
get effectiveTooltipKey(): string | undefined;
|
|
969
|
+
/** Resolved plain tooltip text — `tooltip` if provided, otherwise
|
|
970
|
+
* `label`. Used only when neither `tooltipKey` nor `labelKey` is
|
|
971
|
+
* set. */
|
|
972
|
+
get effectiveTooltip(): string | undefined;
|
|
672
973
|
clickEvent: EventEmitter<Event>;
|
|
974
|
+
/** Composed class string for the Comptoir variant —
|
|
975
|
+
* `btn btn-{severity} btn-sm` plus any caller-supplied `styleClass`. */
|
|
976
|
+
get comptoirClass(): string;
|
|
977
|
+
/** Inline danger tint for the `severity="danger"` Comptoir variant. */
|
|
978
|
+
get comptoirInlineColor(): string | null;
|
|
673
979
|
handleClick(event: Event): void;
|
|
674
980
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfButtonComponent, never>;
|
|
675
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfButtonComponent, "ef-button", never, { "label": { "alias": "label"; "required": false; }; "labelKey": { "alias": "labelKey"; "required": false; }; "icon": { "alias": "icon"; "required": false; }; "severity": { "alias": "severity"; "required": false; }; "size": { "alias": "size"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "rounded": { "alias": "rounded"; "required": false; }; "outlined": { "alias": "outlined"; "required": false; }; "raised": { "alias": "raised"; "required": false; }; "text": { "alias": "text"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "type": { "alias": "type"; "required": false; }; "badge": { "alias": "badge"; "required": false; }; "badgeSeverity": { "alias": "badgeSeverity"; "required": false; }; "tooltip": { "alias": "tooltip"; "required": false; }; "tooltipKey": { "alias": "tooltipKey"; "required": false; }; "tooltipPosition": { "alias": "tooltipPosition"; "required": false; }; }, { "clickEvent": "clickEvent"; }, never, never, true, never>;
|
|
981
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfButtonComponent, "ef-button", never, { "label": { "alias": "label"; "required": false; }; "labelKey": { "alias": "labelKey"; "required": false; }; "icon": { "alias": "icon"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "severity": { "alias": "severity"; "required": false; }; "size": { "alias": "size"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "rounded": { "alias": "rounded"; "required": false; }; "outlined": { "alias": "outlined"; "required": false; }; "raised": { "alias": "raised"; "required": false; }; "text": { "alias": "text"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "type": { "alias": "type"; "required": false; }; "badge": { "alias": "badge"; "required": false; }; "badgeSeverity": { "alias": "badgeSeverity"; "required": false; }; "tooltip": { "alias": "tooltip"; "required": false; }; "tooltipKey": { "alias": "tooltipKey"; "required": false; }; "tooltipPosition": { "alias": "tooltipPosition"; "required": false; }; }, { "clickEvent": "clickEvent"; }, never, never, true, never>;
|
|
676
982
|
static ngAcceptInputType_disabled: unknown;
|
|
677
983
|
static ngAcceptInputType_rounded: unknown;
|
|
678
984
|
static ngAcceptInputType_outlined: unknown;
|
|
@@ -681,17 +987,46 @@ declare class EfButtonComponent {
|
|
|
681
987
|
static ngAcceptInputType_loading: unknown;
|
|
682
988
|
}
|
|
683
989
|
|
|
990
|
+
declare class EfButtonGroupComponent {
|
|
991
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfButtonGroupComponent, never>;
|
|
992
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfButtonGroupComponent, "ef-button-group", never, {}, {}, never, ["*"], true, never>;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/**
|
|
996
|
+
* Comptoir form label — renders a `<label>` with the design-system
|
|
997
|
+
* typography (uppercase Manrope 11px / 700 / `--text-mute`,
|
|
998
|
+
* 0.06em letter-spacing) defined under `.ef-label` in
|
|
999
|
+
* `@elasticias/ui/styles/patterns`.
|
|
1000
|
+
*
|
|
1001
|
+
* - `[labelKey]` — translation key (preferred). Falls back to
|
|
1002
|
+
* `[label]` when missing. The `feedback_i18n_keys` memory says
|
|
1003
|
+
* always use `*Key` on shared `ef-*` components.
|
|
1004
|
+
* - `[for]` — DOM id of the input the label labels. Mapped through
|
|
1005
|
+
* `[attr.for]` so an empty value renders no attribute (the input
|
|
1006
|
+
* doesn't end up with a broken `for=""`).
|
|
1007
|
+
* - `[required]` — toggles a red asterisk via
|
|
1008
|
+
* `.ef-label.is-required::after`.
|
|
1009
|
+
* - `[styleClass]` — caller-supplied extra class. Defaults to
|
|
1010
|
+
* `'form-label'` for v1 back-compat. The `.ef-label` Comptoir
|
|
1011
|
+
* class is always applied on top.
|
|
1012
|
+
*/
|
|
684
1013
|
declare class EfLabelComponent {
|
|
685
|
-
/** Direct label text
|
|
1014
|
+
/** Direct label text — use `labelKey` for i18n. */
|
|
686
1015
|
label?: string;
|
|
687
|
-
/** Translation key —
|
|
1016
|
+
/** Translation key — preferred. */
|
|
688
1017
|
labelKey?: string;
|
|
689
|
-
/**
|
|
1018
|
+
/** DOM id of the labelled input. Empty / unset → no `for` attr. */
|
|
690
1019
|
for?: string;
|
|
691
|
-
/**
|
|
1020
|
+
/** Caller-supplied extra class. The Comptoir `.ef-label` class is
|
|
1021
|
+
* always applied; this stacks on top. Defaults to `'form-label'`
|
|
1022
|
+
* for v1 back-compat. */
|
|
692
1023
|
styleClass: string;
|
|
693
|
-
/** Show required
|
|
1024
|
+
/** Show the required-asterisk modifier. */
|
|
694
1025
|
required: boolean;
|
|
1026
|
+
/** Composes `'ef-label'` + `styleClass` + the `'is-required'`
|
|
1027
|
+
* modifier into a single class string. Angular's `[class]`
|
|
1028
|
+
* binding replaces (doesn't merge) so we do the joining here. */
|
|
1029
|
+
get resolvedClass(): string;
|
|
695
1030
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfLabelComponent, never>;
|
|
696
1031
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfLabelComponent, "ef-label", never, { "label": { "alias": "label"; "required": false; }; "labelKey": { "alias": "labelKey"; "required": false; }; "for": { "alias": "for"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "required": { "alias": "required"; "required": false; }; }, {}, never, never, true, never>;
|
|
697
1032
|
static ngAcceptInputType_required: unknown;
|
|
@@ -872,7 +1207,7 @@ declare class EfToolbarComponent {
|
|
|
872
1207
|
get isSearchState(): boolean;
|
|
873
1208
|
get isDetailState(): boolean;
|
|
874
1209
|
get hasReadPermission(): boolean;
|
|
875
|
-
get
|
|
1210
|
+
get hasCreatePermission(): boolean;
|
|
876
1211
|
get hasEditPermission(): boolean;
|
|
877
1212
|
get hasDeletePermission(): boolean;
|
|
878
1213
|
get hasDuplicatePermission(): boolean;
|
|
@@ -892,6 +1227,459 @@ declare class EfToolbarComponent {
|
|
|
892
1227
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfToolbarComponent, "ef-toolbar", never, { "context": { "alias": "context"; "required": false; }; "state": { "alias": "state"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "backButton": { "alias": "backButton"; "required": false; }; "deleteButton": { "alias": "deleteButton"; "required": false; }; "duplicateButton": { "alias": "duplicateButton"; "required": false; }; "saveButton": { "alias": "saveButton"; "required": false; }; "exportButton": { "alias": "exportButton"; "required": false; }; "printButton": { "alias": "printButton"; "required": false; }; "addButton": { "alias": "addButton"; "required": false; }; "clearButton": { "alias": "clearButton"; "required": false; }; "searchButton": { "alias": "searchButton"; "required": false; }; "showFreeSearchInput": { "alias": "showFreeSearchInput"; "required": false; }; }, { "back": "back"; "save": "save"; "delete": "delete"; "duplicate": "duplicate"; "print": "print"; "triggerCustoAction": "triggerCustoAction"; "add": "add"; "search": "search"; "clear": "clear"; }, never, ["[toolbarStart]", "[toolbarEnd]"], true, never>;
|
|
893
1228
|
}
|
|
894
1229
|
|
|
1230
|
+
/**
|
|
1231
|
+
* Top-level Comptoir shell.
|
|
1232
|
+
*
|
|
1233
|
+
* Composes the chrome an Elasticias app puts around its `<router-outlet />`.
|
|
1234
|
+
* Apps mount it at their root component:
|
|
1235
|
+
*
|
|
1236
|
+
* ```html
|
|
1237
|
+
* <ef-app-shell>
|
|
1238
|
+
* <router-outlet />
|
|
1239
|
+
* </ef-app-shell>
|
|
1240
|
+
* ```
|
|
1241
|
+
*
|
|
1242
|
+
* The shell reads:
|
|
1243
|
+
* - `EfViewportService` to switch between desktop and mobile branches
|
|
1244
|
+
* - `EfPermissionService` (via the rail / mobile tabs) for visible modules
|
|
1245
|
+
* - `EfActiveModuleService` for the active module accent
|
|
1246
|
+
*
|
|
1247
|
+
* **Desktop / tablet:** rail (64px) + side (240px) + (top + main).
|
|
1248
|
+
* **Mobile:** delegates to `<ef-app-shell-mobile>` — top bar + scrollable
|
|
1249
|
+
* body + 5-tab bottom bar + FAB slot.
|
|
1250
|
+
*
|
|
1251
|
+
* Top-bar slots are forwarded to `<ef-app-top>` on both layouts: project
|
|
1252
|
+
* with `breadcrumb`, `search`, `actions` attributes. The `side-footer`
|
|
1253
|
+
* slot is forwarded to the bottom of `<ef-module-side>` (desktop only —
|
|
1254
|
+
* mobile drops it; surface identity via `[actions]` instead). The `logo`
|
|
1255
|
+
* slot is forwarded to the top of `<ef-module-rail>` (desktop/tablet
|
|
1256
|
+
* only — mobile uses the bottom tab bar instead).
|
|
1257
|
+
*/
|
|
1258
|
+
declare class EfAppShellComponent {
|
|
1259
|
+
private readonly vp;
|
|
1260
|
+
/** Show the 3px module-color stripe at the top of the content area. */
|
|
1261
|
+
stripe: boolean;
|
|
1262
|
+
readonly viewport: _angular_core.Signal<_elasticias_core.EfViewport>;
|
|
1263
|
+
readonly isMobile: _angular_core.Signal<boolean>;
|
|
1264
|
+
readonly showSide: _angular_core.Signal<boolean>;
|
|
1265
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfAppShellComponent, never>;
|
|
1266
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfAppShellComponent, "ef-app-shell", never, { "stripe": { "alias": "stripe"; "required": false; }; }, {}, never, ["[breadcrumb]", "[search]", "[actions]", "[fab]", "*", "[logo]", "[side-header-meta]", "[side-footer]", "[breadcrumb]", "[actions]", "*"], true, never>;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
/**
|
|
1270
|
+
* Mobile-only shell. Picks up when `ef-app-shell` detects a mobile
|
|
1271
|
+
* viewport. Composition:
|
|
1272
|
+
*
|
|
1273
|
+
* - Top bar (`ef-app-top`) with a menu trigger that opens the module
|
|
1274
|
+
* switcher in a bottom sheet.
|
|
1275
|
+
* - Scrollable content (`ef-app-main`) — projects `<router-outlet />`.
|
|
1276
|
+
* - 5-tab bottom bar — first 5 visible modules from
|
|
1277
|
+
* `EfPermissionService.visibleModules()`. Apps that want a usage-
|
|
1278
|
+
* ranked tab order can replace the registry via `EF_MODULES_TOKEN`.
|
|
1279
|
+
* - FAB slot (`[fab]`) — apps project a `<ef-fab />` here.
|
|
1280
|
+
*
|
|
1281
|
+
* The module switcher (bottom sheet) lists all visible modules so
|
|
1282
|
+
* users can reach modules outside the top-5 tabs.
|
|
1283
|
+
*/
|
|
1284
|
+
declare class EfAppShellMobileComponent {
|
|
1285
|
+
private readonly perms;
|
|
1286
|
+
private readonly active;
|
|
1287
|
+
private readonly router;
|
|
1288
|
+
readonly activeId: _angular_core.Signal<_elasticias_core.EfModuleId>;
|
|
1289
|
+
readonly switcherOpen: _angular_core.WritableSignal<boolean>;
|
|
1290
|
+
readonly tabs: _angular_core.Signal<EfModule[]>;
|
|
1291
|
+
readonly allVisible: _angular_core.Signal<readonly EfModule[]>;
|
|
1292
|
+
openSwitcher(): void;
|
|
1293
|
+
onSwitcherChange(open: boolean): void;
|
|
1294
|
+
onSelect(module: EfModule): void;
|
|
1295
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfAppShellMobileComponent, never>;
|
|
1296
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfAppShellMobileComponent, "ef-app-shell-mobile", never, {}, {}, never, ["[breadcrumb]", "[search]", "[actions]", "*", "[fab]"], true, never>;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
/**
|
|
1300
|
+
* Content scroll container. Lives at the right of the rail+side
|
|
1301
|
+
* on desktop, full-width on mobile. Sets `data-module` so the
|
|
1302
|
+
* Comptoir SCSS layer's `[data-module="..."]` rules apply the
|
|
1303
|
+
* active module's `--module` accent inside this region.
|
|
1304
|
+
*
|
|
1305
|
+
* Usage:
|
|
1306
|
+
* ```html
|
|
1307
|
+
* <ef-app-main [stripe]="true">
|
|
1308
|
+
* <router-outlet />
|
|
1309
|
+
* </ef-app-main>
|
|
1310
|
+
* ```
|
|
1311
|
+
*
|
|
1312
|
+
* Reads the active module from `EfActiveModuleService` — no per-app
|
|
1313
|
+
* wiring required.
|
|
1314
|
+
*/
|
|
1315
|
+
declare class EfAppMainComponent {
|
|
1316
|
+
private readonly activeModule;
|
|
1317
|
+
/** Render the 3px module-color stripe at the top of the content area. */
|
|
1318
|
+
stripe: boolean;
|
|
1319
|
+
/** `data-module` value bound to the host. Null when no module is active. */
|
|
1320
|
+
readonly moduleId: _angular_core.Signal<_elasticias_core.EfModuleId>;
|
|
1321
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfAppMainComponent, never>;
|
|
1322
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfAppMainComponent, "ef-app-main", never, { "stripe": { "alias": "stripe"; "required": false; }; }, {}, never, ["*"], true, never>;
|
|
1323
|
+
static ngAcceptInputType_stripe: unknown;
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
/**
|
|
1327
|
+
* Top chrome bar for the desktop and mobile shells.
|
|
1328
|
+
*
|
|
1329
|
+
* Layout is three slots: `breadcrumb` (left), `search` (centre), and
|
|
1330
|
+
* `actions` (right). Apps project into `search` and `actions` for global
|
|
1331
|
+
* features (⌘K, notifications bell, profile chip).
|
|
1332
|
+
*
|
|
1333
|
+
* The breadcrumb slot fills automatically from `EfActiveModuleService`:
|
|
1334
|
+
* a leading dot in the active module's accent, the module label, then
|
|
1335
|
+
* the active nav-item label as the leaf. Apps that need a custom
|
|
1336
|
+
* breadcrumb can still project their own content into `[breadcrumb]`.
|
|
1337
|
+
*/
|
|
1338
|
+
declare class EfAppTopComponent {
|
|
1339
|
+
private readonly active;
|
|
1340
|
+
readonly module: _angular_core.Signal<_elasticias_core.EfModule>;
|
|
1341
|
+
readonly navItem: _angular_core.Signal<_elasticias_core.EfNavItem>;
|
|
1342
|
+
readonly hasBreadcrumb: _angular_core.Signal<boolean>;
|
|
1343
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfAppTopComponent, never>;
|
|
1344
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfAppTopComponent, "ef-app-top", never, {}, {}, never, ["[breadcrumb]", "[actions]"], true, never>;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
/**
|
|
1348
|
+
* Rail row — either a module button (with the metadata needed by the
|
|
1349
|
+
* template) or a divider rendered between two modules whose `group`
|
|
1350
|
+
* differs.
|
|
1351
|
+
*/
|
|
1352
|
+
type RailRow = {
|
|
1353
|
+
kind: 'module';
|
|
1354
|
+
module: EfModule;
|
|
1355
|
+
} | {
|
|
1356
|
+
kind: 'divider';
|
|
1357
|
+
};
|
|
1358
|
+
/**
|
|
1359
|
+
* 64px vertical module switcher rendered at the left of `ef-app-shell`
|
|
1360
|
+
* on desktop and tablet. Black (`--ink-active`) background with
|
|
1361
|
+
* white-alpha icons, 44×44px buttons, and a 3px module-color accent
|
|
1362
|
+
* strip on the inside edge of the active button.
|
|
1363
|
+
*
|
|
1364
|
+
* Reads from `EfPermissionService.visibleModules()` and
|
|
1365
|
+
* `EfActiveModuleService.activeModule()`. No per-app wiring needed.
|
|
1366
|
+
*
|
|
1367
|
+
* Apps can supply per-module badge content (e.g., notification counts)
|
|
1368
|
+
* via the `[badges]` input keyed by module id, and project a logo into
|
|
1369
|
+
* the `[logo]` content slot — typical content is the tenant initial,
|
|
1370
|
+
* an avatar, or a small SVG. When a logo is projected, a hairline
|
|
1371
|
+
* divider is rendered between the logo and the first module group.
|
|
1372
|
+
*
|
|
1373
|
+
* Dividers also appear automatically between consecutive modules whose
|
|
1374
|
+
* `EfModule.group` differs (e.g. Sales/operations followed by
|
|
1375
|
+
* Admin/admin).
|
|
1376
|
+
*/
|
|
1377
|
+
declare class EfModuleRailComponent {
|
|
1378
|
+
private readonly perms;
|
|
1379
|
+
private readonly active;
|
|
1380
|
+
private readonly router;
|
|
1381
|
+
/** Optional notification badges per module id. */
|
|
1382
|
+
badges: Partial<Record<EfModuleId, string | number>>;
|
|
1383
|
+
readonly visibleModules: _angular_core.Signal<readonly EfModule[]>;
|
|
1384
|
+
readonly activeId: _angular_core.Signal<EfModuleId>;
|
|
1385
|
+
/** Visible modules interleaved with dividers at group boundaries. */
|
|
1386
|
+
readonly rows: _angular_core.Signal<RailRow[]>;
|
|
1387
|
+
readonly hasBadges: _angular_core.Signal<boolean>;
|
|
1388
|
+
onSelect(module: EfModule): void;
|
|
1389
|
+
badgeFor(id: EfModuleId): string | number | undefined;
|
|
1390
|
+
trackRow(index: number, row: RailRow): string;
|
|
1391
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfModuleRailComponent, never>;
|
|
1392
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfModuleRailComponent, "ef-module-rail", never, { "badges": { "alias": "badges"; "required": false; }; }, {}, never, ["[logo]"], true, never>;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
/**
|
|
1396
|
+
* 240px module-specific side panel. Renders the active module's
|
|
1397
|
+
* `navSections`, filtered by `EfPermissionService.can()` against
|
|
1398
|
+
* each item's `requiredAction` (defaults to `'read'`).
|
|
1399
|
+
*
|
|
1400
|
+
* When no module is active, or the active module has no sections,
|
|
1401
|
+
* the panel collapses (renders nothing) — apps using `ef-app-shell`
|
|
1402
|
+
* already handle the layout reflow.
|
|
1403
|
+
*/
|
|
1404
|
+
declare class EfModuleSideComponent {
|
|
1405
|
+
private readonly active;
|
|
1406
|
+
private readonly perms;
|
|
1407
|
+
readonly module: _angular_core.Signal<_elasticias_core.EfModule>;
|
|
1408
|
+
readonly moduleId: _angular_core.Signal<_elasticias_core.EfModuleId>;
|
|
1409
|
+
readonly visibleSections: _angular_core.Signal<EfNavSection[]>;
|
|
1410
|
+
trackSection(_: number, s: EfNavSection): string;
|
|
1411
|
+
trackItem(_: number, i: EfNavItem): string;
|
|
1412
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfModuleSideComponent, never>;
|
|
1413
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfModuleSideComponent, "ef-module-side", never, {}, {}, never, ["[side-header-meta]", "*"], true, never>;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
/**
|
|
1417
|
+
* Slide-up overlay with a grabber. Replaces dropdowns and dialogs on
|
|
1418
|
+
* mobile per the Comptoir plan. Controlled component — apps drive
|
|
1419
|
+
* `[open]` and listen to `(openChange)`.
|
|
1420
|
+
*
|
|
1421
|
+
* Tapping the backdrop or pressing Escape emits `openChange.emit(false)`.
|
|
1422
|
+
*
|
|
1423
|
+
* Usage:
|
|
1424
|
+
* ```html
|
|
1425
|
+
* <ef-bottom-sheet [open]="filtersOpen()" (openChange)="filtersOpen.set($event)">
|
|
1426
|
+
* <ng-template>...filters body...</ng-template>
|
|
1427
|
+
* </ef-bottom-sheet>
|
|
1428
|
+
* ```
|
|
1429
|
+
*/
|
|
1430
|
+
declare class EfBottomSheetComponent {
|
|
1431
|
+
open: boolean;
|
|
1432
|
+
dismissOnBackdrop: boolean;
|
|
1433
|
+
openChange: EventEmitter<boolean>;
|
|
1434
|
+
onBackdropClick(): void;
|
|
1435
|
+
onEscape(): void;
|
|
1436
|
+
close(): void;
|
|
1437
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfBottomSheetComponent, never>;
|
|
1438
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfBottomSheetComponent, "ef-bottom-sheet", never, { "open": { "alias": "open"; "required": false; }; "dismissOnBackdrop": { "alias": "dismissOnBackdrop"; "required": false; }; }, { "openChange": "openChange"; }, never, ["*"], true, never>;
|
|
1439
|
+
static ngAcceptInputType_open: unknown;
|
|
1440
|
+
static ngAcceptInputType_dismissOnBackdrop: unknown;
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
type EfFabPosition = 'bottom-right' | 'bottom-center' | 'bottom-left';
|
|
1444
|
+
/**
|
|
1445
|
+
* Floating action button — mobile primary action surface.
|
|
1446
|
+
*
|
|
1447
|
+
* Lives at the bottom of the mobile viewport, carrying the screen's
|
|
1448
|
+
* principal action (e.g. Nouvelle commande). Reads `--tenant-500`
|
|
1449
|
+
* for its background; foreground is `--tenant-contrast` (defaults
|
|
1450
|
+
* to white). When `label` / `labelKey` is provided, renders as an
|
|
1451
|
+
* extended FAB with the label inline.
|
|
1452
|
+
*
|
|
1453
|
+
* Usage:
|
|
1454
|
+
* ```html
|
|
1455
|
+
* <ef-fab icon="pi pi-plus" labelKey="orders.new" (press)="onNew()" />
|
|
1456
|
+
* ```
|
|
1457
|
+
*/
|
|
1458
|
+
declare class EfFabComponent {
|
|
1459
|
+
icon: string;
|
|
1460
|
+
label?: string;
|
|
1461
|
+
/** Translation key — takes priority over `label`. */
|
|
1462
|
+
labelKey?: string;
|
|
1463
|
+
position: EfFabPosition;
|
|
1464
|
+
disabled: boolean;
|
|
1465
|
+
press: EventEmitter<MouseEvent>;
|
|
1466
|
+
get isExtended(): boolean;
|
|
1467
|
+
onClick(e: MouseEvent): void;
|
|
1468
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfFabComponent, never>;
|
|
1469
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfFabComponent, "ef-fab", never, { "icon": { "alias": "icon"; "required": false; }; "label": { "alias": "label"; "required": false; }; "labelKey": { "alias": "labelKey"; "required": false; }; "position": { "alias": "position"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, { "press": "press"; }, never, never, true, never>;
|
|
1470
|
+
static ngAcceptInputType_disabled: unknown;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
interface EfPillItem<T = string> {
|
|
1474
|
+
value: T;
|
|
1475
|
+
/** Direct label (no translation). */
|
|
1476
|
+
label?: string;
|
|
1477
|
+
/** Translation key — takes priority over label. */
|
|
1478
|
+
labelKey?: string;
|
|
1479
|
+
/** Optional count rendered after a thin separator. */
|
|
1480
|
+
count?: number;
|
|
1481
|
+
}
|
|
1482
|
+
/**
|
|
1483
|
+
* Segmented pill filter. Used for tab-like selectors over a small
|
|
1484
|
+
* set of options — "Toutes · 87 / À approuver · 14 / En retard · 3".
|
|
1485
|
+
*
|
|
1486
|
+
* ```html
|
|
1487
|
+
* <ef-pill-group
|
|
1488
|
+
* [items]="filters"
|
|
1489
|
+
* [(value)]="activeFilter"
|
|
1490
|
+
* (valueChange)="onFilterChange($event)"
|
|
1491
|
+
* />
|
|
1492
|
+
* ```
|
|
1493
|
+
*
|
|
1494
|
+
* The active pill picks up a contrast fill (`--ink-active`); inactive
|
|
1495
|
+
* pills sit on transparent ground with muted text. Heights map to
|
|
1496
|
+
* `--hit` (32px) so it stacks naturally next to compact action buttons.
|
|
1497
|
+
*/
|
|
1498
|
+
declare class EfPillGroupComponent<T = string> {
|
|
1499
|
+
items: ReadonlyArray<EfPillItem<T>>;
|
|
1500
|
+
value: T | null;
|
|
1501
|
+
ariaLabel: string;
|
|
1502
|
+
/** Hide counts even when items provide them. */
|
|
1503
|
+
hideCounts: boolean;
|
|
1504
|
+
readonly valueChange: EventEmitter<T>;
|
|
1505
|
+
select(item: EfPillItem<T>): void;
|
|
1506
|
+
trackValue(_: number, item: EfPillItem<T>): T;
|
|
1507
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfPillGroupComponent<any>, never>;
|
|
1508
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPillGroupComponent<any>, "ef-pill-group", never, { "items": { "alias": "items"; "required": true; }; "value": { "alias": "value"; "required": false; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; }; "hideCounts": { "alias": "hideCounts"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
/** Visual treatment of the tabset. `'pill'` is the default. */
|
|
1512
|
+
type EfTabsVariant = 'pill' | 'underline';
|
|
1513
|
+
/** Known module slugs whose accent (`var(--m-{slug})`) drives the
|
|
1514
|
+
* active indicator and count tint when `variant === 'underline'`. */
|
|
1515
|
+
type EfTabsModule = 'sales' | 'purchase' | 'stock' | 'pos' | 'marketing' | 'store' | 'finance' | 'admin';
|
|
1516
|
+
interface EfTabItem<T = string> {
|
|
1517
|
+
value: T;
|
|
1518
|
+
/** Direct label (not translated). */
|
|
1519
|
+
label?: string;
|
|
1520
|
+
/** Translation key — takes priority over `label`. */
|
|
1521
|
+
labelKey?: string;
|
|
1522
|
+
/** PrimeIcons class string, e.g. `'pi pi-th-large'`. Rendered
|
|
1523
|
+
* before the label, muted when idle. */
|
|
1524
|
+
icon?: string;
|
|
1525
|
+
/** Optional count rendered after the label in a mono badge. */
|
|
1526
|
+
count?: number;
|
|
1527
|
+
/** Show a dirty/unread dot after the label/count. */
|
|
1528
|
+
dirty?: boolean;
|
|
1529
|
+
disabled?: boolean;
|
|
1530
|
+
}
|
|
1531
|
+
/**
|
|
1532
|
+
* Comptoir tabset. Pilots the visible *view* on a detail screen
|
|
1533
|
+
* (Identité / Médias / Variantes / SEO / Activité…). Defaults to the
|
|
1534
|
+
* pill variant — chunky toggle suited for sub-modes (Editor / Preview,
|
|
1535
|
+
* Day / Week) — with `'underline'` available for fiche-wide navigation
|
|
1536
|
+
* where the active tab adopts the module accent.
|
|
1537
|
+
*
|
|
1538
|
+
* Two consumer surfaces, mirroring `<ef-data-card>`:
|
|
1539
|
+
*
|
|
1540
|
+
* 1. **Tablist only** — no panels projected. The component renders
|
|
1541
|
+
* the tab strip and emits `valueChange` ; the consumer owns panel
|
|
1542
|
+
* rendering via `@switch` / `@if`.
|
|
1543
|
+
*
|
|
1544
|
+
* ```html
|
|
1545
|
+
* <ef-tabs [items]="sections" [(value)]="active" />
|
|
1546
|
+
* @switch (active) {
|
|
1547
|
+
* @case ('identity') { <product-identity /> }
|
|
1548
|
+
* @case ('media') { <product-media /> }
|
|
1549
|
+
* }
|
|
1550
|
+
* ```
|
|
1551
|
+
*
|
|
1552
|
+
* 2. **Tabs + projected panels** — `<ng-template efTabPanel="…">`
|
|
1553
|
+
* blocks declare the body of each tab. The component shows the one
|
|
1554
|
+
* whose `efTabPanel` matches the active value.
|
|
1555
|
+
*
|
|
1556
|
+
* ```html
|
|
1557
|
+
* <ef-tabs [items]="sections" [(value)]="active" variant="underline" module="store">
|
|
1558
|
+
* <ng-template efTabPanel="identity"><product-identity /></ng-template>
|
|
1559
|
+
* <ng-template efTabPanel="media"><product-media /></ng-template>
|
|
1560
|
+
* </ef-tabs>
|
|
1561
|
+
* ```
|
|
1562
|
+
*
|
|
1563
|
+
* For filter toggles over result sets (Toutes / Pending / Shipped),
|
|
1564
|
+
* prefer `<ef-pill-group>` — it shares the pill look but stays scoped
|
|
1565
|
+
* to filter selection rather than view switching.
|
|
1566
|
+
*/
|
|
1567
|
+
declare class EfTabsComponent<T = string> implements AfterContentInit {
|
|
1568
|
+
items: ReadonlyArray<EfTabItem<T>>;
|
|
1569
|
+
/** Currently-selected tab value. When no `*efTabPanel` templates
|
|
1570
|
+
* are projected, panel rendering is the consumer's job (typically
|
|
1571
|
+
* via `@switch (active)` in the template). */
|
|
1572
|
+
value: T | null;
|
|
1573
|
+
/** Visual variant. `'pill'` (default) is the segmented toggle ;
|
|
1574
|
+
* `'underline'` draws a 2px indicator under the active tab. */
|
|
1575
|
+
variant: EfTabsVariant;
|
|
1576
|
+
/** Forces the module accent on the active indicator + count tint
|
|
1577
|
+
* (only meaningful for `variant='underline'`). When omitted, the
|
|
1578
|
+
* underline inherits `--module` from the closest `[data-module]`
|
|
1579
|
+
* ancestor (and falls back to `--ink-active`). */
|
|
1580
|
+
module?: EfTabsModule;
|
|
1581
|
+
/** Show edge fades when the tablist overflows horizontally. The
|
|
1582
|
+
* list itself always scrolls — tabs are never collapsed into a
|
|
1583
|
+
* menu. */
|
|
1584
|
+
overflow: boolean;
|
|
1585
|
+
/** Hide count badges even when items provide them. */
|
|
1586
|
+
hideCounts: boolean;
|
|
1587
|
+
ariaLabel: string;
|
|
1588
|
+
/** Translation key used as the `aria-label` of the dirty dot.
|
|
1589
|
+
* Defaults to `'common.dirty'` — apps add the matching entry to
|
|
1590
|
+
* `fr.json` / `ar.json`. */
|
|
1591
|
+
dirtyLabelKey: string;
|
|
1592
|
+
readonly valueChange: EventEmitter<T>;
|
|
1593
|
+
private tabEls?;
|
|
1594
|
+
private readonly panels;
|
|
1595
|
+
private readonly panelMap;
|
|
1596
|
+
/** Active panel template for the current `value`, or `null` when
|
|
1597
|
+
* no template matches (incl. tablist-only mode). Read by the
|
|
1598
|
+
* template via `ngTemplateOutlet`. */
|
|
1599
|
+
activePanel(): TemplateRef<unknown> | null;
|
|
1600
|
+
/** `true` when at least one `*efTabPanel` template has been
|
|
1601
|
+
* projected — toggles the panel rendering slot in the template. */
|
|
1602
|
+
hasPanels(): boolean;
|
|
1603
|
+
ngAfterContentInit(): void;
|
|
1604
|
+
select(item: EfTabItem<T>): void;
|
|
1605
|
+
onKeydown(event: KeyboardEvent, index: number): void;
|
|
1606
|
+
trackValue(_: number, item: EfTabItem<T>): T;
|
|
1607
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfTabsComponent<any>, never>;
|
|
1608
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfTabsComponent<any>, "ef-tabs", never, { "items": { "alias": "items"; "required": true; }; "value": { "alias": "value"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "module": { "alias": "module"; "required": false; }; "overflow": { "alias": "overflow"; "required": false; }; "hideCounts": { "alias": "hideCounts"; "required": false; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; }; "dirtyLabelKey": { "alias": "dirtyLabelKey"; "required": false; }; }, { "valueChange": "valueChange"; }, ["panels"], never, true, never>;
|
|
1609
|
+
static ngAcceptInputType_overflow: unknown;
|
|
1610
|
+
static ngAcceptInputType_hideCounts: unknown;
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
/**
|
|
1614
|
+
* Marks an `<ng-template>` as the panel renderer for a tab value on
|
|
1615
|
+
* `<ef-tabs>`. When at least one panel template is projected,
|
|
1616
|
+
* `ef-tabs` renders the matching one below the tablist. When none is
|
|
1617
|
+
* projected, the component stays a tablist only — the consumer owns
|
|
1618
|
+
* panel rendering via `@switch` / `@if` on the active value.
|
|
1619
|
+
*
|
|
1620
|
+
* ```html
|
|
1621
|
+
* <ef-tabs [items]="sections" [(value)]="active">
|
|
1622
|
+
* <ng-template efTabPanel="identity">
|
|
1623
|
+
* <product-identity />
|
|
1624
|
+
* </ng-template>
|
|
1625
|
+
* <ng-template efTabPanel="media">
|
|
1626
|
+
* <product-media />
|
|
1627
|
+
* </ng-template>
|
|
1628
|
+
* </ef-tabs>
|
|
1629
|
+
* ```
|
|
1630
|
+
*
|
|
1631
|
+
* The input value must match one of the `EfTabItem.value` entries the
|
|
1632
|
+
* tabset is driven by.
|
|
1633
|
+
*/
|
|
1634
|
+
declare class EfTabPanelDirective {
|
|
1635
|
+
readonly templateRef: TemplateRef<unknown>;
|
|
1636
|
+
value: string;
|
|
1637
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfTabPanelDirective, never>;
|
|
1638
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<EfTabPanelDirective, "[efTabPanel]", never, { "value": { "alias": "efTabPanel"; "required": true; }; }, {}, never, never, true, never>;
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
/**
|
|
1642
|
+
* Compact identity chip — avatar + name + role — designed to sit at the
|
|
1643
|
+
* bottom of `ef-module-side` (project via the `side-footer` slot of
|
|
1644
|
+
* `ef-app-shell`). On mobile, apps usually surface the same identity in
|
|
1645
|
+
* the top bar `[actions]` slot instead.
|
|
1646
|
+
*
|
|
1647
|
+
* ```html
|
|
1648
|
+
* <ef-app-shell>
|
|
1649
|
+
* <ef-profile-chip
|
|
1650
|
+
* side-footer
|
|
1651
|
+
* [name]="user.name"
|
|
1652
|
+
* [role]="user.roleLabel"
|
|
1653
|
+
* (clickEvent)="openUserMenu()"
|
|
1654
|
+
* />
|
|
1655
|
+
* <router-outlet />
|
|
1656
|
+
* </ef-app-shell>
|
|
1657
|
+
* ```
|
|
1658
|
+
*
|
|
1659
|
+
* The component is intentionally dumb: apps wire their own identity
|
|
1660
|
+
* source. Initials are derived from `name` unless explicitly overridden.
|
|
1661
|
+
*/
|
|
1662
|
+
declare class EfProfileChipComponent {
|
|
1663
|
+
/** Direct name text (not translated). */
|
|
1664
|
+
name?: string;
|
|
1665
|
+
/** Direct role text (not translated). */
|
|
1666
|
+
role?: string;
|
|
1667
|
+
/** Translation key for the role line — takes priority over `role`. */
|
|
1668
|
+
roleKey?: string;
|
|
1669
|
+
/** Override the avatar glyph. Defaults to the first letter of `name`. */
|
|
1670
|
+
initial?: string;
|
|
1671
|
+
/** Tenant tone uses `--tenant-500`; neutral uses `--ink-active`. */
|
|
1672
|
+
tone: 'tenant' | 'neutral';
|
|
1673
|
+
/** Render as a non-interactive container (no hover/focus, no click). */
|
|
1674
|
+
readonly: boolean;
|
|
1675
|
+
readonly clickEvent: EventEmitter<Event>;
|
|
1676
|
+
get computedInitial(): string;
|
|
1677
|
+
handleClick(event: Event): void;
|
|
1678
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfProfileChipComponent, never>;
|
|
1679
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfProfileChipComponent, "ef-profile-chip", never, { "name": { "alias": "name"; "required": false; }; "role": { "alias": "role"; "required": false; }; "roleKey": { "alias": "roleKey"; "required": false; }; "initial": { "alias": "initial"; "required": false; }; "tone": { "alias": "tone"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; }, { "clickEvent": "clickEvent"; }, never, never, true, never>;
|
|
1680
|
+
static ngAcceptInputType_readonly: unknown;
|
|
1681
|
+
}
|
|
1682
|
+
|
|
895
1683
|
declare class EfBlockUiComponent {
|
|
896
1684
|
isLoading: boolean;
|
|
897
1685
|
contentPanel: any;
|
|
@@ -914,75 +1702,1193 @@ declare class EfBlockableDivComponent implements BlockableUI {
|
|
|
914
1702
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfBlockableDivComponent, "ef-blockable-div", never, { "style": { "alias": "style"; "required": false; }; "cssClass": { "alias": "cssClass"; "required": false; }; }, {}, never, ["*"], true, never>;
|
|
915
1703
|
}
|
|
916
1704
|
|
|
917
|
-
|
|
1705
|
+
/**
|
|
1706
|
+
* Live-indicator dot with a soft breath animation.
|
|
1707
|
+
*
|
|
1708
|
+
* Used for "Live", presence indicators, anything that says "this is
|
|
1709
|
+
* happening right now." Defaults to the Comptoir `--st-delivered-fg`
|
|
1710
|
+
* green; pass `[severity]="'warn' | 'danger' | 'mute'"` for amber, red,
|
|
1711
|
+
* or grey variants.
|
|
1712
|
+
*
|
|
1713
|
+
* ```html
|
|
1714
|
+
* <ef-pulse labelKey="status.live" />
|
|
1715
|
+
* <ef-pulse label="Offline" severity="mute" />
|
|
1716
|
+
* ```
|
|
1717
|
+
*/
|
|
1718
|
+
declare class EfPulseComponent {
|
|
1719
|
+
/** Direct label text (no translation). */
|
|
918
1720
|
label?: string;
|
|
1721
|
+
/** Translation key — takes priority over label. */
|
|
919
1722
|
labelKey?: string;
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1723
|
+
/** Visual tone of the dot. */
|
|
1724
|
+
severity: 'success' | 'warn' | 'danger' | 'mute';
|
|
1725
|
+
/** Set false to freeze the breath animation. */
|
|
1726
|
+
active: boolean;
|
|
1727
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfPulseComponent, never>;
|
|
1728
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPulseComponent, "ef-pulse", never, { "label": { "alias": "label"; "required": false; }; "labelKey": { "alias": "labelKey"; "required": false; }; "severity": { "alias": "severity"; "required": false; }; "active": { "alias": "active"; "required": false; }; }, {}, never, never, true, never>;
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
/**
|
|
1732
|
+
* Reusable PDF preview overlay — an `ef-dialog` hosting the browser's native
|
|
1733
|
+
* PDF viewer (an `<iframe>` fed a sanitized object URL) plus an optional action
|
|
1734
|
+
* bar (WhatsApp share · download · open in new tab · print · close).
|
|
1735
|
+
*
|
|
1736
|
+
* Self-contained: pass a `Blob` and a `fileName`, toggle which actions show.
|
|
1737
|
+
* The object URL is created/revoked automatically with the blob's lifetime.
|
|
1738
|
+
*
|
|
1739
|
+
* @example
|
|
1740
|
+
* <ef-pdf-preview
|
|
1741
|
+
* [(visible)]="pdfVisible"
|
|
1742
|
+
* [blob]="pdfBlob()"
|
|
1743
|
+
* [fileName]="pdfName()"
|
|
1744
|
+
* [showWhatsappShare]="true"
|
|
1745
|
+
* [whatsappPhone]="customerPhone()" />
|
|
1746
|
+
*/
|
|
1747
|
+
declare class EfPdfPreviewComponent {
|
|
1748
|
+
private readonly sanitizer;
|
|
1749
|
+
/** The PDF blob to preview. Setting it (re)creates the object URL. */
|
|
1750
|
+
blob: _angular_core.InputSignal<Blob>;
|
|
1751
|
+
/** File name shown in the header + used for download / share. */
|
|
1752
|
+
fileName: _angular_core.InputSignal<string>;
|
|
1753
|
+
/** Two-way dialog visibility. */
|
|
1754
|
+
visible: _angular_core.ModelSignal<boolean>;
|
|
1755
|
+
/** Header title translation key. */
|
|
1756
|
+
titleKey: _angular_core.InputSignal<string>;
|
|
1757
|
+
showDownload: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1758
|
+
showPrint: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1759
|
+
showOpenInNewTab: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1760
|
+
/** Show the WhatsApp share button (Web Share API → wa.me fallback). */
|
|
1761
|
+
showWhatsappShare: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1762
|
+
/** Optional recipient phone for the wa.me fallback (digits / +). */
|
|
1763
|
+
whatsappPhone: _angular_core.InputSignal<string>;
|
|
1764
|
+
private readonly objectUrl;
|
|
1765
|
+
private currentUrl;
|
|
1766
|
+
readonly safeUrl: _angular_core.Signal<SafeResourceUrl>;
|
|
1767
|
+
/** Footer buttons, rendered by `ef-dialog`'s `[actions]`. `dismiss:false`
|
|
1768
|
+
* keeps the preview open after download/print/share/open. */
|
|
1769
|
+
readonly actions: _angular_core.Signal<EfDialogAction[]>;
|
|
940
1770
|
constructor();
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
handleInput(value: string): void;
|
|
951
|
-
handleBlur(): void;
|
|
952
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfInputTextComponent, never>;
|
|
953
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfInputTextComponent, "ef-input-text", never, { "label": { "alias": "label"; "required": false; }; "labelKey": { "alias": "labelKey"; "required": false; }; "inputId": { "alias": "inputId"; "required": false; }; "name": { "alias": "name"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "placeholderKey": { "alias": "placeholderKey"; "required": false; }; "size": { "alias": "size"; "required": false; }; "type": { "alias": "type"; "required": false; }; "maxlength": { "alias": "maxlength"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "required": { "alias": "required"; "required": false; }; "fluid": { "alias": "fluid"; "required": false; }; "inline": { "alias": "inline"; "required": false; }; "autocomplete": { "alias": "autocomplete"; "required": false; }; }, { "valueChangeEvent": "valueChangeEvent"; }, never, never, true, never>;
|
|
954
|
-
static ngAcceptInputType_readonly: unknown;
|
|
955
|
-
static ngAcceptInputType_required: unknown;
|
|
956
|
-
static ngAcceptInputType_fluid: unknown;
|
|
957
|
-
static ngAcceptInputType_inline: unknown;
|
|
1771
|
+
private revoke;
|
|
1772
|
+
close(): void;
|
|
1773
|
+
download(): void;
|
|
1774
|
+
openInNewTab(): void;
|
|
1775
|
+
print(): void;
|
|
1776
|
+
shareWhatsapp(): void;
|
|
1777
|
+
private openWhatsappWeb;
|
|
1778
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfPdfPreviewComponent, never>;
|
|
1779
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPdfPreviewComponent, "ef-pdf-preview", never, { "blob": { "alias": "blob"; "required": false; "isSignal": true; }; "fileName": { "alias": "fileName"; "required": false; "isSignal": true; }; "visible": { "alias": "visible"; "required": false; "isSignal": true; }; "titleKey": { "alias": "titleKey"; "required": false; "isSignal": true; }; "showDownload": { "alias": "showDownload"; "required": false; "isSignal": true; }; "showPrint": { "alias": "showPrint"; "required": false; "isSignal": true; }; "showOpenInNewTab": { "alias": "showOpenInNewTab"; "required": false; "isSignal": true; }; "showWhatsappShare": { "alias": "showWhatsappShare"; "required": false; "isSignal": true; }; "whatsappPhone": { "alias": "whatsappPhone"; "required": false; "isSignal": true; }; }, { "visible": "visibleChange"; }, never, never, true, never>;
|
|
958
1780
|
}
|
|
959
1781
|
|
|
960
|
-
|
|
1782
|
+
/**
|
|
1783
|
+
* Comptoir status spectrum — the canonical set of chip tones every
|
|
1784
|
+
* status reference can map to via `metadata.color`.
|
|
1785
|
+
*
|
|
1786
|
+
* Tenants customize their status palettes by writing one of these
|
|
1787
|
+
* values into `reference_data.metadata.color` for each entry. The
|
|
1788
|
+
* elastic-portal admin (when ready) picks from this same enum, so
|
|
1789
|
+
* the framework stays tenant-agnostic and the data layer is the
|
|
1790
|
+
* only knob that needs to change per tenant.
|
|
1791
|
+
*/
|
|
1792
|
+
type EfStatusColor = 'pending' | 'processing' | 'shipped' | 'delivered' | 'cancelled' | 'refunded' | 'onhold' | 'tenant' | 'module' | 'neutral';
|
|
1793
|
+
/**
|
|
1794
|
+
* Shape `ef-status-chip` expects when reading from a reference
|
|
1795
|
+
* dictionary. Mirrors the `reference_data` MongoDB collection in
|
|
1796
|
+
* ElasticERP — apps can pass any object with these fields.
|
|
1797
|
+
*/
|
|
1798
|
+
interface EfStatusReferenceItem {
|
|
1799
|
+
code: string;
|
|
961
1800
|
label?: string;
|
|
962
1801
|
labelKey?: string;
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
1802
|
+
metadata?: {
|
|
1803
|
+
color?: EfStatusColor | string;
|
|
1804
|
+
icon?: string;
|
|
1805
|
+
[key: string]: unknown;
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
/** Canonical tone list — used for membership checks by the resolver. */
|
|
1809
|
+
declare const EF_STATUS_COLORS: ReadonlyArray<EfStatusColor>;
|
|
1810
|
+
/**
|
|
1811
|
+
* Generic color-name aliases → Comptoir tones. Seeded `reference_data`
|
|
1812
|
+
* commonly stores plain color names in `metadata.color` (e.g.
|
|
1813
|
+
* `sales_order_status`: Draft=gray, Completed=green, Cancelled=red).
|
|
1814
|
+
* Resolving them here keeps chips AND status-keyed charts on the same
|
|
1815
|
+
* `--st-*` tokens without migrating tenant data.
|
|
1816
|
+
*/
|
|
1817
|
+
declare const EF_STATUS_COLOR_ALIASES: Readonly<Record<string, EfStatusColor>>;
|
|
1818
|
+
/**
|
|
1819
|
+
* Resolve a `metadata.color` value — a canonical tone OR a generic
|
|
1820
|
+
* color-name alias — to its Comptoir tone. `undefined` when unknown,
|
|
1821
|
+
* so callers can chain fallbacks (e.g. the status code itself, then
|
|
1822
|
+
* `'neutral'`). Case-insensitive.
|
|
1823
|
+
*/
|
|
1824
|
+
declare function resolveEfStatusColor(value: string | null | undefined): EfStatusColor | undefined;
|
|
1825
|
+
|
|
1826
|
+
/**
|
|
1827
|
+
* Comptoir status chip — single source of truth for any kind of
|
|
1828
|
+
* status / pill across the app.
|
|
1829
|
+
*
|
|
1830
|
+
* Resolves the chip's tone + label from the `reference_data`
|
|
1831
|
+
* collection so each tenant can re-skin its status palette without
|
|
1832
|
+
* touching consumer code:
|
|
1833
|
+
*
|
|
1834
|
+
* 1. Look up `referenceKey` in `SCREEN_REF_DATA_SERVICE`.
|
|
1835
|
+
* 2. Find the entry whose `code` matches the `code` input.
|
|
1836
|
+
* 3. Use `metadata.color` for the chip class and `label` /
|
|
1837
|
+
* `labelKey` for the text.
|
|
1838
|
+
* 4. Fall back to the `code` itself (lowercased) when no reference
|
|
1839
|
+
* data is registered — this lets screens render meaningfully even
|
|
1840
|
+
* before the real `ReferenceDataService` is wired.
|
|
1841
|
+
*
|
|
1842
|
+
* ```html
|
|
1843
|
+
* <ef-status-chip
|
|
1844
|
+
* referenceKey="sales_order_status"
|
|
1845
|
+
* [code]="row.status"
|
|
1846
|
+
* />
|
|
1847
|
+
* ```
|
|
1848
|
+
*
|
|
1849
|
+
* Override knobs (escape hatches):
|
|
1850
|
+
* - `[color]` forces a specific Comptoir tone, ignoring metadata.
|
|
1851
|
+
* - `[label]` / `[labelKey]` force the text, ignoring reference data.
|
|
1852
|
+
* - `[hideDot]` removes the leading ● glyph.
|
|
1853
|
+
* - `[showCode]` displays the raw code (useful for admin screens).
|
|
1854
|
+
*/
|
|
1855
|
+
declare class EfStatusChipComponent {
|
|
1856
|
+
private readonly refDataService;
|
|
1857
|
+
/** Reference key (e.g. `'sales_order_status'`). */
|
|
1858
|
+
readonly referenceKey: _angular_core.InputSignal<string>;
|
|
1859
|
+
/** Entry code to look up (e.g. `'Pending'`). */
|
|
1860
|
+
readonly code: _angular_core.InputSignal<string>;
|
|
1861
|
+
/** Force a specific Comptoir tone (overrides metadata.color). */
|
|
1862
|
+
readonly color: _angular_core.InputSignal<"" | EfStatusColor>;
|
|
1863
|
+
/** Force the displayed label (skips reference lookup). */
|
|
1864
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
1865
|
+
/** Translation key — preferred when forcing a label. */
|
|
1866
|
+
readonly labelKey: _angular_core.InputSignal<string>;
|
|
1867
|
+
/** Hide the leading ● dot. */
|
|
1868
|
+
readonly hideDot: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1869
|
+
/** Render the raw `code` after the label (admin-screen helper). */
|
|
1870
|
+
readonly showCode: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1871
|
+
/** The reference entry matching `code`, or `undefined`. */
|
|
1872
|
+
private readonly entry;
|
|
1873
|
+
/** Chip tone — explicit override → metadata (canonical tone or
|
|
1874
|
+
* generic color-name alias, e.g. `green` → `delivered`) → code
|
|
1875
|
+
* fallback → `neutral`. */
|
|
1876
|
+
readonly resolvedColor: _angular_core.Signal<EfStatusColor>;
|
|
1877
|
+
/** Resolved label — labelKey input → label input → reference label → code. */
|
|
1878
|
+
readonly resolvedLabel: _angular_core.Signal<string>;
|
|
1879
|
+
/** Translation key returned for the template's translate pipe. */
|
|
1880
|
+
readonly resolvedLabelKey: _angular_core.Signal<string>;
|
|
1881
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfStatusChipComponent, never>;
|
|
1882
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfStatusChipComponent, "ef-status-chip", never, { "referenceKey": { "alias": "referenceKey"; "required": false; "isSignal": true; }; "code": { "alias": "code"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelKey": { "alias": "labelKey"; "required": false; "isSignal": true; }; "hideDot": { "alias": "hideDot"; "required": false; "isSignal": true; }; "showCode": { "alias": "showCode"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
/**
|
|
1886
|
+
* Available anchor positions for the toast region.
|
|
1887
|
+
*/
|
|
1888
|
+
type EfToastRegionPosition = 'top-right' | 'top-left' | 'top-center' | 'bottom-right' | 'bottom-left' | 'bottom-center';
|
|
1889
|
+
/**
|
|
1890
|
+
* Comptoir toast region — V2 successor to PrimeNG `<p-toast>`.
|
|
1891
|
+
*
|
|
1892
|
+
* Mounts once at the app root (or any layout shell) and renders the
|
|
1893
|
+
* live `EfToastService.toasts` queue. Auto-dismiss timers + manual
|
|
1894
|
+
* close button + optional inline action buttons. Severity styling
|
|
1895
|
+
* comes from the `.toast.<severity>` rules in `_patterns.scss`,
|
|
1896
|
+
* mapped 1:1 to the Comptoir status spectrum.
|
|
1897
|
+
*
|
|
1898
|
+
* ```html
|
|
1899
|
+
* <!-- App root -->
|
|
1900
|
+
* <ef-toast-region position="bottom-right" />
|
|
1901
|
+
* ```
|
|
1902
|
+
*/
|
|
1903
|
+
declare class EfToastRegionComponent {
|
|
1904
|
+
private readonly toastService;
|
|
1905
|
+
private readonly destroyRef;
|
|
1906
|
+
/** Anchor position. Default: bottom-right. */
|
|
1907
|
+
readonly position: _angular_core.InputSignal<EfToastRegionPosition>;
|
|
1908
|
+
/** Cap the visible stack — older toasts get auto-dismissed. */
|
|
1909
|
+
readonly maxStack: _angular_core.InputSignal<number>;
|
|
1910
|
+
/** Hide the bottom progress bar across all toasts. */
|
|
1911
|
+
readonly hideProgress: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1912
|
+
/** Toasts currently mid-exit-animation (kept around for the
|
|
1913
|
+
* duration of the CSS transition before being removed from DOM). */
|
|
1914
|
+
readonly exiting: _angular_core.WritableSignal<ReadonlySet<number>>;
|
|
1915
|
+
/** Live queue from the service — direct read so the template
|
|
1916
|
+
* re-renders when a toast is pushed or dismissed. */
|
|
1917
|
+
readonly toasts: _angular_core.WritableSignal<readonly EfToast[]>;
|
|
1918
|
+
/** Per-toast lifespan timers (manual setTimeout — robust against
|
|
1919
|
+
* Angular zoneless mode and visible across HMR reloads). */
|
|
1920
|
+
private readonly timers;
|
|
1921
|
+
constructor();
|
|
1922
|
+
severityClass(t: EfToast): string;
|
|
1923
|
+
iconClass(t: EfToast): string;
|
|
1924
|
+
progressStyle(t: EfToast): {
|
|
1925
|
+
[k: string]: string;
|
|
1926
|
+
} | null;
|
|
1927
|
+
onClose(t: EfToast): void;
|
|
1928
|
+
onActionClick(t: EfToast, action: EfToastAction): void;
|
|
1929
|
+
trackById: (_: number, t: EfToast) => number;
|
|
1930
|
+
private syncTimers;
|
|
1931
|
+
private enforceMaxStack;
|
|
1932
|
+
/** Mark the toast as exiting → wait for the CSS animation → tell
|
|
1933
|
+
* the service to remove it. Keeps the DOM around for the
|
|
1934
|
+
* out-animation duration. */
|
|
1935
|
+
private beginExit;
|
|
1936
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfToastRegionComponent, never>;
|
|
1937
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfToastRegionComponent, "ef-toast-region", never, { "position": { "alias": "position"; "required": false; "isSignal": true; }; "maxStack": { "alias": "maxStack"; "required": false; "isSignal": true; }; "hideProgress": { "alias": "hideProgress"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
/** Shape of the placeholder rendered while a widget's data is in flight. */
|
|
1941
|
+
type EfSkeletonVariant = 'text' | 'kpi' | 'chart' | 'table';
|
|
1942
|
+
/**
|
|
1943
|
+
* Comptoir loading skeleton — the one reusable "waiting for results"
|
|
1944
|
+
* placeholder for async card/widget bodies (dashboards, reports,
|
|
1945
|
+
* detail sidebars). Pure CSS shimmer on the design-system tokens;
|
|
1946
|
+
* decorative only (`aria-hidden`), so hosts flag busyness themselves
|
|
1947
|
+
* (`ef-card` sets `aria-busy` on its body when `[loading]` is true).
|
|
1948
|
+
*
|
|
1949
|
+
* Prefer injecting it through `ef-card`'s `[loading]` + `skeleton`
|
|
1950
|
+
* inputs — the card swaps its body for the skeleton with a single
|
|
1951
|
+
* binding. Use the component directly only for non-card shells
|
|
1952
|
+
* (e.g. a KPI tile row):
|
|
1953
|
+
*
|
|
1954
|
+
* ```html
|
|
1955
|
+
* <ef-card titleKey="…" [loading]="state() === 'loading'" skeleton="chart">…</ef-card>
|
|
1956
|
+
* <ef-skeleton class="kpi" variant="kpi" />
|
|
1957
|
+
* ```
|
|
1958
|
+
*
|
|
1959
|
+
* Variants: `text` (default, `rows` lines), `kpi` (label / value /
|
|
1960
|
+
* delta bars), `chart` (one block, `height` px), `table` (header bar
|
|
1961
|
+
* + `rows` row bars).
|
|
1962
|
+
*/
|
|
1963
|
+
declare class EfSkeletonComponent {
|
|
1964
|
+
/** Placeholder shape. */
|
|
1965
|
+
readonly variant: _angular_core.InputSignal<EfSkeletonVariant>;
|
|
1966
|
+
/** Line/row count for the `text` and `table` variants. */
|
|
1967
|
+
readonly rows: _angular_core.InputSignal<number>;
|
|
1968
|
+
/** Block height (px) for the `chart` variant. */
|
|
1969
|
+
readonly height: _angular_core.InputSignal<number>;
|
|
1970
|
+
readonly lines: _angular_core.Signal<number[]>;
|
|
1971
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfSkeletonComponent, never>;
|
|
1972
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfSkeletonComponent, "ef-skeleton", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
/**
|
|
1976
|
+
* Comptoir card primitive — `.card` shell with optional `.card-head`,
|
|
1977
|
+
* `.card-body`, `.card-foot`. Phase 7's most reused container.
|
|
1978
|
+
*
|
|
1979
|
+
* Three projection slots:
|
|
1980
|
+
* `head-extra` — projected on the right of the head row, after the
|
|
1981
|
+
* built-in title/meta. Use for a status chip,
|
|
1982
|
+
* action button, kbd hint, etc.
|
|
1983
|
+
* default — body content (replaced by the reusable
|
|
1984
|
+
* `ef-skeleton` while `[loading]` is true).
|
|
1985
|
+
* `foot` — bottom strip with rule-soft separator + paper bg.
|
|
1986
|
+
*
|
|
1987
|
+
* ```html
|
|
1988
|
+
* <ef-card titleKey="orders_status" [tone]="'module'">
|
|
1989
|
+
* <ng-container head-extra>
|
|
1990
|
+
* <ef-status-chip referenceKey="sales_order_status" [code]="status" />
|
|
1991
|
+
* </ng-container>
|
|
1992
|
+
* <div>… body content …</div>
|
|
1993
|
+
* <div foot>
|
|
1994
|
+
* <span class="small text-mute">Modifié il y a 2 min</span>
|
|
1995
|
+
* </div>
|
|
1996
|
+
* </ef-card>
|
|
1997
|
+
* ```
|
|
1998
|
+
*/
|
|
1999
|
+
declare class EfCardComponent {
|
|
2000
|
+
/** Translation key for the head title — preferred. */
|
|
2001
|
+
readonly titleKey: _angular_core.InputSignal<string>;
|
|
2002
|
+
/** Direct title fallback when `titleKey` is empty. */
|
|
2003
|
+
readonly title: _angular_core.InputSignal<string>;
|
|
2004
|
+
/** Translation key for the head's small meta line. */
|
|
2005
|
+
readonly metaKey: _angular_core.InputSignal<string>;
|
|
2006
|
+
readonly meta: _angular_core.InputSignal<string>;
|
|
2007
|
+
/** Module-tinted head — uses `var(--module)` for the head bg. */
|
|
2008
|
+
readonly tone: _angular_core.InputSignal<"default" | "module">;
|
|
2009
|
+
/** Force the head to render even when no title/meta (e.g. when
|
|
2010
|
+
* using only the head-extra slot). Defaults to auto-detect. */
|
|
2011
|
+
readonly forceHead: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2012
|
+
/** Render the foot strip — set when projecting `[foot]` content. */
|
|
2013
|
+
readonly hasFoot: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2014
|
+
/** When true, the head shows a chevron toggle and the body/foot collapse. */
|
|
2015
|
+
readonly collapsible: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2016
|
+
/** Let overlay content (custom dropdowns/menus rendered inside the body)
|
|
2017
|
+
* escape the card's `overflow: hidden`. PrimeNG overlays should prefer
|
|
2018
|
+
* `appendTo="body"`; use this for non-PrimeNG absolute-positioned menus. */
|
|
2019
|
+
readonly overflowVisible: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2020
|
+
/** While true, the body renders the reusable `ef-skeleton` instead of
|
|
2021
|
+
* the projected content (and flags `aria-busy`). Bind each card's own
|
|
2022
|
+
* async state so widgets shimmer independently:
|
|
2023
|
+
* `[loading]="state().series === 'loading'"`. */
|
|
2024
|
+
readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2025
|
+
/** Skeleton shape shown while `loading` — match the body content. */
|
|
2026
|
+
readonly skeleton: _angular_core.InputSignal<EfSkeletonVariant>;
|
|
2027
|
+
/** Line/row count for the `text` / `table` skeleton variants. */
|
|
2028
|
+
readonly skeletonRows: _angular_core.InputSignal<number>;
|
|
2029
|
+
/** Block height (px) for the `chart` skeleton variant. */
|
|
2030
|
+
readonly skeletonHeight: _angular_core.InputSignal<number>;
|
|
2031
|
+
/** Collapsed state (two-way). Bind `[collapsed]="true"` to start collapsed. */
|
|
2032
|
+
readonly collapsed: _angular_core.ModelSignal<boolean>;
|
|
2033
|
+
readonly showHead: _angular_core.Signal<boolean>;
|
|
2034
|
+
readonly showFoot: _angular_core.Signal<boolean>;
|
|
2035
|
+
/** Toggle collapsed state (no-op when not collapsible). */
|
|
2036
|
+
toggle(): void;
|
|
2037
|
+
/** Clicking anywhere on a collapsible head (except the actions area, which
|
|
2038
|
+
* stops propagation) toggles the card. */
|
|
2039
|
+
onHeadClick(): void;
|
|
2040
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfCardComponent, never>;
|
|
2041
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfCardComponent, "ef-card", never, { "titleKey": { "alias": "titleKey"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "metaKey": { "alias": "metaKey"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "forceHead": { "alias": "forceHead"; "required": false; "isSignal": true; }; "hasFoot": { "alias": "hasFoot"; "required": false; "isSignal": true; }; "collapsible": { "alias": "collapsible"; "required": false; "isSignal": true; }; "overflowVisible": { "alias": "overflowVisible"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "skeleton": { "alias": "skeleton"; "required": false; "isSignal": true; }; "skeletonRows": { "alias": "skeletonRows"; "required": false; "isSignal": true; }; "skeletonHeight": { "alias": "skeletonHeight"; "required": false; "isSignal": true; }; "collapsed": { "alias": "collapsed"; "required": false; "isSignal": true; }; }, { "collapsed": "collapsedChange"; }, never, ["[head-extra]", "*", "[foot]"], true, never>;
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
/**
|
|
2045
|
+
* 12-column form-grid primitive. Children use `.col-2/3/4/6/8/9/12`
|
|
2046
|
+
* to claim spans; on viewports < 720px every span collapses to 12.
|
|
2047
|
+
*
|
|
2048
|
+
* ```html
|
|
2049
|
+
* <ef-form-grid>
|
|
2050
|
+
* <div class="col-6 ef-field">
|
|
2051
|
+
* <label>Client</label>
|
|
2052
|
+
* <ef-select … />
|
|
2053
|
+
* </div>
|
|
2054
|
+
* <div class="col-3 ef-field">
|
|
2055
|
+
* <label>Date</label>
|
|
2056
|
+
* <ef-datepicker … />
|
|
2057
|
+
* </div>
|
|
2058
|
+
* <div class="col-3 ef-field">
|
|
2059
|
+
* <label>Total</label>
|
|
2060
|
+
* <span class="read strong">12 350,00 MAD</span>
|
|
2061
|
+
* </div>
|
|
2062
|
+
* </ef-form-grid>
|
|
2063
|
+
* ```
|
|
2064
|
+
*/
|
|
2065
|
+
declare class EfFormGridComponent {
|
|
2066
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfFormGridComponent, never>;
|
|
2067
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfFormGridComponent, "ef-form-grid", never, {}, {}, never, ["*"], true, never>;
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
/**
|
|
2071
|
+
* Sticky detail-screen toolbar. Two slots and an optional declarative
|
|
2072
|
+
* action API:
|
|
2073
|
+
*
|
|
2074
|
+
* - default — entity identity (ref / name / status chip / meta).
|
|
2075
|
+
* - `[customActions]` input — declarative array of EfDetailToolbarAction;
|
|
2076
|
+
* rendered at the start of the right group,
|
|
2077
|
+
* before the standard actions.
|
|
2078
|
+
* - `[actions]` slot — full-template escape hatch (rendered after
|
|
2079
|
+
* `[customActions]`, before the separator).
|
|
2080
|
+
* - Standard actions — Print, Duplicate, Delete, Save (in that order),
|
|
2081
|
+
* shown via `[showPrintAction]` / `[showDuplicateAction]`
|
|
2082
|
+
* / `[showDeleteAction]` / `[showSaveAction]` and
|
|
2083
|
+
* gated by `[context]`'s permissions.
|
|
2084
|
+
*
|
|
2085
|
+
* Layout: `…identity (left) | …customActions [actions] | print duplicate delete save…`
|
|
2086
|
+
*
|
|
2087
|
+
* ```html
|
|
2088
|
+
* <ef-detail-toolbar
|
|
2089
|
+
* [customActions]="screenActions()"
|
|
2090
|
+
* [context]="context"
|
|
2091
|
+
* [showPrintAction]="editionState()"
|
|
2092
|
+
* [showDuplicateAction]="editionState()"
|
|
2093
|
+
* [showDeleteAction]="editionState()"
|
|
2094
|
+
* [saving]="loading()"
|
|
2095
|
+
* [saveLabelKey]="editionState() ? 'common_save' : 'common_create'"
|
|
2096
|
+
* (print)="print()"
|
|
2097
|
+
* (duplicate)="duplicate()"
|
|
2098
|
+
* (delete)="delete()"
|
|
2099
|
+
* (save)="save()"
|
|
2100
|
+
* >
|
|
2101
|
+
* <span class="ref">{{ ref() }}</span>
|
|
2102
|
+
* <ef-status-chip referenceKey="…" [code]="status()" />
|
|
2103
|
+
* </ef-detail-toolbar>
|
|
2104
|
+
* ```
|
|
2105
|
+
*
|
|
2106
|
+
* Custom actions can declare `permission` and `visible` like
|
|
2107
|
+
* `EfRowAction`. With `[context]` bound, the toolbar filters them
|
|
2108
|
+
* against `ScreenContext.isGranted()` automatically.
|
|
2109
|
+
*/
|
|
2110
|
+
declare class EfDetailToolbarComponent {
|
|
2111
|
+
/** Custom screen-specific actions, rendered before the standard
|
|
2112
|
+
* set in the right group. Each one gets the same permission /
|
|
2113
|
+
* visibility filtering used by EfRowAction. */
|
|
2114
|
+
readonly customActions: _angular_core.InputSignal<readonly EfDetailToolbarAction[]>;
|
|
2115
|
+
/** Optional ScreenContext — when present, custom actions with a
|
|
2116
|
+
* `permission` field and standard actions Print / Duplicate /
|
|
2117
|
+
* Delete are filtered against `context.isGranted(...)`. */
|
|
2118
|
+
readonly context: _angular_core.InputSignal<ScreenContext>;
|
|
2119
|
+
/** Render the standard Print action (left of the standard group). */
|
|
2120
|
+
readonly showPrintAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2121
|
+
/** Render the standard Duplicate action. */
|
|
2122
|
+
readonly showDuplicateAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2123
|
+
/** Render the standard Delete action (danger-tinted). */
|
|
2124
|
+
readonly showDeleteAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2125
|
+
/** Render the standard Save action (rightmost, tenant-styled). */
|
|
2126
|
+
readonly showSaveAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2127
|
+
/** Disable Save while a save round-trip is in flight. */
|
|
2128
|
+
readonly saving: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2129
|
+
/** i18n key for the Save button label. Screens typically pass
|
|
2130
|
+
* `'common_create'` in create mode and `'common_save'` in edit. */
|
|
2131
|
+
readonly saveLabelKey: _angular_core.InputSignal<string>;
|
|
2132
|
+
/** Fired when a `customActions` button is clicked. The toast
|
|
2133
|
+
* service or screen handler should consume `id`. The `command`
|
|
2134
|
+
* callback on the action is also invoked. */
|
|
2135
|
+
readonly customAction: _angular_core.OutputEmitterRef<EfDetailToolbarAction>;
|
|
2136
|
+
readonly print: _angular_core.OutputEmitterRef<void>;
|
|
2137
|
+
readonly duplicate: _angular_core.OutputEmitterRef<void>;
|
|
2138
|
+
readonly delete: _angular_core.OutputEmitterRef<void>;
|
|
2139
|
+
readonly save: _angular_core.OutputEmitterRef<void>;
|
|
2140
|
+
/** Custom actions after permission + `visible` filtering. */
|
|
2141
|
+
readonly visibleCustomActions: _angular_core.Signal<readonly EfDetailToolbarAction[]>;
|
|
2142
|
+
readonly canPrint: _angular_core.Signal<boolean>;
|
|
2143
|
+
readonly canDuplicate: _angular_core.Signal<boolean>;
|
|
2144
|
+
readonly canDelete: _angular_core.Signal<boolean>;
|
|
2145
|
+
readonly canSave: _angular_core.Signal<boolean>;
|
|
2146
|
+
readonly hasStandardActions: _angular_core.Signal<boolean>;
|
|
2147
|
+
readonly hasCustomActions: _angular_core.Signal<boolean>;
|
|
2148
|
+
/** Whether the `|` separator should render — both groups present. */
|
|
2149
|
+
readonly showSeparator: _angular_core.Signal<boolean>;
|
|
2150
|
+
onCustomClick(action: EfDetailToolbarAction): void;
|
|
2151
|
+
private isCustomVisible;
|
|
2152
|
+
/** Standard action visibility: `show*Action` flag AND permission
|
|
2153
|
+
* granted by `context` (or no context bound). */
|
|
2154
|
+
private checkStandard;
|
|
2155
|
+
/** Stable trackBy across renders. */
|
|
2156
|
+
trackByAction: (i: number, a: EfDetailToolbarAction) => unknown;
|
|
2157
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfDetailToolbarComponent, never>;
|
|
2158
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfDetailToolbarComponent, "ef-detail-toolbar", never, { "customActions": { "alias": "customActions"; "required": false; "isSignal": true; }; "context": { "alias": "context"; "required": false; "isSignal": true; }; "showPrintAction": { "alias": "showPrintAction"; "required": false; "isSignal": true; }; "showDuplicateAction": { "alias": "showDuplicateAction"; "required": false; "isSignal": true; }; "showDeleteAction": { "alias": "showDeleteAction"; "required": false; "isSignal": true; }; "showSaveAction": { "alias": "showSaveAction"; "required": false; "isSignal": true; }; "saving": { "alias": "saving"; "required": false; "isSignal": true; }; "saveLabelKey": { "alias": "saveLabelKey"; "required": false; "isSignal": true; }; }, { "customAction": "customAction"; "print": "print"; "duplicate": "duplicate"; "delete": "delete"; "save": "save"; }, never, ["*", "[actions]"], true, never>;
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
/**
|
|
2162
|
+
* Page-level toolbar for list / search screens. Mirrors the
|
|
2163
|
+
* {@link EfDetailToolbarComponent} concept — two slots and a
|
|
2164
|
+
* declarative action API — but ships with the search-screen
|
|
2165
|
+
* default actions instead of the detail-screen ones.
|
|
2166
|
+
*
|
|
2167
|
+
* - default — page identity (title / meta / status pills).
|
|
2168
|
+
* - `[customActions]` input — declarative array of
|
|
2169
|
+
* EfSearchToolbarAction; rendered at the
|
|
2170
|
+
* start of the right group, before the
|
|
2171
|
+
* standard actions.
|
|
2172
|
+
* - `[actions]` slot — full-template escape hatch (rendered after
|
|
2173
|
+
* `[customActions]`, before the separator).
|
|
2174
|
+
* - Standard actions — Export, Add (in that order), shown via
|
|
2175
|
+
* `[showExportAction]` / `[showAddAction]` and
|
|
2176
|
+
* gated by `[context]`'s permissions.
|
|
2177
|
+
*
|
|
2178
|
+
* Search / Clear deliberately do **not** live here — those belong
|
|
2179
|
+
* to `ef-smart-bar` (its built-in `(search)` / `(clear)` outputs).
|
|
2180
|
+
* This toolbar owns the page-level actions, not the filter actions.
|
|
2181
|
+
*
|
|
2182
|
+
* Layout: `…title (left) | …customActions [actions] | export add`
|
|
2183
|
+
*
|
|
2184
|
+
* ```html
|
|
2185
|
+
* <ef-search-toolbar
|
|
2186
|
+
* [context]="context"
|
|
2187
|
+
* [customActions]="screenActions()"
|
|
2188
|
+
* showExportAction
|
|
2189
|
+
* (export)="exportItems()"
|
|
2190
|
+
* (add)="add()"
|
|
2191
|
+
* >
|
|
2192
|
+
* <div class="title-meta">
|
|
2193
|
+
* <h1>{{ 'catalog_products_title' | translate }}</h1>
|
|
2194
|
+
* <p class="meta">{{ totalCount() }} items</p>
|
|
2195
|
+
* </div>
|
|
2196
|
+
* </ef-search-toolbar>
|
|
2197
|
+
* ```
|
|
2198
|
+
*
|
|
2199
|
+
* Custom actions can declare `permission` and `visible` like
|
|
2200
|
+
* `EfRowAction`. With `[context]` bound, the toolbar filters them
|
|
2201
|
+
* against `ScreenContext.isGranted()` automatically.
|
|
2202
|
+
*/
|
|
2203
|
+
declare class EfSearchToolbarComponent {
|
|
2204
|
+
/** Custom screen-specific actions, rendered before the standard
|
|
2205
|
+
* set in the right group. Each one gets the same permission /
|
|
2206
|
+
* visibility filtering used by EfRowAction. */
|
|
2207
|
+
readonly customActions: _angular_core.InputSignal<readonly _elasticias_screens.EfDetailToolbarAction[]>;
|
|
2208
|
+
/** Optional ScreenContext — when present, custom actions with a
|
|
2209
|
+
* `permission` field and standard actions Export / Add are
|
|
2210
|
+
* filtered against `context.isGranted(...)`. */
|
|
2211
|
+
readonly context: _angular_core.InputSignal<ScreenContext>;
|
|
2212
|
+
/** Render the standard Export action (left of the standard group). */
|
|
2213
|
+
readonly showExportAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2214
|
+
/** Render the standard Add action (rightmost, tenant-styled). */
|
|
2215
|
+
readonly showAddAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2216
|
+
/** Disable Add while a navigation / fetch is in flight. */
|
|
2217
|
+
readonly busy: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2218
|
+
/** i18n key for the Add button label. Screens typically pass
|
|
2219
|
+
* `'common_new'` (default) or a screen-specific
|
|
2220
|
+
* `'catalog_products_new'`. */
|
|
2221
|
+
readonly addLabelKey: _angular_core.InputSignal<string>;
|
|
2222
|
+
/** i18n key for the Export button label. */
|
|
2223
|
+
readonly exportLabelKey: _angular_core.InputSignal<string>;
|
|
2224
|
+
/** Fired when a `customActions` button is clicked. The toast
|
|
2225
|
+
* service or screen handler should consume `id`. The `command`
|
|
2226
|
+
* callback on the action is also invoked. */
|
|
2227
|
+
readonly customAction: _angular_core.OutputEmitterRef<_elasticias_screens.EfDetailToolbarAction>;
|
|
2228
|
+
readonly export: _angular_core.OutputEmitterRef<void>;
|
|
2229
|
+
readonly add: _angular_core.OutputEmitterRef<void>;
|
|
2230
|
+
/** Custom actions after permission + `visible` filtering. */
|
|
2231
|
+
readonly visibleCustomActions: _angular_core.Signal<readonly _elasticias_screens.EfDetailToolbarAction[]>;
|
|
2232
|
+
readonly canExport: _angular_core.Signal<boolean>;
|
|
2233
|
+
readonly canAdd: _angular_core.Signal<boolean>;
|
|
2234
|
+
readonly hasStandardActions: _angular_core.Signal<boolean>;
|
|
2235
|
+
readonly hasCustomActions: _angular_core.Signal<boolean>;
|
|
2236
|
+
/** Whether the `|` separator should render — both groups present. */
|
|
2237
|
+
readonly showSeparator: _angular_core.Signal<boolean>;
|
|
2238
|
+
onCustomClick(action: EfSearchToolbarAction): void;
|
|
2239
|
+
private isCustomVisible;
|
|
2240
|
+
/** Standard action visibility: `show*Action` flag AND permission
|
|
2241
|
+
* granted by `context` (or no context bound). */
|
|
2242
|
+
private checkStandard;
|
|
2243
|
+
/** Stable trackBy across renders. */
|
|
2244
|
+
trackByAction: (i: number, a: EfSearchToolbarAction) => unknown;
|
|
2245
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfSearchToolbarComponent, never>;
|
|
2246
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfSearchToolbarComponent, "ef-search-toolbar", never, { "customActions": { "alias": "customActions"; "required": false; "isSignal": true; }; "context": { "alias": "context"; "required": false; "isSignal": true; }; "showExportAction": { "alias": "showExportAction"; "required": false; "isSignal": true; }; "showAddAction": { "alias": "showAddAction"; "required": false; "isSignal": true; }; "busy": { "alias": "busy"; "required": false; "isSignal": true; }; "addLabelKey": { "alias": "addLabelKey"; "required": false; "isSignal": true; }; "exportLabelKey": { "alias": "exportLabelKey"; "required": false; "isSignal": true; }; }, { "customAction": "customAction"; "export": "export"; "add": "add"; }, never, ["*", "[actions]"], true, never>;
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
/**
|
|
2250
|
+
* One key-value row in the totals stack.
|
|
2251
|
+
*/
|
|
2252
|
+
interface EfTotalsRow {
|
|
2253
|
+
/** Translation key for the row label — preferred. */
|
|
2254
|
+
labelKey?: string;
|
|
2255
|
+
/** Direct label fallback when `labelKey` is empty. */
|
|
2256
|
+
label?: string;
|
|
2257
|
+
/** Pre-formatted value text (e.g. `'12 350,00'`). */
|
|
2258
|
+
value: string | number;
|
|
2259
|
+
/** Optional small unit text right of the value (e.g. `'MAD'`). */
|
|
2260
|
+
unit?: string;
|
|
2261
|
+
/** `'discount'` paints the value in `--st-pending-fg`. */
|
|
2262
|
+
tone?: 'default' | 'discount';
|
|
2263
|
+
}
|
|
2264
|
+
/**
|
|
2265
|
+
* Display-size grand row (Bricolage 28px) shown after a divider.
|
|
2266
|
+
* Same shape as a regular row but rendered with the `.grand-row` class.
|
|
2267
|
+
*/
|
|
2268
|
+
interface EfTotalsGrand {
|
|
2269
|
+
labelKey?: string;
|
|
2270
|
+
label?: string;
|
|
2271
|
+
value: string | number;
|
|
2272
|
+
/** Currency / unit suffix shown smaller after the big number. */
|
|
2273
|
+
currency?: string;
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2276
|
+
/**
|
|
2277
|
+
* Sidebar totals stack — key-value rows with optional display-size
|
|
2278
|
+
* grand-row (Bricolage Grotesque, ~28px). Lives inside an `<ef-card>`
|
|
2279
|
+
* on order / invoice / quote detail screens.
|
|
2280
|
+
*
|
|
2281
|
+
* ```html
|
|
2282
|
+
* <ef-card titleKey="orders_totals">
|
|
2283
|
+
* <ef-totals
|
|
2284
|
+
* [rows]="[
|
|
2285
|
+
* { labelKey: 'totals_subtotal', value: '12 350,00', unit: 'MAD' },
|
|
2286
|
+
* { labelKey: 'totals_discount', value: '-450,00', unit: 'MAD', tone: 'discount' },
|
|
2287
|
+
* { labelKey: 'totals_tax', value: '2 372,40', unit: 'MAD' },
|
|
2288
|
+
* ]"
|
|
2289
|
+
* [grand]="{ labelKey: 'totals_grand', value: '14 272,40', currency: 'MAD' }"
|
|
2290
|
+
* />
|
|
2291
|
+
* </ef-card>
|
|
2292
|
+
* ```
|
|
2293
|
+
*/
|
|
2294
|
+
declare class EfTotalsComponent {
|
|
2295
|
+
readonly rows: _angular_core.InputSignal<readonly EfTotalsRow[]>;
|
|
2296
|
+
readonly grand: _angular_core.InputSignal<EfTotalsGrand>;
|
|
2297
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfTotalsComponent, never>;
|
|
2298
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfTotalsComponent, "ef-totals", never, { "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "grand": { "alias": "grand"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
/**
|
|
2302
|
+
* One row in the stats stack — a label/value pair with optional unit
|
|
2303
|
+
* and an optional `big` flag that swaps the value to a Bricolage
|
|
2304
|
+
* display number (~22px).
|
|
2305
|
+
*/
|
|
2306
|
+
interface EfStatsRow {
|
|
2307
|
+
labelKey?: string;
|
|
2308
|
+
label?: string;
|
|
2309
|
+
value: string | number;
|
|
2310
|
+
/** Small grey unit shown right of the value (e.g. `'MAD'`, `'cmds'`). */
|
|
2311
|
+
unit?: string;
|
|
2312
|
+
/** Render the value as a Bricolage display number. Used for the
|
|
2313
|
+
* one or two headline metrics in a sidebar stats card. */
|
|
2314
|
+
big?: boolean;
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
/**
|
|
2318
|
+
* Sidebar mini-KPI stack. Lives inside an `<ef-card>` on detail
|
|
2319
|
+
* screens; rule-soft separators between rows, optional `.big` row
|
|
2320
|
+
* swaps the value to a Bricolage display number.
|
|
2321
|
+
*
|
|
2322
|
+
* ```html
|
|
2323
|
+
* <ef-card titleKey="clients_stats">
|
|
2324
|
+
* <ef-stats
|
|
2325
|
+
* [rows]="[
|
|
2326
|
+
* { labelKey: 'stats_revenue_ytd', value: '128 450', unit: 'MAD', big: true },
|
|
2327
|
+
* { labelKey: 'stats_orders_count', value: 42 },
|
|
2328
|
+
* { labelKey: 'stats_last_order', value: 'Il y a 3 jours' },
|
|
2329
|
+
* ]"
|
|
2330
|
+
* />
|
|
2331
|
+
* </ef-card>
|
|
2332
|
+
* ```
|
|
2333
|
+
*
|
|
2334
|
+
* Stats are sidebar-only — never on list/search screens (KPIs there
|
|
2335
|
+
* are forbidden, see CLAUDE.md memory).
|
|
2336
|
+
*/
|
|
2337
|
+
declare class EfStatsComponent {
|
|
2338
|
+
readonly rows: _angular_core.InputSignal<readonly EfStatsRow[]>;
|
|
2339
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfStatsComponent, never>;
|
|
2340
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfStatsComponent, "ef-stats", never, { "rows": { "alias": "rows"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
type EfTimelineState = 'done' | 'now' | 'upcoming';
|
|
2344
|
+
/**
|
|
2345
|
+
* One step in a vertical timeline.
|
|
2346
|
+
*/
|
|
2347
|
+
interface EfTimelineItem {
|
|
2348
|
+
/** Stable id for trackBy / template references. */
|
|
2349
|
+
id?: string | number;
|
|
2350
|
+
labelKey?: string;
|
|
2351
|
+
label?: string;
|
|
2352
|
+
/** Small grey meta line below the label (e.g. `'Karim · 12 mai 14:30'`). */
|
|
2353
|
+
metaKey?: string;
|
|
2354
|
+
meta?: string;
|
|
2355
|
+
/**
|
|
2356
|
+
* Step state — drives the dot styling:
|
|
2357
|
+
* - `'done'` → filled with `--st-delivered-fg`
|
|
2358
|
+
* - `'now'` → filled with `--module` + halo
|
|
2359
|
+
* - `'upcoming'` → outlined `--ink-300` (default)
|
|
2360
|
+
*/
|
|
2361
|
+
state?: EfTimelineState;
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
/**
|
|
2365
|
+
* Vertical timeline — used on order / user / client detail screens
|
|
2366
|
+
* to surface the entity's history. Three dot states (`done` / `now`
|
|
2367
|
+
* / `upcoming`) line up with the prototype.
|
|
2368
|
+
*
|
|
2369
|
+
* ```html
|
|
2370
|
+
* <ef-card titleKey="orders_history">
|
|
2371
|
+
* <ef-timeline
|
|
2372
|
+
* [items]="[
|
|
2373
|
+
* { state: 'done', label: 'Commande créée', meta: 'Karim · 12 mai 14:30' },
|
|
2374
|
+
* { state: 'done', label: 'Paiement reçu', meta: 'Stripe · 12 mai 14:32' },
|
|
2375
|
+
* { state: 'now', label: 'Préparation', meta: 'En cours' },
|
|
2376
|
+
* { state: 'upcoming', label: 'Expédition' },
|
|
2377
|
+
* ]"
|
|
2378
|
+
* />
|
|
2379
|
+
* </ef-card>
|
|
2380
|
+
* ```
|
|
2381
|
+
*
|
|
2382
|
+
* The `'now'` dot picks up `var(--module)` so each module's accent
|
|
2383
|
+
* tints its own active step.
|
|
2384
|
+
*/
|
|
2385
|
+
declare class EfTimelineComponent {
|
|
2386
|
+
readonly items: _angular_core.InputSignal<readonly EfTimelineItem[]>;
|
|
2387
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfTimelineComponent, never>;
|
|
2388
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfTimelineComponent, "ef-timeline", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
interface OpMeta {
|
|
2392
|
+
cls: string;
|
|
2393
|
+
}
|
|
2394
|
+
/**
|
|
2395
|
+
* Standardized change-history box. Drop it on any detail screen and feed it the
|
|
2396
|
+
* record's audit entries (from `GET /api/audit/{entityType}/{id}` via the NSwag
|
|
2397
|
+
* `AuditClient`). Renders a vertical timeline inside an {@link EfCardComponent},
|
|
2398
|
+
* resolving operation labels through `audit_op_*` i18n keys and field labels
|
|
2399
|
+
* through `audit_field_*` (falling back to the raw field key when unmapped).
|
|
2400
|
+
*
|
|
2401
|
+
* ```html
|
|
2402
|
+
* <ef-change-history [entries]="auditEntries()" />
|
|
2403
|
+
* ```
|
|
2404
|
+
*/
|
|
2405
|
+
declare class EfChangeHistoryComponent {
|
|
2406
|
+
private readonly translate;
|
|
2407
|
+
readonly entries: _angular_core.InputSignal<readonly EfChangeHistoryEntry[]>;
|
|
2408
|
+
readonly titleKey: _angular_core.InputSignal<string>;
|
|
2409
|
+
readonly emptyKey: _angular_core.InputSignal<string>;
|
|
2410
|
+
/** Cap the total rows considered (newest first). 0 = no cap. */
|
|
2411
|
+
readonly limit: _angular_core.InputSignal<number>;
|
|
2412
|
+
/** How many recent entries to show inline in the card. 0 = all. The rest
|
|
2413
|
+
* are reachable via the "view details" dialog. */
|
|
2414
|
+
readonly previewLimit: _angular_core.InputSignal<number>;
|
|
2415
|
+
/** Render inside a collapsible card. */
|
|
2416
|
+
readonly collapsible: _angular_core.InputSignal<boolean>;
|
|
2417
|
+
/** Initial collapsed state — expanded by default. */
|
|
2418
|
+
readonly startCollapsed: _angular_core.InputSignal<boolean>;
|
|
2419
|
+
/** "Show more" dialog visibility. */
|
|
2420
|
+
readonly dialogVisible: _angular_core.WritableSignal<boolean>;
|
|
2421
|
+
/** First `previewLimit` rows shown inline in the card. */
|
|
2422
|
+
readonly previewRows: _angular_core.Signal<{
|
|
2423
|
+
entry: EfChangeHistoryEntry;
|
|
2424
|
+
meta: OpMeta;
|
|
2425
|
+
operationLabel: string;
|
|
2426
|
+
}[]>;
|
|
2427
|
+
/** True when the full list has more entries than the inline preview. */
|
|
2428
|
+
readonly hasMore: _angular_core.Signal<boolean>;
|
|
2429
|
+
openDialog(event?: Event): void;
|
|
2430
|
+
readonly rows: _angular_core.Signal<{
|
|
2431
|
+
entry: EfChangeHistoryEntry;
|
|
2432
|
+
meta: OpMeta;
|
|
2433
|
+
operationLabel: string;
|
|
2434
|
+
}[]>;
|
|
2435
|
+
/** Resolve a field key to its label. Adding an `audit_field_<field>` key is
|
|
2436
|
+
* OPTIONAL — when it's missing the raw field name is humanized
|
|
2437
|
+
* (`clientCode` → "Client code"), so new entities/fields work with zero
|
|
2438
|
+
* i18n maintenance. Add a key only for a properly localized (fr/ar) term. */
|
|
2439
|
+
fieldLabel(field: string | undefined): string;
|
|
2440
|
+
/** Returns the translation when present, otherwise a humanized fallback of
|
|
2441
|
+
* the source token (ngx-translate echoes the key on a miss). */
|
|
2442
|
+
private resolveLabel;
|
|
2443
|
+
/** `clientCode` / `status_changed` → "Client code" / "Status changed". */
|
|
2444
|
+
private humanize;
|
|
2445
|
+
/** Locale-stable dd/MM/yyyy HH:mm — avoids depending on Angular locale data
|
|
2446
|
+
* registration (the app's default locale is fr-MA). */
|
|
2447
|
+
formatWhen(value: string | Date | null | undefined): string;
|
|
2448
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfChangeHistoryComponent, never>;
|
|
2449
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfChangeHistoryComponent, "ef-change-history", never, { "entries": { "alias": "entries"; "required": false; "isSignal": true; }; "titleKey": { "alias": "titleKey"; "required": false; "isSignal": true; }; "emptyKey": { "alias": "emptyKey"; "required": false; "isSignal": true; }; "limit": { "alias": "limit"; "required": false; "isSignal": true; }; "previewLimit": { "alias": "previewLimit"; "required": false; "isSignal": true; }; "collapsible": { "alias": "collapsible"; "required": false; "isSignal": true; }; "startCollapsed": { "alias": "startCollapsed"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
/**
|
|
2453
|
+
* Sparkline series — array of numeric values, normalized to the
|
|
2454
|
+
* card's viewBox at render time. Pass an empty array to hide the
|
|
2455
|
+
* sparkline.
|
|
2456
|
+
*/
|
|
2457
|
+
type EfKpiSparkline = ReadonlyArray<number>;
|
|
2458
|
+
/**
|
|
2459
|
+
* Trend tone — drives the delta arrow color.
|
|
2460
|
+
* - `'up'` → success green (`--st-delivered-fg`)
|
|
2461
|
+
* - `'down'` → danger red (`--st-cancelled-fg`)
|
|
2462
|
+
* - `'flat'` → muted grey
|
|
2463
|
+
*/
|
|
2464
|
+
type EfKpiDeltaTone = 'up' | 'down' | 'flat';
|
|
2465
|
+
|
|
2466
|
+
/**
|
|
2467
|
+
* Dashboard headline KPI tile — the one place KPIs are allowed in
|
|
2468
|
+
* the design system. List/search screens stay focused on results;
|
|
2469
|
+
* KPIs live on per-module dashboards (and detail-screen sidebars
|
|
2470
|
+
* via `ef-stats`).
|
|
2471
|
+
*
|
|
2472
|
+
* ```html
|
|
2473
|
+
* <ef-kpi-card
|
|
2474
|
+
* labelKey="kpi_revenue_7d"
|
|
2475
|
+
* value="52 480"
|
|
2476
|
+
* unit="MAD"
|
|
2477
|
+
* delta="▲ 12%"
|
|
2478
|
+
* deltaTone="up"
|
|
2479
|
+
* [spark]="[22, 20, 17, 18, 12, 14, 9, 11, 7, 10, 5, 8, 4, 3, 2]"
|
|
2480
|
+
* />
|
|
2481
|
+
* ```
|
|
2482
|
+
*
|
|
2483
|
+
* Sparkline values are normalized to a fixed 200×28 viewBox; the
|
|
2484
|
+
* stroke colour follows the active module's color (`--module`, e.g.
|
|
2485
|
+
* Sales blue) by default — the convention for report/dashboard
|
|
2486
|
+
* accents — override via `[sparkColor]="'var(--st-pending-fg)'"` for
|
|
2487
|
+
* variants. Pass an empty array to hide the sparkline.
|
|
2488
|
+
*/
|
|
2489
|
+
declare class EfKpiCardComponent {
|
|
2490
|
+
/** Translation key for the small label above the headline number. */
|
|
2491
|
+
readonly labelKey: _angular_core.InputSignal<string>;
|
|
2492
|
+
/** Direct label fallback. */
|
|
2493
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
2494
|
+
/** Pre-formatted headline value (e.g. `'52 480'`, `'603'`). */
|
|
2495
|
+
readonly value: _angular_core.InputSignal<string | number>;
|
|
2496
|
+
/** Optional small unit suffix (e.g. `'MAD'`, `'%'`). */
|
|
2497
|
+
readonly unit: _angular_core.InputSignal<string>;
|
|
2498
|
+
/** Pre-formatted delta text including the arrow glyph (`'▲ 12%'`). */
|
|
2499
|
+
readonly delta: _angular_core.InputSignal<string>;
|
|
2500
|
+
/** Delta tone — drives the arrow color. */
|
|
2501
|
+
readonly deltaTone: _angular_core.InputSignal<EfKpiDeltaTone>;
|
|
2502
|
+
/** Raw series for the sparkline. */
|
|
2503
|
+
readonly spark: _angular_core.InputSignal<EfKpiSparkline>;
|
|
2504
|
+
/** Stroke color for the sparkline polyline. Defaults to the active
|
|
2505
|
+
* module's color (report-accent convention); SVG resolves the CSS
|
|
2506
|
+
* custom property natively. */
|
|
2507
|
+
readonly sparkColor: _angular_core.InputSignal<string>;
|
|
2508
|
+
/** Computed `points="x,y x,y …"` attribute, normalized into the
|
|
2509
|
+
* 200×28 viewBox so the polyline always fits. Returns null
|
|
2510
|
+
* when the series is empty. */
|
|
2511
|
+
readonly sparkPoints: _angular_core.Signal<string>;
|
|
2512
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfKpiCardComponent, never>;
|
|
2513
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfKpiCardComponent, "ef-kpi-card", never, { "labelKey": { "alias": "labelKey"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "unit": { "alias": "unit"; "required": false; "isSignal": true; }; "delta": { "alias": "delta"; "required": false; "isSignal": true; }; "deltaTone": { "alias": "deltaTone"; "required": false; "isSignal": true; }; "spark": { "alias": "spark"; "required": false; "isSignal": true; }; "sparkColor": { "alias": "sparkColor"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
type EfChartType = 'line' | 'bar' | 'donut';
|
|
2517
|
+
interface EfChartSeries {
|
|
2518
|
+
label?: string;
|
|
2519
|
+
data: ReadonlyArray<number>;
|
|
2520
|
+
color?: string;
|
|
2521
|
+
/** Per-point colors (donut slices / bars). Sparse entries fall back to
|
|
2522
|
+
* `color`, then the palette — use for status-keyed charts so slices
|
|
2523
|
+
* reuse the exact status-chip tokens (`--st-*-fg`) instead of accents. */
|
|
2524
|
+
colors?: ReadonlyArray<string | undefined>;
|
|
2525
|
+
}
|
|
2526
|
+
/** Concrete hexes (canvas can't resolve CSS var() strings). Order matches the tenant accents.
|
|
2527
|
+
*
|
|
2528
|
+
* Convention: the DOMINANT color of report/dashboard visuals is the **active
|
|
2529
|
+
* module's color** (`--module`, e.g. Sales blue `--m-sales`). `ef-chart`
|
|
2530
|
+
* resolves the token at render time and passes it as `moduleColor`, which
|
|
2531
|
+
* takes the palette's first slot — these accents only color secondary
|
|
2532
|
+
* series/slices. A series' explicit `color` always wins. */
|
|
2533
|
+
declare const EF_CHART_PALETTE: ReadonlyArray<string>;
|
|
2534
|
+
declare function buildChartConfig(type: EfChartType, labels: ReadonlyArray<string>, series: ReadonlyArray<EfChartSeries>,
|
|
2535
|
+
/** Resolved `--module` color — becomes the palette's first (dominant) slot. */
|
|
2536
|
+
moduleColor?: string): ChartConfiguration;
|
|
2537
|
+
|
|
2538
|
+
/**
|
|
2539
|
+
* Thin chart.js wrapper for report/dashboard visuals (line, bar, donut).
|
|
2540
|
+
* Labels/series are data — i18n happens in the parent. Zoneless-safe: the
|
|
2541
|
+
* effect below re-renders whenever inputs change; instance destroyed on cleanup.
|
|
2542
|
+
*
|
|
2543
|
+
* Color convention: the dominant series/slice color defaults to the **active
|
|
2544
|
+
* module's color** — the component resolves `--module` (set by `ef-app-main`'s
|
|
2545
|
+
* `[data-module]`, e.g. Sales blue) from the canvas at render time, since the
|
|
2546
|
+
* chart.js canvas can't consume CSS `var()` strings. Secondary series fall back
|
|
2547
|
+
* to `EF_CHART_PALETTE`; a series' explicit `color` always wins.
|
|
2548
|
+
*/
|
|
2549
|
+
declare class EfChartComponent implements OnDestroy {
|
|
2550
|
+
readonly type: _angular_core.InputSignal<EfChartType>;
|
|
2551
|
+
readonly labels: _angular_core.InputSignal<readonly string[]>;
|
|
2552
|
+
readonly series: _angular_core.InputSignal<readonly EfChartSeries[]>;
|
|
2553
|
+
readonly height: _angular_core.InputSignal<number>;
|
|
2554
|
+
private readonly canvas;
|
|
2555
|
+
private chart;
|
|
2556
|
+
constructor();
|
|
2557
|
+
ngOnDestroy(): void;
|
|
2558
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfChartComponent, never>;
|
|
2559
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfChartComponent, "ef-chart", never, { "type": { "alias": "type"; "required": true; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "series": { "alias": "series"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
interface EfRankRow {
|
|
2563
|
+
label: string;
|
|
2564
|
+
value: string;
|
|
2565
|
+
secondary?: string;
|
|
2566
|
+
pct: number;
|
|
2567
|
+
}
|
|
2568
|
+
/** Top-N ranked rows (label · proportional bar · value). Lives inside an ef-card. */
|
|
2569
|
+
declare class EfRankListComponent {
|
|
2570
|
+
readonly rows: _angular_core.InputSignal<readonly EfRankRow[]>;
|
|
2571
|
+
clampPct(pct: number): number;
|
|
2572
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfRankListComponent, never>;
|
|
2573
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfRankListComponent, "ef-rank-list", never, { "rows": { "alias": "rows"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2576
|
+
/**
|
|
2577
|
+
* Shared base for every Comptoir form control (`ef-input-text`,
|
|
2578
|
+
* `ef-textarea`, `ef-select`, `ef-input-number`, `ef-checkbox`, …).
|
|
2579
|
+
*
|
|
2580
|
+
* Hoists the cross-cutting concerns that every form control wants
|
|
2581
|
+
* to handle the same way:
|
|
2582
|
+
*
|
|
2583
|
+
* - **Identity** — `inputId` / `name` plus an auto-generated id
|
|
2584
|
+
* (`ef-ctrl-<n>`) so the `<label for>` ↔ `<input id>` binding
|
|
2585
|
+
* always works for screen readers + click-to-focus, even when
|
|
2586
|
+
* the consumer didn't pass anything.
|
|
2587
|
+
* - **Label / placeholder i18n** — `labelKey` / `label` and
|
|
2588
|
+
* `placeholderKey` / `placeholder` with the same precedence
|
|
2589
|
+
* convention (`*Key` wins, falls back to literal). All ef-*
|
|
2590
|
+
* form controls follow the
|
|
2591
|
+
* [feedback_i18n_keys](memory) convention by surfacing both
|
|
2592
|
+
* inputs.
|
|
2593
|
+
* - **ARIA** — `ariaLabelKey` / `ariaLabel` for screen-reader-only
|
|
2594
|
+
* labels; `effectiveAriaLabel` returns `null` when a visible
|
|
2595
|
+
* label is rendered (which already serves as the ARIA name).
|
|
2596
|
+
* `errorsId` provides a stable id for the error/hint container
|
|
2597
|
+
* so subclasses can wire `aria-describedby`.
|
|
2598
|
+
* - **State** — `required` / `readonly` / `disabled` shared inputs,
|
|
2599
|
+
* used directly in subclass templates and toggled by CVA's
|
|
2600
|
+
* `setDisabledState` in subclasses.
|
|
2601
|
+
*
|
|
2602
|
+
* Subclasses still own their own `value` field, ControlValueAccessor
|
|
2603
|
+
* implementation, and any control-specific inputs (e.g. textarea's
|
|
2604
|
+
* `rows`, select's `options`).
|
|
2605
|
+
*
|
|
2606
|
+
* ```ts
|
|
2607
|
+
* export class EfInputTextComponent extends AbstractEfFormControl
|
|
2608
|
+
* implements ControlValueAccessor {
|
|
2609
|
+
* @Input() type = 'text';
|
|
2610
|
+
* @Input() value = '';
|
|
2611
|
+
* // ... CVA + value-specific logic
|
|
2612
|
+
* }
|
|
2613
|
+
* ```
|
|
2614
|
+
*/
|
|
2615
|
+
declare abstract class AbstractEfFormControl {
|
|
2616
|
+
/** Explicit DOM `id` for the inner control. Falls back to
|
|
2617
|
+
* `name`, then to the auto-generated `_autoId`. */
|
|
2618
|
+
readonly inputId: _angular_core.InputSignal<string>;
|
|
2619
|
+
/** Form `name` attribute — also used as the id fallback. */
|
|
2620
|
+
readonly name: _angular_core.InputSignal<string>;
|
|
2621
|
+
/** Per-instance auto id used when neither `inputId` nor `name`
|
|
2622
|
+
* is supplied. The static counter is shared across all
|
|
2623
|
+
* AbstractEfFormControl subclasses, which is fine — uniqueness
|
|
2624
|
+
* per-page is the only requirement. */
|
|
2625
|
+
private static _nextId;
|
|
2626
|
+
protected readonly _autoId: string;
|
|
2627
|
+
/** Direct label text. Use `labelKey` for i18n. */
|
|
2628
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
2629
|
+
/** Translation key for the label — preferred (memory:
|
|
2630
|
+
* feedback_i18n_keys says always use `*Key`). */
|
|
2631
|
+
readonly labelKey: _angular_core.InputSignal<string>;
|
|
2632
|
+
readonly placeholder: _angular_core.InputSignal<string>;
|
|
2633
|
+
readonly placeholderKey: _angular_core.InputSignal<string>;
|
|
2634
|
+
readonly ariaLabel: _angular_core.InputSignal<string>;
|
|
2635
|
+
readonly ariaLabelKey: _angular_core.InputSignal<string>;
|
|
2636
|
+
readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2637
|
+
readonly readonly: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2638
|
+
/** The `[disabled]` input. The **effective** disabled (input OR
|
|
2639
|
+
* form-driven via CVA) is {@link isDisabled} — bind that in templates. */
|
|
2640
|
+
readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2641
|
+
/** Form-driven disabled set by CVA `setDisabledState`, merged with the
|
|
2642
|
+
* `[disabled]` input. Writable signal (the input itself is read-only). */
|
|
2643
|
+
private readonly _cvaDisabled;
|
|
2644
|
+
/** Effective disabled state — the `[disabled]` input OR a reactive-form
|
|
2645
|
+
* `disable()`. Templates/logic should use this, not `disabled()`. */
|
|
2646
|
+
readonly isDisabled: _angular_core.Signal<boolean>;
|
|
2647
|
+
/** CVA hook for subclasses: `setDisabledState(d) { this.updateDisabledState(d); }`. */
|
|
2648
|
+
protected updateDisabledState(disabled: boolean): void;
|
|
2649
|
+
/**
|
|
2650
|
+
* Show the inline clear ✕ (the shared `ef-clear-button`). On by default —
|
|
2651
|
+
* every control is clearable; the ✕ only appears when there's a value and
|
|
2652
|
+
* the field is editable (see {@link canClear}). Set `[showClear]="false"`
|
|
2653
|
+
* to opt a field out.
|
|
2654
|
+
*/
|
|
2655
|
+
readonly showClear: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
2656
|
+
/** Whether the clear ✕ should currently render: opted in, the control
|
|
2657
|
+
* holds a value ({@link hasValue}), and the field is editable. */
|
|
2658
|
+
get canClear(): boolean;
|
|
2659
|
+
/** Subclasses report whether they currently hold a clearable value.
|
|
2660
|
+
* Default `false` (controls that don't override never show a clear). */
|
|
2661
|
+
protected get hasValue(): boolean;
|
|
2662
|
+
/** Reset the control's value (and notify forms / `valueChangeEvent`).
|
|
2663
|
+
* Overridden by subclasses that support clearing. */
|
|
2664
|
+
clearValue(): void;
|
|
2665
|
+
/**
|
|
2666
|
+
* Forms-independent server/validation errors for this field.
|
|
2667
|
+
*
|
|
2668
|
+
* The signal-based V2 detail screens bind values with `[value]` +
|
|
2669
|
+
* `(valueChangeEvent)` and never register an `NgControl`, so the
|
|
2670
|
+
* `ngControl`-based `serverError` path can't surface backend
|
|
2671
|
+
* validation messages. Two ways to feed them in:
|
|
2672
|
+
*
|
|
2673
|
+
* - Explicit, per-field: `[errors]="serverErrors()['clientType']"`.
|
|
2674
|
+
* - Automatic, by `name`: wrap the fields in `[efServerErrors]="serverErrors()"`
|
|
2675
|
+
* and the control links itself via {@link EfServerErrorsDirective}
|
|
2676
|
+
* (no per-field binding). See {@link resolvedExternalErrors}.
|
|
2677
|
+
*
|
|
2678
|
+
* Either way the control renders the messages and the invalid state.
|
|
2679
|
+
* Falls back to the `NgControl` `serverError` path when neither is
|
|
2680
|
+
* present, so `ngModel`-based (v1) screens keep working unchanged.
|
|
2681
|
+
*/
|
|
2682
|
+
readonly errors: _angular_core.InputSignal<string[]>;
|
|
2683
|
+
/** Optional enclosing `[efServerErrors]` scope (auto-link by `name`). */
|
|
2684
|
+
private readonly serverErrorsScope;
|
|
2685
|
+
/**
|
|
2686
|
+
* External (server) errors for this control, resolved reactively from
|
|
2687
|
+
* either the explicit `[errors]` input (wins) or the enclosing
|
|
2688
|
+
* `[efServerErrors]` scope keyed by `name`. A `computed` so reads inside
|
|
2689
|
+
* the subclass `serverErrors` / `isInvalid` getters track the source
|
|
2690
|
+
* signals under zoneless change detection.
|
|
2691
|
+
*/
|
|
2692
|
+
readonly resolvedExternalErrors: _angular_core.Signal<string[]>;
|
|
2693
|
+
protected readonly translateService: TranslateService;
|
|
2694
|
+
/** Resolved DOM id. Always non-empty so `<label for>` and
|
|
2695
|
+
* `<input id>` can match unambiguously. */
|
|
2696
|
+
get effectiveId(): string;
|
|
2697
|
+
/** Translated placeholder (or empty string). */
|
|
2698
|
+
get effectivePlaceholder(): string;
|
|
2699
|
+
/**
|
|
2700
|
+
* Resolved `aria-label` value — used when no visible label is
|
|
2701
|
+
* rendered. Returns `null` (no attribute) when a visible label
|
|
2702
|
+
* IS shown, since the visible label already serves as the
|
|
2703
|
+
* accessible name and duplicate `aria-label` would override it.
|
|
2704
|
+
*/
|
|
2705
|
+
get effectiveAriaLabel(): string | null;
|
|
2706
|
+
/** Stable id for the error / hint container — wired through
|
|
2707
|
+
* `aria-describedby` on the input so screen readers announce
|
|
2708
|
+
* the validation message together with the field name. */
|
|
2709
|
+
get errorsId(): string;
|
|
2710
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AbstractEfFormControl, never>;
|
|
2711
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<AbstractEfFormControl, "ng-component", never, { "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelKey": { "alias": "labelKey"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "placeholderKey": { "alias": "placeholderKey"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "ariaLabelKey": { "alias": "ariaLabelKey"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2714
|
+
declare class EfInputTextComponent extends AbstractEfFormControl implements ControlValueAccessor {
|
|
2715
|
+
size: 'small' | 'large';
|
|
2716
|
+
type: string;
|
|
2717
|
+
maxlength?: number;
|
|
2718
|
+
fluid: boolean;
|
|
2719
|
+
inline: boolean;
|
|
2720
|
+
autocomplete?: string;
|
|
2721
|
+
/** Clearable (showClear / canClear) is inherited from AbstractEfFormControl;
|
|
2722
|
+
* we only supply the value predicate + the reset. */
|
|
2723
|
+
protected get hasValue(): boolean;
|
|
2724
|
+
clearValue(): void;
|
|
2725
|
+
/**
|
|
2726
|
+
* Rendering variant — same dual-mode pattern as `ef-button`.
|
|
2727
|
+
* - `'comptoir'` (default) — native `<input class="ef-input">` against
|
|
2728
|
+
* the Comptoir pattern styles. Renders at the
|
|
2729
|
+
* canonical `--hit-base` (40px) control height.
|
|
2730
|
+
* Required for `prefix` / `suffix`.
|
|
2731
|
+
* - `'primeng'` — wraps `<input pInputText>` (v1). Opt in when
|
|
2732
|
+
* you specifically need PrimeNG input behaviour.
|
|
2733
|
+
* See ADR-009 for why comptoir is the height-consistent default.
|
|
2734
|
+
*/
|
|
2735
|
+
variant: 'primeng' | 'comptoir';
|
|
2736
|
+
/** Inline prefix addon — e.g. `'/p/'` for slugs, `'$'` for prices.
|
|
2737
|
+
* Renders only in the Comptoir variant; ignored otherwise. */
|
|
2738
|
+
prefix?: string;
|
|
2739
|
+
/** Inline suffix addon — e.g. `'MAD'`, `'cm'`. Renders only in the
|
|
2740
|
+
* Comptoir variant; ignored otherwise. */
|
|
2741
|
+
suffix?: string;
|
|
2742
|
+
get isInline(): boolean;
|
|
2743
|
+
valueChangeEvent: EventEmitter<string>;
|
|
2744
|
+
/** Two-way-bindable as `[value]` (one-way) or
|
|
2745
|
+
* `[(value)]="signal()"` (set + listen via `valueChangeEvent`). */
|
|
2746
|
+
value: string;
|
|
2747
|
+
private onChange;
|
|
2748
|
+
private onTouched;
|
|
2749
|
+
readonly ngControl: NgControl;
|
|
2750
|
+
constructor();
|
|
2751
|
+
get showRequired(): boolean;
|
|
2752
|
+
get serverErrors(): string[] | null;
|
|
2753
|
+
get isInvalid(): boolean;
|
|
2754
|
+
writeValue(value: string): void;
|
|
2755
|
+
registerOnChange(fn: (value: string) => void): void;
|
|
2756
|
+
registerOnTouched(fn: () => void): void;
|
|
2757
|
+
setDisabledState(isDisabled: boolean): void;
|
|
2758
|
+
handleInput(value: string): void;
|
|
2759
|
+
handleBlur(): void;
|
|
2760
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfInputTextComponent, never>;
|
|
2761
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfInputTextComponent, "ef-input-text", never, { "size": { "alias": "size"; "required": false; }; "type": { "alias": "type"; "required": false; }; "maxlength": { "alias": "maxlength"; "required": false; }; "fluid": { "alias": "fluid"; "required": false; }; "inline": { "alias": "inline"; "required": false; }; "autocomplete": { "alias": "autocomplete"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "prefix": { "alias": "prefix"; "required": false; }; "suffix": { "alias": "suffix"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, { "valueChangeEvent": "valueChangeEvent"; }, never, never, true, never>;
|
|
2762
|
+
static ngAcceptInputType_fluid: unknown;
|
|
2763
|
+
static ngAcceptInputType_inline: unknown;
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2766
|
+
/**
|
|
2767
|
+
* Comptoir select — wraps PrimeNG `p-select` (single) or `p-multiselect`
|
|
2768
|
+
* (multi) and skins it against the `.es` / `.es__panel` patterns lifted
|
|
2769
|
+
* from the static prototype (`docs/ux-ui/erp/screens/components.html`,
|
|
2770
|
+
* Section 04). All the heavy machinery (filter, virtual scroll, group
|
|
2771
|
+
* support, keyboard nav, ARIA listbox semantics, RTL, focus trapping,
|
|
2772
|
+
* lazy loading) comes from PrimeNG; we own only the visuals + the
|
|
2773
|
+
* Elasticias API surface (i18n `*Key` inputs, `selectionChangeEvent`,
|
|
2774
|
+
* `filterByKeys`, content-projected templates).
|
|
2775
|
+
*
|
|
2776
|
+
* The `'comptoir'` variant remains as a lite, no-deps escape hatch
|
|
2777
|
+
* (native `<select>` styled via `.ef-select-native`); use the default
|
|
2778
|
+
* `'primeng'` variant for any screen that needs filter / multi /
|
|
2779
|
+
* group / templating.
|
|
2780
|
+
*
|
|
2781
|
+
* ```html
|
|
2782
|
+
* <ef-select
|
|
2783
|
+
* labelKey="orders.status"
|
|
2784
|
+
* placeholderKey="orders.status_placeholder"
|
|
2785
|
+
* [(value)]="status"
|
|
2786
|
+
* [options]="statuses"
|
|
2787
|
+
* optionLabel="label" optionValue="code"
|
|
2788
|
+
* [filter]="true" [showClear]="true">
|
|
2789
|
+
* </ef-select>
|
|
2790
|
+
*
|
|
2791
|
+
* <ef-select
|
|
2792
|
+
* labelKey="users.assigned"
|
|
2793
|
+
* [options]="users" optionLabel="name" optionValue="id"
|
|
2794
|
+
* [multiple]="true" [filter]="true">
|
|
2795
|
+
* <ng-template #item let-u>
|
|
2796
|
+
* <span class="av">{{ u.initials }}</span>
|
|
2797
|
+
* <span class="body">
|
|
2798
|
+
* <span class="nm">{{ u.name }}</span>
|
|
2799
|
+
* <span class="meta">{{ u.role }}</span>
|
|
2800
|
+
* </span>
|
|
2801
|
+
* </ng-template>
|
|
2802
|
+
* </ef-select>
|
|
2803
|
+
* ```
|
|
2804
|
+
*/
|
|
2805
|
+
declare class EfSelectComponent extends AbstractEfFormControl implements ControlValueAccessor, OnInit, OnChanges {
|
|
2806
|
+
options: any[];
|
|
2807
|
+
optionLabel: string;
|
|
2808
|
+
optionValue?: string;
|
|
2809
|
+
optionDisabled?: string;
|
|
2810
|
+
/** Stable identity key — required for groups and virtual scroll. */
|
|
2811
|
+
dataKey?: string;
|
|
2812
|
+
/** Group mode — pair with `optionGroupLabel` + `optionGroupChildren`. */
|
|
2813
|
+
group: boolean;
|
|
2814
|
+
optionGroupLabel: string;
|
|
2815
|
+
optionGroupChildren: string;
|
|
2816
|
+
/** Control height. Default (undefined) = the canonical `--hit-base` (40px),
|
|
2817
|
+
* matching native inputs (ADR-009). `'small'` opts into the dense 32px
|
|
2818
|
+
* variant for compact contexts (e.g. table-row editors). */
|
|
2819
|
+
size?: 'small' | 'large';
|
|
2820
|
+
fluid: boolean;
|
|
2821
|
+
inline: boolean;
|
|
2822
|
+
appendTo?: string;
|
|
2823
|
+
/** Multi-selection — internally swaps `<p-select>` for `<p-multiselect>`. */
|
|
2824
|
+
multiple: boolean;
|
|
2825
|
+
filter: boolean;
|
|
2826
|
+
/** Filter the list against these option fields (string or csv).
|
|
2827
|
+
* PrimeNG default: `optionLabel`. */
|
|
2828
|
+
filterBy?: string;
|
|
2829
|
+
filterPlaceholder?: string;
|
|
2830
|
+
filterPlaceholderKey?: string;
|
|
2831
|
+
/** Auto-focus the filter input when the panel opens (default: true). */
|
|
2832
|
+
autofocusFilter: boolean;
|
|
2833
|
+
editable: boolean;
|
|
2834
|
+
loading: boolean;
|
|
2835
|
+
/** Virtual-scroll for long lists (>100 items). Pair with
|
|
2836
|
+
* `virtualScrollItemSize` (default 38px). */
|
|
2837
|
+
virtualScroll: boolean;
|
|
2838
|
+
virtualScrollItemSize: number;
|
|
2839
|
+
scrollHeight: string;
|
|
2840
|
+
/** Multi-select trigger display: `'chip'` (default — chips visible
|
|
2841
|
+
* in the trigger, individually removable) or `'comma'`. */
|
|
2842
|
+
multiDisplay: 'chip' | 'comma';
|
|
2843
|
+
/** Multi-select header "select all" toggle. Off by default — the
|
|
2844
|
+
* Comptoir multiselect leads with the filter; opt in when bulk
|
|
2845
|
+
* select-all is genuinely useful. */
|
|
2846
|
+
showToggleAll: boolean;
|
|
2847
|
+
emptyMessage?: string;
|
|
2848
|
+
emptyMessageKey?: string;
|
|
2849
|
+
emptyFilterMessage?: string;
|
|
2850
|
+
emptyFilterMessageKey?: string;
|
|
2851
|
+
styleClass?: string;
|
|
2852
|
+
panelStyleClass?: string;
|
|
2853
|
+
/** Filter options by matching key-value pairs (legacy Elasticias
|
|
2854
|
+
* helper — pre-filters `options` before they reach PrimeNG). */
|
|
979
2855
|
filterByKeys?: {
|
|
980
2856
|
[key: string]: any;
|
|
981
2857
|
};
|
|
2858
|
+
/**
|
|
2859
|
+
* Rendering variant.
|
|
2860
|
+
* - `'primeng'` (default) — wraps `p-select` / `p-multiselect`, skinned with
|
|
2861
|
+
* the `.es` / `.es__panel` patterns (the custom
|
|
2862
|
+
* dropdown: filter, styled options, animated panel
|
|
2863
|
+
* — see `components.html` Section 04). Also pinned
|
|
2864
|
+
* to the canonical `--hit-base` (40px) trigger
|
|
2865
|
+
* height (`.es.p-select { min-height: --hit-base }`),
|
|
2866
|
+
* so it aligns with inputs/buttons in a row.
|
|
2867
|
+
* - `'comptoir'` — lite native `<select class="ef-select-native">`.
|
|
2868
|
+
* No filter / panel / multi / templates; use it for
|
|
2869
|
+
* inline / dense contexts that want the plain native
|
|
2870
|
+
* control (e.g. table-row editors).
|
|
2871
|
+
* The `.es` dropdown is the default per the design system; opt into
|
|
2872
|
+
* `comptoir` only when a native control is specifically wanted. See ADR-009.
|
|
2873
|
+
*/
|
|
2874
|
+
variant: 'primeng' | 'comptoir';
|
|
982
2875
|
get isInline(): boolean;
|
|
2876
|
+
readonly hostClass = true;
|
|
983
2877
|
itemTemplate: TemplateRef<any> | null;
|
|
984
2878
|
selectedItemTemplate: TemplateRef<any> | null;
|
|
2879
|
+
groupTemplate: TemplateRef<any> | null;
|
|
2880
|
+
headerTemplate: TemplateRef<any> | null;
|
|
2881
|
+
footerTemplate: TemplateRef<any> | null;
|
|
2882
|
+
emptyTemplate: TemplateRef<any> | null;
|
|
2883
|
+
emptyFilterTemplate: TemplateRef<any> | null;
|
|
2884
|
+
filterTemplate: TemplateRef<any> | null;
|
|
2885
|
+
loaderTemplate: TemplateRef<any> | null;
|
|
985
2886
|
selectionChangeEvent: EventEmitter<any>;
|
|
2887
|
+
filterChangeEvent: EventEmitter<string>;
|
|
2888
|
+
panelShowEvent: EventEmitter<void>;
|
|
2889
|
+
panelHideEvent: EventEmitter<void>;
|
|
2890
|
+
/** Two-way-bindable as `[value]` (one-way) or
|
|
2891
|
+
* `[(value)]` (set + listen via `selectionChangeEvent`). */
|
|
986
2892
|
value: any;
|
|
987
2893
|
filteredOptions: any[];
|
|
988
2894
|
private onChange;
|
|
@@ -990,10 +2896,17 @@ declare class EfSelectComponent implements ControlValueAccessor, OnInit, OnChang
|
|
|
990
2896
|
/** Resolved lazily in ngOnInit to avoid circular DI with NG_VALUE_ACCESSOR */
|
|
991
2897
|
ngControl: NgControl | null;
|
|
992
2898
|
private readonly injector;
|
|
993
|
-
private readonly translateService;
|
|
994
2899
|
ngOnInit(): void;
|
|
995
|
-
|
|
996
|
-
|
|
2900
|
+
/** Translated filter placeholder. Falls back to a generic key, then
|
|
2901
|
+
* to "Search…" so it always renders something readable. */
|
|
2902
|
+
get effectiveFilterPlaceholder(): string;
|
|
2903
|
+
get effectiveEmptyMessage(): string;
|
|
2904
|
+
get effectiveEmptyFilterMessage(): string;
|
|
2905
|
+
/** Always include `.es` so the global Comptoir skin in
|
|
2906
|
+
* `_patterns.scss` always finds a hook, regardless of what the
|
|
2907
|
+
* consumer passes via `styleClass`. */
|
|
2908
|
+
get effectiveStyleClass(): string;
|
|
2909
|
+
get effectivePanelStyleClass(): string;
|
|
997
2910
|
get showRequired(): boolean;
|
|
998
2911
|
get serverErrors(): string[] | null;
|
|
999
2912
|
get isInvalid(): boolean;
|
|
@@ -1007,49 +2920,134 @@ declare class EfSelectComponent implements ControlValueAccessor, OnInit, OnChang
|
|
|
1007
2920
|
value: any;
|
|
1008
2921
|
}): void;
|
|
1009
2922
|
handleClear(): void;
|
|
2923
|
+
handleFilter(event: {
|
|
2924
|
+
originalEvent?: Event;
|
|
2925
|
+
filter: string;
|
|
2926
|
+
}): void;
|
|
2927
|
+
handlePanelShow(): void;
|
|
2928
|
+
handlePanelHide(): void;
|
|
2929
|
+
/** Comptoir variant — native `<select>` change handler. The empty
|
|
2930
|
+
* string from the placeholder option becomes `null`; otherwise we
|
|
2931
|
+
* resolve the value through `optionValue` if provided. */
|
|
2932
|
+
handleNativeSelectChange(rawValue: string): void;
|
|
1010
2933
|
private applyFilters;
|
|
1011
2934
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfSelectComponent, never>;
|
|
1012
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfSelectComponent, "ef-select", never, { "
|
|
1013
|
-
static
|
|
2935
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfSelectComponent, "ef-select", never, { "options": { "alias": "options"; "required": false; }; "optionLabel": { "alias": "optionLabel"; "required": false; }; "optionValue": { "alias": "optionValue"; "required": false; }; "optionDisabled": { "alias": "optionDisabled"; "required": false; }; "dataKey": { "alias": "dataKey"; "required": false; }; "group": { "alias": "group"; "required": false; }; "optionGroupLabel": { "alias": "optionGroupLabel"; "required": false; }; "optionGroupChildren": { "alias": "optionGroupChildren"; "required": false; }; "size": { "alias": "size"; "required": false; }; "fluid": { "alias": "fluid"; "required": false; }; "inline": { "alias": "inline"; "required": false; }; "appendTo": { "alias": "appendTo"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "filter": { "alias": "filter"; "required": false; }; "filterBy": { "alias": "filterBy"; "required": false; }; "filterPlaceholder": { "alias": "filterPlaceholder"; "required": false; }; "filterPlaceholderKey": { "alias": "filterPlaceholderKey"; "required": false; }; "autofocusFilter": { "alias": "autofocusFilter"; "required": false; }; "editable": { "alias": "editable"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "virtualScroll": { "alias": "virtualScroll"; "required": false; }; "virtualScrollItemSize": { "alias": "virtualScrollItemSize"; "required": false; }; "scrollHeight": { "alias": "scrollHeight"; "required": false; }; "multiDisplay": { "alias": "multiDisplay"; "required": false; }; "showToggleAll": { "alias": "showToggleAll"; "required": false; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; }; "emptyMessageKey": { "alias": "emptyMessageKey"; "required": false; }; "emptyFilterMessage": { "alias": "emptyFilterMessage"; "required": false; }; "emptyFilterMessageKey": { "alias": "emptyFilterMessageKey"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "panelStyleClass": { "alias": "panelStyleClass"; "required": false; }; "filterByKeys": { "alias": "filterByKeys"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, { "selectionChangeEvent": "selectionChangeEvent"; "filterChangeEvent": "filterChangeEvent"; "panelShowEvent": "panelShowEvent"; "panelHideEvent": "panelHideEvent"; }, ["itemTemplate", "selectedItemTemplate", "groupTemplate", "headerTemplate", "footerTemplate", "emptyTemplate", "emptyFilterTemplate", "filterTemplate", "loaderTemplate"], never, true, never>;
|
|
2936
|
+
static ngAcceptInputType_group: unknown;
|
|
1014
2937
|
static ngAcceptInputType_fluid: unknown;
|
|
1015
2938
|
static ngAcceptInputType_inline: unknown;
|
|
2939
|
+
static ngAcceptInputType_multiple: unknown;
|
|
1016
2940
|
static ngAcceptInputType_filter: unknown;
|
|
1017
|
-
static
|
|
1018
|
-
static
|
|
2941
|
+
static ngAcceptInputType_autofocusFilter: unknown;
|
|
2942
|
+
static ngAcceptInputType_editable: unknown;
|
|
2943
|
+
static ngAcceptInputType_loading: unknown;
|
|
2944
|
+
static ngAcceptInputType_virtualScroll: unknown;
|
|
2945
|
+
static ngAcceptInputType_showToggleAll: unknown;
|
|
1019
2946
|
}
|
|
1020
2947
|
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
2948
|
+
/**
|
|
2949
|
+
* Comptoir checkbox.
|
|
2950
|
+
*
|
|
2951
|
+
* Two render variants share the same API:
|
|
2952
|
+
* - `'primeng'` (default) — wraps `p-checkbox`. Stock PrimeNG visuals.
|
|
2953
|
+
* - `'comptoir'` — native `<input type="checkbox">` styled
|
|
2954
|
+
* against `.ef-checkbox-native`. Lean, no animation, fits dense
|
|
2955
|
+
* grids (variants table, role / permission lists, etc.).
|
|
2956
|
+
*
|
|
2957
|
+
* Identity / label / aria / required / readonly / disabled inherited
|
|
2958
|
+
* from `AbstractEfFormControl`. `binary` flips between boolean mode
|
|
2959
|
+
* (`checked: true/false`) and value-mode (`checked` is the bound
|
|
2960
|
+
* value when ticked, `null` when unticked) — the latter pairs with
|
|
2961
|
+
* a parent NgModel array for multi-select scenarios.
|
|
2962
|
+
*
|
|
2963
|
+
* ```html
|
|
2964
|
+
* <ef-checkbox
|
|
2965
|
+
* labelKey="catalog.is_active"
|
|
2966
|
+
* variant="comptoir"
|
|
2967
|
+
* [(checked)]="variant.isActive"
|
|
2968
|
+
* binary />
|
|
2969
|
+
* ```
|
|
2970
|
+
*/
|
|
2971
|
+
declare class EfCheckboxComponent extends AbstractEfFormControl implements ControlValueAccessor {
|
|
2972
|
+
/** Underlying checkbox value when ticked (non-binary mode). */
|
|
1028
2973
|
value?: any;
|
|
2974
|
+
/** Binary mode — checked becomes a boolean rather than the
|
|
2975
|
+
* `value` input. Default for new code. */
|
|
1029
2976
|
binary: boolean;
|
|
1030
|
-
|
|
1031
|
-
|
|
2977
|
+
/**
|
|
2978
|
+
* Render variant.
|
|
2979
|
+
* - `'primeng'` (default) — wraps `p-checkbox`.
|
|
2980
|
+
* - `'comptoir'` — native `<input type="checkbox">`
|
|
2981
|
+
* styled against `.ef-checkbox-native`.
|
|
2982
|
+
*/
|
|
2983
|
+
variant: 'primeng' | 'comptoir';
|
|
2984
|
+
/** Two-way bindable `[(checked)]`. */
|
|
1032
2985
|
checked: any;
|
|
2986
|
+
checkedChange: EventEmitter<any>;
|
|
1033
2987
|
private onChange;
|
|
1034
2988
|
private onTouched;
|
|
1035
2989
|
readonly ngControl: NgControl;
|
|
1036
2990
|
constructor();
|
|
1037
|
-
get effectiveId(): string;
|
|
1038
|
-
get effectiveLabel(): string | undefined;
|
|
1039
2991
|
get showRequired(): boolean;
|
|
1040
2992
|
get serverErrors(): string[] | null;
|
|
2993
|
+
get isInvalid(): boolean;
|
|
1041
2994
|
writeValue(value: any): void;
|
|
1042
2995
|
registerOnChange(fn: (value: any) => void): void;
|
|
1043
2996
|
registerOnTouched(fn: () => void): void;
|
|
1044
2997
|
setDisabledState(isDisabled: boolean): void;
|
|
2998
|
+
/** Handler for PrimeNG's onChange event. */
|
|
1045
2999
|
handleChange(event: any): void;
|
|
3000
|
+
/** Handler for the native checkbox change event (Comptoir variant). */
|
|
3001
|
+
handleNativeChange(rawChecked: boolean): void;
|
|
1046
3002
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfCheckboxComponent, never>;
|
|
1047
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfCheckboxComponent, "ef-checkbox", never, { "
|
|
3003
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfCheckboxComponent, "ef-checkbox", never, { "value": { "alias": "value"; "required": false; }; "binary": { "alias": "binary"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "checked": { "alias": "checked"; "required": false; }; }, { "checkedChange": "checkedChange"; }, never, never, true, never>;
|
|
1048
3004
|
static ngAcceptInputType_binary: unknown;
|
|
1049
|
-
static ngAcceptInputType_required: unknown;
|
|
1050
|
-
static ngAcceptInputType_disabled: unknown;
|
|
1051
3005
|
}
|
|
1052
3006
|
|
|
3007
|
+
/**
|
|
3008
|
+
* Comptoir toggle switch — wraps `p-toggleswitch`, boolean-only.
|
|
3009
|
+
*
|
|
3010
|
+
* Identity / label / aria / required / readonly / disabled inherited
|
|
3011
|
+
* from `AbstractEfFormControl`. Use for on/off state that applies
|
|
3012
|
+
* immediately (row activation toggles, settings), `ef-checkbox` for
|
|
3013
|
+
* form fields that are saved with the enclosing form.
|
|
3014
|
+
*
|
|
3015
|
+
* ```html
|
|
3016
|
+
* <ef-toggleswitch
|
|
3017
|
+
* [checked]="row.isActive"
|
|
3018
|
+
* [disabled]="!context.hasEditPermission"
|
|
3019
|
+
* ariaLabelKey="sales_clients_toggle_active_aria"
|
|
3020
|
+
* (checkedChange)="setActive(row, $event)" />
|
|
3021
|
+
* ```
|
|
3022
|
+
*/
|
|
3023
|
+
declare class EfToggleSwitchComponent extends AbstractEfFormControl implements ControlValueAccessor {
|
|
3024
|
+
/** Two-way bindable `[(checked)]` — boolean only. */
|
|
3025
|
+
checked: boolean;
|
|
3026
|
+
checkedChange: EventEmitter<boolean>;
|
|
3027
|
+
private onChange;
|
|
3028
|
+
private onTouched;
|
|
3029
|
+
readonly ngControl: NgControl;
|
|
3030
|
+
constructor();
|
|
3031
|
+
writeValue(value: unknown): void;
|
|
3032
|
+
registerOnChange(fn: (value: boolean) => void): void;
|
|
3033
|
+
registerOnTouched(fn: () => void): void;
|
|
3034
|
+
setDisabledState(isDisabled: boolean): void;
|
|
3035
|
+
handleChange(event: {
|
|
3036
|
+
checked: boolean;
|
|
3037
|
+
}): void;
|
|
3038
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfToggleSwitchComponent, never>;
|
|
3039
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfToggleSwitchComponent, "ef-toggleswitch", never, { "checked": { "alias": "checked"; "required": false; }; }, { "checkedChange": "checkedChange"; }, never, never, true, never>;
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
/**
|
|
3043
|
+
* @deprecated Wraps PrimeNG `p-datepicker`, which does not follow the
|
|
3044
|
+
* Comptoir design system. Prefer `ef-datepicker-advanced` in **field
|
|
3045
|
+
* mode** (`mode="field"`, `selectionMode="single" | "range"`) — it is a
|
|
3046
|
+
* Comptoir-native form control (ControlValueAccessor) with the same
|
|
3047
|
+
* `[(ngModel)]` / `formControlName` binding and a `Date` / `[start, end]`
|
|
3048
|
+
* value shape. This wrapper is kept only for legacy V1 screens and will
|
|
3049
|
+
* be removed once they are migrated.
|
|
3050
|
+
*/
|
|
1053
3051
|
declare class EfDatepickerComponent implements ControlValueAccessor {
|
|
1054
3052
|
label?: string;
|
|
1055
3053
|
labelKey?: string;
|
|
@@ -1101,15 +3099,42 @@ declare class EfDatepickerComponent implements ControlValueAccessor {
|
|
|
1101
3099
|
static ngAcceptInputType_showButtonBar: unknown;
|
|
1102
3100
|
}
|
|
1103
3101
|
|
|
1104
|
-
|
|
3102
|
+
/**
|
|
3103
|
+
* Comptoir number input.
|
|
3104
|
+
*
|
|
3105
|
+
* Two render variants share the same API:
|
|
3106
|
+
* - `'comptoir'` (default) — native `<input type="text" inputmode="decimal">`
|
|
3107
|
+
* styled against `.ef-input` / `.ef-input-group`. Lean, no locale
|
|
3108
|
+
* formatting on display, but data entry accepts both `,` and `.` as
|
|
3109
|
+
* the decimal separator (fr-MA users type commas) and ignores
|
|
3110
|
+
* space group separators; pair with `suffix="MAD"` for unit display
|
|
3111
|
+
* in dense grids (variants table, inventory adjustments, etc.).
|
|
3112
|
+
* See ADR-009.
|
|
3113
|
+
* - `'primeng'` — wraps `p-inputnumber`. Full locale-aware
|
|
3114
|
+
* currency / decimal formatting, stepper buttons, prefix / suffix.
|
|
3115
|
+
*
|
|
3116
|
+
* Identity / label / placeholder / aria / required / readonly /
|
|
3117
|
+
* disabled are inherited from `AbstractEfFormControl`.
|
|
3118
|
+
*
|
|
3119
|
+
* ```html
|
|
3120
|
+
* <ef-inputnumber
|
|
3121
|
+
* labelKey="catalog.price"
|
|
3122
|
+
* variant="primeng"
|
|
3123
|
+
* mode="currency" currency="MAD" locale="fr-MA"
|
|
3124
|
+
* [(value)]="variant.price" />
|
|
3125
|
+
*
|
|
3126
|
+
* <ef-inputnumber
|
|
3127
|
+
* labelKey="catalog.inventory"
|
|
3128
|
+
* variant="comptoir"
|
|
3129
|
+
* [showButtons]="true" buttonLayout="horizontal"
|
|
3130
|
+
* [min]="0" [step]="1"
|
|
3131
|
+
* [(value)]="variant.inventoryQuantity" />
|
|
3132
|
+
* ```
|
|
3133
|
+
*/
|
|
3134
|
+
declare class EfInputNumberComponent extends AbstractEfFormControl implements ControlValueAccessor {
|
|
1105
3135
|
inputNumber?: InputNumber;
|
|
1106
|
-
label?: string;
|
|
1107
|
-
labelKey?: string;
|
|
1108
|
-
required: boolean;
|
|
1109
3136
|
value?: Nullable<number>;
|
|
1110
3137
|
invalid: boolean;
|
|
1111
|
-
disabled?: boolean;
|
|
1112
|
-
readonly: boolean;
|
|
1113
3138
|
format: boolean;
|
|
1114
3139
|
showButtons: boolean;
|
|
1115
3140
|
buttonLayout: 'stacked' | 'horizontal' | 'vertical';
|
|
@@ -1130,49 +3155,56 @@ declare class EfInputNumberComponent implements ControlValueAccessor {
|
|
|
1130
3155
|
min?: number;
|
|
1131
3156
|
max?: number;
|
|
1132
3157
|
step: number;
|
|
1133
|
-
allowEmpty: boolean;
|
|
1134
|
-
inputId?: string;
|
|
1135
|
-
name?: string;
|
|
1136
|
-
placeholder?: string;
|
|
1137
|
-
placeholderKey?: string;
|
|
3158
|
+
allowEmpty: boolean;
|
|
1138
3159
|
inputSize?: number;
|
|
3160
|
+
/** Default (undefined) = canonical `--hit-base` (40px); `'small'` = dense 32px. */
|
|
1139
3161
|
size?: 'small' | 'large';
|
|
1140
3162
|
maxlength?: number;
|
|
1141
3163
|
minlength?: number;
|
|
1142
3164
|
pattern?: string;
|
|
1143
3165
|
tabindex?: number;
|
|
1144
3166
|
title?: string;
|
|
1145
|
-
ariaLabel?: string;
|
|
1146
3167
|
ariaLabelledBy?: string;
|
|
1147
|
-
ariaDescribedBy?: string;
|
|
1148
|
-
ariaRequired?: boolean;
|
|
1149
3168
|
inputStyle?: any;
|
|
1150
3169
|
inputStyleClass?: string;
|
|
1151
3170
|
style?: any;
|
|
1152
3171
|
styleClass?: string;
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
3172
|
+
/** PrimeNG visual variant (`'filled'` | `'outlined'`) — only
|
|
3173
|
+
* honored when {@link variant} === 'primeng'. */
|
|
3174
|
+
primeNgVariant?: 'filled' | 'outlined';
|
|
3175
|
+
autofocus: boolean;
|
|
1156
3176
|
autocomplete?: string;
|
|
1157
|
-
fluid
|
|
3177
|
+
fluid: boolean;
|
|
1158
3178
|
inline: boolean;
|
|
3179
|
+
/**
|
|
3180
|
+
* Render variant.
|
|
3181
|
+
* - `'comptoir'` (default) — native `<input type="text" inputmode="decimal">`
|
|
3182
|
+
* styled against `.ef-input` / `.ef-input-group`,
|
|
3183
|
+
* at the canonical `--hit-base` (40px) height.
|
|
3184
|
+
* Accepts `,` and `.` as decimal separator.
|
|
3185
|
+
* - `'primeng'` — wraps `p-inputnumber`. Opt in for PrimeNG's
|
|
3186
|
+
* formatted stepper behaviour.
|
|
3187
|
+
* See ADR-009 for why comptoir is the height-consistent default.
|
|
3188
|
+
*/
|
|
3189
|
+
variant: 'primeng' | 'comptoir';
|
|
1159
3190
|
get isInline(): boolean;
|
|
1160
3191
|
pt?: any;
|
|
1161
3192
|
ptOptions?: any;
|
|
1162
3193
|
dt?: any;
|
|
1163
3194
|
unstyled?: boolean;
|
|
1164
3195
|
inputEvent: EventEmitter<InputNumberInputEvent>;
|
|
3196
|
+
valueChangeEvent: EventEmitter<number | null>;
|
|
1165
3197
|
focusEvent: EventEmitter<Event>;
|
|
1166
3198
|
blurEvent: EventEmitter<Event>;
|
|
1167
3199
|
keyDownEvent: EventEmitter<KeyboardEvent>;
|
|
1168
3200
|
clearEvent: EventEmitter<void>;
|
|
3201
|
+
/** A number field is clearable when it holds any value (including 0). */
|
|
3202
|
+
protected get hasValue(): boolean;
|
|
3203
|
+
clearValue(): void;
|
|
1169
3204
|
private onChange;
|
|
1170
3205
|
private onTouched;
|
|
1171
3206
|
readonly ngControl: NgControl;
|
|
1172
|
-
private readonly translateService;
|
|
1173
3207
|
constructor();
|
|
1174
|
-
get effectivePlaceholder(): string;
|
|
1175
|
-
get effectiveId(): string;
|
|
1176
3208
|
get showRequired(): boolean;
|
|
1177
3209
|
get serverErrors(): string[] | null;
|
|
1178
3210
|
get isInvalid(): boolean;
|
|
@@ -1181,6 +3213,30 @@ declare class EfInputNumberComponent implements ControlValueAccessor {
|
|
|
1181
3213
|
registerOnTouched(fn: any): void;
|
|
1182
3214
|
setDisabledState(isDisabled: boolean): void;
|
|
1183
3215
|
handleInput(event: InputNumberInputEvent): void;
|
|
3216
|
+
/** Comptoir native input handler — the text input emits a raw
|
|
3217
|
+
* string; normalize + coerce to number or null (empty / invalid). */
|
|
3218
|
+
handleNativeInput(raw: string): void;
|
|
3219
|
+
/**
|
|
3220
|
+
* Parses comptoir free-text numeric entry.
|
|
3221
|
+
*
|
|
3222
|
+
* fr-MA users type commas as the decimal separator (`23,50`), while
|
|
3223
|
+
* `Number()` only understands `.` — so a comma is normalized to a
|
|
3224
|
+
* dot before parsing, and spaces (JS `\s` covers NBSP / narrow-NBSP
|
|
3225
|
+
* group separators) are stripped. Both `23,50` and `23.50` parse to
|
|
3226
|
+
* 23.5; unparseable text yields `null` (existing empty semantics).
|
|
3227
|
+
*/
|
|
3228
|
+
private parseComptoirValue;
|
|
3229
|
+
/**
|
|
3230
|
+
* Blur-time clamp for the comptoir variant. The native input no
|
|
3231
|
+
* longer carries `min` / `max` attributes (it's `type="text"`), so
|
|
3232
|
+
* range enforcement — previously only advisory on `type="number"`
|
|
3233
|
+
* anyway — happens here, and the field text is re-synced to the
|
|
3234
|
+
* canonical parsed value (e.g. a dangling `23,` becomes `23`).
|
|
3235
|
+
*/
|
|
3236
|
+
private clampAndReflect;
|
|
3237
|
+
/** Comptoir stepper buttons handler — bumps `value` by `step`,
|
|
3238
|
+
* clamped to `min` / `max`. */
|
|
3239
|
+
step$(direction: 1 | -1): void;
|
|
1184
3240
|
handleFocus(event: Event): void;
|
|
1185
3241
|
handleBlur(event: Event): void;
|
|
1186
3242
|
handleKeyDown(event: KeyboardEvent): void;
|
|
@@ -1188,20 +3244,14 @@ declare class EfInputNumberComponent implements ControlValueAccessor {
|
|
|
1188
3244
|
focus(): void;
|
|
1189
3245
|
clear(): void;
|
|
1190
3246
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfInputNumberComponent, never>;
|
|
1191
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfInputNumberComponent, "ef-inputnumber", never, { "
|
|
1192
|
-
static
|
|
3247
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfInputNumberComponent, "ef-inputnumber", never, { "value": { "alias": "value"; "required": false; }; "invalid": { "alias": "invalid"; "required": false; }; "format": { "alias": "format"; "required": false; }; "showButtons": { "alias": "showButtons"; "required": false; }; "buttonLayout": { "alias": "buttonLayout"; "required": false; }; "incrementButtonClass": { "alias": "incrementButtonClass"; "required": false; }; "decrementButtonClass": { "alias": "decrementButtonClass"; "required": false; }; "incrementButtonIcon": { "alias": "incrementButtonIcon"; "required": false; }; "decrementButtonIcon": { "alias": "decrementButtonIcon"; "required": false; }; "prefix": { "alias": "prefix"; "required": false; }; "suffix": { "alias": "suffix"; "required": false; }; "currency": { "alias": "currency"; "required": false; }; "currencyDisplay": { "alias": "currencyDisplay"; "required": false; }; "locale": { "alias": "locale"; "required": false; }; "localeMatcher": { "alias": "localeMatcher"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "useGrouping": { "alias": "useGrouping"; "required": false; }; "minFractionDigits": { "alias": "minFractionDigits"; "required": false; }; "maxFractionDigits": { "alias": "maxFractionDigits"; "required": false; }; "min": { "alias": "min"; "required": false; }; "max": { "alias": "max"; "required": false; }; "step": { "alias": "step"; "required": false; }; "allowEmpty": { "alias": "allowEmpty"; "required": false; }; "inputSize": { "alias": "inputSize"; "required": false; }; "size": { "alias": "size"; "required": false; }; "maxlength": { "alias": "maxlength"; "required": false; }; "minlength": { "alias": "minlength"; "required": false; }; "pattern": { "alias": "pattern"; "required": false; }; "tabindex": { "alias": "tabindex"; "required": false; }; "title": { "alias": "title"; "required": false; }; "ariaLabelledBy": { "alias": "ariaLabelledBy"; "required": false; }; "inputStyle": { "alias": "inputStyle"; "required": false; }; "inputStyleClass": { "alias": "inputStyleClass"; "required": false; }; "style": { "alias": "style"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "primeNgVariant": { "alias": "primeNgVariant"; "required": false; }; "autofocus": { "alias": "autofocus"; "required": false; }; "autocomplete": { "alias": "autocomplete"; "required": false; }; "fluid": { "alias": "fluid"; "required": false; }; "inline": { "alias": "inline"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "pt": { "alias": "pt"; "required": false; }; "ptOptions": { "alias": "ptOptions"; "required": false; }; "dt": { "alias": "dt"; "required": false; }; "unstyled": { "alias": "unstyled"; "required": false; }; }, { "inputEvent": "inputEvent"; "valueChangeEvent": "valueChangeEvent"; "focusEvent": "focusEvent"; "blurEvent": "blurEvent"; "keyDownEvent": "keyDownEvent"; "clearEvent": "clearEvent"; }, never, never, true, never>;
|
|
3248
|
+
static ngAcceptInputType_showButtons: unknown;
|
|
3249
|
+
static ngAcceptInputType_autofocus: unknown;
|
|
1193
3250
|
static ngAcceptInputType_inline: unknown;
|
|
1194
3251
|
}
|
|
1195
3252
|
|
|
1196
|
-
declare class EfPasswordComponent implements ControlValueAccessor {
|
|
1197
|
-
|
|
1198
|
-
labelKey?: string;
|
|
1199
|
-
inputId?: string;
|
|
1200
|
-
name?: string;
|
|
1201
|
-
placeholder?: string;
|
|
1202
|
-
placeholderKey?: string;
|
|
1203
|
-
size: 'small' | 'large';
|
|
1204
|
-
required: boolean;
|
|
3253
|
+
declare class EfPasswordComponent extends AbstractEfFormControl implements ControlValueAccessor {
|
|
3254
|
+
size?: 'small' | 'large';
|
|
1205
3255
|
fluid: boolean;
|
|
1206
3256
|
inline: boolean;
|
|
1207
3257
|
toggleMask: boolean;
|
|
@@ -1210,17 +3260,16 @@ declare class EfPasswordComponent implements ControlValueAccessor {
|
|
|
1210
3260
|
get isInline(): boolean;
|
|
1211
3261
|
valueChangeEvent: EventEmitter<string>;
|
|
1212
3262
|
value: string;
|
|
1213
|
-
disabled: boolean;
|
|
1214
3263
|
private onChange;
|
|
1215
3264
|
private onTouched;
|
|
1216
3265
|
readonly ngControl: NgControl;
|
|
1217
|
-
private readonly translateService;
|
|
1218
3266
|
constructor();
|
|
1219
|
-
get effectivePlaceholder(): string;
|
|
1220
|
-
get effectiveId(): string;
|
|
1221
3267
|
get showRequired(): boolean;
|
|
1222
3268
|
get serverErrors(): string[] | null;
|
|
1223
3269
|
get isInvalid(): boolean;
|
|
3270
|
+
/** Clearable hooks (showClear / canClear inherited from the base). */
|
|
3271
|
+
protected get hasValue(): boolean;
|
|
3272
|
+
clearValue(): void;
|
|
1224
3273
|
writeValue(value: string): void;
|
|
1225
3274
|
registerOnChange(fn: (value: string) => void): void;
|
|
1226
3275
|
registerOnTouched(fn: () => void): void;
|
|
@@ -1228,34 +3277,24 @@ declare class EfPasswordComponent implements ControlValueAccessor {
|
|
|
1228
3277
|
handleChange(value: string): void;
|
|
1229
3278
|
handleBlur(): void;
|
|
1230
3279
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfPasswordComponent, never>;
|
|
1231
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPasswordComponent, "ef-password", never, { "
|
|
1232
|
-
static ngAcceptInputType_required: unknown;
|
|
3280
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPasswordComponent, "ef-password", never, { "size": { "alias": "size"; "required": false; }; "fluid": { "alias": "fluid"; "required": false; }; "inline": { "alias": "inline"; "required": false; }; "toggleMask": { "alias": "toggleMask"; "required": false; }; "feedback": { "alias": "feedback"; "required": false; }; "autocomplete": { "alias": "autocomplete"; "required": false; }; }, { "valueChangeEvent": "valueChangeEvent"; }, never, never, true, never>;
|
|
1233
3281
|
static ngAcceptInputType_fluid: unknown;
|
|
1234
3282
|
static ngAcceptInputType_inline: unknown;
|
|
1235
3283
|
static ngAcceptInputType_toggleMask: unknown;
|
|
1236
3284
|
static ngAcceptInputType_feedback: unknown;
|
|
1237
3285
|
}
|
|
1238
3286
|
|
|
1239
|
-
declare class EfMultiSelectComponent implements ControlValueAccessor, OnChanges {
|
|
3287
|
+
declare class EfMultiSelectComponent extends AbstractEfFormControl implements ControlValueAccessor, OnChanges {
|
|
1240
3288
|
changeEvent: EventEmitter<string[]>;
|
|
1241
|
-
label?: string;
|
|
1242
|
-
labelKey?: string;
|
|
1243
|
-
id: string;
|
|
1244
|
-
name: string;
|
|
1245
3289
|
optionLabel: string;
|
|
1246
3290
|
optionValue: string;
|
|
1247
3291
|
options: any;
|
|
1248
3292
|
filteredOptions: any;
|
|
1249
3293
|
maxSelectedLabels: number;
|
|
1250
|
-
disabled: boolean;
|
|
1251
3294
|
display: 'comma' | 'chip';
|
|
1252
3295
|
size: 'large' | 'small';
|
|
1253
3296
|
selectionLimit: any;
|
|
1254
3297
|
filters: any;
|
|
1255
|
-
placeholder: string;
|
|
1256
|
-
placeholderKey?: string;
|
|
1257
|
-
showClear: boolean;
|
|
1258
|
-
required: boolean;
|
|
1259
3298
|
inline: boolean;
|
|
1260
3299
|
get isInline(): boolean;
|
|
1261
3300
|
get isRequired(): boolean;
|
|
@@ -1263,9 +3302,7 @@ declare class EfMultiSelectComponent implements ControlValueAccessor, OnChanges
|
|
|
1263
3302
|
private propagateChange;
|
|
1264
3303
|
private propagateTouched;
|
|
1265
3304
|
readonly ngControl: NgControl;
|
|
1266
|
-
private readonly translateService;
|
|
1267
3305
|
constructor();
|
|
1268
|
-
get effectivePlaceholder(): string;
|
|
1269
3306
|
get showRequired(): boolean;
|
|
1270
3307
|
get serverErrors(): string[] | null;
|
|
1271
3308
|
writeValue(value: string[]): void;
|
|
@@ -1277,22 +3314,16 @@ declare class EfMultiSelectComponent implements ControlValueAccessor, OnChanges
|
|
|
1277
3314
|
ngOnChanges(): void;
|
|
1278
3315
|
private applyFilters;
|
|
1279
3316
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfMultiSelectComponent, never>;
|
|
1280
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfMultiSelectComponent, "ef-multi-select", never, { "
|
|
1281
|
-
static ngAcceptInputType_showClear: unknown;
|
|
3317
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfMultiSelectComponent, "ef-multi-select", never, { "optionLabel": { "alias": "optionLabel"; "required": false; }; "optionValue": { "alias": "optionValue"; "required": false; }; "options": { "alias": "options"; "required": false; }; "filteredOptions": { "alias": "filteredOptions"; "required": false; }; "maxSelectedLabels": { "alias": "maxSelectedLabels"; "required": false; }; "display": { "alias": "display"; "required": false; }; "size": { "alias": "size"; "required": false; }; "selectionLimit": { "alias": "selectionLimit"; "required": false; }; "filters": { "alias": "filters"; "required": false; }; "inline": { "alias": "inline"; "required": false; }; }, { "changeEvent": "changeEvent"; }, never, never, true, never>;
|
|
1282
3318
|
static ngAcceptInputType_inline: unknown;
|
|
1283
3319
|
}
|
|
1284
3320
|
|
|
1285
|
-
declare class EfSelectButtonComponent implements ControlValueAccessor {
|
|
1286
|
-
/** Direct label text above the selectbutton (not translated) */
|
|
1287
|
-
label?: string;
|
|
1288
|
-
/** Translation key for label — takes priority over label */
|
|
1289
|
-
labelKey?: string;
|
|
3321
|
+
declare class EfSelectButtonComponent extends AbstractEfFormControl implements ControlValueAccessor {
|
|
1290
3322
|
options: any[];
|
|
1291
3323
|
optionLabel: string;
|
|
1292
3324
|
optionValue: string;
|
|
1293
3325
|
multiple: boolean;
|
|
1294
3326
|
allowEmpty: boolean;
|
|
1295
|
-
disabled: boolean;
|
|
1296
3327
|
size: 'small' | 'large';
|
|
1297
3328
|
styleClass?: string;
|
|
1298
3329
|
itemTemplate?: TemplateRef<any>;
|
|
@@ -1307,10 +3338,9 @@ declare class EfSelectButtonComponent implements ControlValueAccessor {
|
|
|
1307
3338
|
setDisabledState(isDisabled: boolean): void;
|
|
1308
3339
|
handleChange(event: any): void;
|
|
1309
3340
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfSelectButtonComponent, never>;
|
|
1310
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfSelectButtonComponent, "ef-selectbutton", never, { "
|
|
3341
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfSelectButtonComponent, "ef-selectbutton", never, { "options": { "alias": "options"; "required": false; }; "optionLabel": { "alias": "optionLabel"; "required": false; }; "optionValue": { "alias": "optionValue"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "allowEmpty": { "alias": "allowEmpty"; "required": false; }; "size": { "alias": "size"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; }, {}, ["itemTemplate"], never, true, never>;
|
|
1311
3342
|
static ngAcceptInputType_multiple: unknown;
|
|
1312
3343
|
static ngAcceptInputType_allowEmpty: unknown;
|
|
1313
|
-
static ngAcceptInputType_disabled: unknown;
|
|
1314
3344
|
}
|
|
1315
3345
|
|
|
1316
3346
|
/**
|
|
@@ -1749,6 +3779,1033 @@ declare class EfDatatableActionBarComponent {
|
|
|
1749
3779
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfDatatableActionBarComponent, "ef-datatable-actionbar", never, { "context": { "alias": "context"; "required": false; }; "state": { "alias": "state"; "required": false; }; "duplicateButton": { "alias": "duplicateButton"; "required": false; }; "editButton": { "alias": "editButton"; "required": false; }; "deleteButton": { "alias": "deleteButton"; "required": false; }; }, { "duplicate": "duplicate"; "edit": "edit"; "delete": "delete"; }, never, never, true, never>;
|
|
1750
3780
|
}
|
|
1751
3781
|
|
|
3782
|
+
/**
|
|
3783
|
+
* Declarative row-action item consumed by `ef-row-actions`.
|
|
3784
|
+
*
|
|
3785
|
+
* The component renders a native Comptoir-styled popup (no PrimeNG
|
|
3786
|
+
* Menu) so the design — kbd hint, danger tone, divider, ink-active
|
|
3787
|
+
* trigger when open — matches the prototype 1:1.
|
|
3788
|
+
*
|
|
3789
|
+
* Use `command` for actions, `separator: true` for a divider line.
|
|
3790
|
+
*/
|
|
3791
|
+
interface EfRowAction {
|
|
3792
|
+
/** Stable identifier for trackBy / tests. */
|
|
3793
|
+
id?: string;
|
|
3794
|
+
/** Translation key — preferred. */
|
|
3795
|
+
labelKey?: string;
|
|
3796
|
+
/** Direct label — used only when `labelKey` is empty. */
|
|
3797
|
+
label?: string;
|
|
3798
|
+
/** PrimeIcons class (e.g. `'pi pi-pencil'`). */
|
|
3799
|
+
icon?: string;
|
|
3800
|
+
/** Optional keyboard-shortcut hint shown right-aligned (e.g. `'↵'`, `'E'`, `'⌘D'`). */
|
|
3801
|
+
kbd?: string;
|
|
3802
|
+
/** Tone: `'danger'` styles destructive items in the cancelled palette. */
|
|
3803
|
+
severity?: 'default' | 'danger';
|
|
3804
|
+
/** Render a divider in this slot — all other fields ignored. */
|
|
3805
|
+
separator?: boolean;
|
|
3806
|
+
/** Disable without removing. */
|
|
3807
|
+
disabled?: boolean;
|
|
3808
|
+
/**
|
|
3809
|
+
* Hide the item explicitly. Combined with `permission` and any
|
|
3810
|
+
* caller-supplied filter; defaults to `true` (visible).
|
|
3811
|
+
*/
|
|
3812
|
+
visible?: boolean;
|
|
3813
|
+
/**
|
|
3814
|
+
* If set, the item is hidden unless the bound `ScreenContext`
|
|
3815
|
+
* grants this permission. Items with no `permission` always show.
|
|
3816
|
+
*/
|
|
3817
|
+
permission?: Permissions;
|
|
3818
|
+
/** Click handler. The container handles closing the popup. */
|
|
3819
|
+
command?: () => void;
|
|
3820
|
+
}
|
|
3821
|
+
|
|
3822
|
+
/** Action identifier emitted by `ef-data-card`'s auto row-actions cell. */
|
|
3823
|
+
type EfDataCardRowAction = 'view' | 'edit' | 'duplicate' | 'delete';
|
|
3824
|
+
/**
|
|
3825
|
+
* Comptoir data card — column-driven `.tbl-wrap` with header (count
|
|
3826
|
+
* info + actions) and integrated pager.
|
|
3827
|
+
*
|
|
3828
|
+
* Two consumer surfaces:
|
|
3829
|
+
* 1. **Columns + rows + templates** (preferred): declare columns in
|
|
3830
|
+
* TS as `EfDataCardColumn[]`, project body / header templates via
|
|
3831
|
+
* `*efColumnTemplate` / `*efColumnHeaderTemplate` for cells that
|
|
3832
|
+
* need rich HTML. Built-in cell renderers handle text / number /
|
|
3833
|
+
* money / date / datetime / boolean / mono / chip / reference.
|
|
3834
|
+
* 2. **`tbl-head-info` / `tbl-head-actions` slots**: still projected
|
|
3835
|
+
* so the consumer can render the count text + density / columns /
|
|
3836
|
+
* view-toggle buttons next to the table header.
|
|
3837
|
+
*
|
|
3838
|
+
* ```html
|
|
3839
|
+
* <ef-data-card
|
|
3840
|
+
* [columns]="cols"
|
|
3841
|
+
* [rows]="orders()"
|
|
3842
|
+
* [pageNumber]="criteria().pagination.pageNumber"
|
|
3843
|
+
* [pageSize]="criteria().pagination.pageSize"
|
|
3844
|
+
* [totalCount]="totalCount()"
|
|
3845
|
+
* [loading]="loading()"
|
|
3846
|
+
* [sort]="currentSort()"
|
|
3847
|
+
* (pageChange)="setPage($event)"
|
|
3848
|
+
* (sortChange)="setSort($event.field, $event.direction)"
|
|
3849
|
+
* trackByField="id"
|
|
3850
|
+
* >
|
|
3851
|
+
* <span tbl-head-info>…count…</span>
|
|
3852
|
+
*
|
|
3853
|
+
* <ng-template efColumnTemplate="status" let-row>
|
|
3854
|
+
* <span class="chip" [class]="'chip chip-' + row.status">…</span>
|
|
3855
|
+
* </ng-template>
|
|
3856
|
+
* </ef-data-card>
|
|
3857
|
+
* ```
|
|
3858
|
+
*/
|
|
3859
|
+
declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
|
|
3860
|
+
private readonly refDataService;
|
|
3861
|
+
readonly columns: _angular_core.InputSignal<readonly EfDataCardColumn[]>;
|
|
3862
|
+
readonly rows: _angular_core.InputSignal<readonly TRow[]>;
|
|
3863
|
+
/** Field path on each row used as the trackBy key. */
|
|
3864
|
+
readonly trackByField: _angular_core.InputSignal<string>;
|
|
3865
|
+
readonly pageNumber: _angular_core.InputSignal<number>;
|
|
3866
|
+
readonly pageSize: _angular_core.InputSignal<number>;
|
|
3867
|
+
readonly totalCount: _angular_core.InputSignal<number>;
|
|
3868
|
+
readonly pageSizeOptions: _angular_core.InputSignal<readonly number[]>;
|
|
3869
|
+
readonly hidePager: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
3870
|
+
/** Currently active sort. Header click toggles asc / desc. */
|
|
3871
|
+
readonly sort: _angular_core.InputSignal<EfDataCardSort>;
|
|
3872
|
+
readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
3873
|
+
/** Empty string = no error. Non-empty triggers an error chip in tbl-head. */
|
|
3874
|
+
readonly errorMsg: _angular_core.InputSignal<string>;
|
|
3875
|
+
readonly loadingKey: _angular_core.InputSignal<string>;
|
|
3876
|
+
/**
|
|
3877
|
+
* When `true`, double-clicking anywhere on a `<tr>` emits the row
|
|
3878
|
+
* via `rowDoubleClick` and the body rows render with
|
|
3879
|
+
* `cursor: pointer`. Consumers typically wire the output to
|
|
3880
|
+
* `navigateToDetails(row.id)` from {@link AbstractSearchScreenV2}.
|
|
3881
|
+
*
|
|
3882
|
+
* Double-clicks that originate inside an interactive child
|
|
3883
|
+
* (checkbox, button, link, form control) are ignored — those keep
|
|
3884
|
+
* their native behaviour (toggle selection, run an action, …).
|
|
3885
|
+
*/
|
|
3886
|
+
readonly rowDoubleClickable: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
3887
|
+
readonly hasActionsColumn: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
3888
|
+
readonly rowActionsContext: _angular_core.InputSignal<ScreenContext>;
|
|
3889
|
+
readonly showViewAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
3890
|
+
readonly showEditAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
3891
|
+
readonly showDuplicateAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
3892
|
+
readonly showDeleteAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
3893
|
+
readonly pageChange: _angular_core.OutputEmitterRef<number>;
|
|
3894
|
+
readonly pageSizeChange: _angular_core.OutputEmitterRef<number>;
|
|
3895
|
+
readonly sortChange: _angular_core.OutputEmitterRef<EfDataCardSort>;
|
|
3896
|
+
readonly rowDoubleClick: _angular_core.OutputEmitterRef<TRow>;
|
|
3897
|
+
/** Emitted by the auto row-actions cell — `{ action, row }`. */
|
|
3898
|
+
readonly rowAction: _angular_core.OutputEmitterRef<{
|
|
3899
|
+
action: EfDataCardRowAction;
|
|
3900
|
+
row: TRow;
|
|
3901
|
+
}>;
|
|
3902
|
+
private readonly bodyTemplates;
|
|
3903
|
+
private readonly headerTemplates;
|
|
3904
|
+
private readonly bodyTemplateMap;
|
|
3905
|
+
private readonly headerTemplateMap;
|
|
3906
|
+
ngAfterContentInit(): void;
|
|
3907
|
+
/** Columns enriched with effective alignment / sortField defaults
|
|
3908
|
+
* + the auto `'actions'` column when `[hasActionsColumn]` is on
|
|
3909
|
+
* and the consumer hasn't declared one already. */
|
|
3910
|
+
readonly effectiveColumns: _angular_core.Signal<readonly EfDataCardColumn[]>;
|
|
3911
|
+
/** Items array for the auto row-actions cell. Rebuilt per call so
|
|
3912
|
+
* the ef-row-actions component receives a fresh closure per row.
|
|
3913
|
+
* Visibility is filtered later by ef-row-actions against
|
|
3914
|
+
* `rowActionsContext` (ScreenContext.isGranted). */
|
|
3915
|
+
defaultRowActions(row: TRow): ReadonlyArray<EfRowAction>;
|
|
3916
|
+
bodyTemplate(columnId: string): TemplateRef<unknown> | undefined;
|
|
3917
|
+
headerTemplate(columnId: string): TemplateRef<unknown> | undefined;
|
|
3918
|
+
/** Pluck `column.field` (or `column.id`) from a row, dotted-path safe. */
|
|
3919
|
+
cellValue(row: TRow, col: EfDataCardColumn): unknown;
|
|
3920
|
+
headerAlignClass(col: EfDataCardColumn): string;
|
|
3921
|
+
cellAlignClass(col: EfDataCardColumn): string;
|
|
3922
|
+
/** Sort indicator: '↑' / '↓' / '' for the given column. */
|
|
3923
|
+
sortIndicator(col: EfDataCardColumn): string;
|
|
3924
|
+
/**
|
|
3925
|
+
* Resolve a reference cell — looks up the row's value in
|
|
3926
|
+
* `referenceKey`, finds the entry where
|
|
3927
|
+
* `entry[referenceValueField] === value`, returns
|
|
3928
|
+
* `entry[referenceLabelField]`. Falls back to the raw value when
|
|
3929
|
+
* no match is found.
|
|
3930
|
+
*/
|
|
3931
|
+
resolveReference(value: unknown, col: EfDataCardColumn): string;
|
|
3932
|
+
/** Build an Angular DigitInfo string from min/max fraction-digit hints. */
|
|
3933
|
+
numberFormat(col: EfDataCardColumn): string;
|
|
3934
|
+
/** Tracks how many `ef-row-actions` are currently open inside this
|
|
3935
|
+
* card. When > 0, `.tbl-wrap` lifts its `overflow: hidden` so the
|
|
3936
|
+
* popup can escape its rounded edges. */
|
|
3937
|
+
readonly openMenuCount: _angular_core.WritableSignal<number>;
|
|
3938
|
+
onRowActionsToggle(event: Event): void;
|
|
3939
|
+
/** Fires `rowDoubleClick` unless the dblclick originated on an
|
|
3940
|
+
* interactive child (checkbox, button, link, form control). */
|
|
3941
|
+
onRowDoubleClick(row: TRow, event: MouseEvent): void;
|
|
3942
|
+
onHeaderClick(col: EfDataCardColumn): void;
|
|
3943
|
+
trackByRow: (_: number, row: TRow) => unknown;
|
|
3944
|
+
trackByColumn: (_: number, col: EfDataCardColumn) => string;
|
|
3945
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfDataCardComponent<any>, never>;
|
|
3946
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfDataCardComponent<any>, "ef-data-card", never, { "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "trackByField": { "alias": "trackByField"; "required": false; "isSignal": true; }; "pageNumber": { "alias": "pageNumber"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "totalCount": { "alias": "totalCount"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "hidePager": { "alias": "hidePager"; "required": false; "isSignal": true; }; "sort": { "alias": "sort"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "errorMsg": { "alias": "errorMsg"; "required": false; "isSignal": true; }; "loadingKey": { "alias": "loadingKey"; "required": false; "isSignal": true; }; "rowDoubleClickable": { "alias": "rowDoubleClickable"; "required": false; "isSignal": true; }; "hasActionsColumn": { "alias": "hasActionsColumn"; "required": false; "isSignal": true; }; "rowActionsContext": { "alias": "rowActionsContext"; "required": false; "isSignal": true; }; "showViewAction": { "alias": "showViewAction"; "required": false; "isSignal": true; }; "showEditAction": { "alias": "showEditAction"; "required": false; "isSignal": true; }; "showDuplicateAction": { "alias": "showDuplicateAction"; "required": false; "isSignal": true; }; "showDeleteAction": { "alias": "showDeleteAction"; "required": false; "isSignal": true; }; }, { "pageChange": "pageChange"; "pageSizeChange": "pageSizeChange"; "sortChange": "sortChange"; "rowDoubleClick": "rowDoubleClick"; "rowAction": "rowAction"; }, ["bodyTemplates", "headerTemplates"], ["[tbl-head-info]", "[tbl-head-actions]", "[empty-state]"], true, never>;
|
|
3947
|
+
}
|
|
3948
|
+
|
|
3949
|
+
/**
|
|
3950
|
+
* Marks an `<ng-template>` as the body cell renderer for a given
|
|
3951
|
+
* column id on `<ef-data-card>`.
|
|
3952
|
+
*
|
|
3953
|
+
* ```html
|
|
3954
|
+
* <ng-template efColumnTemplate="status" let-row let-col="col">
|
|
3955
|
+
* <span class="chip" [class]="'chip chip-' + row.status">…</span>
|
|
3956
|
+
* </ng-template>
|
|
3957
|
+
* ```
|
|
3958
|
+
*
|
|
3959
|
+
* Context:
|
|
3960
|
+
* - `$implicit` — the row data
|
|
3961
|
+
* - `col` — the column config (`EfDataCardColumn`)
|
|
3962
|
+
* - `index` — the row index in the current page
|
|
3963
|
+
*/
|
|
3964
|
+
declare class EfColumnTemplateDirective {
|
|
3965
|
+
readonly templateRef: TemplateRef<unknown>;
|
|
3966
|
+
columnId: string;
|
|
3967
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfColumnTemplateDirective, never>;
|
|
3968
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<EfColumnTemplateDirective, "[efColumnTemplate]", never, { "columnId": { "alias": "efColumnTemplate"; "required": true; }; }, {}, never, never, true, never>;
|
|
3969
|
+
}
|
|
3970
|
+
/**
|
|
3971
|
+
* Marks an `<ng-template>` as the **header** cell renderer for a
|
|
3972
|
+
* given column id. Use this when the header needs richer markup
|
|
3973
|
+
* than a translated string (e.g. a select-all checkbox).
|
|
3974
|
+
*
|
|
3975
|
+
* ```html
|
|
3976
|
+
* <ng-template efColumnHeaderTemplate="select">
|
|
3977
|
+
* <input type="checkbox" class="cb"
|
|
3978
|
+
* [checked]="allSelected()" (change)="toggleAll()" />
|
|
3979
|
+
* </ng-template>
|
|
3980
|
+
* ```
|
|
3981
|
+
*/
|
|
3982
|
+
declare class EfColumnHeaderTemplateDirective {
|
|
3983
|
+
readonly templateRef: TemplateRef<unknown>;
|
|
3984
|
+
columnId: string;
|
|
3985
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfColumnHeaderTemplateDirective, never>;
|
|
3986
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<EfColumnHeaderTemplateDirective, "[efColumnHeaderTemplate]", never, { "columnId": { "alias": "efColumnHeaderTemplate"; "required": true; }; }, {}, never, never, true, never>;
|
|
3987
|
+
}
|
|
3988
|
+
|
|
3989
|
+
/**
|
|
3990
|
+
* Row-actions dropdown — V2 successor to `ef-datatable-actionbar`.
|
|
3991
|
+
*
|
|
3992
|
+
* Renders a discreet trailing-cell ⋯ trigger (34×28 pill) that opens
|
|
3993
|
+
* a small Comptoir-styled menu with the items declared in TS:
|
|
3994
|
+
*
|
|
3995
|
+
* ```ts
|
|
3996
|
+
* actions: ReadonlyArray<EfRowAction> = [
|
|
3997
|
+
* { id: 'view', labelKey: 'common_view', icon: 'pi pi-eye', kbd: '↵',
|
|
3998
|
+
* permission: Permissions.Read, command: () => view(row) },
|
|
3999
|
+
* { id: 'edit', labelKey: 'common_edit', icon: 'pi pi-pencil', kbd: 'E',
|
|
4000
|
+
* permission: Permissions.Edit, command: () => edit(row) },
|
|
4001
|
+
* { id: 'duplicate', labelKey: 'common_duplicate', icon: 'pi pi-copy',
|
|
4002
|
+
* command: () => duplicate(row) },
|
|
4003
|
+
* { separator: true },
|
|
4004
|
+
* { id: 'delete', labelKey: 'common_delete', icon: 'pi pi-trash', severity: 'danger',
|
|
4005
|
+
* permission: Permissions.Delete, command: () => delete(row) },
|
|
4006
|
+
* ];
|
|
4007
|
+
* ```
|
|
4008
|
+
*
|
|
4009
|
+
* ```html
|
|
4010
|
+
* <ng-template efColumnTemplate="actions" let-row>
|
|
4011
|
+
* <ef-row-actions [items]="rowActions(row)" [context]="context" />
|
|
4012
|
+
* </ng-template>
|
|
4013
|
+
* ```
|
|
4014
|
+
*
|
|
4015
|
+
* Behaviour:
|
|
4016
|
+
* - Click the trigger to toggle. Trigger gets `.open` (ink-active) while the menu is open.
|
|
4017
|
+
* - Click outside or press `Escape` to close.
|
|
4018
|
+
* - Clicking an item runs its `command` then closes the menu.
|
|
4019
|
+
* - dblclick on the trigger or menu does NOT propagate, so the data-card's
|
|
4020
|
+
* `rowDoubleClickable` won't fire from this column.
|
|
4021
|
+
*
|
|
4022
|
+
* Permission filtering: pass `[context]="..."` (a `ScreenContext`); items
|
|
4023
|
+
* declaring a `permission` are hidden unless that permission is granted.
|
|
4024
|
+
* Items with no `permission` always show.
|
|
4025
|
+
*/
|
|
4026
|
+
declare class EfRowActionsComponent {
|
|
4027
|
+
private readonly host;
|
|
4028
|
+
/** Action descriptors. */
|
|
4029
|
+
readonly items: _angular_core.InputSignal<readonly EfRowAction[]>;
|
|
4030
|
+
/** Optional context — when present, items with a `permission` are
|
|
4031
|
+
* filtered against `context.isGranted(permission)`. */
|
|
4032
|
+
readonly context: _angular_core.InputSignal<ScreenContext>;
|
|
4033
|
+
/** Override the trigger icon (default ellipsis). */
|
|
4034
|
+
readonly triggerIcon: _angular_core.InputSignal<string>;
|
|
4035
|
+
/** Override the trigger aria-label translation key. */
|
|
4036
|
+
readonly triggerAriaKey: _angular_core.InputSignal<string>;
|
|
4037
|
+
/** Disable the entire trigger (e.g., row not actionable). */
|
|
4038
|
+
readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4039
|
+
/**
|
|
4040
|
+
* Pin the menu to the inline-start edge of the trigger instead of
|
|
4041
|
+
* inline-end. Use when the actions cell sits at the start of the row.
|
|
4042
|
+
*/
|
|
4043
|
+
readonly menuLeft: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4044
|
+
/** Forwarded when the menu opens (e.g., for a data-card to lift overflow). */
|
|
4045
|
+
readonly opened: _angular_core.OutputEmitterRef<void>;
|
|
4046
|
+
/** Forwarded when the menu closes. */
|
|
4047
|
+
readonly closed: _angular_core.OutputEmitterRef<void>;
|
|
4048
|
+
/** Visible items (after permission + visible filtering). */
|
|
4049
|
+
readonly visibleItems: _angular_core.Signal<readonly EfRowAction[]>;
|
|
4050
|
+
/** Open state. */
|
|
4051
|
+
readonly open: _angular_core.WritableSignal<boolean>;
|
|
4052
|
+
toggle(event: MouseEvent): void;
|
|
4053
|
+
runCommand(action: EfRowAction, event: MouseEvent): void;
|
|
4054
|
+
close(): void;
|
|
4055
|
+
/** Bubbling DOM event so ancestors (e.g. ef-data-card) can react —
|
|
4056
|
+
* see `.tbl-wrap.has-open-menu { overflow: visible }`. */
|
|
4057
|
+
private dispatchToggle;
|
|
4058
|
+
/** Outside click — closes the menu. */
|
|
4059
|
+
onDocumentClick(event: MouseEvent): void;
|
|
4060
|
+
/** Escape closes the menu. */
|
|
4061
|
+
onEscape(): void;
|
|
4062
|
+
/** Swallow dblclick so row-double-click doesn't fire from this column. */
|
|
4063
|
+
onDblClick(event: MouseEvent): void;
|
|
4064
|
+
private isVisible;
|
|
4065
|
+
/** Stable trackBy across renders. */
|
|
4066
|
+
trackByItem: (i: number, action: EfRowAction) => unknown;
|
|
4067
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfRowActionsComponent, never>;
|
|
4068
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfRowActionsComponent, "ef-row-actions", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "context": { "alias": "context"; "required": false; "isSignal": true; }; "triggerIcon": { "alias": "triggerIcon"; "required": false; "isSignal": true; }; "triggerAriaKey": { "alias": "triggerAriaKey"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "menuLeft": { "alias": "menuLeft"; "required": false; "isSignal": true; }; }, { "opened": "opened"; "closed": "closed"; }, never, never, true, never>;
|
|
4069
|
+
}
|
|
4070
|
+
|
|
4071
|
+
interface PageBtn {
|
|
4072
|
+
kind: 'page' | 'ellipsis';
|
|
4073
|
+
value: number;
|
|
4074
|
+
}
|
|
4075
|
+
/**
|
|
4076
|
+
* Pagination control matching the Comptoir prototype's `.pager`
|
|
4077
|
+
* shape (lines-per-page selector · range · page buttons).
|
|
4078
|
+
*
|
|
4079
|
+
* ```html
|
|
4080
|
+
* <ef-pager
|
|
4081
|
+
* [pageNumber]="criteria().pagination.pageNumber"
|
|
4082
|
+
* [pageSize]="criteria().pagination.pageSize"
|
|
4083
|
+
* [totalCount]="totalCount()"
|
|
4084
|
+
* (pageChange)="setPage($event)"
|
|
4085
|
+
* (pageSizeChange)="setPage(1, $event)"
|
|
4086
|
+
* />
|
|
4087
|
+
* ```
|
|
4088
|
+
*
|
|
4089
|
+
* Renders a windowed page list (first / current ±1 / last with
|
|
4090
|
+
* ellipsis) for total > 7 pages. Below 7 pages all buttons show.
|
|
4091
|
+
*/
|
|
4092
|
+
declare class EfPagerComponent {
|
|
4093
|
+
readonly pageNumber: _angular_core.InputSignal<number>;
|
|
4094
|
+
readonly pageSize: _angular_core.InputSignal<number>;
|
|
4095
|
+
readonly totalCount: _angular_core.InputSignal<number>;
|
|
4096
|
+
readonly pageSizeOptions: _angular_core.InputSignal<readonly number[]>;
|
|
4097
|
+
/** Translation keys (preferred — consumer-side i18n). */
|
|
4098
|
+
readonly linesPerPageLabelKey: _angular_core.InputSignal<string>;
|
|
4099
|
+
readonly ofLabelKey: _angular_core.InputSignal<string>;
|
|
4100
|
+
readonly prevLabelKey: _angular_core.InputSignal<string>;
|
|
4101
|
+
readonly nextLabelKey: _angular_core.InputSignal<string>;
|
|
4102
|
+
/** Hide the lines-per-page selector + range when only paging is wanted. */
|
|
4103
|
+
readonly hideSize: _angular_core.InputSignal<boolean>;
|
|
4104
|
+
readonly pageChange: _angular_core.OutputEmitterRef<number>;
|
|
4105
|
+
readonly pageSizeChange: _angular_core.OutputEmitterRef<number>;
|
|
4106
|
+
readonly totalPages: _angular_core.Signal<number>;
|
|
4107
|
+
readonly range: _angular_core.Signal<{
|
|
4108
|
+
start: number;
|
|
4109
|
+
end: number;
|
|
4110
|
+
}>;
|
|
4111
|
+
/** First page · current ±1 · last page, with ellipsis fillers. */
|
|
4112
|
+
readonly pageButtons: _angular_core.Signal<readonly PageBtn[]>;
|
|
4113
|
+
goToPage(page: number): void;
|
|
4114
|
+
onSizeChange(value: string): void;
|
|
4115
|
+
trackBtn(index: number, btn: PageBtn): string;
|
|
4116
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfPagerComponent, never>;
|
|
4117
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPagerComponent, "ef-pager", never, { "pageNumber": { "alias": "pageNumber"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "totalCount": { "alias": "totalCount"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "linesPerPageLabelKey": { "alias": "linesPerPageLabelKey"; "required": false; "isSignal": true; }; "ofLabelKey": { "alias": "ofLabelKey"; "required": false; "isSignal": true; }; "prevLabelKey": { "alias": "prevLabelKey"; "required": false; "isSignal": true; }; "nextLabelKey": { "alias": "nextLabelKey"; "required": false; "isSignal": true; }; "hideSize": { "alias": "hideSize"; "required": false; "isSignal": true; }; }, { "pageChange": "pageChange"; "pageSizeChange": "pageSizeChange"; }, never, never, true, never>;
|
|
4118
|
+
}
|
|
4119
|
+
|
|
4120
|
+
/**
|
|
4121
|
+
* Comptoir bulk-action bar — ink-active pill that shows a selection
|
|
4122
|
+
* count + projected action buttons. Auto-hides when count is 0.
|
|
4123
|
+
*
|
|
4124
|
+
* ```html
|
|
4125
|
+
* <ef-bulk-bar [count]="selectionCount()">
|
|
4126
|
+
* <button class="btn">{{ 'common_export' | translate }}</button>
|
|
4127
|
+
* <button class="btn">{{ 'sales_orders_bulk_approve' | translate }}</button>
|
|
4128
|
+
* </ef-bulk-bar>
|
|
4129
|
+
* ```
|
|
4130
|
+
*/
|
|
4131
|
+
declare class EfBulkBarComponent {
|
|
4132
|
+
readonly count: _angular_core.InputSignal<number>;
|
|
4133
|
+
/** Translation key for the suffix word ("selected"). */
|
|
4134
|
+
readonly suffixKey: _angular_core.InputSignal<string>;
|
|
4135
|
+
/** Direct suffix text (used only when `suffixKey` is empty). */
|
|
4136
|
+
readonly suffix: _angular_core.InputSignal<string>;
|
|
4137
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfBulkBarComponent, never>;
|
|
4138
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfBulkBarComponent, "ef-bulk-bar", never, { "count": { "alias": "count"; "required": false; "isSignal": true; }; "suffixKey": { "alias": "suffixKey"; "required": false; "isSignal": true; }; "suffix": { "alias": "suffix"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
4139
|
+
}
|
|
4140
|
+
|
|
4141
|
+
/**
|
|
4142
|
+
* Comptoir empty-state — circular dashed icon + title + optional
|
|
4143
|
+
* message + projected actions slot. Drop into a data-card body when
|
|
4144
|
+
* results are zero.
|
|
4145
|
+
*
|
|
4146
|
+
* ```html
|
|
4147
|
+
* <ef-empty-state
|
|
4148
|
+
* icon="pi pi-inbox"
|
|
4149
|
+
* titleKey="sales_orders_empty_title"
|
|
4150
|
+
* messageKey="sales_orders_empty_msg">
|
|
4151
|
+
* <button class="btn btn-tenant btn-sm">{{ 'sales_orders_new' | translate }}</button>
|
|
4152
|
+
* </ef-empty-state>
|
|
4153
|
+
* ```
|
|
4154
|
+
*/
|
|
4155
|
+
declare class EfEmptyStateComponent {
|
|
4156
|
+
readonly icon: _angular_core.InputSignal<string>;
|
|
4157
|
+
readonly titleKey: _angular_core.InputSignal<string>;
|
|
4158
|
+
readonly title: _angular_core.InputSignal<string>;
|
|
4159
|
+
readonly messageKey: _angular_core.InputSignal<string>;
|
|
4160
|
+
readonly message: _angular_core.InputSignal<string>;
|
|
4161
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfEmptyStateComponent, never>;
|
|
4162
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfEmptyStateComponent, "ef-empty-state", never, { "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "titleKey": { "alias": "titleKey"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "messageKey": { "alias": "messageKey"; "required": false; "isSignal": true; }; "message": { "alias": "message"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
4163
|
+
}
|
|
4164
|
+
|
|
4165
|
+
/**
|
|
4166
|
+
* Comptoir smart bar — the search/filter card every list screen
|
|
4167
|
+
* starts with. Composes:
|
|
4168
|
+
* 1. Search input (with `⌘K` kbd hint) + Effacer / Rechercher
|
|
4169
|
+
* action buttons.
|
|
4170
|
+
* 2. A filter-row slot for `[filters]` (pill-group + filter-pill +
|
|
4171
|
+
* preset-pill + "+ Plus de filtres").
|
|
4172
|
+
* 3. A drawer slot for `[drawer]` (advanced filters via
|
|
4173
|
+
* `ef-filter-drawer`).
|
|
4174
|
+
*
|
|
4175
|
+
* The `searchText` is a `model()` so consumers can `[(searchText)]`
|
|
4176
|
+
* for two-way binding, or watch the (search) output for explicit
|
|
4177
|
+
* Rechercher clicks.
|
|
4178
|
+
*
|
|
4179
|
+
* ```html
|
|
4180
|
+
* <ef-smart-bar
|
|
4181
|
+
* [(searchText)]="searchQuery"
|
|
4182
|
+
* placeholderKey="sales_orders_search_placeholder"
|
|
4183
|
+
* (search)="setSearchText($event)"
|
|
4184
|
+
* (clear)="clearAll()"
|
|
4185
|
+
* >
|
|
4186
|
+
* <ng-container filters>
|
|
4187
|
+
* <ef-pill-group …/>
|
|
4188
|
+
* <ef-filter-pill …/>
|
|
4189
|
+
* <ef-preset-pill …/>
|
|
4190
|
+
* </ng-container>
|
|
4191
|
+
* <ng-container drawer>
|
|
4192
|
+
* <ef-filter-drawer …/>
|
|
4193
|
+
* </ng-container>
|
|
4194
|
+
* </ef-smart-bar>
|
|
4195
|
+
* ```
|
|
4196
|
+
*/
|
|
4197
|
+
declare class EfSmartBarComponent {
|
|
4198
|
+
/** Two-way bound search input. */
|
|
4199
|
+
readonly searchText: _angular_core.ModelSignal<string>;
|
|
4200
|
+
readonly placeholderKey: _angular_core.InputSignal<string>;
|
|
4201
|
+
readonly placeholder: _angular_core.InputSignal<string>;
|
|
4202
|
+
readonly clearLabelKey: _angular_core.InputSignal<string>;
|
|
4203
|
+
readonly clearTitleKey: _angular_core.InputSignal<string>;
|
|
4204
|
+
readonly searchLabelKey: _angular_core.InputSignal<string>;
|
|
4205
|
+
readonly showKbdHint: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4206
|
+
readonly hideClear: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4207
|
+
readonly hideSearch: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4208
|
+
readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4209
|
+
readonly search: _angular_core.OutputEmitterRef<string>;
|
|
4210
|
+
readonly clear: _angular_core.OutputEmitterRef<void>;
|
|
4211
|
+
onSubmit(): void;
|
|
4212
|
+
onClear(): void;
|
|
4213
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfSmartBarComponent, never>;
|
|
4214
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfSmartBarComponent, "ef-smart-bar", never, { "searchText": { "alias": "searchText"; "required": false; "isSignal": true; }; "placeholderKey": { "alias": "placeholderKey"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "clearLabelKey": { "alias": "clearLabelKey"; "required": false; "isSignal": true; }; "clearTitleKey": { "alias": "clearTitleKey"; "required": false; "isSignal": true; }; "searchLabelKey": { "alias": "searchLabelKey"; "required": false; "isSignal": true; }; "showKbdHint": { "alias": "showKbdHint"; "required": false; "isSignal": true; }; "hideClear": { "alias": "hideClear"; "required": false; "isSignal": true; }; "hideSearch": { "alias": "hideSearch"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; }, { "searchText": "searchTextChange"; "search": "search"; "clear": "clear"; }, never, ["[filters]", "[drawer]"], true, never>;
|
|
4215
|
+
}
|
|
4216
|
+
|
|
4217
|
+
/**
|
|
4218
|
+
* Comptoir filter pill — value-bearing button used in the smart-bar's
|
|
4219
|
+
* filter row. Three tones (`neutral` / `active` / `tenant`), optional
|
|
4220
|
+
* caret (when the pill toggles a popover), optional ✕ clear button.
|
|
4221
|
+
*
|
|
4222
|
+
* The popover content is consumer-projected via the `[popover]` slot
|
|
4223
|
+
* — the pill positions it absolutely below itself per the prototype's
|
|
4224
|
+
* `.popover` class. Visibility is driven by the `popoverOpen` input.
|
|
4225
|
+
*
|
|
4226
|
+
* ```html
|
|
4227
|
+
* <!-- value-bearing, removable -->
|
|
4228
|
+
* <ef-filter-pill
|
|
4229
|
+
* icon="pi pi-user"
|
|
4230
|
+
* labelKey="filter_client"
|
|
4231
|
+
* value="Leila Bennani"
|
|
4232
|
+
* tone="active"
|
|
4233
|
+
* hasClear
|
|
4234
|
+
* (clearClick)="removeFilter('client')"
|
|
4235
|
+
* />
|
|
4236
|
+
*
|
|
4237
|
+
* <!-- with popover (consumer renders preset list inside) -->
|
|
4238
|
+
* <ef-filter-pill
|
|
4239
|
+
* icon="pi pi-calendar"
|
|
4240
|
+
* labelKey="filter_date"
|
|
4241
|
+
* [value]="activeDatePreset().labelKey | translate"
|
|
4242
|
+
* hasPopover
|
|
4243
|
+
* [popoverOpen]="datePopoverOpen()"
|
|
4244
|
+
* (pillClick)="toggleDatePopover()"
|
|
4245
|
+
* >
|
|
4246
|
+
* <ng-container popover>
|
|
4247
|
+
* @for (p of presets; track p.key) {
|
|
4248
|
+
* <div class="preset" [class.active]="p === active">…</div>
|
|
4249
|
+
* }
|
|
4250
|
+
* </ng-container>
|
|
4251
|
+
* </ef-filter-pill>
|
|
4252
|
+
* ```
|
|
4253
|
+
*/
|
|
4254
|
+
declare class EfFilterPillComponent {
|
|
4255
|
+
/** PrimeNG icon class (e.g. `pi pi-calendar`). */
|
|
4256
|
+
readonly icon: _angular_core.InputSignal<string>;
|
|
4257
|
+
/** Translation key — preferred. */
|
|
4258
|
+
readonly labelKey: _angular_core.InputSignal<string>;
|
|
4259
|
+
/** Direct label text (used only when `labelKey` is empty). */
|
|
4260
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
4261
|
+
/** Current value displayed after the label. */
|
|
4262
|
+
readonly value: _angular_core.InputSignal<string>;
|
|
4263
|
+
/** `'active'` paints ink-active; `'tenant'` paints the tenant-50 surface. */
|
|
4264
|
+
readonly tone: _angular_core.InputSignal<"active" | "tenant" | "neutral">;
|
|
4265
|
+
/** Show the ✕ clear button at the end of the pill. */
|
|
4266
|
+
readonly hasClear: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4267
|
+
/** Show a chevron + position the projected `[popover]` slot. */
|
|
4268
|
+
readonly hasPopover: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4269
|
+
/** Whether the popover is currently open (consumer-controlled). */
|
|
4270
|
+
readonly popoverOpen: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4271
|
+
/** Translation key for the ✕ clear button's aria-label. */
|
|
4272
|
+
readonly clearAriaKey: _angular_core.InputSignal<string>;
|
|
4273
|
+
/** Emitted when the pill body is clicked (open popover, etc.). */
|
|
4274
|
+
readonly pillClick: _angular_core.OutputEmitterRef<void>;
|
|
4275
|
+
/** Emitted when the ✕ clear button is clicked (stops propagation). */
|
|
4276
|
+
readonly clearClick: _angular_core.OutputEmitterRef<void>;
|
|
4277
|
+
onPillClick(): void;
|
|
4278
|
+
onClearClick(event: Event): void;
|
|
4279
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfFilterPillComponent, never>;
|
|
4280
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfFilterPillComponent, "ef-filter-pill", never, { "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "labelKey": { "alias": "labelKey"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "hasClear": { "alias": "hasClear"; "required": false; "isSignal": true; }; "hasPopover": { "alias": "hasPopover"; "required": false; "isSignal": true; }; "popoverOpen": { "alias": "popoverOpen"; "required": false; "isSignal": true; }; "clearAriaKey": { "alias": "clearAriaKey"; "required": false; "isSignal": true; }; }, { "pillClick": "pillClick"; "clearClick": "clearClick"; }, never, ["[popover]"], true, never>;
|
|
4281
|
+
}
|
|
4282
|
+
|
|
4283
|
+
/**
|
|
4284
|
+
* Scopes a map of server/validation errors to its descendant `ef-*` form
|
|
4285
|
+
* controls, which auto-link by their `name` — no per-field `[errors]`
|
|
4286
|
+
* binding needed.
|
|
4287
|
+
*
|
|
4288
|
+
* Drop it on any container that wraps the form fields and bind the screen's
|
|
4289
|
+
* `serverErrors()` signal once:
|
|
4290
|
+
*
|
|
4291
|
+
* ```html
|
|
4292
|
+
* <div class="detail-grid" [efServerErrors]="serverErrors()">
|
|
4293
|
+
* <ef-input-text name="companyName" ... /> <!-- picks up errors['companyName'] -->
|
|
4294
|
+
* <ef-select name="clientType" ... /> <!-- picks up errors['clientType'] -->
|
|
4295
|
+
* </div>
|
|
4296
|
+
* ```
|
|
4297
|
+
*
|
|
4298
|
+
* Each control resolves its messages via `AbstractEfFormControl`
|
|
4299
|
+
* (`resolvedExternalErrors`): an explicit `[errors]` input still wins when
|
|
4300
|
+
* present, otherwise the control falls back to this scope keyed by `name`.
|
|
4301
|
+
* Keys must match the control `name` (camelCase) — `AbstractScreenComponent.setServerErrors`
|
|
4302
|
+
* already normalizes the backend's PascalCase keys, so the map is camelCase.
|
|
4303
|
+
*
|
|
4304
|
+
* The input is a signal, so updates propagate to controls under zoneless
|
|
4305
|
+
* change detection (controls read it through a `computed`).
|
|
4306
|
+
*/
|
|
4307
|
+
declare class EfServerErrorsDirective {
|
|
4308
|
+
/** Field-name → messages map (camelCase keys, matching control `name`). */
|
|
4309
|
+
readonly errors: _angular_core.InputSignal<{
|
|
4310
|
+
[key: string]: string[];
|
|
4311
|
+
}>;
|
|
4312
|
+
/** Messages for a control by its `name`, or `null` when none. */
|
|
4313
|
+
errorsFor(name: string | undefined | null): string[] | null;
|
|
4314
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfServerErrorsDirective, never>;
|
|
4315
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<EfServerErrorsDirective, "[efServerErrors]", never, { "errors": { "alias": "efServerErrors"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
4316
|
+
}
|
|
4317
|
+
|
|
4318
|
+
/**
|
|
4319
|
+
* The shared inline "clear" affordance — a circular button with the canonical
|
|
4320
|
+
* stroke-✕ glyph. One component so every clearable control (ef-input-text,
|
|
4321
|
+
* ef-inputnumber, ef-select via its `#clearicon` template, ef-product-typeahead,
|
|
4322
|
+
* …) shows the exact same clear icon, hover circle, and hit area.
|
|
4323
|
+
*
|
|
4324
|
+
* Styling lives in `_patterns.scss` under `.ef-clear` (global, so the same
|
|
4325
|
+
* glyph is reachable from PrimeNG templates that can't import this component).
|
|
4326
|
+
*
|
|
4327
|
+
* `mousedown` is prevented so clicking the clear doesn't blur/commit the field
|
|
4328
|
+
* before the `clear` handler runs.
|
|
4329
|
+
*/
|
|
4330
|
+
declare class EfClearButtonComponent {
|
|
4331
|
+
ariaLabel: string;
|
|
4332
|
+
disabled: boolean;
|
|
4333
|
+
clear: EventEmitter<Event>;
|
|
4334
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfClearButtonComponent, never>;
|
|
4335
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfClearButtonComponent, "ef-clear-button", never, { "ariaLabel": { "alias": "ariaLabel"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, { "clear": "clear"; }, never, never, true, never>;
|
|
4336
|
+
}
|
|
4337
|
+
|
|
4338
|
+
/**
|
|
4339
|
+
* Native Comptoir textarea — no PrimeNG wrapper. Pairs with the
|
|
4340
|
+
* `.ef-textarea` rule in `@elasticias/ui/styles/patterns` (focus
|
|
4341
|
+
* ring, paper-alt bg, rule border).
|
|
4342
|
+
*
|
|
4343
|
+
* Identity / label / placeholder / aria / required / readonly /
|
|
4344
|
+
* disabled inherited from `AbstractEfFormControl`. Implements
|
|
4345
|
+
* ControlValueAccessor so it slots into reactive forms AND works
|
|
4346
|
+
* with `[(value)]` two-way binding via `(valueChangeEvent)`.
|
|
4347
|
+
*
|
|
4348
|
+
* ```html
|
|
4349
|
+
* <ef-textarea
|
|
4350
|
+
* labelKey="products_details_description_label"
|
|
4351
|
+
* placeholderKey="products_details_description_placeholder"
|
|
4352
|
+
* [rows]="4"
|
|
4353
|
+
* [(value)]="description"
|
|
4354
|
+
* />
|
|
4355
|
+
* ```
|
|
4356
|
+
*/
|
|
4357
|
+
declare class EfTextareaComponent extends AbstractEfFormControl implements ControlValueAccessor {
|
|
4358
|
+
rows: number;
|
|
4359
|
+
maxlength?: number;
|
|
4360
|
+
autofocus: boolean;
|
|
4361
|
+
valueChangeEvent: EventEmitter<string>;
|
|
4362
|
+
/** Two-way-bindable as `[value]` (one-way) or
|
|
4363
|
+
* `[(value)]="signal()"` (set + listen via `valueChangeEvent`). */
|
|
4364
|
+
value: string;
|
|
4365
|
+
/** Clearable (showClear / canClear) inherited from AbstractEfFormControl. */
|
|
4366
|
+
protected get hasValue(): boolean;
|
|
4367
|
+
clearValue(): void;
|
|
4368
|
+
private onChange;
|
|
4369
|
+
private onTouched;
|
|
4370
|
+
readonly ngControl: NgControl;
|
|
4371
|
+
constructor();
|
|
4372
|
+
get isInvalid(): boolean;
|
|
4373
|
+
get serverErrors(): string[] | null;
|
|
4374
|
+
get showRequired(): boolean;
|
|
4375
|
+
writeValue(value: string): void;
|
|
4376
|
+
registerOnChange(fn: (value: string) => void): void;
|
|
4377
|
+
registerOnTouched(fn: () => void): void;
|
|
4378
|
+
setDisabledState(isDisabled: boolean): void;
|
|
4379
|
+
handleInput(value: string): void;
|
|
4380
|
+
handleBlur(): void;
|
|
4381
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfTextareaComponent, never>;
|
|
4382
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfTextareaComponent, "ef-textarea", never, { "rows": { "alias": "rows"; "required": false; }; "maxlength": { "alias": "maxlength"; "required": false; }; "autofocus": { "alias": "autofocus"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, { "valueChangeEvent": "valueChangeEvent"; }, never, never, true, never>;
|
|
4383
|
+
static ngAcceptInputType_autofocus: unknown;
|
|
4384
|
+
}
|
|
4385
|
+
|
|
4386
|
+
interface EfPresetItem<T = string> {
|
|
4387
|
+
/** Stable identifier (used as the `value`). */
|
|
4388
|
+
key: T;
|
|
4389
|
+
/** Translation key for the row label (preferred). */
|
|
4390
|
+
labelKey?: string;
|
|
4391
|
+
/** Direct label (used only when `labelKey` is empty). */
|
|
4392
|
+
label?: string;
|
|
4393
|
+
/** Mono hint to the right (date range, count, …). */
|
|
4394
|
+
hint?: string;
|
|
4395
|
+
}
|
|
4396
|
+
/**
|
|
4397
|
+
* Filter pill that opens a list of presets on click. Consumer-side
|
|
4398
|
+
* use cases: date ranges (`Aujourd'hui · 30 derniers jours · …`),
|
|
4399
|
+
* non-date enums (`Jamais connecté`), any short canned list.
|
|
4400
|
+
*
|
|
4401
|
+
* State model: `open` is a `model()` so callers can let the pill
|
|
4402
|
+
* manage its own visibility (default) or hoist it into a parent
|
|
4403
|
+
* signal for fully controlled use (`[(open)]`).
|
|
4404
|
+
*
|
|
4405
|
+
* ```html
|
|
4406
|
+
* <ef-preset-pill
|
|
4407
|
+
* icon="pi pi-calendar"
|
|
4408
|
+
* labelKey="filter_date"
|
|
4409
|
+
* [presets]="datePresets"
|
|
4410
|
+
* [(activeKey)]="activeDateKey"
|
|
4411
|
+
* (presetChange)="onDateRangeChange($event)"
|
|
4412
|
+
* />
|
|
4413
|
+
* ```
|
|
4414
|
+
*/
|
|
4415
|
+
declare class EfPresetPillComponent<T = string> {
|
|
4416
|
+
private readonly translate;
|
|
4417
|
+
readonly icon: _angular_core.InputSignal<string>;
|
|
4418
|
+
readonly labelKey: _angular_core.InputSignal<string>;
|
|
4419
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
4420
|
+
readonly tone: _angular_core.InputSignal<"active" | "tenant" | "neutral">;
|
|
4421
|
+
readonly presets: _angular_core.InputSignal<readonly EfPresetItem<T>[]>;
|
|
4422
|
+
readonly activeKey: _angular_core.ModelSignal<T>;
|
|
4423
|
+
/** Two-way; consumer can hoist for controlled mode. */
|
|
4424
|
+
readonly open: _angular_core.ModelSignal<boolean>;
|
|
4425
|
+
/** Auto-close the popover after selection (default on). */
|
|
4426
|
+
readonly closeOnSelect: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4427
|
+
readonly presetChange: _angular_core.OutputEmitterRef<EfPresetItem<T>>;
|
|
4428
|
+
/** Displayed value — translates `labelKey` of the active preset if present. */
|
|
4429
|
+
readonly activeLabel: _angular_core.Signal<any>;
|
|
4430
|
+
toggle(): void;
|
|
4431
|
+
select(preset: EfPresetItem<T>): void;
|
|
4432
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfPresetPillComponent<any>, never>;
|
|
4433
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPresetPillComponent<any>, "ef-preset-pill", never, { "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "labelKey": { "alias": "labelKey"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "presets": { "alias": "presets"; "required": true; "isSignal": true; }; "activeKey": { "alias": "activeKey"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "closeOnSelect": { "alias": "closeOnSelect"; "required": false; "isSignal": true; }; }, { "activeKey": "activeKeyChange"; "open": "openChange"; "presetChange": "presetChange"; }, never, never, true, never>;
|
|
4434
|
+
}
|
|
4435
|
+
|
|
4436
|
+
/**
|
|
4437
|
+
* One row in the picker's presets list. UI-specific — carries the
|
|
4438
|
+
* optional `compute` and `hintFn` callbacks that the picker invokes
|
|
4439
|
+
* at render time. Stays in @elasticias/ui because it's a render-time
|
|
4440
|
+
* descriptor, not a state shape.
|
|
4441
|
+
*/
|
|
4442
|
+
interface EfDatePreset {
|
|
4443
|
+
/** Stable key. Built-in keys (`today`, `this_week`, …) are computed
|
|
4444
|
+
* automatically; custom keys must come with a date computer. */
|
|
4445
|
+
key: _elasticias_screens.EfDatePresetKey;
|
|
4446
|
+
/** Translation key for the row label. */
|
|
4447
|
+
labelKey?: string;
|
|
4448
|
+
/** Direct label fallback when `labelKey` is empty. */
|
|
4449
|
+
label?: string;
|
|
4450
|
+
/**
|
|
4451
|
+
* Computer for non-built-in presets — given today, return start/end
|
|
4452
|
+
* (inclusive). For built-in keys this is provided by the component.
|
|
4453
|
+
*/
|
|
4454
|
+
compute?: (today: Date) => {
|
|
4455
|
+
start: Date;
|
|
4456
|
+
end: Date;
|
|
4457
|
+
};
|
|
4458
|
+
/** Optional secondary text right-aligned (e.g. `'5 j'`, `'T2'`). */
|
|
4459
|
+
hintFn?: (today: Date) => string;
|
|
4460
|
+
}
|
|
4461
|
+
|
|
4462
|
+
/** Value shape emitted / accepted by the field-mode ControlValueAccessor.
|
|
4463
|
+
* Mirrors PrimeNG's `p-datepicker`: a lone `Date` for single selection,
|
|
4464
|
+
* a `[start, end]` tuple for a range — so `ef-datepicker-advanced` is a
|
|
4465
|
+
* drop-in replacement for the legacy `ef-datepicker` in forms. */
|
|
4466
|
+
type EfDateFieldValue = Date | [Date, Date] | null;
|
|
4467
|
+
/**
|
|
4468
|
+
* Comptoir period selector for smart-bars — a pill trigger ("Date — 30
|
|
4469
|
+
* derniers jours v") that opens a popover with a preset list and an
|
|
4470
|
+
* optional custom-range view (full month calendar with range band).
|
|
4471
|
+
*
|
|
4472
|
+
* Replaces the legacy `ef-preset-pill` for date filters and the
|
|
4473
|
+
* date-range mini-popover that screens used to roll inline.
|
|
4474
|
+
*
|
|
4475
|
+
* ```html
|
|
4476
|
+
* <ef-datepicker-advanced
|
|
4477
|
+
* [activePreset]="dateFilter().presetKey"
|
|
4478
|
+
* [start]="dateFilter().start"
|
|
4479
|
+
* [end]="dateFilter().end"
|
|
4480
|
+
* triggerLabelKey="filter_date"
|
|
4481
|
+
* (rangeChange)="onDateChange($event)"
|
|
4482
|
+
* />
|
|
4483
|
+
* ```
|
|
4484
|
+
*
|
|
4485
|
+
* Built-in presets (computed from `today` at open time):
|
|
4486
|
+
* `today`, `this_week`, `this_month`, `last_30_days`, `last_90_days`,
|
|
4487
|
+
* `this_quarter`, `this_year`. Override with `[presets]="customList"`
|
|
4488
|
+
* if you need a different set.
|
|
4489
|
+
*/
|
|
4490
|
+
declare class EfDatepickerAdvancedComponent extends AbstractEfFormControl implements ControlValueAccessor, AfterViewInit {
|
|
4491
|
+
private readonly host;
|
|
4492
|
+
private readonly locale;
|
|
4493
|
+
private readonly vcr;
|
|
4494
|
+
private readonly destroyRef;
|
|
4495
|
+
private readonly cdr;
|
|
4496
|
+
/**
|
|
4497
|
+
* Self-injected form control (present only when the consumer binds
|
|
4498
|
+
* `[(ngModel)]` / `formControlName` in field mode). We register as its
|
|
4499
|
+
* `valueAccessor` manually — same pattern as `ef-datepicker` — so no
|
|
4500
|
+
* `NG_VALUE_ACCESSOR` provider is needed and there's no circular DI.
|
|
4501
|
+
* `null` in filter mode (the output-only smart-bar usage).
|
|
4502
|
+
*/
|
|
4503
|
+
readonly ngControl: NgControl;
|
|
4504
|
+
/** Always-present wrapper — the anchor for portal positioning (the
|
|
4505
|
+
* trigger itself lives behind an `@if`, so we anchor to the host box). */
|
|
4506
|
+
private anchorEl;
|
|
4507
|
+
/** Panel template — instantiated and attached to <body> on open. */
|
|
4508
|
+
private panelTpl;
|
|
4509
|
+
/** Active embedded view + its root node, while the panel is open. */
|
|
4510
|
+
private panelView;
|
|
4511
|
+
private panelRoot;
|
|
4512
|
+
private resizeHandler;
|
|
4513
|
+
constructor();
|
|
4514
|
+
ngAfterViewInit(): void;
|
|
4515
|
+
/** Trigger left-side label (translation key). Default: `'filter_date'`. */
|
|
4516
|
+
readonly triggerLabelKey: _angular_core.InputSignal<string>;
|
|
4517
|
+
/** Direct label fallback when `triggerLabelKey` is empty. */
|
|
4518
|
+
readonly triggerLabel: _angular_core.InputSignal<string>;
|
|
4519
|
+
/**
|
|
4520
|
+
* Override the default preset list. The component ships sensible
|
|
4521
|
+
* defaults for `today`, `this_week`, `this_month`, `last_30_days`,
|
|
4522
|
+
* `last_90_days`, `this_quarter`, `this_year` — pass anything to
|
|
4523
|
+
* replace them outright (e.g. include a `last_year` preset).
|
|
4524
|
+
*/
|
|
4525
|
+
readonly presets: _angular_core.InputSignal<readonly EfDatePreset[]>;
|
|
4526
|
+
/** Currently active preset key (controlled). */
|
|
4527
|
+
readonly activePreset: _angular_core.InputSignal<string>;
|
|
4528
|
+
/** Currently selected start (controlled — pairs with `activePreset`). */
|
|
4529
|
+
readonly start: _angular_core.InputSignal<Date>;
|
|
4530
|
+
/** Currently selected end. */
|
|
4531
|
+
readonly end: _angular_core.InputSignal<Date>;
|
|
4532
|
+
/** Show a `'Personnalisé…'` row that opens the calendar view. */
|
|
4533
|
+
readonly allowCustomRange: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4534
|
+
/** Component behaviour: smart-bar filter vs. form field. */
|
|
4535
|
+
readonly mode: _angular_core.InputSignal<"filter" | "field">;
|
|
4536
|
+
/** Field mode only — pick a single date or a `[start, end]` range. */
|
|
4537
|
+
readonly selectionMode: _angular_core.InputSignal<"single" | "range">;
|
|
4538
|
+
/** Field mode trigger appearance: a labelled field box (default) or
|
|
4539
|
+
* the rounded pill used by filter mode. */
|
|
4540
|
+
readonly variant: _angular_core.InputSignal<"field" | "pill">;
|
|
4541
|
+
/**
|
|
4542
|
+
* Field mode only — also pick a time (24h `HH:mm`, free minutes).
|
|
4543
|
+
* Single: the calendar no longer commits on day-click; a time field +
|
|
4544
|
+
* Apply appear. Range: an `HH:mm` field sits under each of Du / Au.
|
|
4545
|
+
* The committed value is a `Date` with hours/minutes set (not
|
|
4546
|
+
* start-of-day) and the trigger renders `DD/MM/YYYY HH:mm`.
|
|
4547
|
+
*/
|
|
4548
|
+
readonly showTime: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4549
|
+
/** Emitted whenever a preset or applied custom range changes. */
|
|
4550
|
+
readonly rangeChange: _angular_core.OutputEmitterRef<EfDateRange>;
|
|
4551
|
+
/** Forwarded when the popover opens / closes (mirrors ef-row-actions). */
|
|
4552
|
+
readonly opened: _angular_core.OutputEmitterRef<void>;
|
|
4553
|
+
readonly closed: _angular_core.OutputEmitterRef<void>;
|
|
4554
|
+
readonly open: _angular_core.WritableSignal<boolean>;
|
|
4555
|
+
readonly view: _angular_core.WritableSignal<"custom" | "presets">;
|
|
4556
|
+
/**
|
|
4557
|
+
* Custom view sub-mode: the day grid, the month picker, or the year
|
|
4558
|
+
* picker. Clicking the month / year labels in the calendar header
|
|
4559
|
+
* drills into the corresponding picker; selecting a cell returns to
|
|
4560
|
+
* the day grid.
|
|
4561
|
+
*/
|
|
4562
|
+
readonly calMode: _angular_core.WritableSignal<"days" | "months" | "years">;
|
|
4563
|
+
/** First year shown in the 12-cell year picker grid. */
|
|
4564
|
+
readonly yearWindowStart: _angular_core.WritableSignal<number>;
|
|
4565
|
+
/** Custom view: month being displayed (1st of the month, 00:00). */
|
|
4566
|
+
readonly visibleMonth: _angular_core.WritableSignal<Date>;
|
|
4567
|
+
/** Custom view: working start/end, before the user clicks Apply. */
|
|
4568
|
+
readonly draftStart: _angular_core.WritableSignal<Date>;
|
|
4569
|
+
readonly draftEnd: _angular_core.WritableSignal<Date>;
|
|
4570
|
+
/** Effective preset list — defaults if none provided. */
|
|
4571
|
+
readonly effectivePresets: _angular_core.Signal<readonly EfDatePreset[]>;
|
|
4572
|
+
/** Current value resolved against today's date. */
|
|
4573
|
+
readonly resolvedRange: _angular_core.Signal<EfDateRange>;
|
|
4574
|
+
/** 7×6 grid for the visible month, prev/next-month overflow days included. */
|
|
4575
|
+
readonly calendarGrid: _angular_core.Signal<readonly {
|
|
4576
|
+
date: Date;
|
|
4577
|
+
day: number;
|
|
4578
|
+
out: boolean;
|
|
4579
|
+
today: boolean;
|
|
4580
|
+
inRange: boolean;
|
|
4581
|
+
rangeStart: boolean;
|
|
4582
|
+
rangeEnd: boolean;
|
|
4583
|
+
}[]>;
|
|
4584
|
+
/** Day-of-week labels from CLDR (Mon-first). */
|
|
4585
|
+
readonly dowLabels: _angular_core.Signal<readonly string[]>;
|
|
4586
|
+
/** Month + year title for the calendar header. */
|
|
4587
|
+
readonly monthLabel: _angular_core.Signal<string>;
|
|
4588
|
+
readonly yearLabel: _angular_core.Signal<string>;
|
|
4589
|
+
/** Range label for the year-picker header, e.g. `2024 – 2035`. */
|
|
4590
|
+
readonly yearWindowLabel: _angular_core.Signal<string>;
|
|
4591
|
+
/** 12 abbreviated months for the month picker (Jan…Déc), CLDR-localised. */
|
|
4592
|
+
readonly monthCells: _angular_core.Signal<{
|
|
4593
|
+
month: number;
|
|
4594
|
+
label: string;
|
|
4595
|
+
active: boolean;
|
|
4596
|
+
today: boolean;
|
|
4597
|
+
}[]>;
|
|
4598
|
+
/** 12 consecutive years for the year picker, starting at `yearWindowStart`. */
|
|
4599
|
+
readonly yearCells: _angular_core.Signal<{
|
|
4600
|
+
year: number;
|
|
4601
|
+
active: boolean;
|
|
4602
|
+
today: boolean;
|
|
4603
|
+
}[]>;
|
|
4604
|
+
/** Live duration in days for the draft range. Mirrors `applyCustomRange`:
|
|
4605
|
+
* a lone start is treated as a single-day range (→ "1 jour"). */
|
|
4606
|
+
readonly draftDurationDays: _angular_core.Signal<number>;
|
|
4607
|
+
/** Du / Au inputs as DD/MM/YYYY strings (kept in sync with drafts). */
|
|
4608
|
+
readonly fromText: _angular_core.Signal<string>;
|
|
4609
|
+
readonly toText: _angular_core.Signal<string>;
|
|
4610
|
+
/** Committed value pushed in via `writeValue` / day-pick / Apply. */
|
|
4611
|
+
private readonly fieldValue;
|
|
4612
|
+
/** Committed start / end derived from `fieldValue`. */
|
|
4613
|
+
readonly fieldStart: _angular_core.Signal<Date>;
|
|
4614
|
+
readonly fieldEnd: _angular_core.Signal<Date>;
|
|
4615
|
+
/** Whether the field currently holds a value (vs. placeholder). */
|
|
4616
|
+
readonly hasFieldValue: _angular_core.Signal<boolean>;
|
|
4617
|
+
/** Text rendered in the field-mode trigger (date, +time when enabled). */
|
|
4618
|
+
readonly fieldDisplay: _angular_core.Signal<string>;
|
|
4619
|
+
readonly draftStartTime: _angular_core.WritableSignal<{
|
|
4620
|
+
h: number;
|
|
4621
|
+
m: number;
|
|
4622
|
+
}>;
|
|
4623
|
+
readonly draftEndTime: _angular_core.WritableSignal<{
|
|
4624
|
+
h: number;
|
|
4625
|
+
m: number;
|
|
4626
|
+
}>;
|
|
4627
|
+
/** Du / Au time inputs as `HH:mm` strings (kept in sync with drafts). */
|
|
4628
|
+
readonly fromTimeText: _angular_core.Signal<string>;
|
|
4629
|
+
readonly toTimeText: _angular_core.Signal<string>;
|
|
4630
|
+
private onChange;
|
|
4631
|
+
private onTouched;
|
|
4632
|
+
/** Required error is shown once the control is touched. */
|
|
4633
|
+
get showRequired(): boolean;
|
|
4634
|
+
/** Backend validation messages stashed under `serverError`. */
|
|
4635
|
+
get serverErrors(): string[] | null;
|
|
4636
|
+
/** Invalid + interacted — drives the red border on the field box. */
|
|
4637
|
+
get isInvalid(): boolean;
|
|
4638
|
+
writeValue(value: Date | Date[] | string | number | null | undefined): void;
|
|
4639
|
+
registerOnChange(fn: (value: EfDateFieldValue) => void): void;
|
|
4640
|
+
registerOnTouched(fn: () => void): void;
|
|
4641
|
+
setDisabledState(isDisabled: boolean): void;
|
|
4642
|
+
protected get hasValue(): boolean;
|
|
4643
|
+
clearValue(): void;
|
|
4644
|
+
/** Normalise whatever a form pushes in to our internal value shape.
|
|
4645
|
+
* Tolerates `null`, `[start, null]`, strings/epochs, and stray
|
|
4646
|
+
* multi-element arrays (keeps the first two). */
|
|
4647
|
+
private coerceValue;
|
|
4648
|
+
private toDate;
|
|
4649
|
+
/** Commit a field-mode value: update internal state, notify the form,
|
|
4650
|
+
* and close the popover. `single` → `Date`, `range` → `[start, end]`. */
|
|
4651
|
+
private commitField;
|
|
4652
|
+
/** Merge a day with a draft time. Returns start-of-day when `showTime`
|
|
4653
|
+
* is off, so date-only commits stay time-free. */
|
|
4654
|
+
private composeDateTime;
|
|
4655
|
+
/** Format a draft time as zero-padded `HH:mm`. */
|
|
4656
|
+
private formatTime;
|
|
4657
|
+
/** Parse `H:mm` … `HH:mm` (24h) → `{h, m}`, or null when out of range. */
|
|
4658
|
+
private parseTimeInput;
|
|
4659
|
+
/** Allow only digits and `:` while typing a time; Enter commits via blur. */
|
|
4660
|
+
onTimeKeydown(event: KeyboardEvent, el: HTMLInputElement): void;
|
|
4661
|
+
/** Commit a typed `HH:mm` value to the start or end draft time. */
|
|
4662
|
+
commitTimeInput(which: 'start' | 'end', el: HTMLInputElement): void;
|
|
4663
|
+
toggle(event: MouseEvent): void;
|
|
4664
|
+
close(): void;
|
|
4665
|
+
onDocumentClick(event: MouseEvent): void;
|
|
4666
|
+
onEscape(): void;
|
|
4667
|
+
selectPreset(preset: EfDatePreset): void;
|
|
4668
|
+
isActivePreset(key: EfDatePresetKey): boolean;
|
|
4669
|
+
presetHint(preset: EfDatePreset): string;
|
|
4670
|
+
openCustomView(): void;
|
|
4671
|
+
backToPresets(): void;
|
|
4672
|
+
headerPrev(): void;
|
|
4673
|
+
headerNext(): void;
|
|
4674
|
+
private stepHeader;
|
|
4675
|
+
/** Open the month picker (triggered by clicking the month label). */
|
|
4676
|
+
openMonthPicker(): void;
|
|
4677
|
+
/** Open the year picker (triggered by clicking the year label). */
|
|
4678
|
+
openYearPicker(): void;
|
|
4679
|
+
/** Pick a month → jump the day grid to it. */
|
|
4680
|
+
selectMonth(month: number): void;
|
|
4681
|
+
/** Pick a year → keep the current month, return to the day grid. */
|
|
4682
|
+
selectYear(year: number): void;
|
|
4683
|
+
/** Allow only digits and `/` for printable keys; Enter commits via blur. */
|
|
4684
|
+
onDateKeydown(event: KeyboardEvent, el: HTMLInputElement): void;
|
|
4685
|
+
/** Commit a typed `JJ/MM/AAAA` value to the start or end draft. */
|
|
4686
|
+
commitDateInput(which: 'start' | 'end', el: HTMLInputElement): void;
|
|
4687
|
+
private attachPortal;
|
|
4688
|
+
private detachPortal;
|
|
4689
|
+
/** Anchor the panel's top-left to the trigger's bottom-left, using
|
|
4690
|
+
* page coords so the panel scrolls with the trigger naturally.
|
|
4691
|
+
* Flips to right-aligned (and clamps to the viewport) when the
|
|
4692
|
+
* default left-anchor would overflow the right edge — otherwise the
|
|
4693
|
+
* panel is clipped for triggers that sit near the right of the page. */
|
|
4694
|
+
private positionPanel;
|
|
4695
|
+
/** Click handling: 1st click sets start, 2nd click sets end (or swap).
|
|
4696
|
+
* Field single-date mode short-circuits — one click commits & closes. */
|
|
4697
|
+
selectDay(day: Date): void;
|
|
4698
|
+
applyCustomRange(): void;
|
|
4699
|
+
/** Field single-date mode: commit a typed `JJ/MM/AAAA` value & close.
|
|
4700
|
+
* With `showTime`, only update the draft — Apply commits date + time. */
|
|
4701
|
+
commitSingleInput(el: HTMLInputElement): void;
|
|
4702
|
+
/** Default preset list — built-in semantics, all keys recognised. */
|
|
4703
|
+
private readonly defaultPresets;
|
|
4704
|
+
private seedDraftFromValue;
|
|
4705
|
+
/** Compute the date range for a preset key. */
|
|
4706
|
+
private computePresetRange;
|
|
4707
|
+
/** Assemble an EfDateRange — exposes `labelKey` (for the trigger
|
|
4708
|
+
* to render via `| translate`) and a literal `label` fallback. */
|
|
4709
|
+
private buildRange;
|
|
4710
|
+
private builtInRange;
|
|
4711
|
+
private builtInHint;
|
|
4712
|
+
/** 6 weeks × 7 days. Each cell carries its date + flags. */
|
|
4713
|
+
private buildMonthGrid;
|
|
4714
|
+
private buildDowLabels;
|
|
4715
|
+
private startOfDay;
|
|
4716
|
+
private startOfMonth;
|
|
4717
|
+
private addDays;
|
|
4718
|
+
private addMonths;
|
|
4719
|
+
private daysBetween;
|
|
4720
|
+
private formatDayInput;
|
|
4721
|
+
/** Parse a `J/M/AAAA`…`JJ/MM/AAAA` string to a start-of-day Date, or
|
|
4722
|
+
* null when malformed or out of range (e.g. `31/02/2026`). */
|
|
4723
|
+
private parseDayInput;
|
|
4724
|
+
/** First year of the 12-cell window containing `year` (e.g. 2026 → 2016). */
|
|
4725
|
+
private startOfYearWindow;
|
|
4726
|
+
/** Stable trackBy across renders. */
|
|
4727
|
+
trackByPreset: (_: number, p: EfDatePreset) => string;
|
|
4728
|
+
trackByDay: (_: number, day: {
|
|
4729
|
+
date: Date;
|
|
4730
|
+
}) => number;
|
|
4731
|
+
trackByDow: (_: number, label: string) => string;
|
|
4732
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfDatepickerAdvancedComponent, never>;
|
|
4733
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfDatepickerAdvancedComponent, "ef-datepicker-advanced", never, { "triggerLabelKey": { "alias": "triggerLabelKey"; "required": false; "isSignal": true; }; "triggerLabel": { "alias": "triggerLabel"; "required": false; "isSignal": true; }; "presets": { "alias": "presets"; "required": false; "isSignal": true; }; "activePreset": { "alias": "activePreset"; "required": false; "isSignal": true; }; "start": { "alias": "start"; "required": false; "isSignal": true; }; "end": { "alias": "end"; "required": false; "isSignal": true; }; "allowCustomRange": { "alias": "allowCustomRange"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "selectionMode": { "alias": "selectionMode"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "showTime": { "alias": "showTime"; "required": false; "isSignal": true; }; }, { "rangeChange": "rangeChange"; "opened": "opened"; "closed": "closed"; }, never, never, true, never>;
|
|
4734
|
+
}
|
|
4735
|
+
|
|
4736
|
+
/**
|
|
4737
|
+
* Comptoir advanced-filter drawer — collapsible card that lives at
|
|
4738
|
+
* the bottom of the smart-bar. Consumer projects their grid of
|
|
4739
|
+
* `<div class="field">` controls; the component handles the open
|
|
4740
|
+
* animation, the footer Reset / Apply buttons, and the optional hint
|
|
4741
|
+
* line on the left of the footer.
|
|
4742
|
+
*
|
|
4743
|
+
* ```html
|
|
4744
|
+
* <ef-filter-drawer
|
|
4745
|
+
* [open]="drawerOpen()"
|
|
4746
|
+
* hintKey="sales_orders_adv_hint"
|
|
4747
|
+
* (apply)="runSearch()"
|
|
4748
|
+
* (reset)="clearAll()"
|
|
4749
|
+
* >
|
|
4750
|
+
* <div class="field">
|
|
4751
|
+
* <label for="adv-employee">{{ 'sales_orders_adv_employee' | translate }}</label>
|
|
4752
|
+
* <select id="adv-employee">…</select>
|
|
4753
|
+
* </div>
|
|
4754
|
+
* …
|
|
4755
|
+
* </ef-filter-drawer>
|
|
4756
|
+
* ```
|
|
4757
|
+
*/
|
|
4758
|
+
declare class EfFilterDrawerComponent {
|
|
4759
|
+
readonly open: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4760
|
+
readonly hintKey: _angular_core.InputSignal<string>;
|
|
4761
|
+
readonly hint: _angular_core.InputSignal<string>;
|
|
4762
|
+
readonly resetLabelKey: _angular_core.InputSignal<string>;
|
|
4763
|
+
readonly applyLabelKey: _angular_core.InputSignal<string>;
|
|
4764
|
+
readonly hideApply: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
4765
|
+
readonly apply: _angular_core.OutputEmitterRef<void>;
|
|
4766
|
+
readonly reset: _angular_core.OutputEmitterRef<void>;
|
|
4767
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfFilterDrawerComponent, never>;
|
|
4768
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfFilterDrawerComponent, "ef-filter-drawer", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "hintKey": { "alias": "hintKey"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "resetLabelKey": { "alias": "resetLabelKey"; "required": false; "isSignal": true; }; "applyLabelKey": { "alias": "applyLabelKey"; "required": false; "isSignal": true; }; "hideApply": { "alias": "hideApply"; "required": false; "isSignal": true; }; }, { "apply": "apply"; "reset": "reset"; }, never, ["*"], true, never>;
|
|
4769
|
+
}
|
|
4770
|
+
|
|
4771
|
+
/**
|
|
4772
|
+
* Comptoir activation tri-state filter — a `.field`-anatomy pill group
|
|
4773
|
+
* (all / active / inactive) for boolean activation criteria
|
|
4774
|
+
* (`IsActive: bool?` pattern).
|
|
4775
|
+
*
|
|
4776
|
+
* `value` is the criteria value itself: `true`, `false`, or
|
|
4777
|
+
* `undefined`/`null` for "all". `valueChange` emits the same shape, so
|
|
4778
|
+
* the component binds straight onto a search screen's advanced-filter
|
|
4779
|
+
* state; pair with `AbstractSearchScreenV2.activationFilterKey` for
|
|
4780
|
+
* apply / baseline-clear / cache-restore.
|
|
4781
|
+
*
|
|
4782
|
+
* ```html
|
|
4783
|
+
* <ef-activation-filter
|
|
4784
|
+
* [value]="advancedValues()['isActive']"
|
|
4785
|
+
* (valueChange)="setAdvancedValue('isActive', $event)"
|
|
4786
|
+
* />
|
|
4787
|
+
* ```
|
|
4788
|
+
*/
|
|
4789
|
+
declare class EfActivationFilterComponent {
|
|
4790
|
+
private static nextId;
|
|
4791
|
+
readonly labelId: string;
|
|
4792
|
+
/** Current criteria value: `true` / `false` / `undefined` (= all). */
|
|
4793
|
+
readonly value: _angular_core.InputSignal<unknown>;
|
|
4794
|
+
readonly labelKey: _angular_core.InputSignal<string>;
|
|
4795
|
+
readonly allLabelKey: _angular_core.InputSignal<string>;
|
|
4796
|
+
readonly activeLabelKey: _angular_core.InputSignal<string>;
|
|
4797
|
+
readonly inactiveLabelKey: _angular_core.InputSignal<string>;
|
|
4798
|
+
readonly valueChange: _angular_core.OutputEmitterRef<boolean>;
|
|
4799
|
+
readonly selected: _angular_core.Signal<"active" | "inactive" | "all">;
|
|
4800
|
+
readonly buckets: _angular_core.Signal<{
|
|
4801
|
+
key: string;
|
|
4802
|
+
labelKey: string;
|
|
4803
|
+
value: boolean;
|
|
4804
|
+
}[]>;
|
|
4805
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfActivationFilterComponent, never>;
|
|
4806
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfActivationFilterComponent, "ef-activation-filter", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "labelKey": { "alias": "labelKey"; "required": false; "isSignal": true; }; "allLabelKey": { "alias": "allLabelKey"; "required": false; "isSignal": true; }; "activeLabelKey": { "alias": "activeLabelKey"; "required": false; "isSignal": true; }; "inactiveLabelKey": { "alias": "inactiveLabelKey"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
|
|
4807
|
+
}
|
|
4808
|
+
|
|
1752
4809
|
/**
|
|
1753
4810
|
* Theme configurator panel for switching PrimeNG presets, primary colors,
|
|
1754
4811
|
* surface palettes, ripple effect, and RTL direction.
|
|
@@ -1864,5 +4921,5 @@ declare class EfEmailMetricsCardComponent {
|
|
|
1864
4921
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfEmailMetricsCardComponent, "ef-email-metrics-card", never, { "metrics": { "alias": "metrics"; "required": false; "isSignal": true; }; "recentEvents": { "alias": "recentEvents"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; }, { "rangeChange": "rangeChange"; }, never, never, true, never>;
|
|
1865
4922
|
}
|
|
1866
4923
|
|
|
1867
|
-
export { EF_BADGE_BG_COLORS, EF_BADGE_BG_LIGHT_COLORS, EF_BADGE_BORDER_COLORS, EF_BADGE_DEFAULTS, EF_BADGE_TEXT_COLORS, EF_DATATABLE_ACTIONS_DEFAULTS, EF_DATATABLE_COLUMN_DEFAULTS, EF_DATATABLE_DEFAULTS, EfBadgeComponent, EfBlockUiComponent, EfBlockableDivComponent, EfButtonComponent, EfCheckboxComponent, EfCurrencyPipe, EfDatatableActionBarComponent, EfDatatableComponent, EfDatepickerComponent, EfDialogComponent, EfEmailMetricsCardComponent, EfFieldsetComponent, EfInputNumberComponent, EfInputTextComponent, EfLabelComponent, EfMultiSelectComponent, EfOrderBuilderComponent, EfOrderSummaryComponent, EfPasswordComponent, EfPriceDisplayComponent, EfProductCatalogueComponent, EfProductCatalogueFilterComponent, EfQuantitySelectorComponent, EfQuantityStepperComponent, EfSelectButtonComponent, EfSelectComponent, EfThemeConfiguratorComponent, EfToolbarComponent, OrderEntityHelper, OrderLineItemHelper, TruncatePipe, getColumnAlignment, mergeColumnDefaults };
|
|
1868
|
-
export type { CatalogueProduct, CatalogueProductVariant, CategoryAssignment, CategoryGroup, CategoryItem, DatatableSearchEntity, DocumentConfig, EfBadgeColor, EfBadgeConfig, EfBadgeSize, EfBadgeVariant, EfDatatableActions, EfDatatableColumn, EfDatatableColumnAlign, EfDatatableColumnType, EfDatatableConfig, OrderChangeInfo, OrderEntity, OrderLineItem, OrderProductsSummary, OrderSummaryItem, ProductCountGroup, ProductCountGroupLabel, ProductWithCountGroup, SelectedFilter, ValidationResult };
|
|
4924
|
+
export { EF_BADGE_BG_COLORS, EF_BADGE_BG_LIGHT_COLORS, EF_BADGE_BORDER_COLORS, EF_BADGE_DEFAULTS, EF_BADGE_TEXT_COLORS, EF_CHART_PALETTE, EF_DATATABLE_ACTIONS_DEFAULTS, EF_DATATABLE_COLUMN_DEFAULTS, EF_DATATABLE_DEFAULTS, EF_STATUS_COLORS, EF_STATUS_COLOR_ALIASES, EfActivationFilterComponent, EfAppMainComponent, EfAppShellComponent, EfAppShellMobileComponent, EfAppTopComponent, EfBadgeComponent, EfBlockUiComponent, EfBlockableDivComponent, EfBottomSheetComponent, EfBulkBarComponent, EfButtonComponent, EfButtonGroupComponent, EfCardComponent, EfChangeHistoryComponent, EfChartComponent, EfCheckboxComponent, EfClearButtonComponent, EfColumnHeaderTemplateDirective, EfColumnTemplateDirective, EfCompactPipe, EfCurrencyPipe, EfDataCardComponent, EfDatatableActionBarComponent, EfDatatableComponent, EfDatepickerAdvancedComponent, EfDatepickerComponent, EfDetailToolbarComponent, EfDialogComponent, EfEmailMetricsCardComponent, EfEmptyStateComponent, EfFabComponent, EfFieldsetComponent, EfFilterDrawerComponent, EfFilterPillComponent, EfFormGridComponent, EfInputNumberComponent, EfInputTextComponent, EfKpiCardComponent, EfLabelComponent, EfModuleRailComponent, EfModuleSideComponent, EfMultiSelectComponent, EfOrderBuilderComponent, EfOrderSummaryComponent, EfPagerComponent, EfPasswordComponent, EfPdfPreviewComponent, EfPillGroupComponent, EfPresetPillComponent, EfPriceDisplayComponent, EfProductCatalogueComponent, EfProductCatalogueFilterComponent, EfProductTypeaheadComponent, EfProfileChipComponent, EfPulseComponent, EfQuantitySelectorComponent, EfQuantityStepperComponent, EfRankListComponent, EfRowActionsComponent, EfSearchToolbarComponent, EfSelectButtonComponent, EfSelectComponent, EfServerErrorsDirective, EfSkeletonComponent, EfSmartBarComponent, EfStatsComponent, EfStatusChipComponent, EfTabPanelDirective, EfTabsComponent, EfTextareaComponent, EfThemeConfiguratorComponent, EfTimelineComponent, EfToastRegionComponent, EfToggleSwitchComponent, EfToolbarComponent, EfTotalsComponent, OrderEntityHelper, OrderLineItemHelper, TruncatePipe, buildChartConfig, getColumnAlignment, mergeColumnDefaults, resolveEfStatusColor };
|
|
4925
|
+
export type { CatalogueProduct, CatalogueProductVariant, CategoryAssignment, CategoryGroup, CategoryItem, DatatableSearchEntity, DocumentConfig, EfBadgeColor, EfBadgeConfig, EfBadgeSize, EfBadgeVariant, EfButtonComptoirSeverity, EfButtonPrimeNGSeverity, EfButtonSeverity, EfChangeHistoryEntry, EfChangeHistoryFieldChange, EfChartSeries, EfChartType, EfDataCardRowAction, EfDatatableActions, EfDatatableColumn, EfDatatableColumnAlign, EfDatatableColumnType, EfDatatableConfig, EfDateFieldValue, EfDatePreset, EfDialogAction, EfDialogSeverity, EfDialogSize, EfFabPosition, EfKpiDeltaTone, EfKpiSparkline, EfPillItem, EfPresetItem, EfRankRow, EfRowAction, EfSkeletonVariant, EfStatsRow, EfStatusColor, EfStatusReferenceItem, EfTabItem, EfTabsModule, EfTabsVariant, EfTimelineItem, EfTimelineState, EfToastRegionPosition, EfTotalsGrand, EfTotalsRow, HighlightSegment, OrderChangeInfo, OrderEntity, OrderLineItem, OrderProductsSummary, OrderSummaryItem, ProductCountGroup, ProductCountGroupLabel, ProductTypeaheadRow, ProductTypeaheadSelection, ProductWithCountGroup, SelectedFilter, ValidationResult };
|