@joanroucoux/cairn-ui 0.8.2 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +114 -0
- package/fesm2022/joanroucoux-cairn-ui-action-bar.mjs +57 -53
- package/fesm2022/joanroucoux-cairn-ui-action-bar.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-alert.mjs +155 -47
- package/fesm2022/joanroucoux-cairn-ui-alert.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-amount.mjs +220 -110
- package/fesm2022/joanroucoux-cairn-ui-amount.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-async.mjs +392 -216
- package/fesm2022/joanroucoux-cairn-ui-async.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-avatar.mjs +145 -68
- package/fesm2022/joanroucoux-cairn-ui-avatar.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-back-link.mjs +87 -47
- package/fesm2022/joanroucoux-cairn-ui-back-link.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-badge.mjs +83 -43
- package/fesm2022/joanroucoux-cairn-ui-badge.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-button.mjs +184 -104
- package/fesm2022/joanroucoux-cairn-ui-button.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-card.mjs +232 -137
- package/fesm2022/joanroucoux-cairn-ui-card.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-choice-chips.mjs +298 -102
- package/fesm2022/joanroucoux-cairn-ui-choice-chips.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-control.mjs +4 -17
- package/fesm2022/joanroucoux-cairn-ui-control.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-delta.mjs +150 -83
- package/fesm2022/joanroucoux-cairn-ui-delta.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-dialog.mjs +508 -471
- package/fesm2022/joanroucoux-cairn-ui-dialog.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-donut.mjs +255 -157
- package/fesm2022/joanroucoux-cairn-ui-donut.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-drawer.mjs +303 -0
- package/fesm2022/joanroucoux-cairn-ui-drawer.mjs.map +1 -0
- package/fesm2022/joanroucoux-cairn-ui-empty.mjs +76 -35
- package/fesm2022/joanroucoux-cairn-ui-empty.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-external-link.mjs +40 -31
- package/fesm2022/joanroucoux-cairn-ui-external-link.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-fact.mjs +188 -79
- package/fesm2022/joanroucoux-cairn-ui-fact.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-field.mjs +309 -173
- package/fesm2022/joanroucoux-cairn-ui-field.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-filter-chips.mjs +165 -87
- package/fesm2022/joanroucoux-cairn-ui-filter-chips.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-group-header.mjs +269 -0
- package/fesm2022/joanroucoux-cairn-ui-group-header.mjs.map +1 -0
- package/fesm2022/joanroucoux-cairn-ui-input.mjs +205 -85
- package/fesm2022/joanroucoux-cairn-ui-input.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-line-chart.mjs +838 -512
- package/fesm2022/joanroucoux-cairn-ui-line-chart.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-menu.mjs +401 -225
- package/fesm2022/joanroucoux-cairn-ui-menu.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-meter.mjs +143 -57
- package/fesm2022/joanroucoux-cairn-ui-meter.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-motion.mjs +367 -399
- package/fesm2022/joanroucoux-cairn-ui-motion.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-nav-item.mjs +73 -44
- package/fesm2022/joanroucoux-cairn-ui-nav-item.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-result-group.mjs +191 -0
- package/fesm2022/joanroucoux-cairn-ui-result-group.mjs.map +1 -0
- package/fesm2022/joanroucoux-cairn-ui-row.mjs +408 -146
- package/fesm2022/joanroucoux-cairn-ui-row.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-segmented.mjs +183 -81
- package/fesm2022/joanroucoux-cairn-ui-segmented.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-select-pill.mjs +270 -0
- package/fesm2022/joanroucoux-cairn-ui-select-pill.mjs.map +1 -0
- package/fesm2022/joanroucoux-cairn-ui-select.mjs +121 -67
- package/fesm2022/joanroucoux-cairn-ui-select.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-skeleton.mjs +129 -51
- package/fesm2022/joanroucoux-cairn-ui-skeleton.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-stale-link.mjs +80 -39
- package/fesm2022/joanroucoux-cairn-ui-stale-link.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-stat.mjs +85 -55
- package/fesm2022/joanroucoux-cairn-ui-stat.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-switch.mjs +48 -35
- package/fesm2022/joanroucoux-cairn-ui-switch.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-tab-bar.mjs +113 -69
- package/fesm2022/joanroucoux-cairn-ui-tab-bar.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-table.mjs +1036 -310
- package/fesm2022/joanroucoux-cairn-ui-table.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui-toast.mjs +240 -127
- package/fesm2022/joanroucoux-cairn-ui-toast.mjs.map +1 -1
- package/fesm2022/joanroucoux-cairn-ui.mjs +0 -4
- package/package.json +17 -1
- package/styles/motion.css +1 -13
- package/styles/tokens.css +35 -64
- package/types/joanroucoux-cairn-ui-action-bar.d.ts +9 -14
- package/types/joanroucoux-cairn-ui-alert.d.ts +29 -15
- package/types/joanroucoux-cairn-ui-amount.d.ts +64 -32
- package/types/joanroucoux-cairn-ui-async.d.ts +85 -38
- package/types/joanroucoux-cairn-ui-avatar.d.ts +34 -22
- package/types/joanroucoux-cairn-ui-back-link.d.ts +20 -15
- package/types/joanroucoux-cairn-ui-badge.d.ts +22 -14
- package/types/joanroucoux-cairn-ui-button.d.ts +36 -18
- package/types/joanroucoux-cairn-ui-card.d.ts +48 -23
- package/types/joanroucoux-cairn-ui-choice-chips.d.ts +91 -35
- package/types/joanroucoux-cairn-ui-control.d.ts +9 -18
- package/types/joanroucoux-cairn-ui-delta.d.ts +46 -24
- package/types/joanroucoux-cairn-ui-dialog.d.ts +124 -57
- package/types/joanroucoux-cairn-ui-donut.d.ts +83 -46
- package/types/joanroucoux-cairn-ui-drawer.d.ts +73 -0
- package/types/joanroucoux-cairn-ui-empty.d.ts +20 -13
- package/types/joanroucoux-cairn-ui-external-link.d.ts +6 -10
- package/types/joanroucoux-cairn-ui-fact.d.ts +49 -25
- package/types/joanroucoux-cairn-ui-field.d.ts +72 -49
- package/types/joanroucoux-cairn-ui-filter-chips.d.ts +35 -20
- package/types/joanroucoux-cairn-ui-group-header.d.ts +58 -0
- package/types/joanroucoux-cairn-ui-input.d.ts +59 -37
- package/types/joanroucoux-cairn-ui-line-chart.d.ts +199 -89
- package/types/joanroucoux-cairn-ui-menu.d.ts +81 -44
- package/types/joanroucoux-cairn-ui-meter.d.ts +44 -22
- package/types/joanroucoux-cairn-ui-motion.d.ts +61 -75
- package/types/joanroucoux-cairn-ui-nav-item.d.ts +15 -13
- package/types/joanroucoux-cairn-ui-result-group.d.ts +52 -0
- package/types/joanroucoux-cairn-ui-row.d.ts +92 -37
- package/types/joanroucoux-cairn-ui-segmented.d.ts +51 -27
- package/types/joanroucoux-cairn-ui-select-pill.d.ts +59 -0
- package/types/joanroucoux-cairn-ui-select.d.ts +28 -18
- package/types/joanroucoux-cairn-ui-skeleton.d.ts +35 -18
- package/types/joanroucoux-cairn-ui-stale-link.d.ts +23 -16
- package/types/joanroucoux-cairn-ui-stat.d.ts +26 -21
- package/types/joanroucoux-cairn-ui-switch.d.ts +7 -11
- package/types/joanroucoux-cairn-ui-tab-bar.d.ts +20 -17
- package/types/joanroucoux-cairn-ui-table.d.ts +251 -89
- package/types/joanroucoux-cairn-ui-toast.d.ts +46 -36
- package/types/joanroucoux-cairn-ui.d.ts +1 -2
- package/fesm2022/joanroucoux-cairn-ui.mjs.map +0 -1
|
@@ -1,73 +1,121 @@
|
|
|
1
|
-
import * as i0 from
|
|
2
|
-
import {
|
|
3
|
-
import { holdTransitionsUntilRendered } from
|
|
4
|
-
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { Component, booleanAttribute, computed, input, model, viewChildren } from "@angular/core";
|
|
3
|
+
import { holdTransitionsUntilRendered } from "@joanroucoux/cairn-ui/motion";
|
|
5
4
|
const nextId = (() => {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
let count = 0;
|
|
6
|
+
return () => `ui-segmented-${++count}`;
|
|
8
7
|
})();
|
|
9
8
|
const OPTION_CLASSES = "relative z-10 flex-1 cursor-pointer px-3 text-label font-medium transition-[scale] duration-(--duration-press) ease-out after:absolute after:inset-x-0 after:top-1/2 after:h-(--row-min) after:-translate-y-1/2 after:content-[''] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) active:scale-(--press-scale)";
|
|
10
|
-
const SEGMENTED_SIZES = [
|
|
9
|
+
const SEGMENTED_SIZES = ["md", "sm"];
|
|
11
10
|
const SIZE_CLASSES = {
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
md: "h-10 pointer-fine:h-8",
|
|
12
|
+
sm: "h-10 pointer-fine:h-[30px]"
|
|
14
13
|
};
|
|
15
|
-
const SELECTED_CLASSES =
|
|
16
|
-
const UNSELECTED_CLASSES =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
14
|
+
const SELECTED_CLASSES = "text-(--foreground)";
|
|
15
|
+
const UNSELECTED_CLASSES = "text-(--muted-foreground) hover:text-(--foreground)";
|
|
16
|
+
var UiSegmented = class UiSegmented {
|
|
17
|
+
options = input.required(...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
|
|
18
|
+
label = input.required(...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
|
|
19
|
+
showLabel = input(false, {
|
|
20
|
+
...ngDevMode ? { debugName: "showLabel" } : /* istanbul ignore next */ {},
|
|
21
|
+
transform: booleanAttribute
|
|
22
|
+
});
|
|
23
|
+
labelId = nextId();
|
|
24
|
+
value = model.required(...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
|
|
25
|
+
size = input("md", ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
|
|
26
|
+
radios = viewChildren("radio", ...ngDevMode ? [{ debugName: "radios" }] : /* istanbul ignore next */ []);
|
|
27
|
+
thumbIndex = computed(() => {
|
|
28
|
+
const index = this.options().findIndex((option) => option.value === this.value());
|
|
29
|
+
return index === -1 ? 0 : index + 1;
|
|
30
|
+
}, ...ngDevMode ? [{ debugName: "thumbIndex" }] : /* istanbul ignore next */ []);
|
|
31
|
+
constructor() {
|
|
32
|
+
holdTransitionsUntilRendered();
|
|
33
|
+
}
|
|
34
|
+
optionClasses(optionValue) {
|
|
35
|
+
return `${OPTION_CLASSES} ${SIZE_CLASSES[this.size()]} ${optionValue === this.value() ? SELECTED_CLASSES : UNSELECTED_CLASSES}`;
|
|
36
|
+
}
|
|
37
|
+
tabIndexFor(optionValue) {
|
|
38
|
+
const opts = this.options();
|
|
39
|
+
return optionValue === (opts.some((option) => option.value === this.value()) ? this.value() : opts[0]?.value) ? 0 : -1;
|
|
40
|
+
}
|
|
41
|
+
select(optionValue) {
|
|
42
|
+
this.value.set(optionValue);
|
|
43
|
+
}
|
|
44
|
+
onKeydown(event) {
|
|
45
|
+
const delta = {
|
|
46
|
+
ArrowRight: 1,
|
|
47
|
+
ArrowDown: 1,
|
|
48
|
+
ArrowLeft: -1,
|
|
49
|
+
ArrowUp: -1
|
|
50
|
+
}[event.key];
|
|
51
|
+
if (delta === void 0) return;
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
const opts = this.options();
|
|
54
|
+
const nextIndex = (opts.findIndex((option) => option.value === this.value()) + delta + opts.length) % opts.length;
|
|
55
|
+
const next = opts[nextIndex];
|
|
56
|
+
this.value.set(next.value);
|
|
57
|
+
this.radios()[nextIndex]?.nativeElement.focus();
|
|
58
|
+
}
|
|
59
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
60
|
+
minVersion: "12.0.0",
|
|
61
|
+
version: "22.2.0",
|
|
62
|
+
ngImport: i0,
|
|
63
|
+
type: UiSegmented,
|
|
64
|
+
deps: [],
|
|
65
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
66
|
+
});
|
|
67
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
68
|
+
minVersion: "17.0.0",
|
|
69
|
+
version: "22.2.0",
|
|
70
|
+
type: UiSegmented,
|
|
71
|
+
isStandalone: true,
|
|
72
|
+
selector: "ui-segmented",
|
|
73
|
+
inputs: {
|
|
74
|
+
options: {
|
|
75
|
+
classPropertyName: "options",
|
|
76
|
+
publicName: "options",
|
|
77
|
+
isSignal: true,
|
|
78
|
+
isRequired: true,
|
|
79
|
+
transformFunction: null
|
|
80
|
+
},
|
|
81
|
+
label: {
|
|
82
|
+
classPropertyName: "label",
|
|
83
|
+
publicName: "label",
|
|
84
|
+
isSignal: true,
|
|
85
|
+
isRequired: true,
|
|
86
|
+
transformFunction: null
|
|
87
|
+
},
|
|
88
|
+
showLabel: {
|
|
89
|
+
classPropertyName: "showLabel",
|
|
90
|
+
publicName: "showLabel",
|
|
91
|
+
isSignal: true,
|
|
92
|
+
isRequired: false,
|
|
93
|
+
transformFunction: null
|
|
94
|
+
},
|
|
95
|
+
value: {
|
|
96
|
+
classPropertyName: "value",
|
|
97
|
+
publicName: "value",
|
|
98
|
+
isSignal: true,
|
|
99
|
+
isRequired: true,
|
|
100
|
+
transformFunction: null
|
|
101
|
+
},
|
|
102
|
+
size: {
|
|
103
|
+
classPropertyName: "size",
|
|
104
|
+
publicName: "size",
|
|
105
|
+
isSignal: true,
|
|
106
|
+
isRequired: false,
|
|
107
|
+
transformFunction: null
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
outputs: { value: "valueChange" },
|
|
111
|
+
viewQueries: [{
|
|
112
|
+
propertyName: "radios",
|
|
113
|
+
predicate: ["radio"],
|
|
114
|
+
descendants: true,
|
|
115
|
+
isSignal: true
|
|
116
|
+
}],
|
|
117
|
+
ngImport: i0,
|
|
118
|
+
template: `
|
|
71
119
|
<div [class]="showLabel() ? 'flex flex-col gap-1.5' : ''">
|
|
72
120
|
@if (showLabel()) {
|
|
73
121
|
<span class="text-label leading-[17px] font-medium text-(--muted-foreground)" [id]="labelId">{{
|
|
@@ -107,13 +155,20 @@ class UiSegmented {
|
|
|
107
155
|
}
|
|
108
156
|
</div>
|
|
109
157
|
</div>
|
|
110
|
-
`,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
158
|
+
`,
|
|
159
|
+
isInline: true
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
163
|
+
minVersion: "12.0.0",
|
|
164
|
+
version: "22.2.0",
|
|
165
|
+
ngImport: i0,
|
|
166
|
+
type: UiSegmented,
|
|
167
|
+
decorators: [{
|
|
168
|
+
type: Component,
|
|
169
|
+
args: [{
|
|
170
|
+
selector: "ui-segmented",
|
|
171
|
+
template: `
|
|
117
172
|
<div [class]="showLabel() ? 'flex flex-col gap-1.5' : ''">
|
|
118
173
|
@if (showLabel()) {
|
|
119
174
|
<span class="text-label leading-[17px] font-medium text-(--muted-foreground)" [id]="labelId">{{
|
|
@@ -153,13 +208,60 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
|
|
|
153
208
|
}
|
|
154
209
|
</div>
|
|
155
210
|
</div>
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
211
|
+
`
|
|
212
|
+
}]
|
|
213
|
+
}],
|
|
214
|
+
ctorParameters: () => [],
|
|
215
|
+
propDecorators: {
|
|
216
|
+
options: [{
|
|
217
|
+
type: i0.Input,
|
|
218
|
+
args: [{
|
|
219
|
+
isSignal: true,
|
|
220
|
+
alias: "options",
|
|
221
|
+
required: true
|
|
222
|
+
}]
|
|
223
|
+
}],
|
|
224
|
+
label: [{
|
|
225
|
+
type: i0.Input,
|
|
226
|
+
args: [{
|
|
227
|
+
isSignal: true,
|
|
228
|
+
alias: "label",
|
|
229
|
+
required: true
|
|
230
|
+
}]
|
|
231
|
+
}],
|
|
232
|
+
showLabel: [{
|
|
233
|
+
type: i0.Input,
|
|
234
|
+
args: [{
|
|
235
|
+
isSignal: true,
|
|
236
|
+
alias: "showLabel",
|
|
237
|
+
required: false
|
|
238
|
+
}]
|
|
239
|
+
}],
|
|
240
|
+
value: [{
|
|
241
|
+
type: i0.Input,
|
|
242
|
+
args: [{
|
|
243
|
+
isSignal: true,
|
|
244
|
+
alias: "value",
|
|
245
|
+
required: true
|
|
246
|
+
}]
|
|
247
|
+
}, {
|
|
248
|
+
type: i0.Output,
|
|
249
|
+
args: ["valueChange"]
|
|
250
|
+
}],
|
|
251
|
+
size: [{
|
|
252
|
+
type: i0.Input,
|
|
253
|
+
args: [{
|
|
254
|
+
isSignal: true,
|
|
255
|
+
alias: "size",
|
|
256
|
+
required: false
|
|
257
|
+
}]
|
|
258
|
+
}],
|
|
259
|
+
radios: [{
|
|
260
|
+
type: i0.ViewChildren,
|
|
261
|
+
args: ["radio", { isSignal: true }]
|
|
262
|
+
}]
|
|
263
|
+
}
|
|
264
|
+
});
|
|
164
265
|
export { SEGMENTED_SIZES, UiSegmented };
|
|
165
|
-
|
|
266
|
+
|
|
267
|
+
//# sourceMappingURL=joanroucoux-cairn-ui-segmented.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"joanroucoux-cairn-ui-segmented.mjs","
|
|
1
|
+
{"version":3,"file":"joanroucoux-cairn-ui-segmented.mjs","names":[],"sources":["../../../projects/ui/segmented/segmented.ts"],"sourcesContent":["import { Component, ElementRef, booleanAttribute, computed, input, model, viewChildren } from '@angular/core';\n\nimport { holdTransitionsUntilRendered } from '@joanroucoux/cairn-ui/motion';\n\nconst nextId = (() => {\n let count = 0;\n\n return () => `ui-segmented-${++count}`;\n})();\n\nexport type SegmentedOption = {\n value: string;\n label: string;\n};\n\nconst OPTION_CLASSES =\n \"relative z-10 flex-1 cursor-pointer px-3 text-label font-medium transition-[scale] duration-(--duration-press) ease-out after:absolute after:inset-x-0 after:top-1/2 after:h-(--row-min) after:-translate-y-1/2 after:content-[''] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) active:scale-(--press-scale)\";\n\nexport const SEGMENTED_SIZES = ['md', 'sm'] as const;\nexport type SegmentedSize = (typeof SEGMENTED_SIZES)[number];\n\nconst SIZE_CLASSES: Record<SegmentedSize, string> = {\n md: 'h-10 pointer-fine:h-8',\n sm: 'h-10 pointer-fine:h-[30px]',\n};\n\nconst SELECTED_CLASSES = 'text-(--foreground)';\n\nconst UNSELECTED_CLASSES = 'text-(--muted-foreground) hover:text-(--foreground)';\n\n/**\n * Exclusive choice within a small, known set: a time range, a unit, a mode.\n *\n * @example\n * <ui-segmented [options]=\"ranges\" label=\"Time range\" [(value)]=\"range\" />\n */\n@Component({\n selector: 'ui-segmented',\n template: `\n <div [class]=\"showLabel() ? 'flex flex-col gap-1.5' : ''\">\n @if (showLabel()) {\n <span class=\"text-label leading-[17px] font-medium text-(--muted-foreground)\" [id]=\"labelId\">{{\n label()\n }}</span>\n }\n <div\n class=\"rounded-control relative grid bg-(--muted) p-0.5\"\n role=\"radiogroup\"\n [attr.aria-label]=\"showLabel() ? null : label()\"\n [attr.aria-labelledby]=\"showLabel() ? labelId : null\"\n [style.grid-template-columns]=\"'repeat(' + options().length + ', 1fr)'\"\n >\n @if (thumbIndex(); as index) {\n <span\n aria-hidden=\"true\"\n class=\"absolute top-0.5 bottom-0.5 left-0.5 rounded-[calc(var(--radius-control)-2px)] bg-(--card) shadow-[0_1px_2px_rgb(0_0_0/0.08),inset_0_0_0_1px_var(--border)] transition-transform duration-(--duration-fast) ease-out\"\n data-thumb\n [style.transform]=\"'translateX(' + (index - 1) * 100 + '%)'\"\n [style.width]=\"'calc((100% - 4px) / ' + options().length + ')'\"\n ></span>\n }\n\n @for (option of options(); track option.value) {\n <button\n #radio\n role=\"radio\"\n type=\"button\"\n [attr.aria-checked]=\"option.value === value()\"\n [attr.tabindex]=\"tabIndexFor(option.value)\"\n [class]=\"optionClasses(option.value)\"\n (click)=\"select(option.value)\"\n (keydown)=\"onKeydown($event)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n `,\n})\nexport class UiSegmented {\n readonly options = input.required<SegmentedOption[]>();\n readonly label = input.required<string>();\n readonly showLabel = input(false, { transform: booleanAttribute });\n\n protected readonly labelId = nextId();\n readonly value = model.required<string>();\n readonly size = input<SegmentedSize>('md');\n\n protected readonly radios = viewChildren<ElementRef<HTMLButtonElement>>('radio');\n\n protected readonly thumbIndex = computed(() => {\n const index = this.options().findIndex((option) => option.value === this.value());\n\n return index === -1 ? 0 : index + 1;\n });\n\n constructor() {\n holdTransitionsUntilRendered();\n }\n\n protected optionClasses(optionValue: string): string {\n return `${OPTION_CLASSES} ${SIZE_CLASSES[this.size()]} ${optionValue === this.value() ? SELECTED_CLASSES : UNSELECTED_CLASSES}`;\n }\n\n protected tabIndexFor(optionValue: string): number {\n const opts = this.options();\n const tabStopValue = opts.some((option) => option.value === this.value()) ? this.value() : opts[0]?.value;\n\n return optionValue === tabStopValue ? 0 : -1;\n }\n\n protected select(optionValue: string): void {\n this.value.set(optionValue);\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n const delta = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[event.key];\n if (delta === undefined) {\n return;\n }\n event.preventDefault();\n\n const opts = this.options();\n const currentIndex = opts.findIndex((option) => option.value === this.value());\n const nextIndex = (currentIndex + delta + opts.length) % opts.length;\n const next = opts[nextIndex]!;\n\n this.value.set(next.value);\n this.radios()[nextIndex]?.nativeElement.focus();\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { Component, booleanAttribute, computed, contentChild, input, output, viewChild } from "@angular/core";
|
|
3
|
+
import { UiMenu, UiMenuTrigger } from "@joanroucoux/cairn-ui/menu";
|
|
4
|
+
const HOST_CLASSES = "relative flex-none inline-flex h-11 items-center pointer-fine:h-8";
|
|
5
|
+
const DISABLED_HOST_CLASSES = "opacity-40";
|
|
6
|
+
const TRIGGER_CLASSES = "-mx-[5px] flex h-11 cursor-pointer items-center rounded-pill border-x-[5px] border-y-0 border-transparent bg-transparent p-0 font-[inherit] focus-visible:outline-2 focus-visible:-outline-offset-5 focus-visible:outline-(--ring) pointer-fine:mx-0 pointer-fine:h-8 pointer-fine:border-x-0 pointer-fine:focus-visible:outline-offset-0 disabled:pointer-events-none";
|
|
7
|
+
const PILL_CLASSES = "flex h-[34px] items-center rounded-pill pr-[30px] pl-3 text-label font-medium whitespace-nowrap forced-colors:border pointer-fine:h-8";
|
|
8
|
+
const REST_PILL_CLASSES = "bg-(--card) text-(--foreground) shadow-[inset_0_0_0_1px_var(--border)]";
|
|
9
|
+
const ACTIVE_PILL_CLASSES = "bg-(--primary) text-(--primary-foreground)";
|
|
10
|
+
const CLEAR_CLASSES = "absolute end-0 flex size-[34px] cursor-pointer items-center justify-center rounded-pill border-0 bg-transparent p-0 text-(--primary-foreground) focus-visible:outline-2 focus-visible:-outline-offset-7 focus-visible:outline-(--primary-foreground) pointer-fine:size-8 pointer-fine:focus-visible:-outline-offset-6 after:absolute after:-inset-[5px] pointer-fine:after:-inset-0.5";
|
|
11
|
+
var UiSelectPill = class UiSelectPill {
|
|
12
|
+
active = input(false, {
|
|
13
|
+
...ngDevMode ? { debugName: "active" } : /* istanbul ignore next */ {},
|
|
14
|
+
transform: booleanAttribute
|
|
15
|
+
});
|
|
16
|
+
disabled = input(false, {
|
|
17
|
+
...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
|
|
18
|
+
transform: booleanAttribute
|
|
19
|
+
});
|
|
20
|
+
clearLabel = input.required(...ngDevMode ? [{ debugName: "clearLabel" }] : /* istanbul ignore next */ []);
|
|
21
|
+
contextLabel = input(...ngDevMode ? [void 0, { debugName: "contextLabel" }] : /* istanbul ignore next */ []);
|
|
22
|
+
cleared = output();
|
|
23
|
+
menu = contentChild.required(UiMenu, ...ngDevMode ? [{ debugName: "menu" }] : /* istanbul ignore next */ []);
|
|
24
|
+
trigger = viewChild.required("trigger", ...ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []);
|
|
25
|
+
hostClasses = computed(() => this.disabled() ? `${HOST_CLASSES} ${DISABLED_HOST_CLASSES}` : HOST_CLASSES, ...ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []);
|
|
26
|
+
chevronClasses = computed(() => this.active() ? "text-(--primary-foreground)" : "text-(--foreground)", ...ngDevMode ? [{ debugName: "chevronClasses" }] : /* istanbul ignore next */ []);
|
|
27
|
+
triggerClasses = TRIGGER_CLASSES;
|
|
28
|
+
clearClasses = CLEAR_CLASSES;
|
|
29
|
+
clear() {
|
|
30
|
+
this.cleared.emit();
|
|
31
|
+
this.trigger().nativeElement.focus();
|
|
32
|
+
}
|
|
33
|
+
pillClasses = computed(() => `${PILL_CLASSES} ${this.active() ? ACTIVE_PILL_CLASSES : REST_PILL_CLASSES}`, ...ngDevMode ? [{ debugName: "pillClasses" }] : /* istanbul ignore next */ []);
|
|
34
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
35
|
+
minVersion: "12.0.0",
|
|
36
|
+
version: "22.2.0",
|
|
37
|
+
ngImport: i0,
|
|
38
|
+
type: UiSelectPill,
|
|
39
|
+
deps: [],
|
|
40
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
41
|
+
});
|
|
42
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
43
|
+
minVersion: "17.0.0",
|
|
44
|
+
version: "22.2.0",
|
|
45
|
+
type: UiSelectPill,
|
|
46
|
+
isStandalone: true,
|
|
47
|
+
selector: "ui-select-pill",
|
|
48
|
+
inputs: {
|
|
49
|
+
active: {
|
|
50
|
+
classPropertyName: "active",
|
|
51
|
+
publicName: "active",
|
|
52
|
+
isSignal: true,
|
|
53
|
+
isRequired: false,
|
|
54
|
+
transformFunction: null
|
|
55
|
+
},
|
|
56
|
+
disabled: {
|
|
57
|
+
classPropertyName: "disabled",
|
|
58
|
+
publicName: "disabled",
|
|
59
|
+
isSignal: true,
|
|
60
|
+
isRequired: false,
|
|
61
|
+
transformFunction: null
|
|
62
|
+
},
|
|
63
|
+
clearLabel: {
|
|
64
|
+
classPropertyName: "clearLabel",
|
|
65
|
+
publicName: "clearLabel",
|
|
66
|
+
isSignal: true,
|
|
67
|
+
isRequired: true,
|
|
68
|
+
transformFunction: null
|
|
69
|
+
},
|
|
70
|
+
contextLabel: {
|
|
71
|
+
classPropertyName: "contextLabel",
|
|
72
|
+
publicName: "contextLabel",
|
|
73
|
+
isSignal: true,
|
|
74
|
+
isRequired: false,
|
|
75
|
+
transformFunction: null
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
outputs: { cleared: "cleared" },
|
|
79
|
+
host: { properties: { "class": "hostClasses()" } },
|
|
80
|
+
queries: [{
|
|
81
|
+
propertyName: "menu",
|
|
82
|
+
first: true,
|
|
83
|
+
predicate: UiMenu,
|
|
84
|
+
descendants: true,
|
|
85
|
+
isSignal: true
|
|
86
|
+
}],
|
|
87
|
+
viewQueries: [{
|
|
88
|
+
propertyName: "trigger",
|
|
89
|
+
first: true,
|
|
90
|
+
predicate: ["trigger"],
|
|
91
|
+
descendants: true,
|
|
92
|
+
isSignal: true
|
|
93
|
+
}],
|
|
94
|
+
ngImport: i0,
|
|
95
|
+
template: `
|
|
96
|
+
<button
|
|
97
|
+
#trigger
|
|
98
|
+
type="button"
|
|
99
|
+
[attr.aria-disabled]="disabled() || null"
|
|
100
|
+
[class]="triggerClasses"
|
|
101
|
+
[disabled]="disabled()"
|
|
102
|
+
[uiMenuTrigger]="menu()"
|
|
103
|
+
>
|
|
104
|
+
<span data-pill [class]="pillClasses()">
|
|
105
|
+
@if (active() && contextLabel()) {
|
|
106
|
+
<span class="sr-only">{{ contextLabel() }} </span>
|
|
107
|
+
}
|
|
108
|
+
<ng-content
|
|
109
|
+
/></span>
|
|
110
|
+
</button>
|
|
111
|
+
@if (active() && !disabled()) {
|
|
112
|
+
<button data-clear type="button" [attr.aria-label]="clearLabel()" [class]="clearClasses" (click)="clear()">
|
|
113
|
+
<svg
|
|
114
|
+
aria-hidden="true"
|
|
115
|
+
fill="none"
|
|
116
|
+
height="14"
|
|
117
|
+
stroke="currentColor"
|
|
118
|
+
stroke-linecap="round"
|
|
119
|
+
stroke-linejoin="round"
|
|
120
|
+
stroke-width="2"
|
|
121
|
+
viewBox="0 0 24 24"
|
|
122
|
+
width="14"
|
|
123
|
+
>
|
|
124
|
+
<path d="M18 6 6 18M6 6l12 12" />
|
|
125
|
+
</svg>
|
|
126
|
+
</button>
|
|
127
|
+
} @else {
|
|
128
|
+
<svg
|
|
129
|
+
aria-hidden="true"
|
|
130
|
+
class="pointer-events-none absolute right-2.5"
|
|
131
|
+
data-chevron
|
|
132
|
+
fill="none"
|
|
133
|
+
height="14"
|
|
134
|
+
stroke="currentColor"
|
|
135
|
+
stroke-linecap="round"
|
|
136
|
+
stroke-linejoin="round"
|
|
137
|
+
stroke-width="2"
|
|
138
|
+
viewBox="0 0 24 24"
|
|
139
|
+
width="14"
|
|
140
|
+
[class]="chevronClasses()"
|
|
141
|
+
>
|
|
142
|
+
<path d="m6 9 6 6 6-6" />
|
|
143
|
+
</svg>
|
|
144
|
+
}
|
|
145
|
+
<ng-content select="ui-menu" />
|
|
146
|
+
`,
|
|
147
|
+
isInline: true,
|
|
148
|
+
dependencies: [{
|
|
149
|
+
kind: "directive",
|
|
150
|
+
type: UiMenuTrigger,
|
|
151
|
+
selector: "[uiMenuTrigger]",
|
|
152
|
+
inputs: ["uiMenuTrigger"]
|
|
153
|
+
}]
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
157
|
+
minVersion: "12.0.0",
|
|
158
|
+
version: "22.2.0",
|
|
159
|
+
ngImport: i0,
|
|
160
|
+
type: UiSelectPill,
|
|
161
|
+
decorators: [{
|
|
162
|
+
type: Component,
|
|
163
|
+
args: [{
|
|
164
|
+
selector: "ui-select-pill",
|
|
165
|
+
imports: [UiMenuTrigger],
|
|
166
|
+
template: `
|
|
167
|
+
<button
|
|
168
|
+
#trigger
|
|
169
|
+
type="button"
|
|
170
|
+
[attr.aria-disabled]="disabled() || null"
|
|
171
|
+
[class]="triggerClasses"
|
|
172
|
+
[disabled]="disabled()"
|
|
173
|
+
[uiMenuTrigger]="menu()"
|
|
174
|
+
>
|
|
175
|
+
<span data-pill [class]="pillClasses()">
|
|
176
|
+
@if (active() && contextLabel()) {
|
|
177
|
+
<span class="sr-only">{{ contextLabel() }} </span>
|
|
178
|
+
}
|
|
179
|
+
<ng-content
|
|
180
|
+
/></span>
|
|
181
|
+
</button>
|
|
182
|
+
@if (active() && !disabled()) {
|
|
183
|
+
<button data-clear type="button" [attr.aria-label]="clearLabel()" [class]="clearClasses" (click)="clear()">
|
|
184
|
+
<svg
|
|
185
|
+
aria-hidden="true"
|
|
186
|
+
fill="none"
|
|
187
|
+
height="14"
|
|
188
|
+
stroke="currentColor"
|
|
189
|
+
stroke-linecap="round"
|
|
190
|
+
stroke-linejoin="round"
|
|
191
|
+
stroke-width="2"
|
|
192
|
+
viewBox="0 0 24 24"
|
|
193
|
+
width="14"
|
|
194
|
+
>
|
|
195
|
+
<path d="M18 6 6 18M6 6l12 12" />
|
|
196
|
+
</svg>
|
|
197
|
+
</button>
|
|
198
|
+
} @else {
|
|
199
|
+
<svg
|
|
200
|
+
aria-hidden="true"
|
|
201
|
+
class="pointer-events-none absolute right-2.5"
|
|
202
|
+
data-chevron
|
|
203
|
+
fill="none"
|
|
204
|
+
height="14"
|
|
205
|
+
stroke="currentColor"
|
|
206
|
+
stroke-linecap="round"
|
|
207
|
+
stroke-linejoin="round"
|
|
208
|
+
stroke-width="2"
|
|
209
|
+
viewBox="0 0 24 24"
|
|
210
|
+
width="14"
|
|
211
|
+
[class]="chevronClasses()"
|
|
212
|
+
>
|
|
213
|
+
<path d="m6 9 6 6 6-6" />
|
|
214
|
+
</svg>
|
|
215
|
+
}
|
|
216
|
+
<ng-content select="ui-menu" />
|
|
217
|
+
`,
|
|
218
|
+
host: { "[class]": "hostClasses()" }
|
|
219
|
+
}]
|
|
220
|
+
}],
|
|
221
|
+
propDecorators: {
|
|
222
|
+
active: [{
|
|
223
|
+
type: i0.Input,
|
|
224
|
+
args: [{
|
|
225
|
+
isSignal: true,
|
|
226
|
+
alias: "active",
|
|
227
|
+
required: false
|
|
228
|
+
}]
|
|
229
|
+
}],
|
|
230
|
+
disabled: [{
|
|
231
|
+
type: i0.Input,
|
|
232
|
+
args: [{
|
|
233
|
+
isSignal: true,
|
|
234
|
+
alias: "disabled",
|
|
235
|
+
required: false
|
|
236
|
+
}]
|
|
237
|
+
}],
|
|
238
|
+
clearLabel: [{
|
|
239
|
+
type: i0.Input,
|
|
240
|
+
args: [{
|
|
241
|
+
isSignal: true,
|
|
242
|
+
alias: "clearLabel",
|
|
243
|
+
required: true
|
|
244
|
+
}]
|
|
245
|
+
}],
|
|
246
|
+
contextLabel: [{
|
|
247
|
+
type: i0.Input,
|
|
248
|
+
args: [{
|
|
249
|
+
isSignal: true,
|
|
250
|
+
alias: "contextLabel",
|
|
251
|
+
required: false
|
|
252
|
+
}]
|
|
253
|
+
}],
|
|
254
|
+
cleared: [{
|
|
255
|
+
type: i0.Output,
|
|
256
|
+
args: ["cleared"]
|
|
257
|
+
}],
|
|
258
|
+
menu: [{
|
|
259
|
+
type: i0.ContentChild,
|
|
260
|
+
args: [i0.forwardRef(() => UiMenu), { isSignal: true }]
|
|
261
|
+
}],
|
|
262
|
+
trigger: [{
|
|
263
|
+
type: i0.ViewChild,
|
|
264
|
+
args: ["trigger", { isSignal: true }]
|
|
265
|
+
}]
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
export { UiSelectPill };
|
|
269
|
+
|
|
270
|
+
//# sourceMappingURL=joanroucoux-cairn-ui-select-pill.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"joanroucoux-cairn-ui-select-pill.mjs","names":[],"sources":["../../../projects/ui/select-pill/select-pill.ts"],"sourcesContent":["import {\n Component,\n ElementRef,\n booleanAttribute,\n computed,\n contentChild,\n input,\n output,\n viewChild,\n} from '@angular/core';\n\nimport { UiMenu, UiMenuTrigger } from '@joanroucoux/cairn-ui/menu';\n\nconst HOST_CLASSES = 'relative flex-none inline-flex h-11 items-center pointer-fine:h-8';\n\nconst DISABLED_HOST_CLASSES = 'opacity-40';\n\nconst TRIGGER_CLASSES =\n '-mx-[5px] flex h-11 cursor-pointer items-center rounded-pill border-x-[5px] border-y-0 border-transparent bg-transparent p-0 font-[inherit] focus-visible:outline-2 focus-visible:-outline-offset-5 focus-visible:outline-(--ring) pointer-fine:mx-0 pointer-fine:h-8 pointer-fine:border-x-0 pointer-fine:focus-visible:outline-offset-0 disabled:pointer-events-none';\n\nconst PILL_CLASSES =\n 'flex h-[34px] items-center rounded-pill pr-[30px] pl-3 text-label font-medium whitespace-nowrap forced-colors:border pointer-fine:h-8';\n\nconst REST_PILL_CLASSES = 'bg-(--card) text-(--foreground) shadow-[inset_0_0_0_1px_var(--border)]';\n\nconst ACTIVE_PILL_CLASSES = 'bg-(--primary) text-(--primary-foreground)';\n\nconst CLEAR_CLASSES =\n 'absolute end-0 flex size-[34px] cursor-pointer items-center justify-center rounded-pill border-0 bg-transparent p-0 text-(--primary-foreground) focus-visible:outline-2 focus-visible:-outline-offset-7 focus-visible:outline-(--primary-foreground) pointer-fine:size-8 pointer-fine:focus-visible:-outline-offset-6 after:absolute after:-inset-[5px] pointer-fine:after:-inset-0.5';\n\n/**\n * A pill that opens a `ui-menu` of exclusive choices, to head a row of filter chips: outlined at rest with a\n * chevron, solid primary when `active`, where a separate 14 px cross replaces the chevron and emits `cleared`.\n * It is 34 px tall inside a 44 px target on touch and 32 px with a fine pointer; its focus ring is an outline\n * 2 px outside the pill; the cross has a 44 px hit area on touch (36 px with a fine pointer). `contextLabel`, when\n * given, is read before the label while active so a screen reader hears what the account is. Clearing moves focus\n * back to the trigger. `disabled` dims it like a disabled button, opens nothing and draws the chevron even when `active`. The projected text is the pill label and the projected `ui-menu` is what it opens.\n *\n * @example\n * <ui-select-pill uiChipsLeading [active]=\"!!account()\" clearLabel=\"Clear the account\" (cleared)=\"account.set('')\">\n * {{ accountName() }}\n * <ui-menu label=\"Account\" sheet>\n * <button uiMenuItem [checked]=\"!account()\" (click)=\"account.set('')\">All accounts</button>\n * </ui-menu>\n * </ui-select-pill>\n */\n@Component({\n selector: 'ui-select-pill',\n imports: [UiMenuTrigger],\n template: `\n <button\n #trigger\n type=\"button\"\n [attr.aria-disabled]=\"disabled() || null\"\n [class]=\"triggerClasses\"\n [disabled]=\"disabled()\"\n [uiMenuTrigger]=\"menu()\"\n >\n <span data-pill [class]=\"pillClasses()\">\n @if (active() && contextLabel()) {\n <span class=\"sr-only\">{{ contextLabel() }} </span>\n }\n <ng-content\n /></span>\n </button>\n @if (active() && !disabled()) {\n <button data-clear type=\"button\" [attr.aria-label]=\"clearLabel()\" [class]=\"clearClasses\" (click)=\"clear()\">\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n height=\"14\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n viewBox=\"0 0 24 24\"\n width=\"14\"\n >\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </button>\n } @else {\n <svg\n aria-hidden=\"true\"\n class=\"pointer-events-none absolute right-2.5\"\n data-chevron\n fill=\"none\"\n height=\"14\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n viewBox=\"0 0 24 24\"\n width=\"14\"\n [class]=\"chevronClasses()\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n }\n <ng-content select=\"ui-menu\" />\n `,\n host: {\n '[class]': 'hostClasses()',\n },\n})\nexport class UiSelectPill {\n readonly active = input(false, { transform: booleanAttribute });\n readonly disabled = input(false, { transform: booleanAttribute });\n readonly clearLabel = input.required<string>();\n readonly contextLabel = input<string>();\n readonly cleared = output();\n\n protected readonly menu = contentChild.required(UiMenu);\n protected readonly trigger = viewChild.required<ElementRef<HTMLButtonElement>>('trigger');\n\n protected readonly hostClasses = computed(() =>\n this.disabled() ? `${HOST_CLASSES} ${DISABLED_HOST_CLASSES}` : HOST_CLASSES,\n );\n protected readonly chevronClasses = computed(() =>\n this.active() ? 'text-(--primary-foreground)' : 'text-(--foreground)',\n );\n protected readonly triggerClasses = TRIGGER_CLASSES;\n protected readonly clearClasses = CLEAR_CLASSES;\n protected clear(): void {\n this.cleared.emit();\n this.trigger().nativeElement.focus();\n }\n\n protected readonly pillClasses = computed(\n () => `${PILL_CLASSES} ${this.active() ? ACTIVE_PILL_CLASSES : REST_PILL_CLASSES}`,\n );\n}\n"],"mappings":"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"}
|