@besaitech/ng-design-system 0.0.53 → 0.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,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, input, computed, ChangeDetectionStrategy, Component, booleanAttribute, isDevMode, effect, numberAttribute, output, signal, forwardRef, viewChild, viewChildren, afterRenderEffect, model, ElementRef, Directive, Injector, contentChild, untracked, afterNextRender, TemplateRef, linkedSignal, Injectable, contentChildren, DestroyRef } from '@angular/core';
2
+ import { inject, input, computed, ChangeDetectionStrategy, Component, booleanAttribute, isDevMode, effect, numberAttribute, output, signal, forwardRef, viewChild, viewChildren, afterRenderEffect, model, ElementRef, Directive, Injector, contentChild, untracked, afterNextRender, TemplateRef, linkedSignal, DestroyRef, Injectable, contentChildren } from '@angular/core';
3
3
  import { DomSanitizer } from '@angular/platform-browser';
4
4
  import * as i1 from '@angular/forms';
5
5
  import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormsModule } from '@angular/forms';
@@ -380,11 +380,10 @@ class SdsInput {
380
380
  /** Hard character cap on the native field; 0 means no limit. */
381
381
  maxLength = input(0, ...(ngDevMode ? [{ debugName: "maxLength", transform: numberAttribute }] : [{ transform: numberAttribute }]));
382
382
  /**
383
- * Accessible name for the clear button. French default so existing consumers are unchanged, but an
384
- * app serving more than one language MUST translate it — it is an icon-only control, so this string
385
- * is its only name.
383
+ * Accessible name for the clear button. English default; an app serving more than one language MUST
384
+ * translate it — it is an icon-only control, so this string is its only name.
386
385
  */
387
- clearLabel = input('Effacer', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
386
+ clearLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
388
387
  leadingIcon = input(null, ...(ngDevMode ? [{ debugName: "leadingIcon" }] : []));
389
388
  trailingIcon = input(null, ...(ngDevMode ? [{ debugName: "trailingIcon" }] : []));
390
389
  /**
@@ -697,6 +696,11 @@ const TEXT = {
697
696
  * The field formats **live as you type**: the currency symbol, grouping separators and prefix/suffix
698
697
  * stay visible on every keystroke, and the caret is kept where it belongs. The value is clamped to
699
698
  * {@link min}/{@link max} on blur and on every spinner step; ArrowUp / ArrowDown also step it.
699
+ *
700
+ * In a locale whose decimal separator is a comma (fr-BE, nl-BE, de-DE…) a typed "." — the key most
701
+ * keyboards and numpads offer — is taken as the decimal separator: "12.50" becomes "12,50". Pasted
702
+ * text works the same way, except that a "." followed by exactly three digits in a locale that groups
703
+ * with "." ("1.234" in nl-BE) stays a thousands separator.
700
704
  */
701
705
  class SdsInputNumber {
702
706
  inputId = `sds-input-number-${nextId$k++}`;
@@ -707,6 +711,13 @@ class SdsInputNumber {
707
711
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
708
712
  hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
709
713
  error = input('', ...(ngDevMode ? [{ debugName: "error" }] : []));
714
+ /**
715
+ * Mark the field invalid (danger frame + `aria-invalid`) without showing an [error] message — for a
716
+ * host that renders the message itself, e.g. an editable table cell.
717
+ */
718
+ invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
719
+ /** Extra id(s) for the field's `aria-describedby`, added to its own hint/error message id. */
720
+ ariaDescribedby = input('', ...(ngDevMode ? [{ debugName: "ariaDescribedby" }] : []));
710
721
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
711
722
  /** `filled` is a borderless field on a muted ground; `default` is the bordered white field. */
712
723
  appearance = input('default', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
@@ -743,22 +754,25 @@ class SdsInputNumber {
743
754
  allowEmpty = input(true, ...(ngDevMode ? [{ debugName: "allowEmpty", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
744
755
  clearable = input(false, ...(ngDevMode ? [{ debugName: "clearable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
745
756
  /**
746
- * Accessible names for the icon-only controls. French defaults so existing consumers are unchanged;
747
- * translate them in a multi-language app.
757
+ * Accessible names for the icon-only controls. English defaults; translate them in a
758
+ * multi-language app.
748
759
  */
749
- clearLabel = input('Effacer', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
750
- incrementLabel = input('Augmenter', ...(ngDevMode ? [{ debugName: "incrementLabel" }] : []));
751
- decrementLabel = input('Diminuer', ...(ngDevMode ? [{ debugName: "decrementLabel" }] : []));
760
+ clearLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
761
+ incrementLabel = input('Increase', ...(ngDevMode ? [{ debugName: "incrementLabel" }] : []));
762
+ decrementLabel = input('Decrease', ...(ngDevMode ? [{ debugName: "decrementLabel" }] : []));
752
763
  /** The committed numeric value (driven by CVA + user input). */
753
764
  value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
754
765
  cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : []));
755
766
  isDisabled = computed(() => this.disabled() || this.cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
756
767
  describedBy = computed(() => {
768
+ const ids = [];
757
769
  if (this.error())
758
- return `${this.inputId}-err`;
759
- if (this.hint())
760
- return `${this.inputId}-hint`;
761
- return null;
770
+ ids.push(`${this.inputId}-err`);
771
+ else if (this.hint())
772
+ ids.push(`${this.inputId}-hint`);
773
+ if (this.ariaDescribedby())
774
+ ids.push(this.ariaDescribedby());
775
+ return ids.length ? ids.join(' ') : null;
762
776
  }, ...(ngDevMode ? [{ debugName: "describedBy" }] : []));
763
777
  clearVisible = computed(() => this.clearable() && this.value() !== null && !this.isDisabled() && !this.readonly(), ...(ngDevMode ? [{ debugName: "clearVisible" }] : []));
764
778
  incrementIconName = computed(() => this.incrementIcon() ?? (this.buttonLayout() === 'stacked' ? 'chevron-up' : 'plus'), ...(ngDevMode ? [{ debugName: "incrementIconName" }] : []));
@@ -829,13 +843,13 @@ class SdsInputNumber {
829
843
  parts.push('opacity-60 cursor-not-allowed');
830
844
  if (this.appearance() === 'filled') {
831
845
  parts.push('border-transparent bg-muted text-ink');
832
- parts.push(this.error()
846
+ parts.push(this.error() || this.invalid()
833
847
  ? 'border-danger focus-within:ring-2 focus-within:ring-danger/30'
834
848
  : 'focus-within:ring-2 focus-within:ring-brand-500/25');
835
849
  }
836
850
  else {
837
851
  parts.push('bg-surface text-ink');
838
- parts.push(this.error()
852
+ parts.push(this.error() || this.invalid()
839
853
  ? 'border-danger focus-within:border-danger focus-within:ring-2 focus-within:ring-danger/25'
840
854
  : 'border-border focus-within:border-brand-500 focus-within:ring-2 focus-within:ring-brand-500/25');
841
855
  }
@@ -964,6 +978,38 @@ class SdsInputNumber {
964
978
  const n = Number(s);
965
979
  return Number.isFinite(n) ? n : null;
966
980
  }
981
+ /**
982
+ * In a locale whose decimal separator is not "." (fr-BE, nl-BE, de-DE…), turn the "." people type
983
+ * for a decimal point into the locale separator before parsing, so "12.50" reads as 12.5.
984
+ * - `typed` is the text of the keystroke: a "." just typed sits right before the caret and is
985
+ * always the decimal point (even in a locale that groups with ".", whose group marks come from
986
+ * the formatter, never from the keyboard).
987
+ * - Otherwise (paste, autofill, programmatic input) and only when the text holds no locale decimal
988
+ * separator, the last "." is the decimal point — unless the locale groups with "." and exactly
989
+ * three digits follow it ("1.234" in nl-BE is one thousand two hundred thirty-four).
990
+ */
991
+ localizeDecimalPoint(raw, caret, typed) {
992
+ const { group, decimal } = this.separators();
993
+ if (decimal === '.' || !raw.includes('.') || this.maxFrac() === 0)
994
+ return raw;
995
+ if (typed === '.' && raw[caret - 1] === '.') {
996
+ return raw.slice(0, caret - 1) + decimal + raw.slice(caret);
997
+ }
998
+ // A keystroke without a "." leaves the formatter's own "." group marks alone.
999
+ if ((typed !== null && !typed.includes('.')) || raw.includes(decimal))
1000
+ return raw;
1001
+ // Only a "." inside the number counts, not one in a prefix/suffix (" sq.ft").
1002
+ const prefix = this.prefix();
1003
+ const suffix = this.suffix();
1004
+ const start = prefix && raw.startsWith(prefix) ? prefix.length : 0;
1005
+ const end = suffix && raw.endsWith(suffix) ? raw.length - suffix.length : raw.length;
1006
+ const last = raw.lastIndexOf('.', end - 1);
1007
+ if (last < start)
1008
+ return raw;
1009
+ if (group === '.' && /^\d{3}(?!\d)/.test(raw.slice(last + 1, end)))
1010
+ return raw;
1011
+ return raw.slice(0, last) + decimal + raw.slice(last + 1);
1012
+ }
967
1013
  /** Pull the sign / integer / fraction fragments out of a formatted, partially-typed string. */
968
1014
  parseInput(raw) {
969
1015
  const { group, decimal } = this.separators();
@@ -1032,8 +1078,12 @@ class SdsInputNumber {
1032
1078
  // --- Interaction ----------------------------------------------------------
1033
1079
  onInput(event) {
1034
1080
  const el = event.target;
1035
- const raw = el.value;
1036
- const caret = el.selectionStart ?? raw.length;
1081
+ const caret = el.selectionStart ?? el.value.length;
1082
+ // `data` is the keystroke's text; null/undefined for a paste, deletion or a synthetic event.
1083
+ const data = event.data;
1084
+ const kind = event.inputType;
1085
+ const typed = data != null && (kind === 'insertText' || kind === 'insertCompositionText') ? data : null;
1086
+ const raw = this.localizeDecimalPoint(el.value, caret, typed);
1037
1087
  const target = this.significantBefore(raw, caret);
1038
1088
  const parsed = this.parseInput(raw);
1039
1089
  if (parsed.intDigits === '' && parsed.fracDigits === '' && !parsed.hadDecimal) {
@@ -1116,7 +1166,7 @@ class SdsInputNumber {
1116
1166
  this.cvaDisabled.set(isDisabled);
1117
1167
  }
1118
1168
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsInputNumber, deps: [], target: i0.ɵɵFactoryTarget.Component });
1119
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsInputNumber, isStandalone: true, selector: "sds-input-number", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null }, currencyDisplay: { classPropertyName: "currencyDisplay", publicName: "currencyDisplay", isSignal: true, isRequired: false, transformFunction: null }, useGrouping: { classPropertyName: "useGrouping", publicName: "useGrouping", isSignal: true, isRequired: false, transformFunction: null }, minFractionDigits: { classPropertyName: "minFractionDigits", publicName: "minFractionDigits", isSignal: true, isRequired: false, transformFunction: null }, maxFractionDigits: { classPropertyName: "maxFractionDigits", publicName: "maxFractionDigits", isSignal: true, isRequired: false, transformFunction: null }, prefix: { classPropertyName: "prefix", publicName: "prefix", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, showButtons: { classPropertyName: "showButtons", publicName: "showButtons", isSignal: true, isRequired: false, transformFunction: null }, buttonLayout: { classPropertyName: "buttonLayout", publicName: "buttonLayout", isSignal: true, isRequired: false, transformFunction: null }, incrementIcon: { classPropertyName: "incrementIcon", publicName: "incrementIcon", isSignal: true, isRequired: false, transformFunction: null }, decrementIcon: { classPropertyName: "decrementIcon", publicName: "decrementIcon", isSignal: true, isRequired: false, transformFunction: null }, allowEmpty: { classPropertyName: "allowEmpty", publicName: "allowEmpty", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, incrementLabel: { classPropertyName: "incrementLabel", publicName: "incrementLabel", isSignal: true, isRequired: false, transformFunction: null }, decrementLabel: { classPropertyName: "decrementLabel", publicName: "decrementLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
1169
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsInputNumber, isStandalone: true, selector: "sds-input-number", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedby: { classPropertyName: "ariaDescribedby", publicName: "ariaDescribedby", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null }, currencyDisplay: { classPropertyName: "currencyDisplay", publicName: "currencyDisplay", isSignal: true, isRequired: false, transformFunction: null }, useGrouping: { classPropertyName: "useGrouping", publicName: "useGrouping", isSignal: true, isRequired: false, transformFunction: null }, minFractionDigits: { classPropertyName: "minFractionDigits", publicName: "minFractionDigits", isSignal: true, isRequired: false, transformFunction: null }, maxFractionDigits: { classPropertyName: "maxFractionDigits", publicName: "maxFractionDigits", isSignal: true, isRequired: false, transformFunction: null }, prefix: { classPropertyName: "prefix", publicName: "prefix", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, showButtons: { classPropertyName: "showButtons", publicName: "showButtons", isSignal: true, isRequired: false, transformFunction: null }, buttonLayout: { classPropertyName: "buttonLayout", publicName: "buttonLayout", isSignal: true, isRequired: false, transformFunction: null }, incrementIcon: { classPropertyName: "incrementIcon", publicName: "incrementIcon", isSignal: true, isRequired: false, transformFunction: null }, decrementIcon: { classPropertyName: "decrementIcon", publicName: "decrementIcon", isSignal: true, isRequired: false, transformFunction: null }, allowEmpty: { classPropertyName: "allowEmpty", publicName: "allowEmpty", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, incrementLabel: { classPropertyName: "incrementLabel", publicName: "incrementLabel", isSignal: true, isRequired: false, transformFunction: null }, decrementLabel: { classPropertyName: "decrementLabel", publicName: "decrementLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
1120
1170
  {
1121
1171
  provide: NG_VALUE_ACCESSOR,
1122
1172
  useExisting: forwardRef(() => SdsInputNumber),
@@ -1169,7 +1219,7 @@ class SdsInputNumber {
1169
1219
  [disabled]="isDisabled()"
1170
1220
  [readOnly]="readonly()"
1171
1221
  [attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
1172
- [attr.aria-invalid]="error() ? 'true' : null"
1222
+ [attr.aria-invalid]="error() || invalid() ? 'true' : null"
1173
1223
  [attr.aria-describedby]="describedBy()"
1174
1224
  [attr.aria-valuenow]="value()"
1175
1225
  [attr.aria-valuemin]="min()"
@@ -1324,7 +1374,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
1324
1374
  [disabled]="isDisabled()"
1325
1375
  [readOnly]="readonly()"
1326
1376
  [attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
1327
- [attr.aria-invalid]="error() ? 'true' : null"
1377
+ [attr.aria-invalid]="error() || invalid() ? 'true' : null"
1328
1378
  [attr.aria-describedby]="describedBy()"
1329
1379
  [attr.aria-valuenow]="value()"
1330
1380
  [attr.aria-valuemin]="min()"
@@ -1418,7 +1468,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
1418
1468
  }
1419
1469
  `,
1420
1470
  }]
1421
- }], ctorParameters: () => [], propDecorators: { fieldRef: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], currency: [{ type: i0.Input, args: [{ isSignal: true, alias: "currency", required: false }] }], currencyDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencyDisplay", required: false }] }], useGrouping: [{ type: i0.Input, args: [{ isSignal: true, alias: "useGrouping", required: false }] }], minFractionDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "minFractionDigits", required: false }] }], maxFractionDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFractionDigits", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], showButtons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showButtons", required: false }] }], buttonLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonLayout", required: false }] }], incrementIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "incrementIcon", required: false }] }], decrementIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "decrementIcon", required: false }] }], allowEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowEmpty", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], incrementLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "incrementLabel", required: false }] }], decrementLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "decrementLabel", required: false }] }] } });
1471
+ }], ctorParameters: () => [], propDecorators: { fieldRef: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], ariaDescribedby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedby", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], currency: [{ type: i0.Input, args: [{ isSignal: true, alias: "currency", required: false }] }], currencyDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencyDisplay", required: false }] }], useGrouping: [{ type: i0.Input, args: [{ isSignal: true, alias: "useGrouping", required: false }] }], minFractionDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "minFractionDigits", required: false }] }], maxFractionDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFractionDigits", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], showButtons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showButtons", required: false }] }], buttonLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonLayout", required: false }] }], incrementIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "incrementIcon", required: false }] }], decrementIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "decrementIcon", required: false }] }], allowEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowEmpty", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], incrementLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "incrementLabel", required: false }] }], decrementLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "decrementLabel", required: false }] }] } });
1422
1472
 
1423
1473
  let nextId$j = 0;
1424
1474
  const SIZES$9 = {
@@ -1454,11 +1504,11 @@ class SdsLocalizedInput {
1454
1504
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
1455
1505
  /**
1456
1506
  * Accessible name for the in-field language switcher, and the "no translation yet" title suffix on each
1457
- * language button. French defaults so existing consumers are unchanged; translate them in a multi-language
1458
- * app (the buttons are letter-only, so the title carries their meaning).
1507
+ * language button. English defaults; translate them in a multi-language app (the buttons are
1508
+ * letter-only, so the title carries their meaning).
1459
1509
  */
1460
- languageSwitcherLabel = input('Langue', ...(ngDevMode ? [{ debugName: "languageSwitcherLabel" }] : []));
1461
- untranslatedLabel = input('à traduire', ...(ngDevMode ? [{ debugName: "untranslatedLabel" }] : []));
1510
+ languageSwitcherLabel = input('Language', ...(ngDevMode ? [{ debugName: "languageSwitcherLabel" }] : []));
1511
+ untranslatedLabel = input('not translated yet', ...(ngDevMode ? [{ debugName: "untranslatedLabel" }] : []));
1462
1512
  valueMap = signal({}, ...(ngDevMode ? [{ debugName: "valueMap" }] : []));
1463
1513
  /** Language chosen via the switcher; null means "follow currentLanguage / the first language". */
1464
1514
  manual = signal(null, ...(ngDevMode ? [{ debugName: "manual" }] : []));
@@ -1729,10 +1779,10 @@ class SdsOtpInput {
1729
1779
  autoFocus = input(false, ...(ngDevMode ? [{ debugName: "autoFocus", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
1730
1780
  /**
1731
1781
  * Accessible name for an individual box, suffixed with its 1-based position ("Digit 1", "Digit
1732
- * 2", …). French default so existing consumers are unchanged; translate it in an app serving more
1733
- * than one language, since each box is an icon-less control whose only name this is.
1782
+ * 2", …). English default; translate it in an app serving more than one language, since each box
1783
+ * is an icon-less control whose only name this is.
1734
1784
  */
1735
- cellLabel = input('Chiffre', ...(ngDevMode ? [{ debugName: "cellLabel" }] : []));
1785
+ cellLabel = input('Digit', ...(ngDevMode ? [{ debugName: "cellLabel" }] : []));
1736
1786
  /** Emitted with the full value the moment the last box is filled. */
1737
1787
  completed = output();
1738
1788
  cells = viewChildren('cell', ...(ngDevMode ? [{ debugName: "cells" }] : []));
@@ -2050,6 +2100,13 @@ class SdsTextarea {
2050
2100
  maxLength = input(0, ...(ngDevMode ? [{ debugName: "maxLength", transform: numberAttribute }] : [{ transform: numberAttribute }]));
2051
2101
  /** Show a character counter row. */
2052
2102
  showCount = input(false, ...(ngDevMode ? [{ debugName: "showCount", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
2103
+ /**
2104
+ * Spoken text of the counter when {@link maxLength} is set; tokens `{count}` and `{max}`. English
2105
+ * default — translate it in a multi-language app.
2106
+ */
2107
+ countLimitLabel = input('{count} of {max} characters used', ...(ngDevMode ? [{ debugName: "countLimitLabel" }] : []));
2108
+ /** Spoken text of the counter without a {@link maxLength}; token `{count}`. */
2109
+ countLabelTemplate = input('{count} characters', ...(ngDevMode ? [{ debugName: "countLabelTemplate" }] : []));
2053
2110
  resize = input('vertical', ...(ngDevMode ? [{ debugName: "resize" }] : []));
2054
2111
  /** Current value (driven by CVA + user input). */
2055
2112
  value = signal('', ...(ngDevMode ? [{ debugName: "value" }] : []));
@@ -2058,9 +2115,9 @@ class SdsTextarea {
2058
2115
  count = computed(() => this.value().length, ...(ngDevMode ? [{ debugName: "count" }] : []));
2059
2116
  hasCounter = computed(() => this.showCount() || this.maxLength() > 0, ...(ngDevMode ? [{ debugName: "hasCounter" }] : []));
2060
2117
  /** Spoken description of the counter for assistive tech. */
2061
- countLabel = computed(() => this.maxLength()
2062
- ? `${this.count()} sur ${this.maxLength()} caractères utilisés`
2063
- : `${this.count()} caractère(s)`, ...(ngDevMode ? [{ debugName: "countLabel" }] : []));
2118
+ countLabel = computed(() => (this.maxLength() ? this.countLimitLabel() : this.countLabelTemplate())
2119
+ .replace('{count}', String(this.count()))
2120
+ .replace('{max}', String(this.maxLength())), ...(ngDevMode ? [{ debugName: "countLabel" }] : []));
2064
2121
  describedBy = computed(() => {
2065
2122
  const ids = [];
2066
2123
  if (this.error())
@@ -2137,7 +2194,7 @@ class SdsTextarea {
2137
2194
  el.style.height = `${el.scrollHeight}px`;
2138
2195
  }
2139
2196
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
2140
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsTextarea, isStandalone: true, selector: "sds-textarea", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, autoResize: { classPropertyName: "autoResize", publicName: "autoResize", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, showCount: { classPropertyName: "showCount", publicName: "showCount", isSignal: true, isRequired: false, transformFunction: null }, resize: { classPropertyName: "resize", publicName: "resize", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
2197
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsTextarea, isStandalone: true, selector: "sds-textarea", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, autoResize: { classPropertyName: "autoResize", publicName: "autoResize", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, showCount: { classPropertyName: "showCount", publicName: "showCount", isSignal: true, isRequired: false, transformFunction: null }, countLimitLabel: { classPropertyName: "countLimitLabel", publicName: "countLimitLabel", isSignal: true, isRequired: false, transformFunction: null }, countLabelTemplate: { classPropertyName: "countLabelTemplate", publicName: "countLabelTemplate", isSignal: true, isRequired: false, transformFunction: null }, resize: { classPropertyName: "resize", publicName: "resize", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
2141
2198
  {
2142
2199
  provide: NG_VALUE_ACCESSOR,
2143
2200
  useExisting: forwardRef(() => SdsTextarea),
@@ -2276,7 +2333,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2276
2333
  }
2277
2334
  `,
2278
2335
  }]
2279
- }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], autoResize: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoResize", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], showCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCount", required: false }] }], resize: [{ type: i0.Input, args: [{ isSignal: true, alias: "resize", required: false }] }] } });
2336
+ }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], autoResize: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoResize", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], showCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCount", required: false }] }], countLimitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "countLimitLabel", required: false }] }], countLabelTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "countLabelTemplate", required: false }] }], resize: [{ type: i0.Input, args: [{ isSignal: true, alias: "resize", required: false }] }] } });
2280
2337
 
2281
2338
  let nextId$g = 0;
2282
2339
  const SIZES$6 = {
@@ -2543,8 +2600,11 @@ let nextId$f = 0;
2543
2600
  * of its own, so it can sit inside the consumer's `<label>` (a whole clickable
2544
2601
  * row), whose text then names it.
2545
2602
  *
2603
+ * Set [indeterminate] for a "some but not all" state (e.g. a select-all box over a partial
2604
+ * selection): the box shows a bar and reads as "mixed"; a click checks it.
2605
+ *
2546
2606
  * @example
2547
- * <sds-checkbox label="Fusion automatique" [(ngModel)]="autoMerge" />
2607
+ * <sds-checkbox label="Auto-merge" [(ngModel)]="autoMerge" />
2548
2608
  */
2549
2609
  class SdsCheckbox {
2550
2610
  id = `sds-checkbox-${nextId$f++}`;
@@ -2553,14 +2613,20 @@ class SdsCheckbox {
2553
2613
  ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
2554
2614
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
2555
2615
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
2616
+ /**
2617
+ * "Some but not all": shows a bar and is announced as mixed while the value is false. Clicking
2618
+ * checks it (the native behaviour); the host then decides the next [indeterminate].
2619
+ */
2620
+ indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
2556
2621
  checked = signal(false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
2622
+ mixed = computed(() => this.indeterminate() && !this.checked(), ...(ngDevMode ? [{ debugName: "mixed" }] : []));
2557
2623
  cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : []));
2558
2624
  isDisabled = computed(() => this.disabled() || this.cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
2559
2625
  iconSize = computed(() => (this.size() === 'sm' ? 11 : 13), ...(ngDevMode ? [{ debugName: "iconSize" }] : []));
2560
2626
  stateClasses = computed(() => this.isDisabled() ? 'cursor-not-allowed opacity-60' : 'cursor-pointer', ...(ngDevMode ? [{ debugName: "stateClasses" }] : []));
2561
2627
  boxClasses = computed(() => {
2562
2628
  const size = this.size() === 'sm' ? 'h-4 w-4' : 'h-5 w-5';
2563
- const state = this.checked()
2629
+ const state = this.checked() || this.mixed()
2564
2630
  ? 'border-brand-600 bg-brand-600 text-white'
2565
2631
  : 'border-border bg-surface text-transparent';
2566
2632
  const focus = 'focus-within:ring-2 focus-within:ring-brand-500/30 focus-within:border-brand-500';
@@ -2587,7 +2653,7 @@ class SdsCheckbox {
2587
2653
  this.onChange(next);
2588
2654
  }
2589
2655
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
2590
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsCheckbox, isStandalone: true, selector: "sds-checkbox", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "inline-flex" }, providers: [
2656
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsCheckbox, isStandalone: true, selector: "sds-checkbox", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "inline-flex align-middle" }, providers: [
2591
2657
  {
2592
2658
  provide: NG_VALUE_ACCESSOR,
2593
2659
  useExisting: forwardRef(() => SdsCheckbox),
@@ -2617,6 +2683,7 @@ class SdsCheckbox {
2617
2683
  class="absolute inset-0 m-0 cursor-[inherit] opacity-0"
2618
2684
  [id]="id"
2619
2685
  [checked]="checked()"
2686
+ [indeterminate]="mixed()"
2620
2687
  [disabled]="isDisabled()"
2621
2688
  [attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
2622
2689
  (change)="onInput($event)"
@@ -2624,6 +2691,8 @@ class SdsCheckbox {
2624
2691
  />
2625
2692
  @if (checked()) {
2626
2693
  <sds-icon name="check" [size]="iconSize()" [strokeWidth]="3" />
2694
+ } @else if (mixed()) {
2695
+ <span class="h-0.5 w-2.5 rounded-full bg-current" aria-hidden="true"></span>
2627
2696
  }
2628
2697
  </span>
2629
2698
  </ng-template>
@@ -2642,7 +2711,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2642
2711
  multi: true,
2643
2712
  },
2644
2713
  ],
2645
- host: { class: 'inline-flex' },
2714
+ // align-middle: in an inline context (a table cell) an empty box and a checked one would otherwise
2715
+ // sit on different baselines, and the row would jump by a few pixels on every toggle.
2716
+ host: { class: 'inline-flex align-middle' },
2646
2717
  template: `
2647
2718
  <!-- With a visible label the whole thing is a <label>. Without one it is a plain span, so the box can
2648
2719
  sit inside the consumer's own <label> (a clickable row, say) without nesting labels. -->
@@ -2667,6 +2738,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2667
2738
  class="absolute inset-0 m-0 cursor-[inherit] opacity-0"
2668
2739
  [id]="id"
2669
2740
  [checked]="checked()"
2741
+ [indeterminate]="mixed()"
2670
2742
  [disabled]="isDisabled()"
2671
2743
  [attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
2672
2744
  (change)="onInput($event)"
@@ -2674,12 +2746,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2674
2746
  />
2675
2747
  @if (checked()) {
2676
2748
  <sds-icon name="check" [size]="iconSize()" [strokeWidth]="3" />
2749
+ } @else if (mixed()) {
2750
+ <span class="h-0.5 w-2.5 rounded-full bg-current" aria-hidden="true"></span>
2677
2751
  }
2678
2752
  </span>
2679
2753
  </ng-template>
2680
2754
  `,
2681
2755
  }]
2682
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
2756
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }] } });
2683
2757
 
2684
2758
  let nextId$e = 0;
2685
2759
  /**
@@ -4053,6 +4127,9 @@ const STATES = {
4053
4127
  * for multi-select ("select all matches"): it then carries `aria-pressed` and a corner check. [busy]
4054
4128
  * shows a spinner and sets `aria-busy` while a save is in flight.
4055
4129
  *
4130
+ * A photo that fails to load (404, blocked, not an image) falls back to the no-photo layout — never
4131
+ * a broken-image icon — and `(imageError)` reports the URL. A new [image] URL is tried again.
4132
+ *
4056
4133
  * @example
4057
4134
  * <sds-status-tile title="Bacon" subtitle="Extras" state="sold-out" note="Back at 22:00"
4058
4135
  * soldOutLabel="Sold out" (activate)="toggle(item)" />
@@ -4077,6 +4154,21 @@ class SdsStatusTile {
4077
4154
  hiddenLabel = input('Hidden', ...(ngDevMode ? [{ debugName: "hiddenLabel" }] : []));
4078
4155
  /** The tile was pressed (click, tap, Enter or Space). */
4079
4156
  activate = output();
4157
+ /** The [image] URL failed to load; the tile has fallen back to its no-photo layout. */
4158
+ imageError = output();
4159
+ /** The URL that last failed to load — hidden until [image] changes to another URL. */
4160
+ failedImage = signal(null, ...(ngDevMode ? [{ debugName: "failedImage" }] : []));
4161
+ showImage = computed(() => {
4162
+ const src = this.image();
4163
+ return !!src && src !== this.failedImage();
4164
+ }, ...(ngDevMode ? [{ debugName: "showImage" }] : []));
4165
+ onImageError() {
4166
+ const src = this.image();
4167
+ if (!src)
4168
+ return;
4169
+ this.failedImage.set(src);
4170
+ this.imageError.emit(src);
4171
+ }
4080
4172
  style = computed(() => STATES[this.state()] ?? STATES.available, ...(ngDevMode ? [{ debugName: "style" }] : []));
4081
4173
  stateText = computed(() => {
4082
4174
  switch (this.state()) {
@@ -4107,7 +4199,7 @@ class SdsStatusTile {
4107
4199
  ring);
4108
4200
  }, ...(ngDevMode ? [{ debugName: "tileClass" }] : []));
4109
4201
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsStatusTile, deps: [], target: i0.ɵɵFactoryTarget.Component });
4110
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsStatusTile, isStandalone: true, selector: "sds-status-tile", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, image: { classPropertyName: "image", publicName: "image", isSignal: true, isRequired: false, transformFunction: null }, imageAlt: { classPropertyName: "imageAlt", publicName: "imageAlt", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, note: { classPropertyName: "note", publicName: "note", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, availableLabel: { classPropertyName: "availableLabel", publicName: "availableLabel", isSignal: true, isRequired: false, transformFunction: null }, soldOutLabel: { classPropertyName: "soldOutLabel", publicName: "soldOutLabel", isSignal: true, isRequired: false, transformFunction: null }, hiddenLabel: { classPropertyName: "hiddenLabel", publicName: "hiddenLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activate: "activate" }, host: { classAttribute: "block" }, ngImport: i0, template: `
4202
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsStatusTile, isStandalone: true, selector: "sds-status-tile", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, image: { classPropertyName: "image", publicName: "image", isSignal: true, isRequired: false, transformFunction: null }, imageAlt: { classPropertyName: "imageAlt", publicName: "imageAlt", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, note: { classPropertyName: "note", publicName: "note", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, availableLabel: { classPropertyName: "availableLabel", publicName: "availableLabel", isSignal: true, isRequired: false, transformFunction: null }, soldOutLabel: { classPropertyName: "soldOutLabel", publicName: "soldOutLabel", isSignal: true, isRequired: false, transformFunction: null }, hiddenLabel: { classPropertyName: "hiddenLabel", publicName: "hiddenLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activate: "activate", imageError: "imageError" }, host: { classAttribute: "block" }, ngImport: i0, template: `
4111
4203
  <button
4112
4204
  type="button"
4113
4205
  [class]="tileClass()"
@@ -4118,11 +4210,12 @@ class SdsStatusTile {
4118
4210
  [style.background-image]="hatch()"
4119
4211
  (click)="activate.emit()"
4120
4212
  >
4121
- @if (image()) {
4213
+ @if (showImage()) {
4122
4214
  <span class="relative block h-[45%] w-full shrink-0 overflow-hidden bg-muted">
4123
4215
  <img
4124
4216
  [src]="image()"
4125
4217
  [alt]="imageAlt()"
4218
+ (error)="onImageError()"
4126
4219
  class="h-full w-full object-cover"
4127
4220
  [class.grayscale]="state() !== 'available'"
4128
4221
  [class.opacity-60]="state() !== 'available'"
@@ -4135,7 +4228,7 @@ class SdsStatusTile {
4135
4228
  <span class="flex min-h-0 w-full flex-1 flex-col gap-1 p-3 text-left">
4136
4229
  <span
4137
4230
  class="line-clamp-2 break-words font-bold leading-tight text-ink"
4138
- [class]="image() ? 'text-base' : 'text-lg'"
4231
+ [class]="showImage() ? 'text-base' : 'text-lg'"
4139
4232
  [class.line-through]="state() === 'sold-out'"
4140
4233
  [class.decoration-2]="state() === 'sold-out'"
4141
4234
  >{{ title() }}</span
@@ -4198,11 +4291,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
4198
4291
  [style.background-image]="hatch()"
4199
4292
  (click)="activate.emit()"
4200
4293
  >
4201
- @if (image()) {
4294
+ @if (showImage()) {
4202
4295
  <span class="relative block h-[45%] w-full shrink-0 overflow-hidden bg-muted">
4203
4296
  <img
4204
4297
  [src]="image()"
4205
4298
  [alt]="imageAlt()"
4299
+ (error)="onImageError()"
4206
4300
  class="h-full w-full object-cover"
4207
4301
  [class.grayscale]="state() !== 'available'"
4208
4302
  [class.opacity-60]="state() !== 'available'"
@@ -4215,7 +4309,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
4215
4309
  <span class="flex min-h-0 w-full flex-1 flex-col gap-1 p-3 text-left">
4216
4310
  <span
4217
4311
  class="line-clamp-2 break-words font-bold leading-tight text-ink"
4218
- [class]="image() ? 'text-base' : 'text-lg'"
4312
+ [class]="showImage() ? 'text-base' : 'text-lg'"
4219
4313
  [class.line-through]="state() === 'sold-out'"
4220
4314
  [class.decoration-2]="state() === 'sold-out'"
4221
4315
  >{{ title() }}</span
@@ -4260,7 +4354,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
4260
4354
  </button>
4261
4355
  `,
4262
4356
  }]
4263
- }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], image: [{ type: i0.Input, args: [{ isSignal: true, alias: "image", required: false }] }], imageAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageAlt", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], busy: [{ type: i0.Input, args: [{ isSignal: true, alias: "busy", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], availableLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableLabel", required: false }] }], soldOutLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "soldOutLabel", required: false }] }], hiddenLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenLabel", required: false }] }], activate: [{ type: i0.Output, args: ["activate"] }] } });
4357
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], image: [{ type: i0.Input, args: [{ isSignal: true, alias: "image", required: false }] }], imageAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageAlt", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], busy: [{ type: i0.Input, args: [{ isSignal: true, alias: "busy", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], availableLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableLabel", required: false }] }], soldOutLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "soldOutLabel", required: false }] }], hiddenLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenLabel", required: false }] }], activate: [{ type: i0.Output, args: ["activate"] }], imageError: [{ type: i0.Output, args: ["imageError"] }] } });
4264
4358
 
4265
4359
  let nextId$b = 0;
4266
4360
  /**
@@ -4904,6 +4998,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
4904
4998
  }]
4905
4999
  }] });
4906
5000
  let nextId$a = 0;
5001
+ /** Fastest auto-scroll step, in px per animation frame (reached at the very edge). */
5002
+ const AUTO_SCROLL_MAX_STEP = 18;
5003
+ /** The nearest ancestor that scrolls vertically (below the document, which is handled as the window). */
5004
+ function scrollParentOf(el) {
5005
+ const doc = el.ownerDocument;
5006
+ for (let node = el.parentElement; node; node = node.parentElement) {
5007
+ if (node === doc.body || node === doc.documentElement)
5008
+ break;
5009
+ const overflowY = getComputedStyle(node).overflowY;
5010
+ if (/(auto|scroll|overlay)/.test(overflowY) && node.scrollHeight > node.clientHeight)
5011
+ return node;
5012
+ }
5013
+ return null;
5014
+ }
5015
+ /**
5016
+ * Signed scroll step for a pointer at `y` inside the band [top, bottom]: negative near the top edge,
5017
+ * positive near the bottom, faster the closer it gets, 0 elsewhere.
5018
+ */
5019
+ function edgeStep(y, top, bottom, edge) {
5020
+ if (bottom - top < edge * 2)
5021
+ edge = (bottom - top) / 3;
5022
+ if (edge <= 0)
5023
+ return 0;
5024
+ const speed = (depth) => Math.ceil(AUTO_SCROLL_MAX_STEP * Math.min(1, depth / edge));
5025
+ if (y < top + edge)
5026
+ return -speed(top + edge - y);
5027
+ if (y > bottom - edge)
5028
+ return speed(y - (bottom - edge));
5029
+ return 0;
5030
+ }
4907
5031
  /** Move one entry of `list` from `from` to `to`, returning a new array. */
4908
5032
  function moveItem(list, from, to) {
4909
5033
  const next = [...list];
@@ -4919,6 +5043,10 @@ function moveItem(list, from, to) {
4919
5043
  * - **Keyboard**: focus a handle, **Space/Enter** picks the item up, **↑/↓** (and Home/End) move it,
4920
5044
  * **Space/Enter** drops it, **Escape** cancels (the event is stopped, so an enclosing drawer stays open).
4921
5045
  * Moving focus away also cancels.
5046
+ * - **Long lists**: while a pointer drag nears the top or bottom edge of the nearest scrollable
5047
+ * ancestor (a drawer body, a panel) — or of the window — that container scrolls, faster closer to
5048
+ * the edge, and the dragged row stays under the pointer. A keyboard move scrolls just enough to keep
5049
+ * the moving row in view. Turn off with `[autoScroll]="false"`.
4922
5050
  * - **Screen readers**: every handle is named ("Reorder Burgers") and described by the instructions; an
4923
5051
  * assertive live region announces pick-up, each move ("moved to position 3 of 8"), the drop and a cancel.
4924
5052
  *
@@ -4955,6 +5083,13 @@ class SdsSortableList {
4955
5083
  appearance = input('card', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
4956
5084
  /** Accessible name of the list. */
4957
5085
  ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
5086
+ /**
5087
+ * Scroll the nearest scrollable ancestor (then the window) while dragging near its top or bottom
5088
+ * edge, and keep a keyboard-moved row in view.
5089
+ */
5090
+ autoScroll = input(true, ...(ngDevMode ? [{ debugName: "autoScroll", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
5091
+ /** Height (px) of the band along each scroll edge where a pointer drag starts auto-scrolling. */
5092
+ autoScrollEdge = input(56, ...(ngDevMode ? [{ debugName: "autoScrollEdge", transform: numberAttribute }] : [{ transform: numberAttribute }]));
4958
5093
  /** Name of each handle; `{item}` is the item's label. */
4959
5094
  handleLabel = input('Reorder {item}', ...(ngDevMode ? [{ debugName: "handleLabel" }] : []));
4960
5095
  /** Read after a handle's name (aria-describedby). */
@@ -4985,6 +5120,16 @@ class SdsSortableList {
4985
5120
  gap = 0;
4986
5121
  pointerId = null;
4987
5122
  startY = 0;
5123
+ /** Latest pointer position during a pointer drag (auto-scroll re-reads it every frame). */
5124
+ lastY = 0;
5125
+ /** The host's viewport top at drag start: the drift since then is how far its scrollers moved. */
5126
+ startHostTop = 0;
5127
+ /** Nearest scrollable ancestor, found at drag start. */
5128
+ scroller = null;
5129
+ frame = null;
5130
+ constructor() {
5131
+ inject(DestroyRef).onDestroy(() => this.stopAutoScroll());
5132
+ }
4988
5133
  /** Per-row offsets that open a gap where the moving row will land. */
4989
5134
  shifts = computed(() => {
4990
5135
  const a = this.active();
@@ -5118,7 +5263,7 @@ class SdsSortableList {
5118
5263
  case 'Escape':
5119
5264
  event.preventDefault();
5120
5265
  event.stopPropagation();
5121
- this.cancel();
5266
+ this.cancel(true, true);
5122
5267
  return;
5123
5268
  case 'Tab':
5124
5269
  this.cancel();
@@ -5130,6 +5275,7 @@ class SdsSortableList {
5130
5275
  return;
5131
5276
  this.target.set(to);
5132
5277
  this.announce(this.movedMessage(), to);
5278
+ this.revealActive();
5133
5279
  }
5134
5280
  /** Focus leaving the list while an item is picked up cancels the move. */
5135
5281
  onFocusOut(event) {
@@ -5152,17 +5298,39 @@ class SdsSortableList {
5152
5298
  event.currentTarget.focus({ preventScroll: true });
5153
5299
  this.pointerId = event.pointerId;
5154
5300
  this.startY = event.clientY;
5301
+ this.lastY = event.clientY;
5155
5302
  this.pointerDy.set(0);
5156
5303
  this.begin(i, 'pointer');
5304
+ this.startAutoScroll();
5157
5305
  }
5158
5306
  onPointerMove(event) {
5159
5307
  if (this.mode() !== 'pointer' || event.pointerId !== this.pointerId)
5160
5308
  return;
5309
+ this.lastY = event.clientY;
5310
+ this.track();
5311
+ }
5312
+ /**
5313
+ * Place the dragged row under the pointer and pick its landing slot. Positions are compared in
5314
+ * drag-start coordinates: the pointer's travel plus however far the list has scrolled since.
5315
+ */
5316
+ track() {
5161
5317
  const a = this.active();
5162
- if (a === null)
5163
- return;
5164
- const dy = event.clientY - this.startY;
5318
+ if (a === null || !this.rects[a])
5319
+ return;
5320
+ // Keep the row inside the list: it can't be dropped beyond either end, and a row dragged past the
5321
+ // end would grow the scroll area under an auto-scroll that then never stops.
5322
+ const first = this.rects[0];
5323
+ const last = this.rects[this.rects.length - 1];
5324
+ const minDy = first.top - this.rects[a].top;
5325
+ const maxDy = last.top + last.height - (this.rects[a].top + this.rects[a].height);
5326
+ const dy = Math.min(maxDy, Math.max(minDy, this.lastY - this.startY + this.scrolledBy()));
5165
5327
  this.pointerDy.set(dy);
5328
+ // Pinned at an end of the list: that end's slot (with equal row heights the centre test below
5329
+ // would stop one short of the last slot).
5330
+ if (dy >= maxDy)
5331
+ return this.target.set(this.rects.length - 1);
5332
+ if (dy <= minDy)
5333
+ return this.target.set(0);
5166
5334
  const center = this.rects[a].top + this.rects[a].height / 2 + dy;
5167
5335
  let t = 0;
5168
5336
  this.rects.forEach((r, j) => {
@@ -5171,6 +5339,103 @@ class SdsSortableList {
5171
5339
  });
5172
5340
  this.target.set(t);
5173
5341
  }
5342
+ /** How far (px) the list has moved up the viewport since the drag began — any ancestor or the window. */
5343
+ scrolledBy() {
5344
+ return this.startHostTop - this.host.nativeElement.getBoundingClientRect().top;
5345
+ }
5346
+ // --- auto-scroll ----------------------------------------------------------------
5347
+ startAutoScroll() {
5348
+ if (!this.autoScroll() || typeof requestAnimationFrame === 'undefined')
5349
+ return;
5350
+ this.stopAutoScroll();
5351
+ const tick = () => {
5352
+ this.frame = null;
5353
+ if (this.mode() !== 'pointer')
5354
+ return;
5355
+ this.scrollNearEdge(this.lastY);
5356
+ // Re-track every frame: auto-scroll, or a wheel/trackpad scroll, moves the list under a still pointer.
5357
+ this.track();
5358
+ this.frame = requestAnimationFrame(tick);
5359
+ };
5360
+ this.frame = requestAnimationFrame(tick);
5361
+ }
5362
+ stopAutoScroll() {
5363
+ if (this.frame !== null)
5364
+ cancelAnimationFrame(this.frame);
5365
+ this.frame = null;
5366
+ }
5367
+ /**
5368
+ * One auto-scroll step for a pointer at `y`: the scroll container first, then the window. A side
5369
+ * only scrolls while part of the list is still hidden past that edge.
5370
+ */
5371
+ scrollNearEdge(y) {
5372
+ const edge = Math.max(0, this.autoScrollEdge());
5373
+ const view = this.host.nativeElement.ownerDocument.defaultView;
5374
+ const vh = view?.innerHeight ?? 0;
5375
+ const list = this.host.nativeElement.getBoundingClientRect();
5376
+ /** A step toward a side of the band [top, bottom], or 0 when the list doesn't extend past it. */
5377
+ const stepFor = (top, bottom) => {
5378
+ const step = edgeStep(y, top, bottom, edge);
5379
+ if (step < 0 && list.top >= top)
5380
+ return 0;
5381
+ if (step > 0 && list.bottom <= bottom)
5382
+ return 0;
5383
+ return step;
5384
+ };
5385
+ const el = this.scroller;
5386
+ if (el) {
5387
+ const box = el.getBoundingClientRect();
5388
+ const step = stepFor(Math.max(box.top, 0), Math.min(box.bottom, vh));
5389
+ const room = step < 0 ? el.scrollTop : el.scrollHeight - el.clientHeight - el.scrollTop;
5390
+ if (step !== 0 && room > 0.5) {
5391
+ el.scrollTop += step;
5392
+ return true;
5393
+ }
5394
+ }
5395
+ const doc = this.host.nativeElement.ownerDocument.scrollingElement;
5396
+ if (!view || !doc)
5397
+ return false;
5398
+ const step = stepFor(0, vh);
5399
+ const room = step < 0 ? doc.scrollTop : doc.scrollHeight - doc.clientHeight - doc.scrollTop;
5400
+ if (step === 0 || room <= 0.5)
5401
+ return false;
5402
+ view.scrollBy(0, step);
5403
+ return true;
5404
+ }
5405
+ /**
5406
+ * Keyboard move: scroll just enough (container, then window) to keep the moving row in view. Its
5407
+ * resting box comes from drag-start geometry, since its transform may still be animating.
5408
+ */
5409
+ revealActive() {
5410
+ if (!this.autoScroll())
5411
+ return;
5412
+ afterNextRender(() => {
5413
+ const a = this.active();
5414
+ if (a === null || !this.rects[a] || this.mode() !== 'keyboard')
5415
+ return;
5416
+ const margin = 8;
5417
+ const view = this.host.nativeElement.ownerDocument.defaultView;
5418
+ const vh = view?.innerHeight ?? 0;
5419
+ /** How far the row sticks out of [lo, hi]: negative above, positive below, 0 inside. */
5420
+ const overflow = (lo, hi) => {
5421
+ const top = this.rects[a].top + this.activeOffset() - this.scrolledBy();
5422
+ const bottom = top + this.rects[a].height;
5423
+ return top < lo ? top - lo : bottom > hi ? bottom - hi : 0;
5424
+ };
5425
+ const el = this.scroller;
5426
+ if (el) {
5427
+ const box = el.getBoundingClientRect();
5428
+ const d = overflow(Math.max(box.top, 0) + margin, Math.min(box.bottom, vh) - margin);
5429
+ if (d)
5430
+ el.scrollTop += d;
5431
+ }
5432
+ if (view) {
5433
+ const d = overflow(margin, vh - margin);
5434
+ if (d)
5435
+ view.scrollBy(0, d);
5436
+ }
5437
+ }, { injector: this.injector });
5438
+ }
5174
5439
  onPointerUp(event) {
5175
5440
  if (this.mode() !== 'pointer' || event.pointerId !== this.pointerId)
5176
5441
  return;
@@ -5183,6 +5448,8 @@ class SdsSortableList {
5183
5448
  // --- lifecycle of a move -------------------------------------------------------
5184
5449
  begin(i, mode) {
5185
5450
  this.measure();
5451
+ this.startHostTop = this.host.nativeElement.getBoundingClientRect().top;
5452
+ this.scroller = this.autoScroll() ? scrollParentOf(this.host.nativeElement) : null;
5186
5453
  this.active.set(i);
5187
5454
  this.target.set(i);
5188
5455
  this.mode.set(mode);
@@ -5223,20 +5490,29 @@ class SdsSortableList {
5223
5490
  this.focusHandle(to);
5224
5491
  }
5225
5492
  /** Nothing was moved in the DOM while dragging, so focus is still where it should be. */
5226
- cancel(announce = true) {
5493
+ cancel(announce = true, reveal = false) {
5227
5494
  const from = this.active();
5228
5495
  if (from === null)
5229
5496
  return;
5497
+ const keyboard = this.mode() === 'keyboard';
5230
5498
  this.reset();
5231
5499
  if (announce)
5232
5500
  this.announce(this.cancelledMessage(), from);
5501
+ // Escape after a keyboard move that scrolled away: bring the row (and its focused handle) back.
5502
+ if (reveal && keyboard && this.autoScroll()) {
5503
+ afterNextRender(() => this.host.nativeElement
5504
+ .querySelector(`[data-sortable-index="${from}"]`)
5505
+ ?.scrollIntoView({ block: 'nearest' }), { injector: this.injector });
5506
+ }
5233
5507
  }
5234
5508
  reset() {
5509
+ this.stopAutoScroll();
5235
5510
  this.active.set(null);
5236
5511
  this.target.set(null);
5237
5512
  this.mode.set(null);
5238
5513
  this.pointerDy.set(0);
5239
5514
  this.pointerId = null;
5515
+ this.scroller = null;
5240
5516
  }
5241
5517
  focusHandle(index) {
5242
5518
  afterNextRender(() => {
@@ -5257,7 +5533,7 @@ class SdsSortableList {
5257
5533
  queueMicrotask(() => this.liveMessage.set(text));
5258
5534
  }
5259
5535
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsSortableList, deps: [], target: i0.ɵɵFactoryTarget.Component });
5260
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsSortableList, isStandalone: true, selector: "sds-sortable-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, labelField: { classPropertyName: "labelField", publicName: "labelField", isSignal: true, isRequired: false, transformFunction: null }, itemLabel: { classPropertyName: "itemLabel", publicName: "itemLabel", isSignal: true, isRequired: false, transformFunction: null }, itemDisabled: { classPropertyName: "itemDisabled", publicName: "itemDisabled", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, handleLabel: { classPropertyName: "handleLabel", publicName: "handleLabel", isSignal: true, isRequired: false, transformFunction: null }, instructions: { classPropertyName: "instructions", publicName: "instructions", isSignal: true, isRequired: false, transformFunction: null }, pickedUpMessage: { classPropertyName: "pickedUpMessage", publicName: "pickedUpMessage", isSignal: true, isRequired: false, transformFunction: null }, movedMessage: { classPropertyName: "movedMessage", publicName: "movedMessage", isSignal: true, isRequired: false, transformFunction: null }, droppedMessage: { classPropertyName: "droppedMessage", publicName: "droppedMessage", isSignal: true, isRequired: false, transformFunction: null }, cancelledMessage: { classPropertyName: "cancelledMessage", publicName: "cancelledMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { items: "itemsChange", reorder: "reorder" }, host: { classAttribute: "block" }, queries: [{ propertyName: "itemTpl", first: true, predicate: SdsSortableItem, descendants: true, isSignal: true }, { propertyName: "handleTpl", first: true, predicate: SdsSortableHandle, descendants: true, isSignal: true }], ngImport: i0, template: `
5536
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsSortableList, isStandalone: true, selector: "sds-sortable-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, labelField: { classPropertyName: "labelField", publicName: "labelField", isSignal: true, isRequired: false, transformFunction: null }, itemLabel: { classPropertyName: "itemLabel", publicName: "itemLabel", isSignal: true, isRequired: false, transformFunction: null }, itemDisabled: { classPropertyName: "itemDisabled", publicName: "itemDisabled", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, autoScroll: { classPropertyName: "autoScroll", publicName: "autoScroll", isSignal: true, isRequired: false, transformFunction: null }, autoScrollEdge: { classPropertyName: "autoScrollEdge", publicName: "autoScrollEdge", isSignal: true, isRequired: false, transformFunction: null }, handleLabel: { classPropertyName: "handleLabel", publicName: "handleLabel", isSignal: true, isRequired: false, transformFunction: null }, instructions: { classPropertyName: "instructions", publicName: "instructions", isSignal: true, isRequired: false, transformFunction: null }, pickedUpMessage: { classPropertyName: "pickedUpMessage", publicName: "pickedUpMessage", isSignal: true, isRequired: false, transformFunction: null }, movedMessage: { classPropertyName: "movedMessage", publicName: "movedMessage", isSignal: true, isRequired: false, transformFunction: null }, droppedMessage: { classPropertyName: "droppedMessage", publicName: "droppedMessage", isSignal: true, isRequired: false, transformFunction: null }, cancelledMessage: { classPropertyName: "cancelledMessage", publicName: "cancelledMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { items: "itemsChange", reorder: "reorder" }, host: { classAttribute: "block" }, queries: [{ propertyName: "itemTpl", first: true, predicate: SdsSortableItem, descendants: true, isSignal: true }, { propertyName: "handleTpl", first: true, predicate: SdsSortableHandle, descendants: true, isSignal: true }], ngImport: i0, template: `
5261
5537
  <ul
5262
5538
  role="list"
5263
5539
  [attr.aria-label]="ariaLabel() || null"
@@ -5380,7 +5656,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
5380
5656
  <div class="sr-only" aria-live="assertive" aria-atomic="true">{{ liveMessage() }}</div>
5381
5657
  `,
5382
5658
  }]
5383
- }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }, { type: i0.Output, args: ["itemsChange"] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], labelField: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelField", required: false }] }], itemLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemLabel", required: false }] }], itemDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemDisabled", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], handleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "handleLabel", required: false }] }], instructions: [{ type: i0.Input, args: [{ isSignal: true, alias: "instructions", required: false }] }], pickedUpMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "pickedUpMessage", required: false }] }], movedMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "movedMessage", required: false }] }], droppedMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "droppedMessage", required: false }] }], cancelledMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelledMessage", required: false }] }], reorder: [{ type: i0.Output, args: ["reorder"] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSortableItem), { isSignal: true }] }], handleTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSortableHandle), { isSignal: true }] }] } });
5659
+ }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }, { type: i0.Output, args: ["itemsChange"] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], labelField: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelField", required: false }] }], itemLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemLabel", required: false }] }], itemDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemDisabled", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], autoScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoScroll", required: false }] }], autoScrollEdge: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoScrollEdge", required: false }] }], handleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "handleLabel", required: false }] }], instructions: [{ type: i0.Input, args: [{ isSignal: true, alias: "instructions", required: false }] }], pickedUpMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "pickedUpMessage", required: false }] }], movedMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "movedMessage", required: false }] }], droppedMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "droppedMessage", required: false }] }], cancelledMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelledMessage", required: false }] }], reorder: [{ type: i0.Output, args: ["reorder"] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSortableItem), { isSignal: true }] }], handleTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSortableHandle), { isSignal: true }] }] } });
5384
5660
 
5385
5661
  let nextId$9 = 0;
5386
5662
  /** "1.5 MB" style size (decimal units, like file managers show them), for messages. */
@@ -6282,41 +6558,41 @@ class SdsCalendar {
6282
6558
  max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : []));
6283
6559
  /** 0 = Sunday, 1 = Monday (default, European). */
6284
6560
  firstDayOfWeek = input(1, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : []));
6285
- locale = input('fr-FR', ...(ngDevMode ? [{ debugName: "locale" }] : []));
6561
+ /** BCP 47 locale for month and weekday names. Defaults to `en-GB`; pass the app's locale. */
6562
+ locale = input('en-GB', ...(ngDevMode ? [{ debugName: "locale" }] : []));
6286
6563
  showActions = input(true, ...(ngDevMode ? [{ debugName: "showActions" }] : []));
6287
6564
  /** When true, a time editor (HH:mm, 24h) is shown and the value keeps its time-of-day. */
6288
6565
  showTime = input(false, ...(ngDevMode ? [{ debugName: "showTime", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
6289
6566
  /** When true, a "done" action is shown (used by the overlay picker to close the panel). */
6290
6567
  showDone = input(false, ...(ngDevMode ? [{ debugName: "showDone", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
6291
6568
  /** Visible label of the time editor. Translate it in the consuming app. */
6292
- timeLabel = input('Heure', ...(ngDevMode ? [{ debugName: "timeLabel" }] : []));
6569
+ timeLabel = input('Time', ...(ngDevMode ? [{ debugName: "timeLabel" }] : []));
6293
6570
  /** Accessible name of the hours field (it is a bare numeric input). */
6294
- hoursLabel = input('Heures', ...(ngDevMode ? [{ debugName: "hoursLabel" }] : []));
6571
+ hoursLabel = input('Hours', ...(ngDevMode ? [{ debugName: "hoursLabel" }] : []));
6295
6572
  /** Accessible name of the minutes field. */
6296
6573
  minutesLabel = input('Minutes', ...(ngDevMode ? [{ debugName: "minutesLabel" }] : []));
6297
6574
  /** Visible text of the "done" action (shown when {@link showDone} is true). */
6298
- doneLabel = input('Terminé', ...(ngDevMode ? [{ debugName: "doneLabel" }] : []));
6575
+ doneLabel = input('Done', ...(ngDevMode ? [{ debugName: "doneLabel" }] : []));
6299
6576
  /**
6300
- * Accessible name for the calendar container. French default so existing consumers are unchanged,
6301
- * but an app serving more than one language MUST translate it.
6577
+ * Accessible name for the calendar container. English default; an app serving more than one
6578
+ * language MUST translate it.
6302
6579
  */
6303
- calendarLabel = input('Calendrier', ...(ngDevMode ? [{ debugName: "calendarLabel" }] : []));
6580
+ calendarLabel = input('Calendar', ...(ngDevMode ? [{ debugName: "calendarLabel" }] : []));
6304
6581
  /**
6305
6582
  * Accessible name for the "previous" nav button. It is icon-only, so this string is its ONLY
6306
- * accessible name — a hardcoded French one is simply wrong in every other locale. Translate it in
6307
- * the consuming app.
6583
+ * accessible name. English default; translate it in the consuming app.
6308
6584
  */
6309
- previousLabel = input('Précédent', ...(ngDevMode ? [{ debugName: "previousLabel" }] : []));
6585
+ previousLabel = input('Previous', ...(ngDevMode ? [{ debugName: "previousLabel" }] : []));
6310
6586
  /** Accessible name for the icon-only "next" nav button. See {@link previousLabel}. */
6311
- nextLabel = input('Suivant', ...(ngDevMode ? [{ debugName: "nextLabel" }] : []));
6587
+ nextLabel = input('Next', ...(ngDevMode ? [{ debugName: "nextLabel" }] : []));
6312
6588
  /**
6313
6589
  * Visible text of the "today" action (shown when {@link showActions} is true). Translate it in the
6314
6590
  * consuming app — the library ships no i18n of its own.
6315
6591
  */
6316
- todayActionLabel = input("Aujourd'hui", ...(ngDevMode ? [{ debugName: "todayActionLabel" }] : []));
6592
+ todayActionLabel = input('Today', ...(ngDevMode ? [{ debugName: "todayActionLabel" }] : []));
6317
6593
  /** Visible text of the "clear" action. See {@link todayActionLabel}. */
6318
- clearActionLabel = input('Effacer', ...(ngDevMode ? [{ debugName: "clearActionLabel" }] : []));
6319
- /** Emitted when a concrete date is picked (day click or "Aujourd'hui"). */
6594
+ clearActionLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearActionLabel" }] : []));
6595
+ /** Emitted when a concrete date is picked (day click or "Today"). */
6320
6596
  dateSelect = output();
6321
6597
  /** Emitted when the "done" action is used (see {@link showDone}). */
6322
6598
  done = output();
@@ -7079,7 +7355,7 @@ const SIZES$5 = {
7079
7355
  * [(ngModel)]; the value is a `Date | null`.
7080
7356
  *
7081
7357
  * @example
7082
- * <sds-date-picker label="Date de garde" [(ngModel)]="date" />
7358
+ * <sds-date-picker label="Delivery date" [(ngModel)]="date" />
7083
7359
  */
7084
7360
  class SdsDatePicker {
7085
7361
  host = inject(ElementRef);
@@ -7087,14 +7363,18 @@ class SdsDatePicker {
7087
7363
  fieldId = `sds-date-${nextId$7++}`;
7088
7364
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
7089
7365
  ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
7090
- placeholder = input('jj/mm/aaaa', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
7366
+ placeholder = input('dd/mm/yyyy', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
7091
7367
  hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
7092
7368
  error = input('', ...(ngDevMode ? [{ debugName: "error" }] : []));
7093
7369
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
7094
7370
  min = input(null, ...(ngDevMode ? [{ debugName: "min" }] : []));
7095
7371
  max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : []));
7096
7372
  firstDayOfWeek = input(1, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : []));
7097
- locale = input('fr-FR', ...(ngDevMode ? [{ debugName: "locale" }] : []));
7373
+ /**
7374
+ * BCP 47 locale for the calendar's month and weekday names. Defaults to `en-GB` (English names, and
7375
+ * the same day-first order as the default dd/MM/yyyy display); pass the app's locale.
7376
+ */
7377
+ locale = input('en-GB', ...(ngDevMode ? [{ debugName: "locale" }] : []));
7098
7378
  inline = input(false, ...(ngDevMode ? [{ debugName: "inline", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
7099
7379
  clearable = input(true, ...(ngDevMode ? [{ debugName: "clearable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
7100
7380
  showActions = input(true, ...(ngDevMode ? [{ debugName: "showActions", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
@@ -7108,38 +7388,37 @@ class SdsDatePicker {
7108
7388
  /** Custom display formatter for the DATE part (default dd/MM/yyyy). The time is appended as HH:mm. */
7109
7389
  format = input(formatDdMmYyyy, ...(ngDevMode ? [{ debugName: "format" }] : []));
7110
7390
  /** Visible label of the time editor (forwarded to the calendar). See {@link showTime}. */
7111
- timeLabel = input('Heure', ...(ngDevMode ? [{ debugName: "timeLabel" }] : []));
7391
+ timeLabel = input('Time', ...(ngDevMode ? [{ debugName: "timeLabel" }] : []));
7112
7392
  /** Accessible name of the hours field (forwarded to the calendar). */
7113
- hoursLabel = input('Heures', ...(ngDevMode ? [{ debugName: "hoursLabel" }] : []));
7393
+ hoursLabel = input('Hours', ...(ngDevMode ? [{ debugName: "hoursLabel" }] : []));
7114
7394
  /** Accessible name of the minutes field (forwarded to the calendar). */
7115
7395
  minutesLabel = input('Minutes', ...(ngDevMode ? [{ debugName: "minutesLabel" }] : []));
7116
7396
  /** Visible text of the calendar's "done" action, shown in the overlay when {@link showTime}. */
7117
- doneLabel = input('Terminé', ...(ngDevMode ? [{ debugName: "doneLabel" }] : []));
7397
+ doneLabel = input('Done', ...(ngDevMode ? [{ debugName: "doneLabel" }] : []));
7118
7398
  /**
7119
- * Accessible name for the clear button. French default so existing consumers are unchanged, but an
7120
- * app serving more than one language MUST translate it — it is an icon-only control, so this string
7121
- * is its only name.
7399
+ * Accessible name for the clear button. English default; an app serving more than one language MUST
7400
+ * translate it — it is an icon-only control, so this string is its only name.
7122
7401
  */
7123
- clearLabel = input('Effacer la date', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
7402
+ clearLabel = input('Clear date', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
7124
7403
  /**
7125
7404
  * Accessible name for the icon-only calendar toggle while the panel is CLOSED. See
7126
7405
  * {@link clearLabel} for why this has to be translatable.
7127
7406
  */
7128
- openCalendarLabel = input('Ouvrir le calendrier', ...(ngDevMode ? [{ debugName: "openCalendarLabel" }] : []));
7407
+ openCalendarLabel = input('Open calendar', ...(ngDevMode ? [{ debugName: "openCalendarLabel" }] : []));
7129
7408
  /** Accessible name for the calendar toggle while the panel is OPEN. See {@link openCalendarLabel}. */
7130
- closeCalendarLabel = input('Fermer le calendrier', ...(ngDevMode ? [{ debugName: "closeCalendarLabel" }] : []));
7409
+ closeCalendarLabel = input('Close calendar', ...(ngDevMode ? [{ debugName: "closeCalendarLabel" }] : []));
7131
7410
  /** Accessible name for the overlay dialog that holds the calendar. */
7132
- panelLabel = input('Sélection de date', ...(ngDevMode ? [{ debugName: "panelLabel" }] : []));
7411
+ panelLabel = input('Choose a date', ...(ngDevMode ? [{ debugName: "panelLabel" }] : []));
7133
7412
  /**
7134
7413
  * Labels forwarded to the embedded <sds-calendar>. They live here because the picker is how the
7135
7414
  * calendar is normally reached — without forwarding, a consumer could translate the field but not
7136
7415
  * the panel it opens. Defaults match SdsCalendar's own, so nothing changes for existing consumers.
7137
7416
  */
7138
- calendarLabel = input('Calendrier', ...(ngDevMode ? [{ debugName: "calendarLabel" }] : []));
7139
- previousLabel = input('Précédent', ...(ngDevMode ? [{ debugName: "previousLabel" }] : []));
7140
- nextLabel = input('Suivant', ...(ngDevMode ? [{ debugName: "nextLabel" }] : []));
7141
- todayActionLabel = input("Aujourd'hui", ...(ngDevMode ? [{ debugName: "todayActionLabel" }] : []));
7142
- clearActionLabel = input('Effacer', ...(ngDevMode ? [{ debugName: "clearActionLabel" }] : []));
7417
+ calendarLabel = input('Calendar', ...(ngDevMode ? [{ debugName: "calendarLabel" }] : []));
7418
+ previousLabel = input('Previous', ...(ngDevMode ? [{ debugName: "previousLabel" }] : []));
7419
+ nextLabel = input('Next', ...(ngDevMode ? [{ debugName: "nextLabel" }] : []));
7420
+ todayActionLabel = input('Today', ...(ngDevMode ? [{ debugName: "todayActionLabel" }] : []));
7421
+ clearActionLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearActionLabel" }] : []));
7143
7422
  value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
7144
7423
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
7145
7424
  cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : []));
@@ -7705,7 +7984,7 @@ let nextId$6 = 0;
7705
7984
  *
7706
7985
  * @example
7707
7986
  * <sds-select [options]="services" optionLabel="name" optionValue="id"
7708
- * placeholder="Choisir un service" [(ngModel)]="serviceId" filter clearable />
7987
+ * placeholder="Choose a service" [(ngModel)]="serviceId" filter clearable />
7709
7988
  *
7710
7989
  * @example
7711
7990
  * <sds-select [options]="categories" optionLabel="name" optionValue="id" [(ngModel)]="categoryId">
@@ -7725,7 +8004,7 @@ class SdsSelect {
7725
8004
  optionDisabled = input('disabled', ...(ngDevMode ? [{ debugName: "optionDisabled" }] : []));
7726
8005
  /** Key used to compare object values for selection equality. */
7727
8006
  dataKey = input('', ...(ngDevMode ? [{ debugName: "dataKey" }] : []));
7728
- placeholder = input('Sélectionner…', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
8007
+ placeholder = input('Select…', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
7729
8008
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
7730
8009
  ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
7731
8010
  hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
@@ -7735,8 +8014,15 @@ class SdsSelect {
7735
8014
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
7736
8015
  clearable = input(false, ...(ngDevMode ? [{ debugName: "clearable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
7737
8016
  filter = input(false, ...(ngDevMode ? [{ debugName: "filter", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
7738
- filterPlaceholder = input('Rechercher…', ...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : []));
7739
- emptyMessage = input('Aucun résultat', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : []));
8017
+ filterPlaceholder = input('Search…', ...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : []));
8018
+ emptyMessage = input('No results', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : []));
8019
+ /**
8020
+ * Accessible name of the icon-only clear button (see {@link clearable}). English default; an app
8021
+ * serving more than one language passes a translated value — it is the button's only name.
8022
+ */
8023
+ clearLabel = input('Clear selection', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
8024
+ /** Accessible name of the filter field inside the panel (see {@link filter}). */
8025
+ filterLabel = input('Search', ...(ngDevMode ? [{ debugName: "filterLabel" }] : []));
7740
8026
  /** Optional projected `<ng-template sdsSelectOption>` — custom option + selected-value rendering. */
7741
8027
  optionTpl = contentChild(SdsSelectOption, ...(ngDevMode ? [{ debugName: "optionTpl" }] : []));
7742
8028
  /** Optional projected `<ng-template sdsSelectEmpty>` — custom no-results content. */
@@ -8092,7 +8378,7 @@ class SdsSelect {
8092
8378
  this.close();
8093
8379
  }
8094
8380
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
8095
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsSelect, isStandalone: true, selector: "sds-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, optionDisabled: { classPropertyName: "optionDisabled", publicName: "optionDisabled", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
8381
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsSelect, isStandalone: true, selector: "sds-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, optionDisabled: { classPropertyName: "optionDisabled", publicName: "optionDisabled", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, filterLabel: { classPropertyName: "filterLabel", publicName: "filterLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
8096
8382
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SdsSelect), multi: true },
8097
8383
  ], queries: [{ propertyName: "optionTpl", first: true, predicate: SdsSelectOption, descendants: true, isSignal: true }, { propertyName: "emptyTpl", first: true, predicate: SdsSelectEmpty, descendants: true, isSignal: true }, { propertyName: "footerTpl", first: true, predicate: SdsSelectFooter, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: `
8098
8384
  @if (label()) {
@@ -8137,7 +8423,7 @@ class SdsSelect {
8137
8423
  <button
8138
8424
  type="button"
8139
8425
  tabindex="-1"
8140
- aria-label="Effacer la sélection"
8426
+ [attr.aria-label]="clearLabel()"
8141
8427
  class="mr-1 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-ink-faint hover:bg-black/5 hover:text-ink-soft"
8142
8428
  (click)="clear($event)"
8143
8429
  >
@@ -8170,7 +8456,7 @@ class SdsSelect {
8170
8456
  [value]="filterText()"
8171
8457
  (input)="onFilter($event)"
8172
8458
  (keydown)="onFilterKeydown($event)"
8173
- aria-label="Rechercher"
8459
+ [attr.aria-label]="filterLabel()"
8174
8460
  class="h-9 w-full bg-transparent pl-8 pr-2 text-sm text-ink outline-none placeholder:text-ink-faint"
8175
8461
  />
8176
8462
  </div>
@@ -8293,7 +8579,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
8293
8579
  <button
8294
8580
  type="button"
8295
8581
  tabindex="-1"
8296
- aria-label="Effacer la sélection"
8582
+ [attr.aria-label]="clearLabel()"
8297
8583
  class="mr-1 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-ink-faint hover:bg-black/5 hover:text-ink-soft"
8298
8584
  (click)="clear($event)"
8299
8585
  >
@@ -8326,7 +8612,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
8326
8612
  [value]="filterText()"
8327
8613
  (input)="onFilter($event)"
8328
8614
  (keydown)="onFilterKeydown($event)"
8329
- aria-label="Rechercher"
8615
+ [attr.aria-label]="filterLabel()"
8330
8616
  class="h-9 w-full bg-transparent pl-8 pr-2 text-sm text-ink outline-none placeholder:text-ink-faint"
8331
8617
  />
8332
8618
  </div>
@@ -8393,7 +8679,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
8393
8679
  }
8394
8680
  `,
8395
8681
  }]
8396
- }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], optionDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionDisabled", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], optionTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectOption), { isSignal: true }] }], emptyTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectEmpty), { isSignal: true }] }], footerTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectFooter), { isSignal: true }] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }] } });
8682
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], optionDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionDisabled", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], filterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterLabel", required: false }] }], optionTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectOption), { isSignal: true }] }], emptyTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectEmpty), { isSignal: true }] }], footerTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectFooter), { isSignal: true }] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }] } });
8397
8683
 
8398
8684
  const SIZES$3 = {
8399
8685
  sm: 'min-h-9 text-sm',
@@ -8440,7 +8726,7 @@ class SdsMultiSelect {
8440
8726
  optionValue = input('', ...(ngDevMode ? [{ debugName: "optionValue" }] : []));
8441
8727
  optionDisabled = input('disabled', ...(ngDevMode ? [{ debugName: "optionDisabled" }] : []));
8442
8728
  dataKey = input('', ...(ngDevMode ? [{ debugName: "dataKey" }] : []));
8443
- placeholder = input('Sélectionner…', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
8729
+ placeholder = input('Select…', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
8444
8730
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
8445
8731
  ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
8446
8732
  hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
@@ -8449,13 +8735,24 @@ class SdsMultiSelect {
8449
8735
  display = input('comma', ...(ngDevMode ? [{ debugName: "display" }] : []));
8450
8736
  /** In comma mode, show a count label once more than this many are selected. */
8451
8737
  maxSelectedLabels = input(3, ...(ngDevMode ? [{ debugName: "maxSelectedLabels", transform: numberAttribute }] : [{ transform: numberAttribute }]));
8452
- selectedItemsLabel = input('{0} éléments sélectionnés', ...(ngDevMode ? [{ debugName: "selectedItemsLabel" }] : []));
8738
+ selectedItemsLabel = input('{0} items selected', ...(ngDevMode ? [{ debugName: "selectedItemsLabel" }] : []));
8453
8739
  showToggleAll = input(true, ...(ngDevMode ? [{ debugName: "showToggleAll", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
8454
8740
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
8455
8741
  clearable = input(false, ...(ngDevMode ? [{ debugName: "clearable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
8456
8742
  filter = input(false, ...(ngDevMode ? [{ debugName: "filter", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
8457
- filterPlaceholder = input('Rechercher…', ...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : []));
8458
- emptyMessage = input('Aucun résultat', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : []));
8743
+ filterPlaceholder = input('Search…', ...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : []));
8744
+ emptyMessage = input('No results', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : []));
8745
+ /**
8746
+ * Accessible name of a chip's icon-only remove button (`display="chip"`); `{label}` is the option's
8747
+ * label. English defaults throughout — an app serving more than one language passes translations.
8748
+ */
8749
+ removeLabel = input('Remove {label}', ...(ngDevMode ? [{ debugName: "removeLabel" }] : []));
8750
+ /** Accessible name of the icon-only clear-all button (see {@link clearable}). */
8751
+ clearLabel = input('Clear all', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
8752
+ /** Accessible name of the filter field inside the panel (see {@link filter}). */
8753
+ filterLabel = input('Search', ...(ngDevMode ? [{ debugName: "filterLabel" }] : []));
8754
+ /** Visible text of the "select all" row (see {@link showToggleAll}). */
8755
+ selectAllLabel = input('Select all', ...(ngDevMode ? [{ debugName: "selectAllLabel" }] : []));
8459
8756
  /** Optional projected `<ng-template sdsSelectOption>` — custom option-row rendering. */
8460
8757
  optionTpl = contentChild(SdsSelectOption, ...(ngDevMode ? [{ debugName: "optionTpl" }] : []));
8461
8758
  /** Optional projected `<ng-template sdsSelectEmpty>` — custom no-results content. */
@@ -8855,7 +9152,7 @@ class SdsMultiSelect {
8855
9152
  this.close();
8856
9153
  }
8857
9154
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsMultiSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
8858
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsMultiSelect, isStandalone: true, selector: "sds-multi-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, optionDisabled: { classPropertyName: "optionDisabled", publicName: "optionDisabled", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, maxSelectedLabels: { classPropertyName: "maxSelectedLabels", publicName: "maxSelectedLabels", isSignal: true, isRequired: false, transformFunction: null }, selectedItemsLabel: { classPropertyName: "selectedItemsLabel", publicName: "selectedItemsLabel", isSignal: true, isRequired: false, transformFunction: null }, showToggleAll: { classPropertyName: "showToggleAll", publicName: "showToggleAll", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
9155
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsMultiSelect, isStandalone: true, selector: "sds-multi-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, optionDisabled: { classPropertyName: "optionDisabled", publicName: "optionDisabled", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, maxSelectedLabels: { classPropertyName: "maxSelectedLabels", publicName: "maxSelectedLabels", isSignal: true, isRequired: false, transformFunction: null }, selectedItemsLabel: { classPropertyName: "selectedItemsLabel", publicName: "selectedItemsLabel", isSignal: true, isRequired: false, transformFunction: null }, showToggleAll: { classPropertyName: "showToggleAll", publicName: "showToggleAll", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, filterLabel: { classPropertyName: "filterLabel", publicName: "filterLabel", isSignal: true, isRequired: false, transformFunction: null }, selectAllLabel: { classPropertyName: "selectAllLabel", publicName: "selectAllLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
8859
9156
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SdsMultiSelect), multi: true },
8860
9157
  ], queries: [{ propertyName: "optionTpl", first: true, predicate: SdsSelectOption, descendants: true, isSignal: true }, { propertyName: "emptyTpl", first: true, predicate: SdsSelectEmpty, descendants: true, isSignal: true }, { propertyName: "footerTpl", first: true, predicate: SdsSelectFooter, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: `
8861
9158
  @if (label()) {
@@ -8888,7 +9185,7 @@ class SdsMultiSelect {
8888
9185
  <button
8889
9186
  type="button"
8890
9187
  tabindex="-1"
8891
- [attr.aria-label]="'Retirer ' + opt.label"
9188
+ [attr.aria-label]="removeLabel().replace('{label}', opt.label)"
8892
9189
  class="inline-flex h-4 w-4 items-center justify-center rounded-full hover:bg-brand-100"
8893
9190
  (click)="removeChip($event, opt)"
8894
9191
  >
@@ -8910,7 +9207,7 @@ class SdsMultiSelect {
8910
9207
  <button
8911
9208
  type="button"
8912
9209
  tabindex="-1"
8913
- aria-label="Tout effacer"
9210
+ [attr.aria-label]="clearLabel()"
8914
9211
  class="mr-1 inline-flex h-6 w-6 shrink-0 items-center justify-center self-center rounded-full text-ink-faint hover:bg-black/5 hover:text-ink-soft"
8915
9212
  (click)="clear($event)"
8916
9213
  >
@@ -8943,7 +9240,7 @@ class SdsMultiSelect {
8943
9240
  [value]="filterText()"
8944
9241
  (input)="onFilter($event)"
8945
9242
  (keydown)="onFilterKeydown($event)"
8946
- aria-label="Rechercher"
9243
+ [attr.aria-label]="filterLabel()"
8947
9244
  class="h-9 w-full bg-transparent pl-8 pr-2 text-sm text-ink outline-none placeholder:text-ink-faint"
8948
9245
  />
8949
9246
  </div>
@@ -8969,7 +9266,7 @@ class SdsMultiSelect {
8969
9266
  <span class="h-0.5 w-2.5 rounded-full bg-white"></span>
8970
9267
  }
8971
9268
  </span>
8972
- Tout sélectionner
9269
+ {{ selectAllLabel() }}
8973
9270
  </button>
8974
9271
  }
8975
9272
 
@@ -9079,7 +9376,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
9079
9376
  <button
9080
9377
  type="button"
9081
9378
  tabindex="-1"
9082
- [attr.aria-label]="'Retirer ' + opt.label"
9379
+ [attr.aria-label]="removeLabel().replace('{label}', opt.label)"
9083
9380
  class="inline-flex h-4 w-4 items-center justify-center rounded-full hover:bg-brand-100"
9084
9381
  (click)="removeChip($event, opt)"
9085
9382
  >
@@ -9101,7 +9398,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
9101
9398
  <button
9102
9399
  type="button"
9103
9400
  tabindex="-1"
9104
- aria-label="Tout effacer"
9401
+ [attr.aria-label]="clearLabel()"
9105
9402
  class="mr-1 inline-flex h-6 w-6 shrink-0 items-center justify-center self-center rounded-full text-ink-faint hover:bg-black/5 hover:text-ink-soft"
9106
9403
  (click)="clear($event)"
9107
9404
  >
@@ -9134,7 +9431,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
9134
9431
  [value]="filterText()"
9135
9432
  (input)="onFilter($event)"
9136
9433
  (keydown)="onFilterKeydown($event)"
9137
- aria-label="Rechercher"
9434
+ [attr.aria-label]="filterLabel()"
9138
9435
  class="h-9 w-full bg-transparent pl-8 pr-2 text-sm text-ink outline-none placeholder:text-ink-faint"
9139
9436
  />
9140
9437
  </div>
@@ -9160,7 +9457,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
9160
9457
  <span class="h-0.5 w-2.5 rounded-full bg-white"></span>
9161
9458
  }
9162
9459
  </span>
9163
- Tout sélectionner
9460
+ {{ selectAllLabel() }}
9164
9461
  </button>
9165
9462
  }
9166
9463
 
@@ -9226,29 +9523,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
9226
9523
  }
9227
9524
  `,
9228
9525
  }]
9229
- }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], optionDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionDisabled", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], maxSelectedLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelectedLabels", required: false }] }], selectedItemsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemsLabel", required: false }] }], showToggleAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToggleAll", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], optionTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectOption), { isSignal: true }] }], emptyTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectEmpty), { isSignal: true }] }], footerTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectFooter), { isSignal: true }] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }] } });
9526
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], optionDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionDisabled", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], maxSelectedLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelectedLabels", required: false }] }], selectedItemsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemsLabel", required: false }] }], showToggleAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToggleAll", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], filterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterLabel", required: false }] }], selectAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllLabel", required: false }] }], optionTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectOption), { isSignal: true }] }], emptyTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectEmpty), { isSignal: true }] }], footerTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsSelectFooter), { isSignal: true }] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }] } });
9230
9527
 
9231
9528
  const SDS_PHONE_COUNTRIES = [
9232
- { iso2: 'BE', name: 'Belgique', dialCode: '32', lengths: [9], format: '### ## ## ##', example: '470123456' },
9529
+ { iso2: 'BE', name: 'Belgium', dialCode: '32', lengths: [9], format: '### ## ## ##', example: '470123456' },
9233
9530
  { iso2: 'FR', name: 'France', dialCode: '33', lengths: [9], format: '# ## ## ## ##', example: '612345678' },
9234
9531
  { iso2: 'LU', name: 'Luxembourg', dialCode: '352', lengths: [9, 8, 6], format: '### ### ###', example: '628123456' },
9235
- { iso2: 'NL', name: 'Pays-Bas', dialCode: '31', lengths: [9], format: '# ## ## ## ##', example: '612345678' },
9236
- { iso2: 'DE', name: 'Allemagne', dialCode: '49', lengths: [10, 11], format: '#### #######', example: '15123456789' },
9237
- { iso2: 'GB', name: 'Royaume-Uni', dialCode: '44', lengths: [10], format: '#### ######', example: '7400123456' },
9238
- { iso2: 'IE', name: 'Irlande', dialCode: '353', lengths: [9], format: '## ### ####', example: '850123456' },
9239
- { iso2: 'CH', name: 'Suisse', dialCode: '41', lengths: [9], format: '## ### ## ##', example: '781234567' },
9240
- { iso2: 'ES', name: 'Espagne', dialCode: '34', lengths: [9], format: '### ## ## ##', example: '612345678' },
9241
- { iso2: 'IT', name: 'Italie', dialCode: '39', lengths: [9, 10], format: '### ### ####', example: '3123456789' },
9532
+ { iso2: 'NL', name: 'Netherlands', dialCode: '31', lengths: [9], format: '# ## ## ## ##', example: '612345678' },
9533
+ { iso2: 'DE', name: 'Germany', dialCode: '49', lengths: [10, 11], format: '#### #######', example: '15123456789' },
9534
+ { iso2: 'GB', name: 'United Kingdom', dialCode: '44', lengths: [10], format: '#### ######', example: '7400123456' },
9535
+ { iso2: 'IE', name: 'Ireland', dialCode: '353', lengths: [9], format: '## ### ####', example: '850123456' },
9536
+ { iso2: 'CH', name: 'Switzerland', dialCode: '41', lengths: [9], format: '## ### ## ##', example: '781234567' },
9537
+ { iso2: 'ES', name: 'Spain', dialCode: '34', lengths: [9], format: '### ## ## ##', example: '612345678' },
9538
+ { iso2: 'IT', name: 'Italy', dialCode: '39', lengths: [9, 10], format: '### ### ####', example: '3123456789' },
9242
9539
  { iso2: 'PT', name: 'Portugal', dialCode: '351', lengths: [9], format: '### ### ###', example: '912345678' },
9243
- { iso2: 'AT', name: 'Autriche', dialCode: '43', lengths: [10, 11], format: '### #######', example: '6641234567' },
9244
- { iso2: 'DK', name: 'Danemark', dialCode: '45', lengths: [8], format: '## ## ## ##', example: '20123456' },
9245
- { iso2: 'SE', name: 'Suède', dialCode: '46', lengths: [9], format: '## ### ## ##', example: '701234567' },
9246
- { iso2: 'NO', name: 'Norvège', dialCode: '47', lengths: [8], format: '### ## ###', example: '40612345' },
9247
- { iso2: 'PL', name: 'Pologne', dialCode: '48', lengths: [9], format: '### ### ###', example: '512345678' },
9248
- { iso2: 'US', name: 'États-Unis', dialCode: '1', lengths: [10], format: '(###) ###-####', example: '2015550123' },
9540
+ { iso2: 'AT', name: 'Austria', dialCode: '43', lengths: [10, 11], format: '### #######', example: '6641234567' },
9541
+ { iso2: 'DK', name: 'Denmark', dialCode: '45', lengths: [8], format: '## ## ## ##', example: '20123456' },
9542
+ { iso2: 'SE', name: 'Sweden', dialCode: '46', lengths: [9], format: '## ### ## ##', example: '701234567' },
9543
+ { iso2: 'NO', name: 'Norway', dialCode: '47', lengths: [8], format: '### ## ###', example: '40612345' },
9544
+ { iso2: 'PL', name: 'Poland', dialCode: '48', lengths: [9], format: '### ### ###', example: '512345678' },
9545
+ { iso2: 'US', name: 'United States', dialCode: '1', lengths: [10], format: '(###) ###-####', example: '2015550123' },
9249
9546
  { iso2: 'CA', name: 'Canada', dialCode: '1', lengths: [10], format: '(###) ###-####', example: '2042345678' },
9250
- { iso2: 'MA', name: 'Maroc', dialCode: '212', lengths: [9], format: '### ## ## ##', example: '612345678' },
9251
- { iso2: 'TR', name: 'Turquie', dialCode: '90', lengths: [10], format: '### ### ## ##', example: '5012345678' },
9547
+ { iso2: 'MA', name: 'Morocco', dialCode: '212', lengths: [9], format: '### ## ## ##', example: '612345678' },
9548
+ { iso2: 'TR', name: 'Turkey', dialCode: '90', lengths: [10], format: '### ### ## ##', example: '5012345678' },
9252
9549
  ];
9253
9550
  /** Reduce raw input to national-significant digits (drops non-digits & leading trunk zeros). */
9254
9551
  function sdsNormalizeSignificant(raw) {
@@ -9303,7 +9600,7 @@ let nextId$4 = 0;
9303
9600
  * '+32470123456') and Validator (national length is checked per country).
9304
9601
  *
9305
9602
  * @example
9306
- * <sds-phone-input label="Téléphone" defaultCountry="BE"
9603
+ * <sds-phone-input label="Phone" defaultCountry="BE"
9307
9604
  * [preferredCountries]="['BE','FR','LU']"
9308
9605
  * [(ngModel)]="phone" required />
9309
9606
  */
@@ -9328,43 +9625,67 @@ class SdsPhoneInput {
9328
9625
  onlyCountries = input([], ...(ngDevMode ? [{ debugName: "onlyCountries" }] : []));
9329
9626
  /** Show an example number as a hint when no [hint] is provided. */
9330
9627
  showExampleHint = input(true, ...(ngDevMode ? [{ debugName: "showExampleHint", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
9331
- requiredMessage = input('Numéro de téléphone requis', ...(ngDevMode ? [{ debugName: "requiredMessage" }] : []));
9628
+ /**
9629
+ * BCP 47 locale for the country names (list, search and the selector's accessible name), resolved
9630
+ * with `Intl.DisplayNames` — e.g. `nl-BE` shows "België". Empty (default) uses the built-in English
9631
+ * names. The search also matches the English name.
9632
+ */
9633
+ locale = input('', ...(ngDevMode ? [{ debugName: "locale" }] : []));
9634
+ requiredMessage = input('Phone number required', ...(ngDevMode ? [{ debugName: "requiredMessage" }] : []));
9332
9635
  /**
9333
9636
  * Accessible name of the country selector. `{country}` is replaced with the selected country's
9334
- * name. A token rather than a prefix because word order differs per language. French default so
9335
- * existing consumers are unchanged; translate it in any app serving more than one language.
9336
- *
9337
- * Note the interpolated country NAME still comes from the library's built-in country table, which
9338
- * is French-only — translating this template fixes the wrapper, not the name inside it.
9637
+ * name (localised by {@link locale}). A token rather than a prefix because word order differs per
9638
+ * language. English default; translate it in any app serving more than one language.
9339
9639
  */
9340
- countryLabel = input('Indicatif pays : {country}', ...(ngDevMode ? [{ debugName: "countryLabel" }] : []));
9640
+ countryLabel = input('Country code: {country}', ...(ngDevMode ? [{ debugName: "countryLabel" }] : []));
9341
9641
  /**
9342
9642
  * Accessible name for the clear button. It is icon-only, so this string is its ONLY accessible
9343
- * name — a hardcoded French one is simply wrong in every other locale.
9643
+ * name — translate it in any app serving more than one language.
9344
9644
  */
9345
- clearLabel = input('Effacer', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
9645
+ clearLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
9346
9646
  /** Accessible name for the country-search field inside the dropdown. */
9347
- searchLabel = input('Rechercher un pays', ...(ngDevMode ? [{ debugName: "searchLabel" }] : []));
9647
+ searchLabel = input('Search countries', ...(ngDevMode ? [{ debugName: "searchLabel" }] : []));
9348
9648
  /** Placeholder text of the country-search field. */
9349
- searchPlaceholder = input('Rechercher un pays…', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
9649
+ searchPlaceholder = input('Search countries…', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
9350
9650
  /** Shown in place of the list when no country matches the filter. */
9351
- noResultsLabel = input('Aucun pays', ...(ngDevMode ? [{ debugName: "noResultsLabel" }] : []));
9651
+ noResultsLabel = input('No countries found', ...(ngDevMode ? [{ debugName: "noResultsLabel" }] : []));
9352
9652
  /**
9353
9653
  * Built-in validation messages. `{lengths}` is replaced with the country's accepted national
9354
- * lengths, joined with {@link lengthSeparator}. Siblings of {@link requiredMessage}, which was
9355
- * already translatable — these two were not, so an English or Dutch app showed French errors.
9654
+ * lengths, joined with {@link lengthSeparator}. English defaults; translate them alongside
9655
+ * {@link requiredMessage}.
9356
9656
  */
9357
- incompleteMessage = input('Numéro incomplet — {lengths} chiffres attendus', ...(ngDevMode ? [{ debugName: "incompleteMessage" }] : []));
9358
- invalidMessage = input('Numéro invalide — {lengths} chiffres attendus', ...(ngDevMode ? [{ debugName: "invalidMessage" }] : []));
9359
- /** Joins the accepted lengths when a country allows more than one (e.g. "8 ou 9"). */
9360
- lengthSeparator = input(' ou ', ...(ngDevMode ? [{ debugName: "lengthSeparator" }] : []));
9657
+ incompleteMessage = input('Incomplete number — {lengths} digits expected', ...(ngDevMode ? [{ debugName: "incompleteMessage" }] : []));
9658
+ invalidMessage = input('Invalid number — {lengths} digits expected', ...(ngDevMode ? [{ debugName: "invalidMessage" }] : []));
9659
+ /** Joins the accepted lengths when a country allows more than one (e.g. "8 or 9"). */
9660
+ lengthSeparator = input(' or ', ...(ngDevMode ? [{ debugName: "lengthSeparator" }] : []));
9361
9661
  /**
9362
9662
  * Auto-generated example hint (see {@link showExampleHint}). `{number}` is replaced with the
9363
9663
  * formatted international example number.
9364
9664
  */
9365
- exampleHintTemplate = input('Ex. {number}', ...(ngDevMode ? [{ debugName: "exampleHintTemplate" }] : []));
9665
+ exampleHintTemplate = input('e.g. {number}', ...(ngDevMode ? [{ debugName: "exampleHintTemplate" }] : []));
9366
9666
  /** Emitted with the parsed parts whenever the number or country changes. */
9367
9667
  phoneChange = output();
9668
+ /** `Intl.DisplayNames` for {@link locale}, or null (built-in English names). */
9669
+ regionNames = computed(() => {
9670
+ const locale = this.locale();
9671
+ if (!locale || typeof Intl === 'undefined' || !('DisplayNames' in Intl))
9672
+ return null;
9673
+ try {
9674
+ return new Intl.DisplayNames([locale], { type: 'region' });
9675
+ }
9676
+ catch {
9677
+ return null;
9678
+ }
9679
+ }, ...(ngDevMode ? [{ debugName: "regionNames" }] : []));
9680
+ /** The country's display name in {@link locale}, falling back to the built-in English name. */
9681
+ countryName(c) {
9682
+ try {
9683
+ return this.regionNames()?.of(c.iso2) ?? c.name;
9684
+ }
9685
+ catch {
9686
+ return c.name;
9687
+ }
9688
+ }
9368
9689
  national = signal('', ...(ngDevMode ? [{ debugName: "national" }] : []));
9369
9690
  countryIso = signal('', ...(ngDevMode ? [{ debugName: "countryIso" }] : []));
9370
9691
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
@@ -9403,7 +9724,8 @@ class SdsPhoneInput {
9403
9724
  const all = this.availableCountries();
9404
9725
  if (!f)
9405
9726
  return all;
9406
- return all.filter((c) => c.name.toLowerCase().includes(f) ||
9727
+ return all.filter((c) => this.countryName(c).toLowerCase().includes(f) ||
9728
+ c.name.toLowerCase().includes(f) ||
9407
9729
  c.iso2.toLowerCase().includes(f) ||
9408
9730
  c.dialCode.includes(f.replace('+', '')));
9409
9731
  }, ...(ngDevMode ? [{ debugName: "filteredCountries" }] : []));
@@ -9416,7 +9738,7 @@ class SdsPhoneInput {
9416
9738
  const number = `+${c.dialCode} ${sdsFormatNational(c.example, c.format)}`;
9417
9739
  return this.exampleHintTemplate().replace('{number}', number);
9418
9740
  }, ...(ngDevMode ? [{ debugName: "autoHint" }] : []));
9419
- countryAriaLabel = computed(() => this.countryLabel().replace('{country}', this.country().name), ...(ngDevMode ? [{ debugName: "countryAriaLabel" }] : []));
9741
+ countryAriaLabel = computed(() => this.countryLabel().replace('{country}', this.countryName(this.country())), ...(ngDevMode ? [{ debugName: "countryAriaLabel" }] : []));
9420
9742
  e164 = computed(() => {
9421
9743
  const d = this.national();
9422
9744
  return d ? `+${this.country().dialCode}${d}` : '';
@@ -9732,7 +10054,7 @@ class SdsPhoneInput {
9732
10054
  this.onValidatorChange = fn;
9733
10055
  }
9734
10056
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsPhoneInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
9735
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsPhoneInput, isStandalone: true, selector: "sds-phone-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, defaultCountry: { classPropertyName: "defaultCountry", publicName: "defaultCountry", isSignal: true, isRequired: false, transformFunction: null }, preferredCountries: { classPropertyName: "preferredCountries", publicName: "preferredCountries", isSignal: true, isRequired: false, transformFunction: null }, onlyCountries: { classPropertyName: "onlyCountries", publicName: "onlyCountries", isSignal: true, isRequired: false, transformFunction: null }, showExampleHint: { classPropertyName: "showExampleHint", publicName: "showExampleHint", isSignal: true, isRequired: false, transformFunction: null }, requiredMessage: { classPropertyName: "requiredMessage", publicName: "requiredMessage", isSignal: true, isRequired: false, transformFunction: null }, countryLabel: { classPropertyName: "countryLabel", publicName: "countryLabel", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, searchLabel: { classPropertyName: "searchLabel", publicName: "searchLabel", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, noResultsLabel: { classPropertyName: "noResultsLabel", publicName: "noResultsLabel", isSignal: true, isRequired: false, transformFunction: null }, incompleteMessage: { classPropertyName: "incompleteMessage", publicName: "incompleteMessage", isSignal: true, isRequired: false, transformFunction: null }, invalidMessage: { classPropertyName: "invalidMessage", publicName: "invalidMessage", isSignal: true, isRequired: false, transformFunction: null }, lengthSeparator: { classPropertyName: "lengthSeparator", publicName: "lengthSeparator", isSignal: true, isRequired: false, transformFunction: null }, exampleHintTemplate: { classPropertyName: "exampleHintTemplate", publicName: "exampleHintTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { phoneChange: "phoneChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
10057
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsPhoneInput, isStandalone: true, selector: "sds-phone-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, defaultCountry: { classPropertyName: "defaultCountry", publicName: "defaultCountry", isSignal: true, isRequired: false, transformFunction: null }, preferredCountries: { classPropertyName: "preferredCountries", publicName: "preferredCountries", isSignal: true, isRequired: false, transformFunction: null }, onlyCountries: { classPropertyName: "onlyCountries", publicName: "onlyCountries", isSignal: true, isRequired: false, transformFunction: null }, showExampleHint: { classPropertyName: "showExampleHint", publicName: "showExampleHint", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, requiredMessage: { classPropertyName: "requiredMessage", publicName: "requiredMessage", isSignal: true, isRequired: false, transformFunction: null }, countryLabel: { classPropertyName: "countryLabel", publicName: "countryLabel", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, searchLabel: { classPropertyName: "searchLabel", publicName: "searchLabel", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, noResultsLabel: { classPropertyName: "noResultsLabel", publicName: "noResultsLabel", isSignal: true, isRequired: false, transformFunction: null }, incompleteMessage: { classPropertyName: "incompleteMessage", publicName: "incompleteMessage", isSignal: true, isRequired: false, transformFunction: null }, invalidMessage: { classPropertyName: "invalidMessage", publicName: "invalidMessage", isSignal: true, isRequired: false, transformFunction: null }, lengthSeparator: { classPropertyName: "lengthSeparator", publicName: "lengthSeparator", isSignal: true, isRequired: false, transformFunction: null }, exampleHintTemplate: { classPropertyName: "exampleHintTemplate", publicName: "exampleHintTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { phoneChange: "phoneChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "block" }, providers: [
9736
10058
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SdsPhoneInput), multi: true },
9737
10059
  { provide: NG_VALIDATORS, useExisting: forwardRef(() => SdsPhoneInput), multi: true },
9738
10060
  ], viewQueries: [{ propertyName: "anchor", first: true, predicate: ["anchor"], descendants: true, isSignal: true }, { propertyName: "field", first: true, predicate: ["field"], descendants: true, isSignal: true }], ngImport: i0, template: `
@@ -9841,7 +10163,7 @@ class SdsPhoneInput {
9841
10163
  <span class="grid h-5 min-w-7 place-items-center rounded bg-muted px-1 text-[11px] font-semibold tracking-wide text-ink-soft">
9842
10164
  {{ c.iso2 }}
9843
10165
  </span>
9844
- <span class="flex-1 truncate">{{ c.name }}</span>
10166
+ <span class="flex-1 truncate">{{ countryName(c) }}</span>
9845
10167
  <span class="text-ink-faint">+{{ c.dialCode }}</span>
9846
10168
  </li>
9847
10169
  } @empty {
@@ -9982,7 +10304,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
9982
10304
  <span class="grid h-5 min-w-7 place-items-center rounded bg-muted px-1 text-[11px] font-semibold tracking-wide text-ink-soft">
9983
10305
  {{ c.iso2 }}
9984
10306
  </span>
9985
- <span class="flex-1 truncate">{{ c.name }}</span>
10307
+ <span class="flex-1 truncate">{{ countryName(c) }}</span>
9986
10308
  <span class="text-ink-faint">+{{ c.dialCode }}</span>
9987
10309
  </li>
9988
10310
  } @empty {
@@ -10003,7 +10325,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
10003
10325
  }
10004
10326
  `,
10005
10327
  }]
10006
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], defaultCountry: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultCountry", required: false }] }], preferredCountries: [{ type: i0.Input, args: [{ isSignal: true, alias: "preferredCountries", required: false }] }], onlyCountries: [{ type: i0.Input, args: [{ isSignal: true, alias: "onlyCountries", required: false }] }], showExampleHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExampleHint", required: false }] }], requiredMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "requiredMessage", required: false }] }], countryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "countryLabel", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], searchLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchLabel", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], noResultsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsLabel", required: false }] }], incompleteMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "incompleteMessage", required: false }] }], invalidMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalidMessage", required: false }] }], lengthSeparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "lengthSeparator", required: false }] }], exampleHintTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "exampleHintTemplate", required: false }] }], phoneChange: [{ type: i0.Output, args: ["phoneChange"] }], anchor: [{ type: i0.ViewChild, args: ['anchor', { isSignal: true }] }], field: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }] } });
10328
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], defaultCountry: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultCountry", required: false }] }], preferredCountries: [{ type: i0.Input, args: [{ isSignal: true, alias: "preferredCountries", required: false }] }], onlyCountries: [{ type: i0.Input, args: [{ isSignal: true, alias: "onlyCountries", required: false }] }], showExampleHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExampleHint", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], requiredMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "requiredMessage", required: false }] }], countryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "countryLabel", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], searchLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchLabel", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], noResultsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsLabel", required: false }] }], incompleteMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "incompleteMessage", required: false }] }], invalidMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalidMessage", required: false }] }], lengthSeparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "lengthSeparator", required: false }] }], exampleHintTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "exampleHintTemplate", required: false }] }], phoneChange: [{ type: i0.Output, args: ["phoneChange"] }], anchor: [{ type: i0.ViewChild, args: ['anchor', { isSignal: true }] }], field: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }] } });
10007
10329
 
10008
10330
  const SIZES$1 = {
10009
10331
  sm: 'h-8 min-w-8 text-xs',
@@ -10279,7 +10601,7 @@ class SdsPaginator {
10279
10601
  </label>
10280
10602
  }
10281
10603
  </div>
10282
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }, { kind: "component", type: SdsSelect, selector: "sds-select", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "dataKey", "placeholder", "label", "ariaLabel", "hint", "error", "size", "appearance", "disabled", "clearable", "filter", "filterPlaceholder", "emptyMessage"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10604
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }, { kind: "component", type: SdsSelect, selector: "sds-select", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "dataKey", "placeholder", "label", "ariaLabel", "hint", "error", "size", "appearance", "disabled", "clearable", "filter", "filterPlaceholder", "emptyMessage", "clearLabel", "filterLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10283
10605
  }
10284
10606
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsPaginator, decorators: [{
10285
10607
  type: Component,
@@ -10451,7 +10773,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
10451
10773
  * @example
10452
10774
  * <sds-tabs [(value)]="active">
10453
10775
  * <sds-tab-list>
10454
- * <sds-tab value="0">Détails</sds-tab>
10776
+ * <sds-tab value="0">Details</sds-tab>
10455
10777
  * <sds-tab value="1">Historique</sds-tab>
10456
10778
  * </sds-tab-list>
10457
10779
  * <sds-tab-panels>
@@ -10968,8 +11290,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
10968
11290
  *
10969
11291
  * @example
10970
11292
  * <sds-table [value]="rows" [columns]="cols">
10971
- * <ng-template sdsCell="statut" let-value let-row="row">
10972
- * <sds-badge [variant]="row.actif ? 'success' : 'neutral'">{{ value }}</sds-badge>
11293
+ * <ng-template sdsCell="status" let-value let-row="row">
11294
+ * <sds-badge [variant]="row.active ? 'success' : 'neutral'">{{ value }}</sds-badge>
10973
11295
  * </ng-template>
10974
11296
  * </sds-table>
10975
11297
  */
@@ -10993,6 +11315,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
10993
11315
  }]
10994
11316
  }], propDecorators: { column: [{ type: i0.Input, args: [{ isSignal: true, alias: "sdsCell", required: true }] }] } });
10995
11317
 
11318
+ /**
11319
+ * Supplies a custom template for a column's header cell, matched by its field key. The template
11320
+ * replaces the header's whole content — label and sort button — so it may hold its own controls
11321
+ * (a column with a header template is not sortable from the header). Typical use: a "select all"
11322
+ * checkbox above a checkbox column rendered with `sdsCell`.
11323
+ *
11324
+ * @example
11325
+ * <sds-table [value]="rows" [columns]="cols" dataKey="id">
11326
+ * <ng-template sdsHeader="select" let-rows="rows">
11327
+ * <sds-checkbox ariaLabel="Select all rows" [ngModel]="allSelected(rows)"
11328
+ * [indeterminate]="someSelected(rows)" (ngModelChange)="selectAll(rows, $event)" />
11329
+ * </ng-template>
11330
+ * <ng-template sdsCell="select" let-row="row">
11331
+ * <sds-checkbox [ariaLabel]="'Select ' + row.name" [ngModel]="isSelected(row)"
11332
+ * (ngModelChange)="toggle(row, $event)" />
11333
+ * </ng-template>
11334
+ * </sds-table>
11335
+ */
11336
+ class SdsTableHeader {
11337
+ /** The column `field` whose header this template renders. */
11338
+ column = input.required(...(ngDevMode ? [{ debugName: "column", alias: 'sdsHeader' }] : [{ alias: 'sdsHeader' }]));
11339
+ /** The wrapped template, rendered by the host table via ngTemplateOutlet. */
11340
+ template = inject(TemplateRef);
11341
+ /** Lets the compiler type-check `let-*` bindings against SdsTableHeaderContext. */
11342
+ static ngTemplateContextGuard(_dir, _ctx) {
11343
+ return true;
11344
+ }
11345
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTableHeader, deps: [], target: i0.ɵɵFactoryTarget.Directive });
11346
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.25", type: SdsTableHeader, isStandalone: true, selector: "ng-template[sdsHeader]", inputs: { column: { classPropertyName: "column", publicName: "sdsHeader", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
11347
+ }
11348
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTableHeader, decorators: [{
11349
+ type: Directive,
11350
+ args: [{
11351
+ selector: 'ng-template[sdsHeader]',
11352
+ standalone: true,
11353
+ }]
11354
+ }], propDecorators: { column: [{ type: i0.Input, args: [{ isSignal: true, alias: "sdsHeader", required: true }] }] } });
11355
+
10996
11356
  /**
10997
11357
  * Supplies the detail template rendered beneath an expanded row when the host
10998
11358
  * `<sds-table>` has `expandable`. Use as a structural template inside the table:
@@ -11000,7 +11360,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
11000
11360
  * @example
11001
11361
  * <sds-table [value]="rows" [columns]="cols" expandable>
11002
11362
  * <ng-template sdsRowExpansion let-row>
11003
- * <div>Détails de {{ row.nom }}</div>
11363
+ * <div>Details of {{ row.name }}</div>
11004
11364
  * </ng-template>
11005
11365
  * </sds-table>
11006
11366
  */
@@ -11050,6 +11410,11 @@ let nextId$1 = 0;
11050
11410
  * across all pages**, not just the current page. Toggling it selects/clears
11051
11411
  * every filtered row regardless of pagination (this is an intentional
11052
11412
  * deviation from PrimeNG's per-page select-all).
11413
+ * - **Custom headers:** `<ng-template sdsHeader="field">` replaces a column's header content (label and
11414
+ * sort button) — e.g. a "select all" checkbox above your own checkbox column. Its context carries the
11415
+ * filtered `rows` (all pages) and the displayed `pageRows` (see {@link SdsTableHeaderContext}).
11416
+ * - **Labels:** every visible and spoken string is an input with an English default (paginator,
11417
+ * filter, selection, expansion, editor). An app serving more than one language passes translations.
11053
11418
  *
11054
11419
  * **Editable grid (opt-in).** Set `editable` and give columns an `editor` (`text` · `number` ·
11055
11420
  * `currency` · `select`). The table becomes an ARIA grid with one tab stop: arrow keys move between
@@ -11059,14 +11424,16 @@ let nextId$1 = 0;
11059
11424
  * commits. Each changed commit emits `(cellCommit)` — the host applies it to its data (the table never
11060
11425
  * mutates rows) — and marks the cell dirty until {@link clearDirty}. Errors from `[cellErrors]` show
11061
11426
  * under the cell with `aria-invalid`. Number/currency cells use sds-input-number (live, locale-aware
11062
- * formatting: "11,9" → "€11.90"). Everything else — sort, paging, selection — is unchanged.
11427
+ * formatting: "11,9" → "€11.90"; in a comma locale such as fr-BE or nl-BE a typed "." is taken as the
11428
+ * decimal separator, so "12.50" → "12,50 €"). The `select` editor is a styled native select with the
11429
+ * column header as its name. Everything else — sort, paging, selection — is unchanged.
11063
11430
  *
11064
11431
  * @example
11065
11432
  * <sds-table [value]="staff" [columns]="cols" dataKey="id"
11066
11433
  * sortable paginator [rows]="10" globalFilter
11067
11434
  * selectionMode="multiple" [(selection)]="selected">
11068
- * <ng-template sdsCell="statut" let-value let-row="row">
11069
- * <sds-badge [variant]="row.actif ? 'success' : 'neutral'">{{ value }}</sds-badge>
11435
+ * <ng-template sdsCell="status" let-value let-row="row">
11436
+ * <sds-badge [variant]="row.active ? 'success' : 'neutral'">{{ value }}</sds-badge>
11070
11437
  * </ng-template>
11071
11438
  * </sds-table>
11072
11439
  *
@@ -11142,6 +11509,20 @@ class SdsTable {
11142
11509
  locale = input('', ...(ngDevMode ? [{ debugName: "locale" }] : []));
11143
11510
  /** Spoken marker of an edited (dirty) cell. */
11144
11511
  dirtyLabel = input('edited', ...(ngDevMode ? [{ debugName: "dirtyLabel" }] : []));
11512
+ /** Empty choice of a `select` editor while the cell has no value (a column's `placeholder` wins). */
11513
+ selectPlaceholder = input('Select…', ...(ngDevMode ? [{ debugName: "selectPlaceholder" }] : []));
11514
+ /**
11515
+ * Selection and expansion labels (English defaults; translate them in a multi-language app). The
11516
+ * checkbox/radio and expander buttons are icon-only, so these strings are their only names.
11517
+ */
11518
+ selectAllLabel = input('Select all rows', ...(ngDevMode ? [{ debugName: "selectAllLabel" }] : []));
11519
+ selectRowLabel = input('Select row', ...(ngDevMode ? [{ debugName: "selectRowLabel" }] : []));
11520
+ /** Screen-reader name of the selection column's header in `single` mode. */
11521
+ selectionColumnLabel = input('Selection', ...(ngDevMode ? [{ debugName: "selectionColumnLabel" }] : []));
11522
+ /** Screen-reader name of the expander column's header (see {@link expandable}). */
11523
+ expandColumnLabel = input('Details', ...(ngDevMode ? [{ debugName: "expandColumnLabel" }] : []));
11524
+ expandRowLabel = input('Expand row', ...(ngDevMode ? [{ debugName: "expandRowLabel" }] : []));
11525
+ collapseRowLabel = input('Collapse row', ...(ngDevMode ? [{ debugName: "collapseRowLabel" }] : []));
11145
11526
  // --- outputs --------------------------------------------------------------
11146
11527
  sortChange = output();
11147
11528
  pageChange = output();
@@ -11168,6 +11549,26 @@ class SdsTable {
11168
11549
  templateFor(field) {
11169
11550
  return this.templateMap().get(field) ?? null;
11170
11551
  }
11552
+ // --- custom header templates ----------------------------------------------
11553
+ headerTemplates = contentChildren(SdsTableHeader, ...(ngDevMode ? [{ debugName: "headerTemplates" }] : []));
11554
+ headerTemplateMap = computed(() => {
11555
+ const map = new Map();
11556
+ for (const h of this.headerTemplates())
11557
+ map.set(h.column(), h.template);
11558
+ return map;
11559
+ }, ...(ngDevMode ? [{ debugName: "headerTemplateMap" }] : []));
11560
+ headerTemplateFor(field) {
11561
+ return this.headerTemplateMap().get(field) ?? null;
11562
+ }
11563
+ headerContext(column, index) {
11564
+ return {
11565
+ $implicit: column,
11566
+ column,
11567
+ index,
11568
+ rows: this.filtered(),
11569
+ pageRows: this.displayRows(),
11570
+ };
11571
+ }
11171
11572
  // --- row-expansion template -----------------------------------------------
11172
11573
  rowExpansion = contentChild(SdsTableRowExpansion, ...(ngDevMode ? [{ debugName: "rowExpansion" }] : []));
11173
11574
  expansionTemplate() {
@@ -11293,7 +11694,8 @@ class SdsTable {
11293
11694
  totalColumnCount = computed(() => this.effectiveColumns().length + this.leadingColumnCount(), ...(ngDevMode ? [{ debugName: "totalColumnCount" }] : []));
11294
11695
  // --- sorting UI -----------------------------------------------------------
11295
11696
  isColumnSortable(col) {
11296
- return this.sortable() && !!col.sortable;
11697
+ // A custom header template owns the header content, so it has no sort button.
11698
+ return this.sortable() && !!col.sortable && !this.headerTemplateFor(col.field);
11297
11699
  }
11298
11700
  sortIcon(col) {
11299
11701
  if (this.sortField() !== col.field || this.sortOrder() === 0) {
@@ -11653,6 +12055,13 @@ class SdsTable {
11653
12055
  }
11654
12056
  return String(v);
11655
12057
  }
12058
+ /** Shared frame of the in-cell editors (text, select): height, radius, focus ring, error state. */
12059
+ editorClass(row, col) {
12060
+ const tone = this.cellErrorFor(row, col.field)
12061
+ ? 'border-danger ring-danger/25'
12062
+ : 'border-brand-500 ring-brand-500/25';
12063
+ return `h-9 w-full rounded-control border bg-surface text-sm text-ink outline-none ring-2 ${tone}`;
12064
+ }
11656
12065
  gridCellClass(row, col, r, c) {
11657
12066
  const align = ALIGN[col.align ?? 'left'];
11658
12067
  const editing = this.isEditing(r, c);
@@ -11992,7 +12401,7 @@ class SdsTable {
11992
12401
  : 'border-border bg-surface';
11993
12402
  }
11994
12403
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
11995
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsTable, isStandalone: true, selector: "sds-table", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, gridlines: { classPropertyName: "gridlines", publicName: "gridlines", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, sortable: { classPropertyName: "sortable", publicName: "sortable", isSignal: true, isRequired: false, transformFunction: null }, paginator: { classPropertyName: "paginator", publicName: "paginator", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageOptions: { classPropertyName: "rowsPerPageOptions", publicName: "rowsPerPageOptions", isSignal: true, isRequired: false, transformFunction: null }, showCurrentPageReport: { classPropertyName: "showCurrentPageReport", publicName: "showCurrentPageReport", isSignal: true, isRequired: false, transformFunction: null }, currentPageReportTemplate: { classPropertyName: "currentPageReportTemplate", publicName: "currentPageReportTemplate", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageLabel: { classPropertyName: "rowsPerPageLabel", publicName: "rowsPerPageLabel", isSignal: true, isRequired: false, transformFunction: null }, paginationLabel: { classPropertyName: "paginationLabel", publicName: "paginationLabel", isSignal: true, isRequired: false, transformFunction: null }, firstPageLabel: { classPropertyName: "firstPageLabel", publicName: "firstPageLabel", isSignal: true, isRequired: false, transformFunction: null }, previousPageLabel: { classPropertyName: "previousPageLabel", publicName: "previousPageLabel", isSignal: true, isRequired: false, transformFunction: null }, nextPageLabel: { classPropertyName: "nextPageLabel", publicName: "nextPageLabel", isSignal: true, isRequired: false, transformFunction: null }, lastPageLabel: { classPropertyName: "lastPageLabel", publicName: "lastPageLabel", isSignal: true, isRequired: false, transformFunction: null }, pageLinkLabel: { classPropertyName: "pageLinkLabel", publicName: "pageLinkLabel", isSignal: true, isRequired: false, transformFunction: null }, globalFilter: { classPropertyName: "globalFilter", publicName: "globalFilter", isSignal: true, isRequired: false, transformFunction: null }, globalFilterPlaceholder: { classPropertyName: "globalFilterPlaceholder", publicName: "globalFilterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, globalFilterAriaLabel: { classPropertyName: "globalFilterAriaLabel", publicName: "globalFilterAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, globalFilterFields: { classPropertyName: "globalFilterFields", publicName: "globalFilterFields", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, scrollHeight: { classPropertyName: "scrollHeight", publicName: "scrollHeight", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, totalRecords: { classPropertyName: "totalRecords", publicName: "totalRecords", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, resizableColumns: { classPropertyName: "resizableColumns", publicName: "resizableColumns", isSignal: true, isRequired: false, transformFunction: null }, reorderableColumns: { classPropertyName: "reorderableColumns", publicName: "reorderableColumns", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, editOn: { classPropertyName: "editOn", publicName: "editOn", isSignal: true, isRequired: false, transformFunction: null }, cellErrors: { classPropertyName: "cellErrors", publicName: "cellErrors", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, dirtyLabel: { classPropertyName: "dirtyLabel", publicName: "dirtyLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selection: "selectionChange", sortChange: "sortChange", pageChange: "pageChange", rowSelect: "rowSelect", rowUnselect: "rowUnselect", lazyLoad: "lazyLoad", rowClick: "rowClick", rowExpand: "rowExpand", rowCollapse: "rowCollapse", colReorder: "colReorder", cellCommit: "cellCommit" }, host: { classAttribute: "block" }, queries: [{ propertyName: "cellTemplates", predicate: SdsTableCell, isSignal: true }, { propertyName: "rowExpansion", first: true, predicate: SdsTableRowExpansion, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "numberEditor", first: true, predicate: SdsInputNumber, descendants: true, isSignal: true }], ngImport: i0, template: `
12404
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsTable, isStandalone: true, selector: "sds-table", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, gridlines: { classPropertyName: "gridlines", publicName: "gridlines", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, sortable: { classPropertyName: "sortable", publicName: "sortable", isSignal: true, isRequired: false, transformFunction: null }, paginator: { classPropertyName: "paginator", publicName: "paginator", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageOptions: { classPropertyName: "rowsPerPageOptions", publicName: "rowsPerPageOptions", isSignal: true, isRequired: false, transformFunction: null }, showCurrentPageReport: { classPropertyName: "showCurrentPageReport", publicName: "showCurrentPageReport", isSignal: true, isRequired: false, transformFunction: null }, currentPageReportTemplate: { classPropertyName: "currentPageReportTemplate", publicName: "currentPageReportTemplate", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageLabel: { classPropertyName: "rowsPerPageLabel", publicName: "rowsPerPageLabel", isSignal: true, isRequired: false, transformFunction: null }, paginationLabel: { classPropertyName: "paginationLabel", publicName: "paginationLabel", isSignal: true, isRequired: false, transformFunction: null }, firstPageLabel: { classPropertyName: "firstPageLabel", publicName: "firstPageLabel", isSignal: true, isRequired: false, transformFunction: null }, previousPageLabel: { classPropertyName: "previousPageLabel", publicName: "previousPageLabel", isSignal: true, isRequired: false, transformFunction: null }, nextPageLabel: { classPropertyName: "nextPageLabel", publicName: "nextPageLabel", isSignal: true, isRequired: false, transformFunction: null }, lastPageLabel: { classPropertyName: "lastPageLabel", publicName: "lastPageLabel", isSignal: true, isRequired: false, transformFunction: null }, pageLinkLabel: { classPropertyName: "pageLinkLabel", publicName: "pageLinkLabel", isSignal: true, isRequired: false, transformFunction: null }, globalFilter: { classPropertyName: "globalFilter", publicName: "globalFilter", isSignal: true, isRequired: false, transformFunction: null }, globalFilterPlaceholder: { classPropertyName: "globalFilterPlaceholder", publicName: "globalFilterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, globalFilterAriaLabel: { classPropertyName: "globalFilterAriaLabel", publicName: "globalFilterAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, globalFilterFields: { classPropertyName: "globalFilterFields", publicName: "globalFilterFields", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, scrollHeight: { classPropertyName: "scrollHeight", publicName: "scrollHeight", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, totalRecords: { classPropertyName: "totalRecords", publicName: "totalRecords", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, resizableColumns: { classPropertyName: "resizableColumns", publicName: "resizableColumns", isSignal: true, isRequired: false, transformFunction: null }, reorderableColumns: { classPropertyName: "reorderableColumns", publicName: "reorderableColumns", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, editOn: { classPropertyName: "editOn", publicName: "editOn", isSignal: true, isRequired: false, transformFunction: null }, cellErrors: { classPropertyName: "cellErrors", publicName: "cellErrors", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, dirtyLabel: { classPropertyName: "dirtyLabel", publicName: "dirtyLabel", isSignal: true, isRequired: false, transformFunction: null }, selectPlaceholder: { classPropertyName: "selectPlaceholder", publicName: "selectPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, selectAllLabel: { classPropertyName: "selectAllLabel", publicName: "selectAllLabel", isSignal: true, isRequired: false, transformFunction: null }, selectRowLabel: { classPropertyName: "selectRowLabel", publicName: "selectRowLabel", isSignal: true, isRequired: false, transformFunction: null }, selectionColumnLabel: { classPropertyName: "selectionColumnLabel", publicName: "selectionColumnLabel", isSignal: true, isRequired: false, transformFunction: null }, expandColumnLabel: { classPropertyName: "expandColumnLabel", publicName: "expandColumnLabel", isSignal: true, isRequired: false, transformFunction: null }, expandRowLabel: { classPropertyName: "expandRowLabel", publicName: "expandRowLabel", isSignal: true, isRequired: false, transformFunction: null }, collapseRowLabel: { classPropertyName: "collapseRowLabel", publicName: "collapseRowLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selection: "selectionChange", sortChange: "sortChange", pageChange: "pageChange", rowSelect: "rowSelect", rowUnselect: "rowUnselect", lazyLoad: "lazyLoad", rowClick: "rowClick", rowExpand: "rowExpand", rowCollapse: "rowCollapse", colReorder: "colReorder", cellCommit: "cellCommit" }, host: { classAttribute: "block" }, queries: [{ propertyName: "cellTemplates", predicate: SdsTableCell, isSignal: true }, { propertyName: "headerTemplates", predicate: SdsTableHeader, isSignal: true }, { propertyName: "rowExpansion", first: true, predicate: SdsTableRowExpansion, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "numberEditor", first: true, predicate: SdsInputNumber, descendants: true, isSignal: true }], ngImport: i0, template: `
11996
12405
  <div class="rounded-card border border-border bg-surface overflow-hidden">
11997
12406
  <!-- Toolbar: caption + global filter -->
11998
12407
  @if (caption() || globalFilter()) {
@@ -12057,7 +12466,7 @@ class SdsTable {
12057
12466
  [class.z-10]="scrollHeight()"
12058
12467
  [class.bg-muted]="scrollHeight()"
12059
12468
  >
12060
- <span class="sr-only">Détails</span>
12469
+ <span class="sr-only">{{ expandColumnLabel() }}</span>
12061
12470
  </th>
12062
12471
  }
12063
12472
 
@@ -12076,7 +12485,7 @@ class SdsTable {
12076
12485
  type="button"
12077
12486
  role="checkbox"
12078
12487
  [attr.aria-checked]="headerChecked() ? 'true' : (headerIndeterminate() ? 'mixed' : 'false')"
12079
- aria-label="Tout sélectionner"
12488
+ [attr.aria-label]="selectAllLabel()"
12080
12489
  [disabled]="loading()"
12081
12490
  class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
12082
12491
  [class]="checkboxClass(headerChecked(), headerIndeterminate())"
@@ -12089,7 +12498,7 @@ class SdsTable {
12089
12498
  }
12090
12499
  </button>
12091
12500
  } @else {
12092
- <span class="sr-only">Sélection</span>
12501
+ <span class="sr-only">{{ selectionColumnLabel() }}</span>
12093
12502
  }
12094
12503
  </th>
12095
12504
  }
@@ -12112,7 +12521,12 @@ class SdsTable {
12112
12521
  (drop)="onColDrop($event, i)"
12113
12522
  (dragend)="onColDragEnd()"
12114
12523
  >
12115
- @if (isColumnSortable(col)) {
12524
+ @if (headerTemplateFor(col.field); as htpl) {
12525
+ <ng-container
12526
+ [ngTemplateOutlet]="htpl"
12527
+ [ngTemplateOutletContext]="headerContext(col, i)"
12528
+ />
12529
+ } @else if (isColumnSortable(col)) {
12116
12530
  <button
12117
12531
  type="button"
12118
12532
  [disabled]="loading()"
@@ -12154,7 +12568,7 @@ class SdsTable {
12154
12568
  type="button"
12155
12569
  [attr.aria-expanded]="isExpanded(row)"
12156
12570
  [attr.aria-controls]="isExpanded(row) ? rowDetailId(row) : null"
12157
- [attr.aria-label]="isExpanded(row) ? 'Réduire la ligne' : 'Développer la ligne'"
12571
+ [attr.aria-label]="isExpanded(row) ? collapseRowLabel() : expandRowLabel()"
12158
12572
  [disabled]="loading()"
12159
12573
  class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded text-ink-soft hover:text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
12160
12574
  (click)="onExpanderClick($event, row)"
@@ -12179,7 +12593,7 @@ class SdsTable {
12179
12593
  type="button"
12180
12594
  role="checkbox"
12181
12595
  [attr.aria-checked]="isRowSelected(row) ? 'true' : 'false'"
12182
- aria-label="Sélectionner la ligne"
12596
+ [attr.aria-label]="selectRowLabel()"
12183
12597
  [disabled]="loading()"
12184
12598
  class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
12185
12599
  [class]="checkboxClass(isRowSelected(row), false)"
@@ -12194,7 +12608,7 @@ class SdsTable {
12194
12608
  type="button"
12195
12609
  role="radio"
12196
12610
  [attr.aria-checked]="isRowSelected(row) ? 'true' : 'false'"
12197
- aria-label="Sélectionner la ligne"
12611
+ [attr.aria-label]="selectRowLabel()"
12198
12612
  [disabled]="loading()"
12199
12613
  class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded-full border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
12200
12614
  [class]="checkboxClass(isRowSelected(row), false)"
@@ -12241,20 +12655,31 @@ class SdsTable {
12241
12655
  @if (isEditing(i, ci)) {
12242
12656
  @switch (col.editor) {
12243
12657
  @case ('select') {
12244
- <select
12245
- data-sds-cell-editor
12246
- class="h-9 w-full rounded-control border border-brand-500 bg-surface px-2 text-sm text-ink outline-none ring-2 ring-brand-500/25"
12247
- [attr.aria-label]="col.header"
12248
- (change)="onSelectEditorChange($event, col)"
12249
- (blur)="onEditorBlur()"
12250
- >
12251
- @if (draft() === null || draft() === undefined) {
12252
- <option value="" disabled selected>{{ col.placeholder ?? '' }}</option>
12253
- }
12254
- @for (opt of col.options ?? []; track $index; let oi = $index) {
12255
- <option [value]="oi" [selected]="opt.value === draft()">{{ opt.label }}</option>
12256
- }
12257
- </select>
12658
+ <!-- A native select (dependable inside a grid cell), dressed like the other editors:
12659
+ same height, radius, focus ring and padding, a library chevron, dark-mode popup. -->
12660
+ <div class="relative flex items-center">
12661
+ <select
12662
+ data-sds-cell-editor
12663
+ [class]="editorClass(row, col) + ' cursor-pointer appearance-none pl-2.5 pr-8 dark:scheme-dark'"
12664
+ [attr.aria-label]="col.header"
12665
+ [attr.aria-invalid]="cellErrorFor(row, col.field) ? 'true' : null"
12666
+ [attr.aria-describedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : null"
12667
+ (change)="onSelectEditorChange($event, col)"
12668
+ (blur)="onEditorBlur()"
12669
+ >
12670
+ @if (draft() === null || draft() === undefined) {
12671
+ <option value="" disabled selected>{{ col.placeholder ?? selectPlaceholder() }}</option>
12672
+ }
12673
+ @for (opt of col.options ?? []; track $index; let oi = $index) {
12674
+ <option [value]="oi" [selected]="opt.value === draft()">{{ opt.label }}</option>
12675
+ }
12676
+ </select>
12677
+ <sds-icon
12678
+ name="chevron-down"
12679
+ [size]="16"
12680
+ class="pointer-events-none absolute right-2.5 text-ink-soft"
12681
+ />
12682
+ </div>
12258
12683
  }
12259
12684
  @case ('number') {
12260
12685
  <sds-input-number
@@ -12269,6 +12694,8 @@ class SdsTable {
12269
12694
  [maxFractionDigits]="col.maxFractionDigits ?? null"
12270
12695
  [placeholder]="col.placeholder ?? ''"
12271
12696
  [ariaLabel]="col.header"
12697
+ [invalid]="!!cellErrorFor(row, col.field)"
12698
+ [ariaDescribedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : ''"
12272
12699
  (focusout)="onEditorBlur()"
12273
12700
  />
12274
12701
  }
@@ -12286,6 +12713,8 @@ class SdsTable {
12286
12713
  [maxFractionDigits]="col.maxFractionDigits ?? null"
12287
12714
  [placeholder]="col.placeholder ?? ''"
12288
12715
  [ariaLabel]="col.header"
12716
+ [invalid]="!!cellErrorFor(row, col.field)"
12717
+ [ariaDescribedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : ''"
12289
12718
  (focusout)="onEditorBlur()"
12290
12719
  />
12291
12720
  }
@@ -12293,10 +12722,12 @@ class SdsTable {
12293
12722
  <input
12294
12723
  data-sds-cell-editor
12295
12724
  type="text"
12296
- class="h-9 w-full rounded-control border border-brand-500 bg-surface px-2.5 text-sm text-ink outline-none ring-2 ring-brand-500/25 placeholder:text-ink-faint"
12725
+ [class]="editorClass(row, col) + ' px-2.5 placeholder:text-ink-faint'"
12297
12726
  [value]="draftText()"
12298
12727
  [placeholder]="col.placeholder ?? ''"
12299
12728
  [attr.aria-label]="col.header"
12729
+ [attr.aria-invalid]="cellErrorFor(row, col.field) ? 'true' : null"
12730
+ [attr.aria-describedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : null"
12300
12731
  (input)="onTextEditorInput($event)"
12301
12732
  (blur)="onEditorBlur()"
12302
12733
  />
@@ -12396,7 +12827,7 @@ class SdsTable {
12396
12827
  </div>
12397
12828
  }
12398
12829
  </div>
12399
- `, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }, { kind: "component", type: SdsPaginator, selector: "sds-paginator", inputs: ["totalRecords", "first", "rows", "rowsPerPageOptions", "pageLinkSize", "showFirstLastIcon", "showPageLinks", "showCurrentPageReport", "currentPageReportTemplate", "showJumpToPageInput", "rowsPerPageLabel", "jumpToPageLabel", "paginationLabel", "firstPageLabel", "previousPageLabel", "nextPageLabel", "lastPageLabel", "pageLinkLabel", "jumpToPageAriaLabel", "size", "disabled"], outputs: ["firstChange", "rowsChange", "pageChange"] }, { kind: "component", type: SdsInputNumber, selector: "sds-input-number", inputs: ["label", "ariaLabel", "placeholder", "hint", "error", "size", "appearance", "disabled", "readonly", "mode", "locale", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "min", "max", "step", "showButtons", "buttonLayout", "incrementIcon", "decrementIcon", "allowEmpty", "clearable", "clearLabel", "incrementLabel", "decrementLabel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
12830
+ `, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }, { kind: "component", type: SdsPaginator, selector: "sds-paginator", inputs: ["totalRecords", "first", "rows", "rowsPerPageOptions", "pageLinkSize", "showFirstLastIcon", "showPageLinks", "showCurrentPageReport", "currentPageReportTemplate", "showJumpToPageInput", "rowsPerPageLabel", "jumpToPageLabel", "paginationLabel", "firstPageLabel", "previousPageLabel", "nextPageLabel", "lastPageLabel", "pageLinkLabel", "jumpToPageAriaLabel", "size", "disabled"], outputs: ["firstChange", "rowsChange", "pageChange"] }, { kind: "component", type: SdsInputNumber, selector: "sds-input-number", inputs: ["label", "ariaLabel", "placeholder", "hint", "error", "invalid", "ariaDescribedby", "size", "appearance", "disabled", "readonly", "mode", "locale", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "min", "max", "step", "showButtons", "buttonLayout", "incrementIcon", "decrementIcon", "allowEmpty", "clearable", "clearLabel", "incrementLabel", "decrementLabel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
12400
12831
  }
12401
12832
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTable, decorators: [{
12402
12833
  type: Component,
@@ -12470,7 +12901,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12470
12901
  [class.z-10]="scrollHeight()"
12471
12902
  [class.bg-muted]="scrollHeight()"
12472
12903
  >
12473
- <span class="sr-only">Détails</span>
12904
+ <span class="sr-only">{{ expandColumnLabel() }}</span>
12474
12905
  </th>
12475
12906
  }
12476
12907
 
@@ -12489,7 +12920,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12489
12920
  type="button"
12490
12921
  role="checkbox"
12491
12922
  [attr.aria-checked]="headerChecked() ? 'true' : (headerIndeterminate() ? 'mixed' : 'false')"
12492
- aria-label="Tout sélectionner"
12923
+ [attr.aria-label]="selectAllLabel()"
12493
12924
  [disabled]="loading()"
12494
12925
  class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
12495
12926
  [class]="checkboxClass(headerChecked(), headerIndeterminate())"
@@ -12502,7 +12933,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12502
12933
  }
12503
12934
  </button>
12504
12935
  } @else {
12505
- <span class="sr-only">Sélection</span>
12936
+ <span class="sr-only">{{ selectionColumnLabel() }}</span>
12506
12937
  }
12507
12938
  </th>
12508
12939
  }
@@ -12525,7 +12956,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12525
12956
  (drop)="onColDrop($event, i)"
12526
12957
  (dragend)="onColDragEnd()"
12527
12958
  >
12528
- @if (isColumnSortable(col)) {
12959
+ @if (headerTemplateFor(col.field); as htpl) {
12960
+ <ng-container
12961
+ [ngTemplateOutlet]="htpl"
12962
+ [ngTemplateOutletContext]="headerContext(col, i)"
12963
+ />
12964
+ } @else if (isColumnSortable(col)) {
12529
12965
  <button
12530
12966
  type="button"
12531
12967
  [disabled]="loading()"
@@ -12567,7 +13003,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12567
13003
  type="button"
12568
13004
  [attr.aria-expanded]="isExpanded(row)"
12569
13005
  [attr.aria-controls]="isExpanded(row) ? rowDetailId(row) : null"
12570
- [attr.aria-label]="isExpanded(row) ? 'Réduire la ligne' : 'Développer la ligne'"
13006
+ [attr.aria-label]="isExpanded(row) ? collapseRowLabel() : expandRowLabel()"
12571
13007
  [disabled]="loading()"
12572
13008
  class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded text-ink-soft hover:text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
12573
13009
  (click)="onExpanderClick($event, row)"
@@ -12592,7 +13028,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12592
13028
  type="button"
12593
13029
  role="checkbox"
12594
13030
  [attr.aria-checked]="isRowSelected(row) ? 'true' : 'false'"
12595
- aria-label="Sélectionner la ligne"
13031
+ [attr.aria-label]="selectRowLabel()"
12596
13032
  [disabled]="loading()"
12597
13033
  class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
12598
13034
  [class]="checkboxClass(isRowSelected(row), false)"
@@ -12607,7 +13043,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12607
13043
  type="button"
12608
13044
  role="radio"
12609
13045
  [attr.aria-checked]="isRowSelected(row) ? 'true' : 'false'"
12610
- aria-label="Sélectionner la ligne"
13046
+ [attr.aria-label]="selectRowLabel()"
12611
13047
  [disabled]="loading()"
12612
13048
  class="grid h-[18px] w-[18px] shrink-0 place-items-center rounded-full border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 disabled:opacity-60"
12613
13049
  [class]="checkboxClass(isRowSelected(row), false)"
@@ -12654,20 +13090,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12654
13090
  @if (isEditing(i, ci)) {
12655
13091
  @switch (col.editor) {
12656
13092
  @case ('select') {
12657
- <select
12658
- data-sds-cell-editor
12659
- class="h-9 w-full rounded-control border border-brand-500 bg-surface px-2 text-sm text-ink outline-none ring-2 ring-brand-500/25"
12660
- [attr.aria-label]="col.header"
12661
- (change)="onSelectEditorChange($event, col)"
12662
- (blur)="onEditorBlur()"
12663
- >
12664
- @if (draft() === null || draft() === undefined) {
12665
- <option value="" disabled selected>{{ col.placeholder ?? '' }}</option>
12666
- }
12667
- @for (opt of col.options ?? []; track $index; let oi = $index) {
12668
- <option [value]="oi" [selected]="opt.value === draft()">{{ opt.label }}</option>
12669
- }
12670
- </select>
13093
+ <!-- A native select (dependable inside a grid cell), dressed like the other editors:
13094
+ same height, radius, focus ring and padding, a library chevron, dark-mode popup. -->
13095
+ <div class="relative flex items-center">
13096
+ <select
13097
+ data-sds-cell-editor
13098
+ [class]="editorClass(row, col) + ' cursor-pointer appearance-none pl-2.5 pr-8 dark:scheme-dark'"
13099
+ [attr.aria-label]="col.header"
13100
+ [attr.aria-invalid]="cellErrorFor(row, col.field) ? 'true' : null"
13101
+ [attr.aria-describedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : null"
13102
+ (change)="onSelectEditorChange($event, col)"
13103
+ (blur)="onEditorBlur()"
13104
+ >
13105
+ @if (draft() === null || draft() === undefined) {
13106
+ <option value="" disabled selected>{{ col.placeholder ?? selectPlaceholder() }}</option>
13107
+ }
13108
+ @for (opt of col.options ?? []; track $index; let oi = $index) {
13109
+ <option [value]="oi" [selected]="opt.value === draft()">{{ opt.label }}</option>
13110
+ }
13111
+ </select>
13112
+ <sds-icon
13113
+ name="chevron-down"
13114
+ [size]="16"
13115
+ class="pointer-events-none absolute right-2.5 text-ink-soft"
13116
+ />
13117
+ </div>
12671
13118
  }
12672
13119
  @case ('number') {
12673
13120
  <sds-input-number
@@ -12682,6 +13129,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12682
13129
  [maxFractionDigits]="col.maxFractionDigits ?? null"
12683
13130
  [placeholder]="col.placeholder ?? ''"
12684
13131
  [ariaLabel]="col.header"
13132
+ [invalid]="!!cellErrorFor(row, col.field)"
13133
+ [ariaDescribedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : ''"
12685
13134
  (focusout)="onEditorBlur()"
12686
13135
  />
12687
13136
  }
@@ -12699,6 +13148,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12699
13148
  [maxFractionDigits]="col.maxFractionDigits ?? null"
12700
13149
  [placeholder]="col.placeholder ?? ''"
12701
13150
  [ariaLabel]="col.header"
13151
+ [invalid]="!!cellErrorFor(row, col.field)"
13152
+ [ariaDescribedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : ''"
12702
13153
  (focusout)="onEditorBlur()"
12703
13154
  />
12704
13155
  }
@@ -12706,10 +13157,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12706
13157
  <input
12707
13158
  data-sds-cell-editor
12708
13159
  type="text"
12709
- class="h-9 w-full rounded-control border border-brand-500 bg-surface px-2.5 text-sm text-ink outline-none ring-2 ring-brand-500/25 placeholder:text-ink-faint"
13160
+ [class]="editorClass(row, col) + ' px-2.5 placeholder:text-ink-faint'"
12710
13161
  [value]="draftText()"
12711
13162
  [placeholder]="col.placeholder ?? ''"
12712
13163
  [attr.aria-label]="col.header"
13164
+ [attr.aria-invalid]="cellErrorFor(row, col.field) ? 'true' : null"
13165
+ [attr.aria-describedby]="cellErrorFor(row, col.field) ? cellErrorId(i, ci) : null"
12713
13166
  (input)="onTextEditorInput($event)"
12714
13167
  (blur)="onEditorBlur()"
12715
13168
  />
@@ -12811,7 +13264,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12811
13264
  </div>
12812
13265
  `,
12813
13266
  }]
12814
- }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], gridlines: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridlines", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], sortable: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortable", required: false }] }], paginator: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginator", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], rowsPerPageOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageOptions", required: false }] }], showCurrentPageReport: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCurrentPageReport", required: false }] }], currentPageReportTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPageReportTemplate", required: false }] }], rowsPerPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageLabel", required: false }] }], paginationLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationLabel", required: false }] }], firstPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstPageLabel", required: false }] }], previousPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousPageLabel", required: false }] }], nextPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextPageLabel", required: false }] }], lastPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "lastPageLabel", required: false }] }], pageLinkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageLinkLabel", required: false }] }], globalFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilter", required: false }] }], globalFilterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterPlaceholder", required: false }] }], globalFilterAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterAriaLabel", required: false }] }], globalFilterFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterFields", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }, { type: i0.Output, args: ["selectionChange"] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], scrollHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollHeight", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], resizableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizableColumns", required: false }] }], reorderableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderableColumns", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], editOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "editOn", required: false }] }], cellErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellErrors", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], dirtyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirtyLabel", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], rowSelect: [{ type: i0.Output, args: ["rowSelect"] }], rowUnselect: [{ type: i0.Output, args: ["rowUnselect"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowExpand: [{ type: i0.Output, args: ["rowExpand"] }], rowCollapse: [{ type: i0.Output, args: ["rowCollapse"] }], colReorder: [{ type: i0.Output, args: ["colReorder"] }], cellCommit: [{ type: i0.Output, args: ["cellCommit"] }], cellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SdsTableCell), { isSignal: true }] }], rowExpansion: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsTableRowExpansion), { isSignal: true }] }], numberEditor: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SdsInputNumber), { isSignal: true }] }] } });
13267
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], gridlines: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridlines", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], sortable: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortable", required: false }] }], paginator: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginator", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], rowsPerPageOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageOptions", required: false }] }], showCurrentPageReport: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCurrentPageReport", required: false }] }], currentPageReportTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPageReportTemplate", required: false }] }], rowsPerPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageLabel", required: false }] }], paginationLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationLabel", required: false }] }], firstPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstPageLabel", required: false }] }], previousPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousPageLabel", required: false }] }], nextPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextPageLabel", required: false }] }], lastPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "lastPageLabel", required: false }] }], pageLinkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageLinkLabel", required: false }] }], globalFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilter", required: false }] }], globalFilterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterPlaceholder", required: false }] }], globalFilterAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterAriaLabel", required: false }] }], globalFilterFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalFilterFields", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }, { type: i0.Output, args: ["selectionChange"] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], scrollHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollHeight", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], resizableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizableColumns", required: false }] }], reorderableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderableColumns", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], editOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "editOn", required: false }] }], cellErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellErrors", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], dirtyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirtyLabel", required: false }] }], selectPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectPlaceholder", required: false }] }], selectAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllLabel", required: false }] }], selectRowLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectRowLabel", required: false }] }], selectionColumnLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionColumnLabel", required: false }] }], expandColumnLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandColumnLabel", required: false }] }], expandRowLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandRowLabel", required: false }] }], collapseRowLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseRowLabel", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], rowSelect: [{ type: i0.Output, args: ["rowSelect"] }], rowUnselect: [{ type: i0.Output, args: ["rowUnselect"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowExpand: [{ type: i0.Output, args: ["rowExpand"] }], rowCollapse: [{ type: i0.Output, args: ["rowCollapse"] }], colReorder: [{ type: i0.Output, args: ["colReorder"] }], cellCommit: [{ type: i0.Output, args: ["cellCommit"] }], cellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SdsTableCell), { isSignal: true }] }], headerTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SdsTableHeader), { isSignal: true }] }], rowExpansion: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdsTableRowExpansion), { isSignal: true }] }], numberEditor: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SdsInputNumber), { isSignal: true }] }] } });
12815
13268
 
12816
13269
  /**
12817
13270
  * A tiny transient-notification bus. Application code calls {@link success} / {@link error} / {@link info}
@@ -12823,7 +13276,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12823
13276
  *
12824
13277
  * ```ts
12825
13278
  * private readonly toasts = inject(SdsToastService);
12826
- * this.toasts.success('Enregistré.');
13279
+ * this.toasts.success('Saved.');
12827
13280
  * ```
12828
13281
  *
12829
13282
  * Mount the host once (e.g. in the shell): `<sds-toast-host />`.
@@ -12873,10 +13326,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
12873
13326
  class SdsToastHost {
12874
13327
  toasts = inject(SdsToastService);
12875
13328
  /**
12876
- * Accessible name for each toast's close button. French default so existing consumers are unchanged; the
12877
- * button is icon-only, so an app serving more than one language MUST translate it.
13329
+ * Accessible name for each toast's close button. English default; the button is icon-only, so an app
13330
+ * serving more than one language MUST translate it.
12878
13331
  */
12879
- closeLabel = input('Fermer', ...(ngDevMode ? [{ debugName: "closeLabel" }] : []));
13332
+ closeLabel = input('Close', ...(ngDevMode ? [{ debugName: "closeLabel" }] : []));
12880
13333
  errors = computed(() => this.toasts.toasts().filter((t) => t.kind === 'error'), ...(ngDevMode ? [{ debugName: "errors" }] : []));
12881
13334
  notices = computed(() => this.toasts.toasts().filter((t) => t.kind !== 'error'), ...(ngDevMode ? [{ debugName: "notices" }] : []));
12882
13335
  icon(kind) {
@@ -13059,11 +13512,11 @@ class SdsThemeToggle {
13059
13512
  /** `surface` for light/glass bars, `on-brand` for the dark brand bar. */
13060
13513
  appearance = input('surface', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
13061
13514
  /**
13062
- * Accessible names for the two actions. French defaults keep existing consumers unchanged; a
13063
- * multilingual app must pass translated values.
13515
+ * Accessible names for the two actions. English defaults; a multilingual app must pass translated
13516
+ * values.
13064
13517
  */
13065
- darkLabel = input('Passer en mode sombre', ...(ngDevMode ? [{ debugName: "darkLabel" }] : []));
13066
- lightLabel = input('Passer en mode clair', ...(ngDevMode ? [{ debugName: "lightLabel" }] : []));
13518
+ darkLabel = input('Switch to dark mode', ...(ngDevMode ? [{ debugName: "darkLabel" }] : []));
13519
+ lightLabel = input('Switch to light mode', ...(ngDevMode ? [{ debugName: "lightLabel" }] : []));
13067
13520
  iconSize = computed(() => Math.round(this.size() * 0.5), ...(ngDevMode ? [{ debugName: "iconSize" }] : []));
13068
13521
  label = computed(() => (this.isDark() ? this.lightLabel() : this.darkLabel()), ...(ngDevMode ? [{ debugName: "label" }] : []));
13069
13522
  buttonClasses = computed(() => this.appearance() === 'on-brand'
@@ -13204,11 +13657,10 @@ class SdsTopbar {
13204
13657
  /** Show the mobile hamburger that toggles the sidebar drawer (< lg). */
13205
13658
  menuButton = input(true, ...(ngDevMode ? [{ debugName: "menuButton", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
13206
13659
  /**
13207
- * Accessible name for the hamburger. Defaults to French so nothing changes for existing consumers,
13208
- * but any app serving more than one language MUST pass a translated value — an icon-only control's
13209
- * aria-label is its only name, and a hardcoded one is simply wrong in every other locale.
13660
+ * Accessible name for the hamburger. English default; any app serving more than one language MUST
13661
+ * pass a translated value — an icon-only control's aria-label is its only name.
13210
13662
  */
13211
- menuLabel = input('Ouvrir le menu', ...(ngDevMode ? [{ debugName: "menuLabel" }] : []));
13663
+ menuLabel = input('Open menu', ...(ngDevMode ? [{ debugName: "menuLabel" }] : []));
13212
13664
  /**
13213
13665
  * `brand` (default) paints the gradient and the wave; `surface` is white on a hairline border;
13214
13666
  * `glass` is a translucent, brand-tinted bar with a backdrop blur.
@@ -13549,7 +14001,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
13549
14001
  * @example
13550
14002
  * <sds-sidebar appearance="surface" decorations>
13551
14003
  * <sds-nav-group label="Membres">
13552
- * <sds-nav-item icon="user-plus" label="Créer un membre" link="/membres/new" />
14004
+ * <sds-nav-item icon="user-plus" label="Add a member" link="/members/new" />
13553
14005
  * </sds-nav-group>
13554
14006
  * <div sdsFooter>…</div>
13555
14007
  * </sds-sidebar>
@@ -13589,12 +14041,12 @@ class SdsSidebar {
13589
14041
  });
13590
14042
  }
13591
14043
  /**
13592
- * Accessible names for the rail's three icon-only controls. French defaults keep existing consumers
13593
- * unchanged; a multilingual app must pass translated values.
14044
+ * Accessible names for the rail's three icon-only controls. English defaults; a multilingual app
14045
+ * must pass translated values.
13594
14046
  */
13595
- collapseLabel = input('Replier le menu', ...(ngDevMode ? [{ debugName: "collapseLabel" }] : []));
13596
- expandLabel = input('Déplier le menu', ...(ngDevMode ? [{ debugName: "expandLabel" }] : []));
13597
- closeLabel = input('Fermer le menu', ...(ngDevMode ? [{ debugName: "closeLabel" }] : []));
14047
+ collapseLabel = input('Collapse menu', ...(ngDevMode ? [{ debugName: "collapseLabel" }] : []));
14048
+ expandLabel = input('Expand menu', ...(ngDevMode ? [{ debugName: "expandLabel" }] : []));
14049
+ closeLabel = input('Close menu', ...(ngDevMode ? [{ debugName: "closeLabel" }] : []));
13598
14050
  /** `brand` (default) is the dark rail; `surface` is a light rail with brand accents. */
13599
14051
  appearance = input('brand', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
13600
14052
  /** Add slow-drifting brand-tinted blobs behind the rail (opt-in). */
@@ -14246,8 +14698,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
14246
14698
  * @example
14247
14699
  * <sds-user-menu name="Souhail AIT SAID" email="souhail@example.com" status="online" appearance="surface">
14248
14700
  * <sds-menu-item icon="user" label="Profil" link="/profile" />
14249
- * <sds-menu-item icon="settings" label="Paramètres" link="/settings" />
14250
- * <sds-menu-item icon="log-out" label="Se déconnecter" tone="danger" (select)="signOut()" />
14701
+ * <sds-menu-item icon="settings" label="Settings" link="/settings" />
14702
+ * <sds-menu-item icon="log-out" label="Sign out" tone="danger" (select)="signOut()" />
14251
14703
  * </sds-user-menu>
14252
14704
  */
14253
14705
  class SdsUserMenu {
@@ -14269,7 +14721,7 @@ class SdsUserMenu {
14269
14721
  /** Override the trigger avatar's initials background; defaults per appearance. */
14270
14722
  avatarBgClass = input(null, ...(ngDevMode ? [{ debugName: "avatarBgClass" }] : []));
14271
14723
  /** Accessible name for the trigger (icon/avatar only when details are hidden). */
14272
- menuLabel = input('Menu du compte', ...(ngDevMode ? [{ debugName: "menuLabel" }] : []));
14724
+ menuLabel = input('Account menu', ...(ngDevMode ? [{ debugName: "menuLabel" }] : []));
14273
14725
  openChange = output();
14274
14726
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
14275
14727
  toggle() {
@@ -14465,7 +14917,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
14465
14917
  * @example
14466
14918
  * <sds-menu-item icon="user" label="Profil" link="/profile" /> <!-- in-app route -->
14467
14919
  * <sds-menu-item icon="external-link" label="Site public" href="https://…" target="_blank" />
14468
- * <sds-menu-item icon="log-out" label="Se déconnecter" tone="danger" (select)="signOut()" />
14920
+ * <sds-menu-item icon="log-out" label="Sign out" tone="danger" (select)="signOut()" />
14469
14921
  */
14470
14922
  class SdsMenuItem {
14471
14923
  icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : []));
@@ -14593,7 +15045,7 @@ class SdsSearchCommand {
14593
15045
  /** The searchable entries. Order is preserved; when the field is empty they show as quick navigation. */
14594
15046
  items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
14595
15047
  /** Placeholder on the trigger pill and the search field. */
14596
- placeholder = input('Rechercher…', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
15048
+ placeholder = input('Search…', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
14597
15049
  /** Show the built-in trigger pill. Turn off to drive the palette from your own control (`cmd.open()`). */
14598
15050
  showTrigger = input(true, ...(ngDevMode ? [{ debugName: "showTrigger", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
14599
15051
  /** Enable the global ⌘K / Ctrl-K shortcut. */
@@ -14603,15 +15055,15 @@ class SdsSearchCommand {
14603
15055
  /** `surface` (default) for a light / glass bar; `on-brand` for the dark brand bar. */
14604
15056
  appearance = input('surface', ...(ngDevMode ? [{ debugName: "appearance" }] : []));
14605
15057
  /**
14606
- * User-facing copy. French defaults; a multilingual app passes translated values (the trigger and the
14607
- * field share `placeholder`, and `searchLabel` is the accessible name for both).
15058
+ * User-facing copy. English defaults; a multilingual app passes translated values (the trigger and
15059
+ * the field share `placeholder`, and `searchLabel` is the accessible name for both).
14608
15060
  */
14609
- searchLabel = input('Rechercher', ...(ngDevMode ? [{ debugName: "searchLabel" }] : []));
14610
- clearLabel = input('Effacer', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
14611
- emptyLabel = input('Aucun résultat', ...(ngDevMode ? [{ debugName: "emptyLabel" }] : []));
14612
- selectHint = input('Sélectionner', ...(ngDevMode ? [{ debugName: "selectHint" }] : []));
14613
- navigateHint = input('Naviguer', ...(ngDevMode ? [{ debugName: "navigateHint" }] : []));
14614
- closeHint = input('Fermer', ...(ngDevMode ? [{ debugName: "closeHint" }] : []));
15061
+ searchLabel = input('Search', ...(ngDevMode ? [{ debugName: "searchLabel" }] : []));
15062
+ clearLabel = input('Clear', ...(ngDevMode ? [{ debugName: "clearLabel" }] : []));
15063
+ emptyLabel = input('No results', ...(ngDevMode ? [{ debugName: "emptyLabel" }] : []));
15064
+ selectHint = input('Select', ...(ngDevMode ? [{ debugName: "selectHint" }] : []));
15065
+ navigateHint = input('Navigate', ...(ngDevMode ? [{ debugName: "navigateHint" }] : []));
15066
+ closeHint = input('Close', ...(ngDevMode ? [{ debugName: "closeHint" }] : []));
14615
15067
  select = output();
14616
15068
  openChange = output();
14617
15069
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
@@ -15085,8 +15537,8 @@ class SdsLanguageSwitcher {
15085
15537
  /** `up` prefers opening the panel above the trigger — for a switcher near the bottom of the page. */
15086
15538
  direction = input('down', ...(ngDevMode ? [{ debugName: "direction" }] : []));
15087
15539
  /** Accessible name for the trigger and panel. */
15088
- menuLabel = input('Choisir la langue', ...(ngDevMode ? [{ debugName: "menuLabel" }] : []));
15089
- /** Optional visible header above the list (e.g. "Langue"). Omitted when empty. */
15540
+ menuLabel = input('Choose language', ...(ngDevMode ? [{ debugName: "menuLabel" }] : []));
15541
+ /** Optional visible header above the list (e.g. "Language"). Omitted when empty. */
15090
15542
  heading = input('', ...(ngDevMode ? [{ debugName: "heading" }] : []));
15091
15543
  openChange = output();
15092
15544
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
@@ -15450,5 +15902,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
15450
15902
  * Generated bundle index. Do not edit.
15451
15903
  */
15452
15904
 
15453
- export { SDS_ALLERGENS, SDS_ALLERGEN_ICONS, SDS_ALLERGEN_LABELS_EN, SDS_ICONS, SDS_PHONE_COUNTRIES, SdsAccordion, SdsAccordionContent, SdsAccordionHeader, SdsAccordionPanel, SdsAccordionStore, SdsAllergenIcon, SdsAvatar, SdsBadge, SdsBulkBar, SdsButton, SdsCalendar, SdsCard, SdsCheckbox, SdsChecklistRow, SdsDatePicker, SdsFileDrop, SdsIcon, SdsImageCropper, SdsInput, SdsInputNumber, SdsLanguageSwitcher, SdsLocalizedInput, SdsMenu, SdsMenuItem, SdsMenuTrigger, SdsMultiSelect, SdsNavGroup, SdsNavItem, SdsOtpInput, SdsPaginator, SdsPhoneInput, SdsRadio, SdsScore, SdsSearchCommand, SdsSegmented, SdsSelect, SdsSelectEmpty, SdsSelectFooter, SdsSelectOption, SdsShell, SdsSidebar, SdsSortableHandle, SdsSortableItem, SdsSortableList, SdsStatusTile, SdsTab, SdsTabList, SdsTabPanel, SdsTabPanels, SdsTable, SdsTableCell, SdsTableRowExpansion, SdsTabs, SdsTabsStore, SdsTextarea, SdsThemeService, SdsThemeToggle, SdsToastHost, SdsToastService, SdsToggleSwitch, SdsTopbar, SdsTriStateChip, SdsUserMenu, SidebarStore, addDays, addMonths, addMonthsKeepDay, formatDdMmYyyy, formatHhMm, isOutOfRange, isSameDay, isoDay, pad2, sdsFileMatchesAccept, sdsFormatBytes, sdsFormatNational, sdsMatchDialCode, sdsNormalizeSignificant, startOfDay, startOfMonth };
15905
+ export { SDS_ALLERGENS, SDS_ALLERGEN_ICONS, SDS_ALLERGEN_LABELS_EN, SDS_ICONS, SDS_PHONE_COUNTRIES, SdsAccordion, SdsAccordionContent, SdsAccordionHeader, SdsAccordionPanel, SdsAccordionStore, SdsAllergenIcon, SdsAvatar, SdsBadge, SdsBulkBar, SdsButton, SdsCalendar, SdsCard, SdsCheckbox, SdsChecklistRow, SdsDatePicker, SdsFileDrop, SdsIcon, SdsImageCropper, SdsInput, SdsInputNumber, SdsLanguageSwitcher, SdsLocalizedInput, SdsMenu, SdsMenuItem, SdsMenuTrigger, SdsMultiSelect, SdsNavGroup, SdsNavItem, SdsOtpInput, SdsPaginator, SdsPhoneInput, SdsRadio, SdsScore, SdsSearchCommand, SdsSegmented, SdsSelect, SdsSelectEmpty, SdsSelectFooter, SdsSelectOption, SdsShell, SdsSidebar, SdsSortableHandle, SdsSortableItem, SdsSortableList, SdsStatusTile, SdsTab, SdsTabList, SdsTabPanel, SdsTabPanels, SdsTable, SdsTableCell, SdsTableHeader, SdsTableRowExpansion, SdsTabs, SdsTabsStore, SdsTextarea, SdsThemeService, SdsThemeToggle, SdsToastHost, SdsToastService, SdsToggleSwitch, SdsTopbar, SdsTriStateChip, SdsUserMenu, SidebarStore, addDays, addMonths, addMonthsKeepDay, formatDdMmYyyy, formatHhMm, isOutOfRange, isSameDay, isoDay, pad2, sdsFileMatchesAccept, sdsFormatBytes, sdsFormatNational, sdsMatchDialCode, sdsNormalizeSignificant, startOfDay, startOfMonth };
15454
15906
  //# sourceMappingURL=besaitech-ng-design-system.mjs.map