@hanzo/ui 0.5.15 → 0.5.17
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/blocks/components/carte-blanche-block/index.tsx +9 -2
- package/blocks/components/carte-blanche-block/variant-content-left.tsx +11 -9
- package/common/contact-dialog/disclaimer.tsx +1 -1
- package/common/contact-dialog/index.tsx +2 -2
- package/next/analytics/fpixel.ts +10 -0
- package/next/analytics/google-analytics.tsx +47 -0
- package/next/analytics/gtag.ts +17 -0
- package/next/analytics/pixel-analytics.tsx +55 -0
- package/next/root-layout.tsx +6 -0
- package/package.json +1 -1
- package/primitives/dialog.tsx +1 -1
- package/siteDef/footer/legal.ts +2 -2
|
@@ -47,6 +47,9 @@ const _getClx = (specifier: string, section: CardSection): string => {
|
|
|
47
47
|
case 'header': {
|
|
48
48
|
result = 'border-none'
|
|
49
49
|
} break
|
|
50
|
+
case 'footer': {
|
|
51
|
+
result = 'border-t-0'
|
|
52
|
+
} break
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
|
|
@@ -83,6 +86,10 @@ const CarteBlancheBlockComponent: React.FC<
|
|
|
83
86
|
getClx('big-padding-content', 'content'),
|
|
84
87
|
].join(' ')
|
|
85
88
|
|
|
89
|
+
const footerclx = [
|
|
90
|
+
getClx('no-inner-borders', 'footer'),
|
|
91
|
+
].join(' ')
|
|
92
|
+
|
|
86
93
|
const noOuterBorders = specified('no-outer-borders')
|
|
87
94
|
const contentLeft = specified('variant-content-left')
|
|
88
95
|
const mobileContentLeft = specified('variant-mobile-content-left')
|
|
@@ -90,7 +97,7 @@ const CarteBlancheBlockComponent: React.FC<
|
|
|
90
97
|
return (
|
|
91
98
|
<Card className={cn('flex flex-col', className, noOuterBorders ? 'border-none' : '')} >
|
|
92
99
|
{contentLeft || (mobileContentLeft && agent === 'phone') ? (
|
|
93
|
-
<VariantContentLeft block={b} agent={agent} className={className} contentclx={contentclx}
|
|
100
|
+
<VariantContentLeft block={b} agent={agent} className={className} headingclx={headingclx} contentclx={contentclx} footerclx={footerclx}/>
|
|
94
101
|
) : (<>
|
|
95
102
|
{(b.heading || b.topContent) && (
|
|
96
103
|
<CardHeader className={cn('typography-img:m-0', headingclx)} >
|
|
@@ -108,7 +115,7 @@ const CarteBlancheBlockComponent: React.FC<
|
|
|
108
115
|
</CardContent>
|
|
109
116
|
)}
|
|
110
117
|
{b.cta && (
|
|
111
|
-
<CardFooter className={'grid grid-cols-1 gap-2 md:flex md:flex-row md:justify-center
|
|
118
|
+
<CardFooter className={cn('grid grid-cols-1 gap-2 md:flex md:flex-row md:justify-center', footerclx)} >
|
|
112
119
|
<CTABlockComponent block={b.cta} agent={agent}/>
|
|
113
120
|
</CardFooter>
|
|
114
121
|
)}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EnhHeadingBlockComponent, type
|
|
1
|
+
import { EnhHeadingBlockComponent, type CarteBlancheBlock, CTABlockComponent } from '../..'
|
|
2
2
|
import {
|
|
3
3
|
CardContent,
|
|
4
4
|
CardFooter,
|
|
@@ -13,16 +13,18 @@ const VariantContentLeft: React.FC<{
|
|
|
13
13
|
className?: string
|
|
14
14
|
headingclx?: string
|
|
15
15
|
contentclx?: string
|
|
16
|
+
footerclx?: string
|
|
16
17
|
}> = ({
|
|
17
18
|
block,
|
|
18
19
|
agent,
|
|
19
20
|
className,
|
|
20
21
|
headingclx,
|
|
21
22
|
contentclx,
|
|
23
|
+
footerclx,
|
|
22
24
|
}) => {
|
|
23
|
-
return (
|
|
25
|
+
return (<>
|
|
24
26
|
<div className='flex gap-2'>
|
|
25
|
-
{block.topContent && <Content blocks={block.topContent} agent={agent} className='self-
|
|
27
|
+
{block.topContent && <Content blocks={block.topContent} agent={agent} className='self-center ml-6 mt-6'/>}
|
|
26
28
|
<div className='flex flex-col'>
|
|
27
29
|
{block.heading && (
|
|
28
30
|
<CardHeader className={cn('typography-img:m-0', headingclx)} >
|
|
@@ -34,14 +36,14 @@ const VariantContentLeft: React.FC<{
|
|
|
34
36
|
<Content blocks={block.content} agent={agent}/>
|
|
35
37
|
</CardContent>
|
|
36
38
|
)}
|
|
37
|
-
{block.cta && (
|
|
38
|
-
<CardFooter className={'grid grid-cols-1 gap-2 md:flex md:flex-row md:justify-center ' /*+ paddingclx*/} >
|
|
39
|
-
<CTABlockComponent block={block.cta} agent={agent}/>
|
|
40
|
-
</CardFooter>
|
|
41
|
-
)}
|
|
42
39
|
</div>
|
|
43
40
|
</div>
|
|
44
|
-
|
|
41
|
+
{block.cta && (
|
|
42
|
+
<CardFooter className={cn('grid grid-cols-1 gap-2 md:flex md:flex-row md:justify-center mx-auto', footerclx)}>
|
|
43
|
+
<CTABlockComponent block={block.cta} agent={agent}/>
|
|
44
|
+
</CardFooter>
|
|
45
|
+
)}
|
|
46
|
+
</>)
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
export default VariantContentLeft
|
|
@@ -5,7 +5,7 @@ const Disclaimer: React.FC = () => (
|
|
|
5
5
|
By entering your mobile number and submitting, you consent to receive text messages from Lux at the number provided.
|
|
6
6
|
Message and data rates may apply. Message frequency varies.
|
|
7
7
|
You can unsubscribe at any time by replying STOP.
|
|
8
|
-
View our <a href='/
|
|
8
|
+
View our <a href='/privacy'>Privacy Policy</a> and <a href='/terms'>Terms & conditions</a>.
|
|
9
9
|
</div>
|
|
10
10
|
)
|
|
11
11
|
|
|
@@ -30,8 +30,8 @@ const ContactDialog: React.FC<ButtonModalProps> = ({
|
|
|
30
30
|
<DialogTrigger asChild>
|
|
31
31
|
<Button {...buttonProps} >{buttonText}</Button>
|
|
32
32
|
</DialogTrigger>
|
|
33
|
-
<DialogContent className="sm:max-w-[500px] p-0 gap-0
|
|
34
|
-
<DialogHeader className='py-6
|
|
33
|
+
<DialogContent className="sm:max-w-[500px] p-0 gap-0 bg-background border">
|
|
34
|
+
<DialogHeader className='py-6 text-foreground'>
|
|
35
35
|
<DialogTitle className='text-4xl font-heading text-center text-inherit'>{title}</DialogTitle>
|
|
36
36
|
{byline && (<DialogDescription className='text-inherit text-xl text-center'>{byline} </DialogDescription>)}
|
|
37
37
|
</DialogHeader>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const FB_PIXEL_ID = process.env.NEXT_PUBLIC_FACEBOOK_PIXEL_ID
|
|
2
|
+
|
|
3
|
+
export const pageview = () => {
|
|
4
|
+
window.fbq('track', 'PageView')
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// https://developers.facebook.com/docs/facebook-pixel/advanced/
|
|
8
|
+
export const event = (name: string, options = {}) => {
|
|
9
|
+
window.fbq('track', name, options)
|
|
10
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from 'react'
|
|
4
|
+
import * as gtag from './gtag'
|
|
5
|
+
import Script from 'next/script'
|
|
6
|
+
import { usePathname } from 'next/navigation'
|
|
7
|
+
|
|
8
|
+
const GoogleAnalyticsHead = () => {
|
|
9
|
+
return (
|
|
10
|
+
<script
|
|
11
|
+
dangerouslySetInnerHTML={{
|
|
12
|
+
__html: `
|
|
13
|
+
window.dataLayer = window.dataLayer || [];
|
|
14
|
+
function gtag(){dataLayer.push(arguments);}
|
|
15
|
+
gtag('js', new Date());
|
|
16
|
+
|
|
17
|
+
gtag('config', '${gtag.GA_TRACKING_ID}', {
|
|
18
|
+
page_path: window.location.pathname,
|
|
19
|
+
});
|
|
20
|
+
`,
|
|
21
|
+
}}
|
|
22
|
+
/>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const GoogleAnalytics = () => {
|
|
27
|
+
const [loaded, setLoaded] = useState(false)
|
|
28
|
+
const pathname = usePathname()
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (!loaded) return
|
|
32
|
+
|
|
33
|
+
gtag.pageview(pathname)
|
|
34
|
+
}, [pathname, loaded])
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div>
|
|
38
|
+
<Script
|
|
39
|
+
strategy='afterInteractive'
|
|
40
|
+
onLoad={() => setLoaded(true)}
|
|
41
|
+
src={`https://www.googletagmanager.com/gtag/js?id=${gtag.GA_TRACKING_ID}`}
|
|
42
|
+
/>
|
|
43
|
+
</div>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export {GoogleAnalyticsHead, GoogleAnalytics}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GA_ID
|
|
2
|
+
|
|
3
|
+
// https://developers.google.com/analytics/devguides/collection/gtagjs/pages
|
|
4
|
+
export const pageview = (url: string) => {
|
|
5
|
+
window.gtag('config', GA_TRACKING_ID, {
|
|
6
|
+
page_path: url,
|
|
7
|
+
})
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// https://developers.google.com/analytics/devguides/collection/gtagjs/events
|
|
11
|
+
export const event = ({ action, category, label, value }: {action: string, category: string, label: string, value: string}) => {
|
|
12
|
+
window.gtag('event', action, {
|
|
13
|
+
event_category: category,
|
|
14
|
+
event_label: label,
|
|
15
|
+
value: value,
|
|
16
|
+
})
|
|
17
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { usePathname } from 'next/navigation'
|
|
4
|
+
import Script from 'next/script'
|
|
5
|
+
import { useEffect, useState } from 'react'
|
|
6
|
+
import * as fbq from './fpixel'
|
|
7
|
+
|
|
8
|
+
const FacebookPixelHead = () => {
|
|
9
|
+
return (
|
|
10
|
+
<noscript>
|
|
11
|
+
<img
|
|
12
|
+
height='1'
|
|
13
|
+
width='1'
|
|
14
|
+
style={{ display: 'none' }}
|
|
15
|
+
src={`https://www.facebook.com/tr?id=${fbq.FB_PIXEL_ID}&ev=PageView&noscript=1`}
|
|
16
|
+
/>
|
|
17
|
+
</noscript>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const FacebookPixel = () => {
|
|
22
|
+
const [loaded, setLoaded] = useState(false)
|
|
23
|
+
const pathname = usePathname()
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (!loaded) return
|
|
27
|
+
|
|
28
|
+
fbq.pageview()
|
|
29
|
+
}, [pathname, loaded])
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div>
|
|
33
|
+
<Script
|
|
34
|
+
id='fb-pixel'
|
|
35
|
+
strategy='afterInteractive'
|
|
36
|
+
onLoad={() => setLoaded(true)}
|
|
37
|
+
dangerouslySetInnerHTML={{
|
|
38
|
+
__html: `
|
|
39
|
+
!function(f,b,e,v,n,t,s)
|
|
40
|
+
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
|
|
41
|
+
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
|
|
42
|
+
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
|
|
43
|
+
n.queue=[];t=b.createElement(e);t.async=!0;
|
|
44
|
+
t.src=v;s=b.getElementsByTagName(e)[0];
|
|
45
|
+
s.parentNode.insertBefore(t,s)}(window, document,'script',
|
|
46
|
+
'https://connect.facebook.net/en_US/fbevents.js');
|
|
47
|
+
fbq('init', ${fbq.FB_PIXEL_ID});
|
|
48
|
+
`,
|
|
49
|
+
}}
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export {FacebookPixelHead, FacebookPixel}
|
package/next/root-layout.tsx
CHANGED
|
@@ -3,6 +3,8 @@ import React, { type PropsWithChildren } from 'react'
|
|
|
3
3
|
import Header from '../common/header'
|
|
4
4
|
import type { SiteDef } from '../types'
|
|
5
5
|
import getAppRouterBodyFontClasses from './get-app-router-font-classes'
|
|
6
|
+
import { FacebookPixelHead, FacebookPixel } from './analytics/pixel-analytics'
|
|
7
|
+
import { GoogleAnalytics, GoogleAnalyticsHead } from './analytics/google-analytics'
|
|
6
8
|
|
|
7
9
|
// Next 14: https://nextjs.org/docs/app/building-your-application/upgrading/codemods#use-viewport-export
|
|
8
10
|
const viewport = {
|
|
@@ -39,8 +41,12 @@ const RootLayout: React.FC<PropsWithChildren & {
|
|
|
39
41
|
<head >
|
|
40
42
|
{/* https://stackoverflow.com/a/75716588/11645689 */ }
|
|
41
43
|
<base target='_blank' />
|
|
44
|
+
<FacebookPixelHead/>
|
|
45
|
+
<GoogleAnalyticsHead/>
|
|
42
46
|
</head>
|
|
43
47
|
<body className={bodyClasses}>
|
|
48
|
+
<FacebookPixel />
|
|
49
|
+
<GoogleAnalytics />
|
|
44
50
|
{header && <Header siteDef={siteDef}/>}
|
|
45
51
|
{children}
|
|
46
52
|
</body>
|
package/package.json
CHANGED
package/primitives/dialog.tsx
CHANGED
|
@@ -50,7 +50,7 @@ const DialogClose = React.forwardRef<
|
|
|
50
50
|
<DialogPrimitive.Close
|
|
51
51
|
ref={ref}
|
|
52
52
|
className={cn(
|
|
53
|
-
"absolute right-4 top-3 p-1 justify-self-start hover:brightness-105 hover:scale-110 duration-100 ring-1 ring-
|
|
53
|
+
"absolute right-4 top-3 p-1 justify-self-start hover:brightness-105 hover:scale-110 duration-100 ring-1 ring-muted transition bg-secondary-500 hover:text-primary-text focus:outline-none rounded-full items-center",
|
|
54
54
|
className
|
|
55
55
|
)}
|
|
56
56
|
{...props}
|
package/siteDef/footer/legal.ts
CHANGED
|
@@ -3,12 +3,12 @@ import type { LinkDef } from '../../types'
|
|
|
3
3
|
const legal: LinkDef[] = [
|
|
4
4
|
{
|
|
5
5
|
title: 'Terms and Conditions',
|
|
6
|
-
href: '/
|
|
6
|
+
href: '/terms',
|
|
7
7
|
newTab: true,
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
title: 'Privacy Policy',
|
|
11
|
-
href: '/
|
|
11
|
+
href: '/privacy',
|
|
12
12
|
newTab: true,
|
|
13
13
|
},
|
|
14
14
|
]
|