@conciso/design-system-angular 0.0.0-bootstrap.0 → 2.1.1

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.
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { signal, Injectable, input, output, computed, ChangeDetectionStrategy, Component, inject, ElementRef, model, Directive, forwardRef, DestroyRef, viewChild, linkedSignal, numberAttribute, afterNextRender, TemplateRef, contentChildren, effect, viewChildren, afterRenderEffect } from '@angular/core';
3
3
  import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
4
4
  import { provideIcons, NgIcon } from '@ng-icons/core';
5
- import { icons } from '@conciso/design-system/icons';
5
+ import { uiCaretDown as uiCaretDown$1, uiCheck as uiCheck$1 } from '@conciso/design-system/icons';
6
6
  import { heroComputerDesktop, heroMoon, heroSun, heroXMark, heroMagnifyingGlass, heroBars3, heroChevronDown } from '@ng-icons/heroicons/outline';
7
7
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
8
8
  import { DomSanitizer } from '@angular/platform-browser';
@@ -203,6 +203,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
203
203
  * · `ui-caret-down` — kräftiger Caret (10er-viewBox), kein Heroicon-Pendant.
204
204
  * · `ui-check` — eigener Haken (12er-viewBox), weicht vom heroCheck (24er) ab.
205
205
  *
206
+ * Importiert werden ausschließlich die BENANNTEN Exporte der beiden gebrauchten Glyphen
207
+ * (`uiCaretDown`, `uiCheck`), nie das aggregierte `icons`-Objekt — ein Property-Zugriff
208
+ * darauf (`icons['ui-caret-down']`) ist für Bundler nicht tree-shakable und zöge alle
209
+ * alle DS-Icons in jedes Consumer-Bundle (siehe icons/README.md „Verwendung“).
210
+ *
206
211
  * 2. **Heroicons**: für Glyphen, die im DS mit dem Heroicon glyph-identisch sind
207
212
  * (chevron-down, magnifying-glass — gleicher Pfad, das DS setzt nur einen dünneren
208
213
  * Stroke) sowie für die im DS-Set (noch) fehlenden Chrome-Icons (bars-3, x-mark,
@@ -212,13 +217,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
212
217
  * Komponenten importieren ausschließlich aus dieser Datei, nie direkt aus
213
218
  * `@ng-icons/heroicons`.
214
219
  */
215
- // @ts-expect-error — @conciso/design-system liefert icons.js als reines generiertes JS ohne
216
- // eigene Typdeklaration; die Form ist in ds-icons-export.d.ts dokumentiert (ngtsc greift die
217
- // Ambient-Deklaration dort nicht, anders als tsc, deshalb die explizite Unterdrückung hier).
218
- // DS-eigene Glyphen aus dem generierten Export (kein Duplizieren des SVG-Markups).
220
+ // DS-eigene Glyphen aus dem generierten, benannten Export (kein Duplizieren des SVG-Markups).
219
221
  // Als @ng-icons-Custom-Icons registrierbar: der Wert ist das komplette <svg>-Markup.
220
- const uiCaretDown = icons['ui-caret-down'].svg;
221
- const uiCheck = icons['ui-check'].svg;
222
+ const uiCaretDown = uiCaretDown$1.svg;
223
+ const uiCheck = uiCheck$1.svg;
222
224
 
223
225
  /**
224
226
  * Theme-Cycle-Button — ein einzelner Icon-Button (Stil `.ep-nav-icon-btn` aus der
@@ -4286,34 +4288,106 @@ class ScaleComponent extends CvaBase {
4286
4288
  outputClasses = computed(() => `field-slider-output slider-${this.area()}`, /* @ts-ignore */
4287
4289
  ...(ngDevMode ? [{ debugName: "outputClasses" }] : /* istanbul ignore next */ []));
4288
4290
  /**
4289
- * Alle Labels + Positions-Style. Mitte-Labels sind auf ihrer Thumb-Position
4290
- * zentriert; das ERSTE/LETZTE Label wird an der jeweiligen Kante verankert
4291
- * (linksbündig bei 11px bzw. rechtsbündig bei Breite−11px), damit lange
4292
- * Kategorie-Labels an den Enden nicht über den Rand hinaus abgeschnitten werden.
4293
- * (11px = halbe Thumb-Breite, siehe css/components.css.)
4291
+ * Spaltenbreiten für das Tick-Grid, mit `minmax()` statt fixer Breiten: Bei
4292
+ * ausreichend Platz treffen die Spaltenmitten exakt die Thumb-Positionen (wie
4293
+ * bisher); wird es zu schmal, um alle Labels einzeilig zu zeigen, gibt das Grid
4294
+ * Lesbarkeit den Vorrang vor exakter Ausrichtung (Entscheidung: Umbruch statt
4295
+ * Überlappung ODER Abschneiden).
4296
+ *
4297
+ * - Rand-Spalten: `minmax(halber Schritt + 11px, max-content)`. Der Mindestwert ist
4298
+ * wie zuvor die halbe „Schritt“-Distanz `(100% − 22px) / (n − 1)` zwischen zwei
4299
+ * benachbarten Thumb-Positionen plus 11px (halbe Thumb-Breite, siehe
4300
+ * css/components.css) — das kantenbündige Rand-Label beansprucht nur EINE
4301
+ * Richtung, die Gegenseite (vor der ersten/nach der letzten Thumb-Position) fließt
4302
+ * seiner Spalte zu. Bei breiten Containern übersteigt dieser Mindestwert die
4303
+ * natürliche (einzeilige) Breite des Labels — dann klemmt `minmax()` laut Spezifikation
4304
+ * auf den Mindestwert, die Spalte verhält sich also identisch zu vorher. Erst wenn
4305
+ * der Container schmaler wird als diese Mindestbreite, wächst die Spalte auf bis
4306
+ * zu `max-content`, das Label bleibt einzeilig, solange noch Platz da ist.
4307
+ * - Mitte-Spalten: `minmax(min-content, 1fr)` — nie schmäler als das breiteste
4308
+ * unteilbare Wort, sonst gleichberechtigt (1fr) um den verbleibenden Platz. Bei
4309
+ * schmalen Breiten kann die Spalte dadurch von ihrem rechnerischen Schritt
4310
+ * abweichen; die Spaltenmitte (und damit das zentrierte Label) liegt dann
4311
+ * geringfügig neben der Thumb-Position — akzeptierter Trade-off.
4312
+ *
4313
+ * Bei nur einem Label eine volle Spalte.
4314
+ *
4315
+ * @internal
4316
+ */
4317
+ tickColumns = computed(() => {
4318
+ const n = this.labels().length;
4319
+ if (n <= 1)
4320
+ return '1fr';
4321
+ const gaps = n - 1;
4322
+ const edge = `minmax(calc(11px + (100% - 22px) / ${gaps} / 2), max-content)`;
4323
+ if (n === 2)
4324
+ return `${edge} ${edge}`;
4325
+ const mid = `repeat(${n - 2}, minmax(min-content, 1fr))`;
4326
+ return `${edge} ${mid} ${edge}`;
4327
+ }, /* @ts-ignore */
4328
+ ...(ngDevMode ? [{ debugName: "tickColumns" }] : /* istanbul ignore next */ []));
4329
+ /**
4330
+ * Alle Labels + Ausrichtung innerhalb ihrer Grid-Spalte (`tickColumns()`). Mitte-
4331
+ * Labels sind in ihrer Spalte zentriert — bei ausreichend Platz liegt die
4332
+ * Spaltenmitte exakt auf der Thumb-Position; bei sehr schmalen Breiten, wenn
4333
+ * `minmax(min-content, 1fr)` eine Spalte über ihren rechnerischen Schritt hinaus
4334
+ * wachsen lässt, kann die Mitte geringfügig davon abweichen (siehe
4335
+ * `tickColumns()`). Das ERSTE/LETZTE Label wird an der jeweiligen Kante verankert
4336
+ * (linksbündig bzw. rechtsbündig, 11px Innenabstand = halbe Thumb-Breite), damit
4337
+ * lange Kategorie-Labels an den Enden nicht über den Rand hinaus abgeschnitten
4338
+ * werden.
4339
+ *
4340
+ * Zusätzlich 4px `padding-inline` an der jeweils INNEREN Seite (Mitte-Labels:
4341
+ * beidseitig — bei zentriertem Text bleibt die Mitte dadurch unverschoben):
4342
+ * Mindestabstand zwischen benachbarten Labels. Ohne das können bei mittleren
4343
+ * Breiten (Spalte klemmt schon auf `minmax()`-Mindestwert, aber Label füllt sie
4344
+ * fast aus) die Text-Ink-Boxes zweier Nachbarn exakt aneinanderstoßen (0px Lücke,
4345
+ * liest sich als ein zusammengeschriebenes Wort), obwohl sie sich nicht
4346
+ * überlappen. `box-sizing:border-box` (s. u.) sorgt dafür, dass `min-content` in
4347
+ * `tickColumns()` das Padding mit einrechnet, statt die Spalte zusätzlich zu
4348
+ * stauchen.
4349
+ *
4350
+ * `hyphens:auto` trennt einzelne Wörter, die trotz der `max-content`/
4351
+ * `min-content`-Untergrenze in `tickColumns()` noch breiter als ihre Spalte sind —
4352
+ * wirkt nur, wenn die einbettende Seite `lang="de"` setzt (Storybooks Vitest-Iframe
4353
+ * tut das nicht; bei Konsumenten ist es nicht garantiert, daher rein additiv).
4354
+ * Bewusst OHNE `overflow-wrap:break-word`: das bricht mitten im Wort ohne
4355
+ * Trennzeichen (z. B. „zufriede“/„n“) und ist schlechter lesbar als ein Wort, das
4356
+ * im Ausnahmefall über seine Spalte hinausragt — Lesbarkeit vor exakter
4357
+ * Breiteneinhaltung. Ohne `white-space:nowrap` umbrechen Labels normal (zeilenweise),
4358
+ * statt sich zu überlagern.
4294
4359
  *
4295
4360
  * @internal
4296
4361
  */
4297
4362
  tickItems = computed(() => {
4298
4363
  const labels = this.labels();
4299
4364
  const n = labels.length;
4300
- const base = { position: 'absolute', 'white-space': 'nowrap' };
4301
- // transform/left aus .field-slider-ticks>* (components.css) an den Kanten
4302
- // explizit neutralisieren — sonst spannt left+right das letzte Label über die
4303
- // volle Breite und translateX(-50%) schiebt es in die Mitte.
4365
+ // position/transform/white-space aus .field-slider-ticks>* (components.css)
4366
+ // explizit neutralisieren — sonst bleiben die Labels absolut positioniert und
4367
+ // ignorieren die Grid-Spalten, auf denen dieser Ansatz aufbaut.
4368
+ const base = {
4369
+ position: 'static',
4370
+ transform: 'none',
4371
+ 'white-space': 'normal',
4372
+ 'box-sizing': 'border-box',
4373
+ hyphens: 'auto',
4374
+ };
4304
4375
  return labels.map((label, i) => {
4305
- if (n <= 1 || i === 0)
4306
- return { label, style: { ...base, left: '11px', 'text-align': 'left', transform: 'none' } };
4376
+ if (n <= 1)
4377
+ return { label, style: { ...base, 'text-align': 'left', 'padding-left': '11px' } };
4378
+ if (i === 0)
4379
+ // Innere Seite (rechts, Richtung nächstes Label) zusätzlich 4px — Mindestlücke,
4380
+ // s. Kommentar oben.
4381
+ return {
4382
+ label,
4383
+ style: { ...base, 'text-align': 'left', 'padding-left': '11px', 'padding-right': '4px' },
4384
+ };
4307
4385
  if (i === n - 1)
4308
4386
  return {
4309
4387
  label,
4310
- style: { ...base, left: 'auto', right: '11px', 'text-align': 'right', transform: 'none' },
4388
+ style: { ...base, 'text-align': 'right', 'padding-left': '4px', 'padding-right': '11px' },
4311
4389
  };
4312
- const p = i / (n - 1);
4313
- return {
4314
- label,
4315
- style: { ...base, left: `calc(11px + ${p} * (100% - 22px))`, transform: 'translateX(-50%)' },
4316
- };
4390
+ return { label, style: { ...base, 'text-align': 'center', 'padding-inline': '4px' } };
4317
4391
  });
4318
4392
  }, /* @ts-ignore */
4319
4393
  ...(ngDevMode ? [{ debugName: "tickItems" }] : /* istanbul ignore next */ []));
@@ -4351,14 +4425,21 @@ class ScaleComponent extends CvaBase {
4351
4425
  (blur)="markTouched()"
4352
4426
  />
4353
4427
  @if (labels().length) {
4354
- <!-- Alle Skalen-Labels exakt auf ihre Position ausgerichtet (Thumb 22px, siehe
4355
- css/components.css), zentriert. KEINE Reduktion — jedes Label ist wählbar.
4356
- Self-contained positioniert (der --tick-p-Kernmechanismus liegt noch auf
4357
- dem main-PR; nach Merge kann das vereinfacht werden). -->
4428
+ <!-- Alle Skalen-Labels als CSS-Grid-Spalten (Breiten: tickColumns()), bei
4429
+ ausreichend Platz exakt auf ihre Thumb-Position ausgerichtet (Thumb 22px,
4430
+ siehe css/components.css); bei schmalen Breiten gibt das Grid lieber den
4431
+ Umbruch frei, statt Labels zu überlagern oder abzuschneiden (siehe dort).
4432
+ KEINE Reduktion — jedes Label ist wählbar, PFLICHT-Inhalt (kein Dropping
4433
+ wie bei cds-slider). Statt Absolut-Positionierung Normalfluss: mehrzeilige
4434
+ Labels (lange Kategorien bei schmaler Breite) wachsen den Container in der
4435
+ Höhe und schieben nachfolgenden Inhalt nach unten, statt ihn zu
4436
+ überlagern. Self-contained positioniert (der --tick-p-Kernmechanismus liegt
4437
+ noch auf dem main-PR; nach Merge kann das vereinfacht werden). -->
4358
4438
  <div
4359
4439
  class="field-slider-ticks"
4360
4440
  aria-hidden="true"
4361
- style="position:relative;display:block;padding:0;height:16px"
4441
+ style="position:relative;display:grid;padding:0;height:auto;align-items:start"
4442
+ [style.grid-template-columns]="tickColumns()"
4362
4443
  >
4363
4444
  @for (t of tickItems(); track $index) {
4364
4445
  <span [style]="t.style">{{ t.label }}</span>
@@ -4400,14 +4481,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
4400
4481
  (blur)="markTouched()"
4401
4482
  />
4402
4483
  @if (labels().length) {
4403
- <!-- Alle Skalen-Labels exakt auf ihre Position ausgerichtet (Thumb 22px, siehe
4404
- css/components.css), zentriert. KEINE Reduktion — jedes Label ist wählbar.
4405
- Self-contained positioniert (der --tick-p-Kernmechanismus liegt noch auf
4406
- dem main-PR; nach Merge kann das vereinfacht werden). -->
4484
+ <!-- Alle Skalen-Labels als CSS-Grid-Spalten (Breiten: tickColumns()), bei
4485
+ ausreichend Platz exakt auf ihre Thumb-Position ausgerichtet (Thumb 22px,
4486
+ siehe css/components.css); bei schmalen Breiten gibt das Grid lieber den
4487
+ Umbruch frei, statt Labels zu überlagern oder abzuschneiden (siehe dort).
4488
+ KEINE Reduktion — jedes Label ist wählbar, PFLICHT-Inhalt (kein Dropping
4489
+ wie bei cds-slider). Statt Absolut-Positionierung Normalfluss: mehrzeilige
4490
+ Labels (lange Kategorien bei schmaler Breite) wachsen den Container in der
4491
+ Höhe und schieben nachfolgenden Inhalt nach unten, statt ihn zu
4492
+ überlagern. Self-contained positioniert (der --tick-p-Kernmechanismus liegt
4493
+ noch auf dem main-PR; nach Merge kann das vereinfacht werden). -->
4407
4494
  <div
4408
4495
  class="field-slider-ticks"
4409
4496
  aria-hidden="true"
4410
- style="position:relative;display:block;padding:0;height:16px"
4497
+ style="position:relative;display:grid;padding:0;height:auto;align-items:start"
4498
+ [style.grid-template-columns]="tickColumns()"
4411
4499
  >
4412
4500
  @for (t of tickItems(); track $index) {
4413
4501
  <span [style]="t.style">{{ t.label }}</span>
@@ -4450,11 +4538,13 @@ class SnackbarComponent {
4450
4538
  isError = computed(() => this.tone() === 'err', /* @ts-ignore */
4451
4539
  ...(ngDevMode ? [{ debugName: "isError" }] : /* istanbul ignore next */ []));
4452
4540
  /**
4453
- * Tonfarbe des Icons (wie im Doku-Markup).
4541
+ * Tonfarbe des Icons (wie im Doku-Markup). CSS-Variablen statt Hex (Befund 04) — als
4542
+ * [style.stroke] gesetzt, nicht als Präsentationsattribut, weil Präsentationsattribute var()
4543
+ * nicht auflösen.
4454
4544
  *
4455
4545
  * @internal
4456
4546
  */
4457
- iconStroke = computed(() => ({ def: '#80DEDE', ok: '#88f0c4', err: '#f9a8a8' })[this.tone()], /* @ts-ignore */
4547
+ iconStroke = computed(() => ({ def: 'var(--co-200)', ok: 'var(--c-success-strong-icon)', err: 'var(--c-error-strong-icon)' })[this.tone()], /* @ts-ignore */
4458
4548
  ...(ngDevMode ? [{ debugName: "iconStroke" }] : /* istanbul ignore next */ []));
4459
4549
  /**
4460
4550
  * Lucide-artiger Pfad je Ton (Glühbirne / Häkchen-Kreis / Ausrufezeichen-Kreis).
@@ -4479,7 +4569,7 @@ class SnackbarComponent {
4479
4569
  height="24"
4480
4570
  viewBox="0 0 24 24"
4481
4571
  fill="none"
4482
- [attr.stroke]="iconStroke()"
4572
+ [style.stroke]="iconStroke()"
4483
4573
  stroke-width="1.25"
4484
4574
  aria-hidden="true"
4485
4575
  focusable="false"
@@ -4510,7 +4600,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
4510
4600
  height="24"
4511
4601
  viewBox="0 0 24 24"
4512
4602
  fill="none"
4513
- [attr.stroke]="iconStroke()"
4603
+ [style.stroke]="iconStroke()"
4514
4604
  stroke-width="1.25"
4515
4605
  aria-hidden="true"
4516
4606
  focusable="false"