@stratakit/structures
Version:
Medium-sized component structures for the Strata design system
206 lines (205 loc) • 5.69 kB
JavaScript
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
};