Fix auth form errors and redirects: Add React keys/useEffects for error rendering and scroll, Inertia::location in controllers for SPA navigation, extend RegistrationTest and add E2E. Update docs (changes/2025-10-02-registration-fixes.md, prp/13-backend-authentication.md). Add new UI components (accordion, carousel, progress, table, tabs), marketing/legal pages (Blog, Kontakt, Datenschutz, etc.), fonts, user migration (remove_name), views/css/package updates, seeders/factories.
This commit is contained in:
144
resources/js/components/ui/carousel.tsx
Normal file
144
resources/js/components/ui/carousel.tsx
Normal file
@@ -0,0 +1,144 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { ArrowLeft, ArrowRight } from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
import Autoplay from "embla-carousel-autoplay"
|
||||
import useEmblaCarousel from "embla-carousel-react"
|
||||
|
||||
interface CarouselApi {
|
||||
slideNodes(): HTMLElement[]
|
||||
on(event: string, listener: (...args: any[]) => void): void
|
||||
scrollPrev(): void
|
||||
scrollNext(): void
|
||||
reInit(): void
|
||||
}
|
||||
|
||||
const CarouselContext = React.createContext<CarouselApi | null>(null)
|
||||
|
||||
interface CarouselProps {
|
||||
opts?: {
|
||||
align?: "start" | "center" | "end"
|
||||
loop?: boolean
|
||||
}
|
||||
plugins?: any[]
|
||||
setApi?: (api: CarouselApi) => void
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
|
||||
({ opts, plugins = [Autoplay()], setApi, className, children, ...props }, ref) => {
|
||||
const [api, setApiInternal] = React.useState<CarouselApi | null>(null)
|
||||
const [current, setCurrent] = React.useState(0)
|
||||
const [count, setCount] = React.useState(0)
|
||||
|
||||
const [emblaRef] = useEmblaCarousel(opts, plugins)
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api) {
|
||||
return
|
||||
}
|
||||
|
||||
setCount(api.slideNodes().length)
|
||||
api.on("reInit", setCount)
|
||||
api.on("slideChanged", ({ slide }: { slide: number }) => setCurrent(slide))
|
||||
setApi?.(api)
|
||||
}, [api, setApi])
|
||||
|
||||
return (
|
||||
<CarouselContext.Provider value={api}>
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative w-full",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
className="overflow-hidden"
|
||||
ref={emblaRef}
|
||||
>
|
||||
<div className="flex">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</CarouselContext.Provider>
|
||||
)
|
||||
}
|
||||
)
|
||||
Carousel.displayName = "Carousel"
|
||||
|
||||
interface CarouselContentProps {
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
}
|
||||
|
||||
const CarouselContent = React.forwardRef<HTMLDivElement, CarouselContentProps>(
|
||||
({ children, className }, ref) => (
|
||||
<div ref={ref} className={cn("flex", className)}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
CarouselContent.displayName = "CarouselContent"
|
||||
|
||||
interface CarouselItemProps {
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
}
|
||||
|
||||
const CarouselItem = React.forwardRef<HTMLDivElement, CarouselItemProps>(
|
||||
({ children, className }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("min-w-0 shrink-0 grow-0 basis-full pl-4 md:pl-6", className)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
CarouselItem.displayName = "CarouselItem"
|
||||
|
||||
const CarouselPrevious = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
React.ButtonHTMLAttributes<HTMLButtonElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<Button
|
||||
ref={ref}
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className={cn(
|
||||
"absolute -left-1 top-1/2 -translate-y-1/2 rounded-full h-8 w-8 bg-background/80 backdrop-blur-sm hover:bg-background/90 disabled:pointer-events-none disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
<span className="sr-only">Previous slide</span>
|
||||
</Button>
|
||||
))
|
||||
CarouselPrevious.displayName = "CarouselPrevious"
|
||||
|
||||
const CarouselNext = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
React.ButtonHTMLAttributes<HTMLButtonElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<Button
|
||||
ref={ref}
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className={cn(
|
||||
"absolute -right-1 top-1/2 -translate-y-1/2 rounded-full h-8 w-8 bg-background/80 backdrop-blur-sm hover:bg-background/90 disabled:pointer-events-none disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
<span className="sr-only">Next slide</span>
|
||||
</Button>
|
||||
))
|
||||
CarouselNext.displayName = "CarouselNext"
|
||||
|
||||
export { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext }
|
||||
Reference in New Issue
Block a user