feature/research-di #1
20
components.json
Normal file
20
components.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "new-york",
|
||||
"rsc": true,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
"css": "src/app/globals.css",
|
||||
"baseColor": "zinc",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
}
|
||||
}
|
@ -9,10 +9,16 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-icons": "^1.3.1",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.454.0",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
"react-dom": "19.0.0-rc-69d4b800-20241021",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"tailwind-merge": "^2.5.4",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tsyringe": "^4.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -1,10 +1,12 @@
|
||||
"use client"
|
||||
import BaseView, { BuildProps } from "@/bootstrap/helpers/view/base-view";
|
||||
import ButtonVm from "@/components/button/button-vm";
|
||||
import ButtonVm from "@/app/components/button/button-vm";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
export default class Button extends BaseView<ButtonVm> {
|
||||
protected Build(props: BuildProps<ButtonVm>): ReactNode {
|
||||
const {vm} = props
|
||||
|
||||
return <button onClick={vm.onClick} >{vm.props.title}</button>
|
||||
}
|
||||
}
|
@ -2,20 +2,71 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@layer base {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 240 10% 3.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 240 10% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 240 10% 3.9%;
|
||||
--primary: 240 5.9% 10%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 240 4.8% 95.9%;
|
||||
--secondary-foreground: 240 5.9% 10%;
|
||||
--muted: 240 4.8% 95.9%;
|
||||
--muted-foreground: 240 3.8% 46.1%;
|
||||
--accent: 240 4.8% 95.9%;
|
||||
--accent-foreground: 240 5.9% 10%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 240 5.9% 90%;
|
||||
--input: 240 5.9% 90%;
|
||||
--ring: 240 10% 3.9%;
|
||||
--chart-1: 12 76% 61%;
|
||||
--chart-2: 173 58% 39%;
|
||||
--chart-3: 197 37% 24%;
|
||||
--chart-4: 43 74% 66%;
|
||||
--chart-5: 27 87% 67%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
.dark {
|
||||
--background: 240 10% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 240 10% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 240 10% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 240 5.9% 10%;
|
||||
--secondary: 240 3.7% 15.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 240 3.7% 15.9%;
|
||||
--muted-foreground: 240 5% 64.9%;
|
||||
--accent: 240 3.7% 15.9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 240 3.7% 15.9%;
|
||||
--input: 240 3.7% 15.9%;
|
||||
--ring: 240 4.9% 83.9%;
|
||||
--chart-1: 220 70% 50%;
|
||||
--chart-2: 160 60% 45%;
|
||||
--chart-3: 30 80% 55%;
|
||||
--chart-4: 280 65% 60%;
|
||||
--chart-5: 340 75% 55%;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--foreground);
|
||||
background: var(--background);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import "reflect-metadata"
|
||||
import type { Metadata } from "next";
|
||||
import localFont from "next/font/local";
|
||||
import "./globals.css";
|
||||
|
13
src/app/test/client/view/parent-view.tsx
Normal file
13
src/app/test/client/view/parent-view.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
"use client"
|
||||
import Button from "@/app/components/button/button"
|
||||
import { TestButtonVM } from "@/app/test/client/vm/test-button-vm"
|
||||
import { useDI } from "@/bootstrap/di/di-context"
|
||||
import { useRef } from "react"
|
||||
|
||||
export default function ParentView() {
|
||||
const di = useDI()
|
||||
|
||||
const vmRef = useRef(di.resolve(TestButtonVM))
|
||||
|
||||
return <Button vm={vmRef.current} />
|
||||
}
|
34
src/app/test/client/vm/test-button-vm.ts
Normal file
34
src/app/test/client/vm/test-button-vm.ts
Normal file
@ -0,0 +1,34 @@
|
||||
"use client"
|
||||
import BaseVM from "@/bootstrap/helpers/vm/base-vm";
|
||||
import ButtonVm from "@/app/components/button/button-vm";
|
||||
import { useEffect, useState } from "react";
|
||||
import getButtonTitle from "@/feature/domain/test/service/test-get-button-title-service";
|
||||
|
||||
export class TestButtonVM extends BaseVM<ButtonVm> {
|
||||
private getButtonTitle: () => Promise<string>
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.getButtonTitle = this.di.resolve(getButtonTitle.name)
|
||||
}
|
||||
|
||||
useVM(): ButtonVm {
|
||||
const [ buttonTitle, setTitle ] = useState("Default title")
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const title = await this.getButtonTitle()
|
||||
setTitle(title)
|
||||
})()
|
||||
}, [])
|
||||
return {
|
||||
props: {
|
||||
title: buttonTitle
|
||||
},
|
||||
onClick: () => {
|
||||
console.log("clicked on the button");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const testKey = "testKey"
|
10
src/app/test/layout.tsx
Normal file
10
src/app/test/layout.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
"use client"
|
||||
import testAppModule from "@/app/test/modules/test-app-module";
|
||||
import { DiContext } from "@/bootstrap/di/di-context";
|
||||
import { PropsWithChildren, useRef } from "react";
|
||||
|
||||
export default function WithDILayout(props: PropsWithChildren) {
|
||||
const testDi = useRef(testAppModule())
|
||||
return <DiContext.Provider value={testDi.current}>{props.children}</DiContext.Provider>
|
||||
}
|
||||
|
13
src/app/test/modules/test-app-module.ts
Normal file
13
src/app/test/modules/test-app-module.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { TestButtonVM, testKey } from "@/app/test/client/vm/test-button-vm";
|
||||
import di from "@/bootstrap/di/init-di"
|
||||
import getButtonTitle from "@/feature/domain/test/service/test-get-button-title-service";
|
||||
|
||||
export default function testAppModule() {
|
||||
const testDi = di.createChildContainer()
|
||||
|
||||
testDi.registerInstance(testKey, TestButtonVM);
|
||||
testDi.register(getButtonTitle.name, {
|
||||
useValue: getButtonTitle
|
||||
})
|
||||
return testDi
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
"use client"
|
||||
import "reflect-metadata"
|
||||
import TestButtonVM from "@/app/test/vm/test-button-vm";
|
||||
import Button from "@/components/button/button";
|
||||
import ParentView from "@/app/test/client/view/parent-view";
|
||||
|
||||
export default function Page() {
|
||||
return <Button vmName={TestButtonVM.name} />
|
||||
return <ParentView />
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import BaseVM from "@/bootstrap/helpers/vm/base-vm";
|
||||
import injectableVm from "@/bootstrap/helpers/vm/vm-decorator";
|
||||
import ButtonVm from "@/components/button/button-vm";
|
||||
|
||||
@injectableVm()
|
||||
export default class TestButtonVM extends BaseVM<ButtonVm> {
|
||||
useVM(): ButtonVm {
|
||||
return {
|
||||
props: {
|
||||
title: "Test Button"
|
||||
},
|
||||
onClick: () => {
|
||||
console.log("clicked on the button");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
src/bootstrap/di/di-context.tsx
Normal file
21
src/bootstrap/di/di-context.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
"use client"
|
||||
import di from "@/bootstrap/di/init-di";
|
||||
import { createContext, use } from "react";
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
const DiContext = createContext<null | DependencyContainer>(di)
|
||||
|
||||
const useDI = () => {
|
||||
const di = use(DiContext)
|
||||
|
||||
if (!di) {
|
||||
throw new Error("Di has not provided")
|
||||
}
|
||||
|
||||
return di
|
||||
}
|
||||
|
||||
export {
|
||||
DiContext,
|
||||
useDI,
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// "use client"
|
||||
import "reflect-metadata"
|
||||
|
||||
import { container, DependencyContainer } from "tsyringe";
|
||||
|
||||
/**
|
||||
@ -8,7 +8,7 @@ import { container, DependencyContainer } from "tsyringe";
|
||||
* are registered and available for injection throughout the application.
|
||||
*/
|
||||
const InitDI = (): DependencyContainer => {
|
||||
const di = container;
|
||||
const di = container.createChildContainer();
|
||||
|
||||
return di;
|
||||
};
|
||||
|
@ -1,17 +1,17 @@
|
||||
"use client"
|
||||
// import gdi from "@/bootstrap/di/init-di";
|
||||
/* eslint-disable react/display-name */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable react/jsx-props-no-spreading */
|
||||
import di from "@/bootstrap/di/init-di";
|
||||
import BaseVM from "@/bootstrap/helpers/vm/base-vm";
|
||||
import { Component, ReactNode, FC, PropsWithChildren, memo, MemoExoticComponent } from "react";
|
||||
import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm";
|
||||
import { Component, ReactNode, FC, PropsWithChildren, memo } from "react";
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Connector Component */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
interface IVvmConnector<IVM, PROPS> extends PropsWithChildren {
|
||||
View: FC<any & { vm: IVM }>;
|
||||
vmName: string;
|
||||
Vm: IBaseVM<IVM>;
|
||||
restProps?: PROPS;
|
||||
memoizedByVM?: boolean;
|
||||
}
|
||||
@ -21,11 +21,9 @@ interface IVvmConnector<IVM, PROPS> extends PropsWithChildren {
|
||||
*/
|
||||
const VvmConnector = memo(
|
||||
<IVM, PROPS>(props: IVvmConnector<IVM, PROPS>) => {
|
||||
const { View, vmName, restProps, children } = props;
|
||||
const VmInstance = di.resolve(vmName) as new () => BaseVM<IVM>;
|
||||
if (!VmInstance) throw new Error(`Provided vm as ${vmName} is not exists`)
|
||||
const { View, Vm, restProps, children } = props;
|
||||
|
||||
const vm = new VmInstance().useVM()
|
||||
const vm = Vm.useVM()
|
||||
|
||||
const allProps = {
|
||||
restProps,
|
||||
@ -46,8 +44,8 @@ const VvmConnector = memo(
|
||||
type IVMParent = Record<string, any>;
|
||||
type IPropParent = Record<string, any> | undefined;
|
||||
|
||||
type BaseProps<PROPS extends IPropParent = undefined> = {
|
||||
vmName: string;
|
||||
type BaseProps<IVM extends IVMParent, PROPS extends IPropParent = undefined> = {
|
||||
vm: IBaseVM<IVM>;
|
||||
restProps?: PROPS;
|
||||
/**
|
||||
* By default it's true.
|
||||
@ -70,25 +68,23 @@ export type BuildProps<
|
||||
export default abstract class BaseView<
|
||||
IVM extends IVMParent,
|
||||
PROPS extends IPropParent = undefined,
|
||||
> extends Component<BaseProps<PROPS>> {
|
||||
> extends Component<BaseProps<IVM, PROPS>> {
|
||||
/* -------------------------------- Abstracts ------------------------------- */
|
||||
protected abstract Build(props: BuildProps<IVM, PROPS>): ReactNode;
|
||||
|
||||
/* -------------------------------- Renderer -------------------------------- */
|
||||
render(): ReactNode {
|
||||
const { vmName, restProps, memoizedByVM, children, ...rest } = this.props;
|
||||
|
||||
const Connector = VvmConnector as MemoExoticComponent<((props: IVvmConnector<IVM, PROPS>) => JSX.Element)>;
|
||||
const { vm, restProps, memoizedByVM, children, ...rest } = this.props;
|
||||
|
||||
return (
|
||||
<Connector
|
||||
<VvmConnector
|
||||
View={this.Build}
|
||||
vmName={vmName}
|
||||
Vm={vm}
|
||||
memoizedByVM={typeof memoizedByVM === "undefined" ? true : memoizedByVM}
|
||||
restProps={{ ...restProps, ...rest } as PROPS}
|
||||
restProps={{ ...restProps, ...rest }}
|
||||
>
|
||||
{children}
|
||||
</Connector>
|
||||
</VvmConnector>
|
||||
);
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -1,4 +1,5 @@
|
||||
"use client"
|
||||
import { useDI } from "@/bootstrap/di/di-context";
|
||||
import { NoOverride } from "@/bootstrap/helpers/type-helper";
|
||||
import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm";
|
||||
import { useState } from "react";
|
||||
@ -28,6 +29,10 @@ export default abstract class BaseVM<
|
||||
*/
|
||||
protected rerender?: () => void;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
protected get di() {
|
||||
return useDI()
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/**
|
||||
* You can use this hook in your useVm method to get rerender method
|
||||
|
@ -1,9 +0,0 @@
|
||||
"use client"
|
||||
import di from "@/bootstrap/di/init-di";
|
||||
import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm";
|
||||
|
||||
export default function injectableVm() {
|
||||
return function (target: new (...args: unknown[]) => IBaseVM<object>) {
|
||||
di.registerInstance(target.name, target);
|
||||
};
|
||||
}
|
13
src/feature/common/server-di.ts
Normal file
13
src/feature/common/server-di.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { testModuleKey } from "@/feature/domain/test/test-module-key";
|
||||
import getTestModule from "@/feature/infra/test/module/test-module";
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
export default function serverDi(module: string): DependencyContainer {
|
||||
const getDi = {
|
||||
[testModuleKey]: getTestModule
|
||||
}[module]
|
||||
|
||||
if (!getDi) throw new Error("Server Di didn't found for module: " + module)
|
||||
|
||||
return getDi()
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
"use server"
|
||||
import serverDi from "@/feature/common/server-di";
|
||||
import TestRepo, { testRepoKey } from "@/feature/domain/test/service/test-service-repo"
|
||||
import { testModuleKey } from "@/feature/domain/test/test-module-key";
|
||||
|
||||
export default async function getButtonTitle() {
|
||||
const repo = serverDi(testModuleKey).resolve<TestRepo>(testRepoKey)
|
||||
return repo.getButtonTitle()
|
||||
}
|
5
src/feature/domain/test/service/test-service-repo.ts
Normal file
5
src/feature/domain/test/service/test-service-repo.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export default interface TestRepo {
|
||||
getButtonTitle(): Promise<string>
|
||||
}
|
||||
|
||||
export const testRepoKey = "restRepoKey"
|
1
src/feature/domain/test/test-module-key.ts
Normal file
1
src/feature/domain/test/test-module-key.ts
Normal file
@ -0,0 +1 @@
|
||||
export const testModuleKey = "testModuleKey"
|
12
src/feature/infra/test/module/test-module.ts
Normal file
12
src/feature/infra/test/module/test-module.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import di from "@/bootstrap/di/init-di"
|
||||
import { testRepoKey } from "@/feature/domain/test/service/test-service-repo"
|
||||
import TestRepoImpl from "@/feature/infra/test/repo/test-repo-iml"
|
||||
|
||||
export default function getTestModule() {
|
||||
const testDi = di.createChildContainer()
|
||||
|
||||
di.register(testRepoKey, {
|
||||
useClass: TestRepoImpl
|
||||
})
|
||||
return testDi
|
||||
}
|
14
src/feature/infra/test/repo/test-repo-iml.ts
Normal file
14
src/feature/infra/test/repo/test-repo-iml.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import TestRepo from "@/feature/domain/test/service/test-service-repo";
|
||||
|
||||
export default class TestRepoImpl implements TestRepo {
|
||||
async getButtonTitle(): Promise<string> {
|
||||
await new Promise((res) => {
|
||||
setTimeout(() => {
|
||||
res(true)
|
||||
}, 3000)
|
||||
})
|
||||
console.log('hereee');
|
||||
return Promise.resolve("Button title")
|
||||
}
|
||||
|
||||
}
|
6
src/lib/utils.ts
Normal file
6
src/lib/utils.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
import type { Config } from "tailwindcss";
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
@ -9,11 +11,54 @@ const config: Config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
background: "var(--background)",
|
||||
foreground: "var(--foreground)",
|
||||
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))'
|
||||
},
|
||||
plugins: [],
|
||||
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))'
|
||||
}
|
||||
},
|
||||
borderRadius: {
|
||||
lg: 'var(--radius)',
|
||||
md: 'calc(var(--radius) - 2px)',
|
||||
sm: 'calc(var(--radius) - 4px)'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
};
|
||||
export default config;
|
||||
|
37
yarn.lock
37
yarn.lock
@ -305,6 +305,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@radix-ui/react-icons@^1.3.1":
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.3.1.tgz#462c85fd726a77854cd5956e29eb19a575aa7ce5"
|
||||
integrity sha512-QvYompk0X+8Yjlo/Fv4McrzxohDdM5GgLHyQcPpcsPvlOSXCGFjdbuyGL5dzRbg0GpknAjQJJZzdiRK7iWVuFQ==
|
||||
|
||||
"@rtsao/scc@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
|
||||
@ -714,11 +719,28 @@ chokidar@^3.5.3:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
class-variance-authority@^0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.0.tgz#1c3134d634d80271b1837452b06d821915954522"
|
||||
integrity sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==
|
||||
dependencies:
|
||||
clsx "2.0.0"
|
||||
|
||||
client-only@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
|
||||
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
|
||||
|
||||
clsx@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b"
|
||||
integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==
|
||||
|
||||
clsx@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
|
||||
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
|
||||
|
||||
color-convert@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
|
||||
@ -1871,6 +1893,11 @@ lru-cache@^10.2.0:
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
|
||||
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
|
||||
|
||||
lucide-react@^0.454.0:
|
||||
version "0.454.0"
|
||||
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.454.0.tgz#a81b9c482018720f07ead0503ae502d94d528444"
|
||||
integrity sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ==
|
||||
|
||||
merge2@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
@ -2599,6 +2626,16 @@ supports-preserve-symlinks-flag@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
tailwind-merge@^2.5.4:
|
||||
version "2.5.4"
|
||||
resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.5.4.tgz#4bf574e81fa061adeceba099ae4df56edcee78d1"
|
||||
integrity sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==
|
||||
|
||||
tailwindcss-animate@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4"
|
||||
integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==
|
||||
|
||||
tailwindcss@^3.4.1:
|
||||
version "3.4.14"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.14.tgz#6dd23a7f54ec197b19159e91e3bb1e55e7aa73ac"
|
||||
|
Loading…
x
Reference in New Issue
Block a user