diff --git a/apps/frontend/src/app.tsx b/apps/frontend/src/app.tsx index 125c7ec..7bfb3c2 100644 --- a/apps/frontend/src/app.tsx +++ b/apps/frontend/src/app.tsx @@ -1,10 +1,10 @@ import { useEffect } from 'react'; import { createBrowserRouter, RouterProvider } from 'react-router-dom'; - +import './styles.css'; import apiClient from '@api/apiClient'; import Root from '@containers/root'; import NotFound from '@containers/404'; -import Test from '@containers/test'; +import TestimonialTester from '@containers/TestimonialTester'; import { DonationForm } from '@containers/donations/DonationForm'; import { ShadcnExample } from '@components/ShadcnExample'; import { AuthProvider } from '@components/AuthProvider'; @@ -34,7 +34,7 @@ const router = createBrowserRouter([ }, { path: '/test', - element: , + element: , }, { path: '/shadcn-example', diff --git a/apps/frontend/src/components/testimonials/AutoRotatingTestimonialCarousel.tsx b/apps/frontend/src/components/testimonials/AutoRotatingTestimonialCarousel.tsx index 74c8600..8e97141 100644 --- a/apps/frontend/src/components/testimonials/AutoRotatingTestimonialCarousel.tsx +++ b/apps/frontend/src/components/testimonials/AutoRotatingTestimonialCarousel.tsx @@ -1,47 +1,203 @@ -import React, { useEffect, useState } from 'react'; -import { - TestimonialCarousel, - TestimonialCarouselProps, -} from './TestimonialCarousel'; - -const SLIDES: TestimonialCarouselProps[] = [ - { - title: 'Make a Difference', - body: 'Read below for more about FCC and how your gift supports our small organization serving the entire Fenway community!', - linkText: 'Contact Us for any questions!', - }, - { - title: 'Support the Arts', - body: 'Your generosity helps us bring live performances, workshops, and community events to the Fenway neighborhood.', - linkText: 'Learn how to get involved', - }, - { - title: 'Invest in Community', - body: 'Every contribution—large or small—directly funds programs that connect neighbors, families, and local artists.', - linkText: 'See where your gift goes', - }, - { - title: 'Join Our Mission', - body: 'Partner with FCC to build a more vibrant, inclusive Fenway community through culture, creativity, and care.', - linkText: 'Become a supporter today', - }, -]; - -export const AutoRotatingTestimonialCarousel: React.FC = () => { - const [index, setIndex] = useState(0); - - // auto-rotate every 7 seconds +import React, { useCallback, useEffect, useMemo, useState } from 'react'; + +export interface CarouselSlide { + id: number | string; + image: string; + alt?: string; + objectPosition?: string; +} + +type Props = { + slides: CarouselSlide[]; + animMs?: number; + autoMs?: number; +}; + +const ArrowSvgRight: React.FC<{ className?: string }> = ({ className }) => ( + +); + +const CardSlot: React.FC<{ + slide: CarouselSlide; + style: React.CSSProperties; + animMs: number; +}> = ({ slide, style, animMs }) => { + return ( +
+ ); +}; + +export const AutoRotatingTestimonialCarousel: React.FC = ({ + slides, + animMs = 500, + autoMs = 7000, +}) => { + const len = slides.length; + const [activeIndex, setActiveIndex] = useState(0); + const [isAnimating, setIsAnimating] = useState(false); + + const goTo = useCallback( + (next: number) => { + if (len <= 1 || isAnimating) return; + setIsAnimating(true); + setActiveIndex(((next % len) + len) % len); + window.setTimeout(() => setIsAnimating(false), animMs); + }, + [animMs, isAnimating, len], + ); + useEffect(() => { - const id = window.setInterval(() => { - setIndex((prev) => (prev + 1) % SLIDES.length); - }, 7000); + if (len <= 1) return; - return () => window.clearInterval(id); + const t = window.setInterval(() => { + if (isAnimating) return; + setIsAnimating(true); + setActiveIndex((prev) => (prev - 1 + len) % len); + window.setTimeout(() => setIsAnimating(false), animMs); + }, autoMs); + + return () => window.clearInterval(t); + }, [autoMs, animMs, isAnimating, len]); + + const slotStyles = useMemo(() => { + const base = { width: 193.834, height: 193.833 }; + + return { + left: { + ...base, + opacity: 0.85, + zIndex: 10, + boxShadow: '0 4px 8px 0 rgba(0,0,0,0.25)', + transform: `translate(-50%, -50%) translateX(-120px) scale(0.8)`, + } as React.CSSProperties, + center: { + ...base, + opacity: 1, + zIndex: 30, + boxShadow: '0 4px 10px 0 rgba(0,0,0,0.50)', + transform: `translate(-50%, -50%) translateX(0px) scale(1)`, + } as React.CSSProperties, + right: { + ...base, + opacity: 0.85, + zIndex: 10, + boxShadow: '0 4px 8px 0 rgba(0,0,0,0.25)', + transform: `translate(-50%, -50%) translateX(120px) scale(0.8)`, + } as React.CSSProperties, + }; }, []); - const currentSlide = SLIDES[index]; + if (!len) return null; + + const ArrowButton = ({ + direction, + onClick, + }: { + direction: 'left' | 'right'; + onClick: () => void; + }) => ( + + ); + + return ( +
+
+
+ {/* Left arrow (previous) */} + goTo(activeIndex + 1)} /> + + {/* Overlapping stage */} +
+ {slides.map((slide, index) => { + const position = (index - activeIndex + len) % len; + let style: React.CSSProperties; + + if (position === len - 1) { + // Left position + style = slotStyles.left; + } else if (position === 0) { + // Center position + style = slotStyles.center; + } else if (position === 1) { + // Right position + style = slotStyles.right; + } else { + // Hidden - off screen + style = { + ...slotStyles.right, + opacity: 0, + transform: `translate(-50%, -50%) translateX(240px) scale(0.6)`, + pointerEvents: 'none', + }; + } + + return ( + + ); + })} +
- return ; + {/* Right arrow (next) */} + goTo(activeIndex - 1)} + /> +
+
+
+ ); }; export default AutoRotatingTestimonialCarousel; diff --git a/apps/frontend/src/components/testimonials/TestimonialCarousel.spec.tsx b/apps/frontend/src/components/testimonials/TestimonialCarousel.spec.tsx deleted file mode 100644 index 03ead27..0000000 --- a/apps/frontend/src/components/testimonials/TestimonialCarousel.spec.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import { TestimonialCarousel } from './TestimonialCarousel'; - -describe('TestimonialCarousel', () => { - describe('Rendering with default props', () => { - it('renders with default title', () => { - render(); - - expect(screen.getByText('Make a Difference')).toBeTruthy(); - }); - - it('renders with default body text', () => { - render(); - - expect( - screen.getByText( - /Read below for more about FCC and how your gift supports our small organization/i, - ), - ).toBeTruthy(); - }); - - it('renders with default link text', () => { - render(); - - expect(screen.getByText('Contact Us for any questions!')).toBeTruthy(); - }); - - it('renders the contact link with correct href', () => { - render(); - - const link = screen.getByRole('link', { - name: /contact us for any questions/i, - }); - expect(link).toBeTruthy(); - expect(link.getAttribute('href')).toBe('#contact'); - }); - }); - - describe('Rendering with custom props', () => { - it('renders with custom title', () => { - render(); - - expect(screen.getByText('Custom Title')).toBeTruthy(); - }); - - it('renders with custom body text', () => { - render(); - - expect(screen.getByText('Custom body content here')).toBeTruthy(); - }); - - it('renders with custom link text', () => { - render(); - - expect(screen.getByText('Learn More')).toBeTruthy(); - }); - - it('renders all custom props together', () => { - render( - , - ); - - expect(screen.getByText('Support Us')).toBeTruthy(); - expect( - screen.getByText('Your donations help our community'), - ).toBeTruthy(); - expect(screen.getByText('Get in Touch')).toBeTruthy(); - }); - }); - - describe('Accessibility', () => { - it('renders title as h2 heading', () => { - render(); - - const heading = screen.getByRole('heading', { level: 2 }); - expect(heading).toBeTruthy(); - expect(heading.textContent).toBe('Make a Difference'); - }); - - it('renders link as accessible anchor element', () => { - render(); - - const link = screen.getByRole('link'); - expect(link).toBeTruthy(); - }); - }); - - describe('Edge cases', () => { - it('handles component unmounting gracefully', () => { - const { unmount } = render(); - expect(() => unmount()).not.toThrow(); - }); - }); -}); diff --git a/apps/frontend/src/components/testimonials/TestimonialCarousel.tsx b/apps/frontend/src/components/testimonials/TestimonialCarousel.tsx index 9f109dd..bbe219d 100644 --- a/apps/frontend/src/components/testimonials/TestimonialCarousel.tsx +++ b/apps/frontend/src/components/testimonials/TestimonialCarousel.tsx @@ -1,28 +1,18 @@ import React from 'react'; -import './testimonials.css'; +import AutoRotatingTestimonialCarousel, { + CarouselSlide, +} from './AutoRotatingTestimonialCarousel'; export interface TestimonialCarouselProps { - title?: string; - body?: string; - linkText?: string; + slides: CarouselSlide[]; } export const TestimonialCarousel: React.FC = ({ - title = 'Make a Difference', - body = 'Read below for more about FCC and how your gift supports our small organization serving the entire Fenway community!', - linkText = 'Contact Us for any questions!', + slides, }) => { return ( -
-
-

{title}

- -

{body}

- - - {linkText} - -
+
+
); }; diff --git a/apps/frontend/src/components/testimonials/TestimonialImages/Carousel_image1.png b/apps/frontend/src/components/testimonials/TestimonialImages/Carousel_image1.png new file mode 100644 index 0000000..5a5dc4b Binary files /dev/null and b/apps/frontend/src/components/testimonials/TestimonialImages/Carousel_image1.png differ diff --git a/apps/frontend/src/components/testimonials/TestimonialImages/Carousel_image2.png b/apps/frontend/src/components/testimonials/TestimonialImages/Carousel_image2.png new file mode 100644 index 0000000..f92a68c Binary files /dev/null and b/apps/frontend/src/components/testimonials/TestimonialImages/Carousel_image2.png differ diff --git a/apps/frontend/src/components/testimonials/TestimonialImages/Carousel_image3.png b/apps/frontend/src/components/testimonials/TestimonialImages/Carousel_image3.png new file mode 100644 index 0000000..8e3c8e8 Binary files /dev/null and b/apps/frontend/src/components/testimonials/TestimonialImages/Carousel_image3.png differ diff --git a/apps/frontend/src/components/testimonials/testimonials.css b/apps/frontend/src/components/testimonials/testimonials.css deleted file mode 100644 index 136b7c2..0000000 --- a/apps/frontend/src/components/testimonials/testimonials.css +++ /dev/null @@ -1,78 +0,0 @@ -/* Outer card */ -.testimonial-carousel { - max-width: 1200px; - width: 100%; - min-height: 395px; - height: auto; - border-radius: 10px; - overflow: hidden; - position: relative; - box-sizing: border-box; - - /* IMAGE lives here – from your spec */ - background: url('./TestimonialImages/Dinner_Party.png') lightgray 50% / cover - no-repeat; - - display: flex; - align-items: center; - padding: clamp(20px, 5vw, 40px) clamp(24px, 8vw, 64px); - - font-family: 'Helvetica Neue LT Std', 'Helvetica Neue', Arial, sans-serif; - color: #ffffff; -} - -/* Brown → transparent overlay on the LEFT side */ -.testimonial-carousel::before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 60%; /* how far the brown extends; tweak to taste */ - height: 100%; - - background: linear-gradient( - to right, - #863b27 0%, - #863b27 50%, - rgba(134, 59, 39, 0.7) 80%, - rgba(134, 59, 39, 0) 100% - ); - - pointer-events: none; -} - -/* Text block */ -.testimonial-carousel__text { - position: relative; /* so it sits above ::before */ - z-index: 1; - max-width: min(440px, 50%); - display: flex; - flex-direction: column; - gap: clamp(24px, 5vw, 48px); -} - -.testimonial-carousel__title { - margin: 0; - font-size: clamp(28px, 6vw, 48px); - font-weight: 700; - line-height: 110%; -} - -.testimonial-carousel__body { - margin: 0; - font-size: clamp(12px, 2.5vw, 20px); - font-weight: 500; - line-height: 120%; -} - -.testimonial-carousel__link { - font-size: clamp(12px, 2.5vw, 20px); - font-weight: 500; - line-height: 140%; - color: #ffffff; - text-decoration-line: underline; - text-decoration-style: solid; - text-decoration-skip-ink: auto; - text-decoration-color: rgba(255, 255, 255, 0.58); - text-underline-offset: 5px; -} diff --git a/apps/frontend/src/containers/TestimonialTester.tsx b/apps/frontend/src/containers/TestimonialTester.tsx new file mode 100644 index 0000000..5ecb6b9 --- /dev/null +++ b/apps/frontend/src/containers/TestimonialTester.tsx @@ -0,0 +1,24 @@ +import TestimonialCarousel from '@components/testimonials/TestimonialCarousel'; +import Carousel_image1 from '@components/testimonials/TestimonialImages/Carousel_image1.png'; +import Carousel_image2 from '@components/testimonials/TestimonialImages/Carousel_image2.png'; +import Carousel_image3 from '@components/testimonials/TestimonialImages/Carousel_image3.png'; + +const slides = [ + { id: 1, image: Carousel_image1, objectPosition: '100% 100%' }, + { id: 2, image: Carousel_image2, objectPosition: '100% 100%' }, + { id: 3, image: Carousel_image3, objectPosition: '100% 100%' }, +]; + +export default function TestimonialTester() { + return ( +
+ {/* Center the stage like Figma */} +
+ {/* Important: allow overlap to be visible */} +
+ +
+
+
+ ); +} diff --git a/apps/frontend/src/containers/root.tsx b/apps/frontend/src/containers/root.tsx index b0db0fb..498431f 100644 --- a/apps/frontend/src/containers/root.tsx +++ b/apps/frontend/src/containers/root.tsx @@ -7,6 +7,9 @@ import { } from '@components/GrowingGoal/GrowingGoal'; import { TestimonialCarousel } from '@components/testimonials/TestimonialCarousel'; import { DonationForm } from './donations/DonationForm'; +import CarouselImage1 from '@components/testimonials/TestimonialImages/Carousel_image1.png'; +import CarouselImage2 from '@components/testimonials/TestimonialImages/Carousel_image2.png'; +import CarouselImage3 from '@components/testimonials/TestimonialImages/Carousel_image3.png'; const SAMPLE_DONATION: SampleDonation = { name: 'C4C', @@ -15,6 +18,24 @@ const SAMPLE_DONATION: SampleDonation = { 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAALElEQVR42mNgGAWjgLGB4T8DGjBgFiMDw38GphCjEopFY1GNRg0Y1GgAAAD9YB5WfVii1AAAAABJRU5ErkJggg==', }; +const TESTIMONIAL_SLIDES = [ + { + id: 1, + image: CarouselImage1, + alt: 'Testimonial image 1', + }, + { + id: 2, + image: CarouselImage2, + alt: 'Testimonial image 2', + }, + { + id: 3, + image: CarouselImage3, + alt: 'Testimonial image 3', + }, +]; + const Root: React.FC = () => { const donationTotal = 3000; @@ -30,7 +51,7 @@ const Root: React.FC = () => {
- +
diff --git a/apps/frontend/src/containers/test.tsx b/apps/frontend/src/containers/test.tsx deleted file mode 100644 index 39f35cc..0000000 --- a/apps/frontend/src/containers/test.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react'; -import { AutoRotatingTestimonialCarousel } from '../components/testimonials/AutoRotatingTestimonialCarousel'; - -const Test: React.FC = () => { - return ( -
-

Testimonial Carousel Test

- - - -
-
- ); -}; - -export default Test; diff --git a/package.json b/package.json index 64dd622..54e516f 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "@nx/react": "22.0.2", "@nx/vite": "22.0.2", "@nx/webpack": "22.0.2", + "@tailwindcss/postcss": "^4.1.18", "@testing-library/dom": "^10.4.1", "@testing-library/react": "16.1.0", "@testing-library/user-event": "^14.6.1", diff --git a/postcss.config.js b/postcss.config.js index 2aa7205..7415447 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,6 +1,9 @@ -export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; +module.exports = { + plugins: { + "@tailwindcss/postcss": {}, + }, + }; + + + + \ No newline at end of file diff --git a/tailwind.config.ts b/tailwind.config.ts index d320b1e..5b4cd8d 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -2,8 +2,9 @@ import type { Config } from 'tailwindcss' export default { content: [ - './apps/frontend/index.html', - './apps/frontend/src/**/*.{js,ts,jsx,tsx}', + './index.html', + './apps/frontend/**/*.{js,ts,jsx,tsx,html}', + './libs/**/*.{js,ts,jsx,tsx,html}', ], theme: { extend: { diff --git a/yarn.lock b/yarn.lock index adc41b7..eec390d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1632,7 +1632,7 @@ "@emnapi/wasi-threads" "1.1.0" tslib "^2.4.0" -"@emnapi/core@^1.4.3", "@emnapi/core@^1.5.0": +"@emnapi/core@^1.4.3", "@emnapi/core@^1.5.0", "@emnapi/core@^1.7.1": version "1.8.1" resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.8.1.tgz#fd9efe721a616288345ffee17a1f26ac5dd01349" integrity sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg== @@ -1647,14 +1647,14 @@ dependencies: tslib "^2.4.0" -"@emnapi/runtime@^1.4.3", "@emnapi/runtime@^1.5.0": +"@emnapi/runtime@^1.4.3", "@emnapi/runtime@^1.5.0", "@emnapi/runtime@^1.7.1": version "1.8.1" resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.8.1.tgz#550fa7e3c0d49c5fb175a116e8cd70614f9a22a5" integrity sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg== dependencies: tslib "^2.4.0" -"@emnapi/wasi-threads@1.1.0": +"@emnapi/wasi-threads@1.1.0", "@emnapi/wasi-threads@^1.1.0": version "1.1.0" resolved "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz" integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== @@ -2428,7 +2428,7 @@ "@jridgewell/sourcemap-codec" "^1.5.0" "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/remapping@^2.3.5": +"@jridgewell/remapping@^2.3.4", "@jridgewell/remapping@^2.3.5": version "2.3.5" resolved "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz" integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== @@ -2907,6 +2907,15 @@ "@emnapi/runtime" "^1.4.3" "@tybys/wasm-util" "^0.10.0" +"@napi-rs/wasm-runtime@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz#c3705ab549d176b8dc5172723d6156c3dc426af2" + integrity sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A== + dependencies: + "@emnapi/core" "^1.7.1" + "@emnapi/runtime" "^1.7.1" + "@tybys/wasm-util" "^0.10.1" + "@nestjs/cli@^10.1.17": version "10.2.1" resolved "https://registry.npmjs.org/@nestjs/cli/-/cli-10.2.1.tgz" @@ -5075,6 +5084,115 @@ dependencies: tslib "^2.8.0" +"@tailwindcss/node@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.1.18.tgz#9863be0d26178638794a38d6c7c14666fb992e8a" + integrity sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ== + dependencies: + "@jridgewell/remapping" "^2.3.4" + enhanced-resolve "^5.18.3" + jiti "^2.6.1" + lightningcss "1.30.2" + magic-string "^0.30.21" + source-map-js "^1.2.1" + tailwindcss "4.1.18" + +"@tailwindcss/oxide-android-arm64@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz#79717f87e90135e5d3d23a3d3aecde4ca5595dd5" + integrity sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q== + +"@tailwindcss/oxide-darwin-arm64@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz#7fa47608d62d60e9eb020682249d20159667fbb0" + integrity sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A== + +"@tailwindcss/oxide-darwin-x64@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz#c05991c85aa2af47bf9d1f8172fe9e4636591e79" + integrity sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw== + +"@tailwindcss/oxide-freebsd-x64@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz#3d48e8d79fd08ece0e02af8e72d5059646be34d0" + integrity sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA== + +"@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz#982ecd1a65180807ccfde67dc17c6897f2e50aa8" + integrity sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA== + +"@tailwindcss/oxide-linux-arm64-gnu@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz#df49357bc9737b2e9810ea950c1c0647ba6573c3" + integrity sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw== + +"@tailwindcss/oxide-linux-arm64-musl@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz#b266c12822bf87883cf152615f8fffb8519d689c" + integrity sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg== + +"@tailwindcss/oxide-linux-x64-gnu@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz#5c737f13dd9529b25b314e6000ff54e05b3811da" + integrity sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g== + +"@tailwindcss/oxide-linux-x64-musl@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz#3380e17f7be391f1ef924be9f0afe1f304fe3478" + integrity sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ== + +"@tailwindcss/oxide-wasm32-wasi@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz#9464df0e28a499aab1c55e97682be37b3a656c88" + integrity sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA== + dependencies: + "@emnapi/core" "^1.7.1" + "@emnapi/runtime" "^1.7.1" + "@emnapi/wasi-threads" "^1.1.0" + "@napi-rs/wasm-runtime" "^1.1.0" + "@tybys/wasm-util" "^0.10.1" + tslib "^2.4.0" + +"@tailwindcss/oxide-win32-arm64-msvc@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz#bbcdd59c628811f6a0a4d5b09616967d8fb0c4d4" + integrity sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA== + +"@tailwindcss/oxide-win32-x64-msvc@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz#9c628d04623aa4c3536c508289f58d58ba4b3fb1" + integrity sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q== + +"@tailwindcss/oxide@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide/-/oxide-4.1.18.tgz#c8335cd0a83e9880caecd60abf7904f43ebab582" + integrity sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A== + optionalDependencies: + "@tailwindcss/oxide-android-arm64" "4.1.18" + "@tailwindcss/oxide-darwin-arm64" "4.1.18" + "@tailwindcss/oxide-darwin-x64" "4.1.18" + "@tailwindcss/oxide-freebsd-x64" "4.1.18" + "@tailwindcss/oxide-linux-arm-gnueabihf" "4.1.18" + "@tailwindcss/oxide-linux-arm64-gnu" "4.1.18" + "@tailwindcss/oxide-linux-arm64-musl" "4.1.18" + "@tailwindcss/oxide-linux-x64-gnu" "4.1.18" + "@tailwindcss/oxide-linux-x64-musl" "4.1.18" + "@tailwindcss/oxide-wasm32-wasi" "4.1.18" + "@tailwindcss/oxide-win32-arm64-msvc" "4.1.18" + "@tailwindcss/oxide-win32-x64-msvc" "4.1.18" + +"@tailwindcss/postcss@^4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/postcss/-/postcss-4.1.18.tgz#19152640d676beaa2a4a70b00bbc36ef54e998b5" + integrity sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g== + dependencies: + "@alloc/quick-lru" "^5.2.0" + "@tailwindcss/node" "4.1.18" + "@tailwindcss/oxide" "4.1.18" + postcss "^8.4.41" + tailwindcss "4.1.18" + "@testing-library/dom@^10.4.1": version "10.4.1" resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz" @@ -8067,7 +8185,7 @@ detect-libc@^1.0.3: resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz" integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== -detect-libc@^2.0.0: +detect-libc@^2.0.0, detect-libc@^2.0.3: version "2.1.2" resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz" integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== @@ -8353,6 +8471,14 @@ enhanced-resolve@^5.0.0, enhanced-resolve@^5.15.0, enhanced-resolve@^5.17.3, enh graceful-fs "^4.2.4" tapable "^2.2.0" +enhanced-resolve@^5.18.3: + version "5.19.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz#6687446a15e969eaa63c2fa2694510e17ae6d97c" + integrity sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.3.0" + enquirer@^2.3.6, enquirer@~2.3.6: version "2.3.6" resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" @@ -11436,6 +11562,11 @@ jiti@^1.21.7: resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz" integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A== +jiti@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.6.1.tgz#178ef2fc9a1a594248c20627cd820187a4d78d92" + integrity sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ== + jose@^4.14.6: version "4.15.4" resolved "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz" @@ -11804,6 +11935,80 @@ license-webpack-plugin@^4.0.2: dependencies: webpack-sources "^3.0.0" +lightningcss-android-arm64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz#6966b7024d39c94994008b548b71ab360eb3a307" + integrity sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A== + +lightningcss-darwin-arm64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz#a5fa946d27c029e48c7ff929e6e724a7de46eb2c" + integrity sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA== + +lightningcss-darwin-x64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz#5ce87e9cd7c4f2dcc1b713f5e8ee185c88d9b7cd" + integrity sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ== + +lightningcss-freebsd-x64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz#6ae1d5e773c97961df5cff57b851807ef33692a5" + integrity sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA== + +lightningcss-linux-arm-gnueabihf@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz#62c489610c0424151a6121fa99d77731536cdaeb" + integrity sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA== + +lightningcss-linux-arm64-gnu@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz#2a3661b56fe95a0cafae90be026fe0590d089298" + integrity sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A== + +lightningcss-linux-arm64-musl@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz#d7ddd6b26959245e026bc1ad9eb6aa983aa90e6b" + integrity sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA== + +lightningcss-linux-x64-gnu@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz#5a89814c8e63213a5965c3d166dff83c36152b1a" + integrity sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w== + +lightningcss-linux-x64-musl@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz#808c2e91ce0bf5d0af0e867c6152e5378c049728" + integrity sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA== + +lightningcss-win32-arm64-msvc@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz#ab4a8a8a2e6a82a4531e8bbb6bf0ff161ee6625a" + integrity sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ== + +lightningcss-win32-x64-msvc@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz#f01f382c8e0a27e1c018b0bee316d210eac43b6e" + integrity sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw== + +lightningcss@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.30.2.tgz#4ade295f25d140f487d37256f4cd40dc607696d0" + integrity sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ== + dependencies: + detect-libc "^2.0.3" + optionalDependencies: + lightningcss-android-arm64 "1.30.2" + lightningcss-darwin-arm64 "1.30.2" + lightningcss-darwin-x64 "1.30.2" + lightningcss-freebsd-x64 "1.30.2" + lightningcss-linux-arm-gnueabihf "1.30.2" + lightningcss-linux-arm64-gnu "1.30.2" + lightningcss-linux-arm64-musl "1.30.2" + lightningcss-linux-x64-gnu "1.30.2" + lightningcss-linux-x64-musl "1.30.2" + lightningcss-win32-arm64-msvc "1.30.2" + lightningcss-win32-x64-msvc "1.30.2" + lilconfig@2.1.0, lilconfig@^2.0.3, lilconfig@^2.0.5, lilconfig@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz" @@ -12122,7 +12327,7 @@ magic-string@0.30.1: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" -magic-string@^0.30.3, magic-string@^0.30.5: +magic-string@^0.30.21, magic-string@^0.30.3, magic-string@^0.30.5: version "0.30.21" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz" integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== @@ -13975,7 +14180,7 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^ resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.38, postcss@^8.4.43, postcss@^8.4.47, postcss@^8.5.6: +postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.38, postcss@^8.4.41, postcss@^8.4.43, postcss@^8.4.47, postcss@^8.5.6: version "8.5.6" resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz" integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== @@ -15881,6 +16086,11 @@ tailwindcss@3: resolve "^1.22.8" sucrase "^3.35.0" +tailwindcss@4.1.18: + version "4.1.18" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.1.18.tgz#f488ba47853abdb5354daf9679d3e7791fc4f4e3" + integrity sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw== + tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1, tapable@^2.3.0: version "2.3.0" resolved "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz"