@skra/ui 0.5.0 → 0.7.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/consumer-guide/README.md +90 -85
- package/consumer-guide/accessible-names.md +2 -1
- package/consumer-guide/custom-components.md +154 -0
- package/consumer-guide/feedback.md +100 -0
- package/consumer-guide/wrapping-patterns.md +98 -90
- package/fesm2022/skra-ui-alert.mjs +55 -6
- package/fesm2022/skra-ui-alert.mjs.map +1 -1
- package/fesm2022/skra-ui-button.mjs +2 -2
- package/fesm2022/skra-ui-button.mjs.map +1 -1
- package/fesm2022/skra-ui-checkbox.mjs +2 -2
- package/fesm2022/skra-ui-checkbox.mjs.map +1 -1
- package/fesm2022/skra-ui-chip.mjs +2 -2
- package/fesm2022/skra-ui-chip.mjs.map +1 -1
- package/fesm2022/skra-ui-core.mjs +30 -5
- package/fesm2022/skra-ui-core.mjs.map +1 -1
- package/fesm2022/skra-ui-input.mjs +2 -2
- package/fesm2022/skra-ui-input.mjs.map +1 -1
- package/fesm2022/skra-ui-menu.mjs +38 -14
- package/fesm2022/skra-ui-menu.mjs.map +1 -1
- package/fesm2022/skra-ui-popover.mjs +25 -9
- package/fesm2022/skra-ui-popover.mjs.map +1 -1
- package/fesm2022/skra-ui-radio.mjs +2 -2
- package/fesm2022/skra-ui-radio.mjs.map +1 -1
- package/fesm2022/skra-ui-rating-display.mjs +2 -2
- package/fesm2022/skra-ui-rating-display.mjs.map +1 -1
- package/fesm2022/skra-ui-star-rating.mjs +2 -2
- package/fesm2022/skra-ui-star-rating.mjs.map +1 -1
- package/fesm2022/skra-ui-switch.mjs +2 -2
- package/fesm2022/skra-ui-switch.mjs.map +1 -1
- package/fesm2022/skra-ui-toast.mjs +2 -2
- package/fesm2022/skra-ui-toast.mjs.map +1 -1
- package/fesm2022/skra-ui-tooltip.mjs +7 -2
- package/fesm2022/skra-ui-tooltip.mjs.map +1 -1
- package/package.json +2 -2
- package/types/skra-ui-alert.d.ts +39 -2
- package/types/skra-ui-alert.d.ts.map +1 -1
- package/types/skra-ui-core.d.ts.map +1 -1
- package/types/skra-ui-menu.d.ts +18 -6
- package/types/skra-ui-menu.d.ts.map +1 -1
- package/types/skra-ui-popover.d.ts +13 -4
- package/types/skra-ui-popover.d.ts.map +1 -1
- package/types/skra-ui-tooltip.d.ts.map +1 -1
|
@@ -1,90 +1,98 @@
|
|
|
1
|
-
# Wrapping Skra in Your Own Components
|
|
2
|
-
|
|
3
|
-
> Load this for: building project-specific components on top of Skra atoms to simplify the
|
|
4
|
-
> API down to the inputs your app actually needs. Governed by the
|
|
5
|
-
> ADR 037 (consumer owns value/ergonomics).
|
|
6
|
-
|
|
7
|
-
## Why wrap, and where the wrapper belongs
|
|
8
|
-
|
|
9
|
-
Skra atoms are deliberately low-level and semantic-only — they ship a11y + tokens + binding
|
|
10
|
-
seams, not app ergonomics. The intended consumption shape is: **your app wraps Skra atoms in
|
|
11
|
-
higher-level components** that expose just the inputs your domain needs.
|
|
12
|
-
|
|
13
|
-
The hard rule: **the wrapper lives in YOUR app (or a consumer library), never back inside
|
|
14
|
-
`@skra/*`.** Pulling app ergonomics into the atom breaks the agnostic contract (ADR 037). If a
|
|
15
|
-
wrapper becomes reusable across several of your apps, promote it to **your own library built ON
|
|
16
|
-
Skra** (`@yourorg/ui`), not into Skra core.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
1
|
+
# Wrapping Skra in Your Own Components
|
|
2
|
+
|
|
3
|
+
> Load this for: building project-specific components on top of Skra atoms to simplify the
|
|
4
|
+
> API down to the inputs your app actually needs. Governed by the _atoms-agnostic_ doctrine +
|
|
5
|
+
> ADR 037 (consumer owns value/ergonomics).
|
|
6
|
+
|
|
7
|
+
## Why wrap, and where the wrapper belongs
|
|
8
|
+
|
|
9
|
+
Skra atoms are deliberately low-level and semantic-only — they ship a11y + tokens + binding
|
|
10
|
+
seams, not app ergonomics. The intended consumption shape is: **your app wraps Skra atoms in
|
|
11
|
+
higher-level components** that expose just the inputs your domain needs.
|
|
12
|
+
|
|
13
|
+
The hard rule: **the wrapper lives in YOUR app (or a consumer library), never back inside
|
|
14
|
+
`@skra/*`.** Pulling app ergonomics into the atom breaks the agnostic contract (ADR 037). If a
|
|
15
|
+
wrapper becomes reusable across several of your apps, promote it to **your own library built ON
|
|
16
|
+
Skra** (`@yourorg/ui`), not into Skra core.
|
|
17
|
+
|
|
18
|
+
**If there is no atom to wrap** — a net-new widget Skra does not ship at all (a scrubber, a
|
|
19
|
+
timeline, a domain visual) — this page does not cover it. Go to `custom-components.md`, which
|
|
20
|
+
gives the token contract that keeps such a component on-skin, on-density and dark-mode-correct.
|
|
21
|
+
|
|
22
|
+
## Pattern 1 — a field wrapper (collapse the field boilerplate)
|
|
23
|
+
|
|
24
|
+
The `<skra-field>` + label + control + hint + error + binding cluster is verbose to repeat.
|
|
25
|
+
Wrap it once:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// app-text-field.component.ts (YOUR code)
|
|
29
|
+
@Component({
|
|
30
|
+
selector: 'app-text-field',
|
|
31
|
+
standalone: true,
|
|
32
|
+
imports: [SkraField, SkraInput, SkraLabelFor, SkraHint, SkraError],
|
|
33
|
+
template: `
|
|
34
|
+
<skra-field>
|
|
35
|
+
<label skraLabelFor>{{ label() }}</label>
|
|
36
|
+
<input skraInput [formField]="field()" />
|
|
37
|
+
@if (hint()) {
|
|
38
|
+
<skra-hint>{{ hint() }}</skra-hint>
|
|
39
|
+
}
|
|
40
|
+
@if (errorText()) {
|
|
41
|
+
<skra-error>{{ errorText() }}</skra-error>
|
|
42
|
+
}
|
|
43
|
+
</skra-field>
|
|
44
|
+
`,
|
|
45
|
+
})
|
|
46
|
+
export class AppTextField {
|
|
47
|
+
readonly label = input.required<string>();
|
|
48
|
+
readonly field = input.required<Field<string>>(); // your Signal Forms node type
|
|
49
|
+
readonly hint = input<string>();
|
|
50
|
+
readonly errorText = input<string>();
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```html
|
|
55
|
+
<!-- call site: domain-minimal API -->
|
|
56
|
+
<app-text-field label="Email" [field]="form().email" hint="We never share it." />
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**What NOT to break when wrapping:**
|
|
60
|
+
|
|
61
|
+
- Don't re-implement a11y — keep the control inside `<skra-field>` so the DI context still
|
|
62
|
+
wires `id`/`for`/`aria-describedby` (ADR 013). Don't add `aria-label` (ADR 033).
|
|
63
|
+
- Don't introduce inline styles to theme — scope tokens with a class (ADR 021).
|
|
64
|
+
- Keep the accessible-name path intact (the projected `<label skraLabelFor>` IS the name).
|
|
65
|
+
|
|
66
|
+
## Pattern 2 — a value-bridge adapter for class-B overlays
|
|
67
|
+
|
|
68
|
+
The class-B overlays (`skra-select`, `skra-datepicker`, `skra-star-rating`, …) need the
|
|
69
|
+
two-binding `[value]`/`(valueChange)` bridge (see `forms-and-binding.md`). If that recurs, the
|
|
70
|
+
sanctioned shape is a **consumer-side adapter directive** that maps a form node ↔
|
|
71
|
+
value/valueChange, so the call site goes back to one binding:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
// app-control.directive.ts (YOUR interop layer — a sketch)
|
|
75
|
+
@Directive({ selector: '[appControl]', standalone: true })
|
|
76
|
+
export class AppControl<T> {
|
|
77
|
+
readonly appControl = input.required<Field<T>>();
|
|
78
|
+
// read [value] from the host element + write back on (valueChange),
|
|
79
|
+
// syncing this.appControl().value() ↔ the field node
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<skra-select [appControl]="form().country">…</skra-select>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
This adapter is **yours**, in your interop layer — it must not live in the atom (ADR 037). The
|
|
88
|
+
friction journal calls this candidate `[skraControl]` (F-3).
|
|
89
|
+
|
|
90
|
+
## The open question — `@skra/angular-interop`? (resolved: not now)
|
|
91
|
+
|
|
92
|
+
If _every_ Angular consumer needs the same value-bridge adapter, there is an argument that
|
|
93
|
+
Skra could ship an **optional, opt-in** `@skra/angular-interop` package — separate from the
|
|
94
|
+
agnostic atoms (atoms stay pure; interop is a voluntary layer on top). **Resolved 2026-06-25
|
|
95
|
+
(ADR 037 §7): DECLINED for now** — with one consumer and a still-iterating Signal Forms API,
|
|
96
|
+
the bridge stays consumer-owned (Pattern 2). The trigger to revisit, then via its own ADR:
|
|
97
|
+
several real consumers feeling the friction AND a stabilised Angular forms API (that ADR must
|
|
98
|
+
first resolve strategy-agnosticism — Signal Forms AND Reactive via a seam, never bless one).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Directive, input, booleanAttribute, output, contentChild, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
2
|
+
import { Directive, input, booleanAttribute, output, contentChild, computed, contentChildren, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Marker directive for the leading icon slot of `<skra-alert>`.
|
|
@@ -37,6 +37,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
|
|
|
37
37
|
standalone: true,
|
|
38
38
|
}]
|
|
39
39
|
}] });
|
|
40
|
+
/**
|
|
41
|
+
* Marker directive for an ACTION of `<skra-alert>` — "what to do next" ("Try again").
|
|
42
|
+
* Put it on each action; several are allowed and keep the consumer's order. Detected via
|
|
43
|
+
* `contentChildren` (ADR 020) to render the actions region below the message only when one
|
|
44
|
+
* exists. The region sits inside the content column, so it never collides with the dismiss
|
|
45
|
+
* control.
|
|
46
|
+
*
|
|
47
|
+
* The action keeps its OWN meaning: the alert never sets or changes a projected button's
|
|
48
|
+
* `intent` / `emphasis` (ADR 0059 R59.1) — a retry inside a danger alert is not a destructive
|
|
49
|
+
* action. What the alert owns is the region's layout and the focus ring its actions draw on the
|
|
50
|
+
* alert's fill (R59.3). Guaranteed legible on the alert's fill (ADR 0059 R59.2 — the gate
|
|
51
|
+
* measures exactly these):
|
|
52
|
+
*
|
|
53
|
+
* | Alert emphasis | Guaranteed actions |
|
|
54
|
+
* | ------------------- | --------------------------------------------------------------- |
|
|
55
|
+
* | `medium` (default) | `neutral` at any emphasis; any intent at `emphasis="high"` |
|
|
56
|
+
* | `high` | any intent at `emphasis="high"` other than the alert's intent |
|
|
57
|
+
*
|
|
58
|
+
* Anything else (a coloured `medium`/`low` action, a `medium`/`low` action on a `high` alert,
|
|
59
|
+
* a `high` action in the alert's own intent) is unsupported. The zero-config
|
|
60
|
+
* `<button skraButton skra-alert-actions>` (`neutral × high`) is guaranteed everywhere except
|
|
61
|
+
* on a `neutral × high` alert. Admitted atom: `button[skraButton]`.
|
|
62
|
+
*
|
|
63
|
+
* Announcement: a live alert (`live="polite"|"assertive"`) announces its whole text, action
|
|
64
|
+
* labels included (the implicit `role` carries `aria-atomic`, ADR 0052) — the label tells the
|
|
65
|
+
* user an action exists.
|
|
66
|
+
*/
|
|
67
|
+
class SkraAlertActions {
|
|
68
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraAlertActions, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
69
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.1", type: SkraAlertActions, isStandalone: true, selector: "[skra-alert-actions]", ngImport: i0 });
|
|
70
|
+
}
|
|
71
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraAlertActions, decorators: [{
|
|
72
|
+
type: Directive,
|
|
73
|
+
args: [{
|
|
74
|
+
selector: '[skra-alert-actions]',
|
|
75
|
+
standalone: true,
|
|
76
|
+
}]
|
|
77
|
+
}] });
|
|
40
78
|
|
|
41
79
|
/**
|
|
42
80
|
* `<skra-alert>` — in-content, page/section-level feedback message (Feedback/Status
|
|
@@ -53,6 +91,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
|
|
|
53
91
|
* Forge does NOT remove itself from the DOM — the consumer owns removal via `@if`
|
|
54
92
|
* (agnostic-atom doctrine). The close control's accessible name comes from a projected
|
|
55
93
|
* `[skra-alert-close-label]` (sr-only; ADR 033 Path 2) — the "×" glyph is `aria-hidden`.
|
|
94
|
+
*
|
|
95
|
+
* Actions (GitHub #4, ADR 0059): mark each next-step button `[skra-alert-actions]`; they render
|
|
96
|
+
* in a region below the message. The alert owns that region's layout and its focus ring, never
|
|
97
|
+
* the actions' meaning — see `SkraAlertActions` for the guaranteed combinations.
|
|
56
98
|
*/
|
|
57
99
|
class SkraAlert {
|
|
58
100
|
// --- Variant Surface (ADR 035) ---
|
|
@@ -75,6 +117,12 @@ class SkraAlert {
|
|
|
75
117
|
...(ngDevMode ? [{ debugName: "titleSlot" }] : /* istanbul ignore next */ []));
|
|
76
118
|
hasTitle = computed(() => !!this.titleSlot(), /* @ts-ignore */
|
|
77
119
|
...(ngDevMode ? [{ debugName: "hasTitle" }] : /* istanbul ignore next */ []));
|
|
120
|
+
// Several actions are allowed (consumer order) — hence contentChildren, not contentChild.
|
|
121
|
+
// The alert never touches their intent/emphasis (ADR 0059 R59.1); see SkraAlertActions.
|
|
122
|
+
actionSlots = contentChildren(SkraAlertActions, /* @ts-ignore */
|
|
123
|
+
...(ngDevMode ? [{ debugName: "actionSlots" }] : /* istanbul ignore next */ []));
|
|
124
|
+
hasActions = computed(() => this.actionSlots().length > 0, /* @ts-ignore */
|
|
125
|
+
...(ngDevMode ? [{ debugName: "hasActions" }] : /* istanbul ignore next */ []));
|
|
78
126
|
/**
|
|
79
127
|
* Map `live` politeness to the implicit-live ARIA role (ADR 0052). The role
|
|
80
128
|
* carries `aria-live` + `aria-atomic` implicitly; `off` → no live region.
|
|
@@ -94,11 +142,11 @@ class SkraAlert {
|
|
|
94
142
|
this.dismissed.emit();
|
|
95
143
|
}
|
|
96
144
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraAlert, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
97
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", 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()) {\r\n<span class=\"skra-alert-icon\">\r\n <ng-content select=\"[skra-alert-icon]\"></ng-content>\r\n</span>\r\n}\r\n\r\n<div class=\"skra-alert-content\">\r\n @if (hasTitle()) {\r\n <div class=\"skra-alert-title\">\r\n <ng-content select=\"[skra-alert-title]\"></ng-content>\r\n </div>\r\n }\r\n <div class=\"skra-alert-body\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n\r\n@if (dismissible()) {\r\n<button type=\"button\" class=\"skra-alert-dismiss\" (click)=\"onDismiss()\">\r\n <span class=\"skra-alert-dismiss-glyph\" aria-hidden=\"true\">×</span>\r\n <ng-content select=\"[skra-alert-close-label]\"></ng-content>\r\n</button>\r\n}\r\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)}@media(hover:hover)and (pointer:fine){.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 });
|
|
145
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", 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", "attr.data-skra-has-actions": "hasActions() ? \"\" : null" } }, queries: [{ propertyName: "iconSlot", first: true, predicate: SkraAlertIcon, descendants: true, isSignal: true }, { propertyName: "titleSlot", first: true, predicate: SkraAlertTitle, descendants: true, isSignal: true }, { propertyName: "actionSlots", predicate: SkraAlertActions, 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 @if (hasActions()) {\n <div class=\"skra-alert-actions\">\n <ng-content select=\"[skra-alert-actions]\"></ng-content>\n </div>\n }\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 );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-neutral-high, var(--skra-sys-color-neutral-contrast) )}: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) );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-neutral-medium, var(--skra-sys-color-focus-ring) )}: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 );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-info-high, var(--skra-sys-color-info-contrast) )}: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) );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-info-medium, var(--skra-sys-color-focus-ring) )}: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 );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-success-high, var(--skra-sys-color-success-contrast) )}: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) );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-success-medium, var(--skra-sys-color-focus-ring) )}: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 );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-warning-high, var(--skra-sys-color-warning-contrast) )}: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) );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-warning-medium, var(--skra-sys-color-focus-ring) )}: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 );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-danger-high, var(--skra-sys-color-danger-contrast) )}: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-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-danger-medium, var(--skra-sys-color-focus-ring) )}.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-actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--skra-comp-alert-actions-gap);padding-block-start:var(--skra-comp-alert-actions-gap);--skra-comp-button-focus-ring-color: var(--skra-comp-alert-focus-ring-color)}.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)}@media(hover:hover)and (pointer:fine){.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 });
|
|
98
146
|
}
|
|
99
147
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraAlert, decorators: [{
|
|
100
148
|
type: Component,
|
|
101
|
-
args: [{ selector: 'skra-alert', standalone: true, imports: [SkraAlertIcon, SkraAlertTitle], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: {
|
|
149
|
+
args: [{ selector: 'skra-alert', standalone: true, imports: [SkraAlertIcon, SkraAlertTitle, SkraAlertActions], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: {
|
|
102
150
|
// Variant Surface reflection (ADR 035 §3.5)
|
|
103
151
|
'[attr.data-skra-intent]': 'intent()',
|
|
104
152
|
'[attr.data-skra-emphasis]': 'emphasis()',
|
|
@@ -107,12 +155,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
|
|
|
107
155
|
// Smart Slots layout reflection (ADR 020 v2.0 — slot-presence, State-Surface-exempt §3.6)
|
|
108
156
|
'[attr.data-skra-has-icon]': 'hasIcon() ? "" : null',
|
|
109
157
|
'[attr.data-skra-has-title]': 'hasTitle() ? "" : null',
|
|
110
|
-
|
|
111
|
-
|
|
158
|
+
'[attr.data-skra-has-actions]': 'hasActions() ? "" : null',
|
|
159
|
+
}, 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 @if (hasActions()) {\n <div class=\"skra-alert-actions\">\n <ng-content select=\"[skra-alert-actions]\"></ng-content>\n </div>\n }\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 );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-neutral-high, var(--skra-sys-color-neutral-contrast) )}: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) );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-neutral-medium, var(--skra-sys-color-focus-ring) )}: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 );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-info-high, var(--skra-sys-color-info-contrast) )}: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) );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-info-medium, var(--skra-sys-color-focus-ring) )}: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 );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-success-high, var(--skra-sys-color-success-contrast) )}: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) );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-success-medium, var(--skra-sys-color-focus-ring) )}: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 );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-warning-high, var(--skra-sys-color-warning-contrast) )}: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) );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-warning-medium, var(--skra-sys-color-focus-ring) )}: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 );--skra-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-danger-high, var(--skra-sys-color-danger-contrast) )}: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-comp-alert-focus-ring-color: var( --skra-comp-alert-focus-ring-color-danger-medium, var(--skra-sys-color-focus-ring) )}.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-actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--skra-comp-alert-actions-gap);padding-block-start:var(--skra-comp-alert-actions-gap);--skra-comp-button-focus-ring-color: var(--skra-comp-alert-focus-ring-color)}.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)}@media(hover:hover)and (pointer:fine){.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"] }]
|
|
160
|
+
}], 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 }] }], actionSlots: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SkraAlertActions), { isSignal: true }] }] } });
|
|
112
161
|
|
|
113
162
|
/**
|
|
114
163
|
* Generated bundle index. Do not edit.
|
|
115
164
|
*/
|
|
116
165
|
|
|
117
|
-
export { SkraAlert, SkraAlertIcon, SkraAlertTitle };
|
|
166
|
+
export { SkraAlert, SkraAlertActions, SkraAlertIcon, SkraAlertTitle };
|
|
118
167
|
//# sourceMappingURL=skra-ui-alert.mjs.map
|
|
@@ -1 +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()) {\r\n<span class=\"skra-alert-icon\">\r\n <ng-content select=\"[skra-alert-icon]\"></ng-content>\r\n</span>\r\n}\r\n\r\n<div class=\"skra-alert-content\">\r\n @if (hasTitle()) {\r\n <div class=\"skra-alert-title\">\r\n <ng-content select=\"[skra-alert-title]\"></ng-content>\r\n </div>\r\n }\r\n <div class=\"skra-alert-body\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n\r\n@if (dismissible()) {\r\n<button type=\"button\" class=\"skra-alert-dismiss\" (click)=\"onDismiss()\">\r\n <span class=\"skra-alert-dismiss-glyph\" aria-hidden=\"true\">×</span>\r\n <ng-content select=\"[skra-alert-close-label]\"></ng-content>\r\n</button>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
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\n/**\n * Marker directive for an ACTION of `<skra-alert>` — \"what to do next\" (\"Try again\").\n * Put it on each action; several are allowed and keep the consumer's order. Detected via\n * `contentChildren` (ADR 020) to render the actions region below the message only when one\n * exists. The region sits inside the content column, so it never collides with the dismiss\n * control.\n *\n * The action keeps its OWN meaning: the alert never sets or changes a projected button's\n * `intent` / `emphasis` (ADR 0059 R59.1) — a retry inside a danger alert is not a destructive\n * action. What the alert owns is the region's layout and the focus ring its actions draw on the\n * alert's fill (R59.3). Guaranteed legible on the alert's fill (ADR 0059 R59.2 — the gate\n * measures exactly these):\n *\n * | Alert emphasis | Guaranteed actions |\n * | ------------------- | --------------------------------------------------------------- |\n * | `medium` (default) | `neutral` at any emphasis; any intent at `emphasis=\"high\"` |\n * | `high` | any intent at `emphasis=\"high\"` other than the alert's intent |\n *\n * Anything else (a coloured `medium`/`low` action, a `medium`/`low` action on a `high` alert,\n * a `high` action in the alert's own intent) is unsupported. The zero-config\n * `<button skraButton skra-alert-actions>` (`neutral × high`) is guaranteed everywhere except\n * on a `neutral × high` alert. Admitted atom: `button[skraButton]`.\n *\n * Announcement: a live alert (`live=\"polite\"|\"assertive\"`) announces its whole text, action\n * labels included (the implicit `role` carries `aria-atomic`, ADR 0052) — the label tells the\n * user an action exists.\n */\n@Directive({\n selector: '[skra-alert-actions]',\n standalone: true,\n})\nexport class SkraAlertActions {}\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n contentChild,\n contentChildren,\n input,\n output,\n} from '@angular/core';\nimport {\n SkraAlertActions,\n SkraAlertIcon,\n SkraAlertTitle,\n} 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 * Actions (GitHub #4, ADR 0059): mark each next-step button `[skra-alert-actions]`; they render\n * in a region below the message. The alert owns that region's layout and its focus ring, never\n * the actions' meaning — see `SkraAlertActions` for the guaranteed combinations.\n */\n@Component({\n selector: 'skra-alert',\n standalone: true,\n imports: [SkraAlertIcon, SkraAlertTitle, SkraAlertActions],\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 '[attr.data-skra-has-actions]': 'hasActions() ? \"\" : 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 // Several actions are allowed (consumer order) — hence contentChildren, not contentChild.\n // The alert never touches their intent/emphasis (ADR 0059 R59.1); see SkraAlertActions.\n readonly actionSlots = contentChildren(SkraAlertActions);\n readonly hasActions = computed(() => this.actionSlots().length > 0);\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 @if (hasActions()) {\n <div class=\"skra-alert-actions\">\n <ng-content select=\"[skra-alert-actions]\"></ng-content>\n </div>\n }\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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"}
|