UNPKG

@stratakit/structures

Version:

Medium-sized component structures for the Strata design system

171 lines (170 loc) 5.64 kB
import { Fragment, jsx, jsxs } from "react/jsx-runtime"; import * as React from "react"; import { Collection, CollectionItem, useCollectionStore } from "@ariakit/react/collection"; import { Dialog, DialogDisclosure, DialogProvider } from "@ariakit/react/dialog"; import { Role } from "@ariakit/react/role"; import { useStoreState } from "@ariakit/react/store"; import { Button, Text, VisuallyHidden } from "@stratakit/bricks"; import { IconButtonPresentation } from "@stratakit/bricks/secret-internals"; import { forwardRef, useControlledState } from "@stratakit/foundations/secret-internals"; import cx from "classnames"; import { ChevronDown, StatusIcon } from "./~utils.icons.js"; const ErrorRegionRoot = forwardRef( (props, forwardedRef) => { const { label, items, open: openProp, setOpen: setOpenProp, ...rest } = props; const labelId = React.useId(); const sectionLabelledBy = props["aria-labelledby"] ?? (props["aria-label"] ? void 0 : labelId); const [open, setOpen] = useControlledState( false, openProp, setOpenProp ); const containerRef = React.useRef(null); const pulse = () => { const el = containerRef.current; if (!el) return; const id = "--\u{1F95D}error-region-pulse"; const animations = el.getAnimations({ subtree: true }); if (animations.find((animation) => animation.id === id)) return; el.animate( [ { boxShadow: "0 0 0 0 var(--stratakit-color-border-attention-base)", opacity: 1 }, { boxShadow: "0 0 15px 2px var(--stratakit-color-border-attention-base)", opacity: 0.7, offset: 0.5 }, { boxShadow: "0 0 0 0 var(--stratakit-color-border-attention-base)", opacity: 1 } ], { id, duration: 600, easing: "cubic-bezier(0.4, 0, 0.2, 1)", pseudoElement: "::before" } ); }; const store = useCollectionStore({ setItems: (newItems) => { const prevItemsSet = new Set(prevItems.map((item) => item.id)); const addedItems = newItems.filter( (item) => !prevItemsSet.has(item.id) ); if (addedItems.length === 0) return; pulse(); setLiveLabel(label); } }); const prevItems = useStoreState(store, "items"); const [liveLabel, setLiveLabel] = React.useState(label); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "polite", "aria-atomic": true, children: liveLabel === label ? liveLabel : void 0 }), /* @__PURE__ */ jsx(DialogProvider, { open, setOpen, children: /* @__PURE__ */ jsx( Role.section, { ...rest, "aria-labelledby": sectionLabelledBy, className: cx("\u{1F95D}-error-region", props.className), "data-kiwi-visible": !!label, "data-kiwi-expanded": open, ref: forwardedRef, children: /* @__PURE__ */ jsxs("div", { className: "\u{1F95D}-error-region-container", ref: containerRef, children: [ /* @__PURE__ */ jsxs( DialogDisclosure, { className: "\u{1F95D}-error-region-header", render: /* @__PURE__ */ jsx(Button, { variant: "ghost" }), children: [ /* @__PURE__ */ jsx(StatusIcon, { tone: "attention", className: "\u{1F95D}-error-region-icon" }), /* @__PURE__ */ jsx( Text, { render: /* @__PURE__ */ jsx("span", {}), id: labelId, className: "\u{1F95D}-error-region-label", variant: "body-sm", children: label } ), /* @__PURE__ */ jsx(IconButtonPresentation, { inert: true, variant: "ghost", children: /* @__PURE__ */ jsx(ChevronDown, {}) }) ] } ), /* @__PURE__ */ jsx( Dialog, { className: "\u{1F95D}-error-region-dialog", portal: false, modal: false, autoFocusOnShow: false, "aria-labelledby": labelId, children: /* @__PURE__ */ jsx( Collection, { store, className: "\u{1F95D}-error-region-items", role: "list", children: items } ) } ) ] }) } ) }) ] }); } ); DEV: ErrorRegionRoot.displayName = "ErrorRegion.Root"; const ErrorRegionItem = forwardRef( (props, forwardedRef) => { const generatedId = React.useId(); const { message, messageId = `${generatedId}-message`, actions, ...rest } = props; return /* @__PURE__ */ jsxs( CollectionItem, { ...rest, role: "listitem", className: cx("\u{1F95D}-error-region-item", props.className), ref: forwardedRef, children: [ /* @__PURE__ */ jsx(Text, { id: messageId, variant: "body-sm", children: message }), /* @__PURE__ */ jsx("div", { className: "\u{1F95D}-error-region-item-actions", children: actions }) ] } ); } ); DEV: ErrorRegionItem.displayName = "ErrorRegion.Item"; export { ErrorRegionItem as Item, ErrorRegionRoot as Root };