@hubspot/cms-component-library 0.3.7 → 0.3.8

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.
@@ -1,4 +1,4 @@
1
- import { RichTextField } from '@hubspot/cms-components/fields';
1
+ import Text from '../../Text/index.js';
2
2
  import type { ContentFieldsProps } from './types.js';
3
3
 
4
4
  const ContentFields = ({
@@ -7,11 +7,11 @@ const ContentFields = ({
7
7
  contentDefault = '<p>Accordion content goes here. You can add multiple lines of text.</p>',
8
8
  }: ContentFieldsProps) => {
9
9
  return (
10
- // Todo: consider migrating over field library
11
- <RichTextField
12
- label={contentLabel}
13
- name={contentName}
14
- default={contentDefault}
10
+ <Text.ContentFields
11
+ textLabel={contentLabel}
12
+ textName={contentName}
13
+ textDefault={contentDefault}
14
+ textFeatureSet="bodyContent"
15
15
  />
16
16
  );
17
17
  };
@@ -1,9 +1,11 @@
1
+ import Text from '../../Text/index.js';
1
2
  import styles from './index.module.scss';
2
3
  import ContentFields from './ContentFields.js';
3
4
  import cx from '../../utils/classname.js';
4
5
  import { AccordionContentProps } from './types.js';
5
6
 
6
7
  const AccordionContentComponent = ({
8
+ fieldPath,
7
9
  className = '',
8
10
  style = {},
9
11
  children,
@@ -12,7 +14,7 @@ const AccordionContentComponent = ({
12
14
 
13
15
  return (
14
16
  <div className={combinedClasses} style={style}>
15
- {children}
17
+ {fieldPath ? <Text fieldPath={fieldPath} /> : children}
16
18
  </div>
17
19
  );
18
20
  };
@@ -1,6 +1,5 @@
1
- import { RichTextFieldDefaults } from '@hubspot/cms-components/fields';
2
-
3
1
  export type AccordionContentProps = {
2
+ fieldPath?: string;
4
3
  className?: string;
5
4
  style?: React.CSSProperties;
6
5
  children?: React.ReactNode;
@@ -9,5 +8,5 @@ export type AccordionContentProps = {
9
8
  export type ContentFieldsProps = {
10
9
  contentLabel?: string;
11
10
  contentName?: string;
12
- contentDefault?: typeof RichTextFieldDefaults;
11
+ contentDefault?: string;
13
12
  };
@@ -1,13 +1,18 @@
1
- import { TextField } from '@hubspot/cms-components/fields';
1
+ import Text from '../../Text/index.js';
2
2
  import type { ContentFieldsProps } from './types.js';
3
3
 
4
4
  const ContentFields = ({
5
5
  titleLabel = 'Title',
6
6
  titleName = 'title',
7
- titleDefault = 'Accordion Title',
7
+ titleDefault = '<p>Accordion Title</p>',
8
8
  }: ContentFieldsProps) => {
9
9
  return (
10
- <TextField label={titleLabel} name={titleName} default={titleDefault} />
10
+ <Text.ContentFields
11
+ textLabel={titleLabel}
12
+ textName={titleName}
13
+ textDefault={titleDefault}
14
+ textFeatureSet="heading"
15
+ />
11
16
  );
12
17
  };
13
18
 
@@ -1,3 +1,4 @@
1
+ import Text from '../../Text/index.js';
1
2
  import styles from './index.module.scss';
2
3
  import ContentFields from './ContentFields.js';
3
4
  import StyleFields from './StyleFields.js';
@@ -7,6 +8,7 @@ import { ChevronIcon, PlusIcon, MinusIcon, CaretIcon } from './icons.js';
7
8
 
8
9
  const AccordionTitleComponent = ({
9
10
  icon = 'chevron',
11
+ fieldPath,
10
12
  className = '',
11
13
  style = {},
12
14
  children,
@@ -32,7 +34,11 @@ const AccordionTitleComponent = ({
32
34
 
33
35
  return (
34
36
  <summary className={combinedClasses} style={style}>
35
- <span className={styles.accordionTitleText}>{children}</span>
37
+ {fieldPath ? (
38
+ <Text fieldPath={fieldPath} className={styles.accordionTitleText} />
39
+ ) : (
40
+ <span className={styles.accordionTitleText}>{children}</span>
41
+ )}
36
42
  {renderIcon()}
37
43
  </summary>
38
44
  );
@@ -2,6 +2,7 @@ export type AccordionIconType = 'chevron' | 'plus' | 'caret';
2
2
 
3
3
  export type AccordionTitleProps = {
4
4
  icon?: AccordionIconType;
5
+ fieldPath?: string;
5
6
  className?: string;
6
7
  style?: React.CSSProperties;
7
8
  children?: React.ReactNode;
@@ -100,28 +100,30 @@ Accordion/
100
100
 
101
101
  ### AccordionTitle (Trigger)
102
102
 
103
- **Purpose:** Clickable trigger component that renders a `<summary>` element with text and an expand/collapse icon.
103
+ **Purpose:** Clickable trigger component that renders a `<summary>` element with rich text and an expand/collapse icon. Uses the `Text` component internally for CMS inline editing support.
104
104
 
105
105
  **Props:**
106
106
  ```tsx
107
107
  {
108
108
  icon?: 'chevron' | 'plus' | 'caret'; // Icon type (default: 'chevron')
109
+ fieldPath?: string; // Path to the RichText field in HubSpot CMS (preferred for CMS modules)
109
110
  className?: string; // Additional CSS classes
110
111
  style?: React.CSSProperties; // Inline styles
111
- children?: React.ReactNode; // Title text content
112
+ children?: React.ReactNode; // Fallback title content (used when fieldPath is not provided, e.g. in Storybook)
112
113
  }
113
114
  ```
114
115
 
115
116
  ### AccordionContent (Panel)
116
117
 
117
- **Purpose:** Content panel component that renders a `<div>` containing the expandable content.
118
+ **Purpose:** Content panel component that renders a `<div>` containing the expandable content. Uses the `Text` component internally when `fieldPath` is provided for CMS inline editing support.
118
119
 
119
120
  **Props:**
120
121
  ```tsx
121
122
  {
123
+ fieldPath?: string; // Path to the RichText field in HubSpot CMS (preferred for CMS modules)
122
124
  className?: string; // Additional CSS classes
123
125
  style?: React.CSSProperties; // Inline styles
124
- children?: React.ReactNode; // Any content (text, HTML, components)
126
+ children?: React.ReactNode; // Fallback content (used when fieldPath is not provided, e.g. in Storybook)
125
127
  }
126
128
  ```
127
129
 
@@ -229,18 +231,18 @@ Configurable props for variant selection:
229
231
 
230
232
  #### AccordionTitle.ContentFields
231
233
 
232
- Configurable props for title text:
234
+ Configurable props for title text. Uses `Text.ContentFields` internally with the `heading` feature set:
233
235
 
234
236
  ```tsx
235
237
  <AccordionTitle.ContentFields
236
238
  titleName="title"
237
239
  titleLabel="Title"
238
- titleDefault="Accordion Title"
240
+ titleDefault="<p>Accordion Title</p>"
239
241
  />
240
242
  ```
241
243
 
242
244
  **Fields:**
243
- - `title`: TextField for accordion title text
245
+ - `title`: RichTextField for accordion title text (heading feature set)
244
246
 
245
247
  #### AccordionTitle.StyleFields
246
248
 
@@ -259,7 +261,7 @@ Configurable props for icon style:
259
261
 
260
262
  #### AccordionContent.ContentFields
261
263
 
262
- Configurable props for content:
264
+ Configurable props for content. Uses `Text.ContentFields` internally with the `bodyContent` feature set:
263
265
 
264
266
  ```tsx
265
267
  <AccordionContent.ContentFields
@@ -270,7 +272,7 @@ Configurable props for content:
270
272
  ```
271
273
 
272
274
  **Fields:**
273
- - `content`: RichTextField for accordion content
275
+ - `content`: RichTextField for accordion content (bodyContent feature set)
274
276
 
275
277
  ### Module Usage Example
276
278
 
@@ -304,10 +306,15 @@ export const Component = ({
304
306
 
305
307
  return (
306
308
  <Accordion>
307
- {accordionItems.map(({ title, content }, index) => (
309
+ {accordionItems.map((_item, index) => (
308
310
  <AccordionItem key={index} variant={variant}>
309
- <AccordionTitle icon={icon}>{title}</AccordionTitle>
310
- <AccordionContent>{content}</AccordionContent>
311
+ <AccordionTitle
312
+ icon={icon}
313
+ fieldPath={`accordionItems[${index}].title`}
314
+ />
315
+ <AccordionContent
316
+ fieldPath={`accordionItems[${index}].content`}
317
+ />
311
318
  </AccordionItem>
312
319
  ))}
313
320
  </Accordion>
@@ -337,7 +344,7 @@ import {
337
344
  } from '@hubspot/cms-component-library/Accordion';
338
345
 
339
346
  const defaultItem = {
340
- title: 'Accordion Title',
347
+ title: '<p>Accordion Title</p>',
341
348
  content: '<p>Accordion content goes here. You can add multiple lines of text.</p>',
342
349
  };
343
350
 
@@ -11,8 +11,16 @@ const ContentFields = ({
11
11
  href: 'https://www.hubspot.com',
12
12
  },
13
13
  },
14
+ fieldVisibility,
14
15
  }: ContentFieldsProps) => {
15
- return <LinkField label={linkLabel} name={linkName} default={linkDefault} />;
16
+ return (
17
+ <LinkField
18
+ label={linkLabel}
19
+ name={linkName}
20
+ visibility={fieldVisibility?.[linkName]}
21
+ default={linkDefault}
22
+ />
23
+ );
16
24
  };
17
25
 
18
26
  export default ContentFields;
@@ -198,6 +198,19 @@ The Link component provides field definitions for easy integration with HubSpot
198
198
  />
199
199
  ```
200
200
 
201
+ **Props:**
202
+ - `linkLabel?: string` — label for the LinkField (default: `'Link'`)
203
+ - `linkName?: string` — field name (default: `'link'`)
204
+ - `linkDefault?` — default value for the LinkField
205
+ - `fieldVisibility?: Partial<Record<string, Visibility>>` — visibility options keyed by field name (keys must match the corresponding field name prop, e.g. `linkName`). Values match the cms-components Visibility schema (e.g. `hidden_subfields`, `controlling_field_path`, `operator`)
206
+
207
+ **Example — hide the nofollow option:**
208
+ ```tsx
209
+ <Link.ContentFields
210
+ fieldVisibility={{ link: { hidden_subfields: { no_follow: true } } }}
211
+ />
212
+ ```
213
+
201
214
  **Fields:**
202
215
  - `link`: LinkField for href destination
203
216
 
@@ -1,4 +1,4 @@
1
- import { LinkFieldDefaults } from '@hubspot/cms-components/fields';
1
+ import { LinkFieldDefaults, Visibility } from '@hubspot/cms-components/fields';
2
2
  import { LinkFieldValue } from '../utils/linkField.js';
3
3
 
4
4
  export type BaseLinkProps = {
@@ -37,6 +37,7 @@ export type ContentFieldsProps = {
37
37
  linkLabel?: string;
38
38
  linkName?: string;
39
39
  linkDefault?: typeof LinkFieldDefaults;
40
+ fieldVisibility?: Partial<Record<string, Visibility>>;
40
41
  };
41
42
 
42
43
  export type StyleFieldsProps = {
@@ -0,0 +1,25 @@
1
+ import { LogoField } from '@hubspot/cms-components/fields';
2
+ import { ContentFieldsProps } from './types.js';
3
+
4
+ const ContentFields = ({
5
+ logoLabel = 'Logo',
6
+ logoName = 'img',
7
+ logoDefault = {
8
+ override_inherited_src: false,
9
+ src: null,
10
+ alt: null,
11
+ loading: 'disabled',
12
+ },
13
+ showLoading = true,
14
+ }: ContentFieldsProps) => {
15
+ return (
16
+ <LogoField
17
+ label={logoLabel}
18
+ name={logoName}
19
+ showLoading={showLoading}
20
+ default={logoDefault}
21
+ />
22
+ );
23
+ };
24
+
25
+ export default ContentFields;
@@ -1,6 +1,7 @@
1
1
  import { useMemo } from 'react';
2
2
  import { useBrandSettings } from '@hubspot/cms-components';
3
3
  import { dummyLogoData } from './_dummyLogoData.js';
4
+ import ContentFields from './ContentFields.js';
4
5
  import { LogoData, LogoProps } from './types.js';
5
6
  import styles from './index.module.scss';
6
7
  import cx from '../utils/classname.js';
@@ -18,9 +19,10 @@ export const Logo = ({
18
19
  }: LogoProps) => {
19
20
  const { primaryLogo } = useBrandSettings() ?? {};
20
21
 
21
- const logo: LogoData | undefined = useMemo(() => {
22
- return useDummyLogo ? dummyLogoData.logo : primaryLogo;
23
- }, [useDummyLogo, primaryLogo]);
22
+ const logo: LogoData | undefined = useMemo(
23
+ () => (useDummyLogo ? dummyLogoData.logo : primaryLogo),
24
+ [useDummyLogo, primaryLogo]
25
+ );
24
26
 
25
27
  if (!logo?.src) {
26
28
  return null;
@@ -70,4 +72,11 @@ export const Logo = ({
70
72
  );
71
73
  };
72
74
 
73
- export default Logo;
75
+ type LogoComponentType = typeof Logo & {
76
+ ContentFields: typeof ContentFields;
77
+ };
78
+
79
+ const LogoWithFields = Logo as LogoComponentType;
80
+ LogoWithFields.ContentFields = ContentFields;
81
+
82
+ export default LogoWithFields;
@@ -6,6 +6,21 @@ export type LogoData = {
6
6
  link?: string;
7
7
  };
8
8
 
9
+ export type ContentFieldsProps = {
10
+ logoLabel?: string;
11
+ logoName?: string;
12
+ logoDefault?: {
13
+ override_inherited_src?: boolean;
14
+ src?: string | null;
15
+ alt?: string | null;
16
+ width?: number;
17
+ height?: number;
18
+ loading?: string;
19
+ suppress_company_name?: boolean;
20
+ };
21
+ showLoading?: boolean;
22
+ };
23
+
9
24
  export type LogoProps = {
10
25
  useDummyLogo?: boolean;
11
26
  className?: string;
@@ -203,6 +203,25 @@ const SHOW_ICON_VISIBILITY_RULES: Visibility = {
203
203
  />
204
204
  ```
205
205
 
206
+ ### Field Visibility Map Pattern
207
+
208
+ For components with configurable field names, use a `fieldVisibility` prop keyed by field name. Values match the cms-components `Visibility` schema (e.g. `hidden_subfields`, `controlling_field_path`, `operator`). Keys must match the field's name prop (e.g. `linkName`).
209
+
210
+ Link component example:
211
+
212
+ ```typescript
213
+ <Link.ContentFields
214
+ fieldVisibility={{ link: { hidden_subfields: { no_follow: true } } }}
215
+ />
216
+
217
+ <Link.ContentFields
218
+ linkName="footerLink"
219
+ fieldVisibility={{ footerLink: { hidden_subfields: { no_follow: true, open_in_new_tab: true } } }}
220
+ />
221
+ ```
222
+
223
+ **Key Pattern:** Look up visibility by the configurable name prop: `visibility={fieldVisibility?.[linkName]}`
224
+
206
225
  ## Nested Component Fields Pattern
207
226
 
208
227
  **Pattern for nested component fields:**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cms-component-library",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "HubSpot CMS React component library for building CMS modules",
5
5
  "license": "Apache-2.0",
6
6
  "exports": {