@elasticias/ui 1.0.51 → 1.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elasticias/ui",
3
- "version": "1.0.51",
3
+ "version": "1.0.53",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^21.0.0",
6
6
  "@angular/core": "^21.0.0",
@@ -3750,10 +3750,39 @@ input.ef-input[type='number'] {
3750
3750
  outline: 0;
3751
3751
  }
3752
3752
 
3753
- .es.p-disabled {
3754
- opacity: 0.55;
3753
+ /* Disabled reads like every other disabled comptoir field (`.ef-input[disabled]`
3754
+ above): flat --paper fill, the usual --rule border, --text-mute text, no
3755
+ fading. The root selector doubles `.p-select` / `.p-multiselect` because
3756
+ PrimeNG injects `.p-select.p-disabled { opacity: 1; background: <its grey> }`
3757
+ at runtime, after this sheet, and at a tie that later rule won, so the
3758
+ disabled select came out a heavier grey than its neighbours. */
3759
+ .es.p-select.p-disabled,
3760
+ .es.p-multiselect.p-disabled {
3761
+ opacity: 1;
3755
3762
  cursor: not-allowed;
3756
3763
  background: var(--paper);
3764
+ border-color: var(--rule);
3765
+ color: var(--text-mute);
3766
+ }
3767
+
3768
+ .es.p-select.p-disabled .p-select-label,
3769
+ .es.p-multiselect.p-disabled .p-multiselect-label {
3770
+ color: var(--text-mute);
3771
+ }
3772
+
3773
+ /* The caret stays as a quiet hint of what the field is, not an affordance. */
3774
+ .es.p-select.p-disabled .p-select-dropdown,
3775
+ .es.p-multiselect.p-disabled .p-multiselect-dropdown {
3776
+ color: var(--text-soft);
3777
+ }
3778
+
3779
+ /* Comptoir variant: the dense-row select. It replaced a native <select>,
3780
+ which had no minimum width, so it keeps none and shrinks with its cell
3781
+ or grid column instead of widening it (the 200px floor above would push
3782
+ a 390px row sideways). Height stays on --hit-field like the default. */
3783
+ .es--comptoir.p-select,
3784
+ .es--comptoir.p-multiselect {
3785
+ min-width: 0;
3757
3786
  }
3758
3787
 
3759
3788
  /* Small variant — match `.btn-sm` height */
@@ -5266,3 +5295,23 @@ input.ef-input[type='number'] {
5266
5295
  color: var(--text-mute);
5267
5296
  cursor: pointer;
5268
5297
  }
5298
+
5299
+ /* -- Touch tier for the ef-select panel --------------------------------
5300
+ The trigger already grows to --hit-touch on a coarse pointer through
5301
+ --hit-field; the rows it opens were still ~36px and the filter 32px,
5302
+ too small for a thumb now that every comptoir select opens this panel
5303
+ instead of the OS list. A virtual-scrolled list is left alone: its rows
5304
+ must match `virtualScrollItemSize`, so a caller that turns it on sets
5305
+ that to the touch height itself. Last in the file so the base rules
5306
+ above do not win. */
5307
+ @media (pointer: coarse) {
5308
+ .es__panel:not(:has(.p-virtualscroller)) .p-select-option,
5309
+ .es__panel:not(:has(.p-virtualscroller)) .p-multiselect-option {
5310
+ min-block-size: var(--hit-touch);
5311
+ }
5312
+
5313
+ .es__panel .p-select-filter,
5314
+ .es__panel .p-multiselect-filter {
5315
+ min-block-size: var(--hit-touch);
5316
+ }
5317
+ }
@@ -2729,6 +2729,7 @@ declare function resolveEfStatusColor(value: string | null | undefined): EfStatu
2729
2729
  * - `[color]` forces a specific Comptoir tone, ignoring metadata.
2730
2730
  * - `[label]` / `[labelKey]` force the text, ignoring reference data.
2731
2731
  * - `[hideDot]` removes the leading ● glyph.
2732
+ * - `metadata.icon` (or `[icon]`) swaps the ● for a PrimeIcons glyph, e.g. `pi-check`.
2732
2733
  * - `[showCode]` displays the raw code (useful for admin screens).
2733
2734
  */
2734
2735
  declare class EfStatusChipComponent {
@@ -2743,6 +2744,8 @@ declare class EfStatusChipComponent {
2743
2744
  readonly label: _angular_core.InputSignal<string>;
2744
2745
  /** Translation key — preferred when forcing a label. */
2745
2746
  readonly labelKey: _angular_core.InputSignal<string>;
2747
+ /** PrimeIcons class (e.g. `pi-check`) shown instead of the ● dot. Overrides `metadata.icon`. */
2748
+ readonly icon: _angular_core.InputSignal<string>;
2746
2749
  /** Hide the leading ● dot. */
2747
2750
  readonly hideDot: _angular_core.InputSignalWithTransform<boolean, unknown>;
2748
2751
  /** Render the raw `code` after the label (admin-screen helper). */
@@ -2753,12 +2756,14 @@ declare class EfStatusChipComponent {
2753
2756
  * generic color-name alias, e.g. `green` → `delivered`) → code
2754
2757
  * fallback → `neutral`. */
2755
2758
  readonly resolvedColor: _angular_core.Signal<EfStatusColor>;
2759
+ /** Leading icon: the `icon` input, else the entry's `metadata.icon`, else none (the ● dot shows). */
2760
+ readonly resolvedIcon: _angular_core.Signal<string>;
2756
2761
  /** Resolved label — labelKey input → label input → reference label → code. */
2757
2762
  readonly resolvedLabel: _angular_core.Signal<string>;
2758
2763
  /** Translation key returned for the template's translate pipe. */
2759
2764
  readonly resolvedLabelKey: _angular_core.Signal<string>;
2760
2765
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfStatusChipComponent, never>;
2761
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfStatusChipComponent, "ef-status-chip", never, { "referenceKey": { "alias": "referenceKey"; "required": false; "isSignal": true; }; "code": { "alias": "code"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelKey": { "alias": "labelKey"; "required": false; "isSignal": true; }; "hideDot": { "alias": "hideDot"; "required": false; "isSignal": true; }; "showCode": { "alias": "showCode"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2766
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfStatusChipComponent, "ef-status-chip", never, { "referenceKey": { "alias": "referenceKey"; "required": false; "isSignal": true; }; "code": { "alias": "code"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelKey": { "alias": "labelKey"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "hideDot": { "alias": "hideDot"; "required": false; "isSignal": true; }; "showCode": { "alias": "showCode"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2762
2767
  }
2763
2768
 
2764
2769
  /**
@@ -3900,10 +3905,14 @@ declare class EfInputTextComponent extends AbstractEfFormControl implements Cont
3900
3905
  * Elasticias API surface (i18n `*Key` inputs, `selectionChangeEvent`,
3901
3906
  * `filterByKeys`, content-projected templates).
3902
3907
  *
3903
- * The `'comptoir'` variant remains as a lite, no-deps escape hatch
3904
- * (native `<select>` styled via `.ef-select-native`); use the default
3905
- * `'primeng'` variant for any screen that needs filter / multi /
3906
- * group / templating.
3908
+ * Both variants render PrimeNG. `'comptoir'` used to be a native
3909
+ * `<select>`, which opened the operating system's own list (a blank,
3910
+ * checked first row on macOS, no search); it now gets the same `.es`
3911
+ * dropdown, sized for dense rows and appended to `body` so a scrolling
3912
+ * card or table cannot clip its panel.
3913
+ *
3914
+ * The search box turns itself on past `EF_SELECT_FILTER_THRESHOLD`
3915
+ * options unless the caller binds `[filter]` either way.
3907
3916
  *
3908
3917
  * ```html
3909
3918
  * <ef-select
@@ -3949,7 +3958,10 @@ declare class EfSelectComponent extends AbstractEfFormControl implements Control
3949
3958
  appendTo?: string;
3950
3959
  /** Multi-selection — internally swaps `<p-select>` for `<p-multiselect>`. */
3951
3960
  multiple: boolean;
3952
- filter: boolean;
3961
+ /** Show the search box in the panel. Unset (the default) turns it on
3962
+ * when there are more than `EF_SELECT_FILTER_THRESHOLD` options; bind
3963
+ * `true` or `false` to decide for the screen. */
3964
+ filter: boolean | undefined;
3953
3965
  /** Filter the list against these option fields (string or csv).
3954
3966
  * PrimeNG default: `optionLabel`. */
3955
3967
  filterBy?: string;
@@ -4004,12 +4016,13 @@ declare class EfSelectComponent extends AbstractEfFormControl implements Control
4004
4016
  * to the canonical `--hit-field` (40px, 48px on touch) trigger
4005
4017
  * height (`.es.p-select { min-height: --hit-field }`),
4006
4018
  * so it aligns with inputs/buttons in a row.
4007
- * - `'comptoir'` — lite native `<select class="ef-select-native">`.
4008
- * No filter / panel / multi / templates; use it for
4009
- * inline / dense contexts that want the plain native
4010
- * control (e.g. table-row editors).
4011
- * The `.es` dropdown is the default per the design system; opt into
4012
- * `comptoir` only when a native control is specifically wanted. See ADR-009.
4019
+ * - `'comptoir'`: the same `p-select` / `p-multiselect`, for dense
4020
+ * rows and table-row editors: no 200px minimum width,
4021
+ * so it shrinks with its cell, and the panel goes to
4022
+ * `body` unless `appendTo` says otherwise. It no
4023
+ * longer renders a native `<select>`.
4024
+ * Both share the `--hit-field` height (40px, 48px on a coarse pointer), so a
4025
+ * select lines up with comptoir inputs and buttons in a row. See ADR-009.
4013
4026
  */
4014
4027
  variant: 'primeng' | 'comptoir';
4015
4028
  get isInline(): boolean;
@@ -4033,10 +4046,47 @@ declare class EfSelectComponent extends AbstractEfFormControl implements Control
4033
4046
  filteredOptions: any[];
4034
4047
  private onChange;
4035
4048
  private onTouched;
4049
+ /** Set once the host binds `[showClear]`, so its value wins over the
4050
+ * required rule. The inherited signal input cannot tell "bound" from its
4051
+ * default, but a bound signal input does show up in `ngOnChanges`. */
4052
+ private showClearBound;
4036
4053
  /** Resolved lazily in ngOnInit to avoid circular DI with NG_VALUE_ACCESSOR */
4037
4054
  ngControl: NgControl | null;
4038
4055
  private readonly injector;
4039
4056
  ngOnInit(): void;
4057
+ /** Whether the panel shows its search box: the bound `filter`, or past
4058
+ * the threshold when the caller left it unset. */
4059
+ get effectiveFilter(): boolean;
4060
+ /**
4061
+ * Whether the clear ✕ is offered. A bound `[showClear]` decides. Otherwise
4062
+ * only an optional select gets one: on a required select the ✕ would just
4063
+ * lead the user into the "required" error, since clearing is never a valid
4064
+ * answer there.
4065
+ */
4066
+ get effectiveShowClear(): boolean;
4067
+ /**
4068
+ * Required by the `[required]` input or by the bound control: a reactive
4069
+ * `Validators.required`, or any validator (template-driven `required`,
4070
+ * a composed list) that rejects an empty value as required.
4071
+ */
4072
+ get isRequiredField(): boolean;
4073
+ /**
4074
+ * Whether the current value is one of the options, compared the way
4075
+ * PrimeNG compares (`optionValue`, else the whole option or its
4076
+ * `dataKey`). An option whose value is null or '' counts: "Aucune" with a
4077
+ * null id is a real choice and must read as a value, not as the
4078
+ * placeholder.
4079
+ */
4080
+ get hasSelectedOption(): boolean;
4081
+ /**
4082
+ * The placeholder handed to PrimeNG. Empty while an option is selected:
4083
+ * PrimeNG greys the trigger whenever its label equals the placeholder, so
4084
+ * a selected "Aucune" beside a placeholder "Aucune" rendered as unset.
4085
+ */
4086
+ get triggerPlaceholder(): string;
4087
+ /** The overlay target. A comptoir select lives in cards and table rows
4088
+ * that scroll, which would clip a panel attached in place. */
4089
+ get effectiveAppendTo(): string | undefined;
4040
4090
  /**
4041
4091
  * The text an unset select shows: the placeholder, or nothing. A blank or
4042
4092
  * dash-only placeholder (a translation of " " or "—") counts as nothing, so
@@ -4083,10 +4133,8 @@ declare class EfSelectComponent extends AbstractEfFormControl implements Control
4083
4133
  }): void;
4084
4134
  handlePanelShow(): void;
4085
4135
  handlePanelHide(): void;
4086
- /** Comptoir variant — native `<select>` change handler. The empty
4087
- * string from the placeholder option becomes `null`; otherwise we
4088
- * resolve the value through `optionValue` if provided. */
4089
- handleNativeSelectChange(rawValue: string): void;
4136
+ private optionValueOf;
4137
+ private flatOptions;
4090
4138
  private applyFilters;
4091
4139
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfSelectComponent, never>;
4092
4140
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfSelectComponent, "ef-select", never, { "options": { "alias": "options"; "required": false; }; "optionLabel": { "alias": "optionLabel"; "required": false; }; "optionValue": { "alias": "optionValue"; "required": false; }; "optionDisabled": { "alias": "optionDisabled"; "required": false; }; "dataKey": { "alias": "dataKey"; "required": false; }; "group": { "alias": "group"; "required": false; }; "optionGroupLabel": { "alias": "optionGroupLabel"; "required": false; }; "optionGroupChildren": { "alias": "optionGroupChildren"; "required": false; }; "size": { "alias": "size"; "required": false; }; "fluid": { "alias": "fluid"; "required": false; }; "inline": { "alias": "inline"; "required": false; }; "appendTo": { "alias": "appendTo"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "filter": { "alias": "filter"; "required": false; }; "filterBy": { "alias": "filterBy"; "required": false; }; "filterPlaceholder": { "alias": "filterPlaceholder"; "required": false; }; "filterPlaceholderKey": { "alias": "filterPlaceholderKey"; "required": false; }; "autofocusFilter": { "alias": "autofocusFilter"; "required": false; }; "autofocus": { "alias": "autofocus"; "required": false; }; "editable": { "alias": "editable"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "virtualScroll": { "alias": "virtualScroll"; "required": false; }; "virtualScrollItemSize": { "alias": "virtualScrollItemSize"; "required": false; }; "scrollHeight": { "alias": "scrollHeight"; "required": false; }; "multiDisplay": { "alias": "multiDisplay"; "required": false; }; "showToggleAll": { "alias": "showToggleAll"; "required": false; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; }; "emptyMessageKey": { "alias": "emptyMessageKey"; "required": false; }; "emptyFilterMessage": { "alias": "emptyFilterMessage"; "required": false; }; "emptyFilterMessageKey": { "alias": "emptyFilterMessageKey"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "panelStyleClass": { "alias": "panelStyleClass"; "required": false; }; "filterByKeys": { "alias": "filterByKeys"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, { "selectionChangeEvent": "selectionChangeEvent"; "filterChangeEvent": "filterChangeEvent"; "panelShowEvent": "panelShowEvent"; "panelHideEvent": "panelHideEvent"; }, ["itemTemplate", "selectedItemTemplate", "groupTemplate", "headerTemplate", "footerTemplate", "emptyTemplate", "emptyFilterTemplate", "filterTemplate", "loaderTemplate"], never, true, never>;