@febkosq8/arc 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.prettierrc ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "tabWidth": 4,
3
+ "printWidth": 120,
4
+ "singleQuote": true,
5
+ "trailingComma": "all",
6
+ "bracketSpacing": true,
7
+ "plugins": ["prettier-plugin-organize-imports"]
8
+ }
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # ARC
2
+
3
+ This is a component library that will be used in all of my projects.
4
+
5
+ Not something I would recommend using in your projects, but feel free to take a look at the code.
@@ -0,0 +1,42 @@
1
+ import { Slot } from "@radix-ui/react-slot";
2
+ import { cva, cx, VariantProps } from "@rinzai/zen";
3
+
4
+ const buttonVariants = cva(
5
+ "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 truncate",
6
+ {
7
+ variants: {
8
+ variant: {
9
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
10
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
11
+ outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
12
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
13
+ ghost: "hover:bg-accent hover:text-accent-foreground",
14
+ link: " border text-primary underline-offset-4 hover:underline",
15
+ },
16
+ size: {
17
+ default: "h-10 px-4 py-2",
18
+ sm: "h-9 rounded-md px-3",
19
+ lg: "h-11 rounded-md px-8",
20
+ icon: "h-10 w-10",
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ variant: "default",
25
+ size: "default",
26
+ },
27
+ },
28
+ );
29
+
30
+ export interface ButtonProps
31
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
32
+ VariantProps<typeof buttonVariants> {
33
+ asChild?: boolean;
34
+ }
35
+
36
+ const Button =({ className, variant, size, asChild = false, ...props }:ButtonProps) => {
37
+ const Comp = asChild ? Slot : "button";
38
+ return <Comp className={cx(buttonVariants({ variant, size, className }))} {...props} />;
39
+ };
40
+
41
+ export default Button
42
+
@@ -0,0 +1,32 @@
1
+ import { cx } from "@rinzai/zen";
2
+ interface CardProps extends React.ComponentPropsWithoutRef<"div"> {}
3
+ const Card = (props: CardProps) => {
4
+ const { className, ...rest } = props;
5
+ return <div className={cx("card p-4 rounded-lg border shadow-sm", className)} {...rest} />;
6
+ };
7
+
8
+ const Header = (props: CardProps) => {
9
+ const { className, ...rest } = props;
10
+ return <h2 className={cx("card-header flex flex-col typography-heading-2", className)} {...rest} />;
11
+ };
12
+ const Content = (props: CardProps) => {
13
+ const { className, ...rest } = props;
14
+ return (
15
+ <div
16
+ className={cx("card-content typography-heading-4 justify-between whitespace-pre-wrap py-2", className)}
17
+ {...rest}
18
+ />
19
+ );
20
+ };
21
+ const Footer = (props: CardProps) => {
22
+ const { className, ...rest } = props;
23
+ return (
24
+ <div className="border-t flex justify-start items-center pt-2">
25
+ <h2 className={cx("card-footer text-2xl", className)} {...rest} />
26
+ </div>
27
+ );
28
+ };
29
+ Card.Header = Header;
30
+ Card.Content = Content;
31
+ Card.Footer = Footer;
32
+ export default Card;
@@ -0,0 +1,114 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 0 0% 96%;
8
+ --foreground: 20 14.3% 4.1%;
9
+ --card: 0 0% 100%;
10
+ --card-foreground: 20 14.3% 4.1%;
11
+ --popover: 0 0% 100%;
12
+ --popover-foreground: 20 14.3% 4.1%;
13
+ --primary: 24.6 95% 53.1%;
14
+ --primary-foreground: 60 9.1% 97.8%;
15
+ --secondary: 60 4.8% 95.9%;
16
+ --secondary-foreground: 24 9.8% 10%;
17
+ --muted: 60 4.8% 95.9%;
18
+ --muted-foreground: 25 5.3% 44.7%;
19
+ --accent: 60 4.8% 95.9%;
20
+ --accent-foreground: 24 9.8% 10%;
21
+ --destructive: 0 84.2% 60.2%;
22
+ --destructive-foreground: 60 9.1% 97.8%;
23
+ --border: 20 5.9% 90%;
24
+ --input: 20 5.9% 90%;
25
+ --ring: 24.6 95% 53.1%;
26
+ --radius: 1rem;
27
+ }
28
+
29
+ .dark {
30
+ --background: 20 14.3% 4.1%;
31
+ --foreground: 60 9.1% 97.8%;
32
+ --card: 20 14.3% 4.1%;
33
+ --card-foreground: 60 9.1% 97.8%;
34
+ --popover: 20 14.3% 4.1%;
35
+ --popover-foreground: 60 9.1% 97.8%;
36
+ --primary: 20.5 90.2% 48.2%;
37
+ --primary-foreground: 60 9.1% 97.8%;
38
+ --secondary: 12 6.5% 15.1%;
39
+ --secondary-foreground: 60 9.1% 97.8%;
40
+ --muted: 12 6.5% 15.1%;
41
+ --muted-foreground: 24 5.4% 63.9%;
42
+ --accent: 12 6.5% 15.1%;
43
+ --accent-foreground: 60 9.1% 97.8%;
44
+ --destructive: 0 72.2% 50.6%;
45
+ --destructive-foreground: 60 9.1% 97.8%;
46
+ --border: 12 6.5% 15.1%;
47
+ --input: 12 6.5% 15.1%;
48
+ --ring: 20.5 90.2% 48.2%;
49
+ }
50
+ }
51
+
52
+ @layer base {
53
+ * {
54
+ @apply border-border;
55
+ }
56
+ body {
57
+ @apply bg-background text-foreground;
58
+ }
59
+ }
60
+
61
+ @layer components {
62
+ .typography-heading-1 {
63
+ @apply scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl;
64
+ }
65
+ .typography-heading-2 {
66
+ @apply scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight transition-colors first:mt-0;
67
+ }
68
+ .typography-heading-3 {
69
+ @apply scroll-m-20 text-2xl font-semibold tracking-tight;
70
+ }
71
+ .typography-heading-4 {
72
+ @apply scroll-m-20 text-xl font-semibold tracking-tight;
73
+ }
74
+ .typography-paragraph {
75
+ @apply leading-7 [&:not(:first-child)]:mt-6;
76
+ }
77
+ .typography-lead {
78
+ @apply text-xl text-muted-foreground;
79
+ }
80
+ .typography-large {
81
+ @apply text-lg font-semibold;
82
+ }
83
+ .typography-small {
84
+ @apply text-sm font-medium leading-none;
85
+ }
86
+ .typography-muted {
87
+ @apply text-sm text-muted-foreground;
88
+ }
89
+ }
90
+
91
+ /* Style for the scrollbar */
92
+ ::-webkit-scrollbar {
93
+ width: 10px;
94
+ }
95
+
96
+ /* Track */
97
+ ::-webkit-scrollbar-track {
98
+ background: hsl(var(--background));
99
+ }
100
+
101
+ /* Handle */
102
+ ::-webkit-scrollbar-thumb {
103
+ background: hsl(var(--primary));
104
+ border-radius: 5px;
105
+ }
106
+
107
+ /* Handle on hover */
108
+ ::-webkit-scrollbar-thumb:hover {
109
+ background: hsl(var(--primary));
110
+ }
111
+
112
+ * {
113
+ @apply scroll-smooth;
114
+ }
@@ -0,0 +1,8 @@
1
+ export {default as Button} from './button';
2
+ export {default as Input} from './input';
3
+ export {default as Card} from './card';
4
+ export {default as Menu} from './menu';
5
+ export {default as Pill} from './pill';
6
+ export {default as Switch} from './switch';
7
+ export {default as TextArea} from './text-area';
8
+ export {default as ThemeSwitcher} from './theme-switcher';
@@ -0,0 +1,21 @@
1
+ import { cx } from "@rinzai/zen";
2
+ import { ComponentPropsWithoutRef } from "react";
3
+
4
+ const Input = ({ className, ...rest }: ComponentPropsWithoutRef<"input">) => {
5
+ return (
6
+ <input
7
+ {...rest}
8
+ autoComplete="off"
9
+ className={cx(
10
+ className,
11
+ "h-10",
12
+ "placeholder:gray-800 rounded border border-border bg-input pl-5 text-foreground",
13
+ "focus:border-transparent focus:outline-none focus:ring-2 focus:ring-ring",
14
+ "disabled:cursor-not-allowed disabled:border-muted",
15
+ "whitespace-pre-wrap",
16
+ )}
17
+ />
18
+ );
19
+ };
20
+
21
+ export default Input;
@@ -0,0 +1,80 @@
1
+ import Pill from "@feb/pill";
2
+ import { faChevronDown, faChevronRight } from "@fortawesome/free-solid-svg-icons";
3
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
+ import * as DropdownBaseMenu from "@radix-ui/react-dropdown-menu";
5
+ import { cx } from "@rinzai/zen";
6
+ import { ReactNode } from "react";
7
+
8
+ interface MenuProps {
9
+ className?: string;
10
+ active?: boolean;
11
+ buttonText: string | ReactNode;
12
+ children: ReactNode;
13
+ }
14
+
15
+ interface MenuComponent extends React.FC<MenuProps> {
16
+ Item: typeof DropdownBaseMenu.Item;
17
+ }
18
+
19
+ const MenuComponent = ({ className, active, buttonText, children }:MenuProps) => {
20
+ return (
21
+ <DropdownBaseMenu.Root>
22
+ <DropdownBaseMenu.Trigger asChild>
23
+ <Pill active={active} className={cx("w-fit", className)}>
24
+ {buttonText}
25
+ <FontAwesomeIcon icon={faChevronDown} className="-mr-1 ml-2 h-4 w-4" aria-hidden="true" />
26
+ </Pill>
27
+ </DropdownBaseMenu.Trigger>
28
+ <DropdownBaseMenu.Portal>
29
+ <DropdownBaseMenu.Content
30
+ loop={true}
31
+ sideOffset={2}
32
+ className="w-fit origin-top-right divide-y border-2 border-border divide-border rounded-md bg-background shadow-lg ring-1 ring-background ring-opacity-5 focus:outline-none focus-visible:ring-0"
33
+ >
34
+ {children}
35
+ </DropdownBaseMenu.Content>
36
+ </DropdownBaseMenu.Portal>
37
+ </DropdownBaseMenu.Root>
38
+ );
39
+ };
40
+
41
+ const Menu: MenuComponent = Object.assign(MenuComponent, {
42
+ Item: DropdownBaseMenu.Item,
43
+ });
44
+
45
+ interface MenuSubProps {
46
+ active?: boolean;
47
+ buttonText: string;
48
+ children: ReactNode;
49
+ }
50
+
51
+ const MenuSub = ({ active, buttonText, children }: MenuSubProps) => {
52
+ return (
53
+ <DropdownBaseMenu.Sub>
54
+ <DropdownBaseMenu.SubTrigger asChild>
55
+ <Pill active={active} className="flex w-full items-center justify-between whitespace-nowrap">
56
+ {buttonText}
57
+ <FontAwesomeIcon icon={faChevronRight} className="-mr-1 ml-2 h-4 w-4" aria-hidden="true" />
58
+ </Pill>
59
+ </DropdownBaseMenu.SubTrigger>
60
+ <DropdownBaseMenu.Portal>
61
+ <DropdownBaseMenu.SubContent
62
+ loop={true}
63
+ sideOffset={2}
64
+ arrowPadding={2}
65
+ className="w-fit origin-top-right divide-y border-2 border-gray-600 divide-gray-100 rounded-md bg-neutral-900 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
66
+ >
67
+ {children}
68
+ <DropdownBaseMenu.Arrow className="fill-black dark:fill-stone-200 size-2" />
69
+ </DropdownBaseMenu.SubContent>
70
+ </DropdownBaseMenu.Portal>
71
+ </DropdownBaseMenu.Sub>
72
+ );
73
+ };
74
+
75
+ Object.assign(Menu, {
76
+ Item: DropdownBaseMenu.Item,
77
+ Sub: MenuSub,
78
+ });
79
+
80
+ export default Menu;
@@ -0,0 +1,20 @@
1
+ import { cx } from "@rinzai/zen";
2
+
3
+ interface PillProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
4
+ active?: boolean;
5
+ }
6
+
7
+ const Pill = (({ active, className, ...props }:PillProps) => {
8
+ return (
9
+ <button
10
+ className={cx(
11
+ `rounded-md p-3 text-xl font-bold transition inline-flex w-full items-center justify-center text-foreground hover:bg-accent hover:text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-opacity-75 whitespace-nowrap hover:ring-0 hover:outline-none `,
12
+ active ? "text-primary" : "text-muted-foreground",
13
+ className,
14
+ )}
15
+ {...props}
16
+ />
17
+ );
18
+ });
19
+
20
+ export default Pill;
@@ -0,0 +1,82 @@
1
+ import { faCircle } from "@fortawesome/free-solid-svg-icons";
2
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3
+ import { Switch as SwitchBase } from "@headlessui/react";
4
+ import { cva, cx } from "@rinzai/zen";
5
+ import { JSX } from "react";
6
+ interface SwitchProps {
7
+ checked?: boolean;
8
+ onChange?: (checked: boolean) => void;
9
+ disabled?: boolean;
10
+ variant?: "primary" | "danger" | "success";
11
+ children?: (checked: boolean) => JSX.Element;
12
+ }
13
+ const Switch = ({
14
+ checked = false,
15
+ onChange,
16
+ disabled = false,
17
+ variant = "primary",
18
+ children,
19
+ ...rest
20
+ }: SwitchProps) => {
21
+ return (
22
+ <SwitchBase
23
+ checked={checked}
24
+ disabled={disabled}
25
+ onChange={onChange}
26
+ className={SwitchVariants({ variant, checked, disabled })}
27
+ {...rest}
28
+ >
29
+ {children ? (
30
+ children(checked)
31
+ ) : (
32
+ <div className="relative w-full h-full">
33
+ <FontAwesomeIcon
34
+ icon={faCircle}
35
+ className={cx(
36
+ `absolute top-1/2 transform -translate-y-1/2 `,
37
+ checked ? "left-6 text-blue-600" : "left-1 text-blue-600",
38
+ disabled && "text-gray-400 dark:text-gray-200",
39
+ `inline-block h-4 w-4 rounded-full border border-blue-500 [transition:_all_0.5s_cubic-bezier(1,0,0,1)]`,
40
+ )}
41
+ />
42
+ </div>
43
+ )}
44
+ </SwitchBase>
45
+ );
46
+ };
47
+ const SwitchVariants = cva("relative inline-flex h-6 w-11 items-center rounded-full", {
48
+ variants: {
49
+ variant: {
50
+ danger: "",
51
+ success: "",
52
+ primary: "",
53
+ },
54
+ checked: {
55
+ true: "bg-gray-400 dark:bg-gray-200",
56
+ false: "bg-gray-400 dark:bg-gray-200",
57
+ },
58
+ disabled: {
59
+ true: "dark:bg-gray-600 ring-2 ring-slate-900 dark:ring-slate-400",
60
+ false: "",
61
+ },
62
+ },
63
+ compoundVariants: [
64
+ {
65
+ variant: "danger",
66
+ checked: true,
67
+ className: "bg-red-600",
68
+ },
69
+ {
70
+ variant: "primary",
71
+ checked: true,
72
+ className: "bg-blue-600",
73
+ },
74
+ {
75
+ variant: "success",
76
+ checked: true,
77
+ className: "bg-green-600",
78
+ },
79
+ ],
80
+ });
81
+ export default Switch
82
+
@@ -0,0 +1,21 @@
1
+ import { cx } from "@rinzai/zen";
2
+ import { ComponentPropsWithoutRef } from "react";
3
+
4
+ const TextArea = ({ className, ...rest }: ComponentPropsWithoutRef<"textarea">) => {
5
+ return (
6
+ <textarea
7
+ {...rest}
8
+ autoComplete="off"
9
+ className={cx(
10
+ className,
11
+ "min-h-[200px] max-h-96 !overflow-auto",
12
+ "placeholder:gray-800 rounded border border-border bg-input p-2 text-foreground",
13
+ "focus:border-transparent focus:outline-none focus:ring-2 focus:ring-ring",
14
+ "disabled:cursor-not-allowed disabled:border-muted",
15
+ "whitespace-pre-wrap",
16
+ )}
17
+ />
18
+ );
19
+ };
20
+
21
+ export default TextArea;
@@ -0,0 +1,81 @@
1
+ import { faLaptop, faMoon, faSun } from "@fortawesome/free-solid-svg-icons";
2
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3
+ import Menu from "@feb/menu";
4
+ import Pill from "@feb/pill";
5
+ import { useEffect, useState } from "react";
6
+ type Color = "light" | "dark" | "system";
7
+
8
+ export default function ThemeSwitcher() {
9
+ const colorModeIcon = { light: faSun, dark: faMoon, system: faLaptop };
10
+ const localStorageString = `theme`;
11
+ useEffect(() => {
12
+ if (typeof window !== "undefined" && !(localStorageString in localStorage)) {
13
+ localStorage.setItem(localStorageString, "system");
14
+ }
15
+ }, []);
16
+ const [colorMode, setColorMode] = useState<Color>(
17
+ typeof window !== "undefined" ? ((localStorage.getItem(localStorageString) as Color) ?? "system") : "system",
18
+ );
19
+ useEffect(() => {
20
+ if (["light", "dark"].includes(colorMode)) {
21
+ if (colorMode === "dark") {
22
+ document.documentElement.classList.add("dark");
23
+ setColorMode("dark");
24
+ } else if (colorMode === "light") {
25
+ document.documentElement.classList.remove("dark");
26
+ setColorMode("light");
27
+ }
28
+ localStorage.setItem(localStorageString, colorMode);
29
+ } else {
30
+ const isSystemThemeDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
31
+ if (isSystemThemeDark) {
32
+ document.documentElement.classList.add("dark");
33
+ } else {
34
+ document.documentElement.classList.remove("dark");
35
+ }
36
+ localStorage.setItem(localStorageString, "system");
37
+ }
38
+ }, [colorMode]);
39
+ return (
40
+ <Menu buttonText={<FontAwesomeIcon icon={colorModeIcon[colorMode] ?? faLaptop} />}>
41
+ <>
42
+ <Menu.Item className="focus-visible:outline-none">
43
+ <Pill
44
+ active={colorMode === "system"}
45
+ title="System Theme"
46
+ onClick={() => {
47
+ setColorMode("system");
48
+ }}
49
+ className="flex w-full whitespace-nowrap p-6 rounded-t-sm rounded-b-none"
50
+ >
51
+ <FontAwesomeIcon icon={faLaptop} className={"size-4"} />
52
+ </Pill>
53
+ </Menu.Item>
54
+ <Menu.Item className="focus-visible:outline-none">
55
+ <Pill
56
+ active={colorMode === "light"}
57
+ title="Light Theme"
58
+ onClick={() => {
59
+ setColorMode("light");
60
+ }}
61
+ className="flex w-full whitespace-nowrap p-6 rounded-none"
62
+ >
63
+ <FontAwesomeIcon icon={faSun} className={"size-4"} />
64
+ </Pill>
65
+ </Menu.Item>
66
+ <Menu.Item className="focus-visible:outline-none">
67
+ <Pill
68
+ active={colorMode === "dark"}
69
+ title="Dark Theme"
70
+ onClick={() => {
71
+ setColorMode("dark");
72
+ }}
73
+ className="flex w-full whitespace-nowrap p-6 rounded-b-sm rounded-t-none"
74
+ >
75
+ <FontAwesomeIcon icon={faMoon} className={"size-4"} />
76
+ </Pill>
77
+ </Menu.Item>
78
+ </>
79
+ </Menu>
80
+ );
81
+ }
@@ -0,0 +1,36 @@
1
+ import eslint from '@eslint/js';
2
+ import globals from 'globals';
3
+ import tseslint from 'typescript-eslint';
4
+ export default tseslint.config(
5
+ {
6
+ ignores: ['**/*.js', '**/*.d.ts', 'dist/*'],
7
+ },
8
+ eslint.configs.recommended,
9
+ ...tseslint.configs.recommendedTypeChecked,
10
+ {
11
+ languageOptions: {
12
+ parserOptions: {
13
+ project: ['tsconfig.json'],
14
+ projectService: true,
15
+ },
16
+ globals: {
17
+ ...globals.browser,
18
+ },
19
+ },
20
+ rules: {
21
+ '@typescript-eslint/no-unused-vars': [
22
+ 'error',
23
+ {
24
+ argsIgnorePattern: '^_',
25
+ },
26
+ ],
27
+ '@typescript-eslint/no-empty-object-type': 'off',
28
+ '@typescript-eslint/no-misused-promises': [
29
+ 'error',
30
+ {
31
+ checksVoidReturn: false,
32
+ },
33
+ ],
34
+ },
35
+ },
36
+ );
package/index.html ADDED
@@ -0,0 +1,11 @@
1
+ <!doctype html>
2
+ <html lang="en" className="h-[stretch]">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ </head>
6
+ <body>
7
+ <div id="root">
8
+ <script type="module" src="/src/index.ts"></script>
9
+ </div>
10
+ </body>
11
+ </html>
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@febkosq8/arc",
3
+ "description": "A React components library for febkosq8",
4
+ "private": false,
5
+ "version": "0.3.0",
6
+ "type": "module",
7
+ "repository": "https://github.com/febkosq8/arc",
8
+ "scripts": {
9
+ "build": "vite build",
10
+ "push-npm": "npm publish --access public",
11
+ "prepublishOnly": "npm run build"
12
+ },
13
+ "peerDependencies": {
14
+ "react": "19.0.0",
15
+ "react-dom": "19.0.0"
16
+ },
17
+ "dependencies": {
18
+ "@fortawesome/free-brands-svg-icons": "6.7.1",
19
+ "@fortawesome/free-solid-svg-icons": "6.7.1",
20
+ "@fortawesome/react-fontawesome": "0.2.2",
21
+ "@headlessui/react": "2.2.0",
22
+ "@radix-ui/react-dropdown-menu": "2.1.2",
23
+ "@radix-ui/react-slot": "1.1.0",
24
+ "@radix-ui/react-switch": "1.1.1",
25
+ "@rinzai/zen": "0.0.16",
26
+ "tailwind-merge": "2.5.5"
27
+ },
28
+ "devDependencies": {
29
+ "@tailwindcss/typography": "0.5.15",
30
+ "@types/node": "22.10.2",
31
+ "@types/react": "19.0.1",
32
+ "@types/react-dom": "19.0.2",
33
+ "@typescript-eslint/eslint-plugin": "8.18.0",
34
+ "@typescript-eslint/parser": "8.18.0",
35
+ "@vitejs/plugin-react-swc": "3.7.2",
36
+ "autoprefixer": "10.4.20",
37
+ "eslint": "9.16.0",
38
+ "eslint-plugin-react-hooks": "5.1.0",
39
+ "eslint-plugin-react-refresh": "0.4.16",
40
+ "postcss": "8.4.49",
41
+ "prettier": "3.4.2",
42
+ "react": "19.0.0",
43
+ "react-dom": "19.0.0",
44
+ "tailwindcss": "3.4.16",
45
+ "tailwindcss-animate": "1.0.7",
46
+ "typescript": "5.7.2",
47
+ "vite": "6.0.3",
48
+ "vite-plugin-dts": "4.3.0",
49
+ "vite-tsconfig-paths": "5.1.4"
50
+ }
51
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx",
5
+ "target": "ESNext",
6
+ "lib": ["ESNext", "DOM"],
7
+ "skipLibCheck": true,
8
+ "esModuleInterop": true,
9
+ "allowSyntheticDefaultImports": true,
10
+ "strict": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "noFallthroughCasesInSwitch": true,
13
+ "module": "ESNext",
14
+ "moduleResolution": "Bundler",
15
+ "moduleDetection": "force",
16
+ "resolveJsonModule": true,
17
+ "isolatedModules": true,
18
+ "noEmit": true,
19
+ // "verbatimModuleSyntax": true,
20
+ "baseUrl": ".",
21
+ "paths": {
22
+ "@feb/*": ["components/*"]
23
+ }
24
+ },
25
+ "allowDefaultProject": true,
26
+ "exclude": ["node_modules", "dist", "demo"]
27
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,37 @@
1
+ import react from '@vitejs/plugin-react-swc';
2
+ import { resolve } from 'node:path';
3
+ import tailwindcss from 'tailwindcss';
4
+ import { defineConfig } from 'vite';
5
+ import dts from 'vite-plugin-dts';
6
+ import tsConfigPaths from 'vite-tsconfig-paths';
7
+ import config from './package.json' with {type:"json"};
8
+ export default defineConfig({
9
+ plugins: [
10
+ react(),
11
+ tsConfigPaths(),
12
+ dts({
13
+ include: ['components/'],
14
+ }),
15
+ ],
16
+ css: {
17
+ postcss: {
18
+ plugins: [tailwindcss],
19
+ },
20
+ },
21
+
22
+ build: {
23
+ lib: {
24
+ entry: resolve('components', 'index.ts'),
25
+ formats: ['es'],
26
+ },
27
+
28
+ rollupOptions: {
29
+ external: [...Object.keys(config.peerDependencies)],
30
+ output: {
31
+ globals: {
32
+ react: 'React',
33
+ },
34
+ },
35
+ },
36
+ },
37
+ });