chore(deps): update dependency tailwindcss to v4 - autoclosed #5

Closed
renovate-bot wants to merge 0 commits from renovate/major-tailwindcss-monorepo into master
19 changed files with 9712 additions and 6529 deletions

View File

@@ -4,7 +4,7 @@ on:
pull_request:
push:
branches:
- "**" # matches every branch
- '**' # matches every branch
jobs:
lint_and_check:
@@ -15,17 +15,14 @@ jobs:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Install pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
cache: "pnpm"
cache: 'npm'
- name: Install dependencies
run: pnpm install
run: npm ci
- name: Run check
run: pnpm run check
run: npm run check

View File

@@ -1,44 +0,0 @@
# Event Dates Management Guide
## How to Block Sign-ups on Event Days
The sign-up form automatically closes at 3pm on specified event dates to prevent last-minute registrations.
### Managing Event Dates
1. Open the `event-dates.json` file in the project root
2. Add or remove dates in the `eventDates` array
3. Use the format `YYYY-MM-DD` (e.g., "2024-12-25" for December 25, 2024)
### Example Configuration
```json
{
"eventDates": ["2025-09-05", "1999-01-01"],
"cutoffTime": "15:00",
"message": "Sign-ups are closed for today's event. Please come back tomorrow."
}
```
### Important Notes
- The cutoff time is set to 3pm (15:00) by default
- Sign-ups will automatically reopen at midnight after an event day
- Users will see a friendly message when sign-ups are closed
- The time zone follows the server's local time
### Adding New Event Dates
Simply add a new date to the array:
```json
"eventDates": [
"2024-12-25",
"2024-12-31",
"2025-01-15",
"2025-02-14",
"2025-03-20" // <- New date added
]
```
Remember to save the file after making changes!

View File

@@ -1,90 +1,24 @@
@import 'tailwindcss';
@tailwind base;
@tailwind components;
@tailwind utilities;
@custom-variant dark (&:is(.dark *));
@theme {
--font-sans: var(--font-sans);
--background-image-gradient-radial: radial-gradient(var(--tw-gradient-stops));
--background-image-gradient-conic: conic-gradient(
from 180deg at 50% 50%,
var(--tw-gradient-stops)
);
--radius-lg: var(--radius);
--radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px);
--color-background: hsl(var(--background));
--color-foreground: hsl(var(--foreground));
--color-card: hsl(var(--card));
--color-card-foreground: hsl(var(--card-foreground));
--color-popover: hsl(var(--popover));
--color-popover-foreground: hsl(var(--popover-foreground));
--color-primary: hsl(var(--primary));
--color-primary-foreground: hsl(var(--primary-foreground));
--color-secondary: hsl(var(--secondary));
--color-secondary-foreground: hsl(var(--secondary-foreground));
--color-muted: hsl(var(--muted));
--color-muted-foreground: hsl(var(--muted-foreground));
--color-accent: hsl(var(--accent));
--color-accent-foreground: hsl(var(--accent-foreground));
--color-destructive: hsl(var(--destructive));
--color-destructive-foreground: hsl(var(--destructive-foreground));
--color-border: hsl(var(--border));
--color-input: hsl(var(--input));
--color-ring: hsl(var(--ring));
--color-chart-1: hsl(var(--chart-1));
--color-chart-2: hsl(var(--chart-2));
--color-chart-3: hsl(var(--chart-3));
--color-chart-4: hsl(var(--chart-4));
--color-chart-5: hsl(var(--chart-5));
:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}
/*
The default border color has changed to `currentcolor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentcolor);
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
}
@utility text-balance {
text-wrap: balance;
}
@layer utilities {
:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
.text-balance {
text-wrap: balance;
}
}

View File

@@ -5,8 +5,6 @@ export default function Page() {
return (
<div className="w-4/5 max-w-2xl mx-auto my-12">
<Image
priority
unoptimized
src="/image/bam.svg"
alt="Bangers and Mash GBG"
width={200}

View File

@@ -5,7 +5,15 @@ import { useForm } from "react-hook-form";
import { z } from "zod";
import { Button } from "@/components/ui/button";
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { format } from "date-fns";
import { CalendarIcon } from "lucide-react";
import { Input } from "@/components/ui/input";
@@ -14,12 +22,11 @@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover
import { cn } from "@/lib/utils";
import { signupFormSubmit } from "@/lib/actions";
import { useState } from "react";
import { isSignupBlocked } from "@/lib/signup-time-check";
export const signupFormSchema = z.object({
name: z.string().min(2, { error: "Name is required" }).max(50, { error: "Name is too long" }),
email: z.email({ error: "Email is invalid" }),
dob: z.date({ error: "Birthday is required" }),
name: z.string().min(2, { message: "Name is required" }).max(50, { message: "Name is too long" }),
email: z.string().email({ message: "Email is invalid" }),
dob: z.date({ required_error: "Birthday is required" }),
});
export const youngestDate = new Date(new Date().setFullYear(new Date().getFullYear() - 20));
export const oldestDate = new Date(new Date().setFullYear(new Date().getFullYear() - 100));
@@ -27,8 +34,6 @@ export const oldestDate = new Date(new Date().setFullYear(new Date().getFullYear
export default function SignUp() {
const [submitted, setSubmitted] = useState(false);
const [response, setResponse] = useState<string | null>(null);
const signupStatus = isSignupBlocked();
const form = useForm<z.infer<typeof signupFormSchema>>({
resolver: zodResolver(signupFormSchema),
defaultValues: {
@@ -38,12 +43,6 @@ export default function SignUp() {
},
});
async function onSubmit(values: z.infer<typeof signupFormSchema>) {
// Double-check signup isn't blocked before submitting
const currentStatus = isSignupBlocked();
if (currentStatus.blocked) {
setResponse(currentStatus.message || "Sign-ups are currently closed.");
return;
}
setSubmitted(true);
setResponse(await signupFormSubmit(values));
}
@@ -60,7 +59,9 @@ export default function SignUp() {
<FormControl>
<Input placeholder="name@example.com" {...field} />
</FormControl>
<FormDescription>We will contact you here with information about events.</FormDescription>
<FormDescription>
We will contact you here with information about events.
</FormDescription>
<FormMessage />
</FormItem>
)}
@@ -90,7 +91,10 @@ export default function SignUp() {
<FormControl>
<Button
variant={"outline"}
className={cn("w-[240px] pl-3 text-left font-normal", !field.value && "text-muted-foreground")}
className={cn(
"w-[240px] pl-3 text-left font-normal",
!field.value && "text-muted-foreground"
)}
>
{field.value ? format(field.value, "PPP") : <span>Pick a date</span>}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
@@ -118,22 +122,12 @@ export default function SignUp() {
</FormItem>
)}
/>
<Button type="submit" disabled={submitted || signupStatus.blocked}>
<Button type="submit" disabled={submitted}>
Submit
</Button>
</form>
</Form>
);
}
// If signup is blocked, show the message
if (signupStatus.blocked && !response) {
return (
<div className="rounded-lg border bg-orange-50 p-6 text-center">
<p className="text-lg font-semibold text-orange-900 mb-2">Sign-ups Temporarily Closed</p>
<p className="text-orange-800">{signupStatus.message}</p>
</div>
);
}
return response ?? SignupForm();
}

View File

@@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{
variants: {
variant: {

View File

@@ -2,17 +2,23 @@ import * as React from "react";
import { cn } from "@/lib/utils";
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
return (
<input
type={type}
data-slot="input"
className={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
/>
);
}
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
ref={ref}
{...props}
/>
);
}
);
Input.displayName = "Input";
export { Input };

View File

@@ -19,7 +19,7 @@ const PopoverContent = React.forwardRef<
align={align}
sideOffset={sideOffset}
className={cn(
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}

View File

@@ -19,7 +19,7 @@ const SelectTrigger = React.forwardRef<
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className
)}
{...props}
@@ -68,7 +68,7 @@ const SelectContent = React.forwardRef<
<SelectPrimitive.Content
ref={ref}
className={cn(
"relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className
@@ -81,7 +81,7 @@ const SelectContent = React.forwardRef<
className={cn(
"p-1",
position === "popper" &&
"h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width)"
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
)}
>
{children}
@@ -111,7 +111,7 @@ const SelectItem = React.forwardRef<
<SelectPrimitive.Item
ref={ref}
className={cn(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}

View File

@@ -1,7 +0,0 @@
{
"eventDates": ["2025-09-05", "1999-01-01"],
"cutoffTime": "15:00",
"message": "Sign-ups are closed for today's event. Please come back tomorrow.",
"internalComment": "Add event dates in YYYY-MM-DD format. Signups will be disabled after 3pm (15:00) on these dates by default."
}

View File

@@ -29,7 +29,7 @@ async function listmonk(data: listmonkData): Promise<string> {
return "An error occurred or this email is already subscribed.";
}
return "Thanks for signing up! Please check your email for a confirmation.";
} catch {
} catch (error) {
return "An error occurred while trying to sign up. Please try again.";
}
}

View File

@@ -1,23 +0,0 @@
import eventConfig from "@/event-dates.json";
export function isSignupBlocked(): { blocked: boolean; message?: string } {
const now = new Date();
const currentDate = now.toISOString().split("T")[0]; // YYYY-MM-DD format
const currentTime = now.toTimeString().slice(0, 5); // HH:MM format
// Check if today is an event date
const isEventDay = eventConfig.eventDates.includes(currentDate);
if (isEventDay) {
// Check if current time is after the cutoff time (default 15:00 / 3pm)
const cutoffTime = eventConfig.cutoffTime || "15:00";
if (currentTime >= cutoffTime) {
return {
blocked: true,
message: eventConfig.message,
};
}
}
return { blocked: false };
}

9546
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -9,40 +9,40 @@
"check": "next lint && npx tsc --noEmit"
},
"dependencies": {
"@hookform/resolvers": "^5.1.1",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-popover": "^1.1.14",
"@radix-ui/react-select": "^2.2.5",
"@radix-ui/react-slot": "^1.2.3",
"class-variance-authority": "^0.7.1",
"@hookform/resolvers": "^5.0.0",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-slot": "^1.1.2",
"autoprefixer": "^10.4.19",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cssnano": "^7.1.0",
"date-fns": "^4.1.0",
"lucide-react": "^0.526.0",
"next": "^15.4.1",
"next-plausible": "^3.12.4",
"cssnano": "^7.0.1",
"date-fns": "^4.0.0",
"lucide-react": "^0.509.0",
"next": "^15.2.1",
"next-plausible": "^3.12.0",
"postcss-flexbugs-fixes": "^5.0.2",
"postcss-preset-env": "^10.2.4",
"react": "^19.1.0",
"react-day-picker": "^9.8.0",
"react-dom": "^19.1.0",
"react-hook-form": "^7.60.0",
"tailwind-merge": "^3.3.1",
"postcss-preset-env": "^10.0.0",
"react": "^19.0.0",
"react-day-picker": "^9.5.1",
"react-dom": "^19.0.0",
"react-hook-form": "^7.54.2",
"tailwind-merge": "^3.0.0",
"tailwindcss-animate": "^1.0.7",
"zod": "^4.0.5"
"zod": "^3.24.2"
},
"devDependencies": {
"@tailwindcss/postcss": "4.1.11",
"@types/node": "22.16.5",
"@types/react": "19.1.8",
"@types/react-dom": "19.1.6",
"eslint": "9.32.0",
"eslint-config-next": "15.4.1",
"eslint-config-prettier": "10.1.8",
"postcss": "8.5.6",
"tailwindcss": "4.1.11",
"turbo": "2.5.5",
"@types/node": "22.15.17",
"@types/react": "19.1.3",
"@types/react-dom": "19.1.3",
"eslint": "9.26.0",
"eslint-config-next": "15.3.2",
"eslint-config-prettier": "10.0.2",
"postcss": "8.5.3",
"tailwindcss": "4.1.6",
"turbo": "2.5.3",
"typescript": "5.8.3"
},
"packageManager": "pnpm@10.13.1"
"packageManager": "npm@11.3.0"
}

6286
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +0,0 @@
onlyBuiltDependencies:
- '@tailwindcss/oxide'
- sharp

View File

@@ -1,8 +1,9 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
'@tailwindcss/postcss': {},
tailwindcss: {},
autoprefixer: {},
"postcss-flexbugs-fixes": {
"postcss-preset-env": {
autoprefixer: {

70
tailwind.config.ts Normal file
View File

@@ -0,0 +1,70 @@
import type { Config } from "tailwindcss";
const config: Config = {
darkMode: ["class"],
content: [
"./lib/**/*.{ts,tsx,js,jsx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
fontFamily: {
sans: ["var(--font-sans)"]
},
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))'
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)'
},
colors: {
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))'
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))'
},
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))'
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))'
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))'
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))'
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))'
},
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
chart: {
'1': 'hsl(var(--chart-1))',
'2': 'hsl(var(--chart-2))',
'3': 'hsl(var(--chart-3))',
'4': 'hsl(var(--chart-4))',
'5': 'hsl(var(--chart-5))'
}
}
}
},
plugins: [require("tailwindcss-animate")],
};
export default config;

View File

@@ -22,6 +22,6 @@
},
"target": "ES2023"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "event-dates.json"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}