@elasticias/ui 1.0.49 → 1.0.50

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.
@@ -70,6 +70,20 @@ declare class EfQuantitySelectorComponent {
70
70
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfQuantitySelectorComponent, "ef-quantity-selector", never, { "quantity": { "alias": "quantity"; "required": false; "isSignal": true; }; }, { "quantityChange": "quantityChange"; }, never, never, true, never>;
71
71
  }
72
72
 
73
+ /**
74
+ * Which catalogue price a new order line starts from.
75
+ * - `wholesale`: the ERP channel price (`variant.price`, then `product.unitPrice`,
76
+ * which mirrors the default variant's, then `product.salePrice`). B2B sales orders.
77
+ * - `retail`: the shop price (`variant.salePrice`, then `product.salePrice`). A Web
78
+ * order must cost what the shop charges, and the shop sells a variant at its
79
+ * `salePrice` only: an unpriced variant is not sold, so retail never falls back to
80
+ * the wholesale price, and `compareAtPrice` (the "was" price) is never charged.
81
+ * With no shop price the line starts at 0 for the staff to set.
82
+ */
83
+ type EfOrderPriceList = 'wholesale' | 'retail';
84
+ /** The unit price a new line for `product` (and its chosen `variant`) starts at under `priceList`. */
85
+ declare function defaultUnitPrice(product: Record<string, unknown>, variant: Record<string, unknown> | null | undefined, priceList?: EfOrderPriceList): number;
86
+
73
87
  /**
74
88
  * Summary item for product count groups
75
89
  */
@@ -91,7 +105,7 @@ interface OrderProductsSummary {
91
105
  */
92
106
  interface OrderLineItem {
93
107
  id?: string | number;
94
- product?: Record<string, unknown>;
108
+ product?: Record<string, unknown> | null;
95
109
  productId?: unknown;
96
110
  variantId?: string | null;
97
111
  countGroup?: string;
@@ -135,6 +149,17 @@ interface OrderEntity {
135
149
  billingAddress?: string;
136
150
  productsSummary?: OrderProductsSummary;
137
151
  }
152
+ /**
153
+ * The person an order goes to when there is no client to pick (a storefront
154
+ * order placed by a shopper). The builder shows it read-only in place of the
155
+ * customer select.
156
+ */
157
+ interface EfOrderRecipient {
158
+ name: string;
159
+ phone?: string | null;
160
+ city?: string | null;
161
+ address?: string | null;
162
+ }
138
163
  /**
139
164
  * Configuration for document types (order, invoice, quote)
140
165
  */
@@ -201,8 +226,9 @@ declare class OrderLineItemHelper {
201
226
  /**
202
227
  * Create a line item from product selection
203
228
  * @param keyField - Field name used to identify the product (default: 'id')
229
+ * @param priceList - Which catalogue price the line starts at (see `EfOrderPriceList`)
204
230
  */
205
- static createFromProduct(product: Record<string, unknown>, quantity?: number, keyField?: string, variantId?: string): OrderLineItem;
231
+ static createFromProduct(product: Record<string, unknown>, quantity?: number, keyField?: string, variantId?: string, priceList?: EfOrderPriceList): OrderLineItem;
206
232
  /**
207
233
  * Update calculations for an existing line item
208
234
  */
@@ -397,15 +423,38 @@ interface ProductTypeaheadRow {
397
423
  /** Numeric line columns that support inline click-to-edit. */
398
424
  type EditableLineField = 'price' | 'qty' | 'discount' | 'tva';
399
425
  declare class EfOrderBuilderComponent implements OnInit {
400
- rowTrackBy: (_: number, item: OrderLineItem) => string | number;
426
+ rowTrackBy: (_: number, item: OrderLineItem) => string | number | undefined;
401
427
  config: _angular_core.InputSignal<DocumentConfig>;
402
428
  order: _angular_core.ModelSignal<OrderEntity>;
403
429
  products: _angular_core.InputSignal<Record<string, unknown>[]>;
404
430
  customers: _angular_core.InputSignal<Record<string, unknown>[]>;
431
+ /**
432
+ * Who the order goes to when it has no client to pick (a storefront order).
433
+ * When set, the header shows it read-only instead of the customer select,
434
+ * `customers` may be `[]` and the order validates without a `customerId`.
435
+ * Null keeps the customer select and its required rule.
436
+ */
437
+ recipient: _angular_core.InputSignal<EfOrderRecipient | null>;
438
+ /**
439
+ * Calling code (`'212'` or `'+212'`) for a national recipient phone, so the
440
+ * `tel:` link dials `+212612345678` for `0612345678` from anywhere.
441
+ */
442
+ defaultCallingCode: _angular_core.InputSignal<string>;
443
+ /**
444
+ * `tel:` target for the recipient's phone: E.164 when it can be made, else
445
+ * the digits as typed (a national number still dials inside the country).
446
+ */
447
+ recipientTel: _angular_core.Signal<string | null>;
405
448
  readonly: _angular_core.InputSignal<boolean>;
406
449
  countGroupLabels: _angular_core.InputSignal<ProductCountGroupLabel[]>;
407
450
  /** Field name used to identify products (must match catalogue's trackByField) */
408
451
  productKeyField: _angular_core.InputSignal<string>;
452
+ /**
453
+ * Which catalogue price a new line starts at, in quick-add, its typeahead
454
+ * and the catalogue: `'wholesale'` (default, B2B sales) or `'retail'`, the
455
+ * shop price a Web order is charged. Lines already on the order keep theirs.
456
+ */
457
+ priceList: _angular_core.InputSignal<EfOrderPriceList>;
409
458
  backendErrors: _angular_core.InputSignal<{
410
459
  [key: string]: string[];
411
460
  }>;
@@ -416,8 +465,15 @@ declare class EfOrderBuilderComponent implements OnInit {
416
465
  * the bound order then carries no `shippingTotal` at all. A negative or
417
466
  * non-numeric fee is treated as 0.
418
467
  */
419
- shippingTotal: _angular_core.InputSignalWithTransform<number, number>;
420
- /** Optional change-history entries; when non-empty the Historique rail card renders. */
468
+ shippingTotal: _angular_core.InputSignalWithTransform<number, number | null | undefined>;
469
+ /**
470
+ * Optional change-history entries; when non-empty the Historique rail card renders.
471
+ *
472
+ * Host cards that belong in the rail (a delivery card, internal notes) are
473
+ * projected with the `obRail` attribute: `<ef-card obRail ...>`. They sit
474
+ * after the totals and the recap and before the history, as a column at
475
+ * desktop width and inside the drawer below that or in focus mode.
476
+ */
421
477
  auditEntries: _angular_core.InputSignal<EfChangeHistoryEntry[]>;
422
478
  openCatalogue: _angular_core.OutputEmitterRef<void>;
423
479
  orderChanged: _angular_core.OutputEmitterRef<OrderChangeInfo>;
@@ -425,7 +481,7 @@ declare class EfOrderBuilderComponent implements OnInit {
425
481
  productsAdded: _angular_core.OutputEmitterRef<OrderLineItem[]>;
426
482
  private originalOrder;
427
483
  private initialized;
428
- quickAddSelection: _angular_core.WritableSignal<ProductTypeaheadSelection>;
484
+ quickAddSelection: _angular_core.WritableSignal<ProductTypeaheadSelection | null>;
429
485
  quickAddPrice: _angular_core.WritableSignal<number>;
430
486
  quickAddQuantity: _angular_core.WritableSignal<number>;
431
487
  quickAddDisabled: _angular_core.Signal<boolean>;
@@ -444,7 +500,7 @@ declare class EfOrderBuilderComponent implements OnInit {
444
500
  }>;
445
501
  hasErrors: _angular_core.Signal<boolean>;
446
502
  isValid: _angular_core.Signal<boolean>;
447
- changeInfo: _angular_core.Signal<OrderChangeInfo>;
503
+ changeInfo: _angular_core.Signal<OrderChangeInfo | null>;
448
504
  hasChanges: _angular_core.Signal<boolean>;
449
505
  focusMode: _angular_core.ModelSignal<boolean>;
450
506
  railOpen: _angular_core.WritableSignal<boolean>;
@@ -457,7 +513,7 @@ declare class EfOrderBuilderComponent implements OnInit {
457
513
  editingCell: _angular_core.WritableSignal<{
458
514
  id: OrderLineItem["id"];
459
515
  field: EditableLineField;
460
- }>;
516
+ } | null>;
461
517
  /**
462
518
  * Columns for the lines table.
463
519
  *
@@ -535,7 +591,7 @@ declare class EfOrderBuilderComponent implements OnInit {
535
591
  */
536
592
  private withTotals;
537
593
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfOrderBuilderComponent, never>;
538
- 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; }; "shippingTotal": { "alias": "shippingTotal"; "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>;
594
+ 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; }; "recipient": { "alias": "recipient"; "required": false; "isSignal": true; }; "defaultCallingCode": { "alias": "defaultCallingCode"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "countGroupLabels": { "alias": "countGroupLabels"; "required": false; "isSignal": true; }; "productKeyField": { "alias": "productKeyField"; "required": false; "isSignal": true; }; "priceList": { "alias": "priceList"; "required": false; "isSignal": true; }; "backendErrors": { "alias": "backendErrors"; "required": false; "isSignal": true; }; "shippingTotal": { "alias": "shippingTotal"; "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, ["[obRail]"], true, never>;
539
595
  }
540
596
 
541
597
  /**
@@ -569,6 +625,11 @@ declare class EfProductTypeaheadComponent {
569
625
  * variant + unit price) is identical either way.
570
626
  */
571
627
  showVariants: _angular_core.InputSignalWithTransform<boolean, unknown>;
628
+ /**
629
+ * Which catalogue price each row shows and its selection carries: the
630
+ * wholesale price (default) or the shop price for a Web order.
631
+ */
632
+ priceList: _angular_core.InputSignal<EfOrderPriceList>;
572
633
  productSelect: _angular_core.OutputEmitterRef<ProductTypeaheadSelection>;
573
634
  query: _angular_core.WritableSignal<string>;
574
635
  open: _angular_core.WritableSignal<boolean>;
@@ -591,7 +652,7 @@ declare class EfProductTypeaheadComponent {
591
652
  /** Clear the field after the consumer has consumed the selection. */
592
653
  reset(): void;
593
654
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfProductTypeaheadComponent, never>;
594
- 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>;
655
+ 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; }; "priceList": { "alias": "priceList"; "required": false; "isSignal": true; }; }, { "productSelect": "productSelect"; }, never, never, true, never>;
595
656
  }
596
657
 
597
658
  /**
@@ -854,7 +915,7 @@ declare class EfProductPickerComponent {
854
915
  readonly confirm: _angular_core.OutputEmitterRef<string[]>;
855
916
  readonly closed: _angular_core.OutputEmitterRef<void>;
856
917
  /** The list screen behind the dialog already owns the search shortcut. */
857
- readonly searchShortcut: any;
918
+ readonly searchShortcut: null;
858
919
  protected readonly isMobile: _angular_core.Signal<boolean>;
859
920
  private readonly selected;
860
921
  readonly selectedIds: _angular_core.Signal<string[]>;
@@ -1007,6 +1068,12 @@ declare class EfProductCatalogueComponent implements OnChanges {
1007
1068
  trackByField: _angular_core.InputSignal<string>;
1008
1069
  /** Currency code for price formatting */
1009
1070
  currencyCode: _angular_core.InputSignal<string>;
1071
+ /**
1072
+ * Which price the cards show: `'wholesale'` (default) or `'retail'`, the shop price.
1073
+ * Bind the same value as the order builder's `priceList`, so a card shows the price
1074
+ * of the line it adds (the rule lives in `defaultUnitPrice`).
1075
+ */
1076
+ priceList: _angular_core.InputSignal<EfOrderPriceList>;
1010
1077
  /** Locale used for number/currency formatting and the quantity stepper */
1011
1078
  localeCode: _angular_core.InputSignal<string>;
1012
1079
  /**
@@ -1020,7 +1087,7 @@ declare class EfProductCatalogueComponent implements OnChanges {
1020
1087
  * </ng-template>
1021
1088
  * </ef-product-catalogue>
1022
1089
  */
1023
- productThumbnailTpl: _angular_core.Signal<TemplateRef<unknown>>;
1090
+ productThumbnailTpl: _angular_core.Signal<TemplateRef<unknown> | undefined>;
1024
1091
  sortMenu: Menu;
1025
1092
  /** Emitted when products are validated */
1026
1093
  productsValidated: _angular_core.OutputEmitterRef<{
@@ -1073,11 +1140,13 @@ declare class EfProductCatalogueComponent implements OnChanges {
1073
1140
  getPackagingLabel(product: CatalogueProduct): string;
1074
1141
  getVariantTitle(product: CatalogueProduct, variantId: string): string;
1075
1142
  trackKey(product: CatalogueProduct): unknown;
1143
+ /** The price a variant (or a simple product, `variant` null) is shown at under the active list. */
1144
+ private priceOf;
1076
1145
  formatPrice(product: CatalogueProduct): string;
1077
- formatVariantPrice(variant: CatalogueProductVariant): string;
1146
+ formatVariantPrice(variant: CatalogueProductVariant, product?: CatalogueProduct): string;
1078
1147
  private formatCurrency;
1079
1148
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfProductCatalogueComponent, never>;
1080
- 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>;
1149
+ 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; }; "priceList": { "alias": "priceList"; "required": false; "isSignal": true; }; "localeCode": { "alias": "localeCode"; "required": false; "isSignal": true; }; }, { "productsValidated": "productsValidated"; }, ["productThumbnailTpl"], never, true, never>;
1081
1150
  }
1082
1151
 
1083
1152
  /**
@@ -1137,7 +1206,7 @@ declare class EfThemeToggleComponent {
1137
1206
  * Where the tooltip opens. Below suits a top bar (the app bar, the
1138
1207
  * login header); a toggle placed low on a page can open it above.
1139
1208
  */
1140
- readonly tooltipPosition: _angular_core.InputSignal<"top" | "left" | "bottom" | "right">;
1209
+ readonly tooltipPosition: _angular_core.InputSignal<"top" | "bottom" | "left" | "right">;
1141
1210
  /** Translation key for the accessible name (also the tooltip text). */
1142
1211
  readonly ariaLabelKey: _angular_core.InputSignal<string>;
1143
1212
  readonly isDark: _angular_core.Signal<boolean>;
@@ -1162,7 +1231,7 @@ declare class EfThemeToggleComponent {
1162
1231
  declare class EfBuildStampComponent {
1163
1232
  /** Copyright holder shown before the build. Omit for the build alone. */
1164
1233
  readonly owner: _angular_core.InputSignal<string>;
1165
- protected readonly info: _elasticias_core.EfBuildInfo;
1234
+ protected readonly info: _elasticias_core.EfBuildInfo | null;
1166
1235
  protected readonly year: number;
1167
1236
  /**
1168
1237
  * A released build is known by its version; an unreleased one has no
@@ -1231,7 +1300,7 @@ declare class EfAboutDialogComponent {
1231
1300
  readonly initial: _angular_core.InputSignal<string>;
1232
1301
  /** Copyright holder on the last line. */
1233
1302
  readonly owner: _angular_core.InputSignal<string>;
1234
- protected readonly info: _elasticias_core.EfBuildInfo;
1303
+ protected readonly info: _elasticias_core.EfBuildInfo | null;
1235
1304
  protected readonly year: number;
1236
1305
  protected readonly packages: _angular_core.Signal<EfBuildPackage[]>;
1237
1306
  /**
@@ -1350,7 +1419,7 @@ declare class EfShortcutsDialogComponent {
1350
1419
  declare class EfSessionIdleDialogComponent {
1351
1420
  protected readonly idle: EfSessionIdleService;
1352
1421
  private readonly session;
1353
- protected readonly secondsLeft: _angular_core.Signal<number>;
1422
+ protected readonly secondsLeft: _angular_core.Signal<number | null>;
1354
1423
  protected readonly actions: EfDialogAction[];
1355
1424
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfSessionIdleDialogComponent, never>;
1356
1425
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfSessionIdleDialogComponent, "ef-session-idle-dialog", never, {}, {}, never, never, true, never>;
@@ -1490,7 +1559,7 @@ declare class EfButtonComponent implements OnInit {
1490
1559
  * `'small' | 'large'`, with the default (unset) being the normal height, so
1491
1560
  * `'base'` maps to `null` rather than being forwarded verbatim.
1492
1561
  */
1493
- get pnSize(): 'small' | 'large' | null;
1562
+ get pnSize(): 'small' | 'large' | undefined;
1494
1563
  /** Composed class string for the Comptoir variant —
1495
1564
  * `btn btn-{severity} btn-sm` plus any caller-supplied `styleClass`. */
1496
1565
  get comptoirClass(): string;
@@ -1656,11 +1725,11 @@ declare class EfBadgeComponent {
1656
1725
  /**
1657
1726
  * Badge label text
1658
1727
  */
1659
- label: _angular_core.InputSignal<string>;
1728
+ label: _angular_core.InputSignal<string | undefined>;
1660
1729
  /**
1661
1730
  * Translation key for the label; wins over `label`.
1662
1731
  */
1663
- labelKey: _angular_core.InputSignal<string>;
1732
+ labelKey: _angular_core.InputSignal<string | undefined>;
1664
1733
  /**
1665
1734
  * Opt in to the pointer cursor and hover lift. Off by default so a
1666
1735
  * read-only badge does not look like a button.
@@ -1685,7 +1754,7 @@ declare class EfBadgeComponent {
1685
1754
  /**
1686
1755
  * Icon class (e.g., PrimeIcons)
1687
1756
  */
1688
- icon: _angular_core.InputSignal<string>;
1757
+ icon: _angular_core.InputSignal<string | undefined>;
1689
1758
  /**
1690
1759
  * Whether to show the dot indicator
1691
1760
  */
@@ -1818,7 +1887,7 @@ declare class EfAppShellComponent {
1818
1887
  readonly shortcutHint: string;
1819
1888
  toggleSide(): void;
1820
1889
  constructor();
1821
- readonly activeId: _angular_core.Signal<_elasticias_core.EfModuleId>;
1890
+ readonly activeId: _angular_core.Signal<_elasticias_core.EfModuleId | null>;
1822
1891
  readonly switcherOpen: _angular_core.WritableSignal<boolean>;
1823
1892
  /** Five tabs is what fits a phone; the rest live in the sheet. */
1824
1893
  readonly tabs: _angular_core.Signal<EfModule[]>;
@@ -1870,7 +1939,7 @@ declare class EfAppShellMobileComponent {
1870
1939
  private readonly perms;
1871
1940
  private readonly active;
1872
1941
  private readonly router;
1873
- readonly activeId: _angular_core.Signal<_elasticias_core.EfModuleId>;
1942
+ readonly activeId: _angular_core.Signal<_elasticias_core.EfModuleId | null>;
1874
1943
  readonly switcherOpen: _angular_core.WritableSignal<boolean>;
1875
1944
  readonly tabs: _angular_core.Signal<EfModule[]>;
1876
1945
  readonly allVisible: _angular_core.Signal<readonly EfModule[]>;
@@ -1902,7 +1971,7 @@ declare class EfAppMainComponent {
1902
1971
  /** Render the 3px module-color stripe at the top of the content area. */
1903
1972
  stripe: boolean;
1904
1973
  /** `data-module` value bound to the host. Null when no module is active. */
1905
- readonly moduleId: _angular_core.Signal<_elasticias_core.EfModuleId>;
1974
+ readonly moduleId: _angular_core.Signal<_elasticias_core.EfModuleId | null>;
1906
1975
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfAppMainComponent, never>;
1907
1976
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfAppMainComponent, "ef-app-main", never, { "stripe": { "alias": "stripe"; "required": false; }; }, {}, never, ["*"], true, never>;
1908
1977
  static ngAcceptInputType_stripe: unknown;
@@ -1937,7 +2006,7 @@ declare class EfAppTopComponent {
1937
2006
  */
1938
2007
  readonly logout: _angular_core.InputSignalWithTransform<boolean, unknown>;
1939
2008
  /** Present only when the app provides `EF_SESSION`. */
1940
- protected readonly session: _elasticias_core.EfSession;
2009
+ protected readonly session: _elasticias_core.EfSession | null;
1941
2010
  protected signOut(): void;
1942
2011
  /** A touch or pen press at least this long is a hold, not a tap. */
1943
2012
  static readonly HOLD_MS = 500;
@@ -1955,8 +2024,8 @@ declare class EfAppTopComponent {
1955
2024
  protected forgetSignOutPress(): void;
1956
2025
  protected onSignOutClick(event: MouseEvent): void;
1957
2026
  private readonly active;
1958
- readonly module: _angular_core.Signal<_elasticias_core.EfModule>;
1959
- readonly navItem: _angular_core.Signal<_elasticias_core.EfNavItem>;
2027
+ readonly module: _angular_core.Signal<_elasticias_core.EfModule | null>;
2028
+ readonly navItem: _angular_core.Signal<_elasticias_core.EfNavItem | null>;
1960
2029
  readonly hasBreadcrumb: _angular_core.Signal<boolean>;
1961
2030
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfAppTopComponent, never>;
1962
2031
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfAppTopComponent, "ef-app-top", never, { "themeToggle": { "alias": "themeToggle"; "required": false; "isSignal": true; }; "logout": { "alias": "logout"; "required": false; "isSignal": true; }; }, {}, never, ["[breadcrumb]", "[actions]"], true, never>;
@@ -1999,7 +2068,7 @@ declare class EfModuleRailComponent {
1999
2068
  /** Optional notification badges per module id. */
2000
2069
  badges: Partial<Record<EfModuleId, string | number>>;
2001
2070
  readonly visibleModules: _angular_core.Signal<readonly EfModule[]>;
2002
- readonly activeId: _angular_core.Signal<EfModuleId>;
2071
+ readonly activeId: _angular_core.Signal<EfModuleId | null>;
2003
2072
  /** Visible modules interleaved with dividers at group boundaries. */
2004
2073
  readonly rows: _angular_core.Signal<RailRow[]>;
2005
2074
  readonly hasBadges: _angular_core.Signal<boolean>;
@@ -2022,8 +2091,8 @@ declare class EfModuleRailComponent {
2022
2091
  declare class EfModuleSideComponent {
2023
2092
  private readonly active;
2024
2093
  private readonly perms;
2025
- readonly module: _angular_core.Signal<_elasticias_core.EfModule>;
2026
- readonly moduleId: _angular_core.Signal<_elasticias_core.EfModuleId>;
2094
+ readonly module: _angular_core.Signal<_elasticias_core.EfModule | null>;
2095
+ readonly moduleId: _angular_core.Signal<_elasticias_core.EfModuleId | null>;
2027
2096
  readonly visibleSections: _angular_core.Signal<EfNavSection[]>;
2028
2097
  trackSection(_: number, s: EfNavSection): string;
2029
2098
  trackItem(_: number, i: EfNavItem): string;
@@ -2128,8 +2197,15 @@ interface EfPillItem<T = string> {
2128
2197
  */
2129
2198
  declare class EfPillGroupComponent<T = string> {
2130
2199
  readonly items: _angular_core.InputSignal<readonly EfPillItem<T>[]>;
2131
- /** Two-way bound selection. */
2132
- readonly value: _angular_core.ModelSignal<T>;
2200
+ /** Selected value; `null` when nothing is selected. Two-way bindable
2201
+ * with `[(value)]`. */
2202
+ readonly value: _angular_core.InputSignal<T | null>;
2203
+ /** Emits the picked pill's value. Never `null`: a click always picks
2204
+ * a pill, so handlers can take `T` without a null check. */
2205
+ readonly valueChange: _angular_core.OutputEmitterRef<T>;
2206
+ /** What the pills render: the bound value, or the last pick when the
2207
+ * caller only listens to `valueChange`. */
2208
+ protected readonly selected: _angular_core.WritableSignal<T | null>;
2133
2209
  /** Translation key for the group's accessible name. */
2134
2210
  readonly ariaLabelKey: _angular_core.InputSignal<string>;
2135
2211
  /** Hide counts even when items provide them. */
@@ -2149,7 +2225,7 @@ declare class EfPillGroupComponent<T = string> {
2149
2225
  private measure;
2150
2226
  private scrollActiveIntoView;
2151
2227
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfPillGroupComponent<any>, never>;
2152
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPillGroupComponent<any>, "ef-pill-group", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "ariaLabelKey": { "alias": "ariaLabelKey"; "required": false; "isSignal": true; }; "hideCounts": { "alias": "hideCounts"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
2228
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPillGroupComponent<any>, "ef-pill-group", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "ariaLabelKey": { "alias": "ariaLabelKey"; "required": false; "isSignal": true; }; "hideCounts": { "alias": "hideCounts"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
2153
2229
  }
2154
2230
 
2155
2231
  /** Visual treatment of the tabset. `'pill'` is the default. */
@@ -2228,7 +2304,10 @@ declare class EfTabsComponent<T = string> implements AfterContentInit {
2228
2304
  overflow: boolean;
2229
2305
  /** Hide count badges even when items provide them. */
2230
2306
  hideCounts: boolean;
2307
+ /** Untranslated accessible name of the tablist. Prefer `ariaLabelKey`. */
2231
2308
  ariaLabel: string;
2309
+ /** Translation key for the tablist's accessible name; wins over `ariaLabel`. */
2310
+ ariaLabelKey?: string;
2232
2311
  /** Translation key used as the `aria-label` of the dirty dot.
2233
2312
  * Defaults to `'common.dirty'` — apps add the matching entry to
2234
2313
  * `fr.json` / `ar.json`. */
@@ -2249,7 +2328,7 @@ declare class EfTabsComponent<T = string> implements AfterContentInit {
2249
2328
  onKeydown(event: KeyboardEvent, index: number): void;
2250
2329
  trackValue(_: number, item: EfTabItem<T>): T;
2251
2330
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfTabsComponent<any>, never>;
2252
- 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>;
2331
+ 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; }; "ariaLabelKey": { "alias": "ariaLabelKey"; "required": false; }; "dirtyLabelKey": { "alias": "dirtyLabelKey"; "required": false; }; }, { "valueChange": "valueChange"; }, ["panels"], never, true, never>;
2253
2332
  static ngAcceptInputType_overflow: unknown;
2254
2333
  static ngAcceptInputType_hideCounts: unknown;
2255
2334
  }
@@ -2479,7 +2558,7 @@ declare class EfPulseComponent {
2479
2558
  declare class EfPdfPreviewComponent {
2480
2559
  private readonly sanitizer;
2481
2560
  /** The PDF blob to preview. Setting it (re)creates the object URL. */
2482
- blob: _angular_core.InputSignal<Blob>;
2561
+ blob: _angular_core.InputSignal<Blob | null>;
2483
2562
  /** File name shown in the header + used for download / share. */
2484
2563
  fileName: _angular_core.InputSignal<string>;
2485
2564
  /** Two-way dialog visibility. */
@@ -2491,11 +2570,16 @@ declare class EfPdfPreviewComponent {
2491
2570
  showOpenInNewTab: _angular_core.InputSignalWithTransform<boolean, unknown>;
2492
2571
  /** Show the WhatsApp share button (Web Share API → wa.me fallback). */
2493
2572
  showWhatsappShare: _angular_core.InputSignalWithTransform<boolean, unknown>;
2494
- /** Optional recipient phone for the wa.me fallback (digits / +). */
2573
+ /** Optional recipient phone for the wa.me fallback, as typed: international
2574
+ * (`+`/`00`) or national with `defaultCallingCode`. */
2495
2575
  whatsappPhone: _angular_core.InputSignal<string>;
2576
+ /** Calling code (`'212'` or `'+212'`) that turns a national
2577
+ * `whatsappPhone` (`0612345678`) into the international number wa.me
2578
+ * needs. Without it a national number opens the contact picker. */
2579
+ defaultCallingCode: _angular_core.InputSignal<string>;
2496
2580
  private readonly objectUrl;
2497
2581
  private currentUrl;
2498
- readonly safeUrl: _angular_core.Signal<SafeResourceUrl>;
2582
+ readonly safeUrl: _angular_core.Signal<SafeResourceUrl | null>;
2499
2583
  /** Footer buttons, rendered by `ef-dialog`'s `[actions]`. `dismiss:false`
2500
2584
  * keeps the preview open after download/print/share/open. */
2501
2585
  readonly actions: _angular_core.Signal<EfDialogAction[]>;
@@ -2508,7 +2592,7 @@ declare class EfPdfPreviewComponent {
2508
2592
  shareWhatsapp(): void;
2509
2593
  private openWhatsappWeb;
2510
2594
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfPdfPreviewComponent, never>;
2511
- 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>;
2595
+ 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; }; "defaultCallingCode": { "alias": "defaultCallingCode"; "required": false; "isSignal": true; }; }, { "visible": "visibleChange"; }, never, never, true, never>;
2512
2596
  }
2513
2597
 
2514
2598
  /**
@@ -2884,13 +2968,19 @@ interface EfRowAction {
2884
2968
  * ```
2885
2969
  *
2886
2970
  * Phone overflow: on the mobile tier, when the visible actions (custom and
2887
- * standard, Save included) outnumber `[overflowAfter]`, Save stays in view
2888
- * and every other action moves into a kebab menu (`ef-row-actions`, so it is
2971
+ * standard, Save included) outnumber `[overflowAfter]`, Save and any custom
2972
+ * action flagged `keepInView` stay in view and every other action moves
2973
+ * into a kebab menu (`ef-row-actions`, so it is
2889
2974
  * a `role="menu"` with Escape, outside-click and RTL placement). The split
2890
2975
  * happens after permission and `requiresWrite` filtering, so a hidden action
2891
2976
  * is hidden in the menu too. The projected `[actions]` slot is not moved.
2892
2977
  * Buttons are 48px on a coarse pointer (see `.detail-toolbar` in patterns).
2893
2978
  *
2979
+ * Tablet and desktop reflow: the identity has a basis
2980
+ * (`--detail-toolbar-identity-min`, 22rem), so when it and the actions
2981
+ * cannot share a row the actions wrap below it, rather than squeezing the
2982
+ * identity until its notices are cut.
2983
+ *
2894
2984
  * Custom actions can declare `permission` and `visible` like
2895
2985
  * `EfRowAction`. With `[context]` bound, the toolbar filters them
2896
2986
  * against `ScreenContext.isGranted()` automatically.
@@ -2910,7 +3000,7 @@ declare class EfDetailToolbarComponent {
2910
3000
  /** Optional ScreenContext — when present, custom actions with a
2911
3001
  * `permission` field and standard actions Print / Duplicate /
2912
3002
  * Delete are filtered against `context.isGranted(...)`. */
2913
- readonly context: _angular_core.InputSignal<ScreenContext>;
3003
+ readonly context: _angular_core.InputSignal<ScreenContext | undefined>;
2914
3004
  /** Render the standard Print action (left of the standard group). */
2915
3005
  readonly showPrintAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
2916
3006
  /** Render the standard Duplicate action. */
@@ -2951,10 +3041,21 @@ declare class EfDetailToolbarComponent {
2951
3041
  readonly hasCustomActions: _angular_core.Signal<boolean>;
2952
3042
  /** The phone is showing the overflow menu instead of inline buttons. */
2953
3043
  readonly overflowing: _angular_core.Signal<boolean>;
2954
- /** Everything but Save, as menu items, in toolbar order. */
3044
+ /** Visible custom actions that stay inline on a phone even when the rest overflow. */
3045
+ readonly keptInView: _angular_core.Signal<readonly EfDetailToolbarAction[]>;
3046
+ /** Everything but Save and the keepInView actions, as menu items, in toolbar order. */
2955
3047
  readonly overflowItems: _angular_core.Signal<readonly EfRowAction[]>;
2956
3048
  /** Whether the `|` separator should render — both groups present. */
2957
3049
  readonly showSeparator: _angular_core.Signal<boolean>;
3050
+ private readonly host;
3051
+ private readonly destroyRef;
3052
+ /** The standard group (separator, Print … Save) starts a row of its own,
3053
+ * below the custom actions: its leading separator would separate nothing. */
3054
+ readonly standardWrapped: _angular_core.WritableSignal<boolean>;
3055
+ constructor();
3056
+ /** Compares the standard group's row with the first item of the right
3057
+ * group. Public for specs: jsdom lays nothing out. */
3058
+ measureWrap(): void;
2958
3059
  onCustomClick(action: EfDetailToolbarAction): void;
2959
3060
  private isCustomVisible;
2960
3061
  /** Standard action visibility: `show*Action` flag AND permission
@@ -3016,7 +3117,7 @@ declare class EfSearchToolbarComponent {
3016
3117
  /** Optional ScreenContext — when present, custom actions with a
3017
3118
  * `permission` field and standard actions Export / Add are
3018
3119
  * filtered against `context.isGranted(...)`. */
3019
- readonly context: _angular_core.InputSignal<ScreenContext>;
3120
+ readonly context: _angular_core.InputSignal<ScreenContext | undefined>;
3020
3121
  /** Render the standard Export action (left of the standard group). */
3021
3122
  readonly showExportAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
3022
3123
  /** Render the standard Add action (rightmost, tenant-styled). */
@@ -3101,7 +3202,7 @@ interface EfTotalsGrand {
3101
3202
  */
3102
3203
  declare class EfTotalsComponent {
3103
3204
  readonly rows: _angular_core.InputSignal<readonly EfTotalsRow[]>;
3104
- readonly grand: _angular_core.InputSignal<EfTotalsGrand>;
3205
+ readonly grand: _angular_core.InputSignal<EfTotalsGrand | undefined>;
3105
3206
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfTotalsComponent, never>;
3106
3207
  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>;
3107
3208
  }
@@ -3320,7 +3421,7 @@ declare class EfKpiCardComponent {
3320
3421
  /** Computed `points="x,y x,y …"` attribute, normalized into the
3321
3422
  * 200×28 viewBox so the polyline always fits. Returns null
3322
3423
  * when the series is empty. */
3323
- readonly sparkPoints: _angular_core.Signal<string>;
3424
+ readonly sparkPoints: _angular_core.Signal<string | null>;
3324
3425
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfKpiCardComponent, never>;
3325
3426
  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; }; "hintKey": { "alias": "hintKey"; "required": false; "isSignal": true; }; "hintParams": { "alias": "hintParams"; "required": false; "isSignal": true; }; "spark": { "alias": "spark"; "required": false; "isSignal": true; }; "sparkColor": { "alias": "sparkColor"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
3326
3427
  }
@@ -3400,8 +3501,8 @@ type EfIdentityThumbSize = 'sm' | 'md';
3400
3501
  * ```
3401
3502
  */
3402
3503
  declare class EfIdentityThumbComponent {
3403
- readonly imageUrl: _angular_core.InputSignal<string>;
3404
- readonly name: _angular_core.InputSignal<string>;
3504
+ readonly imageUrl: _angular_core.InputSignal<string | null | undefined>;
3505
+ readonly name: _angular_core.InputSignal<string | null | undefined>;
3405
3506
  readonly size: _angular_core.InputSignal<EfIdentityThumbSize>;
3406
3507
  /** Set when the image fails; reset whenever the url changes. */
3407
3508
  protected readonly failed: _angular_core.WritableSignal<boolean>;
@@ -3437,18 +3538,18 @@ declare class EfIdentityThumbComponent {
3437
3538
  */
3438
3539
  declare class EfSeoPreviewComponent {
3439
3540
  /** The page title. Named `pageTitle` so it does not become the host's tooltip. */
3440
- readonly pageTitle: _angular_core.InputSignal<string>;
3541
+ readonly pageTitle: _angular_core.InputSignal<string | null | undefined>;
3441
3542
  /** The address as shown (no scheme needed), always rendered left to right. */
3442
- readonly url: _angular_core.InputSignal<string>;
3443
- readonly description: _angular_core.InputSignal<string>;
3543
+ readonly url: _angular_core.InputSignal<string | null | undefined>;
3544
+ readonly description: _angular_core.InputSignal<string | null | undefined>;
3444
3545
  /** i18n key of the small heading above the preview. */
3445
3546
  readonly labelKey: _angular_core.InputSignal<string>;
3446
3547
  /** Characters kept of the title; `null` shows it whole. */
3447
- readonly titleMaxLength: _angular_core.InputSignal<number>;
3548
+ readonly titleMaxLength: _angular_core.InputSignal<number | null>;
3448
3549
  /** Characters kept of the description; `null` shows it whole. */
3449
- readonly descriptionMaxLength: _angular_core.InputSignal<number>;
3550
+ readonly descriptionMaxLength: _angular_core.InputSignal<number | null>;
3450
3551
  /** Language of the previewed text (`fr`, `ar`, `en`), for screen readers and hyphenation. */
3451
- readonly contentLang: _angular_core.InputSignal<string>;
3552
+ readonly contentLang: _angular_core.InputSignal<string | null>;
3452
3553
  protected readonly labelId: string;
3453
3554
  protected readonly shownTitle: _angular_core.Signal<string>;
3454
3555
  protected readonly shownUrl: _angular_core.Signal<string>;
@@ -3574,7 +3675,7 @@ declare abstract class AbstractEfFormControl {
3574
3675
  * Falls back to the `NgControl` `serverError` path when neither is
3575
3676
  * present, so `ngModel`-based (v1) screens keep working unchanged.
3576
3677
  */
3577
- readonly errors: _angular_core.InputSignal<string[]>;
3678
+ readonly errors: _angular_core.InputSignal<string[] | null | undefined>;
3578
3679
  /** Optional enclosing `[efServerErrors]` scope (auto-link by `name`). */
3579
3680
  private readonly serverErrorsScope;
3580
3681
  /**
@@ -3584,7 +3685,7 @@ declare abstract class AbstractEfFormControl {
3584
3685
  * the subclass `serverErrors` / `isInvalid` getters track the source
3585
3686
  * signals under zoneless change detection.
3586
3687
  */
3587
- readonly resolvedExternalErrors: _angular_core.Signal<string[]>;
3688
+ readonly resolvedExternalErrors: _angular_core.Signal<string[] | null>;
3588
3689
  protected readonly translateService: TranslateService;
3589
3690
  /** Resolved DOM id. Always non-empty so `<label for>` and
3590
3691
  * `<input id>` can match unambiguously. */
@@ -3598,6 +3699,9 @@ declare abstract class AbstractEfFormControl {
3598
3699
  * accessible name and duplicate `aria-label` would override it.
3599
3700
  */
3600
3701
  get effectiveAriaLabel(): string | null;
3702
+ /** Ids of elements outside the control that describe it too (a character
3703
+ * counter, a help block), appended to `aria-describedby`. */
3704
+ readonly describedByExtra: _angular_core.InputSignal<string>;
3601
3705
  /** Translated hint (or empty string). */
3602
3706
  get effectiveHint(): string;
3603
3707
  /** Stable id of the hint element, `<id>-hint`. */
@@ -3614,7 +3718,7 @@ declare abstract class AbstractEfFormControl {
3614
3718
  * the validation message together with the field name. */
3615
3719
  get errorsId(): string;
3616
3720
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AbstractEfFormControl, never>;
3617
- 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; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "hintKey": { "alias": "hintKey"; "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>;
3721
+ 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; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "hintKey": { "alias": "hintKey"; "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; }; "describedByExtra": { "alias": "describedByExtra"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
3618
3722
  }
3619
3723
 
3620
3724
  declare class EfInputTextComponent extends AbstractEfFormControl implements ControlValueAccessor {
@@ -3652,7 +3756,7 @@ declare class EfInputTextComponent extends AbstractEfFormControl implements Cont
3652
3756
  value: string;
3653
3757
  private onChange;
3654
3758
  private onTouched;
3655
- readonly ngControl: NgControl;
3759
+ readonly ngControl: NgControl | null;
3656
3760
  constructor();
3657
3761
  get showRequired(): boolean;
3658
3762
  get serverErrors(): string[] | null;
@@ -3937,7 +4041,7 @@ declare class EfCheckboxComponent extends AbstractEfFormControl implements Contr
3937
4041
  checkedChange: EventEmitter<any>;
3938
4042
  private onChange;
3939
4043
  private onTouched;
3940
- readonly ngControl: NgControl;
4044
+ readonly ngControl: NgControl | null;
3941
4045
  constructor();
3942
4046
  get showRequired(): boolean;
3943
4047
  get serverErrors(): string[] | null;
@@ -3991,7 +4095,7 @@ declare class EfToggleSwitchComponent extends AbstractEfFormControl implements C
3991
4095
  checkedChange: EventEmitter<boolean>;
3992
4096
  private onChange;
3993
4097
  private onTouched;
3994
- readonly ngControl: NgControl;
4098
+ readonly ngControl: NgControl | null;
3995
4099
  constructor();
3996
4100
  writeValue(value: unknown): void;
3997
4101
  registerOnChange(fn: (value: boolean) => void): void;
@@ -4053,7 +4157,7 @@ declare class EfDatepickerComponent implements ControlValueAccessor {
4053
4157
  value: any;
4054
4158
  private onChange;
4055
4159
  private onTouched;
4056
- readonly ngControl: NgControl;
4160
+ readonly ngControl: NgControl | null;
4057
4161
  private readonly translateService;
4058
4162
  constructor();
4059
4163
  get effectivePlaceholder(): string;
@@ -4194,7 +4298,7 @@ declare class EfInputNumberComponent extends AbstractEfFormControl implements Co
4194
4298
  get displayText(): string | number;
4195
4299
  private onChange;
4196
4300
  private onTouched;
4197
- readonly ngControl: NgControl;
4301
+ readonly ngControl: NgControl | null;
4198
4302
  private readonly localeId;
4199
4303
  private readonly cdr;
4200
4304
  constructor();
@@ -4266,7 +4370,7 @@ declare class EfPasswordComponent extends AbstractEfFormControl implements Contr
4266
4370
  value: string;
4267
4371
  private onChange;
4268
4372
  private onTouched;
4269
- readonly ngControl: NgControl;
4373
+ readonly ngControl: NgControl | null;
4270
4374
  constructor();
4271
4375
  get showRequired(): boolean;
4272
4376
  get serverErrors(): string[] | null;
@@ -4306,7 +4410,7 @@ declare class EfMultiSelectComponent extends AbstractEfFormControl implements Co
4306
4410
  selectedValues: any[];
4307
4411
  private propagateChange;
4308
4412
  private propagateTouched;
4309
- readonly ngControl: NgControl;
4413
+ readonly ngControl: NgControl | null;
4310
4414
  constructor();
4311
4415
  get showRequired(): boolean;
4312
4416
  get serverErrors(): string[] | null;
@@ -4335,7 +4439,7 @@ declare class EfSelectButtonComponent extends AbstractEfFormControl implements C
4335
4439
  value: any;
4336
4440
  private onChange;
4337
4441
  private onTouched;
4338
- readonly ngControl: NgControl;
4442
+ readonly ngControl: NgControl | null;
4339
4443
  constructor();
4340
4444
  writeValue(value: any): void;
4341
4445
  registerOnChange(fn: (value: any) => void): void;
@@ -4401,7 +4505,7 @@ declare class EfQuantityStepperComponent implements ControlValueAccessor {
4401
4505
  /**
4402
4506
  * Callback to invoke when the value changes
4403
4507
  */
4404
- valueChange: EventEmitter<number>;
4508
+ valueChange: EventEmitter<number | null>;
4405
4509
  /**
4406
4510
  * Pass Through configuration for custom styling
4407
4511
  */
@@ -4634,23 +4738,23 @@ declare class EfDatatableComponent implements OnInit {
4634
4738
  /**
4635
4739
  * Action column configuration (edit/delete/duplicate buttons)
4636
4740
  */
4637
- actions: _angular_core.InputSignal<EfDatatableActions>;
4741
+ actions: _angular_core.InputSignal<EfDatatableActions | undefined>;
4638
4742
  /**
4639
4743
  * SearchEntity containing items, pagination, etc.
4640
4744
  */
4641
- searchEntity: _angular_core.InputSignal<DatatableSearchEntity>;
4745
+ searchEntity: _angular_core.InputSignal<DatatableSearchEntity | undefined>;
4642
4746
  /**
4643
4747
  * ScreenContext for reference data access
4644
4748
  */
4645
- context: _angular_core.InputSignal<ScreenContext>;
4749
+ context: _angular_core.InputSignal<ScreenContext | undefined>;
4646
4750
  /**
4647
4751
  * PassThrough options for deep DOM customization
4648
4752
  */
4649
- pt: _angular_core.InputSignal<Record<string, unknown>>;
4753
+ pt: _angular_core.InputSignal<Record<string, unknown> | undefined>;
4650
4754
  /**
4651
4755
  * Screen state key for state persistence (auto-generates stateKey if not provided in config)
4652
4756
  */
4653
- screenStateKey: _angular_core.InputSignal<string>;
4757
+ screenStateKey: _angular_core.InputSignal<string | undefined>;
4654
4758
  /**
4655
4759
  * Emitted when edit button is clicked (emits row ID)
4656
4760
  */
@@ -4711,7 +4815,7 @@ declare class EfDatatableComponent implements OnInit {
4711
4815
  /**
4712
4816
  * Computed sort field from searchEntity for restoring table state
4713
4817
  */
4714
- sortField: _angular_core.Signal<string>;
4818
+ sortField: _angular_core.Signal<string | undefined>;
4715
4819
  /**
4716
4820
  * Computed sort order from searchEntity for restoring table state
4717
4821
  * 1 = ascending, -1 = descending
@@ -4881,7 +4985,7 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
4881
4985
  private readonly configuredMobileLayout;
4882
4986
  readonly isMobile: _angular_core.Signal<boolean>;
4883
4987
  /** Per-screen override of the app-wide default. */
4884
- readonly mobileLayout: _angular_core.InputSignal<EfDataCardMobileLayout>;
4988
+ readonly mobileLayout: _angular_core.InputSignal<EfDataCardMobileLayout | null>;
4885
4989
  protected readonly effectiveMobileLayout: _angular_core.Signal<EfDataCardMobileLayout>;
4886
4990
  /** Rows currently showing their detail, keyed the same way as trackByRow. */
4887
4991
  private readonly expandedRows;
@@ -4916,8 +5020,8 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
4916
5020
  type?: string;
4917
5021
  }): string;
4918
5022
  private readonly derivedPrimaryId;
4919
- protected readonly primaryColumn: _angular_core.Signal<EfDataCardColumn>;
4920
- protected readonly statusColumn: _angular_core.Signal<EfDataCardColumn>;
5023
+ protected readonly primaryColumn: _angular_core.Signal<EfDataCardColumn | undefined>;
5024
+ protected readonly statusColumn: _angular_core.Signal<EfDataCardColumn | undefined>;
4921
5025
  protected readonly secondaryColumns: _angular_core.Signal<EfDataCardColumn[]>;
4922
5026
  /**
4923
5027
  * Fields shown once a row opens. The primary column is excluded: the
@@ -4951,7 +5055,7 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
4951
5055
  readonly pageSizeOptions: _angular_core.InputSignal<readonly number[]>;
4952
5056
  readonly hidePager: _angular_core.InputSignalWithTransform<boolean, unknown>;
4953
5057
  /** Currently active sort. Header click toggles asc / desc. */
4954
- readonly sort: _angular_core.InputSignal<EfDataCardSort>;
5058
+ readonly sort: _angular_core.InputSignal<EfDataCardSort | undefined>;
4955
5059
  /**
4956
5060
  * First load and every refresh. While true with no rows yet, the body
4957
5061
  * shimmers `ef-skeleton` placeholders instead of the empty state — a
@@ -5020,18 +5124,18 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
5020
5124
  * not have, and `aria-selected` is not allowed on a button. Unset, no
5021
5125
  * attribute is written.
5022
5126
  */
5023
- readonly rowPressed: _angular_core.InputSignal<(row: TRow) => boolean>;
5127
+ readonly rowPressed: _angular_core.InputSignal<((row: TRow) => boolean) | null>;
5024
5128
  /**
5025
5129
  * A row that is shown but cannot be activated (a product already in the
5026
5130
  * collection): `.is-disabled` dims it, `aria-disabled` says so, and
5027
5131
  * click, Enter and Space are ignored. It stays focusable, so a screen
5028
5132
  * reader user can still find it and hear why nothing happens.
5029
5133
  */
5030
- readonly rowDisabled: _angular_core.InputSignal<(row: TRow) => boolean>;
5134
+ readonly rowDisabled: _angular_core.InputSignal<((row: TRow) => boolean) | null>;
5031
5135
  protected pressedAttr(row: TRow): 'true' | 'false' | null;
5032
5136
  protected isRowDisabled(row: TRow): boolean;
5033
5137
  readonly hasActionsColumn: _angular_core.InputSignalWithTransform<boolean, unknown>;
5034
- readonly rowActionsContext: _angular_core.InputSignal<ScreenContext>;
5138
+ readonly rowActionsContext: _angular_core.InputSignal<ScreenContext | undefined>;
5035
5139
  readonly showViewAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
5036
5140
  readonly showEditAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
5037
5141
  readonly showDuplicateAction: _angular_core.InputSignalWithTransform<boolean, unknown>;
@@ -5049,7 +5153,7 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
5049
5153
  * on desktop rows and phone cards alike. A row whose actions are all
5050
5154
  * hidden gets a disabled trigger. Unset, every row keeps every action.
5051
5155
  */
5052
- readonly rowActionState: _angular_core.InputSignal<(action: EfDataCardRowAction, row: TRow) => EfDataCardRowActionState>;
5156
+ readonly rowActionState: _angular_core.InputSignal<((action: EfDataCardRowAction, row: TRow) => EfDataCardRowActionState) | null>;
5053
5157
  /** Render the Density control in the head row. */
5054
5158
  readonly showDensityControl: _angular_core.InputSignalWithTransform<boolean, unknown>;
5055
5159
  /** Render the Columns picker in the head row. */
@@ -5073,7 +5177,7 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
5073
5177
  * moving Export out of `ef-search-toolbar` does not quietly drop the
5074
5178
  * permission check that lived there.
5075
5179
  */
5076
- readonly screenContext: _angular_core.InputSignal<ScreenContext>;
5180
+ readonly screenContext: _angular_core.InputSignal<ScreenContext | undefined>;
5077
5181
  /**
5078
5182
  * Mirrors `ef-search-toolbar`'s rule exactly: hidden unless asked for,
5079
5183
  * and with a context present it obeys `hasExportPermission`. No
@@ -5154,7 +5258,7 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
5154
5258
  /** Build an Angular DigitInfo string from min/max fraction-digit hints. */
5155
5259
  numberFormat(col: EfDataCardColumn): string;
5156
5260
  /** Which tools panel is open, if any. */
5157
- readonly openTool: _angular_core.WritableSignal<"density" | "columns">;
5261
+ readonly openTool: _angular_core.WritableSignal<"density" | "columns" | null>;
5158
5262
  /**
5159
5263
  * Density this table starts at.
5160
5264
  *
@@ -5178,8 +5282,8 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
5178
5282
  to: number;
5179
5283
  }>;
5180
5284
  /** Index being dragged, and the index it would land on. */
5181
- readonly dragFrom: _angular_core.WritableSignal<number>;
5182
- readonly dragTo: _angular_core.WritableSignal<number>;
5285
+ readonly dragFrom: _angular_core.WritableSignal<number | null>;
5286
+ readonly dragTo: _angular_core.WritableSignal<number | null>;
5183
5287
  onDragPointerDown(index: number, ev: PointerEvent): void;
5184
5288
  onDragPointerMove(ev: PointerEvent): void;
5185
5289
  onDragPointerUp(): void;
@@ -5474,7 +5578,7 @@ declare class EfRowActionsComponent {
5474
5578
  readonly items: _angular_core.InputSignal<readonly EfRowAction[]>;
5475
5579
  /** Optional context — when present, items with a `permission` are
5476
5580
  * filtered against `context.isGranted(permission)`. */
5477
- readonly context: _angular_core.InputSignal<ScreenContext>;
5581
+ readonly context: _angular_core.InputSignal<ScreenContext | undefined>;
5478
5582
  /** Override the trigger icon (default ellipsis). */
5479
5583
  readonly triggerIcon: _angular_core.InputSignal<string>;
5480
5584
  /** Override the trigger aria-label translation key. */
@@ -5541,7 +5645,7 @@ declare class EfRowActionsComponent {
5541
5645
  bottom: string;
5542
5646
  left: string;
5543
5647
  maxHeight: string;
5544
- }>;
5648
+ } | null>;
5545
5649
  /**
5546
5650
  * Fixed rather than absolute: inside ef-data-card the table sits in a
5547
5651
  * horizontal scroller, and `overflow-x: auto` makes the block axis clip
@@ -5763,7 +5867,7 @@ declare class EfSmartBarComponent {
5763
5867
  /** Keyboard shortcut that focuses the search input. `null` opts out
5764
5868
  * (a screen with two smart bars registers the binding on only one
5765
5869
  * of them). Defaults to `'mod+k'`. */
5766
- readonly shortcut: _angular_core.InputSignal<string>;
5870
+ readonly shortcut: _angular_core.InputSignal<string | null>;
5767
5871
  /**
5768
5872
  * Accessible name for the search field: the placeholder text, which
5769
5873
  * already says what this box searches ("Search by order N, customer,
@@ -5828,7 +5932,7 @@ declare class EfFilterPillComponent {
5828
5932
  /** Current value displayed after the label. */
5829
5933
  readonly value: _angular_core.InputSignal<string>;
5830
5934
  /** `'active'` paints ink-active; `'tenant'` paints the tenant-50 surface. */
5831
- readonly tone: _angular_core.InputSignal<"active" | "tenant" | "neutral">;
5935
+ readonly tone: _angular_core.InputSignal<"tenant" | "neutral" | "active">;
5832
5936
  /** Show the ✕ clear button at the end of the pill. */
5833
5937
  readonly hasClear: _angular_core.InputSignalWithTransform<boolean, unknown>;
5834
5938
  /** Show a chevron + position the projected `[popover]` slot. */
@@ -5899,7 +6003,7 @@ declare class EfServerErrorsDirective {
5899
6003
  /** Field-name → messages map (camelCase keys, matching control `name`). */
5900
6004
  readonly errors: _angular_core.InputSignal<{
5901
6005
  [key: string]: string[];
5902
- }>;
6006
+ } | null>;
5903
6007
  /** Messages for a control by its `name`, or `null` when none. */
5904
6008
  errorsFor(name: string | undefined | null): string[] | null;
5905
6009
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfServerErrorsDirective, never>;
@@ -6023,7 +6127,7 @@ declare class EfRadioComponent extends AbstractEfFormControl implements ControlV
6023
6127
  selectionChangeEvent: EventEmitter<any>;
6024
6128
  private onChange;
6025
6129
  private onTouched;
6026
- readonly ngControl: NgControl;
6130
+ readonly ngControl: NgControl | null;
6027
6131
  constructor();
6028
6132
  get hasLabel(): boolean;
6029
6133
  /** Shared `name` so the browser treats the options as one group. */
@@ -6082,7 +6186,7 @@ declare class EfTextareaComponent extends AbstractEfFormControl implements Contr
6082
6186
  clearValue(): void;
6083
6187
  private onChange;
6084
6188
  private onTouched;
6085
- readonly ngControl: NgControl;
6189
+ readonly ngControl: NgControl | null;
6086
6190
  constructor();
6087
6191
  get isInvalid(): boolean;
6088
6192
  get serverErrors(): string[] | null;
@@ -6099,6 +6203,65 @@ declare class EfTextareaComponent extends AbstractEfFormControl implements Contr
6099
6203
  static ngAcceptInputType_mono: unknown;
6100
6204
  }
6101
6205
 
6206
+ /** A language the SEO texts are written in. */
6207
+ interface EfSeoLocale {
6208
+ code: string;
6209
+ labelKey: string;
6210
+ dir: 'auto' | 'rtl' | 'ltr';
6211
+ }
6212
+ /** What the fields write back: French is the scalar, every other language a dictionary entry. */
6213
+ interface EfSeoPatch {
6214
+ seoTitle?: string;
6215
+ seoDescription?: string;
6216
+ seoTitleTranslations?: Record<string, string>;
6217
+ seoDescriptionTranslations?: Record<string, string>;
6218
+ }
6219
+ type Field = 'title' | 'description';
6220
+ declare const EF_SEO_DEFAULT_LOCALES: ReadonlyArray<EfSeoLocale>;
6221
+ /**
6222
+ * SEO title and description per language, each with a counter against what a
6223
+ * search engine shows (60 / 160), capped at the server's limits (256 / 512),
6224
+ * and the shared `ef-seo-preview` of the French result with the entity's own
6225
+ * title and description as the fallback the shop uses. Card-less: each screen
6226
+ * wraps it in its own `ef-card`.
6227
+ *
6228
+ * The French controls carry the backend names (`seoTitle`, `seoDescription`)
6229
+ * so `[efServerErrors]` links their errors; the others (`seoTitleAr`, ...) are
6230
+ * dictionary entries whose errors are toasted (ADR-010).
6231
+ *
6232
+ * ```html
6233
+ * <ef-seo-fields [seoTitle]="p.seoTitle" ... [previewUrl]="url()" (seoChange)="patch($event)" />
6234
+ * ```
6235
+ */
6236
+ declare class EfSeoFieldsComponent {
6237
+ readonly seoTitle: _angular_core.InputSignal<string | null | undefined>;
6238
+ readonly seoDescription: _angular_core.InputSignal<string | null | undefined>;
6239
+ readonly seoTitleTranslations: _angular_core.InputSignal<Record<string, string> | null | undefined>;
6240
+ readonly seoDescriptionTranslations: _angular_core.InputSignal<Record<string, string> | null | undefined>;
6241
+ /** The entity's own texts, which the shop uses when SEO is empty. */
6242
+ readonly fallbackTitle: _angular_core.InputSignal<string | null | undefined>;
6243
+ readonly fallbackDescription: _angular_core.InputSignal<string | null | undefined>;
6244
+ /** The page address shown in the preview, computed by the app. */
6245
+ readonly previewUrl: _angular_core.InputSignal<string>;
6246
+ readonly titleMax: _angular_core.InputSignal<number>;
6247
+ readonly descriptionMax: _angular_core.InputSignal<number>;
6248
+ readonly titleAdvised: _angular_core.InputSignal<number>;
6249
+ readonly descriptionAdvised: _angular_core.InputSignal<number>;
6250
+ readonly locales: _angular_core.InputSignal<readonly EfSeoLocale[]>;
6251
+ readonly seoChange: _angular_core.OutputEmitterRef<EfSeoPatch>;
6252
+ text(locale: string, field: Field): string;
6253
+ /** Id of a counter, which the field it counts points at with `aria-describedby`. */
6254
+ counterId(locale: string, field: Field): string;
6255
+ private readonly uid;
6256
+ /** French matches the backend property; the others are unique for the label link. */
6257
+ name(locale: string, field: Field): string;
6258
+ setText(locale: string, field: Field, value: string): void;
6259
+ protected readonly previewTitle: _angular_core.Signal<string>;
6260
+ protected readonly previewDescription: _angular_core.Signal<string>;
6261
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfSeoFieldsComponent, never>;
6262
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfSeoFieldsComponent, "ef-seo-fields", never, { "seoTitle": { "alias": "seoTitle"; "required": false; "isSignal": true; }; "seoDescription": { "alias": "seoDescription"; "required": false; "isSignal": true; }; "seoTitleTranslations": { "alias": "seoTitleTranslations"; "required": false; "isSignal": true; }; "seoDescriptionTranslations": { "alias": "seoDescriptionTranslations"; "required": false; "isSignal": true; }; "fallbackTitle": { "alias": "fallbackTitle"; "required": false; "isSignal": true; }; "fallbackDescription": { "alias": "fallbackDescription"; "required": false; "isSignal": true; }; "previewUrl": { "alias": "previewUrl"; "required": false; "isSignal": true; }; "titleMax": { "alias": "titleMax"; "required": false; "isSignal": true; }; "descriptionMax": { "alias": "descriptionMax"; "required": false; "isSignal": true; }; "titleAdvised": { "alias": "titleAdvised"; "required": false; "isSignal": true; }; "descriptionAdvised": { "alias": "descriptionAdvised"; "required": false; "isSignal": true; }; "locales": { "alias": "locales"; "required": false; "isSignal": true; }; }, { "seoChange": "seoChange"; }, never, never, true, never>;
6263
+ }
6264
+
6102
6265
  type EfFileRejectReason = 'size' | 'type';
6103
6266
  interface EfFileRejection {
6104
6267
  file: File;
@@ -6129,13 +6292,13 @@ interface EfFileRejection {
6129
6292
  */
6130
6293
  declare class EfFileUploadComponent {
6131
6294
  /** Visible label (translation key). Omit for an icon-only button and set `ariaLabelKey`. */
6132
- readonly labelKey: _angular_core.InputSignal<string>;
6133
- readonly ariaLabelKey: _angular_core.InputSignal<string>;
6134
- readonly icon: _angular_core.InputSignal<string>;
6295
+ readonly labelKey: _angular_core.InputSignal<string | undefined>;
6296
+ readonly ariaLabelKey: _angular_core.InputSignal<string | undefined>;
6297
+ readonly icon: _angular_core.InputSignal<string | undefined>;
6135
6298
  readonly severity: _angular_core.InputSignal<"primary" | "danger" | "tenant" | "ghost">;
6136
6299
  /** The `<input accept>` list: MIME types, `type/*` and `.ext`, comma separated. */
6137
- readonly accept: _angular_core.InputSignal<string>;
6138
- readonly maxSizeBytes: _angular_core.InputSignal<number>;
6300
+ readonly accept: _angular_core.InputSignal<string | undefined>;
6301
+ readonly maxSizeBytes: _angular_core.InputSignal<number | undefined>;
6139
6302
  /** Translation key shown when the file is over `maxSizeBytes`. */
6140
6303
  readonly sizeErrorKey: _angular_core.InputSignal<string>;
6141
6304
  /** Translation key shown when the file does not match `accept`. */
@@ -6145,7 +6308,7 @@ declare class EfFileUploadComponent {
6145
6308
  readonly fileRejected: _angular_core.OutputEmitterRef<EfFileRejection>;
6146
6309
  private readonly picker;
6147
6310
  private readonly reason;
6148
- protected readonly errorKey: _angular_core.Signal<string>;
6311
+ protected readonly errorKey: _angular_core.Signal<string | null>;
6149
6312
  protected open(): void;
6150
6313
  protected onChange(event: Event): void;
6151
6314
  private check;
@@ -6188,9 +6351,9 @@ declare class EfPresetPillComponent<T = string> {
6188
6351
  readonly icon: _angular_core.InputSignal<string>;
6189
6352
  readonly labelKey: _angular_core.InputSignal<string>;
6190
6353
  readonly label: _angular_core.InputSignal<string>;
6191
- readonly tone: _angular_core.InputSignal<"active" | "tenant" | "neutral">;
6354
+ readonly tone: _angular_core.InputSignal<"tenant" | "neutral" | "active">;
6192
6355
  readonly presets: _angular_core.InputSignal<readonly EfPresetItem<T>[]>;
6193
- readonly activeKey: _angular_core.ModelSignal<T>;
6356
+ readonly activeKey: _angular_core.ModelSignal<T | null>;
6194
6357
  /** Two-way; consumer can hoist for controlled mode. */
6195
6358
  readonly open: _angular_core.ModelSignal<boolean>;
6196
6359
  /** Auto-close the popover after selection (default on). */
@@ -6276,7 +6439,7 @@ declare class EfDatepickerAdvancedComponent extends AbstractEfFormControl implem
6276
6439
  * `NG_VALUE_ACCESSOR` provider is needed and there's no circular DI.
6277
6440
  * `null` in filter mode (the output-only smart-bar usage).
6278
6441
  */
6279
- readonly ngControl: NgControl;
6442
+ readonly ngControl: NgControl | null;
6280
6443
  /** Always-present wrapper — the anchor for portal positioning (the
6281
6444
  * trigger itself lives behind an `@if`, so we anchor to the host box). */
6282
6445
  private anchorEl;
@@ -6298,13 +6461,13 @@ declare class EfDatepickerAdvancedComponent extends AbstractEfFormControl implem
6298
6461
  * `last_90_days`, `this_quarter`, `this_year` — pass anything to
6299
6462
  * replace them outright (e.g. include a `last_year` preset).
6300
6463
  */
6301
- readonly presets: _angular_core.InputSignal<readonly EfDatePreset[]>;
6464
+ readonly presets: _angular_core.InputSignal<readonly EfDatePreset[] | undefined>;
6302
6465
  /** Currently active preset key (controlled). */
6303
- readonly activePreset: _angular_core.InputSignal<string>;
6466
+ readonly activePreset: _angular_core.InputSignal<string | undefined>;
6304
6467
  /** Currently selected start (controlled — pairs with `activePreset`). */
6305
- readonly start: _angular_core.InputSignal<Date>;
6468
+ readonly start: _angular_core.InputSignal<Date | null | undefined>;
6306
6469
  /** Currently selected end. */
6307
- readonly end: _angular_core.InputSignal<Date>;
6470
+ readonly end: _angular_core.InputSignal<Date | null | undefined>;
6308
6471
  /** Show a `'Personnalisé…'` row that opens the calendar view. */
6309
6472
  readonly allowCustomRange: _angular_core.InputSignalWithTransform<boolean, unknown>;
6310
6473
  /**
@@ -6361,8 +6524,8 @@ declare class EfDatepickerAdvancedComponent extends AbstractEfFormControl implem
6361
6524
  /** Custom view: month being displayed (1st of the month, 00:00). */
6362
6525
  readonly visibleMonth: _angular_core.WritableSignal<Date>;
6363
6526
  /** Custom view: working start/end, before the user clicks Apply. */
6364
- readonly draftStart: _angular_core.WritableSignal<Date>;
6365
- readonly draftEnd: _angular_core.WritableSignal<Date>;
6527
+ readonly draftStart: _angular_core.WritableSignal<Date | null>;
6528
+ readonly draftEnd: _angular_core.WritableSignal<Date | null>;
6366
6529
  /** Effective preset list — defaults if none provided. */
6367
6530
  readonly effectivePresets: _angular_core.Signal<readonly EfDatePreset[]>;
6368
6531
  /** Current value resolved against today's date. */
@@ -6406,8 +6569,8 @@ declare class EfDatepickerAdvancedComponent extends AbstractEfFormControl implem
6406
6569
  /** Committed value pushed in via `writeValue` / day-pick / Apply. */
6407
6570
  private readonly fieldValue;
6408
6571
  /** Committed start / end derived from `fieldValue`. */
6409
- readonly fieldStart: _angular_core.Signal<Date>;
6410
- readonly fieldEnd: _angular_core.Signal<Date>;
6572
+ readonly fieldStart: _angular_core.Signal<Date | null>;
6573
+ readonly fieldEnd: _angular_core.Signal<Date | null>;
6411
6574
  /** Whether the field currently holds a value (vs. placeholder). */
6412
6575
  readonly hasFieldValue: _angular_core.Signal<boolean>;
6413
6576
  /** Text rendered in the field-mode trigger (date, +time when enabled). */
@@ -6599,13 +6762,17 @@ declare class EfActivationFilterComponent {
6599
6762
  readonly allLabelKey: _angular_core.InputSignal<string>;
6600
6763
  readonly activeLabelKey: _angular_core.InputSignal<string>;
6601
6764
  readonly inactiveLabelKey: _angular_core.InputSignal<string>;
6602
- readonly valueChange: _angular_core.OutputEmitterRef<boolean>;
6765
+ readonly valueChange: _angular_core.OutputEmitterRef<boolean | undefined>;
6603
6766
  readonly selected: _angular_core.Signal<"active" | "inactive" | "all">;
6604
- readonly buckets: _angular_core.Signal<{
6767
+ readonly buckets: _angular_core.Signal<({
6768
+ key: string;
6769
+ labelKey: string;
6770
+ value: undefined;
6771
+ } | {
6605
6772
  key: string;
6606
6773
  labelKey: string;
6607
6774
  value: boolean;
6608
- }[]>;
6775
+ })[]>;
6609
6776
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfActivationFilterComponent, never>;
6610
6777
  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>;
6611
6778
  }
@@ -6637,7 +6804,7 @@ declare class EfThemeConfiguratorComponent implements OnInit {
6637
6804
  presetsDisplayNameKeys: Record<string, string>;
6638
6805
  get ripple(): boolean;
6639
6806
  set ripple(value: boolean);
6640
- get isRTL(): boolean;
6807
+ get isRTL(): boolean | undefined;
6641
6808
  config: PrimeNG;
6642
6809
  configService: EfThemeConfigService;
6643
6810
  platformId: Object;
@@ -6661,9 +6828,9 @@ declare class EfThemeConfiguratorComponent implements OnInit {
6661
6828
  950: string;
6662
6829
  };
6663
6830
  }[];
6664
- selectedPrimaryColor: _angular_core.Signal<string>;
6665
- selectedSurfaceColor: _angular_core.Signal<string>;
6666
- selectedPreset: _angular_core.Signal<string>;
6831
+ selectedPrimaryColor: _angular_core.Signal<string | undefined>;
6832
+ selectedSurfaceColor: _angular_core.Signal<string | undefined>;
6833
+ selectedPreset: _angular_core.Signal<string | undefined>;
6667
6834
  primaryColors: _angular_core.Signal<{
6668
6835
  name: string;
6669
6836
  palette: Record<string, string>;
@@ -6704,7 +6871,7 @@ declare class EfEmailMetricsCardComponent {
6704
6871
  protected readonly noAutofocus: {
6705
6872
  autofocus: boolean;
6706
6873
  };
6707
- metrics: _angular_core.InputSignal<EmailMetrics>;
6874
+ metrics: _angular_core.InputSignal<EmailMetrics | null>;
6708
6875
  recentEvents: _angular_core.InputSignal<EmailEventRecord[]>;
6709
6876
  loading: _angular_core.InputSignal<boolean>;
6710
6877
  title: _angular_core.InputSignal<string>;
@@ -6733,5 +6900,5 @@ declare class EfEmailMetricsCardComponent {
6733
6900
  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>;
6734
6901
  }
6735
6902
 
6736
- 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_DATA_CARD_MOBILE_LAYOUT, EF_STATUS_COLORS, EF_STATUS_COLOR_ALIASES, EfAboutDialogComponent, EfActivationFilterComponent, EfAppMainComponent, EfAppShellComponent, EfAppShellMobileComponent, EfAppTopComponent, EfBadgeComponent, EfBlockUiComponent, EfBlockableDivComponent, EfBottomSheetComponent, EfBuildStampComponent, EfBulkBarComponent, EfButtonComponent, EfButtonGroupComponent, EfCardComponent, EfChangeHistoryComponent, EfChangePasswordComponent, EfChartComponent, EfCheckboxComponent, EfClearButtonComponent, EfColumnHeaderTemplateDirective, EfColumnTemplateDirective, EfCompactPipe, EfConfirmDialogComponent, EfCurrencyPipe, EfDataCardComponent, EfDatatableActionBarComponent, EfDatatableComponent, EfDatepickerAdvancedComponent, EfDatepickerComponent, EfDetailToolbarComponent, EfDialogComponent, EfEmailMetricsCardComponent, EfEmptyStateComponent, EfFabComponent, EfFieldsetComponent, EfFileUploadComponent, EfFilterDrawerComponent, EfFilterPillComponent, EfFormGridComponent, EfIdentityThumbComponent, EfInputNumberComponent, EfInputTextComponent, EfKpiCardComponent, EfLabelComponent, EfModuleRailComponent, EfModuleSideComponent, EfMultiSelectComponent, EfOrderBuilderComponent, EfOrderSummaryComponent, EfOverflowTooltipDirective, EfPagerComponent, EfPasswordComponent, EfPdfPreviewComponent, EfPillGroupComponent, EfPresetPillComponent, EfPriceDisplayComponent, EfProductCatalogueComponent, EfProductCatalogueFilterComponent, EfProductPickerComponent, EfProductTypeaheadComponent, EfProfileChipComponent, EfProfileMenuComponent, EfPulseComponent, EfQuantitySelectorComponent, EfQuantityStepperComponent, EfRadioComponent, EfRankListComponent, EfReadOnlyDirective, EfRowActionsComponent, EfSearchToolbarComponent, EfSelectButtonComponent, EfSelectComponent, EfSeoPreviewComponent, EfServerErrorsDirective, EfSessionIdleDialogComponent, EfShortcutsDialogComponent, EfSkeletonComponent, EfSmartBarComponent, EfStatsComponent, EfStatusChipComponent, EfTabPanelDirective, EfTabsComponent, EfTextareaComponent, EfThemeConfiguratorComponent, EfThemeToggleComponent, EfTimelineComponent, EfToastRegionComponent, EfToggleSwitchComponent, EfToolbarComponent, EfTooltipDirective, EfTotalsComponent, OrderEntityHelper, OrderLineItemHelper, TruncatePipe, buildChartConfig, getColumnAlignment, mergeColumnDefaults, resolveEfStatusColor };
6737
- export type { CatalogueProduct, CatalogueProductVariant, CategoryAssignment, CategoryGroup, CategoryItem, DatatableSearchEntity, DocumentConfig, EfAboutServer, EfBadgeColor, EfBadgeConfig, EfBadgeSize, EfBadgeVariant, EfButtonComptoirSeverity, EfButtonPrimeNGSeverity, EfButtonSeverity, EfChangeHistoryEntry, EfChangeHistoryFieldChange, EfChangePasswordSubmit, EfChartSeries, EfChartType, EfDataCardMobileLayout, EfDataCardRowAction, EfDataCardRowActionState, EfDatatableActions, EfDatatableColumn, EfDatatableColumnAlign, EfDatatableColumnType, EfDatatableConfig, EfDateFieldOutput, EfDateFieldValue, EfDatePreset, EfDialogAction, EfDialogSeverity, EfDialogSize, EfFabPosition, EfFileRejectReason, EfFileRejection, EfIdentityThumbSize, EfKpiDeltaTone, EfKpiSparkline, EfPillItem, EfPresetItem, EfProductPickerItem, EfProductPickerQuery, EfProfileMenuItem, 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 };
6903
+ 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_DATA_CARD_MOBILE_LAYOUT, EF_SEO_DEFAULT_LOCALES, EF_STATUS_COLORS, EF_STATUS_COLOR_ALIASES, EfAboutDialogComponent, EfActivationFilterComponent, EfAppMainComponent, EfAppShellComponent, EfAppShellMobileComponent, EfAppTopComponent, EfBadgeComponent, EfBlockUiComponent, EfBlockableDivComponent, EfBottomSheetComponent, EfBuildStampComponent, EfBulkBarComponent, EfButtonComponent, EfButtonGroupComponent, EfCardComponent, EfChangeHistoryComponent, EfChangePasswordComponent, EfChartComponent, EfCheckboxComponent, EfClearButtonComponent, EfColumnHeaderTemplateDirective, EfColumnTemplateDirective, EfCompactPipe, EfConfirmDialogComponent, EfCurrencyPipe, EfDataCardComponent, EfDatatableActionBarComponent, EfDatatableComponent, EfDatepickerAdvancedComponent, EfDatepickerComponent, EfDetailToolbarComponent, EfDialogComponent, EfEmailMetricsCardComponent, EfEmptyStateComponent, EfFabComponent, EfFieldsetComponent, EfFileUploadComponent, EfFilterDrawerComponent, EfFilterPillComponent, EfFormGridComponent, EfIdentityThumbComponent, EfInputNumberComponent, EfInputTextComponent, EfKpiCardComponent, EfLabelComponent, EfModuleRailComponent, EfModuleSideComponent, EfMultiSelectComponent, EfOrderBuilderComponent, EfOrderSummaryComponent, EfOverflowTooltipDirective, EfPagerComponent, EfPasswordComponent, EfPdfPreviewComponent, EfPillGroupComponent, EfPresetPillComponent, EfPriceDisplayComponent, EfProductCatalogueComponent, EfProductCatalogueFilterComponent, EfProductPickerComponent, EfProductTypeaheadComponent, EfProfileChipComponent, EfProfileMenuComponent, EfPulseComponent, EfQuantitySelectorComponent, EfQuantityStepperComponent, EfRadioComponent, EfRankListComponent, EfReadOnlyDirective, EfRowActionsComponent, EfSearchToolbarComponent, EfSelectButtonComponent, EfSelectComponent, EfSeoFieldsComponent, EfSeoPreviewComponent, EfServerErrorsDirective, EfSessionIdleDialogComponent, EfShortcutsDialogComponent, EfSkeletonComponent, EfSmartBarComponent, EfStatsComponent, EfStatusChipComponent, EfTabPanelDirective, EfTabsComponent, EfTextareaComponent, EfThemeConfiguratorComponent, EfThemeToggleComponent, EfTimelineComponent, EfToastRegionComponent, EfToggleSwitchComponent, EfToolbarComponent, EfTooltipDirective, EfTotalsComponent, OrderEntityHelper, OrderLineItemHelper, TruncatePipe, buildChartConfig, defaultUnitPrice, getColumnAlignment, mergeColumnDefaults, resolveEfStatusColor };
6904
+ export type { CatalogueProduct, CatalogueProductVariant, CategoryAssignment, CategoryGroup, CategoryItem, DatatableSearchEntity, DocumentConfig, EfAboutServer, EfBadgeColor, EfBadgeConfig, EfBadgeSize, EfBadgeVariant, EfButtonComptoirSeverity, EfButtonPrimeNGSeverity, EfButtonSeverity, EfChangeHistoryEntry, EfChangeHistoryFieldChange, EfChangePasswordSubmit, EfChartSeries, EfChartType, EfDataCardMobileLayout, EfDataCardRowAction, EfDataCardRowActionState, EfDatatableActions, EfDatatableColumn, EfDatatableColumnAlign, EfDatatableColumnType, EfDatatableConfig, EfDateFieldOutput, EfDateFieldValue, EfDatePreset, EfDialogAction, EfDialogSeverity, EfDialogSize, EfFabPosition, EfFileRejectReason, EfFileRejection, EfIdentityThumbSize, EfKpiDeltaTone, EfKpiSparkline, EfOrderPriceList, EfOrderRecipient, EfPillItem, EfPresetItem, EfProductPickerItem, EfProductPickerQuery, EfProfileMenuItem, EfRankRow, EfRowAction, EfSeoLocale, EfSeoPatch, 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 };