@skra/ui 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -201
- package/NOTICE +7 -7
- package/README.md +39 -39
- package/consumer-guide/README.md +84 -84
- package/consumer-guide/forms-and-binding.md +19 -3
- package/consumer-guide/layout.md +19 -0
- package/consumer-guide/overlays.md +100 -100
- package/consumer-guide/setup-and-gotchas.md +165 -103
- package/consumer-guide/theming-and-encapsulation.md +129 -115
- package/fesm2022/skra-ui-accordion.mjs +61 -43
- package/fesm2022/skra-ui-accordion.mjs.map +1 -1
- package/fesm2022/skra-ui-alert.mjs +26 -18
- package/fesm2022/skra-ui-alert.mjs.map +1 -1
- package/fesm2022/skra-ui-avatar.mjs +12 -8
- package/fesm2022/skra-ui-avatar.mjs.map +1 -1
- package/fesm2022/skra-ui-badge.mjs +19 -13
- package/fesm2022/skra-ui-badge.mjs.map +1 -1
- package/fesm2022/skra-ui-button.mjs +28 -19
- package/fesm2022/skra-ui-button.mjs.map +1 -1
- package/fesm2022/skra-ui-checkbox.mjs +3 -3
- package/fesm2022/skra-ui-checkbox.mjs.map +1 -1
- package/fesm2022/skra-ui-chip.mjs +15 -11
- package/fesm2022/skra-ui-chip.mjs.map +1 -1
- package/fesm2022/skra-ui-combobox.mjs +135 -130
- package/fesm2022/skra-ui-combobox.mjs.map +1 -1
- package/fesm2022/skra-ui-core.mjs +95 -73
- package/fesm2022/skra-ui-core.mjs.map +1 -1
- package/fesm2022/skra-ui-counter.mjs +9 -6
- package/fesm2022/skra-ui-counter.mjs.map +1 -1
- package/fesm2022/skra-ui-datepicker.mjs +334 -307
- package/fesm2022/skra-ui-datepicker.mjs.map +1 -1
- package/fesm2022/skra-ui-dialog.mjs +5 -4
- package/fesm2022/skra-ui-dialog.mjs.map +1 -1
- package/fesm2022/skra-ui-field.mjs +65 -43
- package/fesm2022/skra-ui-field.mjs.map +1 -1
- package/fesm2022/skra-ui-icon.mjs +5 -4
- package/fesm2022/skra-ui-icon.mjs.map +1 -1
- package/fesm2022/skra-ui-input.mjs +53 -12
- package/fesm2022/skra-ui-input.mjs.map +1 -1
- package/fesm2022/skra-ui-kbd.mjs +3 -3
- package/fesm2022/skra-ui-kbd.mjs.map +1 -1
- package/fesm2022/skra-ui-layout.mjs +33 -21
- package/fesm2022/skra-ui-layout.mjs.map +1 -1
- package/fesm2022/skra-ui-link.mjs +3 -3
- package/fesm2022/skra-ui-link.mjs.map +1 -1
- package/fesm2022/skra-ui-loading-indicator.mjs +3 -3
- package/fesm2022/skra-ui-loading-indicator.mjs.map +1 -1
- package/fesm2022/skra-ui-menu.mjs +8 -7
- package/fesm2022/skra-ui-menu.mjs.map +1 -1
- package/fesm2022/skra-ui-multi-select.mjs +102 -98
- package/fesm2022/skra-ui-multi-select.mjs.map +1 -1
- package/fesm2022/skra-ui-native-select.mjs +35 -17
- package/fesm2022/skra-ui-native-select.mjs.map +1 -1
- package/fesm2022/skra-ui-popover.mjs +5 -4
- package/fesm2022/skra-ui-popover.mjs.map +1 -1
- package/fesm2022/skra-ui-progress.mjs +7 -5
- package/fesm2022/skra-ui-progress.mjs.map +1 -1
- package/fesm2022/skra-ui-radio.mjs +3 -3
- package/fesm2022/skra-ui-radio.mjs.map +1 -1
- package/fesm2022/skra-ui-rating-display.mjs +14 -9
- package/fesm2022/skra-ui-rating-display.mjs.map +1 -1
- package/fesm2022/skra-ui-select.mjs +98 -95
- package/fesm2022/skra-ui-select.mjs.map +1 -1
- package/fesm2022/skra-ui-skeleton.mjs +16 -13
- package/fesm2022/skra-ui-skeleton.mjs.map +1 -1
- package/fesm2022/skra-ui-star-rating.mjs +18 -11
- package/fesm2022/skra-ui-star-rating.mjs.map +1 -1
- package/fesm2022/skra-ui-status-dot.mjs +7 -5
- package/fesm2022/skra-ui-status-dot.mjs.map +1 -1
- package/fesm2022/skra-ui-switch.mjs +3 -3
- package/fesm2022/skra-ui-switch.mjs.map +1 -1
- package/fesm2022/skra-ui-tabs.mjs +43 -29
- package/fesm2022/skra-ui-tabs.mjs.map +1 -1
- package/fesm2022/skra-ui-textarea.mjs +41 -15
- package/fesm2022/skra-ui-textarea.mjs.map +1 -1
- package/fesm2022/skra-ui-toast.mjs +35 -23
- package/fesm2022/skra-ui-toast.mjs.map +1 -1
- package/fesm2022/skra-ui-tooltip.mjs +12 -9
- package/fesm2022/skra-ui-tooltip.mjs.map +1 -1
- package/fesm2022/skra-ui-typography.mjs +9 -6
- package/fesm2022/skra-ui-typography.mjs.map +1 -1
- package/package.json +6 -6
- package/types/skra-ui-field.d.ts +3 -3
- package/types/skra-ui-field.d.ts.map +1 -1
- package/types/skra-ui-input.d.ts +24 -1
- package/types/skra-ui-input.d.ts.map +1 -1
- package/types/skra-ui-native-select.d.ts +9 -1
- package/types/skra-ui-native-select.d.ts.map +1 -1
- package/types/skra-ui-textarea.d.ts +10 -1
- package/types/skra-ui-textarea.d.ts.map +1 -1
|
@@ -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()) {\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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"}
|
|
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';\r\n\r\n/**\r\n * Marker directive for the leading icon slot of `<skra-alert>`.\r\n * Detected via `contentChild` (ADR 020 Smart Slots v2.0) to toggle the icon\r\n * wrapper without emitting an empty DOM node. Feedback-local (not the button\r\n * lib's `[skra-start]`) to avoid a cross-lib marker dependency.\r\n */\r\n@Directive({\r\n selector: '[skra-alert-icon]',\r\n standalone: true,\r\n})\r\nexport class SkraAlertIcon {}\r\n\r\n/**\r\n * Marker directive for the OPTIONAL title slot of `<skra-alert>` — a short, bold\r\n * heading rendered above the message. Detected via `contentChild` (ADR 020) to\r\n * toggle the title row. It is styled bold via a typography role but is NOT a\r\n * semantic heading (`<h*>`): an alert title is not part of the document outline,\r\n * and a heading would pollute screen-reader heading navigation (especially for a\r\n * dynamically-injected alert). The live region announces title + body atomically.\r\n */\r\n@Directive({\r\n selector: '[skra-alert-title]',\r\n standalone: true,\r\n})\r\nexport class SkraAlertTitle {}\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n ViewEncapsulation,\r\n booleanAttribute,\r\n computed,\r\n contentChild,\r\n input,\r\n output,\r\n} from '@angular/core';\r\nimport { SkraAlertIcon, SkraAlertTitle } from '../alert.directives';\r\n\r\n/**\r\n * AlertIntent — semantic feedback meaning (ADR 035 §3.1, downward subset).\r\n * Excludes the action intents `primary`/`secondary` (meaningless for a status\r\n * message). Closed enum; extension requires an ADR 035 amendment.\r\n */\r\nexport type AlertIntent = 'neutral' | 'info' | 'success' | 'warning' | 'danger';\r\n\r\n/**\r\n * AlertEmphasis — visual loudness within the chosen intent (ADR 035 §3.1, subset).\r\n * `high` = filled banner, `medium` = soft/tinted. `low` deferred.\r\n */\r\nexport type AlertEmphasis = 'high' | 'medium';\r\n\r\n/**\r\n * AlertLive — screen-reader announcement politeness (ADR 0052). Maps to the\r\n * implicit-live ARIA role; politeness is a property of USE (static vs injected),\r\n * NOT of intent.\r\n */\r\nexport type AlertLive = 'off' | 'polite' | 'assertive';\r\n\r\n/**\r\n * `<skra-alert>` — in-content, page/section-level feedback message (Feedback/Status\r\n * family, ADR 0052). Serves BOTH a static notification (`live=\"off\"`, present at load)\r\n * and a dynamically-injected alert (`live=\"polite\"|\"assertive\"`, announced on insertion).\r\n *\r\n * SRP-distinct from `<skra-error>` (form-validation-bound, `SkraFieldContext`, error-only).\r\n *\r\n * Announcement (ADR 0052): the `live` input maps to the implicit-live ARIA role\r\n * (`status`/`alert`) — which carries `aria-live` + `aria-atomic` implicitly. NO explicit\r\n * `aria-live` is set (that would be redundant/contradictory; the `skra-error` pattern).\r\n *\r\n * Dismissal: `dismissible` renders a built-in close control that emits `(dismissed)`.\r\n * Forge does NOT remove itself from the DOM — the consumer owns removal via `@if`\r\n * (agnostic-atom doctrine). The close control's accessible name comes from a projected\r\n * `[skra-alert-close-label]` (sr-only; ADR 033 Path 2) — the \"×\" glyph is `aria-hidden`.\r\n */\r\n@Component({\r\n selector: 'skra-alert',\r\n standalone: true,\r\n imports: [SkraAlertIcon, SkraAlertTitle],\r\n templateUrl: './alert.html',\r\n styleUrl: './alert.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.Emulated,\r\n host: {\r\n // Variant Surface reflection (ADR 035 §3.5)\r\n '[attr.data-skra-intent]': 'intent()',\r\n '[attr.data-skra-emphasis]': 'emphasis()',\r\n\r\n // Announcement role (ADR 0052) — implicit-live role ONLY; never an explicit aria-live.\r\n '[attr.role]': 'liveRole()',\r\n\r\n // Smart Slots layout reflection (ADR 020 v2.0 — slot-presence, State-Surface-exempt §3.6)\r\n '[attr.data-skra-has-icon]': 'hasIcon() ? \"\" : null',\r\n '[attr.data-skra-has-title]': 'hasTitle() ? \"\" : null',\r\n },\r\n})\r\nexport class SkraAlert {\r\n // --- Variant Surface (ADR 035) ---\r\n readonly intent = input<AlertIntent>('neutral');\r\n readonly emphasis = input<AlertEmphasis>('medium');\r\n\r\n // --- Announcement (ADR 0052) ---\r\n readonly live = input<AlertLive>('off');\r\n\r\n // --- Dismissal ---\r\n readonly dismissible = input(false, { transform: booleanAttribute });\r\n readonly dismissed = output<void>();\r\n\r\n // --- Smart Slots v2.0 (ADR 020) ---\r\n readonly iconSlot = contentChild(SkraAlertIcon);\r\n readonly hasIcon = computed(() => !!this.iconSlot());\r\n\r\n readonly titleSlot = contentChild(SkraAlertTitle);\r\n readonly hasTitle = computed(() => !!this.titleSlot());\r\n\r\n /**\r\n * Map `live` politeness to the implicit-live ARIA role (ADR 0052). The role\r\n * carries `aria-live` + `aria-atomic` implicitly; `off` → no live region.\r\n */\r\n readonly liveRole = computed<'alert' | 'status' | null>(() => {\r\n switch (this.live()) {\r\n case 'assertive':\r\n return 'alert';\r\n case 'polite':\r\n return 'status';\r\n default:\r\n return null;\r\n }\r\n });\r\n\r\n protected onDismiss(): void {\r\n this.dismissed.emit();\r\n }\r\n}\r\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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"}
|
|
@@ -44,27 +44,31 @@ class SkraAvatar {
|
|
|
44
44
|
* Image URL — a data input (ADR 037; agnostic). Absent or failed-to-load → the projected
|
|
45
45
|
* fallback (initials / icon) shows.
|
|
46
46
|
*/
|
|
47
|
-
src = input(
|
|
47
|
+
src = input(/* @ts-ignore */
|
|
48
|
+
...(ngDevMode ? [undefined, { debugName: "src" }] : /* istanbul ignore next */ []));
|
|
48
49
|
/** Variant Surface Size axis (ADR 035) — the square box dimension + initials scale. */
|
|
49
|
-
size = input('md',
|
|
50
|
+
size = input('md', /* @ts-ignore */
|
|
51
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
50
52
|
/**
|
|
51
53
|
* The `src` value that failed to load, if any. Keyed by URL (not a boolean) so that changing
|
|
52
54
|
* `src` to a new URL re-attempts the image instead of staying on the fallback.
|
|
53
55
|
*/
|
|
54
|
-
failedSrc = signal(null,
|
|
56
|
+
failedSrc = signal(null, /* @ts-ignore */
|
|
57
|
+
...(ngDevMode ? [{ debugName: "failedSrc" }] : /* istanbul ignore next */ []));
|
|
55
58
|
/** Whether the internal `<img>` should render (a `src` is set and has not failed). */
|
|
56
59
|
showImage = computed(() => {
|
|
57
60
|
const current = this.src();
|
|
58
61
|
return !!current && this.failedSrc() !== current;
|
|
59
|
-
},
|
|
62
|
+
}, /* @ts-ignore */
|
|
63
|
+
...(ngDevMode ? [{ debugName: "showImage" }] : /* istanbul ignore next */ []));
|
|
60
64
|
/** The `<img>` failed to load → fall back to the projected content. */
|
|
61
65
|
onImageError() {
|
|
62
66
|
this.failedSrc.set(this.src() ?? null);
|
|
63
67
|
}
|
|
64
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
65
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
68
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraAvatar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
69
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: SkraAvatar, isStandalone: true, selector: "skra-avatar", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-skra-size": "size()", "attr.data-skra-state": "showImage() ? \"image\" : \"fallback\"" } }, ngImport: i0, template: "@if (showImage()) {\r\n<!-- alt=\"\" \u2014 the image is always decorative; the accessible name lives on the host\r\n (consumer native aria-label / adjacent text). ADR 033 Path 3. -->\r\n<img class=\"skra-avatar-image\" [src]=\"src()\" alt=\"\" (error)=\"onImageError()\" />\r\n} @else {\r\n<!-- Fallback (initials / icon) is a decorative visual stand-in \u2014 aria-hidden so it never\r\n competes as a visible accessible name (the name is host-level). ADR 034. -->\r\n<span class=\"skra-avatar-fallback\" aria-hidden=\"true\">\r\n <ng-content></ng-content>\r\n</span>\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;margin:0;overflow:hidden;inline-size:var(--skra-comp-avatar-size-md);block-size:var(--skra-comp-avatar-size-md);font-size:var(--skra-comp-avatar-font-size-md);font-family:var(--skra-sys-typography-role-label-medium-font-family);font-weight:var(--skra-sys-typography-role-label-medium-font-weight);letter-spacing:var(--skra-sys-typography-role-label-medium-letter-spacing);line-height:1;-webkit-user-select:none;user-select:none;background:var(--skra-comp-avatar-background);color:var(--skra-comp-avatar-foreground);border-color:var(--skra-comp-avatar-border-color);border-width:var(--skra-comp-avatar-border-width);border-style:var(--skra-comp-avatar-border-style);border-radius:var(--skra-comp-avatar-radius);padding-block:var(--skra-comp-avatar-padding-block);padding-inline:var(--skra-comp-avatar-padding-inline);box-shadow:var(--skra-comp-avatar-shadow)}:host([data-skra-size=sm]){inline-size:var(--skra-comp-avatar-size-sm);block-size:var(--skra-comp-avatar-size-sm);font-size:var(--skra-comp-avatar-font-size-sm)}:host([data-skra-size=lg]){inline-size:var(--skra-comp-avatar-size-lg);block-size:var(--skra-comp-avatar-size-lg);font-size:var(--skra-comp-avatar-font-size-lg)}.skra-avatar-image{display:block;inline-size:100%;block-size:100%;object-fit:cover;border-radius:inherit}.skra-avatar-fallback{display:inline-flex;align-items:center;justify-content:center;--skra-comp-icon-size: var(--skra-comp-avatar-icon-size)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
66
70
|
}
|
|
67
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
71
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraAvatar, decorators: [{
|
|
68
72
|
type: Component,
|
|
69
73
|
args: [{ selector: 'skra-avatar', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: {
|
|
70
74
|
// Variant Surface reflection (ADR 035 §3.5; ADR 021 — never [style.--var])
|
|
@@ -72,7 +76,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImpor
|
|
|
72
76
|
// Presentational state for SCSS (image painted vs placeholder/fallback). Not an ADR 027
|
|
73
77
|
// State — it is presentational, like a Smart-Slot flag (§3.6 exempt).
|
|
74
78
|
'[attr.data-skra-state]': 'showImage() ? "image" : "fallback"',
|
|
75
|
-
}, template: "@if (showImage()) {\n<!-- alt=\"\" \u2014 the image is always decorative; the accessible name lives on the host\n (consumer native aria-label / adjacent text). ADR 033 Path 3. -->\n<img class=\"skra-avatar-image\" [src]=\"src()\" alt=\"\" (error)=\"onImageError()\" />\n} @else {\n<!-- Fallback (initials / icon) is a decorative visual stand-in \u2014 aria-hidden so it never\n competes as a visible accessible name (the name is host-level). ADR 034. -->\n<span class=\"skra-avatar-fallback\" aria-hidden=\"true\">\n <ng-content></ng-content>\n</span>\n}\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;margin:0;overflow:hidden;inline-size:var(--skra-comp-avatar-size-md);block-size:var(--skra-comp-avatar-size-md);font-size:var(--skra-comp-avatar-font-size-md);font-family:var(--skra-sys-typography-role-label-medium-font-family);font-weight:var(--skra-sys-typography-role-label-medium-font-weight);letter-spacing:var(--skra-sys-typography-role-label-medium-letter-spacing);line-height:1;-webkit-user-select:none;user-select:none;background:var(--skra-comp-avatar-background);color:var(--skra-comp-avatar-foreground);border-color:var(--skra-comp-avatar-border-color);border-width:var(--skra-comp-avatar-border-width);border-style:var(--skra-comp-avatar-border-style);border-radius:var(--skra-comp-avatar-radius);padding-block:var(--skra-comp-avatar-padding-block);padding-inline:var(--skra-comp-avatar-padding-inline);box-shadow:var(--skra-comp-avatar-shadow)}:host([data-skra-size=sm]){inline-size:var(--skra-comp-avatar-size-sm);block-size:var(--skra-comp-avatar-size-sm);font-size:var(--skra-comp-avatar-font-size-sm)}:host([data-skra-size=lg]){inline-size:var(--skra-comp-avatar-size-lg);block-size:var(--skra-comp-avatar-size-lg);font-size:var(--skra-comp-avatar-font-size-lg)}.skra-avatar-image{display:block;inline-size:100%;block-size:100%;object-fit:cover;border-radius:inherit}.skra-avatar-fallback{display:inline-flex;align-items:center;justify-content:center;--skra-comp-icon-size: var(--skra-comp-avatar-icon-size)}\n"] }]
|
|
79
|
+
}, template: "@if (showImage()) {\r\n<!-- alt=\"\" \u2014 the image is always decorative; the accessible name lives on the host\r\n (consumer native aria-label / adjacent text). ADR 033 Path 3. -->\r\n<img class=\"skra-avatar-image\" [src]=\"src()\" alt=\"\" (error)=\"onImageError()\" />\r\n} @else {\r\n<!-- Fallback (initials / icon) is a decorative visual stand-in \u2014 aria-hidden so it never\r\n competes as a visible accessible name (the name is host-level). ADR 034. -->\r\n<span class=\"skra-avatar-fallback\" aria-hidden=\"true\">\r\n <ng-content></ng-content>\r\n</span>\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;margin:0;overflow:hidden;inline-size:var(--skra-comp-avatar-size-md);block-size:var(--skra-comp-avatar-size-md);font-size:var(--skra-comp-avatar-font-size-md);font-family:var(--skra-sys-typography-role-label-medium-font-family);font-weight:var(--skra-sys-typography-role-label-medium-font-weight);letter-spacing:var(--skra-sys-typography-role-label-medium-letter-spacing);line-height:1;-webkit-user-select:none;user-select:none;background:var(--skra-comp-avatar-background);color:var(--skra-comp-avatar-foreground);border-color:var(--skra-comp-avatar-border-color);border-width:var(--skra-comp-avatar-border-width);border-style:var(--skra-comp-avatar-border-style);border-radius:var(--skra-comp-avatar-radius);padding-block:var(--skra-comp-avatar-padding-block);padding-inline:var(--skra-comp-avatar-padding-inline);box-shadow:var(--skra-comp-avatar-shadow)}:host([data-skra-size=sm]){inline-size:var(--skra-comp-avatar-size-sm);block-size:var(--skra-comp-avatar-size-sm);font-size:var(--skra-comp-avatar-font-size-sm)}:host([data-skra-size=lg]){inline-size:var(--skra-comp-avatar-size-lg);block-size:var(--skra-comp-avatar-size-lg);font-size:var(--skra-comp-avatar-font-size-lg)}.skra-avatar-image{display:block;inline-size:100%;block-size:100%;object-fit:cover;border-radius:inherit}.skra-avatar-fallback{display:inline-flex;align-items:center;justify-content:center;--skra-comp-icon-size: var(--skra-comp-avatar-icon-size)}\n"] }]
|
|
76
80
|
}], propDecorators: { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
77
81
|
|
|
78
82
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skra-ui-avatar.mjs","sources":["../../../../libs/ui/avatar/src/lib/avatar/avatar.ts","../../../../libs/ui/avatar/src/lib/avatar/avatar.html","../../../../libs/ui/avatar/src/skra-ui-avatar.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n signal,\n} from '@angular/core';\n\n/**\n * AvatarSize — the Variant Surface Size axis (ADR 035 §3.1, downward subset `sm|md|lg`).\n * `xs`/`xl` are reserved (ADR 035 §3.2) and NOT in MVP — adding them later is purely additive\n * (new enum values + token rows, zero migration). Closed enum; extension requires an ADR 035\n * amendment. See `adr/specs/component-avatar-spec.md` OQ 1.\n */\nexport type AvatarSize = 'sm' | 'md' | 'lg';\n\n/**\n * `<skra-avatar>` — a compact graphical representation of a person/entity: a photo with a\n * graceful fallback to projected **initials** or an **icon** when the image is absent or fails\n * to load. First resident of `libs/ui/data-display` (the identity/media-display family). See\n * `adr/specs/component-avatar-spec.md`.\n *\n * **Element, not a decorated native (ADR 012):** there is no native `<avatar>`, and a bare\n * `<img>` has nowhere to render the text/icon fallback — so Forge owns a container that\n * conditionally renders an internal `<img>` OR the projected fallback. NOT a Web Component\n * (ADR 000).\n *\n * **Image + fallback (the defining value-add):** Forge owns the internal `<img>` (rendered from\n * the `src` *data* input — value not look, ADR 037, agnostic) so it can observe `(error)`/`(load)`\n * and swap to the projected fallback. The swap is internal presentational logic, NOT an ADR 028\n * `loading` operation (no `aria-busy`, no `[skraLoadingIndicator]`). SSR-safe: pure signals +\n * template; on the server the `<img>` renders, the client swaps on error.\n *\n * **Non-interactive (Badge precedent):** no focusable node, no role, no keyboard, no outputs →\n * State Surface all-N/A. A clickable avatar is `button[skraButton]`/`a[skraLink]` wrapping\n * `<skra-avatar>` (composition), not a variant.\n *\n * **Accessible name (ADR 033 Path 3 — graphic host, the SkraIcon/ADR 034 §3.4 contract):** the\n * inner content is **always decorative** — the internal `<img>` is `alt=\"\"` and the fallback\n * wrapper is `aria-hidden` — and the host carries **NO default ARIA**. The consumer declares\n * semantics explicitly, exactly as for `<skra-icon>`:\n * - decorative (Mode A, the ~90% case — avatar beside a visible name) → `aria-hidden=\"true\"`;\n * - meaningful (Mode B — standalone) → **`role=\"img\"` + `aria-label`/`aria-labelledby` TOGETHER**.\n * `role=\"img\"` is REQUIRED: `aria-label` on the roleless custom-element host is ARIA-prohibited\n * (axe `aria-prohibited-attr`) and conveys no name. Forge does NOT auto-set the role (parity\n * with SkraIcon — host owns no default ARIA).\n * NO `ariaLabel` input (ADR 033 boundary #8), NO `name`/`alt` input (no initials derivation —\n * agnostic; the name survives image failure by living on the host, not on the swapped-out img).\n *\n * **Look is skin-owned:** circle-vs-square is the `radius` comp token (a skin with\n * `sys.radius.full: 0` — e.g. brutal — ships square avatars automatically). NO `shape`/`color`/\n * `variant` look-inputs (skin philosophy). NO `intent`/`emphasis` (a neutral identity graphic —\n * status colour is the sibling StatusDot's job, SRP).\n */\n@Component({\n selector: 'skra-avatar',\n standalone: true,\n templateUrl: './avatar.html',\n styleUrl: './avatar.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n // Variant Surface reflection (ADR 035 §3.5; ADR 021 — never [style.--var])\n '[attr.data-skra-size]': 'size()',\n // Presentational state for SCSS (image painted vs placeholder/fallback). Not an ADR 027\n // State — it is presentational, like a Smart-Slot flag (§3.6 exempt).\n '[attr.data-skra-state]': 'showImage() ? \"image\" : \"fallback\"',\n },\n})\nexport class SkraAvatar {\n /**\n * Image URL — a data input (ADR 037; agnostic). Absent or failed-to-load → the projected\n * fallback (initials / icon) shows.\n */\n readonly src = input<string>();\n\n /** Variant Surface Size axis (ADR 035) — the square box dimension + initials scale. */\n readonly size = input<AvatarSize>('md');\n\n /**\n * The `src` value that failed to load, if any. Keyed by URL (not a boolean) so that changing\n * `src` to a new URL re-attempts the image instead of staying on the fallback.\n */\n private readonly failedSrc = signal<string | null>(null);\n\n /** Whether the internal `<img>` should render (a `src` is set and has not failed). */\n readonly showImage = computed(() => {\n const current = this.src();\n return !!current && this.failedSrc() !== current;\n });\n\n /** The `<img>` failed to load → fall back to the projected content. */\n protected onImageError(): void {\n this.failedSrc.set(this.src() ?? null);\n }\n}\n","@if (showImage()) {\n<!-- alt=\"\" — the image is always decorative; the accessible name lives on the host\n (consumer native aria-label / adjacent text). ADR 033 Path 3. -->\n<img class=\"skra-avatar-image\" [src]=\"src()\" alt=\"\" (error)=\"onImageError()\" />\n} @else {\n<!-- Fallback (initials / icon) is a decorative visual stand-in — aria-hidden so it never\n competes as a visible accessible name (the name is host-level). ADR 034. -->\n<span class=\"skra-avatar-fallback\" aria-hidden=\"true\">\n <ng-content></ng-content>\n</span>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCG;MAgBU,UAAU,CAAA;AACrB;;;AAGG;
|
|
1
|
+
{"version":3,"file":"skra-ui-avatar.mjs","sources":["../../../../libs/ui/avatar/src/lib/avatar/avatar.ts","../../../../libs/ui/avatar/src/lib/avatar/avatar.html","../../../../libs/ui/avatar/src/skra-ui-avatar.ts"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n ViewEncapsulation,\r\n computed,\r\n input,\r\n signal,\r\n} from '@angular/core';\r\n\r\n/**\r\n * AvatarSize — the Variant Surface Size axis (ADR 035 §3.1, downward subset `sm|md|lg`).\r\n * `xs`/`xl` are reserved (ADR 035 §3.2) and NOT in MVP — adding them later is purely additive\r\n * (new enum values + token rows, zero migration). Closed enum; extension requires an ADR 035\r\n * amendment. See `adr/specs/component-avatar-spec.md` OQ 1.\r\n */\r\nexport type AvatarSize = 'sm' | 'md' | 'lg';\r\n\r\n/**\r\n * `<skra-avatar>` — a compact graphical representation of a person/entity: a photo with a\r\n * graceful fallback to projected **initials** or an **icon** when the image is absent or fails\r\n * to load. First resident of `libs/ui/data-display` (the identity/media-display family). See\r\n * `adr/specs/component-avatar-spec.md`.\r\n *\r\n * **Element, not a decorated native (ADR 012):** there is no native `<avatar>`, and a bare\r\n * `<img>` has nowhere to render the text/icon fallback — so Forge owns a container that\r\n * conditionally renders an internal `<img>` OR the projected fallback. NOT a Web Component\r\n * (ADR 000).\r\n *\r\n * **Image + fallback (the defining value-add):** Forge owns the internal `<img>` (rendered from\r\n * the `src` *data* input — value not look, ADR 037, agnostic) so it can observe `(error)`/`(load)`\r\n * and swap to the projected fallback. The swap is internal presentational logic, NOT an ADR 028\r\n * `loading` operation (no `aria-busy`, no `[skraLoadingIndicator]`). SSR-safe: pure signals +\r\n * template; on the server the `<img>` renders, the client swaps on error.\r\n *\r\n * **Non-interactive (Badge precedent):** no focusable node, no role, no keyboard, no outputs →\r\n * State Surface all-N/A. A clickable avatar is `button[skraButton]`/`a[skraLink]` wrapping\r\n * `<skra-avatar>` (composition), not a variant.\r\n *\r\n * **Accessible name (ADR 033 Path 3 — graphic host, the SkraIcon/ADR 034 §3.4 contract):** the\r\n * inner content is **always decorative** — the internal `<img>` is `alt=\"\"` and the fallback\r\n * wrapper is `aria-hidden` — and the host carries **NO default ARIA**. The consumer declares\r\n * semantics explicitly, exactly as for `<skra-icon>`:\r\n * - decorative (Mode A, the ~90% case — avatar beside a visible name) → `aria-hidden=\"true\"`;\r\n * - meaningful (Mode B — standalone) → **`role=\"img\"` + `aria-label`/`aria-labelledby` TOGETHER**.\r\n * `role=\"img\"` is REQUIRED: `aria-label` on the roleless custom-element host is ARIA-prohibited\r\n * (axe `aria-prohibited-attr`) and conveys no name. Forge does NOT auto-set the role (parity\r\n * with SkraIcon — host owns no default ARIA).\r\n * NO `ariaLabel` input (ADR 033 boundary #8), NO `name`/`alt` input (no initials derivation —\r\n * agnostic; the name survives image failure by living on the host, not on the swapped-out img).\r\n *\r\n * **Look is skin-owned:** circle-vs-square is the `radius` comp token (a skin with\r\n * `sys.radius.full: 0` — e.g. brutal — ships square avatars automatically). NO `shape`/`color`/\r\n * `variant` look-inputs (skin philosophy). NO `intent`/`emphasis` (a neutral identity graphic —\r\n * status colour is the sibling StatusDot's job, SRP).\r\n */\r\n@Component({\r\n selector: 'skra-avatar',\r\n standalone: true,\r\n templateUrl: './avatar.html',\r\n styleUrl: './avatar.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.Emulated,\r\n host: {\r\n // Variant Surface reflection (ADR 035 §3.5; ADR 021 — never [style.--var])\r\n '[attr.data-skra-size]': 'size()',\r\n // Presentational state for SCSS (image painted vs placeholder/fallback). Not an ADR 027\r\n // State — it is presentational, like a Smart-Slot flag (§3.6 exempt).\r\n '[attr.data-skra-state]': 'showImage() ? \"image\" : \"fallback\"',\r\n },\r\n})\r\nexport class SkraAvatar {\r\n /**\r\n * Image URL — a data input (ADR 037; agnostic). Absent or failed-to-load → the projected\r\n * fallback (initials / icon) shows.\r\n */\r\n readonly src = input<string>();\r\n\r\n /** Variant Surface Size axis (ADR 035) — the square box dimension + initials scale. */\r\n readonly size = input<AvatarSize>('md');\r\n\r\n /**\r\n * The `src` value that failed to load, if any. Keyed by URL (not a boolean) so that changing\r\n * `src` to a new URL re-attempts the image instead of staying on the fallback.\r\n */\r\n private readonly failedSrc = signal<string | null>(null);\r\n\r\n /** Whether the internal `<img>` should render (a `src` is set and has not failed). */\r\n readonly showImage = computed(() => {\r\n const current = this.src();\r\n return !!current && this.failedSrc() !== current;\r\n });\r\n\r\n /** The `<img>` failed to load → fall back to the projected content. */\r\n protected onImageError(): void {\r\n this.failedSrc.set(this.src() ?? null);\r\n }\r\n}\r\n","@if (showImage()) {\r\n<!-- alt=\"\" — the image is always decorative; the accessible name lives on the host\r\n (consumer native aria-label / adjacent text). ADR 033 Path 3. -->\r\n<img class=\"skra-avatar-image\" [src]=\"src()\" alt=\"\" (error)=\"onImageError()\" />\r\n} @else {\r\n<!-- Fallback (initials / icon) is a decorative visual stand-in — aria-hidden so it never\r\n competes as a visible accessible name (the name is host-level). ADR 034. -->\r\n<span class=\"skra-avatar-fallback\" aria-hidden=\"true\">\r\n <ng-content></ng-content>\r\n</span>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCG;MAgBU,UAAU,CAAA;AACrB;;;AAGG;AACM,IAAA,GAAG,GAAG,KAAK;uFAAU;;IAGrB,IAAI,GAAG,KAAK,CAAa,IAAI;6EAAC;AAEvC;;;AAGG;IACc,SAAS,GAAG,MAAM,CAAgB,IAAI;kFAAC;;AAG/C,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAK;AACjC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE;QAC1B,OAAO,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,KAAK,OAAO;IAClD,CAAC;kFAAC;;IAGQ,YAAY,GAAA;AACpB,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC;IACxC;uGAzBW,UAAU,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAV,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAU,ubCtEvB,6kBAWA,EAAA,MAAA,EAAA,CAAA,ihDAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FD2Da,UAAU,EAAA,UAAA,EAAA,CAAA;kBAftB,SAAS;+BACE,aAAa,EAAA,UAAA,EACX,IAAI,EAAA,eAAA,EAGC,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,QAAQ,EAAA,IAAA,EACnC;;AAEJ,wBAAA,uBAAuB,EAAE,QAAQ;;;AAGjC,wBAAA,wBAAwB,EAAE,oCAAoC;AAC/D,qBAAA,EAAA,QAAA,EAAA,6kBAAA,EAAA,MAAA,EAAA,CAAA,ihDAAA,CAAA,EAAA;;;AEpEH;;AAEG;;;;"}
|
|
@@ -13,10 +13,10 @@ import { Directive, input, contentChild, computed, ViewEncapsulation, ChangeDete
|
|
|
13
13
|
* a leading dot enables the `● Active` pattern but never substitutes for the word.
|
|
14
14
|
*/
|
|
15
15
|
class SkraBadgeIcon {
|
|
16
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
17
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
16
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraBadgeIcon, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
17
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.1", type: SkraBadgeIcon, isStandalone: true, selector: "[skra-badge-icon]", ngImport: i0 });
|
|
18
18
|
}
|
|
19
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
19
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraBadgeIcon, decorators: [{
|
|
20
20
|
type: Directive,
|
|
21
21
|
args: [{
|
|
22
22
|
selector: '[skra-badge-icon]',
|
|
@@ -46,13 +46,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImpor
|
|
|
46
46
|
*/
|
|
47
47
|
class SkraBadge {
|
|
48
48
|
// --- Variant Surface (ADR 035) ---
|
|
49
|
-
intent = input('neutral',
|
|
50
|
-
|
|
49
|
+
intent = input('neutral', /* @ts-ignore */
|
|
50
|
+
...(ngDevMode ? [{ debugName: "intent" }] : /* istanbul ignore next */ []));
|
|
51
|
+
emphasis = input('medium', /* @ts-ignore */
|
|
52
|
+
...(ngDevMode ? [{ debugName: "emphasis" }] : /* istanbul ignore next */ []));
|
|
51
53
|
// --- Announcement (ADR 0052) ---
|
|
52
|
-
live = input('off',
|
|
54
|
+
live = input('off', /* @ts-ignore */
|
|
55
|
+
...(ngDevMode ? [{ debugName: "live" }] : /* istanbul ignore next */ []));
|
|
53
56
|
// --- Smart Slots v2.0 (ADR 020) ---
|
|
54
|
-
iconSlot = contentChild(SkraBadgeIcon,
|
|
55
|
-
|
|
57
|
+
iconSlot = contentChild(SkraBadgeIcon, /* @ts-ignore */
|
|
58
|
+
...(ngDevMode ? [{ debugName: "iconSlot" }] : /* istanbul ignore next */ []));
|
|
59
|
+
hasIcon = computed(() => !!this.iconSlot(), /* @ts-ignore */
|
|
60
|
+
...(ngDevMode ? [{ debugName: "hasIcon" }] : /* istanbul ignore next */ []));
|
|
56
61
|
/**
|
|
57
62
|
* Map `live` politeness to the implicit-live ARIA role (ADR 0052). The role
|
|
58
63
|
* carries `aria-live` + `aria-atomic` implicitly; `off` → no live region.
|
|
@@ -66,11 +71,12 @@ class SkraBadge {
|
|
|
66
71
|
default:
|
|
67
72
|
return null;
|
|
68
73
|
}
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
static
|
|
74
|
+
}, /* @ts-ignore */
|
|
75
|
+
...(ngDevMode ? [{ debugName: "liveRole" }] : /* istanbul ignore next */ []));
|
|
76
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraBadge, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
77
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: SkraBadge, isStandalone: true, selector: "skra-badge", 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 } }, host: { properties: { "attr.data-skra-intent": "intent()", "attr.data-skra-emphasis": "emphasis()", "attr.role": "liveRole()", "attr.data-skra-has-icon": "hasIcon() ? \"\" : null" } }, queries: [{ propertyName: "iconSlot", first: true, predicate: SkraBadgeIcon, descendants: true, isSignal: true }], ngImport: i0, template: "@if (hasIcon()) {\r\n<span class=\"skra-badge-icon\">\r\n <ng-content select=\"[skra-badge-icon]\"></ng-content>\r\n</span>\r\n}\r\n\r\n<ng-content></ng-content>\r\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;box-sizing:border-box;margin:0;white-space:nowrap;gap:var(--skra-comp-badge-icon-gap);font-family:var(--skra-sys-typography-role-label-small-font-family);font-size:var(--skra-sys-typography-role-label-small-font-size);font-weight:var(--skra-sys-typography-role-label-small-font-weight);line-height:var(--skra-sys-typography-role-label-small-line-height);letter-spacing:var(--skra-sys-typography-role-label-small-letter-spacing);background:var(--skra-comp-badge-background);color:var(--skra-comp-badge-foreground);border-color:var(--skra-comp-badge-border-color);border-width:var(--skra-comp-badge-border-width);border-style:var(--skra-comp-badge-border-style);border-radius:var(--skra-comp-badge-radius);padding-block:var(--skra-comp-badge-padding-block);padding-inline:var(--skra-comp-badge-padding-inline);box-shadow:var(--skra-comp-badge-shadow)}:host([data-skra-emphasis=high]){--skra-comp-badge-border-width: 0}:host([data-skra-intent=neutral][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-neutral-high, var(--skra-sys-color-neutral-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-neutral-high, var(--skra-sys-color-neutral-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-neutral-high, transparent )}:host([data-skra-intent=neutral][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-neutral-medium, var(--skra-sys-color-neutral-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-neutral-medium, var(--skra-sys-color-neutral-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-neutral-medium, var(--skra-sys-color-neutral-border) )}:host([data-skra-intent=info][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-info-high, var(--skra-sys-color-info-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-info-high, var(--skra-sys-color-info-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-info-high, transparent )}:host([data-skra-intent=info][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-info-medium, var(--skra-sys-color-info-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-info-medium, var(--skra-sys-color-info-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-info-medium, var(--skra-sys-color-info-border) )}:host([data-skra-intent=success][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-success-high, var(--skra-sys-color-success-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-success-high, var(--skra-sys-color-success-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-success-high, transparent )}:host([data-skra-intent=success][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-success-medium, var(--skra-sys-color-success-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-success-medium, var(--skra-sys-color-success-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-success-medium, var(--skra-sys-color-success-border) )}:host([data-skra-intent=warning][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-warning-high, var(--skra-sys-color-warning-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-warning-high, var(--skra-sys-color-warning-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-warning-high, transparent )}:host([data-skra-intent=warning][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-warning-medium, var(--skra-sys-color-warning-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-warning-medium, var(--skra-sys-color-warning-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-warning-medium, var(--skra-sys-color-warning-border) )}:host([data-skra-intent=danger][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-danger-high, var(--skra-sys-color-danger-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-danger-high, var(--skra-sys-color-danger-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-danger-high, transparent )}:host([data-skra-intent=danger][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-danger-medium, var(--skra-sys-color-danger-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-danger-medium, var(--skra-sys-color-danger-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-danger-medium, var(--skra-sys-color-danger-border) )}.skra-badge-icon{display:inline-flex;flex-shrink:0;align-items:center;block-size:1lh;--skra-comp-icon-size: var(--skra-comp-badge-icon-size)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
72
78
|
}
|
|
73
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
79
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraBadge, decorators: [{
|
|
74
80
|
type: Component,
|
|
75
81
|
args: [{ selector: 'skra-badge', standalone: true, imports: [SkraBadgeIcon], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: {
|
|
76
82
|
// Variant Surface reflection (ADR 035 §3.5; ADR 021 — never [style.--var])
|
|
@@ -80,7 +86,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImpor
|
|
|
80
86
|
'[attr.role]': 'liveRole()',
|
|
81
87
|
// Smart Slot layout reflection (ADR 020 v2.0 — slot-presence, State-Surface-exempt §3.6)
|
|
82
88
|
'[attr.data-skra-has-icon]': 'hasIcon() ? "" : null',
|
|
83
|
-
}, template: "@if (hasIcon()) {\n<span class=\"skra-badge-icon\">\n <ng-content select=\"[skra-badge-icon]\"></ng-content>\n</span>\n}\n\n<ng-content></ng-content>\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;box-sizing:border-box;margin:0;white-space:nowrap;gap:var(--skra-comp-badge-icon-gap);font-family:var(--skra-sys-typography-role-label-small-font-family);font-size:var(--skra-sys-typography-role-label-small-font-size);font-weight:var(--skra-sys-typography-role-label-small-font-weight);line-height:var(--skra-sys-typography-role-label-small-line-height);letter-spacing:var(--skra-sys-typography-role-label-small-letter-spacing);background:var(--skra-comp-badge-background);color:var(--skra-comp-badge-foreground);border-color:var(--skra-comp-badge-border-color);border-width:var(--skra-comp-badge-border-width);border-style:var(--skra-comp-badge-border-style);border-radius:var(--skra-comp-badge-radius);padding-block:var(--skra-comp-badge-padding-block);padding-inline:var(--skra-comp-badge-padding-inline);box-shadow:var(--skra-comp-badge-shadow)}:host([data-skra-emphasis=high]){--skra-comp-badge-border-width: 0}:host([data-skra-intent=neutral][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-neutral-high, var(--skra-sys-color-neutral-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-neutral-high, var(--skra-sys-color-neutral-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-neutral-high, transparent )}:host([data-skra-intent=neutral][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-neutral-medium, var(--skra-sys-color-neutral-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-neutral-medium, var(--skra-sys-color-neutral-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-neutral-medium, var(--skra-sys-color-neutral-border) )}:host([data-skra-intent=info][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-info-high, var(--skra-sys-color-info-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-info-high, var(--skra-sys-color-info-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-info-high, transparent )}:host([data-skra-intent=info][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-info-medium, var(--skra-sys-color-info-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-info-medium, var(--skra-sys-color-info-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-info-medium, var(--skra-sys-color-info-border) )}:host([data-skra-intent=success][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-success-high, var(--skra-sys-color-success-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-success-high, var(--skra-sys-color-success-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-success-high, transparent )}:host([data-skra-intent=success][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-success-medium, var(--skra-sys-color-success-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-success-medium, var(--skra-sys-color-success-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-success-medium, var(--skra-sys-color-success-border) )}:host([data-skra-intent=warning][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-warning-high, var(--skra-sys-color-warning-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-warning-high, var(--skra-sys-color-warning-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-warning-high, transparent )}:host([data-skra-intent=warning][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-warning-medium, var(--skra-sys-color-warning-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-warning-medium, var(--skra-sys-color-warning-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-warning-medium, var(--skra-sys-color-warning-border) )}:host([data-skra-intent=danger][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-danger-high, var(--skra-sys-color-danger-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-danger-high, var(--skra-sys-color-danger-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-danger-high, transparent )}:host([data-skra-intent=danger][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-danger-medium, var(--skra-sys-color-danger-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-danger-medium, var(--skra-sys-color-danger-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-danger-medium, var(--skra-sys-color-danger-border) )}.skra-badge-icon{display:inline-flex;flex-shrink:0;align-items:center;block-size:1lh;--skra-comp-icon-size: var(--skra-comp-badge-icon-size)}\n"] }]
|
|
89
|
+
}, template: "@if (hasIcon()) {\r\n<span class=\"skra-badge-icon\">\r\n <ng-content select=\"[skra-badge-icon]\"></ng-content>\r\n</span>\r\n}\r\n\r\n<ng-content></ng-content>\r\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;box-sizing:border-box;margin:0;white-space:nowrap;gap:var(--skra-comp-badge-icon-gap);font-family:var(--skra-sys-typography-role-label-small-font-family);font-size:var(--skra-sys-typography-role-label-small-font-size);font-weight:var(--skra-sys-typography-role-label-small-font-weight);line-height:var(--skra-sys-typography-role-label-small-line-height);letter-spacing:var(--skra-sys-typography-role-label-small-letter-spacing);background:var(--skra-comp-badge-background);color:var(--skra-comp-badge-foreground);border-color:var(--skra-comp-badge-border-color);border-width:var(--skra-comp-badge-border-width);border-style:var(--skra-comp-badge-border-style);border-radius:var(--skra-comp-badge-radius);padding-block:var(--skra-comp-badge-padding-block);padding-inline:var(--skra-comp-badge-padding-inline);box-shadow:var(--skra-comp-badge-shadow)}:host([data-skra-emphasis=high]){--skra-comp-badge-border-width: 0}:host([data-skra-intent=neutral][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-neutral-high, var(--skra-sys-color-neutral-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-neutral-high, var(--skra-sys-color-neutral-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-neutral-high, transparent )}:host([data-skra-intent=neutral][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-neutral-medium, var(--skra-sys-color-neutral-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-neutral-medium, var(--skra-sys-color-neutral-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-neutral-medium, var(--skra-sys-color-neutral-border) )}:host([data-skra-intent=info][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-info-high, var(--skra-sys-color-info-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-info-high, var(--skra-sys-color-info-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-info-high, transparent )}:host([data-skra-intent=info][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-info-medium, var(--skra-sys-color-info-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-info-medium, var(--skra-sys-color-info-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-info-medium, var(--skra-sys-color-info-border) )}:host([data-skra-intent=success][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-success-high, var(--skra-sys-color-success-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-success-high, var(--skra-sys-color-success-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-success-high, transparent )}:host([data-skra-intent=success][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-success-medium, var(--skra-sys-color-success-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-success-medium, var(--skra-sys-color-success-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-success-medium, var(--skra-sys-color-success-border) )}:host([data-skra-intent=warning][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-warning-high, var(--skra-sys-color-warning-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-warning-high, var(--skra-sys-color-warning-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-warning-high, transparent )}:host([data-skra-intent=warning][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-warning-medium, var(--skra-sys-color-warning-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-warning-medium, var(--skra-sys-color-warning-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-warning-medium, var(--skra-sys-color-warning-border) )}:host([data-skra-intent=danger][data-skra-emphasis=high]){--skra-comp-badge-background: var( --skra-comp-badge-background-danger-high, var(--skra-sys-color-danger-base) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-danger-high, var(--skra-sys-color-danger-contrast) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-danger-high, transparent )}:host([data-skra-intent=danger][data-skra-emphasis=medium]){--skra-comp-badge-background: var( --skra-comp-badge-background-danger-medium, var(--skra-sys-color-danger-soft) );--skra-comp-badge-foreground: var( --skra-comp-badge-foreground-danger-medium, var(--skra-sys-color-danger-strong) );--skra-comp-badge-border-color: var( --skra-comp-badge-border-color-danger-medium, var(--skra-sys-color-danger-border) )}.skra-badge-icon{display:inline-flex;flex-shrink:0;align-items:center;block-size:1lh;--skra-comp-icon-size: var(--skra-comp-badge-icon-size)}\n"] }]
|
|
84
90
|
}], 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 }] }], iconSlot: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SkraBadgeIcon), { isSignal: true }] }] } });
|
|
85
91
|
|
|
86
92
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skra-ui-badge.mjs","sources":["../../../../libs/ui/badge/src/lib/badge.directives.ts","../../../../libs/ui/badge/src/lib/badge/badge.ts","../../../../libs/ui/badge/src/lib/badge/badge.html","../../../../libs/ui/badge/src/skra-ui-badge.ts"],"sourcesContent":["import { Directive } from '@angular/core';\n\n/**\n * Marker directive for the OPTIONAL leading icon/dot slot of `<skra-badge>`.\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, mirroring\n * `[skra-alert-icon]`.\n *\n * The icon is decorative — the consumer sets `aria-hidden` on its content (ADR\n * 034). The badge's visible text label still carries the meaning (WCAG 1.4.1):\n * a leading dot enables the `● Active` pattern but never substitutes for the word.\n */\n@Directive({\n selector: '[skra-badge-icon]',\n standalone: true,\n})\nexport class SkraBadgeIcon {}\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n contentChild,\n input,\n} from '@angular/core';\nimport { SkraBadgeIcon } from '../badge.directives';\n\n/**\n * BadgeIntent — semantic feedback meaning (ADR 035 §3.1, downward subset).\n * Excludes the action intents `primary`/`secondary` (meaningless for a status\n * indicator). Closed enum; extension requires an ADR 035 amendment.\n */\nexport type BadgeIntent = 'neutral' | 'info' | 'success' | 'warning' | 'danger';\n\n/**\n * BadgeEmphasis — visual loudness within the chosen intent (ADR 035 §3.1, subset).\n * `high` = filled chip, `medium` = soft/tinted lozenge. `low` deferred.\n */\nexport type BadgeEmphasis = 'high' | 'medium';\n\n/**\n * BadgeLive — screen-reader announcement politeness (ADR 0052). Maps to the\n * implicit-live ARIA role; politeness is a property of USE (static status vs a\n * live notification count), NOT of intent. Default `off` (the static-status case).\n */\nexport type BadgeLive = 'off' | 'polite' | 'assertive';\n\n/**\n * `<skra-badge>` — a small, inline, non-interactive status indicator (Feedback/Status\n * family, ADR 0052). Carries semantic importance (intent) as a short label or count —\n * e.g. a status lozenge (`Active`/`Failed`) in a table, or a notification count.\n *\n * SRP-distinct from `<skra-counter>` (form value-bound character counter, `libs/ui/forms`)\n * and from the closable `Tag/Chip` (interactive/dismissible — a different SRP, Wave 2).\n *\n * Non-interactive: no focusable node, no widget role, no keyboard, no outputs. The host is\n * a presentational surface; severity is a Variant Surface axis (ADR 035), not a State (ADR 027).\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; the `skra-alert`/`skra-error` pattern).\n * When `live ≠ off`, the content must be self-describing (`3 unread`, not a bare `3`) — the\n * role announces the whole badge atomically.\n *\n * Positioning (ADR 022): the badge owns no outer position. Overlaying it on a host's corner\n * (a notification badge) is a consumer composition, not an atom responsibility.\n */\n@Component({\n selector: 'skra-badge',\n standalone: true,\n imports: [SkraBadgeIcon],\n templateUrl: './badge.html',\n styleUrl: './badge.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n // Variant Surface reflection (ADR 035 §3.5; ADR 021 — never [style.--var])\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 Slot layout reflection (ADR 020 v2.0 — slot-presence, State-Surface-exempt §3.6)\n '[attr.data-skra-has-icon]': 'hasIcon() ? \"\" : null',\n },\n})\nexport class SkraBadge {\n // --- Variant Surface (ADR 035) ---\n readonly intent = input<BadgeIntent>('neutral');\n readonly emphasis = input<BadgeEmphasis>('medium');\n\n // --- Announcement (ADR 0052) ---\n readonly live = input<BadgeLive>('off');\n\n // --- Smart Slots v2.0 (ADR 020) ---\n readonly iconSlot = contentChild(SkraBadgeIcon);\n readonly hasIcon = computed(() => !!this.iconSlot());\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","@if (hasIcon()) {\n<span class=\"skra-badge-icon\">\n <ng-content select=\"[skra-badge-icon]\"></ng-content>\n</span>\n}\n\n<ng-content></ng-content>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAEA;;;;;;;;;;AAUG;MAKU,aAAa,CAAA;uGAAb,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAb,aAAa,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAb,aAAa,EAAA,UAAA,EAAA,CAAA;kBAJzB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,mBAAmB;AAC7B,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACcD;;;;;;;;;;;;;;;;;;;AAmBG;MAqBU,SAAS,CAAA;;
|
|
1
|
+
{"version":3,"file":"skra-ui-badge.mjs","sources":["../../../../libs/ui/badge/src/lib/badge.directives.ts","../../../../libs/ui/badge/src/lib/badge/badge.ts","../../../../libs/ui/badge/src/lib/badge/badge.html","../../../../libs/ui/badge/src/skra-ui-badge.ts"],"sourcesContent":["import { Directive } from '@angular/core';\r\n\r\n/**\r\n * Marker directive for the OPTIONAL leading icon/dot slot of `<skra-badge>`.\r\n * Detected via `contentChild` (ADR 020 Smart Slots v2.0) to toggle the icon\r\n * wrapper without emitting an empty DOM node. Feedback-local (not the button\r\n * lib's `[skra-start]`) to avoid a cross-lib marker dependency, mirroring\r\n * `[skra-alert-icon]`.\r\n *\r\n * The icon is decorative — the consumer sets `aria-hidden` on its content (ADR\r\n * 034). The badge's visible text label still carries the meaning (WCAG 1.4.1):\r\n * a leading dot enables the `● Active` pattern but never substitutes for the word.\r\n */\r\n@Directive({\r\n selector: '[skra-badge-icon]',\r\n standalone: true,\r\n})\r\nexport class SkraBadgeIcon {}\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n ViewEncapsulation,\r\n computed,\r\n contentChild,\r\n input,\r\n} from '@angular/core';\r\nimport { SkraBadgeIcon } from '../badge.directives';\r\n\r\n/**\r\n * BadgeIntent — semantic feedback meaning (ADR 035 §3.1, downward subset).\r\n * Excludes the action intents `primary`/`secondary` (meaningless for a status\r\n * indicator). Closed enum; extension requires an ADR 035 amendment.\r\n */\r\nexport type BadgeIntent = 'neutral' | 'info' | 'success' | 'warning' | 'danger';\r\n\r\n/**\r\n * BadgeEmphasis — visual loudness within the chosen intent (ADR 035 §3.1, subset).\r\n * `high` = filled chip, `medium` = soft/tinted lozenge. `low` deferred.\r\n */\r\nexport type BadgeEmphasis = 'high' | 'medium';\r\n\r\n/**\r\n * BadgeLive — screen-reader announcement politeness (ADR 0052). Maps to the\r\n * implicit-live ARIA role; politeness is a property of USE (static status vs a\r\n * live notification count), NOT of intent. Default `off` (the static-status case).\r\n */\r\nexport type BadgeLive = 'off' | 'polite' | 'assertive';\r\n\r\n/**\r\n * `<skra-badge>` — a small, inline, non-interactive status indicator (Feedback/Status\r\n * family, ADR 0052). Carries semantic importance (intent) as a short label or count —\r\n * e.g. a status lozenge (`Active`/`Failed`) in a table, or a notification count.\r\n *\r\n * SRP-distinct from `<skra-counter>` (form value-bound character counter, `libs/ui/forms`)\r\n * and from the closable `Tag/Chip` (interactive/dismissible — a different SRP, Wave 2).\r\n *\r\n * Non-interactive: no focusable node, no widget role, no keyboard, no outputs. The host is\r\n * a presentational surface; severity is a Variant Surface axis (ADR 035), not a State (ADR 027).\r\n *\r\n * Announcement (ADR 0052): the `live` input maps to the implicit-live ARIA role\r\n * (`status`/`alert`) — which carries `aria-live` + `aria-atomic` implicitly. NO explicit\r\n * `aria-live` is set (that would be redundant; the `skra-alert`/`skra-error` pattern).\r\n * When `live ≠ off`, the content must be self-describing (`3 unread`, not a bare `3`) — the\r\n * role announces the whole badge atomically.\r\n *\r\n * Positioning (ADR 022): the badge owns no outer position. Overlaying it on a host's corner\r\n * (a notification badge) is a consumer composition, not an atom responsibility.\r\n */\r\n@Component({\r\n selector: 'skra-badge',\r\n standalone: true,\r\n imports: [SkraBadgeIcon],\r\n templateUrl: './badge.html',\r\n styleUrl: './badge.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.Emulated,\r\n host: {\r\n // Variant Surface reflection (ADR 035 §3.5; ADR 021 — never [style.--var])\r\n '[attr.data-skra-intent]': 'intent()',\r\n '[attr.data-skra-emphasis]': 'emphasis()',\r\n\r\n // Announcement role (ADR 0052) — implicit-live role ONLY; never an explicit aria-live.\r\n '[attr.role]': 'liveRole()',\r\n\r\n // Smart Slot layout reflection (ADR 020 v2.0 — slot-presence, State-Surface-exempt §3.6)\r\n '[attr.data-skra-has-icon]': 'hasIcon() ? \"\" : null',\r\n },\r\n})\r\nexport class SkraBadge {\r\n // --- Variant Surface (ADR 035) ---\r\n readonly intent = input<BadgeIntent>('neutral');\r\n readonly emphasis = input<BadgeEmphasis>('medium');\r\n\r\n // --- Announcement (ADR 0052) ---\r\n readonly live = input<BadgeLive>('off');\r\n\r\n // --- Smart Slots v2.0 (ADR 020) ---\r\n readonly iconSlot = contentChild(SkraBadgeIcon);\r\n readonly hasIcon = computed(() => !!this.iconSlot());\r\n\r\n /**\r\n * Map `live` politeness to the implicit-live ARIA role (ADR 0052). The role\r\n * carries `aria-live` + `aria-atomic` implicitly; `off` → no live region.\r\n */\r\n readonly liveRole = computed<'alert' | 'status' | null>(() => {\r\n switch (this.live()) {\r\n case 'assertive':\r\n return 'alert';\r\n case 'polite':\r\n return 'status';\r\n default:\r\n return null;\r\n }\r\n });\r\n}\r\n","@if (hasIcon()) {\r\n<span class=\"skra-badge-icon\">\r\n <ng-content select=\"[skra-badge-icon]\"></ng-content>\r\n</span>\r\n}\r\n\r\n<ng-content></ng-content>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|