@nanahoshi/mona-ui 0.11.3 → 0.12.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/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-cell.component-C86jzKCU.mjs → nanahoshi-mona-ui-grid-grid-footer-cell.component-WEDbZ5vy.mjs} +2 -2
- package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-D_GxIU2u.mjs → nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-ibH5osCg.mjs} +2 -2
- package/fesm2022/{nanahoshi-mona-ui-grid-grid-list.component-C9VBe6IU.mjs → nanahoshi-mona-ui-grid-grid-list.component-ZM3CneJ0.mjs} +5 -5
- package/fesm2022/{nanahoshi-mona-ui-grid-grid-toggle.component-BpgLVr6a.mjs → nanahoshi-mona-ui-grid-grid-toggle.component-hc-LeIb0.mjs} +2 -2
- package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-9f5wNcOJ.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-DYajpOb9.mjs} +5 -5
- package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-CChyqXg7.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-Pm8Fbp6M.mjs} +27 -14
- package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
- package/fesm2022/nanahoshi-mona-ui-rating.mjs +606 -0
- package/fesm2022/nanahoshi-mona-ui-segmented.mjs +1 -1
- package/package.json +5 -1
- package/rating/package.json +4 -0
- package/types/nanahoshi-mona-ui-grid.d.ts +6 -1
- package/types/nanahoshi-mona-ui-rating.d.ts +295 -0
- package/types/nanahoshi-mona-ui-segmented.d.ts +1 -1
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { inject, TemplateRef, Directive, computed, viewChild, contentChild, signal, input, output, model, Component } from '@angular/core';
|
|
4
|
+
import { LucideStar, LucideHeart, LucideFlame, LucideDiamond, LucideCircle, LucideDynamicIcon } from '@lucide/angular';
|
|
5
|
+
import { createElementControlId } from '@nanahoshi/mona-ui/internal';
|
|
6
|
+
import { range } from '@mirei/ts-collections';
|
|
7
|
+
import { twMerge } from 'tailwind-merge';
|
|
8
|
+
import { cva } from 'class-variance-authority';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @description Renders the pointer-preview visual for rating items. Overrides the default preset
|
|
12
|
+
* overlay whenever the visible state comes from pointer preview.
|
|
13
|
+
*/
|
|
14
|
+
class RatingHoveredItemTemplateDirective {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.templateRef = inject(TemplateRef);
|
|
17
|
+
}
|
|
18
|
+
static ngTemplateContextGuard(_directive, context) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingHoveredItemTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
22
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.6", type: RatingHoveredItemTemplateDirective, isStandalone: true, selector: "ng-template[monaRatingHoveredItemTemplate]", ngImport: i0 }); }
|
|
23
|
+
}
|
|
24
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingHoveredItemTemplateDirective, decorators: [{
|
|
25
|
+
type: Directive,
|
|
26
|
+
args: [{
|
|
27
|
+
selector: "ng-template[monaRatingHoveredItemTemplate]"
|
|
28
|
+
}]
|
|
29
|
+
}] });
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @description Renders the default (unselected) visual for every rating item. Overrides the
|
|
33
|
+
* default preset icon for the base layer of each item.
|
|
34
|
+
*/
|
|
35
|
+
class RatingItemTemplateDirective {
|
|
36
|
+
constructor() {
|
|
37
|
+
this.templateRef = inject(TemplateRef);
|
|
38
|
+
}
|
|
39
|
+
static ngTemplateContextGuard(_directive, context) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingItemTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
43
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.6", type: RatingItemTemplateDirective, isStandalone: true, selector: "ng-template[monaRatingItemTemplate]", ngImport: i0 }); }
|
|
44
|
+
}
|
|
45
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingItemTemplateDirective, decorators: [{
|
|
46
|
+
type: Directive,
|
|
47
|
+
args: [{
|
|
48
|
+
selector: "ng-template[monaRatingItemTemplate]"
|
|
49
|
+
}]
|
|
50
|
+
}] });
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @description Renders the committed selected visual for rating items. Overrides the default
|
|
54
|
+
* preset overlay whenever the visible state comes from the committed value.
|
|
55
|
+
*/
|
|
56
|
+
class RatingSelectedItemTemplateDirective {
|
|
57
|
+
constructor() {
|
|
58
|
+
this.templateRef = inject(TemplateRef);
|
|
59
|
+
}
|
|
60
|
+
static ngTemplateContextGuard(_directive, context) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingSelectedItemTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
64
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.6", type: RatingSelectedItemTemplateDirective, isStandalone: true, selector: "ng-template[monaRatingSelectedItemTemplate]", ngImport: i0 }); }
|
|
65
|
+
}
|
|
66
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingSelectedItemTemplateDirective, decorators: [{
|
|
67
|
+
type: Directive,
|
|
68
|
+
args: [{
|
|
69
|
+
selector: "ng-template[monaRatingSelectedItemTemplate]"
|
|
70
|
+
}]
|
|
71
|
+
}] });
|
|
72
|
+
|
|
73
|
+
const ratingContainerThemeVariants = cva(`inline-flex items-center gap-2.5`);
|
|
74
|
+
const ratingControlThemeVariants = cva(`
|
|
75
|
+
group
|
|
76
|
+
inline-flex items-center
|
|
77
|
+
cursor-pointer select-none
|
|
78
|
+
rounded-md
|
|
79
|
+
outline-none
|
|
80
|
+
transition-colors duration-(--mona-motion-fast)
|
|
81
|
+
focus-visible:ring-2 focus-visible:ring-focus-indicator/35
|
|
82
|
+
data-[disabled="true"]:pointer-events-none
|
|
83
|
+
data-[disabled="true"]:cursor-not-allowed
|
|
84
|
+
data-[readonly="true"]:cursor-default
|
|
85
|
+
data-[invalid="true"]:ring-2 data-[invalid="true"]:ring-error/35
|
|
86
|
+
data-[invalid="true"]:focus-visible:ring-error/35
|
|
87
|
+
`, {
|
|
88
|
+
variants: {
|
|
89
|
+
size: {
|
|
90
|
+
small: "gap-1 p-0.5",
|
|
91
|
+
medium: "gap-1 p-1",
|
|
92
|
+
large: "gap-1.5 p-1.5"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
defaultVariants: {
|
|
96
|
+
size: "medium"
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const ratingItemThemeVariants = cva(`relative flex items-center justify-center overflow-hidden`, {
|
|
100
|
+
variants: {
|
|
101
|
+
size: {
|
|
102
|
+
small: "h-6 w-6",
|
|
103
|
+
medium: "h-7 w-7",
|
|
104
|
+
large: "h-8 w-8"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
defaultVariants: {
|
|
108
|
+
size: "medium"
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
const ratingIconThemeVariants = cva(`
|
|
112
|
+
block shrink-0
|
|
113
|
+
text-muted-foreground opacity-45
|
|
114
|
+
transition-colors duration-(--mona-motion-fast)
|
|
115
|
+
group-data-[disabled="true"]:text-disabled-foreground
|
|
116
|
+
`, {
|
|
117
|
+
variants: {
|
|
118
|
+
size: {
|
|
119
|
+
small: "h-4 w-4",
|
|
120
|
+
medium: "h-5 w-5",
|
|
121
|
+
large: "h-6 w-6"
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
defaultVariants: {
|
|
125
|
+
size: "medium"
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
const ratingOverlayIconThemeVariants = cva(`block shrink-0`, {
|
|
129
|
+
variants: {
|
|
130
|
+
size: {
|
|
131
|
+
small: "h-4 w-4",
|
|
132
|
+
medium: "h-5 w-5",
|
|
133
|
+
large: "h-6 w-6"
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
defaultVariants: {
|
|
137
|
+
size: "medium"
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
const ratingOverlayClipThemeVariants = cva(`
|
|
141
|
+
absolute bottom-0 start-0 top-0
|
|
142
|
+
pointer-events-none
|
|
143
|
+
overflow-hidden
|
|
144
|
+
`);
|
|
145
|
+
const ratingOverlayContentThemeVariants = cva(`
|
|
146
|
+
flex items-center justify-center
|
|
147
|
+
transition-colors duration-(--mona-motion-fast)
|
|
148
|
+
group-data-[disabled="true"]:text-disabled-foreground
|
|
149
|
+
`, {
|
|
150
|
+
variants: {
|
|
151
|
+
size: {
|
|
152
|
+
small: "h-6 w-6",
|
|
153
|
+
medium: "h-7 w-7",
|
|
154
|
+
large: "h-8 w-8"
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
defaultVariants: {
|
|
158
|
+
size: "medium"
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
const ratingLabelThemeVariants = cva(`whitespace-nowrap`, {
|
|
162
|
+
variants: {
|
|
163
|
+
size: {
|
|
164
|
+
small: "text-sm",
|
|
165
|
+
medium: "text-sm",
|
|
166
|
+
large: "text-base"
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
defaultVariants: {
|
|
170
|
+
size: "medium"
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const DEFAULT_ITEMS_COUNT = 5;
|
|
175
|
+
/**
|
|
176
|
+
* Normalizes an arbitrary `itemsCount` value into a safe positive integer.
|
|
177
|
+
* Numeric strings are converted, fractional values are floored, and
|
|
178
|
+
* non-finite values fall back to the default.
|
|
179
|
+
*/
|
|
180
|
+
function normalizeItemsCount(value) {
|
|
181
|
+
if (typeof value === "string") {
|
|
182
|
+
if (value.trim() === "") {
|
|
183
|
+
return DEFAULT_ITEMS_COUNT;
|
|
184
|
+
}
|
|
185
|
+
value = Number(value);
|
|
186
|
+
}
|
|
187
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
188
|
+
return DEFAULT_ITEMS_COUNT;
|
|
189
|
+
}
|
|
190
|
+
return Math.max(1, Math.floor(value));
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Returns the interaction step for the given precision.
|
|
194
|
+
*/
|
|
195
|
+
function getRatingStep(precision) {
|
|
196
|
+
return precision === "half" ? 0.5 : 1;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Rounds a value to the nearest multiple of the given step while avoiding
|
|
200
|
+
* floating-point drift. The result is constrained to one decimal place.
|
|
201
|
+
*/
|
|
202
|
+
function normalizeToStep(value, step) {
|
|
203
|
+
const normalized = Math.round((value + Number.EPSILON) / step) * step;
|
|
204
|
+
return Number(normalized.toFixed(1));
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Normalizes an externally supplied value for rendering and interaction.
|
|
208
|
+
* Non-finite values become `0`, out-of-range values are clamped to the
|
|
209
|
+
* valid domain, and the result is snapped to the active precision step.
|
|
210
|
+
*/
|
|
211
|
+
function normalizeRatingValue(value, itemsCount, precision) {
|
|
212
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
213
|
+
return 0;
|
|
214
|
+
}
|
|
215
|
+
const clamped = Math.max(0, Math.min(itemsCount, value));
|
|
216
|
+
return Math.max(0, Math.min(itemsCount, normalizeToStep(clamped, getRatingStep(precision))));
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Fill amount for one item in continuous selection mode: every item at or
|
|
220
|
+
* below the display value fills fully, one boundary item fills partially.
|
|
221
|
+
*/
|
|
222
|
+
function getContinuousItemFill(displayValue, itemValue) {
|
|
223
|
+
return Math.max(0, Math.min(1, displayValue - (itemValue - 1)));
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Fill amount for one item in single selection mode: only the item
|
|
227
|
+
* representing the display value fills, possibly partially.
|
|
228
|
+
*/
|
|
229
|
+
function getSingleItemFill(displayValue, itemValue) {
|
|
230
|
+
if (displayValue === 0) {
|
|
231
|
+
return 0;
|
|
232
|
+
}
|
|
233
|
+
const activeItem = Math.ceil(displayValue);
|
|
234
|
+
if (itemValue !== activeItem) {
|
|
235
|
+
return 0;
|
|
236
|
+
}
|
|
237
|
+
return Math.max(0, Math.min(1, displayValue - (itemValue - 1)));
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Converts a pointer position inside an item into a candidate rating value.
|
|
241
|
+
* Whole-item precision always selects the full item; half precision splits
|
|
242
|
+
* the item into two horizontal regions, honoring the effective text
|
|
243
|
+
* direction so the first visual half maps to the lower value.
|
|
244
|
+
*/
|
|
245
|
+
function getPointerRatingValue(args) {
|
|
246
|
+
const { clientX, direction, itemRect, itemValue, precision } = args;
|
|
247
|
+
if (precision === "item") {
|
|
248
|
+
return itemValue;
|
|
249
|
+
}
|
|
250
|
+
let ratio = (clientX - itemRect.left) / itemRect.width;
|
|
251
|
+
if (direction === "rtl") {
|
|
252
|
+
ratio = 1 - ratio;
|
|
253
|
+
}
|
|
254
|
+
return ratio <= 0.5 ? itemValue - 0.5 : itemValue;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const ratingIcons = {
|
|
258
|
+
circle: LucideCircle,
|
|
259
|
+
diamond: LucideDiamond,
|
|
260
|
+
flame: LucideFlame,
|
|
261
|
+
heart: LucideHeart,
|
|
262
|
+
star: LucideStar
|
|
263
|
+
};
|
|
264
|
+
class RatingComponent {
|
|
265
|
+
constructor() {
|
|
266
|
+
this.activeState = computed(() => this.previewActive() ? "hovered" : "selected", /* @ts-ignore */
|
|
267
|
+
...(ngDevMode ? [{ debugName: "activeState" }] : /* istanbul ignore next */ []));
|
|
268
|
+
this.containerClasses = computed(() => twMerge(ratingContainerThemeVariants(), this.userClass()), /* @ts-ignore */
|
|
269
|
+
...(ngDevMode ? [{ debugName: "containerClasses" }] : /* istanbul ignore next */ []));
|
|
270
|
+
this.controlClasses = computed(() => ratingControlThemeVariants({ size: this.size() }), /* @ts-ignore */
|
|
271
|
+
...(ngDevMode ? [{ debugName: "controlClasses" }] : /* istanbul ignore next */ []));
|
|
272
|
+
this.controlElement = viewChild.required("ratingControl", /* @ts-ignore */
|
|
273
|
+
...(ngDevMode ? [{ debugName: "controlElement" }] : /* istanbul ignore next */ []));
|
|
274
|
+
this.displayValue = computed(() => this.previewValue() ?? this.normalizedValue(), /* @ts-ignore */
|
|
275
|
+
...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
|
|
276
|
+
this.effectiveAriaLabelledBy = computed(() => {
|
|
277
|
+
if (this.ariaLabelledBy()) {
|
|
278
|
+
return this.ariaLabelledBy();
|
|
279
|
+
}
|
|
280
|
+
if (!this.ariaLabel() && this.label()) {
|
|
281
|
+
return this.labelId;
|
|
282
|
+
}
|
|
283
|
+
return null;
|
|
284
|
+
}, /* @ts-ignore */
|
|
285
|
+
...(ngDevMode ? [{ debugName: "effectiveAriaLabelledBy" }] : /* istanbul ignore next */ []));
|
|
286
|
+
this.effectiveAriaValueText = computed(() => {
|
|
287
|
+
const custom = this.ariaValueText();
|
|
288
|
+
if (custom) {
|
|
289
|
+
return custom(this.normalizedValue(), this.itemsCount());
|
|
290
|
+
}
|
|
291
|
+
return this.normalizedValue() === 0 ? "Not rated" : `${this.normalizedValue()} out of ${this.itemsCount()}`;
|
|
292
|
+
}, /* @ts-ignore */
|
|
293
|
+
...(ngDevMode ? [{ debugName: "effectiveAriaValueText" }] : /* istanbul ignore next */ []));
|
|
294
|
+
this.effectiveTabIndex = computed(() => (this.disabled() ? -1 : this.tabindex()), /* @ts-ignore */
|
|
295
|
+
...(ngDevMode ? [{ debugName: "effectiveTabIndex" }] : /* istanbul ignore next */ []));
|
|
296
|
+
this.hoveredTemplate = contentChild(RatingHoveredItemTemplateDirective, { ...(ngDevMode ? { debugName: "hoveredTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
|
|
297
|
+
this.iconClasses = computed(() => ratingIconThemeVariants({ size: this.size() }), /* @ts-ignore */
|
|
298
|
+
...(ngDevMode ? [{ debugName: "iconClasses" }] : /* istanbul ignore next */ []));
|
|
299
|
+
this.iconToRender = computed(() => ratingIcons[this.icon()], /* @ts-ignore */
|
|
300
|
+
...(ngDevMode ? [{ debugName: "iconToRender" }] : /* istanbul ignore next */ []));
|
|
301
|
+
this.interactionDisabled = computed(() => this.disabled() || this.readonly(), /* @ts-ignore */
|
|
302
|
+
...(ngDevMode ? [{ debugName: "interactionDisabled" }] : /* istanbul ignore next */ []));
|
|
303
|
+
this.interactionStep = computed(() => getRatingStep(this.precision()), /* @ts-ignore */
|
|
304
|
+
...(ngDevMode ? [{ debugName: "interactionStep" }] : /* istanbul ignore next */ []));
|
|
305
|
+
this.invalidState = computed(() => this.touched() && this.invalid(), /* @ts-ignore */
|
|
306
|
+
...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
|
|
307
|
+
this.itemClasses = computed(() => ratingItemThemeVariants({ size: this.size() }), /* @ts-ignore */
|
|
308
|
+
...(ngDevMode ? [{ debugName: "itemClasses" }] : /* istanbul ignore next */ []));
|
|
309
|
+
this.itemTemplate = contentChild(RatingItemTemplateDirective, { ...(ngDevMode ? { debugName: "itemTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
|
|
310
|
+
this.items = computed(() => range(1, this.itemsCount())
|
|
311
|
+
.select(itemValue => ({ index: itemValue - 1, itemValue }))
|
|
312
|
+
.toArray(), /* @ts-ignore */
|
|
313
|
+
...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
314
|
+
this.labelClasses = computed(() => ratingLabelThemeVariants({ size: this.size() }), /* @ts-ignore */
|
|
315
|
+
...(ngDevMode ? [{ debugName: "labelClasses" }] : /* istanbul ignore next */ []));
|
|
316
|
+
this.labelId = createElementControlId();
|
|
317
|
+
this.normalizedValue = computed(() => normalizeRatingValue(this.value(), this.itemsCount(), this.precision()), /* @ts-ignore */
|
|
318
|
+
...(ngDevMode ? [{ debugName: "normalizedValue" }] : /* istanbul ignore next */ []));
|
|
319
|
+
this.overlayClipClasses = computed(() => ratingOverlayClipThemeVariants(), /* @ts-ignore */
|
|
320
|
+
...(ngDevMode ? [{ debugName: "overlayClipClasses" }] : /* istanbul ignore next */ []));
|
|
321
|
+
this.overlayColor = computed(() => this.color() || "var(--color-primary)", /* @ts-ignore */
|
|
322
|
+
...(ngDevMode ? [{ debugName: "overlayColor" }] : /* istanbul ignore next */ []));
|
|
323
|
+
this.overlayContentClasses = computed(() => ratingOverlayContentThemeVariants({ size: this.size() }), /* @ts-ignore */
|
|
324
|
+
...(ngDevMode ? [{ debugName: "overlayContentClasses" }] : /* istanbul ignore next */ []));
|
|
325
|
+
this.overlayIconClasses = computed(() => ratingOverlayIconThemeVariants({ size: this.size() }), /* @ts-ignore */
|
|
326
|
+
...(ngDevMode ? [{ debugName: "overlayIconClasses" }] : /* istanbul ignore next */ []));
|
|
327
|
+
this.overlayTemplate = computed(() => this.activeState() === "hovered" ? this.hoveredTemplate() : this.selectedTemplate(), /* @ts-ignore */
|
|
328
|
+
...(ngDevMode ? [{ debugName: "overlayTemplate" }] : /* istanbul ignore next */ []));
|
|
329
|
+
this.previewActive = computed(() => this.previewValue() !== null, /* @ts-ignore */
|
|
330
|
+
...(ngDevMode ? [{ debugName: "previewActive" }] : /* istanbul ignore next */ []));
|
|
331
|
+
this.previewValue = signal(null, /* @ts-ignore */
|
|
332
|
+
...(ngDevMode ? [{ debugName: "previewValue" }] : /* istanbul ignore next */ []));
|
|
333
|
+
this.selectedTemplate = contentChild(RatingSelectedItemTemplateDirective, { ...(ngDevMode ? { debugName: "selectedTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
|
|
334
|
+
/**
|
|
335
|
+
* @description Associates help text or an error description with the focusable rating control.
|
|
336
|
+
* @default null
|
|
337
|
+
*/
|
|
338
|
+
this.ariaDescribedBy = input(null, { ...(ngDevMode ? { debugName: "ariaDescribedBy" } : /* istanbul ignore next */ {}), alias: "aria-describedby" });
|
|
339
|
+
/**
|
|
340
|
+
* @description Explicit accessible name for the rating control. Provide `aria-label`,
|
|
341
|
+
* `aria-labelledby`, or `label` so assistive technology can announce the control.
|
|
342
|
+
* @default null
|
|
343
|
+
*/
|
|
344
|
+
this.ariaLabel = input(null, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: "aria-label" });
|
|
345
|
+
/**
|
|
346
|
+
* @description IDs of external elements providing the accessible name for the rating control.
|
|
347
|
+
* @default null
|
|
348
|
+
*/
|
|
349
|
+
this.ariaLabelledBy = input(null, { ...(ngDevMode ? { debugName: "ariaLabelledBy" } : /* istanbul ignore next */ {}), alias: "aria-labelledby" });
|
|
350
|
+
/**
|
|
351
|
+
* @description Custom screen-reader value announcement. Receives the normalized value and the
|
|
352
|
+
* item count and returns the string to expose through `aria-valuetext`.
|
|
353
|
+
* @default null
|
|
354
|
+
*/
|
|
355
|
+
this.ariaValueText = input(null, /* @ts-ignore */
|
|
356
|
+
...(ngDevMode ? [{ debugName: "ariaValueText" }] : /* istanbul ignore next */ []));
|
|
357
|
+
/**
|
|
358
|
+
* @description CSS color for selected and hovered rating visuals. Empty, `null`, and `undefined` values use the
|
|
359
|
+
* primary theme color.
|
|
360
|
+
* @default undefined
|
|
361
|
+
*/
|
|
362
|
+
this.color = input(/* @ts-ignore */
|
|
363
|
+
...(ngDevMode ? [undefined, { debugName: "color" }] : /* istanbul ignore next */ []));
|
|
364
|
+
/**
|
|
365
|
+
* @description Disables pointer and keyboard interaction and removes the control from the tab
|
|
366
|
+
* sequence. When bound to a signal form field via `[formField]`, this is written by the signal
|
|
367
|
+
* forms `Field` directive.
|
|
368
|
+
* @default false
|
|
369
|
+
*/
|
|
370
|
+
this.disabled = input(false, /* @ts-ignore */
|
|
371
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
372
|
+
/**
|
|
373
|
+
* @description Built-in icon used for the default rating visuals. Choose `star`, `heart`,
|
|
374
|
+
* `circle`, `diamond`, or `flame`; use item templates to supply a custom icon.
|
|
375
|
+
* @default "star"
|
|
376
|
+
*/
|
|
377
|
+
this.icon = input("star", /* @ts-ignore */
|
|
378
|
+
...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
379
|
+
/**
|
|
380
|
+
* @description Marks the component as invalid. Error styling requires both `invalid` and
|
|
381
|
+
* `touched` to be `true`. When bound to a signal form field via `[formField]`, this is written
|
|
382
|
+
* by the signal forms `Field` directive.
|
|
383
|
+
* @default false
|
|
384
|
+
*/
|
|
385
|
+
this.invalid = input(false, /* @ts-ignore */
|
|
386
|
+
...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
387
|
+
/**
|
|
388
|
+
* @description Number of rating items. Fractional values are floored and values below one are
|
|
389
|
+
* raised to one.
|
|
390
|
+
* @default 5
|
|
391
|
+
*/
|
|
392
|
+
this.itemsCount = input(5, { ...(ngDevMode ? { debugName: "itemsCount" } : /* istanbul ignore next */ {}), transform: normalizeItemsCount });
|
|
393
|
+
/**
|
|
394
|
+
* @description Optional visible label rendered before or after the rating items. When no
|
|
395
|
+
* explicit `aria-label` or `aria-labelledby` is supplied, the label provides the accessible
|
|
396
|
+
* name.
|
|
397
|
+
* @default null
|
|
398
|
+
*/
|
|
399
|
+
this.label = input(null, /* @ts-ignore */
|
|
400
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
401
|
+
/**
|
|
402
|
+
* @description Places the visible label before or after the item group.
|
|
403
|
+
* @default "after"
|
|
404
|
+
*/
|
|
405
|
+
this.labelPosition = input("after", /* @ts-ignore */
|
|
406
|
+
...(ngDevMode ? [{ debugName: "labelPosition" }] : /* istanbul ignore next */ []));
|
|
407
|
+
/**
|
|
408
|
+
* @description Selection granularity of the rating.
|
|
409
|
+
* @default "item"
|
|
410
|
+
*/
|
|
411
|
+
this.precision = input("item", /* @ts-ignore */
|
|
412
|
+
...(ngDevMode ? [{ debugName: "precision" }] : /* istanbul ignore next */ []));
|
|
413
|
+
/**
|
|
414
|
+
* @description Prevents value changes while preserving focusability and normal visual emphasis.
|
|
415
|
+
* @default false
|
|
416
|
+
*/
|
|
417
|
+
this.readonly = input(false, /* @ts-ignore */
|
|
418
|
+
...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
419
|
+
/**
|
|
420
|
+
* @description Controls cumulative or single-item filling.
|
|
421
|
+
* @default "continuous"
|
|
422
|
+
*/
|
|
423
|
+
this.selection = input("continuous", /* @ts-ignore */
|
|
424
|
+
...(ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []));
|
|
425
|
+
/**
|
|
426
|
+
* @description Size preset controlling the icon dimensions, item hitboxes, spacing, and label
|
|
427
|
+
* typography.
|
|
428
|
+
* @default "medium"
|
|
429
|
+
*/
|
|
430
|
+
this.size = input("medium", /* @ts-ignore */
|
|
431
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
432
|
+
/**
|
|
433
|
+
* @description Tab index applied to the focusable rating control when not disabled. Accepts a
|
|
434
|
+
* numeric string and converts it to a number.
|
|
435
|
+
* @default 0
|
|
436
|
+
*/
|
|
437
|
+
this.tabindex = input(0, { ...(ngDevMode ? { debugName: "tabindex" } : /* istanbul ignore next */ {}), transform: (value) => (typeof value === "string" ? parseInt(value, 10) : value) });
|
|
438
|
+
/**
|
|
439
|
+
* @description Emitted when the user interacts with the control, marking the field as touched.
|
|
440
|
+
*/
|
|
441
|
+
this.touch = output();
|
|
442
|
+
/**
|
|
443
|
+
* @description Marks the component as touched. When bound to a signal form field via
|
|
444
|
+
* `[formField]`, this is written by the signal forms `Field` directive.
|
|
445
|
+
* @default false
|
|
446
|
+
*/
|
|
447
|
+
this.touched = input(false, /* @ts-ignore */
|
|
448
|
+
...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
449
|
+
/**
|
|
450
|
+
* @description Additional CSS classes merged onto the host element via `tailwind-merge`.
|
|
451
|
+
* @default ""
|
|
452
|
+
*/
|
|
453
|
+
this.userClass = input("", { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: "class" });
|
|
454
|
+
/**
|
|
455
|
+
* @description Current rating value. `0` represents an unrated state. Values are normalized
|
|
456
|
+
* for rendering but are not rewritten until the user interacts with the component.
|
|
457
|
+
* @default 0
|
|
458
|
+
*/
|
|
459
|
+
this.value = model(0, /* @ts-ignore */
|
|
460
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
461
|
+
}
|
|
462
|
+
blur() {
|
|
463
|
+
this.controlElement().nativeElement.blur();
|
|
464
|
+
}
|
|
465
|
+
focus(options) {
|
|
466
|
+
if (!this.disabled()) {
|
|
467
|
+
this.controlElement().nativeElement.focus(options);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
createItemContext(item) {
|
|
471
|
+
return {
|
|
472
|
+
$implicit: item.index,
|
|
473
|
+
fill: this.getItemFill(item.itemValue),
|
|
474
|
+
hovered: this.previewActive(),
|
|
475
|
+
index: item.index,
|
|
476
|
+
itemValue: item.itemValue,
|
|
477
|
+
selected: !this.previewActive()
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
getItemFill(itemValue) {
|
|
481
|
+
const displayValue = this.displayValue();
|
|
482
|
+
if (this.selection() === "single") {
|
|
483
|
+
return getSingleItemFill(displayValue, itemValue);
|
|
484
|
+
}
|
|
485
|
+
return getContinuousItemFill(displayValue, itemValue);
|
|
486
|
+
}
|
|
487
|
+
onBlur() {
|
|
488
|
+
this.previewValue.set(null);
|
|
489
|
+
this.touch.emit();
|
|
490
|
+
}
|
|
491
|
+
onClick(event) {
|
|
492
|
+
if (this.interactionDisabled()) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
const candidate = this.getCandidateFromPointerEvent(event);
|
|
496
|
+
if (candidate === null) {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
const normalized = this.normalizeCandidate(candidate);
|
|
500
|
+
if (normalized !== this.normalizedValue()) {
|
|
501
|
+
this.value.set(normalized);
|
|
502
|
+
}
|
|
503
|
+
this.touch.emit();
|
|
504
|
+
}
|
|
505
|
+
onKeydown(event) {
|
|
506
|
+
if (this.interactionDisabled()) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
const action = this.getKeyAction(event.key);
|
|
510
|
+
if (action === null) {
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
event.preventDefault();
|
|
514
|
+
this.previewValue.set(null);
|
|
515
|
+
const current = this.normalizedValue();
|
|
516
|
+
let next;
|
|
517
|
+
switch (action) {
|
|
518
|
+
case "decrease":
|
|
519
|
+
next = this.normalizeCandidate(current - this.interactionStep());
|
|
520
|
+
break;
|
|
521
|
+
case "end":
|
|
522
|
+
next = this.itemsCount();
|
|
523
|
+
break;
|
|
524
|
+
case "home":
|
|
525
|
+
next = 0;
|
|
526
|
+
break;
|
|
527
|
+
case "increase":
|
|
528
|
+
next = this.normalizeCandidate(current + this.interactionStep());
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
if (next !== current) {
|
|
532
|
+
this.value.set(next);
|
|
533
|
+
}
|
|
534
|
+
this.touch.emit();
|
|
535
|
+
}
|
|
536
|
+
onPointerLeave() {
|
|
537
|
+
this.previewValue.set(null);
|
|
538
|
+
}
|
|
539
|
+
onPointerMove(event) {
|
|
540
|
+
if (this.interactionDisabled()) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const candidate = this.getCandidateFromPointerEvent(event);
|
|
544
|
+
if (candidate !== null) {
|
|
545
|
+
this.previewValue.set(candidate);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
getCandidateFromPointerEvent(event) {
|
|
549
|
+
const controlElement = this.controlElement().nativeElement;
|
|
550
|
+
const target = event.target;
|
|
551
|
+
const itemElement = target?.closest("[data-rating-index]") ?? null;
|
|
552
|
+
if (!itemElement || !controlElement.contains(itemElement)) {
|
|
553
|
+
return null;
|
|
554
|
+
}
|
|
555
|
+
const itemValue = Number(itemElement.getAttribute("data-rating-value"));
|
|
556
|
+
const itemRect = itemElement.getBoundingClientRect();
|
|
557
|
+
const direction = getComputedStyle(controlElement).direction === "rtl" ? "rtl" : "ltr";
|
|
558
|
+
return getPointerRatingValue({
|
|
559
|
+
clientX: event.clientX,
|
|
560
|
+
direction,
|
|
561
|
+
itemRect,
|
|
562
|
+
itemValue,
|
|
563
|
+
precision: this.precision()
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
getKeyAction(key) {
|
|
567
|
+
switch (key) {
|
|
568
|
+
case "ArrowRight":
|
|
569
|
+
case "ArrowUp":
|
|
570
|
+
return "increase";
|
|
571
|
+
case "ArrowLeft":
|
|
572
|
+
case "ArrowDown":
|
|
573
|
+
return "decrease";
|
|
574
|
+
case "Home":
|
|
575
|
+
return "home";
|
|
576
|
+
case "End":
|
|
577
|
+
return "end";
|
|
578
|
+
default:
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
normalizeCandidate(value) {
|
|
583
|
+
return normalizeRatingValue(value, this.itemsCount(), this.precision());
|
|
584
|
+
}
|
|
585
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
586
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: RatingComponent, isStandalone: true, selector: "mona-rating", inputs: { ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "aria-describedby", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null }, ariaValueText: { classPropertyName: "ariaValueText", publicName: "ariaValueText", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, itemsCount: { classPropertyName: "itemsCount", publicName: "itemsCount", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null }, precision: { classPropertyName: "precision", publicName: "precision", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, tabindex: { classPropertyName: "tabindex", publicName: "tabindex", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { touch: "touch", value: "valueChange" }, queries: [{ propertyName: "hoveredTemplate", first: true, predicate: RatingHoveredItemTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "itemTemplate", first: true, predicate: RatingItemTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "selectedTemplate", first: true, predicate: RatingSelectedItemTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }], viewQueries: [{ propertyName: "controlElement", first: true, predicate: ["ratingControl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"containerClasses()\">\n @if (label() && labelPosition() === \"before\") {\n <span [id]=\"labelId\" [class]=\"labelClasses()\">{{ label() }}</span>\n }\n\n <div\n #ratingControl\n role=\"slider\"\n [class]=\"controlClasses()\"\n [attr.tabindex]=\"effectiveTabIndex()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"itemsCount()\"\n [attr.aria-valuenow]=\"normalizedValue()\"\n [attr.aria-valuetext]=\"effectiveAriaValueText()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-labelledby]=\"effectiveAriaLabelledBy()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-invalid]=\"invalidState() || null\"\n [attr.data-disabled]=\"disabled() || null\"\n [attr.data-readonly]=\"readonly() || null\"\n [attr.data-invalid]=\"invalidState() || null\"\n [attr.data-precision]=\"precision()\"\n [attr.data-selection]=\"selection()\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerleave)=\"onPointerLeave()\"\n (click)=\"onClick($event)\">\n @for (item of items(); track item.itemValue) {\n <span\n [class]=\"itemClasses()\"\n [attr.data-rating-index]=\"item.index\"\n [attr.data-rating-value]=\"item.itemValue\"\n aria-hidden=\"true\">\n <span class=\"flex h-full w-full items-center justify-center\">\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"createItemContext(item)\">\n </ng-container>\n } @else {\n <svg lucideIcon [lucideIcon]=\"iconToRender()\" [class]=\"iconClasses()\" fill=\"none\"></svg>\n }\n </span>\n\n @let fill = getItemFill(item.itemValue);\n\n @if (fill > 0) {\n <span [class]=\"overlayClipClasses()\" [style.inline-size.%]=\"fill * 100\">\n <span\n [class]=\"overlayContentClasses()\"\n [attr.data-state]=\"activeState()\"\n [style.color]=\"disabled() ? null : overlayColor()\">\n @if (overlayTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"overlayTemplate()!\"\n [ngTemplateOutletContext]=\"createItemContext(item)\">\n </ng-container>\n } @else {\n <svg\n lucideIcon\n [lucideIcon]=\"iconToRender()\"\n [class]=\"overlayIconClasses()\"\n fill=\"currentColor\"></svg>\n }\n </span>\n </span>\n }\n </span>\n }\n </div>\n\n @if (label() && labelPosition() === \"after\") {\n <span [id]=\"labelId\" [class]=\"labelClasses()\">{{ label() }}</span>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }] }); }
|
|
587
|
+
}
|
|
588
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingComponent, decorators: [{
|
|
589
|
+
type: Component,
|
|
590
|
+
args: [{ selector: "mona-rating", imports: [NgTemplateOutlet, LucideDynamicIcon], template: "<div [class]=\"containerClasses()\">\n @if (label() && labelPosition() === \"before\") {\n <span [id]=\"labelId\" [class]=\"labelClasses()\">{{ label() }}</span>\n }\n\n <div\n #ratingControl\n role=\"slider\"\n [class]=\"controlClasses()\"\n [attr.tabindex]=\"effectiveTabIndex()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"itemsCount()\"\n [attr.aria-valuenow]=\"normalizedValue()\"\n [attr.aria-valuetext]=\"effectiveAriaValueText()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-labelledby]=\"effectiveAriaLabelledBy()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-invalid]=\"invalidState() || null\"\n [attr.data-disabled]=\"disabled() || null\"\n [attr.data-readonly]=\"readonly() || null\"\n [attr.data-invalid]=\"invalidState() || null\"\n [attr.data-precision]=\"precision()\"\n [attr.data-selection]=\"selection()\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerleave)=\"onPointerLeave()\"\n (click)=\"onClick($event)\">\n @for (item of items(); track item.itemValue) {\n <span\n [class]=\"itemClasses()\"\n [attr.data-rating-index]=\"item.index\"\n [attr.data-rating-value]=\"item.itemValue\"\n aria-hidden=\"true\">\n <span class=\"flex h-full w-full items-center justify-center\">\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"createItemContext(item)\">\n </ng-container>\n } @else {\n <svg lucideIcon [lucideIcon]=\"iconToRender()\" [class]=\"iconClasses()\" fill=\"none\"></svg>\n }\n </span>\n\n @let fill = getItemFill(item.itemValue);\n\n @if (fill > 0) {\n <span [class]=\"overlayClipClasses()\" [style.inline-size.%]=\"fill * 100\">\n <span\n [class]=\"overlayContentClasses()\"\n [attr.data-state]=\"activeState()\"\n [style.color]=\"disabled() ? null : overlayColor()\">\n @if (overlayTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"overlayTemplate()!\"\n [ngTemplateOutletContext]=\"createItemContext(item)\">\n </ng-container>\n } @else {\n <svg\n lucideIcon\n [lucideIcon]=\"iconToRender()\"\n [class]=\"overlayIconClasses()\"\n fill=\"currentColor\"></svg>\n }\n </span>\n </span>\n }\n </span>\n }\n </div>\n\n @if (label() && labelPosition() === \"after\") {\n <span [id]=\"labelId\" [class]=\"labelClasses()\">{{ label() }}</span>\n }\n</div>\n" }]
|
|
591
|
+
}], propDecorators: { controlElement: [{ type: i0.ViewChild, args: ["ratingControl", { isSignal: true }] }], hoveredTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RatingHoveredItemTemplateDirective), { ...{
|
|
592
|
+
read: TemplateRef
|
|
593
|
+
}, isSignal: true }] }], itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RatingItemTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], selectedTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RatingSelectedItemTemplateDirective), { ...{
|
|
594
|
+
read: TemplateRef
|
|
595
|
+
}, isSignal: true }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-describedby", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaLabelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-labelledby", required: false }] }], ariaValueText: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaValueText", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], itemsCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemsCount", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], labelPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPosition", required: false }] }], precision: [{ type: i0.Input, args: [{ isSignal: true, alias: "precision", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], tabindex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabindex", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
|
|
596
|
+
|
|
597
|
+
/*
|
|
598
|
+
* Public API Surface of @nanahoshi/mona-ui/rating
|
|
599
|
+
*/
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Generated bundle index. Do not edit.
|
|
603
|
+
*/
|
|
604
|
+
|
|
605
|
+
export { RatingComponent, RatingHoveredItemTemplateDirective, RatingItemTemplateDirective, RatingSelectedItemTemplateDirective };
|
|
606
|
+
//# sourceMappingURL=nanahoshi-mona-ui-rating.mjs.map
|
|
@@ -114,7 +114,7 @@ class SegmentedComponent {
|
|
|
114
114
|
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
115
115
|
/**
|
|
116
116
|
* @description Border-radius preset applied to the segmented container and its options.
|
|
117
|
-
* @default "
|
|
117
|
+
* @default "medium"
|
|
118
118
|
*/
|
|
119
119
|
this.rounded = input("medium", /* @ts-ignore */
|
|
120
120
|
...(ngDevMode ? [{ debugName: "rounded" }] : /* istanbul ignore next */ []));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nanahoshi/mona-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "A very light Angular UI framework",
|
|
5
5
|
"author": "Nanahoshi",
|
|
6
6
|
"repository": {
|
|
@@ -261,6 +261,10 @@
|
|
|
261
261
|
"types": "./types/nanahoshi-mona-ui-radio-button.d.ts",
|
|
262
262
|
"default": "./fesm2022/nanahoshi-mona-ui-radio-button.mjs"
|
|
263
263
|
},
|
|
264
|
+
"./rating": {
|
|
265
|
+
"types": "./types/nanahoshi-mona-ui-rating.d.ts",
|
|
266
|
+
"default": "./fesm2022/nanahoshi-mona-ui-rating.mjs"
|
|
267
|
+
},
|
|
264
268
|
"./scroll-view": {
|
|
265
269
|
"types": "./types/nanahoshi-mona-ui-scroll-view.d.ts",
|
|
266
270
|
"default": "./fesm2022/nanahoshi-mona-ui-scroll-view.mjs"
|