@telekom/scale-components
Version:
Scale is the digital design system for Telekom products and experiences.
144 lines (138 loc) • 10.9 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
const index = require('./index-a0ea3d79.js');
const utils = require('./utils-e9c3b953.js');
const statusNote = require('./status-note-dceee5a3.js');
const ratingStarsCss = ":host{--stars-color:var(--telekom-color-text-and-icon-primary-standard);--stars-hover-color:var(--telekom-color-text-and-icon-primary-hovered);--stars-active-color:var(--telekom-color-text-and-icon-primary-pressed);--stars-inactive-color:transparent;--stars-placeholder-color:var(--telekom-color-ui-border-standard);--stars-placeholder-hover-color:var(--telekom-color-ui-border-hovered);--stars-disabled-color:var(--telekom-color-text-and-icon-disabled);--stars-spacing:var(--telekom-spacing-composition-space-02);--stars-transition:color var(--telekom-motion-duration-immediate);--stars-size:24px;--label-font:var(--telekom-text-style-ui);--infotext-font:var(--telekom-text-style-body);--infotext-font-small:var(--telekom-text-style-body);--infotext-color:var(--telekom-color-text-and-icon-additional);--focus-outline:var(--telekom-line-weight-highlight) solid\n var(--telekom-color-functional-focus-standard)}[star-size='small'],[size='small']{--stars-size:16px}[part='container']{display:inline-flex;flex-direction:column;position:relative}[part='range-slider']{position:absolute;border:0;margin:0;left:calc(-1 * var(--stars-size));bottom:0;z-index:2;width:calc(100% + var(--stars-size) * 2);opacity:0;height:var(--stars-size)}@media (hover: hover){[part='range-slider']{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;white-space:nowrap;width:1px}}input[type='range']::-webkit-slider-thumb{-webkit-appearance:none;border:0;height:var(--stars-size);width:var(--stars-size);border-radius:50%;background:#ffffff;cursor:pointer;margin-left:0px;margin-top:0}[part='content']{display:flex;align-items:center}[part='wrapper']{display:inline-flex;border-radius:var(--telekom-spacing-composition-space-03);margin-left:calc(-1 * var(--stars-spacing))}[part='wrapper']:hover [part='star'] [part='selected-star']{opacity:1}[part='star']>*{pointer-events:none}[part='label']{font:var(--label-font);margin-bottom:var(--telekom-spacing-composition-space-04);white-space:nowrap}[part='infotext']{margin-left:var(--telekom-spacing-composition-space-04);display:flex;align-items:center;font:var(--infotext-font);color:var(--infotext-color);white-space:nowrap}:host([size='small']) [part='infotext']{font:var(--infotext-font-small)}[part='star']{--decimal-width:100%;display:inline-flex;position:relative;color:var(--stars-color);cursor:pointer;padding:0 var(--stars-spacing)}[part='placeholder-star']{display:inline-flex;color:var(--stars-placeholder-color);transition:var(--stars-transition)}[part='selected-star']{color:var(--stars-inactive-color);margin-left:0px;position:relative;transition:var(--stars-transition)}.icon-clip{overflow:hidden;position:absolute;width:var(--decimal-width);height:100%}[part='star'][data-half]{--decimal-width:calc(50% - var(--stars-spacing))}[part='star'][data-selected]{--stars-placeholder-color:transparent}[part='star'][data-half]{--stars-placeholder-color:currentColor}[part='star'][data-selected] [part='selected-star']{color:var(--stars-color)}@media (hover: hover){[part='wrapper']:hover{--stars-color:var(--stars-hover-color);--stars-placeholder-color:transparent}[part='wrapper']:hover [part='star']{--decimal-width:100%}[part='wrapper']:hover [part='star'][data-half]{--stars-placeholder-color:transparent}[part='wrapper']:hover [part='selected-star']{color:var(--stars-color)}[part='star']:hover~[part='star'] [part='selected-star']{color:var(--stars-inactive-color)}[part='star']:hover~[part='star'] [part='placeholder-star']{color:var(--stars-placeholder-hover-color)}}[part='wrapper']:active{--stars-color:var(--stars-active-color)}:host(:focus-within) [part='wrapper'],[part='wrapper']:focus{outline:var(--focus-outline)}:host(.readonly) [part='wrapper']{--stars-placeholder-color:var(--stars-disabled-color);pointer-events:none}:host(.disabled) [part='label'],:host(.disabled) [part='infotext']{color:var(--stars-disabled-color)}:host(.disabled) [part='wrapper']{--stars-color:var(--stars-disabled-color);--stars-placeholder-color:var(--stars-disabled-color);pointer-events:none}:host(.hideLabel) [part='label']{visibility:hidden;height:0;margin-bottom:0}@media screen and (forced-colors: active), (-ms-high-contrast: active){[part='star'] [part='placeholder-star']{color:var(--telekom-color-text-and-icon-inverted-standard)}[part='star'][data-selected] [part='placeholder-star']{color:var(--stars-inactive-color)}[part='star']:hover~[part='star'] [part='placeholder-star']{color:var(--telekom-color-text-and-icon-inverted-standard)}[part='wrapper']:hover [part='placeholder-star']{color:var(--stars-inactive-color)}}";
const sizes = {
small: 16,
large: 24,
};
let ratingStarCount = 0;
const RatingStars = class {
constructor(hostRef) {
index.registerInstance(this, hostRef);
this.scaleChange = index.createEvent(this, "scale-change", 7);
this.scaleChangeLegacy = index.createEvent(this, "scaleChange", 7);
this.ratingStarId = `scale-rating-star-${ratingStarCount++}`;
/** @deprecated; size should be used instead of starSize */
this.starSize = 'large';
/** size of the stars */
this.size = 'large';
/** @deprecated; The lower limit of the rating */
this.minRating = 0;
/** @deprecated; max should be used instead of maxRating */
this.maxRating = 5;
/** The upper limit of the rating */
this.max = 5;
/** Represents the current value of the rating */
this.rating = 0;
/** makes the rating non-interactive (but still accessible) */
this.readonly = false;
/** disables input */
this.disabled = false;
/** a11y text for getting meaningful value. `$rating` and `$max` (deprecated `$maxRating`) are template variables and will be replaces by their corresponding properties. */
this.ariaLabelTranslation = '$rating out of $max stars';
/** (optional) rating label */
this.label = 'Rating';
/** (optional) info text */
this.hideLabel = false;
this.handleInput = (ev) => {
const input = ev.composedPath()[0];
const value = Number(input.value);
switch (true) {
case value < this.minRating:
input.value = this.minRating.toString();
break;
case value > this.max:
input.value = this.max.toString();
break;
}
this.rating = Number(input.value);
utils.emitEvent(this, 'scaleChange', { value: this.rating });
};
this.handleStarClick = (ev) => {
const star = ev.composedPath()[0];
const starValue = Number(star.dataset.value);
// set focus on input to make arrow keys work to select stars
const input = this.host.shadowRoot.querySelector('input');
input.focus();
if (starValue === 1 && this.rating === 1 && this.minRating === 0) {
this.rating = this.minRating;
}
else {
this.rating = starValue;
}
utils.emitEvent(this, 'scaleChange', { value: this.rating });
};
}
componentWillRender() {
// make sure the deprecated props overwrite the actual ones if used
// and show status note deprecated
if (this.maxRating !== 5) {
this.max = this.maxRating;
statusNote.statusNote({
tag: 'deprecated',
message: 'Property "maxRating" is deprecated. Please use the "max" property!',
type: 'warn',
source: this.host,
});
}
if (this.minRating !== 0) {
statusNote.statusNote({
tag: 'deprecated',
message: 'Property "minRating" is deprecated and will be deleted upon the next release',
type: 'warn',
source: this.host,
});
}
if (this.starSize !== 'large') {
this.size = this.starSize;
statusNote.statusNote({
tag: 'deprecated',
message: 'Property "starSize" is deprecated. Please use the "size" property!',
type: 'warn',
source: this.host,
});
}
// deactivate showing half stars while keeping the code
this.rating = Math.round(this.rating);
}
// constructs the aria message for the current rating
getRatingText() {
const filledText = this.ariaLabelTranslation
.replace(/\$rating/g, `${this.rating}`)
// TODO: remove when `maxRating` is also being removed
.replace(/\$maxRating/g, `${this.max}`)
.replace(/\$max/g, `${this.max}`);
return filledText;
}
renderStar(index$1, selected = false, rating) {
const size = sizes[this.size];
const isWholeNumber = rating % 1 === 0;
const isLastNumber = Math.ceil(rating) === index$1;
return (index.h("div", { part: "star", "data-value": index$1, "data-selected": selected, "data-half": isLastNumber && !isWholeNumber, onMouseUp: !this.readonly && this.handleStarClick,
// sets up first star to be the resetter above the input element
style: { zIndex: index$1 === 1 ? '5' : 'auto' } }, index.h("scale-icon-action-favorite", { size: size, part: "placeholder-star" }), index.h("div", { class: "icon-clip" }, index.h("scale-icon-action-favorite", { size: size, selected: true, part: "selected-star" }))));
}
renderRating() {
const stars = [];
const roundedRating = Math.ceil(this.rating);
const max = this.max;
for (let index = 1; index <= max; index++) {
const isSelected = roundedRating >= index;
stars.push(this.renderStar(index, isSelected, this.rating));
}
return stars;
}
render() {
return (index.h(index.Host, { class: {
hideLabel: this.hideLabel,
disabled: this.disabled,
readonly: this.readonly,
} }, index.h("div", { part: "container" }, index.h("label", { id: `${this.ratingStarId}-label`, part: "label", htmlFor: this.ratingStarId }, this.label), index.h("div", { part: "content" }, index.h("div", { part: "wrapper", "aria-valuetext": this.getRatingText(), "aria-orientation": "horizontal", "aria-describedby": this.infoText ? `${this.ratingStarId}-infotext` : false }, index.h("input", { disabled: this.disabled, readonly: this.readonly, part: "range-slider", type: this.readonly ? 'number' : 'range', id: this.ratingStarId, min: 0, max: this.max + 1, value: this.rating, step: "1", "aria-labelledby": `${this.ratingStarId}-label`, "aria-readonly": this.readonly ? 'true' : false, "aria-valuemin": this.minRating, "aria-valuemax": this.max, "aria-valuenow": this.rating, "aria-valuetext": this.getRatingText(), onInput: !this.readonly && this.handleInput }), this.renderRating()), this.infoText && (index.h("div", { part: "infotext", id: `${this.ratingStarId}-infotext` }, this.infoText))))));
}
get host() { return index.getElement(this); }
};
RatingStars.style = ratingStarsCss;
exports.scale_rating_stars = RatingStars;