@hashicorp/react-components 1.1.10 → 1.2.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/README.md +1 -1
- package/package.json +8 -13
- package/postcss.config.js +1 -1
- package/src/components/nav-panel/components/flight-icon/index.tsx +53 -0
- package/src/components/nav-panel/components/flight-icon/style.module.css +3 -0
- package/src/components/nav-panel/components/link/cloud-fill.svg +3 -0
- package/src/components/nav-panel/components/link/index.tsx +139 -0
- package/src/components/nav-panel/components/link/layers-fill.svg +5 -0
- package/src/components/nav-panel/components/link/shield-alert-fill.svg +3 -0
- package/src/components/nav-panel/components/link/style.module.css +64 -0
- package/src/components/nav-panel/components/link/zap-fill.svg +3 -0
- package/src/components/nav-panel/components/link-list/index.tsx +12 -64
- package/src/components/nav-panel/components/link-list/style.module.css +1 -50
- package/src/components/nav-panel/components/panel/column/style.module.css +2 -2
- package/src/components/nav-panel/components/panel/root/style.module.css +5 -5
- package/src/components/nav-panel/components/promo/index.tsx +35 -15
- package/src/components/nav-panel/components/promo/style.module.css +32 -28
- package/src/components/nav-panel/components/text/index.tsx +34 -0
- package/src/components/nav-panel/product-panel/index.tsx +71 -20
- package/src/components/nav-panel/product-panel/style.module.css +111 -53
- package/src/components/nav-panel/standard-panel/index.tsx +3 -0
- package/src/components/nav-panel/standard-panel/style.module.css +2 -2
- package/src/lib/get-localized-link-props/index.test.ts +30 -0
- package/src/lib/get-localized-link-props/index.ts +45 -0
- package/src/lib/parse-url/index.test.ts +57 -2
- package/src/lib/parse-url/index.ts +97 -13
- package/src/lib/send-posthog-event/index.ts +22 -0
- package/src/lib/supported-locales/index.ts +10 -0
- package/src/lib/track-nav-click-event/index.ts +5 -5
- package/src/lib/v/index.ts +9 -4
- package/tsconfig.json +1 -2
- package/.eslintrc.js +0 -4
- package/.stylelintrc.js +0 -3
- package/src/components/actions/index.tsx +0 -107
- package/src/components/actions/style.module.css +0 -28
- package/src/components/actions/types.ts +0 -73
- package/src/components/call-to-action/index.tsx +0 -205
- package/src/components/call-to-action/styles/variant-centered.module.css +0 -93
- package/src/components/call-to-action/styles/variant-compact-grid.module.css +0 -88
- package/src/components/call-to-action/styles/variant-compact.module.css +0 -91
- package/src/components/call-to-action/styles/variant-links.module.css +0 -85
- package/src/components/card/README.md +0 -11
- package/src/components/card/card.tsx +0 -45
- package/src/components/card/index.test.tsx +0 -69
- package/src/components/card/index.tsx +0 -14
- package/src/components/card/newsroom-card/index.test.tsx +0 -39
- package/src/components/card/newsroom-card/index.tsx +0 -37
- package/src/components/card/newsroom-card/style.module.css +0 -12
- package/src/components/card/partner-card/index.test.tsx +0 -57
- package/src/components/card/partner-card/index.tsx +0 -69
- package/src/components/card/partner-card/style.module.css +0 -24
- package/src/components/card/person-card/index.test.tsx +0 -71
- package/src/components/card/person-card/index.tsx +0 -93
- package/src/components/card/person-card/style.module.css +0 -33
- package/src/components/card/primitives.tsx +0 -176
- package/src/components/card/promo-card/index.tsx +0 -51
- package/src/components/card/resource-card/index.test.tsx +0 -48
- package/src/components/card/resource-card/index.tsx +0 -37
- package/src/components/card/style.module.css +0 -145
- package/src/components/card/types.ts +0 -66
- package/src/components/card/unified-card/index.tsx +0 -64
- package/src/components/consent-manager/README.md +0 -73
- package/src/components/consent-manager/components/banner/banner.module.css +0 -23
- package/src/components/consent-manager/components/banner/banner.test.tsx +0 -31
- package/src/components/consent-manager/components/banner/banner.tsx +0 -73
- package/src/components/consent-manager/components/dialog/dialog.module.css +0 -145
- package/src/components/consent-manager/components/dialog/dialog.test.tsx +0 -194
- package/src/components/consent-manager/components/dialog/dialog.tsx +0 -339
- package/src/components/consent-manager/img/icn_close.tsx +0 -19
- package/src/components/consent-manager/index.test.tsx +0 -334
- package/src/components/consent-manager/index.tsx +0 -186
- package/src/components/consent-manager/loader/README.md +0 -29
- package/src/components/consent-manager/loader/categories.ts +0 -22
- package/src/components/consent-manager/loader/index.tsx +0 -94
- package/src/components/consent-manager/loader/presets/enterprise.ts +0 -12
- package/src/components/consent-manager/loader/presets/oss.ts +0 -10
- package/src/components/consent-manager/loader/services.ts +0 -45
- package/src/components/consent-manager/scripts/custom.tsx +0 -59
- package/src/components/consent-manager/scripts/segment.tsx +0 -87
- package/src/components/consent-manager/style.module.css +0 -9
- package/src/components/consent-manager/types.ts +0 -55
- package/src/components/consent-manager/util/cookies.test.ts +0 -75
- package/src/components/consent-manager/util/cookies.ts +0 -70
- package/src/components/consent-manager/util/integrations.test.ts +0 -115
- package/src/components/consent-manager/util/integrations.ts +0 -110
- package/src/components/intro/index.tsx +0 -82
- package/src/components/intro/style.module.css +0 -67
- package/src/components/intro/types.ts +0 -44
- package/src/components/marketo-form/CHANGELOG.md +0 -122
- package/src/components/marketo-form/README.md +0 -1
- package/src/components/marketo-form/contexts/FormMetadata.ts +0 -11
- package/src/components/marketo-form/docs.mdx +0 -197
- package/src/components/marketo-form/fixtures/index.ts +0 -185
- package/src/components/marketo-form/form/index.tsx +0 -369
- package/src/components/marketo-form/index.test.tsx +0 -320
- package/src/components/marketo-form/index.ts +0 -11
- package/src/components/marketo-form/package.original.json +0 -30
- package/src/components/marketo-form/partials/error-message/index.tsx +0 -12
- package/src/components/marketo-form/partials/error-message/style.module.css +0 -13
- package/src/components/marketo-form/partials/field/index.tsx +0 -90
- package/src/components/marketo-form/partials/field-wrapper/index.tsx +0 -26
- package/src/components/marketo-form/partials/fields/checkbox-field/index.tsx +0 -32
- package/src/components/marketo-form/partials/fields/email-field/index.tsx +0 -35
- package/src/components/marketo-form/partials/fields/form-page-url-field/index.tsx +0 -21
- package/src/components/marketo-form/partials/fields/hidden-field/index.tsx +0 -37
- package/src/components/marketo-form/partials/fields/htmltext-field/index.tsx +0 -21
- package/src/components/marketo-form/partials/fields/htmltext-field/style.module.css +0 -18
- package/src/components/marketo-form/partials/fields/name-field/index.tsx +0 -19
- package/src/components/marketo-form/partials/fields/name-field/style.module.css +0 -13
- package/src/components/marketo-form/partials/fields/radio-buttons-field/index.tsx +0 -48
- package/src/components/marketo-form/partials/fields/select-field/index.tsx +0 -39
- package/src/components/marketo-form/partials/fields/select-field/style.module.css +0 -5
- package/src/components/marketo-form/partials/fields/telephone-field/index.tsx +0 -30
- package/src/components/marketo-form/partials/fields/text-field/index.tsx +0 -30
- package/src/components/marketo-form/partials/fields/textarea-field/index.tsx +0 -29
- package/src/components/marketo-form/partials/label/index.tsx +0 -24
- package/src/components/marketo-form/partials/label/style.module.css +0 -12
- package/src/components/marketo-form/partials/visibility-rule/index.tsx +0 -84
- package/src/components/marketo-form/props.js +0 -66
- package/src/components/marketo-form/server/api-routes.ts +0 -109
- package/src/components/marketo-form/server/client.ts +0 -98
- package/src/components/marketo-form/server/index.ts +0 -8
- package/src/components/marketo-form/types.ts +0 -268
- package/src/components/marketo-form/utils.test.tsx +0 -103
- package/src/components/marketo-form/utils.ts +0 -449
- package/src/components/next-steps/index.tsx +0 -137
- package/src/components/next-steps/style.module.css +0 -270
- package/src/components/next-steps/types.ts +0 -63
- package/src/components/product-badge/index.test.tsx +0 -11
- package/src/components/product-badge/index.tsx +0 -42
- package/src/components/product-badge/style.module.css +0 -76
- package/src/components/products-used/index.tsx +0 -84
- package/src/components/products-used/style.module.css +0 -87
- package/src/components/products-used/types.ts +0 -31
- package/src/components/related-content/index.test.tsx +0 -74
- package/src/components/related-content/index.tsx +0 -56
- package/src/components/related-content/style.module.css +0 -89
- package/src/components/related-content/types.ts +0 -21
- package/src/components/subnav/helpers/areBasePathsMatching.ts +0 -13
- package/src/components/subnav/helpers/traverse/index.ts +0 -42
- package/src/components/subnav/helpers/useHeightRef.ts +0 -42
- package/src/components/subnav/helpers/useNavRef.ts +0 -30
- package/src/components/subnav/helpers/useOverflowRef.ts +0 -85
- package/src/components/subnav/helpers/useStuckRef.ts +0 -51
- package/src/components/subnav/index.tsx +0 -199
- package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.test.ts +0 -26
- package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.ts +0 -22
- package/src/components/subnav/partials/CtaLinks/github-stars-link/index.tsx +0 -87
- package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.test.ts +0 -29
- package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.ts +0 -32
- package/src/components/subnav/partials/CtaLinks/github-stars-link/style.module.css +0 -85
- package/src/components/subnav/partials/CtaLinks/icons/github-logo.js +0 -20
- package/src/components/subnav/partials/CtaLinks/icons/github.svg.js +0 -7
- package/src/components/subnav/partials/CtaLinks/icons/star.js +0 -20
- package/src/components/subnav/partials/CtaLinks/index.tsx +0 -130
- package/src/components/subnav/partials/CtaLinks/style.module.css +0 -45
- package/src/components/subnav/partials/DropdownTrigger/index.tsx +0 -35
- package/src/components/subnav/partials/DropdownTrigger/style.module.css +0 -36
- package/src/components/subnav/partials/MenuItemsDefault/index.tsx +0 -151
- package/src/components/subnav/partials/MenuItemsDefault/style.module.css +0 -91
- package/src/components/subnav/partials/MenuItemsOverflow/index.tsx +0 -139
- package/src/components/subnav/partials/MenuItemsOverflow/style.module.css +0 -82
- package/src/components/subnav/partials/TitleLink/index.tsx +0 -113
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-dark.ts +0 -9
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-light.ts +0 -9
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-dark.ts +0 -23
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-light.ts +0 -23
- package/src/components/subnav/partials/TitleLink/style.module.css +0 -43
- package/src/components/subnav/partials/nav-item-text/index.tsx +0 -37
- package/src/components/subnav/partials/nav-item-text/style.module.css +0 -15
- package/src/components/subnav/style.module.css +0 -68
- package/src/components/subnav/subnav-consts.ts +0 -1
- package/src/components/subnav/theme.module.css +0 -50
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import TextField from '../text-field'
|
|
7
|
-
import type { MarketoFormField, MarketoFormTextField } from '../../../types'
|
|
8
|
-
import styles from './style.module.css'
|
|
9
|
-
|
|
10
|
-
const NameFields = ({ fields }: { fields: MarketoFormField[] }) => {
|
|
11
|
-
return (
|
|
12
|
-
<div className={styles.name}>
|
|
13
|
-
<TextField field={fields[0] as MarketoFormTextField} />
|
|
14
|
-
<TextField field={fields[1] as MarketoFormTextField} />
|
|
15
|
-
</div>
|
|
16
|
-
)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default NameFields
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { useFormContext } from 'react-hook-form'
|
|
2
|
-
import RadioCard, {
|
|
3
|
-
RadioCardGroup,
|
|
4
|
-
} from '@hashicorp/react-design-system-components/src/components/form/radio-card'
|
|
5
|
-
import FieldWrapper from '../../field-wrapper'
|
|
6
|
-
import type { MarketoFormRadioButtonsField } from '../../../types'
|
|
7
|
-
|
|
8
|
-
const RadioCardField = ({ field }: { field: MarketoFormRadioButtonsField }) => {
|
|
9
|
-
const {
|
|
10
|
-
register,
|
|
11
|
-
watch,
|
|
12
|
-
formState: { errors },
|
|
13
|
-
} = useFormContext()
|
|
14
|
-
const error = errors[field.id]?.message as string
|
|
15
|
-
const currentSelection = watch(field.id)
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<FieldWrapper fieldId={field.id}>
|
|
19
|
-
<RadioCardGroup
|
|
20
|
-
error={error}
|
|
21
|
-
layout="vertical"
|
|
22
|
-
isRequired={field.required}
|
|
23
|
-
legend={field.label}
|
|
24
|
-
id={field.id}
|
|
25
|
-
aria-describedby={error && `error-${field.id}-error`}
|
|
26
|
-
>
|
|
27
|
-
{field.fieldMetaData.values.map(({ label, value }) => (
|
|
28
|
-
<RadioCard
|
|
29
|
-
controlPosition="left"
|
|
30
|
-
key={value}
|
|
31
|
-
label={label}
|
|
32
|
-
field={{
|
|
33
|
-
...register(field.id, { required: field.validationMessage }),
|
|
34
|
-
checked: currentSelection === value,
|
|
35
|
-
value,
|
|
36
|
-
name: field.id,
|
|
37
|
-
required: field.required,
|
|
38
|
-
'aria-invalid': Boolean(errors[field.id]),
|
|
39
|
-
'aria-describedby': error && `error-${field.id}-error`,
|
|
40
|
-
}}
|
|
41
|
-
/>
|
|
42
|
-
))}
|
|
43
|
-
</RadioCardGroup>
|
|
44
|
-
</FieldWrapper>
|
|
45
|
-
)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export default RadioCardField
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useFormContext } from 'react-hook-form'
|
|
7
|
-
import Select from '@hashicorp/react-design-system-components/src/components/form/select'
|
|
8
|
-
import FieldWrapper from '../../field-wrapper'
|
|
9
|
-
import { formattedLabel, useErrorMessage } from '../../../utils'
|
|
10
|
-
import type { MarketoFormSelectField } from '../../../types'
|
|
11
|
-
import s from './style.module.css'
|
|
12
|
-
|
|
13
|
-
const SelectField = ({ field }: { field: MarketoFormSelectField }) => {
|
|
14
|
-
const { register } = useFormContext()
|
|
15
|
-
const error = useErrorMessage(field.id)
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<FieldWrapper fieldId={field.id}>
|
|
19
|
-
<Select
|
|
20
|
-
field={{ ...register(field.id) }}
|
|
21
|
-
size="large"
|
|
22
|
-
label={formattedLabel(field)}
|
|
23
|
-
error={error}
|
|
24
|
-
isRequired={field.required}
|
|
25
|
-
className={s.selectConstrainWidth}
|
|
26
|
-
>
|
|
27
|
-
{field.fieldMetaData.values
|
|
28
|
-
? field.fieldMetaData.values.map(({ label, value }) => (
|
|
29
|
-
<option key={label} value={value}>
|
|
30
|
-
{label}
|
|
31
|
-
</option>
|
|
32
|
-
))
|
|
33
|
-
: []}
|
|
34
|
-
</Select>
|
|
35
|
-
</FieldWrapper>
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export default SelectField
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useFormContext } from 'react-hook-form'
|
|
7
|
-
import TextInput from '@hashicorp/react-design-system-components/src/components/form/text-input'
|
|
8
|
-
import FieldWrapper from '../../field-wrapper'
|
|
9
|
-
import { formattedLabel, useErrorMessage } from '../../../utils'
|
|
10
|
-
import type { MarketoFormTelephoneField } from '../../../types'
|
|
11
|
-
|
|
12
|
-
const TelephoneField = ({ field }: { field: MarketoFormTelephoneField }) => {
|
|
13
|
-
const { register } = useFormContext()
|
|
14
|
-
const error = useErrorMessage(field.id)
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<FieldWrapper fieldId={field.id}>
|
|
18
|
-
<TextInput
|
|
19
|
-
label={formattedLabel(field)}
|
|
20
|
-
type="tel"
|
|
21
|
-
field={{ ...register(field.id), placeholder: field.hintText }}
|
|
22
|
-
size="large"
|
|
23
|
-
error={error}
|
|
24
|
-
isRequired={field.required}
|
|
25
|
-
/>
|
|
26
|
-
</FieldWrapper>
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export default TelephoneField
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useFormContext } from 'react-hook-form'
|
|
7
|
-
import TextInput from '@hashicorp/react-design-system-components/src/components/form/text-input'
|
|
8
|
-
import FieldWrapper from '../../field-wrapper'
|
|
9
|
-
import { formattedLabel, useErrorMessage } from '../../../utils'
|
|
10
|
-
import type { MarketoFormTextField } from '../../../types'
|
|
11
|
-
|
|
12
|
-
const Index = ({ field }: { field: MarketoFormTextField }) => {
|
|
13
|
-
const { register } = useFormContext()
|
|
14
|
-
const error = useErrorMessage(field.id)
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<FieldWrapper fieldId={field.id}>
|
|
18
|
-
<TextInput
|
|
19
|
-
label={formattedLabel(field)}
|
|
20
|
-
type="text"
|
|
21
|
-
field={{ ...register(field.id), placeholder: field.hintText }}
|
|
22
|
-
size="large"
|
|
23
|
-
error={error}
|
|
24
|
-
isRequired={field.required}
|
|
25
|
-
/>
|
|
26
|
-
</FieldWrapper>
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export default Index
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useFormContext } from 'react-hook-form'
|
|
7
|
-
import Textarea from '@hashicorp/react-design-system-components/src/components/form/textarea'
|
|
8
|
-
import FieldWrapper from '../../field-wrapper'
|
|
9
|
-
import { formattedLabel, useErrorMessage } from '../../../utils'
|
|
10
|
-
import type { MarketoFormTextAreaField } from '../../../types'
|
|
11
|
-
|
|
12
|
-
const Index = ({ field }: { field: MarketoFormTextAreaField }) => {
|
|
13
|
-
const { register } = useFormContext()
|
|
14
|
-
const error = useErrorMessage(field.id)
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<FieldWrapper fieldId={field.id}>
|
|
18
|
-
<Textarea
|
|
19
|
-
label={formattedLabel(field)}
|
|
20
|
-
field={{ ...register(field.id), placeholder: field.hintText }}
|
|
21
|
-
size="large"
|
|
22
|
-
error={error}
|
|
23
|
-
isRequired={field.required}
|
|
24
|
-
/>
|
|
25
|
-
</FieldWrapper>
|
|
26
|
-
)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default Index
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import clsx from 'clsx'
|
|
7
|
-
import s from './style.module.css'
|
|
8
|
-
|
|
9
|
-
interface LabelProps {
|
|
10
|
-
label: string
|
|
11
|
-
fieldName: string
|
|
12
|
-
className?: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default function Label({ label, fieldName, className }: LabelProps) {
|
|
16
|
-
return (
|
|
17
|
-
<label
|
|
18
|
-
htmlFor={fieldName}
|
|
19
|
-
className={clsx(className && className, s.label)}
|
|
20
|
-
>
|
|
21
|
-
{label}
|
|
22
|
-
</label>
|
|
23
|
-
)
|
|
24
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useMemo } from 'react'
|
|
7
|
-
import { useFormContext } from 'react-hook-form'
|
|
8
|
-
import Field from '../field'
|
|
9
|
-
import type {
|
|
10
|
-
MarketoFormField,
|
|
11
|
-
MarketoFormComponents,
|
|
12
|
-
VisibilityRule as VisibilityRuleType,
|
|
13
|
-
} from '../../types'
|
|
14
|
-
|
|
15
|
-
function ruleApplies(rule: VisibilityRuleType, value: any): boolean {
|
|
16
|
-
switch (rule.operator) {
|
|
17
|
-
case 'is':
|
|
18
|
-
return (
|
|
19
|
-
rule.values.includes(value) ||
|
|
20
|
-
(value === false && rule.values.includes('no')) ||
|
|
21
|
-
(value === true && rule.values.includes('yes'))
|
|
22
|
-
)
|
|
23
|
-
case 'isNot':
|
|
24
|
-
return !rule.values.includes(value)
|
|
25
|
-
case 'isEmpty':
|
|
26
|
-
return value === null || typeof value === 'undefined' || value === ''
|
|
27
|
-
default:
|
|
28
|
-
return false
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const FieldWithVisibilityRule = ({
|
|
33
|
-
field,
|
|
34
|
-
components,
|
|
35
|
-
}: {
|
|
36
|
-
field: MarketoFormField
|
|
37
|
-
components?: MarketoFormComponents
|
|
38
|
-
}) => {
|
|
39
|
-
const { watch } = useFormContext()
|
|
40
|
-
|
|
41
|
-
// Currently we only support the first defined rule.
|
|
42
|
-
const value = watch(field.visibilityRules!.rules![0].subjectField)
|
|
43
|
-
|
|
44
|
-
const hasMatchingRule = useMemo(() => {
|
|
45
|
-
return field.visibilityRules!.rules!.some((rule) =>
|
|
46
|
-
ruleApplies(rule, value)
|
|
47
|
-
)
|
|
48
|
-
}, [field, value])
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
hasMatchingRule &&
|
|
52
|
-
(field.visibilityRules!.ruleType === 'show' ||
|
|
53
|
-
field.visibilityRules!.ruleType === 'hide')
|
|
54
|
-
) {
|
|
55
|
-
return field.visibilityRules!.ruleType === 'show' ? (
|
|
56
|
-
<Field field={field} components={components} />
|
|
57
|
-
) : null
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// If the ruleType is show, that means the field is hidden by default.
|
|
61
|
-
return field.visibilityRules!.ruleType === 'show' ? null : (
|
|
62
|
-
<Field field={field} components={components} />
|
|
63
|
-
)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const VisibilityRule = ({
|
|
67
|
-
field,
|
|
68
|
-
components,
|
|
69
|
-
}: {
|
|
70
|
-
field: MarketoFormField
|
|
71
|
-
components?: MarketoFormComponents
|
|
72
|
-
}) => {
|
|
73
|
-
if (
|
|
74
|
-
field.visibilityRules &&
|
|
75
|
-
(field.visibilityRules.ruleType === 'show' ||
|
|
76
|
-
field.visibilityRules.ruleType === 'hide')
|
|
77
|
-
) {
|
|
78
|
-
return <FieldWithVisibilityRule field={field} components={components} />
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return <Field field={field} components={components} />
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export default VisibilityRule
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
module.exports = {
|
|
7
|
-
formId: {
|
|
8
|
-
type: 'number',
|
|
9
|
-
required: true,
|
|
10
|
-
description:
|
|
11
|
-
'The numeric ID of the Marketo form that this component is rendering.',
|
|
12
|
-
},
|
|
13
|
-
marketoForm: {
|
|
14
|
-
type: 'object',
|
|
15
|
-
required: true,
|
|
16
|
-
description:
|
|
17
|
-
'The API response containing the fields of the form this component should render.',
|
|
18
|
-
},
|
|
19
|
-
groups: {
|
|
20
|
-
type: 'object',
|
|
21
|
-
description:
|
|
22
|
-
'Mapping of fields that should be rendered with a single component.',
|
|
23
|
-
},
|
|
24
|
-
components: {
|
|
25
|
-
type: 'object',
|
|
26
|
-
description: 'Custom components to use instead of the built-in components',
|
|
27
|
-
properties: {
|
|
28
|
-
text: {
|
|
29
|
-
type: 'React.ComponentType',
|
|
30
|
-
description: 'Component to use for text fields',
|
|
31
|
-
},
|
|
32
|
-
email: {
|
|
33
|
-
type: 'React.ComponentType',
|
|
34
|
-
description: 'Component to use for email fields',
|
|
35
|
-
},
|
|
36
|
-
select: {
|
|
37
|
-
type: 'React.ComponentType',
|
|
38
|
-
description: 'Component to use for select fields',
|
|
39
|
-
},
|
|
40
|
-
checkbox: {
|
|
41
|
-
type: 'React.ComponentType',
|
|
42
|
-
description: 'Component to use for checkbox fields',
|
|
43
|
-
},
|
|
44
|
-
hidden: {
|
|
45
|
-
type: 'React.ComponentType',
|
|
46
|
-
description: 'Component to use for hidden fields',
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
submitTitle: {
|
|
51
|
-
type: 'string',
|
|
52
|
-
description: 'Title to use for the submit button',
|
|
53
|
-
},
|
|
54
|
-
className: {
|
|
55
|
-
type: 'string',
|
|
56
|
-
description: 'Additional classNames passed to the form element.',
|
|
57
|
-
},
|
|
58
|
-
onSubmitSuccess: {
|
|
59
|
-
type: 'function',
|
|
60
|
-
description: 'Callback function invoked on submission success',
|
|
61
|
-
},
|
|
62
|
-
onSubmitFailure: {
|
|
63
|
-
type: 'function',
|
|
64
|
-
description: 'Callback function invoked on submission failure',
|
|
65
|
-
},
|
|
66
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as client from './client'
|
|
7
|
-
import { includesSkippedRecords } from '../utils'
|
|
8
|
-
import type { SubmissionFilter, MarketoSubmissionResponse } from '../types'
|
|
9
|
-
import type { NextApiRequest, NextApiResponse } from 'next'
|
|
10
|
-
|
|
11
|
-
async function notifyError(body: unknown, err: unknown) {
|
|
12
|
-
if (process.env.MARKETO_ERROR_ZAPIER_WEBHOOK) {
|
|
13
|
-
try {
|
|
14
|
-
await fetch(process.env.MARKETO_ERROR_ZAPIER_WEBHOOK, {
|
|
15
|
-
method: 'POST',
|
|
16
|
-
headers: {
|
|
17
|
-
'Content-Type': 'application/json',
|
|
18
|
-
},
|
|
19
|
-
body: JSON.stringify({ body, err }, null, 2),
|
|
20
|
-
})
|
|
21
|
-
} catch (err) {
|
|
22
|
-
console.error({ body, err })
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return Promise.resolve()
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function isE2ETest(req: NextApiRequest): boolean {
|
|
30
|
-
// running e2e tests locally
|
|
31
|
-
if (process.env.E2E_TESTS === 'true') {
|
|
32
|
-
return true
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// running e2e tests against a Vercel preview
|
|
36
|
-
if (
|
|
37
|
-
'input' in req.body &&
|
|
38
|
-
req.body.input.length > 0 &&
|
|
39
|
-
req.body.input[0].leadFormFields.email === 'daniela.rod@example.com'
|
|
40
|
-
) {
|
|
41
|
-
return true
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return false
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async function submitForm(
|
|
48
|
-
req: NextApiRequest,
|
|
49
|
-
res: NextApiResponse,
|
|
50
|
-
{
|
|
51
|
-
submissionFilter,
|
|
52
|
-
}: {
|
|
53
|
-
submissionFilter?: SubmissionFilter
|
|
54
|
-
}
|
|
55
|
-
) {
|
|
56
|
-
// Don't submit forms to the Marketo API when using E2E tests.
|
|
57
|
-
if (isE2ETest(req)) {
|
|
58
|
-
res.status(200).json({
|
|
59
|
-
requestId: '7d85#181a7ae5e56',
|
|
60
|
-
result: [
|
|
61
|
-
{
|
|
62
|
-
id: 25325329,
|
|
63
|
-
status: 'updated',
|
|
64
|
-
},
|
|
65
|
-
],
|
|
66
|
-
success: true,
|
|
67
|
-
})
|
|
68
|
-
return
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
try {
|
|
72
|
-
const passesSubmissionFilter = submissionFilter
|
|
73
|
-
? await submissionFilter(req)
|
|
74
|
-
: true
|
|
75
|
-
if (!passesSubmissionFilter) {
|
|
76
|
-
// trick spammers into thinking their form submitted successfully
|
|
77
|
-
res.status(200).json({ success: true })
|
|
78
|
-
return
|
|
79
|
-
}
|
|
80
|
-
const marketoRes = await client.submitForm(req.body)
|
|
81
|
-
const form = (await marketoRes.json()) as MarketoSubmissionResponse
|
|
82
|
-
if (!form.success || includesSkippedRecords(form)) {
|
|
83
|
-
await notifyError(req.body, form)
|
|
84
|
-
}
|
|
85
|
-
res.status(marketoRes.status).json(form)
|
|
86
|
-
} catch (err) {
|
|
87
|
-
await notifyError(req.body, err)
|
|
88
|
-
res.status(500).json({ error: 'internal server error' })
|
|
89
|
-
throw err
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function buildApiRoutes({
|
|
94
|
-
submissionFilter,
|
|
95
|
-
}: {
|
|
96
|
-
submissionFilter?: SubmissionFilter
|
|
97
|
-
} = {}) {
|
|
98
|
-
return async function apiRoutes(req: NextApiRequest, res: NextApiResponse) {
|
|
99
|
-
const route = Array.isArray(req.query.marketo)
|
|
100
|
-
? req.query.marketo[0]
|
|
101
|
-
: req.query.marketo
|
|
102
|
-
switch (route) {
|
|
103
|
-
case 'submit':
|
|
104
|
-
return submitForm(req, res, { submissionFilter })
|
|
105
|
-
default:
|
|
106
|
-
return res.status(404).json({ error: 'not found' })
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) HashiCorp, Inc.
|
|
3
|
-
* SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import moize from 'moize'
|
|
7
|
-
import type {
|
|
8
|
-
MarketoFormFieldsResponse,
|
|
9
|
-
MarketoFormMetadataResponse,
|
|
10
|
-
MarketoFormAPIResponse,
|
|
11
|
-
} from '../types'
|
|
12
|
-
|
|
13
|
-
interface MarketoTokenResponse {
|
|
14
|
-
access_token: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function getToken(): Promise<MarketoTokenResponse> {
|
|
18
|
-
const url = new URL(`${process.env.MARKETO_IDENTITY}/oauth/token`)
|
|
19
|
-
url.searchParams.append('grant_type', 'client_credentials')
|
|
20
|
-
url.searchParams.append('client_id', process.env.MARKETO_CLIENT_ID!)
|
|
21
|
-
url.searchParams.append('client_secret', process.env.MARKETO_CLIENT_SECRET!)
|
|
22
|
-
const res = await fetch(url.toString())
|
|
23
|
-
return await res.json()
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export async function getForm(formId: number) {
|
|
27
|
-
return await fetch(`https://content.hashicorp.com/api/marketo?id=${formId}`)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export async function getDraftFormProps(formId: number) {
|
|
31
|
-
const { access_token } = await getToken()
|
|
32
|
-
|
|
33
|
-
const fieldsResponse = await fetch(
|
|
34
|
-
`${process.env.MARKETO_ENDPOINT}/asset/v1/form/${formId}/fields.json?status=draft`,
|
|
35
|
-
{
|
|
36
|
-
headers: {
|
|
37
|
-
'Content-Type': 'application/json',
|
|
38
|
-
Authorization: `Bearer ${access_token}`,
|
|
39
|
-
},
|
|
40
|
-
}
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
const metadataResponse = await fetch(
|
|
44
|
-
`${process.env.MARKETO_ENDPOINT}/asset/v1/form/${formId}.json?status=draft`,
|
|
45
|
-
{
|
|
46
|
-
headers: {
|
|
47
|
-
'Content-Type': 'application/json',
|
|
48
|
-
Authorization: `Bearer ${access_token}`,
|
|
49
|
-
},
|
|
50
|
-
}
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
const [fields, metadata] = await Promise.all([
|
|
54
|
-
fieldsResponse.json(),
|
|
55
|
-
metadataResponse.json(),
|
|
56
|
-
])
|
|
57
|
-
|
|
58
|
-
return { fields, metadata }
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export async function getFormProps(
|
|
62
|
-
id: number
|
|
63
|
-
): Promise<MarketoFormAPIResponse> {
|
|
64
|
-
const res = await getForm(id)
|
|
65
|
-
if (res.status !== 200) {
|
|
66
|
-
throw new Error(
|
|
67
|
-
`[marketo-form] non-200 status code when requesting form ${id}: ${res.status}`
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const form = (await res.json()) as {
|
|
72
|
-
result: {
|
|
73
|
-
fields: MarketoFormFieldsResponse
|
|
74
|
-
metadata: MarketoFormMetadataResponse
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return form.result
|
|
79
|
-
}
|
|
80
|
-
export const memoizedGetFormProps = moize(getFormProps, {
|
|
81
|
-
isPromise: true,
|
|
82
|
-
maxAge: 60 * 1000, // 60 seconds
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
export async function submitForm(body: unknown) {
|
|
86
|
-
const { access_token } = await getToken()
|
|
87
|
-
return await fetch(
|
|
88
|
-
`${process.env.MARKETO_ENDPOINT}/v1/leads/submitForm.json`,
|
|
89
|
-
{
|
|
90
|
-
method: 'POST',
|
|
91
|
-
headers: {
|
|
92
|
-
'Content-Type': 'application/json',
|
|
93
|
-
Authorization: `Bearer ${access_token}`,
|
|
94
|
-
},
|
|
95
|
-
body: JSON.stringify(body),
|
|
96
|
-
}
|
|
97
|
-
)
|
|
98
|
-
}
|