@jmeirinkmarimed/form-popup 1.0.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/LICENSE +21 -0
- package/README.md +162 -0
- package/dist/FormPopup/FormPopup.d.ts +5 -0
- package/dist/FormPopup/FormPopup.injected.css.d.ts +5 -0
- package/dist/FormPopup/FormPopup.styles.d.ts +13 -0
- package/dist/FormPopup/api/submitHubSpotForm.d.ts +20 -0
- package/dist/FormPopup/getWebComponentHost.d.ts +3 -0
- package/dist/FormPopup/hooks/useDeferredReady.d.ts +8 -0
- package/dist/FormPopup/hooks/useFormPopupVisibility.d.ts +5 -0
- package/dist/FormPopup/parseCommunicationConsents.d.ts +3 -0
- package/dist/FormPopup/parseStates.d.ts +1 -0
- package/dist/FormPopup/resolveRecaptchaText.d.ts +6 -0
- package/dist/FormPopup/screens/ConfirmationScreen.d.ts +10 -0
- package/dist/FormPopup/screens/FormScreen.d.ts +27 -0
- package/dist/FormPopup/types.d.ts +82 -0
- package/dist/form-popup.cjs.js +45 -0
- package/dist/form-popup.cjs.js.map +1 -0
- package/dist/form-popup.es.js +1052 -0
- package/dist/form-popup.es.js.map +1 -0
- package/dist/form-popup.min.js +84 -0
- package/dist/form-popup.min.js.map +1 -0
- package/dist/form-popup.umd.js +45 -0
- package/dist/form-popup.umd.js.map +1 -0
- package/dist/iife.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/utils/cloudinaryPlaceholder.d.ts +5 -0
- package/dist/web-component/registerFormPopupElement.d.ts +4 -0
- package/package.json +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Jesse Meirink / Marimed Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Form Popup
|
|
2
|
+
|
|
3
|
+
Email-capture modal for React apps and plain HTML sites. Ships as a React component and as a `<form-popup>` custom element (IIFE for static pages). Submits to HubSpot, then shows a confirmation screen. After a successful submit, the popup stays dismissed on later visits via `localStorage`.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Form screen, then confirmation screen after submit
|
|
8
|
+
- Persists completion in `localStorage` (`formPopupSubmitted:<formId>`) so returning visitors do not see it again
|
|
9
|
+
- Maps email, state, and one extra property to HubSpot field names of your choosing
|
|
10
|
+
- Optional GDPR processing consent and HubSpot communication/subscription checkboxes
|
|
11
|
+
- Customizable copy, state list, colors, and fonts
|
|
12
|
+
- Style isolation via Shadow DOM on the web-component path
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @jmeirinkmarimed/form-popup
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Peer dependency: React 17 or 18.
|
|
21
|
+
|
|
22
|
+
### React
|
|
23
|
+
|
|
24
|
+
```jsx
|
|
25
|
+
import { FormPopup } from '@jmeirinkmarimed/form-popup';
|
|
26
|
+
|
|
27
|
+
function App() {
|
|
28
|
+
return (
|
|
29
|
+
<FormPopup
|
|
30
|
+
hubspotPortalId="YOUR_PORTAL_ID"
|
|
31
|
+
hubspotFormId="YOUR_FORM_GUID"
|
|
32
|
+
emailProperty="email"
|
|
33
|
+
stateProperty="state"
|
|
34
|
+
additionalPropertyName="signup_source"
|
|
35
|
+
additionalPropertyValue="homepage_popup"
|
|
36
|
+
consentToProcessText="I agree to allow Example Company to store and process my personal data."
|
|
37
|
+
formTitle="Sign up for 10% off your first purchase!"
|
|
38
|
+
formSubtitle="Enter your email to join our mailing list."
|
|
39
|
+
states={[
|
|
40
|
+
"Delaware",
|
|
41
|
+
"Maryland",
|
|
42
|
+
"Massachusetts",
|
|
43
|
+
"Illinois",
|
|
44
|
+
"Missouri",
|
|
45
|
+
"Just Browsing",
|
|
46
|
+
]}
|
|
47
|
+
confirmationTitle="Use code WELCOME10 for 10% off!"
|
|
48
|
+
confirmationMessage="You're officially on the list for sweet updates delivered straight to your inbox."
|
|
49
|
+
confirmationButtonText="Shop Betty's"
|
|
50
|
+
confirmationButtonUrl="https://shopbettys.com"
|
|
51
|
+
waitForAgeGate
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### HTML
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<script src="https://unpkg.com/@jmeirinkmarimed/form-popup/dist/form-popup.min.js"></script>
|
|
61
|
+
|
|
62
|
+
<form-popup
|
|
63
|
+
hubspot-portal-id="YOUR_PORTAL_ID"
|
|
64
|
+
hubspot-form-id="YOUR_FORM_GUID"
|
|
65
|
+
email-property="email"
|
|
66
|
+
state-property="state"
|
|
67
|
+
additional-property-name="signup_source"
|
|
68
|
+
additional-property-value="homepage_popup"
|
|
69
|
+
consent-to-process-text="I agree to allow Example Company to store and process my personal data."
|
|
70
|
+
communication-consents='[{"subscriptionTypeId":999,"text":"I agree to receive other communications from Example Company."}]'
|
|
71
|
+
form-title="Sign up for 10% off your first purchase!"
|
|
72
|
+
form-subtitle="Enter your email to join our mailing list."
|
|
73
|
+
states="Delaware,Maryland,Massachusetts,Illinois,Missouri,Just Browsing"
|
|
74
|
+
confirmation-title="Use code WELCOME10 for 10% off!"
|
|
75
|
+
confirmation-message="You're officially on the list for sweet updates delivered straight to your inbox."
|
|
76
|
+
confirmation-button-text="Shop Betty's"
|
|
77
|
+
confirmation-button-url="https://shopbettys.com"
|
|
78
|
+
wait-for-age-gate="true"
|
|
79
|
+
></form-popup>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Attribute names are kebab-case versions of the React props. `states` is a comma-separated list in HTML. `communicationConsents` is a JSON array in HTML.
|
|
83
|
+
|
|
84
|
+
## Props / attributes
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Default | Description |
|
|
87
|
+
|------|------|---------|-------------|
|
|
88
|
+
| `hubspotPortalId` | string | — | HubSpot portal ID (required). Use `"demo"` to skip the API in local previews. |
|
|
89
|
+
| `hubspotFormId` | string | — | HubSpot form GUID fields are submitted to (required) |
|
|
90
|
+
| `emailProperty` | string | `"email"` | HubSpot property name for the email address |
|
|
91
|
+
| `stateProperty` | string | `"state"` | HubSpot property name for the selected state |
|
|
92
|
+
| `additionalPropertyName` | string | — | Extra HubSpot property name (for lists/segments) |
|
|
93
|
+
| `additionalPropertyValue` | string | — | Value sent for `additionalPropertyName` |
|
|
94
|
+
| `consentToProcessText` | string | — | GDPR processing-consent checkbox label. Omit to skip consent UI and `legalConsentOptions` |
|
|
95
|
+
| `communicationConsents` | `CommunicationConsent[]` \| string | — | Optional marketing opt-ins. React: array. HTML: JSON array. Each item: `subscriptionTypeId`, `text`, optional `required` |
|
|
96
|
+
| `formTitle` | string | — | Form-screen headline (required) |
|
|
97
|
+
| `formSubtitle` | string | — | Form-screen supporting line |
|
|
98
|
+
| `states` | string[] \| string | — | Radio options. React: array. HTML: comma-separated (required) |
|
|
99
|
+
| `submitButtonText` | string | `"Submit"` | Form submit label |
|
|
100
|
+
| `emailPlaceholder` | string | `"Email *"` | Email input placeholder |
|
|
101
|
+
| `stateLabel` | string | `"Select A State *"` | State radio group label |
|
|
102
|
+
| `confirmationTitle` | string | — | Confirmation-screen headline (required) |
|
|
103
|
+
| `confirmationMessage` | string | — | Confirmation-screen supporting line |
|
|
104
|
+
| `confirmationButtonText` | string | — | Confirmation CTA label (hidden if omitted) |
|
|
105
|
+
| `confirmationButtonUrl` | string | — | Confirmation CTA destination |
|
|
106
|
+
| `recaptchaText` | string | `"This site is protected by reCAPTCHA."` | Footer disclaimer. Hide with `""` or `"false"` (`recaptcha-text=""` / `recaptcha-text="false"` in HTML) |
|
|
107
|
+
| `backgroundColor` | string | `#d4ecec` | Modal card background |
|
|
108
|
+
| `overlayColor` | string | `rgba(0, 0, 0, 0.55)` | Page overlay |
|
|
109
|
+
| `textColor` | string | `#111111` | Text color |
|
|
110
|
+
| `buttonColor` | string | `#000000` | Button background |
|
|
111
|
+
| `buttonTextColor` | string | `#ffffff` | Button text |
|
|
112
|
+
| `buttonHoverColor` | string | `#333333` | Button hover background |
|
|
113
|
+
| `buttonHoverTextColor` | string | `#ffffff` | Button hover text |
|
|
114
|
+
| `fontFamily` | string | system sans | Body / UI font stack |
|
|
115
|
+
| `headingFontFamily` | string | Georgia / serif | Headline and submit font stack |
|
|
116
|
+
| `waitForAgeGate` | boolean | `false` | Wait for `@jmeirinkmarimed/age-gate`: `localStorage.ageVerified === "true"` and `#age-gate-modal` gone |
|
|
117
|
+
| `waitForStorageKey` | string | — | Wait until this localStorage key equals `waitForStorageValue` |
|
|
118
|
+
| `waitForStorageValue` | string | `"true"` | Expected value for `waitForStorageKey` |
|
|
119
|
+
| `waitUntilHidden` | string | — | Wait until this selector matches no overlay (light DOM or `<age-gate>` shadow root) |
|
|
120
|
+
| `waitUntilHiddenHost` | string | `"age-gate"` | Shadow-host selector for `waitUntilHidden` |
|
|
121
|
+
|
|
122
|
+
## Behavior
|
|
123
|
+
|
|
124
|
+
- Closing the popup (X, overlay click, or Escape) hides it for the current page view only.
|
|
125
|
+
- After a successful HubSpot submit, `localStorage` is set so the popup does not return on later visits. The confirmation screen still shows until the user closes it or follows the CTA.
|
|
126
|
+
- Set `hubspotPortalId="demo"` in local examples to skip the network call and still reach the confirmation screen.
|
|
127
|
+
- HubSpot forms with a required GDPR processing checkbox need `consentToProcessText` (copy the checkbox label from the form). Optional email-subscription checkboxes go in `communicationConsents`, using each checkbox’s HubSpot subscription type ID. Leave both unset for forms with no legal-consent options.
|
|
128
|
+
- Both this popup and `@jmeirinkmarimed/age-gate` use the maximum `z-index`. Put `<age-gate>` on the page and set `wait-for-age-gate="true"` so the form waits until `ageVerified` is `"true"` **and** `#age-gate-modal` has unmounted. Do not treat a missing overlay as done — the gate may not have rendered yet. Returning visitors already in `localStorage` see the form immediately. Put `<age-gate>` before `<form-popup>` in the theme.
|
|
129
|
+
|
|
130
|
+
## Custom fonts
|
|
131
|
+
|
|
132
|
+
Import fonts in your app (or `<link>` / `@font-face` in HTML). Set `headingFontFamily` / `fontFamily` to match. The Betty's preview loads Alegreya for headlines.
|
|
133
|
+
|
|
134
|
+
## Local development
|
|
135
|
+
|
|
136
|
+
This repo uses **Bun** only (`bun.lock`). Do not commit `package-lock.json`.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
bun install
|
|
140
|
+
bun run dev # playground → http://localhost:5173
|
|
141
|
+
bun run build # dist/ (ES + CJS + UMD + IIFE + .d.ts)
|
|
142
|
+
bun run examples:serve # previews :8080, playground :5173, react-consumer :5174
|
|
143
|
+
bun run lint
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
HTML previews live in [`examples/previews/`](examples/previews/) and load a locally built `form-popup.min.js` (gitignored; created by `examples:serve`). Customize a preview here, then copy the `<form-popup>` markup onto the live site.
|
|
147
|
+
|
|
148
|
+
## Publishing
|
|
149
|
+
|
|
150
|
+
`bun run build` produces:
|
|
151
|
+
|
|
152
|
+
| File | Purpose |
|
|
153
|
+
|------|---------|
|
|
154
|
+
| `dist/form-popup.es.js` | ESM (React peer externals) |
|
|
155
|
+
| `dist/form-popup.cjs.js` | CommonJS |
|
|
156
|
+
| `dist/form-popup.umd.js` | UMD |
|
|
157
|
+
| `dist/form-popup.min.js` | Standalone IIFE (React bundled) for `<script>` / unpkg |
|
|
158
|
+
| `dist/index.d.ts` | TypeScript declarations |
|
|
159
|
+
|
|
160
|
+
Importing the package registers `<form-popup>` as a side effect. The IIFE build also exposes `window.React` / `window.ReactDOM`.
|
|
161
|
+
|
|
162
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution notes.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FormPopupProps } from "./types";
|
|
2
|
+
declare const FormPopup: ({ hubspotPortalId, hubspotFormId, emailProperty, stateProperty, additionalPropertyName, additionalPropertyValue, consentToProcessText, communicationConsents, formTitle, formSubtitle, states, submitButtonText, emailPlaceholder, stateLabel, confirmationTitle, confirmationMessage, confirmationButtonText, confirmationButtonUrl, recaptchaText, backgroundColor, overlayColor, textColor, buttonColor, buttonTextColor, buttonHoverColor, buttonHoverTextColor, fontFamily, headingFontFamily, waitForAgeGate, waitForStorageKey, waitForStorageValue, waitUntilHidden, waitUntilHiddenHost, container, }: FormPopupProps & {
|
|
3
|
+
container?: HTMLElement;
|
|
4
|
+
}) => import("react").JSX.Element | null;
|
|
5
|
+
export default FormPopup;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
interface StyleProps {
|
|
3
|
+
backgroundColor?: string;
|
|
4
|
+
overlayColor?: string;
|
|
5
|
+
textColor?: string;
|
|
6
|
+
buttonColor?: string;
|
|
7
|
+
buttonTextColor?: string;
|
|
8
|
+
fontFamily?: string;
|
|
9
|
+
headingFontFamily?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const resetStyles: CSSProperties;
|
|
12
|
+
export declare const createStyles: (props: StyleProps) => Record<string, CSSProperties>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface HubSpotField {
|
|
2
|
+
name: string;
|
|
3
|
+
value: string;
|
|
4
|
+
}
|
|
5
|
+
export interface HubSpotCommunicationConsent {
|
|
6
|
+
subscriptionTypeId: number;
|
|
7
|
+
text: string;
|
|
8
|
+
value: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface HubSpotLegalConsent {
|
|
11
|
+
consentToProcess: boolean;
|
|
12
|
+
text?: string;
|
|
13
|
+
communications?: HubSpotCommunicationConsent[];
|
|
14
|
+
}
|
|
15
|
+
export declare function submitHubSpotForm(options: {
|
|
16
|
+
portalId: string;
|
|
17
|
+
formId: string;
|
|
18
|
+
fields: HubSpotField[];
|
|
19
|
+
legalConsent?: HubSpotLegalConsent;
|
|
20
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function getWebComponentHost(container?: HTMLElement): HTMLElement | undefined;
|
|
2
|
+
export declare function readHostAttribute(container: HTMLElement | undefined, attribute: string): string | undefined;
|
|
3
|
+
export declare function resolveHostFlag(prop: boolean | string | undefined, container: HTMLElement | undefined, attribute: string): boolean;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface DeferredReadyOptions {
|
|
2
|
+
waitForAgeGate?: boolean;
|
|
3
|
+
waitForStorageKey?: string;
|
|
4
|
+
waitForStorageValue?: string;
|
|
5
|
+
waitUntilHidden?: string;
|
|
6
|
+
waitUntilHiddenHost?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function useDeferredReady(options: DeferredReadyOptions): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function parseStates(states: string | string[] | undefined): string[];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* r2wc skips empty HTML attributes (`if (value)`), so `recaptcha-text=""` never
|
|
3
|
+
* reaches React. Read the host attribute when present, and treat empty / false /
|
|
4
|
+
* none / off / hidden as hidden.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveRecaptchaText(recaptchaText: string | undefined, container?: HTMLElement): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
interface ConfirmationScreenProps {
|
|
3
|
+
styles: Record<string, CSSProperties>;
|
|
4
|
+
confirmationTitle: string;
|
|
5
|
+
confirmationMessage?: string;
|
|
6
|
+
confirmationButtonText?: string;
|
|
7
|
+
onButtonClick: () => void;
|
|
8
|
+
}
|
|
9
|
+
export default function ConfirmationScreen({ styles, confirmationTitle, confirmationMessage, confirmationButtonText, onButtonClick, }: ConfirmationScreenProps): import("react").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CSSProperties, FormEvent } from "react";
|
|
2
|
+
import type { CommunicationConsent } from "../types";
|
|
3
|
+
interface FormScreenProps {
|
|
4
|
+
styles: Record<string, CSSProperties>;
|
|
5
|
+
formTitle: string;
|
|
6
|
+
formSubtitle?: string;
|
|
7
|
+
email: string;
|
|
8
|
+
emailPlaceholder: string;
|
|
9
|
+
state: string;
|
|
10
|
+
stateLabel: string;
|
|
11
|
+
states: string[];
|
|
12
|
+
consentToProcessText?: string;
|
|
13
|
+
consentToProcess: boolean;
|
|
14
|
+
communicationConsents: CommunicationConsent[];
|
|
15
|
+
communicationValues: Record<string, boolean>;
|
|
16
|
+
submitButtonText: string;
|
|
17
|
+
recaptchaText?: string;
|
|
18
|
+
error?: string;
|
|
19
|
+
submitting: boolean;
|
|
20
|
+
onEmailChange: (value: string) => void;
|
|
21
|
+
onStateChange: (value: string) => void;
|
|
22
|
+
onConsentToProcessChange: (value: boolean) => void;
|
|
23
|
+
onCommunicationChange: (key: string, value: boolean) => void;
|
|
24
|
+
onSubmit: (event: FormEvent<HTMLFormElement>) => void;
|
|
25
|
+
}
|
|
26
|
+
export default function FormScreen({ styles, formTitle, formSubtitle, email, emailPlaceholder, state, stateLabel, states, consentToProcessText, consentToProcess, communicationConsents, communicationValues, submitButtonText, recaptchaText, error, submitting, onEmailChange, onStateChange, onConsentToProcessChange, onCommunicationChange, onSubmit, }: FormScreenProps): import("react").JSX.Element;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export interface CommunicationConsent {
|
|
2
|
+
/** HubSpot subscription type ID from the form’s communication-consent checkbox. */
|
|
3
|
+
subscriptionTypeId: number | string;
|
|
4
|
+
/** Checkbox label; also sent as HubSpot `communications[].text`. */
|
|
5
|
+
text: string;
|
|
6
|
+
/** When true, the visitor must check this box to submit. Defaults to false. */
|
|
7
|
+
required?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface FormPopupProps {
|
|
10
|
+
/** HubSpot portal (hub) ID. Use `"demo"` to skip the network call in local fixtures. */
|
|
11
|
+
hubspotPortalId: string;
|
|
12
|
+
/** HubSpot form GUID that fields are submitted to. */
|
|
13
|
+
hubspotFormId: string;
|
|
14
|
+
/** HubSpot contact property that receives the email address. Defaults to `"email"`. */
|
|
15
|
+
emailProperty?: string;
|
|
16
|
+
/** HubSpot contact property that receives the selected state. Defaults to `"state"`. */
|
|
17
|
+
stateProperty?: string;
|
|
18
|
+
/** Extra HubSpot property name, e.g. for list/segment membership. */
|
|
19
|
+
additionalPropertyName?: string;
|
|
20
|
+
/** Value sent for `additionalPropertyName`. */
|
|
21
|
+
additionalPropertyValue?: string;
|
|
22
|
+
/**
|
|
23
|
+
* GDPR processing-consent checkbox label. When set, a required checkbox is shown
|
|
24
|
+
* and HubSpot `legalConsentOptions.consent` is sent on submit.
|
|
25
|
+
* Use the form’s processing-consent checkbox label from HubSpot.
|
|
26
|
+
*/
|
|
27
|
+
consentToProcessText?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Optional marketing subscription checkboxes (HubSpot communication consent).
|
|
30
|
+
* React: array. HTML: JSON array string.
|
|
31
|
+
*/
|
|
32
|
+
communicationConsents?: CommunicationConsent[] | string;
|
|
33
|
+
/** Form-screen headline. */
|
|
34
|
+
formTitle: string;
|
|
35
|
+
/** Form-screen supporting line under the headline. */
|
|
36
|
+
formSubtitle?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Radio options for the state field.
|
|
39
|
+
* React: string array. HTML: comma-separated string.
|
|
40
|
+
*/
|
|
41
|
+
states: string | string[];
|
|
42
|
+
submitButtonText?: string;
|
|
43
|
+
emailPlaceholder?: string;
|
|
44
|
+
stateLabel?: string;
|
|
45
|
+
/** Confirmation-screen headline. */
|
|
46
|
+
confirmationTitle: string;
|
|
47
|
+
/** Confirmation-screen supporting line. */
|
|
48
|
+
confirmationMessage?: string;
|
|
49
|
+
confirmationButtonText?: string;
|
|
50
|
+
confirmationButtonUrl?: string;
|
|
51
|
+
/** Footer disclaimer. Omit for the default reCAPTCHA line; `""` or `"false"` hides it. */
|
|
52
|
+
recaptchaText?: string;
|
|
53
|
+
/** Modal card background. */
|
|
54
|
+
backgroundColor?: string;
|
|
55
|
+
overlayColor?: string;
|
|
56
|
+
textColor?: string;
|
|
57
|
+
buttonColor?: string;
|
|
58
|
+
buttonTextColor?: string;
|
|
59
|
+
buttonHoverColor?: string;
|
|
60
|
+
buttonHoverTextColor?: string;
|
|
61
|
+
/** Body / UI font stack. */
|
|
62
|
+
fontFamily?: string;
|
|
63
|
+
/** Headline font stack (form title, submit, state labels). */
|
|
64
|
+
headingFontFamily?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Wait for `@jmeirinkmarimed/age-gate` before showing.
|
|
67
|
+
* Requires `localStorage.ageVerified === "true"` and `#age-gate-modal` gone
|
|
68
|
+
* (including inside `<age-gate>` shadow root). Returning visitors who are
|
|
69
|
+
* already verified see the popup immediately.
|
|
70
|
+
*/
|
|
71
|
+
waitForAgeGate?: boolean;
|
|
72
|
+
/** Wait until this localStorage key equals `waitForStorageValue` (default `"true"`). */
|
|
73
|
+
waitForStorageKey?: string;
|
|
74
|
+
waitForStorageValue?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Wait until this selector matches no element in the light DOM or in
|
|
77
|
+
* `waitUntilHiddenHost` / `<age-gate>` open shadow roots.
|
|
78
|
+
*/
|
|
79
|
+
waitUntilHidden?: string;
|
|
80
|
+
/** Shadow-host selector used with `waitUntilHidden`. Defaults to `"age-gate"`. */
|
|
81
|
+
waitUntilHiddenHost?: string;
|
|
82
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("react"),tt=require("react-dom"),n=require("react/jsx-runtime");var Kt=Object.defineProperty,Jt=(t,e,o)=>e in t?Kt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[e]=o,D=(t,e,o)=>Jt(t,typeof e!="symbol"?e+"":e,o);const Xt={stringify:t=>t?"true":"false",parse:t=>/^[ty1-9]/i.test(t)},Yt={stringify:t=>t.name,parse:(t,e,o)=>{const r=(()=>{if(typeof window<"u"&&t in window)return window[t];if(typeof global<"u"&&t in global)return global[t]})();return typeof r=="function"?r.bind(o):void 0}},Zt={stringify:t=>JSON.stringify(t),parse:t=>JSON.parse(t)},Qt={stringify:t=>`${t}`,parse:t=>parseFloat(t)},te={stringify:t=>t,parse:t=>t},Z={string:te,number:Qt,boolean:Xt,function:Yt,json:Zt};function ee(t){return t.replace(/([a-z0-9])([A-Z])/g,(e,o,r)=>`${o}-${r.toLowerCase()}`)}const P=Symbol.for("r2wc.render"),U=Symbol.for("r2wc.connected"),j=Symbol.for("r2wc.context"),E=Symbol.for("r2wc.props");function oe(t,e,o){var r,i,u;e.props||(e.props=t.propTypes?Object.keys(t.propTypes):[]),e.events||(e.events=[]);const a=Array.isArray(e.props)?e.props.slice():Object.keys(e.props),x=Array.isArray(e.events)?e.events.slice():Object.keys(e.events),p={},w={},v={},A={};for(const s of a){p[s]=Array.isArray(e.props)?"string":e.props[s];const l=ee(s);v[s]=l,A[l]=s}for(const s of x)w[s]=Array.isArray(e.events)?{}:e.events[s];class k extends HTMLElement{constructor(){super(),D(this,u,!0),D(this,i),D(this,r,{}),D(this,"container"),e.shadow?this.container=this.attachShadow({mode:e.shadow}):this.container=this,this[E].container=this.container;for(const l of a){const g=v[l],f=this.getAttribute(g),d=p[l],b=d?Z[d]:null;b!=null&&b.parse&&f&&(this[E][l]=b.parse(f,g,this))}for(const l of x)this[E][l]=g=>{const f=l.replace(/^on/,"").toLowerCase();this.dispatchEvent(new CustomEvent(f,{detail:g,...w[l]}))}}static get observedAttributes(){return Object.keys(A)}connectedCallback(){this[U]=!0,this[P]()}disconnectedCallback(){this[U]=!1,this[j]&&o.unmount(this[j]),delete this[j]}attributeChangedCallback(l,g,f){const d=A[l],b=p[d],C=b?Z[b]:null;d in p&&C!=null&&C.parse&&f&&(this[E][d]=C.parse(f,l,this),this[P]())}[(u=U,i=j,r=E,P)](){this[U]&&(this[j]?o.update(this[j],this[E]):this[j]=o.mount(this.container,t,this[E]))}}for(const s of a){const l=v[s],g=p[s];Object.defineProperty(k.prototype,s,{enumerable:!0,configurable:!0,get(){return this[E][s]},set(f){this[E][s]=f;const d=g?Z[g]:null;if(d!=null&&d.stringify){const b=d.stringify(f,l,this);this.getAttribute(l)!==b&&this.setAttribute(l,b)}else this[P]()}})}return k}function re(t,e,o){const r=h.createElement(e,o);return tt.render(r,t),{container:t,ReactComponent:e}}function ne({container:t,ReactComponent:e},o){const r=h.createElement(e,o);tt.render(r,t)}function ie({container:t}){tt.unmountComponentAtNode(t)}function se(t,e={}){return oe(t,e,{mount:re,update:ne,unmount:ie})}const m={boxSizing:"border-box",margin:"0",padding:"0",letterSpacing:"normal"},ae="#d4ecec",le="#111111",bt="#000000",yt="#ffffff",ce='system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',ue='Georgia, "Times New Roman", Times, serif',me=t=>{const e=t.fontFamily||ce,o=t.headingFontFamily||ue,r=t.textColor||le;return{overlay:{...m,fontFamily:e,position:"fixed",top:0,left:0,width:"100%",height:"100%",minHeight:"100vh",maxWidth:"100vw",zIndex:2147483647,display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:t.overlayColor||"rgba(0, 0, 0, 0.55)",overflow:"auto",WebkitTextSizeAdjust:"100%",WebkitFontSmoothing:"antialiased",MozOsxFontSmoothing:"grayscale",padding:"1.5rem"},card:{...m,fontFamily:e,position:"relative",width:"100%",maxWidth:"440px",minHeight:"480px",justifyContent:"center",backgroundColor:t.backgroundColor||ae,color:r,padding:"3rem 2.25rem 1.5rem",display:"flex",flexDirection:"column",alignItems:"center",textAlign:"center",boxShadow:"0 12px 40px rgba(0, 0, 0, 0.18)"},closeButton:{...m,position:"absolute",top:"14px",right:"14px",width:"28px",height:"28px",borderRadius:"50%",border:"none",backgroundColor:"#cfcfcf",color:"#4a4a4a",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",padding:"0",lineHeight:1},formTitle:{...m,fontFamily:o,fontSize:"30px",fontWeight:700,lineHeight:1.25,color:r,maxWidth:"22ch"},formSubtitle:{...m,fontFamily:e,fontSize:"15px",fontWeight:400,lineHeight:1.4,color:r,marginTop:"0.85rem",marginBottom:"1.35rem"},form:{...m,width:"100%",display:"flex",flexDirection:"column",alignItems:"stretch",textAlign:"left"},emailInput:{...m,fontFamily:o,width:"100%",height:"48px",padding:"0 14px",fontSize:"16px",backgroundColor:"#ffffff",color:"#111111",border:"1px solid #e6e6e6",borderRadius:"0",outline:"none",appearance:"none",WebkitAppearance:"none"},stateLabel:{...m,fontFamily:e,fontSize:"15px",fontWeight:700,color:r,marginTop:"1.15rem",marginBottom:"0.75rem"},stateGrid:{...m,display:"grid",gridTemplateColumns:"1fr 1fr",columnGap:"1.25rem",rowGap:"0.7rem",width:"100%"},radioRow:{...m,display:"flex",alignItems:"center",gap:"0.5rem",cursor:"pointer",fontFamily:o,fontSize:"16px",color:r,userSelect:"none"},radio:{...m,width:"16px",height:"16px",flexShrink:0,accentColor:r,cursor:"pointer"},consentList:{...m,display:"flex",flexDirection:"column",gap:"0.65rem",width:"100%",marginTop:"1.15rem"},consentRow:{...m,display:"flex",alignItems:"flex-start",gap:"0.5rem",cursor:"pointer",fontFamily:e,fontSize:"12px",lineHeight:1.4,color:r,userSelect:"none"},consentCheckbox:{...m,width:"16px",height:"16px",marginTop:"1px",flexShrink:0,accentColor:r,cursor:"pointer"},consentRequired:{...m,color:"#9b1c1c",fontSize:"16px",fontWeight:700,lineHeight:1,marginLeft:"0.15em"},submitButton:{...m,fontFamily:o,alignSelf:"center",marginTop:"1.75rem",minWidth:"168px",height:"46px",padding:"0 2rem",border:"none",borderRadius:"0",backgroundColor:t.buttonColor||bt,color:t.buttonTextColor||yt,fontSize:"20px",fontWeight:700,cursor:"pointer",lineHeight:1},error:{...m,fontFamily:e,fontSize:"13px",color:"#9b1c1c",textAlign:"center",marginTop:"0.75rem"},recaptcha:{...m,fontFamily:e,fontSize:"11px",color:r,textAlign:"center",marginTop:"1.75rem"},confirmationTitle:{...m,fontFamily:o,fontSize:"26px",fontWeight:700,lineHeight:1.3,color:r,maxWidth:"20ch"},confirmationMessage:{...m,fontFamily:e,fontSize:"15px",fontWeight:400,lineHeight:1.45,color:r,marginTop:"1rem",maxWidth:"34ch"},confirmationButton:{...m,fontFamily:o,marginTop:"1.75rem",minWidth:"168px",height:"46px",padding:"0 1.5rem",border:"none",borderRadius:"0",backgroundColor:t.buttonColor||bt,color:t.buttonTextColor||yt,fontSize:"18px",fontWeight:700,cursor:"pointer",lineHeight:1}}};function de(t){const{buttonHoverColor:e,buttonHoverTextColor:o}=t;return`
|
|
2
|
+
.sr-only {
|
|
3
|
+
position: absolute !important;
|
|
4
|
+
width: 1px !important;
|
|
5
|
+
height: 1px !important;
|
|
6
|
+
padding: 0 !important;
|
|
7
|
+
margin: -1px !important;
|
|
8
|
+
overflow: hidden !important;
|
|
9
|
+
clip: rect(0, 0, 0, 0) !important;
|
|
10
|
+
white-space: nowrap !important;
|
|
11
|
+
border: 0 !important;
|
|
12
|
+
}
|
|
13
|
+
#form-popup-email:focus {
|
|
14
|
+
border-color: #111111 !important;
|
|
15
|
+
box-shadow: 0 0 0 1px #111111 !important;
|
|
16
|
+
}
|
|
17
|
+
#form-popup-email::placeholder {
|
|
18
|
+
color: #9a9a9a !important;
|
|
19
|
+
font-family: inherit !important;
|
|
20
|
+
}
|
|
21
|
+
#form-popup-close:hover {
|
|
22
|
+
background-color: #bdbdbd !important;
|
|
23
|
+
}
|
|
24
|
+
#form-popup-submit:hover:not(:disabled),
|
|
25
|
+
#form-popup-confirmation-button:hover {
|
|
26
|
+
background-color: ${e} !important;
|
|
27
|
+
color: ${o} !important;
|
|
28
|
+
}
|
|
29
|
+
#form-popup-submit:disabled {
|
|
30
|
+
opacity: 0.65 !important;
|
|
31
|
+
cursor: wait !important;
|
|
32
|
+
}
|
|
33
|
+
@media screen and (max-width: 480px) {
|
|
34
|
+
#form-popup-card {
|
|
35
|
+
padding: 2.5rem 1.25rem 1.25rem !important;
|
|
36
|
+
}
|
|
37
|
+
#form-popup-form-title {
|
|
38
|
+
font-size: 24px !important;
|
|
39
|
+
}
|
|
40
|
+
#form-popup-confirmation-title {
|
|
41
|
+
font-size: 22px !important;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
`}function vt(t){return`formPopupSubmitted:${t||"default"}`}function xt(t){return typeof window>"u"||!t?!1:localStorage.getItem(vt(t))==="true"}function pe(t){const[e,o]=h.useState(()=>t?!xt(t):!1);h.useEffect(()=>{t&&o(!xt(t))},[t]);const r=h.useCallback(()=>{t&&localStorage.setItem(vt(t),"true")},[t]),i=h.useCallback(()=>{o(!1)},[]);return{showModal:e,markSubmitted:r,dismiss:i}}const fe="ageVerified",he="true",et="age-gate",ge="#age-gate-modal";function be(t,e){return typeof window>"u"?!1:localStorage.getItem(t)===e}function wt(t,e){var o;try{const r=document.querySelectorAll(t);for(const i of r){const u=(o=i.shadowRoot)==null?void 0:o.querySelector(e);if(u)return u}}catch{return null}return null}function ye(t,e){if(typeof document>"u"||!t)return null;try{const o=document.querySelector(t);if(o)return o}catch{return null}{const o=wt(e,t);if(o)return o}return wt(et,t)}function St(t){var a,x,p,w;const e=!!t.waitForAgeGate,o=((a=t.waitForStorageKey)==null?void 0:a.trim())||(e?fe:""),r=((x=t.waitForStorageValue)==null?void 0:x.trim())||he,i=((p=t.waitUntilHidden)==null?void 0:p.trim())||(e?ge:""),u=((w=t.waitUntilHiddenHost)==null?void 0:w.trim())||et;return!o&&!i?!0:!(o&&!be(o,r)||i&&ye(i,u))}function xe(t){var p,w,v,A;const e=!!t.waitForAgeGate,o=((p=t.waitForStorageKey)==null?void 0:p.trim())||"",r=((w=t.waitForStorageValue)==null?void 0:w.trim())||"",i=((v=t.waitUntilHidden)==null?void 0:v.trim())||"",u=((A=t.waitUntilHiddenHost)==null?void 0:A.trim())||"",[a,x]=h.useState(()=>St(t));return h.useEffect(()=>{const k={waitForAgeGate:e,waitForStorageKey:o,waitForStorageValue:r,waitUntilHidden:i,waitUntilHiddenHost:u};if(!e&&!o&&!i){x(!0);return}const s=()=>x(St(k));s();const l=[],g=new WeakSet,f=()=>{const C=u||et;try{document.querySelectorAll(C).forEach(W=>{const c=W.shadowRoot;if(!c||g.has(c))return;g.add(c);const S=new MutationObserver(s);S.observe(c,{childList:!0,subtree:!0}),l.push(S)})}catch{}};f();const d=new MutationObserver(()=>{f(),s()});d.observe(document.documentElement,{childList:!0,subtree:!0});const b=window.setInterval(s,250);return()=>{d.disconnect(),l.forEach(C=>C.disconnect()),window.clearInterval(b)}},[e,o,r,i,u]),a}function we(t){return t?Array.isArray(t)?t.map(e=>e.trim()).filter(Boolean):String(t).split(",").map(e=>e.trim()).filter(Boolean):[]}function ot(t){if(!t)return;if(t instanceof ShadowRoot)return t.host;const e=t.getRootNode();if(e instanceof ShadowRoot)return e.host}function O(t,e){const o=ot(t);if(!(o!=null&&o.hasAttribute(e)))return;const r=o.getAttribute(e);return r??void 0}function Se(t,e,o){const r=ot(e);if(r!=null&&r.hasAttribute(o)){const i=(r.getAttribute(o)??"").trim().toLowerCase();return!(i==="false"||i==="0"||i==="no"||i==="off")}return t===!0||t==="true"}const ve="This site is protected by reCAPTCHA.",Ce=new Set(["","false","none","off","hidden"]);function Ae(t,e){const o=ot(e),r=(o==null?void 0:o.hasAttribute("recaptcha-text"))===!0?o.getAttribute("recaptcha-text")??"":t;return r===void 0?ve:Ce.has(String(r).trim().toLowerCase())?"":String(r)}function Te(t){if(!t||typeof t!="object")return null;const e=t,o=String(e.text??"").trim(),r=e.subscriptionTypeId;return!o||typeof r!="string"&&typeof r!="number"||String(r).trim()===""?null:{subscriptionTypeId:r,text:o,required:!!e.required}}function Ee(t){if(!t)return[];let e=[];if(Array.isArray(t))e=t;else{const o=t.trim();if(!o)return[];try{const r=JSON.parse(o);if(!Array.isArray(r))return[];e=r}catch{return[]}}return e.flatMap(o=>{const r=Te(o);return r?[r]:[]})}function Q(t){return String(t.subscriptionTypeId)}function ke(t){if(typeof document>"u")return;const e=document.cookie.match(new RegExp(`(?:^|; )${t}=([^;]*)`));return e?decodeURIComponent(e[1]):void 0}async function Fe(t){var u;const e=ke("hubspotutk"),o=t.legalConsent,r=(u=o==null?void 0:o.communications)==null?void 0:u.map(a=>({subscriptionTypeId:a.subscriptionTypeId,text:a.text,value:a.value})),i=await fetch(`https://api.hsforms.com/submissions/v3/integration/submit/${t.portalId}/${t.formId}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({fields:t.fields.map(a=>({objectTypeId:"0-1",name:a.name,value:a.value})),context:{pageUri:window.location.href,pageName:document.title,...e?{hutk:e}:{}},...o?{legalConsentOptions:{consent:{consentToProcess:o.consentToProcess,...o.text?{text:o.text}:{},...r!=null&&r.length?{communications:r}:{}}}}:{}})});if(!i.ok){let a="";try{a=await i.text()}catch{a=""}throw new Error(a||`HubSpot submission failed (${i.status})`)}}function je({styles:t,formTitle:e,formSubtitle:o,email:r,emailPlaceholder:i,state:u,stateLabel:a,states:x,consentToProcessText:p,consentToProcess:w,communicationConsents:v,communicationValues:A,submitButtonText:k,recaptchaText:s,error:l,submitting:g,onEmailChange:f,onStateChange:d,onConsentToProcessChange:b,onCommunicationChange:C,onSubmit:W}){return n.jsxs(n.Fragment,{children:[n.jsx("h1",{id:"form-popup-form-title",style:t.formTitle,children:e}),o!=null&&o.trim()?n.jsx("p",{id:"form-popup-form-subtitle",style:t.formSubtitle,children:o}):null,n.jsxs("form",{id:"form-popup-form",style:t.form,onSubmit:W,noValidate:!0,children:[n.jsx("label",{htmlFor:"form-popup-email",className:"sr-only",children:"Email"}),n.jsx("input",{id:"form-popup-email",name:"email",type:"email",autoComplete:"email",required:!0,value:r,placeholder:i,onChange:c=>f(c.target.value),style:t.emailInput,"aria-required":"true"}),n.jsx("p",{id:"form-popup-state-label",style:t.stateLabel,children:a}),n.jsx("div",{role:"radiogroup","aria-labelledby":"form-popup-state-label","aria-required":"true",style:t.stateGrid,children:x.map(c=>{const S=`form-popup-state-${c.replace(/\s+/g,"-").toLowerCase()}`;return n.jsxs("label",{htmlFor:S,style:t.radioRow,children:[n.jsx("input",{id:S,type:"radio",name:"form-popup-state",value:c,checked:u===c,onChange:()=>d(c),style:t.radio}),c]},c)})}),p||v.length>0?n.jsxs("div",{style:t.consentList,children:[p?n.jsxs("label",{htmlFor:"form-popup-consent-process",style:t.consentRow,children:[n.jsx("input",{id:"form-popup-consent-process",type:"checkbox",checked:w,required:!0,"aria-required":"true",onChange:c=>b(c.target.checked),style:t.consentCheckbox}),n.jsxs("span",{children:[p,n.jsx("span",{style:t.consentRequired,"aria-hidden":"true",children:"*"})]})]}):null,v.map(c=>{const S=Q(c),I=`form-popup-consent-comm-${S}`;return n.jsxs("label",{htmlFor:I,style:t.consentRow,children:[n.jsx("input",{id:I,type:"checkbox",checked:!!A[S],required:c.required,"aria-required":c.required?!0:void 0,onChange:$=>C(S,$.target.checked),style:t.consentCheckbox}),n.jsxs("span",{children:[c.text,c.required?n.jsx("span",{style:t.consentRequired,"aria-hidden":"true",children:"*"}):null]})]},S)})]}):null,n.jsx("button",{id:"form-popup-submit",type:"submit",style:t.submitButton,disabled:g,children:g?"Submitting…":k}),l?n.jsx("p",{id:"form-popup-error",role:"alert",style:t.error,children:l}):null]}),s!=null&&s.trim()?n.jsx("p",{id:"form-popup-recaptcha",style:t.recaptcha,children:s}):null]})}function Re({styles:t,confirmationTitle:e,confirmationMessage:o,confirmationButtonText:r,onButtonClick:i}){const u=!!(r!=null&&r.trim());return n.jsxs(n.Fragment,{children:[n.jsx("h1",{id:"form-popup-confirmation-title",style:t.confirmationTitle,children:e}),o!=null&&o.trim()?n.jsx("p",{id:"form-popup-confirmation-message",style:t.confirmationMessage,children:o}):null,u?n.jsx("button",{id:"form-popup-confirmation-button",type:"button",style:t.confirmationButton,onClick:i,children:r}):null]})}const He=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;function Le(t){return!t||t==="demo"}const Ct=({hubspotPortalId:t,hubspotFormId:e,emailProperty:o="email",stateProperty:r="state",additionalPropertyName:i,additionalPropertyValue:u,consentToProcessText:a,communicationConsents:x,formTitle:p,formSubtitle:w,states:v,submitButtonText:A="Submit",emailPlaceholder:k="Email *",stateLabel:s="Select A State *",confirmationTitle:l,confirmationMessage:g,confirmationButtonText:f,confirmationButtonUrl:d,recaptchaText:b,backgroundColor:C,overlayColor:W,textColor:c="#111111",buttonColor:S="#000000",buttonTextColor:I="#ffffff",buttonHoverColor:$="#333333",buttonHoverTextColor:Tt="#ffffff",fontFamily:Et,headingFontFamily:kt,waitForAgeGate:Ft,waitForStorageKey:V,waitForStorageValue:N,waitUntilHidden:M,waitUntilHiddenHost:K,container:F})=>{var ct,ut,mt,dt,pt,ft;const q=me({backgroundColor:C,overlayColor:W,textColor:c,buttonColor:S,buttonTextColor:I,fontFamily:Et,headingFontFamily:kt}),rt=(e==null?void 0:e.trim())||((ct=O(F,"hubspot-form-id"))==null?void 0:ct.trim())||"",nt=(t==null?void 0:t.trim())||((ut=O(F,"hubspot-portal-id"))==null?void 0:ut.trim())||"",jt=Se(Ft,F,"wait-for-age-gate"),Rt=(V==null?void 0:V.trim())||((mt=O(F,"wait-for-storage-key"))==null?void 0:mt.trim())||"",Ht=(N==null?void 0:N.trim())||((dt=O(F,"wait-for-storage-value"))==null?void 0:dt.trim())||"",Lt=(M==null?void 0:M.trim())||((pt=O(F,"wait-until-hidden"))==null?void 0:pt.trim())||"",Ot=(K==null?void 0:K.trim())||((ft=O(F,"wait-until-hidden-host"))==null?void 0:ft.trim())||"",{showModal:Wt,markSubmitted:qt,dismiss:G}=pe(rt),Gt=xe({waitForAgeGate:jt,waitForStorageKey:Rt,waitForStorageValue:Ht,waitUntilHidden:Lt,waitUntilHiddenHost:Ot}),_=Wt&&Gt,[it,_t]=h.useState("form"),[st,Bt]=h.useState(""),[J,It]=h.useState(""),[X,zt]=h.useState(!1),[Y,Dt]=h.useState({}),[at,lt]=h.useState(!1),[z,T]=h.useState(""),Pt=we(v),Ut=Ae(b,F),R=(a==null?void 0:a.trim())||"",B=Ee(x),$t=!!R||B.length>0;h.useEffect(()=>{if(!_)return;const y=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.body.style.overflow=y}},[_]),h.useEffect(()=>{if(!_)return;const y=H=>{H.key==="Escape"&&G()};return window.addEventListener("keydown",y),()=>window.removeEventListener("keydown",y)},[_,G]);const Vt=async y=>{y.preventDefault();const H=st.trim();if(!He.test(H)){T("Please enter a valid email address.");return}if(!J){T("Please select a state.");return}if(R&&!X){T("Please agree to the privacy terms.");return}if(B.find(L=>L.required&&!Y[Q(L)])){T("Please agree to the required communications terms.");return}T(""),lt(!0);const gt=[{name:o,value:H},{name:r,value:J}];i!=null&&i.trim()&&u!=null&>.push({name:i.trim(),value:u});try{Le(nt)||await Fe({portalId:nt,formId:rt,fields:gt,legalConsent:$t?{consentToProcess:!!(R&&X),...R?{text:R}:{},...B.length?{communications:B.map(L=>({subscriptionTypeId:Number(L.subscriptionTypeId),text:L.text,value:!!Y[Q(L)]}))}:{}}:void 0}),qt(),_t("confirmation")}catch{T("Something went wrong. Please try again.")}finally{lt(!1)}},Nt=()=>{if(d){window.location.href=d;return}G()};if(!_)return null;const Mt=it==="form"?"form-popup-form-title":"form-popup-confirmation-title";return n.jsxs("div",{id:"form-popup-overlay",style:q.overlay,role:"dialog","aria-modal":"true","aria-labelledby":Mt,onClick:y=>{y.target===y.currentTarget&&!at&&G()},children:[n.jsx("style",{children:de({buttonHoverColor:$,buttonHoverTextColor:Tt})}),n.jsxs("div",{id:"form-popup-card",style:q.card,role:"document",children:[n.jsx("button",{id:"form-popup-close",type:"button",style:q.closeButton,"aria-label":"Close",onClick:G,children:n.jsx("svg",{width:"10",height:"10",viewBox:"0 0 10 10","aria-hidden":"true",children:n.jsx("path",{d:"M1 1l8 8M9 1L1 9",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})})}),it==="form"?n.jsx(je,{styles:q,formTitle:p,formSubtitle:w,email:st,emailPlaceholder:k,state:J,stateLabel:s,states:Pt,consentToProcessText:R||void 0,consentToProcess:X,communicationConsents:B,communicationValues:Y,submitButtonText:A,recaptchaText:Ut,error:z,submitting:at,onEmailChange:Bt,onStateChange:y=>{It(y),z&&T("")},onConsentToProcessChange:y=>{zt(y),z&&T("")},onCommunicationChange:(y,H)=>{Dt(ht=>({...ht,[y]:H})),z&&T("")},onSubmit:Vt}):n.jsx(Re,{styles:q,confirmationTitle:l,confirmationMessage:g,confirmationButtonText:f,onButtonClick:Nt})]})]})},Oe=se(Ct,{props:{hubspotPortalId:"string",hubspotFormId:"string",emailProperty:"string",stateProperty:"string",additionalPropertyName:"string",additionalPropertyValue:"string",consentToProcessText:"string",communicationConsents:"string",formTitle:"string",formSubtitle:"string",states:"string",submitButtonText:"string",emailPlaceholder:"string",stateLabel:"string",confirmationTitle:"string",confirmationMessage:"string",confirmationButtonText:"string",confirmationButtonUrl:"string",recaptchaText:"string",backgroundColor:"string",overlayColor:"string",textColor:"string",buttonColor:"string",buttonTextColor:"string",buttonHoverColor:"string",buttonHoverTextColor:"string",fontFamily:"string",headingFontFamily:"string",waitForAgeGate:"string",waitForStorageKey:"string",waitForStorageValue:"string",waitUntilHidden:"string",waitUntilHiddenHost:"string"},shadow:"open"});function At(){typeof customElements>"u"||customElements.get("form-popup")||customElements.define("form-popup",Oe)}At();At();exports.FormPopup=Ct;
|
|
45
|
+
//# sourceMappingURL=form-popup.cjs.js.map
|