@besaitech/ng-design-system 0.0.50 → 0.0.52

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, ElementRef, model, Injector, afterNextRender, TemplateRef, Directive, contentChild, Injectable, contentChildren, untracked, DestroyRef } from '@angular/core';
2
+ import { inject, input, computed, ChangeDetectionStrategy, Component, booleanAttribute, isDevMode, effect, numberAttribute, output, signal, forwardRef, viewChild, viewChildren, afterRenderEffect, model, ElementRef, Injector, afterNextRender, TemplateRef, Directive, contentChild, Injectable, contentChildren, untracked, DestroyRef } 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';
@@ -108,6 +108,27 @@ const SDS_ICONS = {
108
108
  'search-x': '<path d="m13.5 8.5-5 5"/><path d="m8.5 8.5 5 5"/><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>',
109
109
  command: '<path d="M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3"/>',
110
110
  sparkles: '<path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/><path d="M20 3v4"/><path d="M22 5h-4"/><path d="M4 17v2"/><path d="M5 18H3"/>',
111
+ // A question mark in a circle: the "may contain" mark on sds-tri-state-chip, and a generic help glyph.
112
+ 'circle-help': '<circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/>',
113
+ // Stock / inventory (the kitchen stock board, the sold-out toolkit). Original glyph: three stacked boxes.
114
+ stock: '<rect x="3" y="13" width="8" height="8" rx="1"/><rect x="13" y="13" width="8" height="8" rx="1"/><rect x="8" y="3" width="8" height="8" rx="1"/><path d="M6 13v2.5h2V13"/><path d="M16 13v2.5h2V13"/><path d="M11 3v2.5h2V3"/>',
115
+ // The 14 EU allergens of Regulation (EU) 1169/2011 Annex II, in Annex order. Original Belvigo drawings
116
+ // (Lucide has none), same grammar as the rest of the set: 24x24, stroke only, 2px, round caps/joins.
117
+ // Names mirror the API enum (CEREALS_GLUTEN -> allergen-cereals-gluten); sds-allergen-icon maps them.
118
+ 'allergen-cereals-gluten': '<path d="M12 22V8"/><path d="M12 8c-1.6-1.6-1.6-4.2 0-6 1.6 1.8 1.6 4.4 0 6z"/><path d="M12 13c-2.6 0-4.6-1.6-5.2-4.2 2.6 0 4.6 1.6 5.2 4.2z"/><path d="M12 13c2.6 0 4.6-1.6 5.2-4.2-2.6 0-4.6 1.6-5.2 4.2z"/><path d="M12 18c-2.6 0-4.6-1.6-5.2-4.2 2.6 0 4.6 1.6 5.2 4.2z"/><path d="M12 18c2.6 0 4.6-1.6 5.2-4.2-2.6 0-4.6 1.6-5.2 4.2z"/>',
119
+ 'allergen-crustaceans': '<ellipse cx="12" cy="15" rx="6" ry="4"/><path d="M3.5 4a2.5 2.5 0 1 0 5 0"/><path d="M15.5 4a2.5 2.5 0 1 0 5 0"/><path d="M6 6.5 8.5 11.8"/><path d="M18 6.5 15.5 11.8"/><path d="M6 15H3"/><path d="M18 15h3"/><path d="M7.3 17.5 4.5 20"/><path d="M16.7 17.5 19.5 20"/><path d="M10.5 11.2V9.5"/><path d="M13.5 11.2V9.5"/>',
120
+ 'allergen-eggs': '<path d="M12 2.5c-3.6 0-6.5 5.5-6.5 10.5a6.5 6.5 0 0 0 13 0c0-5-2.9-10.5-6.5-10.5z"/><path d="M9 13.5a3 3 0 0 0 2.5 3"/>',
121
+ 'allergen-fish': '<path d="M2.5 12c2-3.5 5-5.5 8.5-5.5 3 0 5.5 2 7 5.5-1.5 3.5-4 5.5-7 5.5-3.5 0-6.5-2-8.5-5.5z"/><path d="M18 12l3.5-3.5v7z"/><path d="M10 9a4.5 4.5 0 0 1 0 6"/><path d="M6.5 11h.01"/>',
122
+ 'allergen-peanuts': '<path d="M8.8 12a5 5 0 1 1 6.4 0 5 5 0 1 1-6.4 0z"/><path d="M10.5 6.5h.01"/><path d="M13.5 8.5h.01"/><path d="M10.5 15.5h.01"/><path d="M13.5 17.5h.01"/>',
123
+ 'allergen-soybeans': '<path d="M15.88 3.88 3.88 15.88a3 3 0 0 0 4.24 4.24L20.12 8.12a3 3 0 0 0-4.24-4.24z"/><circle cx="8.5" cy="15.5" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="15.5" cy="8.5" r="1.5"/><path d="M20.5 3.5 22 2"/>',
124
+ 'allergen-milk': '<path d="M6 10v10.5A1.5 1.5 0 0 0 7.5 22h9a1.5 1.5 0 0 0 1.5-1.5V10"/><path d="M6 10l3-5h6l3 5z"/><path d="M9 5V2.5h6V5"/><path d="M12 13.5c-1 1.3-1.5 2.1-1.5 2.8a1.5 1.5 0 0 0 3 0c0-.7-.5-1.5-1.5-2.8z"/>',
125
+ 'allergen-nuts': '<path d="M5 9.5C5 6.5 8 4 12 4s7 2.5 7 5.5z"/><path d="M6.5 9.5v1.5c0 4.5 2.5 8.5 5.5 10 3-1.5 5.5-5.5 5.5-10V9.5"/><path d="M12 4c0-1 .5-1.7 1.5-2"/>',
126
+ 'allergen-celery': '<path d="M7 22c-.8-4-.5-8.5 1-12.5h8c1.5 4 1.8 8.5 1 12.5z"/><path d="M10.5 22c-.3-4-.2-8.5.5-12.5"/><path d="M13.5 22c.3-4 .2-8.5-.5-12.5"/><path d="M9.5 9.5 7.5 6.5"/><path d="M12 9.5V5"/><path d="M14.5 9.5l2-3"/><circle cx="6.5" cy="5" r="1.5"/><circle cx="12" cy="3.5" r="1.5"/><circle cx="17.5" cy="5" r="1.5"/>',
127
+ 'allergen-mustard': '<rect x="5" y="7" width="14" height="3" rx="1"/><path d="M6 10v8.5A3.5 3.5 0 0 0 9.5 22h5a3.5 3.5 0 0 0 3.5-3.5V10"/><path d="M13.5 7l3-4.5"/><rect x="9" y="13" width="6" height="5" rx="1"/>',
128
+ 'allergen-sesame': '<path d="M7 3c1.2 1.2 1.8 2.5 1.8 3.5a1.8 1.8 0 0 1-3.6 0C5.2 5.5 5.8 4.2 7 3z" transform="rotate(-25 7 6)"/><path d="M16.5 3.5c1.2 1.2 1.8 2.5 1.8 3.5a1.8 1.8 0 0 1-3.6 0c0-1 .6-2.3 1.8-3.5z" transform="rotate(30 16.5 6.5)"/><path d="M8.5 13c1.2 1.2 1.8 2.5 1.8 3.5a1.8 1.8 0 0 1-3.6 0c0-1 .6-2.3 1.8-3.5z" transform="rotate(15 8.5 16)"/><path d="M17 12c1.2 1.2 1.8 2.5 1.8 3.5a1.8 1.8 0 0 1-3.6 0c0-1 .6-2.3 1.8-3.5z" transform="rotate(-20 17 15)"/>',
129
+ 'allergen-sulphites': '<path d="M7.5 3h9c.3 1.5.5 3 .5 4.5a5 5 0 0 1-10 0c0-1.5.2-3 .5-4.5z"/><path d="M12 12.5V21"/><path d="M8.5 21h7"/><path d="M7.2 7h9.6"/>',
130
+ 'allergen-lupin': '<path d="M12 2.5a1.7 1.7 0 0 1 1.2 3 1.8 1.8 0 0 1 .8 3 1.9 1.9 0 0 1 .8 3 2 2 0 0 1-.3 2.8H9.5a2 2 0 0 1-.3-2.8 1.9 1.9 0 0 1 .8-3 1.8 1.8 0 0 1 .8-3 1.7 1.7 0 0 1 1.2-3z"/><path d="M10.8 8.5h2.4"/><path d="M10.2 11.5h3.6"/><path d="M12 14.3V22"/><path d="M12 19.5 7 17.5"/><path d="M12 19.5 8.5 16"/><path d="M12 19.5l5-2"/><path d="M12 19.5l3.5-3.5"/>',
131
+ 'allergen-molluscs': '<path d="M12 19 4.5 11a7.5 7.5 0 0 1 15 0z"/><path d="M12 19V3.5"/><path d="M12 19 7.2 5.2"/><path d="M12 19l4.8-13.8"/><path d="M9.5 22 12 19l2.5 3z"/>',
111
132
  };
112
133
 
113
134
  const SIZE_PX = { sm: 16, md: 20, lg: 24, xl: 32 };
@@ -163,12 +184,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
163
184
  const BASE = 'inline-flex items-center justify-center gap-2 font-medium ' +
164
185
  'transition-colors duration-150 select-none whitespace-nowrap cursor-pointer ' +
165
186
  'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 ' +
166
- 'focus-visible:ring-brand-500 disabled:opacity-50 disabled:pointer-events-none';
187
+ 'focus-visible:ring-offset-surface focus-visible:ring-brand-500 ' +
188
+ 'disabled:opacity-50 disabled:pointer-events-none';
189
+ /**
190
+ * Dark mode has its own fills. A monochrome brand's dark 600 step is a mid-dark grey: as a primary fill
191
+ * it read as disabled, and at `disabled:opacity-50` the real disabled state looked the same. So the dark
192
+ * primary is the inverted light fill (`ink` on `surface`); tertiary and ghost swap their black/brand-50
193
+ * tints for white ones, which show on a dark surface.
194
+ */
167
195
  const VARIANTS$2 = {
168
- primary: 'bg-brand-600 text-white shadow-sm hover:bg-brand-700 active:bg-brand-800',
196
+ primary: 'bg-brand-600 text-white shadow-sm hover:bg-brand-700 active:bg-brand-800 ' +
197
+ 'dark:bg-ink dark:text-surface dark:hover:bg-ink/90 dark:active:bg-ink/80',
169
198
  secondary: 'bg-surface text-ink border border-border shadow-sm hover:bg-muted active:bg-brand-50',
170
- tertiary: 'bg-brand-50 text-brand-700 hover:bg-brand-100 active:bg-brand-200/70',
171
- ghost: 'bg-transparent text-ink-soft hover:bg-black/5 active:bg-black/10',
199
+ tertiary: 'bg-brand-50 text-brand-700 hover:bg-brand-100 active:bg-brand-200/70 ' +
200
+ 'dark:bg-white/10 dark:text-ink dark:hover:bg-white/15 dark:active:bg-white/20',
201
+ ghost: 'bg-transparent text-ink-soft hover:bg-black/5 active:bg-black/10 ' +
202
+ 'dark:hover:bg-white/10 dark:active:bg-white/15',
172
203
  danger: 'bg-danger text-white shadow-sm hover:brightness-95 active:brightness-90',
173
204
  };
174
205
  const SIZES$b = {
@@ -283,7 +314,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
283
314
  `, styles: [".sds-spinner{width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:9999px;animation:sds-spin .6s linear infinite}@keyframes sds-spin{to{transform:rotate(360deg)}}\n"] }]
284
315
  }], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
285
316
 
286
- let nextId$f = 0;
317
+ let nextId$g = 0;
287
318
  const SIZES$a = {
288
319
  sm: 'h-9 text-sm',
289
320
  md: 'h-10 text-sm',
@@ -296,7 +327,7 @@ const SIZES$a = {
296
327
  * sidebar search field).
297
328
  */
298
329
  class SdsInput {
299
- inputId = `sds-input-${nextId$f++}`;
330
+ inputId = `sds-input-${nextId$g++}`;
300
331
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
301
332
  /** Accessible name used when no visible [label] is provided. */
302
333
  ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
@@ -629,7 +660,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
629
660
  `, styles: ["input:-webkit-autofill,input:-webkit-autofill:hover,input:-webkit-autofill:focus,input:-webkit-autofill:active{transition:background-color 100000s ease-in-out 0s;-webkit-text-fill-color:currentColor;caret-color:currentColor}\n"] }]
630
661
  }], propDecorators: { 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 }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], leadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "leadingIcon", required: false }] }], trailingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingIcon", required: false }] }], trailingAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingAction", required: false }] }], trailingActionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingActionLabel", required: false }] }], trailingActionPressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingActionPressed", required: false }] }], trailingActionClick: [{ type: i0.Output, args: ["trailingActionClick"] }] } });
631
662
 
632
- let nextId$e = 0;
663
+ let nextId$f = 0;
633
664
  const HEIGHTS = {
634
665
  sm: 'h-9',
635
666
  md: 'h-10',
@@ -652,7 +683,7 @@ const TEXT = {
652
683
  * {@link min}/{@link max} on blur and on every spinner step; ArrowUp / ArrowDown also step it.
653
684
  */
654
685
  class SdsInputNumber {
655
- inputId = `sds-input-number-${nextId$e++}`;
686
+ inputId = `sds-input-number-${nextId$f++}`;
656
687
  fieldRef = viewChild('field', ...(ngDevMode ? [{ debugName: "fieldRef" }] : []));
657
688
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
658
689
  /** Accessible name used when no visible [label] is provided. */
@@ -1359,7 +1390,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
1359
1390
  }]
1360
1391
  }], 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 }] }] } });
1361
1392
 
1362
- let nextId$d = 0;
1393
+ let nextId$e = 0;
1363
1394
  const SIZES$9 = {
1364
1395
  sm: 'min-h-9 text-sm',
1365
1396
  md: 'min-h-10 text-sm',
@@ -1379,7 +1410,7 @@ const SIZES$9 = {
1379
1410
  * `<sds-localized-input [languages]="['fr','nl','en']" [(ngModel)]="title" />`.
1380
1411
  */
1381
1412
  class SdsLocalizedInput {
1382
- inputId = `sds-localized-input-${nextId$d++}`;
1413
+ inputId = `sds-localized-input-${nextId$e++}`;
1383
1414
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
1384
1415
  hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
1385
1416
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
@@ -1635,7 +1666,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
1635
1666
  }]
1636
1667
  }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], languages: [{ type: i0.Input, args: [{ isSignal: true, alias: "languages", required: false }] }], currentLanguage: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentLanguage", required: false }] }], multiline: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiline", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], languageSwitcherLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "languageSwitcherLabel", required: false }] }], untranslatedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "untranslatedLabel", required: false }] }] } });
1637
1668
 
1638
- let nextId$c = 0;
1669
+ let nextId$d = 0;
1639
1670
  const SIZES$8 = {
1640
1671
  md: 'h-12 w-11 text-lg',
1641
1672
  lg: 'h-14 w-12 text-xl',
@@ -1652,7 +1683,7 @@ const SIZES$8 = {
1652
1683
  * first box and have it land correctly.
1653
1684
  */
1654
1685
  class SdsOtpInput {
1655
- groupId = `sds-otp-${nextId$c++}`;
1686
+ groupId = `sds-otp-${nextId$d++}`;
1656
1687
  /** How many boxes / characters the code has. */
1657
1688
  length = input(6, ...(ngDevMode ? [{ debugName: "length", transform: numberAttribute }] : [{ transform: numberAttribute }]));
1658
1689
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
@@ -1952,7 +1983,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
1952
1983
  }]
1953
1984
  }], ctorParameters: () => [], propDecorators: { length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", 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 }] }], inputMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputMode", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], autoFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoFocus", required: false }] }], cellLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellLabel", required: false }] }], completed: [{ type: i0.Output, args: ["completed"] }], cells: [{ type: i0.ViewChildren, args: ['cell', { isSignal: true }] }] } });
1954
1985
 
1955
- let nextId$b = 0;
1986
+ let nextId$c = 0;
1956
1987
  const SIZES$7 = {
1957
1988
  sm: 'text-sm px-3 py-2',
1958
1989
  md: 'text-sm px-3.5 py-2.5',
@@ -1964,7 +1995,7 @@ const SIZES$7 = {
1964
1995
  * [(ngModel)].
1965
1996
  */
1966
1997
  class SdsTextarea {
1967
- fieldId = `sds-textarea-${nextId$b++}`;
1998
+ fieldId = `sds-textarea-${nextId$c++}`;
1968
1999
  field = viewChild('field', ...(ngDevMode ? [{ debugName: "field" }] : []));
1969
2000
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
1970
2001
  /** Accessible name used when no visible [label] is provided. */
@@ -2217,7 +2248,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2217
2248
  }]
2218
2249
  }], 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 }] }] } });
2219
2250
 
2220
- let nextId$a = 0;
2251
+ let nextId$b = 0;
2221
2252
  const SIZES$6 = {
2222
2253
  sm: { track: 'h-5 w-9', knob: 'h-4 w-4', on: 'translate-x-4', icon: 11 },
2223
2254
  md: { track: 'h-6 w-11', knob: 'h-5 w-5', on: 'translate-x-5', icon: 13 },
@@ -2230,7 +2261,7 @@ const SIZES$6 = {
2230
2261
  * states.
2231
2262
  */
2232
2263
  class SdsToggleSwitch {
2233
- fieldId = `sds-toggle-switch-${nextId$a++}`;
2264
+ fieldId = `sds-toggle-switch-${nextId$b++}`;
2234
2265
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
2235
2266
  /** Accessible name used when no visible [label] is provided. */
2236
2267
  ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
@@ -2474,7 +2505,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2474
2505
  }]
2475
2506
  }], ctorParameters: () => [], 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 }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], trueValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "trueValue", required: false }] }], falseValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "falseValue", required: false }] }], onIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "onIcon", required: false }] }], offIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "offIcon", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }] } });
2476
2507
 
2477
- let nextId$9 = 0;
2508
+ let nextId$a = 0;
2478
2509
  /**
2479
2510
  * Boolean checkbox. Implements ControlValueAccessor — use with reactive forms
2480
2511
  * or `[(ngModel)]`. Renders a styled box (brand-filled with a check when on)
@@ -2486,7 +2517,7 @@ let nextId$9 = 0;
2486
2517
  * <sds-checkbox label="Fusion automatique" [(ngModel)]="autoMerge" />
2487
2518
  */
2488
2519
  class SdsCheckbox {
2489
- id = `sds-checkbox-${nextId$9++}`;
2520
+ id = `sds-checkbox-${nextId$a++}`;
2490
2521
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
2491
2522
  /** Accessible name used when no visible [label] is provided. */
2492
2523
  ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
@@ -2620,7 +2651,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2620
2651
  }]
2621
2652
  }], 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 }] }] } });
2622
2653
 
2623
- let nextId$8 = 0;
2654
+ let nextId$9 = 0;
2624
2655
  /**
2625
2656
  * Mounted radios by group name. A pick updates the rest of its group, because a native radio says
2626
2657
  * nothing when the browser unchecks it — without this a reactive form would leave the old choice drawn.
@@ -2646,7 +2677,7 @@ const groups = new Map();
2646
2677
  * <sds-radio name="size" value="large" label="Grand" [(ngModel)]="size" />
2647
2678
  */
2648
2679
  class SdsRadio {
2649
- id = `sds-radio-${nextId$8++}`;
2680
+ id = `sds-radio-${nextId$9++}`;
2650
2681
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
2651
2682
  /** Accessible name used when no visible [label] is provided. */
2652
2683
  ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
@@ -3008,6 +3039,372 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
3008
3039
  }]
3009
3040
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], padding: [{ type: i0.Input, args: [{ isSignal: true, alias: "padding", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }] } });
3010
3041
 
3042
+ /** Every allergen in Annex II order — iterate it to render a declaration grid of 14. */
3043
+ const SDS_ALLERGENS = [
3044
+ 'CEREALS_GLUTEN',
3045
+ 'CRUSTACEANS',
3046
+ 'EGGS',
3047
+ 'FISH',
3048
+ 'PEANUTS',
3049
+ 'SOYBEANS',
3050
+ 'MILK',
3051
+ 'NUTS',
3052
+ 'CELERY',
3053
+ 'MUSTARD',
3054
+ 'SESAME',
3055
+ 'SULPHITES',
3056
+ 'LUPIN',
3057
+ 'MOLLUSCS',
3058
+ ];
3059
+ /** Registry icon for each allergen. */
3060
+ const SDS_ALLERGEN_ICONS = {
3061
+ CEREALS_GLUTEN: 'allergen-cereals-gluten',
3062
+ CRUSTACEANS: 'allergen-crustaceans',
3063
+ EGGS: 'allergen-eggs',
3064
+ FISH: 'allergen-fish',
3065
+ PEANUTS: 'allergen-peanuts',
3066
+ SOYBEANS: 'allergen-soybeans',
3067
+ MILK: 'allergen-milk',
3068
+ NUTS: 'allergen-nuts',
3069
+ CELERY: 'allergen-celery',
3070
+ MUSTARD: 'allergen-mustard',
3071
+ SESAME: 'allergen-sesame',
3072
+ SULPHITES: 'allergen-sulphites',
3073
+ LUPIN: 'allergen-lupin',
3074
+ MOLLUSCS: 'allergen-molluscs',
3075
+ };
3076
+ /**
3077
+ * English names, as a fallback and for the showcase. An app serving more than one language passes its
3078
+ * own translated name through [label] — the library never picks a language for you.
3079
+ */
3080
+ const SDS_ALLERGEN_LABELS_EN = {
3081
+ CEREALS_GLUTEN: 'Cereals containing gluten',
3082
+ CRUSTACEANS: 'Crustaceans',
3083
+ EGGS: 'Eggs',
3084
+ FISH: 'Fish',
3085
+ PEANUTS: 'Peanuts',
3086
+ SOYBEANS: 'Soybeans',
3087
+ MILK: 'Milk',
3088
+ NUTS: 'Nuts',
3089
+ CELERY: 'Celery',
3090
+ MUSTARD: 'Mustard',
3091
+ SESAME: 'Sesame',
3092
+ SULPHITES: 'Sulphites',
3093
+ LUPIN: 'Lupin',
3094
+ MOLLUSCS: 'Molluscs',
3095
+ };
3096
+ /** Accepts the enum spelling, and tolerates `milk` / `cereals-gluten` so a hand-typed value still resolves. */
3097
+ function normalize(value) {
3098
+ if (!value)
3099
+ return null;
3100
+ const key = String(value).trim().toUpperCase().replace(/-/g, '_');
3101
+ return key in SDS_ALLERGEN_ICONS ? key : null;
3102
+ }
3103
+ /**
3104
+ * The pictogram for one EU allergen, taking the API enum value directly. With a [label] it is an image
3105
+ * with that accessible name (role="img"); without one it is decorative (aria-hidden), for when visible
3106
+ * text beside it already names the allergen.
3107
+ *
3108
+ * @example
3109
+ * <sds-allergen-icon allergen="MILK" label="Milk" />
3110
+ * <sds-allergen-icon [allergen]="a" [size]="16" /> <!-- decorative: text next to it names it -->
3111
+ */
3112
+ class SdsAllergenIcon {
3113
+ /** The allergen, as the API enum value (`MILK`, `CEREALS_GLUTEN`, …). */
3114
+ allergen = input.required(...(ngDevMode ? [{ debugName: "allergen" }] : []));
3115
+ /** Accessible name. Empty (default) = decorative, hidden from assistive tech. */
3116
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
3117
+ /** Also show the [label] as a native tooltip on hover. */
3118
+ showTitle = input(false, ...(ngDevMode ? [{ debugName: "showTitle", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
3119
+ /** Square size: a pixel number, a numeric string, or a keyword (sm·md·lg·xl). */
3120
+ size = input(20, ...(ngDevMode ? [{ debugName: "size" }] : []));
3121
+ /** Stroke width of the line icon. */
3122
+ strokeWidth = input(2, ...(ngDevMode ? [{ debugName: "strokeWidth" }] : []));
3123
+ iconName = computed(() => {
3124
+ const key = normalize(this.allergen());
3125
+ return key ? SDS_ALLERGEN_ICONS[key] : null;
3126
+ }, ...(ngDevMode ? [{ debugName: "iconName" }] : []));
3127
+ constructor() {
3128
+ if (isDevMode()) {
3129
+ effect(() => {
3130
+ if (!this.iconName()) {
3131
+ console.warn(`sds-allergen-icon: unknown allergen "${this.allergen()}".`);
3132
+ }
3133
+ });
3134
+ }
3135
+ }
3136
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsAllergenIcon, deps: [], target: i0.ɵɵFactoryTarget.Component });
3137
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsAllergenIcon, isStandalone: true, selector: "sds-allergen-icon", inputs: { allergen: { classPropertyName: "allergen", publicName: "allergen", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, showTitle: { classPropertyName: "showTitle", publicName: "showTitle", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.role": "label() ? \"img\" : null", "attr.aria-label": "label() || null", "attr.aria-hidden": "label() ? null : \"true\"", "attr.title": "showTitle() && label() ? label() : null" }, classAttribute: "inline-flex shrink-0" }, ngImport: i0, template: `
3138
+ @if (iconName(); as name) {
3139
+ <sds-icon [name]="name" [size]="size()" [strokeWidth]="strokeWidth()" />
3140
+ }
3141
+ `, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3142
+ }
3143
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsAllergenIcon, decorators: [{
3144
+ type: Component,
3145
+ args: [{
3146
+ selector: 'sds-allergen-icon',
3147
+ changeDetection: ChangeDetectionStrategy.OnPush,
3148
+ imports: [SdsIcon],
3149
+ host: {
3150
+ class: 'inline-flex shrink-0',
3151
+ '[attr.role]': 'label() ? "img" : null',
3152
+ '[attr.aria-label]': 'label() || null',
3153
+ '[attr.aria-hidden]': 'label() ? null : "true"',
3154
+ '[attr.title]': 'showTitle() && label() ? label() : null',
3155
+ },
3156
+ template: `
3157
+ @if (iconName(); as name) {
3158
+ <sds-icon [name]="name" [size]="size()" [strokeWidth]="strokeWidth()" />
3159
+ }
3160
+ `,
3161
+ }]
3162
+ }], ctorParameters: () => [], propDecorators: { allergen: [{ type: i0.Input, args: [{ isSignal: true, alias: "allergen", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], showTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTitle", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }] } });
3163
+
3164
+ /** Activation order: none → contains → may-contain → none. */
3165
+ const ORDER = ['none', 'contains', 'may-contain'];
3166
+ let nextId$8 = 0;
3167
+ /**
3168
+ * A chip that cycles through three states — `none`, `contains`, `may-contain` — built for the 14-tile
3169
+ * allergen declaration grid, but generic (any "no / yes / maybe" declaration).
3170
+ *
3171
+ * **The state never relies on colour alone.** Each state has its own border (thin solid · thick solid
3172
+ * and filled · thick dashed), its own mark (none · a check · a question mark), a visible state caption
3173
+ * (turn off with `showState`), and the state text is part of the button's accessible name.
3174
+ *
3175
+ * Interaction: click, Enter or Space moves to the next state; Shift+Enter / Shift+Space moves back;
3176
+ * Delete or Backspace resets to `none`. A polite live region announces the new state after a change.
3177
+ * The value is a two-way `model` — bind `[(value)]`.
3178
+ *
3179
+ * All visible and spoken text comes from inputs with English defaults; pass translated labels.
3180
+ *
3181
+ * @example
3182
+ * <sds-tri-state-chip label="Milk" icon="allergen-milk" [(value)]="state.MILK"
3183
+ * containsLabel="Contains" mayContainLabel="May contain" noneLabel="Not present" />
3184
+ */
3185
+ class SdsTriStateChip {
3186
+ chipId = `sds-tri-state-chip-${nextId$8++}`;
3187
+ /** Current state. Two-way: `[(value)]`. */
3188
+ value = model('none', ...(ngDevMode ? [{ debugName: "value" }] : []));
3189
+ /** Visible name (e.g. the allergen). Required — the chip has no other accessible name. */
3190
+ label = input.required(...(ngDevMode ? [{ debugName: "label" }] : []));
3191
+ /** Optional leading registry icon, e.g. an `allergen-*` pictogram. */
3192
+ icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : []));
3193
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
3194
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
3195
+ /** Show the state as a small visible caption under the label. */
3196
+ showState = input(true, ...(ngDevMode ? [{ debugName: "showState", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
3197
+ /** State text for `none` (visible caption and spoken). */
3198
+ noneLabel = input('Not present', ...(ngDevMode ? [{ debugName: "noneLabel" }] : []));
3199
+ /** State text for `contains`. */
3200
+ containsLabel = input('Contains', ...(ngDevMode ? [{ debugName: "containsLabel" }] : []));
3201
+ /** State text for `may-contain`. */
3202
+ mayContainLabel = input('May contain', ...(ngDevMode ? [{ debugName: "mayContainLabel" }] : []));
3203
+ /**
3204
+ * Optional usage hint read after the name, e.g. "Press to change". Off by default: a button that
3205
+ * announces its state and changes on activation is self-explanatory to most users.
3206
+ */
3207
+ hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
3208
+ /** Last user-driven change, spoken by the live region. Programmatic writes stay silent. */
3209
+ announcement = signal('', ...(ngDevMode ? [{ debugName: "announcement" }] : []));
3210
+ stateText = computed(() => this.textFor(this.value()), ...(ngDevMode ? [{ debugName: "stateText" }] : []));
3211
+ chipClass = computed(() => {
3212
+ const sm = this.size() === 'sm';
3213
+ const base = 'relative flex w-full min-w-0 cursor-pointer select-none items-center rounded-control border-2 ' +
3214
+ 'text-left transition-colors focus-visible:outline-none focus-visible:ring-2 ' +
3215
+ 'focus-visible:ring-brand-500 focus-visible:ring-offset-2 focus-visible:ring-offset-surface ' +
3216
+ 'disabled:cursor-not-allowed disabled:opacity-60 ' +
3217
+ (sm ? 'min-h-9 gap-2 px-2 py-1' : 'min-h-12 gap-2.5 px-3 py-2');
3218
+ switch (this.value()) {
3219
+ case 'contains':
3220
+ // Filled + solid thick border + check. In dark mode a monochrome brand-600 is a dim grey, so the
3221
+ // fill inverts to ink/surface (the same rule as sds-toggle-switch and sds-button primary).
3222
+ return (`${base} border-brand-600 bg-brand-600 text-white ` +
3223
+ 'dark:border-ink dark:bg-ink dark:text-surface hover:bg-brand-700 dark:hover:bg-ink-soft');
3224
+ case 'may-contain':
3225
+ // Unfilled + DASHED thick border + question mark.
3226
+ return (`${base} border-dashed border-brand-600 bg-brand-50 text-ink ` +
3227
+ 'dark:border-ink-soft dark:bg-muted hover:bg-brand-100 dark:hover:bg-surface');
3228
+ default:
3229
+ return `${base} border-border bg-surface text-ink-soft hover:border-ink-faint hover:text-ink`;
3230
+ }
3231
+ }, ...(ngDevMode ? [{ debugName: "chipClass" }] : []));
3232
+ captionClass = computed(() => {
3233
+ switch (this.value()) {
3234
+ case 'contains':
3235
+ return 'text-white/85 dark:text-surface/85';
3236
+ case 'may-contain':
3237
+ return 'text-ink-soft';
3238
+ default:
3239
+ return 'text-ink-faint';
3240
+ }
3241
+ }, ...(ngDevMode ? [{ debugName: "captionClass" }] : []));
3242
+ onClick(event) {
3243
+ if (this.disabled())
3244
+ return;
3245
+ // A real Shift+click steps back too; keyboard activation is handled in onKeydown.
3246
+ this.step(event.shiftKey ? -1 : 1);
3247
+ }
3248
+ onKeydown(event) {
3249
+ if (this.disabled())
3250
+ return;
3251
+ if ((event.key === 'Enter' || event.key === ' ') && event.shiftKey) {
3252
+ // Handle it here so the native button click (always "forward") does not also fire.
3253
+ event.preventDefault();
3254
+ this.step(-1);
3255
+ }
3256
+ else if (event.key === 'Delete' || event.key === 'Backspace') {
3257
+ event.preventDefault();
3258
+ this.set('none');
3259
+ }
3260
+ }
3261
+ step(delta) {
3262
+ const i = ORDER.indexOf(this.value());
3263
+ const next = ORDER[(Math.max(0, i) + delta + ORDER.length) % ORDER.length];
3264
+ this.set(next);
3265
+ }
3266
+ set(next) {
3267
+ if (next === this.value())
3268
+ return;
3269
+ this.value.set(next);
3270
+ this.announcement.set(`${this.label()}: ${this.textFor(next)}`);
3271
+ }
3272
+ textFor(state) {
3273
+ switch (state) {
3274
+ case 'contains':
3275
+ return this.containsLabel();
3276
+ case 'may-contain':
3277
+ return this.mayContainLabel();
3278
+ default:
3279
+ return this.noneLabel();
3280
+ }
3281
+ }
3282
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTriStateChip, deps: [], target: i0.ɵɵFactoryTarget.Component });
3283
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsTriStateChip, isStandalone: true, selector: "sds-tri-state-chip", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", 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 }, showState: { classPropertyName: "showState", publicName: "showState", isSignal: true, isRequired: false, transformFunction: null }, noneLabel: { classPropertyName: "noneLabel", publicName: "noneLabel", isSignal: true, isRequired: false, transformFunction: null }, containsLabel: { classPropertyName: "containsLabel", publicName: "containsLabel", isSignal: true, isRequired: false, transformFunction: null }, mayContainLabel: { classPropertyName: "mayContainLabel", publicName: "mayContainLabel", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { classAttribute: "inline-flex min-w-0" }, ngImport: i0, template: `
3284
+ <button
3285
+ type="button"
3286
+ [id]="chipId"
3287
+ [class]="chipClass()"
3288
+ [disabled]="disabled()"
3289
+ [attr.data-state]="value()"
3290
+ [attr.aria-describedby]="hint() ? chipId + '-hint' : null"
3291
+ (click)="onClick($event)"
3292
+ (keydown)="onKeydown($event)"
3293
+ >
3294
+ @if (icon()) {
3295
+ <sds-icon [name]="icon()!" [size]="size() === 'sm' ? 18 : 22" class="shrink-0" />
3296
+ }
3297
+
3298
+ <span class="flex min-w-0 flex-1 flex-col text-left leading-tight">
3299
+ <!-- Up to two lines, so "Cereals containing gluten" stays readable in a narrow grid cell. -->
3300
+ <span
3301
+ class="line-clamp-2 break-words font-semibold"
3302
+ [class]="size() === 'sm' ? 'text-xs' : 'text-sm'"
3303
+ >{{ label() }}</span
3304
+ >
3305
+ @if (showState()) {
3306
+ <span
3307
+ class="truncate text-[11px] font-medium"
3308
+ [class]="captionClass()"
3309
+ aria-hidden="true"
3310
+ >{{ stateText() }}</span
3311
+ >
3312
+ }
3313
+ </span>
3314
+ <!-- The state is part of the accessible name ("Milk, may contain"), visible caption or not. -->
3315
+ <span class="sr-only">, {{ stateText() }}</span>
3316
+
3317
+ <!-- Non-colour mark: nothing / a check / a question mark. The slot keeps its width in every
3318
+ state so the chip never shifts when cycled. -->
3319
+ <span
3320
+ class="grid shrink-0 place-items-center"
3321
+ [class]="size() === 'sm' ? 'h-4 w-4' : 'h-5 w-5'"
3322
+ aria-hidden="true"
3323
+ >
3324
+ @switch (value()) {
3325
+ @case ('contains') {
3326
+ <sds-icon name="check" [size]="size() === 'sm' ? 14 : 18" [strokeWidth]="3" />
3327
+ }
3328
+ @case ('may-contain') {
3329
+ <sds-icon name="circle-help" [size]="size() === 'sm' ? 15 : 19" />
3330
+ }
3331
+ }
3332
+ </span>
3333
+ </button>
3334
+
3335
+ @if (hint()) {
3336
+ <span [id]="chipId + '-hint'" class="sr-only">{{ hint() }}</span>
3337
+ }
3338
+ <span class="sr-only" aria-live="polite" aria-atomic="true">{{ announcement() }}</span>
3339
+ `, isInline: true, dependencies: [{ kind: "component", type: SdsIcon, selector: "sds-icon", inputs: ["name", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3340
+ }
3341
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsTriStateChip, decorators: [{
3342
+ type: Component,
3343
+ args: [{
3344
+ selector: 'sds-tri-state-chip',
3345
+ changeDetection: ChangeDetectionStrategy.OnPush,
3346
+ imports: [SdsIcon],
3347
+ host: { class: 'inline-flex min-w-0' },
3348
+ template: `
3349
+ <button
3350
+ type="button"
3351
+ [id]="chipId"
3352
+ [class]="chipClass()"
3353
+ [disabled]="disabled()"
3354
+ [attr.data-state]="value()"
3355
+ [attr.aria-describedby]="hint() ? chipId + '-hint' : null"
3356
+ (click)="onClick($event)"
3357
+ (keydown)="onKeydown($event)"
3358
+ >
3359
+ @if (icon()) {
3360
+ <sds-icon [name]="icon()!" [size]="size() === 'sm' ? 18 : 22" class="shrink-0" />
3361
+ }
3362
+
3363
+ <span class="flex min-w-0 flex-1 flex-col text-left leading-tight">
3364
+ <!-- Up to two lines, so "Cereals containing gluten" stays readable in a narrow grid cell. -->
3365
+ <span
3366
+ class="line-clamp-2 break-words font-semibold"
3367
+ [class]="size() === 'sm' ? 'text-xs' : 'text-sm'"
3368
+ >{{ label() }}</span
3369
+ >
3370
+ @if (showState()) {
3371
+ <span
3372
+ class="truncate text-[11px] font-medium"
3373
+ [class]="captionClass()"
3374
+ aria-hidden="true"
3375
+ >{{ stateText() }}</span
3376
+ >
3377
+ }
3378
+ </span>
3379
+ <!-- The state is part of the accessible name ("Milk, may contain"), visible caption or not. -->
3380
+ <span class="sr-only">, {{ stateText() }}</span>
3381
+
3382
+ <!-- Non-colour mark: nothing / a check / a question mark. The slot keeps its width in every
3383
+ state so the chip never shifts when cycled. -->
3384
+ <span
3385
+ class="grid shrink-0 place-items-center"
3386
+ [class]="size() === 'sm' ? 'h-4 w-4' : 'h-5 w-5'"
3387
+ aria-hidden="true"
3388
+ >
3389
+ @switch (value()) {
3390
+ @case ('contains') {
3391
+ <sds-icon name="check" [size]="size() === 'sm' ? 14 : 18" [strokeWidth]="3" />
3392
+ }
3393
+ @case ('may-contain') {
3394
+ <sds-icon name="circle-help" [size]="size() === 'sm' ? 15 : 19" />
3395
+ }
3396
+ }
3397
+ </span>
3398
+ </button>
3399
+
3400
+ @if (hint()) {
3401
+ <span [id]="chipId + '-hint'" class="sr-only">{{ hint() }}</span>
3402
+ }
3403
+ <span class="sr-only" aria-live="polite" aria-atomic="true">{{ announcement() }}</span>
3404
+ `,
3405
+ }]
3406
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], showState: [{ type: i0.Input, args: [{ isSignal: true, alias: "showState", required: false }] }], noneLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noneLabel", required: false }] }], containsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "containsLabel", required: false }] }], mayContainLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "mayContainLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }] } });
3407
+
3011
3408
  /** Small, dependency-free date helpers (day-granularity, local time). */
3012
3409
  function startOfDay(d) {
3013
3410
  return new Date(d.getFullYear(), d.getMonth(), d.getDate());
@@ -11537,5 +11934,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
11537
11934
  * Generated bundle index. Do not edit.
11538
11935
  */
11539
11936
 
11540
- export { SDS_ICONS, SDS_PHONE_COUNTRIES, SdsAccordion, SdsAccordionContent, SdsAccordionHeader, SdsAccordionPanel, SdsAccordionStore, SdsAvatar, SdsBadge, SdsButton, SdsCalendar, SdsCard, SdsCheckbox, SdsDatePicker, SdsIcon, SdsInput, SdsInputNumber, SdsLanguageSwitcher, SdsLocalizedInput, SdsMenuItem, SdsMultiSelect, SdsNavGroup, SdsNavItem, SdsOtpInput, SdsPaginator, SdsPhoneInput, SdsRadio, SdsSearchCommand, SdsSelect, SdsSelectEmpty, SdsSelectFooter, SdsSelectOption, SdsShell, SdsSidebar, SdsTab, SdsTabList, SdsTabPanel, SdsTabPanels, SdsTable, SdsTableCell, SdsTableRowExpansion, SdsTabs, SdsTabsStore, SdsTextarea, SdsThemeService, SdsThemeToggle, SdsToastHost, SdsToastService, SdsToggleSwitch, SdsTopbar, SdsUserMenu, SidebarStore, addDays, addMonths, addMonthsKeepDay, formatDdMmYyyy, formatHhMm, isOutOfRange, isSameDay, isoDay, pad2, sdsFormatNational, sdsMatchDialCode, sdsNormalizeSignificant, startOfDay, startOfMonth };
11937
+ export { SDS_ALLERGENS, SDS_ALLERGEN_ICONS, SDS_ALLERGEN_LABELS_EN, SDS_ICONS, SDS_PHONE_COUNTRIES, SdsAccordion, SdsAccordionContent, SdsAccordionHeader, SdsAccordionPanel, SdsAccordionStore, SdsAllergenIcon, SdsAvatar, SdsBadge, SdsButton, SdsCalendar, SdsCard, SdsCheckbox, SdsDatePicker, SdsIcon, SdsInput, SdsInputNumber, SdsLanguageSwitcher, SdsLocalizedInput, SdsMenuItem, SdsMultiSelect, SdsNavGroup, SdsNavItem, SdsOtpInput, SdsPaginator, SdsPhoneInput, SdsRadio, SdsSearchCommand, SdsSelect, SdsSelectEmpty, SdsSelectFooter, SdsSelectOption, SdsShell, SdsSidebar, 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, sdsFormatNational, sdsMatchDialCode, sdsNormalizeSignificant, startOfDay, startOfMonth };
11541
11938
  //# sourceMappingURL=besaitech-ng-design-system.mjs.map