@nextworks/blocks-sections 0.1.0-alpha.8 → 0.2.0-alpha.2

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 (65) hide show
  1. package/README.md +16 -11
  2. package/dist/components/Features.d.ts +4 -2
  3. package/dist/components/Features.d.ts.map +1 -1
  4. package/dist/components/Features.jsx +2 -2
  5. package/dist/components/HeroMotion.d.ts +4 -2
  6. package/dist/components/HeroMotion.d.ts.map +1 -1
  7. package/dist-types/components/About.d.ts +93 -0
  8. package/dist-types/components/About.d.ts.map +1 -0
  9. package/dist-types/components/CTA.d.ts +118 -0
  10. package/dist-types/components/CTA.d.ts.map +1 -0
  11. package/dist-types/components/Contact.d.ts +111 -0
  12. package/dist-types/components/Contact.d.ts.map +1 -0
  13. package/dist-types/components/FAQ.d.ts +89 -0
  14. package/dist-types/components/FAQ.d.ts.map +1 -0
  15. package/dist-types/components/Features.d.ts +113 -0
  16. package/dist-types/components/Features.d.ts.map +1 -0
  17. package/dist-types/components/Footer.d.ts +120 -0
  18. package/dist-types/components/Footer.d.ts.map +1 -0
  19. package/dist-types/components/HeroMotion.d.ts +109 -0
  20. package/dist-types/components/HeroMotion.d.ts.map +1 -0
  21. package/dist-types/components/HeroOverlay.d.ts +116 -0
  22. package/dist-types/components/HeroOverlay.d.ts.map +1 -0
  23. package/dist-types/components/HeroSplit.d.ts +98 -0
  24. package/dist-types/components/HeroSplit.d.ts.map +1 -0
  25. package/dist-types/components/Navbar.d.ts +112 -0
  26. package/dist-types/components/Navbar.d.ts.map +1 -0
  27. package/dist-types/components/Newsletter.d.ts +59 -0
  28. package/dist-types/components/Newsletter.d.ts.map +1 -0
  29. package/dist-types/components/PortfolioSimple.d.ts +137 -0
  30. package/dist-types/components/PortfolioSimple.d.ts.map +1 -0
  31. package/dist-types/components/Pricing.d.ts +96 -0
  32. package/dist-types/components/Pricing.d.ts.map +1 -0
  33. package/dist-types/components/ProcessTimeline.d.ts +121 -0
  34. package/dist-types/components/ProcessTimeline.d.ts.map +1 -0
  35. package/dist-types/components/ServicesGrid.d.ts +64 -0
  36. package/dist-types/components/ServicesGrid.d.ts.map +1 -0
  37. package/dist-types/components/Team.d.ts +115 -0
  38. package/dist-types/components/Team.d.ts.map +1 -0
  39. package/dist-types/components/Testimonials.d.ts +81 -0
  40. package/dist-types/components/Testimonials.d.ts.map +1 -0
  41. package/dist-types/components/TrustBadges.d.ts +80 -0
  42. package/dist-types/components/TrustBadges.d.ts.map +1 -0
  43. package/dist-types/components/index.d.ts +21 -0
  44. package/dist-types/components/index.d.ts.map +1 -0
  45. package/dist-types/index.d.ts +2 -0
  46. package/dist-types/index.d.ts.map +1 -0
  47. package/package.json +8 -6
  48. package/dist/components/About.js +0 -129
  49. package/dist/components/CTA.js +0 -58
  50. package/dist/components/Contact.js +0 -82
  51. package/dist/components/FAQ.js +0 -78
  52. package/dist/components/Features.js +0 -109
  53. package/dist/components/Footer.js +0 -101
  54. package/dist/components/HeroMotion.js +0 -55
  55. package/dist/components/HeroOverlay.js +0 -111
  56. package/dist/components/HeroSplit.js +0 -100
  57. package/dist/components/Navbar.js +0 -80
  58. package/dist/components/Newsletter.js +0 -34
  59. package/dist/components/PortfolioSimple.js +0 -180
  60. package/dist/components/Pricing.js +0 -91
  61. package/dist/components/ProcessTimeline.js +0 -88
  62. package/dist/components/ServicesGrid.js +0 -72
  63. package/dist/components/Team.js +0 -107
  64. package/dist/components/Testimonials.js +0 -46
  65. package/dist/components/TrustBadges.js +0 -46
@@ -1,78 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useMemo, useState } from "react";
4
- import { cn } from "@nextworks/blocks-core";
5
- import { ChevronDown, ChevronUp } from "lucide-react";
6
- // const defaultFaqData: FAQS[] = [
7
- // {
8
- // question: "What does IntelliOpAI do?",
9
- // answer: "Automates ops with real-time insights.",
10
- // },
11
- // {
12
- // question: "Do I need coding skills?",
13
- // answer: "No, it's designed for ease of use.",
14
- // },
15
- // ];
16
- const defaultFaqData = [
17
- {
18
- question: "What does IntelliOpAI do?",
19
- answer: "Automates ops with real-time insights.",
20
- },
21
- {
22
- question: "How secure is my data?",
23
- answer: "We use industry-standard encryption and strict access controls.",
24
- },
25
- {
26
- question: "Can I integrate with other tools?",
27
- answer: "Yes — supports APIs and popular integrations like Slack, GitHub, and Jira.",
28
- },
29
- {
30
- question: "How do I get support?",
31
- answer: "Contact our support team via in-app chat or the help center for assistance.",
32
- },
33
- ];
34
- /**
35
- * Expandable FAQ section with accessible toggles and optional icons.
36
- *
37
- * @remarks
38
- * - Supports multiple or single open item behavior via allowMultipleOpen.
39
- * - Uses button with aria-expanded and a region with aria-labelledby.
40
- * - Motion can be disabled via enableMotion for reduced animation.
41
- *
42
- * @example
43
- * <FAQ faqData={[{ question: 'What is X?', answer: 'Y' }]} />
44
- */
45
- export function FAQ({ faqSectionHeaderText = "Frequently Asked Questions", faqData = defaultFaqData, sectionId = "faq", className, allowMultipleOpen = true, defaultOpenIndices = [], openIcon, closedIcon, ariaLabel = "Frequently asked questions section", section = { className: "py-10 px-5 bg-muted text-foreground" }, container = { className: "mx-auto max-w-7xl" }, heading = {
46
- className: "mb-6 text-center text-2xl font-bold text-foreground",
47
- }, grid = { className: "grid grid-cols-1 gap-4 md:grid-cols-2 md:gap-6" }, item = { className: "mb-4" }, questionButton = {
48
- className: "shadow-md hover:shadow-lg border-[var(--btn-border)] focus-visible:ring-[var(--btn-ring)] bg-[var(--faq-btn-bg,var(--btn-bg))] text-[var(--faq-btn-fg,var(--btn-fg))] hover:bg-[var(--faq-btn-hover-bg,var(--btn-hover-bg))] hover:text-[var(--faq-btn-hover-fg,var(--btn-hover-fg))]",
49
- }, questionText = { className: "" }, chevronIcon = { className: "transition-transform duration-200" }, answer = {
50
- className: "bg-[var(--faq-answer-bg,var(--card-bg))] text-[var(--faq-answer-fg,var(--card-fg))] border-[var(--card-border)]",
51
- }, answerText = { className: "leading-relaxed" }, enableMotion = true, }) {
52
- const [openSet, setOpenSet] = useState(() => new Set(defaultOpenIndices));
53
- const idPrefix = useMemo(() => sectionId || "faq", [sectionId]);
54
- const onToggle = (idx) => {
55
- setOpenSet((prev) => {
56
- const next = new Set(prev);
57
- if (next.has(idx))
58
- next.delete(idx);
59
- else {
60
- if (!allowMultipleOpen)
61
- next.clear();
62
- next.add(idx);
63
- }
64
- return next;
65
- });
66
- };
67
- return (_jsx("section", { id: sectionId, className: cn(section.className, className), "aria-label": ariaLabel, children: _jsxs("div", { className: cn(container.className), children: [faqSectionHeaderText && (_jsx("h2", { className: cn(heading.className), children: faqSectionHeaderText })), _jsx("div", { className: cn(grid.className), children: faqData.map((faq, index) => {
68
- const transitionCls = enableMotion
69
- ? "transition-all duration-300 ease-in-out"
70
- : "transition-none";
71
- const isOpen = openSet.has(index);
72
- return (_jsxs("div", { className: cn("w-full", item.className), children: [_jsxs("button", { id: `${idPrefix}-trigger-${index}`, "aria-controls": `${idPrefix}-panel-${index}`, "aria-expanded": isOpen, onClick: () => onToggle(index), className: cn("flex w-full items-center justify-between rounded-md p-4 text-left focus:outline-none",
73
- // preset-first ring/border
74
- "border-[var(--btn-border)] focus-visible:ring-2 focus-visible:ring-[var(--btn-ring)] focus-visible:ring-offset-2", questionButton.className), children: [_jsx("span", { className: cn("flex-1 font-medium select-none", questionText.className), children: faq.question }), _jsx("span", { className: cn("ml-3 flex-shrink-0", chevronIcon.className), children: isOpen
75
- ? (openIcon !== null && openIcon !== void 0 ? openIcon : _jsx(ChevronUp, { className: "h-5 w-5" }))
76
- : (closedIcon !== null && closedIcon !== void 0 ? closedIcon : _jsx(ChevronDown, { className: "h-5 w-5" })) })] }), _jsx("div", { id: `${idPrefix}-panel-${index}`, role: "region", "aria-labelledby": `${idPrefix}-trigger-${index}`, className: cn("border-border overflow-hidden rounded-md border", isOpen ? "max-h-96 opacity-100" : "max-h-0 opacity-0", transitionCls, answer.className), children: _jsx("div", { className: cn("p-4", answerText.className), children: faq.answer }) })] }, `${idPrefix}-item-${index}`));
77
- }) })] }) }));
78
- }
@@ -1,109 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { motion } from "motion/react";
4
- import { cn } from "@nextworks/blocks-core";
5
- import { FeatureCard } from "@nextworks/blocks-core";
6
- const defaultFeaturesData = [
7
- {
8
- imageSrc: "/feature_1.png",
9
- imageAlt: "Advanced Analytics Dashboard",
10
- headingText: "Advanced Analytics",
11
- subheadingText: "Get deep insights into your business performance with our comprehensive analytics dashboard that tracks key metrics and provides actionable recommendations.",
12
- },
13
- {
14
- imageSrc: "/feature_2.png",
15
- imageAlt: "Real-time Collaboration Tools",
16
- headingText: "Real-time Collaboration",
17
- subheadingText: "Work seamlessly with your team using our real-time collaboration tools that keep everyone in sync and boost productivity across all projects.",
18
- },
19
- {
20
- imageSrc: "/feature_3.png",
21
- imageAlt: "Secure Data Management",
22
- headingText: "Secure Data Management",
23
- subheadingText: "Protect your sensitive information with enterprise-grade security features including encryption, access controls, and compliance monitoring.",
24
- },
25
- {
26
- imageSrc: "/feature_4.png",
27
- imageAlt: "Mobile-First Design",
28
- headingText: "Mobile-First Design",
29
- subheadingText: "Access your data and manage your workflow from anywhere with our responsive, mobile-optimized interface that works perfectly on all devices.",
30
- },
31
- ];
32
- /**
33
- * Responsive Features section that renders a heading, optional subheading,
34
- * and a grid of FeatureCard items with configurable entrance animations.
35
- *
36
- * @remarks
37
- * - Styling: slot-style className overrides are merged after defaults via cn().
38
- * - Motion: Controlled by enableMotion and motionConfig; animations are reduced
39
- * or disabled when users prefer reduced motion.
40
- * - Accessibility: Uses a semantic <section> with an aria-label.
41
- *
42
- * @example
43
- * <Features
44
- * sectionHeading="Key Features"
45
- * featuresData={[{ imageSrc: "/a.png", imageAlt: "", headingText: "Fast", subheadingText: "Blazing" }]}
46
- * />
47
- */
48
- export function Features({ id = "features", sectionHeading = "Key Features", sectionSubheading = "Discover what makes our platform unique and powerful", featuresData = defaultFeaturesData, className, section = { className: "py-16 md:py-20 lg:py-24 bg-background" }, container = { className: "max-w-7xl mx-auto px-4 md:px-6 lg:px-8" }, header = { className: "text-center mb-12 md:mb-16" }, heading = {
49
- className: "text-3xl md:text-4xl lg:text-5xl font-bold text-foreground mb-4",
50
- }, subheading = {
51
- className: "text-lg md:text-xl text-muted-foreground max-w-3xl mx-auto leading-relaxed",
52
- }, grid = {
53
- className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-4 gap-6 md:gap-8",
54
- }, cardWrapper = {
55
- className: "motion-reduce:transform-none motion-reduce:transition-none",
56
- }, card = {
57
- className: "h-full bg-card border border-border rounded-lg shadow-md transition-all duration-200 hover:-translate-y-1 hover:shadow-lg overflow-hidden motion-reduce:transition-none motion-reduce:transform-none",
58
- }, image = {
59
- className: "w-full h-48 md:h-56 object-cover transition-none hover:!scale-100 group-hover:!scale-100 [transform:none]",
60
- }, cardHeading = {
61
- className: "text-xl md:text-2xl font-semibold text-card-foreground mb-3 leading-tight",
62
- }, cardSubheading = {
63
- className: "text-sm md:text-base text-muted-foreground leading-relaxed",
64
- }, enableMotion = true, motionConfig = {
65
- initial: { opacity: 0, y: 12 },
66
- whileInView: { opacity: 1, y: 0 },
67
- viewport: { once: true, amount: 0.2 },
68
- transition: {
69
- type: "tween",
70
- stiffness: 0,
71
- damping: 50,
72
- mass: 1,
73
- delay: 0.15,
74
- },
75
- }, ariaLabel = "Features section", }) {
76
- return (_jsx("section", { id: id, className: cn(section.className, className), "aria-label": ariaLabel, children: _jsxs("div", { className: cn(container.className), children: [_jsxs("div", { className: cn(header.className), children: [_jsx("h2", { className: cn(heading.className), children: sectionHeading }), sectionSubheading && (_jsx("p", { className: cn(subheading.className), children: sectionSubheading }))] }), _jsx("div", { className: cn(grid.className), children: featuresData.map((feature, index) => {
77
- var _a, _b, _c;
78
- const mConfig = enableMotion
79
- ? motionConfig
80
- : {
81
- initial: { opacity: 1, y: 0 },
82
- whileInView: { opacity: 1, y: 0 },
83
- viewport: { once: true, amount: 0 },
84
- transition: {
85
- type: "tween",
86
- duration: 0,
87
- },
88
- };
89
- // Ensure we always spread a defined object into transition
90
- const baseTransition = ((_a = mConfig.transition) !== null && _a !== void 0 ? _a : {
91
- type: "tween",
92
- duration: 0,
93
- });
94
- const noMotionCard = "transition-none hover:!translate-y-0 hover:shadow-none motion-reduce:transition-none motion-reduce:transform-none";
95
- const noMotionImage = "transition-none hover:!scale-100 transform-none motion-reduce:transform-none group-hover:!scale-100";
96
- return (_jsx(motion.div, { initial: mConfig.initial, whileInView: mConfig.whileInView, viewport: mConfig.viewport, transition: Object.assign(Object.assign({}, baseTransition), {
97
- // Stagger based on index while preserving provided delay if any
98
- delay: ((_c = (_b = mConfig.transition) === null || _b === void 0 ? void 0 : _b.delay) !== null && _c !== void 0 ? _c : 0.15) +
99
- index * (enableMotion ? 0.06 : 0) }), className: cn(cardWrapper.className), children: _jsx(FeatureCard, { cardImageSrc: feature.imageSrc, cardImageAlt: feature.imageAlt, cardHeadingText: feature.headingText, cardSubheadingText: feature.subheadingText, card: {
100
- className: cn(card.className, !enableMotion && noMotionCard),
101
- }, image: {
102
- className: cn(image.className, !enableMotion && noMotionImage),
103
- },
104
- // image={{
105
- // className: cn(image.className),
106
- // }}
107
- heading: { className: cn(cardHeading.className) }, subheading: { className: cn(cardSubheading.className) }, className: cn("h-full") }) }, index));
108
- }) })] }) }));
109
- }
@@ -1,101 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import Link from "next/link";
4
- import { cn } from "@nextworks/blocks-core";
5
- import { Facebook, Twitter, Instagram, Linkedin } from "lucide-react";
6
- /**
7
- * Default navigation link groups with common footer sections
8
- */
9
- const defaultNavLinks = [
10
- {
11
- heading: "Product",
12
- links: [
13
- { name: "Features", href: "#features" },
14
- { name: "Pricing", href: "#pricing" },
15
- { name: "Documentation", href: "#documentation" },
16
- { name: "FAQ", href: "#faq" },
17
- ],
18
- },
19
- {
20
- heading: "Company",
21
- links: [
22
- { name: "About", href: "#about" },
23
- { name: "Careers", href: "#careers" },
24
- { name: "Blog", href: "#blog" },
25
- { name: "Contact", href: "#contact" },
26
- ],
27
- },
28
- {
29
- heading: "Resources",
30
- links: [
31
- { name: "Help Center", href: "#help" },
32
- { name: "Terms of Service", href: "#terms" },
33
- { name: "Privacy Policy", href: "#privacy" },
34
- { name: "Status", href: "#status" },
35
- ],
36
- },
37
- ];
38
- /**
39
- * Default social media links shown in the footer
40
- */
41
- const defaultSocialLinks = [
42
- {
43
- name: "Facebook",
44
- icon: Facebook,
45
- url: "https://facebook.com",
46
- external: true,
47
- },
48
- {
49
- name: "Twitter",
50
- icon: Twitter,
51
- url: "https://twitter.com",
52
- external: true,
53
- },
54
- {
55
- name: "Instagram",
56
- icon: Instagram,
57
- url: "https://instagram.com",
58
- external: true,
59
- },
60
- {
61
- name: "LinkedIn",
62
- icon: Linkedin,
63
- url: "https://linkedin.com",
64
- external: true,
65
- },
66
- ];
67
- /**
68
- * Site footer with brand, grouped navigation links, social icons, and copyright.
69
- *
70
- * @remarks
71
- * - Styling: slot-style className overrides are merged after defaults via cn().
72
- * - Accessibility: renders a semantic <footer> with aria-label and clear link
73
- * names; external links open in a new tab with rel security attributes.
74
- *
75
- * @example
76
- * <Footer footerBrandName="Acme" />
77
- */
78
- export function Footer({ id, footerBrandName = "Brand Name", brandNode, brandHref, footerNavLinks = defaultNavLinks, footerSocialLinks = defaultSocialLinks, className, section = {
79
- className: "w-full bg-muted text-foreground bg-[var(--footer-bg)] text-[var(--footer-fg)]",
80
- }, container = { className: "max-w-7xl mx-auto px-6" }, brand = { className: "text-lg font-bold font-poppins text-foreground" }, brandWrapper = {
81
- className: "flex flex-col items-center lg:items-start lg:pr-8",
82
- }, navSection = {
83
- className: "flex flex-col lg:flex-row items-start justify-center gap-8 lg:gap-12 pt-6.5 pb-8",
84
- }, navGroup = {
85
- className: "flex flex-col items-center lg:items-start text-center lg:text-left pt-1.5",
86
- }, navHeading = {
87
- className: "font-bold font-poppins text-foreground mb-3 text-sm uppercase tracking-wider text-[var(--footer-heading-fg)]",
88
- }, navLink = {
89
- className: "text-muted-foreground hover:text-primary transition-colors duration-200 text-sm mb-2 block font-inter text-[var(--footer-link-fg)] hover:text-[var(--footer-link-hover-fg)]",
90
- }, linksList = { className: "space-y-2" }, socialSection = { className: "flex items-center justify-center gap-4 py-4" }, socialLink = {
91
- className: "text-muted-foreground hover:text-primary transition-colors duration-200 p-2 rounded-md hover:bg-accent text-[var(--footer-link-fg)] hover:text-[var(--footer-link-hover-fg)] hover:bg-[var(--footer-link-hover-bg)]",
92
- }, socialIcon = { className: "h-5 w-5" }, copyright = {
93
- className: "text-center text-xs text-muted-foreground py-4 border-t border-border font-inter text-[var(--footer-muted-fg)] border-[var(--footer-border)]",
94
- }, copyrightYear, copyrightOverride, ariaLabel = "Footer section", }) {
95
- const year = copyrightYear !== null && copyrightYear !== void 0 ? copyrightYear : new Date().getFullYear();
96
- return (_jsx("footer", { id: id, className: cn("w-full", section.className, className), "aria-label": ariaLabel, children: _jsxs("div", { className: cn(container.className), children: [_jsxs("div", { className: cn(navSection.className), children: [_jsxs("div", { className: cn(brandWrapper.className), children: [brandNode, footerBrandName &&
97
- (brandHref ? (_jsx(Link, { href: brandHref, className: cn(brand.className), "aria-label": footerBrandName, children: footerBrandName })) : (_jsx("h3", { className: cn(brand.className), children: footerBrandName })))] }), footerNavLinks.map((group) => (_jsxs("div", { className: cn(navGroup.className), children: [_jsx("h3", { className: cn(navHeading.className), children: group.heading }), _jsx("div", { className: cn(linksList.className), children: group.links.map((link) => (_jsx(Link, { href: link.href, target: link.external ? "_blank" : undefined, rel: link.external ? "noopener noreferrer" : undefined, className: cn(navLink.className), children: link.name }, link.name))) })] }, group.heading)))] }), _jsx("div", { className: cn(socialSection.className), children: footerSocialLinks.map((social) => {
98
- const IconComponent = social.icon;
99
- return (_jsx(Link, { href: social.url, target: social.external ? "_blank" : undefined, rel: social.external ? "noopener noreferrer" : undefined, "aria-label": social.label || social.name, className: cn(socialLink.className), children: _jsx(IconComponent, { className: cn(socialIcon.className) }) }, social.name));
100
- }) }), _jsx("div", { className: cn(copyright.className), children: copyrightOverride !== null && copyrightOverride !== void 0 ? copyrightOverride : (_jsxs(_Fragment, { children: ["\u00A9 ", year, " ", footerBrandName, ". All rights reserved."] })) })] }) }));
101
- }
@@ -1,55 +0,0 @@
1
- "use client";
2
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import Link from "next/link";
4
- import { motion } from "motion/react";
5
- import { Button } from "@nextworks/blocks-core";
6
- import { cn } from "@nextworks/blocks-core";
7
- const defaultChildTransition = {
8
- type: "tween",
9
- duration: 0.5,
10
- ease: [0.22, 1, 0.36, 1], // smooth easeOut
11
- };
12
- /**
13
- * Motion-first hero with heading/highlight, optional description and CTAs.
14
- *
15
- * @remarks
16
- * - Styling: slot-style className overrides are merged after defaults via cn().
17
- * - Motion: enableMotion toggles entrance transitions; motionOptions controls
18
- * delays and viewport.
19
- * - Accessibility: semantic <section> with aria-label.
20
- *
21
- * @example
22
- * <HeroMotion
23
- * heading="Supercharge growth with"
24
- * highlight="AI-powered insights"
25
- * primaryCta={{ label: 'Get Started', href: '#contact' }}
26
- * />
27
- */
28
- export function HeroMotion({ id, ariaLabel = "Hero section", className, heading = "Supercharge growth with", headingNode, highlight = "AI-powered insights", description = (_jsx(_Fragment, { children: "Real-time trends, accurate user signals, and smarter, data-driven decisions." })), primaryCta = { label: "Get Started" }, secondaryCta = { label: "See Demo" }, section = { className: "bg-background relative overflow-hidden" }, container = { className: "mx-auto max-w-7xl px-6 py-24 sm:py-28 lg:py-32" }, content = { className: "mx-auto max-w-3xl text-center" }, headingText = {
29
- className: "transform-gpu will-change-transform text-foreground text-4xl font-semibold tracking-tight text-balance sm:text-5xl md:text-6xl",
30
- }, highlightText = {
31
- className: "from-primary via-primary/80 to-primary/60 bg-gradient-to-r bg-clip-text text-transparent",
32
- }, descriptionText = {
33
- className: "transform-gpu will-change-transform text-muted-foreground mt-5 text-base text-pretty sm:text-lg",
34
- }, actions = { className: "mt-8 flex items-center justify-center gap-3" }, primaryButtonStyle = { size: "lg", variant: "default", className: "" }, secondaryButtonStyle = { size: "lg", variant: "outline", className: "" }, enableMotion = true, motionOptions = {
35
- viewport: { once: true, amount: 0.25 },
36
- headingDelay: 0.5,
37
- descriptionDelay: 0.58,
38
- actionsDelay: 0.66,
39
- transition: defaultChildTransition,
40
- }, backgroundNode, }) {
41
- var _a, _b, _c, _d, _e, _f, _g, _h;
42
- const viewport = enableMotion
43
- ? {
44
- once: (_b = (_a = motionOptions === null || motionOptions === void 0 ? void 0 : motionOptions.viewport) === null || _a === void 0 ? void 0 : _a.once) !== null && _b !== void 0 ? _b : true,
45
- amount: (_d = (_c = motionOptions === null || motionOptions === void 0 ? void 0 : motionOptions.viewport) === null || _c === void 0 ? void 0 : _c.amount) !== null && _d !== void 0 ? _d : 0.25,
46
- }
47
- : { once: true, amount: 0 };
48
- const transition = Object.assign(Object.assign({}, defaultChildTransition), ((_e = motionOptions === null || motionOptions === void 0 ? void 0 : motionOptions.transition) !== null && _e !== void 0 ? _e : {}));
49
- return (_jsxs("section", { id: id, "aria-label": ariaLabel, className: cn(section.className, className), children: [backgroundNode, _jsx("div", { className: cn(container.className), children: _jsxs(motion.div, { className: cn(content.className), children: [_jsx(motion.h1, { initial: enableMotion ? { opacity: 0, y: 12 } : { opacity: 1, y: 0 }, whileInView: { opacity: 1, y: 0 }, viewport: viewport, transition: enableMotion
50
- ? Object.assign(Object.assign({}, transition), { delay: (_f = motionOptions === null || motionOptions === void 0 ? void 0 : motionOptions.headingDelay) !== null && _f !== void 0 ? _f : 0.5 }) : { type: "tween", duration: 0 }, className: cn(headingText.className), children: headingNode ? (headingNode) : (_jsxs(_Fragment, { children: [heading, highlight ? (_jsxs("span", { className: cn(highlightText.className), children: [" ", highlight] })) : null] })) }), description ? (_jsx(motion.p, { initial: enableMotion ? { opacity: 0, y: 10 } : { opacity: 1, y: 0 }, whileInView: { opacity: 1, y: 0 }, viewport: viewport, transition: enableMotion
51
- ? Object.assign(Object.assign({}, transition), { delay: (_g = motionOptions === null || motionOptions === void 0 ? void 0 : motionOptions.descriptionDelay) !== null && _g !== void 0 ? _g : 0.58 }) : { type: "tween", duration: 0 }, className: cn(descriptionText.className), children: description })) : null, (primaryCta || secondaryCta) && (_jsxs(motion.div, { initial: enableMotion ? { opacity: 0, y: 10 } : { opacity: 1, y: 0 }, whileInView: { opacity: 1, y: 0 }, viewport: viewport, transition: enableMotion
52
- ? Object.assign(Object.assign({}, transition), { delay: (_h = motionOptions === null || motionOptions === void 0 ? void 0 : motionOptions.actionsDelay) !== null && _h !== void 0 ? _h : 0.66 }) : { type: "tween", duration: 0 }, className: cn(actions.className), children: [primaryCta &&
53
- (primaryCta.href ? (_jsx(Button, { asChild: true, unstyled: primaryButtonStyle.unstyled, variant: primaryButtonStyle.variant, size: primaryButtonStyle.size, className: cn(primaryButtonStyle.className), style: primaryButtonStyle.style, children: _jsx(Link, { href: primaryCta.href, "aria-label": primaryCta.label, children: primaryCta.label }) })) : (_jsx(Button, { variant: primaryButtonStyle.variant, size: primaryButtonStyle.size, className: cn(primaryButtonStyle.className), unstyled: primaryButtonStyle.unstyled, style: primaryButtonStyle.style, "aria-label": primaryCta.label, children: primaryCta.label }))), secondaryCta &&
54
- (secondaryCta.href ? (_jsx(Button, { asChild: true, unstyled: secondaryButtonStyle.unstyled, variant: secondaryButtonStyle.variant, size: secondaryButtonStyle.size, className: cn(secondaryButtonStyle.className), style: secondaryButtonStyle.style, children: _jsx(Link, { href: secondaryCta.href, "aria-label": secondaryCta.label, children: secondaryCta.label }) })) : (_jsx(Button, { variant: secondaryButtonStyle.variant, size: secondaryButtonStyle.size, className: cn(secondaryButtonStyle.className), unstyled: secondaryButtonStyle.unstyled, style: secondaryButtonStyle.style, "aria-label": secondaryCta.label, children: secondaryCta.label })))] }))] }) })] }));
55
- }
@@ -1,111 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import Image from "next/image";
4
- import Link from "next/link";
5
- import { Button } from "@nextworks/blocks-core";
6
- import { cn } from "@nextworks/blocks-core";
7
- /**
8
- * Full-bleed image hero with color overlay, heading/subheading, and up to two CTAs.
9
- *
10
- * @remarks
11
- * - Styling: slot-style overrides for container, imageContainer, overlay, content, textContainer.
12
- * - Motion: enableMotion applies hover-lift transitions to CTA buttons only.
13
- * - Accessibility: uses semantic <section> with aria-label; background image is
14
- * decorative with overlay and text content provided separately.
15
- *
16
- * @example
17
- * <HeroOverlay
18
- * image={{ src: "/hero.png", alt: "" }}
19
- * heading="Welcome"
20
- * subheading="Build faster with our blocks"
21
- * cta1={{ label: "Get Started", href: "#getstarted" }}
22
- * />
23
- */
24
- export function HeroOverlay({ id, className,
25
- // Deprecated flat image defaults (still supported)
26
- imageSrc = "/hero.png", imageAlt = "Hero background image", imageObjectFit = "cover", imageObjectPosition = "center",
27
- // New structured image (optional)
28
- image,
29
- // Keep string defaults; object form supported
30
- heading = "Lorem ipsum dolor sit amet, consectetur", subheading = "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.", overlayRGBA = "rgba(255, 255, 255, 0.8)", overlayDarkRGBA = "rgba(0, 0, 0, 0.8)",
31
- // Deprecated CTA label/href (still supported)
32
- ctaBtn1Label = "Get Started", ctaBtn1Href = "#getstarted", ctaBtn2Label, ctaBtn2Href,
33
- // Layout containers
34
- container = { className: "relative h-[440px] md:h-[500px] w-full" },
35
- // container = { className: "relative h-[500px] md:h-[600px] w-full" },
36
- section, imageContainer = { className: "absolute inset-0" }, overlay = { className: "absolute inset-0 z-10 pointer-events-none" }, content = {
37
- className: "relative z-20 h-full w-full flex flex-col justify-start items-center pt-14 pb-8 px-8",
38
- }, textContainer = { className: "max-w-4xl space-y-6 text-center" },
39
- // Typography defaults (deprecated props still merged)
40
- headingStyle = { className: "" }, subheadingStyle = { className: "" },
41
- // CTA containers and variants
42
- ctaContainer = {
43
- className: "flex flex-col sm:flex-row gap-4 mt-6 justify-center items-center",
44
- }, cta1, cta2, ariaLabel = "Hero section", enableMotion = true, }) {
45
- var _a, _b, _c, _d, _e, _f;
46
- // Merge new structured image with deprecated flat props
47
- const effImage = {
48
- src: (_a = image === null || image === void 0 ? void 0 : image.src) !== null && _a !== void 0 ? _a : imageSrc,
49
- alt: (_b = image === null || image === void 0 ? void 0 : image.alt) !== null && _b !== void 0 ? _b : imageAlt,
50
- objectFit: (_c = image === null || image === void 0 ? void 0 : image.objectFit) !== null && _c !== void 0 ? _c : imageObjectFit,
51
- objectPosition: (_d = image === null || image === void 0 ? void 0 : image.objectPosition) !== null && _d !== void 0 ? _d : imageObjectPosition,
52
- className: image === null || image === void 0 ? void 0 : image.className,
53
- };
54
- // Defaults and normalization like HeroSplit
55
- const defaultHeading = {
56
- text: "Lorem ipsum dolor sit amet, consectetur",
57
- className: "text-4xl md:text-5xl font-bold text-center leading-tight text-foreground",
58
- };
59
- const defaultSubheading = {
60
- text: "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
61
- className: "text-xl md:text-2xl text-center text-foreground leading-relaxed",
62
- };
63
- const normalizedHeading = typeof heading === "string"
64
- ? {
65
- text: heading,
66
- className: cn(defaultHeading.className, headingStyle === null || headingStyle === void 0 ? void 0 : headingStyle.className),
67
- }
68
- : {
69
- text: (_e = heading === null || heading === void 0 ? void 0 : heading.text) !== null && _e !== void 0 ? _e : defaultHeading.text,
70
- className: cn(defaultHeading.className, headingStyle === null || headingStyle === void 0 ? void 0 : headingStyle.className, heading === null || heading === void 0 ? void 0 : heading.className),
71
- };
72
- const normalizedSubheading = typeof subheading === "string"
73
- ? {
74
- text: subheading,
75
- className: cn(defaultSubheading.className, subheadingStyle === null || subheadingStyle === void 0 ? void 0 : subheadingStyle.className),
76
- }
77
- : {
78
- text: (_f = subheading === null || subheading === void 0 ? void 0 : subheading.text) !== null && _f !== void 0 ? _f : defaultSubheading.text,
79
- className: cn(defaultSubheading.className, subheadingStyle === null || subheadingStyle === void 0 ? void 0 : subheadingStyle.className, subheading === null || subheading === void 0 ? void 0 : subheading.className),
80
- };
81
- // Motion class for CTA buttons
82
- const buttonLift = enableMotion
83
- ? "transition-all duration-200 hover:-translate-y-0.5"
84
- : "transition-none hover:!translate-y-0";
85
- // CTA defaults and normalization (merge, don't replace).
86
- const defaultCta1 = {
87
- label: ctaBtn1Label,
88
- href: ctaBtn1Href,
89
- variant: "default",
90
- size: "lg",
91
- className: "",
92
- };
93
- const defaultCta2 = {
94
- label: ctaBtn2Label,
95
- href: ctaBtn2Href,
96
- variant: "outline",
97
- size: "lg",
98
- className: "",
99
- };
100
- const mergedCta1 = Object.assign(Object.assign(Object.assign({}, defaultCta1), (cta1 !== null && cta1 !== void 0 ? cta1 : {})), { className: cn(defaultCta1.className, cta1 === null || cta1 === void 0 ? void 0 : cta1.className, buttonLift) });
101
- const mergedCta2 = cta2 || ctaBtn2Label || ctaBtn2Href
102
- ? Object.assign(Object.assign(Object.assign({}, defaultCta2), (cta2 !== null && cta2 !== void 0 ? cta2 : {})), { className: cn(defaultCta2.className, cta2 === null || cta2 === void 0 ? void 0 : cta2.className, buttonLift) }) : undefined;
103
- // buttonLift defined above
104
- // Merge alias section.className with container.className
105
- const finalContainerClass = cn(container.className, section === null || section === void 0 ? void 0 : section.className);
106
- const showCta2 = !!(mergedCta2 === null || mergedCta2 === void 0 ? void 0 : mergedCta2.label);
107
- return (_jsxs("section", { id: id, className: cn(finalContainerClass, className), "aria-label": ariaLabel, children: [_jsx("div", { className: imageContainer.className, children: _jsx(Image, { src: effImage.src, alt: effImage.alt, fill: true, sizes: "100vw", quality: 75, priority: true, className: effImage.className, style: {
108
- objectFit: effImage.objectFit,
109
- objectPosition: effImage.objectPosition,
110
- } }) }), _jsx("div", { className: overlay.className, style: { backgroundColor: overlayRGBA }, "aria-hidden": true }), _jsx("div", { className: cn(overlay.className, "hidden dark:block"), style: { backgroundColor: overlayDarkRGBA }, "aria-hidden": true }), _jsx("div", { className: content.className, children: _jsxs("div", { className: textContainer.className, children: [_jsx("h1", { className: normalizedHeading.className, children: normalizedHeading.text }), _jsx("p", { className: normalizedSubheading.className, children: normalizedSubheading.text }), _jsxs("div", { className: ctaContainer.className, children: [mergedCta1.label && (_jsx(Button, { asChild: true, variant: mergedCta1.variant, size: mergedCta1.size, className: mergedCta1.className, unstyled: mergedCta1.unstyled, style: mergedCta1.style, children: _jsx(Link, { href: mergedCta1.href || "#", "aria-label": mergedCta1.label, children: mergedCta1.label }) })), showCta2 && (_jsx(Button, { asChild: true, variant: mergedCta2.variant, size: mergedCta2.size, className: mergedCta2.className, unstyled: mergedCta2.unstyled, style: mergedCta2.style, children: _jsx(Link, { href: mergedCta2.href || "#", "aria-label": mergedCta2.label, children: mergedCta2.label }) }))] })] }) })] }));
111
- }
@@ -1,100 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import Image from "next/image";
4
- import Link from "next/link";
5
- import { Button } from "@nextworks/blocks-core";
6
- import { cn } from "@nextworks/blocks-core";
7
- /**
8
- * Split hero with text on one side and an image on the other.
9
- *
10
- * @remarks
11
- * - Text props accept string or object forms to easily override classes.
12
- * - Full-bleed layout absolutely positions the image on larger screens.
13
- * - Motion only affects the subtle hover lift on CTA buttons.
14
- *
15
- * @example
16
- * <HeroSplit heading="Build faster" subheading="Launch confidently" />
17
- */
18
- export function HeroSplit({ id, className, heading, subheading, section, cta1, cta2, image = {
19
- src: "/placeholders/gallery/hero-pexels-broken-9945014.avif",
20
- alt: "Hero image",
21
- className: "object-contain",
22
- }, imageContainer, textContainer = { className: "flex-1 p-5" }, buttonsContainer = { className: "flex flex-col md:flex-row gap-4 mt-6" }, textAlign = "center", fallback, ariaLabel = "Hero section", enableMotion = true, imageLayout = "full-bleed", }) {
23
- var _a, _b;
24
- const lgTextAlignClasses = {
25
- left: "lg:text-left",
26
- right: "lg:text-right",
27
- center: "lg:text-center",
28
- };
29
- const lgItemsAlignClasses = {
30
- left: "lg:items-start",
31
- right: "lg:items-end",
32
- center: "lg:items-center",
33
- };
34
- const lgJustifyAlignClasses = {
35
- left: "lg:justify-start",
36
- right: "lg:justify-end",
37
- center: "lg:justify-center",
38
- };
39
- const buttonLift = enableMotion
40
- ? "transition-all duration-200 hover:-translate-y-0.5"
41
- : "transition-none hover:!translate-y-0";
42
- // Defaults for text props (normalized below)
43
- const defaultHeading = {
44
- text: "Lorem ipsum dolor sit amet",
45
- className: "text-3xl md:text-4xl font-bold leading-tight text-foreground",
46
- };
47
- const defaultSubheading = {
48
- text: "Consectetur adipiscing elit, sed do eiusmod tempor.",
49
- className: "text-lg md:text-xl text-foreground mt-4 mb-6",
50
- };
51
- const normalizedHeading = typeof heading === "string"
52
- ? { text: heading, className: defaultHeading.className }
53
- : {
54
- text: (_a = heading === null || heading === void 0 ? void 0 : heading.text) !== null && _a !== void 0 ? _a : defaultHeading.text,
55
- className: cn(defaultHeading.className, heading === null || heading === void 0 ? void 0 : heading.className),
56
- };
57
- const normalizedSubheading = typeof subheading === "string"
58
- ? { text: subheading, className: defaultSubheading.className }
59
- : {
60
- text: (_b = subheading === null || subheading === void 0 ? void 0 : subheading.text) !== null && _b !== void 0 ? _b : defaultSubheading.text,
61
- className: cn(defaultSubheading.className, subheading === null || subheading === void 0 ? void 0 : subheading.className),
62
- };
63
- // CTA defaults and normalization (merge, don't replace)
64
- const defaultCta1 = {
65
- label: "Get Started",
66
- href: "#contact",
67
- variant: "default",
68
- size: "default",
69
- className: "shadow-lg hover:shadow-xl transition-all duration-200 hover:-translate-y-0.5",
70
- };
71
- const mergedCta1 = Object.assign(Object.assign(Object.assign({}, defaultCta1), (cta1 !== null && cta1 !== void 0 ? cta1 : {})), { className: cn(defaultCta1.className, cta1 === null || cta1 === void 0 ? void 0 : cta1.className, buttonLift) });
72
- const defaultCta2 = {
73
- label: "Learn More",
74
- href: "#",
75
- variant: "outline",
76
- size: "default",
77
- className: "",
78
- };
79
- const mergedCta2 = cta2
80
- ? Object.assign(Object.assign(Object.assign({}, defaultCta2), cta2), { className: cn(defaultCta2.className, cta2.className, buttonLift) }) : undefined;
81
- const defaultSectionPadded = cn("px-8 pt-8 pb-8 md:min-h-[60vh] lg:min-h-[70vh]");
82
- const defaultSectionFull = cn("relative overflow-hidden pt-0 pb-0 md:min-h-[60vh] lg:min-h-[70vh]");
83
- const defaultImageContainerPadded = cn("relative mb-4 h-48 min-h-[12rem] w-full md:mb-0 md:h-72 md:w-1/2");
84
- // For full-bleed: absolute positioning on large screens to break out completely
85
- const defaultImageContainerFull = cn("relative h-48 w-full md:absolute md:inset-y-0 md:right-0 md:h-full md:w-1/2");
86
- const baseSectionClass = imageLayout === "full-bleed" ? defaultSectionFull : defaultSectionPadded;
87
- const finalSectionClass = cn(baseSectionClass, section === null || section === void 0 ? void 0 : section.className);
88
- const baseImageContainerClass = imageLayout === "full-bleed"
89
- ? defaultImageContainerFull
90
- : defaultImageContainerPadded;
91
- const finalImageContainerClass = cn(baseImageContainerClass, imageContainer === null || imageContainer === void 0 ? void 0 : imageContainer.className);
92
- // -- This overrides the image.className that is passed from importing components ... devs should be able to decide on cover/contain from the importing component.
93
- const finalImageClass = cn(image === null || image === void 0 ? void 0 : image.className, imageLayout === "full-bleed"
94
- ? "object-cover object-center md:object-right"
95
- : "object-contain object-center");
96
- return (_jsx("section", { id: id, className: cn(finalSectionClass, className), "aria-label": ariaLabel, children: _jsxs("div", { className: cn("flex flex-col items-stretch", imageLayout === "full-bleed"
97
- ? "md:block"
98
- : "md:flex-row md:items-start"), children: [_jsx("div", { className: cn("w-full", imageLayout === "full-bleed" &&
99
- "relative z-10 md:w-1/2 md:px-8 md:py-12", textContainer.className), children: _jsxs("div", { className: cn("flex flex-col items-center", lgItemsAlignClasses[textAlign]), children: [_jsx("h1", { className: cn("text-center", lgTextAlignClasses[textAlign], normalizedHeading.className), children: normalizedHeading.text }), _jsx("p", { className: cn("text-center", lgTextAlignClasses[textAlign], normalizedSubheading.className), children: normalizedSubheading.text }), _jsxs("div", { className: cn("flex flex-col items-center justify-center gap-4 sm:flex-row", lgJustifyAlignClasses[textAlign], lgItemsAlignClasses[textAlign], buttonsContainer.className), children: [mergedCta1.label && (_jsx(Button, { asChild: true, variant: mergedCta1.variant, size: mergedCta1.size, className: mergedCta1.className, unstyled: mergedCta1.unstyled, style: mergedCta1.style, children: _jsx(Link, { href: mergedCta1.href || "#", "aria-label": mergedCta1.label, children: mergedCta1.label }) })), (mergedCta2 === null || mergedCta2 === void 0 ? void 0 : mergedCta2.label) && (_jsx(Button, { asChild: true, variant: mergedCta2.variant, size: mergedCta2.size, className: mergedCta2.className, unstyled: mergedCta2.unstyled, style: mergedCta2.style, children: _jsx(Link, { href: mergedCta2.href || "#", "aria-label": mergedCta2.label, children: mergedCta2.label }) }))] })] }) }), _jsx("div", { className: cn(finalImageContainerClass), children: (image === null || image === void 0 ? void 0 : image.src) ? (_jsx(Image, { priority: true, fetchPriority: "high", src: image.src, alt: image.alt || "Hero image", className: finalImageClass, fill: true, sizes: "(min-width: 768px) 50vw, 100vw", quality: 75 })) : (_jsx("div", { className: "absolute inset-0", children: fallback || null })) })] }) }));
100
- }