@nextworks/blocks-sections 0.1.0-alpha.11 → 0.1.0-alpha.14

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 (59) hide show
  1. package/dist-types/components/About.d.ts +93 -0
  2. package/dist-types/components/About.d.ts.map +1 -0
  3. package/dist-types/components/CTA.d.ts +118 -0
  4. package/dist-types/components/CTA.d.ts.map +1 -0
  5. package/dist-types/components/Contact.d.ts +111 -0
  6. package/dist-types/components/Contact.d.ts.map +1 -0
  7. package/dist-types/components/FAQ.d.ts +89 -0
  8. package/dist-types/components/FAQ.d.ts.map +1 -0
  9. package/dist-types/components/Features.d.ts +111 -0
  10. package/dist-types/components/Features.d.ts.map +1 -0
  11. package/dist-types/components/Footer.d.ts +120 -0
  12. package/dist-types/components/Footer.d.ts.map +1 -0
  13. package/dist-types/components/HeroMotion.d.ts +107 -0
  14. package/dist-types/components/HeroMotion.d.ts.map +1 -0
  15. package/dist-types/components/HeroOverlay.d.ts +116 -0
  16. package/dist-types/components/HeroOverlay.d.ts.map +1 -0
  17. package/dist-types/components/HeroSplit.d.ts +98 -0
  18. package/dist-types/components/HeroSplit.d.ts.map +1 -0
  19. package/dist-types/components/Navbar.d.ts +112 -0
  20. package/dist-types/components/Navbar.d.ts.map +1 -0
  21. package/dist-types/components/Newsletter.d.ts +59 -0
  22. package/dist-types/components/Newsletter.d.ts.map +1 -0
  23. package/dist-types/components/PortfolioSimple.d.ts +137 -0
  24. package/dist-types/components/PortfolioSimple.d.ts.map +1 -0
  25. package/dist-types/components/Pricing.d.ts +96 -0
  26. package/dist-types/components/Pricing.d.ts.map +1 -0
  27. package/dist-types/components/ProcessTimeline.d.ts +121 -0
  28. package/dist-types/components/ProcessTimeline.d.ts.map +1 -0
  29. package/dist-types/components/ServicesGrid.d.ts +64 -0
  30. package/dist-types/components/ServicesGrid.d.ts.map +1 -0
  31. package/dist-types/components/Team.d.ts +115 -0
  32. package/dist-types/components/Team.d.ts.map +1 -0
  33. package/dist-types/components/Testimonials.d.ts +81 -0
  34. package/dist-types/components/Testimonials.d.ts.map +1 -0
  35. package/dist-types/components/TrustBadges.d.ts +80 -0
  36. package/dist-types/components/TrustBadges.d.ts.map +1 -0
  37. package/dist-types/components/index.d.ts +21 -0
  38. package/dist-types/components/index.d.ts.map +1 -0
  39. package/dist-types/index.d.ts +2 -0
  40. package/dist-types/index.d.ts.map +1 -0
  41. package/package.json +6 -4
  42. package/dist/components/About.js +0 -129
  43. package/dist/components/CTA.js +0 -58
  44. package/dist/components/Contact.js +0 -82
  45. package/dist/components/FAQ.js +0 -78
  46. package/dist/components/Features.js +0 -109
  47. package/dist/components/Footer.js +0 -101
  48. package/dist/components/HeroMotion.js +0 -55
  49. package/dist/components/HeroOverlay.js +0 -111
  50. package/dist/components/HeroSplit.js +0 -100
  51. package/dist/components/Navbar.js +0 -80
  52. package/dist/components/Newsletter.js +0 -34
  53. package/dist/components/PortfolioSimple.js +0 -180
  54. package/dist/components/Pricing.js +0 -91
  55. package/dist/components/ProcessTimeline.js +0 -88
  56. package/dist/components/ServicesGrid.js +0 -72
  57. package/dist/components/Team.js +0 -107
  58. package/dist/components/Testimonials.js +0 -46
  59. package/dist/components/TrustBadges.js +0 -46
@@ -1,129 +0,0 @@
1
- "use client";
2
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import React from "react";
4
- import { cn } from "@nextworks/blocks-core";
5
- /**
6
- * Default statistics displayed if no aboutStats are provided.
7
- */
8
- const defaultStatsData = [
9
- { value: "50", label: "Successful Projects", suffix: "+" },
10
- { value: "5", label: "Years Experience", suffix: "+" },
11
- { value: "100", label: "Happy Clients", suffix: "%" },
12
- { value: "24", label: "Support Hours", suffix: "/7" },
13
- ];
14
- /**
15
- * About section with a heading, optional subheading/content, and an optional
16
- * stats block.
17
- *
18
- * @remarks
19
- * - Styling: exposes slot-style className overrides. Consumer classes are
20
- * merged after defaults via cn().
21
- * - Layout: control text alignment with aboutTextAlign.
22
- * - Accessibility: rendered as a semantic <section> with aria-label.
23
- *
24
- * @example
25
- * <About
26
- * aboutHeadingText="Your Success Is Our Mission"
27
- * aboutContentText="We build digital products that convert."
28
- * aboutStats={[{ value: "50", label: "Successful Projects", suffix: "+" }]}
29
- * />
30
- */
31
- /**
32
- * About section with a heading, optional subheading/content, and an optional
33
- * stats block.
34
- *
35
- * @remarks
36
- * - Styling: exposes slot-style className overrides. Consumer classes are
37
- * merged after defaults via cn().
38
- * - Layout: control text alignment with aboutTextAlign.
39
- * - Accessibility: rendered as a semantic <section> with aria-label.
40
- *
41
- * @example
42
- * <About
43
- * aboutHeadingText="Your Success Is Our Mission"
44
- * aboutContentText="We build digital products that convert."
45
- * aboutStats={[{ value: "50", label: "Successful Projects", suffix: "+" }]}
46
- * />
47
- */
48
- /**
49
- * Animated count-up for integers using requestAnimationFrame.
50
- * Eases out and runs once when shouldStart becomes true.
51
- */
52
- function AnimatedCount({ end, shouldStart, duration = 1500, }) {
53
- const [value, setValue] = React.useState(0);
54
- const [done, setDone] = React.useState(false);
55
- const prefersReduced = React.useMemo(() => {
56
- if (typeof window === "undefined")
57
- return false;
58
- return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
59
- }, []);
60
- React.useEffect(() => {
61
- if (prefersReduced)
62
- return; // show end value immediately below
63
- if (!shouldStart || done)
64
- return;
65
- let raf;
66
- const startTs = performance.now();
67
- const tick = (now) => {
68
- const progress = Math.min((now - startTs) / duration, 1);
69
- const eased = 1 - Math.pow(1 - progress, 3);
70
- const next = Math.round(eased * end);
71
- setValue(next);
72
- if (progress < 1) {
73
- raf = requestAnimationFrame(tick);
74
- }
75
- else {
76
- setDone(true);
77
- }
78
- };
79
- raf = requestAnimationFrame(tick);
80
- return () => cancelAnimationFrame(raf);
81
- }, [shouldStart, end, duration, done, prefersReduced]);
82
- if (prefersReduced)
83
- return _jsx(_Fragment, { children: end });
84
- return _jsx(_Fragment, { children: value });
85
- }
86
- export function About({ aboutHeadingText = "Your Success Is Our Mission", aboutSubheadingText, aboutContentText = "With 50+ successful projects and 5 years of experience, we specialize in creating digital solutions that drive real business growth.", aboutStats = defaultStatsData, className, section = { className: "py-20 bg-muted text-foreground" }, container = { className: "max-w-7xl mx-auto px-6" }, inner = { className: "flex flex-col gap-12" }, contentContainer = { className: "max-w-4xl mx-auto" }, contentStack = { className: "flex flex-col gap-6" }, subheading = {
87
- className: "text-sm font-semibold font-poppins text-primary uppercase tracking-wider",
88
- }, heading = {
89
- className: "text-3xl font-bold font-poppins text-foreground leading-tight",
90
- }, content = {
91
- className: "text-lg font-inter text-foreground leading-relaxed opacity-90 max-w-3xl",
92
- }, statsSection = {
93
- className: "bg-card p-8 rounded-xl shadow-lg mx-auto max-w-5xl w-full border border-border",
94
- }, statsGrid = {
95
- className: "grid grid-cols-2 md:grid-cols-4 gap-8 justify-items-center",
96
- }, statItem = { className: "flex flex-col items-center gap-2" }, statNumber = {
97
- className: "text-4xl font-bold font-poppins text-foreground leading-none",
98
- }, statLabel = {
99
- className: "text-sm font-medium font-inter text-foreground text-center opacity-80",
100
- }, aboutTextAlign = "center", showStats = true, animateStats = false, ariaLabel = "About section", }) {
101
- const textAlignClasses = {
102
- left: "text-left",
103
- right: "text-right",
104
- center: "text-center",
105
- };
106
- const statsSectionRef = React.useRef(null);
107
- const [shouldStartCount, setShouldStartCount] = React.useState(false);
108
- React.useEffect(() => {
109
- if (!animateStats)
110
- return;
111
- if (!statsSectionRef.current)
112
- return;
113
- const observer = new IntersectionObserver((entries) => {
114
- for (const entry of entries) {
115
- if (entry.isIntersecting) {
116
- setShouldStartCount(true);
117
- observer.disconnect();
118
- break;
119
- }
120
- }
121
- }, { threshold: 0.3 });
122
- observer.observe(statsSectionRef.current);
123
- return () => observer.disconnect();
124
- }, [animateStats]);
125
- return (_jsx("section", { className: cn(section.className, className), "aria-label": ariaLabel, children: _jsx("div", { className: cn(container.className), children: _jsxs("div", { className: cn(inner.className), children: [_jsx("div", { className: cn(contentContainer.className, textAlignClasses[aboutTextAlign]), children: _jsxs("div", { className: cn(contentStack.className), children: [aboutSubheadingText && (_jsx("div", { className: cn(subheading.className), children: aboutSubheadingText })), _jsx("h2", { className: cn(heading.className), children: aboutHeadingText }), _jsx("p", { className: cn(content.className), children: aboutContentText })] }) }), showStats && (aboutStats === null || aboutStats === void 0 ? void 0 : aboutStats.length) ? (_jsx("div", { ref: statsSectionRef, className: cn(statsSection.className), children: _jsx("div", { className: cn(statsGrid.className), children: aboutStats.map((s, i) => {
126
- var _a;
127
- return (_jsxs("div", { className: cn(statItem.className), children: [_jsxs("div", { className: cn(statNumber.className), children: [animateStats && Number.isFinite(Number(s.value)) ? (_jsx(AnimatedCount, { end: Number(s.value), shouldStart: shouldStartCount })) : (s.value), s.suffix] }), _jsx("div", { className: cn(statLabel.className), children: s.label })] }, `${(_a = s.label) !== null && _a !== void 0 ? _a : "stat"}-${i}`));
128
- }) }) })) : null] }) }) }));
129
- }
@@ -1,58 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import Link from "next/link";
4
- import { Button } from "@nextworks/blocks-core";
5
- import { cn } from "@nextworks/blocks-core";
6
- /**
7
- * Call-to-Action section with a heading, optional subheading/description,
8
- * and up to two actions (primary and secondary).
9
- *
10
- * @remarks
11
- * - Styling: exposes slot-style className overrides (section, container,
12
- * contentWrapper, headingText, subheadingText, descriptionText, actionsWrapper,
13
- * ctaButtonStyle, secondaryButtonStyle). Consumer classes are merged after
14
- * defaults via cn().
15
- * - Accessibility: rendered as a semantic <section> with aria-label. The role
16
- * defaults to "region" but can be customized with the role prop.
17
- * - Motion: subtle hover lift effects on buttons are included by default.
18
- *
19
- * @example
20
- * <CTA
21
- * headingText={{ text: "Join The Launch Today!" }}
22
- * descriptionText={{ text: "Start your free trial in minutes." }}
23
- * ctaButton={{ label: "Sign Up", href: "#contact" }}
24
- * secondaryButton={{ label: "Learn More", href: "#features" }}
25
- * />
26
- */
27
- export function CTA({ id = "cta", className, section = {
28
- className: "bg-background text-foreground",
29
- }, container = {
30
- className: "mx-auto flex min-h-[42vh] w-full max-w-6xl flex-col items-center justify-center overflow-hidden px-4 pb-7",
31
- }, contentWrapper = {
32
- className: "flex w-full flex-col items-center text-center",
33
- }, headingText = {
34
- text: "Join The Launch Today!",
35
- className: "text-3xl font-bold leading-[1.1] text-primary sm:text-4xl md:text-5xl text-[var(--heading-fg)]",
36
- }, subheadingText = {
37
- text: "",
38
- className: "mt-2 text-lg font-medium text-muted-foreground sm:text-xl text-[var(--subheading-fg)]",
39
- }, descriptionText = {
40
- text: "",
41
- className: "mt-3 max-w-2xl text-base text-foreground/80 sm:text-lg text-[var(--description-fg)]",
42
- }, actionsWrapper = {
43
- className: "mt-6 flex flex-col items-center gap-3 sm:flex-row",
44
- }, ctaButton = { label: "Sign Up Now", href: "#contact" }, ctaButtonStyle = {
45
- variant: "default",
46
- size: "default",
47
- className: "shadow-lg transition-all duration-200 hover:-translate-y-0.5 hover:shadow-xl border-[var(--btn-border)] focus-visible:ring-[var(--btn-ring)]",
48
- }, ctaButtonWrapper = { className: "" }, secondaryButton = null, secondaryButtonStyle = {
49
- variant: "outline",
50
- size: "default",
51
- className: "transition-transform duration-200 hover:-translate-y-0.5 border-[var(--btn-border)] focus-visible:ring-[var(--btn-ring)]",
52
- }, secondaryButtonWrapper = { className: "" }, spacing = { topMargin: "mt-0 sm:mt-12" },
53
- // spacing = { topMargin: "mt-[17vh]" },
54
- ariaLabel = "Call to action section", role = "region", }) {
55
- // default class for actions wrapper (keeps a gap and responsive row layout)
56
- const actionsWrapperDefault = "mt-6 flex flex-col items-center gap-3 sm:flex-row";
57
- return (_jsx("section", { id: id, role: role, "aria-label": ariaLabel, className: cn("w-full", section.className, className), children: _jsx("div", { className: cn(container.className), children: _jsxs("div", { className: cn(contentWrapper.className), children: [(headingText === null || headingText === void 0 ? void 0 : headingText.text) ? (_jsx("h2", { className: cn("text-center", spacing === null || spacing === void 0 ? void 0 : spacing.topMargin, headingText.className), children: headingText.text })) : null, (subheadingText === null || subheadingText === void 0 ? void 0 : subheadingText.text) ? (_jsx("p", { className: cn(subheadingText.className), children: subheadingText.text })) : null, (descriptionText === null || descriptionText === void 0 ? void 0 : descriptionText.text) ? (_jsx("p", { className: cn(descriptionText.className), children: descriptionText.text })) : null, _jsxs("div", { className: cn(actionsWrapperDefault, actionsWrapper.className), children: [ctaButton && (_jsx(Button, { asChild: true, unstyled: ctaButtonStyle.unstyled, variant: ctaButtonStyle.variant, size: ctaButtonStyle.size, className: cn(ctaButtonWrapper.className, ctaButtonStyle.className), style: ctaButtonStyle.style, children: _jsx(Link, { href: ctaButton.href, "aria-label": ctaButton.label, children: ctaButton.label }) })), secondaryButton && (_jsx(Button, { asChild: true, unstyled: secondaryButtonStyle.unstyled, variant: secondaryButtonStyle.variant, size: secondaryButtonStyle.size, className: cn(secondaryButtonWrapper.className, secondaryButtonStyle.className), style: secondaryButtonStyle.style, children: _jsx(Link, { href: secondaryButton.href, "aria-label": secondaryButton.label, children: secondaryButton.label }) }))] })] }) }) }));
58
- }
@@ -1,82 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { cn } from "@nextworks/blocks-core";
4
- import { Button, Input, Textarea, Label } from "@nextworks/blocks-core";
5
- const defaultFormData = [
6
- {
7
- id: "name",
8
- label: "Your Full Name",
9
- placeholder: "John Doe",
10
- required: true,
11
- type: "text",
12
- },
13
- {
14
- id: "email",
15
- label: "Email Address",
16
- placeholder: "you@example.com",
17
- required: true,
18
- type: "email",
19
- },
20
- {
21
- id: "phone",
22
- label: "Phone Number",
23
- placeholder: "Enter your phone number",
24
- required: false,
25
- type: "tel",
26
- },
27
- {
28
- id: "company",
29
- label: "Company",
30
- placeholder: "Enter your company name",
31
- required: false,
32
- type: "text",
33
- },
34
- {
35
- id: "message",
36
- label: "Message",
37
- placeholder: "Tell us about your project...",
38
- required: true,
39
- type: "textarea",
40
- },
41
- ];
42
- /**
43
- * Contact section with a configurable form and submit action.
44
- *
45
- * @remarks
46
- * - Styling: slot-style className overrides are merged via cn().
47
- * - Behavior: onSubmit is invoked with the form event after calling
48
- * preventDefault().
49
- * - Motion: enableMotion toggles the button hover lift/transition.
50
- * - Accessibility: Uses a semantic <section> with aria-label.
51
- *
52
- * @example
53
- * <Contact onSubmit={(e) => { // send to your API }} />
54
- */
55
- export function Contact({ fields = defaultFormData, contactHeaderText = "Ready to Grow Your Business?", contactSubHeaderText = "Schedule a free consultation with our experts.", id = "contact", className, section = { className: "py-16 px-4 bg-primary" }, container = { className: "mx-auto max-w-4xl" }, headerWrapper = { className: "mb-8 text-center" }, headerText = {
56
- className: "text-2xl font-bold font-poppins text-primary-foreground",
57
- }, subheaderText = {
58
- className: "mt-2 text-lg font-inter text-primary-foreground px-4 md:px-14",
59
- }, form = {
60
- className: "bg-card p-8 rounded-lg shadow-md border border-border bg-[var(--card-bg)] text-[var(--card-fg)] border-[var(--card-border)] shadow-[var(--card-shadow)]",
61
- }, fieldsWrapper = { className: "space-y-4" }, field = { className: "space-y-2" }, label = {
62
- className: "text-card-foreground text-sm font-medium font-poppins block text-[var(--label-fg)]",
63
- }, input = {
64
- className: "w-full p-3 border border-input rounded-md bg-background text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent font-inter border-[var(--input-border)] bg-[var(--input-bg)] text-[var(--input-fg)] placeholder:text-[var(--input-placeholder)] focus-visible:ring-[var(--input-focus-ring)] focus-visible:ring-offset-[var(--input-ring-offset)]",
65
- }, textarea = {
66
- className: "w-full p-3 border border-input rounded-md bg-background text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent resize-vertical min-h-[120px] font-inter border-[var(--input-border)] bg-[var(--input-bg)] text-[var(--input-fg)] placeholder:text-[var(--input-placeholder)] focus-visible:ring-[var(--input-focus-ring)] focus-visible:ring-offset-[var(--input-ring-offset)]",
67
- }, submitButtonWrapper = { className: "pt-2" }, submitButtonStyle = {
68
- variant: "default",
69
- size: "lg",
70
- className: "w-full shadow-lg hover:shadow-xl transition-all duration-200 hover:-translate-y-0.5 border-[var(--btn-border)] focus-visible:ring-[var(--btn-ring)]",
71
- }, submitButtonText = "Schedule Free Consultation", onSubmit, ariaLabel = "Contact section", enableMotion = true, }) {
72
- const handleSubmit = (e) => {
73
- e.preventDefault();
74
- onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit(e);
75
- };
76
- return (_jsx("section", { id: id, className: cn("w-full", section.className, className), "aria-label": ariaLabel, children: _jsxs("div", { className: cn(container.className), children: [_jsxs("div", { className: cn(headerWrapper.className), children: [contactHeaderText && (_jsx("h2", { className: cn(headerText.className), children: contactHeaderText })), contactSubHeaderText && (_jsx("p", { className: cn(subheaderText.className), children: contactSubHeaderText }))] }), _jsx("form", { onSubmit: handleSubmit, className: cn(form.className), children: _jsxs("div", { className: cn(fieldsWrapper.className), children: [fields.map((f) => {
77
- var _a;
78
- const isTextarea = f.type === "textarea";
79
- return (_jsxs("div", { className: cn(field.className), children: [_jsxs(Label, { htmlFor: f.id, className: cn(label.className), children: [f.label, f.required && (_jsx("span", { className: "text-destructive ml-1", children: "*" }))] }), isTextarea ? (_jsx(Textarea, { id: f.id, name: f.id, placeholder: f.placeholder, required: f.required, rows: 4, className: cn(textarea.className) })) : (_jsx(Input, { type: (_a = f.type) !== null && _a !== void 0 ? _a : "text", id: f.id, name: f.id, placeholder: f.placeholder, required: f.required, className: cn(input.className) }))] }, f.id));
80
- }), _jsx("div", { className: cn(submitButtonWrapper.className), children: _jsx(Button, { type: "submit", unstyled: submitButtonStyle.unstyled, variant: submitButtonStyle.variant, size: submitButtonStyle.size, className: cn(submitButtonStyle.className, !enableMotion &&
81
- "transition-none hover:!translate-y-0 hover:shadow-none"), style: submitButtonStyle.style, children: submitButtonText }) })] }) })] }) }));
82
- }
@@ -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
- }