@sproutsocial/seeds-react-drawer 1.2.11 → 2.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/drawer.css +248 -0
- package/dist/esm/index.js +599 -189
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +109 -19
- package/dist/index.d.ts +109 -19
- package/dist/index.js +607 -191
- package/dist/index.js.map +1 -1
- package/package.json +24 -12
- package/.eslintignore +0 -6
- package/.eslintrc.js +0 -4
- package/.turbo/turbo-build.log +0 -21
- package/CHANGELOG.md +0 -350
- package/jest.config.js +0 -9
- package/src/Drawer.stories.tsx +0 -474
- package/src/Drawer.tsx +0 -291
- package/src/DrawerTypes.ts +0 -88
- package/src/__tests__/Drawer.test.tsx +0 -339
- package/src/__tests__/Drawer.typetest.tsx +0 -39
- package/src/index.ts +0 -5
- package/src/styles.ts +0 -35
- package/tsconfig.json +0 -15
- package/tsup.config.ts +0 -12
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Drawer.tsx","../../src/styles.ts","../../src/DrawerTypes.ts","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport { useContext, useEffect, useRef } from \"react\";\nimport FocusLock from \"react-focus-lock\";\nimport { motion, AnimatePresence } from \"motion/react\";\nimport { MOTION_DURATION_MEDIUM } from \"@sproutsocial/seeds-motion/unitless\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\n// eslint-disable-next-line import/no-deprecated\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport Portal from \"@sproutsocial/seeds-react-portal\";\nimport Container, { Content } from \"./styles\";\nimport type {\n TypeDrawerContext,\n TypeDrawerCloseButtonProps,\n TypeDrawerHeaderProps,\n TypeDrawerProps,\n TypeInnerDrawerProps,\n TypeDrawerContentProps,\n TypeUseCloseOnBodyClickProps,\n} from \"./DrawerTypes\";\n\nconst MotionContainer = motion(Container as any);\n\nconst doesRefContainEventTarget = (\n ref: { current: { contains: (arg0: any) => any } },\n event: Event\n) => {\n return (\n ref.current &&\n event.target instanceof Node &&\n ref.current.contains(event.target)\n );\n};\n\nexport const DrawerContext = React.createContext<TypeDrawerContext>({\n isLocked: false,\n setIsLocked: () => {},\n});\n\nconst DrawerCloseButton = (props: TypeDrawerCloseButtonProps) => {\n const drawerContext = useContext(DrawerContext);\n\n if (props.render) {\n return props.render(drawerContext) ?? null;\n }\n\n return (\n <Button\n appearance=\"pill\"\n aria-label={drawerContext.closeButtonLabel}\n onClick={drawerContext.onClose}\n {...props}\n >\n {props.children || <Icon aria-hidden name=\"x-outline\" />}\n </Button>\n );\n};\n\nconst DrawerHeader = ({\n title = \"\",\n id = undefined,\n children,\n render,\n ...rest\n}: TypeDrawerHeaderProps) => {\n const drawerContext = useContext(DrawerContext);\n\n if (render) {\n return render(drawerContext);\n }\n\n return (\n <Box\n display=\"flex\"\n flex=\"0 0 auto\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n pt={400}\n px={450}\n {...rest}\n >\n {children || (\n <React.Fragment>\n <Text\n as=\"h2\"\n fontSize={400}\n fontWeight=\"semibold\"\n color=\"text.headline\"\n id={id}\n >\n {title}\n </Text>\n <DrawerCloseButton />\n </React.Fragment>\n )}\n </Box>\n );\n};\n\nconst DrawerContent = ({ children, ...rest }: TypeDrawerContentProps) => (\n <Content height=\"100%\" p={450} color=\"text.body\" {...rest}>\n {children}\n </Content>\n);\n\nconst useCloseOnBodyClick = ({\n isOpen,\n ref,\n disableCloseOnClickOutside,\n onClose,\n closeTargets,\n}: TypeUseCloseOnBodyClickProps) => {\n const { isLocked } = useContext(DrawerContext);\n\n useEffect(() => {\n const documentBody = document.body;\n\n if (!documentBody || !isOpen) {\n return;\n }\n\n const onEsc = (event: KeyboardEvent): void => {\n if (!isLocked && event.key === \"Escape\") {\n onClose();\n }\n };\n\n const bodyClick = (event: Event): void => {\n if (\n // @ts-ignore I'm not sure how to type this ref properly\n !doesRefContainEventTarget(ref, event) &&\n !disableCloseOnClickOutside\n ) {\n onClose();\n }\n };\n\n documentBody?.addEventListener(\"keydown\", onEsc, { capture: true });\n\n if (closeTargets) {\n closeTargets.forEach((targetElement) =>\n targetElement?.addEventListener(\"click\", bodyClick, { capture: true })\n );\n } else {\n documentBody.firstElementChild?.addEventListener(\"click\", bodyClick, {\n capture: true,\n });\n }\n\n return () => {\n documentBody?.removeEventListener(\"keydown\", onEsc, { capture: true });\n\n if (closeTargets) {\n closeTargets.forEach((targetElement) =>\n targetElement?.removeEventListener(\"click\", bodyClick, {\n capture: true,\n })\n );\n } else {\n documentBody.firstElementChild?.removeEventListener(\n \"click\",\n bodyClick,\n { capture: true }\n );\n }\n };\n }, [\n onClose,\n disableCloseOnClickOutside,\n closeTargets,\n ref,\n isLocked,\n isOpen,\n ]);\n};\n\nconst Drawer = ({\n id,\n offset,\n direction,\n children,\n disableCloseOnClickOutside,\n onClose,\n zIndex,\n closeTargets,\n width,\n focusLockExemptCheck,\n isOpen,\n ...rest\n}: TypeInnerDrawerProps) => {\n const ref = useRef(null);\n useCloseOnBodyClick({\n ref,\n disableCloseOnClickOutside,\n onClose,\n closeTargets,\n isOpen,\n });\n\n const offset_x = width * (direction === \"left\" ? -1 : 1);\n\n return (\n <FocusLock\n key={id}\n autoFocus={true}\n disabled={!isOpen}\n returnFocus\n whiteList={\n focusLockExemptCheck ? (e) => !focusLockExemptCheck(e) : undefined\n }\n >\n <AnimatePresence>\n {isOpen && (\n <MotionContainer\n ref={ref}\n style={{ zIndex }}\n width={width}\n offset={offset}\n direction={direction}\n data-qa-drawer={id}\n role=\"dialog\"\n initial={{ opacity: 0, x: offset_x }}\n animate={{ opacity: 1, x: 0 }}\n exit={{ opacity: 0, x: offset_x }}\n transition={{ duration: MOTION_DURATION_MEDIUM }}\n {...rest}\n >\n {children}\n </MotionContainer>\n )}\n </AnimatePresence>\n </FocusLock>\n );\n};\n\nconst DrawerContainer = ({\n children,\n closeButtonLabel,\n direction = \"right\",\n disableCloseOnClickOutside = false,\n id,\n isOpen,\n offset = 0,\n onClose,\n zIndex = 7,\n closeTargets = [],\n width = 600,\n ...rest\n}: TypeDrawerProps) => {\n const [isLocked, setIsLocked] = React.useState(false);\n return (\n <Portal id={id}>\n <DrawerContext.Provider\n value={{\n onClose,\n closeButtonLabel,\n isLocked,\n setIsLocked,\n }}\n >\n <Drawer\n isOpen={isOpen}\n id={id}\n offset={offset}\n direction={direction}\n disableCloseOnClickOutside={disableCloseOnClickOutside}\n onClose={onClose}\n zIndex={zIndex}\n closeTargets={closeTargets}\n width={width}\n data-qa-drawer={id || \"\"}\n data-qa-drawer-isopen={isOpen}\n {...rest}\n >\n {children}\n </Drawer>\n </DrawerContext.Provider>\n </Portal>\n );\n};\n\nDrawerHeader.displayName = \"Drawer.Header\";\nDrawerContent.displayName = \"Drawer.Content\";\nDrawerCloseButton.displayName = \"Drawer.CloseButton\";\n\nDrawerContainer.Header = DrawerHeader;\nDrawerContainer.Content = DrawerContent;\nDrawerContainer.CloseButton = DrawerCloseButton;\n\nexport default DrawerContainer;\n","import type { TypeDrawerProps } from \"./DrawerTypes\";\nimport styled, { css } from \"styled-components\";\nimport { COMMON } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeSystemCommonProps } from \"@sproutsocial/seeds-react-system-props\";\n\nimport Box from \"@sproutsocial/seeds-react-box\";\n\nexport const Content = styled(Box)`\n overflow-y: auto;\n`;\n\ninterface ContainerType\n extends Pick<TypeDrawerProps, \"offset\" | \"direction\">,\n TypeSystemCommonProps {\n width: number;\n}\n\nconst Container = styled.div<ContainerType>`\n display: flex;\n flex-direction: column;\n position: fixed;\n top: 0;\n height: 100%;\n width: ${(props) => props.width}px;\n background-color: ${(props) => props.theme.colors.container.background.base};\n box-shadow: ${(props) => props.theme.shadows.high};\n filter: blur(0);\n\n ${(props) => css`\n ${props.direction}: ${props.offset}px;\n `}\n\n ${COMMON}\n`;\nexport default Container;\n","import * as React from \"react\";\nimport type {\n TypeSystemCommonProps,\n TypeStyledComponentsCommonProps,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeBoxProps } from \"@sproutsocial/seeds-react-box\";\nimport type { TypeButtonProps } from \"@sproutsocial/seeds-react-button\";\n\ntype DrawerAnimationDirection = \"left\" | \"right\";\n\nexport interface TypeDrawerContext {\n /** Callback for close button */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onClose?: () => any;\n\n /** aria-label for drawer close button */\n closeButtonLabel?: string;\n /**\n * isLocked and setIsLocked are used when a Drawer contains other components (like Menu) that also\n * listen for Escape key events. By locking the Drawer, we can prevent conflicts\n * where multiple components try to handle the same keydown event.\n */\n isLocked: boolean;\n setIsLocked: (locked: boolean) => void;\n}\n// TODO: Should the render prop be a React.FC?\nexport interface TypeDrawerCloseButtonProps\n extends Omit<TypeButtonProps, \"children\"> {\n /** An optional function that receives the context of the parent drawer as an argument. Can be used to customize the on-close behavior. */\n render?: React.FC<TypeDrawerContext>;\n children?: React.ReactNode;\n}\n\nexport interface TypeDrawerHeaderProps extends TypeBoxProps {\n title?: string;\n children?: React.ReactNode;\n\n /** An optional function that receives the context of the parent drawer as an argument. Can be used to customize the appearance of the header. */\n render?: React.FC<TypeDrawerContext>;\n}\n\nexport interface TypeInnerDrawerProps\n extends Omit<TypeDrawerProps, \"closeButtonLabel\"> {\n width: number;\n direction: DrawerAnimationDirection;\n}\n\ntype useBodyClicksProps = Pick<\n TypeDrawerProps,\n \"closeTargets\" | \"onClose\" | \"disableCloseOnClickOutside\"\n>;\n\nexport interface TypeUseCloseOnBodyClickProps\n extends Pick<\n TypeDrawerProps,\n \"closeTargets\" | \"onClose\" | \"disableCloseOnClickOutside\"\n > {\n ref?: React.RefObject<HTMLElement | null>;\n isOpen: boolean;\n}\n\nexport interface TypeDrawerProps\n extends TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n Omit<React.ComponentPropsWithoutRef<\"nav\">, \"color\"> {\n children: React.ReactNode;\n\n /** Label for the close button. Usually this should be \"Close\" */\n closeButtonLabel: string;\n\n /** Whether the drawer slides in from the left or right side of the screen */\n direction?: DrawerAnimationDirection;\n\n /** In some cases, you may not want the user to be able to click outside of the drawer to close it. You can disable that with this prop. */\n disableCloseOnClickOutside?: boolean;\n id: string;\n isOpen: boolean;\n offset?: number;\n onClose: () => void;\n zIndex?: number;\n closeTargets?: Array<Element>;\n width?: number;\n focusLockExemptCheck?: (element: HTMLElement) => boolean;\n}\n\nexport interface TypeDrawerContentProps extends TypeBoxProps {\n children?: React.ReactNode;\n}\n","import Drawer, { DrawerContext } from \"./Drawer\";\n\nexport default Drawer;\nexport { Drawer, DrawerContext };\nexport * from \"./DrawerTypes\";\n"],"mappings":"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","names":["Box","Box"]}
|
|
1
|
+
{"version":3,"sources":["../../src/DrawerHybrid.tsx","../../src/DrawerStyled.tsx","../../src/styles.ts","../../src/ActionRail/ActionRail.tsx","../../src/ActionRail/ActionRailButton.tsx","../../src/DrawerShared.tsx","../../src/DrawerTailwind.tsx","../../src/Drawer.tsx","../../src/DrawerTypes.ts","../../src/index.ts"],"sourcesContent":["/**\n * Hybrid Drawer component.\n * Automatically chooses between the Tailwind shell (preferred) and the\n * styled-components shell based on props, mirroring `ButtonHybrid`. When a\n * consumer passes styled-system props (`px`, `color`, `height`, …) the styled\n * path is used so existing styling keeps working; otherwise the Tailwind path\n * renders.\n */\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport DrawerStyled from \"./DrawerStyled\";\nimport DrawerTailwind from \"./DrawerTailwind\";\nimport {\n DrawerHeader,\n DrawerContent,\n DrawerCloseButton,\n} from \"./DrawerShared\";\nimport type { TypeDrawerProps } from \"./DrawerTypes\";\n\n// Props the Drawer owns semantically. They must be stripped before the\n// `hasStyledProps` check so a Drawer-specific prop never trips the styled\n// router — most importantly `width`, which `hasStyledProps` also treats as a\n// styled-system prop. Anything left in `rest` is a true pass-through/system\n// prop and is what the routing decision is based on.\nconst DRAWER_OWN_PROPS: readonly string[] = [\n \"children\",\n \"closeButtonLabel\",\n \"direction\",\n \"disableCloseOnClickOutside\",\n \"id\",\n \"modal\",\n \"open\",\n \"offset\",\n \"onClose\",\n \"zIndex\",\n \"width\",\n \"snapPoints\",\n \"defaultSnapPoint\",\n \"snapPoint\",\n \"onSnapPointChange\",\n \"snapToSequentialPoints\",\n \"actions\",\n \"actionsInHeader\",\n];\n\nconst DrawerHybrid = (props: TypeDrawerProps) => {\n const rest: Record<string, unknown> = {};\n for (const key of Object.keys(props)) {\n if (!DRAWER_OWN_PROPS.includes(key)) {\n rest[key] = (props as unknown as Record<string, unknown>)[key];\n }\n }\n\n if (hasStyledProps(rest)) {\n return <DrawerStyled {...props} />;\n }\n\n // Use the Tailwind version (preferred - better performance).\n return <DrawerTailwind {...props} />;\n};\n\nDrawerHybrid.Header = DrawerHeader;\nDrawerHybrid.Content = DrawerContent;\nDrawerHybrid.CloseButton = DrawerCloseButton;\n\nexport default DrawerHybrid;\n","import { Drawer as BaseDrawer } from \"@base-ui/react/drawer\";\nimport {\n StyledPopup,\n StyledBackdrop,\n StyledViewport,\n DragHandle,\n} from \"./styles\";\nimport { useDrawerShell, DrawerPopupContents } from \"./DrawerShared\";\nimport type { TypeDrawerProps } from \"./DrawerTypes\";\n\n/**\n * Legacy styled-components shell. Routed to by `DrawerHybrid` whenever the\n * consumer passes styled-system props (or a `styled()` extension). Renders the\n * exact styled wrappers from `styles.ts` so behaviour is unchanged.\n */\nconst DrawerStyled = (props: TypeDrawerProps) => {\n const shell = useDrawerShell(props);\n const {\n effectiveDirection,\n hasSnapPoints,\n hasActionRail,\n rootProps,\n rest,\n width,\n offset,\n zIndex,\n id,\n open,\n } = shell;\n\n return (\n <BaseDrawer.Root {...rootProps}>\n <BaseDrawer.Portal>\n <StyledBackdrop data-testid=\"drawer-backdrop\" />\n <StyledViewport $hasSnapPoints={hasSnapPoints}>\n <StyledPopup\n initialFocus={true}\n $width={width}\n $offset={offset}\n $direction={effectiveDirection}\n $zIndex={zIndex}\n $hasSnapPoints={hasSnapPoints}\n $hasActionRail={hasActionRail}\n data-qa-drawer={id}\n data-qa-drawer-isopen={open}\n {...rest}\n >\n {effectiveDirection === \"bottom\" && <DragHandle aria-hidden />}\n <DrawerPopupContents shell={shell} />\n </StyledPopup>\n </StyledViewport>\n </BaseDrawer.Portal>\n </BaseDrawer.Root>\n );\n};\n\nexport default DrawerStyled;\n","import { Drawer } from \"@base-ui/react/drawer\";\nimport styled from \"styled-components\";\nimport { COMMON } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeSystemCommonProps } from \"@sproutsocial/seeds-react-system-props\";\nimport { MOTION_DURATION_MEDIUM } from \"@sproutsocial/seeds-motion/unitless\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport { RAIL_BUTTON_HEIGHT, RAIL_OFFSET } from \"./ActionRail\";\n\n// Total vertical space the action rail occupies above the popup\n// (rail height + gap between rail and popup). When the drawer animates\n// closed, the popup must translate this much further so the rail also\n// leaves the viewport instead of flashing at the bottom edge.\nconst ACTION_RAIL_OUTSET = RAIL_BUTTON_HEIGHT + RAIL_OFFSET;\n\nexport const Content = styled(Box)`\n overflow-y: auto;\n`;\n\nexport const StyledViewport = styled(Drawer.Viewport)<{\n $hasSnapPoints: boolean;\n}>`\n ${(props) =>\n props.$hasSnapPoints\n ? `\n position: fixed;\n inset: 0;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n touch-action: none;\n /* The viewport spans the whole screen but the popup only fills part of\n it. Letting clicks fall through the empty area means a nested\n snap-point drawer doesn't block selection/interaction with the\n parent drawer visible underneath. The popup re-enables events. */\n pointer-events: none;\n `\n : \"\"}\n`;\n\ninterface StyledPopupProps extends TypeSystemCommonProps {\n $width: number;\n $offset: number;\n $direction: \"left\" | \"right\" | \"bottom\";\n $zIndex: number;\n $hasSnapPoints: boolean;\n $hasActionRail: boolean;\n}\n\nexport const StyledPopup = styled(Drawer.Popup)<StyledPopupProps>`\n display: flex;\n flex-direction: column;\n position: fixed;\n background-color: ${(props) => props.theme.colors.container.background.base};\n z-index: ${(props) => props.$zIndex};\n filter: blur(0);\n transition: transform ${MOTION_DURATION_MEDIUM}s ease,\n border-radius ${MOTION_DURATION_MEDIUM}s ease,\n height ${MOTION_DURATION_MEDIUM}s ease;\n\n /* Always-on opacity transition so content fades smoothly both into and out of stacked state */\n > * {\n transition: opacity ${MOTION_DURATION_MEDIUM}s ease;\n }\n\n ${(props) => {\n if (props.$direction === \"bottom\") {\n if (props.$hasSnapPoints) {\n // Snap-points popup follows base-ui's reference layout. Critical details:\n // - box-sizing: border-box so offsetHeight ignores padding-bottom; otherwise\n // base-ui's ResizeObserver feedback (padding-bottom driven by snap offset)\n // grows popupHeight on every measurement and snap math diverges.\n // - height (not max-height) so popupHeight is large enough that base-ui's\n // snap offset = max(0, popupHeight - snapHeight) distinguishes snap points;\n // with short content + max-height it collapses to 0 for every snap.\n // - position: relative inside the flex-end Viewport so base-ui can measure\n // popupHeight vs viewportHeight for snap math.\n return `\n box-sizing: border-box;\n position: relative;\n width: 100%;\n height: calc(100dvh - 1rem);\n padding-bottom: max(0px, calc(var(--drawer-snap-point-offset, 0px) + var(--drawer-swipe-movement-y, 0px)));\n overflow: visible;\n touch-action: none;\n /* Counterpart to the viewport's pointer-events: none — the popup\n itself stays interactive. */\n pointer-events: auto;\n border-radius: ${props.theme.radii[800]} ${props.theme.radii[800]} 0 0;\n box-shadow: 0px -8px 16px rgba(39,51,51,.25);\n transform: translateY(calc(var(--drawer-snap-point-offset, 0px) + var(--drawer-swipe-movement-y, 0px)));\n will-change: transform;\n transition:\n transform ${MOTION_DURATION_MEDIUM}s cubic-bezier(0.32, 0.72, 0, 1),\n box-shadow ${MOTION_DURATION_MEDIUM}s cubic-bezier(0.32, 0.72, 0, 1);\n `;\n }\n return `\n --bleed: 3rem;\n --stack-scale: 1;\n --translate-y: 0px;\n bottom: 0;\n left: 0;\n right: 0;\n width: 100%;\n height: calc(90vh + var(--bleed));\n margin-bottom: calc(-1 * var(--bleed));\n border-radius: ${props.theme.radii[800]} ${props.theme.radii[800]} 0 0;\n transform: translateY(var(--translate-y)) scale(var(--stack-scale));\n transform-origin: 50% calc(100% - var(--bleed));\n box-shadow: 0px -8px 16px rgba(39,51,51,.25);\n `;\n }\n return `\n top: 0;\n height: 100%;\n width: ${props.$width}px;\n ${\n props.$direction === \"right\"\n ? `right: ${props.$offset}px;`\n : `left: ${props.$offset}px;`\n }\n box-shadow: ${props.theme.shadows.medium};\n `;\n }}\n\n &[data-starting-style],\n &[data-ending-style] {\n ${(props) => {\n if (props.$direction !== \"bottom\") {\n return `transform: translateX(${\n props.$direction === \"right\" ? \"100%\" : \"-100%\"\n });`;\n }\n // The action rail lives above the popup (position: absolute,\n // bottom: 100% + RAIL_OFFSET). Translating the popup by its own\n // height alone leaves the rail visible at the bottom of the\n // viewport during enter/exit, so we add the rail's outset here.\n const railOffset = props.$hasActionRail\n ? ` + ${ACTION_RAIL_OUTSET}px`\n : \"\";\n if (props.$hasSnapPoints) {\n return `\n transform: translateY(calc(100% + 2px${railOffset}));\n padding-bottom: 0;\n `;\n }\n return `transform: translateY(calc(100% - var(--bleed) + 2px${railOffset}));`;\n }}\n }\n\n &[data-swiping],\n &[data-nested-drawer-swiping] {\n transition-duration: 0ms;\n }\n\n &[data-nested-drawer-open] {\n border-radius: ${(props) => props.theme.radii[800]};\n\n ${(props) => {\n if (props.$direction === \"bottom\") {\n // Snap-point drawers don't participate in the stacked-bottom-sheet\n // animation: the stack math overwrites --translate-y and clips overflow,\n // which collides with base-ui's snap-offset transform.\n if (props.$hasSnapPoints) return \"\";\n return `\n --stack-step: 0.05;\n --stack-progress: clamp(0, var(--drawer-swipe-progress), 1);\n /* Override default vars; base transform rule picks them up automatically */\n --stack-scale: max(0, calc(\n 1 - (var(--nested-drawers) * var(--stack-step))\n + (var(--stack-step) * var(--stack-progress))\n ));\n --stack-shrink: calc(1 - var(--stack-scale));\n --stack-height: max(0px, calc(\n var(--drawer-frontmost-height, var(--drawer-height)) - var(--bleed)\n ));\n --stack-peek-offset: max(0px, calc(\n (var(--nested-drawers) - var(--stack-progress)) * 1rem\n ));\n --translate-y: calc(\n var(--drawer-swipe-movement-y)\n - var(--stack-peek-offset)\n - (var(--stack-shrink) * var(--stack-height))\n );\n height: calc(var(--stack-height) + var(--bleed));\n overflow: hidden;\n `;\n }\n return `\n transform: translateY(calc(var(--nested-drawers) * -20px))\n scale(calc(1 - var(--nested-drawers) * 0.08));\n transform-origin: top center;\n `;\n }}\n\n ${(props) =>\n props.$hasSnapPoints\n ? \"\"\n : `\n > * {\n opacity: 0;\n }\n `}\n }\n\n &[data-nested-drawer-open][data-nested-drawer-swiping] {\n > * {\n opacity: 1;\n }\n }\n\n ${COMMON}\n`;\n\nexport const DragHandle = styled.div`\n position: absolute;\n top: 8px;\n left: 50%;\n transform: translateX(-50%);\n width: 36px;\n height: 4px;\n border-radius: 2px;\n background-color: ${(props) => props.theme.colors.container.border.base};\n`;\n\nexport const StyledBackdrop = styled(Drawer.Backdrop)`\n position: fixed;\n inset: 0;\n background: transparent;\n pointer-events: none;\n`;\n","import * as React from \"react\";\nimport styled, { css } from \"styled-components\";\n\nexport const RAIL_BUTTON_SIZE = 44;\nexport const RAIL_BUTTON_HEIGHT = 32;\nexport const RAIL_OFFSET = 12;\nexport const RAIL_GAP = 12;\n\nconst mobileLayout = css`\n top: auto;\n bottom: calc(100% + ${RAIL_OFFSET}px);\n right: ${RAIL_OFFSET}px;\n left: auto;\n flex-direction: row-reverse;\n`;\n\nconst desktopLayout = css`\n top: ${RAIL_OFFSET}px;\n right: calc(-1 * (${RAIL_BUTTON_SIZE}px + ${RAIL_OFFSET}px));\n flex-direction: column;\n`;\n\nconst Rail = styled.div<{ $isMobile?: boolean }>`\n position: absolute;\n display: flex;\n gap: ${RAIL_GAP}px;\n z-index: 1;\n ${(props) => (props.$isMobile ? mobileLayout : desktopLayout)}\n`;\n\nexport interface TypeActionRailProps {\n children: React.ReactNode;\n /** When true, render horizontally above the parent (bottom-sheet mobile pattern). */\n isMobile?: boolean;\n /** Accessible group label for the rail. */\n \"aria-label\"?: string;\n}\n\nexport const ActionRail: React.FC<TypeActionRailProps> = ({\n children,\n isMobile,\n \"aria-label\": ariaLabel = \"Quick actions\",\n}) => {\n return (\n <Rail\n $isMobile={isMobile}\n data-slot=\"action-rail\"\n data-qa-action-rail\n aria-label={ariaLabel}\n role=\"group\"\n >\n {children}\n </Rail>\n );\n};\n\nActionRail.displayName = \"ActionRail\";\n","import * as React from \"react\";\nimport styled from \"styled-components\";\nimport { focusRing } from \"@sproutsocial/seeds-react-mixins\";\nimport { RAIL_BUTTON_HEIGHT, RAIL_BUTTON_SIZE } from \"./ActionRail\";\n\nconst StyledButton = styled.button`\n width: ${RAIL_BUTTON_SIZE}px;\n height: ${RAIL_BUTTON_HEIGHT}px;\n display: inline-grid;\n place-items: center;\n border-radius: ${(props) => props.theme.radii.outer};\n border: none;\n background: ${(props) => props.theme.colors.button.overlay.background.base};\n color: ${(props) => props.theme.colors.button.overlay.text.base};\n cursor: pointer;\n outline: none;\n transition: all ${(props) => props.theme.duration.fast}\n ${(props) => props.theme.easing.ease_inout};\n\n &:hover {\n background: ${(props) =>\n props.theme.colors.button.overlay.background.hover};\n }\n\n &:hover,\n &:active {\n transform: none;\n }\n\n &:focus-visible {\n ${focusRing}\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n`;\n\nexport type TypeActionRailButtonProps =\n React.ButtonHTMLAttributes<HTMLButtonElement>;\n\nexport const ActionRailButton = React.forwardRef<\n HTMLButtonElement,\n TypeActionRailButtonProps\n>(({ children, ...rest }, ref) => (\n <StyledButton\n ref={ref}\n type=\"button\"\n data-slot=\"action-rail-button\"\n {...rest}\n >\n {children}\n </StyledButton>\n));\n\nActionRailButton.displayName = \"ActionRailButton\";\n","import * as React from \"react\";\nimport { useContext } from \"react\";\nimport { Drawer as BaseDrawer } from \"@base-ui/react/drawer\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\n// eslint-disable-next-line import/no-deprecated\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport { useIsMobile } from \"@sproutsocial/seeds-react-hooks\";\nimport { DisablePortalToBodyContext } from \"@sproutsocial/seeds-react-portal\";\nimport { Content } from \"./styles\";\nimport { ActionRail, ActionRailButton } from \"./ActionRail\";\nimport type {\n TypeDrawerContext,\n TypeDrawerCloseButtonProps,\n TypeDrawerHeaderProps,\n TypeDrawerProps,\n TypeDrawerContentProps,\n} from \"./DrawerTypes\";\n\n/**\n * Single source of truth for the Drawer context. Both the Tailwind and the\n * styled-components shells provide this exact context, and the shared\n * sub-components (`Drawer.CloseButton`, `Drawer.Header`) consume it — so there\n * must be exactly one context identity, or the close button can't see its\n * provider.\n */\nexport const DrawerContext = React.createContext<TypeDrawerContext>({\n isLocked: false,\n setIsLocked: () => {},\n hasActionRail: false,\n});\n\nexport const DrawerCloseButton = (props: TypeDrawerCloseButtonProps) => {\n const drawerContext = useContext(DrawerContext);\n\n if (props.render) {\n return props.render(drawerContext) ?? null;\n }\n\n return (\n <Button\n appearance=\"pill\"\n aria-label={drawerContext.closeButtonLabel}\n onClick={drawerContext.onClose}\n {...props}\n >\n {props.children || <Icon aria-hidden name=\"x-outline\" />}\n </Button>\n );\n};\n\nexport const DrawerHeader = ({\n title = \"\",\n id = undefined,\n children,\n render,\n ...rest\n}: TypeDrawerHeaderProps) => {\n const drawerContext = useContext(DrawerContext);\n\n if (render) {\n return render(drawerContext);\n }\n\n return (\n <Box\n display=\"flex\"\n flex=\"0 0 auto\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n pt={400}\n px={450}\n {...rest}\n >\n {children || (\n <>\n <Text\n as=\"h2\"\n fontSize={400}\n fontWeight=\"semibold\"\n color=\"text.headline\"\n id={id}\n >\n {title}\n </Text>\n {!drawerContext.hasActionRail && <DrawerCloseButton />}\n </>\n )}\n </Box>\n );\n};\n\nexport const DrawerContent = ({ children, ...rest }: TypeDrawerContentProps) => (\n <Content\n height=\"100%\"\n p={450}\n color=\"text.body\"\n data-drawer-content=\"\"\n {...rest}\n >\n {children}\n </Content>\n);\n\nDrawerHeader.displayName = \"Drawer.Header\";\nDrawerContent.displayName = \"Drawer.Content\";\nDrawerCloseButton.displayName = \"Drawer.CloseButton\";\n\n/**\n * Root-level Drawer logic shared by both shells. Centralising it here (rather\n * than duplicating it in each shell) guarantees the two implementations stay\n * behaviourally identical — the esc-key lock and exit-freeze logic is exactly\n * what the lock/close tests exercise.\n */\nexport const useDrawerShell = (props: TypeDrawerProps) => {\n const {\n children,\n closeButtonLabel,\n direction = \"right\",\n disableCloseOnClickOutside = false,\n id,\n modal = false,\n open,\n offset = 0,\n onClose,\n zIndex = 7,\n width = 600,\n snapPoints,\n defaultSnapPoint,\n snapPoint,\n onSnapPointChange,\n snapToSequentialPoints,\n actions,\n actionsInHeader = false,\n ...rest\n } = props;\n\n const isMobile = useIsMobile();\n const effectiveDirection = isMobile ? \"bottom\" : direction;\n const effectiveSnapPoints =\n effectiveDirection === \"bottom\" ? snapPoints : undefined;\n const hasSnapPoints = !!effectiveSnapPoints && effectiveSnapPoints.length > 0;\n const hasActionRail =\n isMobile && !actionsInHeader && !!actions && actions.length > 0;\n const [isLocked, setIsLocked] = React.useState(false);\n\n const ariaLabelledBy = rest[\"aria-labelledby\"];\n const ariaLabel = rest[\"aria-label\"];\n React.useEffect(() => {\n if (process.env.NODE_ENV !== \"production\") {\n if (!ariaLabelledBy && !ariaLabel) {\n console.warn(\n \"[Drawer] Missing accessible name. Add aria-labelledby pointing to your Drawer.Header id, or aria-label, so screen readers can identify the dialog.\"\n );\n }\n }\n }, [ariaLabelledBy, ariaLabel]);\n // Keep a ref so the onOpenChange callback always sees the current isLocked\n // value without needing to be re-created on each render.\n const isLockedRef = React.useRef(isLocked);\n isLockedRef.current = isLocked;\n\n // Freeze the last-rendered children during the exit transition so consumers\n // that conditionally render content (e.g. {isOpen && <Content />}) don't\n // produce an empty drawer shell while Base UI animates the popup out.\n const prevChildrenRef = React.useRef<React.ReactNode>(null);\n if (open) {\n prevChildrenRef.current = children;\n }\n const renderedChildren = open ? children : prevChildrenRef.current;\n\n const rootProps: Omit<\n React.ComponentProps<typeof BaseDrawer.Root>,\n \"children\"\n > = {\n open,\n onOpenChange: (isOpen, eventDetails) => {\n if (!isOpen) {\n if (isLockedRef.current && eventDetails.reason === \"escape-key\") {\n return;\n }\n onClose();\n }\n },\n disablePointerDismissal: disableCloseOnClickOutside,\n swipeDirection:\n effectiveDirection === \"bottom\" ? \"down\" : effectiveDirection,\n modal,\n snapPoints: effectiveSnapPoints,\n defaultSnapPoint,\n snapPoint,\n onSnapPointChange: onSnapPointChange\n ? (sp) => onSnapPointChange(sp)\n : undefined,\n snapToSequentialPoints,\n };\n\n return {\n effectiveDirection,\n hasSnapPoints,\n hasActionRail,\n isLocked,\n setIsLocked,\n renderedChildren,\n rootProps,\n rest,\n width,\n offset,\n zIndex,\n id,\n open,\n closeButtonLabel,\n onClose,\n actions,\n };\n};\n\nexport type TypeDrawerShell = ReturnType<typeof useDrawerShell>;\n\n/**\n * The popup contents shared by both shells: the optional mobile action rail and\n * the context providers wrapping the rendered children. Only the popup wrapper\n * and drag handle differ between the Tailwind and styled paths — everything\n * inside the popup is identical, so it lives here.\n */\nexport const DrawerPopupContents = ({ shell }: { shell: TypeDrawerShell }) => {\n const {\n hasActionRail,\n closeButtonLabel,\n onClose,\n actions,\n isLocked,\n setIsLocked,\n renderedChildren,\n } = shell;\n\n return (\n <>\n {hasActionRail && actions && (\n <ActionRail isMobile aria-label=\"Drawer quick actions\">\n <ActionRailButton\n aria-label={closeButtonLabel}\n onClick={onClose}\n data-qa-drawer-rail-close\n >\n <Icon aria-hidden name=\"x-outline\" />\n </ActionRailButton>\n {actions.map((action, i) => (\n <ActionRailButton\n key={i}\n aria-label={action[\"aria-label\"]}\n onClick={action.onClick}\n disabled={action.disabled}\n >\n {action.iconName && <Icon aria-hidden name={action.iconName} />}\n </ActionRailButton>\n ))}\n </ActionRail>\n )}\n <DisablePortalToBodyContext.Provider value={true}>\n <DrawerContext.Provider\n value={{\n onClose,\n closeButtonLabel,\n isLocked,\n setIsLocked,\n hasActionRail,\n }}\n >\n {renderedChildren}\n </DrawerContext.Provider>\n </DisablePortalToBodyContext.Provider>\n </>\n );\n};\n","import { Drawer as BaseDrawer } from \"@base-ui/react/drawer\";\nimport { useDrawerShell, DrawerPopupContents } from \"./DrawerShared\";\nimport type { TypeDrawerProps } from \"./DrawerTypes\";\nimport type { CSSProperties } from \"react\";\n\n// Utility for merging class names properly. Copied from ButtonTailwind.tsx —\n// `cn` is NOT exported from @sproutsocial/seeds-react-utilities, so each\n// Tailwind component carries its own copy.\nfunction cn(\n ...inputs: (string | undefined | null | false | Record<string, boolean>)[]\n): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === \"string\") {\n classes.push(input);\n } else if (typeof input === \"object\") {\n for (const [key, value] of Object.entries(input)) {\n if (value) {\n classes.push(key);\n }\n }\n }\n }\n\n return classes.join(\" \");\n}\n\n/**\n * Tailwind/CSS-class shell. The preferred path — routed to by `DrawerHybrid`\n * whenever the consumer passes no styled-system props. Renders the real Base UI\n * primitives (Backdrop/Viewport/Popup) with component-scoped classes from\n * `drawer.css`; the runtime numerics (`width`, `offset`, `zIndex`) are applied\n * as direct inline styles so drag/swipe/snap/portal behaviour is preserved.\n */\nconst DrawerTailwind = (props: TypeDrawerProps) => {\n const shell = useDrawerShell(props);\n const {\n effectiveDirection,\n hasSnapPoints,\n hasActionRail,\n rootProps,\n rest,\n width,\n offset,\n zIndex,\n id,\n open,\n } = shell;\n\n // `className` and `style` are public <div> props (TypeDrawerProps extends\n // ComponentPropsWithoutRef<\"div\">) that arrive via `rest`. Pull them out so\n // they MERGE with the popup's computed classes/geometry instead of\n // overwriting them — matching the styled-components path, where a consumer\n // className is appended to the generated class and an inline style wins over\n // the generated width.\n const { className, style, ...domRest } = rest as {\n className?: string;\n style?: CSSProperties;\n } & Record<string, unknown>;\n\n return (\n <BaseDrawer.Root {...rootProps}>\n <BaseDrawer.Portal>\n <BaseDrawer.Backdrop\n data-testid=\"drawer-backdrop\"\n className=\"seeds-drawer-backdrop\"\n />\n <BaseDrawer.Viewport\n className={cn(\"seeds-drawer-viewport\", {\n \"seeds-drawer-viewport--snap\": hasSnapPoints,\n })}\n >\n <BaseDrawer.Popup\n initialFocus\n data-qa-drawer={id}\n data-qa-drawer-isopen={open}\n {...domRest}\n className={cn(\n \"seeds-drawer-popup\",\n effectiveDirection === \"bottom\"\n ? \"seeds-drawer-popup--bottom\"\n : \"seeds-drawer-popup--side\",\n effectiveDirection === \"right\" && \"seeds-drawer-popup--right\",\n effectiveDirection === \"left\" && \"seeds-drawer-popup--left\",\n {\n \"seeds-drawer-popup--snap\": hasSnapPoints,\n \"seeds-drawer-popup--action-rail\": hasActionRail,\n },\n // Consumer className folded in last so it appends to (not\n // replaces) the component classes.\n className\n )}\n style={{\n // z-index is always inline (runtime numeric, mirrors styles.ts).\n zIndex,\n // Side drawers carry their width/offset as direct inline styles —\n // runtime numerics, and required for the jsdom `toHaveStyle`\n // assertions. Bottom drawers derive width/position from the class.\n ...(effectiveDirection === \"right\"\n ? { width: `${width}px`, right: `${offset}px` }\n : effectiveDirection === \"left\"\n ? { width: `${width}px`, left: `${offset}px` }\n : {}),\n // Consumer style folded in last so it wins over the computed\n // geometry, matching the styled-components inline-style semantics.\n ...style,\n }}\n >\n {effectiveDirection === \"bottom\" && (\n <div aria-hidden className=\"seeds-drawer-drag-handle\" />\n )}\n <DrawerPopupContents shell={shell} />\n </BaseDrawer.Popup>\n </BaseDrawer.Viewport>\n </BaseDrawer.Portal>\n </BaseDrawer.Root>\n );\n};\n\nexport default DrawerTailwind;\n","import DrawerHybrid from \"./DrawerHybrid\";\n\n/**\n * Drawer component. Automatically routes between the Tailwind implementation\n * (preferred) and the styled-components implementation (for consumers using\n * system props or a `styled()` extension). The default export carries the\n * `.Header`, `.Content`, and `.CloseButton` statics.\n */\nexport { DrawerContext } from \"./DrawerShared\";\nexport default DrawerHybrid;\n","import * as React from \"react\";\nimport type {\n TypeSystemCommonProps,\n TypeStyledComponentsCommonProps,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeBoxProps } from \"@sproutsocial/seeds-react-box\";\nimport type { TypeButtonProps } from \"@sproutsocial/seeds-react-button\";\nimport type { TypeIconName } from \"@sproutsocial/seeds-react-icon\";\n\ntype DrawerAnimationDirection = \"left\" | \"right\" | \"bottom\";\n\n/**\n * Action button shown in the mobile rail above a bottom-sheet drawer.\n * Mirrors `TypeModalActionProps` so consumers can share the same array shape.\n */\nexport type TypeDrawerActionProps = {\n /** Accessible label for the action button. */\n \"aria-label\": string;\n /** Icon name from the Seeds icon set. */\n iconName?: TypeIconName;\n /** Click handler. */\n onClick?: () => void;\n /** Disable the action. */\n disabled?: boolean;\n};\n\n/**\n * A snap point the bottom drawer can rest at.\n * - Numbers 0–1: fraction of viewport height\n * - Numbers > 1: pixels\n * - Strings: CSS lengths in `px` or `rem` (e.g. `\"480px\"`, `\"30rem\"`)\n */\nexport type TypeDrawerSnapPoint = number | string;\n\nexport interface TypeDrawerContext {\n /** Callback for close button */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onClose?: () => any;\n\n /** aria-label for drawer close button */\n closeButtonLabel?: string;\n /**\n * isLocked and setIsLocked are used when a Drawer contains other components (like Menu) that also\n * listen for Escape key events. By locking the Drawer, we can prevent conflicts\n * where multiple components try to handle the same keydown event.\n */\n isLocked: boolean;\n setIsLocked: (locked: boolean) => void;\n /**\n * True when the Drawer is rendering an `ActionRail` above the popup. The\n * default `Drawer.Header` reads this to omit its built-in close button so the\n * rail can own the close affordance.\n */\n hasActionRail?: boolean;\n}\n// TODO: Should the render prop be a React.FC?\nexport interface TypeDrawerCloseButtonProps\n extends Omit<TypeButtonProps, \"children\"> {\n /** An optional function that receives the context of the parent drawer as an argument. Can be used to customize the on-close behavior. */\n render?: React.FC<TypeDrawerContext>;\n children?: React.ReactNode;\n}\n\nexport interface TypeDrawerHeaderProps extends TypeBoxProps {\n title?: string;\n /**\n * When children are provided, `<Drawer.CloseButton />` is NOT rendered automatically.\n * You must include it yourself inside children to preserve keyboard accessibility.\n */\n children?: React.ReactNode;\n\n /** An optional function that receives the context of the parent drawer as an argument. Can be used to customize the appearance of the header. */\n render?: React.FC<TypeDrawerContext>;\n}\n\nexport interface TypeDrawerProps\n extends TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n Omit<React.ComponentPropsWithoutRef<\"div\">, \"color\"> {\n children: React.ReactNode;\n\n /** Label for the close button. Usually this should be \"Close\" */\n closeButtonLabel: string;\n\n /** Whether the drawer slides in from the left or right side of the screen */\n direction?: DrawerAnimationDirection;\n\n /** In some cases, you may not want the user to be able to click outside of the drawer to close it. You can disable that with this prop. */\n disableCloseOnClickOutside?: boolean;\n\n /**\n * When true, siblings are inerted while the drawer is open — appropriate for forms or settings\n * panels where page interaction should be blocked.\n * Defaults to false to preserve the original non-modal behavior where the rest of the page\n * remains interactive (side info panels, notification slide-outs, persistent inspectors, etc.).\n */\n modal?: boolean;\n /** Optional id used for data-qa-drawer attributes */\n id?: string;\n open: boolean;\n offset?: number;\n onClose: () => void;\n zIndex?: number;\n width?: number;\n\n /**\n * Snap points the drawer can rest at when swiped. Only applied to bottom drawers.\n * Numbers 0–1 are viewport-height fractions; numbers > 1 are pixels; strings accept\n * `px`/`rem` (e.g. `\"480px\"`, `\"30rem\"`). Order matters — the last entry is the\n * \"expanded\" state and gets a `data-expanded` attribute on the popup.\n */\n snapPoints?: TypeDrawerSnapPoint[];\n\n /** Initial snap point for uncontrolled use. */\n defaultSnapPoint?: TypeDrawerSnapPoint | null;\n\n /** Controlled active snap point. Pair with `onSnapPointChange`. */\n snapPoint?: TypeDrawerSnapPoint | null;\n\n /** Fires when the active snap point changes (drag release, programmatic update, etc.). */\n onSnapPointChange?: (snapPoint: TypeDrawerSnapPoint | null) => void;\n\n /**\n * When true, fast swipes can't skip past adjacent snap points — drag distance alone\n * determines the next stop. Defaults to base-ui's `false` (velocity-based skipping).\n */\n snapToSequentialPoints?: boolean;\n\n /**\n * Action buttons shown in a floating rail above the drawer on mobile (the\n * bottom-sheet rendering). The rail also owns the close button — when this\n * prop is provided, the default `Drawer.Header` omits its built-in close\n * button so the rail can render it instead. Ignored on desktop side drawers.\n */\n actions?: TypeDrawerActionProps[];\n\n /**\n * Opt out of the floating rail and keep the actions inside `Drawer.Header`\n * (the pre-rail behavior). Useful for nested bottom sheets and snap-point\n * drawers where the rail-above placement would collide with surrounding UI\n * or fall off-screen at the highest snap point. Defaults to `false`.\n *\n * When `true`, the Drawer does NOT render the rail; consumers are\n * responsible for rendering action buttons (and the close button) inside\n * their `Drawer.Header`.\n */\n actionsInHeader?: boolean;\n}\n\nexport interface TypeDrawerContentProps extends TypeBoxProps {\n children?: React.ReactNode;\n}\n","import Drawer, { DrawerContext } from \"./Drawer\";\n\nexport default Drawer;\nexport { Drawer, DrawerContext };\nexport * from \"./DrawerTypes\";\nexport {\n ActionRail,\n ActionRailButton,\n RAIL_BUTTON_SIZE,\n RAIL_BUTTON_HEIGHT,\n RAIL_OFFSET,\n RAIL_GAP,\n} from \"./ActionRail\";\nexport type {\n TypeActionRailProps,\n TypeActionRailButtonProps,\n} from \"./ActionRail\";\n"],"mappings":"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","names":["BaseDrawer","styled","React","styled","jsx","styled","styled","React","Box","jsx","Box","jsx","jsxs","BaseDrawer","BaseDrawer","jsx","jsxs","BaseDrawer","jsx"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,32 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import * as React from 'react';
|
|
3
2
|
import { TypeStyledComponentsCommonProps, TypeSystemCommonProps } from '@sproutsocial/seeds-react-system-props';
|
|
4
3
|
import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
|
|
5
4
|
import { TypeButtonProps } from '@sproutsocial/seeds-react-button';
|
|
5
|
+
import { TypeIconName } from '@sproutsocial/seeds-react-icon';
|
|
6
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
7
|
|
|
7
|
-
type DrawerAnimationDirection = "left" | "right";
|
|
8
|
+
type DrawerAnimationDirection = "left" | "right" | "bottom";
|
|
9
|
+
/**
|
|
10
|
+
* Action button shown in the mobile rail above a bottom-sheet drawer.
|
|
11
|
+
* Mirrors `TypeModalActionProps` so consumers can share the same array shape.
|
|
12
|
+
*/
|
|
13
|
+
type TypeDrawerActionProps = {
|
|
14
|
+
/** Accessible label for the action button. */
|
|
15
|
+
"aria-label": string;
|
|
16
|
+
/** Icon name from the Seeds icon set. */
|
|
17
|
+
iconName?: TypeIconName;
|
|
18
|
+
/** Click handler. */
|
|
19
|
+
onClick?: () => void;
|
|
20
|
+
/** Disable the action. */
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* A snap point the bottom drawer can rest at.
|
|
25
|
+
* - Numbers 0–1: fraction of viewport height
|
|
26
|
+
* - Numbers > 1: pixels
|
|
27
|
+
* - Strings: CSS lengths in `px` or `rem` (e.g. `"480px"`, `"30rem"`)
|
|
28
|
+
*/
|
|
29
|
+
type TypeDrawerSnapPoint = number | string;
|
|
8
30
|
interface TypeDrawerContext {
|
|
9
31
|
/** Callback for close button */
|
|
10
32
|
onClose?: () => any;
|
|
@@ -17,6 +39,12 @@ interface TypeDrawerContext {
|
|
|
17
39
|
*/
|
|
18
40
|
isLocked: boolean;
|
|
19
41
|
setIsLocked: (locked: boolean) => void;
|
|
42
|
+
/**
|
|
43
|
+
* True when the Drawer is rendering an `ActionRail` above the popup. The
|
|
44
|
+
* default `Drawer.Header` reads this to omit its built-in close button so the
|
|
45
|
+
* rail can own the close affordance.
|
|
46
|
+
*/
|
|
47
|
+
hasActionRail?: boolean;
|
|
20
48
|
}
|
|
21
49
|
interface TypeDrawerCloseButtonProps extends Omit<TypeButtonProps, "children"> {
|
|
22
50
|
/** An optional function that receives the context of the parent drawer as an argument. Can be used to customize the on-close behavior. */
|
|
@@ -25,19 +53,15 @@ interface TypeDrawerCloseButtonProps extends Omit<TypeButtonProps, "children"> {
|
|
|
25
53
|
}
|
|
26
54
|
interface TypeDrawerHeaderProps extends TypeBoxProps {
|
|
27
55
|
title?: string;
|
|
56
|
+
/**
|
|
57
|
+
* When children are provided, `<Drawer.CloseButton />` is NOT rendered automatically.
|
|
58
|
+
* You must include it yourself inside children to preserve keyboard accessibility.
|
|
59
|
+
*/
|
|
28
60
|
children?: React.ReactNode;
|
|
29
61
|
/** An optional function that receives the context of the parent drawer as an argument. Can be used to customize the appearance of the header. */
|
|
30
62
|
render?: React.FC<TypeDrawerContext>;
|
|
31
63
|
}
|
|
32
|
-
interface
|
|
33
|
-
width: number;
|
|
34
|
-
direction: DrawerAnimationDirection;
|
|
35
|
-
}
|
|
36
|
-
interface TypeUseCloseOnBodyClickProps extends Pick<TypeDrawerProps, "closeTargets" | "onClose" | "disableCloseOnClickOutside"> {
|
|
37
|
-
ref?: React.RefObject<HTMLElement | null>;
|
|
38
|
-
isOpen: boolean;
|
|
39
|
-
}
|
|
40
|
-
interface TypeDrawerProps extends TypeStyledComponentsCommonProps, TypeSystemCommonProps, Omit<React.ComponentPropsWithoutRef<"nav">, "color"> {
|
|
64
|
+
interface TypeDrawerProps extends TypeStyledComponentsCommonProps, TypeSystemCommonProps, Omit<React.ComponentPropsWithoutRef<"div">, "color"> {
|
|
41
65
|
children: React.ReactNode;
|
|
42
66
|
/** Label for the close button. Usually this should be "Close" */
|
|
43
67
|
closeButtonLabel: string;
|
|
@@ -45,22 +69,63 @@ interface TypeDrawerProps extends TypeStyledComponentsCommonProps, TypeSystemCom
|
|
|
45
69
|
direction?: DrawerAnimationDirection;
|
|
46
70
|
/** In some cases, you may not want the user to be able to click outside of the drawer to close it. You can disable that with this prop. */
|
|
47
71
|
disableCloseOnClickOutside?: boolean;
|
|
48
|
-
|
|
49
|
-
|
|
72
|
+
/**
|
|
73
|
+
* When true, siblings are inerted while the drawer is open — appropriate for forms or settings
|
|
74
|
+
* panels where page interaction should be blocked.
|
|
75
|
+
* Defaults to false to preserve the original non-modal behavior where the rest of the page
|
|
76
|
+
* remains interactive (side info panels, notification slide-outs, persistent inspectors, etc.).
|
|
77
|
+
*/
|
|
78
|
+
modal?: boolean;
|
|
79
|
+
/** Optional id used for data-qa-drawer attributes */
|
|
80
|
+
id?: string;
|
|
81
|
+
open: boolean;
|
|
50
82
|
offset?: number;
|
|
51
83
|
onClose: () => void;
|
|
52
84
|
zIndex?: number;
|
|
53
|
-
closeTargets?: Array<Element>;
|
|
54
85
|
width?: number;
|
|
55
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Snap points the drawer can rest at when swiped. Only applied to bottom drawers.
|
|
88
|
+
* Numbers 0–1 are viewport-height fractions; numbers > 1 are pixels; strings accept
|
|
89
|
+
* `px`/`rem` (e.g. `"480px"`, `"30rem"`). Order matters — the last entry is the
|
|
90
|
+
* "expanded" state and gets a `data-expanded` attribute on the popup.
|
|
91
|
+
*/
|
|
92
|
+
snapPoints?: TypeDrawerSnapPoint[];
|
|
93
|
+
/** Initial snap point for uncontrolled use. */
|
|
94
|
+
defaultSnapPoint?: TypeDrawerSnapPoint | null;
|
|
95
|
+
/** Controlled active snap point. Pair with `onSnapPointChange`. */
|
|
96
|
+
snapPoint?: TypeDrawerSnapPoint | null;
|
|
97
|
+
/** Fires when the active snap point changes (drag release, programmatic update, etc.). */
|
|
98
|
+
onSnapPointChange?: (snapPoint: TypeDrawerSnapPoint | null) => void;
|
|
99
|
+
/**
|
|
100
|
+
* When true, fast swipes can't skip past adjacent snap points — drag distance alone
|
|
101
|
+
* determines the next stop. Defaults to base-ui's `false` (velocity-based skipping).
|
|
102
|
+
*/
|
|
103
|
+
snapToSequentialPoints?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Action buttons shown in a floating rail above the drawer on mobile (the
|
|
106
|
+
* bottom-sheet rendering). The rail also owns the close button — when this
|
|
107
|
+
* prop is provided, the default `Drawer.Header` omits its built-in close
|
|
108
|
+
* button so the rail can render it instead. Ignored on desktop side drawers.
|
|
109
|
+
*/
|
|
110
|
+
actions?: TypeDrawerActionProps[];
|
|
111
|
+
/**
|
|
112
|
+
* Opt out of the floating rail and keep the actions inside `Drawer.Header`
|
|
113
|
+
* (the pre-rail behavior). Useful for nested bottom sheets and snap-point
|
|
114
|
+
* drawers where the rail-above placement would collide with surrounding UI
|
|
115
|
+
* or fall off-screen at the highest snap point. Defaults to `false`.
|
|
116
|
+
*
|
|
117
|
+
* When `true`, the Drawer does NOT render the rail; consumers are
|
|
118
|
+
* responsible for rendering action buttons (and the close button) inside
|
|
119
|
+
* their `Drawer.Header`.
|
|
120
|
+
*/
|
|
121
|
+
actionsInHeader?: boolean;
|
|
56
122
|
}
|
|
57
123
|
interface TypeDrawerContentProps extends TypeBoxProps {
|
|
58
124
|
children?: React.ReactNode;
|
|
59
125
|
}
|
|
60
126
|
|
|
61
|
-
declare const
|
|
62
|
-
|
|
63
|
-
({ children, closeButtonLabel, direction, disableCloseOnClickOutside, id, isOpen, offset, onClose, zIndex, closeTargets, width, ...rest }: TypeDrawerProps): react_jsx_runtime.JSX.Element;
|
|
127
|
+
declare const DrawerHybrid: {
|
|
128
|
+
(props: TypeDrawerProps): react_jsx_runtime.JSX.Element;
|
|
64
129
|
Header: {
|
|
65
130
|
({ title, id, children, render, ...rest }: TypeDrawerHeaderProps): string | number | boolean | Iterable<React.ReactNode> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
66
131
|
displayName: string;
|
|
@@ -75,4 +140,29 @@ declare const DrawerContainer: {
|
|
|
75
140
|
};
|
|
76
141
|
};
|
|
77
142
|
|
|
78
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Single source of truth for the Drawer context. Both the Tailwind and the
|
|
145
|
+
* styled-components shells provide this exact context, and the shared
|
|
146
|
+
* sub-components (`Drawer.CloseButton`, `Drawer.Header`) consume it — so there
|
|
147
|
+
* must be exactly one context identity, or the close button can't see its
|
|
148
|
+
* provider.
|
|
149
|
+
*/
|
|
150
|
+
declare const DrawerContext: React.Context<TypeDrawerContext>;
|
|
151
|
+
|
|
152
|
+
declare const RAIL_BUTTON_SIZE = 44;
|
|
153
|
+
declare const RAIL_BUTTON_HEIGHT = 32;
|
|
154
|
+
declare const RAIL_OFFSET = 12;
|
|
155
|
+
declare const RAIL_GAP = 12;
|
|
156
|
+
interface TypeActionRailProps {
|
|
157
|
+
children: React.ReactNode;
|
|
158
|
+
/** When true, render horizontally above the parent (bottom-sheet mobile pattern). */
|
|
159
|
+
isMobile?: boolean;
|
|
160
|
+
/** Accessible group label for the rail. */
|
|
161
|
+
"aria-label"?: string;
|
|
162
|
+
}
|
|
163
|
+
declare const ActionRail: React.FC<TypeActionRailProps>;
|
|
164
|
+
|
|
165
|
+
type TypeActionRailButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
166
|
+
declare const ActionRailButton: React.ForwardRefExoticComponent<TypeActionRailButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
167
|
+
|
|
168
|
+
export { ActionRail, ActionRailButton, DrawerHybrid as Drawer, DrawerContext, RAIL_BUTTON_HEIGHT, RAIL_BUTTON_SIZE, RAIL_GAP, RAIL_OFFSET, type TypeActionRailButtonProps, type TypeActionRailProps, type TypeDrawerActionProps, type TypeDrawerCloseButtonProps, type TypeDrawerContentProps, type TypeDrawerContext, type TypeDrawerHeaderProps, type TypeDrawerProps, type TypeDrawerSnapPoint, DrawerHybrid as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,32 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import * as React from 'react';
|
|
3
2
|
import { TypeStyledComponentsCommonProps, TypeSystemCommonProps } from '@sproutsocial/seeds-react-system-props';
|
|
4
3
|
import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
|
|
5
4
|
import { TypeButtonProps } from '@sproutsocial/seeds-react-button';
|
|
5
|
+
import { TypeIconName } from '@sproutsocial/seeds-react-icon';
|
|
6
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
7
|
|
|
7
|
-
type DrawerAnimationDirection = "left" | "right";
|
|
8
|
+
type DrawerAnimationDirection = "left" | "right" | "bottom";
|
|
9
|
+
/**
|
|
10
|
+
* Action button shown in the mobile rail above a bottom-sheet drawer.
|
|
11
|
+
* Mirrors `TypeModalActionProps` so consumers can share the same array shape.
|
|
12
|
+
*/
|
|
13
|
+
type TypeDrawerActionProps = {
|
|
14
|
+
/** Accessible label for the action button. */
|
|
15
|
+
"aria-label": string;
|
|
16
|
+
/** Icon name from the Seeds icon set. */
|
|
17
|
+
iconName?: TypeIconName;
|
|
18
|
+
/** Click handler. */
|
|
19
|
+
onClick?: () => void;
|
|
20
|
+
/** Disable the action. */
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* A snap point the bottom drawer can rest at.
|
|
25
|
+
* - Numbers 0–1: fraction of viewport height
|
|
26
|
+
* - Numbers > 1: pixels
|
|
27
|
+
* - Strings: CSS lengths in `px` or `rem` (e.g. `"480px"`, `"30rem"`)
|
|
28
|
+
*/
|
|
29
|
+
type TypeDrawerSnapPoint = number | string;
|
|
8
30
|
interface TypeDrawerContext {
|
|
9
31
|
/** Callback for close button */
|
|
10
32
|
onClose?: () => any;
|
|
@@ -17,6 +39,12 @@ interface TypeDrawerContext {
|
|
|
17
39
|
*/
|
|
18
40
|
isLocked: boolean;
|
|
19
41
|
setIsLocked: (locked: boolean) => void;
|
|
42
|
+
/**
|
|
43
|
+
* True when the Drawer is rendering an `ActionRail` above the popup. The
|
|
44
|
+
* default `Drawer.Header` reads this to omit its built-in close button so the
|
|
45
|
+
* rail can own the close affordance.
|
|
46
|
+
*/
|
|
47
|
+
hasActionRail?: boolean;
|
|
20
48
|
}
|
|
21
49
|
interface TypeDrawerCloseButtonProps extends Omit<TypeButtonProps, "children"> {
|
|
22
50
|
/** An optional function that receives the context of the parent drawer as an argument. Can be used to customize the on-close behavior. */
|
|
@@ -25,19 +53,15 @@ interface TypeDrawerCloseButtonProps extends Omit<TypeButtonProps, "children"> {
|
|
|
25
53
|
}
|
|
26
54
|
interface TypeDrawerHeaderProps extends TypeBoxProps {
|
|
27
55
|
title?: string;
|
|
56
|
+
/**
|
|
57
|
+
* When children are provided, `<Drawer.CloseButton />` is NOT rendered automatically.
|
|
58
|
+
* You must include it yourself inside children to preserve keyboard accessibility.
|
|
59
|
+
*/
|
|
28
60
|
children?: React.ReactNode;
|
|
29
61
|
/** An optional function that receives the context of the parent drawer as an argument. Can be used to customize the appearance of the header. */
|
|
30
62
|
render?: React.FC<TypeDrawerContext>;
|
|
31
63
|
}
|
|
32
|
-
interface
|
|
33
|
-
width: number;
|
|
34
|
-
direction: DrawerAnimationDirection;
|
|
35
|
-
}
|
|
36
|
-
interface TypeUseCloseOnBodyClickProps extends Pick<TypeDrawerProps, "closeTargets" | "onClose" | "disableCloseOnClickOutside"> {
|
|
37
|
-
ref?: React.RefObject<HTMLElement | null>;
|
|
38
|
-
isOpen: boolean;
|
|
39
|
-
}
|
|
40
|
-
interface TypeDrawerProps extends TypeStyledComponentsCommonProps, TypeSystemCommonProps, Omit<React.ComponentPropsWithoutRef<"nav">, "color"> {
|
|
64
|
+
interface TypeDrawerProps extends TypeStyledComponentsCommonProps, TypeSystemCommonProps, Omit<React.ComponentPropsWithoutRef<"div">, "color"> {
|
|
41
65
|
children: React.ReactNode;
|
|
42
66
|
/** Label for the close button. Usually this should be "Close" */
|
|
43
67
|
closeButtonLabel: string;
|
|
@@ -45,22 +69,63 @@ interface TypeDrawerProps extends TypeStyledComponentsCommonProps, TypeSystemCom
|
|
|
45
69
|
direction?: DrawerAnimationDirection;
|
|
46
70
|
/** In some cases, you may not want the user to be able to click outside of the drawer to close it. You can disable that with this prop. */
|
|
47
71
|
disableCloseOnClickOutside?: boolean;
|
|
48
|
-
|
|
49
|
-
|
|
72
|
+
/**
|
|
73
|
+
* When true, siblings are inerted while the drawer is open — appropriate for forms or settings
|
|
74
|
+
* panels where page interaction should be blocked.
|
|
75
|
+
* Defaults to false to preserve the original non-modal behavior where the rest of the page
|
|
76
|
+
* remains interactive (side info panels, notification slide-outs, persistent inspectors, etc.).
|
|
77
|
+
*/
|
|
78
|
+
modal?: boolean;
|
|
79
|
+
/** Optional id used for data-qa-drawer attributes */
|
|
80
|
+
id?: string;
|
|
81
|
+
open: boolean;
|
|
50
82
|
offset?: number;
|
|
51
83
|
onClose: () => void;
|
|
52
84
|
zIndex?: number;
|
|
53
|
-
closeTargets?: Array<Element>;
|
|
54
85
|
width?: number;
|
|
55
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Snap points the drawer can rest at when swiped. Only applied to bottom drawers.
|
|
88
|
+
* Numbers 0–1 are viewport-height fractions; numbers > 1 are pixels; strings accept
|
|
89
|
+
* `px`/`rem` (e.g. `"480px"`, `"30rem"`). Order matters — the last entry is the
|
|
90
|
+
* "expanded" state and gets a `data-expanded` attribute on the popup.
|
|
91
|
+
*/
|
|
92
|
+
snapPoints?: TypeDrawerSnapPoint[];
|
|
93
|
+
/** Initial snap point for uncontrolled use. */
|
|
94
|
+
defaultSnapPoint?: TypeDrawerSnapPoint | null;
|
|
95
|
+
/** Controlled active snap point. Pair with `onSnapPointChange`. */
|
|
96
|
+
snapPoint?: TypeDrawerSnapPoint | null;
|
|
97
|
+
/** Fires when the active snap point changes (drag release, programmatic update, etc.). */
|
|
98
|
+
onSnapPointChange?: (snapPoint: TypeDrawerSnapPoint | null) => void;
|
|
99
|
+
/**
|
|
100
|
+
* When true, fast swipes can't skip past adjacent snap points — drag distance alone
|
|
101
|
+
* determines the next stop. Defaults to base-ui's `false` (velocity-based skipping).
|
|
102
|
+
*/
|
|
103
|
+
snapToSequentialPoints?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Action buttons shown in a floating rail above the drawer on mobile (the
|
|
106
|
+
* bottom-sheet rendering). The rail also owns the close button — when this
|
|
107
|
+
* prop is provided, the default `Drawer.Header` omits its built-in close
|
|
108
|
+
* button so the rail can render it instead. Ignored on desktop side drawers.
|
|
109
|
+
*/
|
|
110
|
+
actions?: TypeDrawerActionProps[];
|
|
111
|
+
/**
|
|
112
|
+
* Opt out of the floating rail and keep the actions inside `Drawer.Header`
|
|
113
|
+
* (the pre-rail behavior). Useful for nested bottom sheets and snap-point
|
|
114
|
+
* drawers where the rail-above placement would collide with surrounding UI
|
|
115
|
+
* or fall off-screen at the highest snap point. Defaults to `false`.
|
|
116
|
+
*
|
|
117
|
+
* When `true`, the Drawer does NOT render the rail; consumers are
|
|
118
|
+
* responsible for rendering action buttons (and the close button) inside
|
|
119
|
+
* their `Drawer.Header`.
|
|
120
|
+
*/
|
|
121
|
+
actionsInHeader?: boolean;
|
|
56
122
|
}
|
|
57
123
|
interface TypeDrawerContentProps extends TypeBoxProps {
|
|
58
124
|
children?: React.ReactNode;
|
|
59
125
|
}
|
|
60
126
|
|
|
61
|
-
declare const
|
|
62
|
-
|
|
63
|
-
({ children, closeButtonLabel, direction, disableCloseOnClickOutside, id, isOpen, offset, onClose, zIndex, closeTargets, width, ...rest }: TypeDrawerProps): react_jsx_runtime.JSX.Element;
|
|
127
|
+
declare const DrawerHybrid: {
|
|
128
|
+
(props: TypeDrawerProps): react_jsx_runtime.JSX.Element;
|
|
64
129
|
Header: {
|
|
65
130
|
({ title, id, children, render, ...rest }: TypeDrawerHeaderProps): string | number | boolean | Iterable<React.ReactNode> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
66
131
|
displayName: string;
|
|
@@ -75,4 +140,29 @@ declare const DrawerContainer: {
|
|
|
75
140
|
};
|
|
76
141
|
};
|
|
77
142
|
|
|
78
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Single source of truth for the Drawer context. Both the Tailwind and the
|
|
145
|
+
* styled-components shells provide this exact context, and the shared
|
|
146
|
+
* sub-components (`Drawer.CloseButton`, `Drawer.Header`) consume it — so there
|
|
147
|
+
* must be exactly one context identity, or the close button can't see its
|
|
148
|
+
* provider.
|
|
149
|
+
*/
|
|
150
|
+
declare const DrawerContext: React.Context<TypeDrawerContext>;
|
|
151
|
+
|
|
152
|
+
declare const RAIL_BUTTON_SIZE = 44;
|
|
153
|
+
declare const RAIL_BUTTON_HEIGHT = 32;
|
|
154
|
+
declare const RAIL_OFFSET = 12;
|
|
155
|
+
declare const RAIL_GAP = 12;
|
|
156
|
+
interface TypeActionRailProps {
|
|
157
|
+
children: React.ReactNode;
|
|
158
|
+
/** When true, render horizontally above the parent (bottom-sheet mobile pattern). */
|
|
159
|
+
isMobile?: boolean;
|
|
160
|
+
/** Accessible group label for the rail. */
|
|
161
|
+
"aria-label"?: string;
|
|
162
|
+
}
|
|
163
|
+
declare const ActionRail: React.FC<TypeActionRailProps>;
|
|
164
|
+
|
|
165
|
+
type TypeActionRailButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
166
|
+
declare const ActionRailButton: React.ForwardRefExoticComponent<TypeActionRailButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
167
|
+
|
|
168
|
+
export { ActionRail, ActionRailButton, DrawerHybrid as Drawer, DrawerContext, RAIL_BUTTON_HEIGHT, RAIL_BUTTON_SIZE, RAIL_GAP, RAIL_OFFSET, type TypeActionRailButtonProps, type TypeActionRailProps, type TypeDrawerActionProps, type TypeDrawerCloseButtonProps, type TypeDrawerContentProps, type TypeDrawerContext, type TypeDrawerHeaderProps, type TypeDrawerProps, type TypeDrawerSnapPoint, DrawerHybrid as default };
|