Spaces:
Running
Running
Commit
·
1ae14ee
1
Parent(s):
6108f36
updates
Browse files- package-lock.json +457 -0
- package.json +4 -0
- src/App.tsx +27 -34
- src/components/ui/badge.tsx +29 -0
- src/components/ui/command.tsx +153 -0
- src/components/ui/dialog.tsx +120 -0
- src/components/ui/multi-select.tsx +278 -0
- src/components/ui/popover.tsx +29 -0
- src/components/ui/select.tsx +0 -143
- src/components/ui/separator.tsx +29 -0
package-lock.json
CHANGED
|
@@ -10,10 +10,14 @@
|
|
| 10 |
"dependencies": {
|
| 11 |
"@radix-ui/react-checkbox": "^1.1.1",
|
| 12 |
"@radix-ui/react-collapsible": "^1.1.0",
|
|
|
|
|
|
|
| 13 |
"@radix-ui/react-select": "^2.1.1",
|
|
|
|
| 14 |
"@radix-ui/react-slot": "^1.1.0",
|
| 15 |
"class-variance-authority": "^0.7.0",
|
| 16 |
"clsx": "^2.1.1",
|
|
|
|
| 17 |
"lucide-react": "^0.399.0",
|
| 18 |
"react": "^18.3.1",
|
| 19 |
"react-dom": "^18.3.1",
|
|
@@ -1243,6 +1247,41 @@
|
|
| 1243 |
}
|
| 1244 |
}
|
| 1245 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1246 |
"node_modules/@radix-ui/react-direction": {
|
| 1247 |
"version": "1.1.0",
|
| 1248 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
|
|
@@ -1338,6 +1377,42 @@
|
|
| 1338 |
}
|
| 1339 |
}
|
| 1340 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1341 |
"node_modules/@radix-ui/react-popper": {
|
| 1342 |
"version": "1.2.0",
|
| 1343 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
|
|
@@ -1479,6 +1554,28 @@
|
|
| 1479 |
}
|
| 1480 |
}
|
| 1481 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1482 |
"node_modules/@radix-ui/react-slot": {
|
| 1483 |
"version": "1.1.0",
|
| 1484 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
|
@@ -2507,6 +2604,366 @@
|
|
| 2507 |
"node": ">=6"
|
| 2508 |
}
|
| 2509 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2510 |
"node_modules/color-convert": {
|
| 2511 |
"version": "1.9.3",
|
| 2512 |
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
|
|
|
| 10 |
"dependencies": {
|
| 11 |
"@radix-ui/react-checkbox": "^1.1.1",
|
| 12 |
"@radix-ui/react-collapsible": "^1.1.0",
|
| 13 |
+
"@radix-ui/react-dialog": "^1.1.1",
|
| 14 |
+
"@radix-ui/react-popover": "^1.1.1",
|
| 15 |
"@radix-ui/react-select": "^2.1.1",
|
| 16 |
+
"@radix-ui/react-separator": "^1.1.0",
|
| 17 |
"@radix-ui/react-slot": "^1.1.0",
|
| 18 |
"class-variance-authority": "^0.7.0",
|
| 19 |
"clsx": "^2.1.1",
|
| 20 |
+
"cmdk": "^1.0.0",
|
| 21 |
"lucide-react": "^0.399.0",
|
| 22 |
"react": "^18.3.1",
|
| 23 |
"react-dom": "^18.3.1",
|
|
|
|
| 1247 |
}
|
| 1248 |
}
|
| 1249 |
},
|
| 1250 |
+
"node_modules/@radix-ui/react-dialog": {
|
| 1251 |
+
"version": "1.1.1",
|
| 1252 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz",
|
| 1253 |
+
"integrity": "sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==",
|
| 1254 |
+
"dependencies": {
|
| 1255 |
+
"@radix-ui/primitive": "1.1.0",
|
| 1256 |
+
"@radix-ui/react-compose-refs": "1.1.0",
|
| 1257 |
+
"@radix-ui/react-context": "1.1.0",
|
| 1258 |
+
"@radix-ui/react-dismissable-layer": "1.1.0",
|
| 1259 |
+
"@radix-ui/react-focus-guards": "1.1.0",
|
| 1260 |
+
"@radix-ui/react-focus-scope": "1.1.0",
|
| 1261 |
+
"@radix-ui/react-id": "1.1.0",
|
| 1262 |
+
"@radix-ui/react-portal": "1.1.1",
|
| 1263 |
+
"@radix-ui/react-presence": "1.1.0",
|
| 1264 |
+
"@radix-ui/react-primitive": "2.0.0",
|
| 1265 |
+
"@radix-ui/react-slot": "1.1.0",
|
| 1266 |
+
"@radix-ui/react-use-controllable-state": "1.1.0",
|
| 1267 |
+
"aria-hidden": "^1.1.1",
|
| 1268 |
+
"react-remove-scroll": "2.5.7"
|
| 1269 |
+
},
|
| 1270 |
+
"peerDependencies": {
|
| 1271 |
+
"@types/react": "*",
|
| 1272 |
+
"@types/react-dom": "*",
|
| 1273 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1274 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1275 |
+
},
|
| 1276 |
+
"peerDependenciesMeta": {
|
| 1277 |
+
"@types/react": {
|
| 1278 |
+
"optional": true
|
| 1279 |
+
},
|
| 1280 |
+
"@types/react-dom": {
|
| 1281 |
+
"optional": true
|
| 1282 |
+
}
|
| 1283 |
+
}
|
| 1284 |
+
},
|
| 1285 |
"node_modules/@radix-ui/react-direction": {
|
| 1286 |
"version": "1.1.0",
|
| 1287 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
|
|
|
|
| 1377 |
}
|
| 1378 |
}
|
| 1379 |
},
|
| 1380 |
+
"node_modules/@radix-ui/react-popover": {
|
| 1381 |
+
"version": "1.1.1",
|
| 1382 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.1.tgz",
|
| 1383 |
+
"integrity": "sha512-3y1A3isulwnWhvTTwmIreiB8CF4L+qRjZnK1wYLO7pplddzXKby/GnZ2M7OZY3qgnl6p9AodUIHRYGXNah8Y7g==",
|
| 1384 |
+
"dependencies": {
|
| 1385 |
+
"@radix-ui/primitive": "1.1.0",
|
| 1386 |
+
"@radix-ui/react-compose-refs": "1.1.0",
|
| 1387 |
+
"@radix-ui/react-context": "1.1.0",
|
| 1388 |
+
"@radix-ui/react-dismissable-layer": "1.1.0",
|
| 1389 |
+
"@radix-ui/react-focus-guards": "1.1.0",
|
| 1390 |
+
"@radix-ui/react-focus-scope": "1.1.0",
|
| 1391 |
+
"@radix-ui/react-id": "1.1.0",
|
| 1392 |
+
"@radix-ui/react-popper": "1.2.0",
|
| 1393 |
+
"@radix-ui/react-portal": "1.1.1",
|
| 1394 |
+
"@radix-ui/react-presence": "1.1.0",
|
| 1395 |
+
"@radix-ui/react-primitive": "2.0.0",
|
| 1396 |
+
"@radix-ui/react-slot": "1.1.0",
|
| 1397 |
+
"@radix-ui/react-use-controllable-state": "1.1.0",
|
| 1398 |
+
"aria-hidden": "^1.1.1",
|
| 1399 |
+
"react-remove-scroll": "2.5.7"
|
| 1400 |
+
},
|
| 1401 |
+
"peerDependencies": {
|
| 1402 |
+
"@types/react": "*",
|
| 1403 |
+
"@types/react-dom": "*",
|
| 1404 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1405 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1406 |
+
},
|
| 1407 |
+
"peerDependenciesMeta": {
|
| 1408 |
+
"@types/react": {
|
| 1409 |
+
"optional": true
|
| 1410 |
+
},
|
| 1411 |
+
"@types/react-dom": {
|
| 1412 |
+
"optional": true
|
| 1413 |
+
}
|
| 1414 |
+
}
|
| 1415 |
+
},
|
| 1416 |
"node_modules/@radix-ui/react-popper": {
|
| 1417 |
"version": "1.2.0",
|
| 1418 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
|
|
|
|
| 1554 |
}
|
| 1555 |
}
|
| 1556 |
},
|
| 1557 |
+
"node_modules/@radix-ui/react-separator": {
|
| 1558 |
+
"version": "1.1.0",
|
| 1559 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.0.tgz",
|
| 1560 |
+
"integrity": "sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==",
|
| 1561 |
+
"dependencies": {
|
| 1562 |
+
"@radix-ui/react-primitive": "2.0.0"
|
| 1563 |
+
},
|
| 1564 |
+
"peerDependencies": {
|
| 1565 |
+
"@types/react": "*",
|
| 1566 |
+
"@types/react-dom": "*",
|
| 1567 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1568 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1569 |
+
},
|
| 1570 |
+
"peerDependenciesMeta": {
|
| 1571 |
+
"@types/react": {
|
| 1572 |
+
"optional": true
|
| 1573 |
+
},
|
| 1574 |
+
"@types/react-dom": {
|
| 1575 |
+
"optional": true
|
| 1576 |
+
}
|
| 1577 |
+
}
|
| 1578 |
+
},
|
| 1579 |
"node_modules/@radix-ui/react-slot": {
|
| 1580 |
"version": "1.1.0",
|
| 1581 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
|
|
|
| 2604 |
"node": ">=6"
|
| 2605 |
}
|
| 2606 |
},
|
| 2607 |
+
"node_modules/cmdk": {
|
| 2608 |
+
"version": "1.0.0",
|
| 2609 |
+
"resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz",
|
| 2610 |
+
"integrity": "sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==",
|
| 2611 |
+
"dependencies": {
|
| 2612 |
+
"@radix-ui/react-dialog": "1.0.5",
|
| 2613 |
+
"@radix-ui/react-primitive": "1.0.3"
|
| 2614 |
+
},
|
| 2615 |
+
"peerDependencies": {
|
| 2616 |
+
"react": "^18.0.0",
|
| 2617 |
+
"react-dom": "^18.0.0"
|
| 2618 |
+
}
|
| 2619 |
+
},
|
| 2620 |
+
"node_modules/cmdk/node_modules/@radix-ui/primitive": {
|
| 2621 |
+
"version": "1.0.1",
|
| 2622 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz",
|
| 2623 |
+
"integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==",
|
| 2624 |
+
"dependencies": {
|
| 2625 |
+
"@babel/runtime": "^7.13.10"
|
| 2626 |
+
}
|
| 2627 |
+
},
|
| 2628 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-compose-refs": {
|
| 2629 |
+
"version": "1.0.1",
|
| 2630 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz",
|
| 2631 |
+
"integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==",
|
| 2632 |
+
"dependencies": {
|
| 2633 |
+
"@babel/runtime": "^7.13.10"
|
| 2634 |
+
},
|
| 2635 |
+
"peerDependencies": {
|
| 2636 |
+
"@types/react": "*",
|
| 2637 |
+
"react": "^16.8 || ^17.0 || ^18.0"
|
| 2638 |
+
},
|
| 2639 |
+
"peerDependenciesMeta": {
|
| 2640 |
+
"@types/react": {
|
| 2641 |
+
"optional": true
|
| 2642 |
+
}
|
| 2643 |
+
}
|
| 2644 |
+
},
|
| 2645 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-context": {
|
| 2646 |
+
"version": "1.0.1",
|
| 2647 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz",
|
| 2648 |
+
"integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==",
|
| 2649 |
+
"dependencies": {
|
| 2650 |
+
"@babel/runtime": "^7.13.10"
|
| 2651 |
+
},
|
| 2652 |
+
"peerDependencies": {
|
| 2653 |
+
"@types/react": "*",
|
| 2654 |
+
"react": "^16.8 || ^17.0 || ^18.0"
|
| 2655 |
+
},
|
| 2656 |
+
"peerDependenciesMeta": {
|
| 2657 |
+
"@types/react": {
|
| 2658 |
+
"optional": true
|
| 2659 |
+
}
|
| 2660 |
+
}
|
| 2661 |
+
},
|
| 2662 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-dialog": {
|
| 2663 |
+
"version": "1.0.5",
|
| 2664 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz",
|
| 2665 |
+
"integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==",
|
| 2666 |
+
"dependencies": {
|
| 2667 |
+
"@babel/runtime": "^7.13.10",
|
| 2668 |
+
"@radix-ui/primitive": "1.0.1",
|
| 2669 |
+
"@radix-ui/react-compose-refs": "1.0.1",
|
| 2670 |
+
"@radix-ui/react-context": "1.0.1",
|
| 2671 |
+
"@radix-ui/react-dismissable-layer": "1.0.5",
|
| 2672 |
+
"@radix-ui/react-focus-guards": "1.0.1",
|
| 2673 |
+
"@radix-ui/react-focus-scope": "1.0.4",
|
| 2674 |
+
"@radix-ui/react-id": "1.0.1",
|
| 2675 |
+
"@radix-ui/react-portal": "1.0.4",
|
| 2676 |
+
"@radix-ui/react-presence": "1.0.1",
|
| 2677 |
+
"@radix-ui/react-primitive": "1.0.3",
|
| 2678 |
+
"@radix-ui/react-slot": "1.0.2",
|
| 2679 |
+
"@radix-ui/react-use-controllable-state": "1.0.1",
|
| 2680 |
+
"aria-hidden": "^1.1.1",
|
| 2681 |
+
"react-remove-scroll": "2.5.5"
|
| 2682 |
+
},
|
| 2683 |
+
"peerDependencies": {
|
| 2684 |
+
"@types/react": "*",
|
| 2685 |
+
"@types/react-dom": "*",
|
| 2686 |
+
"react": "^16.8 || ^17.0 || ^18.0",
|
| 2687 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
| 2688 |
+
},
|
| 2689 |
+
"peerDependenciesMeta": {
|
| 2690 |
+
"@types/react": {
|
| 2691 |
+
"optional": true
|
| 2692 |
+
},
|
| 2693 |
+
"@types/react-dom": {
|
| 2694 |
+
"optional": true
|
| 2695 |
+
}
|
| 2696 |
+
}
|
| 2697 |
+
},
|
| 2698 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-dismissable-layer": {
|
| 2699 |
+
"version": "1.0.5",
|
| 2700 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz",
|
| 2701 |
+
"integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==",
|
| 2702 |
+
"dependencies": {
|
| 2703 |
+
"@babel/runtime": "^7.13.10",
|
| 2704 |
+
"@radix-ui/primitive": "1.0.1",
|
| 2705 |
+
"@radix-ui/react-compose-refs": "1.0.1",
|
| 2706 |
+
"@radix-ui/react-primitive": "1.0.3",
|
| 2707 |
+
"@radix-ui/react-use-callback-ref": "1.0.1",
|
| 2708 |
+
"@radix-ui/react-use-escape-keydown": "1.0.3"
|
| 2709 |
+
},
|
| 2710 |
+
"peerDependencies": {
|
| 2711 |
+
"@types/react": "*",
|
| 2712 |
+
"@types/react-dom": "*",
|
| 2713 |
+
"react": "^16.8 || ^17.0 || ^18.0",
|
| 2714 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
| 2715 |
+
},
|
| 2716 |
+
"peerDependenciesMeta": {
|
| 2717 |
+
"@types/react": {
|
| 2718 |
+
"optional": true
|
| 2719 |
+
},
|
| 2720 |
+
"@types/react-dom": {
|
| 2721 |
+
"optional": true
|
| 2722 |
+
}
|
| 2723 |
+
}
|
| 2724 |
+
},
|
| 2725 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-focus-guards": {
|
| 2726 |
+
"version": "1.0.1",
|
| 2727 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz",
|
| 2728 |
+
"integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==",
|
| 2729 |
+
"dependencies": {
|
| 2730 |
+
"@babel/runtime": "^7.13.10"
|
| 2731 |
+
},
|
| 2732 |
+
"peerDependencies": {
|
| 2733 |
+
"@types/react": "*",
|
| 2734 |
+
"react": "^16.8 || ^17.0 || ^18.0"
|
| 2735 |
+
},
|
| 2736 |
+
"peerDependenciesMeta": {
|
| 2737 |
+
"@types/react": {
|
| 2738 |
+
"optional": true
|
| 2739 |
+
}
|
| 2740 |
+
}
|
| 2741 |
+
},
|
| 2742 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-focus-scope": {
|
| 2743 |
+
"version": "1.0.4",
|
| 2744 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz",
|
| 2745 |
+
"integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==",
|
| 2746 |
+
"dependencies": {
|
| 2747 |
+
"@babel/runtime": "^7.13.10",
|
| 2748 |
+
"@radix-ui/react-compose-refs": "1.0.1",
|
| 2749 |
+
"@radix-ui/react-primitive": "1.0.3",
|
| 2750 |
+
"@radix-ui/react-use-callback-ref": "1.0.1"
|
| 2751 |
+
},
|
| 2752 |
+
"peerDependencies": {
|
| 2753 |
+
"@types/react": "*",
|
| 2754 |
+
"@types/react-dom": "*",
|
| 2755 |
+
"react": "^16.8 || ^17.0 || ^18.0",
|
| 2756 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
| 2757 |
+
},
|
| 2758 |
+
"peerDependenciesMeta": {
|
| 2759 |
+
"@types/react": {
|
| 2760 |
+
"optional": true
|
| 2761 |
+
},
|
| 2762 |
+
"@types/react-dom": {
|
| 2763 |
+
"optional": true
|
| 2764 |
+
}
|
| 2765 |
+
}
|
| 2766 |
+
},
|
| 2767 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-id": {
|
| 2768 |
+
"version": "1.0.1",
|
| 2769 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz",
|
| 2770 |
+
"integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==",
|
| 2771 |
+
"dependencies": {
|
| 2772 |
+
"@babel/runtime": "^7.13.10",
|
| 2773 |
+
"@radix-ui/react-use-layout-effect": "1.0.1"
|
| 2774 |
+
},
|
| 2775 |
+
"peerDependencies": {
|
| 2776 |
+
"@types/react": "*",
|
| 2777 |
+
"react": "^16.8 || ^17.0 || ^18.0"
|
| 2778 |
+
},
|
| 2779 |
+
"peerDependenciesMeta": {
|
| 2780 |
+
"@types/react": {
|
| 2781 |
+
"optional": true
|
| 2782 |
+
}
|
| 2783 |
+
}
|
| 2784 |
+
},
|
| 2785 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-portal": {
|
| 2786 |
+
"version": "1.0.4",
|
| 2787 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz",
|
| 2788 |
+
"integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==",
|
| 2789 |
+
"dependencies": {
|
| 2790 |
+
"@babel/runtime": "^7.13.10",
|
| 2791 |
+
"@radix-ui/react-primitive": "1.0.3"
|
| 2792 |
+
},
|
| 2793 |
+
"peerDependencies": {
|
| 2794 |
+
"@types/react": "*",
|
| 2795 |
+
"@types/react-dom": "*",
|
| 2796 |
+
"react": "^16.8 || ^17.0 || ^18.0",
|
| 2797 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
| 2798 |
+
},
|
| 2799 |
+
"peerDependenciesMeta": {
|
| 2800 |
+
"@types/react": {
|
| 2801 |
+
"optional": true
|
| 2802 |
+
},
|
| 2803 |
+
"@types/react-dom": {
|
| 2804 |
+
"optional": true
|
| 2805 |
+
}
|
| 2806 |
+
}
|
| 2807 |
+
},
|
| 2808 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-presence": {
|
| 2809 |
+
"version": "1.0.1",
|
| 2810 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz",
|
| 2811 |
+
"integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==",
|
| 2812 |
+
"dependencies": {
|
| 2813 |
+
"@babel/runtime": "^7.13.10",
|
| 2814 |
+
"@radix-ui/react-compose-refs": "1.0.1",
|
| 2815 |
+
"@radix-ui/react-use-layout-effect": "1.0.1"
|
| 2816 |
+
},
|
| 2817 |
+
"peerDependencies": {
|
| 2818 |
+
"@types/react": "*",
|
| 2819 |
+
"@types/react-dom": "*",
|
| 2820 |
+
"react": "^16.8 || ^17.0 || ^18.0",
|
| 2821 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
| 2822 |
+
},
|
| 2823 |
+
"peerDependenciesMeta": {
|
| 2824 |
+
"@types/react": {
|
| 2825 |
+
"optional": true
|
| 2826 |
+
},
|
| 2827 |
+
"@types/react-dom": {
|
| 2828 |
+
"optional": true
|
| 2829 |
+
}
|
| 2830 |
+
}
|
| 2831 |
+
},
|
| 2832 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-primitive": {
|
| 2833 |
+
"version": "1.0.3",
|
| 2834 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz",
|
| 2835 |
+
"integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==",
|
| 2836 |
+
"dependencies": {
|
| 2837 |
+
"@babel/runtime": "^7.13.10",
|
| 2838 |
+
"@radix-ui/react-slot": "1.0.2"
|
| 2839 |
+
},
|
| 2840 |
+
"peerDependencies": {
|
| 2841 |
+
"@types/react": "*",
|
| 2842 |
+
"@types/react-dom": "*",
|
| 2843 |
+
"react": "^16.8 || ^17.0 || ^18.0",
|
| 2844 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
| 2845 |
+
},
|
| 2846 |
+
"peerDependenciesMeta": {
|
| 2847 |
+
"@types/react": {
|
| 2848 |
+
"optional": true
|
| 2849 |
+
},
|
| 2850 |
+
"@types/react-dom": {
|
| 2851 |
+
"optional": true
|
| 2852 |
+
}
|
| 2853 |
+
}
|
| 2854 |
+
},
|
| 2855 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-slot": {
|
| 2856 |
+
"version": "1.0.2",
|
| 2857 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
| 2858 |
+
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
| 2859 |
+
"dependencies": {
|
| 2860 |
+
"@babel/runtime": "^7.13.10",
|
| 2861 |
+
"@radix-ui/react-compose-refs": "1.0.1"
|
| 2862 |
+
},
|
| 2863 |
+
"peerDependencies": {
|
| 2864 |
+
"@types/react": "*",
|
| 2865 |
+
"react": "^16.8 || ^17.0 || ^18.0"
|
| 2866 |
+
},
|
| 2867 |
+
"peerDependenciesMeta": {
|
| 2868 |
+
"@types/react": {
|
| 2869 |
+
"optional": true
|
| 2870 |
+
}
|
| 2871 |
+
}
|
| 2872 |
+
},
|
| 2873 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-use-callback-ref": {
|
| 2874 |
+
"version": "1.0.1",
|
| 2875 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz",
|
| 2876 |
+
"integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==",
|
| 2877 |
+
"dependencies": {
|
| 2878 |
+
"@babel/runtime": "^7.13.10"
|
| 2879 |
+
},
|
| 2880 |
+
"peerDependencies": {
|
| 2881 |
+
"@types/react": "*",
|
| 2882 |
+
"react": "^16.8 || ^17.0 || ^18.0"
|
| 2883 |
+
},
|
| 2884 |
+
"peerDependenciesMeta": {
|
| 2885 |
+
"@types/react": {
|
| 2886 |
+
"optional": true
|
| 2887 |
+
}
|
| 2888 |
+
}
|
| 2889 |
+
},
|
| 2890 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-use-controllable-state": {
|
| 2891 |
+
"version": "1.0.1",
|
| 2892 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz",
|
| 2893 |
+
"integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==",
|
| 2894 |
+
"dependencies": {
|
| 2895 |
+
"@babel/runtime": "^7.13.10",
|
| 2896 |
+
"@radix-ui/react-use-callback-ref": "1.0.1"
|
| 2897 |
+
},
|
| 2898 |
+
"peerDependencies": {
|
| 2899 |
+
"@types/react": "*",
|
| 2900 |
+
"react": "^16.8 || ^17.0 || ^18.0"
|
| 2901 |
+
},
|
| 2902 |
+
"peerDependenciesMeta": {
|
| 2903 |
+
"@types/react": {
|
| 2904 |
+
"optional": true
|
| 2905 |
+
}
|
| 2906 |
+
}
|
| 2907 |
+
},
|
| 2908 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-use-escape-keydown": {
|
| 2909 |
+
"version": "1.0.3",
|
| 2910 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz",
|
| 2911 |
+
"integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==",
|
| 2912 |
+
"dependencies": {
|
| 2913 |
+
"@babel/runtime": "^7.13.10",
|
| 2914 |
+
"@radix-ui/react-use-callback-ref": "1.0.1"
|
| 2915 |
+
},
|
| 2916 |
+
"peerDependencies": {
|
| 2917 |
+
"@types/react": "*",
|
| 2918 |
+
"react": "^16.8 || ^17.0 || ^18.0"
|
| 2919 |
+
},
|
| 2920 |
+
"peerDependenciesMeta": {
|
| 2921 |
+
"@types/react": {
|
| 2922 |
+
"optional": true
|
| 2923 |
+
}
|
| 2924 |
+
}
|
| 2925 |
+
},
|
| 2926 |
+
"node_modules/cmdk/node_modules/@radix-ui/react-use-layout-effect": {
|
| 2927 |
+
"version": "1.0.1",
|
| 2928 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz",
|
| 2929 |
+
"integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==",
|
| 2930 |
+
"dependencies": {
|
| 2931 |
+
"@babel/runtime": "^7.13.10"
|
| 2932 |
+
},
|
| 2933 |
+
"peerDependencies": {
|
| 2934 |
+
"@types/react": "*",
|
| 2935 |
+
"react": "^16.8 || ^17.0 || ^18.0"
|
| 2936 |
+
},
|
| 2937 |
+
"peerDependenciesMeta": {
|
| 2938 |
+
"@types/react": {
|
| 2939 |
+
"optional": true
|
| 2940 |
+
}
|
| 2941 |
+
}
|
| 2942 |
+
},
|
| 2943 |
+
"node_modules/cmdk/node_modules/react-remove-scroll": {
|
| 2944 |
+
"version": "2.5.5",
|
| 2945 |
+
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz",
|
| 2946 |
+
"integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==",
|
| 2947 |
+
"dependencies": {
|
| 2948 |
+
"react-remove-scroll-bar": "^2.3.3",
|
| 2949 |
+
"react-style-singleton": "^2.2.1",
|
| 2950 |
+
"tslib": "^2.1.0",
|
| 2951 |
+
"use-callback-ref": "^1.3.0",
|
| 2952 |
+
"use-sidecar": "^1.1.2"
|
| 2953 |
+
},
|
| 2954 |
+
"engines": {
|
| 2955 |
+
"node": ">=10"
|
| 2956 |
+
},
|
| 2957 |
+
"peerDependencies": {
|
| 2958 |
+
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
| 2959 |
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
| 2960 |
+
},
|
| 2961 |
+
"peerDependenciesMeta": {
|
| 2962 |
+
"@types/react": {
|
| 2963 |
+
"optional": true
|
| 2964 |
+
}
|
| 2965 |
+
}
|
| 2966 |
+
},
|
| 2967 |
"node_modules/color-convert": {
|
| 2968 |
"version": "1.9.3",
|
| 2969 |
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
package.json
CHANGED
|
@@ -12,10 +12,14 @@
|
|
| 12 |
"dependencies": {
|
| 13 |
"@radix-ui/react-checkbox": "^1.1.1",
|
| 14 |
"@radix-ui/react-collapsible": "^1.1.0",
|
|
|
|
|
|
|
| 15 |
"@radix-ui/react-select": "^2.1.1",
|
|
|
|
| 16 |
"@radix-ui/react-slot": "^1.1.0",
|
| 17 |
"class-variance-authority": "^0.7.0",
|
| 18 |
"clsx": "^2.1.1",
|
|
|
|
| 19 |
"lucide-react": "^0.399.0",
|
| 20 |
"react": "^18.3.1",
|
| 21 |
"react-dom": "^18.3.1",
|
|
|
|
| 12 |
"dependencies": {
|
| 13 |
"@radix-ui/react-checkbox": "^1.1.1",
|
| 14 |
"@radix-ui/react-collapsible": "^1.1.0",
|
| 15 |
+
"@radix-ui/react-dialog": "^1.1.1",
|
| 16 |
+
"@radix-ui/react-popover": "^1.1.1",
|
| 17 |
"@radix-ui/react-select": "^2.1.1",
|
| 18 |
+
"@radix-ui/react-separator": "^1.1.0",
|
| 19 |
"@radix-ui/react-slot": "^1.1.0",
|
| 20 |
"class-variance-authority": "^0.7.0",
|
| 21 |
"clsx": "^2.1.1",
|
| 22 |
+
"cmdk": "^1.0.0",
|
| 23 |
"lucide-react": "^0.399.0",
|
| 24 |
"react": "^18.3.1",
|
| 25 |
"react-dom": "^18.3.1",
|
src/App.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
|
| 3 |
import { Checkbox } from '@/components/ui/checkbox'
|
| 4 |
import { Input } from '@/components/ui/input'
|
| 5 |
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
|
| 6 |
-
import {
|
| 7 |
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'
|
| 8 |
import { Button } from '@/components/ui/button'
|
| 9 |
import { ChevronDown, ChevronRight } from 'lucide-react'
|
|
@@ -145,36 +145,8 @@ const App: React.FC = () => {
|
|
| 145 |
<Table>
|
| 146 |
<TableHeader>
|
| 147 |
<TableRow>
|
| 148 |
-
<TableHead>
|
| 149 |
-
|
| 150 |
-
<SelectTrigger>
|
| 151 |
-
<SelectValue placeholder="Select Providers" />
|
| 152 |
-
</SelectTrigger>
|
| 153 |
-
<SelectContent>
|
| 154 |
-
{data.map((provider) => (
|
| 155 |
-
<SelectItem key={provider.provider} value={provider.provider}>
|
| 156 |
-
{provider.provider}
|
| 157 |
-
</SelectItem>
|
| 158 |
-
))}
|
| 159 |
-
</SelectContent>
|
| 160 |
-
</Select>
|
| 161 |
-
</TableHead>
|
| 162 |
-
<TableHead>
|
| 163 |
-
<Select onValueChange={(value) => setSelectedModels(value as string[])} defaultValue={[]} multiple>
|
| 164 |
-
<SelectTrigger>
|
| 165 |
-
<SelectValue placeholder="Select Models" />
|
| 166 |
-
</SelectTrigger>
|
| 167 |
-
<SelectContent>
|
| 168 |
-
{data
|
| 169 |
-
.flatMap((provider) => provider.models)
|
| 170 |
-
.map((model) => (
|
| 171 |
-
<SelectItem key={model.name} value={model.name}>
|
| 172 |
-
{model.name}
|
| 173 |
-
</SelectItem>
|
| 174 |
-
))}
|
| 175 |
-
</SelectContent>
|
| 176 |
-
</Select>
|
| 177 |
-
</TableHead>
|
| 178 |
<TableHead>Input Price (per 1M tokens)</TableHead>
|
| 179 |
<TableHead>Output Price (per 1M tokens)</TableHead>
|
| 180 |
<TableHead>Total Price</TableHead>
|
|
@@ -185,8 +157,24 @@ const App: React.FC = () => {
|
|
| 185 |
))}
|
| 186 |
</TableRow>
|
| 187 |
<TableRow>
|
| 188 |
-
<TableHead
|
| 189 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
<TableHead />
|
| 191 |
<TableHead />
|
| 192 |
<TableHead />
|
|
@@ -200,7 +188,12 @@ const App: React.FC = () => {
|
|
| 200 |
{filteredData.flatMap((provider) =>
|
| 201 |
provider.models.map((model) => (
|
| 202 |
<TableRow key={`${provider.provider}-${model.name}`}>
|
| 203 |
-
<TableCell>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
<TableCell>{model.name}</TableCell>
|
| 205 |
<TableCell>${model.inputPrice.toFixed(2)}</TableCell>
|
| 206 |
<TableCell>${model.outputPrice.toFixed(2)}</TableCell>
|
|
|
|
| 3 |
import { Checkbox } from '@/components/ui/checkbox'
|
| 4 |
import { Input } from '@/components/ui/input'
|
| 5 |
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
|
| 6 |
+
import { MultiSelect } from '@/components/ui/multi-select'
|
| 7 |
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'
|
| 8 |
import { Button } from '@/components/ui/button'
|
| 9 |
import { ChevronDown, ChevronRight } from 'lucide-react'
|
|
|
|
| 145 |
<Table>
|
| 146 |
<TableHeader>
|
| 147 |
<TableRow>
|
| 148 |
+
<TableHead>Provider</TableHead>
|
| 149 |
+
<TableHead>Model</TableHead>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
<TableHead>Input Price (per 1M tokens)</TableHead>
|
| 151 |
<TableHead>Output Price (per 1M tokens)</TableHead>
|
| 152 |
<TableHead>Total Price</TableHead>
|
|
|
|
| 157 |
))}
|
| 158 |
</TableRow>
|
| 159 |
<TableRow>
|
| 160 |
+
<TableHead>
|
| 161 |
+
<MultiSelect
|
| 162 |
+
options={data.map((provider) => ({ label: provider.provider, value: provider.provider })) || []}
|
| 163 |
+
onValueChange={setSelectedProviders}
|
| 164 |
+
defaultValue={selectedProviders}
|
| 165 |
+
/>
|
| 166 |
+
</TableHead>
|
| 167 |
+
<TableHead>
|
| 168 |
+
<MultiSelect
|
| 169 |
+
options={
|
| 170 |
+
data
|
| 171 |
+
.flatMap((provider) => provider.models)
|
| 172 |
+
.map((model) => ({ label: model.name, value: model.name })) || []
|
| 173 |
+
}
|
| 174 |
+
defaultValue={selectedModels}
|
| 175 |
+
onValueChange={setSelectedModels}
|
| 176 |
+
/>
|
| 177 |
+
</TableHead>
|
| 178 |
<TableHead />
|
| 179 |
<TableHead />
|
| 180 |
<TableHead />
|
|
|
|
| 188 |
{filteredData.flatMap((provider) =>
|
| 189 |
provider.models.map((model) => (
|
| 190 |
<TableRow key={`${provider.provider}-${model.name}`}>
|
| 191 |
+
<TableCell>
|
| 192 |
+
{' '}
|
| 193 |
+
<a href={provider.uri} className="underline">
|
| 194 |
+
{provider.provider}
|
| 195 |
+
</a>
|
| 196 |
+
</TableCell>
|
| 197 |
<TableCell>{model.name}</TableCell>
|
| 198 |
<TableCell>${model.inputPrice.toFixed(2)}</TableCell>
|
| 199 |
<TableCell>${model.outputPrice.toFixed(2)}</TableCell>
|
src/components/ui/badge.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from 'react'
|
| 2 |
+
import { cva, type VariantProps } from 'class-variance-authority'
|
| 3 |
+
|
| 4 |
+
import { cn } from '@/lib/utils'
|
| 5 |
+
|
| 6 |
+
const badgeVariants = cva(
|
| 7 |
+
'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
|
| 8 |
+
{
|
| 9 |
+
variants: {
|
| 10 |
+
variant: {
|
| 11 |
+
default: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
|
| 12 |
+
secondary: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
| 13 |
+
destructive: 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
|
| 14 |
+
outline: 'text-foreground',
|
| 15 |
+
},
|
| 16 |
+
},
|
| 17 |
+
defaultVariants: {
|
| 18 |
+
variant: 'default',
|
| 19 |
+
},
|
| 20 |
+
}
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}
|
| 24 |
+
|
| 25 |
+
function Badge({ className, variant, ...props }: BadgeProps) {
|
| 26 |
+
return <div className={cn(badgeVariants({ variant }), className)} {...props} />
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
export { Badge, badgeVariants }
|
src/components/ui/command.tsx
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import { type DialogProps } from "@radix-ui/react-dialog"
|
| 3 |
+
import { Command as CommandPrimitive } from "cmdk"
|
| 4 |
+
import { Search } from "lucide-react"
|
| 5 |
+
|
| 6 |
+
import { cn } from "@/lib/utils"
|
| 7 |
+
import { Dialog, DialogContent } from "@/components/ui/dialog"
|
| 8 |
+
|
| 9 |
+
const Command = React.forwardRef<
|
| 10 |
+
React.ElementRef<typeof CommandPrimitive>,
|
| 11 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
|
| 12 |
+
>(({ className, ...props }, ref) => (
|
| 13 |
+
<CommandPrimitive
|
| 14 |
+
ref={ref}
|
| 15 |
+
className={cn(
|
| 16 |
+
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
| 17 |
+
className
|
| 18 |
+
)}
|
| 19 |
+
{...props}
|
| 20 |
+
/>
|
| 21 |
+
))
|
| 22 |
+
Command.displayName = CommandPrimitive.displayName
|
| 23 |
+
|
| 24 |
+
interface CommandDialogProps extends DialogProps {}
|
| 25 |
+
|
| 26 |
+
const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
|
| 27 |
+
return (
|
| 28 |
+
<Dialog {...props}>
|
| 29 |
+
<DialogContent className="overflow-hidden p-0 shadow-lg">
|
| 30 |
+
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
| 31 |
+
{children}
|
| 32 |
+
</Command>
|
| 33 |
+
</DialogContent>
|
| 34 |
+
</Dialog>
|
| 35 |
+
)
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
const CommandInput = React.forwardRef<
|
| 39 |
+
React.ElementRef<typeof CommandPrimitive.Input>,
|
| 40 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
| 41 |
+
>(({ className, ...props }, ref) => (
|
| 42 |
+
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
|
| 43 |
+
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
| 44 |
+
<CommandPrimitive.Input
|
| 45 |
+
ref={ref}
|
| 46 |
+
className={cn(
|
| 47 |
+
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
| 48 |
+
className
|
| 49 |
+
)}
|
| 50 |
+
{...props}
|
| 51 |
+
/>
|
| 52 |
+
</div>
|
| 53 |
+
))
|
| 54 |
+
|
| 55 |
+
CommandInput.displayName = CommandPrimitive.Input.displayName
|
| 56 |
+
|
| 57 |
+
const CommandList = React.forwardRef<
|
| 58 |
+
React.ElementRef<typeof CommandPrimitive.List>,
|
| 59 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
|
| 60 |
+
>(({ className, ...props }, ref) => (
|
| 61 |
+
<CommandPrimitive.List
|
| 62 |
+
ref={ref}
|
| 63 |
+
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
|
| 64 |
+
{...props}
|
| 65 |
+
/>
|
| 66 |
+
))
|
| 67 |
+
|
| 68 |
+
CommandList.displayName = CommandPrimitive.List.displayName
|
| 69 |
+
|
| 70 |
+
const CommandEmpty = React.forwardRef<
|
| 71 |
+
React.ElementRef<typeof CommandPrimitive.Empty>,
|
| 72 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
| 73 |
+
>((props, ref) => (
|
| 74 |
+
<CommandPrimitive.Empty
|
| 75 |
+
ref={ref}
|
| 76 |
+
className="py-6 text-center text-sm"
|
| 77 |
+
{...props}
|
| 78 |
+
/>
|
| 79 |
+
))
|
| 80 |
+
|
| 81 |
+
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
|
| 82 |
+
|
| 83 |
+
const CommandGroup = React.forwardRef<
|
| 84 |
+
React.ElementRef<typeof CommandPrimitive.Group>,
|
| 85 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
|
| 86 |
+
>(({ className, ...props }, ref) => (
|
| 87 |
+
<CommandPrimitive.Group
|
| 88 |
+
ref={ref}
|
| 89 |
+
className={cn(
|
| 90 |
+
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
| 91 |
+
className
|
| 92 |
+
)}
|
| 93 |
+
{...props}
|
| 94 |
+
/>
|
| 95 |
+
))
|
| 96 |
+
|
| 97 |
+
CommandGroup.displayName = CommandPrimitive.Group.displayName
|
| 98 |
+
|
| 99 |
+
const CommandSeparator = React.forwardRef<
|
| 100 |
+
React.ElementRef<typeof CommandPrimitive.Separator>,
|
| 101 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
| 102 |
+
>(({ className, ...props }, ref) => (
|
| 103 |
+
<CommandPrimitive.Separator
|
| 104 |
+
ref={ref}
|
| 105 |
+
className={cn("-mx-1 h-px bg-border", className)}
|
| 106 |
+
{...props}
|
| 107 |
+
/>
|
| 108 |
+
))
|
| 109 |
+
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
|
| 110 |
+
|
| 111 |
+
const CommandItem = React.forwardRef<
|
| 112 |
+
React.ElementRef<typeof CommandPrimitive.Item>,
|
| 113 |
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
|
| 114 |
+
>(({ className, ...props }, ref) => (
|
| 115 |
+
<CommandPrimitive.Item
|
| 116 |
+
ref={ref}
|
| 117 |
+
className={cn(
|
| 118 |
+
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50",
|
| 119 |
+
className
|
| 120 |
+
)}
|
| 121 |
+
{...props}
|
| 122 |
+
/>
|
| 123 |
+
))
|
| 124 |
+
|
| 125 |
+
CommandItem.displayName = CommandPrimitive.Item.displayName
|
| 126 |
+
|
| 127 |
+
const CommandShortcut = ({
|
| 128 |
+
className,
|
| 129 |
+
...props
|
| 130 |
+
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
| 131 |
+
return (
|
| 132 |
+
<span
|
| 133 |
+
className={cn(
|
| 134 |
+
"ml-auto text-xs tracking-widest text-muted-foreground",
|
| 135 |
+
className
|
| 136 |
+
)}
|
| 137 |
+
{...props}
|
| 138 |
+
/>
|
| 139 |
+
)
|
| 140 |
+
}
|
| 141 |
+
CommandShortcut.displayName = "CommandShortcut"
|
| 142 |
+
|
| 143 |
+
export {
|
| 144 |
+
Command,
|
| 145 |
+
CommandDialog,
|
| 146 |
+
CommandInput,
|
| 147 |
+
CommandList,
|
| 148 |
+
CommandEmpty,
|
| 149 |
+
CommandGroup,
|
| 150 |
+
CommandItem,
|
| 151 |
+
CommandShortcut,
|
| 152 |
+
CommandSeparator,
|
| 153 |
+
}
|
src/components/ui/dialog.tsx
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
| 3 |
+
import { X } from "lucide-react"
|
| 4 |
+
|
| 5 |
+
import { cn } from "@/lib/utils"
|
| 6 |
+
|
| 7 |
+
const Dialog = DialogPrimitive.Root
|
| 8 |
+
|
| 9 |
+
const DialogTrigger = DialogPrimitive.Trigger
|
| 10 |
+
|
| 11 |
+
const DialogPortal = DialogPrimitive.Portal
|
| 12 |
+
|
| 13 |
+
const DialogClose = DialogPrimitive.Close
|
| 14 |
+
|
| 15 |
+
const DialogOverlay = React.forwardRef<
|
| 16 |
+
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
| 17 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
| 18 |
+
>(({ className, ...props }, ref) => (
|
| 19 |
+
<DialogPrimitive.Overlay
|
| 20 |
+
ref={ref}
|
| 21 |
+
className={cn(
|
| 22 |
+
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
| 23 |
+
className
|
| 24 |
+
)}
|
| 25 |
+
{...props}
|
| 26 |
+
/>
|
| 27 |
+
))
|
| 28 |
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
| 29 |
+
|
| 30 |
+
const DialogContent = React.forwardRef<
|
| 31 |
+
React.ElementRef<typeof DialogPrimitive.Content>,
|
| 32 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
| 33 |
+
>(({ className, children, ...props }, ref) => (
|
| 34 |
+
<DialogPortal>
|
| 35 |
+
<DialogOverlay />
|
| 36 |
+
<DialogPrimitive.Content
|
| 37 |
+
ref={ref}
|
| 38 |
+
className={cn(
|
| 39 |
+
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
| 40 |
+
className
|
| 41 |
+
)}
|
| 42 |
+
{...props}
|
| 43 |
+
>
|
| 44 |
+
{children}
|
| 45 |
+
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
| 46 |
+
<X className="h-4 w-4" />
|
| 47 |
+
<span className="sr-only">Close</span>
|
| 48 |
+
</DialogPrimitive.Close>
|
| 49 |
+
</DialogPrimitive.Content>
|
| 50 |
+
</DialogPortal>
|
| 51 |
+
))
|
| 52 |
+
DialogContent.displayName = DialogPrimitive.Content.displayName
|
| 53 |
+
|
| 54 |
+
const DialogHeader = ({
|
| 55 |
+
className,
|
| 56 |
+
...props
|
| 57 |
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
| 58 |
+
<div
|
| 59 |
+
className={cn(
|
| 60 |
+
"flex flex-col space-y-1.5 text-center sm:text-left",
|
| 61 |
+
className
|
| 62 |
+
)}
|
| 63 |
+
{...props}
|
| 64 |
+
/>
|
| 65 |
+
)
|
| 66 |
+
DialogHeader.displayName = "DialogHeader"
|
| 67 |
+
|
| 68 |
+
const DialogFooter = ({
|
| 69 |
+
className,
|
| 70 |
+
...props
|
| 71 |
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
| 72 |
+
<div
|
| 73 |
+
className={cn(
|
| 74 |
+
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
| 75 |
+
className
|
| 76 |
+
)}
|
| 77 |
+
{...props}
|
| 78 |
+
/>
|
| 79 |
+
)
|
| 80 |
+
DialogFooter.displayName = "DialogFooter"
|
| 81 |
+
|
| 82 |
+
const DialogTitle = React.forwardRef<
|
| 83 |
+
React.ElementRef<typeof DialogPrimitive.Title>,
|
| 84 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
| 85 |
+
>(({ className, ...props }, ref) => (
|
| 86 |
+
<DialogPrimitive.Title
|
| 87 |
+
ref={ref}
|
| 88 |
+
className={cn(
|
| 89 |
+
"text-lg font-semibold leading-none tracking-tight",
|
| 90 |
+
className
|
| 91 |
+
)}
|
| 92 |
+
{...props}
|
| 93 |
+
/>
|
| 94 |
+
))
|
| 95 |
+
DialogTitle.displayName = DialogPrimitive.Title.displayName
|
| 96 |
+
|
| 97 |
+
const DialogDescription = React.forwardRef<
|
| 98 |
+
React.ElementRef<typeof DialogPrimitive.Description>,
|
| 99 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
| 100 |
+
>(({ className, ...props }, ref) => (
|
| 101 |
+
<DialogPrimitive.Description
|
| 102 |
+
ref={ref}
|
| 103 |
+
className={cn("text-sm text-muted-foreground", className)}
|
| 104 |
+
{...props}
|
| 105 |
+
/>
|
| 106 |
+
))
|
| 107 |
+
DialogDescription.displayName = DialogPrimitive.Description.displayName
|
| 108 |
+
|
| 109 |
+
export {
|
| 110 |
+
Dialog,
|
| 111 |
+
DialogPortal,
|
| 112 |
+
DialogOverlay,
|
| 113 |
+
DialogClose,
|
| 114 |
+
DialogTrigger,
|
| 115 |
+
DialogContent,
|
| 116 |
+
DialogHeader,
|
| 117 |
+
DialogFooter,
|
| 118 |
+
DialogTitle,
|
| 119 |
+
DialogDescription,
|
| 120 |
+
}
|
src/components/ui/multi-select.tsx
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from 'react'
|
| 2 |
+
import { cva, type VariantProps } from 'class-variance-authority'
|
| 3 |
+
import { CheckIcon, XCircle, ChevronDown, XIcon, WandSparkles } from 'lucide-react'
|
| 4 |
+
|
| 5 |
+
import { cn } from '@/lib/utils'
|
| 6 |
+
import { Separator } from '@/components/ui/separator'
|
| 7 |
+
import { Button } from '@/components/ui/button'
|
| 8 |
+
import { Badge } from '@/components/ui/badge'
|
| 9 |
+
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
| 10 |
+
import {
|
| 11 |
+
Command,
|
| 12 |
+
CommandEmpty,
|
| 13 |
+
CommandGroup,
|
| 14 |
+
CommandInput,
|
| 15 |
+
CommandItem,
|
| 16 |
+
CommandList,
|
| 17 |
+
CommandSeparator,
|
| 18 |
+
} from '@/components/ui/command'
|
| 19 |
+
|
| 20 |
+
const multiSelectVariants = cva(
|
| 21 |
+
'm-1 transition ease-in-out delay-150 hover:-translate-y-1 hover:scale-110 duration-300',
|
| 22 |
+
{
|
| 23 |
+
variants: {
|
| 24 |
+
variant: {
|
| 25 |
+
default: 'border-foreground/10 text-foreground bg-card hover:bg-card/80',
|
| 26 |
+
secondary: 'border-foreground/10 bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
| 27 |
+
destructive: 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
|
| 28 |
+
inverted: 'inverted',
|
| 29 |
+
},
|
| 30 |
+
},
|
| 31 |
+
defaultVariants: {
|
| 32 |
+
variant: 'default',
|
| 33 |
+
},
|
| 34 |
+
}
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
interface MultiSelectProps
|
| 38 |
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
| 39 |
+
VariantProps<typeof multiSelectVariants> {
|
| 40 |
+
options: {
|
| 41 |
+
label: string
|
| 42 |
+
value: string
|
| 43 |
+
icon?: React.ComponentType<{ className?: string }>
|
| 44 |
+
}[]
|
| 45 |
+
onValueChange: (value: string[]) => void
|
| 46 |
+
defaultValue: string[]
|
| 47 |
+
placeholder?: string
|
| 48 |
+
animation?: number
|
| 49 |
+
maxCount?: number
|
| 50 |
+
asChild?: boolean
|
| 51 |
+
className?: string
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
export const MultiSelect = React.forwardRef<HTMLButtonElement, MultiSelectProps>(
|
| 55 |
+
(
|
| 56 |
+
{
|
| 57 |
+
options,
|
| 58 |
+
onValueChange,
|
| 59 |
+
variant,
|
| 60 |
+
defaultValue = [],
|
| 61 |
+
placeholder = 'Select options',
|
| 62 |
+
animation = 0,
|
| 63 |
+
maxCount = 3,
|
| 64 |
+
asChild = false,
|
| 65 |
+
className,
|
| 66 |
+
...props
|
| 67 |
+
},
|
| 68 |
+
ref
|
| 69 |
+
) => {
|
| 70 |
+
const [selectedValues, setSelectedValues] = React.useState<string[]>(defaultValue)
|
| 71 |
+
const [isPopoverOpen, setIsPopoverOpen] = React.useState(false)
|
| 72 |
+
const [isAnimating, setIsAnimating] = React.useState(false)
|
| 73 |
+
|
| 74 |
+
React.useEffect(() => {
|
| 75 |
+
if (JSON.stringify(selectedValues) !== JSON.stringify(defaultValue)) {
|
| 76 |
+
setSelectedValues(defaultValue)
|
| 77 |
+
}
|
| 78 |
+
}, [defaultValue, selectedValues])
|
| 79 |
+
|
| 80 |
+
const handleInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
| 81 |
+
if (event.key === 'Enter') {
|
| 82 |
+
setIsPopoverOpen(true)
|
| 83 |
+
} else if (event.key === 'Backspace' && !event.currentTarget.value) {
|
| 84 |
+
const newSelectedValues = [...selectedValues]
|
| 85 |
+
newSelectedValues.pop()
|
| 86 |
+
setSelectedValues(newSelectedValues)
|
| 87 |
+
onValueChange(newSelectedValues)
|
| 88 |
+
}
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
const toggleOption = (value: string) => {
|
| 92 |
+
const newSelectedValues = selectedValues.includes(value)
|
| 93 |
+
? selectedValues.filter((v) => v !== value)
|
| 94 |
+
: [...selectedValues, value]
|
| 95 |
+
setSelectedValues(newSelectedValues)
|
| 96 |
+
onValueChange(newSelectedValues)
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
const handleClear = () => {
|
| 100 |
+
setSelectedValues([])
|
| 101 |
+
onValueChange([])
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
const handleTogglePopover = () => {
|
| 105 |
+
setIsPopoverOpen((prev) => !prev)
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
const clearExtraOptions = () => {
|
| 109 |
+
const newSelectedValues = selectedValues.slice(0, maxCount)
|
| 110 |
+
setSelectedValues(newSelectedValues)
|
| 111 |
+
onValueChange(newSelectedValues)
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
const toggleAll = () => {
|
| 115 |
+
if (selectedValues.length === options.length) {
|
| 116 |
+
handleClear()
|
| 117 |
+
} else {
|
| 118 |
+
const allValues = options.map((option) => option.value)
|
| 119 |
+
setSelectedValues(allValues)
|
| 120 |
+
onValueChange(allValues)
|
| 121 |
+
}
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
return (
|
| 125 |
+
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
|
| 126 |
+
<PopoverTrigger asChild>
|
| 127 |
+
<Button
|
| 128 |
+
ref={ref}
|
| 129 |
+
{...props}
|
| 130 |
+
onClick={handleTogglePopover}
|
| 131 |
+
className={cn(
|
| 132 |
+
'flex w-full p-1 rounded-md border min-h-10 h-auto items-center justify-between bg-inherit hover:bg-inherit',
|
| 133 |
+
className
|
| 134 |
+
)}
|
| 135 |
+
>
|
| 136 |
+
{selectedValues.length > 0 ? (
|
| 137 |
+
<div className="flex justify-between items-center w-full">
|
| 138 |
+
<div className="flex flex-wrap items-center">
|
| 139 |
+
{selectedValues.slice(0, maxCount).map((value) => {
|
| 140 |
+
const option = options.find((o) => o.value === value)
|
| 141 |
+
const IconComponent = option?.icon
|
| 142 |
+
return (
|
| 143 |
+
<Badge
|
| 144 |
+
key={value}
|
| 145 |
+
className={cn(isAnimating ? 'animate-bounce' : '', multiSelectVariants({ variant, className }))}
|
| 146 |
+
style={{ animationDuration: `${animation}s` }}
|
| 147 |
+
>
|
| 148 |
+
{IconComponent && <IconComponent className="h-4 w-4 mr-2" />}
|
| 149 |
+
{option?.label}
|
| 150 |
+
<XCircle
|
| 151 |
+
className="ml-2 h-4 w-4 cursor-pointer"
|
| 152 |
+
onClick={(event) => {
|
| 153 |
+
event.stopPropagation()
|
| 154 |
+
toggleOption(value)
|
| 155 |
+
}}
|
| 156 |
+
/>
|
| 157 |
+
</Badge>
|
| 158 |
+
)
|
| 159 |
+
})}
|
| 160 |
+
{selectedValues.length > maxCount && (
|
| 161 |
+
<Badge
|
| 162 |
+
className={cn(
|
| 163 |
+
'bg-transparent text-foreground border-foreground/1 hover:bg-transparent',
|
| 164 |
+
isAnimating ? 'animate-bounce' : '',
|
| 165 |
+
multiSelectVariants({ variant, className })
|
| 166 |
+
)}
|
| 167 |
+
style={{ animationDuration: `${animation}s` }}
|
| 168 |
+
>
|
| 169 |
+
{`+ ${selectedValues.length - maxCount} more`}
|
| 170 |
+
<XCircle
|
| 171 |
+
className="ml-2 h-4 w-4 cursor-pointer"
|
| 172 |
+
onClick={(event) => {
|
| 173 |
+
event.stopPropagation()
|
| 174 |
+
clearExtraOptions()
|
| 175 |
+
}}
|
| 176 |
+
/>
|
| 177 |
+
</Badge>
|
| 178 |
+
)}
|
| 179 |
+
</div>
|
| 180 |
+
<div className="flex items-center justify-between">
|
| 181 |
+
<XIcon
|
| 182 |
+
className="h-4 mx-2 cursor-pointer text-muted-foreground"
|
| 183 |
+
onClick={(event) => {
|
| 184 |
+
event.stopPropagation()
|
| 185 |
+
handleClear()
|
| 186 |
+
}}
|
| 187 |
+
/>
|
| 188 |
+
<Separator orientation="vertical" className="flex min-h-6 h-full" />
|
| 189 |
+
<ChevronDown className="h-4 mx-2 cursor-pointer text-muted-foreground" />
|
| 190 |
+
</div>
|
| 191 |
+
</div>
|
| 192 |
+
) : (
|
| 193 |
+
<div className="flex items-center justify-between w-full mx-auto">
|
| 194 |
+
<span className="text-sm text-muted-foreground mx-3">{placeholder}</span>
|
| 195 |
+
<ChevronDown className="h-4 cursor-pointer text-muted-foreground mx-2" />
|
| 196 |
+
</div>
|
| 197 |
+
)}
|
| 198 |
+
</Button>
|
| 199 |
+
</PopoverTrigger>
|
| 200 |
+
<PopoverContent className="w-auto p-0" align="start" onEscapeKeyDown={() => setIsPopoverOpen(false)}>
|
| 201 |
+
<Command>
|
| 202 |
+
<CommandInput placeholder="Search..." onKeyDown={handleInputKeyDown} />
|
| 203 |
+
<CommandList>
|
| 204 |
+
<CommandEmpty>No results found.</CommandEmpty>
|
| 205 |
+
<CommandGroup>
|
| 206 |
+
<CommandItem key="all" onSelect={toggleAll} className="cursor-pointer">
|
| 207 |
+
<div
|
| 208 |
+
className={cn(
|
| 209 |
+
'mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary',
|
| 210 |
+
selectedValues.length === options.length
|
| 211 |
+
? 'bg-primary text-primary-foreground'
|
| 212 |
+
: 'opacity-50 [&_svg]:invisible'
|
| 213 |
+
)}
|
| 214 |
+
>
|
| 215 |
+
<CheckIcon className="h-4 w-4" />
|
| 216 |
+
</div>
|
| 217 |
+
<span>(Select All)</span>
|
| 218 |
+
</CommandItem>
|
| 219 |
+
{options.map((option) => {
|
| 220 |
+
const isSelected = selectedValues.includes(option.value)
|
| 221 |
+
return (
|
| 222 |
+
<CommandItem
|
| 223 |
+
key={option.value}
|
| 224 |
+
onSelect={() => toggleOption(option.value)}
|
| 225 |
+
className="cursor-pointer"
|
| 226 |
+
>
|
| 227 |
+
<div
|
| 228 |
+
className={cn(
|
| 229 |
+
'mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary',
|
| 230 |
+
isSelected ? 'bg-primary text-primary-foreground' : 'opacity-50 [&_svg]:invisible'
|
| 231 |
+
)}
|
| 232 |
+
>
|
| 233 |
+
<CheckIcon className="h-4 w-4" />
|
| 234 |
+
</div>
|
| 235 |
+
{option.icon && <option.icon className="mr-2 h-4 w-4 text-muted-foreground" />}
|
| 236 |
+
<span>{option.label}</span>
|
| 237 |
+
</CommandItem>
|
| 238 |
+
)
|
| 239 |
+
})}
|
| 240 |
+
</CommandGroup>
|
| 241 |
+
<CommandSeparator />
|
| 242 |
+
<CommandGroup>
|
| 243 |
+
<div className="flex items-center justify-between">
|
| 244 |
+
{selectedValues.length > 0 && (
|
| 245 |
+
<>
|
| 246 |
+
<CommandItem onSelect={handleClear} className="flex-1 justify-center cursor-pointer">
|
| 247 |
+
Clear
|
| 248 |
+
</CommandItem>
|
| 249 |
+
<Separator orientation="vertical" className="flex min-h-6 h-full" />
|
| 250 |
+
</>
|
| 251 |
+
)}
|
| 252 |
+
<CommandSeparator />
|
| 253 |
+
<CommandItem
|
| 254 |
+
onSelect={() => setIsPopoverOpen(false)}
|
| 255 |
+
className="flex-1 justify-center cursor-pointer"
|
| 256 |
+
>
|
| 257 |
+
Close
|
| 258 |
+
</CommandItem>
|
| 259 |
+
</div>
|
| 260 |
+
</CommandGroup>
|
| 261 |
+
</CommandList>
|
| 262 |
+
</Command>
|
| 263 |
+
</PopoverContent>
|
| 264 |
+
{animation > 0 && selectedValues.length > 0 && (
|
| 265 |
+
<WandSparkles
|
| 266 |
+
className={cn(
|
| 267 |
+
'cursor-pointer my-2 text-foreground bg-background w-3 h-3',
|
| 268 |
+
isAnimating ? '' : 'text-muted-foreground'
|
| 269 |
+
)}
|
| 270 |
+
onClick={() => setIsAnimating(!isAnimating)}
|
| 271 |
+
/>
|
| 272 |
+
)}
|
| 273 |
+
</Popover>
|
| 274 |
+
)
|
| 275 |
+
}
|
| 276 |
+
)
|
| 277 |
+
|
| 278 |
+
MultiSelect.displayName = 'MultiSelect'
|
src/components/ui/popover.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
| 3 |
+
|
| 4 |
+
import { cn } from "@/lib/utils"
|
| 5 |
+
|
| 6 |
+
const Popover = PopoverPrimitive.Root
|
| 7 |
+
|
| 8 |
+
const PopoverTrigger = PopoverPrimitive.Trigger
|
| 9 |
+
|
| 10 |
+
const PopoverContent = React.forwardRef<
|
| 11 |
+
React.ElementRef<typeof PopoverPrimitive.Content>,
|
| 12 |
+
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
| 13 |
+
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
| 14 |
+
<PopoverPrimitive.Portal>
|
| 15 |
+
<PopoverPrimitive.Content
|
| 16 |
+
ref={ref}
|
| 17 |
+
align={align}
|
| 18 |
+
sideOffset={sideOffset}
|
| 19 |
+
className={cn(
|
| 20 |
+
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
| 21 |
+
className
|
| 22 |
+
)}
|
| 23 |
+
{...props}
|
| 24 |
+
/>
|
| 25 |
+
</PopoverPrimitive.Portal>
|
| 26 |
+
))
|
| 27 |
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName
|
| 28 |
+
|
| 29 |
+
export { Popover, PopoverTrigger, PopoverContent }
|
src/components/ui/select.tsx
DELETED
|
@@ -1,143 +0,0 @@
|
|
| 1 |
-
import * as React from 'react'
|
| 2 |
-
import * as SelectPrimitive from '@radix-ui/react-select'
|
| 3 |
-
import { Check, ChevronDown, ChevronUp } from 'lucide-react'
|
| 4 |
-
|
| 5 |
-
import { cn } from '@/lib/utils'
|
| 6 |
-
|
| 7 |
-
const Select = SelectPrimitive.Root
|
| 8 |
-
|
| 9 |
-
const SelectGroup = SelectPrimitive.Group
|
| 10 |
-
|
| 11 |
-
const SelectValue = SelectPrimitive.Value
|
| 12 |
-
|
| 13 |
-
const SelectTrigger = React.forwardRef<
|
| 14 |
-
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
| 15 |
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
| 16 |
-
>(({ className, children, ...props }, ref) => (
|
| 17 |
-
<SelectPrimitive.Trigger
|
| 18 |
-
ref={ref}
|
| 19 |
-
className={cn(
|
| 20 |
-
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
|
| 21 |
-
className
|
| 22 |
-
)}
|
| 23 |
-
{...props}
|
| 24 |
-
>
|
| 25 |
-
{children}
|
| 26 |
-
<SelectPrimitive.Icon asChild>
|
| 27 |
-
<ChevronDown className="h-4 w-4 opacity-50" />
|
| 28 |
-
</SelectPrimitive.Icon>
|
| 29 |
-
</SelectPrimitive.Trigger>
|
| 30 |
-
))
|
| 31 |
-
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
|
| 32 |
-
|
| 33 |
-
const SelectScrollUpButton = React.forwardRef<
|
| 34 |
-
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
| 35 |
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
| 36 |
-
>(({ className, ...props }, ref) => (
|
| 37 |
-
<SelectPrimitive.ScrollUpButton
|
| 38 |
-
ref={ref}
|
| 39 |
-
className={cn('flex cursor-default items-center justify-center py-1', className)}
|
| 40 |
-
{...props}
|
| 41 |
-
>
|
| 42 |
-
<ChevronUp className="h-4 w-4" />
|
| 43 |
-
</SelectPrimitive.ScrollUpButton>
|
| 44 |
-
))
|
| 45 |
-
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
|
| 46 |
-
|
| 47 |
-
const SelectScrollDownButton = React.forwardRef<
|
| 48 |
-
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
| 49 |
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
| 50 |
-
>(({ className, ...props }, ref) => (
|
| 51 |
-
<SelectPrimitive.ScrollDownButton
|
| 52 |
-
ref={ref}
|
| 53 |
-
className={cn('flex cursor-default items-center justify-center py-1', className)}
|
| 54 |
-
{...props}
|
| 55 |
-
>
|
| 56 |
-
<ChevronDown className="h-4 w-4" />
|
| 57 |
-
</SelectPrimitive.ScrollDownButton>
|
| 58 |
-
))
|
| 59 |
-
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName
|
| 60 |
-
|
| 61 |
-
const SelectContent = React.forwardRef<
|
| 62 |
-
React.ElementRef<typeof SelectPrimitive.Content>,
|
| 63 |
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
| 64 |
-
>(({ className, children, position = 'popper', ...props }, ref) => (
|
| 65 |
-
<SelectPrimitive.Portal>
|
| 66 |
-
<SelectPrimitive.Content
|
| 67 |
-
ref={ref}
|
| 68 |
-
className={cn(
|
| 69 |
-
'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
| 70 |
-
position === 'popper' &&
|
| 71 |
-
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
|
| 72 |
-
className
|
| 73 |
-
)}
|
| 74 |
-
position={position}
|
| 75 |
-
{...props}
|
| 76 |
-
>
|
| 77 |
-
<SelectScrollUpButton />
|
| 78 |
-
<SelectPrimitive.Viewport
|
| 79 |
-
className={cn(
|
| 80 |
-
'p-1',
|
| 81 |
-
position === 'popper' &&
|
| 82 |
-
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'
|
| 83 |
-
)}
|
| 84 |
-
>
|
| 85 |
-
{children}
|
| 86 |
-
</SelectPrimitive.Viewport>
|
| 87 |
-
<SelectScrollDownButton />
|
| 88 |
-
</SelectPrimitive.Content>
|
| 89 |
-
</SelectPrimitive.Portal>
|
| 90 |
-
))
|
| 91 |
-
SelectContent.displayName = SelectPrimitive.Content.displayName
|
| 92 |
-
|
| 93 |
-
const SelectLabel = React.forwardRef<
|
| 94 |
-
React.ElementRef<typeof SelectPrimitive.Label>,
|
| 95 |
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
| 96 |
-
>(({ className, ...props }, ref) => (
|
| 97 |
-
<SelectPrimitive.Label ref={ref} className={cn('py-1.5 pl-8 pr-2 text-sm font-semibold', className)} {...props} />
|
| 98 |
-
))
|
| 99 |
-
SelectLabel.displayName = SelectPrimitive.Label.displayName
|
| 100 |
-
|
| 101 |
-
const SelectItem = React.forwardRef<
|
| 102 |
-
React.ElementRef<typeof SelectPrimitive.Item>,
|
| 103 |
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
| 104 |
-
>(({ className, children, ...props }, ref) => (
|
| 105 |
-
<SelectPrimitive.Item
|
| 106 |
-
ref={ref}
|
| 107 |
-
className={cn(
|
| 108 |
-
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
| 109 |
-
className
|
| 110 |
-
)}
|
| 111 |
-
{...props}
|
| 112 |
-
>
|
| 113 |
-
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
| 114 |
-
<SelectPrimitive.ItemIndicator>
|
| 115 |
-
<Check className="h-4 w-4" />
|
| 116 |
-
</SelectPrimitive.ItemIndicator>
|
| 117 |
-
</span>
|
| 118 |
-
|
| 119 |
-
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
| 120 |
-
</SelectPrimitive.Item>
|
| 121 |
-
))
|
| 122 |
-
SelectItem.displayName = SelectPrimitive.Item.displayName
|
| 123 |
-
|
| 124 |
-
const SelectSeparator = React.forwardRef<
|
| 125 |
-
React.ElementRef<typeof SelectPrimitive.Separator>,
|
| 126 |
-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
| 127 |
-
>(({ className, ...props }, ref) => (
|
| 128 |
-
<SelectPrimitive.Separator ref={ref} className={cn('-mx-1 my-1 h-px bg-muted', className)} {...props} />
|
| 129 |
-
))
|
| 130 |
-
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
|
| 131 |
-
|
| 132 |
-
export {
|
| 133 |
-
Select,
|
| 134 |
-
SelectGroup,
|
| 135 |
-
SelectValue,
|
| 136 |
-
SelectTrigger,
|
| 137 |
-
SelectContent,
|
| 138 |
-
SelectLabel,
|
| 139 |
-
SelectItem,
|
| 140 |
-
SelectSeparator,
|
| 141 |
-
SelectScrollUpButton,
|
| 142 |
-
SelectScrollDownButton,
|
| 143 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/components/ui/separator.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
| 3 |
+
|
| 4 |
+
import { cn } from "@/lib/utils"
|
| 5 |
+
|
| 6 |
+
const Separator = React.forwardRef<
|
| 7 |
+
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
| 8 |
+
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
| 9 |
+
>(
|
| 10 |
+
(
|
| 11 |
+
{ className, orientation = "horizontal", decorative = true, ...props },
|
| 12 |
+
ref
|
| 13 |
+
) => (
|
| 14 |
+
<SeparatorPrimitive.Root
|
| 15 |
+
ref={ref}
|
| 16 |
+
decorative={decorative}
|
| 17 |
+
orientation={orientation}
|
| 18 |
+
className={cn(
|
| 19 |
+
"shrink-0 bg-border",
|
| 20 |
+
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
| 21 |
+
className
|
| 22 |
+
)}
|
| 23 |
+
{...props}
|
| 24 |
+
/>
|
| 25 |
+
)
|
| 26 |
+
)
|
| 27 |
+
Separator.displayName = SeparatorPrimitive.Root.displayName
|
| 28 |
+
|
| 29 |
+
export { Separator }
|