import $67UHm$babelruntimehelpersesmextends from "@babel/runtime/helpers/esm/extends"; import {useRef as $67UHm$useRef, createElement as $67UHm$createElement, useCallback as $67UHm$useCallback, forwardRef as $67UHm$forwardRef, Children as $67UHm$Children, useEffect as $67UHm$useEffect, Fragment as $67UHm$Fragment} from "react"; import {composeEventHandlers as $67UHm$composeEventHandlers} from "@radix-ui/primitive"; import {useComposedRefs as $67UHm$useComposedRefs} from "@radix-ui/react-compose-refs"; import {createContextScope as $67UHm$createContextScope, createContext as $67UHm$createContext} from "@radix-ui/react-context"; import {useId as $67UHm$useId} from "@radix-ui/react-id"; import {useControllableState as $67UHm$useControllableState} from "@radix-ui/react-use-controllable-state"; import {DismissableLayer as $67UHm$DismissableLayer} from "@radix-ui/react-dismissable-layer"; import {FocusScope as $67UHm$FocusScope} from "@radix-ui/react-focus-scope"; import {Portal as $67UHm$Portal} from "@radix-ui/react-portal"; import {Presence as $67UHm$Presence} from "@radix-ui/react-presence"; import {Primitive as $67UHm$Primitive} from "@radix-ui/react-primitive"; import {useFocusGuards as $67UHm$useFocusGuards} from "@radix-ui/react-focus-guards"; import {RemoveScroll as $67UHm$RemoveScroll} from "react-remove-scroll"; import {hideOthers as $67UHm$hideOthers} from "aria-hidden"; import {Slot as $67UHm$Slot} from "@radix-ui/react-slot"; /* ------------------------------------------------------------------------------------------------- * Dialog * -----------------------------------------------------------------------------------------------*/ const $5d3850c4d0b4e6c7$var$DIALOG_NAME = 'Dialog'; const [$5d3850c4d0b4e6c7$var$createDialogContext, $5d3850c4d0b4e6c7$export$cc702773b8ea3e41] = $67UHm$createContextScope($5d3850c4d0b4e6c7$var$DIALOG_NAME); const [$5d3850c4d0b4e6c7$var$DialogProvider, $5d3850c4d0b4e6c7$var$useDialogContext] = $5d3850c4d0b4e6c7$var$createDialogContext($5d3850c4d0b4e6c7$var$DIALOG_NAME); const $5d3850c4d0b4e6c7$export$3ddf2d174ce01153 = (props)=>{ const { __scopeDialog: __scopeDialog , children: children , open: openProp , defaultOpen: defaultOpen , onOpenChange: onOpenChange , modal: modal = true } = props; const triggerRef = $67UHm$useRef(null); const contentRef = $67UHm$useRef(null); const [open = false, setOpen] = $67UHm$useControllableState({ prop: openProp, defaultProp: defaultOpen, onChange: onOpenChange }); return /*#__PURE__*/ $67UHm$createElement($5d3850c4d0b4e6c7$var$DialogProvider, { scope: __scopeDialog, triggerRef: triggerRef, contentRef: contentRef, contentId: $67UHm$useId(), titleId: $67UHm$useId(), descriptionId: $67UHm$useId(), open: open, onOpenChange: setOpen, onOpenToggle: $67UHm$useCallback(()=>setOpen((prevOpen)=>!prevOpen ) , [ setOpen ]), modal: modal }, children); }; /*#__PURE__*/ Object.assign($5d3850c4d0b4e6c7$export$3ddf2d174ce01153, { displayName: $5d3850c4d0b4e6c7$var$DIALOG_NAME }); /* ------------------------------------------------------------------------------------------------- * DialogTrigger * -----------------------------------------------------------------------------------------------*/ const $5d3850c4d0b4e6c7$var$TRIGGER_NAME = 'DialogTrigger'; const $5d3850c4d0b4e6c7$export$2e1e1122cf0cba88 = /*#__PURE__*/ $67UHm$forwardRef((props, forwardedRef)=>{ const { __scopeDialog: __scopeDialog , ...triggerProps } = props; const context = $5d3850c4d0b4e6c7$var$useDialogContext($5d3850c4d0b4e6c7$var$TRIGGER_NAME, __scopeDialog); const composedTriggerRef = $67UHm$useComposedRefs(forwardedRef, context.triggerRef); return /*#__PURE__*/ $67UHm$createElement($67UHm$Primitive.button, $67UHm$babelruntimehelpersesmextends({ type: "button", "aria-haspopup": "dialog", "aria-expanded": context.open, "aria-controls": context.contentId, "data-state": $5d3850c4d0b4e6c7$var$getState(context.open) }, triggerProps, { ref: composedTriggerRef, onClick: $67UHm$composeEventHandlers(props.onClick, context.onOpenToggle) })); }); /*#__PURE__*/ Object.assign($5d3850c4d0b4e6c7$export$2e1e1122cf0cba88, { displayName: $5d3850c4d0b4e6c7$var$TRIGGER_NAME }); /* ------------------------------------------------------------------------------------------------- * DialogPortal * -----------------------------------------------------------------------------------------------*/ const $5d3850c4d0b4e6c7$var$PORTAL_NAME = 'DialogPortal'; const [$5d3850c4d0b4e6c7$var$PortalProvider, $5d3850c4d0b4e6c7$var$usePortalContext] = $5d3850c4d0b4e6c7$var$createDialogContext($5d3850c4d0b4e6c7$var$PORTAL_NAME, { forceMount: undefined }); const $5d3850c4d0b4e6c7$export$dad7c95542bacce0 = (props)=>{ const { __scopeDialog: __scopeDialog , forceMount: forceMount , children: children , container: container } = props; const context = $5d3850c4d0b4e6c7$var$useDialogContext($5d3850c4d0b4e6c7$var$PORTAL_NAME, __scopeDialog); return /*#__PURE__*/ $67UHm$createElement($5d3850c4d0b4e6c7$var$PortalProvider, { scope: __scopeDialog, forceMount: forceMount }, $67UHm$Children.map(children, (child)=>/*#__PURE__*/ $67UHm$createElement($67UHm$Presence, { present: forceMount || context.open }, /*#__PURE__*/ $67UHm$createElement($67UHm$Portal, { asChild: true, container: container }, child)) )); }; /*#__PURE__*/ Object.assign($5d3850c4d0b4e6c7$export$dad7c95542bacce0, { displayName: $5d3850c4d0b4e6c7$var$PORTAL_NAME }); /* ------------------------------------------------------------------------------------------------- * DialogOverlay * -----------------------------------------------------------------------------------------------*/ const $5d3850c4d0b4e6c7$var$OVERLAY_NAME = 'DialogOverlay'; const $5d3850c4d0b4e6c7$export$bd1d06c79be19e17 = /*#__PURE__*/ $67UHm$forwardRef((props, forwardedRef)=>{ const portalContext = $5d3850c4d0b4e6c7$var$usePortalContext($5d3850c4d0b4e6c7$var$OVERLAY_NAME, props.__scopeDialog); const { forceMount: forceMount = portalContext.forceMount , ...overlayProps } = props; const context = $5d3850c4d0b4e6c7$var$useDialogContext($5d3850c4d0b4e6c7$var$OVERLAY_NAME, props.__scopeDialog); return context.modal ? /*#__PURE__*/ $67UHm$createElement($67UHm$Presence, { present: forceMount || context.open }, /*#__PURE__*/ $67UHm$createElement($5d3850c4d0b4e6c7$var$DialogOverlayImpl, $67UHm$babelruntimehelpersesmextends({}, overlayProps, { ref: forwardedRef }))) : null; }); /*#__PURE__*/ Object.assign($5d3850c4d0b4e6c7$export$bd1d06c79be19e17, { displayName: $5d3850c4d0b4e6c7$var$OVERLAY_NAME }); const $5d3850c4d0b4e6c7$var$DialogOverlayImpl = /*#__PURE__*/ $67UHm$forwardRef((props, forwardedRef)=>{ const { __scopeDialog: __scopeDialog , ...overlayProps } = props; const context = $5d3850c4d0b4e6c7$var$useDialogContext($5d3850c4d0b4e6c7$var$OVERLAY_NAME, __scopeDialog); return(/*#__PURE__*/ // Make sure `Content` is scrollable even when it doesn't live inside `RemoveScroll` // ie. when `Overlay` and `Content` are siblings $67UHm$createElement($67UHm$RemoveScroll, { as: $67UHm$Slot, allowPinchZoom: true, shards: [ context.contentRef ] }, /*#__PURE__*/ $67UHm$createElement($67UHm$Primitive.div, $67UHm$babelruntimehelpersesmextends({ "data-state": $5d3850c4d0b4e6c7$var$getState(context.open) }, overlayProps, { ref: forwardedRef // We re-enable pointer-events prevented by `Dialog.Content` to allow scrolling the overlay. , style: { pointerEvents: 'auto', ...overlayProps.style } })))); }); /* ------------------------------------------------------------------------------------------------- * DialogContent * -----------------------------------------------------------------------------------------------*/ const $5d3850c4d0b4e6c7$var$CONTENT_NAME = 'DialogContent'; const $5d3850c4d0b4e6c7$export$b6d9565de1e068cf = /*#__PURE__*/ $67UHm$forwardRef((props, forwardedRef)=>{ const portalContext = $5d3850c4d0b4e6c7$var$usePortalContext($5d3850c4d0b4e6c7$var$CONTENT_NAME, props.__scopeDialog); const { forceMount: forceMount = portalContext.forceMount , ...contentProps } = props; const context = $5d3850c4d0b4e6c7$var$useDialogContext($5d3850c4d0b4e6c7$var$CONTENT_NAME, props.__scopeDialog); return /*#__PURE__*/ $67UHm$createElement($67UHm$Presence, { present: forceMount || context.open }, context.modal ? /*#__PURE__*/ $67UHm$createElement($5d3850c4d0b4e6c7$var$DialogContentModal, $67UHm$babelruntimehelpersesmextends({}, contentProps, { ref: forwardedRef })) : /*#__PURE__*/ $67UHm$createElement($5d3850c4d0b4e6c7$var$DialogContentNonModal, $67UHm$babelruntimehelpersesmextends({}, contentProps, { ref: forwardedRef }))); }); /*#__PURE__*/ Object.assign($5d3850c4d0b4e6c7$export$b6d9565de1e068cf, { displayName: $5d3850c4d0b4e6c7$var$CONTENT_NAME }); /* -----------------------------------------------------------------------------------------------*/ const $5d3850c4d0b4e6c7$var$DialogContentModal = /*#__PURE__*/ $67UHm$forwardRef((props, forwardedRef)=>{ const context = $5d3850c4d0b4e6c7$var$useDialogContext($5d3850c4d0b4e6c7$var$CONTENT_NAME, props.__scopeDialog); const contentRef = $67UHm$useRef(null); const composedRefs = $67UHm$useComposedRefs(forwardedRef, context.contentRef, contentRef); // aria-hide everything except the content (better supported equivalent to setting aria-modal) $67UHm$useEffect(()=>{ const content = contentRef.current; if (content) return $67UHm$hideOthers(content); }, []); return /*#__PURE__*/ $67UHm$createElement($5d3850c4d0b4e6c7$var$DialogContentImpl, $67UHm$babelruntimehelpersesmextends({}, props, { ref: composedRefs // we make sure focus isn't trapped once `DialogContent` has been closed , trapFocus: context.open, disableOutsidePointerEvents: true, onCloseAutoFocus: $67UHm$composeEventHandlers(props.onCloseAutoFocus, (event)=>{ var _context$triggerRef$c; event.preventDefault(); (_context$triggerRef$c = context.triggerRef.current) === null || _context$triggerRef$c === void 0 || _context$triggerRef$c.focus(); }), onPointerDownOutside: $67UHm$composeEventHandlers(props.onPointerDownOutside, (event)=>{ const originalEvent = event.detail.originalEvent; const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true; const isRightClick = originalEvent.button === 2 || ctrlLeftClick; // If the event is a right-click, we shouldn't close because // it is effectively as if we right-clicked the `Overlay`. if (isRightClick) event.preventDefault(); }) // When focus is trapped, a `focusout` event may still happen. , onFocusOutside: $67UHm$composeEventHandlers(props.onFocusOutside, (event)=>event.preventDefault() ) })); }); /* -----------------------------------------------------------------------------------------------*/ const $5d3850c4d0b4e6c7$var$DialogContentNonModal = /*#__PURE__*/ $67UHm$forwardRef((props, forwardedRef)=>{ const context = $5d3850c4d0b4e6c7$var$useDialogContext($5d3850c4d0b4e6c7$var$CONTENT_NAME, props.__scopeDialog); const hasInteractedOutsideRef = $67UHm$useRef(false); const hasPointerDownOutsideRef = $67UHm$useRef(false); return /*#__PURE__*/ $67UHm$createElement($5d3850c4d0b4e6c7$var$DialogContentImpl, $67UHm$babelruntimehelpersesmextends({}, props, { ref: forwardedRef, trapFocus: false, disableOutsidePointerEvents: false, onCloseAutoFocus: (event)=>{ var _props$onCloseAutoFoc; (_props$onCloseAutoFoc = props.onCloseAutoFocus) === null || _props$onCloseAutoFoc === void 0 || _props$onCloseAutoFoc.call(props, event); if (!event.defaultPrevented) { var _context$triggerRef$c2; if (!hasInteractedOutsideRef.current) (_context$triggerRef$c2 = context.triggerRef.current) === null || _context$triggerRef$c2 === void 0 || _context$triggerRef$c2.focus(); // Always prevent auto focus because we either focus manually or want user agent focus event.preventDefault(); } hasInteractedOutsideRef.current = false; hasPointerDownOutsideRef.current = false; }, onInteractOutside: (event)=>{ var _props$onInteractOuts, _context$triggerRef$c3; (_props$onInteractOuts = props.onInteractOutside) === null || _props$onInteractOuts === void 0 || _props$onInteractOuts.call(props, event); if (!event.defaultPrevented) { hasInteractedOutsideRef.current = true; if (event.detail.originalEvent.type === 'pointerdown') hasPointerDownOutsideRef.current = true; } // Prevent dismissing when clicking the trigger. // As the trigger is already setup to close, without doing so would // cause it to close and immediately open. const target = event.target; const targetIsTrigger = (_context$triggerRef$c3 = context.triggerRef.current) === null || _context$triggerRef$c3 === void 0 ? void 0 : _context$triggerRef$c3.contains(target); if (targetIsTrigger) event.preventDefault(); // On Safari if the trigger is inside a container with tabIndex={0}, when clicked // we will get the pointer down outside event on the trigger, but then a subsequent // focus outside event on the container, we ignore any focus outside event when we've // already had a pointer down outside event. if (event.detail.originalEvent.type === 'focusin' && hasPointerDownOutsideRef.current) event.preventDefault(); } })); }); /* -----------------------------------------------------------------------------------------------*/ const $5d3850c4d0b4e6c7$var$DialogContentImpl = /*#__PURE__*/ $67UHm$forwardRef((props, forwardedRef)=>{ const { __scopeDialog: __scopeDialog , trapFocus: trapFocus , onOpenAutoFocus: onOpenAutoFocus , onCloseAutoFocus: onCloseAutoFocus , ...contentProps } = props; const context = $5d3850c4d0b4e6c7$var$useDialogContext($5d3850c4d0b4e6c7$var$CONTENT_NAME, __scopeDialog); const contentRef = $67UHm$useRef(null); const composedRefs = $67UHm$useComposedRefs(forwardedRef, contentRef); // Make sure the whole tree has focus guards as our `Dialog` will be // the last element in the DOM (beacuse of the `Portal`) $67UHm$useFocusGuards(); return /*#__PURE__*/ $67UHm$createElement($67UHm$Fragment, null, /*#__PURE__*/ $67UHm$createElement($67UHm$FocusScope, { asChild: true, loop: true, trapped: trapFocus, onMountAutoFocus: onOpenAutoFocus, onUnmountAutoFocus: onCloseAutoFocus }, /*#__PURE__*/ $67UHm$createElement($67UHm$DismissableLayer, $67UHm$babelruntimehelpersesmextends({ role: "dialog", id: context.contentId, "aria-describedby": context.descriptionId, "aria-labelledby": context.titleId, "data-state": $5d3850c4d0b4e6c7$var$getState(context.open) }, contentProps, { ref: composedRefs, onDismiss: ()=>context.onOpenChange(false) }))), false); }); /* ------------------------------------------------------------------------------------------------- * DialogTitle * -----------------------------------------------------------------------------------------------*/ const $5d3850c4d0b4e6c7$var$TITLE_NAME = 'DialogTitle'; const $5d3850c4d0b4e6c7$export$16f7638e4a34b909 = /*#__PURE__*/ $67UHm$forwardRef((props, forwardedRef)=>{ const { __scopeDialog: __scopeDialog , ...titleProps } = props; const context = $5d3850c4d0b4e6c7$var$useDialogContext($5d3850c4d0b4e6c7$var$TITLE_NAME, __scopeDialog); return /*#__PURE__*/ $67UHm$createElement($67UHm$Primitive.h2, $67UHm$babelruntimehelpersesmextends({ id: context.titleId }, titleProps, { ref: forwardedRef })); }); /*#__PURE__*/ Object.assign($5d3850c4d0b4e6c7$export$16f7638e4a34b909, { displayName: $5d3850c4d0b4e6c7$var$TITLE_NAME }); /* ------------------------------------------------------------------------------------------------- * DialogDescription * -----------------------------------------------------------------------------------------------*/ const $5d3850c4d0b4e6c7$var$DESCRIPTION_NAME = 'DialogDescription'; const $5d3850c4d0b4e6c7$export$94e94c2ec2c954d5 = /*#__PURE__*/ $67UHm$forwardRef((props, forwardedRef)=>{ const { __scopeDialog: __scopeDialog , ...descriptionProps } = props; const context = $5d3850c4d0b4e6c7$var$useDialogContext($5d3850c4d0b4e6c7$var$DESCRIPTION_NAME, __scopeDialog); return /*#__PURE__*/ $67UHm$createElement($67UHm$Primitive.p, $67UHm$babelruntimehelpersesmextends({ id: context.descriptionId }, descriptionProps, { ref: forwardedRef })); }); /*#__PURE__*/ Object.assign($5d3850c4d0b4e6c7$export$94e94c2ec2c954d5, { displayName: $5d3850c4d0b4e6c7$var$DESCRIPTION_NAME }); /* ------------------------------------------------------------------------------------------------- * DialogClose * -----------------------------------------------------------------------------------------------*/ const $5d3850c4d0b4e6c7$var$CLOSE_NAME = 'DialogClose'; const $5d3850c4d0b4e6c7$export$fba2fb7cd781b7ac = /*#__PURE__*/ $67UHm$forwardRef((props, forwardedRef)=>{ const { __scopeDialog: __scopeDialog , ...closeProps } = props; const context = $5d3850c4d0b4e6c7$var$useDialogContext($5d3850c4d0b4e6c7$var$CLOSE_NAME, __scopeDialog); return /*#__PURE__*/ $67UHm$createElement($67UHm$Primitive.button, $67UHm$babelruntimehelpersesmextends({ type: "button" }, closeProps, { ref: forwardedRef, onClick: $67UHm$composeEventHandlers(props.onClick, ()=>context.onOpenChange(false) ) })); }); /*#__PURE__*/ Object.assign($5d3850c4d0b4e6c7$export$fba2fb7cd781b7ac, { displayName: $5d3850c4d0b4e6c7$var$CLOSE_NAME }); /* -----------------------------------------------------------------------------------------------*/ function $5d3850c4d0b4e6c7$var$getState(open) { return open ? 'open' : 'closed'; } const $5d3850c4d0b4e6c7$var$TITLE_WARNING_NAME = 'DialogTitleWarning'; const [$5d3850c4d0b4e6c7$export$69b62a49393917d6, $5d3850c4d0b4e6c7$var$useWarningContext] = $67UHm$createContext($5d3850c4d0b4e6c7$var$TITLE_WARNING_NAME, { contentName: $5d3850c4d0b4e6c7$var$CONTENT_NAME, titleName: $5d3850c4d0b4e6c7$var$TITLE_NAME, docsSlug: 'dialog' }); const $5d3850c4d0b4e6c7$var$TitleWarning = ({ titleId: titleId })=>{ const titleWarningContext = $5d3850c4d0b4e6c7$var$useWarningContext($5d3850c4d0b4e6c7$var$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}`; $67UHm$useEffect(()=>{ if (titleId) { const hasTitle = document.getElementById(titleId); if (!hasTitle) throw new Error(MESSAGE); } }, [ MESSAGE, titleId ]); return null; }; const $5d3850c4d0b4e6c7$var$DESCRIPTION_WARNING_NAME = 'DialogDescriptionWarning'; const $5d3850c4d0b4e6c7$var$DescriptionWarning = ({ contentRef: contentRef , descriptionId: descriptionId })=>{ const descriptionWarningContext = $5d3850c4d0b4e6c7$var$useWarningContext($5d3850c4d0b4e6c7$var$DESCRIPTION_WARNING_NAME); const MESSAGE = `Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${descriptionWarningContext.contentName}}.`; $67UHm$useEffect(()=>{ var _contentRef$current; const describedById = (_contentRef$current = contentRef.current) === null || _contentRef$current === void 0 ? void 0 : _contentRef$current.getAttribute('aria-describedby'); // if we have an id and the user hasn't set aria-describedby={undefined} if (descriptionId && describedById) { const hasDescription = document.getElementById(descriptionId); if (!hasDescription) console.warn(MESSAGE); } }, [ MESSAGE, contentRef, descriptionId ]); return null; }; const $5d3850c4d0b4e6c7$export$be92b6f5f03c0fe9 = $5d3850c4d0b4e6c7$export$3ddf2d174ce01153; const $5d3850c4d0b4e6c7$export$41fb9f06171c75f4 = $5d3850c4d0b4e6c7$export$2e1e1122cf0cba88; const $5d3850c4d0b4e6c7$export$602eac185826482c = $5d3850c4d0b4e6c7$export$dad7c95542bacce0; const $5d3850c4d0b4e6c7$export$c6fdb837b070b4ff = $5d3850c4d0b4e6c7$export$bd1d06c79be19e17; const $5d3850c4d0b4e6c7$export$7c6e2c02157bb7d2 = $5d3850c4d0b4e6c7$export$b6d9565de1e068cf; const $5d3850c4d0b4e6c7$export$f99233281efd08a0 = $5d3850c4d0b4e6c7$export$16f7638e4a34b909; const $5d3850c4d0b4e6c7$export$393edc798c47379d = $5d3850c4d0b4e6c7$export$94e94c2ec2c954d5; const $5d3850c4d0b4e6c7$export$f39c2d165cd861fe = $5d3850c4d0b4e6c7$export$fba2fb7cd781b7ac; export {$5d3850c4d0b4e6c7$export$cc702773b8ea3e41 as createDialogScope, $5d3850c4d0b4e6c7$export$3ddf2d174ce01153 as Dialog, $5d3850c4d0b4e6c7$export$2e1e1122cf0cba88 as DialogTrigger, $5d3850c4d0b4e6c7$export$dad7c95542bacce0 as DialogPortal, $5d3850c4d0b4e6c7$export$bd1d06c79be19e17 as DialogOverlay, $5d3850c4d0b4e6c7$export$b6d9565de1e068cf as DialogContent, $5d3850c4d0b4e6c7$export$16f7638e4a34b909 as DialogTitle, $5d3850c4d0b4e6c7$export$94e94c2ec2c954d5 as DialogDescription, $5d3850c4d0b4e6c7$export$fba2fb7cd781b7ac as DialogClose, $5d3850c4d0b4e6c7$export$be92b6f5f03c0fe9 as Root, $5d3850c4d0b4e6c7$export$41fb9f06171c75f4 as Trigger, $5d3850c4d0b4e6c7$export$602eac185826482c as Portal, $5d3850c4d0b4e6c7$export$c6fdb837b070b4ff as Overlay, $5d3850c4d0b4e6c7$export$7c6e2c02157bb7d2 as Content, $5d3850c4d0b4e6c7$export$f99233281efd08a0 as Title, $5d3850c4d0b4e6c7$export$393edc798c47379d as Description, $5d3850c4d0b4e6c7$export$f39c2d165cd861fe as Close, $5d3850c4d0b4e6c7$export$69b62a49393917d6 as WarningProvider}; //# sourceMappingURL=index.mjs.map