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
JavaScript
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: `
(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')">
(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>
(offIconTemplate()) {
<span [class]="cx('offIcon')" [style]="iconOffStyle()" [pBind]="ptm('offIcon')">
<ng-container *ngTemplateOutlet="offIconTemplate(); context: getOffIconContext(star)"></ng-container>
</span>
} if (iconOffClass()) {
<span [class]="cn(cx('offIcon'), iconOffClass())" [style]="iconOffStyle()" [pBind]="ptm('offIcon')"></span>
} {
<svg data-p-icon="star" [style]="iconOffStyle()" [class]="cx('offIcon')" [pBind]="ptm('offIcon')" />
}
(onIconTemplate()) {
<span [class]="cx('onIcon')" [style]="iconOnStyle()" [attr.data-orientation]="orientation()" [pBind]="ptm('onIcon')">
<ng-container *ngTemplateOutlet="onIconTemplate(); context: getOnIconContext(star)"></ng-container>
</span>
} if (iconOnClass()) {
<span [class]="cn(cx('onIcon'), iconOnClass())" [style]="iconOnStyle()" [attr.data-orientation]="orientation()" [pBind]="ptm('onIcon')"></span>
} {
<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: `
(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')">
(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>
(offIconTemplate()) {
<span [class]="cx('offIcon')" [style]="iconOffStyle()" [pBind]="ptm('offIcon')">
<ng-container *ngTemplateOutlet="offIconTemplate(); context: getOffIconContext(star)"></ng-container>
</span>
} if (iconOffClass()) {
<span [class]="cn(cx('offIcon'), iconOffClass())" [style]="iconOffStyle()" [pBind]="ptm('offIcon')"></span>
} {
<svg data-p-icon="star" [style]="iconOffStyle()" [class]="cx('offIcon')" [pBind]="ptm('offIcon')" />
}
(onIconTemplate()) {
<span [class]="cx('onIcon')" [style]="iconOnStyle()" [attr.data-orientation]="orientation()" [pBind]="ptm('onIcon')">
<ng-container *ngTemplateOutlet="onIconTemplate(); context: getOnIconContext(star)"></ng-container>
</span>
} if (iconOnClass()) {
<span [class]="cn(cx('onIcon'), iconOnClass())" [style]="iconOnStyle()" [attr.data-orientation]="orientation()" [pBind]="ptm('onIcon')"></span>
} {
<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