@opensite/ui 1.5.4 → 1.5.5
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/dist/components.cjs +1 -1
- package/dist/components.js +1 -1
- package/dist/feature-integration-cards.cjs +65 -217
- package/dist/feature-integration-cards.js +65 -217
- package/dist/footer-accordion-social.cjs +39 -37
- package/dist/footer-accordion-social.d.cts +4 -1
- package/dist/footer-accordion-social.d.ts +4 -1
- package/dist/footer-accordion-social.js +39 -37
- package/dist/footer-newsletter-contact.cjs +1 -1
- package/dist/footer-newsletter-contact.d.cts +4 -1
- package/dist/footer-newsletter-contact.d.ts +4 -1
- package/dist/footer-newsletter-contact.js +1 -1
- package/dist/footer-newsletter-minimal.cjs +1 -1
- package/dist/footer-newsletter-minimal.d.cts +4 -1
- package/dist/footer-newsletter-minimal.d.ts +4 -1
- package/dist/footer-newsletter-minimal.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/registry.cjs +105 -98
- package/dist/registry.js +105 -98
- package/package.json +1 -1
|
@@ -3,171 +3,14 @@ import * as React from 'react';
|
|
|
3
3
|
import React__default, { useCallback, useMemo } from 'react';
|
|
4
4
|
import { clsx } from 'clsx';
|
|
5
5
|
import { twMerge } from 'tailwind-merge';
|
|
6
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
6
|
import { cva } from 'class-variance-authority';
|
|
7
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
8
|
import { Img } from '@page-speed/img';
|
|
9
9
|
|
|
10
10
|
// components/blocks/features/feature-integration-cards.tsx
|
|
11
11
|
function cn(...inputs) {
|
|
12
12
|
return twMerge(clsx(inputs));
|
|
13
13
|
}
|
|
14
|
-
function getTextColor(parentBg, variant = "default", options) {
|
|
15
|
-
const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
|
|
16
|
-
if (isDark) {
|
|
17
|
-
switch (variant) {
|
|
18
|
-
case "default":
|
|
19
|
-
return "text-foreground";
|
|
20
|
-
case "muted":
|
|
21
|
-
return "text-foreground/80";
|
|
22
|
-
case "subtle":
|
|
23
|
-
return "text-foreground/60";
|
|
24
|
-
case "accent":
|
|
25
|
-
return "text-accent-foreground";
|
|
26
|
-
}
|
|
27
|
-
} else {
|
|
28
|
-
switch (variant) {
|
|
29
|
-
case "default":
|
|
30
|
-
return "text-foreground";
|
|
31
|
-
case "muted":
|
|
32
|
-
return "text-muted-foreground";
|
|
33
|
-
case "subtle":
|
|
34
|
-
return "text-muted-foreground/70";
|
|
35
|
-
case "accent":
|
|
36
|
-
return "text-primary";
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function getAccentColor(parentBg, options) {
|
|
41
|
-
const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
|
|
42
|
-
return isDark ? "text-accent-foreground" : "text-primary";
|
|
43
|
-
}
|
|
44
|
-
function getBorderColor(parentBg, variant = "default", options) {
|
|
45
|
-
const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
|
|
46
|
-
if (isDark) {
|
|
47
|
-
switch (variant) {
|
|
48
|
-
case "default":
|
|
49
|
-
return "border-foreground/20";
|
|
50
|
-
case "muted":
|
|
51
|
-
return "border-foreground/10";
|
|
52
|
-
case "accent":
|
|
53
|
-
return "border-accent-foreground";
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
switch (variant) {
|
|
57
|
-
case "default":
|
|
58
|
-
return "border-border";
|
|
59
|
-
case "muted":
|
|
60
|
-
return "border-muted";
|
|
61
|
-
case "accent":
|
|
62
|
-
return "border-primary";
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
var svgCache = /* @__PURE__ */ new Map();
|
|
67
|
-
function DynamicIcon({
|
|
68
|
-
name,
|
|
69
|
-
size = 28,
|
|
70
|
-
color,
|
|
71
|
-
className,
|
|
72
|
-
alt
|
|
73
|
-
}) {
|
|
74
|
-
const [svgContent, setSvgContent] = React.useState(null);
|
|
75
|
-
const [isLoading, setIsLoading] = React.useState(true);
|
|
76
|
-
const [error, setError] = React.useState(null);
|
|
77
|
-
const { url, iconName } = React.useMemo(() => {
|
|
78
|
-
const separator = name.includes("/") ? "/" : ":";
|
|
79
|
-
const [prefix, iconName2] = name.split(separator);
|
|
80
|
-
const baseUrl = `https://icons.opensite.ai/api/icon/${prefix}/${iconName2}?format=svg&width=${size}&height=${size}&key=au382bi7fsh96w9h9xlrnat2jglx`;
|
|
81
|
-
return {
|
|
82
|
-
url: baseUrl,
|
|
83
|
-
iconName: iconName2
|
|
84
|
-
};
|
|
85
|
-
}, [name, size]);
|
|
86
|
-
React.useEffect(() => {
|
|
87
|
-
let isMounted = true;
|
|
88
|
-
const fetchSvg = async () => {
|
|
89
|
-
const cached = svgCache.get(url);
|
|
90
|
-
if (cached) {
|
|
91
|
-
if (isMounted) {
|
|
92
|
-
setSvgContent(cached);
|
|
93
|
-
setIsLoading(false);
|
|
94
|
-
}
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
try {
|
|
98
|
-
setIsLoading(true);
|
|
99
|
-
setError(null);
|
|
100
|
-
const response = await fetch(url);
|
|
101
|
-
if (!response.ok) {
|
|
102
|
-
throw new Error(`Failed to fetch icon: ${response.status}`);
|
|
103
|
-
}
|
|
104
|
-
let svg = await response.text();
|
|
105
|
-
svg = processSvgForCurrentColor(svg);
|
|
106
|
-
svgCache.set(url, svg);
|
|
107
|
-
if (isMounted) {
|
|
108
|
-
setSvgContent(svg);
|
|
109
|
-
setIsLoading(false);
|
|
110
|
-
}
|
|
111
|
-
} catch (err) {
|
|
112
|
-
if (isMounted) {
|
|
113
|
-
setError(err instanceof Error ? err.message : "Failed to load icon");
|
|
114
|
-
setIsLoading(false);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
fetchSvg();
|
|
119
|
-
return () => {
|
|
120
|
-
isMounted = false;
|
|
121
|
-
};
|
|
122
|
-
}, [url]);
|
|
123
|
-
if (isLoading) {
|
|
124
|
-
return /* @__PURE__ */ jsx(
|
|
125
|
-
"span",
|
|
126
|
-
{
|
|
127
|
-
className: cn("inline-block", className),
|
|
128
|
-
style: { width: size, height: size },
|
|
129
|
-
"aria-hidden": "true"
|
|
130
|
-
}
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
if (error || !svgContent) {
|
|
134
|
-
return /* @__PURE__ */ jsx(
|
|
135
|
-
"span",
|
|
136
|
-
{
|
|
137
|
-
className: cn("inline-block", className),
|
|
138
|
-
style: { width: size, height: size },
|
|
139
|
-
role: "img",
|
|
140
|
-
"aria-label": alt || iconName
|
|
141
|
-
}
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
return /* @__PURE__ */ jsx(
|
|
145
|
-
"span",
|
|
146
|
-
{
|
|
147
|
-
className: cn("inline-flex items-center justify-center", className),
|
|
148
|
-
style: {
|
|
149
|
-
width: size,
|
|
150
|
-
height: size,
|
|
151
|
-
color: color || "inherit"
|
|
152
|
-
},
|
|
153
|
-
role: "img",
|
|
154
|
-
"aria-label": alt || iconName,
|
|
155
|
-
dangerouslySetInnerHTML: { __html: svgContent }
|
|
156
|
-
}
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
function processSvgForCurrentColor(svg) {
|
|
160
|
-
let processed = svg;
|
|
161
|
-
processed = processed.replace(
|
|
162
|
-
/stroke=["'](#000000|#000|black)["']/gi,
|
|
163
|
-
'stroke="currentColor"'
|
|
164
|
-
);
|
|
165
|
-
processed = processed.replace(
|
|
166
|
-
/fill=["'](#000000|#000|black)["']/gi,
|
|
167
|
-
'fill="currentColor"'
|
|
168
|
-
);
|
|
169
|
-
return processed;
|
|
170
|
-
}
|
|
171
14
|
function normalizePhoneNumber(input) {
|
|
172
15
|
const trimmed = input.trim();
|
|
173
16
|
if (trimmed.toLowerCase().startsWith("tel:")) {
|
|
@@ -980,66 +823,39 @@ function FeatureIntegrationCards({
|
|
|
980
823
|
patternOpacity,
|
|
981
824
|
patternClassName
|
|
982
825
|
}) {
|
|
983
|
-
const renderIntegrationIcon = useCallback(
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
className: cn(
|
|
1004
|
-
"flex items-center gap-1.5 rounded-full border px-3 py-2 text-sm font-medium transition-colors",
|
|
1005
|
-
getBorderColor(background),
|
|
1006
|
-
getAccentColor(background),
|
|
1007
|
-
integration.linkLabelClassName
|
|
1008
|
-
),
|
|
1009
|
-
children: [
|
|
1010
|
-
integration.linkLabel,
|
|
1011
|
-
/* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/arrow-right", size: 14 })
|
|
1012
|
-
]
|
|
1013
|
-
}
|
|
1014
|
-
);
|
|
1015
|
-
}, [background]);
|
|
826
|
+
const renderIntegrationIcon = useCallback(
|
|
827
|
+
(integration) => {
|
|
828
|
+
if (integration.iconSlot) return integration.iconSlot;
|
|
829
|
+
if (!integration.icon) return null;
|
|
830
|
+
return /* @__PURE__ */ jsx(
|
|
831
|
+
Img,
|
|
832
|
+
{
|
|
833
|
+
src: integration.icon,
|
|
834
|
+
alt: integration.iconAlt || (typeof integration.title === "string" ? integration.title : "Integration icon"),
|
|
835
|
+
className: cn(
|
|
836
|
+
"min-h-12 h-auto w-auto object-contain",
|
|
837
|
+
integration.iconClassName
|
|
838
|
+
),
|
|
839
|
+
loading: "lazy",
|
|
840
|
+
optixFlowConfig
|
|
841
|
+
}
|
|
842
|
+
);
|
|
843
|
+
},
|
|
844
|
+
[optixFlowConfig]
|
|
845
|
+
);
|
|
1016
846
|
const integrationsContent = useMemo(() => {
|
|
1017
847
|
if (integrationsSlot) return integrationsSlot;
|
|
1018
848
|
if (!integrations || integrations.length === 0) return null;
|
|
1019
849
|
return integrations.map((integration, index) => {
|
|
1020
850
|
const iconContent = renderIntegrationIcon(integration);
|
|
1021
|
-
const linkLabelContent = renderLinkLabel(integration);
|
|
1022
851
|
const cardContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1023
|
-
/* @__PURE__ */
|
|
1024
|
-
iconContent && /* @__PURE__ */ jsx(
|
|
1025
|
-
"span",
|
|
1026
|
-
{
|
|
1027
|
-
className: cn(
|
|
1028
|
-
"grid size-12 shrink-0 place-content-center rounded-lg border bg-background/50",
|
|
1029
|
-
getBorderColor(background)
|
|
1030
|
-
),
|
|
1031
|
-
children: iconContent
|
|
1032
|
-
}
|
|
1033
|
-
),
|
|
1034
|
-
linkLabelContent
|
|
1035
|
-
] }),
|
|
852
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-start gap-2 justify-between", children: iconContent && /* @__PURE__ */ jsx("div", { className: cn("flex"), children: iconContent }) }),
|
|
1036
853
|
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
1037
854
|
integration.title && (typeof integration.title === "string" ? /* @__PURE__ */ jsx(
|
|
1038
855
|
"h3",
|
|
1039
856
|
{
|
|
1040
857
|
className: cn(
|
|
1041
858
|
"font-semibold md:text-lg",
|
|
1042
|
-
getTextColor(background),
|
|
1043
859
|
integration.titleClassName
|
|
1044
860
|
),
|
|
1045
861
|
children: integration.title
|
|
@@ -1049,7 +865,6 @@ function FeatureIntegrationCards({
|
|
|
1049
865
|
{
|
|
1050
866
|
className: cn(
|
|
1051
867
|
"font-semibold md:text-lg",
|
|
1052
|
-
getTextColor(background),
|
|
1053
868
|
integration.titleClassName
|
|
1054
869
|
),
|
|
1055
870
|
children: integration.title
|
|
@@ -1060,7 +875,6 @@ function FeatureIntegrationCards({
|
|
|
1060
875
|
{
|
|
1061
876
|
className: cn(
|
|
1062
877
|
"text-sm leading-relaxed md:text-base",
|
|
1063
|
-
getTextColor(background, "muted"),
|
|
1064
878
|
integration.descriptionClassName
|
|
1065
879
|
),
|
|
1066
880
|
children: integration.description
|
|
@@ -1070,7 +884,6 @@ function FeatureIntegrationCards({
|
|
|
1070
884
|
{
|
|
1071
885
|
className: cn(
|
|
1072
886
|
"text-sm leading-relaxed md:text-base",
|
|
1073
|
-
getTextColor(background, "muted"),
|
|
1074
887
|
integration.descriptionClassName
|
|
1075
888
|
),
|
|
1076
889
|
children: integration.description
|
|
@@ -1079,8 +892,7 @@ function FeatureIntegrationCards({
|
|
|
1079
892
|
] })
|
|
1080
893
|
] });
|
|
1081
894
|
const cardClasses = cn(
|
|
1082
|
-
"flex flex-col gap-5 rounded-xl border p-6 transition-all duration-300",
|
|
1083
|
-
getBorderColor(background),
|
|
895
|
+
"flex flex-col gap-5 rounded-xl border p-6 transition-all duration-300 bg-card card-text-foreground",
|
|
1084
896
|
"hover:shadow-lg",
|
|
1085
897
|
cardClassName,
|
|
1086
898
|
integration.className
|
|
@@ -1098,7 +910,7 @@ function FeatureIntegrationCards({
|
|
|
1098
910
|
}
|
|
1099
911
|
return /* @__PURE__ */ jsx("div", { className: cardClasses, children: cardContent }, index);
|
|
1100
912
|
});
|
|
1101
|
-
}, [integrationsSlot, integrations, cardClassName, renderIntegrationIcon
|
|
913
|
+
}, [integrationsSlot, integrations, cardClassName, renderIntegrationIcon]);
|
|
1102
914
|
return /* @__PURE__ */ jsxs(
|
|
1103
915
|
Section,
|
|
1104
916
|
{
|
|
@@ -1110,11 +922,47 @@ function FeatureIntegrationCards({
|
|
|
1110
922
|
className,
|
|
1111
923
|
containerClassName,
|
|
1112
924
|
children: [
|
|
1113
|
-
/* @__PURE__ */ jsxs(
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
925
|
+
/* @__PURE__ */ jsxs(
|
|
926
|
+
"div",
|
|
927
|
+
{
|
|
928
|
+
className: cn(
|
|
929
|
+
"mx-auto mb-12 flex max-w-3xl flex-col items-center gap-4 text-center",
|
|
930
|
+
headerClassName
|
|
931
|
+
),
|
|
932
|
+
children: [
|
|
933
|
+
title && (typeof title === "string" ? /* @__PURE__ */ jsx(
|
|
934
|
+
"h2",
|
|
935
|
+
{
|
|
936
|
+
className: cn(
|
|
937
|
+
"text-3xl font-semibold md:text-4xl",
|
|
938
|
+
titleClassName
|
|
939
|
+
),
|
|
940
|
+
children: title
|
|
941
|
+
}
|
|
942
|
+
) : /* @__PURE__ */ jsx(
|
|
943
|
+
"div",
|
|
944
|
+
{
|
|
945
|
+
className: cn(
|
|
946
|
+
"text-3xl font-semibold md:text-4xl",
|
|
947
|
+
titleClassName
|
|
948
|
+
),
|
|
949
|
+
children: title
|
|
950
|
+
}
|
|
951
|
+
)),
|
|
952
|
+
description && (typeof description === "string" ? /* @__PURE__ */ jsx("p", { className: cn(descriptionClassName), children: description }) : /* @__PURE__ */ jsx("div", { className: cn(descriptionClassName), children: description }))
|
|
953
|
+
]
|
|
954
|
+
}
|
|
955
|
+
),
|
|
956
|
+
/* @__PURE__ */ jsx(
|
|
957
|
+
"div",
|
|
958
|
+
{
|
|
959
|
+
className: cn(
|
|
960
|
+
"grid gap-6 sm:grid-cols-2 lg:grid-cols-4",
|
|
961
|
+
gridClassName
|
|
962
|
+
),
|
|
963
|
+
children: integrationsContent
|
|
964
|
+
}
|
|
965
|
+
)
|
|
1118
966
|
]
|
|
1119
967
|
}
|
|
1120
968
|
);
|
|
@@ -1817,43 +1817,45 @@ function FooterAccordionSocial({
|
|
|
1817
1817
|
optixFlowConfig
|
|
1818
1818
|
}
|
|
1819
1819
|
),
|
|
1820
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1821
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1820
|
+
formConfig?.token && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1821
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
1822
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-2xl font-semibold", children: newsletterTitle }),
|
|
1823
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "opacity-80", children: newsletterDescription })
|
|
1824
|
+
] }),
|
|
1825
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1826
|
+
forms.Form,
|
|
1827
|
+
{
|
|
1828
|
+
form,
|
|
1829
|
+
action: formConfig?.endpoint,
|
|
1830
|
+
method: formMethod,
|
|
1831
|
+
className: "flex gap-2",
|
|
1832
|
+
children: [
|
|
1833
|
+
/* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "email", className: "flex-1", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1834
|
+
TextInput,
|
|
1835
|
+
{
|
|
1836
|
+
...field,
|
|
1837
|
+
type: "email",
|
|
1838
|
+
placeholder: "Email Address",
|
|
1839
|
+
error: meta.touched && !!meta.error,
|
|
1840
|
+
className: "flex h-10 w-full rounded-md border border-input px-3 py-2 text-sm ring-offset-background placeholder:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
1841
|
+
"aria-label": "Email Address"
|
|
1842
|
+
}
|
|
1843
|
+
) }),
|
|
1844
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1845
|
+
Pressable,
|
|
1846
|
+
{
|
|
1847
|
+
componentType: "button",
|
|
1848
|
+
type: "submit",
|
|
1849
|
+
className: "inline-flex h-10 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground hover:bg-primary/90",
|
|
1850
|
+
asButton: false,
|
|
1851
|
+
disabled: form.isSubmitting,
|
|
1852
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/arrow-right", size: 16 })
|
|
1853
|
+
}
|
|
1854
|
+
)
|
|
1855
|
+
]
|
|
1856
|
+
}
|
|
1857
|
+
)
|
|
1858
|
+
] })
|
|
1857
1859
|
] }),
|
|
1858
1860
|
footerLinks && footerLinks.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-x-16 gap-y-8 lg:grid-cols-3", children: footerLinks.map((section) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1859
1861
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-4 text-lg font-bold", children: section.title }),
|
|
@@ -74,8 +74,11 @@ interface FooterAccordionSocialProps {
|
|
|
74
74
|
};
|
|
75
75
|
/**
|
|
76
76
|
* Optional form submission configuration for newsletter signup.
|
|
77
|
+
* Requires `token` to render the newsletter UI.
|
|
77
78
|
*/
|
|
78
|
-
formConfig?: PageSpeedFormConfig
|
|
79
|
+
formConfig?: PageSpeedFormConfig & {
|
|
80
|
+
token: string;
|
|
81
|
+
};
|
|
79
82
|
/**
|
|
80
83
|
* Optional custom submission handler for newsletter signup.
|
|
81
84
|
*/
|
|
@@ -74,8 +74,11 @@ interface FooterAccordionSocialProps {
|
|
|
74
74
|
};
|
|
75
75
|
/**
|
|
76
76
|
* Optional form submission configuration for newsletter signup.
|
|
77
|
+
* Requires `token` to render the newsletter UI.
|
|
77
78
|
*/
|
|
78
|
-
formConfig?: PageSpeedFormConfig
|
|
79
|
+
formConfig?: PageSpeedFormConfig & {
|
|
80
|
+
token: string;
|
|
81
|
+
};
|
|
79
82
|
/**
|
|
80
83
|
* Optional custom submission handler for newsletter signup.
|
|
81
84
|
*/
|
|
@@ -1796,43 +1796,45 @@ function FooterAccordionSocial({
|
|
|
1796
1796
|
optixFlowConfig
|
|
1797
1797
|
}
|
|
1798
1798
|
),
|
|
1799
|
-
/* @__PURE__ */ jsxs(
|
|
1800
|
-
/* @__PURE__ */
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1799
|
+
formConfig?.token && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1800
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
1801
|
+
/* @__PURE__ */ jsx("h3", { className: "text-2xl font-semibold", children: newsletterTitle }),
|
|
1802
|
+
/* @__PURE__ */ jsx("p", { className: "opacity-80", children: newsletterDescription })
|
|
1803
|
+
] }),
|
|
1804
|
+
/* @__PURE__ */ jsxs(
|
|
1805
|
+
Form,
|
|
1806
|
+
{
|
|
1807
|
+
form,
|
|
1808
|
+
action: formConfig?.endpoint,
|
|
1809
|
+
method: formMethod,
|
|
1810
|
+
className: "flex gap-2",
|
|
1811
|
+
children: [
|
|
1812
|
+
/* @__PURE__ */ jsx(Field, { name: "email", className: "flex-1", children: ({ field, meta }) => /* @__PURE__ */ jsx(
|
|
1813
|
+
TextInput,
|
|
1814
|
+
{
|
|
1815
|
+
...field,
|
|
1816
|
+
type: "email",
|
|
1817
|
+
placeholder: "Email Address",
|
|
1818
|
+
error: meta.touched && !!meta.error,
|
|
1819
|
+
className: "flex h-10 w-full rounded-md border border-input px-3 py-2 text-sm ring-offset-background placeholder:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
1820
|
+
"aria-label": "Email Address"
|
|
1821
|
+
}
|
|
1822
|
+
) }),
|
|
1823
|
+
/* @__PURE__ */ jsx(
|
|
1824
|
+
Pressable,
|
|
1825
|
+
{
|
|
1826
|
+
componentType: "button",
|
|
1827
|
+
type: "submit",
|
|
1828
|
+
className: "inline-flex h-10 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground hover:bg-primary/90",
|
|
1829
|
+
asButton: false,
|
|
1830
|
+
disabled: form.isSubmitting,
|
|
1831
|
+
children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/arrow-right", size: 16 })
|
|
1832
|
+
}
|
|
1833
|
+
)
|
|
1834
|
+
]
|
|
1835
|
+
}
|
|
1836
|
+
)
|
|
1837
|
+
] })
|
|
1836
1838
|
] }),
|
|
1837
1839
|
footerLinks && footerLinks.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-x-16 gap-y-8 lg:grid-cols-3", children: footerLinks.map((section) => /* @__PURE__ */ jsxs("div", { children: [
|
|
1838
1840
|
/* @__PURE__ */ jsx("h3", { className: "mb-4 text-lg font-bold", children: section.title }),
|
|
@@ -1873,7 +1873,7 @@ function FooterNewsletterContact({
|
|
|
1873
1873
|
className: cn(className),
|
|
1874
1874
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-10", children: [
|
|
1875
1875
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-x-16 gap-y-8 md:grid-cols-2 xl:grid-cols-4", children: [
|
|
1876
|
-
(newsletterTitle || newsletterDescription || newsletterButtonText) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
1876
|
+
formConfig?.token && (newsletterTitle || newsletterDescription || newsletterButtonText) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
1877
1877
|
newsletterTitle && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-3xl font-medium font-serif leading-none", children: newsletterTitle }),
|
|
1878
1878
|
newsletterDescription && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-light leading-normal", children: newsletterDescription }),
|
|
1879
1879
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -108,8 +108,11 @@ interface FooterNewsletterContactProps {
|
|
|
108
108
|
};
|
|
109
109
|
/**
|
|
110
110
|
* Optional form submission configuration for newsletter signup.
|
|
111
|
+
* Requires `token` to render the newsletter UI.
|
|
111
112
|
*/
|
|
112
|
-
formConfig?: PageSpeedFormConfig
|
|
113
|
+
formConfig?: PageSpeedFormConfig & {
|
|
114
|
+
token: string;
|
|
115
|
+
};
|
|
113
116
|
/**
|
|
114
117
|
* Optional custom submission handler for newsletter signup.
|
|
115
118
|
*/
|
|
@@ -108,8 +108,11 @@ interface FooterNewsletterContactProps {
|
|
|
108
108
|
};
|
|
109
109
|
/**
|
|
110
110
|
* Optional form submission configuration for newsletter signup.
|
|
111
|
+
* Requires `token` to render the newsletter UI.
|
|
111
112
|
*/
|
|
112
|
-
formConfig?: PageSpeedFormConfig
|
|
113
|
+
formConfig?: PageSpeedFormConfig & {
|
|
114
|
+
token: string;
|
|
115
|
+
};
|
|
113
116
|
/**
|
|
114
117
|
* Optional custom submission handler for newsletter signup.
|
|
115
118
|
*/
|
|
@@ -1851,7 +1851,7 @@ function FooterNewsletterContact({
|
|
|
1851
1851
|
className: cn(className),
|
|
1852
1852
|
children: /* @__PURE__ */ jsxs("div", { className: "space-y-10", children: [
|
|
1853
1853
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-x-16 gap-y-8 md:grid-cols-2 xl:grid-cols-4", children: [
|
|
1854
|
-
(newsletterTitle || newsletterDescription || newsletterButtonText) && /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
1854
|
+
formConfig?.token && (newsletterTitle || newsletterDescription || newsletterButtonText) && /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
1855
1855
|
newsletterTitle && /* @__PURE__ */ jsx("h3", { className: "text-3xl font-medium font-serif leading-none", children: newsletterTitle }),
|
|
1856
1856
|
newsletterDescription && /* @__PURE__ */ jsx("p", { className: "font-light leading-normal", children: newsletterDescription }),
|
|
1857
1857
|
/* @__PURE__ */ jsxs(
|
|
@@ -1807,7 +1807,7 @@ function FooterNewsletterMinimal({
|
|
|
1807
1807
|
] })
|
|
1808
1808
|
] }),
|
|
1809
1809
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("mt-20 flex flex-col justify-between gap-15 lg:flex-row", newsletterSectionClassName), children: [
|
|
1810
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full max-w-md flex-col gap-10", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 text-sm font-light tracking-tight lg:text-base", children: [
|
|
1810
|
+
formConfig?.token && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full max-w-md flex-col gap-10", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 text-sm font-light tracking-tight lg:text-base", children: [
|
|
1811
1811
|
newsletterLabel && /* @__PURE__ */ jsxRuntime.jsx("p", { children: newsletterLabel }),
|
|
1812
1812
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1813
1813
|
forms.Form,
|
|
@@ -95,6 +95,7 @@ interface FooterNewsletterMinimalProps {
|
|
|
95
95
|
patternOpacity?: number;
|
|
96
96
|
/**
|
|
97
97
|
* Optional form submission configuration.
|
|
98
|
+
* Requires `token` to render the newsletter UI.
|
|
98
99
|
*
|
|
99
100
|
* **Universal Usage**: Works with ANY REST API endpoint. Simply provide an `endpoint` URL
|
|
100
101
|
* and the form will submit to it in JSON format.
|
|
@@ -116,7 +117,9 @@ interface FooterNewsletterMinimalProps {
|
|
|
116
117
|
*
|
|
117
118
|
* See `FORMS_INTEGRATION_GUIDE.md` for complete examples with Next.js, React, and more.
|
|
118
119
|
*/
|
|
119
|
-
formConfig?: PageSpeedFormConfig
|
|
120
|
+
formConfig?: PageSpeedFormConfig & {
|
|
121
|
+
token: string;
|
|
122
|
+
};
|
|
120
123
|
/**
|
|
121
124
|
* Optional custom submission handler for maximum flexibility.
|
|
122
125
|
*
|
|
@@ -95,6 +95,7 @@ interface FooterNewsletterMinimalProps {
|
|
|
95
95
|
patternOpacity?: number;
|
|
96
96
|
/**
|
|
97
97
|
* Optional form submission configuration.
|
|
98
|
+
* Requires `token` to render the newsletter UI.
|
|
98
99
|
*
|
|
99
100
|
* **Universal Usage**: Works with ANY REST API endpoint. Simply provide an `endpoint` URL
|
|
100
101
|
* and the form will submit to it in JSON format.
|
|
@@ -116,7 +117,9 @@ interface FooterNewsletterMinimalProps {
|
|
|
116
117
|
*
|
|
117
118
|
* See `FORMS_INTEGRATION_GUIDE.md` for complete examples with Next.js, React, and more.
|
|
118
119
|
*/
|
|
119
|
-
formConfig?: PageSpeedFormConfig
|
|
120
|
+
formConfig?: PageSpeedFormConfig & {
|
|
121
|
+
token: string;
|
|
122
|
+
};
|
|
120
123
|
/**
|
|
121
124
|
* Optional custom submission handler for maximum flexibility.
|
|
122
125
|
*
|