@skra/ui 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/NOTICE +7 -0
- package/README.md +39 -0
- package/consumer-guide/README.md +84 -0
- package/consumer-guide/accessible-names.md +80 -0
- package/consumer-guide/forms-and-binding.md +149 -0
- package/consumer-guide/layout.md +86 -0
- package/consumer-guide/overlays.md +100 -0
- package/consumer-guide/setup-and-gotchas.md +103 -0
- package/consumer-guide/theming-and-encapsulation.md +115 -0
- package/consumer-guide/wrapping-patterns.md +90 -0
- package/fesm2022/skra-ui-accordion.mjs +333 -0
- package/fesm2022/skra-ui-accordion.mjs.map +1 -0
- package/fesm2022/skra-ui-alert.mjs +110 -0
- package/fesm2022/skra-ui-alert.mjs.map +1 -0
- package/fesm2022/skra-ui-avatar.mjs +83 -0
- package/fesm2022/skra-ui-avatar.mjs.map +1 -0
- package/fesm2022/skra-ui-badge.mjs +91 -0
- package/fesm2022/skra-ui-badge.mjs.map +1 -0
- package/fesm2022/skra-ui-button.mjs +67 -0
- package/fesm2022/skra-ui-button.mjs.map +1 -0
- package/fesm2022/skra-ui-checkbox.mjs +98 -0
- package/fesm2022/skra-ui-checkbox.mjs.map +1 -0
- package/fesm2022/skra-ui-chip.mjs +82 -0
- package/fesm2022/skra-ui-chip.mjs.map +1 -0
- package/fesm2022/skra-ui-combobox.mjs +335 -0
- package/fesm2022/skra-ui-combobox.mjs.map +1 -0
- package/fesm2022/skra-ui-core.mjs +529 -0
- package/fesm2022/skra-ui-core.mjs.map +1 -0
- package/fesm2022/skra-ui-counter.mjs +53 -0
- package/fesm2022/skra-ui-counter.mjs.map +1 -0
- package/fesm2022/skra-ui-datepicker.mjs +867 -0
- package/fesm2022/skra-ui-datepicker.mjs.map +1 -0
- package/fesm2022/skra-ui-dialog.mjs +133 -0
- package/fesm2022/skra-ui-dialog.mjs.map +1 -0
- package/fesm2022/skra-ui-field.mjs +293 -0
- package/fesm2022/skra-ui-field.mjs.map +1 -0
- package/fesm2022/skra-ui-icon.mjs +54 -0
- package/fesm2022/skra-ui-icon.mjs.map +1 -0
- package/fesm2022/skra-ui-input.mjs +42 -0
- package/fesm2022/skra-ui-input.mjs.map +1 -0
- package/fesm2022/skra-ui-kbd.mjs +44 -0
- package/fesm2022/skra-ui-kbd.mjs.map +1 -0
- package/fesm2022/skra-ui-layout.mjs +119 -0
- package/fesm2022/skra-ui-layout.mjs.map +1 -0
- package/fesm2022/skra-ui-link.mjs +29 -0
- package/fesm2022/skra-ui-link.mjs.map +1 -0
- package/fesm2022/skra-ui-loading-indicator.mjs +24 -0
- package/fesm2022/skra-ui-loading-indicator.mjs.map +1 -0
- package/fesm2022/skra-ui-menu.mjs +334 -0
- package/fesm2022/skra-ui-menu.mjs.map +1 -0
- package/fesm2022/skra-ui-multi-select.mjs +179 -0
- package/fesm2022/skra-ui-multi-select.mjs.map +1 -0
- package/fesm2022/skra-ui-native-select.mjs +123 -0
- package/fesm2022/skra-ui-native-select.mjs.map +1 -0
- package/fesm2022/skra-ui-popover.mjs +158 -0
- package/fesm2022/skra-ui-popover.mjs.map +1 -0
- package/fesm2022/skra-ui-progress.mjs +57 -0
- package/fesm2022/skra-ui-progress.mjs.map +1 -0
- package/fesm2022/skra-ui-radio.mjs +92 -0
- package/fesm2022/skra-ui-radio.mjs.map +1 -0
- package/fesm2022/skra-ui-rating-display.mjs +81 -0
- package/fesm2022/skra-ui-rating-display.mjs.map +1 -0
- package/fesm2022/skra-ui-select.mjs +151 -0
- package/fesm2022/skra-ui-select.mjs.map +1 -0
- package/fesm2022/skra-ui-skeleton.mjs +65 -0
- package/fesm2022/skra-ui-skeleton.mjs.map +1 -0
- package/fesm2022/skra-ui-star-rating.mjs +110 -0
- package/fesm2022/skra-ui-star-rating.mjs.map +1 -0
- package/fesm2022/skra-ui-status-dot.mjs +61 -0
- package/fesm2022/skra-ui-status-dot.mjs.map +1 -0
- package/fesm2022/skra-ui-switch.mjs +94 -0
- package/fesm2022/skra-ui-switch.mjs.map +1 -0
- package/fesm2022/skra-ui-tabs.mjs +356 -0
- package/fesm2022/skra-ui-tabs.mjs.map +1 -0
- package/fesm2022/skra-ui-textarea.mjs +81 -0
- package/fesm2022/skra-ui-textarea.mjs.map +1 -0
- package/fesm2022/skra-ui-toast.mjs +208 -0
- package/fesm2022/skra-ui-toast.mjs.map +1 -0
- package/fesm2022/skra-ui-tooltip.mjs +252 -0
- package/fesm2022/skra-ui-tooltip.mjs.map +1 -0
- package/fesm2022/skra-ui-typography.mjs +35 -0
- package/fesm2022/skra-ui-typography.mjs.map +1 -0
- package/fesm2022/skra-ui.mjs +4 -0
- package/fesm2022/skra-ui.mjs.map +1 -0
- package/package.json +175 -0
- package/types/skra-ui-accordion.d.ts +196 -0
- package/types/skra-ui-accordion.d.ts.map +1 -0
- package/types/skra-ui-alert.d.ts +81 -0
- package/types/skra-ui-alert.d.ts.map +1 -0
- package/types/skra-ui-avatar.d.ts +71 -0
- package/types/skra-ui-avatar.d.ts.map +1 -0
- package/types/skra-ui-badge.d.ts +73 -0
- package/types/skra-ui-badge.d.ts.map +1 -0
- package/types/skra-ui-button.d.ts +45 -0
- package/types/skra-ui-button.d.ts.map +1 -0
- package/types/skra-ui-checkbox.d.ts +52 -0
- package/types/skra-ui-checkbox.d.ts.map +1 -0
- package/types/skra-ui-chip.d.ts +60 -0
- package/types/skra-ui-chip.d.ts.map +1 -0
- package/types/skra-ui-combobox.d.ts +95 -0
- package/types/skra-ui-combobox.d.ts.map +1 -0
- package/types/skra-ui-core.d.ts +314 -0
- package/types/skra-ui-core.d.ts.map +1 -0
- package/types/skra-ui-counter.d.ts +33 -0
- package/types/skra-ui-counter.d.ts.map +1 -0
- package/types/skra-ui-datepicker.d.ts +164 -0
- package/types/skra-ui-datepicker.d.ts.map +1 -0
- package/types/skra-ui-dialog.d.ts +59 -0
- package/types/skra-ui-dialog.d.ts.map +1 -0
- package/types/skra-ui-field.d.ts +181 -0
- package/types/skra-ui-field.d.ts.map +1 -0
- package/types/skra-ui-icon.d.ts +38 -0
- package/types/skra-ui-icon.d.ts.map +1 -0
- package/types/skra-ui-input.d.ts +22 -0
- package/types/skra-ui-input.d.ts.map +1 -0
- package/types/skra-ui-kbd.d.ts +33 -0
- package/types/skra-ui-kbd.d.ts.map +1 -0
- package/types/skra-ui-layout.d.ts +86 -0
- package/types/skra-ui-layout.d.ts.map +1 -0
- package/types/skra-ui-link.d.ts +20 -0
- package/types/skra-ui-link.d.ts.map +1 -0
- package/types/skra-ui-loading-indicator.d.ts +9 -0
- package/types/skra-ui-loading-indicator.d.ts.map +1 -0
- package/types/skra-ui-menu.d.ts +116 -0
- package/types/skra-ui-menu.d.ts.map +1 -0
- package/types/skra-ui-multi-select.d.ts +47 -0
- package/types/skra-ui-multi-select.d.ts.map +1 -0
- package/types/skra-ui-native-select.d.ts +74 -0
- package/types/skra-ui-native-select.d.ts.map +1 -0
- package/types/skra-ui-popover.d.ts +57 -0
- package/types/skra-ui-popover.d.ts.map +1 -0
- package/types/skra-ui-progress.d.ts +41 -0
- package/types/skra-ui-progress.d.ts.map +1 -0
- package/types/skra-ui-radio.d.ts +54 -0
- package/types/skra-ui-radio.d.ts.map +1 -0
- package/types/skra-ui-rating-display.d.ts +56 -0
- package/types/skra-ui-rating-display.d.ts.map +1 -0
- package/types/skra-ui-select.d.ts +43 -0
- package/types/skra-ui-select.d.ts.map +1 -0
- package/types/skra-ui-skeleton.d.ts +42 -0
- package/types/skra-ui-skeleton.d.ts.map +1 -0
- package/types/skra-ui-star-rating.d.ts +71 -0
- package/types/skra-ui-star-rating.d.ts.map +1 -0
- package/types/skra-ui-status-dot.d.ts +62 -0
- package/types/skra-ui-status-dot.d.ts.map +1 -0
- package/types/skra-ui-switch.d.ts +54 -0
- package/types/skra-ui-switch.d.ts.map +1 -0
- package/types/skra-ui-tabs.d.ts +191 -0
- package/types/skra-ui-tabs.d.ts.map +1 -0
- package/types/skra-ui-textarea.d.ts +55 -0
- package/types/skra-ui-textarea.d.ts.map +1 -0
- package/types/skra-ui-toast.d.ts +140 -0
- package/types/skra-ui-toast.d.ts.map +1 -0
- package/types/skra-ui-tooltip.d.ts +90 -0
- package/types/skra-ui-tooltip.d.ts.map +1 -0
- package/types/skra-ui-typography.d.ts +17 -0
- package/types/skra-ui-typography.d.ts.map +1 -0
- package/types/skra-ui.d.ts +3 -0
- package/types/skra-ui.d.ts.map +1 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { signal, Injectable, input, inject, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, booleanAttribute, output, contentChildren, effect, ElementRef, Directive, contentChild } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/** Module-global counter → a deterministic, unique id base per `[skraAccordion]`
|
|
5
|
+
* instance. Lib-local (mirrors `SkraTabsContext`) so `@skra/disclosure` takes no
|
|
6
|
+
* dependency on another lib just for id generation. Stable across SSR↔hydration
|
|
7
|
+
* (same instantiation order yields the same ids — the standard counter technique). */
|
|
8
|
+
let accordionInstanceCounter = 0;
|
|
9
|
+
/** Sanitize a consumer `value` into an id-safe fragment (no spaces / special chars). */
|
|
10
|
+
function idSafe(value) {
|
|
11
|
+
return value.replace(/[^a-zA-Z0-9_-]/g, '-');
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* DI Context provided per `[skraAccordion]` instance — the ADR 013 §3.6 **non-form**
|
|
15
|
+
* Contextual-ID-Sync bus (the 2nd consumer of the idiom after `SkraTabsContext`). It
|
|
16
|
+
* carries **IDs + derived, read-only interaction state only** (`expanded` mirrors the
|
|
17
|
+
* consumer's `[expanded]`; `exclusive` mirrors `[exclusive]`). It **never owns value** —
|
|
18
|
+
* the open/closed set stays consumer-owned (ADR 037); a header requests a change through
|
|
19
|
+
* `toggle()`, which the coordinator implements (resolving the exclusive policy) and from
|
|
20
|
+
* which it emits `(expandedChange)`.
|
|
21
|
+
*/
|
|
22
|
+
class SkraAccordionContext {
|
|
23
|
+
/** Unique per `[skraAccordion]` — the prefix for every header/panel id in this group. */
|
|
24
|
+
baseId = `skra-accordion-${++accordionInstanceCounter}`;
|
|
25
|
+
/** Mirror of the consumer's `[expanded]` — the set of OPEN item values (read-only to children). */
|
|
26
|
+
expanded = signal([], ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
27
|
+
/** Mirror of the consumer's `[exclusive]` policy (read-only to children). */
|
|
28
|
+
exclusive = signal(false, ...(ngDevMode ? [{ debugName: "exclusive" }] : /* istanbul ignore next */ []));
|
|
29
|
+
headerId(value) {
|
|
30
|
+
return `${this.baseId}-header-${idSafe(value)}`;
|
|
31
|
+
}
|
|
32
|
+
panelId(value) {
|
|
33
|
+
return `${this.baseId}-panel-${idSafe(value)}`;
|
|
34
|
+
}
|
|
35
|
+
isExpanded(value) {
|
|
36
|
+
return this.expanded().includes(value);
|
|
37
|
+
}
|
|
38
|
+
/** Coordinator-assigned: a header requests a toggle; the coordinator resolves the next
|
|
39
|
+
* open-set (applying the exclusive policy) and emits `(expandedChange)` — never mutated here. */
|
|
40
|
+
toggle = () => undefined;
|
|
41
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionContext, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
42
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionContext });
|
|
43
|
+
}
|
|
44
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionContext, decorators: [{
|
|
45
|
+
type: Injectable
|
|
46
|
+
}] });
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Per-item DI context provided by `[skraAccordionItem]` (via `useExisting`). It lets
|
|
50
|
+
* `button[skraAccordionHeader]` and `[skraAccordionPanel]` read their shared `value`,
|
|
51
|
+
* derived ids, and open state **without each re-declaring `value`** — the item declares it
|
|
52
|
+
* once. All members are read-only/derived; `toggle()` forwards to the group coordinator
|
|
53
|
+
* (the open/closed set stays consumer-owned, ADR 037). `*Id` are `null` only when an item
|
|
54
|
+
* is used outside a `[skraAccordion]` (standalone misuse → dev-warned).
|
|
55
|
+
*/
|
|
56
|
+
class SkraAccordionItemContext {
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* SkraAccordionItem — one item, a Component on the consumer's `<div skraAccordionItem>`
|
|
61
|
+
* (ADR 040, `template: '<ng-content>'`). It declares `[value]` ONCE and provides
|
|
62
|
+
* `SkraAccordionItemContext` (via `useExisting`) so its `button[skraAccordionHeader]` and
|
|
63
|
+
* `[skraAccordionPanel]` read the shared value/ids/open-state without re-declaring it. It
|
|
64
|
+
* owns the per-item top divider (no double borders) and the open-item box (skins may tint it).
|
|
65
|
+
*/
|
|
66
|
+
class SkraAccordionItem {
|
|
67
|
+
/** The item key — matched against `[expanded]` and the id base for its header/panel. */
|
|
68
|
+
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
69
|
+
group = inject(SkraAccordionContext, { optional: true });
|
|
70
|
+
expanded = computed(() => this.group?.isExpanded(this.value()) ?? false, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
71
|
+
headerId = computed(() => this.group?.headerId(this.value()) ?? null, ...(ngDevMode ? [{ debugName: "headerId" }] : /* istanbul ignore next */ []));
|
|
72
|
+
panelId = computed(() => this.group?.panelId(this.value()) ?? null, ...(ngDevMode ? [{ debugName: "panelId" }] : /* istanbul ignore next */ []));
|
|
73
|
+
toggle() {
|
|
74
|
+
this.group?.toggle(this.value());
|
|
75
|
+
}
|
|
76
|
+
constructor() {
|
|
77
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
78
|
+
if (!this.group) {
|
|
79
|
+
console.warn('[skraAccordionItem] has no [skraAccordion] ancestor — its header/panel are not wired ' +
|
|
80
|
+
'(no aria-controls / open state). Project it inside <element skraAccordion>.');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
85
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.7", type: SkraAccordionItem, isStandalone: true, selector: "[skraAccordionItem]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "attr.data-skra-expanded": "expanded() ? \"\" : null" } }, providers: [
|
|
86
|
+
{ provide: SkraAccordionItemContext, useExisting: SkraAccordionItem },
|
|
87
|
+
], exportAs: ["skraAccordionItem"], ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: ["@charset \"UTF-8\";:host{display:block;margin:0;box-sizing:border-box;border-block-start:var(--skra-comp-accordion-item-divider-width) solid var(--skra-comp-accordion-item-divider-color)}:host(:first-child){border-block-start-width:0}:host([data-skra-expanded]){background:var(--skra-comp-accordion-item-background-expanded)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
88
|
+
}
|
|
89
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionItem, decorators: [{
|
|
90
|
+
type: Component,
|
|
91
|
+
args: [{ selector: '[skraAccordionItem]', standalone: true, exportAs: 'skraAccordionItem', template: '<ng-content></ng-content>', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, providers: [
|
|
92
|
+
{ provide: SkraAccordionItemContext, useExisting: SkraAccordionItem },
|
|
93
|
+
], host: {
|
|
94
|
+
'[attr.data-skra-expanded]': 'expanded() ? "" : null',
|
|
95
|
+
}, styles: ["@charset \"UTF-8\";:host{display:block;margin:0;box-sizing:border-box;border-block-start:var(--skra-comp-accordion-item-divider-width) solid var(--skra-comp-accordion-item-divider-color)}:host(:first-child){border-block-start-width:0}:host([data-skra-expanded]){background:var(--skra-comp-accordion-item-background-expanded)}\n"] }]
|
|
96
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }] } });
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* SkraAccordion — the WAI-ARIA APG **Accordion** coordinator. A Component on a wrapping
|
|
100
|
+
* element that holds `[skraAccordionItem]` children (each item wraps a
|
|
101
|
+
* `button[skraAccordionHeader]` + a `[skraAccordionPanel]`). It provides
|
|
102
|
+
* `SkraAccordionContext` (the ADR 013 §3.6 non-form Contextual-ID-Sync bus), owns the
|
|
103
|
+
* consumer-facing `[expanded]` / `(expandedChange)` (controlled, ADR 037 — NO internal open
|
|
104
|
+
* state) and the `[exclusive]` policy, and draws the group's outer border + radius.
|
|
105
|
+
*
|
|
106
|
+
* <div skraAccordion [expanded]="open()" (expandedChange)="open.set($event)">
|
|
107
|
+
* <div skraAccordionItem value="general">
|
|
108
|
+
* <h3><button skraAccordionHeader>General</button></h3>
|
|
109
|
+
* <div skraAccordionPanel>…</div>
|
|
110
|
+
* </div>
|
|
111
|
+
* <div skraAccordionItem value="security"> … </div>
|
|
112
|
+
* </div>
|
|
113
|
+
*
|
|
114
|
+
* Open state is consumer-owned: a header click emits `(expandedChange)` with the resolved
|
|
115
|
+
* next set (the `[exclusive]` policy applied here); the visible state updates when the
|
|
116
|
+
* consumer round-trips `[expanded]`. `[exclusive]` is a POLICY flag on an invariant
|
|
117
|
+
* `string[]` value — NOT a value-type switch, so it does not trigger ADR 0046.
|
|
118
|
+
*
|
|
119
|
+
* Full contract: adr/specs/component-accordion-spec.md.
|
|
120
|
+
*/
|
|
121
|
+
class SkraAccordion {
|
|
122
|
+
/** Consumer-owned set of OPEN item values (ADR 037). `[]` = all closed; order irrelevant. */
|
|
123
|
+
expanded = input([], ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
124
|
+
/** Policy: `true` → opening one item emits a set that drops the others (single-open). */
|
|
125
|
+
exclusive = input(false, { ...(ngDevMode ? { debugName: "exclusive" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
126
|
+
/** Fires ONLY on user toggle — never on a programmatic `[expanded]` change. Carries the resolved next set. */
|
|
127
|
+
expandedChange = output();
|
|
128
|
+
ctx = inject(SkraAccordionContext);
|
|
129
|
+
items = contentChildren(SkraAccordionItem, { ...(ngDevMode ? { debugName: "items" } : /* istanbul ignore next */ {}), descendants: true });
|
|
130
|
+
constructor() {
|
|
131
|
+
// Wire the context bus (a header requests a toggle; the coordinator resolves + emits).
|
|
132
|
+
this.ctx.toggle = (value) => this.toggleItem(value);
|
|
133
|
+
// Mirror inputs → context (read-only to children).
|
|
134
|
+
effect(() => this.ctx.expanded.set(this.expanded()));
|
|
135
|
+
effect(() => this.ctx.exclusive.set(this.exclusive()));
|
|
136
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
137
|
+
effect(() => this.warnDuplicateValues());
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/** A header was activated. Resolve the next open-set per the exclusive policy and REQUEST it
|
|
141
|
+
* from the consumer via `(expandedChange)` — never mutate open state internally (ADR 037). */
|
|
142
|
+
toggleItem(value) {
|
|
143
|
+
const open = this.expanded();
|
|
144
|
+
const isOpen = open.includes(value);
|
|
145
|
+
let next;
|
|
146
|
+
if (this.exclusive()) {
|
|
147
|
+
next = isOpen ? [] : [value];
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
next = isOpen ? open.filter((v) => v !== value) : [...open, value];
|
|
151
|
+
}
|
|
152
|
+
this.expandedChange.emit(next);
|
|
153
|
+
}
|
|
154
|
+
/** Dev-only nudge: duplicate item values collide on the shared header/panel id base. */
|
|
155
|
+
warnDuplicateValues() {
|
|
156
|
+
const seen = new Set();
|
|
157
|
+
for (const item of this.items()) {
|
|
158
|
+
const v = item.value();
|
|
159
|
+
if (seen.has(v)) {
|
|
160
|
+
console.warn(`[skraAccordion] duplicate item value="${v}" — header/panel ids will collide; values must be unique within a group.`);
|
|
161
|
+
}
|
|
162
|
+
seen.add(v);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordion, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
166
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.7", type: SkraAccordion, isStandalone: true, selector: "[skraAccordion]", inputs: { expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, exclusive: { classPropertyName: "exclusive", publicName: "exclusive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expandedChange: "expandedChange" }, providers: [SkraAccordionContext], queries: [{ propertyName: "items", predicate: SkraAccordionItem, descendants: true, isSignal: true }], exportAs: ["skraAccordion"], ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: ["@charset \"UTF-8\";:host{display:block;margin:0;box-sizing:border-box;background:var(--skra-comp-accordion-root-background);border-width:var(--skra-comp-accordion-root-border-width);border-style:solid;border-color:var(--skra-comp-accordion-root-border-color);border-radius:var(--skra-comp-accordion-root-radius);overflow:hidden}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
167
|
+
}
|
|
168
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordion, decorators: [{
|
|
169
|
+
type: Component,
|
|
170
|
+
args: [{ selector: '[skraAccordion]', standalone: true, exportAs: 'skraAccordion', template: '<ng-content></ng-content>', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, providers: [SkraAccordionContext], styles: ["@charset \"UTF-8\";:host{display:block;margin:0;box-sizing:border-box;background:var(--skra-comp-accordion-root-background);border-width:var(--skra-comp-accordion-root-border-width);border-style:solid;border-color:var(--skra-comp-accordion-root-border-color);border-radius:var(--skra-comp-accordion-root-radius);overflow:hidden}\n"] }]
|
|
171
|
+
}], ctorParameters: () => [], propDecorators: { expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], exclusive: [{ type: i0.Input, args: [{ isSignal: true, alias: "exclusive", required: false }] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }], items: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SkraAccordionItem), { ...{
|
|
172
|
+
descendants: true,
|
|
173
|
+
}, isSignal: true }] }] } });
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* SkraAccordionHeader — the heading wrapper, a Component on the consumer's heading element
|
|
177
|
+
* (`<h2 skraAccordionHeader>` … `<h6 skraAccordionHeader>` — the consumer picks the level for
|
|
178
|
+
* the document outline; ADR 012 attach-to-native). It wraps a `button[skraAccordionTrigger]`
|
|
179
|
+
* (the Radix Header+Trigger split, the way Material/Carbon/Radix all OWN the heading box rather
|
|
180
|
+
* than leaving a projected heading's UA margin to leak).
|
|
181
|
+
*
|
|
182
|
+
* Its ONLY job is to OWN the heading's box: because Forge is now the heading's host, its Emulated
|
|
183
|
+
* `:host` CSS can reset the UA heading margin (`margin: 0`) so the collapsed item hugs the
|
|
184
|
+
* trigger height — impossible to do from the item, which only sees the heading as projected
|
|
185
|
+
* content (ADR 040 cross-encapsulation limit; the same reason `_form-controls.scss` exists, but
|
|
186
|
+
* here solved structurally without a global slice). Carries no ARIA role of its own (the native
|
|
187
|
+
* heading element provides the heading semantics).
|
|
188
|
+
*/
|
|
189
|
+
class SkraAccordionHeader {
|
|
190
|
+
constructor() {
|
|
191
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
192
|
+
const tag = inject(ElementRef).nativeElement.tagName;
|
|
193
|
+
if (!/^H[1-6]$/.test(tag)) {
|
|
194
|
+
console.warn(`[skraAccordionHeader] is on <${tag.toLowerCase()}> — APG requires the accordion ` +
|
|
195
|
+
'trigger to sit inside a heading element (<h2>…<h6>) for screen-reader heading navigation. ' +
|
|
196
|
+
'Apply it to a heading element.');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
201
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.7", type: SkraAccordionHeader, isStandalone: true, selector: "[skraAccordionHeader]", exportAs: ["skraAccordionHeader"], ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: ["@charset \"UTF-8\";:host{display:block;margin:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
202
|
+
}
|
|
203
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionHeader, decorators: [{
|
|
204
|
+
type: Component,
|
|
205
|
+
args: [{ selector: '[skraAccordionHeader]', standalone: true, exportAs: 'skraAccordionHeader', template: '<ng-content></ng-content>', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, styles: ["@charset \"UTF-8\";:host{display:block;margin:0}\n"] }]
|
|
206
|
+
}], ctorParameters: () => [] });
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Marker for the leading icon/element slot of `button[skraAccordionTrigger]` (the ADR 003
|
|
210
|
+
* `[skra-start]` convention). Detected via `contentChild` (ADR 020 Smart Slots v2.0) to
|
|
211
|
+
* toggle the start wrapper without emitting an empty DOM node. Lib-local (mirrors the
|
|
212
|
+
* Button/Chip per-lib marker) to avoid a cross-lib marker dependency.
|
|
213
|
+
*/
|
|
214
|
+
class SkraAccordionStart {
|
|
215
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionStart, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
216
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.7", type: SkraAccordionStart, isStandalone: true, selector: "[skra-start]", ngImport: i0 });
|
|
217
|
+
}
|
|
218
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionStart, decorators: [{
|
|
219
|
+
type: Directive,
|
|
220
|
+
args: [{
|
|
221
|
+
selector: '[skra-start]',
|
|
222
|
+
standalone: true,
|
|
223
|
+
}]
|
|
224
|
+
}] });
|
|
225
|
+
/**
|
|
226
|
+
* Marker for the optional expand/collapse indicator override of `button[skraAccordionTrigger]`.
|
|
227
|
+
* When present, it replaces the component-rendered default chevron (the ADR 028 slot+fallback
|
|
228
|
+
* idiom — here a presentation override, NOT the loading primitive).
|
|
229
|
+
*/
|
|
230
|
+
class SkraAccordionIndicator {
|
|
231
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionIndicator, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
232
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.7", type: SkraAccordionIndicator, isStandalone: true, selector: "[skra-accordion-indicator]", ngImport: i0 });
|
|
233
|
+
}
|
|
234
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionIndicator, decorators: [{
|
|
235
|
+
type: Directive,
|
|
236
|
+
args: [{
|
|
237
|
+
selector: '[skra-accordion-indicator]',
|
|
238
|
+
standalone: true,
|
|
239
|
+
}]
|
|
240
|
+
}] });
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* SkraAccordionTrigger — the disclosure trigger, a Component on the native command host
|
|
244
|
+
* `button[skraAccordionTrigger]` (ADR 012/040: a `<button>` gives Enter/Space→click + focus
|
|
245
|
+
* for free — the same attach-to-native-button precedent as `button[skraButton]` / `skraTab` /
|
|
246
|
+
* `skraMenuItem`). It is wrapped by `[skraAccordionHeader]` on a heading element (Radix
|
|
247
|
+
* Header+Trigger split) so the heading owns the document outline + its own box/margin.
|
|
248
|
+
* `aria-expanded` is the canonical Toggle state (no native HTML "expanded" attribute on a button
|
|
249
|
+
* → ARIA is correct, boundary #9); the open STYLE keys off `:host([aria-expanded="true"])` (Tabs
|
|
250
|
+
* `aria-selected` precedent). value/ids/open-state come from `SkraAccordionItemContext` — the
|
|
251
|
+
* trigger declares no `value`.
|
|
252
|
+
*
|
|
253
|
+
* **Iron boundary:** no `expanded` / `ariaLabel` / `size` / `severity` inputs.
|
|
254
|
+
*/
|
|
255
|
+
class SkraAccordionTrigger {
|
|
256
|
+
ctx = inject(SkraAccordionItemContext, { optional: true });
|
|
257
|
+
// Smart Slots v2.0 (ADR 020)
|
|
258
|
+
startSlot = contentChild(SkraAccordionStart, ...(ngDevMode ? [{ debugName: "startSlot" }] : /* istanbul ignore next */ []));
|
|
259
|
+
indicatorSlot = contentChild(SkraAccordionIndicator, ...(ngDevMode ? [{ debugName: "indicatorSlot" }] : /* istanbul ignore next */ []));
|
|
260
|
+
hasStart = computed(() => !!this.startSlot(), ...(ngDevMode ? [{ debugName: "hasStart" }] : /* istanbul ignore next */ []));
|
|
261
|
+
hasIndicator = computed(() => !!this.indicatorSlot(), ...(ngDevMode ? [{ debugName: "hasIndicator" }] : /* istanbul ignore next */ []));
|
|
262
|
+
// Derived id / state from the item context (null only on standalone misuse)
|
|
263
|
+
headerId = computed(() => this.ctx?.headerId() ?? null, ...(ngDevMode ? [{ debugName: "headerId" }] : /* istanbul ignore next */ []));
|
|
264
|
+
panelId = computed(() => this.ctx?.panelId() ?? null, ...(ngDevMode ? [{ debugName: "panelId" }] : /* istanbul ignore next */ []));
|
|
265
|
+
ariaExpanded = computed(() => this.ctx ? (this.ctx.expanded() ? 'true' : 'false') : null, ...(ngDevMode ? [{ debugName: "ariaExpanded" }] : /* istanbul ignore next */ []));
|
|
266
|
+
expandedAttr = computed(() => this.ctx?.expanded() ? '' : null, ...(ngDevMode ? [{ debugName: "expandedAttr" }] : /* istanbul ignore next */ []));
|
|
267
|
+
onClick() {
|
|
268
|
+
this.ctx?.toggle();
|
|
269
|
+
}
|
|
270
|
+
constructor() {
|
|
271
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
272
|
+
if (!this.ctx) {
|
|
273
|
+
console.warn('[skraAccordionTrigger] has no [skraAccordionItem] ancestor — it is not wired to a panel ' +
|
|
274
|
+
'(no aria-controls / toggle). Project it inside <element skraAccordionItem>.');
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionTrigger, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
279
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.7", type: SkraAccordionTrigger, isStandalone: true, selector: "button[skraAccordionTrigger]", host: { attributes: { "type": "button" }, listeners: { "click": "onClick()" }, properties: { "attr.id": "headerId()", "attr.aria-controls": "panelId()", "attr.aria-expanded": "ariaExpanded()", "attr.data-skra-expanded": "expandedAttr()", "attr.data-skra-has-start": "hasStart() ? \"\" : null" } }, queries: [{ propertyName: "startSlot", first: true, predicate: SkraAccordionStart, descendants: true, isSignal: true }, { propertyName: "indicatorSlot", first: true, predicate: SkraAccordionIndicator, descendants: true, isSignal: true }], exportAs: ["skraAccordionTrigger"], ngImport: i0, template: "@if (hasStart()) {\n<span class=\"skra-accordion-trigger-start\">\n <ng-content select=\"[skra-start]\"></ng-content>\n</span>\n}\n\n<span class=\"skra-accordion-trigger-label\">\n <ng-content></ng-content>\n</span>\n\n@if (hasIndicator()) {\n<span class=\"skra-accordion-trigger-indicator\">\n <ng-content select=\"[skra-accordion-indicator]\"></ng-content>\n</span>\n} @else {\n<span\n class=\"skra-accordion-trigger-indicator\"\n data-skra-accordion-indicator\n aria-hidden=\"true\"\n></span>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:var(--skra-comp-accordion-header-gap);inline-size:100%;min-block-size:var(--skra-comp-accordion-min-block-size);margin:0;box-sizing:border-box;cursor:pointer;text-align:start;background:var(--skra-comp-accordion-background);color:var(--skra-comp-accordion-foreground);border-width:var(--skra-comp-accordion-border-width);border-style:var(--skra-comp-accordion-border-style);border-color:var(--skra-comp-accordion-border-color);border-radius:var(--skra-comp-accordion-radius);padding-block:var(--skra-comp-accordion-padding-block);padding-inline:var(--skra-comp-accordion-padding-inline);box-shadow:var(--skra-comp-accordion-shadow);font-family:var(--skra-sys-typography-role-label-large-font-family);font-size:var(--skra-sys-typography-role-label-large-font-size);font-weight:var(--skra-sys-typography-role-label-large-font-weight);line-height:var(--skra-sys-typography-role-label-large-line-height);letter-spacing:var(--skra-sys-typography-role-label-large-letter-spacing);transition:background var(--skra-comp-accordion-motion-duration) var(--skra-comp-accordion-motion-easing),color var(--skra-comp-accordion-motion-duration) var(--skra-comp-accordion-motion-easing)}:host(:hover){background:var(--skra-comp-accordion-header-background-hover)}:host(:focus-visible){outline-style:solid;outline-color:var(--skra-comp-accordion-focus-ring-color);outline-width:var(--skra-comp-accordion-focus-ring-width);outline-offset:-2px}:host([aria-expanded=true]){color:var(--skra-comp-accordion-header-foreground-expanded)}.skra-accordion-trigger-start{display:inline-flex;flex-shrink:0;align-items:center;block-size:1lh;--skra-comp-icon-size: var(--skra-comp-accordion-icon-size)}.skra-accordion-trigger-label{flex:1 1 auto;min-inline-size:0}.skra-accordion-trigger-indicator{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;inline-size:var(--skra-comp-accordion-indicator-size);block-size:var(--skra-comp-accordion-indicator-size);color:var(--skra-comp-accordion-indicator-color);transition:transform var(--skra-comp-accordion-motion-duration) var(--skra-comp-accordion-motion-easing)}.skra-accordion-trigger-indicator[data-skra-accordion-indicator]:before{content:\"\";inline-size:.5em;block-size:.5em;border-inline-end:.125em solid currentColor;border-block-end:.125em solid currentColor;transform:translateY(-.15em) rotate(45deg)}:host([aria-expanded=true]) .skra-accordion-trigger-indicator{transform:rotate(180deg)}@media(prefers-reduced-motion:reduce){:host{transition:none}.skra-accordion-trigger-indicator{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
280
|
+
}
|
|
281
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionTrigger, decorators: [{
|
|
282
|
+
type: Component,
|
|
283
|
+
args: [{ selector: 'button[skraAccordionTrigger]', standalone: true, exportAs: 'skraAccordionTrigger', imports: [SkraAccordionStart, SkraAccordionIndicator], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: {
|
|
284
|
+
type: 'button', // never an implicit submit if the accordion sits inside a <form>
|
|
285
|
+
'[attr.id]': 'headerId()',
|
|
286
|
+
'[attr.aria-controls]': 'panelId()',
|
|
287
|
+
'[attr.aria-expanded]': 'ariaExpanded()',
|
|
288
|
+
'[attr.data-skra-expanded]': 'expandedAttr()',
|
|
289
|
+
'[attr.data-skra-has-start]': 'hasStart() ? "" : null',
|
|
290
|
+
'(click)': 'onClick()',
|
|
291
|
+
}, template: "@if (hasStart()) {\n<span class=\"skra-accordion-trigger-start\">\n <ng-content select=\"[skra-start]\"></ng-content>\n</span>\n}\n\n<span class=\"skra-accordion-trigger-label\">\n <ng-content></ng-content>\n</span>\n\n@if (hasIndicator()) {\n<span class=\"skra-accordion-trigger-indicator\">\n <ng-content select=\"[skra-accordion-indicator]\"></ng-content>\n</span>\n} @else {\n<span\n class=\"skra-accordion-trigger-indicator\"\n data-skra-accordion-indicator\n aria-hidden=\"true\"\n></span>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:var(--skra-comp-accordion-header-gap);inline-size:100%;min-block-size:var(--skra-comp-accordion-min-block-size);margin:0;box-sizing:border-box;cursor:pointer;text-align:start;background:var(--skra-comp-accordion-background);color:var(--skra-comp-accordion-foreground);border-width:var(--skra-comp-accordion-border-width);border-style:var(--skra-comp-accordion-border-style);border-color:var(--skra-comp-accordion-border-color);border-radius:var(--skra-comp-accordion-radius);padding-block:var(--skra-comp-accordion-padding-block);padding-inline:var(--skra-comp-accordion-padding-inline);box-shadow:var(--skra-comp-accordion-shadow);font-family:var(--skra-sys-typography-role-label-large-font-family);font-size:var(--skra-sys-typography-role-label-large-font-size);font-weight:var(--skra-sys-typography-role-label-large-font-weight);line-height:var(--skra-sys-typography-role-label-large-line-height);letter-spacing:var(--skra-sys-typography-role-label-large-letter-spacing);transition:background var(--skra-comp-accordion-motion-duration) var(--skra-comp-accordion-motion-easing),color var(--skra-comp-accordion-motion-duration) var(--skra-comp-accordion-motion-easing)}:host(:hover){background:var(--skra-comp-accordion-header-background-hover)}:host(:focus-visible){outline-style:solid;outline-color:var(--skra-comp-accordion-focus-ring-color);outline-width:var(--skra-comp-accordion-focus-ring-width);outline-offset:-2px}:host([aria-expanded=true]){color:var(--skra-comp-accordion-header-foreground-expanded)}.skra-accordion-trigger-start{display:inline-flex;flex-shrink:0;align-items:center;block-size:1lh;--skra-comp-icon-size: var(--skra-comp-accordion-icon-size)}.skra-accordion-trigger-label{flex:1 1 auto;min-inline-size:0}.skra-accordion-trigger-indicator{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;inline-size:var(--skra-comp-accordion-indicator-size);block-size:var(--skra-comp-accordion-indicator-size);color:var(--skra-comp-accordion-indicator-color);transition:transform var(--skra-comp-accordion-motion-duration) var(--skra-comp-accordion-motion-easing)}.skra-accordion-trigger-indicator[data-skra-accordion-indicator]:before{content:\"\";inline-size:.5em;block-size:.5em;border-inline-end:.125em solid currentColor;border-block-end:.125em solid currentColor;transform:translateY(-.15em) rotate(45deg)}:host([aria-expanded=true]) .skra-accordion-trigger-indicator{transform:rotate(180deg)}@media(prefers-reduced-motion:reduce){:host{transition:none}.skra-accordion-trigger-indicator{transition:none}}\n"] }]
|
|
292
|
+
}], ctorParameters: () => [], propDecorators: { startSlot: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SkraAccordionStart), { isSignal: true }] }], indicatorSlot: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SkraAccordionIndicator), { isSignal: true }] }] } });
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* SkraAccordionPanel — the disclosed region, a Component on the consumer's
|
|
296
|
+
* `<div skraAccordionPanel>` (ADR 040). `role="region"`, auto-named by `aria-labelledby`→its
|
|
297
|
+
* header. Collapse/expand is a CSS-only `grid-template-rows: 0fr↔1fr` animation driven by
|
|
298
|
+
* `data-skra-expanded` (ADR 021 — no `[style.*]`); the inner wrapper's `visibility:hidden`
|
|
299
|
+
* at the collapsed end removes content from the a11y tree + Tab order (see accordion-panel.scss).
|
|
300
|
+
* value/ids/open-state come from `SkraAccordionItemContext`.
|
|
301
|
+
*/
|
|
302
|
+
class SkraAccordionPanel {
|
|
303
|
+
ctx = inject(SkraAccordionItemContext, { optional: true });
|
|
304
|
+
panelId = computed(() => this.ctx?.panelId() ?? null, ...(ngDevMode ? [{ debugName: "panelId" }] : /* istanbul ignore next */ []));
|
|
305
|
+
headerId = computed(() => this.ctx?.headerId() ?? null, ...(ngDevMode ? [{ debugName: "headerId" }] : /* istanbul ignore next */ []));
|
|
306
|
+
expandedAttr = computed(() => this.ctx?.expanded() ? '' : null, ...(ngDevMode ? [{ debugName: "expandedAttr" }] : /* istanbul ignore next */ []));
|
|
307
|
+
constructor() {
|
|
308
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
309
|
+
if (!this.ctx) {
|
|
310
|
+
console.warn('[skraAccordionPanel] has no [skraAccordionItem] ancestor — it is not wired to a header ' +
|
|
311
|
+
'(no aria-labelledby / show-hide). Project it inside <element skraAccordionItem>.');
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
316
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.7", type: SkraAccordionPanel, isStandalone: true, selector: "[skraAccordionPanel]", host: { attributes: { "role": "region" }, properties: { "attr.id": "panelId()", "attr.aria-labelledby": "headerId()", "attr.data-skra-expanded": "expandedAttr()" } }, exportAs: ["skraAccordionPanel"], ngImport: i0, template: '<div class="skra-accordion-panel-clip"><div class="skra-accordion-panel-inner"><ng-content></ng-content></div></div>', isInline: true, styles: ["@charset \"UTF-8\";:host{display:grid;grid-template-rows:0fr;margin:0;transition:grid-template-rows var(--skra-comp-accordion-motion-duration) var(--skra-comp-accordion-motion-easing)}:host([data-skra-expanded]){grid-template-rows:1fr}.skra-accordion-panel-clip{overflow:hidden;min-block-size:0;visibility:hidden;transition:visibility var(--skra-comp-accordion-motion-duration) allow-discrete}:host([data-skra-expanded]) .skra-accordion-panel-clip{visibility:visible}.skra-accordion-panel-inner{color:var(--skra-comp-accordion-panel-foreground);padding-block:var(--skra-comp-accordion-panel-padding-block);padding-inline:var(--skra-comp-accordion-panel-padding-inline)}.skra-accordion-panel-inner>:first-child{margin-block-start:0}@media(prefers-reduced-motion:reduce){:host{transition:none}.skra-accordion-panel-clip{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
317
|
+
}
|
|
318
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAccordionPanel, decorators: [{
|
|
319
|
+
type: Component,
|
|
320
|
+
args: [{ selector: '[skraAccordionPanel]', standalone: true, exportAs: 'skraAccordionPanel', template: '<div class="skra-accordion-panel-clip"><div class="skra-accordion-panel-inner"><ng-content></ng-content></div></div>', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: {
|
|
321
|
+
role: 'region',
|
|
322
|
+
'[attr.id]': 'panelId()',
|
|
323
|
+
'[attr.aria-labelledby]': 'headerId()',
|
|
324
|
+
'[attr.data-skra-expanded]': 'expandedAttr()',
|
|
325
|
+
}, styles: ["@charset \"UTF-8\";:host{display:grid;grid-template-rows:0fr;margin:0;transition:grid-template-rows var(--skra-comp-accordion-motion-duration) var(--skra-comp-accordion-motion-easing)}:host([data-skra-expanded]){grid-template-rows:1fr}.skra-accordion-panel-clip{overflow:hidden;min-block-size:0;visibility:hidden;transition:visibility var(--skra-comp-accordion-motion-duration) allow-discrete}:host([data-skra-expanded]) .skra-accordion-panel-clip{visibility:visible}.skra-accordion-panel-inner{color:var(--skra-comp-accordion-panel-foreground);padding-block:var(--skra-comp-accordion-panel-padding-block);padding-inline:var(--skra-comp-accordion-panel-padding-inline)}.skra-accordion-panel-inner>:first-child{margin-block-start:0}@media(prefers-reduced-motion:reduce){:host{transition:none}.skra-accordion-panel-clip{transition:none}}\n"] }]
|
|
326
|
+
}], ctorParameters: () => [] });
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Generated bundle index. Do not edit.
|
|
330
|
+
*/
|
|
331
|
+
|
|
332
|
+
export { SkraAccordion, SkraAccordionContext, SkraAccordionHeader, SkraAccordionIndicator, SkraAccordionItem, SkraAccordionItemContext, SkraAccordionPanel, SkraAccordionStart, SkraAccordionTrigger };
|
|
333
|
+
//# sourceMappingURL=skra-ui-accordion.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skra-ui-accordion.mjs","sources":["../../../../libs/ui/accordion/src/lib/accordion/accordion-context.ts","../../../../libs/ui/accordion/src/lib/accordion/accordion-item-context.ts","../../../../libs/ui/accordion/src/lib/accordion/accordion-item.ts","../../../../libs/ui/accordion/src/lib/accordion/accordion.ts","../../../../libs/ui/accordion/src/lib/accordion/accordion-header.ts","../../../../libs/ui/accordion/src/lib/accordion/accordion.directives.ts","../../../../libs/ui/accordion/src/lib/accordion/accordion-trigger.ts","../../../../libs/ui/accordion/src/lib/accordion/accordion-trigger.html","../../../../libs/ui/accordion/src/lib/accordion/accordion-panel.ts","../../../../libs/ui/accordion/src/skra-ui-accordion.ts"],"sourcesContent":["import { Injectable, signal } from '@angular/core';\n\n/** Module-global counter → a deterministic, unique id base per `[skraAccordion]`\n * instance. Lib-local (mirrors `SkraTabsContext`) so `@skra/disclosure` takes no\n * dependency on another lib just for id generation. Stable across SSR↔hydration\n * (same instantiation order yields the same ids — the standard counter technique). */\nlet accordionInstanceCounter = 0;\n\n/** Sanitize a consumer `value` into an id-safe fragment (no spaces / special chars). */\nfunction idSafe(value: string): string {\n return value.replace(/[^a-zA-Z0-9_-]/g, '-');\n}\n\n/**\n * DI Context provided per `[skraAccordion]` instance — the ADR 013 §3.6 **non-form**\n * Contextual-ID-Sync bus (the 2nd consumer of the idiom after `SkraTabsContext`). It\n * carries **IDs + derived, read-only interaction state only** (`expanded` mirrors the\n * consumer's `[expanded]`; `exclusive` mirrors `[exclusive]`). It **never owns value** —\n * the open/closed set stays consumer-owned (ADR 037); a header requests a change through\n * `toggle()`, which the coordinator implements (resolving the exclusive policy) and from\n * which it emits `(expandedChange)`.\n */\n@Injectable()\nexport class SkraAccordionContext {\n /** Unique per `[skraAccordion]` — the prefix for every header/panel id in this group. */\n private readonly baseId = `skra-accordion-${++accordionInstanceCounter}`;\n\n /** Mirror of the consumer's `[expanded]` — the set of OPEN item values (read-only to children). */\n readonly expanded = signal<readonly string[]>([]);\n /** Mirror of the consumer's `[exclusive]` policy (read-only to children). */\n readonly exclusive = signal<boolean>(false);\n\n headerId(value: string): string {\n return `${this.baseId}-header-${idSafe(value)}`;\n }\n panelId(value: string): string {\n return `${this.baseId}-panel-${idSafe(value)}`;\n }\n isExpanded(value: string): boolean {\n return this.expanded().includes(value);\n }\n\n /** Coordinator-assigned: a header requests a toggle; the coordinator resolves the next\n * open-set (applying the exclusive policy) and emits `(expandedChange)` — never mutated here. */\n toggle: (value: string) => void = () => undefined;\n}\n","import type { Signal } from '@angular/core';\n\n/**\n * Per-item DI context provided by `[skraAccordionItem]` (via `useExisting`). It lets\n * `button[skraAccordionHeader]` and `[skraAccordionPanel]` read their shared `value`,\n * derived ids, and open state **without each re-declaring `value`** — the item declares it\n * once. All members are read-only/derived; `toggle()` forwards to the group coordinator\n * (the open/closed set stays consumer-owned, ADR 037). `*Id` are `null` only when an item\n * is used outside a `[skraAccordion]` (standalone misuse → dev-warned).\n */\nexport abstract class SkraAccordionItemContext {\n abstract readonly value: Signal<string>;\n abstract readonly expanded: Signal<boolean>;\n abstract readonly headerId: Signal<string | null>;\n abstract readonly panelId: Signal<string | null>;\n abstract toggle(): void;\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n inject,\n input,\n} from '@angular/core';\n\nimport { SkraAccordionContext } from './accordion-context';\nimport { SkraAccordionItemContext } from './accordion-item-context';\n\ndeclare const ngDevMode: boolean | undefined;\n\n/**\n * SkraAccordionItem — one item, a Component on the consumer's `<div skraAccordionItem>`\n * (ADR 040, `template: '<ng-content>'`). It declares `[value]` ONCE and provides\n * `SkraAccordionItemContext` (via `useExisting`) so its `button[skraAccordionHeader]` and\n * `[skraAccordionPanel]` read the shared value/ids/open-state without re-declaring it. It\n * owns the per-item top divider (no double borders) and the open-item box (skins may tint it).\n */\n@Component({\n selector: '[skraAccordionItem]',\n standalone: true,\n exportAs: 'skraAccordionItem',\n template: '<ng-content></ng-content>',\n styleUrl: './accordion-item.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n providers: [\n { provide: SkraAccordionItemContext, useExisting: SkraAccordionItem },\n ],\n host: {\n '[attr.data-skra-expanded]': 'expanded() ? \"\" : null',\n },\n})\nexport class SkraAccordionItem implements SkraAccordionItemContext {\n /** The item key — matched against `[expanded]` and the id base for its header/panel. */\n readonly value = input.required<string>();\n\n private readonly group = inject(SkraAccordionContext, { optional: true });\n\n readonly expanded = computed(\n () => this.group?.isExpanded(this.value()) ?? false,\n );\n readonly headerId = computed(\n () => this.group?.headerId(this.value()) ?? null,\n );\n readonly panelId = computed(() => this.group?.panelId(this.value()) ?? null);\n\n toggle(): void {\n this.group?.toggle(this.value());\n }\n\n constructor() {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!this.group) {\n console.warn(\n '[skraAccordionItem] has no [skraAccordion] ancestor — its header/panel are not wired ' +\n '(no aria-controls / open state). Project it inside <element skraAccordion>.',\n );\n }\n }\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n booleanAttribute,\n contentChildren,\n effect,\n inject,\n input,\n output,\n} from '@angular/core';\n\nimport { SkraAccordionContext } from './accordion-context';\nimport { SkraAccordionItem } from './accordion-item';\n\ndeclare const ngDevMode: boolean | undefined;\n\n/**\n * SkraAccordion — the WAI-ARIA APG **Accordion** coordinator. A Component on a wrapping\n * element that holds `[skraAccordionItem]` children (each item wraps a\n * `button[skraAccordionHeader]` + a `[skraAccordionPanel]`). It provides\n * `SkraAccordionContext` (the ADR 013 §3.6 non-form Contextual-ID-Sync bus), owns the\n * consumer-facing `[expanded]` / `(expandedChange)` (controlled, ADR 037 — NO internal open\n * state) and the `[exclusive]` policy, and draws the group's outer border + radius.\n *\n * <div skraAccordion [expanded]=\"open()\" (expandedChange)=\"open.set($event)\">\n * <div skraAccordionItem value=\"general\">\n * <h3><button skraAccordionHeader>General</button></h3>\n * <div skraAccordionPanel>…</div>\n * </div>\n * <div skraAccordionItem value=\"security\"> … </div>\n * </div>\n *\n * Open state is consumer-owned: a header click emits `(expandedChange)` with the resolved\n * next set (the `[exclusive]` policy applied here); the visible state updates when the\n * consumer round-trips `[expanded]`. `[exclusive]` is a POLICY flag on an invariant\n * `string[]` value — NOT a value-type switch, so it does not trigger ADR 0046.\n *\n * Full contract: adr/specs/component-accordion-spec.md.\n */\n@Component({\n selector: '[skraAccordion]',\n standalone: true,\n exportAs: 'skraAccordion',\n template: '<ng-content></ng-content>',\n styleUrl: './accordion.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n providers: [SkraAccordionContext],\n})\nexport class SkraAccordion {\n /** Consumer-owned set of OPEN item values (ADR 037). `[]` = all closed; order irrelevant. */\n readonly expanded = input<readonly string[]>([]);\n /** Policy: `true` → opening one item emits a set that drops the others (single-open). */\n readonly exclusive = input(false, { transform: booleanAttribute });\n /** Fires ONLY on user toggle — never on a programmatic `[expanded]` change. Carries the resolved next set. */\n readonly expandedChange = output<readonly string[]>();\n\n private readonly ctx = inject(SkraAccordionContext);\n private readonly items = contentChildren(SkraAccordionItem, {\n descendants: true,\n });\n\n constructor() {\n // Wire the context bus (a header requests a toggle; the coordinator resolves + emits).\n this.ctx.toggle = (value) => this.toggleItem(value);\n\n // Mirror inputs → context (read-only to children).\n effect(() => this.ctx.expanded.set(this.expanded()));\n effect(() => this.ctx.exclusive.set(this.exclusive()));\n\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n effect(() => this.warnDuplicateValues());\n }\n }\n\n /** A header was activated. Resolve the next open-set per the exclusive policy and REQUEST it\n * from the consumer via `(expandedChange)` — never mutate open state internally (ADR 037). */\n private toggleItem(value: string): void {\n const open = this.expanded();\n const isOpen = open.includes(value);\n let next: readonly string[];\n if (this.exclusive()) {\n next = isOpen ? [] : [value];\n } else {\n next = isOpen ? open.filter((v) => v !== value) : [...open, value];\n }\n this.expandedChange.emit(next);\n }\n\n /** Dev-only nudge: duplicate item values collide on the shared header/panel id base. */\n private warnDuplicateValues(): void {\n const seen = new Set<string>();\n for (const item of this.items()) {\n const v = item.value();\n if (seen.has(v)) {\n console.warn(\n `[skraAccordion] duplicate item value=\"${v}\" — header/panel ids will collide; values must be unique within a group.`,\n );\n }\n seen.add(v);\n }\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n inject,\n} from '@angular/core';\n\ndeclare const ngDevMode: boolean | undefined;\n\n/**\n * SkraAccordionHeader — the heading wrapper, a Component on the consumer's heading element\n * (`<h2 skraAccordionHeader>` … `<h6 skraAccordionHeader>` — the consumer picks the level for\n * the document outline; ADR 012 attach-to-native). It wraps a `button[skraAccordionTrigger]`\n * (the Radix Header+Trigger split, the way Material/Carbon/Radix all OWN the heading box rather\n * than leaving a projected heading's UA margin to leak).\n *\n * Its ONLY job is to OWN the heading's box: because Forge is now the heading's host, its Emulated\n * `:host` CSS can reset the UA heading margin (`margin: 0`) so the collapsed item hugs the\n * trigger height — impossible to do from the item, which only sees the heading as projected\n * content (ADR 040 cross-encapsulation limit; the same reason `_form-controls.scss` exists, but\n * here solved structurally without a global slice). Carries no ARIA role of its own (the native\n * heading element provides the heading semantics).\n */\n@Component({\n selector: '[skraAccordionHeader]',\n standalone: true,\n exportAs: 'skraAccordionHeader',\n template: '<ng-content></ng-content>',\n styleUrl: './accordion-header.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n})\nexport class SkraAccordionHeader {\n constructor() {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n const tag =\n inject<ElementRef<HTMLElement>>(ElementRef).nativeElement.tagName;\n if (!/^H[1-6]$/.test(tag)) {\n console.warn(\n `[skraAccordionHeader] is on <${tag.toLowerCase()}> — APG requires the accordion ` +\n 'trigger to sit inside a heading element (<h2>…<h6>) for screen-reader heading navigation. ' +\n 'Apply it to a heading element.',\n );\n }\n }\n }\n}\n","import { Directive } from '@angular/core';\n\n/**\n * Marker for the leading icon/element slot of `button[skraAccordionTrigger]` (the ADR 003\n * `[skra-start]` convention). Detected via `contentChild` (ADR 020 Smart Slots v2.0) to\n * toggle the start wrapper without emitting an empty DOM node. Lib-local (mirrors the\n * Button/Chip per-lib marker) to avoid a cross-lib marker dependency.\n */\n@Directive({\n selector: '[skra-start]',\n standalone: true,\n})\nexport class SkraAccordionStart {}\n\n/**\n * Marker for the optional expand/collapse indicator override of `button[skraAccordionTrigger]`.\n * When present, it replaces the component-rendered default chevron (the ADR 028 slot+fallback\n * idiom — here a presentation override, NOT the loading primitive).\n */\n@Directive({\n selector: '[skra-accordion-indicator]',\n standalone: true,\n})\nexport class SkraAccordionIndicator {}\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n contentChild,\n inject,\n} from '@angular/core';\n\nimport {\n SkraAccordionIndicator,\n SkraAccordionStart,\n} from './accordion.directives';\nimport { SkraAccordionItemContext } from './accordion-item-context';\n\ndeclare const ngDevMode: boolean | undefined;\n\n/**\n * SkraAccordionTrigger — the disclosure trigger, a Component on the native command host\n * `button[skraAccordionTrigger]` (ADR 012/040: a `<button>` gives Enter/Space→click + focus\n * for free — the same attach-to-native-button precedent as `button[skraButton]` / `skraTab` /\n * `skraMenuItem`). It is wrapped by `[skraAccordionHeader]` on a heading element (Radix\n * Header+Trigger split) so the heading owns the document outline + its own box/margin.\n * `aria-expanded` is the canonical Toggle state (no native HTML \"expanded\" attribute on a button\n * → ARIA is correct, boundary #9); the open STYLE keys off `:host([aria-expanded=\"true\"])` (Tabs\n * `aria-selected` precedent). value/ids/open-state come from `SkraAccordionItemContext` — the\n * trigger declares no `value`.\n *\n * **Iron boundary:** no `expanded` / `ariaLabel` / `size` / `severity` inputs.\n */\n@Component({\n selector: 'button[skraAccordionTrigger]',\n standalone: true,\n exportAs: 'skraAccordionTrigger',\n imports: [SkraAccordionStart, SkraAccordionIndicator],\n templateUrl: './accordion-trigger.html',\n styleUrl: './accordion-trigger.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n type: 'button', // never an implicit submit if the accordion sits inside a <form>\n '[attr.id]': 'headerId()',\n '[attr.aria-controls]': 'panelId()',\n '[attr.aria-expanded]': 'ariaExpanded()',\n '[attr.data-skra-expanded]': 'expandedAttr()',\n '[attr.data-skra-has-start]': 'hasStart() ? \"\" : null',\n '(click)': 'onClick()',\n },\n})\nexport class SkraAccordionTrigger {\n private readonly ctx = inject(SkraAccordionItemContext, { optional: true });\n\n // Smart Slots v2.0 (ADR 020)\n protected readonly startSlot = contentChild(SkraAccordionStart);\n protected readonly indicatorSlot = contentChild(SkraAccordionIndicator);\n protected readonly hasStart = computed(() => !!this.startSlot());\n protected readonly hasIndicator = computed(() => !!this.indicatorSlot());\n\n // Derived id / state from the item context (null only on standalone misuse)\n protected readonly headerId = computed(() => this.ctx?.headerId() ?? null);\n protected readonly panelId = computed(() => this.ctx?.panelId() ?? null);\n protected readonly ariaExpanded = computed(() =>\n this.ctx ? (this.ctx.expanded() ? 'true' : 'false') : null,\n );\n protected readonly expandedAttr = computed(() =>\n this.ctx?.expanded() ? '' : null,\n );\n\n protected onClick(): void {\n this.ctx?.toggle();\n }\n\n constructor() {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!this.ctx) {\n console.warn(\n '[skraAccordionTrigger] has no [skraAccordionItem] ancestor — it is not wired to a panel ' +\n '(no aria-controls / toggle). Project it inside <element skraAccordionItem>.',\n );\n }\n }\n }\n}\n","@if (hasStart()) {\n<span class=\"skra-accordion-trigger-start\">\n <ng-content select=\"[skra-start]\"></ng-content>\n</span>\n}\n\n<span class=\"skra-accordion-trigger-label\">\n <ng-content></ng-content>\n</span>\n\n@if (hasIndicator()) {\n<span class=\"skra-accordion-trigger-indicator\">\n <ng-content select=\"[skra-accordion-indicator]\"></ng-content>\n</span>\n} @else {\n<span\n class=\"skra-accordion-trigger-indicator\"\n data-skra-accordion-indicator\n aria-hidden=\"true\"\n></span>\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n inject,\n} from '@angular/core';\n\nimport { SkraAccordionItemContext } from './accordion-item-context';\n\ndeclare const ngDevMode: boolean | undefined;\n\n/**\n * SkraAccordionPanel — the disclosed region, a Component on the consumer's\n * `<div skraAccordionPanel>` (ADR 040). `role=\"region\"`, auto-named by `aria-labelledby`→its\n * header. Collapse/expand is a CSS-only `grid-template-rows: 0fr↔1fr` animation driven by\n * `data-skra-expanded` (ADR 021 — no `[style.*]`); the inner wrapper's `visibility:hidden`\n * at the collapsed end removes content from the a11y tree + Tab order (see accordion-panel.scss).\n * value/ids/open-state come from `SkraAccordionItemContext`.\n */\n@Component({\n selector: '[skraAccordionPanel]',\n standalone: true,\n exportAs: 'skraAccordionPanel',\n template:\n '<div class=\"skra-accordion-panel-clip\"><div class=\"skra-accordion-panel-inner\"><ng-content></ng-content></div></div>',\n styleUrl: './accordion-panel.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n role: 'region',\n '[attr.id]': 'panelId()',\n '[attr.aria-labelledby]': 'headerId()',\n '[attr.data-skra-expanded]': 'expandedAttr()',\n },\n})\nexport class SkraAccordionPanel {\n private readonly ctx = inject(SkraAccordionItemContext, { optional: true });\n\n protected readonly panelId = computed(() => this.ctx?.panelId() ?? null);\n protected readonly headerId = computed(() => this.ctx?.headerId() ?? null);\n protected readonly expandedAttr = computed(() =>\n this.ctx?.expanded() ? '' : null,\n );\n\n constructor() {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!this.ctx) {\n console.warn(\n '[skraAccordionPanel] has no [skraAccordionItem] ancestor — it is not wired to a header ' +\n '(no aria-labelledby / show-hide). Project it inside <element skraAccordionItem>.',\n );\n }\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Directive, input, booleanAttribute, output, contentChild, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Marker directive for the leading icon slot of `<skra-alert>`.
|
|
6
|
+
* Detected via `contentChild` (ADR 020 Smart Slots v2.0) to toggle the icon
|
|
7
|
+
* wrapper without emitting an empty DOM node. Feedback-local (not the button
|
|
8
|
+
* lib's `[skra-start]`) to avoid a cross-lib marker dependency.
|
|
9
|
+
*/
|
|
10
|
+
class SkraAlertIcon {
|
|
11
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAlertIcon, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
12
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.7", type: SkraAlertIcon, isStandalone: true, selector: "[skra-alert-icon]", ngImport: i0 });
|
|
13
|
+
}
|
|
14
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAlertIcon, decorators: [{
|
|
15
|
+
type: Directive,
|
|
16
|
+
args: [{
|
|
17
|
+
selector: '[skra-alert-icon]',
|
|
18
|
+
standalone: true,
|
|
19
|
+
}]
|
|
20
|
+
}] });
|
|
21
|
+
/**
|
|
22
|
+
* Marker directive for the OPTIONAL title slot of `<skra-alert>` — a short, bold
|
|
23
|
+
* heading rendered above the message. Detected via `contentChild` (ADR 020) to
|
|
24
|
+
* toggle the title row. It is styled bold via a typography role but is NOT a
|
|
25
|
+
* semantic heading (`<h*>`): an alert title is not part of the document outline,
|
|
26
|
+
* and a heading would pollute screen-reader heading navigation (especially for a
|
|
27
|
+
* dynamically-injected alert). The live region announces title + body atomically.
|
|
28
|
+
*/
|
|
29
|
+
class SkraAlertTitle {
|
|
30
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAlertTitle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
31
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.7", type: SkraAlertTitle, isStandalone: true, selector: "[skra-alert-title]", ngImport: i0 });
|
|
32
|
+
}
|
|
33
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAlertTitle, decorators: [{
|
|
34
|
+
type: Directive,
|
|
35
|
+
args: [{
|
|
36
|
+
selector: '[skra-alert-title]',
|
|
37
|
+
standalone: true,
|
|
38
|
+
}]
|
|
39
|
+
}] });
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* `<skra-alert>` — in-content, page/section-level feedback message (Feedback/Status
|
|
43
|
+
* family, ADR 0052). Serves BOTH a static notification (`live="off"`, present at load)
|
|
44
|
+
* and a dynamically-injected alert (`live="polite"|"assertive"`, announced on insertion).
|
|
45
|
+
*
|
|
46
|
+
* SRP-distinct from `<skra-error>` (form-validation-bound, `SkraFieldContext`, error-only).
|
|
47
|
+
*
|
|
48
|
+
* Announcement (ADR 0052): the `live` input maps to the implicit-live ARIA role
|
|
49
|
+
* (`status`/`alert`) — which carries `aria-live` + `aria-atomic` implicitly. NO explicit
|
|
50
|
+
* `aria-live` is set (that would be redundant/contradictory; the `skra-error` pattern).
|
|
51
|
+
*
|
|
52
|
+
* Dismissal: `dismissible` renders a built-in close control that emits `(dismissed)`.
|
|
53
|
+
* Forge does NOT remove itself from the DOM — the consumer owns removal via `@if`
|
|
54
|
+
* (agnostic-atom doctrine). The close control's accessible name comes from a projected
|
|
55
|
+
* `[skra-alert-close-label]` (sr-only; ADR 033 Path 2) — the "×" glyph is `aria-hidden`.
|
|
56
|
+
*/
|
|
57
|
+
class SkraAlert {
|
|
58
|
+
// --- Variant Surface (ADR 035) ---
|
|
59
|
+
intent = input('neutral', ...(ngDevMode ? [{ debugName: "intent" }] : /* istanbul ignore next */ []));
|
|
60
|
+
emphasis = input('medium', ...(ngDevMode ? [{ debugName: "emphasis" }] : /* istanbul ignore next */ []));
|
|
61
|
+
// --- Announcement (ADR 0052) ---
|
|
62
|
+
live = input('off', ...(ngDevMode ? [{ debugName: "live" }] : /* istanbul ignore next */ []));
|
|
63
|
+
// --- Dismissal ---
|
|
64
|
+
dismissible = input(false, { ...(ngDevMode ? { debugName: "dismissible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
65
|
+
dismissed = output();
|
|
66
|
+
// --- Smart Slots v2.0 (ADR 020) ---
|
|
67
|
+
iconSlot = contentChild(SkraAlertIcon, ...(ngDevMode ? [{ debugName: "iconSlot" }] : /* istanbul ignore next */ []));
|
|
68
|
+
hasIcon = computed(() => !!this.iconSlot(), ...(ngDevMode ? [{ debugName: "hasIcon" }] : /* istanbul ignore next */ []));
|
|
69
|
+
titleSlot = contentChild(SkraAlertTitle, ...(ngDevMode ? [{ debugName: "titleSlot" }] : /* istanbul ignore next */ []));
|
|
70
|
+
hasTitle = computed(() => !!this.titleSlot(), ...(ngDevMode ? [{ debugName: "hasTitle" }] : /* istanbul ignore next */ []));
|
|
71
|
+
/**
|
|
72
|
+
* Map `live` politeness to the implicit-live ARIA role (ADR 0052). The role
|
|
73
|
+
* carries `aria-live` + `aria-atomic` implicitly; `off` → no live region.
|
|
74
|
+
*/
|
|
75
|
+
liveRole = computed(() => {
|
|
76
|
+
switch (this.live()) {
|
|
77
|
+
case 'assertive':
|
|
78
|
+
return 'alert';
|
|
79
|
+
case 'polite':
|
|
80
|
+
return 'status';
|
|
81
|
+
default:
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}, ...(ngDevMode ? [{ debugName: "liveRole" }] : /* istanbul ignore next */ []));
|
|
85
|
+
onDismiss() {
|
|
86
|
+
this.dismissed.emit();
|
|
87
|
+
}
|
|
88
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAlert, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
89
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.7", type: SkraAlert, isStandalone: true, selector: "skra-alert", inputs: { intent: { classPropertyName: "intent", publicName: "intent", isSignal: true, isRequired: false, transformFunction: null }, emphasis: { classPropertyName: "emphasis", publicName: "emphasis", isSignal: true, isRequired: false, transformFunction: null }, live: { classPropertyName: "live", publicName: "live", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed" }, host: { properties: { "attr.data-skra-intent": "intent()", "attr.data-skra-emphasis": "emphasis()", "attr.role": "liveRole()", "attr.data-skra-has-icon": "hasIcon() ? \"\" : null", "attr.data-skra-has-title": "hasTitle() ? \"\" : null" } }, queries: [{ propertyName: "iconSlot", first: true, predicate: SkraAlertIcon, descendants: true, isSignal: true }, { propertyName: "titleSlot", first: true, predicate: SkraAlertTitle, descendants: true, isSignal: true }], ngImport: i0, template: "@if (hasIcon()) {\n<span class=\"skra-alert-icon\">\n <ng-content select=\"[skra-alert-icon]\"></ng-content>\n</span>\n}\n\n<div class=\"skra-alert-content\">\n @if (hasTitle()) {\n <div class=\"skra-alert-title\">\n <ng-content select=\"[skra-alert-title]\"></ng-content>\n </div>\n }\n <div class=\"skra-alert-body\">\n <ng-content></ng-content>\n </div>\n</div>\n\n@if (dismissible()) {\n<button type=\"button\" class=\"skra-alert-dismiss\" (click)=\"onDismiss()\">\n <span class=\"skra-alert-dismiss-glyph\" aria-hidden=\"true\">×</span>\n <ng-content select=\"[skra-alert-close-label]\"></ng-content>\n</button>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:flex-start;box-sizing:border-box;margin:0;gap:var(--skra-comp-alert-icon-gap);font-family:var(--skra-sys-typography-role-body-medium-font-family);font-size:var(--skra-sys-typography-role-body-medium-font-size);font-weight:var(--skra-sys-typography-role-body-medium-font-weight);line-height:var(--skra-sys-typography-role-body-medium-line-height);letter-spacing:var(--skra-sys-typography-role-body-medium-letter-spacing);background:var(--skra-comp-alert-background);color:var(--skra-comp-alert-foreground);border-color:var(--skra-comp-alert-border-color);border-width:var(--skra-comp-alert-border-width);border-style:var(--skra-comp-alert-border-style);border-radius:var(--skra-comp-alert-radius);padding-block:var(--skra-comp-alert-padding-block);padding-inline:var(--skra-comp-alert-padding-inline);box-shadow:var(--skra-comp-alert-shadow)}:host([data-skra-emphasis=high]){--skra-comp-alert-border-width: 0}:host([data-skra-intent=neutral][data-skra-emphasis=high]){--skra-comp-alert-background: var( --skra-comp-alert-background-neutral-high, var(--skra-sys-color-neutral-base) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-neutral-high, var(--skra-sys-color-neutral-contrast) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-neutral-high, transparent )}:host([data-skra-intent=neutral][data-skra-emphasis=medium]){--skra-comp-alert-background: var( --skra-comp-alert-background-neutral-medium, var(--skra-sys-color-neutral-soft) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-neutral-medium, var(--skra-sys-color-neutral-strong) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-neutral-medium, var(--skra-sys-color-neutral-border) )}:host([data-skra-intent=info][data-skra-emphasis=high]){--skra-comp-alert-background: var( --skra-comp-alert-background-info-high, var(--skra-sys-color-info-base) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-info-high, var(--skra-sys-color-info-contrast) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-info-high, transparent )}:host([data-skra-intent=info][data-skra-emphasis=medium]){--skra-comp-alert-background: var( --skra-comp-alert-background-info-medium, var(--skra-sys-color-info-soft) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-info-medium, var(--skra-sys-color-info-strong) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-info-medium, var(--skra-sys-color-info-border) )}:host([data-skra-intent=success][data-skra-emphasis=high]){--skra-comp-alert-background: var( --skra-comp-alert-background-success-high, var(--skra-sys-color-success-base) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-success-high, var(--skra-sys-color-success-contrast) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-success-high, transparent )}:host([data-skra-intent=success][data-skra-emphasis=medium]){--skra-comp-alert-background: var( --skra-comp-alert-background-success-medium, var(--skra-sys-color-success-soft) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-success-medium, var(--skra-sys-color-success-strong) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-success-medium, var(--skra-sys-color-success-border) )}:host([data-skra-intent=warning][data-skra-emphasis=high]){--skra-comp-alert-background: var( --skra-comp-alert-background-warning-high, var(--skra-sys-color-warning-base) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-warning-high, var(--skra-sys-color-warning-contrast) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-warning-high, transparent )}:host([data-skra-intent=warning][data-skra-emphasis=medium]){--skra-comp-alert-background: var( --skra-comp-alert-background-warning-medium, var(--skra-sys-color-warning-soft) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-warning-medium, var(--skra-sys-color-warning-strong) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-warning-medium, var(--skra-sys-color-warning-border) )}:host([data-skra-intent=danger][data-skra-emphasis=high]){--skra-comp-alert-background: var( --skra-comp-alert-background-danger-high, var(--skra-sys-color-danger-base) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-danger-high, var(--skra-sys-color-danger-contrast) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-danger-high, transparent )}:host([data-skra-intent=danger][data-skra-emphasis=medium]){--skra-comp-alert-background: var( --skra-comp-alert-background-danger-medium, var(--skra-sys-color-danger-soft) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-danger-medium, var(--skra-sys-color-danger-strong) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-danger-medium, var(--skra-sys-color-danger-border) )}.skra-alert-icon{display:inline-flex;flex-shrink:0;align-items:center;block-size:1lh;--skra-comp-icon-size: var(--skra-comp-alert-icon-size)}.skra-alert-content{flex:1 1 auto;min-inline-size:0;display:flex;flex-direction:column;gap:var(--skra-comp-alert-title-gap)}.skra-alert-title{font-family:var(--skra-sys-typography-role-label-large-font-family);font-size:var(--skra-sys-typography-role-label-large-font-size);font-weight:var(--skra-sys-typography-role-label-large-font-weight);line-height:var(--skra-sys-typography-role-label-large-line-height);letter-spacing:var(--skra-sys-typography-role-label-large-letter-spacing)}.skra-alert-dismiss{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;inline-size:var(--skra-comp-alert-dismiss-size);block-size:var(--skra-comp-alert-dismiss-size);margin:0;padding:0;border:0;background:transparent;color:inherit;cursor:pointer;border-radius:var(--skra-comp-alert-radius);transition:opacity var(--skra-comp-alert-motion-duration) var(--skra-comp-alert-motion-easing)}.skra-alert-dismiss:hover{opacity:.7}.skra-alert-dismiss:focus-visible{outline-style:solid;outline-color:var(--skra-comp-alert-focus-ring-color);outline-width:var(--skra-comp-alert-focus-ring-width);outline-offset:2px}.skra-alert-dismiss-glyph{font-size:1.25em;line-height:1}@media(prefers-reduced-motion:reduce){.skra-alert-dismiss{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
90
|
+
}
|
|
91
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraAlert, decorators: [{
|
|
92
|
+
type: Component,
|
|
93
|
+
args: [{ selector: 'skra-alert', standalone: true, imports: [SkraAlertIcon, SkraAlertTitle], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: {
|
|
94
|
+
// Variant Surface reflection (ADR 035 §3.5)
|
|
95
|
+
'[attr.data-skra-intent]': 'intent()',
|
|
96
|
+
'[attr.data-skra-emphasis]': 'emphasis()',
|
|
97
|
+
// Announcement role (ADR 0052) — implicit-live role ONLY; never an explicit aria-live.
|
|
98
|
+
'[attr.role]': 'liveRole()',
|
|
99
|
+
// Smart Slots layout reflection (ADR 020 v2.0 — slot-presence, State-Surface-exempt §3.6)
|
|
100
|
+
'[attr.data-skra-has-icon]': 'hasIcon() ? "" : null',
|
|
101
|
+
'[attr.data-skra-has-title]': 'hasTitle() ? "" : null',
|
|
102
|
+
}, template: "@if (hasIcon()) {\n<span class=\"skra-alert-icon\">\n <ng-content select=\"[skra-alert-icon]\"></ng-content>\n</span>\n}\n\n<div class=\"skra-alert-content\">\n @if (hasTitle()) {\n <div class=\"skra-alert-title\">\n <ng-content select=\"[skra-alert-title]\"></ng-content>\n </div>\n }\n <div class=\"skra-alert-body\">\n <ng-content></ng-content>\n </div>\n</div>\n\n@if (dismissible()) {\n<button type=\"button\" class=\"skra-alert-dismiss\" (click)=\"onDismiss()\">\n <span class=\"skra-alert-dismiss-glyph\" aria-hidden=\"true\">×</span>\n <ng-content select=\"[skra-alert-close-label]\"></ng-content>\n</button>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:flex-start;box-sizing:border-box;margin:0;gap:var(--skra-comp-alert-icon-gap);font-family:var(--skra-sys-typography-role-body-medium-font-family);font-size:var(--skra-sys-typography-role-body-medium-font-size);font-weight:var(--skra-sys-typography-role-body-medium-font-weight);line-height:var(--skra-sys-typography-role-body-medium-line-height);letter-spacing:var(--skra-sys-typography-role-body-medium-letter-spacing);background:var(--skra-comp-alert-background);color:var(--skra-comp-alert-foreground);border-color:var(--skra-comp-alert-border-color);border-width:var(--skra-comp-alert-border-width);border-style:var(--skra-comp-alert-border-style);border-radius:var(--skra-comp-alert-radius);padding-block:var(--skra-comp-alert-padding-block);padding-inline:var(--skra-comp-alert-padding-inline);box-shadow:var(--skra-comp-alert-shadow)}:host([data-skra-emphasis=high]){--skra-comp-alert-border-width: 0}:host([data-skra-intent=neutral][data-skra-emphasis=high]){--skra-comp-alert-background: var( --skra-comp-alert-background-neutral-high, var(--skra-sys-color-neutral-base) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-neutral-high, var(--skra-sys-color-neutral-contrast) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-neutral-high, transparent )}:host([data-skra-intent=neutral][data-skra-emphasis=medium]){--skra-comp-alert-background: var( --skra-comp-alert-background-neutral-medium, var(--skra-sys-color-neutral-soft) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-neutral-medium, var(--skra-sys-color-neutral-strong) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-neutral-medium, var(--skra-sys-color-neutral-border) )}:host([data-skra-intent=info][data-skra-emphasis=high]){--skra-comp-alert-background: var( --skra-comp-alert-background-info-high, var(--skra-sys-color-info-base) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-info-high, var(--skra-sys-color-info-contrast) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-info-high, transparent )}:host([data-skra-intent=info][data-skra-emphasis=medium]){--skra-comp-alert-background: var( --skra-comp-alert-background-info-medium, var(--skra-sys-color-info-soft) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-info-medium, var(--skra-sys-color-info-strong) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-info-medium, var(--skra-sys-color-info-border) )}:host([data-skra-intent=success][data-skra-emphasis=high]){--skra-comp-alert-background: var( --skra-comp-alert-background-success-high, var(--skra-sys-color-success-base) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-success-high, var(--skra-sys-color-success-contrast) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-success-high, transparent )}:host([data-skra-intent=success][data-skra-emphasis=medium]){--skra-comp-alert-background: var( --skra-comp-alert-background-success-medium, var(--skra-sys-color-success-soft) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-success-medium, var(--skra-sys-color-success-strong) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-success-medium, var(--skra-sys-color-success-border) )}:host([data-skra-intent=warning][data-skra-emphasis=high]){--skra-comp-alert-background: var( --skra-comp-alert-background-warning-high, var(--skra-sys-color-warning-base) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-warning-high, var(--skra-sys-color-warning-contrast) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-warning-high, transparent )}:host([data-skra-intent=warning][data-skra-emphasis=medium]){--skra-comp-alert-background: var( --skra-comp-alert-background-warning-medium, var(--skra-sys-color-warning-soft) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-warning-medium, var(--skra-sys-color-warning-strong) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-warning-medium, var(--skra-sys-color-warning-border) )}:host([data-skra-intent=danger][data-skra-emphasis=high]){--skra-comp-alert-background: var( --skra-comp-alert-background-danger-high, var(--skra-sys-color-danger-base) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-danger-high, var(--skra-sys-color-danger-contrast) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-danger-high, transparent )}:host([data-skra-intent=danger][data-skra-emphasis=medium]){--skra-comp-alert-background: var( --skra-comp-alert-background-danger-medium, var(--skra-sys-color-danger-soft) );--skra-comp-alert-foreground: var( --skra-comp-alert-foreground-danger-medium, var(--skra-sys-color-danger-strong) );--skra-comp-alert-border-color: var( --skra-comp-alert-border-color-danger-medium, var(--skra-sys-color-danger-border) )}.skra-alert-icon{display:inline-flex;flex-shrink:0;align-items:center;block-size:1lh;--skra-comp-icon-size: var(--skra-comp-alert-icon-size)}.skra-alert-content{flex:1 1 auto;min-inline-size:0;display:flex;flex-direction:column;gap:var(--skra-comp-alert-title-gap)}.skra-alert-title{font-family:var(--skra-sys-typography-role-label-large-font-family);font-size:var(--skra-sys-typography-role-label-large-font-size);font-weight:var(--skra-sys-typography-role-label-large-font-weight);line-height:var(--skra-sys-typography-role-label-large-line-height);letter-spacing:var(--skra-sys-typography-role-label-large-letter-spacing)}.skra-alert-dismiss{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;inline-size:var(--skra-comp-alert-dismiss-size);block-size:var(--skra-comp-alert-dismiss-size);margin:0;padding:0;border:0;background:transparent;color:inherit;cursor:pointer;border-radius:var(--skra-comp-alert-radius);transition:opacity var(--skra-comp-alert-motion-duration) var(--skra-comp-alert-motion-easing)}.skra-alert-dismiss:hover{opacity:.7}.skra-alert-dismiss:focus-visible{outline-style:solid;outline-color:var(--skra-comp-alert-focus-ring-color);outline-width:var(--skra-comp-alert-focus-ring-width);outline-offset:2px}.skra-alert-dismiss-glyph{font-size:1.25em;line-height:1}@media(prefers-reduced-motion:reduce){.skra-alert-dismiss{transition:none}}\n"] }]
|
|
103
|
+
}], propDecorators: { intent: [{ type: i0.Input, args: [{ isSignal: true, alias: "intent", required: false }] }], emphasis: [{ type: i0.Input, args: [{ isSignal: true, alias: "emphasis", required: false }] }], live: [{ type: i0.Input, args: [{ isSignal: true, alias: "live", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }], iconSlot: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SkraAlertIcon), { isSignal: true }] }], titleSlot: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SkraAlertTitle), { isSignal: true }] }] } });
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Generated bundle index. Do not edit.
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
export { SkraAlert, SkraAlertIcon, SkraAlertTitle };
|
|
110
|
+
//# sourceMappingURL=skra-ui-alert.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skra-ui-alert.mjs","sources":["../../../../libs/ui/alert/src/lib/alert.directives.ts","../../../../libs/ui/alert/src/lib/alert/alert.ts","../../../../libs/ui/alert/src/lib/alert/alert.html","../../../../libs/ui/alert/src/skra-ui-alert.ts"],"sourcesContent":["import { Directive } from '@angular/core';\n\n/**\n * Marker directive for the leading icon slot of `<skra-alert>`.\n * Detected via `contentChild` (ADR 020 Smart Slots v2.0) to toggle the icon\n * wrapper without emitting an empty DOM node. Feedback-local (not the button\n * lib's `[skra-start]`) to avoid a cross-lib marker dependency.\n */\n@Directive({\n selector: '[skra-alert-icon]',\n standalone: true,\n})\nexport class SkraAlertIcon {}\n\n/**\n * Marker directive for the OPTIONAL title slot of `<skra-alert>` — a short, bold\n * heading rendered above the message. Detected via `contentChild` (ADR 020) to\n * toggle the title row. It is styled bold via a typography role but is NOT a\n * semantic heading (`<h*>`): an alert title is not part of the document outline,\n * and a heading would pollute screen-reader heading navigation (especially for a\n * dynamically-injected alert). The live region announces title + body atomically.\n */\n@Directive({\n selector: '[skra-alert-title]',\n standalone: true,\n})\nexport class SkraAlertTitle {}\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n contentChild,\n input,\n output,\n} from '@angular/core';\nimport { SkraAlertIcon, SkraAlertTitle } from '../alert.directives';\n\n/**\n * AlertIntent — semantic feedback meaning (ADR 035 §3.1, downward subset).\n * Excludes the action intents `primary`/`secondary` (meaningless for a status\n * message). Closed enum; extension requires an ADR 035 amendment.\n */\nexport type AlertIntent = 'neutral' | 'info' | 'success' | 'warning' | 'danger';\n\n/**\n * AlertEmphasis — visual loudness within the chosen intent (ADR 035 §3.1, subset).\n * `high` = filled banner, `medium` = soft/tinted. `low` deferred.\n */\nexport type AlertEmphasis = 'high' | 'medium';\n\n/**\n * AlertLive — screen-reader announcement politeness (ADR 0052). Maps to the\n * implicit-live ARIA role; politeness is a property of USE (static vs injected),\n * NOT of intent.\n */\nexport type AlertLive = 'off' | 'polite' | 'assertive';\n\n/**\n * `<skra-alert>` — in-content, page/section-level feedback message (Feedback/Status\n * family, ADR 0052). Serves BOTH a static notification (`live=\"off\"`, present at load)\n * and a dynamically-injected alert (`live=\"polite\"|\"assertive\"`, announced on insertion).\n *\n * SRP-distinct from `<skra-error>` (form-validation-bound, `SkraFieldContext`, error-only).\n *\n * Announcement (ADR 0052): the `live` input maps to the implicit-live ARIA role\n * (`status`/`alert`) — which carries `aria-live` + `aria-atomic` implicitly. NO explicit\n * `aria-live` is set (that would be redundant/contradictory; the `skra-error` pattern).\n *\n * Dismissal: `dismissible` renders a built-in close control that emits `(dismissed)`.\n * Forge does NOT remove itself from the DOM — the consumer owns removal via `@if`\n * (agnostic-atom doctrine). The close control's accessible name comes from a projected\n * `[skra-alert-close-label]` (sr-only; ADR 033 Path 2) — the \"×\" glyph is `aria-hidden`.\n */\n@Component({\n selector: 'skra-alert',\n standalone: true,\n imports: [SkraAlertIcon, SkraAlertTitle],\n templateUrl: './alert.html',\n styleUrl: './alert.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n // Variant Surface reflection (ADR 035 §3.5)\n '[attr.data-skra-intent]': 'intent()',\n '[attr.data-skra-emphasis]': 'emphasis()',\n\n // Announcement role (ADR 0052) — implicit-live role ONLY; never an explicit aria-live.\n '[attr.role]': 'liveRole()',\n\n // Smart Slots layout reflection (ADR 020 v2.0 — slot-presence, State-Surface-exempt §3.6)\n '[attr.data-skra-has-icon]': 'hasIcon() ? \"\" : null',\n '[attr.data-skra-has-title]': 'hasTitle() ? \"\" : null',\n },\n})\nexport class SkraAlert {\n // --- Variant Surface (ADR 035) ---\n readonly intent = input<AlertIntent>('neutral');\n readonly emphasis = input<AlertEmphasis>('medium');\n\n // --- Announcement (ADR 0052) ---\n readonly live = input<AlertLive>('off');\n\n // --- Dismissal ---\n readonly dismissible = input(false, { transform: booleanAttribute });\n readonly dismissed = output<void>();\n\n // --- Smart Slots v2.0 (ADR 020) ---\n readonly iconSlot = contentChild(SkraAlertIcon);\n readonly hasIcon = computed(() => !!this.iconSlot());\n\n readonly titleSlot = contentChild(SkraAlertTitle);\n readonly hasTitle = computed(() => !!this.titleSlot());\n\n /**\n * Map `live` politeness to the implicit-live ARIA role (ADR 0052). The role\n * carries `aria-live` + `aria-atomic` implicitly; `off` → no live region.\n */\n readonly liveRole = computed<'alert' | 'status' | null>(() => {\n switch (this.live()) {\n case 'assertive':\n return 'alert';\n case 'polite':\n return 'status';\n default:\n return null;\n }\n });\n\n protected onDismiss(): void {\n this.dismissed.emit();\n }\n}\n","@if (hasIcon()) {\n<span class=\"skra-alert-icon\">\n <ng-content select=\"[skra-alert-icon]\"></ng-content>\n</span>\n}\n\n<div class=\"skra-alert-content\">\n @if (hasTitle()) {\n <div class=\"skra-alert-title\">\n <ng-content select=\"[skra-alert-title]\"></ng-content>\n </div>\n }\n <div class=\"skra-alert-body\">\n <ng-content></ng-content>\n </div>\n</div>\n\n@if (dismissible()) {\n<button type=\"button\" class=\"skra-alert-dismiss\" (click)=\"onDismiss()\">\n <span class=\"skra-alert-dismiss-glyph\" aria-hidden=\"true\">×</span>\n <ng-content select=\"[skra-alert-close-label]\"></ng-content>\n</button>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|