feat: image filter
This commit is contained in:
parent
7242a0afab
commit
67fe4ba060
10 changed files with 38350 additions and 1079 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
import "styles/tailwind.css"
|
import "styles/tailwind.css"
|
||||||
import "styles/custom.css"
|
import "styles/custom.css"
|
||||||
import Navbar from "components/Navbar/Navbar"
|
import Navbar from "components/Navbar/Navbar"
|
||||||
import StarBackground from "components/StarBackground/StarBackground";
|
|
||||||
import Footer from "components/Footer/Footer"
|
import Footer from "components/Footer/Footer"
|
||||||
|
|
||||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
|
|
||||||
51
app/page.tsx
51
app/page.tsx
|
|
@ -13,6 +13,7 @@ import { MdOutlineAppSettingsAlt } from "react-icons/md"
|
||||||
import { Glow, GlowCapture } from "@codaworks/react-glow"
|
import { Glow, GlowCapture } from "@codaworks/react-glow"
|
||||||
import StarBackground from "components/StarBackground/StarBackground"
|
import StarBackground from "components/StarBackground/StarBackground"
|
||||||
import { Textarea } from "@nextui-org/react"
|
import { Textarea } from "@nextui-org/react"
|
||||||
|
import ImageFilter from "components/ImageFilter/ImageFilter"
|
||||||
|
|
||||||
export default function Web() {
|
export default function Web() {
|
||||||
const [init, setInit] = useState(false)
|
const [init, setInit] = useState(false)
|
||||||
|
|
@ -25,7 +26,7 @@ export default function Web() {
|
||||||
<div>
|
<div>
|
||||||
<section className="bg-[#0f172a] md:pl-0 md:pr-0 lg:pl-[15%] lg:pr-[15%]">
|
<section className="bg-[#0f172a] md:pl-0 md:pr-0 lg:pl-[15%] lg:pr-[15%]">
|
||||||
<div
|
<div
|
||||||
className=" h-[80%] rounded-[3rem] pt-[10%]"
|
className=" h-[80%] rounded-[3rem] pt-[10%] max-md:rounded-none"
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: `url('/images/glow-bottom.svg')`,
|
backgroundImage: `url('/images/glow-bottom.svg')`,
|
||||||
backgroundSize: "fill",
|
backgroundSize: "fill",
|
||||||
|
|
@ -73,7 +74,7 @@ export default function Web() {
|
||||||
</section>
|
</section>
|
||||||
<section className="bg-[#0f172a] md:pl-0 md:pr-0 lg:pl-[15%] lg:pr-[15%]">
|
<section className="bg-[#0f172a] md:pl-0 md:pr-0 lg:pl-[15%] lg:pr-[15%]">
|
||||||
<div
|
<div
|
||||||
className=" h-[60%] rounded-[3rem]"
|
className=" h-[60%] rounded-[3rem] max-md:rounded-none"
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: `url('/images/glow-top.svg')`,
|
backgroundImage: `url('/images/glow-top.svg')`,
|
||||||
backgroundSize: "cover",
|
backgroundSize: "cover",
|
||||||
|
|
@ -81,7 +82,7 @@ export default function Web() {
|
||||||
backgroundRepeat: "no-repeat",
|
backgroundRepeat: "no-repeat",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex w-[100%] items-center justify-around pb-[10vh] pt-[5vh]">
|
<div className="flex w-[100%] items-center justify-around pb-[10vh] pt-[5vh] max-md:flex-wrap">
|
||||||
<div className="mx-auto max-w-screen-xl px-4 py-8 lg:py-16">
|
<div className="mx-auto max-w-screen-xl px-4 py-8 lg:py-16">
|
||||||
<div className="mx-auto text-left text-white">
|
<div className="mx-auto text-left text-white">
|
||||||
<h4 className="bg-gradient-to-r from-vizoleG1 via-vizoleG2 to-vizoleG3 bg-clip-text pt-20 font-bold text-transparent ">
|
<h4 className="bg-gradient-to-r from-vizoleG1 via-vizoleG2 to-vizoleG3 bg-clip-text pt-20 font-bold text-transparent ">
|
||||||
|
|
@ -127,8 +128,7 @@ export default function Web() {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<iframe
|
<iframe
|
||||||
width="560"
|
className="h-[315px] w-[560px] max-md:h-[14rem] max-md:w-[25rem]"
|
||||||
height="315"
|
|
||||||
src="https://www.youtube.com/embed/_vhf0RZg0fg"
|
src="https://www.youtube.com/embed/_vhf0RZg0fg"
|
||||||
title="YouTube video player"
|
title="YouTube video player"
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||||
|
|
@ -137,14 +137,16 @@ export default function Web() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section className="mt-[3%] bg-[#0f172a] md:pl-0 md:pr-0 lg:pl-[10%] lg:pr-[10%]">
|
<section className="mt-[3%] bg-[#0f172a] max-md:p-4 md:pl-0 md:pr-0 lg:pl-[10%] lg:pr-[10%]">
|
||||||
<div>
|
<div>
|
||||||
<GlowCapture>
|
<GlowCapture>
|
||||||
<div className="flex flex-col items-center justify-around">
|
<div className="flex flex-col items-center justify-around">
|
||||||
<div className="mb-4 max-w-3xl text-center text-4xl font-extrabold capitalize leading-none tracking-tight text-white md:text-4xl xl:text-5xl">
|
<div className="mb-4 max-w-3xl text-center text-4xl font-extrabold capitalize leading-none tracking-tight text-white md:text-4xl xl:text-5xl">
|
||||||
<h2 className="">Our Services</h2>
|
<h2 className="bg-gradient-to-r from-slate-400 via-white to-slate-400 bg-clip-text text-transparent">
|
||||||
|
Our Services
|
||||||
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<p className="mb-6 max-w-2xl text-center font-light text-gray-200 md:text-lg lg:mb-8 lg:text-xl">
|
<p className="mb-6 max-w-2xl text-center font-light text-[#94a3b8] md:text-lg lg:mb-8 lg:text-xl">
|
||||||
Let us transform your vision into reality with cutting-edge VR/AR experiences and custom software
|
Let us transform your vision into reality with cutting-edge VR/AR experiences and custom software
|
||||||
solutions powered by AI.
|
solutions powered by AI.
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -189,7 +191,7 @@ export default function Web() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Glow>
|
</Glow>
|
||||||
<Glow color="#F5887A">
|
<Glow color="#F0B37D">
|
||||||
<div className=" glowable-text flex max-w-[100%] items-center rounded-[20px] border p-4 glow:border-glow glow:bg-glow/[.50] glow:ring-2 glow:ring-glow">
|
<div className=" glowable-text flex max-w-[100%] items-center rounded-[20px] border p-4 glow:border-glow glow:bg-glow/[.50] glow:ring-2 glow:ring-glow">
|
||||||
<div className=" text-center">
|
<div className=" text-center">
|
||||||
<div className="mr-3 inline-flex flex-shrink-0 items-center justify-center rounded-full px-5 ">
|
<div className="mr-3 inline-flex flex-shrink-0 items-center justify-center rounded-full px-5 ">
|
||||||
|
|
@ -228,7 +230,7 @@ export default function Web() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Glow>
|
</Glow>
|
||||||
<Glow color="#C37EB6">
|
<Glow color="#F0B37D">
|
||||||
<div className=" glowable-text flex max-w-[100%] items-center rounded-[20px] border p-4 glow:border-glow glow:bg-glow/[.50] glow:ring-2 glow:ring-glow">
|
<div className=" glowable-text flex max-w-[100%] items-center rounded-[20px] border p-4 glow:border-glow glow:bg-glow/[.50] glow:ring-2 glow:ring-glow">
|
||||||
<div className=" text-center">
|
<div className=" text-center">
|
||||||
<div className="mr-3 inline-flex flex-shrink-0 items-center justify-center rounded-full px-5 ">
|
<div className="mr-3 inline-flex flex-shrink-0 items-center justify-center rounded-full px-5 ">
|
||||||
|
|
@ -267,7 +269,7 @@ export default function Web() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Glow>
|
</Glow>
|
||||||
<Glow color="#D30253">
|
<Glow color="#F0B37D">
|
||||||
<div className=" glowable-text flex max-w-[100%] items-center rounded-[20px] border p-4 glow:border-glow glow:bg-glow/[.50] glow:ring-2 glow:ring-glow">
|
<div className=" glowable-text flex max-w-[100%] items-center rounded-[20px] border p-4 glow:border-glow glow:bg-glow/[.50] glow:ring-2 glow:ring-glow">
|
||||||
<div className=" text-center">
|
<div className=" text-center">
|
||||||
<div className="mr-3 inline-flex flex-shrink-0 items-center justify-center rounded-full px-5 ">
|
<div className="mr-3 inline-flex flex-shrink-0 items-center justify-center rounded-full px-5 ">
|
||||||
|
|
@ -311,36 +313,19 @@ export default function Web() {
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="h-[150vh] bg-[#0f172a] pl-[10%] pr-[10%] pt-40">
|
<section className="mb-32 h-[150vh] bg-[#0f172a] pl-[10%] pr-[10%] pt-40">
|
||||||
<div className="mx-auto place-self-center text-center">
|
<div className="mx-auto place-self-center text-center">
|
||||||
<div className="mb-4 text-center text-4xl font-extrabold capitalize leading-none tracking-tight text-white md:text-4xl xl:text-5xl">
|
<div className="mb-4 text-center text-4xl font-extrabold capitalize leading-none tracking-tight text-white md:text-4xl xl:text-5xl">
|
||||||
<h1 className="">Our Portfolio</h1>
|
<h1 className="bg-gradient-to-r from-slate-400 via-white to-slate-400 bg-clip-text text-transparent">
|
||||||
|
Our Portfolio
|
||||||
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<p className="pl-5 pr-5 text-2xl text-white">
|
<p className="pl-5 pr-5 text-2xl text-white">
|
||||||
The showcase of our innovations. Dive in to explore our diverse range of projects and see how we’re driving
|
The showcase of our innovations. Dive in to explore our diverse range of projects and see how we’re driving
|
||||||
digital transformation across industries.”
|
digital transformation across industries.”
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-4 md:grid-cols-3">
|
<ImageFilter />
|
||||||
<div className="mt-10 flex max-w-full rounded-xl border border-gray-200 bg-transparent shadow dark:border-gray-700 dark:bg-gray-800">
|
|
||||||
<img className="h-auto max-w-full rounded-lg" src="/images/site01.png" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="mt-10 flex max-w-full rounded-xl border border-gray-200 bg-transparent shadow dark:border-gray-700 dark:bg-gray-800">
|
|
||||||
<img className="h-auto max-w-full rounded-lg" src="/images/site02.png" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="mt-10 flex max-w-full rounded-xl border border-gray-200 bg-transparent shadow dark:border-gray-700 dark:bg-gray-800">
|
|
||||||
<img className="h-auto max-w-full rounded-lg" src="/images/site03.png" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="mt-10 flex max-w-full rounded-xl border border-gray-200 bg-transparent shadow dark:border-gray-700 dark:bg-gray-800">
|
|
||||||
<img className="h-auto max-w-full rounded-lg" src="/images/site01.png" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="mt-10 flex max-w-full rounded-xl border border-gray-200 bg-transparent shadow dark:border-gray-700 dark:bg-gray-800">
|
|
||||||
<img className="h-auto max-w-full rounded-lg" src="/images/site02.png" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="flex] mt-10 max-w-full rounded-xl border border-gray-200 bg-transparent shadow dark:border-gray-700 dark:bg-gray-800">
|
|
||||||
<img className="h-auto max-w-full rounded-lg" src="/images/site03.png" alt="" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="bg-[#0f172a] dark:bg-gray-900">
|
<section className="bg-[#0f172a] dark:bg-gray-900">
|
||||||
|
|
|
||||||
|
|
@ -2,37 +2,67 @@ import { cva, type VariantProps } from "class-variance-authority"
|
||||||
|
|
||||||
import { twMerge } from "tailwind-merge"
|
import { twMerge } from "tailwind-merge"
|
||||||
|
|
||||||
const button = cva(
|
const button = cva(["inline-flex", "items-center", "rounded-xl", "text-center", "transition-colors", "delay-50"], {
|
||||||
[
|
variants: {
|
||||||
|
intent: {
|
||||||
"inline-flex",
|
primary: ["bg-blue-400", "justify-center", "text-white", "hover:enabled:bg-blue-700"],
|
||||||
"items-center",
|
secondary: [
|
||||||
"rounded-xl",
|
"bg-transparent",
|
||||||
"text-center",
|
"justify-center",
|
||||||
"transition-colors",
|
"text-white",
|
||||||
"delay-50",
|
"hover:bg-slate-100",
|
||||||
],
|
"rounded-3xl",
|
||||||
{
|
"hover:text-vizoleG2",
|
||||||
variants: {
|
"border-solid",
|
||||||
intent: {
|
"border-2",
|
||||||
primary: ["bg-blue-400", "justify-center", "text-white", "hover:enabled:bg-blue-700"],
|
"border-slate-100",
|
||||||
secondary: ["bg-transparent", "justify-center", "text-white", "hover:bg-slate-100", "rounded-3xl", "hover:text-vizoleG2", "border-solid", "border-2", "border-slate-100"],
|
],
|
||||||
hero1: ["text-black", "bg-white", "justify-center","font-medium", "rounded-3xl", "text-sm", "text-center", "me-2", "mb-2", "border-solid", "border-2", "border-slate-100"],
|
hero1: [
|
||||||
aboutUs: ["text-left","bg-transparent", "text-white", "font-semibold", "hover:text-white", "py-2", "px-4", "border", "border-gray-400","transition-all", "hover:border-white", "rounded", "flex", , "my-1","w-[50%]"]
|
"text-black",
|
||||||
},
|
"bg-white",
|
||||||
size: {
|
"justify-center",
|
||||||
sm: ["min-w-20", "h-full", "min-h-10", "text-sm", "py-1.5", "px-4"],
|
"font-medium",
|
||||||
lg: ["min-w-32", "h-full", "min-h-12", "text-lg", "py-2.5", "px-6"],
|
"rounded-3xl",
|
||||||
hero1: ["min-w-15", "h-full", "min-h-5", "text-sm", "px-5", "py-2"]
|
"text-sm",
|
||||||
},
|
"text-center",
|
||||||
underline: { true: ["underline"], false: [] },
|
"me-2",
|
||||||
|
"mb-2",
|
||||||
|
"border-solid",
|
||||||
|
"border-2",
|
||||||
|
"border-slate-100",
|
||||||
|
],
|
||||||
|
aboutUs: [
|
||||||
|
"text-left",
|
||||||
|
"bg-transparent",
|
||||||
|
"text-white",
|
||||||
|
"font-semibold",
|
||||||
|
"hover:text-white",
|
||||||
|
"py-2",
|
||||||
|
"px-4",
|
||||||
|
"border",
|
||||||
|
"border-gray-400",
|
||||||
|
"transition-all",
|
||||||
|
"hover:border-white",
|
||||||
|
"rounded",
|
||||||
|
"flex",
|
||||||
|
,
|
||||||
|
"my-1",
|
||||||
|
"w-[50%]",
|
||||||
|
"max-md:w-full",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
size: {
|
||||||
intent: "primary",
|
sm: ["min-w-20", "h-full", "min-h-10", "text-sm", "py-1.5", "px-4"],
|
||||||
size: "lg",
|
lg: ["min-w-32", "h-full", "min-h-12", "text-lg", "py-2.5", "px-6"],
|
||||||
|
hero1: ["min-w-15", "h-full", "min-h-5", "text-sm", "px-5", "py-2"],
|
||||||
},
|
},
|
||||||
}
|
underline: { true: ["underline"], false: [] },
|
||||||
)
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
intent: "primary",
|
||||||
|
size: "lg",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLAnchorElement>, VariantProps<typeof button> {
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLAnchorElement>, VariantProps<typeof button> {
|
||||||
underline?: boolean
|
underline?: boolean
|
||||||
|
|
|
||||||
26
components/ImageFilter/FilterableData.tsx
Normal file
26
components/ImageFilter/FilterableData.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
export const FilterableData = [
|
||||||
|
{
|
||||||
|
name: "Web",
|
||||||
|
src: "/images/site01.png",
|
||||||
|
title: "Mountains",
|
||||||
|
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UI/UX",
|
||||||
|
src: "/images/site02.png",
|
||||||
|
title: "BMW",
|
||||||
|
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Web",
|
||||||
|
src: "/images/site03.png",
|
||||||
|
title: "Modeller",
|
||||||
|
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Web",
|
||||||
|
src: "/images/site04.png",
|
||||||
|
title: "Billing App",
|
||||||
|
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||||
|
},
|
||||||
|
]
|
||||||
59
components/ImageFilter/ImageFilter.tsx
Normal file
59
components/ImageFilter/ImageFilter.tsx
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Button } from "components/Button/Button"
|
||||||
|
import { useState } from "react"
|
||||||
|
import { Image } from "./image"
|
||||||
|
import { FilterableData } from "./FilterableData"
|
||||||
|
import { motion } from "framer-motion" // Import motion
|
||||||
|
|
||||||
|
const ImageFilter = () => {
|
||||||
|
const [activeFilter, setActiveFilter] = useState<string>("all")
|
||||||
|
|
||||||
|
const buttonCaptions = ["all", "Web", "Mobile App", "UI/UX"]
|
||||||
|
|
||||||
|
const handleFilterClick = (filter: string) => {
|
||||||
|
setActiveFilter(filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="mb-3 flex w-full flex-col gap-12 px-5 py-16 md:px-10 lg:px-16">
|
||||||
|
<div className="flex w-full flex-wrap items-start gap-3 md:justify-center md:gap-6">
|
||||||
|
{buttonCaptions.map((filter) => (
|
||||||
|
<button
|
||||||
|
key={filter}
|
||||||
|
onClick={() => handleFilterClick(filter)}
|
||||||
|
type="button"
|
||||||
|
className={`mb-2 rounded-lg border-2 border-[#F0B37D] px-5 py-2.5 text-sm font-medium capitalize text-white hover:bg-[#F0B37D] focus:outline-none ${
|
||||||
|
activeFilter === filter ? "bg-[#F0B37D]" : " "
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{filter === "all" ? "Show all" : filter}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
{/* filtered cards display */}
|
||||||
|
</div>
|
||||||
|
<main className="grid w-full gap-x-5 gap-y-8 md:mt-8 md:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{FilterableData.map((item, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={index}
|
||||||
|
layout
|
||||||
|
className={`w-full cursor-pointer rounded-lg border border-gray-600 bg-gray-800 shadow ${
|
||||||
|
activeFilter === "all" || activeFilter === item.name
|
||||||
|
? "" /* Show card */
|
||||||
|
: "hidden" /* Hide if not matched */
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
className="h-[400px] w-full overflow-hidden rounded-lg"
|
||||||
|
image={item.src}
|
||||||
|
alt={item.name}
|
||||||
|
objectCover="object-cover"
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</main>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ImageFilter
|
||||||
25
components/ImageFilter/image.tsx
Normal file
25
components/ImageFilter/image.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
type ImageOwnProps<T extends React.ElementType> = {
|
||||||
|
className: string
|
||||||
|
image: string
|
||||||
|
alt: string
|
||||||
|
objectCover?: string
|
||||||
|
as?: T
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageProps<T extends React.ElementType> = ImageOwnProps<T> & Omit<React.ComponentProps<T>, keyof ImageOwnProps<T>>
|
||||||
|
|
||||||
|
export const Image = <T extends React.ElementType = "div">({
|
||||||
|
className,
|
||||||
|
image,
|
||||||
|
alt,
|
||||||
|
objectCover,
|
||||||
|
as,
|
||||||
|
...rest
|
||||||
|
}: ImageProps<T>) => {
|
||||||
|
const Component = as || "div"
|
||||||
|
return (
|
||||||
|
<Component className={className} {...rest}>
|
||||||
|
<img src={image} alt={alt} className={`h-full w-full ${objectCover}`} />
|
||||||
|
</Component>
|
||||||
|
)
|
||||||
|
}
|
||||||
37091
package-lock.json
generated
Normal file
37091
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -56,6 +56,7 @@
|
||||||
"@tsparticles/react": "^3.0.0",
|
"@tsparticles/react": "^3.0.0",
|
||||||
"@vercel/otel": "^0.3.0",
|
"@vercel/otel": "^0.3.0",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
|
"framer-motion": "^11.0.25",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"next": "^14.0.3",
|
"next": "^14.0.3",
|
||||||
"next-compose-plugins": "^2.2.1",
|
"next-compose-plugins": "^2.2.1",
|
||||||
|
|
|
||||||
BIN
public/images/site04.png
Normal file
BIN
public/images/site04.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 742 KiB |
Loading…
Add table
Add a link
Reference in a new issue