UNPKG

@veracity/vui

Version:

Veracity UI is a React component library crafted for use within Veracity applications and pages. Based on Styled Components and @xstyled.

159 lines (157 loc) 5.89 kB
import { isReactText, isString } from "../utils/assertion.js"; import { filterUndefined } from "../utils/object.js"; import { cs } from "../utils/styles.js"; import shadows_default from "../theme/foundations/shadows.js"; import { useStyleConfig } from "../core/theme.js"; import styled from "../core/styled.js"; import vui from "../core/vui.js"; import { Box } from "../box/box.js"; import { DismissButton } from "../dismissButton/DismissButton.js"; import { NotificationProvider } from "./context.js"; import { INTENT_ICON_MAP, LOADING_ICON_PROPS, notificationStatusMapping } from "./consts.js"; import { NotificationAction } from "./notificationAction.js"; import { NotificationIcon } from "./notificationIcon.js"; import { NotificationText } from "./notificationText.js"; import { NotificationTitle } from "./notificationTitle.js"; import { DEFAULT_VARIANT, inferNotificationLayout, resolveNotificationAria, resolveNotificationVariant } from "./utils.js"; import { jsx, jsxs } from "react/jsx-runtime"; //#region src/notification/notification.tsx const NotificationContainer = styled(Box)` ${({ $dismissFg }) => $dismissFg && `--vui-dismiss-fg: ${$dismissFg};`} ${` @keyframes linkSwipe { from { background-size: 0 1px; } to { background-size: 100% 1px; } } `} .vui-notificationText a { text-decoration: none; background: linear-gradient(to right, currentColor, currentColor); background-size: 100% 1px; background-position: 0 100%; background-repeat: no-repeat; padding-bottom: 2px; } .vui-notificationText a:hover { animation: linkSwipe 0.5s ease forwards; background-size: 100% 1px; } ${({ $isBanner }) => $isBanner && ` box-shadow: ${shadows_default.md}; position: relative; width: 100%; border: none; `} `; /** * Displays informational content, like text and icon with optional action buttons. * Handles multiple states, like info, error or loading. */ const Notification = vui((props, ref) => { const { action, align, ariaLive, children, className, icon, intent, isLoading, onClose, role, showDismissButton, size, status, statusMapping, text, title, variant: variantProp = DEFAULT_VARIANT, verticalAlign, ...rest } = props; const statuses = { ...notificationStatusMapping, ...statusMapping }; const statusProps = status ? statuses[status] : void 0; const resolvedVariant = variantProp !== "inline" ? variantProp : statusProps?.variant ?? variantProp; const intentFromProps = intent ?? statusProps?.intent; const resolvedIsLoading = isLoading ?? statusProps?.isLoading; const resolvedIntent = resolvedIsLoading && intentFromProps == null ? "info" : intentFromProps; const { themeKey, isBanner } = resolveNotificationVariant(resolvedVariant, resolvedIntent); const layout = inferNotificationLayout({ action, text, title, hasStatus: !!statusProps }); const aria = resolveNotificationAria({ intent: resolvedIntent, isLoading: resolvedIsLoading }); const resolvedRole = role ?? aria.role; const resolvedAriaLive = ariaLive ?? aria.ariaLive; const styles = useStyleConfig("Notification", { variant: themeKey, size }); const autoIconProps = resolvedIsLoading ? LOADING_ICON_PROPS : statuses[status ?? ""]?.iconProps ?? (resolvedIntent ? INTENT_ICON_MAP[resolvedIntent] : void 0); const showIcon = icon !== ""; const iconName = showIcon ? isString(icon) ? icon : !children && autoIconProps?.name || void 0 : void 0; const context = filterUndefined({ size, status, statusMapping, variant: themeKey, intent: resolvedIntent, isLoading: resolvedIsLoading }); context.layout = layout; const resolvedAlign = align ?? (verticalAlign === "center" ? "center" : verticalAlign === "flex-start" ? "top" : void 0); const alignSelf = (resolvedAlign ?? (layout === "one-line" ? "center" : "top")) === "center" ? "center" : "flex-start"; return /* @__PURE__ */ jsx(NotificationProvider, { value: context, children: /* @__PURE__ */ jsxs(NotificationContainer, { borderRadius: "md", borderWidth: 1, className: cs("vui-notification", className), ref, role: resolvedRole, "aria-live": resolvedAriaLive, "data-intent": resolvedIntent, "data-variant": isBanner ? "banner" : "inline", "data-layout": layout, "data-loading": resolvedIsLoading ? "true" : void 0, "data-align": resolvedAlign, w: "fit-content", $dismissFg: styles.container?.["--vui-dismiss-fg"], $isBanner: isBanner, ...styles.container, ...rest, children: [ iconName ? /* @__PURE__ */ jsx(Box, { alignSelf, ...styles.icon, children: /* @__PURE__ */ jsx(NotificationIcon, { ...autoIconProps, name: iconName }) }) : showIcon ? icon : null, children ?? /* @__PURE__ */ jsxs(Box, { column: alignSelf !== "center", flex: 1, ...styles.content, children: [/* @__PURE__ */ jsxs(NotificationText, { children: [ title ? isReactText(title) ? /* @__PURE__ */ jsx(NotificationTitle, { display: alignSelf !== "center" ? "block" : "inline", mb: alignSelf !== "center" && text ? styles.title?.mb : void 0, text: title }) : title : null, title && text && alignSelf === "center" ? " " : null, text ] }), action ? /* @__PURE__ */ jsx(NotificationAction, { children: action }) : null] }), showDismissButton && /* @__PURE__ */ jsx(DismissButton, { alignSelf, "aria-label": "Close", size: "md", onClick: onClose || (() => {}), ...styles.button }) ] }) }); }); Notification.Action = NotificationAction; Notification.Icon = NotificationIcon; Notification.Text = NotificationText; Notification.Title = NotificationTitle; Notification.displayName = "Notification"; //#endregion export { Notification, Notification as default }; globalThis.__vuiVersion__ = "5.3.1" //# sourceMappingURL=notification.js.map