UNPKG

chakra-ui-steps

Version:

Steps component designed to work seamlessly with Chakra UI

803 lines (802 loc) 19 kB
import { jsx as r, jsxs as $ } from "react/jsx-runtime"; import { createIcon as q, forwardRef as H, omitThemingProps as ne, useColorModeValue as re, useMediaQuery as ie, useMultiStyleConfig as ce, chakra as _, Flex as G, Spinner as se, Collapse as ae } from "@chakra-ui/react"; import * as C from "react"; import D from "react"; import { dataAttr as x } from "@chakra-ui/utils"; import { mode as M, anatomy as le } from "@chakra-ui/theme-tools"; import { motion as Z, AnimatePresence as de } from "framer-motion"; import { createIcon as pe } from "@chakra-ui/icon"; import { createContext as he } from "@chakra-ui/react-context"; import { cx as ue } from "@chakra-ui/shared-utils"; import { createMultiStyleConfigHelpers as me } from "@chakra-ui/styled-system"; const J = C.createContext({ activeStep: 0 }), N = () => C.useContext(J), ge = ({ value: e, children: o }) => { const t = e.state === "error", n = e.state === "loading"; return r(J.Provider, { value: { ...e, isError: t, isLoading: n }, children: o }); }, fe = q({ viewBox: "0 0 14 14", path: r("g", { fill: "currentColor", children: r("polygon", { points: "5.5 11.9993304 14 3.49933039 12.5 2 5.5 8.99933039 1.5 4.9968652 0 6.49933039" }) }) }); q({ displayName: "CloseIcon", d: "M.439,21.44a1.5,1.5,0,0,0,2.122,2.121L11.823,14.3a.25.25,0,0,1,.354,0l9.262,9.263a1.5,1.5,0,1,0,2.122-2.121L14.3,12.177a.25.25,0,0,1,0-.354l9.263-9.262A1.5,1.5,0,0,0,21.439.44L12.177,9.7a.25.25,0,0,1-.354,0L2.561.44A1.5,1.5,0,0,0,.439,2.561L9.7,11.823a.25.25,0,0,1,0,.354Z" }); const Ce = pe({ d: "M11.983,0a12.206,12.206,0,0,0-8.51,3.653A11.8,11.8,0,0,0,0,12.207,11.779,11.779,0,0,0,11.8,24h.214A12.111,12.111,0,0,0,24,11.791h0A11.766,11.766,0,0,0,11.983,0ZM10.5,16.542a1.476,1.476,0,0,1,1.449-1.53h.027a1.527,1.527,0,0,1,1.523,1.47,1.475,1.475,0,0,1-1.449,1.53h-.027A1.529,1.529,0,0,1,10.5,16.542ZM11,12.5v-6a1,1,0,0,1,2,0v6a1,1,0,1,1-2,0Z", displayName: "WarningIcon" }), [xe, be] = he({ name: "StepsStyleContext", errorMessage: `useStepsStyles returned 'undefined'. Seems you forgot to wrap the components in "<Steps />" ` }), j = be, Se = H((e, o) => { const { className: t, activeStep: n, children: i, orientation: s, state: a, responsive: c, checkIcon: u, errorIcon: b, onClickStep: l, mobileBreakpoint: S, trackColor: d, expandVerticalSteps: p = !1, ...v } = ne(e), m = d || re("gray.200", "gray.700"), g = C.Children.toArray(i), f = g.length, L = () => n <= g.length ? C.Children.map(g[n], (h) => { if (C.isValidElement(h)) return C.Children.map(h.props.children, (I) => I); }) : null, [k] = ie(`(max-width: ${S || "768px"})`), E = !!l, w = k && c ? "vertical" : s, y = w === "vertical", z = ce("Steps", { ...e, orientation: w, stepCount: f, isVertical: y, trackColor: m }), W = { ...z.root }; return r(xe, { value: z, children: $(ge, { value: { activeStep: n, orientation: w, state: a, responsive: c, checkIcon: u, errorIcon: b, onClickStep: l, clickable: E, colorScheme: e.colorScheme, stepCount: f, trackColor: m, isVertical: y, variant: e.variant || "circles", expandVerticalSteps: p }, children: [r(_.div, { ref: o, __css: { justifyContent: f === 1 ? "flex-end" : "space-between", flexDir: w === "vertical" ? "column" : "row", ...W }, className: ue("cui-steps", t), ...v, children: C.Children.map(i, (h, I) => { const V = (C.isValidElement(h) && h.props.isCompletedStep) ?? I < n, R = I === f - 1, oe = { index: I, isCompletedStep: V, isCurrentStep: I === n, isLastStep: R }; return C.isValidElement(h) ? C.cloneElement(h, oe) : null; }) }), w === "horizontal" && L()] }) }); }); Se.defaultProps = { activeStep: 0, colorScheme: "green", orientation: "horizontal", responsive: !0 }; const B = Z(G), T = Z(Ce), ve = Z(_.span), P = { transition: { duration: 0.25 }, exit: { scale: 0.5, opacity: 0 }, initial: { scale: 0.5, opacity: 0 }, animate: { scale: 1, opacity: 1 } }, O = H((e, o) => { const { icon: t, iconLabel: n, label: i } = j(), { isCompletedStep: s, isCurrentStep: a, isError: c, isLoading: u, isKeepError: b, icon: l, index: S, checkIcon: d, errorIcon: p } = e, v = { fontWeight: "medium", color: M("gray.900", "gray.100")(e), textAlign: "center", fontSize: "md", ...i }, m = D.useMemo(() => l || null, [l]), g = D.useMemo(() => p || null, [p]), f = D.useMemo(() => d || fe, [d]); return D.useMemo(() => { if (s) return c && b ? r(T, { ...P, style: t }, "icon") : r(B, { ...P, children: r(f, { color: "white", style: t }) }, "check-icon"); if (a) { if (c && g) return r(B, { ...P, children: r(g, { color: "white", style: t }) }, "error-icon"); if (c) return r(T, { ...P, style: t }, "icon"); if (u) return r(se, { width: t.width, height: t.height }); } return m ? r(B, { ...P, children: r(m, { style: t }) }, "step-icon") : r(ve, { ref: o, style: n, __css: v, ...P, children: (S || 0) + 1 }, "label"); }, [s, a, c, u, m, t]); }), U = ({ isCurrentStep: e, isCompletedStep: o, children: t, isError: n, isLoading: i }) => { const { stepIconContainer: s } = j(), { clickable: a, isLoading: c } = N(), u = i || c; return r(_.div, { __css: s, className: "cui-steps__step-icon-container", "aria-current": e ? "step" : void 0, "data-invalid": x(n && (e || o)), "data-active": x(o), "data-clickable": x(a), "data-loading": x(u && (e || o)), children: r(de, { mode: "wait", children: t }) }); }, X = ({ isCurrentStep: e, opacity: o, label: t, description: n }) => { const { labelContainer: i, label: s, description: a } = j(); return !!t || !!n ? $(_.div, { "aria-current": e ? "step" : void 0, __css: i, children: [!!t && r(_.span, { __css: { opacity: o, ...s }, children: t }), !!n && r(_.span, { __css: { opacity: o, ...a }, children: n })] }) : null; }, ye = C.forwardRef((e, o) => { const { step: t, stepContainer: n } = j(), { isError: i, isLoading: s, onClickStep: a, variant: c, clickable: u, checkIcon: b, errorIcon: l } = N(), { index: S, isCompletedStep: d, isCurrentStep: p, hasVisited: v, icon: m, label: g, description: f, isKeepError: L, state: k, checkIcon: E, errorIcon: w } = e, y = s || k === "loading", z = i || k === "error", W = v ? 1 : 0.8, h = c === "simple" ? d || p : d, I = E || b, V = w || l; return r(_.div, { "aria-disabled": !v, className: "cui-steps__horizontal-step", "data-active": x(h), "data-invalid": x(z), "data-clickable": x(u), onClick: () => a == null ? void 0 : a(S || 0), ref: o, __css: t, children: $(_.div, { className: "cui-steps__horizontal-step-container", __css: n, children: [r(U, { ...e, isError: z, isLoading: y, children: r(O, { index: S, isCompletedStep: d, isCurrentStep: p, isError: z, isKeepError: L, isLoading: y, icon: m, checkIcon: I, errorIcon: V }) }), r(X, { label: g, description: f, isCurrentStep: p, opacity: W })] }) }); }), Ie = D.forwardRef((e, o) => { const { children: t, index: n, isCompletedStep: i, isCurrentStep: s, label: a, description: c, icon: u, hasVisited: b, state: l, checkIcon: S, errorIcon: d } = e, { checkIcon: p, errorIcon: v, isError: m, isLoading: g, variant: f, onClickStep: L, clickable: k, expandVerticalSteps: E } = N(), { step: w, stepIconContainer: y } = j(), z = b ? 1 : 0.8, W = g || l === "loading", h = m || l === "error", I = f === "simple" ? i || s : i, V = S || p, R = d || v, K = () => E ? t : r(ae, { style: { width: "100%" }, in: s, children: (s || i) && t }); return $(_.div, { ref: o, className: "cui-steps__vertical-step", "data-active": x(I), "data-clickable": x(k), "data-invalid": x(h), onClick: () => L == null ? void 0 : L(n || 0), __css: w, children: [$(G, { "data-vertical": x(!0), className: "cui-steps__vertical-step-container", children: [r(U, { isLoading: W, isError: h, ...e, children: r(O, { index: n, isError: h, isLoading: W, isCurrentStep: s, isCompletedStep: i, icon: u, checkIcon: V, errorIcon: R }) }), r(X, { label: a, description: c, isCurrentStep: s, opacity: z })] }), r(_.div, { className: "cui-steps__vertical-step-content", __css: { minH: "8px", paddingStart: y != null && y.width ? `calc(${y.width})` : 0 }, children: K() })] }); }), Ge = H((e, o) => { const { children: t, description: n, icon: i, state: s, checkIcon: a, errorIcon: c, index: u, isCompletedStep: b, isCurrentStep: l, isLastStep: S, isKeepError: d, label: p } = e, { isVertical: v, isError: m, isLoading: g, clickable: f } = N(), k = { isLastStep: S, isCompletedStep: b, isCurrentStep: l, index: u, isError: m, isLoading: g, clickable: f, label: p, description: n, hasVisited: l || b, icon: i, isKeepError: d, checkIcon: a, state: s, errorIcon: c }; return (() => { switch (v) { case !0: return r(Ie, { ref: o, ...k, children: t }); default: return r(ye, { ref: o, ...k }); } })(); }); function Je({ initialStep: e }) { const [o, t] = C.useState(e); return { nextStep: () => { t((c) => c + 1); }, prevStep: () => { t((c) => c - 1); }, reset: () => { t(e); }, setStep: (c) => { t(c); }, activeStep: o }; } const Y = ({ colorScheme: e, trackColor: o, clickable: t }) => ({ display: "flex", alignItems: "center", "&:not(:last-child)": { flex: 1 }, "&:not(:last-child):after": { content: '""', flex: 1, height: "2px", backgroundColor: `${o}`, mx: 3, transition: "background-color .2s ease" }, _active: { "&:not(:last-child):after": { backgroundColor: `${e}.500`, backgroundPosition: "left", transition: "background-position .2s ease-in-out" } }, _hover: { cursor: t ? "pointer" : "default" } }), _e = ({ colorScheme: e, trackColor: o, clickable: t, inactiveColor: n, stepHeight: i }) => ({ ...Y({ colorScheme: e, trackColor: o, clickable: t }), justifyContent: "flex-start", flexDirection: "column", flex: 1, "&:not(:last-child):after": { content: '""', backgroundColor: o || n, height: "2px", order: -1, insetInline: "50%", position: "relative", top: `calc(${i} / 2)`, transition: "background-color .2s ease", width: `calc(100% - ${i} - calc(8px * 2))` } }), ee = ({ stepHeight: e, colorScheme: o, trackColor: t, clickable: n }) => ({ position: "relative", gap: 4, pb: 4, display: "flex", flexDir: "column", "--size": e, "--gap": "8px", _active: { pb: 4, "&:not(:last-child):after": { backgroundColor: `${o}.500`, backgroundPosition: "left", transition: "background-position .2s ease-in-out" } }, "&:not(:last-child):after": { content: '""', backgroundColor: t, bottom: "var(--gap)", insetInline: "calc(var(--size) / 2)", position: "absolute", top: "calc(var(--size) + var(--gap))", width: "2px" }, _hover: { cursor: n ? "pointer" : "default" } }), te = ({ inactiveColor: e, activeColor: o }) => ({ display: "flex", borderRadius: "50%", alignItems: "center", justifyContent: "center", bg: e, borderColor: e, _activeStep: { borderColor: o, _invalid: { bg: "red.400", borderColor: "red.400" } }, _active: { bg: o, borderColor: o, _invalid: { bg: "red.400", borderColor: "red.400" } }, "&[data-clickable]:hover": { borderColor: o, cursor: "pointer" } }), ke = le("steps").parts("description", "icon", "iconLabel", "label", "labelContainer", "step", "stepContainer", "stepIconContainer", "root"), { defineMultiStyleConfig: we, definePartsStyle: A } = me(ke.keys), Le = { strokeWidth: "2px" }, Q = (e) => ({ color: M("gray.900", "gray.100")(e), textAlign: "center", fontSize: "md", fontWeight: "bold" }), ze = (e) => ({ color: M("gray.800", "gray.200")(e), mt: "-2px", textAlign: "center", fontSize: "sm" }), Ae = ({ stepCount: e, orientation: o }) => ({ justifyContent: e === 1 ? "flex-end" : "space-between", flexDir: o === "vertical" ? "column" : "row", fontFamily: "heading", textAlign: "center", width: "100%", display: "flex", flex: 1, flexWrap: "wrap" }), Ee = () => ({ display: "flex", alignItems: "center" }), We = { display: "flex", position: "relative" }, Pe = () => ({ display: "flex", flexDir: "column", justifyContent: "center" }), Me = A((e) => ({ description: ze(e), icon: Le, iconLabel: Q(e), label: Q(e), labelContainer: Pe(), step: We, stepContainer: Ee(), root: Ae(e) })), F = { sm: A({ stepIconContainer: { width: "32px", height: "32px", borderWidth: "2px" }, icon: { width: "14px", height: "14px" }, label: { fontWeight: "medium", textAlign: "center", fontSize: "sm" }, description: { fontWeight: "300", textAlign: "center", fontSize: "xs" } }), md: A({ stepIconContainer: { width: "40px", height: "40px", borderWidth: "2px" }, icon: { width: "18px", height: "18px" }, label: { fontWeight: "medium", textAlign: "center", fontSize: "md" }, description: { fontWeight: "300", textAlign: "center", fontSize: "sm" } }), lg: A({ stepIconContainer: { width: "48px", height: "48px", borderWidth: "2px" }, icon: { width: "22px", height: "22px" }, label: { fontWeight: "bold", textAlign: "center", fontSize: "lg" }, description: { fontWeight: "300", textAlign: "center", fontSize: "md" } }) }, Ve = A((e) => { const { colorScheme: o } = e, t = M("gray.200", "gray.700")(e), n = `${o}.500`, i = F[e.size].stepIconContainer.height; return { stepIconContainer: te({ inactiveColor: t, activeColor: n }), labelContainer: { flexDir: "column", alignItems: "flex-start", ms: 3 }, step: e.orientation === "horizontal" ? Y({ ...e, stepHeight: i }) : ee({ ...e, stepHeight: i }) }; }), De = A((e) => { const { colorScheme: o } = e, t = M("gray.200", "gray.700")(e), n = `${o}.500`, i = F[e.size].stepIconContainer.height; return { stepIconContainer: { ...te({ inactiveColor: t, activeColor: n }), flexDir: "column" }, stepContainer: { flexDir: "column" }, labelContainer: { flexDir: "column", alignItems: e.orientation === "horizontal" ? "center" : "flex-start", ms: e.orientation === "horizontal" ? 0 : 3 }, step: e.orientation === "horizontal" ? _e({ ...e, stepHeight: i }) : ee({ ...e, stepHeight: i }) }; }), $e = A((e) => { const { colorScheme: o } = e, t = M("gray.200", "gray.700")(e), n = `${o}.500`, i = e.orientation === "vertical"; return { stepIconContainer: { opacity: 0, pointerEvents: "none", borderWidth: 0, display: "flex", alignItems: "center", justifyContent: "flex-end", _loading: { opacity: 1, pointerEvents: "auto" }, _invalid: { opacity: 1, pointerEvents: "auto" } }, stepContainer: { flex: 1, py: 2, flexDir: "row-reverse", alignItems: "center", justifyContent: "space-between" }, label: { mx: 0, fontWeight: "bold" }, labelContainer: { flexDir: "column", alignItems: "flex-start" }, description: { mx: 0 }, root: { gap: 4 }, step: { flexDir: "column", position: "relative", flex: 1, borderTopWidth: i ? 0 : 3, borderColor: (e == null ? void 0 : e.trackColor) || t, "&:not(:last-child):after": { display: "none" }, transition: "border-color .2s ease", _activeStep: { _invalid: { borderColor: "red.400", "& .cui-steps__vertical-step-container": { borderColor: "red.400" } } }, _active: { transition: "border-color .2s ease", borderColor: n, "& .cui-steps__vertical-step-container": { borderColor: n }, _invalid: { borderColor: "red.400", "& .cui-steps__vertical-step-container": { borderColor: "red.400" } } }, "& .cui-steps__vertical-step-container": { borderInlineStartWidth: 3, py: 2, ps: 3, display: "flex", justifyContent: "space-between", flexDirection: "row-reverse", _invalid: { borderColor: "red.400", "& .cui-steps__vertical-step-container": { borderColor: "red.400" } } }, "& .cui-steps__vertical-step-content": { ps: 0, py: 0 }, "&[data-clickable]:hover": { borderColor: n, cursor: "pointer", "& .cui-steps__vertical-step-container": { borderColor: n } } } }; }), je = { circles: Ve, "circles-alt": De, simple: $e }, Oe = we({ baseStyle: Me, sizes: F, variants: je, defaultProps: { size: "md", colorScheme: "blue", variant: "circles" } }); export { Ge as Step, Se as Steps, Oe as StepsTheme, Je as useSteps };