@sproutsocial/seeds-react-modal 2.4.9 → 2.5.1

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.
Files changed (36) hide show
  1. package/.turbo/turbo-build.log +27 -27
  2. package/CHANGELOG.md +70 -0
  3. package/dist/{Modal-ki8oiGbC.d.mts → Modal-DTeKLfEI.d.mts} +1 -1
  4. package/dist/{Modal-ki8oiGbC.d.ts → Modal-DTeKLfEI.d.ts} +1 -1
  5. package/dist/{ModalAction-BHG3Zbd9.d.mts → ModalExternalTrigger-BnbJk9zY.d.mts} +85 -3
  6. package/dist/{ModalAction-BHG3Zbd9.d.ts → ModalExternalTrigger-BnbJk9zY.d.ts} +85 -3
  7. package/dist/esm/{chunk-HOGEFGDN.js → chunk-62MRZAJV.js} +32 -10
  8. package/dist/esm/{chunk-HOGEFGDN.js.map → chunk-62MRZAJV.js.map} +1 -1
  9. package/dist/esm/{chunk-IYDY4OPB.js → chunk-72GBDCA2.js} +17 -1
  10. package/dist/esm/chunk-72GBDCA2.js.map +1 -0
  11. package/dist/esm/index.js +10 -4
  12. package/dist/esm/index.js.map +1 -1
  13. package/dist/esm/v1/index.js +1 -1
  14. package/dist/esm/v2/index.js +1 -1
  15. package/dist/index.d.mts +3 -3
  16. package/dist/index.d.ts +3 -3
  17. package/dist/index.js +81 -11
  18. package/dist/index.js.map +1 -1
  19. package/dist/v1/index.d.mts +2 -2
  20. package/dist/v1/index.d.ts +2 -2
  21. package/dist/v1/index.js +16 -0
  22. package/dist/v1/index.js.map +1 -1
  23. package/dist/v2/index.d.mts +4 -77
  24. package/dist/v2/index.d.ts +4 -77
  25. package/dist/v2/index.js +31 -9
  26. package/dist/v2/index.js.map +1 -1
  27. package/package.json +7 -7
  28. package/src/Modal.stories.tsx +64 -0
  29. package/src/__tests__/v1/Modal.test.tsx +146 -1
  30. package/src/__tests__/v2/Modal.test.tsx +77 -0
  31. package/src/index.ts +4 -0
  32. package/src/v1/Modal.tsx +30 -0
  33. package/src/v2/ModalTypes.ts +9 -2
  34. package/src/v2/ModalV2.stories.tsx +268 -49
  35. package/src/v2/components/ModalFooter.tsx +15 -4
  36. package/dist/esm/chunk-IYDY4OPB.js.map +0 -1
package/dist/v1/index.js CHANGED
@@ -214,11 +214,27 @@ var Modal = (props) => {
214
214
  } = props;
215
215
  const isCloseable = Boolean(onClose);
216
216
  const appElement = appElementSelector && document ? document.querySelector(appElementSelector) : void 0;
217
+ const handleContentRef = React2.useCallback(
218
+ (contentEl) => {
219
+ if (!contentEl) return;
220
+ const portal = contentEl.parentElement?.parentElement;
221
+ if (portal) {
222
+ portal.style.pointerEvents = "auto";
223
+ portal.addEventListener("pointerdown", (e) => {
224
+ if (document.body.style.pointerEvents === "none") {
225
+ e.stopPropagation();
226
+ }
227
+ });
228
+ }
229
+ },
230
+ []
231
+ );
217
232
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
218
233
  Container,
219
234
  {
220
235
  appElement,
221
236
  ariaHideApp: !!appElement,
237
+ contentRef: handleContentRef,
222
238
  isOpen,
223
239
  contentLabel: label,
224
240
  onRequestClose: onClose || (() => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/v1/index.ts","../../src/v1/Modal.tsx","../../src/v1/styles.tsx"],"sourcesContent":["// V1 Modal - Explicit exports for optimal tree shaking\nimport Modal from \"./Modal\";\n\nexport default Modal;\nexport { Modal };\n\n// Explicit type exports\nexport type {\n TypeModalProps,\n TypeModalHeaderProps,\n TypeModalFooterProps,\n TypeModalContentProps,\n TypeModalCloseButtonProps,\n} from \"./ModalTypes\";\n","import * as React from \"react\";\nimport { useContext } from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport { Container, Content, Header, Footer, Body } from \"./styles\";\nimport type {\n TypeModalProps,\n TypeModalCloseButtonProps,\n TypeModalContentProps,\n TypeModalFooterProps,\n TypeModalHeaderProps,\n} from \"./ModalTypes\";\n\ntype TypeModalContext = Partial<{\n onClose: () => void;\n closeButtonLabel: string;\n label: string;\n}>;\n\nconst ModalContext = React.createContext<TypeModalContext>({});\n\nconst ModalHeader = (props: TypeModalHeaderProps) => {\n const { title, subtitle, children, bordered, ...rest } = props;\n return (\n <Header bordered={title || subtitle || bordered} {...rest}>\n {children ? (\n children\n ) : (\n <React.Fragment>\n <Box>\n {title && (\n <Text as=\"h1\" fontSize={400} fontWeight=\"semibold\">\n {title}\n </Text>\n )}\n {subtitle && (\n <Text as=\"div\" fontSize={200}>\n {subtitle}\n </Text>\n )}\n </Box>\n <Box display=\"flex\" alignItems=\"center\" justify-content=\"flex-end\">\n <ModalCloseButton ml={400} />\n </Box>\n </React.Fragment>\n )}\n </Header>\n );\n};\n\nconst ModalCloseButton = (props: TypeModalCloseButtonProps) => {\n const { onClose, closeButtonLabel } = useContext(ModalContext);\n if (!onClose) return null;\n return (\n <Button onClick={onClose} {...props}>\n <Icon name=\"x-outline\" ariaLabel={closeButtonLabel} />\n </Button>\n );\n};\n\nconst ModalFooter = ({\n bg = \"container.background.base\",\n ...rest\n}: TypeModalFooterProps) => (\n <Footer\n bg={bg}\n borderTop={500}\n borderColor=\"container.border.base\"\n {...rest}\n />\n);\n\nconst ModalContent = React.forwardRef(\n ({ children, ...rest }: TypeModalContentProps, ref) => {\n const { label } = useContext(ModalContext);\n return (\n <Content data-qa-modal data-qa-label={label} ref={ref} {...rest}>\n {children}\n </Content>\n );\n }\n);\n\n/**\n * The modal you want\n */\nconst Modal = (props: TypeModalProps) => {\n const {\n appElementSelector,\n children,\n isOpen,\n label,\n onClose,\n closeButtonLabel,\n width = \"800px\",\n zIndex = 6,\n data = {},\n ...rest\n } = props;\n\n const isCloseable = Boolean(onClose);\n const appElement =\n appElementSelector && document\n ? (document.querySelector(appElementSelector) as HTMLElement)\n : undefined;\n\n return (\n <Container\n appElement={appElement}\n ariaHideApp={!!appElement}\n isOpen={isOpen}\n contentLabel={label}\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n onRequestClose={onClose || (() => {})}\n shouldFocusAfterRender={true}\n shouldCloseOnOverlayClick={isCloseable}\n shouldCloseOnEsc={isCloseable}\n shouldReturnFocusAfterClose={true}\n closeTimeoutMS={200}\n role=\"dialog\"\n width={width}\n zIndex={zIndex}\n data={{\n \"qa-modal\": \"\",\n \"qa-modal-isopen\": isOpen,\n ...data,\n }}\n {...rest}\n >\n <React.Fragment>\n <Body />\n\n <ModalContext.Provider\n value={{\n onClose,\n closeButtonLabel,\n label,\n }}\n >\n {children}\n </ModalContext.Provider>\n </React.Fragment>\n </Container>\n );\n};\n\nModalHeader.displayName = \"Modal.Header\";\nModalFooter.displayName = \"Modal.Footer\";\nModalContent.displayName = \"Modal.Content\";\nModalCloseButton.displayName = \"Modal.CloseButton\";\n\nModal.Header = ModalHeader;\nModal.Footer = ModalFooter;\nModal.Content = ModalContent;\nModal.CloseButton = ModalCloseButton;\n\nexport default Modal;\n","import React from \"react\";\nimport styled, { createGlobalStyle } from \"styled-components\";\nimport { width, zIndex } from \"styled-system\";\nimport ReactModal from \"react-modal\";\nimport { COMMON } from \"@sproutsocial/seeds-react-system-props\";\nimport Box, { type TypeContainerProps } from \"@sproutsocial/seeds-react-box\";\n\n// This is the max space allowed between the modal and the edge of the browser\nconst BODY_PADDING = \"64px\";\n\nconst ReactModalAdapter = ({\n className = \"\",\n ...props\n}: { className?: string } & Omit<\n ReactModal.Props,\n \"portalClassName\" | \"className\" | \"overlayClassName\"\n>) => {\n // We want to create *__Content and *__Overlay class names on the subcomponents.\n // Because `className` could be a space-separated list of class names, we make\n // sure that we append `__Content` and `__Overlay` to every class name.\n const contentClassName = className\n .split(\" \")\n .map((className) => `${className} ${className}__Content`)\n .join(\" \");\n\n const overlayClassName = className\n .split(\" \")\n .map((className) => `${className} ${className}__Overlay`)\n .join(\" \");\n\n return (\n <ReactModal\n portalClassName={className}\n className={contentClassName}\n overlayClassName={overlayClassName}\n {...props}\n />\n );\n};\n\nexport const Body = createGlobalStyle`\n .ReactModal__Body--open {\n overflow: hidden;\n }\n`;\n\nexport const Container = styled(ReactModalAdapter)<TypeContainerProps>`\n &__Overlay {\n position: fixed;\n top: 0px;\n left: 0px;\n right: 0px;\n bottom: 0px;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: ${(props) => props.theme.colors.overlay.background.base};\n opacity: 0;\n will-change: opacity;\n transition: opacity ${(props) => props.theme.duration.medium}\n ${(props) => props.theme.easing.ease_inout};\n\n ${zIndex}\n\n &.ReactModal__Overlay--after-open {\n opacity: 1;\n }\n &.ReactModal__Overlay--before-close {\n opacity: 0;\n }\n }\n\n &__Content {\n display: flex;\n flex-direction: column;\n background: ${(props) => props.theme.colors.container.background.base};\n border-radius: ${(props) => props.theme.radii[600]};\n box-shadow: ${(props) => props.theme.shadows.medium};\n filter: blur(0);\n color: ${(props) => props.theme.colors.text.body};\n\n outline: none;\n max-width: calc(100vw - ${BODY_PADDING});\n max-height: calc(100vh - ${BODY_PADDING});\n @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n /**\n * This prevents the modal from being very short in IE11. Better too big\n * than too small.\n */\n height: calc(100vh - ${BODY_PADDING});\n }\n\n ${width}\n\n ${COMMON}\n }\n`;\n\nexport const Content = styled(Box)`\n font-family: ${(props) => props.theme.fontFamily};\n min-height: 80px;\n overflow-y: auto;\n flex: 1 1 auto;\n padding: ${(props) => props.theme.space[400]}\n ${(props) => props.theme.space[450]};\n @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n /* 'flex-basis: auto' breaks overflow in IE11 */\n flex-basis: 100%;\n }\n`;\n\nexport const HeaderContainer = styled(Box)`\n font-family: ${(props) => props.theme.fontFamily};\n padding: ${(props) => props.theme.space[400]}\n ${(props) => props.theme.space[450]};\n`;\n\nexport const Header = styled(HeaderContainer)<{ bordered?: boolean }>`\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex: 0 0 auto;\n border-bottom-width: ${(props) => props.theme.borderWidths[500]};\n border-bottom-color: ${(props) =>\n props.bordered ? props.theme.colors.container.border.base : \"transparent\"};\n border-bottom-style: solid;\n`;\n\nexport const Footer = styled(Box)`\n flex: 0 0 auto;\n font-family: ${(props) => props.theme.fontFamily};\n padding: ${(props) => props.theme.space[400]}\n ${(props) => props.theme.space[450]};\n border-bottom-right-radius: ${(props) => props.theme.radii[500]};\n border-bottom-left-radius: ${(props) => props.theme.radii[500]};\n`;\n\nContainer.displayName = \"ModalContainer\";\nContent.displayName = \"Content\";\nHeader.displayName = \"Modal.Header\";\nFooter.displayName = \"Modal.Footer\";\n"],"mappings":"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","names":["React","import_react","import_seeds_react_box","className","ReactModal","styled","Box","import_jsx_runtime","Box","Text","Button","Icon","width","zIndex"]}
1
+ {"version":3,"sources":["../../src/v1/index.ts","../../src/v1/Modal.tsx","../../src/v1/styles.tsx"],"sourcesContent":["// V1 Modal - Explicit exports for optimal tree shaking\nimport Modal from \"./Modal\";\n\nexport default Modal;\nexport { Modal };\n\n// Explicit type exports\nexport type {\n TypeModalProps,\n TypeModalHeaderProps,\n TypeModalFooterProps,\n TypeModalContentProps,\n TypeModalCloseButtonProps,\n} from \"./ModalTypes\";\n","import * as React from \"react\";\nimport { useContext } from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport { Container, Content, Header, Footer, Body } from \"./styles\";\nimport type {\n TypeModalProps,\n TypeModalCloseButtonProps,\n TypeModalContentProps,\n TypeModalFooterProps,\n TypeModalHeaderProps,\n} from \"./ModalTypes\";\n\ntype TypeModalContext = Partial<{\n onClose: () => void;\n closeButtonLabel: string;\n label: string;\n}>;\n\nconst ModalContext = React.createContext<TypeModalContext>({});\n\nconst ModalHeader = (props: TypeModalHeaderProps) => {\n const { title, subtitle, children, bordered, ...rest } = props;\n return (\n <Header bordered={title || subtitle || bordered} {...rest}>\n {children ? (\n children\n ) : (\n <React.Fragment>\n <Box>\n {title && (\n <Text as=\"h1\" fontSize={400} fontWeight=\"semibold\">\n {title}\n </Text>\n )}\n {subtitle && (\n <Text as=\"div\" fontSize={200}>\n {subtitle}\n </Text>\n )}\n </Box>\n <Box display=\"flex\" alignItems=\"center\" justify-content=\"flex-end\">\n <ModalCloseButton ml={400} />\n </Box>\n </React.Fragment>\n )}\n </Header>\n );\n};\n\nconst ModalCloseButton = (props: TypeModalCloseButtonProps) => {\n const { onClose, closeButtonLabel } = useContext(ModalContext);\n if (!onClose) return null;\n return (\n <Button onClick={onClose} {...props}>\n <Icon name=\"x-outline\" ariaLabel={closeButtonLabel} />\n </Button>\n );\n};\n\nconst ModalFooter = ({\n bg = \"container.background.base\",\n ...rest\n}: TypeModalFooterProps) => (\n <Footer\n bg={bg}\n borderTop={500}\n borderColor=\"container.border.base\"\n {...rest}\n />\n);\n\nconst ModalContent = React.forwardRef(\n ({ children, ...rest }: TypeModalContentProps, ref) => {\n const { label } = useContext(ModalContext);\n return (\n <Content data-qa-modal data-qa-label={label} ref={ref} {...rest}>\n {children}\n </Content>\n );\n }\n);\n\n/**\n * The modal you want\n */\nconst Modal = (props: TypeModalProps) => {\n const {\n appElementSelector,\n children,\n isOpen,\n label,\n onClose,\n closeButtonLabel,\n width = \"800px\",\n zIndex = 6,\n data = {},\n ...rest\n } = props;\n\n const isCloseable = Boolean(onClose);\n const appElement =\n appElementSelector && document\n ? (document.querySelector(appElementSelector) as HTMLElement)\n : undefined;\n\n /**\n * When a Radix Dialog (Modal V2) is open it sets `pointer-events: none` on\n * `document.body` and listens for `pointerdown` on the document to detect\n * \"outside\" clicks. react-modal portals its overlay to body, so:\n * 1. The overlay inherits `pointer-events: none` → unclickable\n * 2. Clicks on the overlay bubble to document → Radix dismisses Modal V2\n *\n * We use `contentRef` to reach the portal DOM and fix both issues.\n */\n const handleContentRef = React.useCallback(\n (contentEl: HTMLElement | null) => {\n if (!contentEl) return;\n // DOM structure: body > portal > overlay > content\n const portal = contentEl.parentElement?.parentElement;\n if (portal) {\n portal.style.pointerEvents = \"auto\";\n portal.addEventListener(\"pointerdown\", (e) => {\n // Only stop propagation when Radix Dialog has disabled body pointer events.\n // This avoids interfering with document-level listeners (analytics, other\n // click-outside patterns) when no Modal V2 is open.\n if (document.body.style.pointerEvents === \"none\") {\n e.stopPropagation();\n }\n });\n }\n },\n []\n );\n\n return (\n <Container\n appElement={appElement}\n ariaHideApp={!!appElement}\n contentRef={handleContentRef}\n isOpen={isOpen}\n contentLabel={label}\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n onRequestClose={onClose || (() => {})}\n shouldFocusAfterRender={true}\n shouldCloseOnOverlayClick={isCloseable}\n shouldCloseOnEsc={isCloseable}\n shouldReturnFocusAfterClose={true}\n closeTimeoutMS={200}\n role=\"dialog\"\n width={width}\n zIndex={zIndex}\n data={{\n \"qa-modal\": \"\",\n \"qa-modal-isopen\": isOpen,\n ...data,\n }}\n {...rest}\n >\n <React.Fragment>\n <Body />\n\n <ModalContext.Provider\n value={{\n onClose,\n closeButtonLabel,\n label,\n }}\n >\n {children}\n </ModalContext.Provider>\n </React.Fragment>\n </Container>\n );\n};\n\nModalHeader.displayName = \"Modal.Header\";\nModalFooter.displayName = \"Modal.Footer\";\nModalContent.displayName = \"Modal.Content\";\nModalCloseButton.displayName = \"Modal.CloseButton\";\n\nModal.Header = ModalHeader;\nModal.Footer = ModalFooter;\nModal.Content = ModalContent;\nModal.CloseButton = ModalCloseButton;\n\nexport default Modal;\n","import React from \"react\";\nimport styled, { createGlobalStyle } from \"styled-components\";\nimport { width, zIndex } from \"styled-system\";\nimport ReactModal from \"react-modal\";\nimport { COMMON } from \"@sproutsocial/seeds-react-system-props\";\nimport Box, { type TypeContainerProps } from \"@sproutsocial/seeds-react-box\";\n\n// This is the max space allowed between the modal and the edge of the browser\nconst BODY_PADDING = \"64px\";\n\nconst ReactModalAdapter = ({\n className = \"\",\n ...props\n}: { className?: string } & Omit<\n ReactModal.Props,\n \"portalClassName\" | \"className\" | \"overlayClassName\"\n>) => {\n // We want to create *__Content and *__Overlay class names on the subcomponents.\n // Because `className` could be a space-separated list of class names, we make\n // sure that we append `__Content` and `__Overlay` to every class name.\n const contentClassName = className\n .split(\" \")\n .map((className) => `${className} ${className}__Content`)\n .join(\" \");\n\n const overlayClassName = className\n .split(\" \")\n .map((className) => `${className} ${className}__Overlay`)\n .join(\" \");\n\n return (\n <ReactModal\n portalClassName={className}\n className={contentClassName}\n overlayClassName={overlayClassName}\n {...props}\n />\n );\n};\n\nexport const Body = createGlobalStyle`\n .ReactModal__Body--open {\n overflow: hidden;\n }\n`;\n\nexport const Container = styled(ReactModalAdapter)<TypeContainerProps>`\n &__Overlay {\n position: fixed;\n top: 0px;\n left: 0px;\n right: 0px;\n bottom: 0px;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: ${(props) => props.theme.colors.overlay.background.base};\n opacity: 0;\n will-change: opacity;\n transition: opacity ${(props) => props.theme.duration.medium}\n ${(props) => props.theme.easing.ease_inout};\n\n ${zIndex}\n\n &.ReactModal__Overlay--after-open {\n opacity: 1;\n }\n &.ReactModal__Overlay--before-close {\n opacity: 0;\n }\n }\n\n &__Content {\n display: flex;\n flex-direction: column;\n background: ${(props) => props.theme.colors.container.background.base};\n border-radius: ${(props) => props.theme.radii[600]};\n box-shadow: ${(props) => props.theme.shadows.medium};\n filter: blur(0);\n color: ${(props) => props.theme.colors.text.body};\n\n outline: none;\n max-width: calc(100vw - ${BODY_PADDING});\n max-height: calc(100vh - ${BODY_PADDING});\n @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n /**\n * This prevents the modal from being very short in IE11. Better too big\n * than too small.\n */\n height: calc(100vh - ${BODY_PADDING});\n }\n\n ${width}\n\n ${COMMON}\n }\n`;\n\nexport const Content = styled(Box)`\n font-family: ${(props) => props.theme.fontFamily};\n min-height: 80px;\n overflow-y: auto;\n flex: 1 1 auto;\n padding: ${(props) => props.theme.space[400]}\n ${(props) => props.theme.space[450]};\n @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n /* 'flex-basis: auto' breaks overflow in IE11 */\n flex-basis: 100%;\n }\n`;\n\nexport const HeaderContainer = styled(Box)`\n font-family: ${(props) => props.theme.fontFamily};\n padding: ${(props) => props.theme.space[400]}\n ${(props) => props.theme.space[450]};\n`;\n\nexport const Header = styled(HeaderContainer)<{ bordered?: boolean }>`\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex: 0 0 auto;\n border-bottom-width: ${(props) => props.theme.borderWidths[500]};\n border-bottom-color: ${(props) =>\n props.bordered ? props.theme.colors.container.border.base : \"transparent\"};\n border-bottom-style: solid;\n`;\n\nexport const Footer = styled(Box)`\n flex: 0 0 auto;\n font-family: ${(props) => props.theme.fontFamily};\n padding: ${(props) => props.theme.space[400]}\n ${(props) => props.theme.space[450]};\n border-bottom-right-radius: ${(props) => props.theme.radii[500]};\n border-bottom-left-radius: ${(props) => props.theme.radii[500]};\n`;\n\nContainer.displayName = \"ModalContainer\";\nContent.displayName = \"Content\";\nHeader.displayName = \"Modal.Header\";\nFooter.displayName = \"Modal.Footer\";\n"],"mappings":"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","names":["React","import_react","import_seeds_react_box","className","ReactModal","styled","Box","import_jsx_runtime","Box","Text","Button","Icon","width","zIndex"]}
@@ -1,84 +1,11 @@
1
- export { M as Modal, g as ModalAction, d as ModalBody, e as ModalCloseWrapper, p as ModalCloseWrapperProps, i as ModalCustomFooter, h as ModalCustomHeader, a as ModalDescription, c as ModalFooter, b as ModalHeader, f as ModalRail, o as TypeModalActionProps, l as TypeModalBodyProps, m as TypeModalDescriptionProps, k as TypeModalFooterProps, j as TypeModalHeaderProps, T as TypeModalProps, n as TypeModalRailProps, q as useModalExternalTrigger, u as useModalTriggerProps } from '../ModalAction-BHG3Zbd9.mjs';
2
- import * as React from 'react';
3
- import { TypeButtonProps } from '@sproutsocial/seeds-react-button';
1
+ export { l as Modal, M as ModalAction, a as ModalBody, b as ModalCloseWrapper, c as ModalCloseWrapperProps, d as ModalCustomFooter, e as ModalCustomHeader, f as ModalDescription, g as ModalExternalTrigger, h as ModalExternalTriggerProps, i as ModalFooter, j as ModalHeader, k as ModalRail, T as TypeModalActionProps, n as TypeModalBodyProps, o as TypeModalDescriptionProps, p as TypeModalFooterProps, q as TypeModalHeaderProps, r as TypeModalProps, m as TypeModalRailProps, u as useModalExternalTrigger, s as useModalTriggerProps } from '../ModalExternalTrigger-BnbJk9zY.mjs';
4
2
  import 'react/jsx-runtime';
3
+ import 'react';
5
4
  import 'styled-components';
6
5
  import '@sproutsocial/seeds-react-box';
7
6
  import '@radix-ui/react-dialog';
8
7
  import '@sproutsocial/seeds-react-icon';
9
-
10
- /**
11
- * Props for ModalExternalTrigger component.
12
- */
13
- interface ModalExternalTriggerProps extends Omit<TypeButtonProps, "onClick"> {
14
- /** Callback when button is clicked to trigger modal open */
15
- onTrigger: () => void;
16
- /** Whether the modal is currently open (for ARIA expanded state) */
17
- isOpen: boolean;
18
- /** Optional modal ID for aria-controls attribute */
19
- modalId?: string;
20
- /** Optional onClick handler (called before onTrigger) */
21
- onClick?: React.MouseEventHandler<HTMLButtonElement>;
22
- }
23
- /**
24
- * A Button component pre-configured for triggering modals from outside the Modal component tree.
25
- *
26
- * ⚠️ **NOT RECOMMENDED** - Prefer using modalTrigger prop or ModalTrigger component.
27
- * Use this component ONLY as a last resort when architectural constraints prevent keeping
28
- * the trigger inside the Modal component tree.
29
- *
30
- * This component wraps the Seeds Button with automatic ARIA attributes for modal triggers.
31
- * However, focus restoration still requires manual handling via onCloseAutoFocus callback
32
- * due to Radix UI's architectural limitations with external triggers.
33
- *
34
- * **Why modalTrigger prop is better:**
35
- * - Automatic ARIA attributes
36
- * - Automatic focus restoration (no onCloseAutoFocus needed)
37
- * - Better touch device support
38
- * - Follows WAI-ARIA Dialog best practices
39
- *
40
- * **When to use ModalExternalTrigger:**
41
- * - Trigger must live outside Modal component tree (e.g., in a page header)
42
- * - Using Seeds Button as the trigger
43
- * - Want automatic ARIA attributes without manual hook usage
44
- *
45
- * **Usage pattern with focus restoration:**
46
- * You must still handle focus restoration manually by passing a ref and implementing
47
- * onCloseAutoFocus on the Modal component.
48
- *
49
- * @example
50
- * ```tsx
51
- * const [isOpen, setIsOpen] = useState(false);
52
- * const triggerRef = useRef<HTMLButtonElement>(null);
53
- *
54
- * return (
55
- * <>
56
- * <ModalExternalTrigger
57
- * ref={triggerRef}
58
- * isOpen={isOpen}
59
- * onTrigger={() => setIsOpen(true)}
60
- * appearance="primary"
61
- * >
62
- * Open Modal
63
- * </ModalExternalTrigger>
64
- *
65
- * <Modal
66
- * open={isOpen}
67
- * onOpenChange={setIsOpen}
68
- * onCloseAutoFocus={(e) => {
69
- * e.preventDefault();
70
- * triggerRef.current?.focus();
71
- * }}
72
- * >
73
- * <ModalBody>Content</ModalBody>
74
- * </Modal>
75
- * </>
76
- * );
77
- * ```
78
- *
79
- * @see useModalExternalTrigger - Hook alternative for non-Button triggers
80
- */
81
- declare const ModalExternalTrigger: React.ForwardRefExoticComponent<Omit<ModalExternalTriggerProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
8
+ import '@sproutsocial/seeds-react-button';
82
9
 
83
10
  declare const DEFAULT_MODAL_WIDTH = "800px";
84
11
  declare const DEFAULT_MODAL_BG = "container.background.base";
@@ -90,4 +17,4 @@ declare const MODAL_SIZE_PRESETS: {
90
17
  readonly full: "90vw";
91
18
  };
92
19
 
93
- export { BODY_PADDING, DEFAULT_MODAL_BG, DEFAULT_MODAL_WIDTH, MODAL_SIZE_PRESETS, ModalExternalTrigger, type ModalExternalTriggerProps };
20
+ export { BODY_PADDING, DEFAULT_MODAL_BG, DEFAULT_MODAL_WIDTH, MODAL_SIZE_PRESETS };
@@ -1,84 +1,11 @@
1
- export { M as Modal, g as ModalAction, d as ModalBody, e as ModalCloseWrapper, p as ModalCloseWrapperProps, i as ModalCustomFooter, h as ModalCustomHeader, a as ModalDescription, c as ModalFooter, b as ModalHeader, f as ModalRail, o as TypeModalActionProps, l as TypeModalBodyProps, m as TypeModalDescriptionProps, k as TypeModalFooterProps, j as TypeModalHeaderProps, T as TypeModalProps, n as TypeModalRailProps, q as useModalExternalTrigger, u as useModalTriggerProps } from '../ModalAction-BHG3Zbd9.js';
2
- import * as React from 'react';
3
- import { TypeButtonProps } from '@sproutsocial/seeds-react-button';
1
+ export { l as Modal, M as ModalAction, a as ModalBody, b as ModalCloseWrapper, c as ModalCloseWrapperProps, d as ModalCustomFooter, e as ModalCustomHeader, f as ModalDescription, g as ModalExternalTrigger, h as ModalExternalTriggerProps, i as ModalFooter, j as ModalHeader, k as ModalRail, T as TypeModalActionProps, n as TypeModalBodyProps, o as TypeModalDescriptionProps, p as TypeModalFooterProps, q as TypeModalHeaderProps, r as TypeModalProps, m as TypeModalRailProps, u as useModalExternalTrigger, s as useModalTriggerProps } from '../ModalExternalTrigger-BnbJk9zY.js';
4
2
  import 'react/jsx-runtime';
3
+ import 'react';
5
4
  import 'styled-components';
6
5
  import '@sproutsocial/seeds-react-box';
7
6
  import '@radix-ui/react-dialog';
8
7
  import '@sproutsocial/seeds-react-icon';
9
-
10
- /**
11
- * Props for ModalExternalTrigger component.
12
- */
13
- interface ModalExternalTriggerProps extends Omit<TypeButtonProps, "onClick"> {
14
- /** Callback when button is clicked to trigger modal open */
15
- onTrigger: () => void;
16
- /** Whether the modal is currently open (for ARIA expanded state) */
17
- isOpen: boolean;
18
- /** Optional modal ID for aria-controls attribute */
19
- modalId?: string;
20
- /** Optional onClick handler (called before onTrigger) */
21
- onClick?: React.MouseEventHandler<HTMLButtonElement>;
22
- }
23
- /**
24
- * A Button component pre-configured for triggering modals from outside the Modal component tree.
25
- *
26
- * ⚠️ **NOT RECOMMENDED** - Prefer using modalTrigger prop or ModalTrigger component.
27
- * Use this component ONLY as a last resort when architectural constraints prevent keeping
28
- * the trigger inside the Modal component tree.
29
- *
30
- * This component wraps the Seeds Button with automatic ARIA attributes for modal triggers.
31
- * However, focus restoration still requires manual handling via onCloseAutoFocus callback
32
- * due to Radix UI's architectural limitations with external triggers.
33
- *
34
- * **Why modalTrigger prop is better:**
35
- * - Automatic ARIA attributes
36
- * - Automatic focus restoration (no onCloseAutoFocus needed)
37
- * - Better touch device support
38
- * - Follows WAI-ARIA Dialog best practices
39
- *
40
- * **When to use ModalExternalTrigger:**
41
- * - Trigger must live outside Modal component tree (e.g., in a page header)
42
- * - Using Seeds Button as the trigger
43
- * - Want automatic ARIA attributes without manual hook usage
44
- *
45
- * **Usage pattern with focus restoration:**
46
- * You must still handle focus restoration manually by passing a ref and implementing
47
- * onCloseAutoFocus on the Modal component.
48
- *
49
- * @example
50
- * ```tsx
51
- * const [isOpen, setIsOpen] = useState(false);
52
- * const triggerRef = useRef<HTMLButtonElement>(null);
53
- *
54
- * return (
55
- * <>
56
- * <ModalExternalTrigger
57
- * ref={triggerRef}
58
- * isOpen={isOpen}
59
- * onTrigger={() => setIsOpen(true)}
60
- * appearance="primary"
61
- * >
62
- * Open Modal
63
- * </ModalExternalTrigger>
64
- *
65
- * <Modal
66
- * open={isOpen}
67
- * onOpenChange={setIsOpen}
68
- * onCloseAutoFocus={(e) => {
69
- * e.preventDefault();
70
- * triggerRef.current?.focus();
71
- * }}
72
- * >
73
- * <ModalBody>Content</ModalBody>
74
- * </Modal>
75
- * </>
76
- * );
77
- * ```
78
- *
79
- * @see useModalExternalTrigger - Hook alternative for non-Button triggers
80
- */
81
- declare const ModalExternalTrigger: React.ForwardRefExoticComponent<Omit<ModalExternalTriggerProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
8
+ import '@sproutsocial/seeds-react-button';
82
9
 
83
10
  declare const DEFAULT_MODAL_WIDTH = "800px";
84
11
  declare const DEFAULT_MODAL_BG = "container.background.base";
@@ -90,4 +17,4 @@ declare const MODAL_SIZE_PRESETS: {
90
17
  readonly full: "90vw";
91
18
  };
92
19
 
93
- export { BODY_PADDING, DEFAULT_MODAL_BG, DEFAULT_MODAL_WIDTH, MODAL_SIZE_PRESETS, ModalExternalTrigger, type ModalExternalTriggerProps };
20
+ export { BODY_PADDING, DEFAULT_MODAL_BG, DEFAULT_MODAL_WIDTH, MODAL_SIZE_PRESETS };
package/dist/v2/index.js CHANGED
@@ -523,15 +523,22 @@ var ModalCustomFooter = (0, import_styled_components3.default)(import_seeds_reac
523
523
  `;
524
524
  ModalCustomFooter.displayName = "ModalCustomFooter";
525
525
  var ModalFooter = (props) => {
526
- const { cancelButton, primaryButton, leftAction, ...rest } = props;
526
+ const {
527
+ cancelButton,
528
+ primaryButton,
529
+ leftAction,
530
+ closeOnPrimaryAction = true,
531
+ ...rest
532
+ } = props;
527
533
  if (!cancelButton && !primaryButton && !leftAction) {
528
534
  return null;
529
535
  }
536
+ const wrappedPrimaryButton = primaryButton && closeOnPrimaryAction ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ModalCloseWrapper, { children: primaryButton }) : primaryButton;
530
537
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(ModalCustomFooter, { "data-slot": "modal-footer", "data-qa-modal-footer": true, ...rest, children: [
531
538
  leftAction ? leftAction : null,
532
539
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_seeds_react_box2.default, { display: "flex", gap: 300, marginLeft: "auto", children: [
533
540
  cancelButton && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ModalCloseWrapper, { children: cancelButton }),
534
- primaryButton && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ModalCloseWrapper, { children: primaryButton })
541
+ wrappedPrimaryButton
535
542
  ] })
536
543
  ] });
537
544
  };
@@ -639,7 +646,6 @@ var import_seeds_react_icon = __toESM(require("@sproutsocial/seeds-react-icon"))
639
646
 
640
647
  // ../seeds-react-mixins/dist/esm/index.js
641
648
  var import_styled_components6 = require("styled-components");
642
- var import_seeds_react_theme = require("@sproutsocial/seeds-react-theme");
643
649
  var visuallyHidden = import_styled_components6.css`
644
650
  position: absolute;
645
651
  width: 1px;
@@ -651,11 +657,12 @@ var visuallyHidden = import_styled_components6.css`
651
657
  border: 0;
652
658
  `;
653
659
  var focusRing = import_styled_components6.css`
654
- box-shadow: 0 0 0 1px ${import_seeds_react_theme.theme.colors.button.primary.background.base},
660
+ box-shadow: 0 0 0 1px
661
+ ${({ theme }) => theme.colors.button.primary.background.base},
655
662
  0 0px 0px 4px
656
663
  color-mix(
657
664
  in srgb,
658
- ${import_seeds_react_theme.theme.colors.button.primary.background.base},
665
+ ${({ theme }) => theme.colors.button.primary.background.base},
659
666
  transparent 70%
660
667
  );
661
668
  outline: none;
@@ -665,15 +672,30 @@ var focusRing = import_styled_components6.css`
665
672
  }
666
673
  `;
667
674
  var pill = import_styled_components6.css`
668
- min-width: ${import_seeds_react_theme.theme.space[600]};
669
- min-height: ${import_seeds_react_theme.theme.space[600]};
670
- padding: ${import_seeds_react_theme.theme.space[300]};
671
- border-radius: ${import_seeds_react_theme.theme.radii.pill};
675
+ min-width: ${({ theme }) => theme.space[600]};
676
+ min-height: ${({ theme }) => theme.space[600]};
677
+ padding: ${({ theme }) => theme.space[300]};
678
+ border-radius: ${({ theme }) => theme.radii.pill};
672
679
  `;
673
680
  var disabled = import_styled_components6.css`
674
681
  opacity: 0.4;
675
682
  pointer-events: none;
676
683
  `;
684
+ var container = import_styled_components6.css`
685
+ background: ${({ theme }) => theme.colors.container.background.base};
686
+ border: ${({ theme }) => theme.borders[500]}
687
+ ${({ theme }) => theme.colors.container.border.base};
688
+ border-radius: ${({ theme }) => theme.radii.outer};
689
+ `;
690
+ var divider = import_styled_components6.css`
691
+ border-bottom: ${({ theme }) => theme.borderWidths[500]} solid
692
+ ${({ theme }) => theme.colors.container.border.base};
693
+ `;
694
+ var truncate = import_styled_components6.css`
695
+ text-overflow: ellipsis;
696
+ overflow: hidden;
697
+ white-space: nowrap;
698
+ `;
677
699
 
678
700
  // src/v2/components/ModalAction.tsx
679
701
  var import_jsx_runtime8 = require("react/jsx-runtime");