ivt
Version:
Ivt Components Library
324 lines (319 loc) • 13.3 kB
JavaScript
import * as React from 'react';
import { P as Primitive, c as composeEventHandlers } from './index-Dsw02Eup.mjs';
import { c as createContextScope, a as createContext2, u as useComposedRefs } from './index-D4jPaBZ2.mjs';
import { u as useId } from './index-gX0V59dZ.mjs';
import { u as useControllableState } from './index-1toTCGyr.mjs';
import { D as DismissableLayer } from './index-4NpeUekv.mjs';
import { h as hideOthers, R as ReactRemoveScroll, u as useFocusGuards, F as FocusScope } from './index-z4Hk6sF4.mjs';
import { P as Portal$1 } from './index-BksCjWh6.mjs';
import { P as Presence } from './index-DfeRLazC.mjs';
import { createSlot } from '@radix-ui/react-slot';
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
var DIALOG_NAME = "Dialog";
var [createDialogContext, createDialogScope] = createContextScope(DIALOG_NAME);
var [DialogProvider, useDialogContext] = createDialogContext(DIALOG_NAME);
var Dialog = (props)=>{
const { __scopeDialog, children, open: openProp, defaultOpen, onOpenChange, modal = true } = props;
const triggerRef = React.useRef(null);
const contentRef = React.useRef(null);
const [open, setOpen] = useControllableState({
prop: openProp,
defaultProp: defaultOpen ?? false,
onChange: onOpenChange,
caller: DIALOG_NAME
});
return /* @__PURE__ */ jsx(DialogProvider, {
scope: __scopeDialog,
triggerRef,
contentRef,
contentId: useId(),
titleId: useId(),
descriptionId: useId(),
open,
onOpenChange: setOpen,
onOpenToggle: React.useCallback(()=>setOpen((prevOpen)=>!prevOpen), [
setOpen
]),
modal,
children
});
};
Dialog.displayName = DIALOG_NAME;
var TRIGGER_NAME = "DialogTrigger";
var DialogTrigger = React.forwardRef((props, forwardedRef)=>{
const { __scopeDialog, ...triggerProps } = props;
const context = useDialogContext(TRIGGER_NAME, __scopeDialog);
const composedTriggerRef = useComposedRefs(forwardedRef, context.triggerRef);
return /* @__PURE__ */ jsx(Primitive.button, {
type: "button",
"aria-haspopup": "dialog",
"aria-expanded": context.open,
"aria-controls": context.contentId,
"data-state": getState(context.open),
...triggerProps,
ref: composedTriggerRef,
onClick: composeEventHandlers(props.onClick, context.onOpenToggle)
});
});
DialogTrigger.displayName = TRIGGER_NAME;
var PORTAL_NAME = "DialogPortal";
var [PortalProvider, usePortalContext] = createDialogContext(PORTAL_NAME, {
forceMount: void 0
});
var DialogPortal = (props)=>{
const { __scopeDialog, forceMount, children, container } = props;
const context = useDialogContext(PORTAL_NAME, __scopeDialog);
return /* @__PURE__ */ jsx(PortalProvider, {
scope: __scopeDialog,
forceMount,
children: React.Children.map(children, (child)=>/* @__PURE__ */ jsx(Presence, {
present: forceMount || context.open,
children: /* @__PURE__ */ jsx(Portal$1, {
asChild: true,
container,
children: child
})
}))
});
};
DialogPortal.displayName = PORTAL_NAME;
var OVERLAY_NAME = "DialogOverlay";
var DialogOverlay = React.forwardRef((props, forwardedRef)=>{
const portalContext = usePortalContext(OVERLAY_NAME, props.__scopeDialog);
const { forceMount = portalContext.forceMount, ...overlayProps } = props;
const context = useDialogContext(OVERLAY_NAME, props.__scopeDialog);
return context.modal ? /* @__PURE__ */ jsx(Presence, {
present: forceMount || context.open,
children: /* @__PURE__ */ jsx(DialogOverlayImpl, {
...overlayProps,
ref: forwardedRef
})
}) : null;
});
DialogOverlay.displayName = OVERLAY_NAME;
var Slot = createSlot("DialogOverlay.RemoveScroll");
var DialogOverlayImpl = React.forwardRef((props, forwardedRef)=>{
const { __scopeDialog, ...overlayProps } = props;
const context = useDialogContext(OVERLAY_NAME, __scopeDialog);
return(// Make sure `Content` is scrollable even when it doesn't live inside `RemoveScroll`
// ie. when `Overlay` and `Content` are siblings
/* @__PURE__ */ jsx(ReactRemoveScroll, {
as: Slot,
allowPinchZoom: true,
shards: [
context.contentRef
],
children: /* @__PURE__ */ jsx(Primitive.div, {
"data-state": getState(context.open),
...overlayProps,
ref: forwardedRef,
style: {
pointerEvents: "auto",
...overlayProps.style
}
})
}));
});
var CONTENT_NAME = "DialogContent";
var DialogContent = React.forwardRef((props, forwardedRef)=>{
const portalContext = usePortalContext(CONTENT_NAME, props.__scopeDialog);
const { forceMount = portalContext.forceMount, ...contentProps } = props;
const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);
return /* @__PURE__ */ jsx(Presence, {
present: forceMount || context.open,
children: context.modal ? /* @__PURE__ */ jsx(DialogContentModal, {
...contentProps,
ref: forwardedRef
}) : /* @__PURE__ */ jsx(DialogContentNonModal, {
...contentProps,
ref: forwardedRef
})
});
});
DialogContent.displayName = CONTENT_NAME;
var DialogContentModal = React.forwardRef((props, forwardedRef)=>{
const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);
const contentRef = React.useRef(null);
const composedRefs = useComposedRefs(forwardedRef, context.contentRef, contentRef);
React.useEffect(()=>{
const content = contentRef.current;
if (content) return hideOthers(content);
}, []);
return /* @__PURE__ */ jsx(DialogContentImpl, {
...props,
ref: composedRefs,
trapFocus: context.open,
disableOutsidePointerEvents: true,
onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event)=>{
event.preventDefault();
context.triggerRef.current?.focus();
}),
onPointerDownOutside: composeEventHandlers(props.onPointerDownOutside, (event)=>{
const originalEvent = event.detail.originalEvent;
const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;
const isRightClick = originalEvent.button === 2 || ctrlLeftClick;
if (isRightClick) event.preventDefault();
}),
onFocusOutside: composeEventHandlers(props.onFocusOutside, (event)=>event.preventDefault())
});
});
var DialogContentNonModal = React.forwardRef((props, forwardedRef)=>{
const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);
const hasInteractedOutsideRef = React.useRef(false);
const hasPointerDownOutsideRef = React.useRef(false);
return /* @__PURE__ */ jsx(DialogContentImpl, {
...props,
ref: forwardedRef,
trapFocus: false,
disableOutsidePointerEvents: false,
onCloseAutoFocus: (event)=>{
props.onCloseAutoFocus?.(event);
if (!event.defaultPrevented) {
if (!hasInteractedOutsideRef.current) context.triggerRef.current?.focus();
event.preventDefault();
}
hasInteractedOutsideRef.current = false;
hasPointerDownOutsideRef.current = false;
},
onInteractOutside: (event)=>{
props.onInteractOutside?.(event);
if (!event.defaultPrevented) {
hasInteractedOutsideRef.current = true;
if (event.detail.originalEvent.type === "pointerdown") {
hasPointerDownOutsideRef.current = true;
}
}
const target = event.target;
const targetIsTrigger = context.triggerRef.current?.contains(target);
if (targetIsTrigger) event.preventDefault();
if (event.detail.originalEvent.type === "focusin" && hasPointerDownOutsideRef.current) {
event.preventDefault();
}
}
});
});
var DialogContentImpl = React.forwardRef((props, forwardedRef)=>{
const { __scopeDialog, trapFocus, onOpenAutoFocus, onCloseAutoFocus, ...contentProps } = props;
const context = useDialogContext(CONTENT_NAME, __scopeDialog);
const contentRef = React.useRef(null);
const composedRefs = useComposedRefs(forwardedRef, contentRef);
useFocusGuards();
return /* @__PURE__ */ jsxs(Fragment, {
children: [
/* @__PURE__ */ jsx(FocusScope, {
asChild: true,
loop: true,
trapped: trapFocus,
onMountAutoFocus: onOpenAutoFocus,
onUnmountAutoFocus: onCloseAutoFocus,
children: /* @__PURE__ */ jsx(DismissableLayer, {
role: "dialog",
id: context.contentId,
"aria-describedby": context.descriptionId,
"aria-labelledby": context.titleId,
"data-state": getState(context.open),
...contentProps,
ref: composedRefs,
onDismiss: ()=>context.onOpenChange(false)
})
}),
/* @__PURE__ */ jsxs(Fragment, {
children: [
/* @__PURE__ */ jsx(TitleWarning, {
titleId: context.titleId
}),
/* @__PURE__ */ jsx(DescriptionWarning, {
contentRef,
descriptionId: context.descriptionId
})
]
})
]
});
});
var TITLE_NAME = "DialogTitle";
var DialogTitle = React.forwardRef((props, forwardedRef)=>{
const { __scopeDialog, ...titleProps } = props;
const context = useDialogContext(TITLE_NAME, __scopeDialog);
return /* @__PURE__ */ jsx(Primitive.h2, {
id: context.titleId,
...titleProps,
ref: forwardedRef
});
});
DialogTitle.displayName = TITLE_NAME;
var DESCRIPTION_NAME = "DialogDescription";
var DialogDescription = React.forwardRef((props, forwardedRef)=>{
const { __scopeDialog, ...descriptionProps } = props;
const context = useDialogContext(DESCRIPTION_NAME, __scopeDialog);
return /* @__PURE__ */ jsx(Primitive.p, {
id: context.descriptionId,
...descriptionProps,
ref: forwardedRef
});
});
DialogDescription.displayName = DESCRIPTION_NAME;
var CLOSE_NAME = "DialogClose";
var DialogClose = React.forwardRef((props, forwardedRef)=>{
const { __scopeDialog, ...closeProps } = props;
const context = useDialogContext(CLOSE_NAME, __scopeDialog);
return /* @__PURE__ */ jsx(Primitive.button, {
type: "button",
...closeProps,
ref: forwardedRef,
onClick: composeEventHandlers(props.onClick, ()=>context.onOpenChange(false))
});
});
DialogClose.displayName = CLOSE_NAME;
function getState(open) {
return open ? "open" : "closed";
}
var TITLE_WARNING_NAME = "DialogTitleWarning";
var [WarningProvider, useWarningContext] = createContext2(TITLE_WARNING_NAME, {
contentName: CONTENT_NAME,
titleName: TITLE_NAME,
docsSlug: "dialog"
});
var TitleWarning = ({ titleId })=>{
const titleWarningContext = useWarningContext(TITLE_WARNING_NAME);
const MESSAGE = `\`${titleWarningContext.contentName}\` requires a \`${titleWarningContext.titleName}\` for the component to be accessible for screen reader users.
If you want to hide the \`${titleWarningContext.titleName}\`, you can wrap it with our VisuallyHidden component.
For more information, see https://radix-ui.com/primitives/docs/components/${titleWarningContext.docsSlug}`;
React.useEffect(()=>{
if (titleId) {
const hasTitle = document.getElementById(titleId);
if (!hasTitle) console.error(MESSAGE);
}
}, [
MESSAGE,
titleId
]);
return null;
};
var DESCRIPTION_WARNING_NAME = "DialogDescriptionWarning";
var DescriptionWarning = ({ contentRef, descriptionId })=>{
const descriptionWarningContext = useWarningContext(DESCRIPTION_WARNING_NAME);
const MESSAGE = `Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${descriptionWarningContext.contentName}}.`;
React.useEffect(()=>{
const describedById = contentRef.current?.getAttribute("aria-describedby");
if (descriptionId && describedById) {
const hasDescription = document.getElementById(descriptionId);
if (!hasDescription) console.warn(MESSAGE);
}
}, [
MESSAGE,
contentRef,
descriptionId
]);
return null;
};
var Root = Dialog;
var Trigger = DialogTrigger;
var Portal = DialogPortal;
var Overlay = DialogOverlay;
var Content = DialogContent;
var Title = DialogTitle;
var Description = DialogDescription;
var Close = DialogClose;
export { Close as C, Description as D, Overlay as O, Portal as P, Root as R, Title as T, WarningProvider as W, Content as a, Trigger as b, createDialogScope as c };
//# sourceMappingURL=index-CaYwp6E6.mjs.map