@elasticias/ui 1.0.53 → 1.0.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,18 +1,18 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { PipeTransform, OnInit, EventEmitter, TemplateRef, OnChanges, AfterContentInit, OnDestroy, SimpleChanges, InjectionToken, AfterViewInit } from '@angular/core';
2
+ import { PipeTransform, OnInit, EventEmitter, TemplateRef, OnChanges, AfterContentInit, OnDestroy, SimpleChanges, InjectionToken, DoCheck, Type, AfterViewInit } from '@angular/core';
3
3
  import * as _elasticias_screens from '@elasticias/screens';
4
4
  import { EfDataCardColumn, ScreenContext, EfDetailToolbarAction, EfSearchToolbarAction, EfDataCardSort, EfDataCardExportRequest, EfDateRange, EfDatePresetKey } from '@elasticias/screens';
5
5
  export { EfBoundedDateRange, EfDataCardColumn, EfDataCardColumnAlign, EfDataCardColumnMobileRole, EfDataCardColumnType, EfDataCardSort, EfDataCardSortDirection, EfDatePresetKey, EfDateRange, EfDetailToolbarAction, EfSearchToolbarAction } from '@elasticias/screens';
6
6
  import { Observable } from 'rxjs';
7
- import { EfPage, Permissions, EmailMetrics, EmailEventRecord, EmailEventKind } from '@elasticias/types';
7
+ import { EfPage, Permissions, LocalizedText, EmailMetrics, EmailEventRecord, EmailEventKind } from '@elasticias/types';
8
8
  import { Menu } from 'primeng/menu';
9
9
  import * as _elasticias_core from '@elasticias/core';
10
- import { EfBuildPackage, EfSessionIdleService, EfModule, EfNavSection, EfNavItem, EfModuleId, EfToast, EfToastAction, EfThemeConfigService } from '@elasticias/core';
10
+ import { EfBuildPackage, EfSessionIdleService, EfModule, EfNavSection, EfNavItem, EfModuleId, EfToast, EfToastAction, EfCulture, EfThemeConfigService } from '@elasticias/core';
11
11
  import * as i1 from 'primeng/tooltip';
12
12
  import { BlockableUI } from 'primeng/api';
13
13
  import { SafeResourceUrl, SafeHtml } from '@angular/platform-browser';
14
14
  import { ChartConfiguration } from 'chart.js';
15
- import { ControlValueAccessor, NgControl } from '@angular/forms';
15
+ import { ControlValueAccessor, NgControl, AbstractControl, ValidationErrors } from '@angular/forms';
16
16
  import { TranslateService } from '@ngx-translate/core';
17
17
  import { InputNumber, InputNumberInputEvent } from 'primeng/inputnumber';
18
18
  import { Nullable } from 'primeng/ts-helpers';
@@ -2260,6 +2260,16 @@ interface EfTabItem<T = string> {
2260
2260
  count?: number;
2261
2261
  /** Show a dirty/unread dot after the label/count. */
2262
2262
  dirty?: boolean;
2263
+ /** Translation key of a short note after the label (`'missing'`). It is
2264
+ * part of the tab's accessible name, so it says what the dot cannot. */
2265
+ noteKey?: string;
2266
+ /** `'danger'` draws the tab in the error status colour: a required panel
2267
+ * left empty, or a panel holding server errors. */
2268
+ tone?: 'danger';
2269
+ /** DOM id of the tab, for a panel's `aria-labelledby`. */
2270
+ id?: string;
2271
+ /** DOM id of the panel the consumer renders for this tab (`aria-controls`). */
2272
+ panelId?: string;
2263
2273
  disabled?: boolean;
2264
2274
  }
2265
2275
  /**
@@ -2327,6 +2337,7 @@ declare class EfTabsComponent<T = string> implements AfterContentInit {
2327
2337
  * `fr.json` / `ar.json`. */
2328
2338
  dirtyLabelKey: string;
2329
2339
  readonly valueChange: EventEmitter<T>;
2340
+ private readonly host;
2330
2341
  private tabEls?;
2331
2342
  private readonly panels;
2332
2343
  private readonly panelMap;
@@ -2340,6 +2351,7 @@ declare class EfTabsComponent<T = string> implements AfterContentInit {
2340
2351
  ngAfterContentInit(): void;
2341
2352
  select(item: EfTabItem<T>): void;
2342
2353
  onKeydown(event: KeyboardEvent, index: number): void;
2354
+ private isRtl;
2343
2355
  trackValue(_: number, item: EfTabItem<T>): T;
2344
2356
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfTabsComponent<any>, never>;
2345
2357
  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>;
@@ -3653,6 +3665,9 @@ declare class EfSeoPreviewComponent {
3653
3665
  }
3654
3666
 
3655
3667
  /**
3668
+ * Exported for `@elasticias/ui/rich-text` only, not a supported extension
3669
+ * point: it may change without a major version.
3670
+ *
3656
3671
  * Shared base for every Comptoir form control (`ef-input-text`,
3657
3672
  * `ef-textarea`, `ef-select`, `ef-input-number`, `ef-checkbox`, …).
3658
3673
  *
@@ -3833,6 +3848,10 @@ declare class EfInputTextComponent extends AbstractEfFormControl implements Cont
3833
3848
  * follow the value's first strong character. The label and messages keep
3834
3849
  * the page direction. Null or absent leaves the input unchanged. */
3835
3850
  dir: 'ltr' | 'rtl' | 'auto' | null;
3851
+ /** Language of the typed value (`'ar'` for an Arabic title on a French
3852
+ * screen), applied to the native input only: the label and hint are page
3853
+ * text and keep the page language. Null or absent renders no attribute. */
3854
+ lang: string | null;
3836
3855
  /** Clearable (showClear / canClear) is inherited from AbstractEfFormControl;
3837
3856
  * we only supply the value predicate + the reset. */
3838
3857
  protected get hasValue(): boolean;
@@ -3890,7 +3909,7 @@ declare class EfInputTextComponent extends AbstractEfFormControl implements Cont
3890
3909
  private nativeField;
3891
3910
  handleBlur(): void;
3892
3911
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfInputTextComponent, never>;
3893
- 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; }; "dir": { "alias": "dir"; "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>;
3912
+ 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; }; "dir": { "alias": "dir"; "required": false; }; "lang": { "alias": "lang"; "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>;
3894
3913
  static ngAcceptInputType_fluid: unknown;
3895
3914
  static ngAcceptInputType_inline: unknown;
3896
3915
  }
@@ -4580,6 +4599,17 @@ declare class EfMultiSelectComponent extends AbstractEfFormControl implements Co
4580
4599
  selectionLimit: any;
4581
4600
  filters: any;
4582
4601
  inline: boolean;
4602
+ /**
4603
+ * Rendering variant, as on `ef-select`.
4604
+ * - `'primeng'` (default): PrimeNG's own multiselect skin, unchanged.
4605
+ * - `'comptoir'`: the shared `.es` skin with `.es--comptoir`, the same hook
4606
+ * `ef-select variant="comptoir"` uses: a trigger on
4607
+ * `--hit-field` (`--hit-base` 40px, `--hit-touch` 48px on a
4608
+ * coarse pointer) and no minimum width, so a select and a
4609
+ * multi-select in one row align and both shrink with it.
4610
+ */
4611
+ variant: 'primeng' | 'comptoir';
4612
+ get effectiveStyleClass(): string | undefined;
4583
4613
  get isInline(): boolean;
4584
4614
  get isRequired(): boolean;
4585
4615
  selectedValues: any[];
@@ -4598,7 +4628,7 @@ declare class EfMultiSelectComponent extends AbstractEfFormControl implements Co
4598
4628
  ngOnChanges(): void;
4599
4629
  private applyFilters;
4600
4630
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfMultiSelectComponent, never>;
4601
- 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>;
4631
+ 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; }; "variant": { "alias": "variant"; "required": false; }; }, { "changeEvent": "changeEvent"; }, never, never, true, never>;
4602
4632
  static ngAcceptInputType_inline: unknown;
4603
4633
  }
4604
4634
 
@@ -6189,6 +6219,15 @@ declare class EfServerErrorsDirective {
6189
6219
  } | null>;
6190
6220
  /** Messages for a control by its `name`, or `null` when none. */
6191
6221
  errorsFor(name: string | undefined | null): string[] | null;
6222
+ /**
6223
+ * Messages for every key that starts with `prefix`, keyed by what follows
6224
+ * it: `errorsWithPrefix('title.')` turns `title.ar` into `ar`. For a control
6225
+ * that owns several backend keys, such as a text per language. Empty lists
6226
+ * are left out.
6227
+ */
6228
+ errorsWithPrefix(prefix: string): {
6229
+ [suffix: string]: string[];
6230
+ };
6192
6231
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfServerErrorsDirective, never>;
6193
6232
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<EfServerErrorsDirective, "[efServerErrors]", never, { "errors": { "alias": "efServerErrors"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
6194
6233
  }
@@ -6356,6 +6395,9 @@ declare class EfRadioComponent extends AbstractEfFormControl implements ControlV
6356
6395
  declare class EfTextareaComponent extends AbstractEfFormControl implements ControlValueAccessor {
6357
6396
  rows: number;
6358
6397
  maxlength?: number;
6398
+ /** Language of the typed value, applied to the native textarea only (the
6399
+ * label and hint keep the page language). Null or absent renders none. */
6400
+ lang: string | null;
6359
6401
  autofocus: boolean;
6360
6402
  /** Monospace face for source text (an HTML body, a JSON snippet), where
6361
6403
  * tags and indentation must stay readable. */
@@ -6398,70 +6440,299 @@ declare class EfTextareaComponent extends AbstractEfFormControl implements Contr
6398
6440
  private nativeField;
6399
6441
  handleBlur(): void;
6400
6442
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfTextareaComponent, never>;
6401
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfTextareaComponent, "ef-textarea", never, { "rows": { "alias": "rows"; "required": false; }; "maxlength": { "alias": "maxlength"; "required": false; }; "autofocus": { "alias": "autofocus"; "required": false; }; "mono": { "alias": "mono"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, { "valueChangeEvent": "valueChangeEvent"; }, never, never, true, never>;
6443
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfTextareaComponent, "ef-textarea", never, { "rows": { "alias": "rows"; "required": false; }; "maxlength": { "alias": "maxlength"; "required": false; }; "lang": { "alias": "lang"; "required": false; }; "autofocus": { "alias": "autofocus"; "required": false; }; "mono": { "alias": "mono"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, { "valueChangeEvent": "valueChangeEvent"; }, never, never, true, never>;
6402
6444
  static ngAcceptInputType_autofocus: unknown;
6403
6445
  static ngAcceptInputType_mono: unknown;
6404
6446
  }
6405
6447
 
6406
- /** A language the SEO texts are written in. */
6407
- interface EfSeoLocale {
6408
- code: string;
6409
- labelKey: string;
6410
- dir: 'auto' | 'rtl' | 'ltr';
6411
- }
6412
- /** What the fields write back: French is the scalar, every other language a dictionary entry. */
6448
+ /** A language the SEO texts are written in: the same shape as every content culture. */
6449
+ type EfSeoLocale = EfCulture;
6450
+ /**
6451
+ * What the fields write back: the whole object of the field that changed,
6452
+ * blank languages removed. Only the field that changed is present.
6453
+ */
6413
6454
  interface EfSeoPatch {
6414
- seoTitle?: string;
6415
- seoDescription?: string;
6416
- seoTitleTranslations?: Record<string, string>;
6417
- seoDescriptionTranslations?: Record<string, string>;
6455
+ seoTitle?: LocalizedText;
6456
+ seoDescription?: LocalizedText;
6418
6457
  }
6419
- type Field = 'title' | 'description';
6458
+ /**
6459
+ * The content cultures the SEO fields start from, shared with `ef-localized-input`.
6460
+ * @deprecated use `EF_DEFAULT_CONTENT_CULTURES` from `@elasticias/core`.
6461
+ */
6420
6462
  declare const EF_SEO_DEFAULT_LOCALES: ReadonlyArray<EfSeoLocale>;
6421
6463
  /**
6422
- * SEO title and description per language, each with a counter against what a
6423
- * search engine shows (60 / 160), capped at the server's limits (256 / 512),
6424
- * and the shared `ef-seo-preview` of the French result with the entity's own
6425
- * title and description as the fallback the shop uses. Card-less: each screen
6426
- * wraps it in its own `ef-card`.
6427
- *
6428
- * The French controls carry the backend names (`seoTitle`, `seoDescription`)
6429
- * so `[efServerErrors]` links their errors; the others (`seoTitleAr`, ...) are
6430
- * dictionary entries whose errors are toasted (ADR-010).
6464
+ * SEO title and description in every content language, each an
6465
+ * `ef-localized-input` with a counter against what a search engine shows
6466
+ * (60 / 160, read out to screen readers), capped at the server's limits
6467
+ * (256 / 512), and the shared `ef-seo-preview` of the default language's
6468
+ * result with the entity's own title and description as the fallback the shop
6469
+ * uses. Card-less: each screen wraps it in its own `ef-card`.
6470
+ *
6471
+ * The controls are named `seoTitle` and `seoDescription`, so under
6472
+ * `[efServerErrors]` a `seoTitle.ar` error lands on the Arabic tab and shows
6473
+ * under its field. Languages come from `EF_CONTENT_CULTURES` unless `cultures`
6474
+ * is set.
6475
+ *
6476
+ * i18n keys the app's bundles must define, besides those of
6477
+ * `ef-localized-input`:
6478
+ *
6479
+ * | key | fr | ar | en |
6480
+ * |---|---|---|---|
6481
+ * | `ef_seo_fields_title_label` | Titre SEO | عنوان SEO | SEO title |
6482
+ * | `ef_seo_fields_description_label` | Description SEO | وصف SEO | SEO description |
6483
+ * | `ef_seo_fields_counter_hint` | Au-delà de {{max}} caractères, Google coupe le texte. | بعد {{max}} حرفا، يقتطع Google النص. | Past {{max}} characters, Google cuts the text. |
6484
+ * | `ef_seo_fields_over_hint` | Le texte dépasse {{max}} caractères. | النص يتجاوز {{max}} حرفا. | The text is over {{max}} characters. |
6485
+ * | `ef_seo_fields_preview` | Aperçu dans Google | المعاينة في Google | Google preview |
6486
+ * | `ef_seo_fields_fallback_hint` | Vide : la boutique reprend le titre et la description. | فارغ: يستخدم المتجر العنوان والوصف. | Empty: the shop uses the title and description. |
6431
6487
  *
6432
6488
  * ```html
6433
- * <ef-seo-fields [seoTitle]="p.seoTitle" ... [previewUrl]="url()" (seoChange)="patch($event)" />
6489
+ * <ef-seo-fields [seoTitle]="p.seoTitle" [seoDescription]="p.seoDescription"
6490
+ * [fallbackTitle]="p.title" [fallbackDescription]="p.description"
6491
+ * [previewUrl]="url()" (seoChange)="patch($event)" />
6434
6492
  * ```
6435
6493
  */
6436
6494
  declare class EfSeoFieldsComponent {
6437
- readonly seoTitle: _angular_core.InputSignal<string | null | undefined>;
6438
- readonly seoDescription: _angular_core.InputSignal<string | null | undefined>;
6439
- readonly seoTitleTranslations: _angular_core.InputSignal<Record<string, string> | null | undefined>;
6440
- readonly seoDescriptionTranslations: _angular_core.InputSignal<Record<string, string> | null | undefined>;
6495
+ readonly seoTitle: _angular_core.InputSignal<Partial<Record<string, string>> | null | undefined>;
6496
+ readonly seoDescription: _angular_core.InputSignal<Partial<Record<string, string>> | null | undefined>;
6441
6497
  /** The entity's own texts, which the shop uses when SEO is empty. */
6442
- readonly fallbackTitle: _angular_core.InputSignal<string | null | undefined>;
6443
- readonly fallbackDescription: _angular_core.InputSignal<string | null | undefined>;
6498
+ readonly fallbackTitle: _angular_core.InputSignal<Partial<Record<string, string>> | null | undefined>;
6499
+ readonly fallbackDescription: _angular_core.InputSignal<Partial<Record<string, string>> | null | undefined>;
6444
6500
  /** The page address shown in the preview, computed by the app. */
6445
6501
  readonly previewUrl: _angular_core.InputSignal<string>;
6446
6502
  readonly titleMax: _angular_core.InputSignal<number>;
6447
6503
  readonly descriptionMax: _angular_core.InputSignal<number>;
6448
6504
  readonly titleAdvised: _angular_core.InputSignal<number>;
6449
6505
  readonly descriptionAdvised: _angular_core.InputSignal<number>;
6450
- readonly locales: _angular_core.InputSignal<readonly EfSeoLocale[]>;
6506
+ /** Overrides the `EF_CONTENT_CULTURES` list for both fields. */
6507
+ readonly cultures: _angular_core.InputSignal<readonly EfCulture[] | undefined>;
6451
6508
  readonly seoChange: _angular_core.OutputEmitterRef<EfSeoPatch>;
6452
- text(locale: string, field: Field): string;
6453
- /** Id of a counter, which the field it counts points at with `aria-describedby`. */
6454
- counterId(locale: string, field: Field): string;
6455
- private readonly uid;
6456
- /** French matches the backend property; the others are unique for the label link. */
6457
- name(locale: string, field: Field): string;
6458
- setText(locale: string, field: Field, value: string): void;
6509
+ private readonly contentCultures;
6510
+ /** The language the preview shows: the tenant's default if listed, else the first listed. */
6511
+ protected readonly previewCode: _angular_core.Signal<string>;
6459
6512
  protected readonly previewTitle: _angular_core.Signal<string>;
6460
6513
  protected readonly previewDescription: _angular_core.Signal<string>;
6514
+ private shown;
6461
6515
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfSeoFieldsComponent, never>;
6462
- 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>;
6516
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfSeoFieldsComponent, "ef-seo-fields", never, { "seoTitle": { "alias": "seoTitle"; "required": false; "isSignal": true; }; "seoDescription": { "alias": "seoDescription"; "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; }; "cultures": { "alias": "cultures"; "required": false; "isSignal": true; }; }, { "seoChange": "seoChange"; }, never, never, true, never>;
6463
6517
  }
6464
6518
 
6519
+ /**
6520
+ * One owner-written text (a title, a description, an HTML body) in every
6521
+ * content language: a pill tab per culture, the active culture's field below
6522
+ * it, and the whole object out on every edit with blank cultures removed
6523
+ * (ADR-050 section 7).
6524
+ *
6525
+ * - **Cultures** come from `EF_CONTENT_CULTURES` (the ERP provides them from
6526
+ * the tenant profile) unless `cultures` is set. The active tab is local and
6527
+ * starts on the default culture.
6528
+ * - **Tabs** carry the `ef_localized_input_missing` note on every culture with
6529
+ * no text, the error tone on the default culture of a `required` field left
6530
+ * empty once the field is touched, changed or its form submitted, and the
6531
+ * dirty dot on cultures edited since the value arrived. Dirty detection
6532
+ * relies on the parent storing the emitted object by reference (the V2
6533
+ * signal pattern): a parent that clones the value resets the dots on every
6534
+ * edit, though it never loses text.
6535
+ * - **Direction.** Each field gets its culture's `dir` and `lang`. In `html`
6536
+ * mode the source stays `ltr` for every culture (raw HTML in an `rtl`
6537
+ * textarea reads reversed) and the sanitised preview takes the culture's
6538
+ * direction.
6539
+ * - **Rich mode** (`mode="rich"`) edits each culture with `ef-rich-text`, the
6540
+ * shared editor in `@elasticias/ui/rich-text`. The app turns it on once with
6541
+ * `provideEfRichText()` (and installs `quill`); without it the field falls
6542
+ * back to the `html` source and logs why in development, as it does when
6543
+ * the editor's chunk fails to load. With `advisedLength` the counter
6544
+ * counts the text a reader sees; with only `maxLength` it counts the
6545
+ * stored HTML, which is what the server measures. Neither caps typing in
6546
+ * this mode.
6547
+ * - **Read-only cultures** are shown read-only (still focusable, so the hint
6548
+ * is read and the text can be copied) with
6549
+ * `ef_localized_input_read_only_hint` and the projected `[read-only-link]`;
6550
+ * their text still travels in the emitted object. `[efReadOnly]`, `[disabled]`
6551
+ * and a form's `disable()` disable every culture; the tabs stay usable so the
6552
+ * other languages can still be read.
6553
+ * - **Forms.** A ControlValueAccessor (`[formControl]`, `formControlName`,
6554
+ * `[(ngModel)]`) as well as `[value]` + `(valueChangeEvent)`. With
6555
+ * `required`, the form control reports `required` while the default culture
6556
+ * is empty.
6557
+ * - **Server errors** (ADR-010) come from the enclosing `[efServerErrors]`
6558
+ * scope. `<name>.<culture>` errors tint that culture's tab, show under its
6559
+ * field while it is active (the field links itself by name) and, from another
6560
+ * tab, show as a hint naming the languages in error; a new set of errors
6561
+ * moves to the first of them. `<name>` errors, or an explicit `[errors]`,
6562
+ * show under the field on every tab, as do errors for a language the field
6563
+ * does not list (`title.xx`). Messages are translated as keys. Keys: `ef_localized_input_errors_in_other`.
6564
+ * - **Spoken limit.** `counterHintKey` is read with the counter (through
6565
+ * `aria-describedby`) and `counterOverKey` is announced politely when the
6566
+ * text passes the limit; both take `{{max}}`.
6567
+ * - **Names.** Each culture's field is named `<name>.<culture>` (`title.ar`),
6568
+ * the key the backend reports a per-culture error under.
6569
+ *
6570
+ * i18n keys the app's bundles must define (the libs ship no JSON):
6571
+ *
6572
+ * | key | fr | ar | en |
6573
+ * |---|---|---|---|
6574
+ * | `ef_localized_input_culture_fr` | Français | الفرنسية | French |
6575
+ * | `ef_localized_input_culture_ar` | Arabe | العربية | Arabic |
6576
+ * | `ef_localized_input_culture_en` | Anglais | الإنجليزية | English |
6577
+ * | `ef_localized_input_missing` | manquant | غير مكتوب | missing |
6578
+ * | `ef_localized_input_cultures` | Langues du texte | لغات النص | Text languages |
6579
+ * | `ef_localized_input_errors_in_other` | Erreur dans : | خطأ في: | Error in: |
6580
+ * | `ef_localized_input_read_only_hint` | Ce texte se modifie ailleurs. | يُعدَّل هذا النص في مكان آخر. | This text is edited elsewhere. |
6581
+ *
6582
+ * ```html
6583
+ * <ef-localized-input name="title" labelKey="product_title" required
6584
+ * [value]="product().title" (valueChangeEvent)="patch({ title: $event })"
6585
+ * [advisedLength]="60" [maxLength]="256" />
6586
+ *
6587
+ * <ef-localized-input name="title" [readOnlyCultures]="['fr']" ...>
6588
+ * <a read-only-link [routerLink]="catalogLink()">{{ 'store_open_catalog' | translate }}</a>
6589
+ * </ef-localized-input>
6590
+ * ```
6591
+ */
6592
+ declare class EfLocalizedInputComponent implements ControlValueAccessor, DoCheck {
6593
+ /** The camelCase backend property (`title`); each field is `<name>.<culture>`. */
6594
+ readonly name: _angular_core.InputSignal<string>;
6595
+ readonly value: _angular_core.InputSignal<Partial<Record<string, string>> | null | undefined>;
6596
+ readonly mode: _angular_core.InputSignal<"html" | "textarea" | "text" | "rich">;
6597
+ readonly rows: _angular_core.InputSignal<number>;
6598
+ /** Hard cap, the server's limit. */
6599
+ readonly maxLength: _angular_core.InputSignal<number | undefined>;
6600
+ /** What the counter measures against (what a search engine shows, say). */
6601
+ readonly advisedLength: _angular_core.InputSignal<number | undefined>;
6602
+ /** The default culture must be filled. */
6603
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
6604
+ /** Cultures shown but not editable here, with the `[read-only-link]` slot. */
6605
+ readonly readOnlyCultures: _angular_core.InputSignal<readonly string[]>;
6606
+ /** Labels the field and names its tablist; without it the tablist is
6607
+ * named `ef_localized_input_cultures`. */
6608
+ readonly labelKey: _angular_core.InputSignal<string>;
6609
+ readonly placeholderKey: _angular_core.InputSignal<string>;
6610
+ readonly hintKey: _angular_core.InputSignal<string>;
6611
+ /** i18n key (with `{{max}}`) read out with the counter, for a limit that is advice rather than a cap. */
6612
+ readonly counterHintKey: _angular_core.InputSignal<string>;
6613
+ /** i18n key (with `{{max}}`) announced politely when the text goes past the limit. */
6614
+ readonly counterOverKey: _angular_core.InputSignal<string>;
6615
+ /** Field style in `text` mode only, named like ef-input-text's (`primeng`
6616
+ * or `comptoir`); the textarea, html and rich modes have one style.
6617
+ * `default` is the former name of `primeng`, kept for one release. */
6618
+ readonly variant: _angular_core.InputSignal<"primeng" | "comptoir" | "default">;
6619
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
6620
+ /**
6621
+ * Messages for the whole field. Without it they come from the enclosing
6622
+ * `[efServerErrors]` scope under `name`; an explicit list wins. The
6623
+ * per-language messages (`<name>.<culture>`) always come from the scope.
6624
+ */
6625
+ readonly errors: _angular_core.InputSignal<string[] | null | undefined>;
6626
+ /** Overrides the `EF_CONTENT_CULTURES` list for this field. */
6627
+ readonly cultures: _angular_core.InputSignal<readonly EfCulture[] | undefined>;
6628
+ /** The whole new object, trimmed, with blank cultures removed. */
6629
+ readonly valueChangeEvent: _angular_core.OutputEmitterRef<Partial<Record<string, string>>>;
6630
+ private readonly contentCultures;
6631
+ private readonly readOnlyScope;
6632
+ readonly ngControl: NgControl | null;
6633
+ private readonly serverErrorsScope;
6634
+ private readonly richLoader;
6635
+ private readonly richType;
6636
+ /** The editor's chunk failed to load (offline, a stale deploy). */
6637
+ private readonly richFailed;
6638
+ private readonly richHost;
6639
+ /** `rich` without a provided editor renders the html source instead. */
6640
+ protected readonly effectiveMode: _angular_core.Signal<"html" | "textarea" | "text" | "rich">;
6641
+ private readonly parentForm;
6642
+ private readonly host;
6643
+ private readonly translateService;
6644
+ /** The user typed in, or left, the field. */
6645
+ private readonly interacted;
6646
+ /** The form control is touched or dirty, or its form was submitted; read on every check. */
6647
+ private readonly formTouched;
6648
+ /** Errors wait for touch, a change or a submit, like every ef-* control. */
6649
+ private readonly showErrors;
6650
+ protected readonly uid: string;
6651
+ /** The object this component last emitted; an echo of it is not new data. */
6652
+ private lastEmitted;
6653
+ /** The text as typed, blanks and spaces kept, so an echo never rewrites a field mid-word. */
6654
+ private readonly raw;
6655
+ /** What the dirty dots compare against: the last value that came from outside. */
6656
+ private readonly baseline;
6657
+ private readonly cleaned;
6658
+ protected readonly list: _angular_core.Signal<readonly EfCulture[]>;
6659
+ protected readonly defaultCode: _angular_core.Signal<string>;
6660
+ private readonly selected;
6661
+ protected readonly active: _angular_core.Signal<EfCulture | undefined>;
6662
+ /** The active culture's code: unlike active(), equal when an equal culture list arrives. */
6663
+ private readonly activeCode;
6664
+ /** Server messages for the whole field (`title`). */
6665
+ protected readonly fieldErrors: _angular_core.Signal<string[] | null>;
6666
+ /** Every `<name>.<culture>` message the scope holds. */
6667
+ private readonly allCultureErrors;
6668
+ /** Server messages per language (`title.ar` gives `ar`), only for listed cultures. */
6669
+ private readonly cultureErrors;
6670
+ /** Messages for a language this field does not list (`title.xx`): shown with the whole field, never dropped. */
6671
+ private readonly unlistedErrors;
6672
+ /** Bumps when texts change, so translated messages follow the language. */
6673
+ private readonly textsVersion;
6674
+ /** The active language's messages, translated once here for the field below. */
6675
+ protected readonly activeErrors: _angular_core.Signal<string[] | null>;
6676
+ /** Cultures with a server error, in tab order. */
6677
+ private readonly culturesInError;
6678
+ /** Cultures in error other than the one on show, for the hint under the tabs. */
6679
+ protected readonly errorsElsewhere: _angular_core.Signal<EfCulture[]>;
6680
+ /** Changes only when the set of errors does, so a tab the user picked stays picked. */
6681
+ private readonly errorSignature;
6682
+ protected readonly tabItems: _angular_core.Signal<EfTabItem<string>[]>;
6683
+ private readonly cvaDisabled;
6684
+ /** Every culture is disabled: `[disabled]`, a form's `disable()`, or `[efReadOnly]`. */
6685
+ readonly isDisabled: _angular_core.Signal<boolean>;
6686
+ protected readonly activeReadOnly: _angular_core.Signal<boolean>;
6687
+ protected readonly activeText: _angular_core.Signal<string>;
6688
+ /**
6689
+ * What the counter counts. Rich text against `advisedLength` counts the
6690
+ * characters a reader sees; against `maxLength` alone it counts the stored
6691
+ * HTML, because that is what the server's limit measures.
6692
+ */
6693
+ protected readonly activeLength: _angular_core.Signal<number>;
6694
+ protected readonly labelId: string;
6695
+ protected readonly counterLimit: _angular_core.Signal<number | undefined>;
6696
+ protected readonly panelId: string;
6697
+ protected readonly counterId: string;
6698
+ private onChange;
6699
+ private touched;
6700
+ constructor();
6701
+ private createRich;
6702
+ protected tabId(code: string): string;
6703
+ protected controlId(code: string): string;
6704
+ protected select(code: string): void;
6705
+ protected setText(code: string, text: string): void;
6706
+ /** Touched when focus leaves the whole field, not when it moves from a tab to the text. */
6707
+ protected onFocusOut(event: FocusEvent): void;
6708
+ ngDoCheck(): void;
6709
+ /** `{ required: true }` while a required field's default culture has no text. */
6710
+ validateRequired(control: AbstractControl): ValidationErrors | null;
6711
+ writeValue(v: LocalizedText | null): void;
6712
+ registerOnChange(fn: (v: LocalizedText) => void): void;
6713
+ registerOnTouched(fn: () => void): void;
6714
+ setDisabledState(disabled: boolean): void;
6715
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfLocalizedInputComponent, never>;
6716
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfLocalizedInputComponent, "ef-localized-input", never, { "name": { "alias": "name"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "maxLength": { "alias": "maxLength"; "required": false; "isSignal": true; }; "advisedLength": { "alias": "advisedLength"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "readOnlyCultures": { "alias": "readOnlyCultures"; "required": false; "isSignal": true; }; "labelKey": { "alias": "labelKey"; "required": false; "isSignal": true; }; "placeholderKey": { "alias": "placeholderKey"; "required": false; "isSignal": true; }; "hintKey": { "alias": "hintKey"; "required": false; "isSignal": true; }; "counterHintKey": { "alias": "counterHintKey"; "required": false; "isSignal": true; }; "counterOverKey": { "alias": "counterOverKey"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "cultures": { "alias": "cultures"; "required": false; "isSignal": true; }; }, { "valueChangeEvent": "valueChangeEvent"; }, never, ["[read-only-link]"], true, never>;
6717
+ }
6718
+
6719
+ /**
6720
+ * Loads the rich text editor component that `ef-localized-input`'s `rich`
6721
+ * mode renders. The editor lives in the `@elasticias/ui/rich-text` entry
6722
+ * point so an app that never edits rich text neither bundles PrimeNG's Editor
6723
+ * nor needs `quill` installed. Provide it with `provideEfRichText()` from that
6724
+ * entry (the editor code is in the app's main bundle, Quill itself still loads
6725
+ * lazily the first time an editor renders), or with your own loader to defer
6726
+ * the editor code too:
6727
+ *
6728
+ * ```ts
6729
+ * { provide: EF_RICH_TEXT, useValue: () => import('@elasticias/ui/rich-text').then(m => m.EfRichTextComponent) }
6730
+ * ```
6731
+ */
6732
+ declare const EF_RICH_TEXT: InjectionToken<() => Promise<Type<unknown>>>;
6733
+ /** Length of the text a reader sees in an HTML fragment, tags not counted. Browser only: it parses with `document`. */
6734
+ declare function plainTextLength(html: string | null | undefined): number;
6735
+
6465
6736
  type EfFileRejectReason = 'size' | 'type';
6466
6737
  interface EfFileRejection {
6467
6738
  file: File;
@@ -7151,5 +7422,5 @@ declare class EfEmailMetricsCardComponent {
7151
7422
  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>;
7152
7423
  }
7153
7424
 
7154
- 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_HTML_PREVIEW_DEFAULT_TITLE_KEY, 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, EfHtmlPreviewComponent, 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 };
7425
+ export { AbstractEfFormControl, 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_HTML_PREVIEW_DEFAULT_TITLE_KEY, EF_RICH_TEXT, 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, EfHtmlPreviewComponent, EfIdentityThumbComponent, EfInputNumberComponent, EfInputTextComponent, EfKpiCardComponent, EfLabelComponent, EfLocalizedInputComponent, 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, plainTextLength, resolveEfStatusColor };
7155
7426
  export type { CatalogueProduct, CatalogueProductVariant, CategoryAssignment, CategoryGroup, CategoryItem, DatatableSearchEntity, DocumentConfig, EfAboutServer, EfBadgeColor, EfBadgeConfig, EfBadgeSize, EfBadgeVariant, EfButtonComptoirSeverity, EfButtonPrimeNGSeverity, EfButtonSeverity, EfChangeHistoryEntry, EfChangeHistoryFieldChange, EfChangeHistoryValueItem, 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 };