@spark-ui/progress-tracker
Version:
A progress tracker component is a visual navigation element typically used to display progress or guide user through a multi-step process.
33 lines (32 loc) • 17.1 kB
JavaScript
import e, { createContext as k, useContext as N, useState as L, useId as V, useEffect as j } from "react";
import { cx as w, cva as f } from "class-variance-authority";
import { Icon as A } from "@spark-ui/icon";
const M = w(["flex flex-nowrap items-start group/list", "data-[orientation=horizontal]:flex-row data-[orientation=horizontal]:w-full", "data-[orientation=vertical]:flex-col"]), S = k({}), E = k({}), P = () => N(S), T = ({ stepIndex: t = 0, onStepClick: a, readOnly: r = !1, intent: i = "basic", size: o = "lg", design: p = "outline", orientation: l = "horizontal", children: n, className: h, ref: d, ...b }) => {
const [x, g] = L(/* @__PURE__ */ new Map()), c = r ? "div" : "nav";
return e.createElement(S.Provider, { value: { stepIndex: t, onStepClick: a, steps: x, setSteps: g, size: o, intent: i, design: p, readOnly: r } }, e.createElement(c, { ref: d, "data-spark-component": "progress-tracker", className: w("inline-flex", h), ...b }, e.createElement("ol", { "data-orientation": l, className: M, style: { counterReset: "step" } }, n)));
};
T.displayName = "ProgressTracker";
const $ = f(["relative inline-flex items-start flex-auto first:grow-0 justify-center group/item", "after:absolute after:z-base", "last:after:content-none", "group-data-[orientation=horizontal]/list:px-[1px]", "group-data-[orientation=horizontal]/list:before:absolute group-data-[orientation=horizontal]/list:before:z-base", "group-data-[orientation=horizontal]/list:before:left-0 group-data-[orientation=horizontal]/list:after:right-0", "group-data-[orientation=horizontal]/list:before:h-[1px] group-data-[orientation=horizontal]/list:after:h-[1px]", "first:group-data-[orientation=horizontal]/list:before:content-none", "group-data-[orientation=vertical]/list:py-[1px]", "group-data-[orientation=vertical]/list:items-start", "group-data-[orientation=vertical]/list:after:w-[1px] group-data-[orientation=vertical]/list:after:bottom-[-1px]"], { variants: { size: { sm: ["group-data-[orientation=horizontal]/list:before:top-[8px] group-data-[orientation=horizontal]/list:after:top-[8px]", "group-data-[orientation=horizontal]/list:before:right-[calc(50%+12px)] group-data-[orientation=horizontal]/list:after:left-[calc(50%+12px)]", "first:group-data-[orientation=horizontal]/list:after:left-[calc(50%+10px)]", "last:group-data-[orientation=horizontal]/list:before:right-[calc(50%+10px)]", "group-data-[orientation=vertical]/list:after:left-[8px]", "group-data-[orientation=vertical]/list:after:top-[25px]", "first:group-data-[orientation=vertical]/list:after:top-[21px]"], md: ["group-data-[orientation=horizontal]/list:before:top-[12px] group-data-[orientation=horizontal]/list:after:top-[12px]", "group-data-[orientation=horizontal]/list:before:right-[calc(50%+16px)] group-data-[orientation=horizontal]/list:after:left-[calc(50%+16px)]", "first:group-data-[orientation=horizontal]/list:after:left-[calc(50%+14px)]", "last:group-data-[orientation=horizontal]/list:before:right-[calc(50%+14px)]", "group-data-[orientation=vertical]/list:after:left-[12px]", "group-data-[orientation=vertical]/list:after:top-[33px]", "first:group-data-[orientation=vertical]/list:after:top-[29px]"], lg: ["group-data-[orientation=horizontal]/list:before:top-[16px] group-data-[orientation=horizontal]/list:after:top-[16px]", "group-data-[orientation=horizontal]/list:before:right-[calc(50%+20px)] group-data-[orientation=horizontal]/list:after:left-[calc(50%+20px)]", "first:group-data-[orientation=horizontal]/list:after:left-[calc(50%+18px)]", "last:group-data-[orientation=horizontal]/list:before:right-[calc(50%+18px)]", "group-data-[orientation=vertical]/list:after:left-[16px]", "group-data-[orientation=vertical]/list:after:top-[41px]", "first:group-data-[orientation=vertical]/list:after:top-[37px]"] }, intent: { basic: ["after:bg-basic", "group-data-[orientation=horizontal]/list:before:bg-basic"], support: ["after:bg-support", "group-data-[orientation=horizontal]/list:before:bg-support"], main: ["after:bg-main", "group-data-[orientation=horizontal]/list:before:bg-main"], neutral: ["after:bg-neutral", "group-data-[orientation=horizontal]/list:before:bg-neutral"], info: ["after:bg-info", "group-data-[orientation=horizontal]/list:before:bg-info"], accent: ["after:bg-accent", "group-data-[orientation=horizontal]/list:before:bg-accent"], danger: ["after:bg-error", "group-data-[orientation=horizontal]/list:before:bg-error"], alert: ["after:bg-alert", "group-data-[orientation=horizontal]/list:before:bg-alert"], success: ["after:bg-success", "group-data-[orientation=horizontal]/list:before:bg-success"] }, disabled: { true: "before:opacity-dim-3", false: "" }, disabledAfter: { true: "after:opacity-dim-3", false: "" } }, defaultVariants: { disabled: !1, disabledAfter: !1, size: "lg", intent: "basic" } }), _ = f(["relative flex group/btn disabled:cursor-default", "group-data-[orientation=horizontal]/list:flex-col group-data-[orientation=horizontal]/list:items-center", "group-data-[orientation=horizontal]/list:text-center group-data-[orientation=horizontal]/list:mx-sm", "group-first/item:group-data-[orientation=horizontal]/list:ml-0 group-last/item:group-data-[orientation=horizontal]/list:mr-0", "group-data-[orientation=vertical]/list:flex-row group-data-[orientation=vertical]/list:items-start", "group-data-[orientation=vertical]/list:text-left group-data-[orientation=vertical]/list:my-sm", "group-first/item:group-data-[orientation=vertical]/list:mt-0 group-last/item:group-data-[orientation=vertical]/list:mb-0"], { variants: { size: { sm: ["group-data-[orientation=horizontal]/list:min-w-sz-16 group-data-[orientation=horizontal]/list:mt-[16px]", "group-data-[orientation=vertical]/list:min-h-sz-16 group-data-[orientation=vertical]/list:ml-[16px]"], md: ["group-data-[orientation=horizontal]/list:min-w-sz-24 group-data-[orientation=horizontal]/list:mt-[24px]", "group-data-[orientation=vertical]/list:min-h-sz-24 group-data-[orientation=vertical]/list:ml-[24px]"], lg: ["group-data-[orientation=horizontal]/list:min-w-sz-32 group-data-[orientation=horizontal]/list:mt-[32px]", "group-data-[orientation=vertical]/list:min-h-sz-32 group-data-[orientation=vertical]/list:ml-[32px]"] }, readOnly: { true: "cursor-default", false: "cursor-pointer" } }, defaultVariants: { size: "lg", readOnly: !1 } }), C = ({ title: t, fill: a = "currentColor", stroke: r = "none", ref: i, ...o }) => e.createElement("svg", { ref: i, viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", "data-title": "Check", ...t && { "data-title": t }, fill: a, stroke: r, ...o, dangerouslySetInnerHTML: { __html: (t === void 0 ? "" : `<title>${t}</title>`) + '<path d="m8.92,19.08c-.18,0-.36-.03-.53-.1s-.33-.17-.47-.31l-5.49-5.34c-.28-.28-.42-.61-.42-1s.14-.73.42-1c.28-.28.62-.41,1.02-.41s.74.14,1.05.41l4.43,4.3,10.62-10.29c.28-.28.62-.42,1.02-.43.39,0,.73.13,1.02.43.28.28.42.61.42,1s-.14.73-.42,1l-11.65,11.32c-.14.14-.3.24-.47.31-.17.07-.35.1-.53.1Z"/>' } });
C.displayName = "Check";
const B = f(["relative flex shrink-0 justify-center items-center", "rounded-full", "text-body-2 font-bold", "group-disabled/btn:opacity-dim-3"], { variants: { size: { sm: ["w-sz-16 h-sz-16", "group-data-[orientation=horizontal]/list:mt-[-16px]", "group-data-[orientation=vertical]/list:ml-[-16px]"], md: ["w-sz-24 h-sz-24", "group-data-[orientation=horizontal]/list:mt-[-24px]", "group-data-[orientation=vertical]/list:ml-[-24px]"], lg: ["w-sz-32 h-sz-32", "group-data-[orientation=horizontal]/list:mt-[-32px]", "group-data-[orientation=vertical]/list:ml-[-32px]"] }, intent: { basic: "", support: "", main: "", neutral: "", info: "", accent: "", danger: "", alert: "", success: "" }, design: { outline: "border-sm", tinted: "" }, state: { complete: "", incomplete: "", active: "" } }, compoundVariants: [{ design: "outline", intent: "basic", state: ["complete", "incomplete"], class: ["text-on-basic-container bg-transparent", "group-hover/btn:group-data-[interactive=true]/btn:bg-basic-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-transparent"] }, { design: "outline", intent: "basic", state: "active", class: "text-on-basic-container bg-basic-container" }, { design: "outline", intent: "support", state: ["complete", "incomplete"], class: ["text-on-support-container bg-transparent", "group-hover/btn:group-data-[interactive=true]/btn:bg-support-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-transparent"] }, { design: "outline", intent: "support", state: "active", class: "text-on-support-container bg-support-container" }, { design: "outline", intent: "main", state: ["complete", "incomplete"], class: ["text-on-main-container bg-transparent", "group-hover/btn:group-data-[interactive=true]/btn:bg-main-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-transparent"] }, { design: "outline", intent: "main", state: "active", class: "text-on-main-container bg-main-container" }, { design: "outline", intent: "neutral", state: ["complete", "incomplete"], class: ["text-on-neutral-container bg-transparent", "group-hover/btn:group-data-[interactive=true]/btn:bg-neutral-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-transparent"] }, { design: "outline", intent: "neutral", state: "active", class: "text-on-neutral-container bg-neutral-container" }, { design: "outline", intent: "info", state: ["complete", "incomplete"], class: ["text-on-info-container bg-transparent", "group-hover/btn:group-data-[interactive=true]/btn:bg-info-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-transparent"] }, { design: "outline", intent: "info", state: "active", class: "text-on-info-container bg-info-container" }, { design: "outline", intent: "accent", state: ["complete", "incomplete"], class: ["text-on-accent-container bg-transparent", "group-hover/btn:group-data-[interactive=true]/btn:bg-accent-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-transparent"] }, { design: "outline", intent: "accent", state: "active", class: "text-on-accent-container bg-accent-container" }, { design: "outline", intent: "danger", state: ["complete", "incomplete"], class: ["text-on-error-container bg-transparent", "group-hover/btn:group-data-[interactive=true]/btn:bg-error-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-transparent"] }, { design: "outline", intent: "danger", state: "active", class: "text-on-error-container bg-error-container" }, { design: "outline", intent: "alert", state: ["complete", "incomplete"], class: ["text-on-alert-container bg-transparent", "group-hover/btn:group-data-[interactive=true]/btn:bg-alert-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-transparent"] }, { design: "outline", intent: "alert", state: "active", class: "text-on-alert-container bg-alert-container" }, { design: "outline", intent: "success", state: ["complete", "incomplete"], class: ["text-on-success-container bg-transparent", "group-hover/btn:group-data-[interactive=true]/btn:bg-success-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-transparent"] }, { design: "outline", intent: "success", state: "active", class: "text-on-success-container bg-success-container" }, { design: "tinted", intent: "basic", state: ["complete", "incomplete"], class: ["text-on-basic-container bg-basic-container", "group-hover/btn:group-data-[interactive=true]/btn:bg-basic-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-basic-container"] }, { design: "tinted", intent: "basic", state: "active", class: "text-on-basic bg-basic" }, { design: "tinted", intent: "support", state: ["complete", "incomplete"], class: ["text-on-support-container bg-support-container", "group-hover/btn:group-data-[interactive=true]/btn:bg-support-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-support-container"] }, { design: "tinted", intent: "support", state: "active", class: "text-on-support bg-support" }, { design: "tinted", intent: "main", state: ["complete", "incomplete"], class: ["text-on-main-container bg-main-container", "group-hover/btn:group-data-[interactive=true]/btn:bg-main-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-main-container"] }, { design: "tinted", intent: "main", state: "active", class: "text-on-main bg-main" }, { design: "tinted", intent: "neutral", state: ["complete", "incomplete"], class: ["text-on-neutral-container bg-neutral-container", "group-hover/btn:group-data-[interactive=true]/btn:bg-neutral-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-neutral-container"] }, { design: "tinted", intent: "neutral", state: "active", class: "text-on-neutral bg-neutral" }, { design: "tinted", intent: "info", state: ["complete", "incomplete"], class: ["text-on-info-container bg-info-container", "group-hover/btn:group-data-[interactive=true]/btn:bg-info-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-info-container"] }, { design: "tinted", intent: "info", state: "active", class: "text-on-info bg-info" }, { design: "tinted", intent: "accent", state: ["complete", "incomplete"], class: ["text-on-accent-container bg-accent-container", "group-hover/btn:group-data-[interactive=true]/btn:bg-accent-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-accent-container"] }, { design: "tinted", intent: "accent", state: "active", class: "text-on-accent bg-accent" }, { design: "tinted", intent: "danger", state: ["complete", "incomplete"], class: ["text-on-error-container bg-error-container", "group-hover/btn:group-data-[interactive=true]/btn:bg-error-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-error-container"] }, { design: "tinted", intent: "danger", state: "active", class: "text-on-error bg-error" }, { design: "tinted", intent: "alert", state: ["complete", "incomplete"], class: ["text-on-alert-container bg-alert-container", "group-hover/btn:group-data-[interactive=true]/btn:bg-alert-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-alert-container"] }, { design: "tinted", intent: "alert", state: "active", class: "text-on-alert bg-alert" }, { design: "tinted", intent: "success", state: ["complete", "incomplete"], class: ["text-on-success-container bg-success-container", "group-hover/btn:group-data-[interactive=true]/btn:bg-success-container-hovered", "group-hover/btn:group-data-[interactive=false]/btn:bg-success-container"] }, { design: "tinted", intent: "success", state: "active", class: "text-on-success bg-success" }], defaultVariants: { size: "lg", state: "incomplete", intent: "basic", design: "outline" } }), F = () => e.createElement(A, { size: "sm" }, e.createElement(C, null)), v = ({ complete: t, incomplete: a, className: r }) => {
const { size: i, intent: o, design: p } = P(), { index: l, state: n } = N(E);
return e.createElement("span", { className: B({ size: i, intent: o, design: p, state: n, className: r }), "aria-hidden": "true" }, i !== "sm" && e.createElement(e.Fragment, null, n === "complete" && (t === void 0 ? e.createElement(F, null) : t), n !== "complete" && (a === void 0 ? `${l + 1}` : a)));
};
v.displayName = "ProgressTracker.StepIndicator";
const z = ({ disabled: t = !1, children: a, "aria-label": r, className: i, ref: o, ...p }) => {
const { stepIndex: l, steps: n, onStepClick: h, setSteps: d, size: b, intent: x, readOnly: g } = P(), c = `:progress-tracker-step-${V()}`, u = [...n.keys()].indexOf(c), I = (() => {
const s = [...n.keys()][u + 1];
return !(!s || !n.get(s)?.includes("disabled"));
})(), m = u === l ? "active" : u < l ? "complete" : "incomplete";
return j(() => (d((s) => new Map(s).set(c, [m, t ? "disabled" : ""].filter((O) => !!O))), () => {
d((s) => (s.delete(c), s));
}), []), e.createElement("li", { id: c, ref: o, "data-state": m, ...m === "active" && { "aria-current": "step" }, className: $({ size: b, intent: x, disabled: t, disabledAfter: I }), ...p }, e.createElement("button", { type: "button", "aria-label": r, "data-interactive": !t && !g, ...!t && !g && { onClick: () => h?.(u) }, disabled: t, className: _({ size: b, readOnly: g, className: i }) }, e.createElement(E.Provider, { value: { index: u, state: m } }, a || e.createElement(v, null))));
};
z.displayName = "ProgressTracker.Step";
const H = f(["flex text-body-2 font-bold", "text-on-surface group-disabled/btn:text-on-surface/dim-1", "group-data-[orientation=horizontal]/list:mt-md", "group-data-[orientation=vertical]/list:ml-md", "group-data-[orientation=vertical]/list:my-auto"]), y = ({ className: t, children: a }) => e.createElement("span", { className: H({ className: t }) }, a);
y.displayName = "ProgressTracker.StepLabel";
const R = Object.assign(T, { Step: z, StepLabel: y, StepIndicator: v });
R.displayName = "ProgressTracker", z.displayName = "ProgressTracker.Step", y.displayName = "ProgressTracker.StepLabel", v.displayName = "ProgressTracker.StepIndicator";
export {
R as ProgressTracker
};