diff --git a/components.json b/components.json
new file mode 100644
index 000000000..285033d31
--- /dev/null
+++ b/components.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "new-york",
+ "rsc": false,
+ "tsx": true,
+ "tailwind": {
+ "config": "",
+ "css": "src/styles/globals.css",
+ "baseColor": "neutral",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ },
+ "iconLibrary": "lucide"
+}
diff --git a/components/ui/button.tsx b/components/ui/button.tsx
new file mode 100644
index 000000000..151015de1
--- /dev/null
+++ b/components/ui/button.tsx
@@ -0,0 +1,61 @@
+/* eslint-disable linebreak-style */
+/* eslint-disable quotes */
+import * as React from 'react';
+import { Slot } from '@radix-ui/react-slot';
+import { cva, type VariantProps } from 'class-variance-authority';
+
+import { cn } from '@/lib/utils';
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
+ {
+ variants: {
+ variant: {
+ default:
+ 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
+ destructive:
+ 'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
+ outline:
+ 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
+ secondary:
+ 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
+ ghost:
+ 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
+ link: 'text-primary underline-offset-4 hover:underline',
+ },
+ size: {
+ default: 'h-9 px-4 py-2 has-[>svg]:px-3',
+ sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
+ lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
+ icon: 'size-9',
+ },
+ },
+ defaultVariants: {
+ variant: 'default',
+ size: 'default',
+ },
+ },
+);
+
+function Button({
+ className,
+ variant,
+ size,
+ asChild = false,
+ ...props
+}: React.ComponentProps<'button'> &
+ VariantProps & {
+ asChild?: boolean;
+ }) {
+ const Comp = asChild ? Slot : 'button';
+
+ return (
+
+ );
+}
+
+export { Button, buttonVariants };
diff --git a/components/ui/checkbox.tsx b/components/ui/checkbox.tsx
new file mode 100644
index 000000000..74d2ffc44
--- /dev/null
+++ b/components/ui/checkbox.tsx
@@ -0,0 +1,36 @@
+/* eslint-disable linebreak-style */
+import * as React from 'react';
+
+import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
+
+import { CheckIcon } from 'lucide-react';
+
+import { cn } from '@/lib/utils';
+
+function Checkbox({
+ // eslint-disable-next-line react/prop-types
+ className,
+
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+ );
+}
+
+export { Checkbox };
diff --git a/lib/utils.ts b/lib/utils.ts
new file mode 100644
index 000000000..2819a830d
--- /dev/null
+++ b/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from 'clsx';
+import { twMerge } from 'tailwind-merge';
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/package.json b/package.json
index e9f53b5f7..22ab9473e 100644
--- a/package.json
+++ b/package.json
@@ -27,10 +27,14 @@
},
"dependencies": {
"@docsearch/react": "3.8.0",
+ "@radix-ui/react-checkbox": "^1.3.1",
+ "@radix-ui/react-slot": "^1.2.2",
"@types/jsonpath": "^0.2.4",
"axios": "1.7.7",
"babel-loader": "^9.2.1",
+ "class-variance-authority": "^0.7.1",
"classnames": "^2.5.1",
+ "clsx": "^2.1.1",
"feed": "^4.2.2",
"file-saver": "^2.0.5",
"fuse.js": "^7.0.0",
@@ -38,6 +42,7 @@
"js-yaml": "^4.1.0",
"jsonpath": "^1.1.1",
"jszip": "^3.10.1",
+ "lucide-react": "^0.510.0",
"markdown-to-jsx": "^7.7.3",
"moment": "2.30.1",
"next": "14.2.14",
@@ -52,6 +57,8 @@
"slate": "^0.112.0",
"slate-react": "^0.108.0",
"slugify": "^1.6.5",
+ "tailwind-merge": "^3.3.0",
+ "tw-animate-css": "^1.2.9",
"yarn": "1.22.22",
"zero-fill": "^2.2.4",
"zustand": "^5.0.0"
diff --git a/tsconfig.json b/tsconfig.json
index 746d414d5..8526f68d4 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -18,7 +18,8 @@
"paths": {
"react": ["./node_modules/@types/react"],
"~/*": ["./*"],
- "@public/*": ["./public/*"]
+ "@public/*": ["./public/*"],
+ "@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "svgr.d.ts", "**/*.ts", "**/*.tsx"],
diff --git a/yarn.lock b/yarn.lock
index d6637ce66..53bb6412d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3291,6 +3291,191 @@ __metadata:
languageName: node
linkType: hard
+"@radix-ui/primitive@npm:1.1.2":
+ version: 1.1.2
+ resolution: "@radix-ui/primitive@npm:1.1.2"
+ checksum: 10c0/5e2d2528d2fe37c16865e77b0beaac2b415a817ad13d8178db6e8187b2a092672568a64ee0041510abfde3034490a5cadd3057049bb15789020c06892047597c
+ languageName: node
+ linkType: hard
+
+"@radix-ui/react-checkbox@npm:^1.3.1":
+ version: 1.3.1
+ resolution: "@radix-ui/react-checkbox@npm:1.3.1"
+ dependencies:
+ "@radix-ui/primitive": "npm:1.1.2"
+ "@radix-ui/react-compose-refs": "npm:1.1.2"
+ "@radix-ui/react-context": "npm:1.1.2"
+ "@radix-ui/react-presence": "npm:1.1.4"
+ "@radix-ui/react-primitive": "npm:2.1.2"
+ "@radix-ui/react-use-controllable-state": "npm:1.2.2"
+ "@radix-ui/react-use-previous": "npm:1.1.1"
+ "@radix-ui/react-use-size": "npm:1.1.1"
+ peerDependencies:
+ "@types/react": "*"
+ "@types/react-dom": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ "@types/react-dom":
+ optional: true
+ checksum: 10c0/e2360ce7c0d894f196e0a4aaa7fe7482a5f1ca035e62d5bee364c6828d30a6024c3de4ea0ed77067489ccab1a583d09f23211ddeda78fa092e09a2026035b86c
+ languageName: node
+ linkType: hard
+
+"@radix-ui/react-compose-refs@npm:1.1.2":
+ version: 1.1.2
+ resolution: "@radix-ui/react-compose-refs@npm:1.1.2"
+ peerDependencies:
+ "@types/react": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10c0/d36a9c589eb75d634b9b139c80f916aadaf8a68a7c1c4b8c6c6b88755af1a92f2e343457042089f04cc3f23073619d08bb65419ced1402e9d4e299576d970771
+ languageName: node
+ linkType: hard
+
+"@radix-ui/react-context@npm:1.1.2":
+ version: 1.1.2
+ resolution: "@radix-ui/react-context@npm:1.1.2"
+ peerDependencies:
+ "@types/react": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10c0/cece731f8cc25d494c6589cc681e5c01a93867d895c75889973afa1a255f163c286e390baa7bc028858eaabe9f6b57270d0ca6377356f652c5557c1c7a41ccce
+ languageName: node
+ linkType: hard
+
+"@radix-ui/react-presence@npm:1.1.4":
+ version: 1.1.4
+ resolution: "@radix-ui/react-presence@npm:1.1.4"
+ dependencies:
+ "@radix-ui/react-compose-refs": "npm:1.1.2"
+ "@radix-ui/react-use-layout-effect": "npm:1.1.1"
+ peerDependencies:
+ "@types/react": "*"
+ "@types/react-dom": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ "@types/react-dom":
+ optional: true
+ checksum: 10c0/8202647139d6f5097b0abcc43dfba471c00b69da95ca336afe3ea23a165e05ca21992f40fc801760fe442f3e064e54e2f2cbcb9ad758c4b07ef6c69a5b6777bd
+ languageName: node
+ linkType: hard
+
+"@radix-ui/react-primitive@npm:2.1.2":
+ version: 2.1.2
+ resolution: "@radix-ui/react-primitive@npm:2.1.2"
+ dependencies:
+ "@radix-ui/react-slot": "npm:1.2.2"
+ peerDependencies:
+ "@types/react": "*"
+ "@types/react-dom": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ "@types/react-dom":
+ optional: true
+ checksum: 10c0/0c1b4b5d2f225dc85e02a915b362e38383eb3bd6d150a72cb9183485c066156caad1a9f530202b84a5ad900d365302c0843fdcabb13100808872b3655709099d
+ languageName: node
+ linkType: hard
+
+"@radix-ui/react-slot@npm:1.2.2, @radix-ui/react-slot@npm:^1.2.2":
+ version: 1.2.2
+ resolution: "@radix-ui/react-slot@npm:1.2.2"
+ dependencies:
+ "@radix-ui/react-compose-refs": "npm:1.1.2"
+ peerDependencies:
+ "@types/react": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10c0/74489f5ad11b17444560a1cdd664c01308206ce5cb9fcd46121b45281ece20273948479711411223c1081f709c15409242d51ca6cc57ff81f6335d70e0cbe0b5
+ languageName: node
+ linkType: hard
+
+"@radix-ui/react-use-controllable-state@npm:1.2.2":
+ version: 1.2.2
+ resolution: "@radix-ui/react-use-controllable-state@npm:1.2.2"
+ dependencies:
+ "@radix-ui/react-use-effect-event": "npm:0.0.2"
+ "@radix-ui/react-use-layout-effect": "npm:1.1.1"
+ peerDependencies:
+ "@types/react": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10c0/f55c4b06e895293aed4b44c9ef26fb24432539f5346fcd6519c7745800535b571058685314e83486a45bf61dc83887e24826490d3068acc317fb0a9010516e63
+ languageName: node
+ linkType: hard
+
+"@radix-ui/react-use-effect-event@npm:0.0.2":
+ version: 0.0.2
+ resolution: "@radix-ui/react-use-effect-event@npm:0.0.2"
+ dependencies:
+ "@radix-ui/react-use-layout-effect": "npm:1.1.1"
+ peerDependencies:
+ "@types/react": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10c0/e84ff72a3e76c5ae9c94941028bb4b6472f17d4104481b9eab773deab3da640ecea035e54da9d6f4df8d84c18ef6913baf92b7511bee06930dc58bd0c0add417
+ languageName: node
+ linkType: hard
+
+"@radix-ui/react-use-layout-effect@npm:1.1.1":
+ version: 1.1.1
+ resolution: "@radix-ui/react-use-layout-effect@npm:1.1.1"
+ peerDependencies:
+ "@types/react": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10c0/9f98fdaba008dfc58050de60a77670b885792df473cf82c1cef8daee919a5dd5a77d270209f5f0b0abfaac78cb1627396e3ff56c81b735be550409426fe8b040
+ languageName: node
+ linkType: hard
+
+"@radix-ui/react-use-previous@npm:1.1.1":
+ version: 1.1.1
+ resolution: "@radix-ui/react-use-previous@npm:1.1.1"
+ peerDependencies:
+ "@types/react": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10c0/52f1089d941491cd59b7f52a5679a14e9381711419a0557ce0f3bc9a4c117078224efec54dcced41a3653a13a386a7b6ec75435d61a273e8b9f5d00235f2b182
+ languageName: node
+ linkType: hard
+
+"@radix-ui/react-use-size@npm:1.1.1":
+ version: 1.1.1
+ resolution: "@radix-ui/react-use-size@npm:1.1.1"
+ dependencies:
+ "@radix-ui/react-use-layout-effect": "npm:1.1.1"
+ peerDependencies:
+ "@types/react": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10c0/851d09a816f44282e0e9e2147b1b571410174cc048703a50c4fa54d672de994fd1dfff1da9d480ecfd12c77ae8f48d74f01adaf668f074156b8cd0043c6c21d8
+ languageName: node
+ linkType: hard
+
"@rushstack/eslint-patch@npm:^1.3.3":
version: 1.6.0
resolution: "@rushstack/eslint-patch@npm:1.6.0"
@@ -5069,6 +5254,15 @@ __metadata:
languageName: node
linkType: hard
+"class-variance-authority@npm:^0.7.1":
+ version: 0.7.1
+ resolution: "class-variance-authority@npm:0.7.1"
+ dependencies:
+ clsx: "npm:^2.1.1"
+ checksum: 10c0/0f438cea22131808b99272de0fa933c2532d5659773bfec0c583de7b3f038378996d3350683426b8e9c74a6286699382106d71fbec52f0dd5fbb191792cccb5b
+ languageName: node
+ linkType: hard
+
"classnames@npm:^2.5.1":
version: 2.5.1
resolution: "classnames@npm:2.5.1"
@@ -5133,6 +5327,13 @@ __metadata:
languageName: node
linkType: hard
+"clsx@npm:^2.1.1":
+ version: 2.1.1
+ resolution: "clsx@npm:2.1.1"
+ checksum: 10c0/c4c8eb865f8c82baab07e71bfa8897c73454881c4f99d6bc81585aecd7c441746c1399d08363dc096c550cceaf97bd4ce1e8854e1771e9998d9f94c4fe075839
+ languageName: node
+ linkType: hard
+
"color-convert@npm:^1.9.0":
version: 1.9.3
resolution: "color-convert@npm:1.9.3"
@@ -8332,6 +8533,8 @@ __metadata:
"@cypress/code-coverage": "npm:^3.13.12"
"@docsearch/react": "npm:3.8.0"
"@next/eslint-plugin-next": "npm:^14.0.1"
+ "@radix-ui/react-checkbox": "npm:^1.3.1"
+ "@radix-ui/react-slot": "npm:^1.2.2"
"@svgr/webpack": "npm:^8.1.0"
"@types/babel__core": "npm:^7"
"@types/babel__preset-env": "npm:^7"
@@ -8348,7 +8551,9 @@ __metadata:
axios: "npm:1.7.7"
babel-loader: "npm:^9.2.1"
babel-plugin-istanbul: "npm:^7.0.0"
+ class-variance-authority: "npm:^0.7.1"
classnames: "npm:^2.5.1"
+ clsx: "npm:^2.1.1"
cypress: "npm:^13.13.1"
eslint: "npm:8.57.0"
eslint-config-next: "npm:14.2.3"
@@ -8370,6 +8575,7 @@ __metadata:
js-yaml: "npm:^4.1.0"
jsonpath: "npm:^1.1.1"
jszip: "npm:^3.10.1"
+ lucide-react: "npm:^0.510.0"
markdown-to-jsx: "npm:^7.7.3"
moment: "npm:2.30.1"
next: "npm:14.2.14"
@@ -8387,7 +8593,9 @@ __metadata:
slate: "npm:^0.112.0"
slate-react: "npm:^0.108.0"
slugify: "npm:^1.6.5"
+ tailwind-merge: "npm:^3.3.0"
tailwindcss: "npm:^3.3.5"
+ tw-animate-css: "npm:^1.2.9"
typescript: "npm:5.7.2"
webpack: "npm:^5.94.0"
yarn: "npm:1.22.22"
@@ -8753,6 +8961,15 @@ __metadata:
languageName: node
linkType: hard
+"lucide-react@npm:^0.510.0":
+ version: 0.510.0
+ resolution: "lucide-react@npm:0.510.0"
+ peerDependencies:
+ react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ checksum: 10c0/00b3efed64c370cd5ae97023583996ff83939baf6f4af11393d536ca9e520b0cc1a82a81aa6d0350625bff398daaa69357df74383631f2c3a0aeb6974f4237c7
+ languageName: node
+ linkType: hard
+
"make-dir@npm:^3.0.0, make-dir@npm:^3.0.2":
version: 3.1.0
resolution: "make-dir@npm:3.1.0"
@@ -11240,6 +11457,13 @@ __metadata:
languageName: node
linkType: hard
+"tailwind-merge@npm:^3.3.0":
+ version: 3.3.0
+ resolution: "tailwind-merge@npm:3.3.0"
+ checksum: 10c0/a50cd141100486f98541dfab3705712af5860556689b7496dc6b0284374f02d12d5471f0f40035f6bb8b1c749c422060a1f3e5f8900057d8a7786b111c8472e6
+ languageName: node
+ linkType: hard
+
"tailwindcss@npm:^3.3.5":
version: 3.3.5
resolution: "tailwindcss@npm:3.3.5"
@@ -11480,6 +11704,13 @@ __metadata:
languageName: node
linkType: hard
+"tw-animate-css@npm:^1.2.9":
+ version: 1.2.9
+ resolution: "tw-animate-css@npm:1.2.9"
+ checksum: 10c0/ffbd6dfbb34490a8752b185b40192168ce4bfa69949d153dc831d9471dec2758501f27f1784b6615de7da73a546d01d7201ed691f5220fe3e0a53694cb275a3a
+ languageName: node
+ linkType: hard
+
"tweetnacl@npm:^0.14.3, tweetnacl@npm:~0.14.0":
version: 0.14.5
resolution: "tweetnacl@npm:0.14.5"