@liveblocks/react-ui
Version:
A set of React pre-built components for the Liveblocks products. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.
124 lines (121 loc) • 4.05 kB
JavaScript
import { jsx } from 'react/jsx-runtime';
import { Slot } from '@radix-ui/react-slot';
import { createContext, forwardRef, useId, useContext, useRef, useEffect, useImperativeHandle } from 'react';
import { useControllableState } from '../../utils/use-controllable-state.js';
const COLLAPSIBLE_ROOT_NAME = "CollapsibleRoot";
const COLLAPSIBLE_TRIGGER_NAME = "CollapsibleTrigger";
const COLLAPSIBLE_CONTENT_NAME = "CollapsibleContent";
const CollapsibleContext = createContext(null);
const CollapsibleRoot = forwardRef(
({
open: controlledOpen,
onOpenChange: controlledOnOpenChange,
defaultOpen,
disabled = false,
asChild,
...props
}, forwardedRef) => {
const [isOpen, onOpenChange] = useControllableState(
defaultOpen ?? true,
controlledOpen,
controlledOnOpenChange
);
const Component = asChild ? Slot : "div";
const id = useId();
return /* @__PURE__ */ jsx(CollapsibleContext.Provider, {
value: { open: isOpen, onOpenChange, disabled, contentId: id },
children: /* @__PURE__ */ jsx(Component, {
...props,
ref: forwardedRef,
"data-state": isOpen ? "open" : "closed",
"data-disabled": disabled ? "" : void 0
})
});
}
);
const CollapsibleTrigger = forwardRef(
({ onClick, asChild, ...props }, forwardedRef) => {
const Component = asChild ? Slot : "button";
const context = useContext(CollapsibleContext);
if (!context) {
throw new Error("Collapsible.Root is missing from the React tree.");
}
const { open, disabled, contentId, onOpenChange } = context;
return /* @__PURE__ */ jsx(Component, {
...props,
ref: forwardedRef,
type: "button",
"aria-controls": contentId,
"aria-expanded": open || false,
"data-state": open ? "open" : "closed",
"data-disabled": disabled ? "" : void 0,
disabled,
onClick: (event) => {
onClick?.(event);
if (event.defaultPrevented)
return;
if (disabled)
return;
onOpenChange(!open);
}
});
}
);
const CollapsibleContent = forwardRef(
({ asChild, ...props }, forwardedRef) => {
const Component = asChild ? Slot : "div";
const context = useContext(CollapsibleContext);
const divRef = useRef(null);
if (!context) {
throw new Error("Collapsible.Root is missing from the React tree.");
}
const { open, onOpenChange, disabled, contentId } = context;
useEffect(() => {
const element = divRef.current;
if (element === null)
return;
const isHiddenUntilFoundSupported = "onbeforematch" in document.body;
if (!isHiddenUntilFoundSupported)
return;
function handleBeforeMatch() {
onOpenChange(true);
}
element.addEventListener("beforematch", handleBeforeMatch);
return () => {
element.removeEventListener("beforematch", handleBeforeMatch);
};
}, [onOpenChange]);
useEffect(() => {
const element = divRef.current;
if (element === null)
return;
if (open)
return;
const isHiddenUntilFoundSupported = "onbeforematch" in document.body;
if (!isHiddenUntilFoundSupported)
return;
element.setAttribute("hidden", "until-found");
return () => {
element.removeAttribute("hidden");
};
}, [open]);
useImperativeHandle(forwardedRef, () => {
return divRef.current;
}, []);
return /* @__PURE__ */ jsx(Component, {
...props,
ref: divRef,
"data-state": open ? "open" : "closed",
"data-disabled": disabled ? "" : void 0,
id: contentId,
hidden: !open
});
}
);
if (process.env.NODE_ENV !== "production") {
CollapsibleContent.displayName = COLLAPSIBLE_CONTENT_NAME;
CollapsibleRoot.displayName = COLLAPSIBLE_ROOT_NAME;
CollapsibleTrigger.displayName = COLLAPSIBLE_TRIGGER_NAME;
}
export { CollapsibleContent as Content, CollapsibleRoot as Root, CollapsibleTrigger as Trigger };
//# sourceMappingURL=index.js.map