keystone-design-bootstrap 1.0.66 → 1.0.69
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 +74 -132
- package/dist/design_system/sections/index.js +42 -11
- package/dist/design_system/sections/index.js.map +1 -1
- package/dist/index.js +42 -11
- package/dist/index.js.map +1 -1
- package/dist/tracking/index.d.ts +6 -1
- package/dist/tracking/index.js +5 -3
- package/dist/tracking/index.js.map +1 -1
- package/package.json +2 -1
- package/src/design_system/components/ChatWidget.tsx +6 -7
- package/src/design_system/portal/LoginForm.tsx +25 -9
- package/src/design_system/portal/LoginModalController.tsx +36 -12
- package/src/design_system/portal/PortalPage.tsx +5 -5
- package/src/design_system/portal/PortalTabTracker.tsx +10 -2
- package/src/design_system/sections/contact-section-form.aman.tsx +6 -1
- package/src/design_system/sections/contact-section-form.balance.tsx +6 -1
- package/src/design_system/sections/contact-section-form.barelux.tsx +6 -1
- package/src/design_system/sections/contact-section-form.tsx +6 -1
- package/src/design_system/sections/email-signup-section.tsx +6 -1
- package/src/design_system/sections/job-application-form.aman.tsx +6 -1
- package/src/design_system/sections/job-application-form.barelux.tsx +6 -1
- package/src/design_system/sections/job-application-form.tsx +6 -1
- package/src/lib/cta-urls.ts +13 -2
- package/src/lib/server-api.ts +18 -0
- package/src/next/layouts/root-layout.tsx +66 -33
- package/src/tracking/KeystoneAnalyticsTracker.tsx +41 -0
- package/src/tracking/PostHogProvider.tsx +128 -0
- package/src/tracking/captureEvent.ts +140 -0
- package/src/tracking/index.ts +5 -0
package/README.md
CHANGED
|
@@ -1,175 +1,117 @@
|
|
|
1
1
|
# Keystone Design Bootstrap
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The shared design system and runtime package powering all Keystone customer websites. Provides themed sections, UI elements, the member portal, server-side API helpers, form handling, Meta Pixel tracking, and the Next.js app shell.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
```typescript
|
|
9
|
-
export const config = {
|
|
10
|
-
site: { theme: "barelux" } // or "aman", "classic"
|
|
11
|
-
}
|
|
12
|
-
```
|
|
7
|
+
## Documentation
|
|
13
8
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
| Doc | Description |
|
|
10
|
+
|---|---|
|
|
11
|
+
| [`docs/architecture.md`](./docs/architecture.md) | Package structure, rendering model, theme system, publishing workflow |
|
|
12
|
+
| [`docs/server-api.md`](./docs/server-api.md) | All data-fetching functions, caching strategy, environment variables |
|
|
13
|
+
| [`docs/navigation-and-layout.md`](./docs/navigation-and-layout.md) | `KeystoneRootLayout`, `SiteConfig`, CTA URL resolution, dynamic nav, mobile sticky footer |
|
|
14
|
+
| [`docs/member-portal.md`](./docs/member-portal.md) | Member portal setup, tabs, auth flow, iframe booking, messaging |
|
|
15
|
+
| [`docs/forms.md`](./docs/forms.md) | Dynamic forms, `ContactSection`, form route, custom form pattern |
|
|
16
|
+
| [`docs/meta-tracking.md`](./docs/meta-tracking.md) | Meta Pixel initialization, automatic events, custom form tracking |
|
|
17
|
+
| [`docs/site-customization.md`](./docs/site-customization.md) | Per-site config, style overrides, component customization hierarchy |
|
|
18
|
+
| [`docs/theme-system.md`](./docs/theme-system.md) | Creating and registering themes, CSS tokens, component variants |
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
---
|
|
23
21
|
|
|
24
|
-
##
|
|
22
|
+
## Quick start (new customer site)
|
|
23
|
+
|
|
24
|
+
### 1. Environment variables
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
|
|
27
|
+
# .env.local
|
|
28
|
+
API_URL=http://localhost:3000/api/v1
|
|
29
|
+
API_KEY=your-api-key-here
|
|
28
30
|
```
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
### Elements
|
|
33
|
-
Reusable UI components:
|
|
32
|
+
### 2. Config
|
|
34
33
|
|
|
35
34
|
```typescript
|
|
36
|
-
|
|
35
|
+
// config/index.ts
|
|
36
|
+
import type { SiteConfig } from 'keystone-design-bootstrap/types';
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
export const config: SiteConfig = {
|
|
39
|
+
site: { title: "Business Name", description: "…", theme: "aman" },
|
|
40
|
+
navigation: { header: […], footer: [[…], […], […], […]] },
|
|
41
|
+
};
|
|
41
42
|
```
|
|
42
43
|
|
|
43
|
-
###
|
|
44
|
-
Async functions for fetching data server-side:
|
|
44
|
+
### 3. Root layout
|
|
45
45
|
|
|
46
46
|
```typescript
|
|
47
|
-
|
|
47
|
+
// app/layout.tsx
|
|
48
|
+
import { KeystoneRootLayout } from 'keystone-design-bootstrap/next/layouts/root-layout';
|
|
49
|
+
import { config } from '@/config';
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Sections
|
|
54
|
-
Pre-built page components that accept data via props:
|
|
55
|
-
|
|
56
|
-
```typescript
|
|
57
|
-
import { HeroHome, TestimonialsHome } from '@keystone-pzjr/design-bootstrap/sections'
|
|
58
|
-
import { getTestimonials } from '@keystone-pzjr/design-bootstrap/lib/server-api'
|
|
59
|
-
|
|
60
|
-
export default async function HomePage() {
|
|
61
|
-
const testimonials = await getTestimonials()
|
|
62
|
-
return (
|
|
63
|
-
<main>
|
|
64
|
-
<HeroHome />
|
|
65
|
-
<TestimonialsHome testimonials={testimonials} />
|
|
66
|
-
</main>
|
|
67
|
-
)
|
|
51
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
52
|
+
return <KeystoneRootLayout config={config}>{children}</KeystoneRootLayout>;
|
|
68
53
|
}
|
|
69
54
|
```
|
|
70
55
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
## Package Exports
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
// Sections (hero, footer, header, testimonials, etc.)
|
|
77
|
-
import { HeroHome, FooterHome, TestimonialsHome } from '@keystone-pzjr/design-bootstrap/sections'
|
|
78
|
-
|
|
79
|
-
// Elements (buttons, inputs, carousels, etc.)
|
|
80
|
-
import { Button, Input, Carousel } from '@keystone-pzjr/design-bootstrap/elements'
|
|
81
|
-
|
|
82
|
-
// Hooks
|
|
83
|
-
import { useBreakpoint } from '@keystone-pzjr/design-bootstrap/hooks'
|
|
84
|
-
|
|
85
|
-
// Theme context
|
|
86
|
-
import { ThemeProvider } from '@keystone-pzjr/design-bootstrap/contexts'
|
|
56
|
+
### 4. CSS imports
|
|
87
57
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
import
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
import { themes } from '@keystone-pzjr/design-bootstrap/themes'
|
|
58
|
+
```css
|
|
59
|
+
/* app/globals.css */
|
|
60
|
+
@import "keystone-design-bootstrap/styles/fonts.css";
|
|
61
|
+
@import "keystone-design-bootstrap/styles/theme.css";
|
|
62
|
+
@import "keystone-design-bootstrap/styles/typography.css";
|
|
63
|
+
@import "keystone-design-bootstrap/styles/style-overrides.aman.css"; /* match your theme */
|
|
64
|
+
@import "../styles/custom-overrides.css";
|
|
96
65
|
```
|
|
97
66
|
|
|
98
|
-
|
|
67
|
+
---
|
|
99
68
|
|
|
100
|
-
|
|
69
|
+
## Package exports reference
|
|
101
70
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
| Event | Trigger |
|
|
71
|
+
| Import path | Contents |
|
|
105
72
|
|---|---|
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
108
|
-
| `
|
|
109
|
-
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
73
|
+
| `keystone-design-bootstrap/sections` | All section components |
|
|
74
|
+
| `keystone-design-bootstrap/elements` | UI element components |
|
|
75
|
+
| `keystone-design-bootstrap/portal` | `PortalPage` and portal sub-components |
|
|
76
|
+
| `keystone-design-bootstrap/next/layouts/root-layout` | `KeystoneRootLayout` |
|
|
77
|
+
| `keystone-design-bootstrap/next/routes/consumer-auth` | `createConsumerAuthHandlers` |
|
|
78
|
+
| `keystone-design-bootstrap/next/routes/form` | `createFormRouteHandlers` (re-exported as `POST`) |
|
|
79
|
+
| `keystone-design-bootstrap/lib/server-api` | Server-side data fetching functions |
|
|
80
|
+
| `keystone-design-bootstrap/lib/cta-urls` | `resolveCtaUrls`, `resolvePortalPath`, `isExternalCtaUrl` |
|
|
81
|
+
| `keystone-design-bootstrap/tracking` | `firePixelEvent`, `setPixelUserData` |
|
|
82
|
+
| `keystone-design-bootstrap/types` | TypeScript types |
|
|
83
|
+
| `keystone-design-bootstrap/hooks` | Client-side hooks |
|
|
84
|
+
| `keystone-design-bootstrap/styles/*` | CSS files |
|
|
114
85
|
|
|
115
|
-
|
|
116
|
-
import { firePixelEvent, setPixelUserData } from 'keystone-design-bootstrap/tracking';
|
|
117
|
-
|
|
118
|
-
// inside your success handler, after a confirmed API response:
|
|
119
|
-
await setPixelUserData({ email: data.email, phone: data.phone });
|
|
120
|
-
firePixelEvent('Lead');
|
|
121
|
-
```
|
|
86
|
+
---
|
|
122
87
|
|
|
123
|
-
|
|
88
|
+
## Local development
|
|
124
89
|
|
|
125
|
-
|
|
90
|
+
Use `yalc` to test local builds in a customer site:
|
|
126
91
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
- **Server-first**: Data fetching happens server-side, components render as Server Components where possible
|
|
132
|
-
- **Theme variants**: Components automatically select variants based on active theme
|
|
133
|
-
- **Tailwind-first**: Use semantic utility classes (`bg-primary`, `text-fg-primary`, `font-display`)
|
|
134
|
-
- **Type-safe**: Full TypeScript support throughout
|
|
135
|
-
- **CSS variables**: Themes customize via CSS custom properties
|
|
136
|
-
- **Self-hosted fonts**: Uses Fontsource for optimized, bundled font loading
|
|
137
|
-
|
|
138
|
-
## Theme System
|
|
139
|
-
|
|
140
|
-
**Available themes:** `classic`, `aman`, `barelux`
|
|
141
|
-
|
|
142
|
-
### Themes
|
|
92
|
+
```bash
|
|
93
|
+
# In this package
|
|
94
|
+
npm run build && yalc publish
|
|
143
95
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
- **barelux**: Modern minimal theme with Poppins, clean lines
|
|
96
|
+
# In the customer site
|
|
97
|
+
yalc update keystone-design-bootstrap
|
|
147
98
|
|
|
148
|
-
|
|
99
|
+
# To restore the published npm version
|
|
100
|
+
yalc remove keystone-design-bootstrap && npm install
|
|
101
|
+
```
|
|
149
102
|
|
|
150
|
-
|
|
103
|
+
---
|
|
151
104
|
|
|
152
|
-
|
|
153
|
-
```
|
|
154
|
-
I am creating a new theme. Here is a link to an example: https://www.example.com
|
|
155
|
-
[Attach screenshots of various pages]
|
|
105
|
+
## Creating a new theme
|
|
156
106
|
|
|
157
|
-
|
|
158
|
-
```
|
|
107
|
+
See [`docs/theme-system.md`](./docs/theme-system.md) for the full guide.
|
|
159
108
|
|
|
160
|
-
|
|
109
|
+
Quick checklist:
|
|
161
110
|
1. Register in `src/themes/index.ts`
|
|
162
111
|
2. Install fonts via Fontsource
|
|
163
112
|
3. Create `src/styles/style-overrides.{theme}.css`
|
|
164
113
|
4. Create component variants (optional)
|
|
165
|
-
5. Add to design gallery
|
|
166
|
-
6.
|
|
167
|
-
|
|
168
|
-
**Critical rules:**
|
|
169
|
-
- Never modify base components or foundation CSS
|
|
170
|
-
- Use semantic variables/classes only
|
|
171
|
-
- Set BOTH `--color-*` and `--background-*` prefixes
|
|
172
|
-
- Match base component props exactly
|
|
173
|
-
- Ensure `npm run lint`, `npm run typecheck`, `npm run build` pass with zero errors/warnings
|
|
114
|
+
5. Add to design gallery
|
|
115
|
+
6. `npm run lint && npm run typecheck && npm run build` — must all pass
|
|
174
116
|
|
|
175
|
-
|
|
117
|
+
**Available themes:** `classic`, `aman`, `barelux`, `balance`
|
|
@@ -6261,7 +6261,7 @@ async function setPixelUserData(userData) {
|
|
|
6261
6261
|
getRegisteredPixelIds().forEach((id3) => fbq("init", id3, hashed));
|
|
6262
6262
|
}
|
|
6263
6263
|
}
|
|
6264
|
-
function firePixelEvent(event, params) {
|
|
6264
|
+
function firePixelEvent(event, params, eventId) {
|
|
6265
6265
|
const fbq = getFbq();
|
|
6266
6266
|
if (!fbq) {
|
|
6267
6267
|
console.debug("[MetaPixel] skipped \u2014 fbq not loaded", { event });
|
|
@@ -6271,8 +6271,10 @@ function firePixelEvent(event, params) {
|
|
|
6271
6271
|
const normalized = {};
|
|
6272
6272
|
if (params == null ? void 0 : params.contentName) normalized.content_name = params.contentName;
|
|
6273
6273
|
if (params == null ? void 0 : params.contentCategory) normalized.content_category = params.contentCategory;
|
|
6274
|
-
|
|
6275
|
-
|
|
6274
|
+
const customData = Object.keys(normalized).length > 0 ? normalized : void 0;
|
|
6275
|
+
const eventData = eventId ? { eventID: eventId } : void 0;
|
|
6276
|
+
console.debug("[MetaPixel]", event, normalized, eventId ? { eventID: eventId } : "");
|
|
6277
|
+
fbq("track", event, customData, eventData);
|
|
6276
6278
|
}
|
|
6277
6279
|
|
|
6278
6280
|
// src/next/contexts/form-definitions.tsx
|
|
@@ -6330,7 +6332,7 @@ var ContactSectionForm = ({
|
|
|
6330
6332
|
(_a = formRef.current) == null ? void 0 : _a.reset();
|
|
6331
6333
|
onSuccess == null ? void 0 : onSuccess();
|
|
6332
6334
|
await setPixelUserData({ email: data.email, phone: data.phone });
|
|
6333
|
-
firePixelEvent("Lead");
|
|
6335
|
+
firePixelEvent("Lead", void 0, result.eventId);
|
|
6334
6336
|
setTimeout(() => setSubmitStatus("idle"), 5e3);
|
|
6335
6337
|
} else {
|
|
6336
6338
|
setSubmitStatus("error");
|
|
@@ -6496,6 +6498,7 @@ var FooterHome = ({
|
|
|
6496
6498
|
// src/design_system/sections/header-navigation.tsx
|
|
6497
6499
|
import React22, { useRef as useRef7, useState as useState10 } from "react";
|
|
6498
6500
|
import Link4 from "next/link";
|
|
6501
|
+
import { usePathname } from "next/navigation";
|
|
6499
6502
|
import Image8 from "next/image";
|
|
6500
6503
|
import { ChevronDown as ChevronDown4 } from "@untitledui/icons";
|
|
6501
6504
|
import { Button as AriaButton8, Dialog as AriaDialog, DialogTrigger as AriaDialogTrigger, Popover as AriaPopover3 } from "react-aria-components";
|
|
@@ -6547,6 +6550,19 @@ var CONTACT_PATH = "/contact";
|
|
|
6547
6550
|
function isExternalCtaUrl(href) {
|
|
6548
6551
|
return href.startsWith("http://") || href.startsWith("https://");
|
|
6549
6552
|
}
|
|
6553
|
+
function resolvePortalPath(companyInformation) {
|
|
6554
|
+
var _a;
|
|
6555
|
+
const url = (_a = companyInformation == null ? void 0 : companyInformation.portal_url) == null ? void 0 : _a.trim();
|
|
6556
|
+
if (!url) return null;
|
|
6557
|
+
let pathname = null;
|
|
6558
|
+
try {
|
|
6559
|
+
pathname = new URL(url).pathname;
|
|
6560
|
+
} catch (e) {
|
|
6561
|
+
pathname = url.startsWith("/") ? url : null;
|
|
6562
|
+
}
|
|
6563
|
+
if (!pathname || pathname === "/") return null;
|
|
6564
|
+
return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
|
6565
|
+
}
|
|
6550
6566
|
function resolveCtaUrls(companyInformation) {
|
|
6551
6567
|
var _a, _b, _c;
|
|
6552
6568
|
const portalUrl = ((_a = companyInformation == null ? void 0 : companyInformation.portal_url) == null ? void 0 : _a.trim()) || null;
|
|
@@ -6610,6 +6626,9 @@ function HeaderNavigation({
|
|
|
6610
6626
|
image: logoImage
|
|
6611
6627
|
};
|
|
6612
6628
|
const dynamicNavigation = navigation;
|
|
6629
|
+
const pathname = usePathname();
|
|
6630
|
+
const portalPath = resolvePortalPath(companyInformation);
|
|
6631
|
+
const isPortalPage = portalPath ? pathname == null ? void 0 : pathname.startsWith(portalPath) : false;
|
|
6613
6632
|
const getVariantClasses = () => {
|
|
6614
6633
|
switch (variant) {
|
|
6615
6634
|
case "minimal":
|
|
@@ -6817,7 +6836,7 @@ function HeaderNavigation({
|
|
|
6817
6836
|
(cta_button == null ? void 0 : cta_button.secondary_label) && ctaUrls.hasSecondary ? cta_button.secondary_label : (cta_button == null ? void 0 : cta_button.label) || "Get Started"
|
|
6818
6837
|
))))
|
|
6819
6838
|
))))
|
|
6820
|
-
), /* @__PURE__ */ React22.createElement("div", { className: "fixed bottom-0 left-0 right-0 z-40 md:hidden bg-fg-primary" }, /* @__PURE__ */ React22.createElement("div", { className: "flex gap-0" }, (cta_button == null ? void 0 : cta_button.secondary_label) && ctaUrls.hasSecondary && /* @__PURE__ */ React22.createElement(
|
|
6839
|
+
), !isPortalPage && /* @__PURE__ */ React22.createElement("div", { className: "fixed bottom-0 left-0 right-0 z-40 md:hidden bg-fg-primary" }, /* @__PURE__ */ React22.createElement("div", { className: "flex gap-0" }, (cta_button == null ? void 0 : cta_button.secondary_label) && ctaUrls.hasSecondary && /* @__PURE__ */ React22.createElement(
|
|
6821
6840
|
Button2,
|
|
6822
6841
|
{
|
|
6823
6842
|
href: ctaUrls.secondaryHref,
|
|
@@ -8591,6 +8610,7 @@ registerThemeVariant("hero-home", "aman", HeroHome2);
|
|
|
8591
8610
|
import React36, { useState as useState16, useRef as useRef9, useCallback as useCallback5 } from "react";
|
|
8592
8611
|
import Link6 from "next/link";
|
|
8593
8612
|
import Image11 from "next/image";
|
|
8613
|
+
import { usePathname as usePathname2 } from "next/navigation";
|
|
8594
8614
|
var MAX_DROPDOWN_ITEMS = 3;
|
|
8595
8615
|
function HeaderNavigation2({
|
|
8596
8616
|
props,
|
|
@@ -8626,6 +8646,9 @@ function HeaderNavigation2({
|
|
|
8626
8646
|
const companyName = logoTextOverride || (companyInformation == null ? void 0 : companyInformation.company_name) || ((_b = props == null ? void 0 : props.logo) == null ? void 0 : _b.text) || "";
|
|
8627
8647
|
const navigation = navigationOverride || ((_c = config == null ? void 0 : config.navigation) == null ? void 0 : _c.header) || [];
|
|
8628
8648
|
const ctaUrls = resolveCtaUrls(companyInformation);
|
|
8649
|
+
const pathname = usePathname2();
|
|
8650
|
+
const portalPath = resolvePortalPath(companyInformation);
|
|
8651
|
+
const isPortalPage = portalPath ? pathname == null ? void 0 : pathname.startsWith(portalPath) : false;
|
|
8629
8652
|
const cancelCloseTimeout = useCallback5(() => {
|
|
8630
8653
|
if (closeTimeoutRef.current) {
|
|
8631
8654
|
clearTimeout(closeTimeoutRef.current);
|
|
@@ -8843,7 +8866,7 @@ function HeaderNavigation2({
|
|
|
8843
8866
|
onClick: () => setIsMobileMenuOpen(false)
|
|
8844
8867
|
},
|
|
8845
8868
|
((_q = props == null ? void 0 : props.cta_button) == null ? void 0 : _q.secondary_label) && ctaUrls.hasSecondary ? props.cta_button.secondary_label : ((_r = props == null ? void 0 : props.cta_button) == null ? void 0 : _r.label) || "Contact"
|
|
8846
|
-
))))), /* @__PURE__ */ React36.createElement("div", { className: "fixed bottom-0 left-0 right-0 z-40 md:hidden bg-fg-primary" }, /* @__PURE__ */ React36.createElement("div", { className: "flex gap-0" }, ((_s = props == null ? void 0 : props.cta_button) == null ? void 0 : _s.secondary_label) && ctaUrls.hasSecondary && /* @__PURE__ */ React36.createElement(
|
|
8869
|
+
))))), !isPortalPage && /* @__PURE__ */ React36.createElement("div", { className: "fixed bottom-0 left-0 right-0 z-40 md:hidden bg-fg-primary" }, /* @__PURE__ */ React36.createElement("div", { className: "flex gap-0" }, ((_s = props == null ? void 0 : props.cta_button) == null ? void 0 : _s.secondary_label) && ctaUrls.hasSecondary && /* @__PURE__ */ React36.createElement(
|
|
8847
8870
|
Button2,
|
|
8848
8871
|
{
|
|
8849
8872
|
href: ctaUrls.secondaryHref,
|
|
@@ -9092,7 +9115,7 @@ var ContactSectionForm2 = ({
|
|
|
9092
9115
|
(_a = formRef.current) == null ? void 0 : _a.reset();
|
|
9093
9116
|
onSuccess == null ? void 0 : onSuccess();
|
|
9094
9117
|
await setPixelUserData({ email: data.email, phone: data.phone });
|
|
9095
|
-
firePixelEvent("Lead");
|
|
9118
|
+
firePixelEvent("Lead", void 0, result.eventId);
|
|
9096
9119
|
setTimeout(() => setSubmitStatus("idle"), 5e3);
|
|
9097
9120
|
} else {
|
|
9098
9121
|
setSubmitStatus("error");
|
|
@@ -17683,6 +17706,7 @@ registerThemeVariant("hero-home", "barelux", HeroHome3);
|
|
|
17683
17706
|
import React45, { useState as useState23, useRef as useRef14, useCallback as useCallback8 } from "react";
|
|
17684
17707
|
import Link8 from "next/link";
|
|
17685
17708
|
import Image12 from "next/image";
|
|
17709
|
+
import { usePathname as usePathname3 } from "next/navigation";
|
|
17686
17710
|
var MAX_DROPDOWN_ITEMS2 = 6;
|
|
17687
17711
|
function HeaderNavigation3({
|
|
17688
17712
|
props,
|
|
@@ -17708,6 +17732,9 @@ function HeaderNavigation3({
|
|
|
17708
17732
|
const companyName = logoTextOverride || (companyInformation == null ? void 0 : companyInformation.company_name) || ((_b = props == null ? void 0 : props.logo) == null ? void 0 : _b.text) || "";
|
|
17709
17733
|
const navigation = navigationOverride || ((_c = config == null ? void 0 : config.navigation) == null ? void 0 : _c.header) || [];
|
|
17710
17734
|
const ctaUrls = resolveCtaUrls(companyInformation);
|
|
17735
|
+
const pathname = usePathname3();
|
|
17736
|
+
const portalPath = resolvePortalPath(companyInformation);
|
|
17737
|
+
const isPortalPage = portalPath ? pathname == null ? void 0 : pathname.startsWith(portalPath) : false;
|
|
17711
17738
|
const cancelCloseTimeout = useCallback8(() => {
|
|
17712
17739
|
if (closeTimeoutRef.current) {
|
|
17713
17740
|
clearTimeout(closeTimeoutRef.current);
|
|
@@ -17899,7 +17926,7 @@ function HeaderNavigation3({
|
|
|
17899
17926
|
onClick: () => setIsMobileMenuOpen(false)
|
|
17900
17927
|
},
|
|
17901
17928
|
((_m = props == null ? void 0 : props.cta_button) == null ? void 0 : _m.label) || ""
|
|
17902
|
-
))))), /* @__PURE__ */ React45.createElement("div", { className: "fixed bottom-0 left-0 right-0 z-40 md:hidden bg-fg-primary" }, /* @__PURE__ */ React45.createElement("div", { className: "flex gap-0" }, ((_n = props == null ? void 0 : props.cta_button) == null ? void 0 : _n.secondary_label) && ctaUrls.hasSecondary && /* @__PURE__ */ React45.createElement(
|
|
17929
|
+
))))), !isPortalPage && /* @__PURE__ */ React45.createElement("div", { className: "fixed bottom-0 left-0 right-0 z-40 md:hidden bg-fg-primary" }, /* @__PURE__ */ React45.createElement("div", { className: "flex gap-0" }, ((_n = props == null ? void 0 : props.cta_button) == null ? void 0 : _n.secondary_label) && ctaUrls.hasSecondary && /* @__PURE__ */ React45.createElement(
|
|
17903
17930
|
Button2,
|
|
17904
17931
|
{
|
|
17905
17932
|
href: ctaUrls.secondaryHref,
|
|
@@ -18294,7 +18321,7 @@ var ContactSectionForm3 = ({
|
|
|
18294
18321
|
(_a = formRef.current) == null ? void 0 : _a.reset();
|
|
18295
18322
|
onSuccess == null ? void 0 : onSuccess();
|
|
18296
18323
|
await setPixelUserData({ email: data.email, phone: data.phone });
|
|
18297
|
-
firePixelEvent("Lead");
|
|
18324
|
+
firePixelEvent("Lead", void 0, result.eventId);
|
|
18298
18325
|
setTimeout(() => setSubmitStatus("idle"), 5e3);
|
|
18299
18326
|
} else {
|
|
18300
18327
|
setSubmitStatus("error");
|
|
@@ -18474,6 +18501,7 @@ registerThemeVariant("hero-home", "balance", HeroHome4);
|
|
|
18474
18501
|
import React53, { useState as useState27, useRef as useRef16, useCallback as useCallback9 } from "react";
|
|
18475
18502
|
import Link10 from "next/link";
|
|
18476
18503
|
import Image13 from "next/image";
|
|
18504
|
+
import { usePathname as usePathname4 } from "next/navigation";
|
|
18477
18505
|
function HeaderNavigation4({
|
|
18478
18506
|
props,
|
|
18479
18507
|
navigation: navigationOverride,
|
|
@@ -18498,6 +18526,9 @@ function HeaderNavigation4({
|
|
|
18498
18526
|
const companyName = logoTextOverride || (companyInformation == null ? void 0 : companyInformation.company_name) || ((_b = props == null ? void 0 : props.logo) == null ? void 0 : _b.text) || "";
|
|
18499
18527
|
const navigation = navigationOverride || ((_c = config == null ? void 0 : config.navigation) == null ? void 0 : _c.header) || [];
|
|
18500
18528
|
const ctaUrls = resolveCtaUrls(companyInformation);
|
|
18529
|
+
const pathname = usePathname4();
|
|
18530
|
+
const portalPath = resolvePortalPath(companyInformation);
|
|
18531
|
+
const isPortalPage = portalPath ? pathname == null ? void 0 : pathname.startsWith(portalPath) : false;
|
|
18501
18532
|
const cancelCloseTimeout = useCallback9(() => {
|
|
18502
18533
|
if (closeTimeoutRef.current) {
|
|
18503
18534
|
clearTimeout(closeTimeoutRef.current);
|
|
@@ -18659,7 +18690,7 @@ function HeaderNavigation4({
|
|
|
18659
18690
|
onClick: () => setIsMobileMenuOpen(false)
|
|
18660
18691
|
},
|
|
18661
18692
|
((_m = props == null ? void 0 : props.cta_button) == null ? void 0 : _m.label) || ""
|
|
18662
|
-
))))), /* @__PURE__ */ React53.createElement("div", { className: "fixed bottom-0 left-0 right-0 z-40 md:hidden", style: { backgroundColor: "rgb(148, 133, 84)" } }, /* @__PURE__ */ React53.createElement("div", { className: "flex gap-0" }, ((_n = props == null ? void 0 : props.cta_button) == null ? void 0 : _n.secondary_label) && ctaUrls.hasSecondary && /* @__PURE__ */ React53.createElement(
|
|
18693
|
+
))))), !isPortalPage && /* @__PURE__ */ React53.createElement("div", { className: "fixed bottom-0 left-0 right-0 z-40 md:hidden", style: { backgroundColor: "rgb(148, 133, 84)" } }, /* @__PURE__ */ React53.createElement("div", { className: "flex gap-0" }, ((_n = props == null ? void 0 : props.cta_button) == null ? void 0 : _n.secondary_label) && ctaUrls.hasSecondary && /* @__PURE__ */ React53.createElement(
|
|
18663
18694
|
Button2,
|
|
18664
18695
|
{
|
|
18665
18696
|
href: ctaUrls.secondaryHref,
|
|
@@ -18788,7 +18819,7 @@ var ContactSectionForm4 = ({
|
|
|
18788
18819
|
(_a = formRef.current) == null ? void 0 : _a.reset();
|
|
18789
18820
|
onSuccess == null ? void 0 : onSuccess();
|
|
18790
18821
|
await setPixelUserData({ email: data.email, phone: data.phone });
|
|
18791
|
-
firePixelEvent("Lead");
|
|
18822
|
+
firePixelEvent("Lead", void 0, result.eventId);
|
|
18792
18823
|
setTimeout(() => setSubmitStatus("idle"), 5e3);
|
|
18793
18824
|
} else {
|
|
18794
18825
|
setSubmitStatus("error");
|