Vokturz commited on
Commit
5541427
·
1 Parent(s): 046ca57

move to vite

Browse files
.gitignore CHANGED
@@ -22,4 +22,6 @@ npm-debug.log*
22
  yarn-debug.log*
23
  yarn-error.log*
24
 
25
- .env
 
 
 
22
  yarn-debug.log*
23
  yarn-error.log*
24
 
25
+ .env
26
+
27
+ dist/
README.md CHANGED
@@ -6,7 +6,7 @@ colorTo: red
6
  sdk: static
7
  pinned: false
8
  app_build_command: npm run build
9
- app_file: build/index.html
10
  ---
11
 
12
 
 
6
  sdk: static
7
  pinned: false
8
  app_build_command: npm run build
9
+ app_file: dist/index.html
10
  ---
11
 
12
 
index.html ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link rel="icon" href="/favicon.ico" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <meta name="theme-color" content="#000000" />
8
+ <meta name="description" content="" />
9
+ <link rel="apple-touch-icon" href="/logo192.png" />
10
+ <link rel="manifest" href="/manifest.json" />
11
+
12
+ <title>Transformers.js Playground</title>
13
+ </head>
14
+ <body>
15
+ <noscript>You need to enable JavaScript to run this app.</noscript>
16
+ <div id="root"></div>
17
+ <script type="module" src="/src/index.tsx"></script>
18
+ </body>
19
+ </html>
package.json CHANGED
@@ -1,11 +1,13 @@
1
  {
 
2
  "name": "transformers-js-playground",
3
  "version": "0.1.0",
4
  "private": true,
5
  "dependencies": {
6
  "@headlessui/react": "^2.2.4",
7
- "@huggingface/transformers": "^3.6.1",
8
  "@tailwindcss/typography": "^0.5.16",
 
9
  "@testing-library/dom": "^10.4.0",
10
  "@testing-library/jest-dom": "^6.6.3",
11
  "@testing-library/react": "^16.3.0",
@@ -14,25 +16,27 @@
14
  "@types/node": "^16.18.126",
15
  "@types/react": "^19.1.8",
16
  "@types/react-dom": "^19.1.6",
 
17
  "build": "^0.1.4",
18
  "dotenv": "^17.0.1",
19
  "lodash": "^4.17.21",
20
  "lucide-react": "^0.525.0",
21
  "path-browserify": "^1.0.1",
 
22
  "react": "^19.1.0",
23
  "react-dom": "^19.1.0",
24
  "react-markdown": "^10.1.0",
25
- "react-scripts": "5.0.1",
26
  "react-syntax-highlighter": "^15.6.1",
27
  "remark-gfm": "^4.0.1",
28
  "typescript": "^4.9.5",
 
 
29
  "web-vitals": "^2.1.4"
30
  },
31
  "scripts": {
32
- "start": "react-scripts start",
33
- "build": "react-scripts build",
34
- "test": "react-scripts test",
35
- "eject": "react-scripts eject"
36
  },
37
  "eslintConfig": {
38
  "extends": [
@@ -55,6 +59,8 @@
55
  "devDependencies": {
56
  "@types/lodash": "^4.17.20",
57
  "@types/react-syntax-highlighter": "^15.5.13",
58
- "tailwindcss": "3"
 
 
59
  }
60
  }
 
1
  {
2
+ "type": "module",
3
  "name": "transformers-js-playground",
4
  "version": "0.1.0",
5
  "private": true,
6
  "dependencies": {
7
  "@headlessui/react": "^2.2.4",
8
+ "@tailwindcss/postcss": "^4.1.11",
9
  "@tailwindcss/typography": "^0.5.16",
10
+ "@tailwindcss/vite": "^4.1.11",
11
  "@testing-library/dom": "^10.4.0",
12
  "@testing-library/jest-dom": "^6.6.3",
13
  "@testing-library/react": "^16.3.0",
 
16
  "@types/node": "^16.18.126",
17
  "@types/react": "^19.1.8",
18
  "@types/react-dom": "^19.1.6",
19
+ "@vitejs/plugin-react-swc": "^3.11.0",
20
  "build": "^0.1.4",
21
  "dotenv": "^17.0.1",
22
  "lodash": "^4.17.21",
23
  "lucide-react": "^0.525.0",
24
  "path-browserify": "^1.0.1",
25
+ "postcss": "^8.5.6",
26
  "react": "^19.1.0",
27
  "react-dom": "^19.1.0",
28
  "react-markdown": "^10.1.0",
 
29
  "react-syntax-highlighter": "^15.6.1",
30
  "remark-gfm": "^4.0.1",
31
  "typescript": "^4.9.5",
32
+ "vite-plugin-svgr": "^4.3.0",
33
+ "vite-tsconfig-paths": "^5.1.4",
34
  "web-vitals": "^2.1.4"
35
  },
36
  "scripts": {
37
+ "start": "vite",
38
+ "build": "tsc && vite build",
39
+ "serve": "vite preview"
 
40
  },
41
  "eslintConfig": {
42
  "extends": [
 
59
  "devDependencies": {
60
  "@types/lodash": "^4.17.20",
61
  "@types/react-syntax-highlighter": "^15.5.13",
62
+ "@vitejs/plugin-react": "^4.7.0",
63
+ "tailwindcss": "^4.1.11",
64
+ "vite": "^7.0.6"
65
  }
66
  }
pnpm-lock.yaml CHANGED
The diff for this file is too large to render. See raw diff
 
postcss.config.mjs ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ export default {
2
+ plugins: {
3
+ '@tailwindcss/postcss': {}
4
+ }
5
+ }
public/index.html DELETED
@@ -1,40 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8" />
5
- <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6
- <meta name="viewport" content="width=device-width, initial-scale=1" />
7
- <meta name="theme-color" content="#000000" />
8
- <meta name="description" content="" />
9
- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
10
- <!--
11
- manifest.json provides metadata used when your web app is installed on a
12
- user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
13
- -->
14
- <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
15
- <!--
16
- Notice the use of %PUBLIC_URL% in the tags above.
17
- It will be replaced with the URL of the `public` folder during the build.
18
- Only files inside the `public` folder can be referenced from the HTML.
19
-
20
- Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
21
- work correctly both with client-side routing and a non-root public URL.
22
- Learn how to configure a non-root public URL by running `npm run build`.
23
- -->
24
- <title>Transformers.js Playground</title>
25
- </head>
26
- <body>
27
- <noscript>You need to enable JavaScript to run this app.</noscript>
28
- <div id="root"></div>
29
- <!--
30
- This HTML file is a template.
31
- If you open it directly in the browser, you will see an empty page.
32
-
33
- You can add webfonts, meta tags, or analytics to this file.
34
- The build step will place the bundled scripts into the <body> tag.
35
-
36
- To begin the development, run `npm start` or `yarn start`.
37
- To create a production bundle, use `npm run build` or `yarn build`.
38
- -->
39
- </body>
40
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/App.css DELETED
@@ -1,38 +0,0 @@
1
- .App {
2
- text-align: center;
3
- }
4
-
5
- .App-logo {
6
- height: 40vmin;
7
- pointer-events: none;
8
- }
9
-
10
- @media (prefers-reduced-motion: no-preference) {
11
- .App-logo {
12
- animation: App-logo-spin infinite 20s linear;
13
- }
14
- }
15
-
16
- .App-header {
17
- background-color: #282c34;
18
- min-height: 100vh;
19
- display: flex;
20
- flex-direction: column;
21
- align-items: center;
22
- justify-content: center;
23
- font-size: calc(10px + 2vmin);
24
- color: white;
25
- }
26
-
27
- .App-link {
28
- color: #61dafb;
29
- }
30
-
31
- @keyframes App-logo-spin {
32
- from {
33
- transform: rotate(0deg);
34
- }
35
- to {
36
- transform: rotate(360deg);
37
- }
38
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/App.tsx CHANGED
@@ -48,7 +48,7 @@ function App() {
48
  <div className="absolute right-0 top-16 lg:hidden mb-4">
49
  <button
50
  onClick={() => setIsSidebarOpen(true)}
51
- className="items-center px-2 py-2 bg-white border border-gray-300 rounded-l-lg shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50"
52
  >
53
  <Settings className="w-5 h-5" />
54
  </button>
 
48
  <div className="absolute right-0 top-16 lg:hidden mb-4">
49
  <button
50
  onClick={() => setIsSidebarOpen(true)}
51
+ className="flex items-center px-2 py-2 bg-white border border-gray-300 rounded-l-lg shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50"
52
  >
53
  <Settings className="w-5 h-5" />
54
  </button>
src/Header.tsx CHANGED
@@ -1,6 +1,6 @@
1
  function Header() {
2
  return (
3
- <header className="bg-white shadow-sm border-b">
4
  <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
5
  <div className="flex items-center justify-center h-16">
6
  <div className="flex items-center space-x-3">
 
1
  function Header() {
2
  return (
3
+ <header className="bg-white shadow-xs border-b">
4
  <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
5
  <div className="flex items-center justify-center h-16">
6
  <div className="flex items-center space-x-3">
src/components/CodeExporter.tsx CHANGED
@@ -8,7 +8,7 @@ const CodeExporter: React.FC<CodeExporterProps> = ({ code }) => {
8
  return (
9
  <div className="flex flex-col">
10
  <h2 className="text-lg font-medium">Code</h2>
11
- <pre className="bg-gray-100 p-2 rounded">{code}</pre>
12
  </div>
13
  );
14
  };
 
8
  return (
9
  <div className="flex flex-col">
10
  <h2 className="text-lg font-medium">Code</h2>
11
+ <pre className="bg-gray-100 p-2 rounded-sm">{code}</pre>
12
  </div>
13
  );
14
  };
src/components/MarkdownRenderer.tsx CHANGED
@@ -33,7 +33,7 @@ const MarkdownRenderer = ({ content }: MarkdownRendererProps) => {
33
  </SyntaxHighlighter>
34
  ) : (
35
  <code
36
- className="bg-gray-100 px-1 py-0.5 rounded text-sm font-mono"
37
  {...props}
38
  >
39
  {children}
 
33
  </SyntaxHighlighter>
34
  ) : (
35
  <code
36
+ className="bg-gray-100 px-1 py-0.5 rounded-sm text-sm font-mono"
37
  {...props}
38
  >
39
  {children}
src/components/Modal.tsx CHANGED
@@ -78,7 +78,7 @@ const Modal: React.FC<ModalProps> = ({
78
  <h3 className="text-lg font-semibold text-gray-900">{title}</h3>
79
  <button
80
  onClick={onClose}
81
- className="rounded-md p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
82
  >
83
  <span className="sr-only">Close</span>
84
  <X className="h-5 w-5" />
 
78
  <h3 className="text-lg font-semibold text-gray-900">{title}</h3>
79
  <button
80
  onClick={onClose}
81
+ className="rounded-md p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 focus:outline-hidden focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
82
  >
83
  <span className="sr-only">Close</span>
84
  <X className="h-5 w-5" />
src/components/ModelInfo.tsx CHANGED
@@ -28,37 +28,37 @@ const ModelInfo = () => {
28
  const { models, modelInfo, selectedQuantization, isFetching } = useModel()
29
 
30
  const ModelInfoSkeleton = () => (
31
- <div className="bg-gradient-to-r from-blue-50 to-indigo-50 px-3 py-3 rounded-lg border border-blue-200 space-y-3 animate-pulse w-4/5">
32
  <div className="flex items-center space-x-2">
33
  <Bot className="w-4 h-4 text-blue-300" />
34
- <div className="h-4 bg-gray-300 rounded flex-1"></div>
35
  <div className="w-4 h-4 bg-gray-300 rounded-full"></div>
36
  </div>
37
 
38
  <div className="flex items-center space-x-2 ml-6">
39
- <div className="h-3 bg-gray-200 rounded w-32"></div>
40
  </div>
41
 
42
  <div className="grid grid-cols-2 gap-2 text-xs">
43
  <div className="flex items-center space-x-1">
44
  <Heart className="w-3 h-3 text-red-300" />
45
- <div className="h-3 bg-gray-200 rounded w-8"></div>
46
  </div>
47
  <div className="flex items-center space-x-1">
48
  <Download className="w-3 h-3 text-green-300" />
49
- <div className="h-3 bg-gray-200 rounded w-8"></div>
50
  </div>
51
  <div className="flex items-center space-x-1">
52
  <Cpu className="w-3 h-3 text-purple-300" />
53
- <div className="h-3 bg-gray-200 rounded w-8"></div>
54
  </div>
55
  <div className="flex items-center space-x-1">
56
  <DatabaseIcon className="w-3 h-3 text-purple-300" />
57
- <div className="h-3 bg-gray-200 rounded w-12"></div>
58
  </div>
59
  </div>
60
  <hr className="border-gray-200" />
61
- <div className="h-8 bg-gray-200 rounded w-full"></div>
62
  </div>
63
  )
64
 
@@ -67,12 +67,12 @@ const ModelInfo = () => {
67
  }
68
 
69
  return (
70
- <div className="relative bg-gradient-to-r from-blue-50 to-indigo-50 px-3 py-3 rounded-lg border border-blue-200 space-y-3 h-full w-4/5">
71
  {/* Model Name Row */}
72
  <div className="flex justify-center items-center space-x-2">
73
  {/* Compatibility Status */}
74
  {typeof modelInfo.isCompatible === 'boolean' && (
75
- <div className="flex-shrink-0 ">
76
  {modelInfo.isCompatible ? (
77
  <CheckCircle className="w-4 h-4 text-green-500" />
78
  ) : (
 
28
  const { models, modelInfo, selectedQuantization, isFetching } = useModel()
29
 
30
  const ModelInfoSkeleton = () => (
31
+ <div className="bg-linear-to-r from-blue-50 to-indigo-50 px-3 py-3 rounded-lg border border-blue-200 space-y-3 animate-pulse w-4/5">
32
  <div className="flex items-center space-x-2">
33
  <Bot className="w-4 h-4 text-blue-300" />
34
+ <div className="h-4 bg-gray-300 rounded-sm flex-1"></div>
35
  <div className="w-4 h-4 bg-gray-300 rounded-full"></div>
36
  </div>
37
 
38
  <div className="flex items-center space-x-2 ml-6">
39
+ <div className="h-3 bg-gray-200 rounded-sm w-32"></div>
40
  </div>
41
 
42
  <div className="grid grid-cols-2 gap-2 text-xs">
43
  <div className="flex items-center space-x-1">
44
  <Heart className="w-3 h-3 text-red-300" />
45
+ <div className="h-3 bg-gray-200 rounded-sm w-8"></div>
46
  </div>
47
  <div className="flex items-center space-x-1">
48
  <Download className="w-3 h-3 text-green-300" />
49
+ <div className="h-3 bg-gray-200 rounded-sm w-8"></div>
50
  </div>
51
  <div className="flex items-center space-x-1">
52
  <Cpu className="w-3 h-3 text-purple-300" />
53
+ <div className="h-3 bg-gray-200 rounded-sm w-8"></div>
54
  </div>
55
  <div className="flex items-center space-x-1">
56
  <DatabaseIcon className="w-3 h-3 text-purple-300" />
57
+ <div className="h-3 bg-gray-200 rounded-sm w-12"></div>
58
  </div>
59
  </div>
60
  <hr className="border-gray-200" />
61
+ <div className="h-8 bg-gray-200 rounded-sm w-full"></div>
62
  </div>
63
  )
64
 
 
67
  }
68
 
69
  return (
70
+ <div className="relative bg-linear-to-r from-blue-50 to-indigo-50 px-3 py-3 rounded-lg border border-blue-200 space-y-3 h-full w-4/5">
71
  {/* Model Name Row */}
72
  <div className="flex justify-center items-center space-x-2">
73
  {/* Compatibility Status */}
74
  {typeof modelInfo.isCompatible === 'boolean' && (
75
+ <div className="shrink-0 ">
76
  {modelInfo.isCompatible ? (
77
  <CheckCircle className="w-4 h-4 text-green-500" />
78
  ) : (
src/components/ModelLoader.tsx CHANGED
@@ -127,7 +127,7 @@ const ModelLoader = () => {
127
  onChange={(e) =>
128
  setSelectedQuantization(e.target.value as QuantizationType)
129
  }
130
- className="appearance-none bg-white border border-gray-300 rounded-md px-3 py-1 pr-8 text-xs text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
131
  >
132
  {modelInfo.supportedQuantizations.map((quant) => (
133
  <option key={quant} value={quant}>
@@ -148,7 +148,7 @@ const ModelLoader = () => {
148
  {selectedQuantization && (
149
  <div className="flex justify-center">
150
  <button
151
- className="w-32 py-2 px-4 bg-green-500 hover:bg-green-600 rounded text-white font-medium disabled:opacity-50 disabled:cursor-not-allowed transition-colors text-sm inline-flex items-center text-center justify-center space-x-2"
152
  disabled={hasBeenLoaded || status === 'loading'}
153
  onClick={loadModel}
154
  >
 
127
  onChange={(e) =>
128
  setSelectedQuantization(e.target.value as QuantizationType)
129
  }
130
+ className="appearance-none bg-white border border-gray-300 rounded-md px-3 py-1 pr-8 text-xs text-gray-700 focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
131
  >
132
  {modelInfo.supportedQuantizations.map((quant) => (
133
  <option key={quant} value={quant}>
 
148
  {selectedQuantization && (
149
  <div className="flex justify-center">
150
  <button
151
+ className="w-32 py-2 px-4 bg-green-500 hover:bg-green-600 rounded-sm text-white font-medium disabled:opacity-50 disabled:cursor-not-allowed transition-colors text-sm inline-flex items-center text-center justify-center space-x-2"
152
  disabled={hasBeenLoaded || status === 'loading'}
153
  onClick={loadModel}
154
  >
src/components/ModelSelector.tsx CHANGED
@@ -252,21 +252,21 @@ function ModelSelector() {
252
  <div className="relative">
253
  <div className="w-full px-3 py-2 border border-gray-300 rounded-md bg-white flex items-center justify-between animate-pulse h-10">
254
  <div className="flex flex-col flex-1 min-w-0 space-y-2">
255
- <div className="h-4 bg-gray-200 rounded w-3/4"></div>
256
  </div>
257
 
258
  <div className="flex items-center space-x-3">
259
  <div className="flex items-center space-x-3">
260
  <div className="flex items-center space-x-1">
261
  <Heart className="w-3 h-3 text-red-500" />
262
- <div className="h-3 bg-gray-200 rounded w-8"></div>
263
  </div>
264
  <div className="flex items-center space-x-1">
265
  <Download className="w-3 h-3 text-green-500" />
266
- <div className="h-3 bg-gray-200 rounded w-8"></div>
267
  </div>
268
  </div>
269
- <div className="w-4 h-4 bg-gray-200 rounded"></div>
270
  </div>
271
  </div>
272
  </div>
@@ -280,7 +280,7 @@ function ModelSelector() {
280
  onChange={(model) => handleModelSelect(model.id)}
281
  >
282
  <div className="relative">
283
- <ListboxButton className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white text-left flex items-center justify-between">
284
  <div className="flex items-center justify-between w-full">
285
  <div className="flex flex-col flex-1 min-w-0">
286
  <Tooltip content={modelInfo?.id || 'Select a model'}>
@@ -308,7 +308,7 @@ function ModelSelector() {
308
  )}
309
  </div>
310
  )}
311
- <ChevronDown className="w-4 h-4 ui-open:rotate-180 transition-transform flex-shrink-0" />
312
  </div>
313
  </div>
314
  </ListboxButton>
@@ -321,7 +321,7 @@ function ModelSelector() {
321
  leaveFrom="transform scale-100 opacity-100"
322
  leaveTo="transform scale-95 opacity-0"
323
  >
324
- <ListboxOptions className="absolute z-10 w-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg max-h-96 overflow-hidden focus:outline-none">
325
  {/* Custom Model Input */}
326
  {showCustomInput ? (
327
  <div className="px-3 py-3 border-b border-gray-200 bg-gray-50 sticky top-0 z-10">
@@ -333,13 +333,13 @@ function ModelSelector() {
333
  onChange={(e) => setCustomModelName(e.target.value)}
334
  onKeyDown={handleCustomInputKeyPress}
335
  placeholder="Enter model name (e.g., Qwen/Qwen3-0.6B)"
336
- className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500"
337
  autoFocus
338
  />
339
  <button
340
  onClick={handleCustomModelLoad}
341
  disabled={isLoadingCustomModel}
342
- className="px-3 py-1 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center space-x-1"
343
  >
344
  {isLoadingCustomModel ? (
345
  <div className="w-3 h-3 border border-white border-t-transparent rounded-full animate-spin" />
@@ -373,7 +373,7 @@ function ModelSelector() {
373
  {/* Load Custom Model Button */}
374
  <button
375
  onClick={() => setShowCustomInput(true)}
376
- className="w-full flex items-center justify-center space-x-2 px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded transition-colors"
377
  >
378
  <Plus className="w-4 h-4" />
379
  <span>Load Custom Model</span>
@@ -469,7 +469,7 @@ function ModelSelector() {
469
  </span>
470
  </Tooltip>
471
  {selected && (
472
- <Check className="w-4 h-4 text-blue-600 ml-2 flex-shrink-0" />
473
  )}
474
  </div>
475
  {/* Stats Display */}
 
252
  <div className="relative">
253
  <div className="w-full px-3 py-2 border border-gray-300 rounded-md bg-white flex items-center justify-between animate-pulse h-10">
254
  <div className="flex flex-col flex-1 min-w-0 space-y-2">
255
+ <div className="h-4 bg-gray-200 rounded-sm w-3/4"></div>
256
  </div>
257
 
258
  <div className="flex items-center space-x-3">
259
  <div className="flex items-center space-x-3">
260
  <div className="flex items-center space-x-1">
261
  <Heart className="w-3 h-3 text-red-500" />
262
+ <div className="h-3 bg-gray-200 rounded-sm w-8"></div>
263
  </div>
264
  <div className="flex items-center space-x-1">
265
  <Download className="w-3 h-3 text-green-500" />
266
+ <div className="h-3 bg-gray-200 rounded-sm w-8"></div>
267
  </div>
268
  </div>
269
+ <div className="w-4 h-4 bg-gray-200 rounded-sm"></div>
270
  </div>
271
  </div>
272
  </div>
 
280
  onChange={(model) => handleModelSelect(model.id)}
281
  >
282
  <div className="relative">
283
+ <ListboxButton className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white text-left flex items-center justify-between">
284
  <div className="flex items-center justify-between w-full">
285
  <div className="flex flex-col flex-1 min-w-0">
286
  <Tooltip content={modelInfo?.id || 'Select a model'}>
 
308
  )}
309
  </div>
310
  )}
311
+ <ChevronDown className="w-4 h-4 ui-open:rotate-180 transition-transform shrink-0" />
312
  </div>
313
  </div>
314
  </ListboxButton>
 
321
  leaveFrom="transform scale-100 opacity-100"
322
  leaveTo="transform scale-95 opacity-0"
323
  >
324
+ <ListboxOptions className="absolute z-10 w-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg max-h-96 overflow-hidden focus:outline-hidden">
325
  {/* Custom Model Input */}
326
  {showCustomInput ? (
327
  <div className="px-3 py-3 border-b border-gray-200 bg-gray-50 sticky top-0 z-10">
 
333
  onChange={(e) => setCustomModelName(e.target.value)}
334
  onKeyDown={handleCustomInputKeyPress}
335
  placeholder="Enter model name (e.g., Qwen/Qwen3-0.6B)"
336
+ className="flex-1 px-2 py-1 text-sm border border-gray-300 rounded-sm focus:outline-hidden focus:ring-1 focus:ring-blue-500"
337
  autoFocus
338
  />
339
  <button
340
  onClick={handleCustomModelLoad}
341
  disabled={isLoadingCustomModel}
342
+ className="px-3 py-1 text-sm bg-blue-600 text-white rounded-sm hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center space-x-1"
343
  >
344
  {isLoadingCustomModel ? (
345
  <div className="w-3 h-3 border border-white border-t-transparent rounded-full animate-spin" />
 
373
  {/* Load Custom Model Button */}
374
  <button
375
  onClick={() => setShowCustomInput(true)}
376
+ className="w-full flex items-center justify-center space-x-2 px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded-sm transition-colors"
377
  >
378
  <Plus className="w-4 h-4" />
379
  <span>Load Custom Model</span>
 
469
  </span>
470
  </Tooltip>
471
  {selected && (
472
+ <Check className="w-4 h-4 text-blue-600 ml-2 shrink-0" />
473
  )}
474
  </div>
475
  {/* Stats Display */}
src/components/PipelineSelector.tsx CHANGED
@@ -40,7 +40,7 @@ const PipelineSelector: React.FC<PipelineSelectorProps> = ({
40
  <div className="relative">
41
  <Listbox value={selectedPipeline} onChange={setPipeline}>
42
  <div className="relative">
43
- <ListboxButton className="relative w-full cursor-default rounded-lg bg-white py-2 pl-3 pr-10 text-left focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 text-sm xl:text-base border border-gray-300">
44
  <span className="block truncate font-medium">
45
  {formatPipelineName(selectedPipeline)}
46
  </span>
@@ -60,7 +60,7 @@ const PipelineSelector: React.FC<PipelineSelectorProps> = ({
60
  leaveFrom="transform scale-100 opacity-100"
61
  leaveTo="transform scale-95 opacity-0"
62
  >
63
- <ListboxOptions className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-sm xl:text-base ring-1 ring-black ring-opacity-5 focus:outline-none">
64
  {supportedPipelines.map((p) => (
65
  <ListboxOption
66
  key={p}
 
40
  <div className="relative">
41
  <Listbox value={selectedPipeline} onChange={setPipeline}>
42
  <div className="relative">
43
+ <ListboxButton className="relative w-full cursor-default rounded-lg bg-white py-2 pl-3 pr-10 text-left focus:outline-hidden focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 text-sm xl:text-base border border-gray-300">
44
  <span className="block truncate font-medium">
45
  {formatPipelineName(selectedPipeline)}
46
  </span>
 
60
  leaveFrom="transform scale-100 opacity-100"
61
  leaveTo="transform scale-95 opacity-0"
62
  >
63
+ <ListboxOptions className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-sm xl:text-base ring-1 ring-black ring-opacity-5 focus:outline-hidden">
64
  {supportedPipelines.map((p) => (
65
  <ListboxOption
66
  key={p}
src/components/Sidebar.tsx CHANGED
@@ -81,7 +81,7 @@ const Sidebar = ({ isOpen, onClose, setIsModalOpen }: SidebarProps) => {
81
  onClick={() => setIsModalOpen(true)}
82
  className="flex items-center w-full px-3 py-2 text-sm text-gray-600 bg-gray-50 rounded-lg border border-gray-200 hover:bg-gray-100 transition-colors"
83
  >
84
- <FileText className="w-4 h-4 mr-2 flex-shrink-0" />
85
  <span className="truncate">View README.md</span>
86
  </button>
87
  </div>
 
81
  onClick={() => setIsModalOpen(true)}
82
  className="flex items-center w-full px-3 py-2 text-sm text-gray-600 bg-gray-50 rounded-lg border border-gray-200 hover:bg-gray-100 transition-colors"
83
  >
84
+ <FileText className="w-4 h-4 mr-2 shrink-0" />
85
  <span className="truncate">View README.md</span>
86
  </button>
87
  </div>
src/components/Tooltip.tsx CHANGED
@@ -11,7 +11,7 @@ const Tooltip: React.FC<TooltipProps> = ({ children, content, className }) => {
11
  <div className="relative group flex items-center">
12
  {children}
13
  <div
14
- className={`absolute left-0 top-full mt-2 w-max max-w-sm px-3 py-1.5 text-xs font-medium text-white bg-gray-900 rounded-lg shadow-sm opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-opacity duration-300 z-20 pointer-events-none ${className}`}
15
  >
16
  {content}
17
  </div>
 
11
  <div className="relative group flex items-center">
12
  {children}
13
  <div
14
+ className={`absolute left-0 top-full mt-2 w-max max-w-sm px-3 py-1.5 text-xs font-medium text-white bg-gray-900 rounded-lg shadow-xs opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-opacity duration-300 z-20 pointer-events-none ${className}`}
15
  >
16
  {content}
17
  </div>
src/components/pipelines/FeatureExtraction.tsx CHANGED
@@ -273,7 +273,7 @@ function FeatureExtraction() {
273
  onChange={(e) => setNewExampleText(e.target.value)}
274
  onKeyPress={handleKeyPress}
275
  placeholder="Enter text to get embeddings... (Press Enter to add)"
276
- className="flex-1 p-3 border border-gray-300 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
277
  rows={2}
278
  disabled={!hasBeenLoaded || isExtracting}
279
  />
 
273
  onChange={(e) => setNewExampleText(e.target.value)}
274
  onKeyPress={handleKeyPress}
275
  placeholder="Enter text to get embeddings... (Press Enter to add)"
276
+ className="flex-1 p-3 border border-gray-300 rounded-lg resize-none focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
277
  rows={2}
278
  disabled={!hasBeenLoaded || isExtracting}
279
  />
src/components/pipelines/FeatureExtractionConfig.tsx CHANGED
@@ -23,7 +23,7 @@ const FeatureExtractionConfig = () => {
23
  pooling: e.target.value as 'mean' | 'cls' | 'max'
24
  }))
25
  }
26
- className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
27
  >
28
  <option value="mean">Mean Pooling</option>
29
  <option value="cls">CLS Token</option>
@@ -45,7 +45,7 @@ const FeatureExtractionConfig = () => {
45
  normalize: e.target.checked
46
  }))
47
  }
48
- className="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50"
49
  />
50
  <span className="text-sm font-medium text-gray-700">
51
  Normalize Embeddings
 
23
  pooling: e.target.value as 'mean' | 'cls' | 'max'
24
  }))
25
  }
26
+ className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-xs focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
27
  >
28
  <option value="mean">Mean Pooling</option>
29
  <option value="cls">CLS Token</option>
 
45
  normalize: e.target.checked
46
  }))
47
  }
48
+ className="rounded border-gray-300 text-blue-600 shadow-xs focus:border-blue-300 focus:ring-3 focus:ring-blue-200 focus:ring-opacity-50"
49
  />
50
  <span className="text-sm font-medium text-gray-700">
51
  Normalize Embeddings
src/components/pipelines/ImageClassification.tsx CHANGED
@@ -305,7 +305,7 @@ function ImageClassification() {
305
  >
306
  <div className="flex gap-3">
307
  {showPreviews && (
308
- <div className="flex-shrink-0">
309
  <img
310
  src={example.url}
311
  alt={example.name}
 
305
  >
306
  <div className="flex gap-3">
307
  {showPreviews && (
308
+ <div className="shrink-0">
309
  <img
310
  src={example.url}
311
  alt={example.name}
src/components/pipelines/TextClassification.tsx CHANGED
@@ -81,28 +81,28 @@ function TextClassification() {
81
 
82
  return (
83
  <div className="flex flex-col h-full max-h-[92vh] w-full p-4">
84
- <h1 className="text-2xl font-bold mb-4 flex-shrink-0">
85
  Text Classification
86
  </h1>
87
 
88
  <div className="flex flex-col lg:flex-row gap-4 flex-1 min-h-0">
89
  {/* Input Section */}
90
  <div className="flex flex-col w-full lg:w-1/2 min-h-0">
91
- <label className="text-lg font-medium mb-2 flex-shrink-0">
92
  Input Text ({numberExamples} examples):
93
  </label>
94
 
95
  <div className="flex flex-col flex-1 min-h-0">
96
  <textarea
97
- className="border border-gray-300 rounded p-3 flex-1 resize-none min-h-[200px]"
98
  value={text}
99
  onChange={(e) => setText(e.target.value)}
100
  placeholder="Enter text to classify (one per line)..."
101
  />
102
 
103
- <div className="flex gap-2 mt-4 flex-shrink-0">
104
  <button
105
- className="flex-1 py-2 px-4 bg-blue-500 hover:bg-blue-600 rounded text-white font-medium disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
106
  disabled={busy}
107
  onClick={classify}
108
  >
@@ -113,7 +113,7 @@ function TextClassification() {
113
  : 'Load model first'}
114
  </button>
115
  <button
116
- className="py-2 px-4 bg-gray-500 hover:bg-gray-600 rounded text-white font-medium transition-colors"
117
  onClick={handleClear}
118
  >
119
  Clear Results
@@ -124,11 +124,11 @@ function TextClassification() {
124
 
125
  {/* Results Section */}
126
  <div className="flex flex-col w-full lg:w-1/2 min-h-0">
127
- <label className="text-lg font-medium mb-2 flex-shrink-0">
128
  Classification Results ({results.length}):
129
  </label>
130
 
131
- <div className="border border-gray-300 rounded p-3 flex-1 overflow-y-auto min-h-[200px]">
132
  {results.length === 0 ? (
133
  <div className="text-gray-500 text-center py-8">
134
  No results yet. Click "Classify Text" to analyze your input.
@@ -136,7 +136,7 @@ function TextClassification() {
136
  ) : (
137
  <div className="space-y-3">
138
  {results.map((result, index) => (
139
- <div key={index} className="p-3 rounded border-2">
140
  <div className="flex justify-between items-start mb-2">
141
  <span className="font-semibold text-sm">
142
  {result.labels[0]}
 
81
 
82
  return (
83
  <div className="flex flex-col h-full max-h-[92vh] w-full p-4">
84
+ <h1 className="text-2xl font-bold mb-4 shrink-0">
85
  Text Classification
86
  </h1>
87
 
88
  <div className="flex flex-col lg:flex-row gap-4 flex-1 min-h-0">
89
  {/* Input Section */}
90
  <div className="flex flex-col w-full lg:w-1/2 min-h-0">
91
+ <label className="text-lg font-medium mb-2 shrink-0">
92
  Input Text ({numberExamples} examples):
93
  </label>
94
 
95
  <div className="flex flex-col flex-1 min-h-0">
96
  <textarea
97
+ className="border border-gray-300 rounded-sm p-3 flex-1 resize-none min-h-[200px]"
98
  value={text}
99
  onChange={(e) => setText(e.target.value)}
100
  placeholder="Enter text to classify (one per line)..."
101
  />
102
 
103
+ <div className="flex gap-2 mt-4 shrink-0">
104
  <button
105
+ className="flex-1 py-2 px-4 bg-blue-500 hover:bg-blue-600 rounded-sm text-white font-medium disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
106
  disabled={busy}
107
  onClick={classify}
108
  >
 
113
  : 'Load model first'}
114
  </button>
115
  <button
116
+ className="py-2 px-4 bg-gray-500 hover:bg-gray-600 rounded-sm text-white font-medium transition-colors"
117
  onClick={handleClear}
118
  >
119
  Clear Results
 
124
 
125
  {/* Results Section */}
126
  <div className="flex flex-col w-full lg:w-1/2 min-h-0">
127
+ <label className="text-lg font-medium mb-2 shrink-0">
128
  Classification Results ({results.length}):
129
  </label>
130
 
131
+ <div className="border border-gray-300 rounded-sm p-3 flex-1 overflow-y-auto min-h-[200px]">
132
  {results.length === 0 ? (
133
  <div className="text-gray-500 text-center py-8">
134
  No results yet. Click "Classify Text" to analyze your input.
 
136
  ) : (
137
  <div className="space-y-3">
138
  {results.map((result, index) => (
139
+ <div key={index} className="p-3 rounded-sm border-2">
140
  <div className="flex justify-between items-start mb-2">
141
  <span className="font-semibold text-sm">
142
  {result.labels[0]}
src/components/pipelines/TextGeneration.tsx CHANGED
@@ -227,7 +227,7 @@ function TextGeneration() {
227
  onChange={(e) => setCurrentMessage(e.target.value)}
228
  onKeyPress={handleKeyPress}
229
  placeholder="Type your message... (Press Enter to send, Shift+Enter for new line)"
230
- className="flex-1 p-3 border border-gray-300 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
231
  rows={2}
232
  disabled={!hasBeenLoaded || isGenerating}
233
  />
@@ -255,7 +255,7 @@ function TextGeneration() {
255
  onChange={(e) => setPrompt(e.target.value)}
256
  onKeyPress={handleKeyPress}
257
  placeholder="Enter your text prompt here... (Press Enter to generate, Shift+Enter for new line)"
258
- className="w-full p-3 border border-gray-300 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
259
  rows={4}
260
  disabled={!hasBeenLoaded || isGenerating}
261
  />
@@ -286,7 +286,7 @@ function TextGeneration() {
286
  </label>
287
  </div>
288
  {generatedText ? (
289
- <div className="whitespace-pre-wrap text-gray-800 bg-gray-50 p-3 rounded border">
290
  {generatedText}
291
  </div>
292
  ) : (
 
227
  onChange={(e) => setCurrentMessage(e.target.value)}
228
  onKeyPress={handleKeyPress}
229
  placeholder="Type your message... (Press Enter to send, Shift+Enter for new line)"
230
+ className="flex-1 p-3 border border-gray-300 rounded-lg resize-none focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
231
  rows={2}
232
  disabled={!hasBeenLoaded || isGenerating}
233
  />
 
255
  onChange={(e) => setPrompt(e.target.value)}
256
  onKeyPress={handleKeyPress}
257
  placeholder="Enter your text prompt here... (Press Enter to generate, Shift+Enter for new line)"
258
+ className="w-full p-3 border border-gray-300 rounded-lg resize-none focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
259
  rows={4}
260
  disabled={!hasBeenLoaded || isGenerating}
261
  />
 
286
  </label>
287
  </div>
288
  {generatedText ? (
289
+ <div className="whitespace-pre-wrap text-gray-800 bg-gray-50 p-3 rounded-sm border">
290
  {generatedText}
291
  </div>
292
  ) : (
src/components/pipelines/TextGenerationConfig.tsx CHANGED
@@ -135,7 +135,7 @@ function TextGenerationConfig() {
135
  <textarea
136
  value={messages.find((m) => m.role === 'system')?.content || ''}
137
  onChange={(e) => updateSystemMessage(e.target.value)}
138
- className="w-full p-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
139
  rows={4}
140
  placeholder="e.g., You are a helpful assistant."
141
  />
 
135
  <textarea
136
  value={messages.find((m) => m.role === 'system')?.content || ''}
137
  onChange={(e) => updateSystemMessage(e.target.value)}
138
+ className="w-full p-2 border border-gray-300 rounded-md text-sm focus:outline-hidden focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
139
  rows={4}
140
  placeholder="e.g., You are a helpful assistant."
141
  />
src/components/pipelines/ZeroShotClassification.tsx CHANGED
@@ -95,7 +95,7 @@ function ZeroShotClassification() {
95
  value={text}
96
  onChange={(e) => setText(e.target.value)}
97
  placeholder="Enter text items to classify, one per line..."
98
- className="w-full p-3 border border-gray-300 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
99
  rows={12}
100
  disabled={!hasBeenLoaded || busy}
101
  />
@@ -147,7 +147,7 @@ function ZeroShotClassification() {
147
  {section.items.map((item, itemIndex) => (
148
  <div
149
  key={itemIndex}
150
- className="p-2 bg-blue-50 border border-blue-200 rounded text-sm"
151
  >
152
  {item}
153
  </div>
 
95
  value={text}
96
  onChange={(e) => setText(e.target.value)}
97
  placeholder="Enter text items to classify, one per line..."
98
+ className="w-full p-3 border border-gray-300 rounded-lg resize-none focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
99
  rows={12}
100
  disabled={!hasBeenLoaded || busy}
101
  />
 
147
  {section.items.map((item, itemIndex) => (
148
  <div
149
  key={itemIndex}
150
+ className="p-2 bg-blue-50 border border-blue-200 rounded-sm text-sm"
151
  >
152
  {item}
153
  </div>
src/components/pipelines/ZeroShotClassificationConfig.tsx CHANGED
@@ -57,9 +57,9 @@ const ZeroShotClassificationConfig = () => {
57
  value={section.title}
58
  onChange={(e) => updateSectionTitle(index, e.target.value)}
59
  disabled={section.title === 'Other'}
60
- className="flex-1 px-2 py-1 text-xs border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
61
  />
62
- <span className="text-xs text-gray-500 min-w-[2rem]">
63
  ({section.items.length})
64
  </span>
65
  </div>
@@ -69,7 +69,7 @@ const ZeroShotClassificationConfig = () => {
69
  <div className="flex gap-2 mt-3">
70
  <button
71
  onClick={addCategory}
72
- className="flex items-center gap-1 px-3 py-1 text-xs bg-green-500 hover:bg-green-600 text-white rounded transition-colors"
73
  title="Add Category"
74
  >
75
  <Plus className="w-3 h-3" />
@@ -78,7 +78,7 @@ const ZeroShotClassificationConfig = () => {
78
  <button
79
  onClick={removeCategory}
80
  disabled={sections.length <= 1}
81
- className="flex items-center gap-1 px-3 py-1 text-xs bg-red-500 hover:bg-red-600 disabled:bg-gray-300 disabled:cursor-not-allowed text-white rounded transition-colors"
82
  title="Remove Category"
83
  >
84
  <Minus className="w-3 h-3" />
@@ -86,7 +86,7 @@ const ZeroShotClassificationConfig = () => {
86
  </button>
87
  <button
88
  onClick={clearResults}
89
- className="flex items-center gap-1 px-3 py-1 text-xs bg-orange-500 hover:bg-orange-600 text-white rounded transition-colors"
90
  title="Clear Results"
91
  >
92
  <Trash2 className="w-3 h-3" />
 
57
  value={section.title}
58
  onChange={(e) => updateSectionTitle(index, e.target.value)}
59
  disabled={section.title === 'Other'}
60
+ className="flex-1 px-2 py-1 text-xs border border-gray-300 rounded-sm focus:outline-hidden focus:ring-1 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
61
  />
62
+ <span className="text-xs text-gray-500 min-w-8">
63
  ({section.items.length})
64
  </span>
65
  </div>
 
69
  <div className="flex gap-2 mt-3">
70
  <button
71
  onClick={addCategory}
72
+ className="flex items-center gap-1 px-3 py-1 text-xs bg-green-500 hover:bg-green-600 text-white rounded-sm transition-colors"
73
  title="Add Category"
74
  >
75
  <Plus className="w-3 h-3" />
 
78
  <button
79
  onClick={removeCategory}
80
  disabled={sections.length <= 1}
81
+ className="flex items-center gap-1 px-3 py-1 text-xs bg-red-500 hover:bg-red-600 disabled:bg-gray-300 disabled:cursor-not-allowed text-white rounded-sm transition-colors"
82
  title="Remove Category"
83
  >
84
  <Minus className="w-3 h-3" />
 
86
  </button>
87
  <button
88
  onClick={clearResults}
89
+ className="flex items-center gap-1 px-3 py-1 text-xs bg-orange-500 hover:bg-orange-600 text-white rounded-sm transition-colors"
90
  title="Clear Results"
91
  >
92
  <Trash2 className="w-3 h-3" />
src/index.css CHANGED
@@ -1,6 +1,22 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  body {
6
  margin: 0;
 
1
+ @import 'tailwindcss';
2
+
3
+ /*
4
+ The default border color has changed to `currentcolor` in Tailwind CSS v4,
5
+ so we've added these compatibility styles to make sure everything still
6
+ looks the same as it did with Tailwind CSS v3.
7
+
8
+ If we ever want to remove these styles, we need to add an explicit border
9
+ color utility to any element that depends on these defaults.
10
+ */
11
+ @layer base {
12
+ *,
13
+ ::after,
14
+ ::before,
15
+ ::backdrop,
16
+ ::file-selector-button {
17
+ border-color: var(--color-gray-200, currentcolor);
18
+ }
19
+ }
20
 
21
  body {
22
  margin: 0;
src/lib/workerManager.ts CHANGED
@@ -6,19 +6,19 @@ export const getWorker = (pipeline: string) => {
6
 
7
  switch (pipeline) {
8
  case 'text-classification':
9
- workerUrl = `${process.env.PUBLIC_URL}/workers/text-classification.js`
10
  break
11
  case 'zero-shot-classification':
12
- workerUrl = `${process.env.PUBLIC_URL}/workers/zero-shot-classification.js`
13
  break
14
  case 'text-generation':
15
- workerUrl = `${process.env.PUBLIC_URL}/workers/text-generation.js`
16
  break
17
  case 'feature-extraction':
18
- workerUrl = `${process.env.PUBLIC_URL}/workers/feature-extraction.js`
19
  break
20
  case 'image-classification':
21
- workerUrl = `${process.env.PUBLIC_URL}/workers/image-classification.js`
22
  break
23
  default:
24
  return null
 
6
 
7
  switch (pipeline) {
8
  case 'text-classification':
9
+ workerUrl = `/workers/text-classification.js`
10
  break
11
  case 'zero-shot-classification':
12
+ workerUrl = `/workers/zero-shot-classification.js`
13
  break
14
  case 'text-generation':
15
+ workerUrl = `/workers/text-generation.js`
16
  break
17
  case 'feature-extraction':
18
+ workerUrl = `/workers/feature-extraction.js`
19
  break
20
  case 'image-classification':
21
+ workerUrl = `/workers/image-classification.js`
22
  break
23
  default:
24
  return null
tailwind.config.js DELETED
@@ -1,8 +0,0 @@
1
- /** @type {import('tailwindcss').Config} */
2
- module.exports = {
3
- content: ['./src/**/*.{js,jsx,ts,tsx}'],
4
- theme: {
5
- extend: {}
6
- }
7
- // plugins: [require('@tailwindcss/typography')]
8
- }
 
 
 
 
 
 
 
 
 
tsconfig.json CHANGED
@@ -1,20 +1,21 @@
1
  {
2
  "compilerOptions": {
3
- "target": "es2020",
4
- "lib": ["dom", "dom.iterable", "esnext", "WebWorker"],
5
- "allowJs": true,
6
  "skipLibCheck": true,
7
  "esModuleInterop": true,
8
  "allowSyntheticDefaultImports": true,
9
  "strict": true,
10
  "forceConsistentCasingInFileNames": true,
11
- "noFallthroughCasesInSwitch": true,
12
  "module": "esnext",
13
  "moduleResolution": "node",
14
  "resolveJsonModule": true,
15
  "isolatedModules": true,
16
  "noEmit": true,
17
- "jsx": "react-jsx"
 
 
18
  },
19
- "include": ["src", "public/workers"]
20
  }
 
1
  {
2
  "compilerOptions": {
3
+ "target": "ESNext",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": false,
6
  "skipLibCheck": true,
7
  "esModuleInterop": true,
8
  "allowSyntheticDefaultImports": true,
9
  "strict": true,
10
  "forceConsistentCasingInFileNames": true,
 
11
  "module": "esnext",
12
  "moduleResolution": "node",
13
  "resolveJsonModule": true,
14
  "isolatedModules": true,
15
  "noEmit": true,
16
+ "noFallthroughCasesInSwitch": true,
17
+ "jsx": "react-jsx",
18
+ "types": ["vite/client", "vite-plugin-svgr/client"]
19
  },
20
+ "include": ["src"]
21
  }
vite-env.d.ts ADDED
@@ -0,0 +1 @@
 
 
1
+ /// <reference types="vite/client" />
vite.config.ts ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react-swc'
3
+ import tailwindcss from '@tailwindcss/vite'
4
+
5
+ // https://vitejs.dev/config/
6
+ export default defineConfig({
7
+ base: '/',
8
+ plugins: [react(), tailwindcss()]
9
+ })