UNPKG

@stratakit/structures

Version:

Medium-sized component structures for the Strata design system

206 lines (205 loc) 5.69 kB
import { c as _c } from "react-compiler-runtime"; import { jsx, jsxs } from "react/jsx-runtime"; import * as React from "react"; import { Role } from "@ariakit/react/role"; import { IconButton, Text } from "@stratakit/bricks"; import { GhostAligner } from "@stratakit/bricks/secret-internals"; import { Icon } from "@stratakit/foundations"; import { forwardRef, useSafeContext } from "@stratakit/foundations/secret-internals"; import cx from "classnames"; import { createStore, useStore } from "zustand"; import { combine } from "zustand/middleware"; import { Dismiss, StatusIcon } from "./~utils.icons.js"; import { useInit } from "./~utils.useInit.js"; function createBannerStore(initialState) { return createStore(combine(initialState, (set, _, store) => ({ setLabelId: (labelId) => { set({ labelId: labelId || store.getInitialState().labelId }); } }))); } const BannerContext = React.createContext(void 0); function BannerProvider(props) { const $ = _c(9); const { tone } = props; let t0; if ($[0] !== tone) { t0 = () => createBannerStore({ tone }); $[0] = tone; $[1] = t0; } else { t0 = $[1]; } const [store] = React.useState(t0); let t1; let t2; if ($[2] !== store || $[3] !== tone) { t1 = function synchronizeWithProps() { store.setState({ tone }); }; t2 = [store, tone]; $[2] = store; $[3] = tone; $[4] = t1; $[5] = t2; } else { t1 = $[4]; t2 = $[5]; } React.useEffect(t1, t2); let t3; if ($[6] !== props.children || $[7] !== store) { t3 = jsx(BannerContext.Provider, { value: store, children: props.children }); $[6] = props.children; $[7] = store; $[8] = t3; } else { t3 = $[8]; } return t3; } function useBannerState(selectorFn) { const store = useSafeContext(BannerContext); return useStore(store, selectorFn); } const BannerRoot = forwardRef((props, forwardedRef) => { useInit(); const { tone = "neutral", variant = "outline", ...rest } = props; return /* @__PURE__ */ jsx(BannerProvider, { tone, children: /* @__PURE__ */ jsx(Role, { ...rest, "data-_sk-tone": tone, "data-_sk-variant": variant, className: cx("\u{1F95D}Banner", props.className), ref: forwardedRef }) }); }); const BannerIcon = forwardRef((props, forwardedRef) => { const tone = useBannerState((state) => state.tone); const hasDefaultIcon = props.href === void 0 && tone !== "neutral"; const { render = hasDefaultIcon ? /* @__PURE__ */ jsx(StatusIcon, { tone }) : void 0, ...rest } = props; return /* @__PURE__ */ jsx(Icon, { ...rest, render, className: cx("\u{1F95D}BannerIcon", props.className), ref: forwardedRef }); }); const BannerLabel = forwardRef((props, forwardedRef) => { const defaultLabelId = React.useId(); const labelId = useBannerState((state) => state.labelId); const setLabelId = useBannerState((state_0) => state_0.setLabelId); const id = props.id ?? defaultLabelId; React.useEffect(() => { setLabelId(id); return () => setLabelId(void 0); }, [setLabelId, id]); return /* @__PURE__ */ jsx(Text, { id: labelId, render: /* @__PURE__ */ jsx("span", {}), ...props, className: cx("\u{1F95D}BannerLabel", props.className), variant: "body-sm", ref: forwardedRef }); }); const BannerMessage = forwardRef((props, forwardedRef) => { return /* @__PURE__ */ jsx(Text, { ...props, variant: "body-sm", className: cx("\u{1F95D}BannerMessage", props.className), ref: forwardedRef }); }); const BannerActions = forwardRef((props, forwardedRef) => { return /* @__PURE__ */ jsx(Role.div, { ...props, className: cx("\u{1F95D}BannerActions", props.className), ref: forwardedRef }); }); const BannerDismissButton = forwardRef((props, forwardedRef) => { const { label = "Dismiss", ...rest } = props; const labelId = useBannerState((state) => state.labelId); const defaultId = React.useId(); const id = props.id ?? defaultId; return /* @__PURE__ */ jsx(GhostAligner, { align: "block", children: /* @__PURE__ */ jsx(IconButton, { ...rest, id, className: cx("\u{1F95D}BannerDismissButton", props.className), variant: "ghost", label, "aria-labelledby": `${id} ${labelId || ""}`, icon: /* @__PURE__ */ jsx(Dismiss, {}), ref: forwardedRef }) }); }); const Banner = forwardRef((props, forwardedRef) => { useInit(); const { message, label, actions, onDismiss, icon, tone = "neutral", ...rest } = props; const shouldRenderIcon = React.useMemo(() => icon !== void 0 || tone !== "neutral", [icon, tone]); return /* @__PURE__ */ jsxs(BannerRoot, { tone, ...rest, ref: forwardedRef, children: [shouldRenderIcon ? /* @__PURE__ */ jsx(BannerIcon, { href: typeof icon === "string" ? icon : void 0, render: React.isValidElement(icon) ? icon : void 0 }) : null, /* @__PURE__ */ jsx(BannerLabel, { render: React.isValidElement(label) ? label : void 0, children: label }), /* @__PURE__ */ jsx(BannerMessage, { children: message }), actions != null ? /* @__PURE__ */ jsx(BannerActions, { children: actions }) : null, onDismiss ? /* @__PURE__ */ jsx(BannerDismissButton, { onClick: onDismiss }) : null] }); }); var Banner_default = Banner; export { BannerActions as Actions, BannerDismissButton as DismissButton, BannerIcon as Icon, BannerLabel as Label, BannerMessage as Message, BannerRoot as Root, Banner_default as default };