@geneui/components
Version:
The Gene UI components library designed for BI tools
175 lines (170 loc) • 9.72 kB
JavaScript
import { _ as __rest } from '../tslib.es6-f211516f.js';
import * as React from 'react';
import React__default, { useState, useLayoutEffect, isValidElement, cloneElement } from 'react';
import { c as classnames } from '../index-031ff73c.js';
import { s as styleInject } from '../style-inject.es-746bb8ed.js';
function SvgSquareMajor(props) {
return React.createElement('svg', {
xmlns: 'http://www.w3.org/2000/svg',
width: 24,
height: 24,
viewBox: '0 0 24 24',
strokeLinecap: 'round',
strokeLinejoin: 'round'
}, props, React.createElement('rect', {
width: 18,
height: 18,
x: 3,
y: 3,
rx: 2
}));
}
var css_248z = "[data-gene-ui-version=\"2.16.5\"] .rating{box-sizing:border-box;display:flex;-webkit-user-select:none;user-select:none;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}[data-gene-ui-version=\"2.16.5\"] .rating *>svg{color:unset!important}[data-gene-ui-version=\"2.16.5\"] .rating__wrapper{display:flex;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;justify-content:center;position:relative;transition:transform .1s ease-in;width:100%}[data-gene-ui-version=\"2.16.5\"] .rating__wrapper:hover{cursor:pointer;transform:scale(1.1)}[data-gene-ui-version=\"2.16.5\"] .rating__wrapper-readonly{pointer-events:none}[data-gene-ui-version=\"2.16.5\"] .rating__wrapper:focus-visible{outline:.02rem solid var(--hero)}[data-gene-ui-version=\"2.16.5\"] .rating__wrapper-small:not(:first-child){margin-inline-start:.4rem}[data-gene-ui-version=\"2.16.5\"] .rating__wrapper-medium:not(:first-child){margin-inline-start:.8rem}[data-gene-ui-version=\"2.16.5\"] .rating__wrapper-big:not(:first-child){margin-inline-start:1.2rem}[data-gene-ui-version=\"2.16.5\"] .rating__element{height:100%;inset-inline-start:0;overflow:hidden;position:absolute;top:0;width:100%;z-index:7}[data-gene-ui-version=\"2.16.5\"] .rating__icon-small{font-size:3.2rem}[data-gene-ui-version=\"2.16.5\"] .rating__icon-medium{font-size:3.6rem}[data-gene-ui-version=\"2.16.5\"] .rating__icon-big{font-size:4.2rem}";
styleInject(css_248z);
const sizes = { small: 32, medium: 36, big: 42 };
const Element = ({ isIcon = false, Element, isCompareElement = false, color, bgColor, size }) => {
const currentColor = isCompareElement ? color : bgColor;
const className = `rating__icon rating__icon-${size}`;
const currentSizes = {
width: sizes[size],
height: sizes[size]
};
const elementProps = Object.assign(Object.assign({ fill: currentColor }, currentSizes), { style: Object.assign({ color: currentColor }, currentSizes) });
return isIcon ? (cloneElement(Element, Object.assign(Object.assign({}, elementProps), { className }))) : (React__default.createElement("div", Object.assign({}, elementProps, { className: className }), Element));
};
const calculatePosition = (position) => (position - Math.floor(position)) * 100;
const Rating = (props) => {
const { defaultValue = 0, count = 5, onChange, character = SvgSquareMajor, color = 'var(--hero)', bgColor = 'rgba(var(--hero-rgb), 0.3)', halfAllow = false, readonly = false, size = 'small', value } = props, restProps = __rest(props, ["defaultValue", "count", "onChange", "character", "color", "bgColor", "halfAllow", "readonly", "size", "value"]);
const isControlled = 'value' in props;
const isDefaultValueExist = 'defaultValue' in props;
const isRTLMode = document.dir === 'rtl';
const currentValue = value || defaultValue || 0;
const [rating, setRating] = useState(currentValue);
const [hoveredValue, setHoveredValue] = useState(0);
const [regardingPosition, setRegardingPosition] = useState(0);
const [remainingRating, setRemainingRating] = useState(0);
const [temporaryRating, setTemporaryRating] = useState(0);
const [disableMouseMove, setDisableMouseMove] = useState(false);
const calculateRegardingPosition = (e) => {
const { left, width } = e.currentTarget.getBoundingClientRect();
const getClientPosition = e.clientX - (isRTLMode ? left + width : left);
const getRelativeWidth = Math.abs((getClientPosition / width) * 100);
return halfAllow && getRelativeWidth <= 50 ? 50 : 100;
};
const handleMouseMoveForElement = (e, currentRating) => {
if (readonly)
return;
const regradingPosition = calculateRegardingPosition(e);
setRegardingPosition(regradingPosition);
if (disableMouseMove)
return;
setHoveredValue(currentRating);
setRating(currentRating);
};
useLayoutEffect(() => {
if (isControlled || isDefaultValueExist) {
setRating(currentValue);
setTemporaryRating(currentValue);
}
const ratingDecimalParts = Math.round((currentValue % Math.floor(currentValue)) * 100);
if (ratingDecimalParts > 0) {
setRemainingRating(ratingDecimalParts);
}
if (currentValue < 1) {
setRemainingRating(Math.ceil(currentValue * 100));
}
}, [defaultValue, isDefaultValueExist, value, isControlled, currentValue]);
const mouseLeaveHandler = () => {
setHoveredValue(0);
setRegardingPosition(0);
setDisableMouseMove(false);
setRating(temporaryRating);
};
const ratingController = (currentRating, state, blockMouseMovie = true) => {
setHoveredValue(currentRating);
setRating(0);
setRemainingRating(calculatePosition(state));
setTemporaryRating((prev) => {
if (state !== prev)
return state;
setHoveredValue(0);
setRating(currentValue);
setRemainingRating(calculatePosition(currentValue));
setDisableMouseMove(blockMouseMovie);
return currentValue;
});
};
const getRating = (e, currentRating) => {
if (readonly)
return;
setRegardingPosition(calculateRegardingPosition(e));
const selected = regardingPosition === 50 ? +`${currentRating - 1}.${regardingPosition}` : currentRating;
if (isControlled) {
setDisableMouseMove(true);
setHoveredValue(0);
setRating(selected);
onChange === null || onChange === void 0 ? void 0 : onChange(selected);
return;
}
ratingController(currentRating, selected);
};
const mouseEnterHandler = () => {
setTemporaryRating(rating);
};
const elementsList = Math.round(count) > 0 ? new Array(Math.round(count)).fill(undefined) : [];
const PrimitiveValue = (typeof character === 'string' || typeof character === 'number') && character;
const keyDownHandler = (e, currentRating) => {
if (readonly)
return;
if (e.key === 'Enter') {
if (isControlled) {
setRegardingPosition(100);
onChange === null || onChange === void 0 ? void 0 : onChange(currentRating);
return;
}
setRegardingPosition(0);
ratingController(currentRating + 1, currentRating, false);
}
};
const mouseLeaveHandlerForEveryElement = () => {
setDisableMouseMove(false);
};
return (React__default.createElement("div", Object.assign({}, restProps, { className: "rating", onMouseLeave: mouseLeaveHandler, onMouseEnter: mouseEnterHandler, onBlur: () => setDisableMouseMove(false) }), elementsList.map((_, i) => {
const currentRating = i + 1;
const Icon = typeof character === 'function' &&
isValidElement(character(i)) &&
character(i).type
? character(i)
: null;
let calculatedWidthFor = 0;
if (currentRating < hoveredValue) {
calculatedWidthFor = 100;
}
else if (hoveredValue === currentRating) {
calculatedWidthFor = regardingPosition;
}
else if (currentRating <= rating) {
calculatedWidthFor = 100;
}
else if (currentRating === Math.ceil(rating)) {
calculatedWidthFor = remainingRating;
}
else {
calculatedWidthFor = 0;
}
const clipPath = isRTLMode
? `polygon(${100 - calculatedWidthFor}% 0, 100% 0, 100% 100%, ${100 - calculatedWidthFor}% 100%)`
: `polygon( 0 0, ${calculatedWidthFor}% 0, ${calculatedWidthFor}% 100%,0 100%)`;
return (React__default.createElement("div", { className: classnames('rating__wrapper', `rating__wrapper-${size}`, {
'rating__wrapper-readonly': readonly
}), onMouseMove: (e) => handleMouseMoveForElement(e, currentRating), onMouseLeave: mouseLeaveHandlerForEveryElement, onKeyDown: (e) => keyDownHandler(e, currentRating), onClick: (e) => getRating(e, currentRating), tabIndex: 0, key: i },
Icon && React__default.createElement(Element, { color: color, bgColor: bgColor, size: size, Element: Icon, isIcon: true }),
PrimitiveValue && (React__default.createElement(Element, { color: color, bgColor: bgColor, size: size, Element: PrimitiveValue })),
React__default.createElement("div", { className: "rating__element", style: {
clipPath
} },
Icon && (React__default.createElement(Element, { Element: Icon, isIcon: true, isCompareElement: true, color: color, bgColor: bgColor, size: size })),
PrimitiveValue && (React__default.createElement(Element, { Element: PrimitiveValue, color: color, bgColor: bgColor, size: size, isCompareElement: true })))));
})));
};
export { Rating as default };