angular-star
Version:
A lightweight and customizable **star rating** component for Angular 20+. Supports decimal ratings, hover interactions, read-only mode, and full accessibility.
1 lines • 8.27 kB
Source Map (JSON)
{"version":3,"file":"angular-star.mjs","sources":["../../../projects/angular-star/src/lib/default.ts","../../../projects/angular-star/src/lib/angular-star.ts","../../../projects/angular-star/src/lib/angular-star.html","../../../projects/angular-star/src/public-api.ts","../../../projects/angular-star/src/angular-star.ts"],"sourcesContent":["import { starType } from \"./type\";\n\nexport class DefaultOptions implements starType {\n\n length: number = 5;\n value: number = 0;\n color: string = '';\n badColor: string = '#f20808';\n avgColor: string = '#f39c12';\n goodColor: string = '#3df400';\n spaceBetween: string | number = 0; // Optional, for spacing between stars\n icon: string = '★'; // Optional, for custom star icon\n\n\n constructor(data?: any) {\n if (!data) return;\n Object.keys(data).forEach((key: string) => {\n typeof (data[key] !== undefined) && typeof (data[key] !== null) && ((this as any)[key] = data[key]);\n })\n }\n}","import { Component, computed, effect, input, linkedSignal, output, signal } from '@angular/core';\nimport { starType } from './type';\nimport { DefaultOptions } from './default';\n\n@Component({\n selector: 'angular-star',\n imports: [],\n templateUrl: './angular-star.html',\n styleUrls: ['./angular-star.scss']\n})\nexport class AngularStar {\n config = input.required<starType>();\n getValue = output<number>();\n\n\n protected defaultConfig = computed<starType>(() => {\n return {\n ...new DefaultOptions(),\n ...this.config()\n }\n })\n\n private fractions = signal<boolean>(false);\n\n protected rating = linkedSignal<number>(() => {\n const _config = this.defaultConfig();\n return _config.value || 0\n });\n\n protected hoverFraction = signal<number>(0);\n\n private setValue = linkedSignal<number>(() => {\n const _config = this.defaultConfig();\n return _config.value || 0;\n });\n\n constructor() { }\n\n protected onMouseMove(event: MouseEvent, index: number) {\n const _fraction = this.fractions();\n if (_fraction) {\n const target = event.target as HTMLElement;\n const rect = target.getBoundingClientRect();\n const offsetX = event.clientX - rect.left;\n const fraction = offsetX / rect.width;\n this.hoverFraction.set(Math.round(fraction * 10) / 10);\n this.rating.set(index + this.hoverFraction());\n } else {\n this.rating.set(index + 1); // Set to the next whole number\n }\n\n }\n\n protected resetHover() {\n const _value = this.setValue();\n this.rating.set(_value);\n this.hoverFraction.set(0);\n }\n\n protected rate(value: number) {\n const _fraction = this.fractions();\n const _value = _fraction ? Math.round(value * 10) / 10 : value + 1;\n this.setValue.set(_value);\n this.getValue.emit(_value);\n this.hoverFraction.set(0);\n\n }\n\n protected getFillPercentage(index: number): string {\n const _fraction = this.fractions();\n if (_fraction) {\n const diff = this.rating() - index;\n if (diff >= 1) return '100%';\n if (diff > 0) return `${diff * 100}%`;\n return '0%';\n } else {\n return index < Math.ceil(this.rating()) ? '100%' : '0%';\n }\n }\n\n get classname() {\n const _rating = this.rating();\n const _config = this.defaultConfig();\n const _fraction = this.fractions();\n\n const _value = _fraction ? _config.length / 3 : _config.length / 3 % 1 >= 0.5 ? Math.ceil(_config.length / 3) : Math.floor(_config.length / 3);\n\n\n if (_rating <= _value) {\n return 'bad-color';\n } else if (_rating <= _config.length - _value) {\n return 'avg-color';\n } else {\n return 'good-color';\n }\n }\n}\n","@let _config = defaultConfig();\n@let _hoverFraction = hoverFraction();\n\n<div class=\"angular-stars\" (mouseleave)=\"resetHover()\" [style.--bad-color]=\"_config.color || _config.badColor\"\n [style.--avg-color]=\"_config.color || _config.avgColor\" [style.--good-color]=\"_config.color || _config.goodColor\"\n [style.--space-bw]=\"_config.spaceBetween+'px'\">\n @for (star of [].constructor(_config.length); track $index) {\n <div class=\"star-wrapper\" (mousemove)=\"onMouseMove($event, $index)\" (click)=\"rate($index + _hoverFraction)\"\n [style.--fill]=\"getFillPercentage($index)\">\n <div class=\"star full {{classname}}\" [innerHTML]=\"_config.icon\"></div>\n <div class=\"star empty\" [innerHTML]=\"_config.icon\"></div>\n </div>\n }\n</div>","/*\n * Public API Surface of angular-star\n */\n\nexport * from './lib/angular-star';\nexport type { starType } from './lib/type';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}