UNPKG

primeng

Version:

PrimeNG is a premium UI library for Angular featuring a rich set of 90+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeBlock,

489 lines (484 loc) 26.1 kB
export * from 'primeng/types/rating'; import { NgTemplateOutlet } from '@angular/common'; import * as i0 from '@angular/core'; import { Injectable, InjectionToken, forwardRef, inject, input, booleanAttribute, numberAttribute, output, contentChild, signal, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { uuid } from '@primeuix/utils'; import { SharedModule } from 'primeng/api'; import { AutoFocus } from 'primeng/autofocus'; import { PARENT_INSTANCE } from 'primeng/basecomponent'; import { BaseEditableHolder } from 'primeng/baseeditableholder'; import * as i1 from 'primeng/bind'; import { Bind, BindModule } from 'primeng/bind'; import { StarFill } from '@primeicons/angular/star-fill'; import { Star } from '@primeicons/angular/star'; import { style } from '@primeuix/styles/rating'; import { BaseStyle } from 'primeng/base'; const classes = { root: ({ instance }) => [ 'p-rating', { 'p-readonly': instance.readonly(), 'p-disabled': instance.$disabled() } ], option: 'p-rating-option', onIcon: ({ instance }) => ['p-rating-on-icon', { 'p-invalid': instance.invalid() }], offIcon: ({ instance }) => ['p-rating-off-icon', { 'p-invalid': instance.invalid() }] }; class RatingStyle extends BaseStyle { name = 'rating'; style = style; classes = classes; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingStyle, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingStyle }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingStyle, decorators: [{ type: Injectable }] }); /** * * Rating component is a star based selection input. * * [Live Demo](https://www.primeng.org/rating/) * * @module ratingstyle * */ var RatingClasses; (function (RatingClasses) { /** * Class name of the root element */ RatingClasses["root"] = "p-rating"; /** * Class name of the option element */ RatingClasses["option"] = "p-rating-option"; /** * Class name of the on icon element */ RatingClasses["onIcon"] = "p-rating-on-icon"; /** * Class name of the off icon element */ RatingClasses["offIcon"] = "p-rating-off-icon"; })(RatingClasses || (RatingClasses = {})); const RATING_INSTANCE = new InjectionToken('RATING_INSTANCE'); const RATING_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => Rating), multi: true }; /** * Rating is an extension to standard radio button element with theming. * @group Components */ class Rating extends BaseEditableHolder { componentName = 'Rating'; $pcRating = inject(RATING_INSTANCE, { optional: true, skipSelf: true }) ?? undefined; bindDirectiveInstance = inject(Bind, { self: true }); onAfterViewChecked() { this.bindDirectiveInstance.setAttrs(this.ptms(['host', 'root'])); } /** * When present, changing the value is not possible. * @group Props */ readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Number of stars. * @group Props */ stars = input(5, { ...(ngDevMode ? { debugName: "stars" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * Style class of the on icon. * @group Props */ iconOnClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "iconOnClass" }] : /* istanbul ignore next */ [])); /** * Inline style of the on icon. * @group Props */ iconOnStyle = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "iconOnStyle" }] : /* istanbul ignore next */ [])); /** * Style class of the off icon. * @group Props */ iconOffClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "iconOffClass" }] : /* istanbul ignore next */ [])); /** * Inline style of the off icon. * @group Props */ iconOffStyle = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "iconOffStyle" }] : /* istanbul ignore next */ [])); /** * When present, it specifies that the component should automatically get focus on load. * @group Props */ autofocus = input(false, { ...(ngDevMode ? { debugName: "autofocus" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * When present, selecting half stars is allowed. * @group Props */ allowHalf = input(false, { ...(ngDevMode ? { debugName: "allowHalf" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Orientation of the component. * @group Props */ orientation = input('horizontal', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ [])); /** * Emitted on value change. * @param {RatingRateEvent} value - Custom rate event. * @group Emits */ onRate = output(); /** * Emitted when the rating receives focus. * @param {Event} value - Browser event. * @group Emits */ onFocus = output(); /** * Emitted when the rating loses focus. * @param {Event} value - Browser event. * @group Emits */ onBlur = output(); /** * Custom on icon template. * @param {RatingIconTemplateContext} context - icon context. * @see {@link RatingIconTemplateContext} * @group Templates */ onIconTemplate = contentChild('onicon', { ...(ngDevMode ? { debugName: "onIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom off icon template. * @param {RatingIconTemplateContext} context - icon context. * @see {@link RatingIconTemplateContext} * @group Templates */ offIconTemplate = contentChild('officon', { ...(ngDevMode ? { debugName: "offIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); value = signal(null, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ [])); starsArray; focusedOptionIndex = signal(-1, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "focusedOptionIndex" }] : /* istanbul ignore next */ [])); nameattr = signal(undefined, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "nameattr" }] : /* istanbul ignore next */ [])); hovering = signal(false, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "hovering" }] : /* istanbul ignore next */ [])); hoveringValue = signal(0, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "hoveringValue" }] : /* istanbul ignore next */ [])); _componentStyle = inject(RatingStyle); attrRequired = computed(() => (this.required() ? '' : undefined), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "attrRequired" }] : /* istanbul ignore next */ [])); attrReadonly = computed(() => (this.readonly() ? '' : undefined), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "attrReadonly" }] : /* istanbul ignore next */ [])); attrDisabled = computed(() => (this.$disabled() ? '' : undefined), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "attrDisabled" }] : /* istanbul ignore next */ [])); attrName = computed(() => this.name() || this.nameattr() + '_name', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "attrName" }] : /* istanbul ignore next */ [])); dataP = computed(() => this.cn({ readonly: this.readonly(), disabled: this.$disabled() }), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "dataP" }] : /* istanbul ignore next */ [])); isCustomIcon = computed(() => !!(this.onIconTemplate() || this.offIconTemplate()), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "isCustomIcon" }] : /* istanbul ignore next */ [])); activeValue = computed(() => (this.hovering() ? this.hoveringValue() : (this.value() ?? 0)), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "activeValue" }] : /* istanbul ignore next */ [])); onInit() { this.nameattr.set(this.nameattr() || uuid('pn_id_')); this.starsArray = []; for (let i = 0; i < this.stars(); i++) { this.starsArray[i] = i; } } resolvePointerValue(event, star) { if (this.allowHalf()) { const target = event.currentTarget; const rect = target.getBoundingClientRect(); const isHalf = this.orientation() === 'vertical' ? event.clientY < rect.top + rect.height / 2 : event.clientX < rect.left + rect.width / 2; return isHalf ? star + 0.5 : star + 1; } return star + 1; } onOptionClick(event, star) { if (this.readonly() || this.$disabled()) return; const target = event.target; if (target && target.tagName === 'INPUT' && target.type === 'radio') { return; } const value = this.allowHalf() ? this.resolvePointerValue(event, star - 1) : star; this.onOptionSelect(event, value); } onOptionSelect(event, value) { if (!this.readonly() && !this.$disabled()) { if (value === this.value()) { this.focusedOptionIndex.set(-1); this.updateModel(event, null); } else { this.focusedOptionIndex.set(value); this.updateModel(event, value || null); } } } onPointerMove(event, star) { if (!this.readonly() && !this.$disabled()) { this.hovering.set(true); const value = this.resolvePointerValue(event, star); this.hoveringValue.set(value); } } onPointerEnter() { if (!this.readonly() && !this.$disabled()) { this.hovering.set(true); } } onPointerLeave() { if (!this.readonly() && !this.$disabled()) { this.hovering.set(false); this.hoveringValue.set(0); } } onChange(event, value) { this.onOptionSelect(event, value); } onInputBlur(event) { this.focusedOptionIndex.set(-1); const next = event.relatedTarget; const host = event.currentTarget.closest('.p-rating'); if (!host || !next || !host.contains(next)) { this.hovering.set(false); this.hoveringValue.set(0); } this.onBlur.emit(event); } onInputFocus(event, value) { if (!this.readonly() && !this.$disabled()) { this.focusedOptionIndex.set(value); this.hoveringValue.set(value); this.hovering.set(true); this.onFocus.emit(event); } } updateModel(event, value) { this.writeValue(value); this.onModelChange(this.value()); this.onModelTouched(); this.onRate.emit({ originalEvent: event, value: value }); } starAriaLabel(value) { return value === 1 ? this.config.translation.aria?.star : this.config.translation.aria?.stars?.replace(/{star}/g, String(value)); } isHighlighted(star) { return star < this.activeValue(); } isHalf(star) { if (!this.allowHalf()) return false; const activeVal = this.activeValue(); return activeVal === star + 0.5; } isChecked(star) { return this.value() === star + 1; } getOnIconContext(star) { return { $implicit: star + 1, class: this.cx('onIcon') }; } getOffIconContext(star) { return { $implicit: star + 1, class: this.cx('offIcon') }; } getIconTemplate(i) { return !this.value() || i >= this.value() ? this.offIconTemplate() : this.onIconTemplate() || this.offIconTemplate(); } /** * @override * * @see {@link BaseEditableHolder.writeControlValue} * Writes the value to the control. */ writeControlValue(value, setModelValue) { this.value.set(value); setModelValue(value); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: Rating, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: Rating, isStandalone: true, selector: "p-rating", inputs: { readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, stars: { classPropertyName: "stars", publicName: "stars", isSignal: true, isRequired: false, transformFunction: null }, iconOnClass: { classPropertyName: "iconOnClass", publicName: "iconOnClass", isSignal: true, isRequired: false, transformFunction: null }, iconOnStyle: { classPropertyName: "iconOnStyle", publicName: "iconOnStyle", isSignal: true, isRequired: false, transformFunction: null }, iconOffClass: { classPropertyName: "iconOffClass", publicName: "iconOffClass", isSignal: true, isRequired: false, transformFunction: null }, iconOffStyle: { classPropertyName: "iconOffStyle", publicName: "iconOffStyle", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, allowHalf: { classPropertyName: "allowHalf", publicName: "allowHalf", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onRate: "onRate", onFocus: "onFocus", onBlur: "onBlur" }, host: { listeners: { "pointerenter": "onPointerEnter()", "pointerleave": "onPointerLeave()" }, properties: { "class": "cx('root')", "attr.data-p": "dataP()", "attr.data-orientation": "orientation()" } }, providers: [RATING_VALUE_ACCESSOR, RatingStyle, { provide: RATING_INSTANCE, useExisting: Rating }, { provide: PARENT_INSTANCE, useExisting: Rating }], queries: [{ propertyName: "onIconTemplate", first: true, predicate: ["onicon"], isSignal: true }, { propertyName: "offIconTemplate", first: true, predicate: ["officon"], isSignal: true }], usesInheritance: true, hostDirectives: [{ directive: i1.Bind }], ngImport: i0, template: ` @for (star of starsArray; track star; let i = $index) { <div [class]="cx('option')" [attr.data-highlighted]="isHighlighted(star) ? '' : null" [attr.data-half]="isHalf(star) ? '' : null" (click)="onOptionClick($event, star + 1)" (pointermove)="onPointerMove($event, star)" [pBind]="ptm('option')" > <span class="p-hidden-accessible" [attr.data-p-hidden-accessible]="true" [pBind]="ptm('hiddenOptionInputContainer')"> @if (allowHalf()) { <input type="radio" [value]="star + 0.5" [attr.name]="attrName()" [attr.value]="modelValue()" [attr.required]="attrRequired()" [attr.readonly]="attrReadonly()" [attr.disabled]="attrDisabled()" [checked]="value() === star + 0.5" [attr.aria-label]="starAriaLabel(star + 0.5)" (focus)="onInputFocus($event, star + 0.5)" (blur)="onInputBlur($event)" (change)="onChange($event, star + 0.5)" [pBind]="ptm('hiddenOptionInput')" /> } <input type="radio" [value]="star + 1" [attr.name]="attrName()" [attr.value]="modelValue()" [attr.required]="attrRequired()" [attr.readonly]="attrReadonly()" [attr.disabled]="attrDisabled()" [checked]="isChecked(star)" [attr.aria-label]="starAriaLabel(star + 1)" (focus)="onInputFocus($event, star + 1)" (blur)="onInputBlur($event)" (change)="onChange($event, star + 1)" [pAutoFocus]="autofocus()" [pBind]="ptm('hiddenOptionInput')" /> </span> @if (offIconTemplate()) { <span [class]="cx('offIcon')" [style]="iconOffStyle()" [pBind]="ptm('offIcon')"> <ng-container *ngTemplateOutlet="offIconTemplate(); context: getOffIconContext(star)"></ng-container> </span> } @else if (iconOffClass()) { <span [class]="cn(cx('offIcon'), iconOffClass())" [style]="iconOffStyle()" [pBind]="ptm('offIcon')"></span> } @else { <svg data-p-icon="star" [style]="iconOffStyle()" [class]="cx('offIcon')" [pBind]="ptm('offIcon')" /> } @if (onIconTemplate()) { <span [class]="cx('onIcon')" [style]="iconOnStyle()" [attr.data-orientation]="orientation()" [pBind]="ptm('onIcon')"> <ng-container *ngTemplateOutlet="onIconTemplate(); context: getOnIconContext(star)"></ng-container> </span> } @else if (iconOnClass()) { <span [class]="cn(cx('onIcon'), iconOnClass())" [style]="iconOnStyle()" [attr.data-orientation]="orientation()" [pBind]="ptm('onIcon')"></span> } @else { <svg data-p-icon="star-fill" [style]="iconOnStyle()" [class]="cx('onIcon')" [attr.data-orientation]="orientation()" [pBind]="ptm('onIcon')" /> } </div> } `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: AutoFocus, selector: "[pAutoFocus]", inputs: ["pAutoFocus"] }, { kind: "component", type: StarFill, selector: "svg[data-p-icon=\"star-fill\"]" }, { kind: "component", type: Star, selector: "svg[data-p-icon=\"star\"]" }, { kind: "ngmodule", type: SharedModule }, { kind: "ngmodule", type: BindModule }, { kind: "directive", type: i1.Bind, selector: "[pBind]", inputs: ["pBind"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: Rating, decorators: [{ type: Component, args: [{ selector: 'p-rating', imports: [NgTemplateOutlet, AutoFocus, StarFill, Star, SharedModule, BindModule], standalone: true, template: ` @for (star of starsArray; track star; let i = $index) { <div [class]="cx('option')" [attr.data-highlighted]="isHighlighted(star) ? '' : null" [attr.data-half]="isHalf(star) ? '' : null" (click)="onOptionClick($event, star + 1)" (pointermove)="onPointerMove($event, star)" [pBind]="ptm('option')" > <span class="p-hidden-accessible" [attr.data-p-hidden-accessible]="true" [pBind]="ptm('hiddenOptionInputContainer')"> @if (allowHalf()) { <input type="radio" [value]="star + 0.5" [attr.name]="attrName()" [attr.value]="modelValue()" [attr.required]="attrRequired()" [attr.readonly]="attrReadonly()" [attr.disabled]="attrDisabled()" [checked]="value() === star + 0.5" [attr.aria-label]="starAriaLabel(star + 0.5)" (focus)="onInputFocus($event, star + 0.5)" (blur)="onInputBlur($event)" (change)="onChange($event, star + 0.5)" [pBind]="ptm('hiddenOptionInput')" /> } <input type="radio" [value]="star + 1" [attr.name]="attrName()" [attr.value]="modelValue()" [attr.required]="attrRequired()" [attr.readonly]="attrReadonly()" [attr.disabled]="attrDisabled()" [checked]="isChecked(star)" [attr.aria-label]="starAriaLabel(star + 1)" (focus)="onInputFocus($event, star + 1)" (blur)="onInputBlur($event)" (change)="onChange($event, star + 1)" [pAutoFocus]="autofocus()" [pBind]="ptm('hiddenOptionInput')" /> </span> @if (offIconTemplate()) { <span [class]="cx('offIcon')" [style]="iconOffStyle()" [pBind]="ptm('offIcon')"> <ng-container *ngTemplateOutlet="offIconTemplate(); context: getOffIconContext(star)"></ng-container> </span> } @else if (iconOffClass()) { <span [class]="cn(cx('offIcon'), iconOffClass())" [style]="iconOffStyle()" [pBind]="ptm('offIcon')"></span> } @else { <svg data-p-icon="star" [style]="iconOffStyle()" [class]="cx('offIcon')" [pBind]="ptm('offIcon')" /> } @if (onIconTemplate()) { <span [class]="cx('onIcon')" [style]="iconOnStyle()" [attr.data-orientation]="orientation()" [pBind]="ptm('onIcon')"> <ng-container *ngTemplateOutlet="onIconTemplate(); context: getOnIconContext(star)"></ng-container> </span> } @else if (iconOnClass()) { <span [class]="cn(cx('onIcon'), iconOnClass())" [style]="iconOnStyle()" [attr.data-orientation]="orientation()" [pBind]="ptm('onIcon')"></span> } @else { <svg data-p-icon="star-fill" [style]="iconOnStyle()" [class]="cx('onIcon')" [attr.data-orientation]="orientation()" [pBind]="ptm('onIcon')" /> } </div> } `, providers: [RATING_VALUE_ACCESSOR, RatingStyle, { provide: RATING_INSTANCE, useExisting: Rating }, { provide: PARENT_INSTANCE, useExisting: Rating }], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { '[class]': "cx('root')", '[attr.data-p]': 'dataP()', '[attr.data-orientation]': 'orientation()', '(pointerenter)': 'onPointerEnter()', '(pointerleave)': 'onPointerLeave()' }, hostDirectives: [Bind] }] }], propDecorators: { readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], stars: [{ type: i0.Input, args: [{ isSignal: true, alias: "stars", required: false }] }], iconOnClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnClass", required: false }] }], iconOnStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnStyle", required: false }] }], iconOffClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOffClass", required: false }] }], iconOffStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOffStyle", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], allowHalf: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowHalf", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], onRate: [{ type: i0.Output, args: ["onRate"] }], onFocus: [{ type: i0.Output, args: ["onFocus"] }], onBlur: [{ type: i0.Output, args: ["onBlur"] }], onIconTemplate: [{ type: i0.ContentChild, args: ['onicon', { ...{ descendants: false }, isSignal: true }] }], offIconTemplate: [{ type: i0.ContentChild, args: ['officon', { ...{ descendants: false }, isSignal: true }] }] } }); class RatingModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.6", ngImport: i0, type: RatingModule, imports: [Rating, SharedModule], exports: [Rating, SharedModule] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingModule, imports: [Rating, SharedModule, SharedModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingModule, decorators: [{ type: NgModule, args: [{ imports: [Rating, SharedModule], exports: [Rating, SharedModule] }] }] }); /** * Generated bundle index. Do not edit. */ export { RATING_VALUE_ACCESSOR, Rating, RatingClasses, RatingModule, RatingStyle }; //# sourceMappingURL=primeng-rating.mjs.map