@skra/ui 0.3.1 → 0.5.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 +2 -1
- package/consumer-guide/layout.md +79 -0
- package/consumer-guide/setup-and-gotchas.md +2 -2
- package/fesm2022/skra-ui-accordion.mjs +2 -2
- package/fesm2022/skra-ui-accordion.mjs.map +1 -1
- package/fesm2022/skra-ui-alert.mjs +2 -2
- package/fesm2022/skra-ui-alert.mjs.map +1 -1
- package/fesm2022/skra-ui-avatar.mjs.map +1 -1
- package/fesm2022/skra-ui-badge.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-combobox.mjs +120 -120
- package/fesm2022/skra-ui-combobox.mjs.map +1 -1
- package/fesm2022/skra-ui-core.mjs +36 -36
- package/fesm2022/skra-ui-core.mjs.map +1 -1
- package/fesm2022/skra-ui-counter.mjs.map +1 -1
- package/fesm2022/skra-ui-datepicker.mjs +605 -190
- package/fesm2022/skra-ui-datepicker.mjs.map +1 -1
- package/fesm2022/skra-ui-dialog.mjs.map +1 -1
- package/fesm2022/skra-ui-field.mjs.map +1 -1
- package/fesm2022/skra-ui-icon.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-kbd.mjs.map +1 -1
- package/fesm2022/skra-ui-layout.mjs +40 -1
- package/fesm2022/skra-ui-layout.mjs.map +1 -1
- package/fesm2022/skra-ui-link.mjs +2 -2
- package/fesm2022/skra-ui-link.mjs.map +1 -1
- package/fesm2022/skra-ui-loading-indicator.mjs.map +1 -1
- package/fesm2022/skra-ui-menu.mjs +2 -2
- package/fesm2022/skra-ui-menu.mjs.map +1 -1
- package/fesm2022/skra-ui-multi-select.mjs +94 -94
- package/fesm2022/skra-ui-multi-select.mjs.map +1 -1
- package/fesm2022/skra-ui-native-select.mjs +2 -2
- package/fesm2022/skra-ui-native-select.mjs.map +1 -1
- package/fesm2022/skra-ui-popover.mjs.map +1 -1
- package/fesm2022/skra-ui-progress.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.map +1 -1
- package/fesm2022/skra-ui-select.mjs +92 -92
- package/fesm2022/skra-ui-select.mjs.map +1 -1
- package/fesm2022/skra-ui-skeleton.mjs +8 -8
- package/fesm2022/skra-ui-skeleton.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-status-dot.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-tabs.mjs +2 -2
- package/fesm2022/skra-ui-tabs.mjs.map +1 -1
- package/fesm2022/skra-ui-textarea.mjs +2 -2
- package/fesm2022/skra-ui-textarea.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.map +1 -1
- package/fesm2022/skra-ui-typography.mjs.map +1 -1
- package/package.json +2 -2
- package/types/skra-ui-datepicker.d.ts +146 -46
- package/types/skra-ui-datepicker.d.ts.map +1 -1
- package/types/skra-ui-layout.d.ts +33 -2
- package/types/skra-ui-layout.d.ts.map +1 -1
|
@@ -76,103 +76,103 @@ class SkraMultiSelect extends _SkraSelectBase {
|
|
|
76
76
|
return this.selectedOptions()[0] ?? null;
|
|
77
77
|
}
|
|
78
78
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraMultiSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
79
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: SkraMultiSelect, isStandalone: true, selector: "skra-multi-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, providers: [{ provide: SKRA_LISTBOX_PANEL, useExisting: SkraMultiSelect }], exportAs: ["skraMultiSelect"], usesInheritance: true, ngImport: i0, template: `
|
|
80
|
-
<button
|
|
81
|
-
#trigger
|
|
82
|
-
class="skra-select-trigger"
|
|
83
|
-
type="button"
|
|
84
|
-
role="combobox"
|
|
85
|
-
aria-haspopup="listbox"
|
|
86
|
-
[attr.id]="triggerId()"
|
|
87
|
-
[attr.popovertarget]="panelId"
|
|
88
|
-
[attr.aria-controls]="panelId"
|
|
89
|
-
[attr.aria-expanded]="isOpen()"
|
|
90
|
-
[attr.aria-activedescendant]="activeOptionId()"
|
|
91
|
-
[attr.aria-describedby]="describedBy()"
|
|
92
|
-
[attr.aria-invalid]="hasError() ? 'true' : null"
|
|
93
|
-
[attr.aria-required]="isRequired() ? 'true' : null"
|
|
94
|
-
[attr.aria-readonly]="isReadonly() ? 'true' : null"
|
|
95
|
-
[disabled]="isDisabled()"
|
|
96
|
-
(click)="onTriggerClick($event)"
|
|
97
|
-
(keydown)="onTriggerKeydown($event)"
|
|
98
|
-
>
|
|
99
|
-
<span class="skra-select-trigger-value">
|
|
100
|
-
@if (triggerTemplate(); as tpl) {
|
|
101
|
-
<ng-container
|
|
102
|
-
[ngTemplateOutlet]="tpl"
|
|
103
|
-
[ngTemplateOutletContext]="triggerContext()"
|
|
104
|
-
></ng-container>
|
|
105
|
-
} @else if (selectedOptions().length) {
|
|
106
|
-
{{ summary() }}
|
|
107
|
-
} @else {
|
|
108
|
-
<span class="skra-select-placeholder">{{ placeholder() }}</span>
|
|
109
|
-
}
|
|
110
|
-
</span>
|
|
111
|
-
<span class="skra-select-arrow" aria-hidden="true"></span>
|
|
112
|
-
</button>
|
|
113
|
-
|
|
114
|
-
<div
|
|
115
|
-
#panel
|
|
116
|
-
class="skra-select-listbox"
|
|
117
|
-
[id]="panelId"
|
|
118
|
-
role="listbox"
|
|
119
|
-
aria-multiselectable="true"
|
|
120
|
-
popover="auto"
|
|
121
|
-
(toggle)="onPanelToggle($event)"
|
|
122
|
-
>
|
|
123
|
-
<ng-content></ng-content>
|
|
124
|
-
</div>
|
|
125
|
-
`, isInline: true, styles: ["@charset \"UTF-8\";:host{display:block;box-sizing:border-box;margin:0}.skra-select-trigger{display:flex;align-items:center;gap:var(--skra-comp-select-gap);inline-size:100%;min-block-size:var(--skra-comp-select-min-block-size);box-sizing:border-box;margin:0;padding-block:var(--skra-comp-select-padding-block);padding-inline:var(--skra-comp-select-padding-inline);text-align:start;cursor:pointer;background:var(--skra-comp-select-background);color:var(--skra-comp-select-foreground);border-color:var(--skra-comp-select-border-color);border-width:var(--skra-comp-select-border-width);border-style:var(--skra-comp-select-border-style);border-radius:var(--skra-comp-select-radius);box-shadow:var(--skra-comp-select-shadow);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);transition:background-color var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing),border-color var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing)}.skra-select-trigger:hover:not(:disabled):not([aria-readonly=true]){background:var(--skra-comp-select-background-hover)}.skra-select-trigger:focus-visible{outline:var(--skra-comp-select-focus-ring-width) solid var(--skra-comp-select-focus-ring-color);outline-offset:.125rem}.skra-select-trigger:disabled{background:var(--skra-comp-select-background-disabled);color:var(--skra-comp-select-foreground-disabled);cursor:not-allowed}.skra-select-trigger[aria-readonly=true]{background:var(--skra-comp-select-background-readonly);cursor:default}.skra-select-trigger[aria-invalid=true]{border-color:var(--skra-comp-select-border-color-validation-invalid)}.skra-select-trigger-value{flex:1 1 auto;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;--skra-comp-icon-size: var(--skra-comp-select-icon-size)}.skra-select-placeholder{color:var(--skra-comp-select-foreground-disabled)}.skra-select-arrow{flex:none;inline-size:var(--skra-comp-select-arrow-icon-size);block-size:var(--skra-comp-select-arrow-icon-size);background-color:var(--skra-comp-select-arrow-color);mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M6%209l6%206%206-6'%20fill='none'%20stroke='%23000'%20stroke-width='2'/%3E%3C/svg%3E\") no-repeat center/contain;-webkit-mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M6%209l6%206%206-6'%20fill='none'%20stroke='%23000'%20stroke-width='2'/%3E%3C/svg%3E\") no-repeat center/contain;transition:transform var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing)}.skra-select-trigger[aria-expanded=true] .skra-select-arrow{transform:rotate(180deg)}.skra-select-listbox{position:fixed;margin:0;inset:auto;box-sizing:border-box;padding-block:var(--skra-comp-select-panel-padding-block);padding-inline:var(--skra-comp-select-panel-padding-inline);background:var(--skra-comp-select-panel-background);color:var(--skra-comp-select-panel-foreground);border:var(--skra-comp-select-border-width) solid var(--skra-comp-select-panel-border-color);border-radius:var(--skra-comp-select-panel-radius);box-shadow:var(--skra-comp-select-panel-shadow);inline-size:max-content;max-block-size:var(--skra-comp-select-panel-max-block-size);overflow-y:auto;flex-direction:column;opacity:0;transition:opacity var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing),display var(--skra-comp-select-motion-duration) allow-discrete,overlay var(--skra-comp-select-motion-duration) allow-discrete}.skra-select-listbox:popover-open{display:flex;opacity:1}@starting-style{.skra-select-listbox:popover-open{opacity:0}}@media(prefers-reduced-motion:reduce){.skra-select-trigger,.skra-select-arrow,.skra-select-listbox{transition-duration:0ms}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
79
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: SkraMultiSelect, isStandalone: true, selector: "skra-multi-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, providers: [{ provide: SKRA_LISTBOX_PANEL, useExisting: SkraMultiSelect }], exportAs: ["skraMultiSelect"], usesInheritance: true, ngImport: i0, template: `
|
|
80
|
+
<button
|
|
81
|
+
#trigger
|
|
82
|
+
class="skra-select-trigger"
|
|
83
|
+
type="button"
|
|
84
|
+
role="combobox"
|
|
85
|
+
aria-haspopup="listbox"
|
|
86
|
+
[attr.id]="triggerId()"
|
|
87
|
+
[attr.popovertarget]="panelId"
|
|
88
|
+
[attr.aria-controls]="panelId"
|
|
89
|
+
[attr.aria-expanded]="isOpen()"
|
|
90
|
+
[attr.aria-activedescendant]="activeOptionId()"
|
|
91
|
+
[attr.aria-describedby]="describedBy()"
|
|
92
|
+
[attr.aria-invalid]="hasError() ? 'true' : null"
|
|
93
|
+
[attr.aria-required]="isRequired() ? 'true' : null"
|
|
94
|
+
[attr.aria-readonly]="isReadonly() ? 'true' : null"
|
|
95
|
+
[disabled]="isDisabled()"
|
|
96
|
+
(click)="onTriggerClick($event)"
|
|
97
|
+
(keydown)="onTriggerKeydown($event)"
|
|
98
|
+
>
|
|
99
|
+
<span class="skra-select-trigger-value">
|
|
100
|
+
@if (triggerTemplate(); as tpl) {
|
|
101
|
+
<ng-container
|
|
102
|
+
[ngTemplateOutlet]="tpl"
|
|
103
|
+
[ngTemplateOutletContext]="triggerContext()"
|
|
104
|
+
></ng-container>
|
|
105
|
+
} @else if (selectedOptions().length) {
|
|
106
|
+
{{ summary() }}
|
|
107
|
+
} @else {
|
|
108
|
+
<span class="skra-select-placeholder">{{ placeholder() }}</span>
|
|
109
|
+
}
|
|
110
|
+
</span>
|
|
111
|
+
<span class="skra-select-arrow" aria-hidden="true"></span>
|
|
112
|
+
</button>
|
|
113
|
+
|
|
114
|
+
<div
|
|
115
|
+
#panel
|
|
116
|
+
class="skra-select-listbox"
|
|
117
|
+
[id]="panelId"
|
|
118
|
+
role="listbox"
|
|
119
|
+
aria-multiselectable="true"
|
|
120
|
+
popover="auto"
|
|
121
|
+
(toggle)="onPanelToggle($event)"
|
|
122
|
+
>
|
|
123
|
+
<ng-content></ng-content>
|
|
124
|
+
</div>
|
|
125
|
+
`, isInline: true, styles: ["@charset \"UTF-8\";:host{display:block;box-sizing:border-box;margin:0}.skra-select-trigger{display:flex;align-items:center;gap:var(--skra-comp-select-gap);inline-size:100%;min-block-size:var(--skra-comp-select-min-block-size);box-sizing:border-box;margin:0;padding-block:var(--skra-comp-select-padding-block);padding-inline:var(--skra-comp-select-padding-inline);text-align:start;cursor:pointer;background:var(--skra-comp-select-background);color:var(--skra-comp-select-foreground);border-color:var(--skra-comp-select-border-color);border-width:var(--skra-comp-select-border-width);border-style:var(--skra-comp-select-border-style);border-radius:var(--skra-comp-select-radius);box-shadow:var(--skra-comp-select-shadow);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);transition:background-color var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing),border-color var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing)}@media(hover:hover)and (pointer:fine){.skra-select-trigger:hover:not(:disabled):not([aria-readonly=true]){background:var(--skra-comp-select-background-hover)}}.skra-select-trigger:focus-visible{outline:var(--skra-comp-select-focus-ring-width) solid var(--skra-comp-select-focus-ring-color);outline-offset:.125rem}.skra-select-trigger:disabled{background:var(--skra-comp-select-background-disabled);color:var(--skra-comp-select-foreground-disabled);cursor:not-allowed}.skra-select-trigger[aria-readonly=true]{background:var(--skra-comp-select-background-readonly);cursor:default}.skra-select-trigger[aria-invalid=true]{border-color:var(--skra-comp-select-border-color-validation-invalid)}.skra-select-trigger-value{flex:1 1 auto;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;--skra-comp-icon-size: var(--skra-comp-select-icon-size)}.skra-select-placeholder{color:var(--skra-comp-select-foreground-disabled)}.skra-select-arrow{flex:none;inline-size:var(--skra-comp-select-arrow-icon-size);block-size:var(--skra-comp-select-arrow-icon-size);background-color:var(--skra-comp-select-arrow-color);mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M6%209l6%206%206-6'%20fill='none'%20stroke='%23000'%20stroke-width='2'/%3E%3C/svg%3E\") no-repeat center/contain;-webkit-mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M6%209l6%206%206-6'%20fill='none'%20stroke='%23000'%20stroke-width='2'/%3E%3C/svg%3E\") no-repeat center/contain;transition:transform var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing)}.skra-select-trigger[aria-expanded=true] .skra-select-arrow{transform:rotate(180deg)}.skra-select-listbox{position:fixed;margin:0;inset:auto;box-sizing:border-box;padding-block:var(--skra-comp-select-panel-padding-block);padding-inline:var(--skra-comp-select-panel-padding-inline);background:var(--skra-comp-select-panel-background);color:var(--skra-comp-select-panel-foreground);border:var(--skra-comp-select-border-width) solid var(--skra-comp-select-panel-border-color);border-radius:var(--skra-comp-select-panel-radius);box-shadow:var(--skra-comp-select-panel-shadow);inline-size:max-content;max-block-size:var(--skra-comp-select-panel-max-block-size);overflow-y:auto;flex-direction:column;opacity:0;transition:opacity var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing),display var(--skra-comp-select-motion-duration) allow-discrete,overlay var(--skra-comp-select-motion-duration) allow-discrete}.skra-select-listbox:popover-open{display:flex;opacity:1}@starting-style{.skra-select-listbox:popover-open{opacity:0}}@media(prefers-reduced-motion:reduce){.skra-select-trigger,.skra-select-arrow,.skra-select-listbox{transition-duration:0ms}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
126
126
|
}
|
|
127
127
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraMultiSelect, decorators: [{
|
|
128
128
|
type: Component,
|
|
129
|
-
args: [{ selector: 'skra-multi-select', standalone: true, exportAs: 'skraMultiSelect', imports: [NgTemplateOutlet], template: `
|
|
130
|
-
<button
|
|
131
|
-
#trigger
|
|
132
|
-
class="skra-select-trigger"
|
|
133
|
-
type="button"
|
|
134
|
-
role="combobox"
|
|
135
|
-
aria-haspopup="listbox"
|
|
136
|
-
[attr.id]="triggerId()"
|
|
137
|
-
[attr.popovertarget]="panelId"
|
|
138
|
-
[attr.aria-controls]="panelId"
|
|
139
|
-
[attr.aria-expanded]="isOpen()"
|
|
140
|
-
[attr.aria-activedescendant]="activeOptionId()"
|
|
141
|
-
[attr.aria-describedby]="describedBy()"
|
|
142
|
-
[attr.aria-invalid]="hasError() ? 'true' : null"
|
|
143
|
-
[attr.aria-required]="isRequired() ? 'true' : null"
|
|
144
|
-
[attr.aria-readonly]="isReadonly() ? 'true' : null"
|
|
145
|
-
[disabled]="isDisabled()"
|
|
146
|
-
(click)="onTriggerClick($event)"
|
|
147
|
-
(keydown)="onTriggerKeydown($event)"
|
|
148
|
-
>
|
|
149
|
-
<span class="skra-select-trigger-value">
|
|
150
|
-
@if (triggerTemplate(); as tpl) {
|
|
151
|
-
<ng-container
|
|
152
|
-
[ngTemplateOutlet]="tpl"
|
|
153
|
-
[ngTemplateOutletContext]="triggerContext()"
|
|
154
|
-
></ng-container>
|
|
155
|
-
} @else if (selectedOptions().length) {
|
|
156
|
-
{{ summary() }}
|
|
157
|
-
} @else {
|
|
158
|
-
<span class="skra-select-placeholder">{{ placeholder() }}</span>
|
|
159
|
-
}
|
|
160
|
-
</span>
|
|
161
|
-
<span class="skra-select-arrow" aria-hidden="true"></span>
|
|
162
|
-
</button>
|
|
163
|
-
|
|
164
|
-
<div
|
|
165
|
-
#panel
|
|
166
|
-
class="skra-select-listbox"
|
|
167
|
-
[id]="panelId"
|
|
168
|
-
role="listbox"
|
|
169
|
-
aria-multiselectable="true"
|
|
170
|
-
popover="auto"
|
|
171
|
-
(toggle)="onPanelToggle($event)"
|
|
172
|
-
>
|
|
173
|
-
<ng-content></ng-content>
|
|
174
|
-
</div>
|
|
175
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, providers: [{ provide: SKRA_LISTBOX_PANEL, useExisting: SkraMultiSelect }], styles: ["@charset \"UTF-8\";:host{display:block;box-sizing:border-box;margin:0}.skra-select-trigger{display:flex;align-items:center;gap:var(--skra-comp-select-gap);inline-size:100%;min-block-size:var(--skra-comp-select-min-block-size);box-sizing:border-box;margin:0;padding-block:var(--skra-comp-select-padding-block);padding-inline:var(--skra-comp-select-padding-inline);text-align:start;cursor:pointer;background:var(--skra-comp-select-background);color:var(--skra-comp-select-foreground);border-color:var(--skra-comp-select-border-color);border-width:var(--skra-comp-select-border-width);border-style:var(--skra-comp-select-border-style);border-radius:var(--skra-comp-select-radius);box-shadow:var(--skra-comp-select-shadow);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);transition:background-color var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing),border-color var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing)}.skra-select-trigger:hover:not(:disabled):not([aria-readonly=true]){background:var(--skra-comp-select-background-hover)}.skra-select-trigger:focus-visible{outline:var(--skra-comp-select-focus-ring-width) solid var(--skra-comp-select-focus-ring-color);outline-offset:.125rem}.skra-select-trigger:disabled{background:var(--skra-comp-select-background-disabled);color:var(--skra-comp-select-foreground-disabled);cursor:not-allowed}.skra-select-trigger[aria-readonly=true]{background:var(--skra-comp-select-background-readonly);cursor:default}.skra-select-trigger[aria-invalid=true]{border-color:var(--skra-comp-select-border-color-validation-invalid)}.skra-select-trigger-value{flex:1 1 auto;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;--skra-comp-icon-size: var(--skra-comp-select-icon-size)}.skra-select-placeholder{color:var(--skra-comp-select-foreground-disabled)}.skra-select-arrow{flex:none;inline-size:var(--skra-comp-select-arrow-icon-size);block-size:var(--skra-comp-select-arrow-icon-size);background-color:var(--skra-comp-select-arrow-color);mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M6%209l6%206%206-6'%20fill='none'%20stroke='%23000'%20stroke-width='2'/%3E%3C/svg%3E\") no-repeat center/contain;-webkit-mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M6%209l6%206%206-6'%20fill='none'%20stroke='%23000'%20stroke-width='2'/%3E%3C/svg%3E\") no-repeat center/contain;transition:transform var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing)}.skra-select-trigger[aria-expanded=true] .skra-select-arrow{transform:rotate(180deg)}.skra-select-listbox{position:fixed;margin:0;inset:auto;box-sizing:border-box;padding-block:var(--skra-comp-select-panel-padding-block);padding-inline:var(--skra-comp-select-panel-padding-inline);background:var(--skra-comp-select-panel-background);color:var(--skra-comp-select-panel-foreground);border:var(--skra-comp-select-border-width) solid var(--skra-comp-select-panel-border-color);border-radius:var(--skra-comp-select-panel-radius);box-shadow:var(--skra-comp-select-panel-shadow);inline-size:max-content;max-block-size:var(--skra-comp-select-panel-max-block-size);overflow-y:auto;flex-direction:column;opacity:0;transition:opacity var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing),display var(--skra-comp-select-motion-duration) allow-discrete,overlay var(--skra-comp-select-motion-duration) allow-discrete}.skra-select-listbox:popover-open{display:flex;opacity:1}@starting-style{.skra-select-listbox:popover-open{opacity:0}}@media(prefers-reduced-motion:reduce){.skra-select-trigger,.skra-select-arrow,.skra-select-listbox{transition-duration:0ms}}\n"] }]
|
|
129
|
+
args: [{ selector: 'skra-multi-select', standalone: true, exportAs: 'skraMultiSelect', imports: [NgTemplateOutlet], template: `
|
|
130
|
+
<button
|
|
131
|
+
#trigger
|
|
132
|
+
class="skra-select-trigger"
|
|
133
|
+
type="button"
|
|
134
|
+
role="combobox"
|
|
135
|
+
aria-haspopup="listbox"
|
|
136
|
+
[attr.id]="triggerId()"
|
|
137
|
+
[attr.popovertarget]="panelId"
|
|
138
|
+
[attr.aria-controls]="panelId"
|
|
139
|
+
[attr.aria-expanded]="isOpen()"
|
|
140
|
+
[attr.aria-activedescendant]="activeOptionId()"
|
|
141
|
+
[attr.aria-describedby]="describedBy()"
|
|
142
|
+
[attr.aria-invalid]="hasError() ? 'true' : null"
|
|
143
|
+
[attr.aria-required]="isRequired() ? 'true' : null"
|
|
144
|
+
[attr.aria-readonly]="isReadonly() ? 'true' : null"
|
|
145
|
+
[disabled]="isDisabled()"
|
|
146
|
+
(click)="onTriggerClick($event)"
|
|
147
|
+
(keydown)="onTriggerKeydown($event)"
|
|
148
|
+
>
|
|
149
|
+
<span class="skra-select-trigger-value">
|
|
150
|
+
@if (triggerTemplate(); as tpl) {
|
|
151
|
+
<ng-container
|
|
152
|
+
[ngTemplateOutlet]="tpl"
|
|
153
|
+
[ngTemplateOutletContext]="triggerContext()"
|
|
154
|
+
></ng-container>
|
|
155
|
+
} @else if (selectedOptions().length) {
|
|
156
|
+
{{ summary() }}
|
|
157
|
+
} @else {
|
|
158
|
+
<span class="skra-select-placeholder">{{ placeholder() }}</span>
|
|
159
|
+
}
|
|
160
|
+
</span>
|
|
161
|
+
<span class="skra-select-arrow" aria-hidden="true"></span>
|
|
162
|
+
</button>
|
|
163
|
+
|
|
164
|
+
<div
|
|
165
|
+
#panel
|
|
166
|
+
class="skra-select-listbox"
|
|
167
|
+
[id]="panelId"
|
|
168
|
+
role="listbox"
|
|
169
|
+
aria-multiselectable="true"
|
|
170
|
+
popover="auto"
|
|
171
|
+
(toggle)="onPanelToggle($event)"
|
|
172
|
+
>
|
|
173
|
+
<ng-content></ng-content>
|
|
174
|
+
</div>
|
|
175
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, providers: [{ provide: SKRA_LISTBOX_PANEL, useExisting: SkraMultiSelect }], styles: ["@charset \"UTF-8\";:host{display:block;box-sizing:border-box;margin:0}.skra-select-trigger{display:flex;align-items:center;gap:var(--skra-comp-select-gap);inline-size:100%;min-block-size:var(--skra-comp-select-min-block-size);box-sizing:border-box;margin:0;padding-block:var(--skra-comp-select-padding-block);padding-inline:var(--skra-comp-select-padding-inline);text-align:start;cursor:pointer;background:var(--skra-comp-select-background);color:var(--skra-comp-select-foreground);border-color:var(--skra-comp-select-border-color);border-width:var(--skra-comp-select-border-width);border-style:var(--skra-comp-select-border-style);border-radius:var(--skra-comp-select-radius);box-shadow:var(--skra-comp-select-shadow);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);transition:background-color var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing),border-color var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing)}@media(hover:hover)and (pointer:fine){.skra-select-trigger:hover:not(:disabled):not([aria-readonly=true]){background:var(--skra-comp-select-background-hover)}}.skra-select-trigger:focus-visible{outline:var(--skra-comp-select-focus-ring-width) solid var(--skra-comp-select-focus-ring-color);outline-offset:.125rem}.skra-select-trigger:disabled{background:var(--skra-comp-select-background-disabled);color:var(--skra-comp-select-foreground-disabled);cursor:not-allowed}.skra-select-trigger[aria-readonly=true]{background:var(--skra-comp-select-background-readonly);cursor:default}.skra-select-trigger[aria-invalid=true]{border-color:var(--skra-comp-select-border-color-validation-invalid)}.skra-select-trigger-value{flex:1 1 auto;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;--skra-comp-icon-size: var(--skra-comp-select-icon-size)}.skra-select-placeholder{color:var(--skra-comp-select-foreground-disabled)}.skra-select-arrow{flex:none;inline-size:var(--skra-comp-select-arrow-icon-size);block-size:var(--skra-comp-select-arrow-icon-size);background-color:var(--skra-comp-select-arrow-color);mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M6%209l6%206%206-6'%20fill='none'%20stroke='%23000'%20stroke-width='2'/%3E%3C/svg%3E\") no-repeat center/contain;-webkit-mask:url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M6%209l6%206%206-6'%20fill='none'%20stroke='%23000'%20stroke-width='2'/%3E%3C/svg%3E\") no-repeat center/contain;transition:transform var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing)}.skra-select-trigger[aria-expanded=true] .skra-select-arrow{transform:rotate(180deg)}.skra-select-listbox{position:fixed;margin:0;inset:auto;box-sizing:border-box;padding-block:var(--skra-comp-select-panel-padding-block);padding-inline:var(--skra-comp-select-panel-padding-inline);background:var(--skra-comp-select-panel-background);color:var(--skra-comp-select-panel-foreground);border:var(--skra-comp-select-border-width) solid var(--skra-comp-select-panel-border-color);border-radius:var(--skra-comp-select-panel-radius);box-shadow:var(--skra-comp-select-panel-shadow);inline-size:max-content;max-block-size:var(--skra-comp-select-panel-max-block-size);overflow-y:auto;flex-direction:column;opacity:0;transition:opacity var(--skra-comp-select-motion-duration) var(--skra-comp-select-motion-easing),display var(--skra-comp-select-motion-duration) allow-discrete,overlay var(--skra-comp-select-motion-duration) allow-discrete}.skra-select-listbox:popover-open{display:flex;opacity:1}@starting-style{.skra-select-listbox:popover-open{opacity:0}}@media(prefers-reduced-motion:reduce){.skra-select-trigger,.skra-select-arrow,.skra-select-listbox{transition-duration:0ms}}\n"] }]
|
|
176
176
|
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
177
177
|
|
|
178
178
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skra-ui-multi-select.mjs","sources":["../../../../libs/ui/multi-select/src/lib/multi-select/multi-select.ts","../../../../libs/ui/multi-select/src/skra-ui-multi-select.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\
|
|
1
|
+
{"version":3,"file":"skra-ui-multi-select.mjs","sources":["../../../../libs/ui/multi-select/src/lib/multi-select/multi-select.ts","../../../../libs/ui/multi-select/src/skra-ui-multi-select.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n afterRenderEffect,\n computed,\n input,\n output,\n} from '@angular/core';\n\nimport { _SkraSelectBase } from '@skra/ui/core';\nimport {\n SKRA_LISTBOX_PANEL,\n type SkraListboxKeyboardItem,\n} from '@skra/ui/core';\n\ndeclare const ngDevMode: boolean | undefined;\n\n/**\n * SkraMultiSelect — a custom MULTI-select listbox: the WAI-ARIA APG multi-selectable listbox combobox.\n * The multi-cardinality sibling of `skra-select` over the shared `_SkraSelectBase` (**ADR 0046** —\n * cardinality split: a separate component with an HONEST `readonly T[]` value contract, NOT a `multiple`\n * flag). The trigger (`role=\"combobox\"`) opens a top-layer listbox panel (`popover=\"auto\"`, ADR 0044,\n * `aria-multiselectable=\"true\"`) of the SAME projected `skra-option` children — reused verbatim; the\n * option swaps its indicator to a checkbox via the `SkraListboxPanel.multiple` hint.\n *\n * - **Value (ADR 037):** `value = input<readonly T[]>([])` + `valueChange = output<readonly T[]>()` —\n * consumer-owned, no `@angular/forms`. Selection is membership (`compareWith` per element).\n * - **Toggle (ADR 0046):** picking an option toggles its membership and KEEPS THE PANEL OPEN (the one\n * behavioural divergence from single-select, which closes).\n * - **Trigger summary (ADR 0045 / 033):** comma-joined `getLabel()` of selected options — the VALUE\n * display, never the accessible name. Count-style / chips → the opt-in `[skraSelectTrigger]` recipe.\n *\n * Full contract: adr/specs/component-multi-select-spec.md.\n */\n@Component({\n selector: 'skra-multi-select',\n standalone: true,\n exportAs: 'skraMultiSelect',\n imports: [NgTemplateOutlet],\n template: `\n <button\n #trigger\n class=\"skra-select-trigger\"\n type=\"button\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.id]=\"triggerId()\"\n [attr.popovertarget]=\"panelId\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-activedescendant]=\"activeOptionId()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"hasError() ? 'true' : null\"\n [attr.aria-required]=\"isRequired() ? 'true' : null\"\n [attr.aria-readonly]=\"isReadonly() ? 'true' : null\"\n [disabled]=\"isDisabled()\"\n (click)=\"onTriggerClick($event)\"\n (keydown)=\"onTriggerKeydown($event)\"\n >\n <span class=\"skra-select-trigger-value\">\n @if (triggerTemplate(); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"triggerContext()\"\n ></ng-container>\n } @else if (selectedOptions().length) {\n {{ summary() }}\n } @else {\n <span class=\"skra-select-placeholder\">{{ placeholder() }}</span>\n }\n </span>\n <span class=\"skra-select-arrow\" aria-hidden=\"true\"></span>\n </button>\n\n <div\n #panel\n class=\"skra-select-listbox\"\n [id]=\"panelId\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n popover=\"auto\"\n (toggle)=\"onPanelToggle($event)\"\n >\n <ng-content></ng-content>\n </div>\n `,\n styleUrl: './multi-select.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n providers: [{ provide: SKRA_LISTBOX_PANEL, useExisting: SkraMultiSelect }],\n})\nexport class SkraMultiSelect<T = unknown> extends _SkraSelectBase<T> {\n /** Consumer-owned ARRAY value channel (ADR 037) — default `[]` (never undefined). */\n readonly value = input<readonly T[]>([]);\n /** Fires ONLY on user toggle — emits a NEW array; never on a programmatic `value()` change (ADR 037). */\n readonly valueChange = output<readonly T[]>();\n /** Cardinality hint (ADR 0046) — multi-select (drives the option checkbox indicator + aria-multiselectable). */\n readonly multiple = true;\n\n /** The options whose value is a member of `value()` — feeds the trigger summary + seed. */\n protected readonly selectedOptions = computed(() =>\n this.options().filter((o) => this.isSelected(o.value())),\n );\n\n /** Comma-joined identity labels of the selected options (value display, ADR 0045 — language-neutral). */\n protected readonly summary = computed(() =>\n this.selectedOptions()\n .map((o) => o.getLabel())\n .join(', '),\n );\n\n protected readonly triggerContext = computed(() => ({\n $implicit: this.value(),\n options: this.selectedOptions(),\n }));\n\n constructor() {\n super();\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n // Dev-only consumer warning. Uses afterRenderEffect (NOT effect) so the projected\n // options' required `value` inputs are read only AFTER each render applies their\n // bindings — an eager read during the initial CD (SSR / first render) OR a runtime\n // re-projection would throw NG0950. afterRender hooks never run on the server, so\n // this stays SSR-safe. Covers F-13 (initial render) + F-16 (runtime re-projection).\n afterRenderEffect(() => {\n const opts = this.options();\n const unmatched = this.value().filter(\n (v) => !opts.some((o) => this.compareWith()(o.value() as T, v)),\n );\n if (unmatched.length) {\n console.warn(\n '[skra-multi-select] value contains entries with no matching <skra-option> — they are ' +\n 'dropped from the trigger summary (likely a compareWith mismatch for object values).',\n );\n }\n });\n }\n }\n\n // ── SkraListboxPanel seam ──\n isSelected(value: unknown): boolean {\n return this.value().some((x) => this.compareWith()(x, value as T));\n }\n\n selectValue(value: unknown): void {\n const present = this.isSelected(value);\n const next = present\n ? this.value().filter((x) => !this.compareWith()(x, value as T))\n : [...this.value(), value as T];\n this.valueChange.emit(next);\n // NO close() — multi-select keeps the panel open for further toggling (ADR 0046).\n }\n\n protected activeSeedItem(): SkraListboxKeyboardItem | null {\n return this.selectedOptions()[0] ?? null;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -113,7 +113,7 @@ class SkraNativeSelect {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraNativeSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
116
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.1", type: SkraNativeSelect, isStandalone: true, selector: "select[skraSelect]", host: { listeners: { "mousedown": "blockWhenReadonly($event)", "keydown": "blockKeyWhenReadonly($event)" }, properties: { "attr.aria-describedby": "context?.describedByIds() ?? null", "attr.aria-invalid": "context?.hasError() ? \"true\" : null", "attr.aria-required": "context?.isRequired() ? \"true\" : null", "attr.aria-readonly": "context?.isReadonly() ? \"true\" : null" } }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host{background-color:var(--skra-comp-field-background);color:var(--skra-comp-field-foreground);border-color:var(--skra-comp-field-border-color);border-width:var(--skra-comp-field-border-width);border-style:var(--skra-comp-field-border-style);border-radius:var(--skra-comp-field-radius);padding-block:var(--skra-comp-field-padding-block);padding-inline:var(--skra-comp-field-padding-inline);box-shadow:var(--skra-comp-field-shadow);font:inherit;outline:none;cursor:pointer;transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}:host(:not([size])){appearance:none;padding-inline-end:var(--skra-comp-field-select-arrow-padding-inline-end);background-image:var(--skra-comp-field-select-chevron-glyph);background-repeat:no-repeat;background-position:right var(--skra-comp-field-padding-inline) center;background-size:var(--skra-comp-field-select-arrow-icon-size)}:host([size]){background-image:none;cursor:default}:host(:not([size]):hover:not(:disabled):not([aria-readonly=true])){background-color:var(--skra-comp-field-background-hover);border-color:var(--skra-comp-field-border-color-hover)}:host(:focus-visible){border-color:var(--skra-comp-field-focus-ring-color);box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([aria-readonly=true]){cursor:default}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
116
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.1", type: SkraNativeSelect, isStandalone: true, selector: "select[skraSelect]", host: { listeners: { "mousedown": "blockWhenReadonly($event)", "keydown": "blockKeyWhenReadonly($event)" }, properties: { "attr.aria-describedby": "context?.describedByIds() ?? null", "attr.aria-invalid": "context?.hasError() ? \"true\" : null", "attr.aria-required": "context?.isRequired() ? \"true\" : null", "attr.aria-readonly": "context?.isReadonly() ? \"true\" : null" } }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host{background-color:var(--skra-comp-field-background);color:var(--skra-comp-field-foreground);border-color:var(--skra-comp-field-border-color);border-width:var(--skra-comp-field-border-width);border-style:var(--skra-comp-field-border-style);border-radius:var(--skra-comp-field-radius);padding-block:var(--skra-comp-field-padding-block);padding-inline:var(--skra-comp-field-padding-inline);box-shadow:var(--skra-comp-field-shadow);font:inherit;outline:none;cursor:pointer;transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}:host(:not([size])){appearance:none;padding-inline-end:var(--skra-comp-field-select-arrow-padding-inline-end);background-image:var(--skra-comp-field-select-chevron-glyph);background-repeat:no-repeat;background-position:right var(--skra-comp-field-padding-inline) center;background-size:var(--skra-comp-field-select-arrow-icon-size)}:host([size]){background-image:none;cursor:default}@media(hover:hover)and (pointer:fine){:host(:not([size]):hover:not(:disabled):not([aria-readonly=true])){background-color:var(--skra-comp-field-background-hover);border-color:var(--skra-comp-field-border-color-hover)}}:host(:focus-visible){border-color:var(--skra-comp-field-focus-ring-color);box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([aria-readonly=true]){cursor:default}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
117
117
|
}
|
|
118
118
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraNativeSelect, decorators: [{
|
|
119
119
|
type: Component,
|
|
@@ -128,7 +128,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
|
|
|
128
128
|
// in `_form-controls.scss` (ARIA-only branch, no data-attr companion).
|
|
129
129
|
'(mousedown)': 'blockWhenReadonly($event)',
|
|
130
130
|
'(keydown)': 'blockKeyWhenReadonly($event)',
|
|
131
|
-
}, styles: [":host{background-color:var(--skra-comp-field-background);color:var(--skra-comp-field-foreground);border-color:var(--skra-comp-field-border-color);border-width:var(--skra-comp-field-border-width);border-style:var(--skra-comp-field-border-style);border-radius:var(--skra-comp-field-radius);padding-block:var(--skra-comp-field-padding-block);padding-inline:var(--skra-comp-field-padding-inline);box-shadow:var(--skra-comp-field-shadow);font:inherit;outline:none;cursor:pointer;transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}:host(:not([size])){appearance:none;padding-inline-end:var(--skra-comp-field-select-arrow-padding-inline-end);background-image:var(--skra-comp-field-select-chevron-glyph);background-repeat:no-repeat;background-position:right var(--skra-comp-field-padding-inline) center;background-size:var(--skra-comp-field-select-arrow-icon-size)}:host([size]){background-image:none;cursor:default}:host(:not([size]):hover:not(:disabled):not([aria-readonly=true])){background-color:var(--skra-comp-field-background-hover);border-color:var(--skra-comp-field-border-color-hover)}:host(:focus-visible){border-color:var(--skra-comp-field-focus-ring-color);box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([aria-readonly=true]){cursor:default}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"] }]
|
|
131
|
+
}, styles: [":host{background-color:var(--skra-comp-field-background);color:var(--skra-comp-field-foreground);border-color:var(--skra-comp-field-border-color);border-width:var(--skra-comp-field-border-width);border-style:var(--skra-comp-field-border-style);border-radius:var(--skra-comp-field-radius);padding-block:var(--skra-comp-field-padding-block);padding-inline:var(--skra-comp-field-padding-inline);box-shadow:var(--skra-comp-field-shadow);font:inherit;outline:none;cursor:pointer;transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}:host(:not([size])){appearance:none;padding-inline-end:var(--skra-comp-field-select-arrow-padding-inline-end);background-image:var(--skra-comp-field-select-chevron-glyph);background-repeat:no-repeat;background-position:right var(--skra-comp-field-padding-inline) center;background-size:var(--skra-comp-field-select-arrow-icon-size)}:host([size]){background-image:none;cursor:default}@media(hover:hover)and (pointer:fine){:host(:not([size]):hover:not(:disabled):not([aria-readonly=true])){background-color:var(--skra-comp-field-background-hover);border-color:var(--skra-comp-field-border-color-hover)}}:host(:focus-visible){border-color:var(--skra-comp-field-focus-ring-color);box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([aria-readonly=true]){cursor:default}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"] }]
|
|
132
132
|
}], ctorParameters: () => [] });
|
|
133
133
|
|
|
134
134
|
// select[skraSelect] native form-control directive (SkraNativeSelect — ADR 0054 §4.3).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skra-ui-native-select.mjs","sources":["../../../../libs/ui/native-select/src/lib/select/select.ts","../../../../libs/ui/native-select/src/index.ts","../../../../libs/ui/native-select/src/skra-ui-native-select.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n effect,\n inject,\n isDevMode,\n} from '@angular/core';\nimport { SkraFieldContext } from '@skra/ui/field';\n\n/**\n * Wires a native `<select>` inside `<skra-field>` to SkraFieldContext (ADR 013).\n * Tier 1 Foundations primitive — **single-select only**: a dropdown, or a\n * single-select scrolling listbox via the native `[size]` attribute.\n *\n * Native `[multiple]` is deliberately NOT supported (the directive rejects it,\n * see below). Native `<select multiple>` UX is not production-grade and cannot\n * be fixed at the native-`<select>` tier: selection requires modifier keys or\n * drag, the plain-click-toggle affordance exists only for a bare `<select\n * multiple>` in some engines (and breaks with an explicit `[size]`), and the\n * option markers are UA-drawn / unstylable cross-browser. Multi-select — chip\n * display, search, custom option templates, and a styleable per-row checkbox —\n * is wholly a Tier 2 `skra-select` (CDK listbox) concern per\n * `adr/specs/0039-select-directive-spec.md` §1.1 / §4.1.\n *\n * <skra-field>\n * <label skraLabelFor>Country</label>\n * <select skraSelect [value]=\"country()\" (change)=\"country.set($any($event.target).value)\">\n * <option value=\"pl\">Poland</option>\n * <option value=\"de\">Germany</option>\n * </select>\n * </skra-field>\n *\n * <!-- standalone: native implicit label (wrapping) — no id/for needed -->\n * <label>Country <select skraSelect><option value=\"pl\">Poland</option></select></label>\n *\n * `SkraFieldContext` is injected `{ optional: true }` (ADR 013 §3.7) — same\n * posture as SkraInput / SkraCheckbox. Standalone, the atom renders the skin\n * only, the readonly guards are inert, and the consumer owns every attribute\n * including the accessible name.\n *\n * Native `<select>` is the only web-platform widget whose dropdown renders in\n * the OS / browser top-layer, above modal `<dialog>`, above Shadow DOM\n * boundaries, above z-index stacking contexts. By staying native at Tier 1 we\n * inherit that for free — Tier 2 custom listbox will solve the same problem\n * via CDK overlay + Top Layer API.\n *\n * Value channel stays consumer-owned per ADR 037: bind via native `[value]` +\n * `(change)`, Reactive Forms `formControlName`, Signal Forms `[formField]`,\n * or `[(ngModel)]` — all work orthogonally.\n *\n * `readonly` is ARIA-only because HTML spec does not apply native `[readonly]`\n * to `<select>` (same gotcha as `<input type=\"checkbox|radio\">`). Unlike a text\n * input, though, a native `<select>` is an *uncontrolled* widget: if the listbox\n * opens and the user picks an option, the displayed value changes regardless of\n * the consumer's binding — so \"consumer prevents change\" cannot actually hold a\n * native select readonly. The directive therefore enforces readonly behaviourally\n * (blocks the picker from opening / the value from changing — see\n * `blockWhenReadonly` / `blockKeyWhenReadonly`), mirroring the imperative\n * `el.disabled` enforcement below. Both states are made non-interactive; only\n * readonly stays focusable + un-greyed and presents as the bare value. This is\n * interaction integrity for the control's own state — NOT a value channel, so the\n * ADR 037 no-`@angular/forms` / no-CVA boundary is untouched.\n */\n@Component({\n selector: 'select[skraSelect]',\n standalone: true,\n // Content-bearing host: <ng-content> projects the consumer's\n // <option>/<optgroup> children through. `template: ''` (as used for the void\n // <input> host) would discard them — see ADR 040 §4.\n template: '<ng-content></ng-content>',\n styleUrl: './select.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n '[attr.aria-describedby]': 'context?.describedByIds() ?? null',\n '[attr.aria-invalid]': 'context?.hasError() ? \"true\" : null',\n '[attr.aria-required]': 'context?.isRequired() ? \"true\" : null',\n '[attr.aria-readonly]': 'context?.isReadonly() ? \"true\" : null',\n // No `data-skra-readonly` — slice consumes `[aria-readonly=\"true\"]`\n // directly; emitting a parallel data-attr would be dead surface\n // (no slice selector reads it). Matches checkbox/radio readonly pattern\n // in `_form-controls.scss` (ARIA-only branch, no data-attr companion).\n '(mousedown)': 'blockWhenReadonly($event)',\n '(keydown)': 'blockKeyWhenReadonly($event)',\n },\n})\nexport class SkraNativeSelect {\n private readonly el = inject<ElementRef<HTMLSelectElement>>(ElementRef);\n readonly context = inject(SkraFieldContext, { optional: true });\n\n constructor() {\n const el = this.el.nativeElement;\n\n // Reject native multi-select loudly in dev — Forge fails on contract\n // violations rather than degrading silently. This throw is unrelated to the\n // (now optional, ADR 013 §3.7) field context: `[multiple]` is a capability\n // this atom genuinely cannot honour, whereas a missing field is a supported\n // standalone mode. Dev-only: never crashes a production bundle. A `<select\n // multiple>` that truly wants native UX can drop `skraSelect` and stay raw\n // HTML; for a real multi-select, use the Tier 2 <skra-select>.\n if (isDevMode() && el.multiple) {\n throw new Error(\n '[skraSelect] does not support the native [multiple] attribute at ' +\n 'Tier 1. Native multi-select UX is not production-grade (modifier-key/' +\n 'drag selection, UA-drawn unstylable markers, browser-fragile) and ' +\n 'cannot be fixed at the native <select> tier. Use a single-select ' +\n '<select skraSelect> (optionally with [size] for a listbox), or the ' +\n 'Tier 2 <skra-select> (CDK listbox) for real multi-select. See ' +\n 'adr/specs/0039-select-directive-spec.md §4.1.',\n );\n }\n\n // Field-cascaded native properties — only bind when context is present so\n // standalone consumers retain full control of their static attributes.\n // Mirrors SkraInput / SkraCheckbox.\n if (this.context) {\n const ctx = this.context;\n effect(() => {\n el.id = ctx.fieldId();\n });\n effect(() => {\n el.disabled = ctx.isDisabled();\n });\n }\n }\n\n /**\n * Readonly: suppress the pointer affordance that opens the native listbox.\n * `preventDefault` on `mousedown` stops the picker from opening (and, on a\n * native select, focus-on-click — Tab focus still works, which is the right\n * trade-off for a value-display control).\n */\n protected blockWhenReadonly(event: Event): void {\n if (this.context?.isReadonly()) event.preventDefault();\n }\n\n /**\n * Readonly: suppress every keyboard affordance that opens or mutates the\n * select, while letting Tab through for focus traversal. Space / Enter /\n * Alt+ArrowDown open the listbox; bare Arrows + first-letter typeahead change\n * the value inline without opening it — all are value-changing on a native\n * select, so all are blocked in readonly.\n */\n protected blockKeyWhenReadonly(event: KeyboardEvent): void {\n if (this.context?.isReadonly() && event.key !== 'Tab') {\n event.preventDefault();\n }\n }\n}\n","// select[skraSelect] native form-control directive (SkraNativeSelect — ADR 0054 §4.3).\
|
|
1
|
+
{"version":3,"file":"skra-ui-native-select.mjs","sources":["../../../../libs/ui/native-select/src/lib/select/select.ts","../../../../libs/ui/native-select/src/index.ts","../../../../libs/ui/native-select/src/skra-ui-native-select.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n effect,\n inject,\n isDevMode,\n} from '@angular/core';\nimport { SkraFieldContext } from '@skra/ui/field';\n\n/**\n * Wires a native `<select>` inside `<skra-field>` to SkraFieldContext (ADR 013).\n * Tier 1 Foundations primitive — **single-select only**: a dropdown, or a\n * single-select scrolling listbox via the native `[size]` attribute.\n *\n * Native `[multiple]` is deliberately NOT supported (the directive rejects it,\n * see below). Native `<select multiple>` UX is not production-grade and cannot\n * be fixed at the native-`<select>` tier: selection requires modifier keys or\n * drag, the plain-click-toggle affordance exists only for a bare `<select\n * multiple>` in some engines (and breaks with an explicit `[size]`), and the\n * option markers are UA-drawn / unstylable cross-browser. Multi-select — chip\n * display, search, custom option templates, and a styleable per-row checkbox —\n * is wholly a Tier 2 `skra-select` (CDK listbox) concern per\n * `adr/specs/0039-select-directive-spec.md` §1.1 / §4.1.\n *\n * <skra-field>\n * <label skraLabelFor>Country</label>\n * <select skraSelect [value]=\"country()\" (change)=\"country.set($any($event.target).value)\">\n * <option value=\"pl\">Poland</option>\n * <option value=\"de\">Germany</option>\n * </select>\n * </skra-field>\n *\n * <!-- standalone: native implicit label (wrapping) — no id/for needed -->\n * <label>Country <select skraSelect><option value=\"pl\">Poland</option></select></label>\n *\n * `SkraFieldContext` is injected `{ optional: true }` (ADR 013 §3.7) — same\n * posture as SkraInput / SkraCheckbox. Standalone, the atom renders the skin\n * only, the readonly guards are inert, and the consumer owns every attribute\n * including the accessible name.\n *\n * Native `<select>` is the only web-platform widget whose dropdown renders in\n * the OS / browser top-layer, above modal `<dialog>`, above Shadow DOM\n * boundaries, above z-index stacking contexts. By staying native at Tier 1 we\n * inherit that for free — Tier 2 custom listbox will solve the same problem\n * via CDK overlay + Top Layer API.\n *\n * Value channel stays consumer-owned per ADR 037: bind via native `[value]` +\n * `(change)`, Reactive Forms `formControlName`, Signal Forms `[formField]`,\n * or `[(ngModel)]` — all work orthogonally.\n *\n * `readonly` is ARIA-only because HTML spec does not apply native `[readonly]`\n * to `<select>` (same gotcha as `<input type=\"checkbox|radio\">`). Unlike a text\n * input, though, a native `<select>` is an *uncontrolled* widget: if the listbox\n * opens and the user picks an option, the displayed value changes regardless of\n * the consumer's binding — so \"consumer prevents change\" cannot actually hold a\n * native select readonly. The directive therefore enforces readonly behaviourally\n * (blocks the picker from opening / the value from changing — see\n * `blockWhenReadonly` / `blockKeyWhenReadonly`), mirroring the imperative\n * `el.disabled` enforcement below. Both states are made non-interactive; only\n * readonly stays focusable + un-greyed and presents as the bare value. This is\n * interaction integrity for the control's own state — NOT a value channel, so the\n * ADR 037 no-`@angular/forms` / no-CVA boundary is untouched.\n */\n@Component({\n selector: 'select[skraSelect]',\n standalone: true,\n // Content-bearing host: <ng-content> projects the consumer's\n // <option>/<optgroup> children through. `template: ''` (as used for the void\n // <input> host) would discard them — see ADR 040 §4.\n template: '<ng-content></ng-content>',\n styleUrl: './select.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n '[attr.aria-describedby]': 'context?.describedByIds() ?? null',\n '[attr.aria-invalid]': 'context?.hasError() ? \"true\" : null',\n '[attr.aria-required]': 'context?.isRequired() ? \"true\" : null',\n '[attr.aria-readonly]': 'context?.isReadonly() ? \"true\" : null',\n // No `data-skra-readonly` — slice consumes `[aria-readonly=\"true\"]`\n // directly; emitting a parallel data-attr would be dead surface\n // (no slice selector reads it). Matches checkbox/radio readonly pattern\n // in `_form-controls.scss` (ARIA-only branch, no data-attr companion).\n '(mousedown)': 'blockWhenReadonly($event)',\n '(keydown)': 'blockKeyWhenReadonly($event)',\n },\n})\nexport class SkraNativeSelect {\n private readonly el = inject<ElementRef<HTMLSelectElement>>(ElementRef);\n readonly context = inject(SkraFieldContext, { optional: true });\n\n constructor() {\n const el = this.el.nativeElement;\n\n // Reject native multi-select loudly in dev — Forge fails on contract\n // violations rather than degrading silently. This throw is unrelated to the\n // (now optional, ADR 013 §3.7) field context: `[multiple]` is a capability\n // this atom genuinely cannot honour, whereas a missing field is a supported\n // standalone mode. Dev-only: never crashes a production bundle. A `<select\n // multiple>` that truly wants native UX can drop `skraSelect` and stay raw\n // HTML; for a real multi-select, use the Tier 2 <skra-select>.\n if (isDevMode() && el.multiple) {\n throw new Error(\n '[skraSelect] does not support the native [multiple] attribute at ' +\n 'Tier 1. Native multi-select UX is not production-grade (modifier-key/' +\n 'drag selection, UA-drawn unstylable markers, browser-fragile) and ' +\n 'cannot be fixed at the native <select> tier. Use a single-select ' +\n '<select skraSelect> (optionally with [size] for a listbox), or the ' +\n 'Tier 2 <skra-select> (CDK listbox) for real multi-select. See ' +\n 'adr/specs/0039-select-directive-spec.md §4.1.',\n );\n }\n\n // Field-cascaded native properties — only bind when context is present so\n // standalone consumers retain full control of their static attributes.\n // Mirrors SkraInput / SkraCheckbox.\n if (this.context) {\n const ctx = this.context;\n effect(() => {\n el.id = ctx.fieldId();\n });\n effect(() => {\n el.disabled = ctx.isDisabled();\n });\n }\n }\n\n /**\n * Readonly: suppress the pointer affordance that opens the native listbox.\n * `preventDefault` on `mousedown` stops the picker from opening (and, on a\n * native select, focus-on-click — Tab focus still works, which is the right\n * trade-off for a value-display control).\n */\n protected blockWhenReadonly(event: Event): void {\n if (this.context?.isReadonly()) event.preventDefault();\n }\n\n /**\n * Readonly: suppress every keyboard affordance that opens or mutates the\n * select, while letting Tab through for focus traversal. Space / Enter /\n * Alt+ArrowDown open the listbox; bare Arrows + first-letter typeahead change\n * the value inline without opening it — all are value-changing on a native\n * select, so all are blocked in readonly.\n */\n protected blockKeyWhenReadonly(event: KeyboardEvent): void {\n if (this.context?.isReadonly() && event.key !== 'Tab') {\n event.preventDefault();\n }\n }\n}\n","// select[skraSelect] native form-control directive (SkraNativeSelect — ADR 0054 §4.3).\nexport * from './lib/select/select';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDG;MAwBU,gBAAgB,CAAA;AACV,IAAA,EAAE,GAAG,MAAM,CAAgC,UAAU,CAAC;IAC9D,OAAO,GAAG,MAAM,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAE/D,IAAA,WAAA,GAAA;AACE,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,aAAa;;;;;;;;AAShC,QAAA,IAAI,SAAS,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE;YAC9B,MAAM,IAAI,KAAK,CACb,mEAAmE;gBACjE,uEAAuE;gBACvE,oEAAoE;gBACpE,mEAAmE;gBACnE,qEAAqE;gBACrE,gEAAgE;AAChE,gBAAA,+CAA+C,CAClD;QACH;;;;AAKA,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE;AAChB,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO;YACxB,MAAM,CAAC,MAAK;AACV,gBAAA,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE;AACvB,YAAA,CAAC,CAAC;YACF,MAAM,CAAC,MAAK;AACV,gBAAA,EAAE,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,EAAE;AAChC,YAAA,CAAC,CAAC;QACJ;IACF;AAEA;;;;;AAKG;AACO,IAAA,iBAAiB,CAAC,KAAY,EAAA;AACtC,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE;YAAE,KAAK,CAAC,cAAc,EAAE;IACxD;AAEA;;;;;;AAMG;AACO,IAAA,oBAAoB,CAAC,KAAoB,EAAA;AACjD,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,EAAE;YACrD,KAAK,CAAC,cAAc,EAAE;QACxB;IACF;uGA7DW,gBAAgB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAhB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,gBAAgB,0cAjBjB,2BAA2B,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,k9DAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAiB1B,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBAvB5B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,oBAAoB,EAAA,UAAA,EAClB,IAAI,EAAA,QAAA,EAIN,2BAA2B,EAAA,eAAA,EAEpB,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,QAAQ,EAAA,IAAA,EACnC;AACJ,wBAAA,yBAAyB,EAAE,mCAAmC;AAC9D,wBAAA,qBAAqB,EAAE,qCAAqC;AAC5D,wBAAA,sBAAsB,EAAE,uCAAuC;AAC/D,wBAAA,sBAAsB,EAAE,uCAAuC;;;;;AAK/D,wBAAA,aAAa,EAAE,2BAA2B;AAC1C,wBAAA,WAAW,EAAE,8BAA8B;AAC5C,qBAAA,EAAA,MAAA,EAAA,CAAA,k9DAAA,CAAA,EAAA;;;ACtFH;;ACAA;;AAEG;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skra-ui-popover.mjs","sources":["../../../../libs/ui/popover/src/lib/popover/popover.ts","../../../../libs/ui/popover/src/skra-ui-popover.ts"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n DestroyRef,\r\n ElementRef,\r\n Renderer2,\r\n ViewEncapsulation,\r\n afterNextRender,\r\n inject,\r\n input,\r\n} from '@angular/core';\r\n\r\nimport {\r\n _attachPositioner,\r\n type SkraPlacement,\r\n type _PositionerHandle,\r\n} from '@skra/ui/core';\r\n\r\ndeclare const ngDevMode: boolean | undefined;\r\n\r\n/**\r\n * SkraPopover — a NON-MODAL, anchored panel of arbitrary (interactive) content, rendered in the\r\n * browser TOP LAYER via the native Popover API (`popover=\"auto\"`), per ADR 0044. It is the middle\r\n * ground between Tooltip (supplementary, non-interactive, hover/focus) and the page-blocking modal\r\n * Dialog.\r\n *\r\n * SHAPE (scope 2026-06-06): a Component on the PANEL with projected content — NOT a directive on the\r\n * trigger + `TemplateRef`. The trigger is the consumer's own button linked by the native\r\n * `popovertarget` attribute (zero Forge trigger API); toggle, light-dismiss (pointer-outside),\r\n * Escape and invocation-order stacking are ALL platform-owned (contrast Tooltip's `popover=\"manual\"`,\r\n * which hand-wires Escape). The consumer MUST give `<skra-popover>` an `id` so `popovertarget` can\r\n * reference it.\r\n *\r\n * <button skraButton popovertarget=\"user-menu\">Account</button>\r\n * <skra-popover id=\"user-menu\"> …interactive content… </skra-popover>\r\n *\r\n * Forge owns only: the token-driven surface (see `popover.scss`), positioning via `SkraPositioner`\r\n * (geometry-only inline; ADR 0044 §3 rules 4–5), and the disclosure ARIA on the trigger\r\n * (`aria-expanded` / `aria-controls`). Focus is NOT trapped and NOT force-moved (non-modal — ADR 0044\r\n * §3 rule 8); reachability + focus-return are native to the Popover API. Panel naming is the\r\n * consumer's `aria-labelledby` → projected heading (ADR 033 container carve-out — no `ariaLabel`\r\n * input). A right-click context menu is NOT a Popover concern (→ `skra-menu` + recipe; SRP + WCAG).\r\n *\r\n * Full contract: adr/specs/component-popover-spec.md.\r\n */\r\n@Component({\r\n selector: 'skra-popover',\r\n standalone: true,\r\n exportAs: 'skraPopover',\r\n template: '<ng-content></ng-content>',\r\n styleUrl: './popover.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.Emulated,\r\n host: {\r\n // Native top layer + platform-owned toggle / light-dismiss / Escape / stacking (ADR 0044).\r\n popover: 'auto',\r\n // NOTE: `toggle` is wired IMPERATIVELY (addEventListener) in the constructor, NOT as a host listener.\r\n // A consumer template binding `(toggle)` on <skra-popover> (a documented side-effect path) SHADOWS a\r\n // host-metadata `(toggle)` listener for the same event — which would silently break positioning +\r\n // aria-expanded. A raw `addEventListener` fires alongside the consumer's binding. (Found via the\r\n // skra-menu browser probe, 2026-06-07; same fix applied there.)\r\n },\r\n})\r\nexport class SkraPopover {\r\n /** Placement intent; `flip`/`shift` adjust at runtime. */\r\n readonly placement = input<SkraPlacement>('bottom');\r\n\r\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly renderer = inject(Renderer2);\r\n\r\n /** The consumer's `[popovertarget]` button, resolved once (lazily-idempotent via `resolved`). */\r\n private trigger: HTMLElement | null = null;\r\n private resolved = false;\r\n private positioner?: _PositionerHandle;\r\n\r\n constructor() {\r\n // All imperative DOM wiring lives in afterNextRender — a browser-only hook, so the native listener\r\n // and the trigger resolution never run on the server (SSR-safe by construction; O-18).\r\n afterNextRender(() => {\r\n // Imperative (NOT host-metadata) so a consumer `(toggle)` binding does not shadow it — see host {}.\r\n this.host.nativeElement.addEventListener('toggle', this.onToggleNative);\r\n // Resolve + wire the trigger after the view exists (the trigger may be a later sibling), so the\r\n // disclosure relationship (aria-expanded=\"false\" + aria-controls) is present before first open.\r\n this.ensureTrigger();\r\n });\r\n inject(DestroyRef).onDestroy(() => this.teardown());\r\n }\r\n\r\n // ── Toggle (imperative native listener — see host {} note) ────────────────────\r\n private readonly onToggleNative = (event: Event): void => {\r\n if ((event as ToggleEvent).newState === 'open') this.onOpen();\r\n else this.onClose();\r\n };\r\n\r\n private onOpen(): void {\r\n const anchor = this.ensureTrigger(); // safety net if afterNextRender has not yet run\r\n if (anchor) {\r\n this.renderer.setAttribute(anchor, 'aria-expanded', 'true');\r\n } else {\r\n return; // orphan popover (dev-warned at init); nothing to anchor to.\r\n }\r\n\r\n this.positioner?.destroy();\r\n this.positioner = _attachPositioner(\r\n anchor,\r\n this.host.nativeElement,\r\n () => ({\r\n placement: this.placement(),\r\n offset: this.cssLenPx('--skra-comp-popover-offset'),\r\n viewportPadding: this.cssLenPx('--skra-comp-popover-viewport-padding'),\r\n }),\r\n );\r\n }\r\n\r\n private onClose(): void {\r\n if (this.trigger) {\r\n this.renderer.setAttribute(this.trigger, 'aria-expanded', 'false');\r\n }\r\n this.positioner?.destroy();\r\n this.positioner = undefined;\r\n }\r\n\r\n /**\r\n * Resolve the `[popovertarget]` trigger and establish the disclosure ARIA on it (sanctioned a11y\r\n * wiring, ADR 013-style — not style mutation). Idempotent: runs at most once. Returns the trigger\r\n * (or null for an orphan popover, dev-warned once).\r\n */\r\n private ensureTrigger(): HTMLElement | null {\r\n if (this.resolved) return this.trigger;\r\n this.resolved = true;\r\n\r\n const id = this.host.nativeElement.id;\r\n if (!id) {\r\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\r\n console.warn(\r\n '[skra-popover] has no `id` — it cannot be targeted by a `popovertarget` ' +\r\n 'trigger and the disclosure ARIA (aria-expanded/aria-controls) cannot be wired. ' +\r\n 'Give the popover an id and point the trigger at it: ' +\r\n '<button popovertarget=\"my-id\">…</button> <skra-popover id=\"my-id\">…',\r\n );\r\n }\r\n return null;\r\n }\r\n\r\n // Match by attribute value rather than a built selector — no escaping needed, robust to ids\r\n // with special characters (and `CSS.escape` is not universally available).\r\n this.trigger =\r\n Array.from(\r\n document.querySelectorAll<HTMLElement>('[popovertarget]'),\r\n ).find((el) => el.getAttribute('popovertarget') === id) ?? null;\r\n if (!this.trigger) {\r\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\r\n console.warn(\r\n `[skra-popover] no trigger found with [popovertarget=\"${id}\"] — the popover ` +\r\n 'is unreachable and has no element to carry aria-expanded/aria-controls. ' +\r\n 'Add a focusable trigger button with the matching popovertarget.',\r\n );\r\n }\r\n return null;\r\n }\r\n\r\n // Establish the disclosure relationship before the first open (APG Disclosure).\r\n this.renderer.setAttribute(this.trigger, 'aria-controls', id);\r\n this.renderer.setAttribute(this.trigger, 'aria-expanded', 'false');\r\n return this.trigger;\r\n }\r\n\r\n /** Read a length comp token (px/rem) off the host computed style for the positioner. */\r\n private cssLenPx(prop: string): number {\r\n const raw = getComputedStyle(this.host.nativeElement)\r\n .getPropertyValue(prop)\r\n .trim();\r\n if (raw.endsWith('px')) return parseFloat(raw);\r\n if (raw.endsWith('rem')) {\r\n const rootFontSize =\r\n parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\r\n return parseFloat(raw) * rootFontSize;\r\n }\r\n return parseFloat(raw) || 0;\r\n }\r\n\r\n private teardown(): void {\r\n this.host.nativeElement.removeEventListener('toggle', this.onToggleNative);\r\n this.positioner?.destroy();\r\n if (this.trigger) {\r\n this.renderer.removeAttribute(this.trigger, 'aria-expanded');\r\n this.renderer.removeAttribute(this.trigger, 'aria-controls');\r\n }\r\n }\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-popover.mjs","sources":["../../../../libs/ui/popover/src/lib/popover/popover.ts","../../../../libs/ui/popover/src/skra-ui-popover.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n Renderer2,\n ViewEncapsulation,\n afterNextRender,\n inject,\n input,\n} from '@angular/core';\n\nimport {\n _attachPositioner,\n type SkraPlacement,\n type _PositionerHandle,\n} from '@skra/ui/core';\n\ndeclare const ngDevMode: boolean | undefined;\n\n/**\n * SkraPopover — a NON-MODAL, anchored panel of arbitrary (interactive) content, rendered in the\n * browser TOP LAYER via the native Popover API (`popover=\"auto\"`), per ADR 0044. It is the middle\n * ground between Tooltip (supplementary, non-interactive, hover/focus) and the page-blocking modal\n * Dialog.\n *\n * SHAPE (scope 2026-06-06): a Component on the PANEL with projected content — NOT a directive on the\n * trigger + `TemplateRef`. The trigger is the consumer's own button linked by the native\n * `popovertarget` attribute (zero Forge trigger API); toggle, light-dismiss (pointer-outside),\n * Escape and invocation-order stacking are ALL platform-owned (contrast Tooltip's `popover=\"manual\"`,\n * which hand-wires Escape). The consumer MUST give `<skra-popover>` an `id` so `popovertarget` can\n * reference it.\n *\n * <button skraButton popovertarget=\"user-menu\">Account</button>\n * <skra-popover id=\"user-menu\"> …interactive content… </skra-popover>\n *\n * Forge owns only: the token-driven surface (see `popover.scss`), positioning via `SkraPositioner`\n * (geometry-only inline; ADR 0044 §3 rules 4–5), and the disclosure ARIA on the trigger\n * (`aria-expanded` / `aria-controls`). Focus is NOT trapped and NOT force-moved (non-modal — ADR 0044\n * §3 rule 8); reachability + focus-return are native to the Popover API. Panel naming is the\n * consumer's `aria-labelledby` → projected heading (ADR 033 container carve-out — no `ariaLabel`\n * input). A right-click context menu is NOT a Popover concern (→ `skra-menu` + recipe; SRP + WCAG).\n *\n * Full contract: adr/specs/component-popover-spec.md.\n */\n@Component({\n selector: 'skra-popover',\n standalone: true,\n exportAs: 'skraPopover',\n template: '<ng-content></ng-content>',\n styleUrl: './popover.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n // Native top layer + platform-owned toggle / light-dismiss / Escape / stacking (ADR 0044).\n popover: 'auto',\n // NOTE: `toggle` is wired IMPERATIVELY (addEventListener) in the constructor, NOT as a host listener.\n // A consumer template binding `(toggle)` on <skra-popover> (a documented side-effect path) SHADOWS a\n // host-metadata `(toggle)` listener for the same event — which would silently break positioning +\n // aria-expanded. A raw `addEventListener` fires alongside the consumer's binding. (Found via the\n // skra-menu browser probe, 2026-06-07; same fix applied there.)\n },\n})\nexport class SkraPopover {\n /** Placement intent; `flip`/`shift` adjust at runtime. */\n readonly placement = input<SkraPlacement>('bottom');\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly renderer = inject(Renderer2);\n\n /** The consumer's `[popovertarget]` button, resolved once (lazily-idempotent via `resolved`). */\n private trigger: HTMLElement | null = null;\n private resolved = false;\n private positioner?: _PositionerHandle;\n\n constructor() {\n // All imperative DOM wiring lives in afterNextRender — a browser-only hook, so the native listener\n // and the trigger resolution never run on the server (SSR-safe by construction; O-18).\n afterNextRender(() => {\n // Imperative (NOT host-metadata) so a consumer `(toggle)` binding does not shadow it — see host {}.\n this.host.nativeElement.addEventListener('toggle', this.onToggleNative);\n // Resolve + wire the trigger after the view exists (the trigger may be a later sibling), so the\n // disclosure relationship (aria-expanded=\"false\" + aria-controls) is present before first open.\n this.ensureTrigger();\n });\n inject(DestroyRef).onDestroy(() => this.teardown());\n }\n\n // ── Toggle (imperative native listener — see host {} note) ────────────────────\n private readonly onToggleNative = (event: Event): void => {\n if ((event as ToggleEvent).newState === 'open') this.onOpen();\n else this.onClose();\n };\n\n private onOpen(): void {\n const anchor = this.ensureTrigger(); // safety net if afterNextRender has not yet run\n if (anchor) {\n this.renderer.setAttribute(anchor, 'aria-expanded', 'true');\n } else {\n return; // orphan popover (dev-warned at init); nothing to anchor to.\n }\n\n this.positioner?.destroy();\n this.positioner = _attachPositioner(\n anchor,\n this.host.nativeElement,\n () => ({\n placement: this.placement(),\n offset: this.cssLenPx('--skra-comp-popover-offset'),\n viewportPadding: this.cssLenPx('--skra-comp-popover-viewport-padding'),\n }),\n );\n }\n\n private onClose(): void {\n if (this.trigger) {\n this.renderer.setAttribute(this.trigger, 'aria-expanded', 'false');\n }\n this.positioner?.destroy();\n this.positioner = undefined;\n }\n\n /**\n * Resolve the `[popovertarget]` trigger and establish the disclosure ARIA on it (sanctioned a11y\n * wiring, ADR 013-style — not style mutation). Idempotent: runs at most once. Returns the trigger\n * (or null for an orphan popover, dev-warned once).\n */\n private ensureTrigger(): HTMLElement | null {\n if (this.resolved) return this.trigger;\n this.resolved = true;\n\n const id = this.host.nativeElement.id;\n if (!id) {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n console.warn(\n '[skra-popover] has no `id` — it cannot be targeted by a `popovertarget` ' +\n 'trigger and the disclosure ARIA (aria-expanded/aria-controls) cannot be wired. ' +\n 'Give the popover an id and point the trigger at it: ' +\n '<button popovertarget=\"my-id\">…</button> <skra-popover id=\"my-id\">…',\n );\n }\n return null;\n }\n\n // Match by attribute value rather than a built selector — no escaping needed, robust to ids\n // with special characters (and `CSS.escape` is not universally available).\n this.trigger =\n Array.from(\n document.querySelectorAll<HTMLElement>('[popovertarget]'),\n ).find((el) => el.getAttribute('popovertarget') === id) ?? null;\n if (!this.trigger) {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n console.warn(\n `[skra-popover] no trigger found with [popovertarget=\"${id}\"] — the popover ` +\n 'is unreachable and has no element to carry aria-expanded/aria-controls. ' +\n 'Add a focusable trigger button with the matching popovertarget.',\n );\n }\n return null;\n }\n\n // Establish the disclosure relationship before the first open (APG Disclosure).\n this.renderer.setAttribute(this.trigger, 'aria-controls', id);\n this.renderer.setAttribute(this.trigger, 'aria-expanded', 'false');\n return this.trigger;\n }\n\n /** Read a length comp token (px/rem) off the host computed style for the positioner. */\n private cssLenPx(prop: string): number {\n const raw = getComputedStyle(this.host.nativeElement)\n .getPropertyValue(prop)\n .trim();\n if (raw.endsWith('px')) return parseFloat(raw);\n if (raw.endsWith('rem')) {\n const rootFontSize =\n parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\n return parseFloat(raw) * rootFontSize;\n }\n return parseFloat(raw) || 0;\n }\n\n private teardown(): void {\n this.host.nativeElement.removeEventListener('toggle', this.onToggleNative);\n this.positioner?.destroy();\n if (this.trigger) {\n this.renderer.removeAttribute(this.trigger, 'aria-expanded');\n this.renderer.removeAttribute(this.trigger, 'aria-controls');\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skra-ui-progress.mjs","sources":["../../../../libs/ui/progress/src/lib/progress/progress.ts","../../../../libs/ui/progress/src/skra-ui-progress.ts"],"sourcesContent":["import {\
|
|
1
|
+
{"version":3,"file":"skra-ui-progress.mjs","sources":["../../../../libs/ui/progress/src/lib/progress/progress.ts","../../../../libs/ui/progress/src/skra-ui-progress.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n input,\n} from '@angular/core';\n\n/**\n * `progress[skraProgress]` — a determinate, horizontal task-completion bar (Wave 2,\n * `libs/ui/indicators`). Shows the known progress of a finite task (file upload, wizard\n * \"step 3 of 5\", import job) as a fill from 0 → `value` / `max`.\n *\n * SRP-distinct from `[skraLoadingIndicator]` (ADR 028): that primitive is the\n * *indeterminate* \"host is busy\" spinner injected into another component's `loading()`\n * slot; SkraProgress is the *determinate* \"task is N% complete\" standalone bar. The two\n * are complementary — see `adr/specs/component-progress-spec.md` § SRP boundary.\n *\n * **Why a Component on the native `<progress>` host** (ADR 040), not a `<div role=\"progressbar\">`:\n * 1. ADR 021 (CSP): the fill width is a continuous `value/max` length. A custom element would\n * force `[style.--progress-value]` (forbidden) or a class/`data-*`-per-percent hack. Native\n * `<progress value max>` lets the BROWSER compute the fill width on its\n * `::-webkit-progress-value` / `::-moz-progress-bar` pseudo — zero author inline-style.\n * 2. Free a11y: the native host carries `role=\"progressbar\"` + `aria-valuenow`/`-valuemin`/\n * `-valuemax` with no author ARIA (native-attr-first, boundary #9).\n *\n * Non-interactive: `<progress>` is non-focusable, so the State Surface is all-N/A (no\n * `disabled`/`loading`/`severity` in MVP — those are deferred / belong to other atoms).\n *\n * Naming (ADR 033): the consumer associates a `<label for>` / `aria-labelledby` (passed through\n * to the host). No `SkraFieldContext` injection (a progress bar is a read-only display, not a\n * form field); no `ariaLabel` input.\n *\n * `value`/`max` are plain consumer-driven inputs (ADR 037 — agnostic; wire the source from any\n * signal/form strategy). Native `<progress>` clamps `value` to `[0, max]`, so no author clamp.\n */\n@Component({\n selector: 'progress[skraProgress]',\n standalone: true,\n template: '',\n styleUrl: './progress.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n // The data contract — reflected to the NATIVE attributes. The browser derives\n // role=\"progressbar\" + aria-valuenow/-valuemin/-valuemax + the fill width from these.\n // No [style.*] (ADR 021 — the fill is native, never an inline style) and no data-skra-*\n // (State Surface all-N/A).\n '[attr.value]': 'value()',\n '[attr.max]': 'max()',\n },\n})\nexport class SkraProgress {\n /** Current completion, reflected to the native `value` attribute (native clamps to [0, max]). */\n readonly value = input<number>(0);\n\n /** Upper bound, reflected to the native `max` attribute. Drives native `aria-valuemax`. */\n readonly max = input<number>(100);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;MAiBU,YAAY,CAAA;;IAEd,KAAK,GAAG,KAAK,CAAS,CAAC;8EAAC;;IAGxB,GAAG,GAAG,KAAK,CAAS,GAAG;4EAAC;uGALtB,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAZ,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAY,gZAbb,EAAE,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,+7BAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAaD,YAAY,EAAA,UAAA,EAAA,CAAA;kBAhBxB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,wBAAwB,EAAA,UAAA,EACtB,IAAI,EAAA,QAAA,EACN,EAAE,EAAA,eAAA,EAEK,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,QAAQ,EAAA,IAAA,EACnC;;;;;AAKJ,wBAAA,cAAc,EAAE,SAAS;AACzB,wBAAA,YAAY,EAAE,OAAO;AACtB,qBAAA,EAAA,MAAA,EAAA,CAAA,+7BAAA,CAAA,EAAA;;;ACjDH;;AAEG;;;;"}
|
|
@@ -66,7 +66,7 @@ class SkraRadio {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraRadio, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
69
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.1", type: SkraRadio, isStandalone: true, selector: "input[type=\"radio\"][skraRadio]", host: { listeners: { "click": "blockWhenReadonly($event)", "keydown": "blockKeyWhenReadonly($event)" }, properties: { "attr.data-skra-disabled": "context?.isDisabled() ? \"\" : null", "attr.aria-invalid": "context?.hasError() ? \"true\" : null", "attr.aria-readonly": "context?.isReadonly() ? \"true\" : null", "attr.aria-describedby": "context?.describedByIds() ?? null" } }, ngImport: i0, template: '', isInline: true, styles: [":host{appearance:none;flex-shrink:0;cursor:pointer;outline:none;background-repeat:no-repeat;background-position:center;inline-size:var(--skra-comp-field-radio-size);block-size:var(--skra-comp-field-radio-size);border-width:var(--skra-comp-field-radio-border-width);border-style:solid;border-color:var(--skra-comp-field-radio-border-color);border-radius:50%;background-color:var(--skra-comp-field-radio-background);transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}:host(:checked){background-color:var(--skra-comp-field-radio-checked-background);border-color:var(--skra-comp-field-radio-checked-background);background-image:radial-gradient(circle,var(--skra-comp-field-radio-dot-color) 0,var(--skra-comp-field-radio-dot-color) calc(var(--skra-comp-field-radio-dot-size) / 2),transparent calc(var(--skra-comp-field-radio-dot-size) / 2 + .5px))}:host(:hover:not(:disabled):not([aria-readonly=true])){border-color:var(--skra-comp-field-radio-border-color-hover)}:host(:checked:hover:not(:disabled):not([aria-readonly=true])){background-color:var(--skra-comp-field-radio-checked-background-hover);border-color:var(--skra-comp-field-radio-checked-background-hover)}:host(:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled),:host([data-skra-disabled]){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([aria-readonly=true]){cursor:default;background-color:var(--skra-comp-field-background-readonly);border-color:var(--skra-comp-field-border-color-readonly)}:host(:checked[aria-readonly=true]){background-color:var(--skra-comp-field-radio-checked-background-readonly);border-color:var(--skra-comp-field-radio-checked-background-readonly)}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
69
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.1", type: SkraRadio, isStandalone: true, selector: "input[type=\"radio\"][skraRadio]", host: { listeners: { "click": "blockWhenReadonly($event)", "keydown": "blockKeyWhenReadonly($event)" }, properties: { "attr.data-skra-disabled": "context?.isDisabled() ? \"\" : null", "attr.aria-invalid": "context?.hasError() ? \"true\" : null", "attr.aria-readonly": "context?.isReadonly() ? \"true\" : null", "attr.aria-describedby": "context?.describedByIds() ?? null" } }, ngImport: i0, template: '', isInline: true, styles: [":host{appearance:none;flex-shrink:0;cursor:pointer;outline:none;background-repeat:no-repeat;background-position:center;inline-size:var(--skra-comp-field-radio-size);block-size:var(--skra-comp-field-radio-size);border-width:var(--skra-comp-field-radio-border-width);border-style:solid;border-color:var(--skra-comp-field-radio-border-color);border-radius:50%;background-color:var(--skra-comp-field-radio-background);transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}:host(:checked){background-color:var(--skra-comp-field-radio-checked-background);border-color:var(--skra-comp-field-radio-checked-background);background-image:radial-gradient(circle,var(--skra-comp-field-radio-dot-color) 0,var(--skra-comp-field-radio-dot-color) calc(var(--skra-comp-field-radio-dot-size) / 2),transparent calc(var(--skra-comp-field-radio-dot-size) / 2 + .5px))}@media(hover:hover)and (pointer:fine){:host(:hover:not(:disabled):not([aria-readonly=true])){border-color:var(--skra-comp-field-radio-border-color-hover)}:host(:checked:hover:not(:disabled):not([aria-readonly=true])){background-color:var(--skra-comp-field-radio-checked-background-hover);border-color:var(--skra-comp-field-radio-checked-background-hover)}}:host(:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled),:host([data-skra-disabled]){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([aria-readonly=true]){cursor:default;background-color:var(--skra-comp-field-background-readonly);border-color:var(--skra-comp-field-border-color-readonly)}:host(:checked[aria-readonly=true]){background-color:var(--skra-comp-field-radio-checked-background-readonly);border-color:var(--skra-comp-field-radio-checked-background-readonly)}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
70
70
|
}
|
|
71
71
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraRadio, decorators: [{
|
|
72
72
|
type: Component,
|
|
@@ -81,7 +81,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
|
|
|
81
81
|
'[attr.aria-describedby]': 'context?.describedByIds() ?? null',
|
|
82
82
|
'(click)': 'blockWhenReadonly($event)',
|
|
83
83
|
'(keydown)': 'blockKeyWhenReadonly($event)',
|
|
84
|
-
}, styles: [":host{appearance:none;flex-shrink:0;cursor:pointer;outline:none;background-repeat:no-repeat;background-position:center;inline-size:var(--skra-comp-field-radio-size);block-size:var(--skra-comp-field-radio-size);border-width:var(--skra-comp-field-radio-border-width);border-style:solid;border-color:var(--skra-comp-field-radio-border-color);border-radius:50%;background-color:var(--skra-comp-field-radio-background);transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}:host(:checked){background-color:var(--skra-comp-field-radio-checked-background);border-color:var(--skra-comp-field-radio-checked-background);background-image:radial-gradient(circle,var(--skra-comp-field-radio-dot-color) 0,var(--skra-comp-field-radio-dot-color) calc(var(--skra-comp-field-radio-dot-size) / 2),transparent calc(var(--skra-comp-field-radio-dot-size) / 2 + .5px))}:host(:hover:not(:disabled):not([aria-readonly=true])){border-color:var(--skra-comp-field-radio-border-color-hover)}:host(:checked:hover:not(:disabled):not([aria-readonly=true])){background-color:var(--skra-comp-field-radio-checked-background-hover);border-color:var(--skra-comp-field-radio-checked-background-hover)}:host(:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled),:host([data-skra-disabled]){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([aria-readonly=true]){cursor:default;background-color:var(--skra-comp-field-background-readonly);border-color:var(--skra-comp-field-border-color-readonly)}:host(:checked[aria-readonly=true]){background-color:var(--skra-comp-field-radio-checked-background-readonly);border-color:var(--skra-comp-field-radio-checked-background-readonly)}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"] }]
|
|
84
|
+
}, styles: [":host{appearance:none;flex-shrink:0;cursor:pointer;outline:none;background-repeat:no-repeat;background-position:center;inline-size:var(--skra-comp-field-radio-size);block-size:var(--skra-comp-field-radio-size);border-width:var(--skra-comp-field-radio-border-width);border-style:solid;border-color:var(--skra-comp-field-radio-border-color);border-radius:50%;background-color:var(--skra-comp-field-radio-background);transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}:host(:checked){background-color:var(--skra-comp-field-radio-checked-background);border-color:var(--skra-comp-field-radio-checked-background);background-image:radial-gradient(circle,var(--skra-comp-field-radio-dot-color) 0,var(--skra-comp-field-radio-dot-color) calc(var(--skra-comp-field-radio-dot-size) / 2),transparent calc(var(--skra-comp-field-radio-dot-size) / 2 + .5px))}@media(hover:hover)and (pointer:fine){:host(:hover:not(:disabled):not([aria-readonly=true])){border-color:var(--skra-comp-field-radio-border-color-hover)}:host(:checked:hover:not(:disabled):not([aria-readonly=true])){background-color:var(--skra-comp-field-radio-checked-background-hover);border-color:var(--skra-comp-field-radio-checked-background-hover)}}:host(:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled),:host([data-skra-disabled]){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([aria-readonly=true]){cursor:default;background-color:var(--skra-comp-field-background-readonly);border-color:var(--skra-comp-field-border-color-readonly)}:host(:checked[aria-readonly=true]){background-color:var(--skra-comp-field-radio-checked-background-readonly);border-color:var(--skra-comp-field-radio-checked-background-readonly)}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"] }]
|
|
85
85
|
}], ctorParameters: () => [] });
|
|
86
86
|
|
|
87
87
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skra-ui-radio.mjs","sources":["../../../../libs/ui/radio/src/lib/radio/radio.ts","../../../../libs/ui/radio/src/skra-ui-radio.ts"],"sourcesContent":["import {\
|
|
1
|
+
{"version":3,"file":"skra-ui-radio.mjs","sources":["../../../../libs/ui/radio/src/lib/radio/radio.ts","../../../../libs/ui/radio/src/skra-ui-radio.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n effect,\n inject,\n} from '@angular/core';\nimport { SkraFieldContext } from '@skra/ui/field';\n\n/**\n * Wires a native `<input type=\"radio\">` to SkraFieldContext when inside\n * `<skra-field>`, or stands alone with no cascade. Per ADR 039/040, Forge ships\n * no `<skra-radio>` / `<skra-radio-group>` wrappers — this is a Component-on-\n * the-native-host (`<input>` is void → `template: ''`, ADR 040 §2) carrying its\n * own `radio.scss` via Emulated encapsulation. Radios are\n * grouped via native `<fieldset skraFieldset>` + `<legend skraLegend>`,\n * coordination happens through the shared `name` attribute (HTML-native), and\n * one-of-N value selection is consumer-owned per ADR 037.\n *\n * <fieldset skraFieldset>\n * <legend skraLegend>Choose plan</legend>\n * <skra-field>\n * <input type=\"radio\" skraRadio name=\"plan\" value=\"free\"\n * [checked]=\"plan() === 'free'\" (change)=\"plan.set('free')\" />\n * <label skraLabelFor>Free</label>\n * </skra-field>\n * <skra-field>\n * <input type=\"radio\" skraRadio name=\"plan\" value=\"pro\"\n * [checked]=\"plan() === 'pro'\" (change)=\"plan.set('pro')\" />\n * <label skraLabelFor>Pro</label>\n * </skra-field>\n * </fieldset>\n *\n * Toggle state (`checked`) is NOT reflected as `data-skra-*` — slice CSS uses\n * the native `:checked` pseudo-class. Browser handles `aria-checked` natively.\n */\n@Component({\n selector: 'input[type=\"radio\"][skraRadio]',\n standalone: true,\n // Void host — no <ng-content>. See ADR 040 §2.\n template: '',\n styleUrl: './radio.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n '[attr.data-skra-disabled]': 'context?.isDisabled() ? \"\" : null',\n '[attr.aria-invalid]': 'context?.hasError() ? \"true\" : null',\n // Readonly is ARIA-only (native `readonly` doesn't apply to radios per HTML\n // spec). No `data-skra-readonly` — dead surface (styling keys off\n // `[aria-readonly]`), removed 2026-05-31 to match select's Q-3 ARIA-only\n // pattern (Batch 5 cleanroom review).\n '[attr.aria-readonly]': 'context?.isReadonly() ? \"true\" : null',\n '[attr.aria-describedby]': 'context?.describedByIds() ?? null',\n '(click)': 'blockWhenReadonly($event)',\n '(keydown)': 'blockKeyWhenReadonly($event)',\n },\n})\nexport class SkraRadio {\n private readonly el = inject<ElementRef<HTMLInputElement>>(ElementRef);\n readonly context = inject(SkraFieldContext, { optional: true });\n\n constructor() {\n if (this.context) {\n const ctx = this.context;\n const el = this.el.nativeElement;\n effect(() => {\n el.id = ctx.fieldId();\n });\n effect(() => {\n el.disabled = ctx.isDisabled();\n });\n }\n }\n\n /**\n * Readonly enforcement — native radio has no `[readonly]`, so without this the\n * `aria-readonly` we announce would be a lie (the user could still change the\n * selection). `preventDefault` on `click` blocks the selection change from both\n * pointer and Space/Enter (keyboard activation dispatches a click on form\n * controls). Mirrors the `<select skraSelect>` readonly guard.\n */\n protected blockWhenReadonly(event: Event): void {\n if (this.context?.isReadonly()) event.preventDefault();\n }\n\n /**\n * Arrow keys move selection between radios in a `name` group WITHOUT a click,\n * so they need a separate guard. Block every key except `Tab` (focus traversal)\n * when readonly.\n */\n protected blockKeyWhenReadonly(event: KeyboardEvent): void {\n if (this.context?.isReadonly() && event.key !== 'Tab') {\n event.preventDefault();\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BG;MAsBU,SAAS,CAAA;AACH,IAAA,EAAE,GAAG,MAAM,CAA+B,UAAU,CAAC;IAC7D,OAAO,GAAG,MAAM,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAE/D,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE;AAChB,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO;AACxB,YAAA,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,aAAa;YAChC,MAAM,CAAC,MAAK;AACV,gBAAA,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE;AACvB,YAAA,CAAC,CAAC;YACF,MAAM,CAAC,MAAK;AACV,gBAAA,EAAE,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,EAAE;AAChC,YAAA,CAAC,CAAC;QACJ;IACF;AAEA;;;;;;AAMG;AACO,IAAA,iBAAiB,CAAC,KAAY,EAAA;AACtC,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE;YAAE,KAAK,CAAC,cAAc,EAAE;IACxD;AAEA;;;;AAIG;AACO,IAAA,oBAAoB,CAAC,KAAoB,EAAA;AACjD,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,EAAE;YACrD,KAAK,CAAC,cAAc,EAAE;QACxB;IACF;uGArCW,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAT,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,SAAS,qdAjBV,EAAE,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,0tEAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAiBD,SAAS,EAAA,UAAA,EAAA,CAAA;kBArBrB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,gCAAgC,EAAA,UAAA,EAC9B,IAAI,EAAA,QAAA,EAEN,EAAE,EAAA,eAAA,EAEK,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,QAAQ,EAAA,IAAA,EACnC;AACJ,wBAAA,2BAA2B,EAAE,mCAAmC;AAChE,wBAAA,qBAAqB,EAAE,qCAAqC;;;;;AAK5D,wBAAA,sBAAsB,EAAE,uCAAuC;AAC/D,wBAAA,yBAAyB,EAAE,mCAAmC;AAC9D,wBAAA,SAAS,EAAE,2BAA2B;AACtC,wBAAA,WAAW,EAAE,8BAA8B;AAC5C,qBAAA,EAAA,MAAA,EAAA,CAAA,0tEAAA,CAAA,EAAA;;;ACxDH;;AAEG;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skra-ui-rating-display.mjs","sources":["../../../../libs/ui/rating-display/src/lib/rating-display/rating-display.ts","../../../../libs/ui/rating-display/src/lib/rating-display/rating-display.html","../../../../libs/ui/rating-display/src/index.ts","../../../../libs/ui/rating-display/src/skra-ui-rating-display.ts"],"sourcesContent":["import {\
|
|
1
|
+
{"version":3,"file":"skra-ui-rating-display.mjs","sources":["../../../../libs/ui/rating-display/src/lib/rating-display/rating-display.ts","../../../../libs/ui/rating-display/src/lib/rating-display/rating-display.html","../../../../libs/ui/rating-display/src/index.ts","../../../../libs/ui/rating-display/src/skra-ui-rating-display.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n} from '@angular/core';\n\nexport type RatingDisplaySize = 'sm' | 'md' | 'lg';\n\n/**\n * `<skra-rating-display>` — a static, non-interactive **fractional** rating display\n * (\"4.3 out of 5 stars\"). The read-only counterpart to `skra-star-rating` (the\n * interactive whole-star INPUT in `libs/ui/forms`); a SEPARATE atom by atom-granularity\n * (opposite a11y contract `role=\"img\"` vs `radiogroup`; float vs int; no interaction).\n * Third resident of `libs/ui/data-display`, beside Avatar + StatusDot. See\n * `adr/specs/component-rating-display-spec.md`.\n *\n * **Element, not a decorated native (ADR 012):** there is no native rating element, like\n * StatusDot/Avatar. NOT a Web Component (ADR 000).\n *\n * **Value consumer-owned (ADR 037):** `value` is a plain `input<number>()` (float). The atom\n * owns no value, no `ControlValueAccessor`, no `@angular/forms`.\n *\n * **Fractional fill is CSP-clean (ADR 021):** the fill is QUANTIZED to a `data-skra-fill`\n * bucket reflected on the host (`{0,5,…,100}`); the SCSS maps each bucket to the fill-overlay\n * width. Zero `[style.--var]`, zero inline style — a bounded value is quantizable, so no\n * geometry exception is taken. State Surface all-N/A (non-focusable display; Badge/StatusDot\n * precedent).\n *\n * **Accessible name (ADR 033 Path 3 — the StatusDot/Avatar contract):** the host carries NO\n * default ARIA. The consumer declares semantics:\n * - decorative (Mode A, beside a visible value like \"4.3\") → `aria-hidden=\"true\"`;\n * - meaningful (Mode B, the stars are the sole carrier) → `role=\"img\"` + `aria-label`\n * TOGETHER (e.g. `aria-label=\"Rated 4.3 out of 5\"`).\n * The inner star glyphs are always decorative. NO `ariaLabel` input (boundary #8) — the label\n * is consumer-owned + localizable (the agnostic doctrine; Forge does not hard-code \"out of N\").\n *\n * **Look is skin-owned:** glyph colours + sizes come from the shared family surface\n * (`comp/star-rating.json`). NO `intent`/`emphasis`/`color`/`variant` look-inputs.\n */\n@Component({\n selector: 'skra-rating-display',\n standalone: true,\n templateUrl: './rating-display.html',\n styleUrl: './rating-display.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n // Quantized fractional fill (ADR 021 — data-attr, never [style.--var]).\n '[attr.data-skra-fill]': 'fillBucket()',\n // Variant Surface size axis (ADR 035) — reuses the family star-size-* tokens.\n '[attr.data-skra-size]': 'size()',\n },\n})\nexport class SkraRatingDisplay {\n /** The rating to display — FLOAT (e.g. 4.3). Consumer-owned (ADR 037); clamped to [0, max]. */\n readonly value = input<number>(0);\n /** Number of stars (semantic count). */\n readonly max = input<number>(5);\n /** ADR 035 size axis — the only variant axis. */\n readonly size = input<RatingDisplaySize>('md');\n\n /** Star slots [1..max] — both layers render the same count. */\n readonly stars = computed(() => {\n const n = Math.max(0, Math.floor(this.max()));\n return Array.from({ length: n }, (_, i) => i + 1);\n });\n\n /**\n * Fill percentage quantized to 5% buckets (`{0,5,…,100}`) — reflected as `data-skra-fill`,\n * mapped to the overlay width by the SCSS. 4.3/5 → 86% → bucket 85 (visually exact-enough).\n * A bounded, quantizable value is exactly what ADR 021 reflection is for — no style exception.\n */\n readonly fillBucket = computed(() => {\n const max = this.max();\n if (max <= 0) return 0;\n const ratio = this.value() / max;\n const clamped = Math.min(1, Math.max(0, ratio));\n return Math.round(clamped * 20) * 5;\n });\n}\n","<!--\r\n Two stacked glyph layers: an empty-stars track that defines the box, and a filled-stars\r\n overlay clipped to the quantized fill width (the SCSS maps data-skra-fill → inline-size).\r\n Both layers are decorative (aria-hidden); the accessible name, when any, is on the host\r\n (consumer-applied role=\"img\" + aria-label — ADR 033 Path 3).\r\n-->\r\n<div class=\"skra-rating-display-track\" aria-hidden=\"true\">\r\n @for (star of stars(); track star) {\r\n <svg\r\n class=\"skra-rating-display-glyph\"\r\n viewBox=\"0 0 24 24\"\r\n focusable=\"false\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n d=\"M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z\"\r\n />\r\n </svg>\r\n }\r\n</div>\r\n<div class=\"skra-rating-display-fill\" aria-hidden=\"true\">\r\n @for (star of stars(); track star) {\r\n <svg\r\n class=\"skra-rating-display-glyph\"\r\n viewBox=\"0 0 24 24\"\r\n focusable=\"false\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n d=\"M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z\"\r\n />\r\n </svg>\r\n }\r\n</div>\r\n","// Static fractional rating display — read-only counterpart to skra-star-rating\n// (@skra/ui/star-rating); shares the family glyph surface (comp/star-rating.json).\nexport * from './lib/rating-display/rating-display';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BG;MAeU,iBAAiB,CAAA;;IAEnB,KAAK,GAAG,KAAK,CAAS,CAAC;8EAAC;;IAExB,GAAG,GAAG,KAAK,CAAS,CAAC;4EAAC;;IAEtB,IAAI,GAAG,KAAK,CAAoB,IAAI;6EAAC;;AAGrC,IAAA,KAAK,GAAG,QAAQ,CAAC,MAAK;AAC7B,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC7C,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnD,CAAC;8EAAC;AAEF;;;;AAIG;AACM,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAK;AAClC,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;QACtB,IAAI,GAAG,IAAI,CAAC;AAAE,YAAA,OAAO,CAAC;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG;AAChC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC;IACrC,CAAC;mFAAC;uGAzBS,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,iBAAiB,4hBCvD9B,uqCAkCA,EAAA,MAAA,EAAA,CAAA,+yEAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FDqBa,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAd7B,SAAS;+BACE,qBAAqB,EAAA,UAAA,EACnB,IAAI,EAAA,eAAA,EAGC,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,QAAQ,EAAA,IAAA,EACnC;;AAEJ,wBAAA,uBAAuB,EAAE,cAAc;;AAEvC,wBAAA,uBAAuB,EAAE,QAAQ;AAClC,qBAAA,EAAA,QAAA,EAAA,uqCAAA,EAAA,MAAA,EAAA,CAAA,+yEAAA,CAAA,EAAA;;;AErDH;AACA;;ACDA;;AAEG;;;;"}
|