Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
47 changes: 47 additions & 0 deletions animata/widget/calendar-widget.stories.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof CalendarWidget>;

export default meta;
type Story = StoryObj<typeof meta>;

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,
},
};
154 changes: 154 additions & 0 deletions animata/widget/calendar-widget.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLDivElement>(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 (
<motion.div
className="mx-auto max-w-sm rounded-3xl bg-slate-200 shadow-lg"
initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ duration: 0.3 }}
>
<div className="mx-auto max-w-sm rounded-3xl px-6 py-2">
<h2 className="mb-4 text-2xl font-bold">{`${monthArray[month]} ${year}`}</h2>
<div
ref={scrollRef}
className="scrollbar-hide flex items-start space-x-2 overflow-x-auto py-2"
style={{ scrollbarWidth: "none", msOverflowStyle: "none" }}
>
{dates.map((date, index) => (
<motion.button
key={date}
data-date={date}
className="flex w-10 flex-shrink-0 flex-col items-center justify-center gap-y-2 rounded-lg"
onClick={() => {
setSelectedDate(date);
setShowEvents(true);
}}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
<span className="mb-1 text-xs">{daySymbols[(index + 4) % 7]}</span>
<AnimatePresence>
{selectedDate === date ? (
<motion.span
layoutId="highlighted-date"
className="flex h-8 w-8 items-center justify-center rounded-full bg-gray-100 text-black shadow-lg"
transition={{
type: "spring",
stiffness: 300,
damping: 20,
}}
>
{date}
</motion.span>
) : (
<span className="flex h-8 w-8 items-center justify-center">{date}</span>
)}
</AnimatePresence>
<span>
{eventsData.find((alldates: EventType) => alldates.date === date) ? (
<DotIcon />
) : (
""
)}
</span>
</motion.button>
))}
</div>
</div>

<div className="w-full rounded-3xl bg-[#fefefe] px-6 shadow-lg">
<AnimatePresence mode="wait">
{showEvents && (
<motion.div
key="events"
className="scrollbar-hide mt-2 h-[150px] overflow-scroll border-t pt-4"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.2 }}
>
{filteredEvents.length > 0 ? (
filteredEvents.map((event: EventType, index: number) => (
<motion.div
key={index}
className="mb-2 border-b-2 border-slate-200"
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: index * 0.1 }}
>
<h4 className="font-medium">{event.title}</h4>
<p className="text-sm text-gray-500">{event.time}</p>
</motion.div>
))
) : (
<motion.div
className="flex flex-col items-center text-gray-500"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
>
<CalendarIcon className="mb-2 h-8 w-8" />
<p>No Events</p>
</motion.div>
)}
</motion.div>
)}
</AnimatePresence>
</div>
</motion.div>
);
}
3 changes: 3 additions & 0 deletions content/docs/background/moving-gradient.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ author: harimanok_
```js
theme: {
extend: {
animation: {
"bg-position": "bg-position 3s infinite alternate",
},
keyframes: {
"bg-position": {
"0%": { backgroundPosition: "0% 50%" },
Expand Down
2 changes: 1 addition & 1 deletion content/docs/container/marquee.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion content/docs/section/pricing.mdx
Original file line number Diff line number Diff line change
@@ -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
---

Expand Down
38 changes: 38 additions & 0 deletions content/docs/widget/calendar-widget.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Calendar Widget
description: calendar widget is calender like widget with smooth animations and cool effects
author: anshu_code
---

<ComponentPreview name="widget-calendar-widget--docs" />

## Installation

<Steps>
<Step>Install dependencies</Step>

```bash
npm install framer-motion lucide-react
```

<Step>Run the following command</Step>

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
```

<Step>Paste the code</Step>{" "}

Open the newly created file and paste the following code:

```jsx file=<rootDir>/animata/widget/calendar-widget.tsx

```

</Steps>

## Credits

Built by [Anshuman](https://github.com/anshuman008)
33 changes: 19 additions & 14 deletions hooks/use-newsletter-subscription.ts
Original file line number Diff line number Diff line change
@@ -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 = {
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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

Expand Down