Initial commit
This commit is contained in:
336
packages/ui/README.md
Normal file
336
packages/ui/README.md
Normal file
@@ -0,0 +1,336 @@
|
||||
# UI Package
|
||||
|
||||
This package provides components that make up the UI.
|
||||
|
||||
## Installation
|
||||
|
||||
First, move to the page you want to use.
|
||||
|
||||
```shell
|
||||
cd pages/options
|
||||
```
|
||||
|
||||
Add the following to the dependencies in `package.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"@extension/ui": "workspace:*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then, run:
|
||||
|
||||
```shell
|
||||
pnpm install
|
||||
```
|
||||
|
||||
Add the following to the `tailwind.config.ts` file.
|
||||
|
||||
```ts
|
||||
import baseConfig from '@extension/tailwindcss-config';
|
||||
import { withUI } from '@extension/ui';
|
||||
|
||||
export default withUI({
|
||||
...baseConfig,
|
||||
content: ['./index.html', './src/**/*.tsx'],
|
||||
});
|
||||
```
|
||||
|
||||
Add the following to the first line of `index.css` file.
|
||||
|
||||
```css
|
||||
@import '@extension/ui/global.css';
|
||||
```
|
||||
|
||||
## Add Custom Component
|
||||
|
||||
Add the following to the `lib/components/index.ts` file.
|
||||
|
||||
```tsx
|
||||
export * from './CustomComponent.js';
|
||||
```
|
||||
|
||||
Add the following to the `lib/components/CustomComponent.tsx` file.
|
||||
|
||||
```tsx
|
||||
import { cn } from '@/lib/utils.js';
|
||||
import type { ComponentPropsWithoutRef } from 'react';
|
||||
|
||||
type CustomComponentProps = ComponentPropsWithoutRef<'section'>;
|
||||
|
||||
export const CustomComponent = ({ children, ...props }: CustomComponentProps) => {
|
||||
return <section {...props}>{children}</section>;
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
import { CustomComponent, ErrorDisplay, LoadingSpinner } from '@extension/ui';
|
||||
|
||||
const Page = () => {
|
||||
return <CustomComponent>Hi, I'm a custom component.</CustomComponent>;
|
||||
}
|
||||
|
||||
export default withErrorBoundary(withSuspense(Page, <LoadingSpinner />), ErrorDisplay);
|
||||
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> You are able to set other size of the loading spinner by passing the `size` prop to the `<LoadingSpinner />`.
|
||||
|
||||
## Modifying the tailwind config of the UI library
|
||||
|
||||
Modify the `tailwind.config.ts` file to make global style changes to the package.
|
||||
|
||||
## Modifying the css variable of the UI library
|
||||
|
||||
Modify the css variable in the `ui/lib/global.css` code to change the css variable of all pages(with UI).
|
||||
|
||||
## Guide for Adding shadcn to the UI Package
|
||||
|
||||
You can refer to the this [manual guide](https://ui.shadcn.com/docs/installation/manual)
|
||||
|
||||
1. Create components.json in packages/ui
|
||||
|
||||
Create a file named `components.json` in the `packages/ui` directory with the following content:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "new-york",
|
||||
"rsc": false,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
"css": "lib/global.css",
|
||||
"baseColor": "zinc",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/lib/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/lib/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/lib/hooks"
|
||||
},
|
||||
"iconLibrary": "lucide"
|
||||
}
|
||||
```
|
||||
|
||||
2. Install dependencies
|
||||
|
||||
Run the following command from the root of your project:
|
||||
|
||||
```shell
|
||||
pnpm add tailwindcss-animate class-variance-authority tailwind-merge lucide-react -F ui
|
||||
```
|
||||
|
||||
3. Edit `with-ui.ts` in `lib` folder
|
||||
|
||||
This configuration file is from the manual guide. You can refer to the manual guide to modify the configuration file. ([
|
||||
`Configure tailwind.config.js`](https://ui.shadcn.com/docs/installation/manual))
|
||||
|
||||
```ts
|
||||
import deepmerge from 'deepmerge';
|
||||
import { fontFamily } from 'tailwindcss/defaultTheme';
|
||||
import tailwindAnimate from 'tailwindcss-animate';
|
||||
import type { Config } from 'tailwindcss';
|
||||
|
||||
export function withUI(tailwindConfig: Config): Config {
|
||||
return deepmerge(
|
||||
shadcnConfig,
|
||||
deepmerge(tailwindConfig, {
|
||||
content: ['./node_modules/@extension/ui/lib/**/*.{tsx,ts,js,jsx}'],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const shadcnConfig = {
|
||||
darkMode: ['class'],
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: '2rem',
|
||||
screens: {
|
||||
'2xl': '1400px',
|
||||
},
|
||||
},
|
||||
extend: {
|
||||
colors: {
|
||||
border: 'hsl(var(--border))',
|
||||
input: 'hsl(var(--input))',
|
||||
ring: 'hsl(var(--ring))',
|
||||
background: 'hsl(var(--background))',
|
||||
foreground: 'hsl(var(--foreground))',
|
||||
primary: {
|
||||
DEFAULT: 'hsl(var(--primary))',
|
||||
foreground: 'hsl(var(--primary-foreground))',
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: 'hsl(var(--secondary))',
|
||||
foreground: 'hsl(var(--secondary-foreground))',
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: 'hsl(var(--destructive))',
|
||||
foreground: 'hsl(var(--destructive-foreground))',
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: 'hsl(var(--muted))',
|
||||
foreground: 'hsl(var(--muted-foreground))',
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: 'hsl(var(--accent))',
|
||||
foreground: 'hsl(var(--accent-foreground))',
|
||||
},
|
||||
popover: {
|
||||
DEFAULT: 'hsl(var(--popover))',
|
||||
foreground: 'hsl(var(--popover-foreground))',
|
||||
},
|
||||
card: {
|
||||
DEFAULT: 'hsl(var(--card))',
|
||||
foreground: 'hsl(var(--card-foreground))',
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
lg: `var(--radius)`,
|
||||
md: `calc(var(--radius) - 2px)`,
|
||||
sm: 'calc(var(--radius) - 4px)',
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['var(--font-sans)', ...fontFamily.sans],
|
||||
},
|
||||
keyframes: {
|
||||
'accordion-down': {
|
||||
from: { height: '0' },
|
||||
to: { height: 'var(--radix-accordion-content-height)' },
|
||||
},
|
||||
'accordion-up': {
|
||||
from: { height: 'var(--radix-accordion-content-height)' },
|
||||
to: { height: '0' },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||
'accordion-up': 'accordion-up 0.2s ease-out',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [tailwindAnimate],
|
||||
};
|
||||
```
|
||||
|
||||
4. Edit `global.css` in `lib` folder
|
||||
|
||||
This configuration also comes from the manual guide. You can refer to the manual guide to modify the configuration
|
||||
file. ([`Configure styles`](https://ui.shadcn.com/docs/installation/manual))
|
||||
|
||||
```css
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
:host, :root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 47.4% 11.2%;
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 47.4% 11.2%;
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 47.4% 11.2%;
|
||||
--primary: 222.2 47.4% 11.2%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
--destructive: 0 100% 50%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--ring: 215 20.2% 65.1%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 224 71% 4%;
|
||||
--foreground: 213 31% 91%;
|
||||
--muted: 223 47% 11%;
|
||||
--muted-foreground: 215.4 16.3% 56.9%;
|
||||
--accent: 216 34% 17%;
|
||||
--accent-foreground: 210 40% 98%;
|
||||
--popover: 224 71% 4%;
|
||||
--popover-foreground: 215 20.2% 65.1%;
|
||||
--border: 216 34% 17%;
|
||||
--input: 216 34% 17%;
|
||||
--card: 224 71% 4%;
|
||||
--card-foreground: 213 31% 91%;
|
||||
--primary: 210 40% 98%;
|
||||
--primary-foreground: 222.2 47.4% 1.2%;
|
||||
--secondary: 222.2 47.4% 11.2%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
--destructive: 0 63% 31%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--ring: 216 34% 17%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply font-sans antialiased bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
5. Add shadcn components
|
||||
|
||||
Finally, run this command from the root of your project to add the button component:
|
||||
|
||||
```shell
|
||||
pnpm dlx shadcn@latest add button -c ./packages/ui
|
||||
```
|
||||
|
||||
This will add the shadcn button component to your UI package.
|
||||
|
||||
Remember to adjust any paths or package names if your project structure differs from the assumed layout in this guide.
|
||||
|
||||
6. Export components
|
||||
|
||||
Edit the `index.ts` file in the `packages/ui` directory to export the shadcn ui component:
|
||||
|
||||
```ts
|
||||
//...
|
||||
export * from './lib/components/ui/button';
|
||||
```
|
||||
|
||||
7. Apply global.css
|
||||
|
||||
If you want to use shadcn components in content-ui ShadowDOM, you need to import ui package's global.css in the content-ui `tailwind-input.css`
|
||||
|
||||
```css
|
||||
@import '@extension/ui/lib/global.css';
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
```
|
||||
|
||||
If you want to use shadcn components in other pages, you need to import ui package's global.css in the `src/index.css`
|
||||
|
||||
```css
|
||||
@import '@extension/ui/lib/global.css';
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
```
|
||||
20
packages/ui/global.css
Normal file
20
packages/ui/global.css
Normal file
@@ -0,0 +1,20 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans',
|
||||
'Helvetica Neue', sans-serif;
|
||||
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||
}
|
||||
1
packages/ui/index.ts
Normal file
1
packages/ui/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './lib/index';
|
||||
10
packages/ui/lib/assets/warning.svg
Normal file
10
packages/ui/lib/assets/warning.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24" width="400" fill="none" stroke="currentColor">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
fill="none"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 409 B |
11
packages/ui/lib/components/LoadingSpinner.tsx
Normal file
11
packages/ui/lib/components/LoadingSpinner.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { RingLoader } from 'react-spinners';
|
||||
|
||||
interface ILoadingSpinnerProps {
|
||||
size?: number;
|
||||
}
|
||||
|
||||
export const LoadingSpinner = ({ size }: ILoadingSpinnerProps) => (
|
||||
<div className={'flex min-h-screen items-center justify-center'}>
|
||||
<RingLoader size={size ?? 100} color={'aqua'} />
|
||||
</div>
|
||||
);
|
||||
23
packages/ui/lib/components/ToggleButton.tsx
Normal file
23
packages/ui/lib/components/ToggleButton.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useStorage } from '@extension/shared';
|
||||
import { exampleThemeStorage } from '@extension/storage';
|
||||
import type { ComponentPropsWithoutRef } from 'react';
|
||||
|
||||
type ToggleButtonProps = ComponentPropsWithoutRef<'button'>;
|
||||
|
||||
export const ToggleButton = ({ className, children, ...props }: ToggleButtonProps) => {
|
||||
const { isLight } = useStorage(exampleThemeStorage);
|
||||
|
||||
return (
|
||||
<button
|
||||
className={cn(
|
||||
'mt-4 rounded border-2 px-4 py-1 font-bold shadow hover:scale-105',
|
||||
isLight ? 'border-black bg-white text-black' : 'border-white bg-black text-white',
|
||||
className,
|
||||
)}
|
||||
onClick={exampleThemeStorage.toggle}
|
||||
{...props}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
13
packages/ui/lib/components/error-display/ErrorDisplay.tsx
Normal file
13
packages/ui/lib/components/error-display/ErrorDisplay.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { ErrorHeader } from '@/lib/components/error-display/ErrorHeader';
|
||||
import { ErrorResetButton } from '@/lib/components/error-display/ErrorResetButton';
|
||||
import { ErrorStackTraceList } from '@/lib/components/error-display/ErrorStackTraceList';
|
||||
|
||||
export const ErrorDisplay = ({ error, resetErrorBoundary }: { error?: Error; resetErrorBoundary?: () => void }) => (
|
||||
<div className="flex items-center justify-center bg-gray-50 px-4 py-6 sm:px-6 lg:px-8">
|
||||
<div className="w-full max-w-md space-y-8">
|
||||
<ErrorHeader />
|
||||
<ErrorStackTraceList error={error} />
|
||||
<ErrorResetButton resetErrorBoundary={resetErrorBoundary} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
21
packages/ui/lib/components/error-display/ErrorHeader.tsx
Normal file
21
packages/ui/lib/components/error-display/ErrorHeader.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { t } from '@extension/i18n';
|
||||
|
||||
// FIXME: IMPORT SVG ICON INSTEAD OF DEFINING INLINE IT HERE
|
||||
const WarningIcon = ({ className }: { className: string }) => (
|
||||
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" className={className}>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const ErrorHeader = () => (
|
||||
<div className="text-center">
|
||||
<WarningIcon className={'mx-auto h-24 w-24 text-red-500'} />
|
||||
<h2 className="mt-6 text-3xl font-extrabold text-gray-900">{t('displayErrorInfo')}</h2>
|
||||
<p className="mt-2 text-sm text-gray-600">{t('displayErrorDescription')}.</p>
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,11 @@
|
||||
import { t } from '@extension/i18n';
|
||||
|
||||
export const ErrorResetButton = ({ resetErrorBoundary }: { resetErrorBoundary?: () => void }) => (
|
||||
<div className="flex items-center justify-center">
|
||||
<button
|
||||
onClick={resetErrorBoundary}
|
||||
className="inline-flex items-center rounded-md border border-transparent bg-red-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">
|
||||
{t('displayErrorReset')}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,20 @@
|
||||
import { t } from '@extension/i18n';
|
||||
|
||||
export const ErrorStackTraceList = ({ error }: { error?: Error }) => (
|
||||
<div className="overflow-hidden rounded-lg bg-white shadow">
|
||||
<div className="px-4 py-5 sm:p-6">
|
||||
<div className="text-sm text-gray-500">
|
||||
<p className="mb-2 font-medium text-gray-700">{t('displayErrorDetailsInfo')}</p>
|
||||
<div className="overflow-auto rounded-md bg-red-50 p-4">
|
||||
<p className="break-all font-mono text-red-700">{error?.message || t('displayErrorUnknownErrorInfo')}</p>
|
||||
{error?.stack && (
|
||||
<details className="mt-3">
|
||||
<summary className="cursor-pointer text-sm text-red-700">Stack trace</summary>
|
||||
<pre className="mt-2 overflow-auto p-2 text-xs text-red-800">{error?.stack}</pre>
|
||||
</details>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
3
packages/ui/lib/components/index.ts
Normal file
3
packages/ui/lib/components/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './ToggleButton';
|
||||
export * from './LoadingSpinner';
|
||||
export * from './error-display/ErrorDisplay';
|
||||
3
packages/ui/lib/index.ts
Normal file
3
packages/ui/lib/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './components/index';
|
||||
export * from './utils';
|
||||
export * from './with-ui';
|
||||
5
packages/ui/lib/utils.ts
Normal file
5
packages/ui/lib/utils.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { clsx } from 'clsx';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import type { ClassValue } from 'clsx';
|
||||
|
||||
export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs));
|
||||
7
packages/ui/lib/with-ui.ts
Normal file
7
packages/ui/lib/with-ui.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import deepmerge from 'deepmerge';
|
||||
import type { Config } from 'tailwindcss';
|
||||
|
||||
export const withUI = (tailwindConfig: Config): Config =>
|
||||
deepmerge(tailwindConfig, {
|
||||
content: ['../../packages/ui/lib/**/*.tsx'],
|
||||
});
|
||||
37
packages/ui/package.json
Normal file
37
packages/ui/package.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@extension/ui",
|
||||
"version": "0.5.0",
|
||||
"description": "chrome extension - ui components",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"sideEffects": true,
|
||||
"files": [
|
||||
"dist/**"
|
||||
],
|
||||
"types": "index.ts",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"clean:bundle": "rimraf dist",
|
||||
"clean:node_modules": "pnpx rimraf node_modules",
|
||||
"clean:turbo": "rimraf .turbo",
|
||||
"clean": "pnpm clean:bundle && pnpm clean:node_modules && pnpm clean:turbo",
|
||||
"ready": "tsc -b && tsc-alias -p tsconfig.json",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "pnpm lint --fix",
|
||||
"format": "prettier . --write --ignore-path ../../.prettierignore",
|
||||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@extension/i18n": "workspace:*",
|
||||
"@extension/shared": "workspace:*",
|
||||
"@extension/storage": "workspace:*",
|
||||
"clsx": "^2.1.1",
|
||||
"tailwind-merge": "^3.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@extension/tailwindcss-config": "workspace:*",
|
||||
"@extension/tsconfig": "workspace:*",
|
||||
"react-spinners": "^0.17.0",
|
||||
"tsc-alias": "^1.8.16"
|
||||
}
|
||||
}
|
||||
7
packages/ui/tailwind.config.ts
Normal file
7
packages/ui/tailwind.config.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import globalConfig from '@extension/tailwindcss-config';
|
||||
import type { Config } from 'tailwindcss';
|
||||
|
||||
export default {
|
||||
content: ['lib/**/*.tsx'],
|
||||
presets: [globalConfig],
|
||||
} satisfies Config;
|
||||
13
packages/ui/tsconfig.json
Normal file
13
packages/ui/tsconfig.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "@extension/tsconfig/base",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
},
|
||||
"noEmit": false,
|
||||
"declaration": true
|
||||
},
|
||||
"include": ["index.ts", "lib", "tailwind.config.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user