@sproutsocial/seeds-react-content-block 0.5.27 → 0.6.0

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/esm/index.js CHANGED
@@ -71,6 +71,7 @@ var CollapsibleContentBlock = ({
71
71
  children,
72
72
  isLoading,
73
73
  headerActions,
74
+ rightTitleElement,
74
75
  flushLayout,
75
76
  footerContent,
76
77
  footerActions,
@@ -97,6 +98,7 @@ var CollapsibleContentBlock = ({
97
98
  headingLevel: titleAs,
98
99
  subtitleAs,
99
100
  headerActions,
101
+ rightTitleElement,
100
102
  trigger: Collapsible.Trigger,
101
103
  triggerPosition: "left"
102
104
  }
@@ -137,6 +139,7 @@ var ContentBlockTailwind = ({
137
139
  children,
138
140
  isLoading,
139
141
  headerActions,
142
+ rightTitleElement,
140
143
  flushLayout,
141
144
  footerContent,
142
145
  footerActions,
@@ -151,7 +154,8 @@ var ContentBlockTailwind = ({
151
154
  subtitle,
152
155
  headingLevel: titleAs,
153
156
  subtitleAs,
154
- headerActions
157
+ headerActions,
158
+ rightTitleElement
155
159
  }
156
160
  ),
157
161
  /* @__PURE__ */ jsx(
@@ -233,6 +237,7 @@ var CollapsibleContentBlock2 = ({
233
237
  children,
234
238
  isLoading,
235
239
  headerActions,
240
+ rightTitleElement,
236
241
  contentProps,
237
242
  flushLayout,
238
243
  footerContent,
@@ -259,6 +264,7 @@ var CollapsibleContentBlock2 = ({
259
264
  headingLevel: titleAs,
260
265
  subtitleAs,
261
266
  headerActions,
267
+ rightTitleElement,
262
268
  trigger: Collapsible2.Trigger,
263
269
  triggerPosition: "left"
264
270
  }
@@ -299,6 +305,7 @@ var ContentBlockStyled = ({
299
305
  children,
300
306
  isLoading,
301
307
  headerActions,
308
+ rightTitleElement,
302
309
  contentProps,
303
310
  flushLayout,
304
311
  footerContent,
@@ -313,7 +320,8 @@ var ContentBlockStyled = ({
313
320
  subtitle,
314
321
  headingLevel: titleAs,
315
322
  subtitleAs,
316
- headerActions
323
+ headerActions,
324
+ rightTitleElement
317
325
  }
318
326
  ),
319
327
  /* @__PURE__ */ jsx2(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ContentBlock.tsx","../../src/ContentBlockHybrid.tsx","../../src/ContentBlockTailwind.tsx","../../src/ContentBlockStyled.tsx","../../src/styles.ts","../../src/index.ts"],"sourcesContent":["import React from \"react\";\nimport { Box } from \"@sproutsocial/seeds-react-box\";\nimport ContentBlockHybrid from \"./ContentBlockHybrid\";\n\nexport interface ContentBlockBaseProps {\n title: string;\n subtitle?: string;\n titleAs?: \"h1\" | \"h2\" | \"h3\" | \"h4\";\n subtitleAs?: \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"p\";\n isLoading?: boolean;\n children: React.ReactNode;\n headerActions?: React.ReactNode;\n contentProps?: React.ComponentProps<typeof Box>;\n /** Sets content area padding to 0 */\n flushLayout?: boolean;\n /** Left slot of the footer area */\n footerContent?: React.ReactNode;\n /** Right slot of the footer area */\n footerActions?: React.ReactNode;\n}\n\ntype StaticContentBlockProps = ContentBlockBaseProps & {\n isCollapsible?: false;\n isOpen?: never;\n defaultOpen?: never;\n onOpenChange?: never;\n};\n\nexport type CollapsibleContentBlockProps = ContentBlockBaseProps & {\n /** Enables collapse/expand behavior on the content area */\n isCollapsible: true;\n /** Controlled open state. When provided, the component is in controlled mode. */\n isOpen?: boolean;\n /** Initial open state for uncontrolled mode. Defaults to true. */\n defaultOpen?: boolean;\n /** Called when the open state changes */\n onOpenChange?: (open: boolean) => void;\n};\n\nexport type ContentBlockProps =\n | StaticContentBlockProps\n | CollapsibleContentBlockProps;\n\n/**\n * ContentBlock component. Automatically routes between the Tailwind\n * implementation (preferred) and the styled-components implementation (used when\n * `contentProps` carries styled-system props), mirroring the Button hybrid.\n */\nconst ContentBlock = (props: ContentBlockProps) => (\n <ContentBlockHybrid {...props} />\n);\n\nexport default ContentBlock;\n","/**\n * Hybrid ContentBlock\n *\n * Routes the whole component between the Tailwind implementation (preferred)\n * and the styled-components implementation (legacy fallback), mirroring\n * ButtonHybrid's single `hasStyledProps` gate.\n *\n * `contentProps` is ContentBlock's only styled-system passthrough surface: it\n * is spread onto the content `<Box>` and may carry props (`bg`, `py`, …) that a\n * plain Tailwind element cannot honor. When it does, render the styled-components\n * tree so those props still apply; otherwise use the lighter Tailwind path.\n */\n\nimport React from \"react\";\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport {\n ContentBlockTailwind,\n ContentFooterTailwind,\n type ContentFooterProps,\n} from \"./ContentBlockTailwind\";\nimport { ContentBlockStyled } from \"./ContentBlockStyled\";\nimport type { ContentBlockProps } from \"./ContentBlock\";\n\nconst ContentBlockHybrid = (props: ContentBlockProps) => {\n if (props.contentProps && hasStyledProps(props.contentProps)) {\n return <ContentBlockStyled {...props} />;\n }\n\n return <ContentBlockTailwind {...props} />;\n};\n\nexport default ContentBlockHybrid;\n\n/**\n * Hybrid ContentBlock footer.\n *\n * The footer exposes no styled-system props and no styled()-extendable surface\n * (FooterContainer is internal and never re-exported from index.ts), so the\n * Tailwind/CSS-class footer is always used — no routing predicate is needed here.\n * Kept as a separate export so the footer-override story/tests can render it\n * directly.\n */\nexport const ContentFooterHybrid = (props: ContentFooterProps) => (\n <ContentFooterTailwind {...props} />\n);\n","/**\n * Tailwind CSS implementation of the ContentBlock component.\n * Renders the whole component (card, content area, loader, footer) with plain\n * elements and the Seeds content-block CSS classes from content-block.css.\n * Child components (ContentHeader, Collapsible, Loader) are composed unchanged.\n */\n\nimport React, { useState } from \"react\";\nimport { Loader } from \"@sproutsocial/seeds-react-loader\";\nimport { Collapsible } from \"@sproutsocial/seeds-react-collapsible\";\nimport {\n ContentHeader,\n CollapsibleContentHeader,\n} from \"@sproutsocial/seeds-react-content-header\";\nimport type {\n ContentBlockBaseProps,\n ContentBlockProps,\n CollapsibleContentBlockProps,\n} from \"./ContentBlock\";\n\n// Utility for merging class names properly.\n// cn is NOT exported from @sproutsocial/seeds-react-utilities, so it is\n// reproduced locally here (mirrors ButtonTailwind.tsx).\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\nexport type ContentFooterProps = {\n footerContent?: React.ReactNode;\n footerActions?: React.ReactNode;\n className?: string;\n};\n\nexport const ContentFooterTailwind = ({\n footerContent,\n footerActions,\n className,\n}: ContentFooterProps) => (\n <div className={cn(\"seeds-content-block-footer\", className)}>\n {footerContent && <span>{footerContent}</span>}\n {footerActions && <span>{footerActions}</span>}\n </div>\n);\n\nconst ContentArea = ({\n isLoading,\n children,\n flushLayout,\n hasFooter,\n contentProps,\n}: Pick<\n ContentBlockBaseProps,\n \"isLoading\" | \"children\" | \"flushLayout\" | \"contentProps\"\n> & {\n hasFooter?: boolean;\n}) => {\n // By construction, any contentProps reaching the Tailwind path carries no\n // styled-system props (those route to ContentBlockStyled via hasStyledProps),\n // so the rest is pure DOM attributes safe to spread onto a div. Pull className\n // out and merge it via cn so the seeds-content-block-content class is\n // preserved, rendering className after the spread so the merged value wins\n // (mirrors ButtonTailwind).\n const { className, ...domProps } = contentProps ?? {};\n return (\n <div\n {...(domProps as React.HTMLAttributes<HTMLDivElement>)}\n className={cn(\n \"seeds-content-block-content\",\n {\n flush: !!flushLayout,\n \"no-footer\": !hasFooter,\n },\n className\n )}\n >\n {isLoading ? (\n <div className=\"seeds-content-block-loader\">\n <Loader delay={false} />\n </div>\n ) : (\n children\n )}\n </div>\n );\n};\n\nconst CollapsibleContentBlock = ({\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n flushLayout,\n footerContent,\n footerActions,\n contentProps,\n isOpen: controlledIsOpen,\n defaultOpen = true,\n onOpenChange,\n}: Omit<CollapsibleContentBlockProps, \"isCollapsible\">) => {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = controlledIsOpen !== undefined ? controlledIsOpen : internalOpen;\n const hasFooter = !!(footerContent || footerActions);\n\n const handleOpenChange = (newOpen: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalOpen(newOpen);\n }\n onOpenChange?.(newOpen);\n };\n\n return (\n <Collapsible isOpen={open} onOpenChange={handleOpenChange}>\n <section className=\"seeds-content-block\">\n <CollapsibleContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n trigger={Collapsible.Trigger}\n triggerPosition=\"left\"\n />\n <Collapsible.Panel>\n <ContentArea\n isLoading={isLoading}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n contentProps={contentProps}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooterTailwind\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Collapsible.Panel>\n </section>\n </Collapsible>\n );\n};\n\n/**\n * Tailwind/CSS-class implementation of the full ContentBlock. Preferred path;\n * the Hybrid routes here unless `contentProps` carries styled-system props.\n */\nexport const ContentBlockTailwind = ({\n isCollapsible,\n ...props\n}: ContentBlockProps) => {\n if (isCollapsible) {\n return <CollapsibleContentBlock {...props} />;\n }\n\n const {\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n flushLayout,\n footerContent,\n footerActions,\n contentProps,\n } = props;\n\n const hasFooter = !!(footerContent || footerActions);\n\n return (\n <section className=\"seeds-content-block\">\n <ContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n />\n <ContentArea\n isLoading={isLoading}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n contentProps={contentProps}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooterTailwind\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </section>\n );\n};\n","/**\n * Styled-components implementation of the full ContentBlock.\n *\n * This is the legacy fallback the Hybrid delegates to whenever `contentProps`\n * carries styled-system props (e.g. `bg`, `py`) that a plain Tailwind element\n * cannot honor. It reproduces the original Box/Container/FooterContainer tree\n * verbatim so styled-system passthrough and visual parity are preserved.\n */\n\nimport React, { useState } from \"react\";\nimport { Box } from \"@sproutsocial/seeds-react-box\";\nimport { Loader } from \"@sproutsocial/seeds-react-loader\";\nimport { Collapsible } from \"@sproutsocial/seeds-react-collapsible\";\nimport {\n ContentHeader,\n CollapsibleContentHeader,\n} from \"@sproutsocial/seeds-react-content-header\";\nimport { Container } from \"@sproutsocial/seeds-react-container\";\nimport { FooterContainer } from \"./styles\";\nimport type {\n ContentBlockBaseProps,\n ContentBlockProps,\n CollapsibleContentBlockProps,\n} from \"./ContentBlock\";\n\nconst ContentArea = ({\n isLoading,\n children,\n contentProps,\n flushLayout,\n hasFooter,\n}: Pick<\n ContentBlockBaseProps,\n \"isLoading\" | \"children\" | \"contentProps\" | \"flushLayout\"\n> & { hasFooter?: boolean }) => (\n <Box\n p={flushLayout ? 0 : 400}\n {...contentProps}\n borderBottomLeftRadius={hasFooter ? undefined : \"outer\"}\n borderBottomRightRadius={hasFooter ? undefined : \"outer\"}\n >\n {isLoading ? (\n <Box my={400}>\n <Loader delay={false} />\n </Box>\n ) : (\n children\n )}\n </Box>\n);\n\nconst ContentFooter = ({\n footerContent,\n footerActions,\n}: {\n footerContent?: React.ReactNode;\n footerActions?: React.ReactNode;\n}) => (\n <FooterContainer>\n {footerContent && <span>{footerContent}</span>}\n {footerActions && <span>{footerActions}</span>}\n </FooterContainer>\n);\n\nconst CollapsibleContentBlock = ({\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n contentProps,\n flushLayout,\n footerContent,\n footerActions,\n isOpen: controlledIsOpen,\n defaultOpen = true,\n onOpenChange,\n}: Omit<CollapsibleContentBlockProps, \"isCollapsible\">) => {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = controlledIsOpen !== undefined ? controlledIsOpen : internalOpen;\n const hasFooter = !!(footerContent || footerActions);\n\n const handleOpenChange = (newOpen: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalOpen(newOpen);\n }\n onOpenChange?.(newOpen);\n };\n\n return (\n <Collapsible isOpen={open} onOpenChange={handleOpenChange}>\n <Container as=\"section\">\n <CollapsibleContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n trigger={Collapsible.Trigger}\n triggerPosition=\"left\"\n />\n <Collapsible.Panel>\n <ContentArea\n isLoading={isLoading}\n contentProps={contentProps}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooter\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Collapsible.Panel>\n </Container>\n </Collapsible>\n );\n};\n\nexport const ContentBlockStyled = ({\n isCollapsible,\n ...props\n}: ContentBlockProps) => {\n if (isCollapsible) {\n return <CollapsibleContentBlock {...props} />;\n }\n\n const {\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n contentProps,\n flushLayout,\n footerContent,\n footerActions,\n } = props;\n\n const hasFooter = !!(footerContent || footerActions);\n\n return (\n <Container as=\"section\">\n <ContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n />\n <ContentArea\n isLoading={isLoading}\n contentProps={contentProps}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooter\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Container>\n );\n};\n","import styled from \"styled-components\";\n\nexport const FooterContainer = styled.div`\n box-sizing: border-box;\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n padding: ${({ theme }) => theme.space[400]};\n border-top: ${({ theme }) => theme.borderWidths[500]} solid\n ${({ theme }) => theme.colors.container.border.base};\n border-bottom-left-radius: ${({ theme }) => theme.radii.outer};\n border-bottom-right-radius: ${({ theme }) => theme.radii.outer};\n`;\n","import ContentBlock from \"./ContentBlock\";\n\nexport type { ContentBlockProps } from \"./ContentBlock\";\n\nexport default ContentBlock;\nexport { ContentBlock };\n"],"mappings":"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","names":["useState","Loader","Collapsible","ContentHeader","CollapsibleContentHeader","jsx","jsxs","ContentArea","Loader","CollapsibleContentBlock","useState","Collapsible","CollapsibleContentHeader","ContentHeader","jsx","jsx"]}
1
+ {"version":3,"sources":["../../src/ContentBlock.tsx","../../src/ContentBlockHybrid.tsx","../../src/ContentBlockTailwind.tsx","../../src/ContentBlockStyled.tsx","../../src/styles.ts","../../src/index.ts"],"sourcesContent":["import React from \"react\";\nimport { Box } from \"@sproutsocial/seeds-react-box\";\nimport ContentBlockHybrid from \"./ContentBlockHybrid\";\n\nexport interface ContentBlockBaseProps {\n title: string;\n subtitle?: string;\n titleAs?: \"h1\" | \"h2\" | \"h3\" | \"h4\";\n subtitleAs?: \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"p\";\n isLoading?: boolean;\n children: React.ReactNode;\n headerActions?: React.ReactNode;\n contentProps?: React.ComponentProps<typeof Box>;\n /** Sets content area padding to 0 */\n flushLayout?: boolean;\n /** Element rendered inline after the title text (e.g. a beta badge) */\n rightTitleElement?: React.ReactNode;\n /** Left slot of the footer area */\n footerContent?: React.ReactNode;\n /** Right slot of the footer area */\n footerActions?: React.ReactNode;\n}\n\ntype StaticContentBlockProps = ContentBlockBaseProps & {\n isCollapsible?: false;\n isOpen?: never;\n defaultOpen?: never;\n onOpenChange?: never;\n};\n\nexport type CollapsibleContentBlockProps = ContentBlockBaseProps & {\n /** Enables collapse/expand behavior on the content area */\n isCollapsible: true;\n /** Controlled open state. When provided, the component is in controlled mode. */\n isOpen?: boolean;\n /** Initial open state for uncontrolled mode. Defaults to true. */\n defaultOpen?: boolean;\n /** Called when the open state changes */\n onOpenChange?: (open: boolean) => void;\n};\n\nexport type ContentBlockProps =\n | StaticContentBlockProps\n | CollapsibleContentBlockProps;\n\n/**\n * ContentBlock component. Automatically routes between the Tailwind\n * implementation (preferred) and the styled-components implementation (used when\n * `contentProps` carries styled-system props), mirroring the Button hybrid.\n */\nconst ContentBlock = (props: ContentBlockProps) => (\n <ContentBlockHybrid {...props} />\n);\n\nexport default ContentBlock;\n","/**\n * Hybrid ContentBlock\n *\n * Routes the whole component between the Tailwind implementation (preferred)\n * and the styled-components implementation (legacy fallback), mirroring\n * ButtonHybrid's single `hasStyledProps` gate.\n *\n * `contentProps` is ContentBlock's only styled-system passthrough surface: it\n * is spread onto the content `<Box>` and may carry props (`bg`, `py`, …) that a\n * plain Tailwind element cannot honor. When it does, render the styled-components\n * tree so those props still apply; otherwise use the lighter Tailwind path.\n */\n\nimport React from \"react\";\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport {\n ContentBlockTailwind,\n ContentFooterTailwind,\n type ContentFooterProps,\n} from \"./ContentBlockTailwind\";\nimport { ContentBlockStyled } from \"./ContentBlockStyled\";\nimport type { ContentBlockProps } from \"./ContentBlock\";\n\nconst ContentBlockHybrid = (props: ContentBlockProps) => {\n if (props.contentProps && hasStyledProps(props.contentProps)) {\n return <ContentBlockStyled {...props} />;\n }\n\n return <ContentBlockTailwind {...props} />;\n};\n\nexport default ContentBlockHybrid;\n\n/**\n * Hybrid ContentBlock footer.\n *\n * The footer exposes no styled-system props and no styled()-extendable surface\n * (FooterContainer is internal and never re-exported from index.ts), so the\n * Tailwind/CSS-class footer is always used — no routing predicate is needed here.\n * Kept as a separate export so the footer-override story/tests can render it\n * directly.\n */\nexport const ContentFooterHybrid = (props: ContentFooterProps) => (\n <ContentFooterTailwind {...props} />\n);\n","/**\n * Tailwind CSS implementation of the ContentBlock component.\n * Renders the whole component (card, content area, loader, footer) with plain\n * elements and the Seeds content-block CSS classes from content-block.css.\n * Child components (ContentHeader, Collapsible, Loader) are composed unchanged.\n */\n\nimport React, { useState } from \"react\";\nimport { Loader } from \"@sproutsocial/seeds-react-loader\";\nimport { Collapsible } from \"@sproutsocial/seeds-react-collapsible\";\nimport {\n ContentHeader,\n CollapsibleContentHeader,\n} from \"@sproutsocial/seeds-react-content-header\";\nimport type {\n ContentBlockBaseProps,\n ContentBlockProps,\n CollapsibleContentBlockProps,\n} from \"./ContentBlock\";\n\n// Utility for merging class names properly.\n// cn is NOT exported from @sproutsocial/seeds-react-utilities, so it is\n// reproduced locally here (mirrors ButtonTailwind.tsx).\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\nexport type ContentFooterProps = {\n footerContent?: React.ReactNode;\n footerActions?: React.ReactNode;\n className?: string;\n};\n\nexport const ContentFooterTailwind = ({\n footerContent,\n footerActions,\n className,\n}: ContentFooterProps) => (\n <div className={cn(\"seeds-content-block-footer\", className)}>\n {footerContent && <span>{footerContent}</span>}\n {footerActions && <span>{footerActions}</span>}\n </div>\n);\n\nconst ContentArea = ({\n isLoading,\n children,\n flushLayout,\n hasFooter,\n contentProps,\n}: Pick<\n ContentBlockBaseProps,\n \"isLoading\" | \"children\" | \"flushLayout\" | \"contentProps\"\n> & {\n hasFooter?: boolean;\n}) => {\n // By construction, any contentProps reaching the Tailwind path carries no\n // styled-system props (those route to ContentBlockStyled via hasStyledProps),\n // so the rest is pure DOM attributes safe to spread onto a div. Pull className\n // out and merge it via cn so the seeds-content-block-content class is\n // preserved, rendering className after the spread so the merged value wins\n // (mirrors ButtonTailwind).\n const { className, ...domProps } = contentProps ?? {};\n return (\n <div\n {...(domProps as React.HTMLAttributes<HTMLDivElement>)}\n className={cn(\n \"seeds-content-block-content\",\n {\n flush: !!flushLayout,\n \"no-footer\": !hasFooter,\n },\n className\n )}\n >\n {isLoading ? (\n <div className=\"seeds-content-block-loader\">\n <Loader delay={false} />\n </div>\n ) : (\n children\n )}\n </div>\n );\n};\n\nconst CollapsibleContentBlock = ({\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n rightTitleElement,\n flushLayout,\n footerContent,\n footerActions,\n contentProps,\n isOpen: controlledIsOpen,\n defaultOpen = true,\n onOpenChange,\n}: Omit<CollapsibleContentBlockProps, \"isCollapsible\">) => {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = controlledIsOpen !== undefined ? controlledIsOpen : internalOpen;\n const hasFooter = !!(footerContent || footerActions);\n\n const handleOpenChange = (newOpen: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalOpen(newOpen);\n }\n onOpenChange?.(newOpen);\n };\n\n return (\n <Collapsible isOpen={open} onOpenChange={handleOpenChange}>\n <section className=\"seeds-content-block\">\n <CollapsibleContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n rightTitleElement={rightTitleElement}\n trigger={Collapsible.Trigger}\n triggerPosition=\"left\"\n />\n <Collapsible.Panel>\n <ContentArea\n isLoading={isLoading}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n contentProps={contentProps}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooterTailwind\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Collapsible.Panel>\n </section>\n </Collapsible>\n );\n};\n\n/**\n * Tailwind/CSS-class implementation of the full ContentBlock. Preferred path;\n * the Hybrid routes here unless `contentProps` carries styled-system props.\n */\nexport const ContentBlockTailwind = ({\n isCollapsible,\n ...props\n}: ContentBlockProps) => {\n if (isCollapsible) {\n return <CollapsibleContentBlock {...props} />;\n }\n\n const {\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n rightTitleElement,\n flushLayout,\n footerContent,\n footerActions,\n contentProps,\n } = props;\n\n const hasFooter = !!(footerContent || footerActions);\n\n return (\n <section className=\"seeds-content-block\">\n <ContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n rightTitleElement={rightTitleElement}\n />\n <ContentArea\n isLoading={isLoading}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n contentProps={contentProps}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooterTailwind\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </section>\n );\n};\n","/**\n * Styled-components implementation of the full ContentBlock.\n *\n * This is the legacy fallback the Hybrid delegates to whenever `contentProps`\n * carries styled-system props (e.g. `bg`, `py`) that a plain Tailwind element\n * cannot honor. It reproduces the original Box/Container/FooterContainer tree\n * verbatim so styled-system passthrough and visual parity are preserved.\n */\n\nimport React, { useState } from \"react\";\nimport { Box } from \"@sproutsocial/seeds-react-box\";\nimport { Loader } from \"@sproutsocial/seeds-react-loader\";\nimport { Collapsible } from \"@sproutsocial/seeds-react-collapsible\";\nimport {\n ContentHeader,\n CollapsibleContentHeader,\n} from \"@sproutsocial/seeds-react-content-header\";\nimport { Container } from \"@sproutsocial/seeds-react-container\";\nimport { FooterContainer } from \"./styles\";\nimport type {\n ContentBlockBaseProps,\n ContentBlockProps,\n CollapsibleContentBlockProps,\n} from \"./ContentBlock\";\n\nconst ContentArea = ({\n isLoading,\n children,\n contentProps,\n flushLayout,\n hasFooter,\n}: Pick<\n ContentBlockBaseProps,\n \"isLoading\" | \"children\" | \"contentProps\" | \"flushLayout\"\n> & { hasFooter?: boolean }) => (\n <Box\n p={flushLayout ? 0 : 400}\n {...contentProps}\n borderBottomLeftRadius={hasFooter ? undefined : \"outer\"}\n borderBottomRightRadius={hasFooter ? undefined : \"outer\"}\n >\n {isLoading ? (\n <Box my={400}>\n <Loader delay={false} />\n </Box>\n ) : (\n children\n )}\n </Box>\n);\n\nconst ContentFooter = ({\n footerContent,\n footerActions,\n}: {\n footerContent?: React.ReactNode;\n footerActions?: React.ReactNode;\n}) => (\n <FooterContainer>\n {footerContent && <span>{footerContent}</span>}\n {footerActions && <span>{footerActions}</span>}\n </FooterContainer>\n);\n\nconst CollapsibleContentBlock = ({\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n rightTitleElement,\n contentProps,\n flushLayout,\n footerContent,\n footerActions,\n isOpen: controlledIsOpen,\n defaultOpen = true,\n onOpenChange,\n}: Omit<CollapsibleContentBlockProps, \"isCollapsible\">) => {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = controlledIsOpen !== undefined ? controlledIsOpen : internalOpen;\n const hasFooter = !!(footerContent || footerActions);\n\n const handleOpenChange = (newOpen: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalOpen(newOpen);\n }\n onOpenChange?.(newOpen);\n };\n\n return (\n <Collapsible isOpen={open} onOpenChange={handleOpenChange}>\n <Container as=\"section\">\n <CollapsibleContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n rightTitleElement={rightTitleElement}\n trigger={Collapsible.Trigger}\n triggerPosition=\"left\"\n />\n <Collapsible.Panel>\n <ContentArea\n isLoading={isLoading}\n contentProps={contentProps}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooter\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Collapsible.Panel>\n </Container>\n </Collapsible>\n );\n};\n\nexport const ContentBlockStyled = ({\n isCollapsible,\n ...props\n}: ContentBlockProps) => {\n if (isCollapsible) {\n return <CollapsibleContentBlock {...props} />;\n }\n\n const {\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n rightTitleElement,\n contentProps,\n flushLayout,\n footerContent,\n footerActions,\n } = props;\n\n const hasFooter = !!(footerContent || footerActions);\n\n return (\n <Container as=\"section\">\n <ContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n rightTitleElement={rightTitleElement}\n />\n <ContentArea\n isLoading={isLoading}\n contentProps={contentProps}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooter\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Container>\n );\n};\n","import styled from \"styled-components\";\n\nexport const FooterContainer = styled.div`\n box-sizing: border-box;\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n padding: ${({ theme }) => theme.space[400]};\n border-top: ${({ theme }) => theme.borderWidths[500]} solid\n ${({ theme }) => theme.colors.container.border.base};\n border-bottom-left-radius: ${({ theme }) => theme.radii.outer};\n border-bottom-right-radius: ${({ theme }) => theme.radii.outer};\n`;\n","import ContentBlock from \"./ContentBlock\";\n\nexport type { ContentBlockProps } from \"./ContentBlock\";\n\nexport default ContentBlock;\nexport { ContentBlock };\n"],"mappings":"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","names":["useState","Loader","Collapsible","ContentHeader","CollapsibleContentHeader","jsx","jsxs","ContentArea","Loader","CollapsibleContentBlock","useState","Collapsible","CollapsibleContentHeader","ContentHeader","jsx","jsx"]}
package/dist/index.d.mts CHANGED
@@ -13,6 +13,8 @@ interface ContentBlockBaseProps {
13
13
  contentProps?: React.ComponentProps<typeof Box>;
14
14
  /** Sets content area padding to 0 */
15
15
  flushLayout?: boolean;
16
+ /** Element rendered inline after the title text (e.g. a beta badge) */
17
+ rightTitleElement?: React.ReactNode;
16
18
  /** Left slot of the footer area */
17
19
  footerContent?: React.ReactNode;
18
20
  /** Right slot of the footer area */
package/dist/index.d.ts CHANGED
@@ -13,6 +13,8 @@ interface ContentBlockBaseProps {
13
13
  contentProps?: React.ComponentProps<typeof Box>;
14
14
  /** Sets content area padding to 0 */
15
15
  flushLayout?: boolean;
16
+ /** Element rendered inline after the title text (e.g. a beta badge) */
17
+ rightTitleElement?: React.ReactNode;
16
18
  /** Left slot of the footer area */
17
19
  footerContent?: React.ReactNode;
18
20
  /** Right slot of the footer area */
package/dist/index.js CHANGED
@@ -105,6 +105,7 @@ var CollapsibleContentBlock = ({
105
105
  children,
106
106
  isLoading,
107
107
  headerActions,
108
+ rightTitleElement,
108
109
  flushLayout,
109
110
  footerContent,
110
111
  footerActions,
@@ -131,6 +132,7 @@ var CollapsibleContentBlock = ({
131
132
  headingLevel: titleAs,
132
133
  subtitleAs,
133
134
  headerActions,
135
+ rightTitleElement,
134
136
  trigger: import_seeds_react_collapsible.Collapsible.Trigger,
135
137
  triggerPosition: "left"
136
138
  }
@@ -171,6 +173,7 @@ var ContentBlockTailwind = ({
171
173
  children,
172
174
  isLoading,
173
175
  headerActions,
176
+ rightTitleElement,
174
177
  flushLayout,
175
178
  footerContent,
176
179
  footerActions,
@@ -185,7 +188,8 @@ var ContentBlockTailwind = ({
185
188
  subtitle,
186
189
  headingLevel: titleAs,
187
190
  subtitleAs,
188
- headerActions
191
+ headerActions,
192
+ rightTitleElement
189
193
  }
190
194
  ),
191
195
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -264,6 +268,7 @@ var CollapsibleContentBlock2 = ({
264
268
  children,
265
269
  isLoading,
266
270
  headerActions,
271
+ rightTitleElement,
267
272
  contentProps,
268
273
  flushLayout,
269
274
  footerContent,
@@ -290,6 +295,7 @@ var CollapsibleContentBlock2 = ({
290
295
  headingLevel: titleAs,
291
296
  subtitleAs,
292
297
  headerActions,
298
+ rightTitleElement,
293
299
  trigger: import_seeds_react_collapsible2.Collapsible.Trigger,
294
300
  triggerPosition: "left"
295
301
  }
@@ -330,6 +336,7 @@ var ContentBlockStyled = ({
330
336
  children,
331
337
  isLoading,
332
338
  headerActions,
339
+ rightTitleElement,
333
340
  contentProps,
334
341
  flushLayout,
335
342
  footerContent,
@@ -344,7 +351,8 @@ var ContentBlockStyled = ({
344
351
  subtitle,
345
352
  headingLevel: titleAs,
346
353
  subtitleAs,
347
- headerActions
354
+ headerActions,
355
+ rightTitleElement
348
356
  }
349
357
  ),
350
358
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/ContentBlock.tsx","../src/ContentBlockHybrid.tsx","../src/ContentBlockTailwind.tsx","../src/ContentBlockStyled.tsx","../src/styles.ts"],"sourcesContent":["import ContentBlock from \"./ContentBlock\";\n\nexport type { ContentBlockProps } from \"./ContentBlock\";\n\nexport default ContentBlock;\nexport { ContentBlock };\n","import React from \"react\";\nimport { Box } from \"@sproutsocial/seeds-react-box\";\nimport ContentBlockHybrid from \"./ContentBlockHybrid\";\n\nexport interface ContentBlockBaseProps {\n title: string;\n subtitle?: string;\n titleAs?: \"h1\" | \"h2\" | \"h3\" | \"h4\";\n subtitleAs?: \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"p\";\n isLoading?: boolean;\n children: React.ReactNode;\n headerActions?: React.ReactNode;\n contentProps?: React.ComponentProps<typeof Box>;\n /** Sets content area padding to 0 */\n flushLayout?: boolean;\n /** Left slot of the footer area */\n footerContent?: React.ReactNode;\n /** Right slot of the footer area */\n footerActions?: React.ReactNode;\n}\n\ntype StaticContentBlockProps = ContentBlockBaseProps & {\n isCollapsible?: false;\n isOpen?: never;\n defaultOpen?: never;\n onOpenChange?: never;\n};\n\nexport type CollapsibleContentBlockProps = ContentBlockBaseProps & {\n /** Enables collapse/expand behavior on the content area */\n isCollapsible: true;\n /** Controlled open state. When provided, the component is in controlled mode. */\n isOpen?: boolean;\n /** Initial open state for uncontrolled mode. Defaults to true. */\n defaultOpen?: boolean;\n /** Called when the open state changes */\n onOpenChange?: (open: boolean) => void;\n};\n\nexport type ContentBlockProps =\n | StaticContentBlockProps\n | CollapsibleContentBlockProps;\n\n/**\n * ContentBlock component. Automatically routes between the Tailwind\n * implementation (preferred) and the styled-components implementation (used when\n * `contentProps` carries styled-system props), mirroring the Button hybrid.\n */\nconst ContentBlock = (props: ContentBlockProps) => (\n <ContentBlockHybrid {...props} />\n);\n\nexport default ContentBlock;\n","/**\n * Hybrid ContentBlock\n *\n * Routes the whole component between the Tailwind implementation (preferred)\n * and the styled-components implementation (legacy fallback), mirroring\n * ButtonHybrid's single `hasStyledProps` gate.\n *\n * `contentProps` is ContentBlock's only styled-system passthrough surface: it\n * is spread onto the content `<Box>` and may carry props (`bg`, `py`, …) that a\n * plain Tailwind element cannot honor. When it does, render the styled-components\n * tree so those props still apply; otherwise use the lighter Tailwind path.\n */\n\nimport React from \"react\";\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport {\n ContentBlockTailwind,\n ContentFooterTailwind,\n type ContentFooterProps,\n} from \"./ContentBlockTailwind\";\nimport { ContentBlockStyled } from \"./ContentBlockStyled\";\nimport type { ContentBlockProps } from \"./ContentBlock\";\n\nconst ContentBlockHybrid = (props: ContentBlockProps) => {\n if (props.contentProps && hasStyledProps(props.contentProps)) {\n return <ContentBlockStyled {...props} />;\n }\n\n return <ContentBlockTailwind {...props} />;\n};\n\nexport default ContentBlockHybrid;\n\n/**\n * Hybrid ContentBlock footer.\n *\n * The footer exposes no styled-system props and no styled()-extendable surface\n * (FooterContainer is internal and never re-exported from index.ts), so the\n * Tailwind/CSS-class footer is always used — no routing predicate is needed here.\n * Kept as a separate export so the footer-override story/tests can render it\n * directly.\n */\nexport const ContentFooterHybrid = (props: ContentFooterProps) => (\n <ContentFooterTailwind {...props} />\n);\n","/**\n * Tailwind CSS implementation of the ContentBlock component.\n * Renders the whole component (card, content area, loader, footer) with plain\n * elements and the Seeds content-block CSS classes from content-block.css.\n * Child components (ContentHeader, Collapsible, Loader) are composed unchanged.\n */\n\nimport React, { useState } from \"react\";\nimport { Loader } from \"@sproutsocial/seeds-react-loader\";\nimport { Collapsible } from \"@sproutsocial/seeds-react-collapsible\";\nimport {\n ContentHeader,\n CollapsibleContentHeader,\n} from \"@sproutsocial/seeds-react-content-header\";\nimport type {\n ContentBlockBaseProps,\n ContentBlockProps,\n CollapsibleContentBlockProps,\n} from \"./ContentBlock\";\n\n// Utility for merging class names properly.\n// cn is NOT exported from @sproutsocial/seeds-react-utilities, so it is\n// reproduced locally here (mirrors ButtonTailwind.tsx).\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\nexport type ContentFooterProps = {\n footerContent?: React.ReactNode;\n footerActions?: React.ReactNode;\n className?: string;\n};\n\nexport const ContentFooterTailwind = ({\n footerContent,\n footerActions,\n className,\n}: ContentFooterProps) => (\n <div className={cn(\"seeds-content-block-footer\", className)}>\n {footerContent && <span>{footerContent}</span>}\n {footerActions && <span>{footerActions}</span>}\n </div>\n);\n\nconst ContentArea = ({\n isLoading,\n children,\n flushLayout,\n hasFooter,\n contentProps,\n}: Pick<\n ContentBlockBaseProps,\n \"isLoading\" | \"children\" | \"flushLayout\" | \"contentProps\"\n> & {\n hasFooter?: boolean;\n}) => {\n // By construction, any contentProps reaching the Tailwind path carries no\n // styled-system props (those route to ContentBlockStyled via hasStyledProps),\n // so the rest is pure DOM attributes safe to spread onto a div. Pull className\n // out and merge it via cn so the seeds-content-block-content class is\n // preserved, rendering className after the spread so the merged value wins\n // (mirrors ButtonTailwind).\n const { className, ...domProps } = contentProps ?? {};\n return (\n <div\n {...(domProps as React.HTMLAttributes<HTMLDivElement>)}\n className={cn(\n \"seeds-content-block-content\",\n {\n flush: !!flushLayout,\n \"no-footer\": !hasFooter,\n },\n className\n )}\n >\n {isLoading ? (\n <div className=\"seeds-content-block-loader\">\n <Loader delay={false} />\n </div>\n ) : (\n children\n )}\n </div>\n );\n};\n\nconst CollapsibleContentBlock = ({\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n flushLayout,\n footerContent,\n footerActions,\n contentProps,\n isOpen: controlledIsOpen,\n defaultOpen = true,\n onOpenChange,\n}: Omit<CollapsibleContentBlockProps, \"isCollapsible\">) => {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = controlledIsOpen !== undefined ? controlledIsOpen : internalOpen;\n const hasFooter = !!(footerContent || footerActions);\n\n const handleOpenChange = (newOpen: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalOpen(newOpen);\n }\n onOpenChange?.(newOpen);\n };\n\n return (\n <Collapsible isOpen={open} onOpenChange={handleOpenChange}>\n <section className=\"seeds-content-block\">\n <CollapsibleContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n trigger={Collapsible.Trigger}\n triggerPosition=\"left\"\n />\n <Collapsible.Panel>\n <ContentArea\n isLoading={isLoading}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n contentProps={contentProps}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooterTailwind\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Collapsible.Panel>\n </section>\n </Collapsible>\n );\n};\n\n/**\n * Tailwind/CSS-class implementation of the full ContentBlock. Preferred path;\n * the Hybrid routes here unless `contentProps` carries styled-system props.\n */\nexport const ContentBlockTailwind = ({\n isCollapsible,\n ...props\n}: ContentBlockProps) => {\n if (isCollapsible) {\n return <CollapsibleContentBlock {...props} />;\n }\n\n const {\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n flushLayout,\n footerContent,\n footerActions,\n contentProps,\n } = props;\n\n const hasFooter = !!(footerContent || footerActions);\n\n return (\n <section className=\"seeds-content-block\">\n <ContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n />\n <ContentArea\n isLoading={isLoading}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n contentProps={contentProps}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooterTailwind\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </section>\n );\n};\n","/**\n * Styled-components implementation of the full ContentBlock.\n *\n * This is the legacy fallback the Hybrid delegates to whenever `contentProps`\n * carries styled-system props (e.g. `bg`, `py`) that a plain Tailwind element\n * cannot honor. It reproduces the original Box/Container/FooterContainer tree\n * verbatim so styled-system passthrough and visual parity are preserved.\n */\n\nimport React, { useState } from \"react\";\nimport { Box } from \"@sproutsocial/seeds-react-box\";\nimport { Loader } from \"@sproutsocial/seeds-react-loader\";\nimport { Collapsible } from \"@sproutsocial/seeds-react-collapsible\";\nimport {\n ContentHeader,\n CollapsibleContentHeader,\n} from \"@sproutsocial/seeds-react-content-header\";\nimport { Container } from \"@sproutsocial/seeds-react-container\";\nimport { FooterContainer } from \"./styles\";\nimport type {\n ContentBlockBaseProps,\n ContentBlockProps,\n CollapsibleContentBlockProps,\n} from \"./ContentBlock\";\n\nconst ContentArea = ({\n isLoading,\n children,\n contentProps,\n flushLayout,\n hasFooter,\n}: Pick<\n ContentBlockBaseProps,\n \"isLoading\" | \"children\" | \"contentProps\" | \"flushLayout\"\n> & { hasFooter?: boolean }) => (\n <Box\n p={flushLayout ? 0 : 400}\n {...contentProps}\n borderBottomLeftRadius={hasFooter ? undefined : \"outer\"}\n borderBottomRightRadius={hasFooter ? undefined : \"outer\"}\n >\n {isLoading ? (\n <Box my={400}>\n <Loader delay={false} />\n </Box>\n ) : (\n children\n )}\n </Box>\n);\n\nconst ContentFooter = ({\n footerContent,\n footerActions,\n}: {\n footerContent?: React.ReactNode;\n footerActions?: React.ReactNode;\n}) => (\n <FooterContainer>\n {footerContent && <span>{footerContent}</span>}\n {footerActions && <span>{footerActions}</span>}\n </FooterContainer>\n);\n\nconst CollapsibleContentBlock = ({\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n contentProps,\n flushLayout,\n footerContent,\n footerActions,\n isOpen: controlledIsOpen,\n defaultOpen = true,\n onOpenChange,\n}: Omit<CollapsibleContentBlockProps, \"isCollapsible\">) => {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = controlledIsOpen !== undefined ? controlledIsOpen : internalOpen;\n const hasFooter = !!(footerContent || footerActions);\n\n const handleOpenChange = (newOpen: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalOpen(newOpen);\n }\n onOpenChange?.(newOpen);\n };\n\n return (\n <Collapsible isOpen={open} onOpenChange={handleOpenChange}>\n <Container as=\"section\">\n <CollapsibleContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n trigger={Collapsible.Trigger}\n triggerPosition=\"left\"\n />\n <Collapsible.Panel>\n <ContentArea\n isLoading={isLoading}\n contentProps={contentProps}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooter\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Collapsible.Panel>\n </Container>\n </Collapsible>\n );\n};\n\nexport const ContentBlockStyled = ({\n isCollapsible,\n ...props\n}: ContentBlockProps) => {\n if (isCollapsible) {\n return <CollapsibleContentBlock {...props} />;\n }\n\n const {\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n contentProps,\n flushLayout,\n footerContent,\n footerActions,\n } = props;\n\n const hasFooter = !!(footerContent || footerActions);\n\n return (\n <Container as=\"section\">\n <ContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n />\n <ContentArea\n isLoading={isLoading}\n contentProps={contentProps}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooter\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Container>\n );\n};\n","import styled from \"styled-components\";\n\nexport const FooterContainer = styled.div`\n box-sizing: border-box;\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n padding: ${({ theme }) => theme.space[400]};\n border-top: ${({ theme }) => theme.borderWidths[500]} solid\n ${({ theme }) => theme.colors.container.border.base};\n border-bottom-left-radius: ${({ theme }) => theme.radii.outer};\n border-bottom-right-radius: ${({ theme }) => theme.radii.outer};\n`;\n"],"mappings":"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","names":["import_react","import_seeds_react_box","import_react","import_react","import_seeds_react_loader","import_seeds_react_collapsible","import_seeds_react_content_header","styled","import_jsx_runtime","ContentArea","CollapsibleContentBlock","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/ContentBlock.tsx","../src/ContentBlockHybrid.tsx","../src/ContentBlockTailwind.tsx","../src/ContentBlockStyled.tsx","../src/styles.ts"],"sourcesContent":["import ContentBlock from \"./ContentBlock\";\n\nexport type { ContentBlockProps } from \"./ContentBlock\";\n\nexport default ContentBlock;\nexport { ContentBlock };\n","import React from \"react\";\nimport { Box } from \"@sproutsocial/seeds-react-box\";\nimport ContentBlockHybrid from \"./ContentBlockHybrid\";\n\nexport interface ContentBlockBaseProps {\n title: string;\n subtitle?: string;\n titleAs?: \"h1\" | \"h2\" | \"h3\" | \"h4\";\n subtitleAs?: \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"p\";\n isLoading?: boolean;\n children: React.ReactNode;\n headerActions?: React.ReactNode;\n contentProps?: React.ComponentProps<typeof Box>;\n /** Sets content area padding to 0 */\n flushLayout?: boolean;\n /** Element rendered inline after the title text (e.g. a beta badge) */\n rightTitleElement?: React.ReactNode;\n /** Left slot of the footer area */\n footerContent?: React.ReactNode;\n /** Right slot of the footer area */\n footerActions?: React.ReactNode;\n}\n\ntype StaticContentBlockProps = ContentBlockBaseProps & {\n isCollapsible?: false;\n isOpen?: never;\n defaultOpen?: never;\n onOpenChange?: never;\n};\n\nexport type CollapsibleContentBlockProps = ContentBlockBaseProps & {\n /** Enables collapse/expand behavior on the content area */\n isCollapsible: true;\n /** Controlled open state. When provided, the component is in controlled mode. */\n isOpen?: boolean;\n /** Initial open state for uncontrolled mode. Defaults to true. */\n defaultOpen?: boolean;\n /** Called when the open state changes */\n onOpenChange?: (open: boolean) => void;\n};\n\nexport type ContentBlockProps =\n | StaticContentBlockProps\n | CollapsibleContentBlockProps;\n\n/**\n * ContentBlock component. Automatically routes between the Tailwind\n * implementation (preferred) and the styled-components implementation (used when\n * `contentProps` carries styled-system props), mirroring the Button hybrid.\n */\nconst ContentBlock = (props: ContentBlockProps) => (\n <ContentBlockHybrid {...props} />\n);\n\nexport default ContentBlock;\n","/**\n * Hybrid ContentBlock\n *\n * Routes the whole component between the Tailwind implementation (preferred)\n * and the styled-components implementation (legacy fallback), mirroring\n * ButtonHybrid's single `hasStyledProps` gate.\n *\n * `contentProps` is ContentBlock's only styled-system passthrough surface: it\n * is spread onto the content `<Box>` and may carry props (`bg`, `py`, …) that a\n * plain Tailwind element cannot honor. When it does, render the styled-components\n * tree so those props still apply; otherwise use the lighter Tailwind path.\n */\n\nimport React from \"react\";\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport {\n ContentBlockTailwind,\n ContentFooterTailwind,\n type ContentFooterProps,\n} from \"./ContentBlockTailwind\";\nimport { ContentBlockStyled } from \"./ContentBlockStyled\";\nimport type { ContentBlockProps } from \"./ContentBlock\";\n\nconst ContentBlockHybrid = (props: ContentBlockProps) => {\n if (props.contentProps && hasStyledProps(props.contentProps)) {\n return <ContentBlockStyled {...props} />;\n }\n\n return <ContentBlockTailwind {...props} />;\n};\n\nexport default ContentBlockHybrid;\n\n/**\n * Hybrid ContentBlock footer.\n *\n * The footer exposes no styled-system props and no styled()-extendable surface\n * (FooterContainer is internal and never re-exported from index.ts), so the\n * Tailwind/CSS-class footer is always used — no routing predicate is needed here.\n * Kept as a separate export so the footer-override story/tests can render it\n * directly.\n */\nexport const ContentFooterHybrid = (props: ContentFooterProps) => (\n <ContentFooterTailwind {...props} />\n);\n","/**\n * Tailwind CSS implementation of the ContentBlock component.\n * Renders the whole component (card, content area, loader, footer) with plain\n * elements and the Seeds content-block CSS classes from content-block.css.\n * Child components (ContentHeader, Collapsible, Loader) are composed unchanged.\n */\n\nimport React, { useState } from \"react\";\nimport { Loader } from \"@sproutsocial/seeds-react-loader\";\nimport { Collapsible } from \"@sproutsocial/seeds-react-collapsible\";\nimport {\n ContentHeader,\n CollapsibleContentHeader,\n} from \"@sproutsocial/seeds-react-content-header\";\nimport type {\n ContentBlockBaseProps,\n ContentBlockProps,\n CollapsibleContentBlockProps,\n} from \"./ContentBlock\";\n\n// Utility for merging class names properly.\n// cn is NOT exported from @sproutsocial/seeds-react-utilities, so it is\n// reproduced locally here (mirrors ButtonTailwind.tsx).\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\nexport type ContentFooterProps = {\n footerContent?: React.ReactNode;\n footerActions?: React.ReactNode;\n className?: string;\n};\n\nexport const ContentFooterTailwind = ({\n footerContent,\n footerActions,\n className,\n}: ContentFooterProps) => (\n <div className={cn(\"seeds-content-block-footer\", className)}>\n {footerContent && <span>{footerContent}</span>}\n {footerActions && <span>{footerActions}</span>}\n </div>\n);\n\nconst ContentArea = ({\n isLoading,\n children,\n flushLayout,\n hasFooter,\n contentProps,\n}: Pick<\n ContentBlockBaseProps,\n \"isLoading\" | \"children\" | \"flushLayout\" | \"contentProps\"\n> & {\n hasFooter?: boolean;\n}) => {\n // By construction, any contentProps reaching the Tailwind path carries no\n // styled-system props (those route to ContentBlockStyled via hasStyledProps),\n // so the rest is pure DOM attributes safe to spread onto a div. Pull className\n // out and merge it via cn so the seeds-content-block-content class is\n // preserved, rendering className after the spread so the merged value wins\n // (mirrors ButtonTailwind).\n const { className, ...domProps } = contentProps ?? {};\n return (\n <div\n {...(domProps as React.HTMLAttributes<HTMLDivElement>)}\n className={cn(\n \"seeds-content-block-content\",\n {\n flush: !!flushLayout,\n \"no-footer\": !hasFooter,\n },\n className\n )}\n >\n {isLoading ? (\n <div className=\"seeds-content-block-loader\">\n <Loader delay={false} />\n </div>\n ) : (\n children\n )}\n </div>\n );\n};\n\nconst CollapsibleContentBlock = ({\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n rightTitleElement,\n flushLayout,\n footerContent,\n footerActions,\n contentProps,\n isOpen: controlledIsOpen,\n defaultOpen = true,\n onOpenChange,\n}: Omit<CollapsibleContentBlockProps, \"isCollapsible\">) => {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = controlledIsOpen !== undefined ? controlledIsOpen : internalOpen;\n const hasFooter = !!(footerContent || footerActions);\n\n const handleOpenChange = (newOpen: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalOpen(newOpen);\n }\n onOpenChange?.(newOpen);\n };\n\n return (\n <Collapsible isOpen={open} onOpenChange={handleOpenChange}>\n <section className=\"seeds-content-block\">\n <CollapsibleContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n rightTitleElement={rightTitleElement}\n trigger={Collapsible.Trigger}\n triggerPosition=\"left\"\n />\n <Collapsible.Panel>\n <ContentArea\n isLoading={isLoading}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n contentProps={contentProps}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooterTailwind\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Collapsible.Panel>\n </section>\n </Collapsible>\n );\n};\n\n/**\n * Tailwind/CSS-class implementation of the full ContentBlock. Preferred path;\n * the Hybrid routes here unless `contentProps` carries styled-system props.\n */\nexport const ContentBlockTailwind = ({\n isCollapsible,\n ...props\n}: ContentBlockProps) => {\n if (isCollapsible) {\n return <CollapsibleContentBlock {...props} />;\n }\n\n const {\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n rightTitleElement,\n flushLayout,\n footerContent,\n footerActions,\n contentProps,\n } = props;\n\n const hasFooter = !!(footerContent || footerActions);\n\n return (\n <section className=\"seeds-content-block\">\n <ContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n rightTitleElement={rightTitleElement}\n />\n <ContentArea\n isLoading={isLoading}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n contentProps={contentProps}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooterTailwind\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </section>\n );\n};\n","/**\n * Styled-components implementation of the full ContentBlock.\n *\n * This is the legacy fallback the Hybrid delegates to whenever `contentProps`\n * carries styled-system props (e.g. `bg`, `py`) that a plain Tailwind element\n * cannot honor. It reproduces the original Box/Container/FooterContainer tree\n * verbatim so styled-system passthrough and visual parity are preserved.\n */\n\nimport React, { useState } from \"react\";\nimport { Box } from \"@sproutsocial/seeds-react-box\";\nimport { Loader } from \"@sproutsocial/seeds-react-loader\";\nimport { Collapsible } from \"@sproutsocial/seeds-react-collapsible\";\nimport {\n ContentHeader,\n CollapsibleContentHeader,\n} from \"@sproutsocial/seeds-react-content-header\";\nimport { Container } from \"@sproutsocial/seeds-react-container\";\nimport { FooterContainer } from \"./styles\";\nimport type {\n ContentBlockBaseProps,\n ContentBlockProps,\n CollapsibleContentBlockProps,\n} from \"./ContentBlock\";\n\nconst ContentArea = ({\n isLoading,\n children,\n contentProps,\n flushLayout,\n hasFooter,\n}: Pick<\n ContentBlockBaseProps,\n \"isLoading\" | \"children\" | \"contentProps\" | \"flushLayout\"\n> & { hasFooter?: boolean }) => (\n <Box\n p={flushLayout ? 0 : 400}\n {...contentProps}\n borderBottomLeftRadius={hasFooter ? undefined : \"outer\"}\n borderBottomRightRadius={hasFooter ? undefined : \"outer\"}\n >\n {isLoading ? (\n <Box my={400}>\n <Loader delay={false} />\n </Box>\n ) : (\n children\n )}\n </Box>\n);\n\nconst ContentFooter = ({\n footerContent,\n footerActions,\n}: {\n footerContent?: React.ReactNode;\n footerActions?: React.ReactNode;\n}) => (\n <FooterContainer>\n {footerContent && <span>{footerContent}</span>}\n {footerActions && <span>{footerActions}</span>}\n </FooterContainer>\n);\n\nconst CollapsibleContentBlock = ({\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n rightTitleElement,\n contentProps,\n flushLayout,\n footerContent,\n footerActions,\n isOpen: controlledIsOpen,\n defaultOpen = true,\n onOpenChange,\n}: Omit<CollapsibleContentBlockProps, \"isCollapsible\">) => {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = controlledIsOpen !== undefined ? controlledIsOpen : internalOpen;\n const hasFooter = !!(footerContent || footerActions);\n\n const handleOpenChange = (newOpen: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalOpen(newOpen);\n }\n onOpenChange?.(newOpen);\n };\n\n return (\n <Collapsible isOpen={open} onOpenChange={handleOpenChange}>\n <Container as=\"section\">\n <CollapsibleContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n rightTitleElement={rightTitleElement}\n trigger={Collapsible.Trigger}\n triggerPosition=\"left\"\n />\n <Collapsible.Panel>\n <ContentArea\n isLoading={isLoading}\n contentProps={contentProps}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooter\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Collapsible.Panel>\n </Container>\n </Collapsible>\n );\n};\n\nexport const ContentBlockStyled = ({\n isCollapsible,\n ...props\n}: ContentBlockProps) => {\n if (isCollapsible) {\n return <CollapsibleContentBlock {...props} />;\n }\n\n const {\n title,\n subtitle,\n titleAs = \"h2\",\n subtitleAs = \"h3\",\n children,\n isLoading,\n headerActions,\n rightTitleElement,\n contentProps,\n flushLayout,\n footerContent,\n footerActions,\n } = props;\n\n const hasFooter = !!(footerContent || footerActions);\n\n return (\n <Container as=\"section\">\n <ContentHeader\n title={title}\n subtitle={subtitle}\n headingLevel={titleAs}\n subtitleAs={subtitleAs}\n headerActions={headerActions}\n rightTitleElement={rightTitleElement}\n />\n <ContentArea\n isLoading={isLoading}\n contentProps={contentProps}\n flushLayout={flushLayout}\n hasFooter={hasFooter}\n >\n {children}\n </ContentArea>\n {hasFooter && (\n <ContentFooter\n footerContent={footerContent}\n footerActions={footerActions}\n />\n )}\n </Container>\n );\n};\n","import styled from \"styled-components\";\n\nexport const FooterContainer = styled.div`\n box-sizing: border-box;\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n padding: ${({ theme }) => theme.space[400]};\n border-top: ${({ theme }) => theme.borderWidths[500]} solid\n ${({ theme }) => theme.colors.container.border.base};\n border-bottom-left-radius: ${({ theme }) => theme.radii.outer};\n border-bottom-right-radius: ${({ theme }) => theme.radii.outer};\n`;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,gBAAkB;AAClB,IAAAC,0BAAoB;;;ACYpB,IAAAC,gBAAkB;AAClB,sCAA+B;;;ACP/B,mBAAgC;AAChC,gCAAuB;AACvB,qCAA4B;AAC5B,wCAGO;AA2CL;AAjCF,SAAS,MACJ,QACK;AACR,QAAM,UAAoB,CAAC;AAE3B,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,MAAO;AAEZ,QAAI,OAAO,UAAU,UAAU;AAC7B,cAAQ,KAAK,KAAK;AAAA,IACpB,WAAW,OAAO,UAAU,UAAU;AACpC,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,YAAI,OAAO;AACT,kBAAQ,KAAK,GAAG;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,QAAQ,KAAK,GAAG;AACzB;AAQO,IAAM,wBAAwB,CAAC;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AACF,MACE,6CAAC,SAAI,WAAW,GAAG,8BAA8B,SAAS,GACvD;AAAA,mBAAiB,4CAAC,UAAM,yBAAc;AAAA,EACtC,iBAAiB,4CAAC,UAAM,yBAAc;AAAA,GACzC;AAGF,IAAM,cAAc,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAKM;AAOJ,QAAM,EAAE,WAAW,GAAG,SAAS,IAAI,gBAAgB,CAAC;AACpD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAI;AAAA,MACL,WAAW;AAAA,QACT;AAAA,QACA;AAAA,UACE,OAAO,CAAC,CAAC;AAAA,UACT,aAAa,CAAC;AAAA,QAChB;AAAA,QACA;AAAA,MACF;AAAA,MAEC,sBACC,4CAAC,SAAI,WAAU,8BACb,sDAAC,oCAAO,OAAO,OAAO,GACxB,IAEA;AAAA;AAAA,EAEJ;AAEJ;AAEA,IAAM,0BAA0B,CAAC;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,cAAc;AAAA,EACd;AACF,MAA2D;AACzD,QAAM,CAAC,cAAc,eAAe,QAAI,uBAAS,WAAW;AAC5D,QAAM,OAAO,qBAAqB,SAAY,mBAAmB;AACjE,QAAM,YAAY,CAAC,EAAE,iBAAiB;AAEtC,QAAM,mBAAmB,CAAC,YAAqB;AAC7C,QAAI,qBAAqB,QAAW;AAClC,sBAAgB,OAAO;AAAA,IACzB;AACA,mBAAe,OAAO;AAAA,EACxB;AAEA,SACE,4CAAC,8CAAY,QAAQ,MAAM,cAAc,kBACvC,uDAAC,aAAQ,WAAU,uBACjB;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,2CAAY;AAAA,QACrB,iBAAgB;AAAA;AAAA,IAClB;AAAA,IACA,6CAAC,2CAAY,OAAZ,EACC;AAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UAEC;AAAA;AAAA,MACH;AAAA,MACC,aACC;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA;AAAA,MACF;AAAA,OAEJ;AAAA,KACF,GACF;AAEJ;AAMO,IAAM,uBAAuB,CAAC;AAAA,EACnC;AAAA,EACA,GAAG;AACL,MAAyB;AACvB,MAAI,eAAe;AACjB,WAAO,4CAAC,2BAAyB,GAAG,OAAO;AAAA,EAC7C;AAEA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,YAAY,CAAC,EAAE,iBAAiB;AAEtC,SACE,6CAAC,aAAQ,WAAU,uBACjB;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QAEC;AAAA;AAAA,IACH;AAAA,IACC,aACC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;;;ACpNA,IAAAC,gBAAgC;AAChC,6BAAoB;AACpB,IAAAC,6BAAuB;AACvB,IAAAC,kCAA4B;AAC5B,IAAAC,qCAGO;AACP,mCAA0B;;;ACjB1B,+BAAmB;AAEZ,IAAM,kBAAkB,yBAAAC,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAMzB,CAAC,EAAE,MAAM,MAAM,MAAM,MAAM,GAAG,CAAC;AAAA,gBAC5B,CAAC,EAAE,MAAM,MAAM,MAAM,aAAa,GAAG,CAAC;AAAA,MAChD,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,UAAU,OAAO,IAAI;AAAA,+BACxB,CAAC,EAAE,MAAM,MAAM,MAAM,MAAM,KAAK;AAAA,gCAC/B,CAAC,EAAE,MAAM,MAAM,MAAM,MAAM,KAAK;AAAA;;;AD+BxD,IAAAC,sBAAA;AAlBR,IAAMC,eAAc,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAIE;AAAA,EAAC;AAAA;AAAA,IACC,GAAG,cAAc,IAAI;AAAA,IACpB,GAAG;AAAA,IACJ,wBAAwB,YAAY,SAAY;AAAA,IAChD,yBAAyB,YAAY,SAAY;AAAA,IAEhD,sBACC,6CAAC,8BAAI,IAAI,KACP,uDAAC,qCAAO,OAAO,OAAO,GACxB,IAEA;AAAA;AAEJ;AAGF,IAAM,gBAAgB,CAAC;AAAA,EACrB;AAAA,EACA;AACF,MAIE,8CAAC,mBACE;AAAA,mBAAiB,6CAAC,UAAM,yBAAc;AAAA,EACtC,iBAAiB,6CAAC,UAAM,yBAAc;AAAA,GACzC;AAGF,IAAMC,2BAA0B,CAAC;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,cAAc;AAAA,EACd;AACF,MAA2D;AACzD,QAAM,CAAC,cAAc,eAAe,QAAI,wBAAS,WAAW;AAC5D,QAAM,OAAO,qBAAqB,SAAY,mBAAmB;AACjE,QAAM,YAAY,CAAC,EAAE,iBAAiB;AAEtC,QAAM,mBAAmB,CAAC,YAAqB;AAC7C,QAAI,qBAAqB,QAAW;AAClC,sBAAgB,OAAO;AAAA,IACzB;AACA,mBAAe,OAAO;AAAA,EACxB;AAEA,SACE,6CAAC,+CAAY,QAAQ,MAAM,cAAc,kBACvC,wDAAC,0CAAU,IAAG,WACZ;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,4CAAY;AAAA,QACrB,iBAAgB;AAAA;AAAA,IAClB;AAAA,IACA,8CAAC,4CAAY,OAAZ,EACC;AAAA;AAAA,QAACD;AAAA,QAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UAEC;AAAA;AAAA,MACH;AAAA,MACC,aACC;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA;AAAA,MACF;AAAA,OAEJ;AAAA,KACF,GACF;AAEJ;AAEO,IAAM,qBAAqB,CAAC;AAAA,EACjC;AAAA,EACA,GAAG;AACL,MAAyB;AACvB,MAAI,eAAe;AACjB,WAAO,6CAACC,0BAAA,EAAyB,GAAG,OAAO;AAAA,EAC7C;AAEA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,YAAY,CAAC,EAAE,iBAAiB;AAEtC,SACE,8CAAC,0CAAU,IAAG,WACZ;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,IACA;AAAA,MAACD;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QAEC;AAAA;AAAA,IACH;AAAA,IACC,aACC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;;;AFxJW,IAAAE,sBAAA;AAFX,IAAM,qBAAqB,CAAC,UAA6B;AACvD,MAAI,MAAM,oBAAgB,gDAAe,MAAM,YAAY,GAAG;AAC5D,WAAO,6CAAC,sBAAoB,GAAG,OAAO;AAAA,EACxC;AAEA,SAAO,6CAAC,wBAAsB,GAAG,OAAO;AAC1C;AAEA,IAAO,6BAAQ;;;ADoBb,IAAAC,sBAAA;AADF,IAAM,eAAe,CAAC,UACpB,6CAAC,8BAAoB,GAAG,OAAO;AAGjC,IAAO,uBAAQ;;;ADlDf,IAAO,gBAAQ;","names":["import_react","import_seeds_react_box","import_react","import_react","import_seeds_react_loader","import_seeds_react_collapsible","import_seeds_react_content_header","styled","import_jsx_runtime","ContentArea","CollapsibleContentBlock","import_jsx_runtime","import_jsx_runtime"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutsocial/seeds-react-content-block",
3
- "version": "0.5.27",
3
+ "version": "0.6.0",
4
4
  "description": "Seeds React ContentBlock",
5
5
  "author": "Sprout Social, Inc.",
6
6
  "license": "MIT",
@@ -29,14 +29,14 @@
29
29
  "test:watch": "jest --watch --coverage=false"
30
30
  },
31
31
  "dependencies": {
32
- "@sproutsocial/seeds-react-box": "^1.1.30",
33
- "@sproutsocial/seeds-react-button": "^2.3.7",
32
+ "@sproutsocial/seeds-react-box": "^1.1.31",
33
+ "@sproutsocial/seeds-react-button": "^2.3.8",
34
34
  "@sproutsocial/seeds-react-collapsible": "^2.0.1",
35
- "@sproutsocial/seeds-react-container": "^0.3.24",
36
- "@sproutsocial/seeds-react-content-header": "^0.2.30",
37
- "@sproutsocial/seeds-react-loader": "^1.0.32",
38
- "@sproutsocial/seeds-react-system-props": "^3.2.0",
39
- "@sproutsocial/seeds-react-theme": "^4.4.0"
35
+ "@sproutsocial/seeds-react-container": "^0.3.25",
36
+ "@sproutsocial/seeds-react-content-header": "^0.3.0",
37
+ "@sproutsocial/seeds-react-loader": "^1.0.33",
38
+ "@sproutsocial/seeds-react-system-props": "^3.2.1",
39
+ "@sproutsocial/seeds-react-theme": "^4.5.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/react": "^18.0.0",