Merge pull request #1519 from useautumn/charlie/base-ui

chore: migrate shadcn from Radix UI to Base UI
This commit is contained in:
Charlie Lamb
2026-05-11 12:55:33 +01:00
committed by GitHub
95 changed files with 1540 additions and 1123 deletions

2
ai

Submodule ai updated: eb7800f5f7...4bfb2b6ace

152
bun.lock
View File

@@ -1,5 +1,6 @@
{
"lockfileVersion": 1,
"configVersion": 0,
"workspaces": {
"": {
"name": "autumn",
@@ -481,26 +482,12 @@
"dependencies": {
"@ai-sdk/react": "^3.0.25",
"@autumn/shared": "workspace:*",
"@base-ui/react": "^1.4.1",
"@better-auth/dash": "catalog:",
"@fortawesome/free-brands-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@monaco-editor/react": "^4.7.0",
"@phosphor-icons/react": "^2.1.10",
"@radix-ui/react-accordion": "^1.2.11",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-hover-card": "^1.1.15",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-popover": "^1.1.14",
"@radix-ui/react-radio-group": "^1.3.8",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-switch": "^1.2.5",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-tooltip": "^1.2.8",
"@sentry/react": "^10.25.0",
"@sentry/vite-plugin": "^4.6.0",
"@squircle/core": "^1.0.6",
@@ -536,6 +523,7 @@
"react": "^18.2.0",
"react-day-picker": "^8.10.1",
"react-dom": "^18.2.0",
"react-grab": "^0.1.29",
"react-hotkeys-hook": "^4.6.1",
"react-router": "^7.3.0",
"react-router-dom": "^7.6.2",
@@ -1679,7 +1667,7 @@
"@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
"@radix-ui/react-label": ["@radix-ui/react-label@2.1.8", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A=="],
"@radix-ui/react-label": ["@radix-ui/react-label@2.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ=="],
"@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg=="],
@@ -1699,7 +1687,7 @@
"@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
"@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
"@radix-ui/react-progress": ["@radix-ui/react-progress@1.1.7", "", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg=="],
@@ -1711,11 +1699,11 @@
"@radix-ui/react-select": ["@radix-ui/react-select@2.2.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ=="],
"@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.8", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g=="],
"@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA=="],
"@radix-ui/react-slider": ["@radix-ui/react-slider@1.3.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw=="],
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="],
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-switch": ["@radix-ui/react-switch@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ=="],
@@ -1795,6 +1783,8 @@
"@react-email/text": ["@react-email/text@0.1.5", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-o5PNHFSE085VMXayxH+SJ1LSOtGsTv+RpNKnTiJDrJUwoBu77G3PlKOsZZQHCNyD28WsQpl9v2WcJLbQudqwPg=="],
"@react-grab/cli": ["@react-grab/cli@0.1.33", "", { "dependencies": { "@antfu/ni": "^30.1.0", "commander": "^14.0.3", "ignore": "^7.0.5", "jsonc-parser": "^3.3.1", "ora": "^9.4.0", "picocolors": "^1.1.1", "prompts": "^2.4.2", "smol-toml": "^1.6.1" }, "bin": { "react-grab": "bin/cli.js" } }, "sha512-UOc3PwN11Osw0NzaxRLK8trP4X+5iW1Dst3gvHRCafe3wXHyadzHYH8H1hdkcXdlIx3gsoD9ASJ+G/JH+A/jqA=="],
"@reduxjs/toolkit": ["@reduxjs/toolkit@2.11.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0", "immer": "^11.0.0", "redux": "^5.0.1", "redux-thunk": "^3.1.0", "reselect": "^5.1.0" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" }, "optionalPeers": ["react", "react-redux"] }, "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ=="],
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.3", "", {}, "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q=="],
@@ -2759,6 +2749,8 @@
"bintrees": ["bintrees@1.0.2", "", {}, "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw=="],
"bippy": ["bippy@0.5.39", "", { "peerDependencies": { "react": ">=17.0.1" } }, "sha512-8hE8rKSl8JWyeaY+JjpnmceWAZPpLEyzOZQpWXM5Rc7861c5WotMJHy2aRZKZrGA8nMpvLNF01t4yQQ+HcZG3w=="],
"bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
"blueimp-md5": ["blueimp-md5@2.19.0", "", {}, "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w=="],
@@ -4055,7 +4047,7 @@
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
"jsonc-parser": ["jsonc-parser@2.2.1", "", {}, "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w=="],
"jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="],
"jsonc-simple-parser": ["jsonc-simple-parser@3.0.0", "", { "dependencies": { "reghex": "^3.0.2" } }, "sha512-0qi9Kuj4JPar4/3b9wZteuPZrTeFzXsQyOZj7hksnReCZN3Vr17Doz7w/i3E9XH7vRkVTHhHES+r1h97I+hfww=="],
@@ -4861,6 +4853,8 @@
"react-email": ["react-email@4.0.16", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/traverse": "^7.27.0", "chalk": "^5.0.0", "chokidar": "^4.0.3", "commander": "^13.0.0", "debounce": "^2.0.0", "esbuild": "^0.25.0", "glob": "^11.0.0", "log-symbols": "^7.0.0", "mime-types": "^3.0.0", "next": "^15.3.1", "normalize-path": "^3.0.0", "ora": "^8.0.0", "socket.io": "^4.8.1" }, "bin": { "email": "dist/cli/index.mjs" } }, "sha512-auhFU+nQxAkKkP6lQhPyGsa9exwfUEzp2BwZnjHokCwphZlg30tu4t1LgdKRwGPYsi7XNGy6asbVLAUhOVpzzg=="],
"react-grab": ["react-grab@0.1.33", "", { "dependencies": { "@react-grab/cli": "0.1.33", "bippy": "^0.5.39" }, "peerDependencies": { "react": ">=17.0.0" }, "optionalPeers": ["react"], "bin": { "react-grab": "bin/cli.js" } }, "sha512-ER919JMsE4TTrb2CpEivqsIjNMSycD4HtS8v7mS3pq67U7WL1K3+C8m9AYOwW4dpuYh+EanC2eJBmfuczHJZ0A=="],
"react-hotkeys-hook": ["react-hotkeys-hook@4.6.2", "", { "peerDependencies": { "react": ">=16.8.1", "react-dom": ">=16.8.1" } }, "sha512-FmP+ZriY3EG59Ug/lxNfrObCnW9xQShgk7Nb83+CkpfkcCpfS95ydv+E9JuXA5cp8KtskU7LGlIARpkc92X22Q=="],
"react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
@@ -6341,29 +6335,91 @@
"@prisma/instrumentation/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.207.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.207.0", "import-in-the-middle": "^2.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-y6eeli9+TLKnznrR8AZlQMSJT7wILpXH+6EYq5Vf/4Ao+huI7EedxQHwRgVUOMLFbe7VFDvHJrX9/f4lcwnJsA=="],
"@radix-ui/react-alert-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-accordion/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-alert-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-arrow/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-form/@radix-ui/react-label": ["@radix-ui/react-label@2.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ=="],
"@radix-ui/react-aspect-ratio/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-label/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
"@radix-ui/react-avatar/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-menu/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-checkbox/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-popover/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-collapsible/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-collection/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-select/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-context-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-separator/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
"@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-toolbar/@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA=="],
"@radix-ui/react-dismissable-layer/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-tooltip/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-dropdown-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-focus-scope/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-form/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-hover-card/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-label/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-menubar/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-navigation-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-one-time-password-field/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-password-toggle-field/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-popover/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-popper/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-portal/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="],
"@radix-ui/react-progress/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-radio-group/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-roving-focus/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-scroll-area/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-select/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-separator/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-slider/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-switch/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-tabs/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-toast/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-toggle/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-toggle-group/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-toolbar/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-tooltip/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-visually-hidden/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@react-grab/cli/@antfu/ni": ["@antfu/ni@30.1.0", "", { "dependencies": { "fzf": "^0.5.2", "package-manager-detector": "^1.6.0", "tinyexec": "^1.0.4", "tinyglobby": "^0.2.15" }, "bin": { "ni": "bin/ni.mjs", "nci": "bin/nci.mjs", "nr": "bin/nr.mjs", "nup": "bin/nup.mjs", "nd": "bin/nd.mjs", "nlx": "bin/nlx.mjs", "na": "bin/na.mjs", "nun": "bin/nun.mjs" } }, "sha512-3VuAbPjgY52rQNn4wABaXMhBU2Oq91uy6L8nX49eJ35OLI68CyckGU+HZxcaHix4ymuGM2nFL1D6sLpgODK5xw=="],
"@react-grab/cli/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
"@react-grab/cli/ora": ["ora@9.4.0", "", { "dependencies": { "chalk": "^5.6.2", "cli-cursor": "^5.0.0", "cli-spinners": "^3.2.0", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.1.0", "log-symbols": "^7.0.1", "stdin-discarder": "^0.3.2", "string-width": "^8.1.0" } }, "sha512-84cglkRILFxdtA8hAvLNdMrtBpPNBTrQ9/ulg0FA7xLMnD6mifv+enAIeRmvtv+WgdCE+LPGOfQmtJRrVaIVhQ=="],
"@reduxjs/toolkit/immer": ["immer@11.1.4", "", {}, "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw=="],
@@ -6407,6 +6463,8 @@
"@stoplight/better-ajv-errors/leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
"@stoplight/json/jsonc-parser": ["jsonc-parser@2.2.1", "", {}, "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w=="],
"@stoplight/json/safe-stable-stringify": ["safe-stable-stringify@1.1.1", "", {}, "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw=="],
"@stoplight/json-ref-readers/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="],
@@ -6669,8 +6727,6 @@
"clone-response/mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="],
"cmdk/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
"concurrently/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"conf/ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="],
@@ -7037,11 +7093,7 @@
"puppeteer/puppeteer-core": ["puppeteer-core@22.14.0", "", { "dependencies": { "@puppeteer/browsers": "2.3.0", "chromium-bidi": "0.6.2", "debug": "^4.3.5", "devtools-protocol": "0.0.1312386", "ws": "^8.18.0" } }, "sha512-rl4tOY5LcA3e374GAlsGGHc05HL3eGNf5rZ+uxkl6id9zVZKcwcp1Z+Nd6byb6WPiPeecT/dwz8f/iUm+AZQSw=="],
"radix-ui/@radix-ui/react-label": ["@radix-ui/react-label@2.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ=="],
"radix-ui/@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA=="],
"radix-ui/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"radix-ui/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"rc/strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
@@ -7965,6 +8017,22 @@
"@prisma/instrumentation/@opentelemetry/instrumentation/require-in-the-middle": ["require-in-the-middle@8.0.1", "", { "dependencies": { "debug": "^4.3.5", "module-details-from-path": "^1.0.3" } }, "sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ=="],
"@react-grab/cli/@antfu/ni/tinyexec": ["tinyexec@1.1.1", "", {}, "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg=="],
"@react-grab/cli/ora/cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
"@react-grab/cli/ora/cli-spinners": ["cli-spinners@3.4.0", "", {}, "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw=="],
"@react-grab/cli/ora/is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="],
"@react-grab/cli/ora/is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
"@react-grab/cli/ora/log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="],
"@react-grab/cli/ora/stdin-discarder": ["stdin-discarder@0.3.2", "", {}, "sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A=="],
"@react-grab/cli/ora/string-width": ["string-width@8.2.1", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA=="],
"@sentry/cli/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
"@sentry/node-core/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@2.2.0", "", {}, "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ=="],
@@ -9157,6 +9225,8 @@
"@prisma/instrumentation/@opentelemetry/instrumentation/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@2.2.0", "", {}, "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ=="],
"@react-grab/cli/ora/cli-cursor/restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
"@tailwindcss/postcss/@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
"@tailwindcss/postcss/@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
@@ -9585,6 +9655,10 @@
"@mintlify/scraping/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"@react-grab/cli/ora/cli-cursor/restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
"@react-grab/cli/ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
"artillery-plugin-ensure/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
"artillery-plugin-publish-metrics/@opentelemetry/exporter-metrics-otlp-grpc/@opentelemetry/otlp-transformer/protobufjs/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="],

View File

@@ -25,6 +25,7 @@
"server": {
"entry": [
"src/internal/customers/cusUtils/createNewCustomer.ts",
"src/internal/rewards/RewardRedemptionService.ts",
"src/utils/importUtils/addProductFromSubs.ts",
"src/utils/scriptUtils/readOnlyStripe.ts",
"src/utils/scriptUtils/scriptUtils.ts",
@@ -43,7 +44,7 @@
"vite": {
"entry": ["tests/**/*.{ts,tsx}"],
"project": ["src/**/*.{ts,tsx}", "tests/**/*.{ts,tsx}"],
"ignore": ["src/components/ai-elements/**"],
"ignore": ["src/components/ai-elements/**", "src/hooks/useControllableState.ts"],
"ignoreDependencies": [
"tailwindcss",
"tailwind-scrollbar-hide",

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"style": "base-nova",
"rsc": false,
"tsx": true,
"tailwind": {

View File

@@ -21,26 +21,12 @@
"dependencies": {
"@ai-sdk/react": "^3.0.25",
"@autumn/shared": "workspace:*",
"@base-ui/react": "^1.4.1",
"@better-auth/dash": "catalog:",
"@fortawesome/free-brands-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@monaco-editor/react": "^4.7.0",
"@phosphor-icons/react": "^2.1.10",
"@radix-ui/react-accordion": "^1.2.11",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-hover-card": "^1.1.15",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-popover": "^1.1.14",
"@radix-ui/react-radio-group": "^1.3.8",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-switch": "^1.2.5",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-tooltip": "^1.2.8",
"@sentry/react": "^10.25.0",
"@sentry/vite-plugin": "^4.6.0",
"@squircle/core": "^1.0.6",

View File

@@ -1,6 +1,6 @@
"use client";
import { useControllableState } from "@radix-ui/react-use-controllable-state";
import { useControllableState } from "@/hooks/useControllableState";
import {
BrainIcon,
ChevronDownIcon,
@@ -58,7 +58,7 @@ export const ChainOfThought = memo(
});
const chainOfThoughtContext = useMemo(
() => ({ isOpen, setIsOpen }),
() => ({ isOpen: isOpen ?? false, setIsOpen }),
[isOpen, setIsOpen],
);

View File

@@ -80,7 +80,7 @@ export const InlineCitationCardTrigger = ({
</HoverCardTrigger>
);
export type InlineCitationCardBodyProps = ComponentProps<"div">;
export type InlineCitationCardBodyProps = ComponentProps<typeof HoverCardContent>;
export const InlineCitationCardBody = ({
className,

View File

@@ -1,6 +1,6 @@
"use client";
import { useControllableState } from "@radix-ui/react-use-controllable-state";
import { useControllableState } from "@/hooks/useControllableState";
import { BrainIcon, ChevronDownIcon } from "lucide-react";
import type { ComponentProps, ReactNode } from "react";
import { createContext, memo, useContext, useEffect, useState } from "react";

View File

@@ -99,7 +99,7 @@ export function AttachFooter() {
</Button>
</PopoverTrigger>
{!invoiceDisabledReason && (
<PopoverContent className="w-(--radix-popover-trigger-width) p-0">
<PopoverContent className="w-(--anchor-width) p-0">
<div className="flex flex-col">
<button
type="button"
@@ -144,7 +144,7 @@ export function AttachFooter() {
{invoiceDisabledReason && (
<TooltipContent
side="top"
className="max-w-(--radix-tooltip-trigger-width)"
className="max-w-(--anchor-width)"
>
{invoiceDisabledReason}
</TooltipContent>

View File

@@ -99,7 +99,7 @@ export function AttachFooterV3() {
{invoiceDisabledReason && (
<TooltipContent
side="top"
className="max-w-(--radix-tooltip-trigger-width)"
className="max-w-(--anchor-width)"
>
{invoiceDisabledReason}
</TooltipContent>

View File

@@ -202,7 +202,7 @@ export function CreateScheduleReviewContent() {
{invoiceDisabledReason && (
<TooltipContent
side="top"
className="max-w-(--radix-tooltip-trigger-width)"
className="max-w-(--anchor-width)"
>
{invoiceDisabledReason}
</TooltipContent>

View File

@@ -62,14 +62,15 @@ export function PlanSectionTitle({
<span className="flex items-center gap-2">
{trialAction}
{showVersionSelector && (
<Select
value={
selectedVersion !== undefined
? String(selectedVersion)
: undefined
}
onValueChange={(value) => onVersionChange?.(Number(value))}
>
<Select
value={
selectedVersion !== undefined
? String(selectedVersion)
: undefined
}
onValueChange={(value) => onVersionChange?.(Number(value))}
items={Object.fromEntries(versionOptions.map((option) => [option.value, option.label]))}
>
<SelectTrigger className="w-fit h-7 text-xs whitespace-nowrap">
<SelectValue />
</SelectTrigger>

View File

@@ -18,19 +18,17 @@ export function CollapsedBooleanItems({
items,
renderItem,
}: CollapsedBooleanItemsProps) {
const [value, setValue] = useState("");
const [value, setValue] = useState<string[]>([]);
if (items.length === 0) return null;
const isExpanded = value === "boolean-flags";
const isExpanded = value.includes("boolean-flags");
const label = isExpanded
? "Hide"
: `${items.length} more`;
return (
<Accordion
type="single"
collapsible
value={value}
onValueChange={setValue}
className="w-full"

View File

@@ -316,7 +316,7 @@ export function SubscriptionItemRow({
<ConditionalTooltip
enabled={!!prepaid.showTooltip}
content={prepaidTooltipContent}
contentClassName="max-w-(--radix-tooltip-trigger-width)"
contentClassName="max-w-(--anchor-width)"
>
{rowContent}
</ConditionalTooltip>

View File

@@ -79,7 +79,7 @@ export function UpdateSubscriptionFooter() {
{invoiceDisabledReason && (
<TooltipContent
side="top"
className="max-w-(--radix-tooltip-trigger-width)"
className="max-w-(--anchor-width)"
>
{invoiceDisabledReason}
</TooltipContent>

View File

@@ -1,13 +1,8 @@
import { Check, Copy } from "lucide-react";
import type React from "react";
import { cloneElement, forwardRef, isValidElement, useState } from "react";
import { forwardRef, useState } from "react";
import { PreviewCard } from "@base-ui/react/preview-card";
import { useAdmin } from "@/views/admin/hooks/useAdmin";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "../ui/tooltip";
export const AdminHover = forwardRef<
HTMLElement,
@@ -18,54 +13,50 @@ export const AdminHover = forwardRef<
asChild?: boolean;
side?: "top" | "bottom" | "left" | "right";
}
>(
(
{ children, texts, hide = false, asChild = false, side = "bottom" },
ref,
) => {
const { isAdmin, skipHover } = useAdmin();
>(({ children, texts, hide = false, side = "bottom" }, _ref) => {
const { isAdmin, skipHover } = useAdmin();
if (!isAdmin || hide || skipHover) return <>{children}</>;
if (!isAdmin || hide || skipHover) return <>{children}</>;
// Try to forward the ref to the child if possible
let triggerChild = children;
if (isValidElement(children)) {
triggerChild = cloneElement(children as React.ReactElement, { ref });
}
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild={asChild}>{triggerChild}</TooltipTrigger>
{isAdmin && (
<TooltipContent
className="bg-white/50 backdrop-blur-sm shadow-sm border px-2 pr-6 py-2 max-w-none z-[9999]"
align="start"
side={side}
>
<div className="text-xs text-gray-500 flex flex-col gap-2">
{texts.map((text) => {
if (!text) return null;
if (typeof text === "object") {
return (
<div key={text.key}>
<p className="text-xs text-gray-500 font-medium">
{text.key}
</p>
<CopyText text={text.value} />
</div>
);
}
return <CopyText key={text} text={text} />;
})}
</div>
</TooltipContent>
)}
</Tooltip>
</TooltipProvider>
);
},
);
return (
<PreviewCard.Root>
<PreviewCard.Trigger
render={<div className="inline-flex" />}
delay={0}
>
{children}
</PreviewCard.Trigger>
<PreviewCard.Portal>
<PreviewCard.Positioner
side={side}
sideOffset={4}
align="start"
positionMethod="fixed"
className="isolate z-[9999]"
>
<PreviewCard.Popup className="bg-white/50 dark:bg-zinc-900/50 backdrop-blur-sm shadow-sm border rounded-md px-2 pr-6 py-2 max-w-none origin-(--transform-origin) transition-[opacity,scale] duration-150 data-[starting-style]:opacity-0 data-[starting-style]:scale-95 data-[ending-style]:opacity-0 data-[ending-style]:scale-95">
<div className="text-xs text-gray-500 dark:text-gray-400 flex flex-col gap-2 whitespace-nowrap">
{texts.map((text) => {
if (!text) return null;
if (typeof text === "object") {
return (
<div key={text.key}>
<p className="text-xs text-gray-500 dark:text-gray-400 font-medium">
{text.key}
</p>
<CopyText text={text.value} />
</div>
);
}
return <CopyText key={text} text={text} />;
})}
</div>
</PreviewCard.Popup>
</PreviewCard.Positioner>
</PreviewCard.Portal>
</PreviewCard.Root>
);
});
const CopyText = ({ text }: { text: string }) => {
const [isHover, setIsHover] = useState(false);
@@ -76,7 +67,7 @@ const CopyText = ({ text }: { text: string }) => {
<p
onMouseEnter={() => setIsHover(true)}
onMouseLeave={() => setIsHover(false)}
className="flex flex-col items-start gap-1 font-mono hover:underline"
className="flex flex-col items-start gap-1 font-mono hover:underline cursor-pointer"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();

View File

@@ -1,5 +1,4 @@
import { InfoIcon } from "@phosphor-icons/react";
import type { TooltipContentProps } from "@radix-ui/react-tooltip";
import {
Tooltip,
TooltipContent,
@@ -13,7 +12,10 @@ export const InfoTooltip = ({
}: {
children: React.ReactNode;
className?: string;
} & TooltipContentProps) => {
side?: "top" | "bottom" | "left" | "right";
align?: "start" | "center" | "end";
sideOffset?: number;
}) => {
return (
<Tooltip>
<TooltipTrigger

View File

@@ -29,11 +29,9 @@ function ColumnCheckboxItem<T>({ column }: { column: Column<T> }) {
return (
<DropdownMenuItem
key={column.id}
onClick={(e) => {
e.preventDefault();
onClick={() => {
column.toggleVisibility(!isVisible);
}}
onSelect={(e) => e.preventDefault()}
className="flex items-center gap-2 cursor-pointer text-sm"
>
<Checkbox checked={isVisible} className="border-border" />

View File

@@ -1,19 +1,32 @@
import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion";
import { ChevronDownIcon } from "lucide-react";
import type * as React from "react";
import * as React from "react";
import { cn } from "@/lib/utils";
type AccordionProps = AccordionPrimitive.Root.Props & {
type?: "single" | "multiple";
collapsible?: boolean;
};
function Accordion({
type,
collapsible,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
return <AccordionPrimitive.Root data-slot="accordion" {...props} />;
}: AccordionProps) {
return (
<AccordionPrimitive.Root
data-slot="accordion"
multiple={type === "multiple"}
{...props}
/>
);
}
function AccordionItem({
className,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
}: AccordionPrimitive.Item.Props) {
return (
<AccordionPrimitive.Item
data-slot="accordion-item"
@@ -27,13 +40,13 @@ function AccordionTrigger({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
}: AccordionPrimitive.Trigger.Props) {
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
data-slot="accordion-trigger"
className={cn(
"focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
"focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[aria-expanded=true]>svg]:rotate-180",
className,
)}
{...props}
@@ -49,15 +62,15 @@ function AccordionContent({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
}: AccordionPrimitive.Panel.Props) {
return (
<AccordionPrimitive.Content
<AccordionPrimitive.Panel
data-slot="accordion-content"
className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
className="data-closed:animate-accordion-up data-open:animate-accordion-down overflow-hidden text-sm"
{...props}
>
<div className={cn("pt-0 pb-4", className)}>{children}</div>
</AccordionPrimitive.Content>
</AccordionPrimitive.Panel>
);
}

View File

@@ -1,6 +1,7 @@
import { Slot } from "@radix-ui/react-slot";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cva, type VariantProps } from "class-variance-authority";
import type * as React from "react";
import * as React from "react";
import { cn } from "@/lib/utils";
@@ -36,18 +37,28 @@ function Badge({
className,
variant,
asChild = false,
render: renderProp,
children,
...props
}: React.ComponentProps<"span"> &
}: useRender.ComponentProps<"span"> &
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
const Comp = asChild ? Slot : "span";
const effectiveRender =
asChild && React.isValidElement(children) ? children : renderProp;
return (
<Comp
data-slot="badge"
className={cn(badgeVariants({ variant }), className)}
{...props}
/>
);
return useRender({
defaultTagName: "span",
props: mergeProps<"span">(
{
className: cn(badgeVariants({ variant }), className),
},
{ ...props, children: effectiveRender ? undefined : children },
),
render: effectiveRender,
state: {
slot: "badge",
variant,
},
});
}
export { Badge };

View File

@@ -1,6 +1,7 @@
import { Slot } from "@radix-ui/react-slot";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { ChevronRight, MoreHorizontal } from "lucide-react";
import type * as React from "react";
import * as React from "react";
import { cn } from "@/lib/utils";
@@ -34,19 +35,28 @@ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
function BreadcrumbLink({
asChild,
className,
render: renderProp,
children,
...props
}: React.ComponentProps<"a"> & {
}: useRender.ComponentProps<"a"> & {
asChild?: boolean;
}) {
const Comp = asChild ? Slot : "a";
const effectiveRender =
asChild && React.isValidElement(children) ? children : renderProp;
return (
<Comp
data-slot="breadcrumb-link"
className={cn("hover:text-foreground transition-colors", className)}
{...props}
/>
);
return useRender({
defaultTagName: "a",
props: mergeProps<"a">(
{
className: cn("hover:text-foreground transition-colors", className),
},
{ ...props, children: effectiveRender ? undefined : children },
),
render: effectiveRender,
state: {
slot: "breadcrumb-link",
},
});
}
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {

View File

@@ -1,5 +1,7 @@
import { Slot } from "@radix-ui/react-slot";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { Separator } from "@/components/ui/separator";
import { cn } from "@/lib/utils";
@@ -39,21 +41,31 @@ function ButtonGroup({
function ButtonGroupText({
className,
asChild = false,
render: renderProp,
children,
...props
}: React.ComponentProps<"div"> & {
}: useRender.ComponentProps<"div"> & {
asChild?: boolean;
}) {
const Comp = asChild ? Slot : "div";
const effectiveRender =
asChild && React.isValidElement(children) ? children : renderProp;
return (
<Comp
className={cn(
"bg-muted flex items-center gap-2 rounded-md border px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
className,
)}
{...props}
/>
);
return useRender({
defaultTagName: "div",
props: mergeProps<"div">(
{
className: cn(
"bg-muted flex items-center gap-2 rounded-md border px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
className,
),
},
{ ...props, children: effectiveRender ? undefined : children },
),
render: effectiveRender,
state: {
slot: "button-group-text",
},
});
}
function ButtonGroupSeparator({

View File

@@ -1,12 +1,10 @@
import { Slot } from "@radix-ui/react-slot";
import { Button as ButtonPrimitive } from "@base-ui/react/button";
import { cva, type VariantProps } from "class-variance-authority";
import { LoaderCircle, PlusIcon, Search } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip";
// [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0
const buttonVariants = cva(
`inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-sm text-sm transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-zinc-950 disabled:pointer-events-none disabled:opacity-50 dark:focus-visible:ring-zinc-300 font-regular
@@ -14,19 +12,14 @@ const buttonVariants = cva(
{
variants: {
variant: {
// border border-[#8231FF]
default:
// "bg-zinc-900 text-zinc-50 shadow hover:bg-zinc-900/90 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-50/90",
`bg-primary hover:bg-primary/90 text-zinc-50 shadow dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-50/90
!rounded-xs
`,
secondary:
"border border-zinc-200 bg-white shadow-sm hover:bg-zinc-100 hover:text-zinc-900 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-800 dark:hover:text-zinc-50",
// "bg-zinc-100 text-zinc-900 shadow-sm hover:bg-zinc-100/80 dark:bg-zinc-800 dark:text-zinc-50 dark:hover:bg-zinc-800/80",
destructive:
"font-semibold text-red-400 border border-red-400 rounded-md shadow-sm hover:bg-red-500/90 hover:text-zinc-50 dark:bg-red-900 dark:text-zinc-50 dark:hover:bg-red-900/90 shadow-sm ",
// destructive:
// "bg-red-500 font-semibold text-zinc-50 shadow-sm hover:bg-red-500/90 dark:bg-red-900 dark:text-zinc-50 dark:hover:bg-red-900/90",
outline:
"border border-zinc-200 bg-white shadow-sm hover:bg-zinc-100 hover:text-zinc-900 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-800 dark:hover:text-zinc-50",
ghost:
@@ -36,15 +29,12 @@ const buttonVariants = cva(
link: "text-zinc-900 underline-offset-4 hover:underline dark:text-zinc-50",
dashed:
"hover:bg-stone-100 text-t2 border border-1 border-dashed border-stone-300",
// shadow-sm hover:from-stone-100 hover:to-stone-200 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-800 dark:hover:text-zinc-50
gradientPrimary:
"bg-gradient-to-b font-semibold border-t border-purple-400 outline outline-primary rounded-sm from-primary/85 to-primary text-white hover:from-primary hover:to-primary shadow-purple-500/50 transition-[background] duration-300 !h-7.5 mt-0.25",
gradientSecondary:
"border border-stone-300 font-semibold bg-gradient-to-b from-white to-stone-100 text-t1 hover:from-stone-300 hover:to-stone-400 shadow-sm",
// add: "text-primary border-t border-white outline outline-purple-800/20 bg-gradient-to-b from-zinc-50 to-zinc-200/70 shadow-sm hover:from-zinc-200 hover:border-zinc-200 hover:text-primary dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-800 dark:hover:text-zinc-50 !h-6 rounded-md",
add: "text-primary border-t border-white outline outline-zinc-200 bg-gradient-to-b from-stone-100 to-zinc-50 hover:from-stone-100 hover:to-stone-100 hover:border-primary dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-800 dark:hover:text-zinc-50 !h-9.5 rounded-none",
// add: "border-t border-purple-400 bg-gradient-to-b from-primary/90 to-primary text-white hover:from-primary hover:to-primary !shadow-lg !h-6 rounded-md",
analyse:
"text-primary border-t border-white outline outline-zinc-200 bg-gradient-to-b from-stone-100 to-zinc-50 hover:from-stone-100 hover:to-stone-100 hover:border-primary dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-800 dark:hover:text-zinc-50 !h-9.5 rounded-none",
@@ -82,6 +72,7 @@ export interface ButtonProps
tooltipContent?: string;
disableStartIcon?: boolean;
shimmer?: boolean;
render?: React.ReactElement;
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
@@ -100,14 +91,17 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
children,
disableStartIcon = false,
shimmer = false,
render,
...props
},
ref,
) => {
const Comp = asChild ? Slot : "button";
const Button = (
<Comp
const renderProp = asChild && React.isValidElement(children) ? children : render;
const ButtonElement = (
<ButtonPrimitive
{...props}
render={renderProp}
className={cn(
buttonVariants({ variant, size, className }),
isIcon && `w-${dim} h-${dim} p-0`,
@@ -124,33 +118,33 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
}}
disabled={isLoading || props.disabled || shimmer}
>
{isLoading && <LoaderCircle className="animate-spin" size={14} />}
{startIcon && !isLoading && <>{startIcon}</>}
{!isLoading && !startIcon && variant === "add" && !disableStartIcon && (
<PlusIcon size={12} />
{renderProp ? undefined : (
<>
{isLoading && <LoaderCircle className="animate-spin" size={14} />}
{startIcon && !isLoading && <>{startIcon}</>}
{!isLoading && !startIcon && variant === "add" && !disableStartIcon && (
<PlusIcon size={12} />
)}
{!isLoading &&
!startIcon &&
variant === "analyse" &&
!disableStartIcon && <Search size={12} />}
{children}
{endIcon && !isLoading && <>{endIcon}</>}
</>
)}
{!isLoading &&
!startIcon &&
variant === "analyse" &&
!disableStartIcon && <Search size={12} />}
{children}
{endIcon && !isLoading && <>{endIcon}</>}
</Comp>
</ButtonPrimitive>
);
if (tooltipContent) {
return (
<Tooltip delayDuration={200}>
<TooltipTrigger asChild>{Button}</TooltipTrigger>
<TooltipTrigger asChild>{ButtonElement}</TooltipTrigger>
<TooltipContent>{tooltipContent}</TooltipContent>
</Tooltip>
// <Tooltip content={tooltipContent}>
// {Button}
// </Tooltip>
);
} else {
return Button;
}
return ButtonElement;
},
);
Button.displayName = "Button";

View File

@@ -1,12 +1,12 @@
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox";
import { CheckIcon } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> & {
HTMLButtonElement,
CheckboxPrimitive.Root.Props & {
iconClassName?: string;
}
>(({ className, iconClassName, ...props }, ref) => (
@@ -14,7 +14,7 @@ const Checkbox = React.forwardRef<
ref={ref}
data-slot="checkbox"
className={cn(
"peer shrink-0 rounded border border-gray-300 size-4 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-gray-900 data-[state=checked]:border-gray-900 transition-none",
"peer shrink-0 rounded border border-gray-300 size-4 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-checked:bg-gray-900 data-checked:border-gray-900 transition-none",
className,
)}
{...props}
@@ -27,6 +27,6 @@ const Checkbox = React.forwardRef<
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
));
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
Checkbox.displayName = "Checkbox";
export { Checkbox };

View File

@@ -1,6 +1,6 @@
"use client";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
import { XIcon } from "lucide-react";
import * as React from "react";
@@ -8,60 +8,90 @@ import { cn } from "@/lib/utils";
function Dialog({
...props
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
}: DialogPrimitive.Root.Props) {
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
}
function DialogTrigger({
asChild,
children,
...props
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
}: DialogPrimitive.Trigger.Props & { asChild?: boolean }) {
if (asChild && React.isValidElement(children)) {
return (
<DialogPrimitive.Trigger
data-slot="dialog-trigger"
render={children}
{...props}
/>
);
}
return (
<DialogPrimitive.Trigger data-slot="dialog-trigger" {...props}>
{children}
</DialogPrimitive.Trigger>
);
}
function DialogPortal({
...props
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
}: DialogPrimitive.Portal.Props) {
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
}
function DialogClose({
asChild,
children,
...props
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
}: DialogPrimitive.Close.Props & { asChild?: boolean }) {
if (asChild && React.isValidElement(children)) {
return (
<DialogPrimitive.Close
data-slot="dialog-close"
render={children}
{...props}
/>
);
}
return (
<DialogPrimitive.Close data-slot="dialog-close" {...props}>
{children}
</DialogPrimitive.Close>
);
}
const DialogOverlay = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Overlay
ref={ref}
data-slot="dialog-overlay"
onClick={(e) => e.stopPropagation()}
className={cn(
"fixed inset-0 z-[170] bg-white/70 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
{...props}
/>
));
DialogOverlay.displayName = "DialogOverlay";
function DialogOverlay({
className,
...props
}: DialogPrimitive.Backdrop.Props) {
return (
<DialogPrimitive.Backdrop
data-slot="dialog-overlay"
onClick={(e) => e.stopPropagation()}
className={cn(
"fixed inset-0 z-[170] bg-white/70 backdrop-blur-sm data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0",
className,
)}
{...props}
/>
);
}
function DialogContent({
className,
children,
showCloseButton = true,
...props
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
}: DialogPrimitive.Popup.Props & {
showCloseButton?: boolean;
}) {
return (
<DialogPortal data-slot="dialog-portal">
<DialogOverlay />
<DialogPrimitive.Content
<DialogPrimitive.Popup
data-slot="dialog-content"
className={cn(
`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 fixed top-[50%] left-[50%] z-[180] grid translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-3xl
`data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 fixed top-[50%] left-[50%] z-[180] grid translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-3xl
bg-stone-50
min-w-[15rem]
`,
@@ -71,12 +101,12 @@ function DialogContent({
>
{children}
{showCloseButton && (
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-open:bg-accent data-open:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
<XIcon />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
)}
</DialogPrimitive.Content>
</DialogPrimitive.Popup>
</DialogPortal>
);
}
@@ -113,7 +143,7 @@ function DialogFooter({
function DialogTitle({
className,
...props
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
}: DialogPrimitive.Title.Props) {
return (
<DialogPrimitive.Title
data-slot="dialog-title"
@@ -126,7 +156,7 @@ function DialogTitle({
function DialogDescription({
className,
...props
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
}: DialogPrimitive.Description.Props) {
return (
<DialogPrimitive.Description
data-slot="dialog-description"

View File

@@ -1,35 +1,83 @@
"use client";
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
import { Check, ChevronRight, Circle } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
import SmallSpinner from "../general/SmallSpinner";
const DropdownMenu = DropdownMenuPrimitive.Root;
function DropdownMenu({
...props
}: MenuPrimitive.Root.Props) {
return <MenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
}
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
const DropdownMenuTrigger = React.forwardRef<
HTMLButtonElement,
MenuPrimitive.Trigger.Props & { asChild?: boolean }
>(({ asChild, children, ...props }, ref) => {
if (asChild && React.isValidElement(children)) {
return (
<MenuPrimitive.Trigger
ref={ref}
data-slot="dropdown-menu-trigger"
render={children}
{...props}
/>
);
}
return (
<MenuPrimitive.Trigger ref={ref} data-slot="dropdown-menu-trigger" {...props}>
{children}
</MenuPrimitive.Trigger>
);
});
DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
function DropdownMenuGroup({
...props
}: MenuPrimitive.Group.Props) {
return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />;
}
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
function DropdownMenuPortal({
children,
}: {
children: React.ReactNode;
}) {
return <>{children}</>;
}
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
function DropdownMenuSub({
...props
}: MenuPrimitive.SubmenuRoot.Props) {
return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />;
}
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
function DropdownMenuRadioGroup({
...props
}: MenuPrimitive.RadioGroup.Props) {
return (
<MenuPrimitive.RadioGroup
data-slot="dropdown-menu-radio-group"
{...props}
/>
);
}
const DropdownMenuSubTrigger = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
HTMLDivElement,
MenuPrimitive.SubmenuTrigger.Props & {
inset?: boolean;
withIcon?: boolean;
}
>(({ className, inset, children, withIcon = true, ...props }, ref) => (
<DropdownMenuPrimitive.SubTrigger
<MenuPrimitive.SubmenuTrigger
ref={ref}
data-slot="dropdown-menu-sub-trigger"
className={cn(
"flex cursor-pointer gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-zinc-100 data-[state=open]:bg-zinc-100 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus:bg-zinc-800 dark:data-[state=open]:bg-zinc-800",
"flex cursor-pointer gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-zinc-100 data-popup-open:bg-zinc-100 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus:bg-zinc-800 dark:data-popup-open:bg-zinc-800",
inset && "pl-8",
className,
)}
@@ -37,86 +85,131 @@ const DropdownMenuSubTrigger = React.forwardRef<
>
{children}
{withIcon && <ChevronRight className="ml-auto text-t3" />}
</DropdownMenuPrimitive.SubTrigger>
</MenuPrimitive.SubmenuTrigger>
));
DropdownMenuSubTrigger.displayName =
DropdownMenuPrimitive.SubTrigger.displayName;
DropdownMenuSubTrigger.displayName = "DropdownMenuSubTrigger";
const DropdownMenuSubContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.SubContent
ref={ref}
className={cn(
"z-[200] min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white p-1 shadow-lg 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 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50 text-zinc-800 font-regular",
className,
)}
{...props}
/>
HTMLDivElement,
MenuPrimitive.Popup.Props & {
sideOffset?: number;
}
>(({ className, sideOffset = 0, ...props }, ref) => (
<MenuPrimitive.Portal>
<MenuPrimitive.Positioner
sideOffset={sideOffset}
positionMethod="fixed"
className="isolate z-[200]"
>
<MenuPrimitive.Popup
ref={ref}
data-slot="dropdown-menu-sub-content"
className={cn(
"z-[200] min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white p-1 shadow-lg data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50 text-zinc-800 font-regular",
className,
)}
{...props}
/>
</MenuPrimitive.Positioner>
</MenuPrimitive.Portal>
));
DropdownMenuSubContent.displayName =
DropdownMenuPrimitive.SubContent.displayName;
DropdownMenuSubContent.displayName = "DropdownMenuSubContent";
const DropdownMenuContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
onCloseAutoFocus={(e) => e.preventDefault()}
ref={ref}
HTMLDivElement,
MenuPrimitive.Popup.Props & {
sideOffset?: number;
side?: "top" | "bottom" | "left" | "right";
align?: "start" | "center" | "end";
onCloseAutoFocus?: (e: any) => void;
}
>(({ className, sideOffset = 4, side = "bottom", align = "start", onCloseAutoFocus: _onCloseAutoFocus, ...props }, ref) => (
<MenuPrimitive.Portal>
<MenuPrimitive.Positioner
sideOffset={sideOffset}
className={cn(
"z-[200] min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white p-1 text-zinc-950 shadow-md dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50",
"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",
className,
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
side={side}
align={align}
positionMethod="fixed"
className="isolate z-[200] outline-none"
>
<MenuPrimitive.Popup
ref={ref}
data-slot="dropdown-menu-content"
className={cn(
"z-[200] min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white p-1 text-zinc-950 shadow-md dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50",
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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",
className,
)}
{...props}
/>
</MenuPrimitive.Positioner>
</MenuPrimitive.Portal>
));
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
DropdownMenuContent.displayName = "DropdownMenuContent";
const DropdownMenuItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
HTMLDivElement,
MenuPrimitive.Item.Props & {
inset?: boolean;
isLoading?: boolean;
shimmer?: boolean;
asChild?: boolean;
}
>(({ className, inset, shimmer = false, isLoading, ...props }, ref) => (
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
shimmer && "shimmer",
inset && "pl-8",
className,
)}
disabled={shimmer || isLoading}
{...props}
>
{isLoading ? (
<>
{props.children}
<SmallSpinner />
</>
) : (
props.children
)}
</DropdownMenuPrimitive.Item>
));
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
>(({ className, inset, shimmer = false, isLoading, children, asChild, ...props }, ref) => {
if (asChild && React.isValidElement(children)) {
return (
<MenuPrimitive.Item
ref={ref}
data-slot="dropdown-menu-item"
closeOnClick={false}
render={children}
className={cn(
"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
shimmer && "shimmer",
inset && "pl-8",
className,
)}
disabled={shimmer || isLoading}
{...props}
/>
);
}
return (
<MenuPrimitive.Item
ref={ref}
data-slot="dropdown-menu-item"
closeOnClick={false}
className={cn(
"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
shimmer && "shimmer",
inset && "pl-8",
className,
)}
disabled={shimmer || isLoading}
{...props}
>
{isLoading ? (
<>
{children}
<SmallSpinner />
</>
) : (
children
)}
</MenuPrimitive.Item>
);
});
DropdownMenuItem.displayName = "DropdownMenuItem";
const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
HTMLDivElement,
MenuPrimitive.CheckboxItem.Props
>(({ className, children, checked, ...props }, ref) => (
<DropdownMenuPrimitive.CheckboxItem
<MenuPrimitive.CheckboxItem
ref={ref}
data-slot="dropdown-menu-checkbox-item"
className={cn(
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-1 pr-2 text-sm outline-none transition-colors focus:bg-zinc-100 focus:text-zinc-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-zinc-800 dark:focus:text-zinc-50",
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-1 pr-2 text-sm outline-none transition-colors focus:bg-zinc-100 focus:text-zinc-900 data-disabled:pointer-events-none data-disabled:opacity-50 dark:focus:bg-zinc-800 dark:focus:text-zinc-50",
className,
)}
checked={checked}
@@ -124,45 +217,46 @@ const DropdownMenuCheckboxItem = React.forwardRef<
>
{children}
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<MenuPrimitive.CheckboxItemIndicator>
<Check className="h-4 w-4 text-t3" />
</DropdownMenuPrimitive.ItemIndicator>
</MenuPrimitive.CheckboxItemIndicator>
</span>
</DropdownMenuPrimitive.CheckboxItem>
</MenuPrimitive.CheckboxItem>
));
DropdownMenuCheckboxItem.displayName =
DropdownMenuPrimitive.CheckboxItem.displayName;
DropdownMenuCheckboxItem.displayName = "DropdownMenuCheckboxItem";
const DropdownMenuRadioItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
HTMLDivElement,
MenuPrimitive.RadioItem.Props
>(({ className, children, ...props }, ref) => (
<DropdownMenuPrimitive.RadioItem
<MenuPrimitive.RadioItem
ref={ref}
data-slot="dropdown-menu-radio-item"
className={cn(
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-zinc-100 focus:text-zinc-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-zinc-800 dark:focus:text-zinc-50",
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-zinc-100 focus:text-zinc-900 data-disabled:pointer-events-none data-disabled:opacity-50 dark:focus:bg-zinc-800 dark:focus:text-zinc-50",
className,
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<MenuPrimitive.RadioItemIndicator>
<Circle className="h-2 w-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</MenuPrimitive.RadioItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
</MenuPrimitive.RadioItem>
));
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
DropdownMenuRadioItem.displayName = "DropdownMenuRadioItem";
const DropdownMenuLabel = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
HTMLDivElement,
MenuPrimitive.GroupLabel.Props & {
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Label
<MenuPrimitive.GroupLabel
ref={ref}
data-slot="dropdown-menu-label"
className={cn(
"px-2 py-1.5 text-sm font-semibold",
inset && "pl-8",
@@ -171,19 +265,20 @@ const DropdownMenuLabel = React.forwardRef<
{...props}
/>
));
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
DropdownMenuLabel.displayName = "DropdownMenuLabel";
const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
HTMLDivElement,
MenuPrimitive.Separator.Props
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator
<MenuPrimitive.Separator
ref={ref}
data-slot="dropdown-menu-separator"
className={cn("-mx-1 my-1 h-px bg-zinc-100 dark:bg-zinc-800", className)}
{...props}
/>
));
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
const DropdownMenuShortcut = ({
className,

View File

@@ -1,19 +1,37 @@
import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
import type * as React from "react";
import { PreviewCard as PreviewCardPrimitive } from "@base-ui/react/preview-card";
import * as React from "react";
import { cn } from "@/lib/utils";
function HoverCard({
openDelay: _openDelay,
closeDelay: _closeDelay,
...props
}: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />;
}: PreviewCardPrimitive.Root.Props & {
openDelay?: number;
closeDelay?: number;
}) {
return <PreviewCardPrimitive.Root data-slot="hover-card" {...props} />;
}
function HoverCardTrigger({
asChild,
children,
...props
}: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
}: PreviewCardPrimitive.Trigger.Props & { asChild?: boolean }) {
if (asChild && React.isValidElement(children)) {
return (
<PreviewCardPrimitive.Trigger
data-slot="hover-card-trigger"
render={children}
{...props}
/>
);
}
return (
<HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
<PreviewCardPrimitive.Trigger data-slot="hover-card-trigger" {...props}>
{children}
</PreviewCardPrimitive.Trigger>
);
}
@@ -21,21 +39,32 @@ function HoverCardContent({
className,
align = "center",
sideOffset = 4,
side = "bottom",
...props
}: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
}: PreviewCardPrimitive.Popup.Props &
Pick<
PreviewCardPrimitive.Positioner.Props,
"align" | "side" | "sideOffset"
>) {
return (
<HoverCardPrimitive.Portal data-slot="hover-card-portal">
<HoverCardPrimitive.Content
data-slot="hover-card-content"
<PreviewCardPrimitive.Portal data-slot="hover-card-portal">
<PreviewCardPrimitive.Positioner
align={align}
side={side}
sideOffset={sideOffset}
className={cn(
"bg-popover text-popover-foreground 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 z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
className,
)}
{...props}
/>
</HoverCardPrimitive.Portal>
positionMethod="fixed"
className="isolate z-50"
>
<PreviewCardPrimitive.Popup
data-slot="hover-card-content"
className={cn(
"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 w-64 origin-(--transform-origin) rounded-md border p-4 shadow-md outline-hidden",
className,
)}
{...props}
/>
</PreviewCardPrimitive.Positioner>
</PreviewCardPrimitive.Portal>
);
}

View File

@@ -1,4 +1,4 @@
import * as LabelPrimitive from "@radix-ui/react-label";
import { Field } from "@base-ui/react/field";
import type * as React from "react";
import { cn } from "@/lib/utils";
@@ -6,9 +6,9 @@ import { cn } from "@/lib/utils";
function Label({
className,
...props
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
}: Field.Label.Props) {
return (
<LabelPrimitive.Root
<Field.Label
data-slot="label"
className={cn(
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",

View File

@@ -1,46 +1,79 @@
import * as PopoverPrimitive from "@radix-ui/react-popover";
import type * as React from "react";
import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
import * as React from "react";
import { cn } from "@/lib/utils";
function Popover({
...props
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
}: PopoverPrimitive.Root.Props) {
return <PopoverPrimitive.Root data-slot="popover" {...props} />;
}
function PopoverTrigger({
asChild,
children,
...props
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;
}: PopoverPrimitive.Trigger.Props & { asChild?: boolean }) {
if (asChild && React.isValidElement(children)) {
return (
<PopoverPrimitive.Trigger
data-slot="popover-trigger"
render={children}
{...props}
/>
);
}
return (
<PopoverPrimitive.Trigger data-slot="popover-trigger" {...props}>
{children}
</PopoverPrimitive.Trigger>
);
}
function PopoverContent({
className,
align = "center",
sideOffset = 4,
side = "bottom",
onEscapeKeyDown: _onEscapeKeyDown,
onPointerDownOutside: _onPointerDownOutside,
onOpenAutoFocus: _onOpenAutoFocus,
onCloseAutoFocus: _onCloseAutoFocus,
forceMount: _forceMount,
asChild: _asChild,
...props
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
}: PopoverPrimitive.Popup.Props &
Pick<
PopoverPrimitive.Positioner.Props,
"align" | "side" | "sideOffset"
> & {
onEscapeKeyDown?: (e: any) => void;
onPointerDownOutside?: (e: any) => void;
onOpenAutoFocus?: (e: any) => void;
onCloseAutoFocus?: (e: any) => void;
forceMount?: boolean;
asChild?: boolean;
}) {
return (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
data-slot="popover-content"
<PopoverPrimitive.Positioner
align={align}
side={side}
sideOffset={sideOffset}
className={cn(
"bg-popover text-popover-foreground 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 z-[200] w-72 rounded-md border p-4 shadow-md outline-hidden",
className,
)}
{...props}
/>
positionMethod="fixed"
className="isolate z-[200]"
>
<PopoverPrimitive.Popup
data-slot="popover-content"
className={cn(
"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 w-72 rounded-md border p-4 shadow-md outline-hidden",
className,
)}
{...props}
/>
</PopoverPrimitive.Positioner>
</PopoverPrimitive.Portal>
);
}
function PopoverAnchor({
...props
}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />;
}
export { Popover, PopoverTrigger, PopoverContent };

View File

@@ -1,4 +1,4 @@
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area";
import type * as React from "react";
import { cn } from "@/lib/utils";
@@ -7,7 +7,7 @@ function ScrollArea({
className,
children,
...props
}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
}: ScrollAreaPrimitive.Root.Props) {
return (
<ScrollAreaPrimitive.Root
data-slot="scroll-area"
@@ -30,9 +30,9 @@ function ScrollBar({
className,
orientation = "vertical",
...props
}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
}: ScrollAreaPrimitive.Scrollbar.Props) {
return (
<ScrollAreaPrimitive.ScrollAreaScrollbar
<ScrollAreaPrimitive.Scrollbar
data-slot="scroll-area-scrollbar"
orientation={orientation}
className={cn(
@@ -45,12 +45,12 @@ function ScrollBar({
)}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb
<ScrollAreaPrimitive.Thumb
data-slot="scroll-area-thumb"
className="bg-border relative flex-1 rounded-full"
/>
</ScrollAreaPrimitive.ScrollAreaScrollbar>
</ScrollAreaPrimitive.Scrollbar>
);
}
export { ScrollArea };
export { ScrollArea, ScrollBar };

View File

@@ -1,6 +1,6 @@
"use client";
import * as SeparatorPrimitive from "@radix-ui/react-separator";
import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
import type * as React from "react";
import { cn } from "@/lib/utils";
@@ -8,14 +8,17 @@ import { cn } from "@/lib/utils";
function Separator({
className,
orientation = "horizontal",
decorative = true,
decorative,
...props
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
}: SeparatorPrimitive.Props & {
orientation?: "horizontal" | "vertical";
decorative?: boolean;
}) {
return (
<SeparatorPrimitive.Root
<SeparatorPrimitive
data-slot="separator-root"
decorative={decorative}
orientation={orientation}
data-orientation={orientation}
className={cn(
"shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px bg-border",
className,

View File

@@ -1,6 +1,6 @@
"use client";
import * as SwitchPrimitive from "@radix-ui/react-switch";
import { Switch as SwitchPrimitive } from "@base-ui/react/switch";
import type * as React from "react";
import { cn } from "@/lib/utils";
@@ -9,14 +9,14 @@ function Switch({
className,
thumbClassName,
...props
}: React.ComponentProps<typeof SwitchPrimitive.Root> & {
}: SwitchPrimitive.Root.Props & {
thumbClassName?: string;
}) {
return (
<SwitchPrimitive.Root
data-slot="switch"
className={cn(
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
"peer data-checked:bg-primary data-unchecked:bg-input focus-visible:border-ring focus-visible:ring-ring/50 inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
{...props}
@@ -24,7 +24,7 @@ function Switch({
<SwitchPrimitive.Thumb
data-slot="switch-thumb"
className={cn(
"bg-background pointer-events-none block size-4 rounded-full ring-0 shadow-lg transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0",
"bg-background pointer-events-none block size-4 rounded-full ring-0 shadow-lg transition-transform data-checked:translate-x-4 data-unchecked:translate-x-0",
thumbClassName,
)}
/>

View File

@@ -1,59 +1,59 @@
"use client";
import * as TabsPrimitive from "@radix-ui/react-tabs";
import { Tabs as TabsPrimitive } from "@base-ui/react/tabs";
import * as React from "react";
import { cn } from "@/lib/utils";
const Tabs = TabsPrimitive.Root;
function Tabs({ ...props }: TabsPrimitive.Root.Props) {
return <TabsPrimitive.Root data-slot="tabs" {...props} />;
}
const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
"inline-flex h-9 items-center justify-center rounded-lg bg-transparent text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400 px-1",
className,
)}
{...props}
/>
));
TabsList.displayName = TabsPrimitive.List.displayName;
const TabsList = React.forwardRef<HTMLDivElement, TabsPrimitive.List.Props>(
({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
"inline-flex h-9 items-center justify-center rounded-lg bg-transparent text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400 px-1",
className,
)}
{...props}
/>
),
);
TabsList.displayName = "TabsList";
const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger> & {
HTMLButtonElement,
TabsPrimitive.Tab.Props & {
variant?: "default" | "onboarding";
}
>(({ className, variant = "default", ...props }, ref) => (
<TabsPrimitive.Trigger
<TabsPrimitive.Tab
ref={ref}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-2 py-1 text-sm font-medium ring-offset-background transition-all cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-primary hover:bg-interactive-secondary-hover dark:focus-visible:ring-zinc-300 dark:data-[state=active]:bg-zinc-950 dark:data-[state=active]:text-zinc-50",
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-2 py-1 text-sm font-medium ring-offset-background transition-all cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[active]:text-primary hover:bg-interactive-secondary-hover dark:focus-visible:ring-zinc-300 dark:data-[active]:bg-zinc-950 dark:data-[active]:text-zinc-50",
className,
variant === "onboarding" &&
"data-[state=active]:bg-stone-200 data-[state=active]:text-t2 data-[state=active]:font-medium",
"data-[active]:bg-stone-200 data-[active]:text-t2 data-[active]:font-medium",
)}
{...props}
/>
));
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
TabsTrigger.displayName = "TabsTrigger";
const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Content
ref={ref}
className={cn(
"mt-2 mb-4 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className,
)}
{...props}
/>
));
TabsContent.displayName = TabsPrimitive.Content.displayName;
const TabsContent = React.forwardRef<HTMLDivElement, TabsPrimitive.Panel.Props>(
({ className, ...props }, ref) => (
<TabsPrimitive.Panel
ref={ref}
className={cn(
"mt-2 mb-4 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className,
)}
{...props}
/>
),
);
TabsContent.displayName = "TabsContent";
export { Tabs, TabsContent, TabsList, TabsTrigger };

View File

@@ -1,63 +1,90 @@
"use client";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import type * as React from "react";
import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
import * as React from "react";
import { cn } from "@/lib/utils";
function TooltipProvider({
delayDuration = 0,
delay = 0,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
}: TooltipPrimitive.Provider.Props) {
return (
<TooltipPrimitive.Provider
data-slot="tooltip-provider"
delayDuration={delayDuration}
delay={delay}
{...props}
/>
);
}
function Tooltip({
delayDuration,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
}: TooltipPrimitive.Root.Props & { delayDuration?: number }) {
return (
<TooltipProvider>
<TooltipProvider delay={delayDuration}>
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
</TooltipProvider>
);
}
function TooltipTrigger({
asChild,
children,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
}: TooltipPrimitive.Trigger.Props & { asChild?: boolean }) {
if (asChild && React.isValidElement(children)) {
return (
<TooltipPrimitive.Trigger
data-slot="tooltip-trigger"
render={children}
{...props}
/>
);
}
return (
<TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props}>
{children}
</TooltipPrimitive.Trigger>
);
}
function TooltipContent({
className,
sideOffset = 0,
side = "top",
align = "center",
children,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
}: TooltipPrimitive.Popup.Props &
Pick<
TooltipPrimitive.Positioner.Props,
"align" | "side" | "sideOffset"
>) {
return (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
data-slot="tooltip-content"
<TooltipPrimitive.Positioner
side={side}
sideOffset={sideOffset}
className={cn(
`z-[200] overflow-hidden rounded-lg px-4 py-2 text-xs max-w-56 animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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
align={align}
positionMethod="fixed"
className="isolate z-[200]"
>
<TooltipPrimitive.Popup
data-slot="tooltip-content"
className={cn(
`overflow-hidden rounded-lg px-4 py-2 text-xs max-w-56 animate-in fade-in-0 zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-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
backdrop-blur-sm shadow-lg text-t2 border bg-outer-background
`,
className,
)}
{...props}
>
{children}
{/* <TooltipPrimitive.Arrow className="bg-zinc-900 fill-zinc-900 z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" /> */}
</TooltipPrimitive.Content>
className,
)}
{...props}
>
{children}
</TooltipPrimitive.Popup>
</TooltipPrimitive.Positioner>
</TooltipPrimitive.Portal>
);
}

View File

@@ -1,24 +1,24 @@
import { CheckIcon, CopyIcon } from "@phosphor-icons/react";
import * as TabsPrimitive from "@radix-ui/react-tabs";
import { Tabs as TabsPrimitive } from "@base-ui/react/tabs";
import * as React from "react";
import { useTheme } from "@/contexts/ThemeProvider";
import { highlightCode } from "@/lib/shikiHighlighter";
import { cn } from "@/lib/utils";
interface CodeGroupProps
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root> {}
extends TabsPrimitive.Root.Props {}
const CodeGroup = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Root>,
HTMLDivElement,
CodeGroupProps
>(({ ...props }, ref) => <TabsPrimitive.Root ref={ref} {...props} />);
CodeGroup.displayName = "CodeGroup";
interface CodeGroupListProps
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.List> {}
extends TabsPrimitive.List.Props {}
const CodeGroupList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
HTMLDivElement,
CodeGroupListProps
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
@@ -30,13 +30,13 @@ const CodeGroupList = React.forwardRef<
CodeGroupList.displayName = "CodeGroupList";
interface CodeGroupTabProps
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger> {}
extends TabsPrimitive.Tab.Props {}
const CodeGroupTab = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
HTMLButtonElement,
CodeGroupTabProps
>(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger
<TabsPrimitive.Tab
ref={ref}
className={cn(
"flex items-center justify-center flex-1 min-w-0 h-6 px-2 py-1 text-[13px] font-semibold tracking-[-0.039px] leading-normal whitespace-nowrap",
@@ -44,8 +44,8 @@ const CodeGroupTab = React.forwardRef<
"text-t3 transition-none outline-none",
"hover:text-primary",
"focus-visible:text-primary",
"data-[state=active]:bg-interactive-secondary-hover data-[state=active]:shadow-[0px_3px_4px_0px_inset_rgba(0,0,0,0.04)]",
"data-[state=inactive]:shadow-[0px_-3px_4px_0px_inset_rgba(0,0,0,0.04)]",
"data-selected:bg-interactive-secondary-hover data-selected:shadow-[0px_3px_4px_0px_inset_rgba(0,0,0,0.04)]",
"data-unselected:shadow-[0px_-3px_4px_0px_inset_rgba(0,0,0,0.04)]",
"first:rounded-tl-md first:border-l",
className,
)}
@@ -102,16 +102,16 @@ const CodeGroupCopyButton = React.forwardRef<
CodeGroupCopyButton.displayName = "CodeGroupCopyButton";
interface CodeGroupContentProps
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content> {
extends TabsPrimitive.Panel.Props {
copyText?: string;
}
const CodeGroupContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
HTMLDivElement,
CodeGroupContentProps
>(({ className, children, copyText: _copyText, ...props }, ref) => {
return (
<TabsPrimitive.Content
<TabsPrimitive.Panel
ref={ref}
className={cn(
"bg-white dark:bg-background border border-t-0 rounded-bl-lg rounded-br-lg",
@@ -121,7 +121,7 @@ const CodeGroupContent = React.forwardRef<
{...props}
>
{children}
</TabsPrimitive.Content>
</TabsPrimitive.Panel>
);
});
CodeGroupContent.displayName = "CodeGroupContent";

View File

@@ -1,11 +1,10 @@
import { Slot } from "@radix-ui/react-slot";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cva, type VariantProps } from "class-variance-authority";
import type * as React from "react";
import { cn } from "@/lib/utils";
// transition-colors focus:outline-none focus:ring-2 focus:ring-zinc-950 focus:ring-offset-2 dark:border-zinc-800 dark:focus:ring-zinc-300
const badgeVariants = cva(
`inline-flex items-center rounded-lg border border-zinc-200 px-1.5 py-0.5
@@ -38,18 +37,24 @@ function Badge({
variant,
size,
asChild = false,
render: renderProp,
...props
}: React.ComponentProps<"span"> &
}: useRender.ComponentProps<"span"> &
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
const Comp = asChild ? Slot : "span";
return (
<Comp
data-slot="badge"
className={cn(badgeVariants({ variant, size }), className)}
{...props}
/>
);
return useRender({
defaultTagName: "span",
props: mergeProps<"span">(
{
className: cn(badgeVariants({ variant, size }), className),
},
props,
),
render: renderProp,
state: {
slot: "badge",
variant,
},
});
}
export { Badge };

View File

@@ -1,12 +1,10 @@
/* eslint-disable react-refresh/only-export-components */
import { Slot } from "@radix-ui/react-slot";
import { Button as ButtonPrimitive } from "@base-ui/react/button";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import SmallSpinner from "@/components/general/SmallSpinner";
import { cn } from "@/lib/utils";
// Remove ring styles
// focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive
const buttonVariants = cva(
`inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none cursor-pointer
rounded-lg group/btn transition-colors w-fit transform-gpu
@@ -14,7 +12,6 @@ const buttonVariants = cva(
{
variants: {
variant: {
// Custom
primary: `
!text-primary-foreground
bg-primary
@@ -76,6 +73,7 @@ export interface ButtonProps
transition?: boolean;
disableActive?: boolean;
hide?: boolean;
render?: React.ReactElement;
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
@@ -90,11 +88,12 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
disableActive = true,
hide = false,
children,
render: renderProp,
...props
},
ref,
) => {
const Comp = asChild ? Slot : "button";
const effectiveRender = asChild && React.isValidElement(children) ? children : renderProp;
const getDisableActiveStyles = () => {
if (!disableActive) return "";
@@ -126,9 +125,10 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
if (hide) return null;
return (
<Comp
<ButtonPrimitive
ref={ref}
data-slot="button"
render={effectiveRender}
className={cn(
buttonVariants({ variant, size, className }),
getDisableActiveStyles(),
@@ -136,19 +136,23 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
disabled={isLoading || props.disabled}
{...props}
>
{isLoading ? (
<SmallSpinner
size={14}
className={variant === "primary" ? "relative z-10" : undefined}
/>
) : variant === "primary" ? (
<span className="relative z-10 inline-flex items-center gap-2 transition-none">
{children}
</span>
) : (
children
{effectiveRender ? undefined : (
<>
{isLoading ? (
<SmallSpinner
size={14}
className={variant === "primary" ? "relative z-10" : undefined}
/>
) : variant === "primary" ? (
<span className="relative z-10 inline-flex items-center gap-2 transition-none">
{children}
</span>
) : (
children
)}
</>
)}
</Comp>
</ButtonPrimitive>
);
},
);

View File

@@ -1,15 +1,15 @@
import type * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import type { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox";
import * as React from "react";
import { Checkbox } from "@/components/ui/checkbox";
import { cn } from "@/lib/utils";
export const CheckboxButton = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
HTMLButtonElement,
CheckboxPrimitive.Root.Props
>(({ className, onCheckedChange, checked, ...props }, ref) => {
const handleClick = () => {
const newChecked = !checked;
onCheckedChange?.(newChecked);
(onCheckedChange as ((checked: boolean) => void) | undefined)?.(newChecked);
};
return (
@@ -35,7 +35,7 @@ export const CheckboxButton = React.forwardRef<
ref={ref}
tabIndex={-1}
onClick={(e) => e.preventDefault()}
className="data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:shadow-none size-3.5 shadow-[0_2px_4px_0_#00000005,inset_0_2px_1px_0_#FFFFFF] rounded-md border border-border bg-interactive-secondary dark:shadow-none pointer-events-none"
className="data-checked:bg-primary data-checked:border-primary data-checked:shadow-none size-3.5 shadow-[0_2px_4px_0_#00000005,inset_0_2px_1px_0_#FFFFFF] rounded-md border border-border bg-interactive-secondary dark:shadow-none pointer-events-none"
iconClassName="size-2"
{...props}
/>

View File

@@ -1,13 +1,12 @@
"use client";
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox";
import { CheckIcon } from "lucide-react";
import type * as React from "react";
import { cn } from "@/lib/utils";
interface CheckboxProps
extends React.ComponentProps<typeof CheckboxPrimitive.Root> {
interface CheckboxProps extends CheckboxPrimitive.Root.Props {
size?: "sm" | "md" | "lg";
disabled?: boolean;
}
@@ -24,7 +23,7 @@ function Checkbox({
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === "Enter" && !disabled) {
e.preventDefault();
onCheckedChange?.(!checked);
(onCheckedChange as ((checked: boolean) => void) | undefined)?.(!checked);
}
};
@@ -33,7 +32,7 @@ function Checkbox({
data-slot="checkbox"
style={{ cursor: "pointer", ...style }}
className={cn(
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
"peer border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
!disabled && "hover:bg-hover-primary hover:border-primary",
size === "sm" && "size-3.5",

View File

@@ -1,11 +1,10 @@
import type * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import type * as React from "react";
import { useId } from "react";
import { cn } from "@/lib/utils";
import { Checkbox } from "./Checkbox";
interface TextCheckboxProps
extends React.ComponentProps<typeof CheckboxPrimitive.Root> {
extends React.ComponentProps<typeof Checkbox> {
children: React.ReactNode;
}

View File

@@ -1,6 +1,6 @@
"use client";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
import { XIcon } from "lucide-react";
import * as React from "react";
@@ -8,57 +8,87 @@ import { cn } from "@/lib/utils";
function Dialog({
...props
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
}: DialogPrimitive.Root.Props) {
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
}
function DialogTrigger({
asChild,
children,
...props
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
}: DialogPrimitive.Trigger.Props & { asChild?: boolean }) {
if (asChild && React.isValidElement(children)) {
return (
<DialogPrimitive.Trigger
data-slot="dialog-trigger"
render={children}
{...props}
/>
);
}
return (
<DialogPrimitive.Trigger data-slot="dialog-trigger" {...props}>
{children}
</DialogPrimitive.Trigger>
);
}
function DialogPortal({
...props
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
}: DialogPrimitive.Portal.Props) {
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
}
function DialogClose({
asChild,
children,
...props
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
}: DialogPrimitive.Close.Props & { asChild?: boolean }) {
if (asChild && React.isValidElement(children)) {
return (
<DialogPrimitive.Close
data-slot="dialog-close"
render={children}
{...props}
/>
);
}
return (
<DialogPrimitive.Close data-slot="dialog-close" {...props}>
{children}
</DialogPrimitive.Close>
);
}
const DialogOverlay = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Overlay
ref={ref}
data-slot="dialog-overlay"
className={cn(
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-[170] bg-black/50 dark:bg-black/80",
className,
)}
{...props}
/>
));
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
function DialogOverlay({
className,
...props
}: DialogPrimitive.Backdrop.Props) {
return (
<DialogPrimitive.Backdrop
data-slot="dialog-overlay"
className={cn(
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 fixed inset-0 z-[170] bg-black/50 dark:bg-black/80",
className,
)}
{...props}
/>
);
}
const DialogContent = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
HTMLDivElement,
DialogPrimitive.Popup.Props & {
showCloseButton?: boolean;
}
>(({ className, children, showCloseButton = true, ...props }, ref) => (
<DialogPortal data-slot="dialog-portal">
<DialogOverlay />
<DialogPrimitive.Content
<DialogPrimitive.Popup
ref={ref}
data-slot="dialog-content"
className={cn(
"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 fixed top-[40%] left-[50%] z-[180] grid translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200",
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 fixed top-[40%] left-[50%] z-[180] grid translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200",
"w-full max-w-md gap-3 bg-background",
"p-4",
@@ -70,16 +100,16 @@ const DialogContent = React.forwardRef<
{showCloseButton && (
<DialogPrimitive.Close
data-slot="dialog-close"
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
className="ring-offset-background focus:ring-ring data-open:bg-accent data-open:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
>
<XIcon />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
)}
</DialogPrimitive.Content>
</DialogPrimitive.Popup>
</DialogPortal>
));
DialogContent.displayName = DialogPrimitive.Content.displayName;
DialogContent.displayName = "DialogContent";
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
@@ -105,8 +135,8 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
}
const DialogTitle = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
HTMLHeadingElement,
DialogPrimitive.Title.Props
>(({ className, ...props }, ref) => (
<DialogPrimitive.Title
ref={ref}
@@ -115,11 +145,11 @@ const DialogTitle = React.forwardRef<
{...props}
/>
));
DialogTitle.displayName = DialogPrimitive.Title.displayName;
DialogTitle.displayName = "DialogTitle";
const DialogDescription = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
HTMLParagraphElement,
DialogPrimitive.Description.Props
>(({ className, ...props }, ref) => (
<DialogPrimitive.Description
ref={ref}
@@ -128,7 +158,7 @@ const DialogDescription = React.forwardRef<
{...props}
/>
));
DialogDescription.displayName = DialogPrimitive.Description.displayName;
DialogDescription.displayName = "DialogDescription";
export {
Dialog,

View File

@@ -1,6 +1,6 @@
"use client";
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
import { cva, type VariantProps } from "class-variance-authority";
import { Check, ChevronRight, Circle } from "lucide-react";
import * as React from "react";
@@ -9,14 +9,12 @@ import { useHotkeys } from "react-hotkeys-hook";
import SmallSpinner from "@/components/general/SmallSpinner";
import { cn } from "@/lib/utils";
// Context for sharing menu open state with items
const DropdownMenuContext = React.createContext<{ isOpen: boolean }>({
isOpen: false,
});
// CVA variants for menu items
const dropdownMenuItemVariants = cva(
"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-t2 outline-hidden transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-t2 outline-hidden transition-colors data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
{
variants: {
variant: {
@@ -40,86 +38,91 @@ type DropdownMenuItemVariantProps = VariantProps<
typeof dropdownMenuItemVariants
>;
// Root
function DropdownMenu(
props: React.ComponentProps<typeof DropdownMenuPrimitive.Root>,
props: MenuPrimitive.Root.Props,
) {
const isOpen = props.open ?? false;
return (
<DropdownMenuContext.Provider value={{ isOpen }}>
<DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
<MenuPrimitive.Root data-slot="dropdown-menu" {...props} />
</DropdownMenuContext.Provider>
);
}
// Trigger
const DropdownMenuTrigger = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Trigger>,
React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>
>(function DropdownMenuTrigger(props, ref) {
HTMLButtonElement,
MenuPrimitive.Trigger.Props & { asChild?: boolean }
>(function DropdownMenuTrigger({ asChild, children, ...props }, ref) {
if (asChild && React.isValidElement(children)) {
return (
<MenuPrimitive.Trigger
ref={ref}
data-slot="dropdown-menu-trigger"
render={children}
{...props}
/>
);
}
return (
<DropdownMenuPrimitive.Trigger
<MenuPrimitive.Trigger
ref={ref}
data-slot="dropdown-menu-trigger"
{...props}
/>
>
{children}
</MenuPrimitive.Trigger>
);
});
// Group
function DropdownMenuGroup(
props: React.ComponentProps<typeof DropdownMenuPrimitive.Group>,
props: MenuPrimitive.Group.Props,
) {
return (
<DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
<MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
);
}
// Portal
function DropdownMenuPortal(
props: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>,
) {
return <DropdownMenuPrimitive.Portal {...props} />;
function DropdownMenuPortal({
children,
}: {
children: React.ReactNode;
}) {
return <>{children}</>;
}
// Sub
function DropdownMenuSub(
props: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>,
props: MenuPrimitive.SubmenuRoot.Props,
) {
return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />;
return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />;
}
// RadioGroup
function DropdownMenuRadioGroup(
props: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>,
props: MenuPrimitive.RadioGroup.Props,
) {
return (
<DropdownMenuPrimitive.RadioGroup
<MenuPrimitive.RadioGroup
data-slot="dropdown-menu-radio-group"
{...props}
/>
);
}
// SubTrigger
type DropdownMenuSubTriggerProps = React.ComponentProps<
typeof DropdownMenuPrimitive.SubTrigger
> & {
type DropdownMenuSubTriggerProps = MenuPrimitive.SubmenuTrigger.Props & {
inset?: boolean;
withIcon?: boolean;
};
const DropdownMenuSubTrigger = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
HTMLDivElement,
DropdownMenuSubTriggerProps
>(function DropdownMenuSubTrigger(props, ref) {
const { inset, withIcon = true, className, children, ...rest } = props;
return (
<DropdownMenuPrimitive.SubTrigger
<MenuPrimitive.SubmenuTrigger
ref={ref}
data-slot="dropdown-menu-sub-trigger"
className={cn(
"flex cursor-pointer gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm text-t2 outline-hidden hover:bg-accent focus:bg-accent data-[state=open]:bg-accent [&>svg]:pointer-events-none [&>svg]:size-4 [&>svg]:shrink-0",
"flex cursor-pointer gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm text-t2 outline-hidden hover:bg-accent focus:bg-accent data-popup-open:bg-accent [&>svg]:pointer-events-none [&>svg]:size-4 [&>svg]:shrink-0",
inset && "pl-8",
className,
)}
@@ -127,73 +130,82 @@ const DropdownMenuSubTrigger = React.forwardRef<
>
{children}
{withIcon && <ChevronRight className="ml-auto text-t3" />}
</DropdownMenuPrimitive.SubTrigger>
</MenuPrimitive.SubmenuTrigger>
);
});
// SubContent
const DropdownMenuSubContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>
HTMLDivElement,
MenuPrimitive.Popup.Props & { sideOffset?: number }
>(function DropdownMenuSubContent(props, ref) {
const { className, ...rest } = props;
const { className, sideOffset = 0, ...rest } = props;
return (
<DropdownMenuPrimitive.SubContent
ref={ref}
data-slot="dropdown-menu-sub-content"
className={cn(
"bg-interactive-secondary text-t2 z-[101] min-w-[8rem] overflow-hidden rounded-lg border p-1 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",
className,
)}
{...rest}
/>
<MenuPrimitive.Portal>
<MenuPrimitive.Positioner
sideOffset={sideOffset}
positionMethod="fixed"
className="isolate z-[200]"
>
<MenuPrimitive.Popup
ref={ref}
data-slot="dropdown-menu-sub-content"
className={cn(
"bg-interactive-secondary text-t2 min-w-[8rem] overflow-hidden rounded-lg border p-1 shadow-md",
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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",
className,
)}
{...rest}
/>
</MenuPrimitive.Positioner>
</MenuPrimitive.Portal>
);
});
// Content
type DropdownMenuContentProps = React.ComponentProps<
typeof DropdownMenuPrimitive.Content
> & {
type DropdownMenuContentProps = MenuPrimitive.Popup.Props & {
sideOffset?: number;
side?: "top" | "bottom" | "left" | "right";
align?: "start" | "center" | "end";
onCloseAutoFocus?: (e: any) => void;
};
const DropdownMenuContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
HTMLDivElement,
DropdownMenuContentProps
>(function DropdownMenuContent(props, ref) {
const { className, sideOffset = 4, ...rest } = props;
const { className, sideOffset = 4, side = "bottom", align = "start", onCloseAutoFocus: _onCloseAutoFocus, ...rest } = props;
return (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
ref={ref}
data-slot="dropdown-menu-content"
<MenuPrimitive.Portal>
<MenuPrimitive.Positioner
sideOffset={sideOffset}
onCloseAutoFocus={(e) => e.preventDefault()}
className={cn(
"bg-interactive-secondary text-t2 z-[101] min-w-[8rem] overflow-hidden rounded-lg border p-1 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",
className,
)}
{...rest}
/>
</DropdownMenuPrimitive.Portal>
side={side}
align={align}
positionMethod="fixed"
className="isolate z-[200] outline-none"
>
<MenuPrimitive.Popup
ref={ref}
data-slot="dropdown-menu-content"
className={cn(
"bg-interactive-secondary text-t2 min-w-[8rem] overflow-hidden rounded-lg border p-1 shadow-md",
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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",
className,
)}
{...rest}
/>
</MenuPrimitive.Positioner>
</MenuPrimitive.Portal>
);
});
// Item
type DropdownMenuItemProps = React.ComponentProps<
typeof DropdownMenuPrimitive.Item
> &
type DropdownMenuItemProps = MenuPrimitive.Item.Props &
DropdownMenuItemVariantProps & {
isLoading?: boolean;
shimmer?: boolean;
/** Keyboard shortcut that triggers this item when the menu is open */
shortcut?: string;
};
const DropdownMenuItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
HTMLDivElement,
DropdownMenuItemProps
>(function DropdownMenuItem(props, ref) {
const {
@@ -213,7 +225,7 @@ const DropdownMenuItem = React.forwardRef<
shortcut ?? "",
(e) => {
e.preventDefault();
onClick?.(e as unknown as React.MouseEvent<HTMLDivElement>);
onClick?.(e as any);
},
{
enabled: !!shortcut && isOpen,
@@ -222,9 +234,10 @@ const DropdownMenuItem = React.forwardRef<
);
return (
<DropdownMenuPrimitive.Item
<MenuPrimitive.Item
ref={ref}
data-slot="dropdown-menu-item"
closeOnClick={false}
className={cn(
dropdownMenuItemVariants({ variant, inset }),
shimmer && "shimmer",
@@ -240,85 +253,73 @@ const DropdownMenuItem = React.forwardRef<
<SmallSpinner />
</>
) : (
<>
{children}
{/* {shortcut && (
<span className="ml-auto text-xs tracking-widest text-t4 uppercase">
{shortcut}
</span>
)} */}
</>
children
)}
</DropdownMenuPrimitive.Item>
</MenuPrimitive.Item>
);
});
// CheckboxItem
const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>
HTMLDivElement,
MenuPrimitive.CheckboxItem.Props
>(function DropdownMenuCheckboxItem(props, ref) {
const { className, children, ...rest } = props;
return (
<DropdownMenuPrimitive.CheckboxItem
<MenuPrimitive.CheckboxItem
ref={ref}
data-slot="dropdown-menu-checkbox-item"
className={cn(
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-1 pr-2 text-sm text-t2 outline-hidden transition-colors hover:bg-accent focus:bg-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-1 pr-2 text-sm text-t2 outline-hidden transition-colors hover:bg-accent focus:bg-accent data-disabled:pointer-events-none data-disabled:opacity-50",
className,
)}
{...rest}
>
{children}
<span className="absolute right-2 flex size-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<MenuPrimitive.CheckboxItemIndicator>
<Check className="size-4 text-t3" />
</DropdownMenuPrimitive.ItemIndicator>
</MenuPrimitive.CheckboxItemIndicator>
</span>
</DropdownMenuPrimitive.CheckboxItem>
</MenuPrimitive.CheckboxItem>
);
});
// RadioItem
const DropdownMenuRadioItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>
HTMLDivElement,
MenuPrimitive.RadioItem.Props
>(function DropdownMenuRadioItem(props, ref) {
const { className, children, ...rest } = props;
return (
<DropdownMenuPrimitive.RadioItem
<MenuPrimitive.RadioItem
ref={ref}
data-slot="dropdown-menu-radio-item"
className={cn(
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm text-t2 outline-hidden transition-colors hover:bg-accent focus:bg-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm text-t2 outline-hidden transition-colors hover:bg-accent focus:bg-accent data-disabled:pointer-events-none data-disabled:opacity-50",
className,
)}
{...rest}
>
<span className="absolute left-2 flex size-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<MenuPrimitive.RadioItemIndicator>
<Circle className="size-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</MenuPrimitive.RadioItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
</MenuPrimitive.RadioItem>
);
});
// Label
type DropdownMenuLabelProps = React.ComponentProps<
typeof DropdownMenuPrimitive.Label
> & {
type DropdownMenuLabelProps = MenuPrimitive.GroupLabel.Props & {
inset?: boolean;
};
const DropdownMenuLabel = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
HTMLDivElement,
DropdownMenuLabelProps
>(function DropdownMenuLabel(props, ref) {
const { inset, className, ...rest } = props;
return (
<DropdownMenuPrimitive.Label
<MenuPrimitive.GroupLabel
ref={ref}
data-slot="dropdown-menu-label"
className={cn(
@@ -331,14 +332,13 @@ const DropdownMenuLabel = React.forwardRef<
);
});
// Separator
const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
React.ComponentProps<typeof DropdownMenuPrimitive.Separator>
HTMLDivElement,
MenuPrimitive.Separator.Props
>(function DropdownMenuSeparator(props, ref) {
const { className, ...rest } = props;
return (
<DropdownMenuPrimitive.Separator
<MenuPrimitive.Separator
ref={ref}
data-slot="dropdown-menu-separator"
className={cn("-mx-1 my-1 h-px bg-border", className)}
@@ -347,7 +347,6 @@ const DropdownMenuSeparator = React.forwardRef<
);
});
// Shortcut
type DropdownMenuShortcutProps = React.HTMLAttributes<HTMLSpanElement>;
function DropdownMenuShortcut(props: DropdownMenuShortcutProps) {

View File

@@ -75,7 +75,7 @@ export function FeatureSearchDropdown({
</DropdownMenuTrigger>
<DropdownMenuContent
align="start"
className="w-(--radix-dropdown-menu-trigger-width)"
className="w-(--anchor-width)"
>
<div className="flex items-center gap-2 px-2 py-1.5 border-b border-border">
<MagnifyingGlassIcon className="size-4 text-t4" />

View File

@@ -1,5 +1,6 @@
import { type FrontendProduct, sortPlanItems } from "@autumn/shared";
import { AnimatePresence, motion } from "motion/react";
import { useEffect } from "react";
import { createPortal } from "react-dom";
import { Button } from "@/components/v2/buttons/Button";
import { ShortcutButton } from "@/components/v2/buttons/ShortcutButton";
@@ -29,6 +30,15 @@ export function InlinePlanEditor({
}: InlinePlanEditorProps) {
const mainContent = document.querySelector("[data-main-content]");
useEffect(() => {
if (!(mainContent instanceof HTMLElement) || !isOpen) return;
const previousOverflow = mainContent.style.overflow;
mainContent.style.overflow = "hidden";
return () => {
mainContent.style.overflow = previousOverflow;
};
}, [mainContent, isOpen]);
if (!mainContent) {
console.error("[InlinePlanEditor] Could not find portal target");
return null;

View File

@@ -31,7 +31,13 @@ function AreaRadioGroupItem({
const isDisabled = disabled || !!disabledReason;
const content = (
<div className={cn("flex items-start space-x-[6px]", className)}>
<label
className={cn(
"flex items-start space-x-[6px] cursor-pointer",
isDisabled && "cursor-not-allowed",
className,
)}
>
<RadioGroupItem
value={value}
id={id}
@@ -40,21 +46,20 @@ function AreaRadioGroupItem({
/>
<div className="flex-1 space-y-1">
<div className="flex items-center gap-2">
<label
htmlFor={id}
<span
className={cn(
"text-checkbox-label cursor-pointer",
isDisabled && "cursor-not-allowed opacity-50",
"text-checkbox-label",
isDisabled && "opacity-50",
)}
>
{label}
</label>
</span>
</div>
{description && (
<p className="text-body-sec-paragraph">{description}</p>
)}
</div>
</div>
</label>
);
if (disabledReason) {

View File

@@ -1,14 +1,15 @@
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
import { RadioGroup as RadioGroupPrimitive } from "@base-ui/react/radio-group";
import { Radio } from "@base-ui/react/radio";
import * as React from "react";
import { cn } from "@/lib/utils";
const RadioGroup = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
HTMLDivElement,
RadioGroupPrimitive.Props
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Root
<RadioGroupPrimitive
data-slot="radio-group"
className={cn("grid gap-2", className)}
{...props}
@@ -16,14 +17,14 @@ const RadioGroup = React.forwardRef<
/>
);
});
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
RadioGroup.displayName = "RadioGroup";
const RadioGroupItem = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
HTMLButtonElement,
Radio.Root.Props
>(({ className, style, ...props }, ref) => {
return (
<RadioGroupPrimitive.Item
<Radio.Root
ref={ref}
data-slot="radio-group-item"
style={{ cursor: "pointer", ...style }}
@@ -31,23 +32,22 @@ const RadioGroupItem = React.forwardRef<
"w-[13px] h-[13px] px-0.5 py-[3px] rounded-xl inline-flex flex-col justify-center items-center gap-2.5 overflow-hidden transition-none focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
"bg-interactive-secondary shadow-[0px_2px_4px_0px_rgba(0,0,0,0.02)] border-[0.70px] border",
"data-[state=checked]:bg-violet-600 data-[state=checked]:shadow-none data-[state=checked]:border-none",
"data-checked:bg-violet-600 data-checked:shadow-none data-checked:border-none",
// Custom
"hover:bg-interactive-secondary-hover hover:border-primary hover:border-[1px]",
className,
)}
{...props}
>
<RadioGroupPrimitive.Indicator
<Radio.Indicator
data-slot="radio-group-indicator"
className="flex items-center justify-center"
>
<div className="w-1 h-1 bg-white rounded-full" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
</Radio.Indicator>
</Radio.Root>
);
});
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
RadioGroupItem.displayName = "RadioGroupItem";
export { RadioGroup, RadioGroupItem };

View File

@@ -45,7 +45,7 @@ export const CurrencySelect = ({
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="p-0 w-[var(--radix-popover-trigger-width)]">
<PopoverContent className="p-0 w-[var(--anchor-width)]">
<Command className="p-0">
<CommandInput placeholder="Search currency..." />
<CommandEmpty>No currency found.</CommandEmpty>

View File

@@ -105,7 +105,6 @@ export function RoleSelect({
<SelectItem
key={role}
value={role}
textValue={ROLE_META[role].label}
className="items-start"
>
<div className="flex flex-col items-start py-0.5 gap-0.5 w-full">

View File

@@ -116,10 +116,9 @@ export function SearchableSelect<T>({
<AnimatePresence>
{open && (
<PopoverContent
forceMount
align="start"
className={cn(
"w-(--radix-popover-trigger-width) p-0 z-200 rounded-md overflow-hidden",
"w-(--anchor-width) p-0 z-200 rounded-md overflow-hidden",
contentClassName,
)}
asChild

View File

@@ -1,62 +1,48 @@
"use client";
import * as SelectPrimitive from "@radix-ui/react-select";
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
import * as React from "react";
import { Select as SelectPrimitive } from "@base-ui/react/select";
import { CheckIcon, ChevronDownIcon } from "lucide-react";
import type * as React from "react";
import { cn } from "@/lib/utils";
const SelectContext = React.createContext<{
triggerRef: React.RefObject<HTMLButtonElement>;
} | null>(null);
function Select({
onValueChange,
onOpenChange,
value,
defaultValue,
items,
...props
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
const triggerRef = React.useRef<HTMLButtonElement>(null);
const handleValueChange = (value: string) => {
onValueChange?.(value);
};
const handleOpenChange = (open: boolean) => {
// When dropdown closes, blur the trigger to remove focus ring
if (!open) {
setTimeout(() => {
if (triggerRef.current) {
triggerRef.current.blur();
} else {
// Fallback: blur the active element if ref isn't set
(document.activeElement as HTMLElement)?.blur();
}
}, 0);
}
onOpenChange?.(open);
};
}: Omit<SelectPrimitive.Root.Props<string>, "onValueChange" | "onOpenChange"> & {
onValueChange?: (value: string) => void;
onOpenChange?: (open: boolean) => void;
value?: string;
defaultValue?: string;
items?: Record<string, string> | ReadonlyArray<{ label: string; value: string }>;
}) {
const Root = SelectPrimitive.Root<string>;
return (
<SelectContext.Provider value={{ triggerRef }}>
<SelectPrimitive.Root
data-slot="select"
onValueChange={handleValueChange}
onOpenChange={handleOpenChange}
{...props}
/>
</SelectContext.Provider>
<Root
data-slot="select"
value={value}
defaultValue={defaultValue}
items={items}
onValueChange={onValueChange ? (val) => onValueChange(val as string) : undefined}
onOpenChange={onOpenChange ? (open) => onOpenChange(open) : undefined}
{...props}
/>
);
}
function SelectGroup({
...props
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
}: SelectPrimitive.Group.Props) {
return <SelectPrimitive.Group data-slot="select-group" {...props} />;
}
function SelectValue({
...props
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
}: SelectPrimitive.Value.Props) {
return <SelectPrimitive.Value data-slot="select-value" {...props} />;
}
@@ -65,28 +51,22 @@ function SelectTrigger({
size = "default",
children,
...props
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
}: SelectPrimitive.Trigger.Props & {
size?: "sm" | "default";
}) {
const context = React.useContext(SelectContext);
return (
<SelectPrimitive.Trigger
ref={context?.triggerRef}
data-slot="select-trigger"
data-size={size}
className={cn(
// Essential functionality only - no layout-shifting selectors
"[&_svg:not([class*='text-'])]:text-muted-foreground rounded-lg flex items-center justify-between gap-2 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 cursor-pointer",
// Use only custom styles for visual appearance
`input-base input-shadow-default input-state-open`,
className,
)}
{...props}
>
{children}
<SelectPrimitive.Icon asChild>
<SelectPrimitive.Icon>
<ChevronDownIcon className="size-4 opacity-50" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
@@ -96,43 +76,36 @@ function SelectTrigger({
function SelectContent({
className,
children,
position = "popper",
onEscapeKeyDown,
align = "start",
sideOffset = 4,
side = "bottom",
...props
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
}: SelectPrimitive.Popup.Props & {
align?: "start" | "center" | "end";
sideOffset?: number;
side?: "top" | "bottom" | "left" | "right";
}) {
return (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
data-slot="select-content"
onEscapeKeyDown={(e) => {
// Stop propagation to prevent parent dialogs/sheets from closing
e.stopPropagation();
onEscapeKeyDown?.(e);
}}
className={cn(
// z-[200] to appear above sheets (z-[150])
"bg-interactive-secondary text-popover-foreground relative z-[200] max-h-(--radix-select-content-available-height) min-w-[8rem] overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className,
)}
position={position}
{...props}
<SelectPrimitive.Positioner
align={align}
sideOffset={sideOffset}
side={side}
alignItemWithTrigger={false}
positionMethod="fixed"
className="isolate z-[200]"
>
<SelectScrollUpButton />
<SelectPrimitive.Viewport
<SelectPrimitive.Popup
data-slot="select-content"
className={cn(
"p-1",
position === "popper" &&
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1",
"bg-interactive-secondary text-popover-foreground relative max-h-[var(--available-height)] min-w-[var(--anchor-width)] overflow-x-hidden overflow-y-auto rounded-md border shadow-md p-1",
className,
)}
{...props}
>
{children}
</SelectPrimitive.Viewport>
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPrimitive.Popup>
</SelectPrimitive.Positioner>
</SelectPrimitive.Portal>
);
}
@@ -140,9 +113,9 @@ function SelectContent({
function SelectLabel({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
}: SelectPrimitive.GroupLabel.Props) {
return (
<SelectPrimitive.Label
<SelectPrimitive.GroupLabel
data-slot="select-label"
className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
{...props}
@@ -154,12 +127,12 @@ function SelectItem({
className,
children,
...props
}: React.ComponentProps<typeof SelectPrimitive.Item>) {
}: SelectPrimitive.Item.Props) {
return (
<SelectPrimitive.Item
data-slot="select-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-pointer items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-pointer items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
className,
)}
{...props}
@@ -169,7 +142,7 @@ function SelectItem({
<CheckIcon className="size-4" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
<SelectPrimitive.ItemText className="flex items-center gap-2">{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
);
}
@@ -177,52 +150,19 @@ function SelectItem({
function SelectSeparator({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
}: React.ComponentProps<"div">) {
return (
<SelectPrimitive.Separator
<div
data-slot="select-separator"
className={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
className={cn(
"bg-border pointer-events-none -mx-1 my-1 h-px",
className,
)}
{...props}
/>
);
}
function SelectScrollUpButton({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
return (
<SelectPrimitive.ScrollUpButton
data-slot="select-scroll-up-button"
className={cn(
"flex cursor-default items-center justify-center py-1",
className,
)}
{...props}
>
<ChevronUpIcon className="size-4" />
</SelectPrimitive.ScrollUpButton>
);
}
function SelectScrollDownButton({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
return (
<SelectPrimitive.ScrollDownButton
data-slot="select-scroll-down-button"
className={cn(
"flex cursor-default items-center justify-center py-1",
className,
)}
{...props}
>
<ChevronDownIcon className="size-4" />
</SelectPrimitive.ScrollDownButton>
);
}
export {
Select,
SelectContent,

View File

@@ -97,7 +97,9 @@ export function TagSelect({
)}
</div>
</SelectTrigger>
<SelectContent>{renderContent?.(setOpen)}</SelectContent>
<SelectContent className="w-[var(--anchor-width)] max-w-[var(--anchor-width)]">
{renderContent?.(setOpen)}
</SelectContent>
</Select>
);
}

View File

@@ -1,6 +1,6 @@
"use client";
import * as SeparatorPrimitive from "@radix-ui/react-separator";
import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
import type * as React from "react";
import { cn } from "@/lib/utils";
@@ -10,12 +10,15 @@ function Separator({
orientation = "horizontal",
decorative = true,
...props
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
}: SeparatorPrimitive.Props & {
orientation?: "horizontal" | "vertical";
decorative?: boolean;
}) {
return (
<SeparatorPrimitive.Root
<SeparatorPrimitive
data-slot="separator-root"
decorative={decorative}
orientation={orientation}
data-orientation={orientation}
className={cn(
"shrink-0 data-[orientation=horizontal]:!h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px bg-border atmn-sep",
className,

View File

@@ -1,31 +1,61 @@
"use client";
import * as SheetPrimitive from "@radix-ui/react-dialog";
import { Dialog as SheetPrimitive } from "@base-ui/react/dialog";
import { XIcon } from "lucide-react";
import type * as React from "react";
import * as React from "react";
import { cn } from "@/lib/utils";
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
function Sheet({ ...props }: SheetPrimitive.Root.Props) {
return <SheetPrimitive.Root data-slot="sheet" {...props} />;
}
function SheetTrigger({
asChild,
children,
...props
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
}: SheetPrimitive.Trigger.Props & { asChild?: boolean }) {
if (asChild && React.isValidElement(children)) {
return (
<SheetPrimitive.Trigger
data-slot="sheet-trigger"
render={children}
{...props}
/>
);
}
return (
<SheetPrimitive.Trigger data-slot="sheet-trigger" {...props}>
{children}
</SheetPrimitive.Trigger>
);
}
function SheetClose({
asChild,
children,
...props
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />;
}: SheetPrimitive.Close.Props & { asChild?: boolean }) {
if (asChild && React.isValidElement(children)) {
return (
<SheetPrimitive.Close
data-slot="sheet-close"
render={children}
{...props}
/>
);
}
return (
<SheetPrimitive.Close data-slot="sheet-close" {...props}>
{children}
</SheetPrimitive.Close>
);
}
function SheetPortal({
container,
...props
}: React.ComponentProps<typeof SheetPrimitive.Portal> & {
}: SheetPrimitive.Portal.Props & {
container?: HTMLElement | null;
}) {
const resolvedContainer =
@@ -33,7 +63,7 @@ function SheetPortal({
return (
<SheetPrimitive.Portal
data-slot="sheet-portal"
container={resolvedContainer ?? undefined}
container={resolvedContainer as HTMLElement | undefined}
{...props}
/>
);
@@ -42,12 +72,12 @@ function SheetPortal({
function SheetOverlay({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
}: SheetPrimitive.Backdrop.Props) {
return (
<SheetPrimitive.Overlay
<SheetPrimitive.Backdrop
data-slot="sheet-overlay"
className={cn(
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-[150] bg-white/70 dark:bg-black/70",
"fixed inset-0 z-[150] bg-white/70 dark:bg-black/70 transition-opacity duration-300 data-[starting-style]:opacity-0 data-[ending-style]:opacity-0",
className,
)}
{...props}
@@ -55,6 +85,13 @@ function SheetOverlay({
);
}
const SIDE_STYLES = {
right: "top-0 bottom-0 right-0 w-full md:min-w-xs md:max-w-md md:border-l border-border/40 translate-x-0 data-[starting-style]:translate-x-full data-[ending-style]:translate-x-full",
left: "top-0 bottom-0 left-0 w-3/4 border-r border-border/40 sm:max-w-sm translate-x-0 data-[starting-style]:-translate-x-full data-[ending-style]:-translate-x-full",
top: "left-0 right-0 top-0 h-auto border-b border-border/40 translate-y-0 data-[starting-style]:-translate-y-full data-[ending-style]:-translate-y-full",
bottom: "left-0 right-0 bottom-0 h-auto border-t border-border/40 translate-y-0 data-[starting-style]:translate-y-full data-[ending-style]:translate-y-full",
} as const;
function SheetContent({
className,
children,
@@ -62,7 +99,7 @@ function SheetContent({
hideCloseButton = false,
portalContainer,
...props
}: React.ComponentProps<typeof SheetPrimitive.Content> & {
}: SheetPrimitive.Popup.Props & {
side?: "top" | "right" | "bottom" | "left";
hideCloseButton?: boolean;
portalContainer?: HTMLElement | null;
@@ -70,30 +107,23 @@ function SheetContent({
return (
<SheetPortal container={portalContainer}>
<SheetOverlay />
<SheetPrimitive.Content
<SheetPrimitive.Popup
data-slot="sheet-content"
className={cn(
"bg-card data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-[150] flex flex-col gap-0 shadow-sm transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-300",
side === "right" &&
`data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right top-0 bottom-0 right-0 w-full md:min-w-xs md:max-w-md md:border-l border-border/40`,
side === "left" &&
`data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left top-0 bottom-0 left-0 w-3/4 border-r border-border/40 sm:max-w-sm`,
side === "top" &&
"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top left-0 right-0 top-0 h-auto border-b border-border/40",
side === "bottom" &&
"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom left-0 right-0 bottom-0 h-auto border-t border-border/40",
"bg-card fixed z-[150] flex flex-col gap-0 shadow-sm overflow-hidden transition-transform duration-300 ease-in-out",
SIDE_STYLES[side],
className,
)}
{...props}
>
{children}
{!hideCloseButton && (
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-3 right-3 md:top-4 md:right-4 flex items-center justify-center size-10 md:size-auto rounded-sm md:rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-open:bg-secondary absolute top-3 right-3 md:top-4 md:right-4 flex items-center justify-center size-10 md:size-auto rounded-sm md:rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
<XIcon className="size-5 md:size-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
)}
</SheetPrimitive.Content>
</SheetPrimitive.Popup>
</SheetPortal>
);
}
@@ -121,7 +151,7 @@ function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
function SheetTitle({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Title>) {
}: SheetPrimitive.Title.Props) {
return (
<SheetPrimitive.Title
data-slot="sheet-title"
@@ -134,7 +164,7 @@ function SheetTitle({
function SheetDescription({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Description>) {
}: SheetPrimitive.Description.Props) {
return (
<SheetPrimitive.Description
data-slot="sheet-description"

View File

@@ -1,6 +1,6 @@
"use client";
import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion";
import { ChevronDownIcon } from "lucide-react";
import type * as React from "react";
import { Separator } from "@/components/v2/separator";
@@ -22,13 +22,12 @@ function SheetAccordion({
collapsible = true,
...props
}: SheetAccordionProps &
Omit<React.ComponentProps<typeof AccordionPrimitive.Root>, "type">) {
Omit<AccordionPrimitive.Root.Props, "type">) {
return (
<>
<AccordionPrimitive.Root
type={type as any}
defaultValue={defaultValue}
collapsible={collapsible}
multiple={type === "multiple"}
defaultValue={defaultValue as any}
className="w-full"
{...props}
>
@@ -61,7 +60,7 @@ function SheetAccordionItem({
return (
<AccordionPrimitive.Item value={value} className={cn("", className)}>
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger className="flex flex-1 items-start justify-between gap-4 px-4 py-3 text-left transition-all outline-none focus-visible:ring-2 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180 hover:bg-accent/50">
<AccordionPrimitive.Trigger className="flex flex-1 items-start justify-between gap-4 px-4 py-3 text-left transition-all outline-none focus-visible:ring-2 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&[aria-expanded=true]>svg]:rotate-180 hover:bg-accent/50">
<div className="flex flex-col gap-1">
<h3 className="text-sm font-medium">{title}</h3>
{description && (
@@ -71,9 +70,9 @@ function SheetAccordionItem({
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
<AccordionPrimitive.Content className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden">
<AccordionPrimitive.Panel className="data-closed:animate-accordion-up data-open:animate-accordion-down overflow-hidden">
<div className="px-4 pb-4 pt-2">{children}</div>
</AccordionPrimitive.Content>
</AccordionPrimitive.Panel>
</AccordionPrimitive.Item>
);
}

View File

@@ -1,56 +1,84 @@
"use client";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import type * as React from "react";
import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
import * as React from "react";
import { cn } from "@/lib/utils";
function TooltipProvider({
delayDuration = 0,
delay = 0,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
}: TooltipPrimitive.Provider.Props) {
return (
<TooltipPrimitive.Provider
data-slot="tooltip-provider"
delayDuration={delayDuration}
delay={delay}
{...props}
/>
);
}
function Tooltip({
delayDuration,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
}: TooltipPrimitive.Root.Props & { delayDuration?: number }) {
return (
<TooltipProvider>
<TooltipProvider delay={delayDuration}>
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
</TooltipProvider>
);
}
function TooltipTrigger({
asChild,
children,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
}: TooltipPrimitive.Trigger.Props & { asChild?: boolean }) {
if (asChild && React.isValidElement(children)) {
return (
<TooltipPrimitive.Trigger
data-slot="tooltip-trigger"
render={children}
{...props}
/>
);
}
return (
<TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props}>
{children}
</TooltipPrimitive.Trigger>
);
}
function TooltipContent({
className,
sideOffset = 6,
side = "top",
align = "center",
children,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
}: TooltipPrimitive.Popup.Props &
Pick<
TooltipPrimitive.Positioner.Props,
"align" | "side" | "sideOffset"
>) {
return (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
data-slot="tooltip-content"
<TooltipPrimitive.Positioner
side={side}
sideOffset={sideOffset}
className={cn(
`z-[200] overflow-hidden rounded-[6px] px-2 py-[3px] text-t2 border
align={align}
positionMethod="fixed"
className="isolate z-[200]"
>
<TooltipPrimitive.Popup
data-slot="tooltip-content"
className={cn(
`overflow-hidden rounded-[6px] px-2 py-[3px] text-t2 border
bg-interactive-secondary dark:bg-card
text-[13px] font-medium leading-[1.6] tracking-[-0.039px]
shadow-[0px_0px_4px_2px_rgba(0,0,0,0.05)]
animate-in fade-in-0 zoom-in-95
data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95
data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-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
@@ -69,12 +97,13 @@ function TooltipContent({
before:data-[side=right]:border-t-[7px] before:data-[side=right]:border-b-[7px] before:data-[side=right]:border-r-[6px]
before:data-[side=right]:border-t-transparent before:data-[side=right]:border-b-transparent before:data-[side=right]:border-r-t12
`,
className,
)}
{...props}
>
{children}
</TooltipPrimitive.Content>
className,
)}
{...props}
>
{children}
</TooltipPrimitive.Popup>
</TooltipPrimitive.Positioner>
</TooltipPrimitive.Portal>
);
}

View File

@@ -0,0 +1,37 @@
import { useCallback, useRef, useState } from "react";
type UseControllableStateParams<T> = {
prop?: T;
defaultProp?: T;
onChange?: (value: T) => void;
};
/**
* Manages state that can be either controlled or uncontrolled.
* Replacement for @radix-ui/react-use-controllable-state.
*/
function useControllableState<T>({
prop,
defaultProp,
onChange,
}: UseControllableStateParams<T>): [T | undefined, (value: T) => void] {
const [uncontrolled, setUncontrolled] = useState(defaultProp);
const isControlled = prop !== undefined;
const value = isControlled ? prop : uncontrolled;
const onChangeRef = useRef(onChange);
onChangeRef.current = onChange;
const setValue = useCallback(
(nextValue: T) => {
if (!isControlled) {
setUncontrolled(nextValue);
}
onChangeRef.current?.(nextValue);
},
[isControlled],
);
return [value, setValue];
}
export { useControllableState };

View File

@@ -368,13 +368,13 @@ html {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
height: var(--accordion-panel-height);
}
}
@keyframes accordion-up {
from {
height: var(--radix-accordion-content-height);
height: var(--accordion-panel-height);
}
to {
height: 0;
@@ -412,6 +412,7 @@ input[type="number"]::-webkit-inner-spin-button {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
letter-spacing: -0.033px;

View File

@@ -136,10 +136,11 @@ export function RedisV2CacheDialog({
<div className="text-xs font-medium uppercase tracking-wide text-t3">
Active Instance
</div>
<Select
value={selected}
onValueChange={(value) => setSelected(value as InstanceName)}
>
<Select
value={selected}
onValueChange={(value) => setSelected(value as InstanceName)}
items={Object.fromEntries(INSTANCE_OPTIONS.map((option) => [option.value, option.label]))}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>

View File

@@ -225,11 +225,12 @@ export function BalanceCreateSheet() {
<div>
<FormLabel>Interval</FormLabel>
<div className="flex items-center gap-2">
<Select
value={oneOff ? undefined : resetInterval}
onValueChange={setResetInterval}
disabled={oneOff}
>
<Select
value={oneOff ? undefined : resetInterval}
onValueChange={setResetInterval}
disabled={oneOff}
items={RESET_INTERVAL_LABELS}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="None" />
</SelectTrigger>

View File

@@ -365,10 +365,14 @@ export function BillingAutoTopupSheet() {
<div className="flex flex-col gap-3">
<div>
<FormLabel>Interval</FormLabel>
<Select
value={purchaseLimitInterval}
onValueChange={setPurchaseLimitInterval}
>
<Select
value={purchaseLimitInterval}
onValueChange={setPurchaseLimitInterval}
items={Object.fromEntries(Object.entries(INTERVAL_LABELS).map(([value, label]) => {
const count = Number.parseInt(purchaseLimitIntervalCount, 10);
return [value, count > 1 ? `Every ${count} ${label.toLowerCase()}s` : label];
}))}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select interval" />
</SelectTrigger>

View File

@@ -270,7 +270,7 @@ export function BillingUsageAlertSheet() {
<div>
<FormLabel>Threshold type</FormLabel>
<Select value={thresholdType} onValueChange={setThresholdType}>
<Select value={thresholdType} onValueChange={setThresholdType} items={{ usage: "Usage (absolute value)", usage_percentage: "Percentage used of allowance", remaining: "Remaining (absolute value)", remaining_percentage: "Percentage remaining of allowance" }}>
<SelectTrigger className="w-full">
<SelectValue />
</SelectTrigger>

View File

@@ -484,7 +484,7 @@ function LineItemGroupRow({
const paidAmount = firstItem.amount_after_discounts ?? firstItem.amount;
return (
<AdminHover asChild texts={getLineItemHoverTexts(firstItem)}>
<AdminHover texts={getLineItemHoverTexts(firstItem)}>
<div className="flex flex-col py-1">
<div className="flex items-start justify-between gap-2">
<div className="flex flex-col min-w-0 flex-1 gap-0.5">
@@ -563,7 +563,7 @@ function TierRow({
const isRefund = item.direction === "refund";
return (
<AdminHover asChild texts={hoverTexts}>
<AdminHover texts={hoverTexts}>
<div className="flex items-center justify-between text-xs text-t3">
<span>{item.description}</span>
<span

View File

@@ -72,7 +72,7 @@ export const getCustomerInvoicesColumns = ({
cell: ({ row }: { row: Row<CustomerInvoice> }) => {
return (
<div className="min-w-0 max-w-full" title={row.original.productNames}>
<AdminHover asChild texts={getInvoiceHoverTexts({ invoice: row.original })}>
<AdminHover texts={getInvoiceHoverTexts({ invoice: row.original })}>
<span className="block max-w-full truncate">
{row.original.productNames}
</span>

View File

@@ -43,19 +43,17 @@ export function CustomerListFilterButton() {
return (
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger asChild>
<div className="relative">
<IconButton
variant="secondary"
className={cn("gap-2", open && "btn-secondary-active")}
icon={<FunnelSimpleIcon size={14} className="text-t3" />}
>
Filter
</IconButton>
{hasActiveFilters && (
<span className="absolute top-0 right-0 h-2.5 w-2.5 translate-x-1/3 -translate-y-1/3 rounded-full bg-primary" />
)}
</div>
<DropdownMenuTrigger render={<div className="relative" />} nativeButton={false}>
<IconButton
variant="secondary"
className={cn("gap-2", open && "btn-secondary-active")}
icon={<FunnelSimpleIcon size={14} className="text-t3" />}
>
Filter
</IconButton>
{hasActiveFilters && (
<span className="absolute top-0 right-0 h-2.5 w-2.5 translate-x-1/3 -translate-y-1/3 rounded-full bg-primary" />
)}
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-56 font-regular gap-0 p-0"

View File

@@ -92,6 +92,7 @@ export function CustomerListPageSizeSelector() {
page: 1,
});
}}
items={Object.fromEntries(PAGE_SIZE_OPTIONS.map((size) => [size.toString(), size.toString()]))}
>
<SelectTrigger className="h-7 w-fit px-2 text-xs">
<SelectValue />

View File

@@ -104,7 +104,14 @@ export const TransferProductDialog = ({
: "Transfer this plan to an entity."}
</p>
<Select value={selectedValue} onValueChange={setSelectedValue}>
<Select
value={selectedValue}
onValueChange={setSelectedValue}
items={{
...(isOnEntity ? { [CUSTOMER_LEVEL_VALUE]: "Move to Customer" } : {}),
...Object.fromEntries(filteredEntities.map((entity: Entity) => [entity.id, entity.name || entity.id || entity.internal_id])),
}}
>
<SelectTrigger>
<SelectValue placeholder="Select destination" />
</SelectTrigger>

View File

@@ -113,19 +113,20 @@ export const AddCouponDialog = ({
</InfoBox>
)}
<div className="space-y-3">
<Select
value={couponSelected?.internal_id}
onValueChange={(value) => {
const coupon = rewards.find(
(c: Reward) => c.internal_id === value,
);
<Select
value={couponSelected?.internal_id}
onValueChange={(value) => {
const coupon = rewards.find(
(c: Reward) => c.internal_id === value,
);
if (!coupon) return;
if (!coupon) return;
setCouponSelected(coupon);
setPromoCodeSelected(null);
}}
>
setCouponSelected(coupon);
setPromoCodeSelected(null);
}}
items={Object.fromEntries(rewards.filter((c: Reward) => c.type !== RewardType.FreeProduct).map((c: Reward) => [c.internal_id, c.name]))}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select Reward" />
</SelectTrigger>
@@ -151,10 +152,11 @@ export const AddCouponDialog = ({
</Select>
{couponSelected?.type === RewardType.FeatureGrant && (
<Select
value={promoCodeSelected || undefined}
onValueChange={setPromoCodeSelected}
>
<Select
value={promoCodeSelected || undefined}
onValueChange={setPromoCodeSelected}
items={Object.fromEntries(promoCodeOptions.map((promoCode) => [promoCode.code, promoCode.code]))}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select Promo Code" />
</SelectTrigger>

View File

@@ -131,12 +131,13 @@ export const CreateEntity = ({
</div>
<div>
<div className="text-form-label block mb-1">Feature ID</div>
<Select
value={entity.feature_id}
onValueChange={(value) =>
setEntity({ ...entity, feature_id: value })
}
>
<Select
value={entity.feature_id}
onValueChange={(value) =>
setEntity({ ...entity, feature_id: value })
}
items={Object.fromEntries(continuousFeatures.map((feature: Feature) => [feature.id, feature.name]))}
>
<SelectTrigger>
<SelectValue placeholder="Select feature" />
</SelectTrigger>

View File

@@ -106,14 +106,15 @@ const MappingRow = memo(function MappingRow({
an existing mapping to change assignments.
</div>
) : (
<Select
value=""
onValueChange={(value) => {
if (value) {
onAddProduct(mapping.autumnProductId, value);
}
}}
>
<Select
value=""
onValueChange={(value) => {
if (value) {
onAddProduct(mapping.autumnProductId, value);
}
}}
items={Object.fromEntries(availableProducts.map((product) => [product.id, product.name]))}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Add product..." />
</SelectTrigger>

View File

@@ -333,7 +333,7 @@ export const ConfigureVercel = () => {
}}
>
<div className="flex items-center justify-between w-full">
<span className="truncate">{option.label}</span>
<span className="truncate max-w-full">{option.label}</span>
</div>
</div>
);

View File

@@ -45,16 +45,14 @@ export const CollapsibleNavGroup = ({
if (!expanded) {
return (
<DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>
<DropdownMenuTrigger asChild>
<div>
<NavButton
value={value}
icon={icon}
title={title}
env={env}
isGroup
/>
</div>
<DropdownMenuTrigger render={<div />} nativeButton={false}>
<NavButton
value={value}
icon={icon}
title={title}
env={env}
isGroup
/>
</DropdownMenuTrigger>
<DropdownMenuContent
side="right"

View File

@@ -22,16 +22,14 @@ export function SidebarContact() {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<div>
<NavButton
env={env}
value="chat"
icon={<QuestionIcon size={16} weight="duotone" />}
title="Need help?"
onClick={() => {}}
/>
</div>
<DropdownMenuTrigger render={<div />} nativeButton={false}>
<NavButton
env={env}
value="chat"
icon={<QuestionIcon size={16} weight="duotone" />}
title="Need help?"
onClick={() => {}}
/>
</DropdownMenuTrigger>
<DropdownMenuContent side="top" align="start">
<span className="text-xs text-t3 p-2">

View File

@@ -9,7 +9,6 @@ import {
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/v2/dialogs/Dialog";
import { Input } from "@/components/v2/inputs/Input";
import { useOrg } from "@/hooks/common/useOrg";
@@ -64,7 +63,6 @@ export const CreateNewOrg = ({
if (!open) setDialogType(null);
}}
>
<DialogTrigger asChild></DialogTrigger>
<DialogContent className="gap-0 p-0 rounded-xs min-w-[400px]">
<div className="p-6 flex flex-col gap-4">
<DialogHeader>

View File

@@ -5,7 +5,6 @@ import {
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/v2/dialogs/Dialog";
import { InvitePopover } from "../org-dropdown/manage-org/InvitePopover";
import { OrgInvitesList } from "../org-dropdown/manage-org/OrgInvitesList";
@@ -29,7 +28,6 @@ export const ManageOrg = ({
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild></DialogTrigger>
<DialogContent className="gap-0 p-0 rounded-xs w-[90%] max-w-[750px] h-[550px] flex flex-col justify-between">
<div className="flex flex-col gap-6 overflow-hidden h-full">
<DialogHeader className="px-6 pt-6">

View File

@@ -1,4 +1,4 @@
import { DropdownMenuGroup } from "@radix-ui/react-dropdown-menu";
import { DropdownMenuGroup } from "@/components/v2/dropdowns/DropdownMenu";
import { useQueryClient } from "@tanstack/react-query";
import {
ChevronDown,
@@ -49,10 +49,10 @@ export const OrgDropdown = () => {
const { expanded, setExpanded } = useSidebarContext();
const { theme, setTheme } = useTheme();
let { data: orgs } = useListOrganizations();
const { data: orgsData } = useListOrganizations();
let orgs = Array.isArray(orgsData) ? orgsData : undefined;
const { data: activeOrganization } = authClient.useActiveOrganization();
// Exclude the active organization from the orgs list (this makes it easier for users to understand which org is active)
if (activeOrganization && orgs) {
orgs = orgs.filter((o) => o.id !== activeOrganization.id);
}

View File

@@ -50,24 +50,21 @@ export function FeatureSelectDropdown({
}
}}
>
<DropdownMenuTrigger asChild>
<button
type="button"
className={cn(
"flex items-center justify-between w-full rounded-lg border bg-transparent text-sm outline-none h-input input-base input-shadow-default input-state-open p-2",
)}
>
{selectedFeature ? (
<span className="truncate">{selectedFeature.name}</span>
) : (
<span className="text-t4">Select feature</span>
)}
<CaretDownIcon className="size-4 opacity-50 shrink-0" />
</button>
<DropdownMenuTrigger
className={cn(
"flex items-center justify-between w-full rounded-lg border bg-transparent text-sm outline-none h-input input-base input-shadow-default input-state-open p-2",
)}
>
{selectedFeature ? (
<span className="truncate">{selectedFeature.name}</span>
) : (
<span className="text-t4">Select feature</span>
)}
<CaretDownIcon className="size-4 opacity-50 shrink-0" />
</DropdownMenuTrigger>
<DropdownMenuContent
align="start"
className="min-w-[var(--radix-dropdown-menu-trigger-width)] z-200"
className="min-w-[var(--anchor-width)] z-200"
onCloseAutoFocus={(e) => e.preventDefault()}
>
{showCreateForm ? (

View File

@@ -228,10 +228,11 @@ export const DeletePlanDialog = ({
{productInfo.numVersion > 1 &&
!product.archived &&
!productInfo.hasCusProductsLatest && (
<Select
value={deleteAllVersions ? "all" : "latest"}
onValueChange={(value) => setDeleteAllVersions(value === "all")}
>
<Select
value={deleteAllVersions ? "all" : "latest"}
onValueChange={(value) => setDeleteAllVersions(value === "all")}
items={{ latest: "Delete latest version", all: "Archive plan" }}
>
<SelectTrigger className="w-6/12">
<SelectValue placeholder="Select a version" />
</SelectTrigger>

View File

@@ -241,10 +241,11 @@ export const EditPlanHeader = () => {
)}
{numVersions && numVersions > 1 && (
<Select
value={currentVersion.toString()}
onValueChange={handleVersionChange}
>
<Select
value={currentVersion.toString()}
onValueChange={handleVersionChange}
items={Object.fromEntries(versionOptions.map((version) => [version.toString(), `Version ${version}`]))}
>
<SelectTrigger className="w-fit min-w-28 !h-6" size="sm">
<SelectValue placeholder="Version" />
</SelectTrigger>

View File

@@ -13,7 +13,7 @@ export function EditPlanPriceSheet({
if (!product) return null;
return (
<div className="h-full overflow-y-auto [scrollbar-gutter:stable]">
<div className="h-full overflow-y-auto overscroll-none [scrollbar-gutter:stable]">
{!isOnboarding && (
<SheetHeader
title={`Configure ${product.name ? `${product.name} ` : ""}Price`}

View File

@@ -25,7 +25,7 @@ export function EditPlanSheet({ isOnboarding }: { isOnboarding?: boolean }) {
product.basePriceType !== "usage";
return (
<div className="h-full overflow-y-auto [scrollbar-gutter:stable]">
<div className="h-full overflow-y-auto overscroll-none [scrollbar-gutter:stable]">
{!isOnboarding && (
<SheetHeader
title={`Configure ${product.name ? product.name : "your new plan"}`}

View File

@@ -53,21 +53,22 @@ export const FreeTrialSection = () => {
placeholder="eg. 7"
/>
{/* <FormLabel disabled={!product.free_trial}>Duration</FormLabel> */}
<Select
disabled={!product.free_trial}
value={product.free_trial?.duration || ""}
onValueChange={(value) => {
setProduct({
...product,
free_trial: product.free_trial
? {
...product.free_trial,
duration: value as FreeTrialDuration,
}
: null,
});
}}
>
<Select
disabled={!product.free_trial}
value={product.free_trial?.duration || ""}
onValueChange={(value) => {
setProduct({
...product,
free_trial: product.free_trial
? {
...product.free_trial,
duration: value as FreeTrialDuration,
}
: null,
});
}}
items={Object.fromEntries(Object.values(FreeTrialDuration).map((duration) => [duration, `${duration}s`]))}
>
<SelectTrigger className="w-full max-w-32">
<SelectValue placeholder="days" />{" "}
</SelectTrigger>

View File

@@ -30,20 +30,25 @@ export const SelectBillingCycle = ({
return (
<div className="w-full">
<FormLabel disabled={disabled}>Billing Interval</FormLabel>
<Select
disabled={disabled}
value={item ? itemToBillingInterval({ item }) : BillingInterval.Month}
defaultValue={BillingInterval.Month}
onValueChange={(value) => {
if (!item) return;
setItem({
...item,
interval: billingToItemInterval({
billingInterval: value as BillingInterval,
}),
});
}}
>
<Select
disabled={disabled}
value={item ? itemToBillingInterval({ item }) : BillingInterval.Month}
defaultValue={BillingInterval.Month}
onValueChange={(value) => {
if (!item) return;
setItem({
...item,
interval: billingToItemInterval({
billingInterval: value as BillingInterval,
}),
});
}}
items={Object.fromEntries(
Object.values(BillingInterval)
.filter((interval) => !filterOneOff || interval !== BillingInterval.OneOff)
.map((interval) => [interval, formatIntervalText({ billingInterval: interval, intervalCount: item?.interval_count || 1, isBillingInterval: true })])
)}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select interval" />
</SelectTrigger>

View File

@@ -129,7 +129,7 @@ export function EditPlanFeatureSheet({
return (
<div className="flex flex-col h-full overflow-hidden">
{/* Scrollable content area */}
<div className="flex-1 overflow-y-auto [scrollbar-gutter:stable]">
<div className="flex-1 overflow-y-auto overscroll-none [scrollbar-gutter:stable]">
{!isOnboarding && (
<SheetHeader
title={`Configure ${feature?.name}`}

View File

@@ -61,7 +61,7 @@ export function PriceSectionTitle({
</IconCheckbox>
</div>
)}
<Select value={tierBehavior} onValueChange={onTierBehaviorChange}>
<Select value={tierBehavior} onValueChange={onTierBehaviorChange} items={{ [TierBehavior.Graduated]: "Graduated", [TierBehavior.VolumeBased]: "Volume-based" }}>
<SelectTrigger className="w-32 h-6 text-xs!" size="sm">
<SelectValue>
{tierBehavior === TierBehavior.VolumeBased ? (

View File

@@ -95,11 +95,12 @@ export function UsageReset({ showBillingLabel = false }: UsageResetProps) {
<div className={showBillingLabel ? "mt-3" : ""}>
<FormLabel>Interval</FormLabel>
<div className="flex items-center gap-2">
<Select
value={isSelectDisabled ? undefined : intervalValue}
onValueChange={handleIntervalChange}
disabled={isSelectDisabled}
>
<Select
value={isSelectDisabled ? undefined : intervalValue}
onValueChange={handleIntervalChange}
disabled={isSelectDisabled}
items={Object.fromEntries(availableIntervals.map((interval) => [interval, formatIntervalText({ billingInterval: interval, intervalCount: item.interval_count || undefined, isBillingInterval: true })]))}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="None" />
</SelectTrigger>

View File

@@ -43,15 +43,16 @@ export function EntityFeatureConfig() {
<FormLabel>
Link this item to a specific feature entity in your app
</FormLabel>
<Select
value={item.entity_feature_id || undefined}
onValueChange={(value) => {
setItem({
...item,
entity_feature_id: value,
});
}}
>
<Select
value={item.entity_feature_id || undefined}
onValueChange={(value) => {
setItem({
...item,
entity_feature_id: value,
});
}}
items={Object.fromEntries(continuousUseFeatures.map((feature) => [feature.id, feature.name]))}
>
<SelectTrigger
className="w-xs max-w-full"
onClick={(e) => e.stopPropagation()}

View File

@@ -101,15 +101,16 @@ export function ProrationConfig() {
<div className="space-y-4 w-xs max-w-full">
<div className="space-y-2 w-full">
<FormLabel>{increaseText}</FormLabel>
<Select
value={onIncreaseValue}
onValueChange={(value) => {
setItem({
...item,
config: { ...item.config, on_increase: value as OnIncrease },
});
}}
>
<Select
value={onIncreaseValue}
onValueChange={(value) => {
setItem({
...item,
config: { ...item.config, on_increase: value as OnIncrease },
});
}}
items={Object.fromEntries(onIncreaseOptions.map((option) => [option, getOnIncreaseText(option)]))}
>
<SelectTrigger
className="w-full [&>span]:truncate"
onClick={(e) => e.stopPropagation()}
@@ -128,15 +129,16 @@ export function ProrationConfig() {
<div className="space-y-2 w-full">
<FormLabel>{decreaseText}</FormLabel>
<Select
value={onDecreaseValue}
onValueChange={(value) => {
setItem({
...item,
config: { ...item.config, on_decrease: value as OnDecrease },
});
}}
>
<Select
value={onDecreaseValue}
onValueChange={(value) => {
setItem({
...item,
config: { ...item.config, on_decrease: value as OnDecrease },
});
}}
items={Object.fromEntries([OnDecrease.Prorate, OnDecrease.None].map((option) => [option, getOnDecreaseText({ option, usageModel: item.usage_model ?? UsageModel.Prepaid })]))}
>
<SelectTrigger
className="w-full [&>span]:truncate"
onClick={(e) => e.stopPropagation()}

View File

@@ -95,10 +95,11 @@ export function RolloverConfigForm({
<div className="space-y-2 w-full">
<FormLabel>Maximum rollover</FormLabel>
<div className="flex items-center gap-2">
<Select
value={maxMode}
onValueChange={(v) => handleMaxModeChange(v as MaxMode)}
>
<Select
value={maxMode}
onValueChange={(v) => handleMaxModeChange(v as MaxMode)}
items={{ unlimited: "Unlimited", absolute: "Absolute", percentage: "Percentage" }}
>
<SelectTrigger
className="w-32"
onClick={(e) => e.stopPropagation()}
@@ -170,15 +171,16 @@ export function RolloverConfigForm({
onClick={(e) => e.stopPropagation()}
/>
)}
<Select
value={rollover?.duration}
onValueChange={(v) => {
setRolloverConfigKey(
"duration",
v as RolloverExpiryDurationType,
);
}}
>
<Select
value={rollover?.duration}
onValueChange={(v) => {
setRolloverConfigKey(
"duration",
v as RolloverExpiryDurationType,
);
}}
items={Object.fromEntries(Object.values(RolloverExpiryDurationType).map((duration) => [duration, duration]))}
>
<SelectTrigger
className="flex-1"
onClick={(e) => e.stopPropagation()}

View File

@@ -8,7 +8,6 @@ import {
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/v2/dialogs/Dialog";
import { Input } from "@/components/v2/inputs/Input";
import { useProductsQuery } from "@/hooks/queries/useProductsQuery";
@@ -58,7 +57,6 @@ export default function ConfirmNewVersionDialog({
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild></DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Create new version?</DialogTitle>

View File

@@ -128,10 +128,11 @@ export const CopyProductDialog = ({
{!targetEnv && (
<div>
<FormLabel>Copy to environment</FormLabel>
<Select
value={toEnv}
onValueChange={(value) => setToEnv(value as AppEnv)}
>
<Select
value={toEnv}
onValueChange={(value) => setToEnv(value as AppEnv)}
items={{ [AppEnv.Live]: "Production", [AppEnv.Sandbox]: "Sandbox" }}
>
<SelectTrigger className="w-5/12">
<SelectValue placeholder="Select environment" />
</SelectTrigger>

View File

@@ -51,6 +51,11 @@ export function DiscountRewardConfig({
onValueChange={(value) =>
setReward({ ...reward, discountType: value as any })
}
items={{
percentage: "Percentage",
fixed: "Fixed",
...(reward.discountType === "invoice_credits" && { invoice_credits: "Invoice Credits" }),
}}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select discount type" />
@@ -134,6 +139,11 @@ export function DiscountRewardConfig({
onValueChange={(value) =>
setConfig("duration_type", value as CouponDurationType)
}
items={{
[CouponDurationType.OneOff]: "One-off",
[CouponDurationType.Months]: "Months",
[CouponDurationType.Forever]: "Forever",
}}
>
<SelectTrigger className="flex-1">
<SelectValue placeholder="Select duration" />

View File

@@ -323,20 +323,21 @@ export function FeatureGrantRewardConfig({
placeholder="30"
className="w-20"
/>
<Select
value={ent.expiry.duration}
onValueChange={(value) =>
updateEntitlement({
index,
updates: {
expiry: {
duration: value as EntitlementDuration,
length: ent.expiry?.length ?? 1,
},
<Select
value={ent.expiry.duration}
onValueChange={(value) =>
updateEntitlement({
index,
updates: {
expiry: {
duration: value as EntitlementDuration,
length: ent.expiry?.length ?? 1,
},
})
}
>
},
})
}
items={{ [EntitlementDuration.Day]: "Day(s)", [EntitlementDuration.Week]: "Week(s)", [EntitlementDuration.Month]: "Month(s)", [EntitlementDuration.Year]: "Year(s)" }}
>
<SelectTrigger className="flex-1">
<SelectValue />
</SelectTrigger>

View File

@@ -34,13 +34,14 @@ export function FreeProductRewardConfig({
{/* Product Selection */}
<div>
<FormLabel>Plan</FormLabel>
<Select
value={reward.free_product_id || undefined}
onValueChange={(value) =>
setReward({ ...reward, free_product_id: value })
}
disabled={isEmpty}
>
<Select
value={reward.free_product_id || undefined}
onValueChange={(value) =>
setReward({ ...reward, free_product_id: value })
}
disabled={isEmpty}
items={Object.fromEntries(freeAddOns.map((product: ProductV2) => [product.id, product.name]))}
>
<SelectTrigger>
<SelectValue
placeholder={

View File

@@ -62,12 +62,13 @@ export const RewardProgramConfig = ({
</div>
<div className="w-full">
<FieldLabel>Reward</FieldLabel>
<Select
value={rewardProgram.internal_reward_id}
onValueChange={(value) =>
setRewardProgram({ ...rewardProgram, internal_reward_id: value })
}
>
<Select
value={rewardProgram.internal_reward_id}
onValueChange={(value) =>
setRewardProgram({ ...rewardProgram, internal_reward_id: value })
}
items={Object.fromEntries(rewards.map((reward: Reward) => [reward.internal_id, reward.name]))}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select a reward" />
</SelectTrigger>
@@ -84,16 +85,17 @@ export const RewardProgramConfig = ({
<div className="flex gap-2">
<div className="w-full">
<FieldLabel>Redeem On</FieldLabel>
<Select
defaultValue={RewardTriggerEvent.CustomerCreation}
value={rewardProgram.when}
onValueChange={(value) =>
setRewardProgram({
...rewardProgram,
when: value as RewardTriggerEvent,
})
}
>
<Select
defaultValue={RewardTriggerEvent.CustomerCreation}
value={rewardProgram.when}
onValueChange={(value) =>
setRewardProgram({
...rewardProgram,
when: value as RewardTriggerEvent,
})
}
items={Object.fromEntries(Object.values(RewardTriggerEvent).map((event) => [event, keyToTitle(event, { exclusionMap: { [RewardTriggerEvent.CustomerCreation]: "Customer Redemption" } })]))}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select a redeem on" />
</SelectTrigger>
@@ -127,15 +129,16 @@ export const RewardProgramConfig = ({
</div>
<div className="w-full">
<FieldLabel>Received by</FieldLabel>
<Select
value={rewardProgram.received_by}
onValueChange={(value) =>
setRewardProgram({
...rewardProgram,
received_by: value as RewardReceivedBy,
})
}
>
<Select
value={rewardProgram.received_by}
onValueChange={(value) =>
setRewardProgram({
...rewardProgram,
received_by: value as RewardReceivedBy,
})
}
items={Object.fromEntries(Object.values(RewardReceivedBy).map((receivedBy) => [receivedBy, receivedBy === RewardReceivedBy.All ? "Referrer & Redeemer" : keyToTitle(receivedBy)]))}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Who should receive the reward" />
</SelectTrigger>

View File

@@ -43,20 +43,6 @@ export default defineConfig({
"../packages/atmn/src/prompts/skills/index.ts",
),
// Hide Radix UI imports with cleaner aliases
"@radix/accordion": "@radix-ui/react-accordion",
"@radix/checkbox": "@radix-ui/react-checkbox",
"@radix/context-menu": "@radix-ui/react-context-menu",
"@radix/dialog": "@radix-ui/react-dialog",
"@radix/dropdown-menu": "@radix-ui/react-dropdown-menu",
"@radix/popover": "@radix-ui/react-popover",
"@radix/scroll-area": "@radix-ui/react-scroll-area",
"@radix/select": "@radix-ui/react-select",
"@radix/separator": "@radix-ui/react-separator",
"@radix/slot": "@radix-ui/react-slot",
"@radix/switch": "@radix-ui/react-switch",
"@radix/tabs": "@radix-ui/react-tabs",
"@radix/tooltip": "@radix-ui/react-tooltip",
},
},