@spark-ui/components
Version:
Spark (Leboncoin design system) components.
362 lines (350 loc) • 11.3 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/rating/index.ts
var rating_exports = {};
__export(rating_exports, {
Rating: () => Rating
});
module.exports = __toCommonJS(rating_exports);
// src/rating/Rating.tsx
var import_use_combined_state = require("@spark-ui/hooks/use-combined-state");
var import_class_variance_authority4 = require("class-variance-authority");
var import_react3 = require("react");
// src/rating/RatingStar.tsx
var import_StarFill = require("@spark-ui/icons/StarFill");
var import_StarOutline = require("@spark-ui/icons/StarOutline");
var import_class_variance_authority3 = require("class-variance-authority");
// src/icon/Icon.tsx
var import_react2 = require("react");
// src/slot/Slot.tsx
var import_radix_ui = require("radix-ui");
var import_react = require("react");
var import_jsx_runtime = require("react/jsx-runtime");
var Slottable = import_radix_ui.Slot.Slottable;
var Slot = ({ ref, ...props }) => {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_radix_ui.Slot.Root, { ref, ...props });
};
// src/visually-hidden/VisuallyHidden.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var VisuallyHidden = ({ asChild = false, ref, ...props }) => {
const Component = asChild ? Slot : "span";
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
Component,
{
...props,
ref,
style: {
// See: https://github.com/twbs/bootstrap/blob/main/scss/mixins/_visually-hidden.scss
position: "absolute",
border: 0,
width: 1,
height: 1,
padding: 0,
margin: -1,
overflow: "hidden",
clip: "rect(0, 0, 0, 0)",
whiteSpace: "nowrap",
wordWrap: "normal",
...props.style
}
}
);
};
VisuallyHidden.displayName = "VisuallyHidden";
// src/icon/Icon.styles.tsx
var import_internal_utils = require("@spark-ui/internal-utils");
var import_class_variance_authority = require("class-variance-authority");
var iconStyles = (0, import_class_variance_authority.cva)(["fill-current shrink-0"], {
variants: {
/**
* Color scheme of the icon.
*/
intent: (0, import_internal_utils.makeVariants)({
current: ["text-current"],
main: ["text-main"],
support: ["text-support"],
accent: ["text-accent"],
basic: ["text-basic"],
success: ["text-success"],
alert: ["text-alert"],
error: ["text-error"],
info: ["text-info"],
neutral: ["text-neutral"]
}),
/**
* Sets the size of the icon.
*/
size: (0, import_internal_utils.makeVariants)({
current: ["u-current-font-size"],
sm: ["w-sz-16", "h-sz-16"],
md: ["w-sz-24", "h-sz-24"],
lg: ["w-sz-32", "h-sz-32"],
xl: ["w-sz-40", "h-sz-40"]
})
}
});
// src/icon/Icon.tsx
var import_jsx_runtime3 = require("react/jsx-runtime");
var Icon = ({
label,
className,
size = "current",
intent = "current",
children,
...others
}) => {
const child = import_react2.Children.only(children);
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
(0, import_react2.cloneElement)(child, {
className: iconStyles({ className, size, intent }),
"data-spark-component": "icon",
"aria-hidden": "true",
focusable: "false",
...others
}),
label && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(VisuallyHidden, { children: label })
] });
};
Icon.displayName = "Icon";
// src/rating/RatingStar.styles.ts
var import_class_variance_authority2 = require("class-variance-authority");
var emptyRemainingStarsOnHoverClass = (0, import_class_variance_authority2.cx)("[&_>_div]:peer-hover:w-0!");
var ratingStarStyles = (0, import_class_variance_authority2.cva)(
["peer", "after:inset-0", "group", "relative", "after:block after:absolute"],
{
variants: {
disabled: {
true: "opacity-dim-3",
false: ""
},
readOnly: {
true: "",
false: ""
},
gap: {
sm: ["after:w-[calc(100%+(var(--spacing-sm)))]", "last-of-type:after:content-none"],
md: ["after:w-[calc(100%+(var(--spacing-md)))]", "last-of-type:after:content-none"]
}
},
compoundVariants: [
{
readOnly: false,
disabled: false,
className: (0, import_class_variance_authority2.cx)(emptyRemainingStarsOnHoverClass, "cursor-pointer")
}
],
defaultVariants: {
disabled: false,
readOnly: false,
gap: "sm"
}
}
);
var ratingStarIconStyles = (0, import_class_variance_authority2.cva)("", {
variants: {
size: {
sm: "text-caption-link",
md: "text-body-1",
lg: "text-display-1"
},
design: {
filled: [
"text-main-variant",
"group-[[data-part=star][data-hovered]]:text-main-variant-hovered"
],
outlined: ["text-on-surface/dim-3"]
}
}
});
// src/rating/RatingStar.tsx
var import_jsx_runtime4 = require("react/jsx-runtime");
var RatingStar = ({
value,
size,
disabled,
readOnly,
onClick,
onMouseEnter,
ref: forwardedRef
}) => {
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
"div",
{
ref: forwardedRef,
onMouseEnter,
className: ratingStarStyles({
gap: size === "lg" ? "md" : "sm",
disabled,
readOnly
}),
"data-part": "star",
onClick,
children: [
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
"div",
{
className: (0, import_class_variance_authority3.cx)(
"z-raised absolute overflow-hidden",
"group-[[data-part=star][data-hovered]]:overflow-visible"
),
style: { width: value * 100 + "%" },
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
Icon,
{
className: ratingStarIconStyles({
size,
design: "filled"
}),
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_StarFill.StarFill, {})
}
)
}
),
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Icon, { className: ratingStarIconStyles({ size, design: "outlined" }), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_StarOutline.StarOutline, {}) })
]
}
);
};
// src/rating/utils.ts
function getNearestHalfDecimal(num) {
return Math.round(num / 0.5) * 0.5;
}
function getStarValue({ value, index }) {
if (value === void 0) return 0;
const starPosition = index + 1;
const formattedValue = getNearestHalfDecimal(value);
if (Math.ceil(formattedValue) < starPosition) return 0;
return formattedValue >= starPosition ? 1 : 0.5;
}
function splitAt(arr, index) {
const prev = arr.slice(0, index);
const next = arr.slice(index);
return [prev, next];
}
// src/rating/Rating.tsx
var import_jsx_runtime5 = require("react/jsx-runtime");
var Rating = ({
defaultValue,
value: propValue,
onValueChange,
size = "md",
disabled,
readOnly,
name,
id,
"aria-label": ariaLabel,
ref,
...rest
}) => {
const inputRef = (0, import_react3.useRef)(null);
const starRefList = (0, import_react3.useRef)([]);
const [value, setRatingValue] = (0, import_use_combined_state.useCombinedState)(propValue, defaultValue, onValueChange);
const valueRef = (0, import_react3.useRef)(value);
const isInteractive = !(disabled || readOnly);
function onStarClick(index) {
if (!inputRef.current) return;
setRatingValue(index + 1);
valueRef.current = index + 1;
inputRef.current.focus();
inputRef.current.setAttribute("data-clicked", "");
}
function onInputChange(event) {
if (valueRef.current === Number(event.target.value) || Number(event.target.value) === 0) {
return;
}
valueRef.current = Number(event.target.value);
setRatingValue(Number(event.target.value));
}
function onStarMouseEnter({ currentTarget }) {
const currentStarIndex = starRefList.current.findIndex((star) => star === currentTarget);
const [previousStars, followingStars] = splitAt(starRefList.current, currentStarIndex + 1);
previousStars.forEach((star) => star.setAttribute("data-hovered", ""));
followingStars.forEach((star) => star.removeAttribute("data-hovered"));
}
const handleStarRef = (0, import_react3.useCallback)((elm) => {
if (!elm) return;
starRefList.current.push(elm);
}, []);
function resetDataPartInputAttr() {
inputRef.current?.removeAttribute("data-clicked");
}
function resetDataPartStarAttr() {
starRefList.current.forEach((star) => star.removeAttribute("data-hovered"));
}
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
"div",
{
className: "relative inline-flex",
ref,
"data-spark-component": "rating",
...rest,
onMouseLeave: resetDataPartStarAttr,
children: [
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
"input",
{
name,
id,
"aria-label": ariaLabel,
ref: inputRef,
"data-part": "input",
className: "peer absolute inset-0 opacity-0",
type: "range",
min: "0",
max: "5",
step: readOnly ? 0.5 : 1,
disabled,
readOnly,
value: getNearestHalfDecimal(value ?? 0),
onChange: (event) => isInteractive && onInputChange(event),
onBlur: resetDataPartInputAttr
}
),
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
"div",
{
className: (0, import_class_variance_authority4.cx)(
size === "lg" ? "gap-x-md" : "gap-x-sm",
"flex",
"peer-focus-visible:u-outline peer-[[data-part=input][data-clicked]]:shadow-none"
),
children: Array.from({ length: 5 }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
RatingStar,
{
disabled,
readOnly,
size,
onClick: () => isInteractive && onStarClick(index),
onMouseEnter: (event) => isInteractive && onStarMouseEnter(event),
ref: handleStarRef,
value: getStarValue({ index, value })
},
index
))
}
)
]
}
);
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Rating
});
//# sourceMappingURL=index.js.map
;