diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ace6ab08..f1027867 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,6 +41,7 @@ jobs: NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ vars.NEXT_PUBLIC_SUPABASE_ANON_KEY }} NEXT_PUBLIC_POSTHOG_KEY: ${{ vars.NEXT_PUBLIC_POSTHOG_KEY }} NEXT_PUBLIC_POSTHOG_HOST: ${{ vars.NEXT_PUBLIC_POSTHOG_HOST }} + NEXT_PUBLIC_PLUNK_API_KEY: ${{ vars.NEXT_PUBLIC_PLUNK_API_KEY }} run: yarn build - name: Deploy to Cloudflare Pages id: deploy diff --git a/animata/widget/calendar-widget.stories.tsx b/animata/widget/calendar-widget.stories.tsx new file mode 100644 index 00000000..2010e17b --- /dev/null +++ b/animata/widget/calendar-widget.stories.tsx @@ -0,0 +1,47 @@ +import CalendarWidget from "@/animata/widget/calendar-widget"; +import { Meta, StoryObj } from "@storybook/react"; + +const meta = { + title: "Widget/Calendar Widget", + component: CalendarWidget, + parameters: { + layout: "centered", + }, + tags: ["autodocs"], + argTypes: { + initialSelectedDate: { + control: { type: "number", min: 1, max: 30 }, + defaultValue: 1, + }, + initialShowEvents: { + control: { type: "boolean" }, + defaultValue: true, + }, + eventsData: { + control: { type: "object" }, + defaultValue: [ + { date: 3, title: "Project Review", time: "10:00 - 11:00 AM" }, + { date: 5, title: "Client Meeting", time: "9:00 - 9:45 AM" }, + { date: 18, title: "Walk", time: "6:00 - 7:00 AM" }, + ], + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + args: { + initialSelectedDate: 1, + initialShowEvents: true, + eventsData: [ + { date: 3, title: "Project Review", time: "10:00 - 11:00 AM" }, + { date: 3, title: "Project discussion", time: "11:00 - 12:00 AM" }, + { date: 5, title: "Client Meeting", time: "9:00 - 9:45 AM" }, + { date: 18, title: "Walk", time: "6:00 - 7:00 AM" }, + ], + month: 3, + year: 2023, + }, +}; diff --git a/animata/widget/calendar-widget.tsx b/animata/widget/calendar-widget.tsx new file mode 100644 index 00000000..bc53ff03 --- /dev/null +++ b/animata/widget/calendar-widget.tsx @@ -0,0 +1,154 @@ +import React, { useEffect, useRef, useState } from "react"; +import { AnimatePresence, motion } from "framer-motion"; +import { Calendar as CalendarIcon, DotIcon } from "lucide-react"; + +const monthArray = [ + "", + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", +]; + +interface EventType { + date: number; + title: string; + time: string; +} + +export default function CalendarWidget({ + initialSelectedDate = 1, + initialShowEvents = true, + eventsData = [], + month = 1, + year = new Date().getFullYear(), +}: { + initialSelectedDate?: number; + initialShowEvents?: boolean; + eventsData?: EventType[]; + month?: number; + year?: number; +}) { + const [selectedDate, setSelectedDate] = useState(initialSelectedDate); + const [showEvents, setShowEvents] = useState(initialShowEvents); + const scrollRef = useRef(null); + + const dates = Array.from({ length: 30 }, (_, i) => i + 1); + const daySymbols = ["S", "M", "T", "W", "T", "F", "S"]; + + const filteredEvents = eventsData.filter((event: EventType) => event.date === selectedDate); + + useEffect(() => { + if (scrollRef.current) { + const selectedElement = scrollRef.current.querySelector(`[data-date="${selectedDate}"]`); + if (selectedElement) { + selectedElement.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" }); + } + } + }, [selectedDate]); + + return ( + +
+

{`${monthArray[month]} ${year}`}

+
+ {dates.map((date, index) => ( + { + setSelectedDate(date); + setShowEvents(true); + }} + whileHover={{ scale: 1.05 }} + whileTap={{ scale: 0.95 }} + > + {daySymbols[(index + 4) % 7]} + + {selectedDate === date ? ( + + {date} + + ) : ( + {date} + )} + + + {eventsData.find((alldates: EventType) => alldates.date === date) ? ( + + ) : ( + "" + )} + + + ))} +
+
+ +
+ + {showEvents && ( + + {filteredEvents.length > 0 ? ( + filteredEvents.map((event: EventType, index: number) => ( + +

{event.title}

+

{event.time}

+
+ )) + ) : ( + + +

No Events

+
+ )} +
+ )} +
+
+
+ ); +} diff --git a/app/_landing/hero.tsx b/app/_landing/hero.tsx index f9ced922..85bdef45 100644 --- a/app/_landing/hero.tsx +++ b/app/_landing/hero.tsx @@ -1,5 +1,6 @@ import Link from "next/link"; +import CarbonAds from "@/components/ads"; import { Icons } from "@/components/icons"; import { PageHeaderDescription } from "@/components/page-header"; import { buttonVariants } from "@/components/ui/button"; @@ -69,19 +70,17 @@ export default function Hero() { 1000+ stars 1033+ hours of development 250+ hours of research - - - + +
+ +
- + - - - diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx index ab137405..d344b1de 100644 --- a/app/docs/[[...slug]]/page.tsx +++ b/app/docs/[[...slug]]/page.tsx @@ -5,6 +5,7 @@ import { allDocs } from "contentlayer/generated"; import Balancer from "react-wrap-balancer"; import NavMenu from "@/app/docs/[[...slug]]/nav-menu"; +import CarbonAds from "@/components/ads"; import { Mdx } from "@/components/mdx-components"; import { DocsPager } from "@/components/pager"; import { DashboardTableOfContents } from "@/components/toc"; @@ -18,7 +19,6 @@ import { ChevronRightIcon, ExternalLinkIcon } from "@radix-ui/react-icons"; import "@/styles/mdx.css"; import "@/styles/storybook.css"; - interface DocPageProps { params: { slug: string[]; @@ -144,6 +144,9 @@ export default async function DocPage({ params }: DocPageProps) { )} ) : null} +
+ +
diff --git a/app/layout.tsx b/app/layout.tsx index 94a306b3..c3391775 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -12,8 +12,8 @@ import "@/styles/globals.css"; export const metadata: Metadata = { title: { - default: siteConfig.name, - template: `%s - ${siteConfig.name}`, + default: `Free & Open Source Animated ReactJS Components | ${siteConfig.name}`, + template: "%s | Free & Open Source Animated ReactJS Components", }, metadataBase: new URL(siteConfig.url), description: siteConfig.description, diff --git a/components/ads.tsx b/components/ads.tsx new file mode 100644 index 00000000..9af71bad --- /dev/null +++ b/components/ads.tsx @@ -0,0 +1,38 @@ +"use client"; + +import { useEffect } from "react"; +import { usePathname } from "next/navigation"; + +export default function CarbonAds() { + const pathname = usePathname(); + + useEffect(() => { + // Skip loading ads in development environment + if ( + typeof window !== "undefined" && + (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1") + ) { + return; + } + + const script = document.createElement("script"); + script.src = + "//cdn.carbonads.com/carbon.js?serve=CW7ITK77&placement=animatadesign&format=cover"; + script.id = "_carbonads_js"; + script.async = true; + + const container = document.getElementById("carbon-container"); + if (container && !document.getElementById("_carbonads_js")) { + container.appendChild(script); + } + + return () => { + const existingScript = document.getElementById("_carbonads_js"); + if (existingScript && existingScript.parentNode) { + existingScript.parentNode.removeChild(existingScript); + } + }; + }, [pathname]); + + return
; +} diff --git a/content/docs/background/moving-gradient.mdx b/content/docs/background/moving-gradient.mdx index ac798d95..c02a44f5 100644 --- a/content/docs/background/moving-gradient.mdx +++ b/content/docs/background/moving-gradient.mdx @@ -15,6 +15,9 @@ author: harimanok_ ```js theme: { extend: { + animation: { + "bg-position": "bg-position 3s infinite alternate", + }, keyframes: { "bg-position": { "0%": { backgroundPosition: "0% 50%" }, diff --git a/content/docs/container/marquee.mdx b/content/docs/container/marquee.mdx index baf8ef75..750789a8 100644 --- a/content/docs/container/marquee.mdx +++ b/content/docs/container/marquee.mdx @@ -24,7 +24,7 @@ theme: { from: { transform: "translateY(0)" }, to: { transform: "translateY(calc(-100% - var(--gap)))" }, }, - } + }, animation: { "marquee-horizontal": "marquee-x var(--duration) infinite linear", "marquee-vertical": "marquee-y var(--duration) linear infinite", diff --git a/content/docs/section/pricing.mdx b/content/docs/section/pricing.mdx index 20aa0532..e063f920 100644 --- a/content/docs/section/pricing.mdx +++ b/content/docs/section/pricing.mdx @@ -1,6 +1,6 @@ --- title: Pricing -description: Pricing component that display the pricing options of various plans in an sleek and interactive way +description: Pricing component that displays the pricing options of various plans in a sleek and interactive way author: SatyamVyas04 --- diff --git a/content/docs/widget/calendar-widget.mdx b/content/docs/widget/calendar-widget.mdx new file mode 100644 index 00000000..f2efdaeb --- /dev/null +++ b/content/docs/widget/calendar-widget.mdx @@ -0,0 +1,38 @@ +--- +title: Calendar Widget +description: calendar widget is calender like widget with smooth animations and cool effects +author: anshu_code +--- + + + +## Installation + + +Install dependencies + +```bash +npm install framer-motion lucide-react +``` + +Run the following command + +It will create a new file `calendar-widget.tsx` inside the `components/animata/widget` directory. + +```bash +mkdir -p components/animata/widget && touch components/animata/widget/calendar-widget.tsx +``` + +Paste the code{" "} + +Open the newly created file and paste the following code: + +```jsx file=/animata/widget/calendar-widget.tsx + +``` + + + +## Credits + +Built by [Anshuman](https://github.com/anshuman008) diff --git a/hooks/use-newsletter-subscription.ts b/hooks/use-newsletter-subscription.ts index d444d2c1..40e46b51 100644 --- a/hooks/use-newsletter-subscription.ts +++ b/hooks/use-newsletter-subscription.ts @@ -1,8 +1,8 @@ "use client"; import { useState } from "react"; -const url = process.env.NEXT_PUBLIC_SUPABASE_URL + "/rest/v1/prelaunch_subscribers"; -const apiKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; +const plunkApiUrl = "https://api.useplunk.com/v1/track"; +const plunkApiKey = process.env.NEXT_PUBLIC_PLUNK_API_KEY; export default function useNewsletterSubscription() { const initialState = { @@ -29,20 +29,25 @@ export default function useNewsletterSubscription() { } setState({ ...state, isLoading: true }); - const data = { email: state.email }; - try { - const response = await fetch(url, { - method: "POST", - // @ts-expect-error - Types for custom headers are not defined in fetch types - headers: { - apikey: apiKey, - Authorization: "Bearer " + apiKey, - "Content-Type": "application/json", - Prefer: "return=minimal", + const options = { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${plunkApiKey}`, + }, + body: JSON.stringify({ + event: "newsletter_subscription", + email: state.email, + subscribed: true, + data: { + project_id: "animata", }, - body: JSON.stringify(data), - }); + }), + }; + + try { + const response = await fetch(plunkApiUrl, options); if (response.status >= 200 && response.status < 300) { // Email added successfully diff --git a/yarn.lock b/yarn.lock index 9568d9ec..a3eedf5f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9414,8 +9414,8 @@ __metadata: linkType: hard "elliptic@npm:^6.5.3, elliptic@npm:^6.5.5": - version: 6.5.7 - resolution: "elliptic@npm:6.5.7" + version: 6.6.1 + resolution: "elliptic@npm:6.6.1" dependencies: bn.js: "npm:^4.11.9" brorand: "npm:^1.1.0" @@ -9424,7 +9424,7 @@ __metadata: inherits: "npm:^2.0.4" minimalistic-assert: "npm:^1.0.1" minimalistic-crypto-utils: "npm:^1.0.1" - checksum: 10c0/799959b6c54ea3564e8961f35abdf8c77e37617f3051614b05ab1fb6a04ddb65bd1caa75ed1bae375b15dda312a0f79fed26ebe76ecf05c5a7af244152a601b8 + checksum: 10c0/8b24ef782eec8b472053793ea1e91ae6bee41afffdfcb78a81c0a53b191e715cbe1292aa07165958a9bbe675bd0955142560b1a007ffce7d6c765bcaf951a867 languageName: node linkType: hard