@opensite/ui 0.1.2 → 0.1.4

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.
Files changed (105) hide show
  1. package/dist/components.cjs +1511 -3
  2. package/dist/components.cjs.map +1 -1
  3. package/dist/components.d.cts +13 -0
  4. package/dist/components.d.ts +13 -0
  5. package/dist/components.js +1499 -4
  6. package/dist/components.js.map +1 -1
  7. package/dist/footer-animated-social.cjs +272 -0
  8. package/dist/footer-animated-social.cjs.map +1 -0
  9. package/dist/footer-animated-social.d.cts +41 -0
  10. package/dist/footer-animated-social.d.ts +41 -0
  11. package/dist/footer-animated-social.js +250 -0
  12. package/dist/footer-animated-social.js.map +1 -0
  13. package/dist/footer-background-card.cjs +149 -0
  14. package/dist/footer-background-card.cjs.map +1 -0
  15. package/dist/footer-background-card.d.cts +74 -0
  16. package/dist/footer-background-card.d.ts +74 -0
  17. package/dist/footer-background-card.js +147 -0
  18. package/dist/footer-background-card.js.map +1 -0
  19. package/dist/footer-brand-description.cjs +244 -0
  20. package/dist/footer-brand-description.cjs.map +1 -0
  21. package/dist/footer-brand-description.d.cts +65 -0
  22. package/dist/footer-brand-description.d.ts +65 -0
  23. package/dist/footer-brand-description.js +222 -0
  24. package/dist/footer-brand-description.js.map +1 -0
  25. package/dist/footer-contact-card.cjs +238 -0
  26. package/dist/footer-contact-card.cjs.map +1 -0
  27. package/dist/footer-contact-card.d.cts +65 -0
  28. package/dist/footer-contact-card.d.ts +65 -0
  29. package/dist/footer-contact-card.js +216 -0
  30. package/dist/footer-contact-card.js.map +1 -0
  31. package/dist/footer-cta-banner.cjs +282 -0
  32. package/dist/footer-cta-banner.cjs.map +1 -0
  33. package/dist/footer-cta-banner.d.cts +77 -0
  34. package/dist/footer-cta-banner.d.ts +77 -0
  35. package/dist/footer-cta-banner.js +260 -0
  36. package/dist/footer-cta-banner.js.map +1 -0
  37. package/dist/footer-cta-social.cjs +221 -0
  38. package/dist/footer-cta-social.cjs.map +1 -0
  39. package/dist/footer-cta-social.d.cts +45 -0
  40. package/dist/footer-cta-social.d.ts +45 -0
  41. package/dist/footer-cta-social.js +199 -0
  42. package/dist/footer-cta-social.js.map +1 -0
  43. package/dist/footer-links-grid.cjs +119 -0
  44. package/dist/footer-links-grid.cjs.map +1 -0
  45. package/dist/footer-links-grid.d.cts +54 -0
  46. package/dist/footer-links-grid.d.ts +54 -0
  47. package/dist/footer-links-grid.js +117 -0
  48. package/dist/footer-links-grid.js.map +1 -0
  49. package/dist/footer-nav-social.cjs +273 -0
  50. package/dist/footer-nav-social.cjs.map +1 -0
  51. package/dist/footer-nav-social.d.cts +72 -0
  52. package/dist/footer-nav-social.d.ts +72 -0
  53. package/dist/footer-nav-social.js +251 -0
  54. package/dist/footer-nav-social.js.map +1 -0
  55. package/dist/footer-newsletter-grid.cjs +271 -0
  56. package/dist/footer-newsletter-grid.cjs.map +1 -0
  57. package/dist/footer-newsletter-grid.d.cts +74 -0
  58. package/dist/footer-newsletter-grid.d.ts +74 -0
  59. package/dist/footer-newsletter-grid.js +249 -0
  60. package/dist/footer-newsletter-grid.js.map +1 -0
  61. package/dist/footer-newsletter-minimal.cjs +271 -0
  62. package/dist/footer-newsletter-minimal.cjs.map +1 -0
  63. package/dist/footer-newsletter-minimal.d.cts +57 -0
  64. package/dist/footer-newsletter-minimal.d.ts +57 -0
  65. package/dist/footer-newsletter-minimal.js +249 -0
  66. package/dist/footer-newsletter-minimal.js.map +1 -0
  67. package/dist/footer-simple-centered.cjs +101 -0
  68. package/dist/footer-simple-centered.cjs.map +1 -0
  69. package/dist/footer-simple-centered.d.cts +52 -0
  70. package/dist/footer-simple-centered.d.ts +52 -0
  71. package/dist/footer-simple-centered.js +99 -0
  72. package/dist/footer-simple-centered.js.map +1 -0
  73. package/dist/footer-social-apps.cjs +247 -0
  74. package/dist/footer-social-apps.cjs.map +1 -0
  75. package/dist/footer-social-apps.d.cts +75 -0
  76. package/dist/footer-social-apps.d.ts +75 -0
  77. package/dist/footer-social-apps.js +225 -0
  78. package/dist/footer-social-apps.js.map +1 -0
  79. package/dist/footer-social-newsletter.cjs +267 -0
  80. package/dist/footer-social-newsletter.cjs.map +1 -0
  81. package/dist/footer-social-newsletter.d.cts +68 -0
  82. package/dist/footer-social-newsletter.d.ts +68 -0
  83. package/dist/footer-social-newsletter.js +245 -0
  84. package/dist/footer-social-newsletter.js.map +1 -0
  85. package/dist/index.cjs +1511 -3
  86. package/dist/index.cjs.map +1 -1
  87. package/dist/index.d.cts +13 -0
  88. package/dist/index.d.ts +13 -0
  89. package/dist/index.js +1499 -4
  90. package/dist/index.js.map +1 -1
  91. package/dist/pressable.cjs +10 -3
  92. package/dist/pressable.cjs.map +1 -1
  93. package/dist/pressable.js +10 -3
  94. package/dist/pressable.js.map +1 -1
  95. package/dist/registry.cjs +1971 -1
  96. package/dist/registry.cjs.map +1 -1
  97. package/dist/registry.js +1971 -1
  98. package/dist/registry.js.map +1 -1
  99. package/dist/team-media-showcase.cjs +182 -0
  100. package/dist/team-media-showcase.cjs.map +1 -0
  101. package/dist/team-media-showcase.d.cts +145 -0
  102. package/dist/team-media-showcase.d.ts +145 -0
  103. package/dist/team-media-showcase.js +160 -0
  104. package/dist/team-media-showcase.js.map +1 -0
  105. package/package.json +71 -1
@@ -0,0 +1,99 @@
1
+ "use client";
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { Img } from '@page-speed/img';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ // lib/utils.ts
8
+ function cn(...inputs) {
9
+ return twMerge(clsx(inputs));
10
+ }
11
+ var defaultSitemap = [
12
+ {
13
+ title: "Company",
14
+ links: [
15
+ { title: "About Us", href: "#" },
16
+ { title: "Careers", href: "#" },
17
+ { title: "Contact", href: "#" },
18
+ { title: "Press", href: "#" }
19
+ ]
20
+ },
21
+ {
22
+ title: "Support",
23
+ links: [
24
+ { title: "Help Center", href: "#" },
25
+ { title: "Community", href: "#" },
26
+ { title: "Status", href: "#" },
27
+ { title: "API Docs", href: "#" }
28
+ ]
29
+ }
30
+ ];
31
+ var defaultBottomLinks = [
32
+ { text: "Terms & Conditions", href: "#" },
33
+ { text: "Privacy Policy", href: "#" }
34
+ ];
35
+ function FooterSimpleCentered({
36
+ logo = {
37
+ url: "https://opensite.ai",
38
+ src: "https://cdn.ing/assets/i/r/285975/eud79qeya11q5w6ueyhklueardyx/os-suircle-black-white.png",
39
+ alt: "Opensite AI",
40
+ title: "Opensite AI"
41
+ },
42
+ className,
43
+ tagline = "Components made easy.",
44
+ sitemap = defaultSitemap,
45
+ copyright = `\xA9 Opensite AI ${(/* @__PURE__ */ new Date()).getFullYear()}`,
46
+ bottomLinks = defaultBottomLinks,
47
+ optixFlowConfig
48
+ }) {
49
+ return /* @__PURE__ */ jsx("section", { className: cn("py-16", className), children: /* @__PURE__ */ jsx("div", { className: "container", children: /* @__PURE__ */ jsxs("footer", { children: [
50
+ /* @__PURE__ */ jsxs("div", { className: "relative mb-8 flex w-full flex-col gap-x-28 gap-y-8 md:flex-row md:justify-between md:gap-y-0", children: [
51
+ /* @__PURE__ */ jsxs("div", { className: "max-w-96", children: [
52
+ /* @__PURE__ */ jsxs("div", { className: "mb-6 flex items-center gap-3", children: [
53
+ /* @__PURE__ */ jsx("div", { className: "flex size-12 items-center justify-center rounded-lg border border-border bg-accent p-2", children: /* @__PURE__ */ jsx(
54
+ Img,
55
+ {
56
+ src: logo.src,
57
+ alt: logo.alt,
58
+ className: "size-12 h-full w-full object-contain object-center",
59
+ optixFlowConfig
60
+ }
61
+ ) }),
62
+ /* @__PURE__ */ jsx("h3", { className: "text-xl font-bold", children: logo.title })
63
+ ] }),
64
+ /* @__PURE__ */ jsx("p", { className: "text-base font-medium text-muted-foreground", children: tagline })
65
+ ] }),
66
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col items-start gap-x-20 gap-y-14 xl:flex-row", children: /* @__PURE__ */ jsx("div", { className: "inline-grid w-fit grid-cols-1 gap-x-20 gap-y-14 sm:grid-cols-2", children: sitemap.map((section) => /* @__PURE__ */ jsxs("div", { className: "h-fit w-min", children: [
67
+ /* @__PURE__ */ jsx("h4", { className: "mb-6 text-base font-semibold whitespace-nowrap", children: section.title }),
68
+ /* @__PURE__ */ jsx("ul", { className: "space-y-3 text-base font-medium text-muted-foreground", children: section.links.map((link) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
69
+ "a",
70
+ {
71
+ href: link.href,
72
+ className: "text-base whitespace-nowrap hover:text-accent-foreground",
73
+ children: link.title
74
+ }
75
+ ) }, link.title)) })
76
+ ] }, section.title)) }) })
77
+ ] }),
78
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-baseline justify-between gap-8 border-t border-border pt-8 md:flex-row md:gap-16", children: [
79
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 text-xs text-muted-foreground sm:flex-row sm:items-center sm:gap-4 sm:text-sm", children: [
80
+ /* @__PURE__ */ jsx("span", { children: copyright }),
81
+ /* @__PURE__ */ jsx(
82
+ "a",
83
+ {
84
+ href: "https://opensite.ai",
85
+ className: "hover:text-accent-foreground",
86
+ target: "_blank",
87
+ rel: "noopener noreferrer",
88
+ children: "AI Website and Automation Platform by Opensite"
89
+ }
90
+ )
91
+ ] }),
92
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col items-start gap-4 text-xs text-muted-foreground sm:text-sm md:flex-row lg:items-center", children: bottomLinks.map((link, idx) => /* @__PURE__ */ jsx("a", { href: link.href, className: "hover:text-accent-foreground", children: link.text }, idx)) })
93
+ ] })
94
+ ] }) }) });
95
+ }
96
+
97
+ export { FooterSimpleCentered };
98
+ //# sourceMappingURL=footer-simple-centered.js.map
99
+ //# sourceMappingURL=footer-simple-centered.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../lib/utils.ts","../components/blocks/footers/footer-simple-centered.tsx"],"names":[],"mappings":"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","file":"footer-simple-centered.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../../lib/utils\";\nimport { Img } from \"@page-speed/img\";\n\n/**\n * Sitemap section configuration\n */\nexport interface FooterSimpleCenteredSection {\n title: string;\n links: {\n title: string;\n href: string;\n }[];\n}\n\n/**\n * Props for the FooterSimpleCentered component\n */\nexport interface FooterSimpleCenteredProps {\n /** Logo configuration */\n logo?: {\n url: string;\n src: string;\n alt: string;\n title: string;\n };\n /** Additional CSS classes */\n className?: string;\n /** Tagline displayed below the logo */\n tagline?: string;\n /** Sitemap sections */\n sitemap?: FooterSimpleCenteredSection[];\n /** Copyright text */\n copyright?: string;\n /** Bottom links (terms, privacy, etc.) */\n bottomLinks?: {\n text: string;\n href: string;\n }[];\n /** Optional Optix Flow configuration for @page-speed/img */\n optixFlowConfig?: {\n apiKey: string;\n compression?: number;\n };\n}\n\nconst defaultSitemap: FooterSimpleCenteredSection[] = [\n {\n title: \"Company\",\n links: [\n { title: \"About Us\", href: \"#\" },\n { title: \"Careers\", href: \"#\" },\n { title: \"Contact\", href: \"#\" },\n { title: \"Press\", href: \"#\" },\n ],\n },\n {\n title: \"Support\",\n links: [\n { title: \"Help Center\", href: \"#\" },\n { title: \"Community\", href: \"#\" },\n { title: \"Status\", href: \"#\" },\n { title: \"API Docs\", href: \"#\" },\n ],\n },\n];\n\nconst defaultBottomLinks = [\n { text: \"Terms & Conditions\", href: \"#\" },\n { text: \"Privacy Policy\", href: \"#\" },\n];\n\n/**\n * FooterSimpleCentered - A clean, minimal footer with logo, sitemap, and legal links.\n *\n * Features a simple two-column sitemap layout with company branding and bottom legal links.\n * Ideal for corporate websites, landing pages, and products that prefer a clean,\n * uncluttered footer design without social media or newsletter elements.\n */\nexport function FooterSimpleCentered({\n logo = {\n url: \"https://opensite.ai\",\n src: \"https://cdn.ing/assets/i/r/285975/eud79qeya11q5w6ueyhklueardyx/os-suircle-black-white.png\",\n alt: \"Opensite AI\",\n title: \"Opensite AI\",\n },\n className,\n tagline = \"Components made easy.\",\n sitemap = defaultSitemap,\n copyright = `© Opensite AI ${new Date().getFullYear()}`,\n bottomLinks = defaultBottomLinks,\n optixFlowConfig,\n}: FooterSimpleCenteredProps): React.JSX.Element {\n return (\n <section className={cn(\"py-16\", className)}>\n <div className=\"container\">\n <footer>\n <div className=\"relative mb-8 flex w-full flex-col gap-x-28 gap-y-8 md:flex-row md:justify-between md:gap-y-0\">\n <div className=\"max-w-96\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex size-12 items-center justify-center rounded-lg border border-border bg-accent p-2\">\n <Img\n src={logo.src}\n alt={logo.alt}\n className=\"size-12 h-full w-full object-contain object-center\"\n optixFlowConfig={optixFlowConfig}\n />\n </div>\n <h3 className=\"text-xl font-bold\">{logo.title}</h3>\n </div>\n <p className=\"text-base font-medium text-muted-foreground\">\n {tagline}\n </p>\n </div>\n <div className=\"flex flex-col items-start gap-x-20 gap-y-14 xl:flex-row\">\n <div className=\"inline-grid w-fit grid-cols-1 gap-x-20 gap-y-14 sm:grid-cols-2\">\n {sitemap.map((section) => (\n <div key={section.title} className=\"h-fit w-min\">\n <h4 className=\"mb-6 text-base font-semibold whitespace-nowrap\">\n {section.title}\n </h4>\n <ul className=\"space-y-3 text-base font-medium text-muted-foreground\">\n {section.links.map((link) => (\n <li key={link.title}>\n <a\n href={link.href}\n className=\"text-base whitespace-nowrap hover:text-accent-foreground\"\n >\n {link.title}\n </a>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n </div>\n </div>\n <div className=\"flex flex-col items-baseline justify-between gap-8 border-t border-border pt-8 md:flex-row md:gap-16\">\n <div className=\"flex flex-col gap-2 text-xs text-muted-foreground sm:flex-row sm:items-center sm:gap-4 sm:text-sm\">\n <span>{copyright}</span>\n <a\n href=\"https://opensite.ai\"\n className=\"hover:text-accent-foreground\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n AI Website and Automation Platform by Opensite\n </a>\n </div>\n <div className=\"flex flex-col items-start gap-4 text-xs text-muted-foreground sm:text-sm md:flex-row lg:items-center\">\n {bottomLinks.map((link, idx) => (\n <a key={idx} href={link.href} className=\"hover:text-accent-foreground\">\n {link.text}\n </a>\n ))}\n </div>\n </div>\n </footer>\n </div>\n </section>\n );\n}\n"]}
@@ -0,0 +1,247 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var clsx = require('clsx');
5
+ var tailwindMerge = require('tailwind-merge');
6
+ var img = require('@page-speed/img');
7
+ var React = require('react');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+
10
+ function _interopNamespace(e) {
11
+ if (e && e.__esModule) return e;
12
+ var n = Object.create(null);
13
+ if (e) {
14
+ Object.keys(e).forEach(function (k) {
15
+ if (k !== 'default') {
16
+ var d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: function () { return e[k]; }
20
+ });
21
+ }
22
+ });
23
+ }
24
+ n.default = e;
25
+ return Object.freeze(n);
26
+ }
27
+
28
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
29
+
30
+ // lib/utils.ts
31
+ function cn(...inputs) {
32
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
33
+ }
34
+ var svgCache = /* @__PURE__ */ new Map();
35
+ function DynamicIcon({
36
+ name,
37
+ size = 28,
38
+ color,
39
+ className,
40
+ alt
41
+ }) {
42
+ const [svgContent, setSvgContent] = React__namespace.useState(null);
43
+ const [isLoading, setIsLoading] = React__namespace.useState(true);
44
+ const [error, setError] = React__namespace.useState(null);
45
+ const { url, iconName } = React__namespace.useMemo(() => {
46
+ const separator = name.includes("/") ? "/" : ":";
47
+ const [prefix, iconName2] = name.split(separator);
48
+ const baseUrl = `https://icons.opensite.ai/api/icon/${prefix}/${iconName2}?format=svg&width=${size}&height=${size}`;
49
+ return {
50
+ url: baseUrl,
51
+ iconName: iconName2
52
+ };
53
+ }, [name, size]);
54
+ React__namespace.useEffect(() => {
55
+ let isMounted = true;
56
+ const fetchSvg = async () => {
57
+ const cached = svgCache.get(url);
58
+ if (cached) {
59
+ if (isMounted) {
60
+ setSvgContent(cached);
61
+ setIsLoading(false);
62
+ }
63
+ return;
64
+ }
65
+ try {
66
+ setIsLoading(true);
67
+ setError(null);
68
+ const response = await fetch(url);
69
+ if (!response.ok) {
70
+ throw new Error(`Failed to fetch icon: ${response.status}`);
71
+ }
72
+ let svg = await response.text();
73
+ svg = processSvgForCurrentColor(svg);
74
+ svgCache.set(url, svg);
75
+ if (isMounted) {
76
+ setSvgContent(svg);
77
+ setIsLoading(false);
78
+ }
79
+ } catch (err) {
80
+ if (isMounted) {
81
+ setError(err instanceof Error ? err.message : "Failed to load icon");
82
+ setIsLoading(false);
83
+ }
84
+ }
85
+ };
86
+ fetchSvg();
87
+ return () => {
88
+ isMounted = false;
89
+ };
90
+ }, [url]);
91
+ if (isLoading) {
92
+ return /* @__PURE__ */ jsxRuntime.jsx(
93
+ "span",
94
+ {
95
+ className: cn("inline-block", className),
96
+ style: { width: size, height: size },
97
+ "aria-hidden": "true"
98
+ }
99
+ );
100
+ }
101
+ if (error || !svgContent) {
102
+ return /* @__PURE__ */ jsxRuntime.jsx(
103
+ "span",
104
+ {
105
+ className: cn("inline-block", className),
106
+ style: { width: size, height: size },
107
+ role: "img",
108
+ "aria-label": alt || iconName
109
+ }
110
+ );
111
+ }
112
+ return /* @__PURE__ */ jsxRuntime.jsx(
113
+ "span",
114
+ {
115
+ className: cn("inline-flex items-center justify-center", className),
116
+ style: {
117
+ width: size,
118
+ height: size,
119
+ color: color || "inherit"
120
+ },
121
+ role: "img",
122
+ "aria-label": alt || iconName,
123
+ dangerouslySetInnerHTML: { __html: svgContent }
124
+ }
125
+ );
126
+ }
127
+ function processSvgForCurrentColor(svg) {
128
+ let processed = svg;
129
+ processed = processed.replace(
130
+ /stroke=["'](#000000|#000|black)["']/gi,
131
+ 'stroke="currentColor"'
132
+ );
133
+ processed = processed.replace(
134
+ /fill=["'](#000000|#000|black)["']/gi,
135
+ 'fill="currentColor"'
136
+ );
137
+ return processed;
138
+ }
139
+ var defaultSections = [
140
+ {
141
+ title: "Product",
142
+ links: [
143
+ { name: "Overview", href: "#" },
144
+ { name: "Pricing", href: "#" },
145
+ { name: "Marketplace", href: "#" },
146
+ { name: "Features", href: "#" }
147
+ ]
148
+ },
149
+ {
150
+ title: "Company",
151
+ links: [
152
+ { name: "About", href: "#" },
153
+ { name: "Team", href: "#" },
154
+ { name: "Blog", href: "#" },
155
+ { name: "Careers", href: "#" }
156
+ ]
157
+ },
158
+ {
159
+ title: "Resources",
160
+ links: [
161
+ { name: "Help", href: "#" },
162
+ { name: "Sales", href: "#" },
163
+ { name: "Advertise", href: "#" }
164
+ ]
165
+ }
166
+ ];
167
+ var defaultSocialLinks = [
168
+ { icon: "simple-icons/discord", href: "#", label: "Discord" },
169
+ { icon: "simple-icons/x", href: "#", label: "X (Twitter)" },
170
+ { icon: "simple-icons/instagram", href: "#", label: "Instagram" },
171
+ { icon: "simple-icons/linkedin", href: "#", label: "LinkedIn" }
172
+ ];
173
+ var defaultAppLinks = [
174
+ { icon: "mdi/android", href: "#", label: "Android" },
175
+ { icon: "mdi/apple", href: "#", label: "iOS" }
176
+ ];
177
+ function FooterSocialApps({
178
+ logo = {
179
+ url: "https://opensite.ai",
180
+ src: "https://cdn.ing/assets/i/r/285975/eud79qeya11q5w6ueyhklueardyx/os-suircle-black-white.png",
181
+ alt: "Opensite AI",
182
+ title: "Opensite AI"
183
+ },
184
+ className,
185
+ sections = defaultSections,
186
+ socialLinks = defaultSocialLinks,
187
+ appLinks = defaultAppLinks,
188
+ socialLabel = "Follow Us",
189
+ appLabel = "Mobile App",
190
+ copyright = `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} Opensite AI. All rights reserved.`,
191
+ optixFlowConfig
192
+ }) {
193
+ return /* @__PURE__ */ jsxRuntime.jsx("section", { className: cn("py-32", className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "container", children: /* @__PURE__ */ jsxRuntime.jsxs("footer", { children: [
194
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-between gap-10 lg:flex-row lg:gap-20", children: [
195
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-6", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: logo.url, className: "flex items-center gap-2", children: [
196
+ /* @__PURE__ */ jsxRuntime.jsx(
197
+ img.Img,
198
+ {
199
+ src: logo.src,
200
+ alt: logo.alt,
201
+ className: "h-10",
202
+ optixFlowConfig
203
+ }
204
+ ),
205
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xl font-semibold", children: logo.title })
206
+ ] }) }),
207
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid flex-1 gap-8 sm:grid-cols-2 md:grid-cols-3", children: sections.map((section, sectionIdx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
208
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-4 font-bold", children: section.title }),
209
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-4 text-muted-foreground", children: section.links.map((link, linkIdx) => /* @__PURE__ */ jsxRuntime.jsx(
210
+ "li",
211
+ {
212
+ className: "font-medium hover:text-primary",
213
+ children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: link.href, children: link.name })
214
+ },
215
+ linkIdx
216
+ )) })
217
+ ] }, sectionIdx)) }),
218
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
219
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
220
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-3 font-bold", children: socialLabel }),
221
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex items-center gap-2 text-muted-foreground", children: socialLinks.map((social, idx) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "font-medium", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: social.href, "aria-label": social.label, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-12 items-center justify-center rounded-full bg-muted transition-colors hover:text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: social.icon, size: 24 }) }) }) }, idx)) })
222
+ ] }),
223
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
224
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-3 font-bold", children: appLabel }),
225
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex items-center gap-2 text-muted-foreground", children: appLinks.map((app, idx) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "font-medium", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: app.href, "aria-label": app.label, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-12 items-center justify-center rounded-full bg-muted transition-colors hover:text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: app.icon, size: 24 }) }) }) }, idx)) })
226
+ ] })
227
+ ] })
228
+ ] }),
229
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-24 border-t pt-8", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-between gap-4 text-center text-sm font-medium text-muted-foreground md:flex-row md:text-left", children: [
230
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: copyright }),
231
+ /* @__PURE__ */ jsxRuntime.jsx(
232
+ "a",
233
+ {
234
+ href: "https://opensite.ai",
235
+ className: "hover:text-primary",
236
+ target: "_blank",
237
+ rel: "noopener noreferrer",
238
+ children: "AI Website and Automation Platform by Opensite"
239
+ }
240
+ )
241
+ ] }) })
242
+ ] }) }) });
243
+ }
244
+
245
+ exports.FooterSocialApps = FooterSocialApps;
246
+ //# sourceMappingURL=footer-social-apps.cjs.map
247
+ //# sourceMappingURL=footer-social-apps.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../lib/utils.ts","../components/ui/dynamic-icon.tsx","../components/blocks/footers/footer-social-apps.tsx"],"names":["twMerge","clsx","React","iconName","jsx","jsxs","Img"],"mappings":"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","file":"footer-social-apps.cjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"../../lib/utils\";\n\ninterface DynamicIconProps {\n /**\n * Icon name in format: prefix/name or prefix:name\n * Examples: \"lucide/home\", \"mdi:account\", \"heroicons/check\"\n */\n name: string;\n /**\n * Icon size in pixels\n * @default 28\n */\n size?: number;\n /**\n * Icon color - accepts any valid CSS color\n * Note: When not specified, the icon inherits color from parent via CSS currentColor\n */\n color?: string;\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * Alt text for accessibility\n */\n alt?: string;\n}\n\n// Simple in-memory cache for fetched SVGs\nconst svgCache = new Map<string, string>();\n\n/**\n * Lightweight icon component that dynamically loads SVG icons from icons.opensite.ai API.\n *\n * Features:\n * - Pulls SVGs from https://icons.opensite.ai API and inlines them for CSS color inheritance\n * - Supports currentColor - icons inherit color from parent element\n * - Accepts prefix/name or prefix:name format\n * - Customizable size and explicit color via props\n * - In-memory caching to prevent duplicate fetches\n *\n * @example\n * ```tsx\n * // Icon inherits color from parent (recommended for hover states, etc.)\n * <span className=\"text-white hover:text-red-500\">\n * <DynamicIcon name=\"lucide/home\" size={24} />\n * </span>\n *\n * // Icon with explicit color\n * <DynamicIcon name=\"mdi:account\" size={32} color=\"#ff0000\" />\n * ```\n */\nexport function DynamicIcon({\n name,\n size = 28,\n color,\n className,\n alt,\n}: DynamicIconProps) {\n const [svgContent, setSvgContent] = React.useState<string | null>(null);\n const [isLoading, setIsLoading] = React.useState(true);\n const [error, setError] = React.useState<string | null>(null);\n\n const { url, iconName } = React.useMemo(() => {\n const separator = name.includes(\"/\") ? \"/\" : \":\";\n const [prefix, iconName] = name.split(separator);\n // Don't pass color to API - we'll handle it via CSS\n const baseUrl = `https://icons.opensite.ai/api/icon/${prefix}/${iconName}?format=svg&width=${size}&height=${size}`;\n\n return {\n url: baseUrl,\n iconName,\n };\n }, [name, size]);\n\n React.useEffect(() => {\n let isMounted = true;\n\n const fetchSvg = async () => {\n // Check cache first\n const cached = svgCache.get(url);\n if (cached) {\n if (isMounted) {\n setSvgContent(cached);\n setIsLoading(false);\n }\n return;\n }\n\n try {\n setIsLoading(true);\n setError(null);\n\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch icon: ${response.status}`);\n }\n\n let svg = await response.text();\n\n // Process SVG to ensure currentColor works:\n // 1. Replace any hardcoded colors with currentColor\n // 2. Ensure stroke/fill use currentColor where appropriate\n svg = processSvgForCurrentColor(svg);\n\n // Cache the processed SVG\n svgCache.set(url, svg);\n\n if (isMounted) {\n setSvgContent(svg);\n setIsLoading(false);\n }\n } catch (err) {\n if (isMounted) {\n setError(err instanceof Error ? err.message : \"Failed to load icon\");\n setIsLoading(false);\n }\n }\n };\n\n fetchSvg();\n\n return () => {\n isMounted = false;\n };\n }, [url]);\n\n // Loading state - show placeholder with same dimensions\n if (isLoading) {\n return (\n <span\n className={cn(\"inline-block\", className)}\n style={{ width: size, height: size }}\n aria-hidden=\"true\"\n />\n );\n }\n\n // Error state - show nothing or fallback\n if (error || !svgContent) {\n return (\n <span\n className={cn(\"inline-block\", className)}\n style={{ width: size, height: size }}\n role=\"img\"\n aria-label={alt || iconName}\n />\n );\n }\n\n // Render inline SVG\n // The color prop applies an explicit color, otherwise inherits from parent via currentColor\n return (\n <span\n className={cn(\"inline-flex items-center justify-center\", className)}\n style={{\n width: size,\n height: size,\n color: color || \"inherit\",\n }}\n role=\"img\"\n aria-label={alt || iconName}\n dangerouslySetInnerHTML={{ __html: svgContent }}\n />\n );\n}\n\n/**\n * Process SVG to ensure it uses currentColor for proper CSS inheritance.\n * This handles various icon libraries that may use different color approaches.\n */\nfunction processSvgForCurrentColor(svg: string): string {\n // Replace stroke=\"currentColor\" is already correct, but ensure fill also works\n // Some icons use fill=\"none\" with stroke, others use fill with no stroke\n\n // Ensure the SVG doesn't have hardcoded colors that should be currentColor\n // Common patterns to replace:\n // - stroke=\"#000\" or stroke=\"#000000\" or stroke=\"black\" -> stroke=\"currentColor\"\n // - fill=\"#000\" or fill=\"#000000\" or fill=\"black\" -> fill=\"currentColor\"\n\n let processed = svg;\n\n // Replace common black color values with currentColor for stroke\n processed = processed.replace(\n /stroke=[\"'](#000000|#000|black)[\"']/gi,\n 'stroke=\"currentColor\"'\n );\n\n // Replace common black color values with currentColor for fill\n // But be careful not to replace fill=\"none\"\n processed = processed.replace(\n /fill=[\"'](#000000|#000|black)[\"']/gi,\n 'fill=\"currentColor\"'\n );\n\n return processed;\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../../lib/utils\";\nimport { Img } from \"@page-speed/img\";\nimport { DynamicIcon } from \"../../ui/dynamic-icon\";\n\n/**\n * Social link configuration\n */\nexport interface FooterSocialAppsSocialLink {\n /** Icon name in format: prefix/name (e.g., \"simple-icons/twitter\") */\n icon: string;\n /** Link URL */\n href: string;\n /** Accessible label */\n label: string;\n}\n\n/**\n * App store link configuration\n */\nexport interface FooterSocialAppsAppLink {\n /** Icon name in format: prefix/name (e.g., \"simple-icons/android\") */\n icon: string;\n /** Link URL */\n href: string;\n /** Accessible label */\n label: string;\n}\n\n/**\n * Navigation section configuration\n */\nexport interface FooterSocialAppsSection {\n title: string;\n links: {\n name: string;\n href: string;\n }[];\n}\n\n/**\n * Props for the FooterSocialApps component\n */\nexport interface FooterSocialAppsProps {\n /** Logo configuration */\n logo?: {\n url: string;\n src: string;\n alt: string;\n title: string;\n };\n /** Additional CSS classes */\n className?: string;\n /** Navigation sections */\n sections?: FooterSocialAppsSection[];\n /** Social media links */\n socialLinks?: FooterSocialAppsSocialLink[];\n /** Mobile app store links */\n appLinks?: FooterSocialAppsAppLink[];\n /** Social section label */\n socialLabel?: string;\n /** Mobile app section label */\n appLabel?: string;\n /** Copyright text */\n copyright?: string;\n /** Optional Optix Flow configuration for @page-speed/img */\n optixFlowConfig?: {\n apiKey: string;\n compression?: number;\n };\n}\n\nconst defaultSections: FooterSocialAppsSection[] = [\n {\n title: \"Product\",\n links: [\n { name: \"Overview\", href: \"#\" },\n { name: \"Pricing\", href: \"#\" },\n { name: \"Marketplace\", href: \"#\" },\n { name: \"Features\", href: \"#\" },\n ],\n },\n {\n title: \"Company\",\n links: [\n { name: \"About\", href: \"#\" },\n { name: \"Team\", href: \"#\" },\n { name: \"Blog\", href: \"#\" },\n { name: \"Careers\", href: \"#\" },\n ],\n },\n {\n title: \"Resources\",\n links: [\n { name: \"Help\", href: \"#\" },\n { name: \"Sales\", href: \"#\" },\n { name: \"Advertise\", href: \"#\" },\n ],\n },\n];\n\nconst defaultSocialLinks: FooterSocialAppsSocialLink[] = [\n { icon: \"simple-icons/discord\", href: \"#\", label: \"Discord\" },\n { icon: \"simple-icons/x\", href: \"#\", label: \"X (Twitter)\" },\n { icon: \"simple-icons/instagram\", href: \"#\", label: \"Instagram\" },\n { icon: \"simple-icons/linkedin\", href: \"#\", label: \"LinkedIn\" },\n];\n\nconst defaultAppLinks: FooterSocialAppsAppLink[] = [\n { icon: \"mdi/android\", href: \"#\", label: \"Android\" },\n { icon: \"mdi/apple\", href: \"#\", label: \"iOS\" },\n];\n\n/**\n * FooterSocialApps - A footer with social icons, navigation links, and mobile app download links.\n *\n * Features prominent social media icons and mobile app store links in circular buttons,\n * along with multi-column navigation. Ideal for products with mobile apps, community-focused\n * platforms, and businesses that want to highlight their cross-platform presence.\n */\nexport function FooterSocialApps({\n logo = {\n url: \"https://opensite.ai\",\n src: \"https://cdn.ing/assets/i/r/285975/eud79qeya11q5w6ueyhklueardyx/os-suircle-black-white.png\",\n alt: \"Opensite AI\",\n title: \"Opensite AI\",\n },\n className,\n sections = defaultSections,\n socialLinks = defaultSocialLinks,\n appLinks = defaultAppLinks,\n socialLabel = \"Follow Us\",\n appLabel = \"Mobile App\",\n copyright = `© ${new Date().getFullYear()} Opensite AI. All rights reserved.`,\n optixFlowConfig,\n}: FooterSocialAppsProps): React.JSX.Element {\n return (\n <section className={cn(\"py-32\", className)}>\n <div className=\"container\">\n <footer>\n <div className=\"flex flex-col justify-between gap-10 lg:flex-row lg:gap-20\">\n <div className=\"flex flex-col gap-6\">\n <a href={logo.url} className=\"flex items-center gap-2\">\n <Img\n src={logo.src}\n alt={logo.alt}\n className=\"h-10\"\n optixFlowConfig={optixFlowConfig}\n />\n <span className=\"text-xl font-semibold\">{logo.title}</span>\n </a>\n </div>\n <div className=\"grid flex-1 gap-8 sm:grid-cols-2 md:grid-cols-3\">\n {sections.map((section, sectionIdx) => (\n <div key={sectionIdx}>\n <h3 className=\"mb-4 font-bold\">{section.title}</h3>\n <ul className=\"space-y-4 text-muted-foreground\">\n {section.links.map((link, linkIdx) => (\n <li\n key={linkIdx}\n className=\"font-medium hover:text-primary\"\n >\n <a href={link.href}>{link.name}</a>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n <div className=\"flex flex-col gap-6\">\n <div>\n <p className=\"mb-3 font-bold\">{socialLabel}</p>\n <ul className=\"flex items-center gap-2 text-muted-foreground\">\n {socialLinks.map((social, idx) => (\n <li key={idx} className=\"font-medium\">\n <a href={social.href} aria-label={social.label}>\n <span className=\"flex size-12 items-center justify-center rounded-full bg-muted transition-colors hover:text-primary\">\n <DynamicIcon name={social.icon} size={24} />\n </span>\n </a>\n </li>\n ))}\n </ul>\n </div>\n <div>\n <p className=\"mb-3 font-bold\">{appLabel}</p>\n <ul className=\"flex items-center gap-2 text-muted-foreground\">\n {appLinks.map((app, idx) => (\n <li key={idx} className=\"font-medium\">\n <a href={app.href} aria-label={app.label}>\n <span className=\"flex size-12 items-center justify-center rounded-full bg-muted transition-colors hover:text-primary\">\n <DynamicIcon name={app.icon} size={24} />\n </span>\n </a>\n </li>\n ))}\n </ul>\n </div>\n </div>\n </div>\n <div className=\"mt-24 border-t pt-8\">\n <div className=\"flex flex-col justify-between gap-4 text-center text-sm font-medium text-muted-foreground md:flex-row md:text-left\">\n <p>{copyright}</p>\n <a\n href=\"https://opensite.ai\"\n className=\"hover:text-primary\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n AI Website and Automation Platform by Opensite\n </a>\n </div>\n </div>\n </footer>\n </div>\n </section>\n );\n}\n"]}
@@ -0,0 +1,75 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * Social link configuration
5
+ */
6
+ interface FooterSocialAppsSocialLink {
7
+ /** Icon name in format: prefix/name (e.g., "simple-icons/twitter") */
8
+ icon: string;
9
+ /** Link URL */
10
+ href: string;
11
+ /** Accessible label */
12
+ label: string;
13
+ }
14
+ /**
15
+ * App store link configuration
16
+ */
17
+ interface FooterSocialAppsAppLink {
18
+ /** Icon name in format: prefix/name (e.g., "simple-icons/android") */
19
+ icon: string;
20
+ /** Link URL */
21
+ href: string;
22
+ /** Accessible label */
23
+ label: string;
24
+ }
25
+ /**
26
+ * Navigation section configuration
27
+ */
28
+ interface FooterSocialAppsSection {
29
+ title: string;
30
+ links: {
31
+ name: string;
32
+ href: string;
33
+ }[];
34
+ }
35
+ /**
36
+ * Props for the FooterSocialApps component
37
+ */
38
+ interface FooterSocialAppsProps {
39
+ /** Logo configuration */
40
+ logo?: {
41
+ url: string;
42
+ src: string;
43
+ alt: string;
44
+ title: string;
45
+ };
46
+ /** Additional CSS classes */
47
+ className?: string;
48
+ /** Navigation sections */
49
+ sections?: FooterSocialAppsSection[];
50
+ /** Social media links */
51
+ socialLinks?: FooterSocialAppsSocialLink[];
52
+ /** Mobile app store links */
53
+ appLinks?: FooterSocialAppsAppLink[];
54
+ /** Social section label */
55
+ socialLabel?: string;
56
+ /** Mobile app section label */
57
+ appLabel?: string;
58
+ /** Copyright text */
59
+ copyright?: string;
60
+ /** Optional Optix Flow configuration for @page-speed/img */
61
+ optixFlowConfig?: {
62
+ apiKey: string;
63
+ compression?: number;
64
+ };
65
+ }
66
+ /**
67
+ * FooterSocialApps - A footer with social icons, navigation links, and mobile app download links.
68
+ *
69
+ * Features prominent social media icons and mobile app store links in circular buttons,
70
+ * along with multi-column navigation. Ideal for products with mobile apps, community-focused
71
+ * platforms, and businesses that want to highlight their cross-platform presence.
72
+ */
73
+ declare function FooterSocialApps({ logo, className, sections, socialLinks, appLinks, socialLabel, appLabel, copyright, optixFlowConfig, }: FooterSocialAppsProps): React.JSX.Element;
74
+
75
+ export { FooterSocialApps, type FooterSocialAppsAppLink, type FooterSocialAppsProps, type FooterSocialAppsSection, type FooterSocialAppsSocialLink };
@@ -0,0 +1,75 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * Social link configuration
5
+ */
6
+ interface FooterSocialAppsSocialLink {
7
+ /** Icon name in format: prefix/name (e.g., "simple-icons/twitter") */
8
+ icon: string;
9
+ /** Link URL */
10
+ href: string;
11
+ /** Accessible label */
12
+ label: string;
13
+ }
14
+ /**
15
+ * App store link configuration
16
+ */
17
+ interface FooterSocialAppsAppLink {
18
+ /** Icon name in format: prefix/name (e.g., "simple-icons/android") */
19
+ icon: string;
20
+ /** Link URL */
21
+ href: string;
22
+ /** Accessible label */
23
+ label: string;
24
+ }
25
+ /**
26
+ * Navigation section configuration
27
+ */
28
+ interface FooterSocialAppsSection {
29
+ title: string;
30
+ links: {
31
+ name: string;
32
+ href: string;
33
+ }[];
34
+ }
35
+ /**
36
+ * Props for the FooterSocialApps component
37
+ */
38
+ interface FooterSocialAppsProps {
39
+ /** Logo configuration */
40
+ logo?: {
41
+ url: string;
42
+ src: string;
43
+ alt: string;
44
+ title: string;
45
+ };
46
+ /** Additional CSS classes */
47
+ className?: string;
48
+ /** Navigation sections */
49
+ sections?: FooterSocialAppsSection[];
50
+ /** Social media links */
51
+ socialLinks?: FooterSocialAppsSocialLink[];
52
+ /** Mobile app store links */
53
+ appLinks?: FooterSocialAppsAppLink[];
54
+ /** Social section label */
55
+ socialLabel?: string;
56
+ /** Mobile app section label */
57
+ appLabel?: string;
58
+ /** Copyright text */
59
+ copyright?: string;
60
+ /** Optional Optix Flow configuration for @page-speed/img */
61
+ optixFlowConfig?: {
62
+ apiKey: string;
63
+ compression?: number;
64
+ };
65
+ }
66
+ /**
67
+ * FooterSocialApps - A footer with social icons, navigation links, and mobile app download links.
68
+ *
69
+ * Features prominent social media icons and mobile app store links in circular buttons,
70
+ * along with multi-column navigation. Ideal for products with mobile apps, community-focused
71
+ * platforms, and businesses that want to highlight their cross-platform presence.
72
+ */
73
+ declare function FooterSocialApps({ logo, className, sections, socialLinks, appLinks, socialLabel, appLabel, copyright, optixFlowConfig, }: FooterSocialAppsProps): React.JSX.Element;
74
+
75
+ export { FooterSocialApps, type FooterSocialAppsAppLink, type FooterSocialAppsProps, type FooterSocialAppsSection, type FooterSocialAppsSocialLink };