@elasticias/ui 1.0.15 → 1.0.17

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.
@@ -5,7 +5,7 @@ import * as _elasticias_core from '@elasticias/core';
5
5
  import { EfBuildPackage, EfModule, EfNavSection, EfNavItem, EfModuleId, EfToast, EfToastAction, EfThemeConfigService } from '@elasticias/core';
6
6
  import * as i1 from 'primeng/tooltip';
7
7
  import * as _elasticias_screens from '@elasticias/screens';
8
- import { ScreenContext, EfDetailToolbarAction, EfSearchToolbarAction, EfDataCardColumn, EfDataCardSort, EfDateRange, EfDatePresetKey } from '@elasticias/screens';
8
+ import { ScreenContext, EfDetailToolbarAction, EfSearchToolbarAction, EfDataCardColumn, EfDataCardSort, EfDataCardExportRequest, EfDateRange, EfDatePresetKey } from '@elasticias/screens';
9
9
  export { EfDataCardColumn, EfDataCardColumnAlign, EfDataCardColumnMobileRole, EfDataCardColumnType, EfDataCardSort, EfDataCardSortDirection, EfDatePresetKey, EfDateRange, EfDetailToolbarAction, EfSearchToolbarAction } from '@elasticias/screens';
10
10
  import { BlockableUI } from 'primeng/api';
11
11
  import { SafeResourceUrl } from '@angular/platform-browser';
@@ -1764,41 +1764,67 @@ declare class EfFabComponent {
1764
1764
  }
1765
1765
 
1766
1766
  interface EfPillItem<T = string> {
1767
+ /** Value emitted when the pill is picked. */
1767
1768
  value: T;
1768
- /** Direct label (no translation). */
1769
- label?: string;
1770
- /** Translation key takes priority over label. */
1771
- labelKey?: string;
1769
+ /**
1770
+ * Translation key for the pill's label. Required, like every other
1771
+ * `ef-*` control: the component translates, the caller never does.
1772
+ *
1773
+ * A value that is not a known key falls through to itself, which is
1774
+ * what lets a label already resolved from reference data (a seeded
1775
+ * status name, say) render correctly until that data carries keys of
1776
+ * its own.
1777
+ */
1778
+ labelKey: string;
1772
1779
  /** Optional count rendered after a thin separator. */
1773
1780
  count?: number;
1774
1781
  }
1775
1782
  /**
1776
- * Segmented pill filter. Used for tab-like selectors over a small
1777
- * set of options — "Toutes · 87 / À approuver · 14 / En retard · 3".
1783
+ * Segmented pill filter "Toutes · 87 / À approuver · 14 / En retard · 3".
1778
1784
  *
1779
1785
  * ```html
1780
1786
  * <ef-pill-group
1781
- * [items]="filters"
1782
- * [(value)]="activeFilter"
1783
- * (valueChange)="onFilterChange($event)"
1787
+ * [items]="statusBuckets()"
1788
+ * [(value)]="statusFilter"
1789
+ * ariaLabelKey="sales_orders_status_aria"
1784
1790
  * />
1785
1791
  * ```
1786
1792
  *
1787
- * The active pill picks up a contrast fill (`--ink-active`); inactive
1788
- * pills sit on transparent ground with muted text. Heights map to
1789
- * `--hit` (32px) so it stacks naturally next to compact action buttons.
1793
+ * The active pill takes a contrast fill (`--ink-active`); inactive pills
1794
+ * sit on transparent ground with muted text.
1795
+ *
1796
+ * **It scrolls rather than clipping.** Nine status filters with French
1797
+ * labels are roughly 676px wide, and the hand-rolled `.pill-group` this
1798
+ * replaces was `inline-flex` with no wrap and no scroller — so on a
1799
+ * 390px phone the last five filters could not be reached at all. The row
1800
+ * now scrolls inside itself, fades at whichever edge has more content,
1801
+ * and keeps the selected pill in view. Pills never squeeze: a pill
1802
+ * radius on a box that has wrapped to two lines is not a pill.
1790
1803
  */
1791
1804
  declare class EfPillGroupComponent<T = string> {
1792
- items: ReadonlyArray<EfPillItem<T>>;
1793
- value: T | null;
1794
- ariaLabel: string;
1805
+ readonly items: _angular_core.InputSignal<readonly EfPillItem<T>[]>;
1806
+ /** Two-way bound selection. */
1807
+ readonly value: _angular_core.ModelSignal<T>;
1808
+ /** Translation key for the group's accessible name. */
1809
+ readonly ariaLabelKey: _angular_core.InputSignal<string>;
1795
1810
  /** Hide counts even when items provide them. */
1796
- hideCounts: boolean;
1797
- readonly valueChange: EventEmitter<T>;
1798
- select(item: EfPillItem<T>): void;
1799
- trackValue(_: number, item: EfPillItem<T>): T;
1811
+ readonly hideCounts: _angular_core.InputSignalWithTransform<boolean, unknown>;
1812
+ private readonly scroller;
1813
+ /** Whether content is hidden past each edge, which drives the fades. */
1814
+ private readonly overflowStart;
1815
+ private readonly overflowEnd;
1816
+ protected readonly fadeClass: _angular_core.Signal<{
1817
+ 'has-fade-start': boolean;
1818
+ 'has-fade-end': boolean;
1819
+ }>;
1820
+ constructor();
1821
+ protected select(item: EfPillItem<T>): void;
1822
+ protected onScroll(): void;
1823
+ protected trackValue: (_: number, item: EfPillItem<T>) => T;
1824
+ private measure;
1825
+ private scrollActiveIntoView;
1800
1826
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfPillGroupComponent<any>, never>;
1801
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPillGroupComponent<any>, "ef-pill-group", never, { "items": { "alias": "items"; "required": true; }; "value": { "alias": "value"; "required": false; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; }; "hideCounts": { "alias": "hideCounts"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
1827
+ 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>;
1802
1828
  }
1803
1829
 
1804
1830
  /** Visual treatment of the tabset. `'pill'` is the default. */
@@ -3906,7 +3932,13 @@ interface EfDatatableConfig {
3906
3932
  styleClass?: string;
3907
3933
  /** Inline table styles */
3908
3934
  tableStyle?: Record<string, string>;
3909
- /** Message when no data (default: 'Aucune entree trouvee') */
3935
+ /**
3936
+ * Translation key for the no-data message. Prefer this over
3937
+ * `emptyMessage`: the old default was a hardcoded, unaccented French
3938
+ * string that rendered in every language.
3939
+ */
3940
+ emptyMessageKey?: string;
3941
+ /** @deprecated Untranslatable. Use `emptyMessageKey`. */
3910
3942
  emptyMessage?: string;
3911
3943
  /** Pagination report template */
3912
3944
  currentPageReportTemplate?: string;
@@ -4354,6 +4386,39 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
4354
4386
  readonly showDensityControl: _angular_core.InputSignalWithTransform<boolean, unknown>;
4355
4387
  /** Render the Columns picker in the head row. */
4356
4388
  readonly showColumnPicker: _angular_core.InputSignalWithTransform<boolean, unknown>;
4389
+ /**
4390
+ * Render the Export control beside Density and Columns. It sits here
4391
+ * rather than in the page toolbar because it acts on the result set,
4392
+ * the way density and the column picker do -- the toolbar is for
4393
+ * page-level actions like creating a record.
4394
+ */
4395
+ readonly showExportControl: _angular_core.InputSignalWithTransform<boolean, unknown>;
4396
+ /**
4397
+ * True while the host is assembling the file. A full export pages the
4398
+ * server and can run for seconds, so the control has to say it is
4399
+ * working rather than look idle and ignore further clicks.
4400
+ */
4401
+ readonly exporting: _angular_core.InputSignalWithTransform<boolean, unknown>;
4402
+ /**
4403
+ * Screen context used to gate Export. Falls back to
4404
+ * `rowActionsContext`, which every list screen already supplies, so
4405
+ * moving Export out of `ef-search-toolbar` does not quietly drop the
4406
+ * permission check that lived there.
4407
+ */
4408
+ readonly screenContext: _angular_core.InputSignal<ScreenContext>;
4409
+ /**
4410
+ * Mirrors `ef-search-toolbar`'s rule exactly: hidden unless asked for,
4411
+ * and with a context present it obeys `hasExportPermission`. No
4412
+ * context means no permission model is in play, so it renders.
4413
+ */
4414
+ readonly canExport: _angular_core.Signal<boolean>;
4415
+ /**
4416
+ * The active free-text query, used only to word the empty state. When
4417
+ * this is set, zero rows means "nothing matched what you typed" and the
4418
+ * user is offered a way back; when it is empty, zero rows means the
4419
+ * collection itself is empty, which is a different message.
4420
+ */
4421
+ readonly searchTerm: _angular_core.InputSignal<string>;
4357
4422
  /**
4358
4423
  * Stable key used to remember density and hidden columns for this
4359
4424
  * table. Preferences are a per-viewer convenience, so they live in
@@ -4370,6 +4435,13 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
4370
4435
  action: EfDataCardRowAction;
4371
4436
  row: TRow;
4372
4437
  }>;
4438
+ /**
4439
+ * Export the current result set. The card holds the columns but not the
4440
+ * query, so the host screen fetches the rows and writes the file.
4441
+ */
4442
+ readonly exportRequest: _angular_core.OutputEmitterRef<EfDataCardExportRequest>;
4443
+ /** Raised by the empty state's "clear search" action. */
4444
+ readonly clearSearch: _angular_core.OutputEmitterRef<void>;
4373
4445
  private readonly bodyTemplates;
4374
4446
  private readonly headerTemplates;
4375
4447
  private readonly bodyTemplateMap;
@@ -4422,6 +4494,29 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
4422
4494
  * the bulk bar and the per-row menu with no way back. */
4423
4495
  readonly hideableColumns: _angular_core.Signal<EfDataCardColumn[]>;
4424
4496
  toggleTool(tool: 'density' | 'columns'): void;
4497
+ /**
4498
+ * Hand the host screen what it needs to write the file: the columns
4499
+ * the viewer can actually see, in the order they see them, plus a
4500
+ * resolver for their values. `select` and `actions` are chrome, never
4501
+ * data, so they are dropped.
4502
+ *
4503
+ * The on-screen rows are deliberately not sent. They were, as a
4504
+ * "fallback for hosts that do not fetch", and no host ever read them
4505
+ * — a published contract carrying a field nobody consumes is a
4506
+ * promise to keep supporting it.
4507
+ */
4508
+ requestExport(): void;
4509
+ /**
4510
+ * Cell value as it belongs in a file rather than on screen.
4511
+ *
4512
+ * Numbers and dates stay raw, because a spreadsheet wants a number it
4513
+ * can total and a date it can sort. Reference and status columns do
4514
+ * not: their stored value is an id or a code, and a column of
4515
+ * `71d4431cd16141338ffcf635` tells the reader nothing. Those resolve
4516
+ * through the same lookup the table renders with, so the file says
4517
+ * what the screen said.
4518
+ */
4519
+ private exportCellValue;
4425
4520
  setDensity(value: EfTableDensity): void;
4426
4521
  isColumnHidden(id: string): boolean;
4427
4522
  toggleColumn(id: string): void;
@@ -4440,11 +4535,24 @@ declare class EfDataCardComponent<TRow = any> implements AfterContentInit {
4440
4535
  /** Fires `rowDoubleClick` unless the dblclick originated on an
4441
4536
  * interactive child (checkbox, button, link, form control). */
4442
4537
  onRowDoubleClick(row: TRow, event: MouseEvent): void;
4538
+ /**
4539
+ * `aria-sort` for the header cell: the only thing that tells a screen
4540
+ * reader which column is ordered and which way. The arrow glyph is
4541
+ * decorative and marked aria-hidden, so without this the sort state
4542
+ * was invisible to assistive technology.
4543
+ */
4544
+ ariaSort(col: EfDataCardColumn): 'ascending' | 'descending' | 'none' | null;
4545
+ /**
4546
+ * Open a row from the keyboard. Desktop opening is a double-click,
4547
+ * which no keyboard can produce, so Enter on a focused row was the
4548
+ * only missing half of the interaction.
4549
+ */
4550
+ onRowKeydown(row: TRow, event: Event): void;
4443
4551
  onHeaderClick(col: EfDataCardColumn): void;
4444
4552
  trackByRow: (_: number, row: TRow) => unknown;
4445
4553
  trackByColumn: (_: number, col: EfDataCardColumn) => string;
4446
4554
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfDataCardComponent<any>, never>;
4447
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfDataCardComponent<any>, "ef-data-card", never, { "mobileLayout": { "alias": "mobileLayout"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "trackByField": { "alias": "trackByField"; "required": false; "isSignal": true; }; "pageNumber": { "alias": "pageNumber"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "totalCount": { "alias": "totalCount"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "hidePager": { "alias": "hidePager"; "required": false; "isSignal": true; }; "sort": { "alias": "sort"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "errorMsg": { "alias": "errorMsg"; "required": false; "isSignal": true; }; "loadingKey": { "alias": "loadingKey"; "required": false; "isSignal": true; }; "rowDoubleClickable": { "alias": "rowDoubleClickable"; "required": false; "isSignal": true; }; "hasActionsColumn": { "alias": "hasActionsColumn"; "required": false; "isSignal": true; }; "rowActionsContext": { "alias": "rowActionsContext"; "required": false; "isSignal": true; }; "showViewAction": { "alias": "showViewAction"; "required": false; "isSignal": true; }; "showEditAction": { "alias": "showEditAction"; "required": false; "isSignal": true; }; "showDuplicateAction": { "alias": "showDuplicateAction"; "required": false; "isSignal": true; }; "showDeleteAction": { "alias": "showDeleteAction"; "required": false; "isSignal": true; }; "showDensityControl": { "alias": "showDensityControl"; "required": false; "isSignal": true; }; "showColumnPicker": { "alias": "showColumnPicker"; "required": false; "isSignal": true; }; "tableKey": { "alias": "tableKey"; "required": false; "isSignal": true; }; }, { "pageChange": "pageChange"; "pageSizeChange": "pageSizeChange"; "sortChange": "sortChange"; "rowDoubleClick": "rowDoubleClick"; "rowAction": "rowAction"; }, ["bodyTemplates", "headerTemplates"], ["[tbl-head-info]", "[tbl-head-actions]", "[empty-state-mobile]", "[empty-state]"], true, never>;
4555
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfDataCardComponent<any>, "ef-data-card", never, { "mobileLayout": { "alias": "mobileLayout"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "trackByField": { "alias": "trackByField"; "required": false; "isSignal": true; }; "pageNumber": { "alias": "pageNumber"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "totalCount": { "alias": "totalCount"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "hidePager": { "alias": "hidePager"; "required": false; "isSignal": true; }; "sort": { "alias": "sort"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "errorMsg": { "alias": "errorMsg"; "required": false; "isSignal": true; }; "loadingKey": { "alias": "loadingKey"; "required": false; "isSignal": true; }; "rowDoubleClickable": { "alias": "rowDoubleClickable"; "required": false; "isSignal": true; }; "hasActionsColumn": { "alias": "hasActionsColumn"; "required": false; "isSignal": true; }; "rowActionsContext": { "alias": "rowActionsContext"; "required": false; "isSignal": true; }; "showViewAction": { "alias": "showViewAction"; "required": false; "isSignal": true; }; "showEditAction": { "alias": "showEditAction"; "required": false; "isSignal": true; }; "showDuplicateAction": { "alias": "showDuplicateAction"; "required": false; "isSignal": true; }; "showDeleteAction": { "alias": "showDeleteAction"; "required": false; "isSignal": true; }; "showDensityControl": { "alias": "showDensityControl"; "required": false; "isSignal": true; }; "showColumnPicker": { "alias": "showColumnPicker"; "required": false; "isSignal": true; }; "showExportControl": { "alias": "showExportControl"; "required": false; "isSignal": true; }; "exporting": { "alias": "exporting"; "required": false; "isSignal": true; }; "screenContext": { "alias": "screenContext"; "required": false; "isSignal": true; }; "searchTerm": { "alias": "searchTerm"; "required": false; "isSignal": true; }; "tableKey": { "alias": "tableKey"; "required": false; "isSignal": true; }; }, { "pageChange": "pageChange"; "pageSizeChange": "pageSizeChange"; "sortChange": "sortChange"; "rowDoubleClick": "rowDoubleClick"; "rowAction": "rowAction"; "exportRequest": "exportRequest"; "clearSearch": "clearSearch"; }, ["bodyTemplates", "headerTemplates"], ["[tbl-head-info]", "[tbl-head-actions]", "[empty-state-mobile]", "[empty-state]"], true, never>;
4448
4556
  }
4449
4557
 
4450
4558
  /**
@@ -4755,6 +4863,7 @@ declare class EfEmptyStateComponent {
4755
4863
  */
4756
4864
  declare class EfSmartBarComponent {
4757
4865
  private readonly shortcuts;
4866
+ private readonly translate;
4758
4867
  /** Distinguishes this instance's registration from any other
4759
4868
  * ef-smart-bar on screen, the same convention ef-row-actions uses. */
4760
4869
  private static nextInstanceId;
@@ -4775,6 +4884,13 @@ declare class EfSmartBarComponent {
4775
4884
  * (a screen with two smart bars registers the binding on only one
4776
4885
  * of them). Defaults to `'mod+k'`. */
4777
4886
  readonly shortcut: _angular_core.InputSignal<string>;
4887
+ /**
4888
+ * Accessible name for the search field: the placeholder text, which
4889
+ * already says what this box searches ("Search by order N, customer,
4890
+ * product, employee"). Falls back to a generic label when a screen
4891
+ * supplies no placeholder.
4892
+ */
4893
+ protected readonly accessibleLabel: _angular_core.Signal<any>;
4778
4894
  protected readonly kbdLabel: _angular_core.Signal<string>;
4779
4895
  readonly search: _angular_core.OutputEmitterRef<string>;
4780
4896
  readonly clear: _angular_core.OutputEmitterRef<void>;