Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0117e197bb | ||
|
37ebe41526 | ||
|
ed367ed27c | ||
|
9666401625 | ||
|
22d638a090 | ||
|
0dd99cbc77 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -40,6 +40,7 @@ wrangler.toml
|
|||||||
|
|
||||||
dist
|
dist
|
||||||
backend/server/projects
|
backend/server/projects
|
||||||
|
backend/database/drizzle
|
||||||
|
|
||||||
app.yaml
|
app.yaml
|
||||||
ingressController.yaml
|
ingressController.yaml
|
@ -78,8 +78,6 @@ npx wrangler deploy
|
|||||||
|
|
||||||
### 4. Deploying the database
|
### 4. Deploying the database
|
||||||
|
|
||||||
Follow this [guide](https://docs.google.com/document/d/1w5dA5daic_sIYB5Seni1KvnFx51pPV2so6lLdN2xa7Q/edit?usp=sharing) for more info.
|
|
||||||
|
|
||||||
Create a database:
|
Create a database:
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -193,10 +191,6 @@ DOKKU_USERNAME=
|
|||||||
DOKKU_KEY=
|
DOKKU_KEY=
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deploying to AWS
|
|
||||||
|
|
||||||
The backend server and deployments server can be deployed using AWS's EC2 service. See [our video guide](https://www.youtube.com/watch?v=WN8HQnimjmk) on how to do this.
|
|
||||||
|
|
||||||
## Creating Custom Templates
|
## Creating Custom Templates
|
||||||
|
|
||||||
Anyone can contribute a custom template for integration in Sandbox. Since Sandbox is built on E2B, there is no limitation to what langauge or runtime a Sandbox can use.
|
Anyone can contribute a custom template for integration in Sandbox. Since Sandbox is built on E2B, there is no limitation to what langauge or runtime a Sandbox can use.
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
CREATE TABLE `sandbox` (
|
|
||||||
`id` text PRIMARY KEY NOT NULL,
|
|
||||||
`name` text NOT NULL,
|
|
||||||
`type` text NOT NULL,
|
|
||||||
`visibility` text,
|
|
||||||
`createdAt` integer DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`user_id` text NOT NULL,
|
|
||||||
`likeCount` integer DEFAULT 0,
|
|
||||||
`viewCount` integer DEFAULT 0,
|
|
||||||
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE `sandbox_likes` (
|
|
||||||
`user_id` text NOT NULL,
|
|
||||||
`sandbox_id` text NOT NULL,
|
|
||||||
`createdAt` integer DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
PRIMARY KEY(`sandbox_id`, `user_id`),
|
|
||||||
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action,
|
|
||||||
FOREIGN KEY (`sandbox_id`) REFERENCES `sandbox`(`id`) ON UPDATE no action ON DELETE no action
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE `user` (
|
|
||||||
`id` text PRIMARY KEY NOT NULL,
|
|
||||||
`name` text NOT NULL,
|
|
||||||
`email` text NOT NULL,
|
|
||||||
`username` text NOT NULL,
|
|
||||||
`avatarUrl` text,
|
|
||||||
`githubToken` text,
|
|
||||||
`createdAt` integer DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`generations` integer DEFAULT 0,
|
|
||||||
`tier` text DEFAULT 'FREE',
|
|
||||||
`tierExpiresAt` integer,
|
|
||||||
`lastResetDate` integer
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE `users_to_sandboxes` (
|
|
||||||
`userId` text NOT NULL,
|
|
||||||
`sandboxId` text NOT NULL,
|
|
||||||
`sharedOn` integer,
|
|
||||||
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action,
|
|
||||||
FOREIGN KEY (`sandboxId`) REFERENCES `sandbox`(`id`) ON UPDATE no action ON DELETE no action
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE UNIQUE INDEX `sandbox_id_unique` ON `sandbox` (`id`);--> statement-breakpoint
|
|
||||||
CREATE UNIQUE INDEX `user_id_unique` ON `user` (`id`);--> statement-breakpoint
|
|
||||||
CREATE UNIQUE INDEX `user_username_unique` ON `user` (`username`);
|
|
@ -1,3 +0,0 @@
|
|||||||
ALTER TABLE user ADD `bio` text;--> statement-breakpoint
|
|
||||||
ALTER TABLE user ADD `personalWebsite` text;--> statement-breakpoint
|
|
||||||
ALTER TABLE user ADD `links` text DEFAULT '[]';
|
|
@ -1 +0,0 @@
|
|||||||
ALTER TABLE sandbox ADD `containerId` text;
|
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": "5",
|
"version": "5",
|
||||||
"dialect": "sqlite",
|
"dialect": "sqlite",
|
||||||
"id": "4ada398d-7e4e-448f-8cea-a10b4d844600",
|
"id": "1288b006-6410-4b1c-8c96-d9797878a116",
|
||||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
"tables": {
|
"tables": {
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
@ -94,72 +94,6 @@
|
|||||||
"compositePrimaryKeys": {},
|
"compositePrimaryKeys": {},
|
||||||
"uniqueConstraints": {}
|
"uniqueConstraints": {}
|
||||||
},
|
},
|
||||||
"sandbox_likes": {
|
|
||||||
"name": "sandbox_likes",
|
|
||||||
"columns": {
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"sandbox_id": {
|
|
||||||
"name": "sandbox_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"name": "createdAt",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "CURRENT_TIMESTAMP"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"sandbox_likes_user_id_user_id_fk": {
|
|
||||||
"name": "sandbox_likes_user_id_user_id_fk",
|
|
||||||
"tableFrom": "sandbox_likes",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"sandbox_likes_sandbox_id_sandbox_id_fk": {
|
|
||||||
"name": "sandbox_likes_sandbox_id_sandbox_id_fk",
|
|
||||||
"tableFrom": "sandbox_likes",
|
|
||||||
"tableTo": "sandbox",
|
|
||||||
"columnsFrom": [
|
|
||||||
"sandbox_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {
|
|
||||||
"sandbox_likes_sandbox_id_user_id_pk": {
|
|
||||||
"columns": [
|
|
||||||
"sandbox_id",
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"name": "sandbox_likes_sandbox_id_user_id_pk"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"user": {
|
"user": {
|
||||||
"name": "user",
|
"name": "user",
|
||||||
"columns": {
|
"columns": {
|
||||||
@ -198,13 +132,6 @@
|
|||||||
"notNull": false,
|
"notNull": false,
|
||||||
"autoincrement": false
|
"autoincrement": false
|
||||||
},
|
},
|
||||||
"githubToken": {
|
|
||||||
"name": "githubToken",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"name": "createdAt",
|
"name": "createdAt",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
@ -1,353 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "5",
|
|
||||||
"dialect": "sqlite",
|
|
||||||
"id": "80c0b0b2-bb0e-449a-b447-c21863686f58",
|
|
||||||
"prevId": "4ada398d-7e4e-448f-8cea-a10b4d844600",
|
|
||||||
"tables": {
|
|
||||||
"sandbox": {
|
|
||||||
"name": "sandbox",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"type": {
|
|
||||||
"name": "type",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"visibility": {
|
|
||||||
"name": "visibility",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"name": "createdAt",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "CURRENT_TIMESTAMP"
|
|
||||||
},
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"likeCount": {
|
|
||||||
"name": "likeCount",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"viewCount": {
|
|
||||||
"name": "viewCount",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"sandbox_id_unique": {
|
|
||||||
"name": "sandbox_id_unique",
|
|
||||||
"columns": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {
|
|
||||||
"sandbox_user_id_user_id_fk": {
|
|
||||||
"name": "sandbox_user_id_user_id_fk",
|
|
||||||
"tableFrom": "sandbox",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"sandbox_likes": {
|
|
||||||
"name": "sandbox_likes",
|
|
||||||
"columns": {
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"sandbox_id": {
|
|
||||||
"name": "sandbox_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"name": "createdAt",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "CURRENT_TIMESTAMP"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"sandbox_likes_user_id_user_id_fk": {
|
|
||||||
"name": "sandbox_likes_user_id_user_id_fk",
|
|
||||||
"tableFrom": "sandbox_likes",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"sandbox_likes_sandbox_id_sandbox_id_fk": {
|
|
||||||
"name": "sandbox_likes_sandbox_id_sandbox_id_fk",
|
|
||||||
"tableFrom": "sandbox_likes",
|
|
||||||
"tableTo": "sandbox",
|
|
||||||
"columnsFrom": [
|
|
||||||
"sandbox_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {
|
|
||||||
"sandbox_likes_sandbox_id_user_id_pk": {
|
|
||||||
"columns": [
|
|
||||||
"sandbox_id",
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"name": "sandbox_likes_sandbox_id_user_id_pk"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"user": {
|
|
||||||
"name": "user",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"name": "email",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"username": {
|
|
||||||
"name": "username",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"avatarUrl": {
|
|
||||||
"name": "avatarUrl",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"githubToken": {
|
|
||||||
"name": "githubToken",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"name": "createdAt",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "CURRENT_TIMESTAMP"
|
|
||||||
},
|
|
||||||
"generations": {
|
|
||||||
"name": "generations",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"bio": {
|
|
||||||
"name": "bio",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"personalWebsite": {
|
|
||||||
"name": "personalWebsite",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"links": {
|
|
||||||
"name": "links",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'[]'"
|
|
||||||
},
|
|
||||||
"tier": {
|
|
||||||
"name": "tier",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'FREE'"
|
|
||||||
},
|
|
||||||
"tierExpiresAt": {
|
|
||||||
"name": "tierExpiresAt",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"lastResetDate": {
|
|
||||||
"name": "lastResetDate",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"user_id_unique": {
|
|
||||||
"name": "user_id_unique",
|
|
||||||
"columns": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
|
||||||
},
|
|
||||||
"user_username_unique": {
|
|
||||||
"name": "user_username_unique",
|
|
||||||
"columns": [
|
|
||||||
"username"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"users_to_sandboxes": {
|
|
||||||
"name": "users_to_sandboxes",
|
|
||||||
"columns": {
|
|
||||||
"userId": {
|
|
||||||
"name": "userId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"sandboxId": {
|
|
||||||
"name": "sandboxId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"sharedOn": {
|
|
||||||
"name": "sharedOn",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"users_to_sandboxes_userId_user_id_fk": {
|
|
||||||
"name": "users_to_sandboxes_userId_user_id_fk",
|
|
||||||
"tableFrom": "users_to_sandboxes",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"userId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"users_to_sandboxes_sandboxId_sandbox_id_fk": {
|
|
||||||
"name": "users_to_sandboxes_sandboxId_sandbox_id_fk",
|
|
||||||
"tableFrom": "users_to_sandboxes",
|
|
||||||
"tableTo": "sandbox",
|
|
||||||
"columnsFrom": [
|
|
||||||
"sandboxId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"enums": {},
|
|
||||||
"_meta": {
|
|
||||||
"schemas": {},
|
|
||||||
"tables": {},
|
|
||||||
"columns": {}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,360 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "5",
|
|
||||||
"dialect": "sqlite",
|
|
||||||
"id": "51abcf01-2921-4885-8058-d1ccd576f3e1",
|
|
||||||
"prevId": "80c0b0b2-bb0e-449a-b447-c21863686f58",
|
|
||||||
"tables": {
|
|
||||||
"sandbox": {
|
|
||||||
"name": "sandbox",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"type": {
|
|
||||||
"name": "type",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"visibility": {
|
|
||||||
"name": "visibility",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"name": "createdAt",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "CURRENT_TIMESTAMP"
|
|
||||||
},
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"likeCount": {
|
|
||||||
"name": "likeCount",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"viewCount": {
|
|
||||||
"name": "viewCount",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"containerId": {
|
|
||||||
"name": "containerId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"sandbox_id_unique": {
|
|
||||||
"name": "sandbox_id_unique",
|
|
||||||
"columns": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {
|
|
||||||
"sandbox_user_id_user_id_fk": {
|
|
||||||
"name": "sandbox_user_id_user_id_fk",
|
|
||||||
"tableFrom": "sandbox",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"sandbox_likes": {
|
|
||||||
"name": "sandbox_likes",
|
|
||||||
"columns": {
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"sandbox_id": {
|
|
||||||
"name": "sandbox_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"name": "createdAt",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "CURRENT_TIMESTAMP"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"sandbox_likes_user_id_user_id_fk": {
|
|
||||||
"name": "sandbox_likes_user_id_user_id_fk",
|
|
||||||
"tableFrom": "sandbox_likes",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"sandbox_likes_sandbox_id_sandbox_id_fk": {
|
|
||||||
"name": "sandbox_likes_sandbox_id_sandbox_id_fk",
|
|
||||||
"tableFrom": "sandbox_likes",
|
|
||||||
"tableTo": "sandbox",
|
|
||||||
"columnsFrom": [
|
|
||||||
"sandbox_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {
|
|
||||||
"sandbox_likes_sandbox_id_user_id_pk": {
|
|
||||||
"columns": [
|
|
||||||
"sandbox_id",
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"name": "sandbox_likes_sandbox_id_user_id_pk"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"user": {
|
|
||||||
"name": "user",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"name": "email",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"username": {
|
|
||||||
"name": "username",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"avatarUrl": {
|
|
||||||
"name": "avatarUrl",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"githubToken": {
|
|
||||||
"name": "githubToken",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"name": "createdAt",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "CURRENT_TIMESTAMP"
|
|
||||||
},
|
|
||||||
"generations": {
|
|
||||||
"name": "generations",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"bio": {
|
|
||||||
"name": "bio",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"personalWebsite": {
|
|
||||||
"name": "personalWebsite",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"links": {
|
|
||||||
"name": "links",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'[]'"
|
|
||||||
},
|
|
||||||
"tier": {
|
|
||||||
"name": "tier",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'FREE'"
|
|
||||||
},
|
|
||||||
"tierExpiresAt": {
|
|
||||||
"name": "tierExpiresAt",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"lastResetDate": {
|
|
||||||
"name": "lastResetDate",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"user_id_unique": {
|
|
||||||
"name": "user_id_unique",
|
|
||||||
"columns": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
|
||||||
},
|
|
||||||
"user_username_unique": {
|
|
||||||
"name": "user_username_unique",
|
|
||||||
"columns": [
|
|
||||||
"username"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"users_to_sandboxes": {
|
|
||||||
"name": "users_to_sandboxes",
|
|
||||||
"columns": {
|
|
||||||
"userId": {
|
|
||||||
"name": "userId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"sandboxId": {
|
|
||||||
"name": "sandboxId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"sharedOn": {
|
|
||||||
"name": "sharedOn",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"users_to_sandboxes_userId_user_id_fk": {
|
|
||||||
"name": "users_to_sandboxes_userId_user_id_fk",
|
|
||||||
"tableFrom": "users_to_sandboxes",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"userId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
},
|
|
||||||
"users_to_sandboxes_sandboxId_sandbox_id_fk": {
|
|
||||||
"name": "users_to_sandboxes_sandboxId_sandbox_id_fk",
|
|
||||||
"tableFrom": "users_to_sandboxes",
|
|
||||||
"tableTo": "sandbox",
|
|
||||||
"columnsFrom": [
|
|
||||||
"sandboxId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"enums": {},
|
|
||||||
"_meta": {
|
|
||||||
"schemas": {},
|
|
||||||
"tables": {},
|
|
||||||
"columns": {}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,22 +5,8 @@
|
|||||||
{
|
{
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"version": "5",
|
"version": "5",
|
||||||
"when": 1736155854410,
|
"when": 1732568535771,
|
||||||
"tag": "0000_sudden_wallop",
|
"tag": "0000_rapid_korath",
|
||||||
"breakpoints": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idx": 1,
|
|
||||||
"version": "5",
|
|
||||||
"when": 1736169498666,
|
|
||||||
"tag": "0001_dusty_komodo",
|
|
||||||
"breakpoints": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idx": 2,
|
|
||||||
"version": "5",
|
|
||||||
"when": 1736768910615,
|
|
||||||
"tag": "0002_chemical_brother_voodoo",
|
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
1960
backend/database/package-lock.json
generated
1960
backend/database/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,7 @@
|
|||||||
"drizzle-kit": "^0.20.17",
|
"drizzle-kit": "^0.20.17",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
"vitest": "1.3.0",
|
"vitest": "1.3.0",
|
||||||
"wrangler": "^3.101.0"
|
"wrangler": "^3.86.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@paralleldrive/cuid2": "^2.2.2",
|
"@paralleldrive/cuid2": "^2.2.2",
|
||||||
|
@ -5,7 +5,13 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { and, eq, sql } from "drizzle-orm"
|
import { and, eq, sql } from "drizzle-orm"
|
||||||
import * as schema from "./schema"
|
import * as schema from "./schema"
|
||||||
import { Sandbox, sandbox, sandboxLikes, user, usersToSandboxes } from "./schema"
|
import {
|
||||||
|
Sandbox,
|
||||||
|
sandbox,
|
||||||
|
sandboxLikes,
|
||||||
|
user,
|
||||||
|
usersToSandboxes,
|
||||||
|
} from "./schema"
|
||||||
|
|
||||||
export interface Env {
|
export interface Env {
|
||||||
DB: D1Database
|
DB: D1Database
|
||||||
@ -67,7 +73,6 @@ export default {
|
|||||||
const params = url.searchParams
|
const params = url.searchParams
|
||||||
if (params.has("id")) {
|
if (params.has("id")) {
|
||||||
const id = params.get("id") as string
|
const id = params.get("id") as string
|
||||||
await db.delete(sandboxLikes).where(eq(sandboxLikes.sandboxId, id))
|
|
||||||
await db
|
await db
|
||||||
.delete(usersToSandboxes)
|
.delete(usersToSandboxes)
|
||||||
.where(eq(usersToSandboxes.sandboxId, id))
|
.where(eq(usersToSandboxes.sandboxId, id))
|
||||||
@ -240,88 +245,6 @@ export default {
|
|||||||
|
|
||||||
return success
|
return success
|
||||||
} else return methodNotAllowed
|
} else return methodNotAllowed
|
||||||
} else if (path === "/api/sandbox/like") {
|
|
||||||
if (method === "POST") {
|
|
||||||
const likeSchema = z.object({
|
|
||||||
sandboxId: z.string(),
|
|
||||||
userId: z.string(),
|
|
||||||
})
|
|
||||||
|
|
||||||
try {
|
|
||||||
const body = await request.json()
|
|
||||||
const { sandboxId, userId } = likeSchema.parse(body)
|
|
||||||
|
|
||||||
// Check if user has already liked
|
|
||||||
const existingLike = await db.query.sandboxLikes.findFirst({
|
|
||||||
where: (likes, { and, eq }) =>
|
|
||||||
and(eq(likes.sandboxId, sandboxId), eq(likes.userId, userId)),
|
|
||||||
})
|
|
||||||
|
|
||||||
if (existingLike) {
|
|
||||||
// Unlike
|
|
||||||
await db
|
|
||||||
.delete(sandboxLikes)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(sandboxLikes.sandboxId, sandboxId),
|
|
||||||
eq(sandboxLikes.userId, userId)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
await db
|
|
||||||
.update(sandbox)
|
|
||||||
.set({
|
|
||||||
likeCount: sql`${sandbox.likeCount} - 1`,
|
|
||||||
})
|
|
||||||
.where(eq(sandbox.id, sandboxId))
|
|
||||||
|
|
||||||
return json({
|
|
||||||
message: "Unlike successful",
|
|
||||||
liked: false,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// Like
|
|
||||||
await db.insert(sandboxLikes).values({
|
|
||||||
sandboxId,
|
|
||||||
userId,
|
|
||||||
createdAt: new Date(),
|
|
||||||
})
|
|
||||||
|
|
||||||
await db
|
|
||||||
.update(sandbox)
|
|
||||||
.set({
|
|
||||||
likeCount: sql`${sandbox.likeCount} + 1`,
|
|
||||||
})
|
|
||||||
.where(eq(sandbox.id, sandboxId))
|
|
||||||
|
|
||||||
return json({
|
|
||||||
message: "Like successful",
|
|
||||||
liked: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return new Response("Invalid request format", { status: 400 })
|
|
||||||
}
|
|
||||||
} else if (method === "GET") {
|
|
||||||
const params = url.searchParams
|
|
||||||
const sandboxId = params.get("sandboxId")
|
|
||||||
const userId = params.get("userId")
|
|
||||||
|
|
||||||
if (!sandboxId || !userId) {
|
|
||||||
return invalidRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
const like = await db.query.sandboxLikes.findFirst({
|
|
||||||
where: (likes, { and, eq }) =>
|
|
||||||
and(eq(likes.sandboxId, sandboxId), eq(likes.userId, userId)),
|
|
||||||
})
|
|
||||||
|
|
||||||
return json({
|
|
||||||
liked: !!like,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return methodNotAllowed
|
|
||||||
}
|
|
||||||
} else if (path === "/api/user") {
|
} else if (path === "/api/user") {
|
||||||
if (method === "GET") {
|
if (method === "GET") {
|
||||||
const params = url.searchParams
|
const params = url.searchParams
|
||||||
@ -393,7 +316,6 @@ export default {
|
|||||||
email: z.string().email(),
|
email: z.string().email(),
|
||||||
username: z.string(),
|
username: z.string(),
|
||||||
avatarUrl: z.string().optional(),
|
avatarUrl: z.string().optional(),
|
||||||
githubToken: z.string().nullable().optional(),
|
|
||||||
createdAt: z.string().optional(),
|
createdAt: z.string().optional(),
|
||||||
generations: z.number().optional(),
|
generations: z.number().optional(),
|
||||||
tier: z.enum(["FREE", "PRO", "ENTERPRISE"]).optional(),
|
tier: z.enum(["FREE", "PRO", "ENTERPRISE"]).optional(),
|
||||||
@ -409,7 +331,6 @@ export default {
|
|||||||
email,
|
email,
|
||||||
username,
|
username,
|
||||||
avatarUrl,
|
avatarUrl,
|
||||||
githubToken,
|
|
||||||
createdAt,
|
createdAt,
|
||||||
generations,
|
generations,
|
||||||
tier,
|
tier,
|
||||||
@ -424,7 +345,6 @@ export default {
|
|||||||
email,
|
email,
|
||||||
username,
|
username,
|
||||||
avatarUrl,
|
avatarUrl,
|
||||||
githubToken,
|
|
||||||
createdAt: createdAt ? new Date(createdAt) : new Date(),
|
createdAt: createdAt ? new Date(createdAt) : new Date(),
|
||||||
generations,
|
generations,
|
||||||
tier,
|
tier,
|
||||||
@ -445,20 +365,9 @@ export default {
|
|||||||
const updateUserSchema = z.object({
|
const updateUserSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
name: z.string().optional(),
|
name: z.string().optional(),
|
||||||
bio: z.string().optional(),
|
|
||||||
personalWebsite: z.string().optional(),
|
|
||||||
links: z
|
|
||||||
.array(
|
|
||||||
z.object({
|
|
||||||
url: z.string(),
|
|
||||||
platform: z.enum(schema.KNOWN_PLATFORMS),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.optional(),
|
|
||||||
email: z.string().email().optional(),
|
email: z.string().email().optional(),
|
||||||
username: z.string().optional(),
|
username: z.string().optional(),
|
||||||
avatarUrl: z.string().optional(),
|
avatarUrl: z.string().optional(),
|
||||||
githubToken: z.string().nullable().optional(),
|
|
||||||
generations: z.number().optional(),
|
generations: z.number().optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -2,26 +2,6 @@ import { createId } from "@paralleldrive/cuid2"
|
|||||||
import { relations, sql } from "drizzle-orm"
|
import { relations, sql } from "drizzle-orm"
|
||||||
import { integer, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core"
|
import { integer, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core"
|
||||||
|
|
||||||
export const KNOWN_PLATFORMS = [
|
|
||||||
"github",
|
|
||||||
"twitter",
|
|
||||||
"instagram",
|
|
||||||
"bluesky",
|
|
||||||
"linkedin",
|
|
||||||
"youtube",
|
|
||||||
"twitch",
|
|
||||||
"discord",
|
|
||||||
"mastodon",
|
|
||||||
"threads",
|
|
||||||
"gitlab",
|
|
||||||
"generic",
|
|
||||||
] as const
|
|
||||||
|
|
||||||
export type KnownPlatform = (typeof KNOWN_PLATFORMS)[number]
|
|
||||||
export type UserLink = {
|
|
||||||
url: string
|
|
||||||
platform: KnownPlatform
|
|
||||||
}
|
|
||||||
// #region Tables
|
// #region Tables
|
||||||
export const user = sqliteTable("user", {
|
export const user = sqliteTable("user", {
|
||||||
id: text("id")
|
id: text("id")
|
||||||
@ -32,14 +12,10 @@ export const user = sqliteTable("user", {
|
|||||||
email: text("email").notNull(),
|
email: text("email").notNull(),
|
||||||
username: text("username").notNull().unique(),
|
username: text("username").notNull().unique(),
|
||||||
avatarUrl: text("avatarUrl"),
|
avatarUrl: text("avatarUrl"),
|
||||||
githubToken: text("githubToken"),
|
|
||||||
createdAt: integer("createdAt", { mode: "timestamp_ms" }).default(
|
createdAt: integer("createdAt", { mode: "timestamp_ms" }).default(
|
||||||
sql`CURRENT_TIMESTAMP`
|
sql`CURRENT_TIMESTAMP`
|
||||||
),
|
),
|
||||||
generations: integer("generations").default(0),
|
generations: integer("generations").default(0),
|
||||||
bio: text("bio"),
|
|
||||||
personalWebsite: text("personalWebsite"),
|
|
||||||
links: text("links", { mode: "json" }).default("[]").$type<UserLink[]>(),
|
|
||||||
tier: text("tier", { enum: ["FREE", "PRO", "ENTERPRISE"] }).default("FREE"),
|
tier: text("tier", { enum: ["FREE", "PRO", "ENTERPRISE"] }).default("FREE"),
|
||||||
tierExpiresAt: integer("tierExpiresAt"),
|
tierExpiresAt: integer("tierExpiresAt"),
|
||||||
lastResetDate: integer("lastResetDate"),
|
lastResetDate: integer("lastResetDate"),
|
||||||
@ -63,7 +39,6 @@ export const sandbox = sqliteTable("sandbox", {
|
|||||||
.references(() => user.id),
|
.references(() => user.id),
|
||||||
likeCount: integer("likeCount").default(0),
|
likeCount: integer("likeCount").default(0),
|
||||||
viewCount: integer("viewCount").default(0),
|
viewCount: integer("viewCount").default(0),
|
||||||
containerId: text("containerId"),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export type Sandbox = typeof sandbox.$inferSelect
|
export type Sandbox = typeof sandbox.$inferSelect
|
||||||
|
@ -91,17 +91,23 @@ export default async function CodePage({ params }: { params: { id: string } }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TerminalProvider>
|
<>
|
||||||
{/* <Room id={sandboxId}> */}
|
<div className="overflow-hidden overscroll-none w-screen flex flex-col h-screen bg-background">
|
||||||
<div className="overflow-hidden overscroll-none w-screen h-screen grid [grid-template-rows:3.5rem_auto] bg-background">
|
{/* <Room id={sandboxId}> */}
|
||||||
<Navbar
|
<TerminalProvider>
|
||||||
userData={userData}
|
<Navbar
|
||||||
sandboxData={sandboxData}
|
userData={userData}
|
||||||
shared={shared as { id: string; name: string; avatarUrl: string }[]}
|
sandboxData={sandboxData}
|
||||||
/>
|
shared={
|
||||||
<CodeEditor userData={userData} sandboxData={sandboxData} />
|
shared as { id: string; name: string; avatarUrl: string }[]
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<div className="w-screen flex grow">
|
||||||
|
<CodeEditor userData={userData} sandboxData={sandboxData} />
|
||||||
|
</div>
|
||||||
|
</TerminalProvider>
|
||||||
|
{/* </Room> */}
|
||||||
</div>
|
</div>
|
||||||
{/* </Room> */}
|
</>
|
||||||
</TerminalProvider>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
BIN
frontend/app/favicon.ico
Normal file
BIN
frontend/app/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
@ -102,27 +102,26 @@
|
|||||||
.light .gradient-button-bg {
|
.light .gradient-button-bg {
|
||||||
background: radial-gradient(
|
background: radial-gradient(
|
||||||
circle at top,
|
circle at top,
|
||||||
#f5f5f5 0%,
|
#262626 0%,
|
||||||
/* Very light gray */ #e0e0e0 50% /* Soft gray */
|
#f5f5f5 50%
|
||||||
);
|
); /* Dark gray -> Light gray */
|
||||||
}
|
}
|
||||||
|
|
||||||
.light .gradient-button {
|
.light .gradient-button {
|
||||||
background: radial-gradient(
|
background: radial-gradient(
|
||||||
circle at bottom,
|
circle at bottom,
|
||||||
hsl(0, 0%, 85%) -10%,
|
hsl(0, 10%, 25%) -10%,
|
||||||
/* Slightly darker gray */ hsl(0, 0%, 95%) 50% /* Very soft light gray */
|
#9d9d9d 50%
|
||||||
);
|
); /* Light gray -> Almost white */
|
||||||
}
|
}
|
||||||
|
|
||||||
.light .gradient-button-bg > div:hover {
|
.light .gradient-button-bg > div:hover {
|
||||||
background: radial-gradient(
|
background: radial-gradient(
|
||||||
circle at bottom,
|
circle at bottom,
|
||||||
hsl(0, 0%, 80%) -10%,
|
hsl(0, 10%, 25%) -10%,
|
||||||
/* Slightly darker gray for hover */ hsl(0, 0%, 90%) 80% /* Softer gray */
|
#9d9d9d 80%
|
||||||
);
|
); /* Light gray -> Almost white */
|
||||||
}
|
}
|
||||||
|
|
||||||
.inline-decoration::before {
|
.inline-decoration::before {
|
||||||
content: "Generate";
|
content: "Generate";
|
||||||
color: #525252;
|
color: #525252;
|
||||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 17 KiB |
@ -11,22 +11,7 @@ import "./globals.css"
|
|||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Sandbox",
|
title: "Sandbox",
|
||||||
description:
|
description: "A collaborative, AI-powered cloud code editing environment",
|
||||||
"an open-source cloud-based code editing environment with custom AI code generation, live preview, real-time collaboration, and AI chat",
|
|
||||||
openGraph: {
|
|
||||||
type: "website",
|
|
||||||
url: "https://sandbox.gitwit.dev",
|
|
||||||
title: "Sandbox",
|
|
||||||
description:
|
|
||||||
"an open-source cloud-based code editing environment with custom AI code generation, live preview, real-time collaboration, and AI chat",
|
|
||||||
},
|
|
||||||
twitter: {
|
|
||||||
site: "https://sandbox.gitwit.dev",
|
|
||||||
title: "Sandbox by Gitwit",
|
|
||||||
description:
|
|
||||||
"an open-source cloud-based code editing environment with custom AI code generation, live preview, real-time collaboration, and AI chat",
|
|
||||||
creator: "@gitwitdev",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
|
@ -1 +0,0 @@
|
|||||||
About Sandbox by Gitwit
|
|
Binary file not shown.
Before Width: | Height: | Size: 465 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 2.3 KiB |
@ -9,19 +9,14 @@ import DashboardNavbarSearch from "./search"
|
|||||||
export default function DashboardNavbar({ userData }: { userData: User }) {
|
export default function DashboardNavbar({ userData }: { userData: User }) {
|
||||||
return (
|
return (
|
||||||
<div className=" py-2 px-4 w-full flex items-center justify-between border-b border-border">
|
<div className=" py-2 px-4 w-full flex items-center justify-between border-b border-border">
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-4">
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/"
|
||||||
className="ring-offset-2 ring-offset-background focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none rounded-sm"
|
className="ring-offset-2 ring-offset-background focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none rounded-sm"
|
||||||
>
|
>
|
||||||
<Image src={Logo} alt="Logo" width={36} height={36} />
|
<Image src={Logo} alt="Logo" width={36} height={36} />
|
||||||
</Link>
|
</Link>
|
||||||
<h1 className="text-xl">
|
<div className="text-sm font-medium flex items-center">Sandbox</div>
|
||||||
<span className="font-semibold">Sandbox</span>{" "}
|
|
||||||
<span className="text-xs font-medium text-muted-foreground">
|
|
||||||
by gitwit
|
|
||||||
</span>
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
<DashboardNavbarSearch />
|
<DashboardNavbarSearch />
|
||||||
|
@ -240,7 +240,7 @@ function ProjectCardComponent({
|
|||||||
>
|
>
|
||||||
<CanvasRevealEffect
|
<CanvasRevealEffect
|
||||||
animationSpeed={3}
|
animationSpeed={3}
|
||||||
containerClassName="bg-muted"
|
containerClassName="bg-black"
|
||||||
colors={colors[type]}
|
colors={colors[type]}
|
||||||
dotSize={2}
|
dotSize={2}
|
||||||
/>
|
/>
|
||||||
|
@ -126,8 +126,8 @@ export default function ChatMessage({
|
|||||||
<div
|
<div
|
||||||
className={`relative p-2 rounded-lg ${
|
className={`relative p-2 rounded-lg ${
|
||||||
message.role === "user"
|
message.role === "user"
|
||||||
? "bg-foreground text-background"
|
? "bg-[#262626] text-white"
|
||||||
: "bg-background text-foreground"
|
: "bg-transparent text-white"
|
||||||
} max-w-full`}
|
} max-w-full`}
|
||||||
>
|
>
|
||||||
{/* Render context tabs */}
|
{/* Render context tabs */}
|
||||||
@ -171,7 +171,7 @@ export default function ChatMessage({
|
|||||||
end: e.target.value.split("\n").length,
|
end: e.target.value.split("\n").length,
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
className="w-full p-2 bg-[#1e1e1e] text-foreground font-mono text-sm rounded"
|
className="w-full p-2 bg-[#1e1e1e] text-white font-mono text-sm rounded"
|
||||||
rows={code.split("\n").length}
|
rows={code.split("\n").length}
|
||||||
style={{
|
style={{
|
||||||
resize: "vertical",
|
resize: "vertical",
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { ScrollArea } from "@/components/ui/scroll-area"
|
|
||||||
import { useSocket } from "@/context/SocketContext"
|
import { useSocket } from "@/context/SocketContext"
|
||||||
import { TFile } from "@/lib/types"
|
import { TFile } from "@/lib/types"
|
||||||
import { ChevronDown, X } from "lucide-react"
|
import { ChevronDown, X } from "lucide-react"
|
||||||
@ -209,9 +208,9 @@ export default function AIChat({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ScrollArea
|
<div
|
||||||
ref={chatContainerRef}
|
ref={chatContainerRef}
|
||||||
className="flex-grow p-4 space-y-4 relative"
|
className="flex-grow overflow-y-auto p-4 space-y-4 relative"
|
||||||
>
|
>
|
||||||
{messages.map((message, messageIndex) => (
|
{messages.map((message, messageIndex) => (
|
||||||
// Render chat message component for each message
|
// Render chat message component for each message
|
||||||
@ -242,7 +241,7 @@ export default function AIChat({
|
|||||||
<ChevronDown className="h-5 w-5" />
|
<ChevronDown className="h-5 w-5" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</ScrollArea>
|
</div>
|
||||||
<div className="p-4 border-t mb-14">
|
<div className="p-4 border-t mb-14">
|
||||||
{/* Render context tabs component */}
|
{/* Render context tabs component */}
|
||||||
<ContextTabs
|
<ContextTabs
|
||||||
|
@ -62,7 +62,7 @@ export default function CodeEditor({
|
|||||||
//SocketContext functions and effects
|
//SocketContext functions and effects
|
||||||
const { socket, setUserAndSandboxId } = useSocket()
|
const { socket, setUserAndSandboxId } = useSocket()
|
||||||
// theme
|
// theme
|
||||||
const { resolvedTheme: theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Ensure userData.id and sandboxData.id are available before attempting to connect
|
// Ensure userData.id and sandboxData.id are available before attempting to connect
|
||||||
if (userData.id && sandboxData.id) {
|
if (userData.id && sandboxData.id) {
|
||||||
@ -980,9 +980,9 @@ export default function CodeEditor({
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex max-h-full overflow-hidden">
|
<>
|
||||||
|
{/* Copilot DOM elements */}
|
||||||
<PreviewProvider>
|
<PreviewProvider>
|
||||||
{/* Copilot DOM elements */}
|
|
||||||
<div ref={generateRef} />
|
<div ref={generateRef} />
|
||||||
<div ref={suggestionRef} className="absolute">
|
<div ref={suggestionRef} className="absolute">
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
@ -1304,7 +1304,7 @@ export default function CodeEditor({
|
|||||||
)}
|
)}
|
||||||
</ResizablePanelGroup>
|
</ResizablePanelGroup>
|
||||||
</PreviewProvider>
|
</PreviewProvider>
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import SidebarFolder from "./folder"
|
|||||||
import New from "./new"
|
import New from "./new"
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area"
|
|
||||||
import { Skeleton } from "@/components/ui/skeleton"
|
import { Skeleton } from "@/components/ui/skeleton"
|
||||||
import { cn, sortFileExplorer } from "@/lib/utils"
|
import { cn, sortFileExplorer } from "@/lib/utils"
|
||||||
import {
|
import {
|
||||||
@ -105,8 +104,8 @@ export default function Sidebar({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-56 select-none flex flex-col text-sm">
|
<div className="h-full w-56 select-none flex flex-col text-sm">
|
||||||
<ScrollArea className="flex-grow overflow-auto px-2 pt-0 pb-4 relative">
|
<div className="flex-grow overflow-auto p-2 pb-[84px]">
|
||||||
<div className="flex w-full items-center justify-between h-8 pb-1 isolate z-10 sticky pt-2 top-0 bg-background">
|
<div className="flex w-full items-center justify-between h-8 mb-1">
|
||||||
<div className="text-muted-foreground">Explorer</div>
|
<div className="text-muted-foreground">Explorer</div>
|
||||||
<div className="flex space-x-1">
|
<div className="flex space-x-1">
|
||||||
<button
|
<button
|
||||||
@ -180,8 +179,8 @@ export default function Sidebar({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</div>
|
||||||
<div className="flex flex-col p-2 bg-background">
|
<div className="fixed bottom-0 w-48 flex flex-col p-2 bg-background">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="w-full justify-start text-sm text-muted-foreground font-normal h-8 px-2 mb-2"
|
className="w-full justify-start text-sm text-muted-foreground font-normal h-8 px-2 mb-2"
|
||||||
|
@ -22,7 +22,7 @@ export default function EditorTerminal({
|
|||||||
setTerm: (term: Terminal) => void
|
setTerm: (term: Terminal) => void
|
||||||
visible: boolean
|
visible: boolean
|
||||||
}) {
|
}) {
|
||||||
const { resolvedTheme: theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const terminalContainerRef = useRef<ElementRef<"div">>(null)
|
const terminalContainerRef = useRef<ElementRef<"div">>(null)
|
||||||
const fitAddonRef = useRef<FitAddon | null>(null)
|
const fitAddonRef = useRef<FitAddon | null>(null)
|
||||||
|
|
||||||
|
@ -9,38 +9,19 @@ import {
|
|||||||
CardDescription,
|
CardDescription,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card"
|
} from "@/components/ui/card"
|
||||||
import {
|
|
||||||
Form,
|
|
||||||
FormControl,
|
|
||||||
FormDescription,
|
|
||||||
FormField,
|
|
||||||
FormItem,
|
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
|
||||||
} from "@/components/ui/form"
|
|
||||||
import {
|
import {
|
||||||
HoverCard,
|
HoverCard,
|
||||||
HoverCardContent,
|
HoverCardContent,
|
||||||
HoverCardTrigger,
|
HoverCardTrigger,
|
||||||
} from "@/components/ui/hover-card"
|
} from "@/components/ui/hover-card"
|
||||||
|
import { Label } from "@/components/ui/label"
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipProvider,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "@/components/ui/tooltip"
|
|
||||||
import { deleteSandbox, updateSandbox, updateUser } from "@/lib/actions"
|
import { deleteSandbox, updateSandbox, updateUser } from "@/lib/actions"
|
||||||
import { socialIcons } from "@/lib/data"
|
|
||||||
import { editUserSchema, EditUserSchema } from "@/lib/schema"
|
|
||||||
import { TIERS } from "@/lib/tiers"
|
import { TIERS } from "@/lib/tiers"
|
||||||
import { SandboxWithLiked, User, UserLink } from "@/lib/types"
|
import { SandboxWithLiked, User } from "@/lib/types"
|
||||||
import { cn, parseSocialLink } from "@/lib/utils"
|
|
||||||
import { useUser } from "@clerk/nextjs"
|
import { useUser } from "@clerk/nextjs"
|
||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
|
||||||
import {
|
import {
|
||||||
Edit,
|
Edit,
|
||||||
Globe,
|
|
||||||
Heart,
|
Heart,
|
||||||
Info,
|
Info,
|
||||||
Loader2,
|
Loader2,
|
||||||
@ -48,27 +29,17 @@ import {
|
|||||||
Package2,
|
Package2,
|
||||||
PlusCircle,
|
PlusCircle,
|
||||||
Sparkles,
|
Sparkles,
|
||||||
Trash2,
|
|
||||||
X,
|
X,
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
import {
|
import { Fragment, useCallback, useEffect, useMemo, useState } from "react"
|
||||||
Fragment,
|
|
||||||
useCallback,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
useTransition,
|
|
||||||
} from "react"
|
|
||||||
import { useFormState, useFormStatus } from "react-dom"
|
import { useFormState, useFormStatus } from "react-dom"
|
||||||
import { useFieldArray, useForm } from "react-hook-form"
|
|
||||||
import { toast } from "sonner"
|
import { toast } from "sonner"
|
||||||
import Avatar from "../ui/avatar"
|
import Avatar from "../ui/avatar"
|
||||||
import { Badge } from "../ui/badge"
|
import { Badge } from "../ui/badge"
|
||||||
import { Input } from "../ui/input"
|
import { Input } from "../ui/input"
|
||||||
import { Progress } from "../ui/progress"
|
import { Progress } from "../ui/progress"
|
||||||
import { Textarea } from "../ui/textarea"
|
|
||||||
// #region Profile Page
|
// #region Profile Page
|
||||||
export default function ProfilePage({
|
export default function ProfilePage({
|
||||||
publicSandboxes,
|
publicSandboxes,
|
||||||
@ -104,9 +75,6 @@ export default function ProfilePage({
|
|||||||
generations={isOwnProfile ? loggedInUser.generations : undefined}
|
generations={isOwnProfile ? loggedInUser.generations : undefined}
|
||||||
isOwnProfile={isOwnProfile}
|
isOwnProfile={isOwnProfile}
|
||||||
tier={profileOwner.tier}
|
tier={profileOwner.tier}
|
||||||
bio={profileOwner.bio}
|
|
||||||
personalWebsite={profileOwner.personalWebsite}
|
|
||||||
socialLinks={profileOwner.links}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="md:col-span-2">
|
<div className="md:col-span-2">
|
||||||
@ -133,17 +101,11 @@ function ProfileCard({
|
|||||||
joinedDate,
|
joinedDate,
|
||||||
generations,
|
generations,
|
||||||
isOwnProfile,
|
isOwnProfile,
|
||||||
bio,
|
|
||||||
personalWebsite,
|
|
||||||
socialLinks = [],
|
|
||||||
tier,
|
tier,
|
||||||
}: {
|
}: {
|
||||||
name: string
|
name: string
|
||||||
username: string
|
username: string
|
||||||
avatarUrl: string | null
|
avatarUrl: string | null
|
||||||
bio: string | null
|
|
||||||
personalWebsite: string | null
|
|
||||||
socialLinks: UserLink[]
|
|
||||||
sandboxes: SandboxWithLiked[]
|
sandboxes: SandboxWithLiked[]
|
||||||
joinedDate: Date
|
joinedDate: Date
|
||||||
generations?: number
|
generations?: number
|
||||||
@ -151,8 +113,9 @@ function ProfileCard({
|
|||||||
tier: string
|
tier: string
|
||||||
}) {
|
}) {
|
||||||
const { user } = useUser()
|
const { user } = useUser()
|
||||||
|
const router = useRouter()
|
||||||
const [isEditing, setIsEditing] = useState(false)
|
const [isEditing, setIsEditing] = useState(false)
|
||||||
|
const [formState, formAction] = useFormState(updateUser, {})
|
||||||
const joinedAt = useMemo(() => {
|
const joinedAt = useMemo(() => {
|
||||||
const date = new Date(joinedDate).toLocaleDateString("en-US", {
|
const date = new Date(joinedDate).toLocaleDateString("en-US", {
|
||||||
month: "long",
|
month: "long",
|
||||||
@ -177,126 +140,103 @@ function ProfileCard({
|
|||||||
}
|
}
|
||||||
}, [sandboxes])
|
}, [sandboxes])
|
||||||
|
|
||||||
const showAddMoreInfoBanner = useMemo(() => {
|
useEffect(() => {
|
||||||
return !bio && !personalWebsite && (socialLinks?.length ?? 0) === 0
|
if ("message" in formState) {
|
||||||
}, [personalWebsite, bio, socialLinks])
|
toast.success(formState.message as String)
|
||||||
|
toggleEdit()
|
||||||
|
if ("newRoute" in formState && typeof formState.newRoute === "string") {
|
||||||
|
router.replace(formState.newRoute)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("error" in formState) {
|
||||||
|
const error = formState.error
|
||||||
|
if (typeof error === "string") {
|
||||||
|
toast.error(error)
|
||||||
|
} else {
|
||||||
|
toast.error("An Error Occured")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [formState])
|
||||||
return (
|
return (
|
||||||
<Card className="mb-6 md:mb-0 sticky top-6">
|
<Card className="mb-6 md:mb-0 sticky top-6">
|
||||||
{isOwnProfile && (
|
{isOwnProfile && (
|
||||||
<div className="absolute top-2 right-2 flex flex-col gap-2">
|
<Button
|
||||||
<TooltipProvider>
|
onClick={toggleEdit}
|
||||||
<Tooltip>
|
aria-label={isEditing ? "close edit form" : "open edit form"}
|
||||||
<TooltipTrigger asChild>
|
size="smIcon"
|
||||||
<Button
|
variant="secondary"
|
||||||
onClick={toggleEdit}
|
className="rounded-full absolute top-2 right-2"
|
||||||
aria-label={isEditing ? "close edit form" : "open edit form"}
|
>
|
||||||
size="smIcon"
|
{isEditing ? <X className="size-4" /> : <Edit className="size-4" />}
|
||||||
variant="secondary"
|
</Button>
|
||||||
className="rounded-full relative"
|
|
||||||
>
|
|
||||||
{isEditing ? (
|
|
||||||
<X className="size-4" />
|
|
||||||
) : showAddMoreInfoBanner ? (
|
|
||||||
<>
|
|
||||||
<Sparkles className="size-4 text-yellow-400 z-[2]" />
|
|
||||||
<div className="z-[1] absolute inset-0 rounded-full bg-secondary animate-ping" />
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Edit className="size-4" />
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
<p>
|
|
||||||
{showAddMoreInfoBanner
|
|
||||||
? "Add more information to your profile"
|
|
||||||
: "Edit your profile"}
|
|
||||||
</p>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
<CardContent className="flex flex-col gap-4 pt-6">
|
<CardContent className="flex flex-col gap-4 items-center pt-6">
|
||||||
{isEditing ? (
|
<Avatar name={name} avatarUrl={avatarUrl} className="size-36" />
|
||||||
<div className="flex flex-col gap-2 items-center ">
|
|
||||||
<Avatar name={name} avatarUrl={avatarUrl} className="size-36" />
|
{!isEditing ? (
|
||||||
<EditProfileForm
|
<div className="space-y-2">
|
||||||
{...{
|
<CardTitle className="text-2xl text-center">{name}</CardTitle>
|
||||||
name,
|
<CardDescription className="text-center">{`@${username}`}</CardDescription>
|
||||||
username,
|
|
||||||
avatarUrl,
|
|
||||||
bio,
|
|
||||||
personalWebsite,
|
|
||||||
socialLinks,
|
|
||||||
toggleEdit,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
<form action={formAction} className="flex flex-col gap-2">
|
||||||
|
<Input
|
||||||
|
name="id"
|
||||||
|
placeholder="ID"
|
||||||
|
className="hidden "
|
||||||
|
value={user?.id}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
name="oldUsername"
|
||||||
|
placeholder="ID"
|
||||||
|
className="hidden "
|
||||||
|
value={user?.username ?? undefined}
|
||||||
|
/>
|
||||||
|
<div className="space-y-1">
|
||||||
|
<Label htmlFor="input-name">Name</Label>
|
||||||
|
<Input
|
||||||
|
id="input-name"
|
||||||
|
name="name"
|
||||||
|
placeholder="Name"
|
||||||
|
defaultValue={name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-1">
|
||||||
|
<Label htmlFor="input-username">User name</Label>
|
||||||
|
<div className="relative">
|
||||||
|
<Input
|
||||||
|
id="input-username"
|
||||||
|
className="peer ps-6"
|
||||||
|
type="text"
|
||||||
|
name="username"
|
||||||
|
placeholder="Username"
|
||||||
|
defaultValue={username}
|
||||||
|
/>
|
||||||
|
<span className="pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-2 text-sm text-muted-foreground peer-disabled:opacity-50">
|
||||||
|
@
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SubmitButton />
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
{!isEditing && (
|
||||||
<>
|
<>
|
||||||
<div className="flex flex-col gap-2 items-center">
|
<div className="flex gap-6">
|
||||||
<Avatar name={name} avatarUrl={avatarUrl} className="size-36" />
|
<StatsItem icon={Package2} label={stats.sandboxes} />
|
||||||
<div className="space-y-1">
|
<StatsItem icon={Heart} label={stats.likes} />
|
||||||
<CardTitle className="text-2xl text-center">{name}</CardTitle>
|
|
||||||
<CardDescription className="text-center">{`@${username}`}</CardDescription>
|
|
||||||
</div>
|
|
||||||
{bio && <p className="text-sm text-center">{bio}</p>}
|
|
||||||
{(socialLinks.length > 0 || personalWebsite) && (
|
|
||||||
<div className="flex gap-2 justify-center">
|
|
||||||
{personalWebsite && (
|
|
||||||
<Button variant="secondary" size="smIcon" asChild>
|
|
||||||
<a
|
|
||||||
href={personalWebsite}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Globe className="size-4" />
|
|
||||||
<span className="sr-only">Personal Website</span>
|
|
||||||
</a>
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{socialLinks.map((link, index) => {
|
|
||||||
const Icon = socialIcons[link.platform]
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
key={index}
|
|
||||||
variant="secondary"
|
|
||||||
size="smIcon"
|
|
||||||
asChild
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href={link.url}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Icon className="size-4" />
|
|
||||||
<span className="sr-only">{link.platform}</span>
|
|
||||||
</a>
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-1 items-center">
|
<div className="flex flex-col items-center gap-2">
|
||||||
|
<p className="text-xs text-muted-foreground">{joinedAt}</p>
|
||||||
{typeof generations === "number" && (
|
{typeof generations === "number" && (
|
||||||
<div className="flex justify-center">
|
<SubscriptionBadge
|
||||||
<SubscriptionBadge
|
generations={generations}
|
||||||
generations={generations}
|
tier={tier as keyof typeof TIERS}
|
||||||
tier={tier as keyof typeof TIERS}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
<div className="flex gap-4">
|
|
||||||
<StatsItem icon={Package2} label={stats.sandboxes} />
|
|
||||||
<StatsItem icon={Heart} label={stats.likes} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs mt-2 text-muted-foreground text-center">
|
|
||||||
{joinedAt}
|
|
||||||
</p>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
@ -304,213 +244,13 @@ function ProfileCard({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function EditProfileForm(props: {
|
function SubmitButton() {
|
||||||
name: string
|
const { pending } = useFormStatus()
|
||||||
username: string
|
|
||||||
avatarUrl: string | null
|
|
||||||
bio: string | null
|
|
||||||
personalWebsite: string | null
|
|
||||||
socialLinks: UserLink[]
|
|
||||||
toggleEdit: () => void
|
|
||||||
}) {
|
|
||||||
const router = useRouter()
|
|
||||||
const { user } = useUser()
|
|
||||||
const formRef = useRef<HTMLFormElement>(null)
|
|
||||||
const [formState, formAction] = useFormState(updateUser, {
|
|
||||||
message: "",
|
|
||||||
})
|
|
||||||
const [isPending, startTransition] = useTransition()
|
|
||||||
const { name, username, bio, personalWebsite, socialLinks, toggleEdit } =
|
|
||||||
props
|
|
||||||
const form = useForm<EditUserSchema>({
|
|
||||||
resolver: zodResolver(editUserSchema),
|
|
||||||
defaultValues: {
|
|
||||||
oldUsername: username,
|
|
||||||
id: user?.id,
|
|
||||||
name,
|
|
||||||
username,
|
|
||||||
bio: bio ?? "",
|
|
||||||
personalWebsite: personalWebsite ?? "",
|
|
||||||
links:
|
|
||||||
socialLinks.length > 0
|
|
||||||
? socialLinks
|
|
||||||
: [{ url: "", platform: "generic" }],
|
|
||||||
...(formState.fields ?? {}),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const { fields, append, remove } = useFieldArray({
|
|
||||||
name: "links",
|
|
||||||
control: form.control,
|
|
||||||
})
|
|
||||||
useEffect(() => {
|
|
||||||
const message = formState.message
|
|
||||||
if (!Boolean(message)) return
|
|
||||||
if ("error" in formState) {
|
|
||||||
toast.error(formState.message)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
toast.success(formState.message as String)
|
|
||||||
toggleEdit()
|
|
||||||
if (formState?.newRoute) {
|
|
||||||
router.replace(formState.newRoute)
|
|
||||||
}
|
|
||||||
}, [formState])
|
|
||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<Button size="sm" type="submit" className="w-full mt-2" disabled={pending}>
|
||||||
<form
|
{pending && <Loader2 className="animate-spin mr-2 h-4 w-4" />}
|
||||||
ref={formRef}
|
Save
|
||||||
action={formAction}
|
|
||||||
onSubmit={(evt) => {
|
|
||||||
evt.preventDefault()
|
|
||||||
form.handleSubmit(() => {
|
|
||||||
startTransition(() => {
|
|
||||||
formAction(new FormData(formRef.current!))
|
|
||||||
})
|
|
||||||
})(evt)
|
|
||||||
}}
|
|
||||||
className="space-y-3 w-full"
|
|
||||||
>
|
|
||||||
<input type="hidden" name="id" value={user?.id} />
|
|
||||||
<input type="hidden" name="oldUsername" value={username} />
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="name"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>Name</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input placeholder="marie doe" {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="username"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>User name</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<div className="relative">
|
|
||||||
<Input
|
|
||||||
className="peer ps-6"
|
|
||||||
type="text"
|
|
||||||
placeholder="Username"
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
<span className="pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-2 text-sm text-muted-foreground peer-disabled:opacity-50">
|
|
||||||
@
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="bio"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>Bio</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Textarea
|
|
||||||
placeholder="hi, I love building things!"
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="personalWebsite"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>Personal Website</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input placeholder="https://chillguy.dev" {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<div>
|
|
||||||
{fields.map((field, index) => (
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
key={field.id}
|
|
||||||
name={`links.${index}`}
|
|
||||||
render={({ field: { onChange, value, ...field } }) => {
|
|
||||||
const Icon = socialIcons[value.platform] ?? socialIcons.generic
|
|
||||||
return (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel className={cn(index !== 0 && "sr-only")}>
|
|
||||||
Social Links
|
|
||||||
</FormLabel>
|
|
||||||
<FormDescription className={cn(index !== 0 && "sr-only")}>
|
|
||||||
Add links to your blogs or social media profiles.
|
|
||||||
</FormDescription>
|
|
||||||
<FormControl>
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<div className="relative flex-1">
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
className="peer ps-9"
|
|
||||||
value={value.url}
|
|
||||||
onChange={(e) =>
|
|
||||||
onChange(parseSocialLink(e.currentTarget.value))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<div className="pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 text-muted-foreground/80 peer-disabled:opacity-50">
|
|
||||||
<Icon
|
|
||||||
size={16}
|
|
||||||
strokeWidth={2}
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
size="smIcon"
|
|
||||||
type="button"
|
|
||||||
variant="secondary"
|
|
||||||
onClick={() => remove(index)}
|
|
||||||
>
|
|
||||||
<Trash2 className="size-4" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
className="mt-2"
|
|
||||||
onClick={() => append({ url: "", platform: "generic" })}
|
|
||||||
>
|
|
||||||
Add URL
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<SubmitButton {...{ isPending }} />
|
|
||||||
</form>
|
|
||||||
</Form>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
function SubmitButton({ isPending }: { isPending: boolean }) {
|
|
||||||
const formStatus = useFormStatus()
|
|
||||||
const { pending } = formStatus
|
|
||||||
const pend = pending || isPending
|
|
||||||
return (
|
|
||||||
<Button size="sm" type="submit" className="w-full mt-2" disabled={pend}>
|
|
||||||
{pend && <Loader2 className="animate-spin mr-2 h-4 w-4" />}
|
|
||||||
Save Changes
|
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -701,8 +441,8 @@ interface StatsItemProps {
|
|||||||
|
|
||||||
const StatsItem = ({ icon: Icon, label }: StatsItemProps) => (
|
const StatsItem = ({ icon: Icon, label }: StatsItemProps) => (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Icon size={16} />
|
<Icon size={18} />
|
||||||
<span className="text-sm text-muted-foreground">{label}</span>
|
<span className="text-sm text-muted-foreground">{label}</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
// #endregion
|
// #endregion
|
||||||
@ -722,8 +462,8 @@ const SubscriptionBadge = ({
|
|||||||
</Badge>
|
</Badge>
|
||||||
<HoverCard>
|
<HoverCard>
|
||||||
<HoverCardTrigger>
|
<HoverCardTrigger>
|
||||||
<Button variant="ghost" size="smIcon" className="size-[26px]">
|
<Button variant="ghost" size="smIcon">
|
||||||
<Info size={16} />
|
<Info size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</HoverCardTrigger>
|
</HoverCardTrigger>
|
||||||
<HoverCardContent>
|
<HoverCardContent>
|
||||||
|
@ -9,19 +9,14 @@ import { Button } from "../ui/button"
|
|||||||
export default function ProfileNavbar({ userData }: { userData: User }) {
|
export default function ProfileNavbar({ userData }: { userData: User }) {
|
||||||
return (
|
return (
|
||||||
<nav className=" py-2 px-4 w-full flex items-center justify-between border-b border-border">
|
<nav className=" py-2 px-4 w-full flex items-center justify-between border-b border-border">
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-4">
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/"
|
||||||
className="ring-offset-2 ring-offset-background focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none rounded-sm"
|
className="ring-offset-2 ring-offset-background focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none rounded-sm"
|
||||||
>
|
>
|
||||||
<Image src={Logo} alt="Logo" width={36} height={36} />
|
<Image src={Logo} alt="Logo" width={36} height={36} />
|
||||||
</Link>
|
</Link>
|
||||||
<h1 className="text-xl">
|
<div className="text-sm font-medium flex items-center">Sandbox</div>
|
||||||
<span className="font-semibold">Sandbox</span>{" "}
|
|
||||||
<span className="text-xs font-medium text-muted-foreground">
|
|
||||||
by gitwit
|
|
||||||
</span>
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
<ThemeSwitcher />
|
<ThemeSwitcher />
|
||||||
|
@ -26,7 +26,7 @@ const buttonVariants = cva(
|
|||||||
sm: "h-8 rounded-md px-3 text-xs",
|
sm: "h-8 rounded-md px-3 text-xs",
|
||||||
lg: "h-10 rounded-md px-8",
|
lg: "h-10 rounded-md px-8",
|
||||||
icon: "h-9 w-9",
|
icon: "h-9 w-9",
|
||||||
smIcon: "size-8",
|
smIcon: "h-8 w-8",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import * as LabelPrimitive from "@radix-ui/react-label"
|
import * as LabelPrimitive from "@radix-ui/react-label"
|
||||||
import { Slot } from "@radix-ui/react-slot"
|
import { Slot } from "@radix-ui/react-slot"
|
||||||
|
import * as React from "react"
|
||||||
import {
|
import {
|
||||||
Controller,
|
Controller,
|
||||||
ControllerProps,
|
ControllerProps,
|
||||||
@ -12,8 +10,8 @@ import {
|
|||||||
useFormContext,
|
useFormContext,
|
||||||
} from "react-hook-form"
|
} from "react-hook-form"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
import { Label } from "@/components/ui/label"
|
import { Label } from "@/components/ui/label"
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
const Form = FormProvider
|
const Form = FormProvider
|
||||||
|
|
||||||
@ -95,7 +93,7 @@ const FormLabel = React.forwardRef<
|
|||||||
return (
|
return (
|
||||||
<Label
|
<Label
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(error && "text-destructive", className)}
|
className={cn(className)}
|
||||||
htmlFor={formItemId}
|
htmlFor={formItemId}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
@ -167,12 +165,12 @@ const FormMessage = React.forwardRef<
|
|||||||
FormMessage.displayName = "FormMessage"
|
FormMessage.displayName = "FormMessage"
|
||||||
|
|
||||||
export {
|
export {
|
||||||
useFormField,
|
|
||||||
Form,
|
Form,
|
||||||
FormItem,
|
|
||||||
FormLabel,
|
|
||||||
FormControl,
|
FormControl,
|
||||||
FormDescription,
|
FormDescription,
|
||||||
FormMessage,
|
|
||||||
FormField,
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
useFormField,
|
||||||
}
|
}
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
const ScrollArea = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<ScrollAreaPrimitive.Root
|
|
||||||
ref={ref}
|
|
||||||
className={cn("relative overflow-hidden", className)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
|
|
||||||
{children}
|
|
||||||
</ScrollAreaPrimitive.Viewport>
|
|
||||||
<ScrollBar />
|
|
||||||
<ScrollAreaPrimitive.Corner />
|
|
||||||
</ScrollAreaPrimitive.Root>
|
|
||||||
))
|
|
||||||
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
|
|
||||||
|
|
||||||
const ScrollBar = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
||||||
>(({ className, orientation = "vertical", ...props }, ref) => (
|
|
||||||
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
|
||||||
ref={ref}
|
|
||||||
orientation={orientation}
|
|
||||||
className={cn(
|
|
||||||
"flex touch-none select-none transition-colors",
|
|
||||||
orientation === "vertical" &&
|
|
||||||
"h-full w-2.5 border-l border-l-transparent p-[1px]",
|
|
||||||
orientation === "horizontal" &&
|
|
||||||
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
|
|
||||||
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
||||||
))
|
|
||||||
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
|
|
||||||
|
|
||||||
export { ScrollArea, ScrollBar }
|
|
@ -1,22 +0,0 @@
|
|||||||
import * as React from "react"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
const Textarea = React.forwardRef<
|
|
||||||
HTMLTextAreaElement,
|
|
||||||
React.ComponentProps<"textarea">
|
|
||||||
>(({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<textarea
|
|
||||||
className={cn(
|
|
||||||
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
Textarea.displayName = "Textarea"
|
|
||||||
|
|
||||||
export { Textarea }
|
|
@ -1,11 +1,8 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import { ThemeProvider as NextThemesProvider } from "next-themes"
|
import { ThemeProvider as NextThemesProvider } from "next-themes"
|
||||||
|
import { type ThemeProviderProps } from "next-themes/dist/types"
|
||||||
|
|
||||||
export function ThemeProvider({
|
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
||||||
children,
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof NextThemesProvider>) {
|
|
||||||
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
|
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
@ -29,4 +29,4 @@ const TooltipContent = React.forwardRef<
|
|||||||
))
|
))
|
||||||
TooltipContent.displayName = TooltipPrimitive.Content.displayName
|
TooltipContent.displayName = TooltipPrimitive.Content.displayName
|
||||||
|
|
||||||
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }
|
||||||
|
@ -2,9 +2,6 @@
|
|||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
import { revalidatePath } from "next/cache"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { editUserSchema } from "./schema"
|
|
||||||
import { UserLink } from "./types"
|
|
||||||
import { parseSocialLink } from "./utils"
|
|
||||||
|
|
||||||
export async function createSandbox(body: {
|
export async function createSandbox(body: {
|
||||||
type: string
|
type: string
|
||||||
@ -97,7 +94,7 @@ export async function unshareSandbox(sandboxId: string, userId: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function toggleLike(sandboxId: string, userId: string) {
|
export async function toggleLike(sandboxId: string, userId: string) {
|
||||||
const res = await fetch(
|
await fetch(
|
||||||
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/sandbox/like`,
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/sandbox/like`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@ -126,31 +123,20 @@ const UpdateErrorSchema = z.object({
|
|||||||
.optional(),
|
.optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
interface FormState {
|
export async function updateUser(prevState: any, formData: FormData) {
|
||||||
message: string
|
const data = Object.fromEntries(formData)
|
||||||
error?: any
|
|
||||||
newRoute?: string
|
const schema = z.object({
|
||||||
fields?: Record<string, unknown>
|
id: z.string(),
|
||||||
}
|
username: z.string(),
|
||||||
export async function updateUser(
|
oldUsername: z.string(),
|
||||||
prevState: any,
|
name: z.string(),
|
||||||
formData: FormData
|
|
||||||
): Promise<FormState> {
|
|
||||||
let data = Object.fromEntries(formData)
|
|
||||||
let links: UserLink[] = []
|
|
||||||
Object.entries(data).forEach(([key, value]) => {
|
|
||||||
if (key.startsWith("link")) {
|
|
||||||
const [_, index] = key.split(".")
|
|
||||||
if (value) {
|
|
||||||
links.splice(parseInt(index), 0, parseSocialLink(value as string))
|
|
||||||
delete data[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
// @ts-ignore
|
console.log(data)
|
||||||
data.links = links
|
|
||||||
try {
|
try {
|
||||||
const validatedData = editUserSchema.parse(data)
|
const validatedData = schema.parse(data)
|
||||||
|
|
||||||
const changedUsername = validatedData.username !== validatedData.oldUsername
|
const changedUsername = validatedData.username !== validatedData.oldUsername
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/user`,
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/user`,
|
||||||
@ -164,9 +150,6 @@ export async function updateUser(
|
|||||||
id: validatedData.id,
|
id: validatedData.id,
|
||||||
username: data.username ?? undefined,
|
username: data.username ?? undefined,
|
||||||
name: data.name ?? undefined,
|
name: data.name ?? undefined,
|
||||||
bio: data.bio ?? undefined,
|
|
||||||
personalWebsite: data.personalWebsite ?? undefined,
|
|
||||||
links: data.links ?? undefined,
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -177,11 +160,11 @@ export async function updateUser(
|
|||||||
const parseResult = UpdateErrorSchema.safeParse(responseData)
|
const parseResult = UpdateErrorSchema.safeParse(responseData)
|
||||||
|
|
||||||
if (!parseResult.success) {
|
if (!parseResult.success) {
|
||||||
return {
|
return { error: "Unexpected error occurred" }
|
||||||
message: "Unexpected error occurred",
|
}
|
||||||
error: parseResult.error,
|
|
||||||
fields: validatedData,
|
if (parseResult.data.error) {
|
||||||
}
|
return parseResult.data
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedUsername) {
|
if (changedUsername) {
|
||||||
@ -192,13 +175,12 @@ export async function updateUser(
|
|||||||
return { message: "Successfully updated" }
|
return { message: "Successfully updated" }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof z.ZodError) {
|
if (error instanceof z.ZodError) {
|
||||||
|
console.log(error)
|
||||||
return {
|
return {
|
||||||
message: "Invalid data",
|
error: error.errors?.[0].message,
|
||||||
error: error.errors,
|
|
||||||
fields: data,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { message: "An unexpected error occurred", fields: data }
|
return { error: "An unexpected error occurred" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
export const KNOWN_PLATFORMS = [
|
|
||||||
"github",
|
|
||||||
"twitter",
|
|
||||||
"instagram",
|
|
||||||
"bluesky",
|
|
||||||
"linkedin",
|
|
||||||
"youtube",
|
|
||||||
"twitch",
|
|
||||||
"discord",
|
|
||||||
"mastodon",
|
|
||||||
"threads",
|
|
||||||
"gitlab",
|
|
||||||
"generic",
|
|
||||||
] as const
|
|
@ -1,37 +1,3 @@
|
|||||||
import {
|
|
||||||
AtSign,
|
|
||||||
Github,
|
|
||||||
GitlabIcon as GitlabLogo,
|
|
||||||
Globe,
|
|
||||||
Instagram,
|
|
||||||
Link,
|
|
||||||
Linkedin,
|
|
||||||
MessageCircle,
|
|
||||||
Twitch,
|
|
||||||
Twitter,
|
|
||||||
Youtube,
|
|
||||||
} from "lucide-react"
|
|
||||||
import { KnownPlatform } from "../types"
|
|
||||||
|
|
||||||
export const socialIcons: Record<
|
|
||||||
KnownPlatform | "website",
|
|
||||||
React.ComponentType<any>
|
|
||||||
> = {
|
|
||||||
github: Github,
|
|
||||||
twitter: Twitter,
|
|
||||||
instagram: Instagram,
|
|
||||||
bluesky: AtSign,
|
|
||||||
linkedin: Linkedin,
|
|
||||||
youtube: Youtube,
|
|
||||||
twitch: Twitch,
|
|
||||||
discord: MessageCircle,
|
|
||||||
mastodon: AtSign,
|
|
||||||
threads: AtSign,
|
|
||||||
gitlab: GitlabLogo,
|
|
||||||
generic: Link,
|
|
||||||
website: Globe,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const projectTemplates: {
|
export const projectTemplates: {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
import { z } from "zod"
|
|
||||||
import { KNOWN_PLATFORMS } from "../constants"
|
|
||||||
|
|
||||||
export const editUserSchema = z.object({
|
|
||||||
id: z.string().trim(),
|
|
||||||
username: z.string().trim().min(1, "Username must be at least 1 character"),
|
|
||||||
oldUsername: z.string().trim(),
|
|
||||||
name: z.string().trim().min(1, "Name must be at least 1 character"),
|
|
||||||
bio: z.string().trim().optional(),
|
|
||||||
personalWebsite: z.string().trim().optional(),
|
|
||||||
links: z
|
|
||||||
.array(
|
|
||||||
z.object({
|
|
||||||
url: z.string().trim(),
|
|
||||||
platform: z.enum(KNOWN_PLATFORMS),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.catch([]),
|
|
||||||
})
|
|
||||||
export type EditUserSchema = z.infer<typeof editUserSchema>
|
|
@ -1,7 +1,5 @@
|
|||||||
// DB Types
|
// DB Types
|
||||||
|
|
||||||
import { KNOWN_PLATFORMS } from "./constants"
|
|
||||||
|
|
||||||
export type User = {
|
export type User = {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
@ -10,20 +8,11 @@ export type User = {
|
|||||||
avatarUrl: string | null
|
avatarUrl: string | null
|
||||||
createdAt: Date
|
createdAt: Date
|
||||||
generations: number
|
generations: number
|
||||||
bio: string | null
|
|
||||||
personalWebsite: string | null
|
|
||||||
links: UserLink[]
|
|
||||||
tier: "FREE" | "PRO" | "ENTERPRISE"
|
|
||||||
tierExpiresAt: Date
|
|
||||||
lastResetDate: number
|
|
||||||
sandbox: Sandbox[]
|
sandbox: Sandbox[]
|
||||||
usersToSandboxes: UsersToSandboxes[]
|
usersToSandboxes: UsersToSandboxes[]
|
||||||
}
|
tier: "FREE" | "PRO" | "ENTERPRISE"
|
||||||
|
tierExpiresAt: Date
|
||||||
export type KnownPlatform = (typeof KNOWN_PLATFORMS)[number]
|
lastResetDate?: number
|
||||||
export type UserLink = {
|
|
||||||
url: string
|
|
||||||
platform: KnownPlatform
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Sandbox = {
|
export type Sandbox = {
|
||||||
|
@ -2,7 +2,7 @@ import { type ClassValue, clsx } from "clsx"
|
|||||||
// import { toast } from "sonner"
|
// import { toast } from "sonner"
|
||||||
import { twMerge } from "tailwind-merge"
|
import { twMerge } from "tailwind-merge"
|
||||||
import fileExtToLang from "./file-extension-to-language.json"
|
import fileExtToLang from "./file-extension-to-language.json"
|
||||||
import { KnownPlatform, TFile, TFolder, UserLink } from "./types"
|
import { TFile, TFolder } from "./types"
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs))
|
return twMerge(clsx(inputs))
|
||||||
@ -98,57 +98,3 @@ export function sortFileExplorer(
|
|||||||
return item
|
return item
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseSocialLink(url: string): UserLink {
|
|
||||||
try {
|
|
||||||
// Handle empty or invalid URLs
|
|
||||||
if (!url) return { url: "", platform: "generic" }
|
|
||||||
|
|
||||||
// Remove protocol and www prefix for consistent parsing
|
|
||||||
const cleanUrl = url
|
|
||||||
.toLowerCase()
|
|
||||||
.replace(/^https?:\/\//, "")
|
|
||||||
.replace(/^www\./, "")
|
|
||||||
.split("/")[0] // Get just the domain part
|
|
||||||
|
|
||||||
// Platform detection mapping
|
|
||||||
const platformPatterns: Record<
|
|
||||||
Exclude<KnownPlatform, "generic">,
|
|
||||||
RegExp
|
|
||||||
> = {
|
|
||||||
github: /github\.com/,
|
|
||||||
twitter: /(?:twitter\.com|x\.com|t\.co)/,
|
|
||||||
instagram: /instagram\.com/,
|
|
||||||
bluesky: /(?:bsky\.app|bluesky\.social)/,
|
|
||||||
linkedin: /linkedin\.com/,
|
|
||||||
youtube: /(?:youtube\.com|youtu\.be)/,
|
|
||||||
twitch: /twitch\.tv/,
|
|
||||||
discord: /discord\.(?:gg|com)/,
|
|
||||||
mastodon: /mastodon\.(?:social|online|world)/,
|
|
||||||
threads: /threads\.net/,
|
|
||||||
gitlab: /gitlab\.com/,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check URL against each pattern
|
|
||||||
for (const [platform, pattern] of Object.entries(platformPatterns)) {
|
|
||||||
if (pattern.test(cleanUrl)) {
|
|
||||||
return {
|
|
||||||
url,
|
|
||||||
platform: platform as KnownPlatform,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fall back to generic if no match found
|
|
||||||
return {
|
|
||||||
url,
|
|
||||||
platform: "generic",
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error parsing social link:", error)
|
|
||||||
return {
|
|
||||||
url: url || "",
|
|
||||||
platform: "generic",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
512
frontend/package-lock.json
generated
512
frontend/package-lock.json
generated
@ -13,7 +13,7 @@
|
|||||||
"@clerk/nextjs": "^4.29.12",
|
"@clerk/nextjs": "^4.29.12",
|
||||||
"@clerk/themes": "^1.7.12",
|
"@clerk/themes": "^1.7.12",
|
||||||
"@codemirror/lang-javascript": "^6.2.2",
|
"@codemirror/lang-javascript": "^6.2.2",
|
||||||
"@hookform/resolvers": "^3.9.1",
|
"@hookform/resolvers": "^3.3.4",
|
||||||
"@liveblocks/client": "^1.12.0",
|
"@liveblocks/client": "^1.12.0",
|
||||||
"@liveblocks/node": "^1.12.0",
|
"@liveblocks/node": "^1.12.0",
|
||||||
"@liveblocks/react": "^1.12.0",
|
"@liveblocks/react": "^1.12.0",
|
||||||
@ -27,15 +27,14 @@
|
|||||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||||
"@radix-ui/react-hover-card": "^1.1.2",
|
"@radix-ui/react-hover-card": "^1.1.2",
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.1.1",
|
"@radix-ui/react-label": "^2.0.2",
|
||||||
"@radix-ui/react-popover": "^1.1.1",
|
"@radix-ui/react-popover": "^1.1.1",
|
||||||
"@radix-ui/react-progress": "^1.1.0",
|
"@radix-ui/react-progress": "^1.1.0",
|
||||||
"@radix-ui/react-scroll-area": "^1.2.2",
|
|
||||||
"@radix-ui/react-select": "^2.0.0",
|
"@radix-ui/react-select": "^2.0.0",
|
||||||
"@radix-ui/react-slot": "^1.1.1",
|
"@radix-ui/react-slot": "^1.0.2",
|
||||||
"@radix-ui/react-switch": "^1.0.3",
|
"@radix-ui/react-switch": "^1.0.3",
|
||||||
"@radix-ui/react-tabs": "^1.1.1",
|
"@radix-ui/react-tabs": "^1.1.1",
|
||||||
"@radix-ui/react-tooltip": "^1.1.6",
|
"@radix-ui/react-tooltip": "^1.1.3",
|
||||||
"@react-three/fiber": "^8.16.6",
|
"@react-three/fiber": "^8.16.6",
|
||||||
"@uiw/codemirror-theme-vscode": "^4.23.5",
|
"@uiw/codemirror-theme-vscode": "^4.23.5",
|
||||||
"@uiw/react-codemirror": "^4.23.5",
|
"@uiw/react-codemirror": "^4.23.5",
|
||||||
@ -54,12 +53,12 @@
|
|||||||
"lucide-react": "^0.365.0",
|
"lucide-react": "^0.365.0",
|
||||||
"monaco-themes": "^0.4.4",
|
"monaco-themes": "^0.4.4",
|
||||||
"next": "14.1.3",
|
"next": "14.1.3",
|
||||||
"next-themes": "^0.4.4",
|
"next-themes": "^0.3.0",
|
||||||
"openai": "^4.73.1",
|
"openai": "^4.73.1",
|
||||||
"posthog-js": "^1.147.0",
|
"posthog-js": "^1.147.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.51.3",
|
||||||
"react-markdown": "^9.0.1",
|
"react-markdown": "^9.0.1",
|
||||||
"react-resizable-panels": "^2.0.16",
|
"react-resizable-panels": "^2.0.16",
|
||||||
"react-syntax-highlighter": "^15.5.0",
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
@ -74,7 +73,7 @@
|
|||||||
"y-monaco": "^0.1.5",
|
"y-monaco": "^0.1.5",
|
||||||
"y-protocols": "^1.0.6",
|
"y-protocols": "^1.0.6",
|
||||||
"yjs": "^13.6.15",
|
"yjs": "^13.6.15",
|
||||||
"zod": "^3.24.1"
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/estree": "^1.0.6",
|
"@types/estree": "^1.0.6",
|
||||||
@ -910,9 +909,9 @@
|
|||||||
"integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
|
"integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
|
||||||
},
|
},
|
||||||
"node_modules/@hookform/resolvers": {
|
"node_modules/@hookform/resolvers": {
|
||||||
"version": "3.9.1",
|
"version": "3.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.3.4.tgz",
|
||||||
"integrity": "sha512-ud2HqmGBM0P0IABqoskKWI6PEf6ZDDBZkFqe2Vnl+mTHCEHzr3ISjjZyCwTjC/qpL25JC9aIDkloQejvMeq0ug==",
|
"integrity": "sha512-o5cgpGOuJYrd+iMKvkttOclgwRW86EsWJZZRC23prf0uU2i48Htq4PuT73AVb9ionFyZrwYEITuOFGF+BydEtQ==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react-hook-form": "^7.0.0"
|
"react-hook-form": "^7.0.0"
|
||||||
}
|
}
|
||||||
@ -1366,24 +1365,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-slot": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.13.10",
|
|
||||||
"@radix-ui/react-compose-refs": "1.0.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-arrow": {
|
"node_modules/@radix-ui/react-arrow": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz",
|
||||||
@ -1553,24 +1534,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.13.10",
|
|
||||||
"@radix-ui/react-compose-refs": "1.0.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-compose-refs": {
|
"node_modules/@radix-ui/react-compose-refs": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz",
|
||||||
@ -1669,24 +1632,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.13.10",
|
|
||||||
"@radix-ui/react-compose-refs": "1.0.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-direction": {
|
"node_modules/@radix-ui/react-direction": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz",
|
||||||
@ -2171,39 +2116,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-label": {
|
"node_modules/@radix-ui/react-label": {
|
||||||
"version": "2.1.1",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz",
|
||||||
"integrity": "sha512-UUw5E4e/2+4kFMH7+YxORXGWggtY6sM8WIwh5RZchhLuUg2H1hc98Py+pr8HMz6rdaYrK2t296ZEjYLOCO5uUw==",
|
"integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-primitive": "2.0.1"
|
"@babel/runtime": "^7.13.10",
|
||||||
|
"@radix-ui/react-primitive": "1.0.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
"@types/react": "*",
|
||||||
"@types/react-dom": "*",
|
"@types/react-dom": "*",
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
"react": "^16.8 || ^17.0 || ^18.0",
|
||||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@types/react-dom": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@radix-ui/react-slot": "1.1.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"@types/react-dom": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
|
||||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@types/react": {
|
"@types/react": {
|
||||||
@ -2254,24 +2178,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.13.10",
|
|
||||||
"@radix-ui/react-compose-refs": "1.0.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-popover": {
|
"node_modules/@radix-ui/react-popover": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.1.tgz",
|
||||||
@ -2787,24 +2693,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.13.10",
|
|
||||||
"@radix-ui/react-compose-refs": "1.0.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-progress": {
|
"node_modules/@radix-ui/react-progress": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.0.tgz",
|
||||||
@ -2930,161 +2818,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-scroll-area": {
|
|
||||||
"version": "1.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.2.tgz",
|
|
||||||
"integrity": "sha512-EFI1N/S3YxZEW/lJ/H1jY3njlvTd8tBmgKEn4GHi51+aMm94i6NmAJstsm5cu3yJwYqYc93gpCPm21FeAbFk6g==",
|
|
||||||
"dependencies": {
|
|
||||||
"@radix-ui/number": "1.1.0",
|
|
||||||
"@radix-ui/primitive": "1.1.1",
|
|
||||||
"@radix-ui/react-compose-refs": "1.1.1",
|
|
||||||
"@radix-ui/react-context": "1.1.1",
|
|
||||||
"@radix-ui/react-direction": "1.1.0",
|
|
||||||
"@radix-ui/react-presence": "1.1.2",
|
|
||||||
"@radix-ui/react-primitive": "2.0.1",
|
|
||||||
"@radix-ui/react-use-callback-ref": "1.1.0",
|
|
||||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"@types/react-dom": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
|
||||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@types/react-dom": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/number": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ=="
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/primitive": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-compose-refs": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-context": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-direction": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-presence": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@radix-ui/react-compose-refs": "1.1.1",
|
|
||||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"@types/react-dom": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
|
||||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@types/react-dom": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-primitive": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@radix-ui/react-slot": "1.1.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"@types/react-dom": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
|
||||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@types/react-dom": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-use-callback-ref": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-use-layout-effect": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-select": {
|
"node_modules/@radix-ui/react-select": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.0.0.tgz",
|
||||||
@ -3128,7 +2861,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
|
"node_modules/@radix-ui/react-slot": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||||
@ -3146,37 +2879,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-slot": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
|
|
||||||
"dependencies": {
|
|
||||||
"@radix-ui/react-compose-refs": "1.1.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "*",
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@radix-ui/react-switch": {
|
"node_modules/@radix-ui/react-switch": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.3.tgz",
|
||||||
@ -3490,22 +3192,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-tooltip": {
|
"node_modules/@radix-ui/react-tooltip": {
|
||||||
"version": "1.1.6",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.3.tgz",
|
||||||
"integrity": "sha512-TLB5D8QLExS1uDn7+wH/bjEmRurNMTzNrtq7IjaS4kjion9NtzsTGkvR5+i7yc9q01Pi2KMM2cN3f8UG4IvvXA==",
|
"integrity": "sha512-Z4w1FIS0BqVFI2c1jZvb/uDVJijJjJ2ZMuPV81oVgTZ7g3BZxobplnMVvXtFWgtozdvYJ+MFWtwkM5S2HnAong==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/primitive": "1.1.1",
|
"@radix-ui/primitive": "1.1.0",
|
||||||
"@radix-ui/react-compose-refs": "1.1.1",
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
"@radix-ui/react-context": "1.1.1",
|
"@radix-ui/react-context": "1.1.1",
|
||||||
"@radix-ui/react-dismissable-layer": "1.1.3",
|
"@radix-ui/react-dismissable-layer": "1.1.1",
|
||||||
"@radix-ui/react-id": "1.1.0",
|
"@radix-ui/react-id": "1.1.0",
|
||||||
"@radix-ui/react-popper": "1.2.1",
|
"@radix-ui/react-popper": "1.2.0",
|
||||||
"@radix-ui/react-portal": "1.1.3",
|
"@radix-ui/react-portal": "1.1.2",
|
||||||
"@radix-ui/react-presence": "1.1.2",
|
"@radix-ui/react-presence": "1.1.1",
|
||||||
"@radix-ui/react-primitive": "2.0.1",
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
"@radix-ui/react-slot": "1.1.1",
|
"@radix-ui/react-slot": "1.1.0",
|
||||||
"@radix-ui/react-use-controllable-state": "1.1.0",
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||||
"@radix-ui/react-visually-hidden": "1.1.1"
|
"@radix-ui/react-visually-hidden": "1.1.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
"@types/react": "*",
|
||||||
@ -3523,16 +3226,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/primitive": {
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/primitive": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz",
|
||||||
"integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="
|
"integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-arrow": {
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-arrow": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz",
|
||||||
"integrity": "sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==",
|
"integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-primitive": "2.0.1"
|
"@radix-ui/react-primitive": "2.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
"@types/react": "*",
|
||||||
@ -3550,9 +3255,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-compose-refs": {
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-compose-refs": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz",
|
||||||
"integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
|
"integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==",
|
||||||
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
"@types/react": "*",
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
@ -3579,13 +3285,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-dismissable-layer": {
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-dismissable-layer": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz",
|
||||||
"integrity": "sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==",
|
"integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/primitive": "1.1.1",
|
"@radix-ui/primitive": "1.1.0",
|
||||||
"@radix-ui/react-compose-refs": "1.1.1",
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
"@radix-ui/react-primitive": "2.0.1",
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
"@radix-ui/react-use-callback-ref": "1.1.0",
|
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||||
"@radix-ui/react-use-escape-keydown": "1.1.0"
|
"@radix-ui/react-use-escape-keydown": "1.1.0"
|
||||||
},
|
},
|
||||||
@ -3623,15 +3330,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper": {
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
|
||||||
"integrity": "sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw==",
|
"integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/react-dom": "^2.0.0",
|
"@floating-ui/react-dom": "^2.0.0",
|
||||||
"@radix-ui/react-arrow": "1.1.1",
|
"@radix-ui/react-arrow": "1.1.0",
|
||||||
"@radix-ui/react-compose-refs": "1.1.1",
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
"@radix-ui/react-context": "1.1.1",
|
"@radix-ui/react-context": "1.1.0",
|
||||||
"@radix-ui/react-primitive": "2.0.1",
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
"@radix-ui/react-use-callback-ref": "1.1.0",
|
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||||
"@radix-ui/react-use-layout-effect": "1.1.0",
|
"@radix-ui/react-use-layout-effect": "1.1.0",
|
||||||
"@radix-ui/react-use-rect": "1.1.0",
|
"@radix-ui/react-use-rect": "1.1.0",
|
||||||
@ -3653,12 +3361,28 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-portal": {
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-portal": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz",
|
||||||
"integrity": "sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==",
|
"integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-primitive": "2.0.1",
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@ -3677,11 +3401,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-presence": {
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-presence": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz",
|
||||||
"integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==",
|
"integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-compose-refs": "1.1.1",
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@ -3700,11 +3425,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": {
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz",
|
||||||
"integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
|
"integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-slot": "1.1.1"
|
"@radix-ui/react-slot": "1.1.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
"@types/react": "*",
|
||||||
@ -3721,6 +3447,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-callback-ref": {
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-callback-ref": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
|
||||||
@ -3758,6 +3502,7 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
|
||||||
"integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==",
|
"integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-use-callback-ref": "1.1.0"
|
"@radix-ui/react-use-callback-ref": "1.1.0"
|
||||||
},
|
},
|
||||||
@ -3790,6 +3535,7 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz",
|
||||||
"integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==",
|
"integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/rect": "1.1.0"
|
"@radix-ui/rect": "1.1.0"
|
||||||
},
|
},
|
||||||
@ -3807,6 +3553,7 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz",
|
||||||
"integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==",
|
"integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||||
},
|
},
|
||||||
@ -3821,11 +3568,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-visually-hidden": {
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-visually-hidden": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz",
|
||||||
"integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==",
|
"integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-primitive": "2.0.1"
|
"@radix-ui/react-primitive": "2.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
"@types/react": "*",
|
||||||
@ -3845,7 +3593,8 @@
|
|||||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/rect": {
|
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/rect": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz",
|
||||||
"integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg=="
|
"integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-use-callback-ref": {
|
"node_modules/@radix-ui/react-use-callback-ref": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -7576,13 +7325,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/next-themes": {
|
"node_modules/next-themes": {
|
||||||
"version": "0.4.4",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz",
|
||||||
"integrity": "sha512-LDQ2qIOJF0VnuVrrMSMLrWGjRMkq+0mpgl6e0juCLqdJ+oo8Q84JRWT6Wh11VDQKkMMe+dVzDKLWs5n87T+PkQ==",
|
"integrity": "sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==",
|
||||||
"license": "MIT",
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc",
|
"react": "^16.8 || ^17 || ^18",
|
||||||
"react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc"
|
"react-dom": "^16.8 || ^17 || ^18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/next/node_modules/postcss": {
|
"node_modules/next/node_modules/postcss": {
|
||||||
@ -8280,18 +8028,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-hook-form": {
|
"node_modules/react-hook-form": {
|
||||||
"version": "7.54.2",
|
"version": "7.51.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.3.tgz",
|
||||||
"integrity": "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==",
|
"integrity": "sha512-cvJ/wbHdhYx8aviSWh28w9ImjmVsb5Y05n1+FW786vEZQJV5STNM0pW6ujS+oiBecb0ARBxJFyAnXj9+GHXACQ==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0"
|
"node": ">=12.22.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/react-hook-form"
|
"url": "https://opencollective.com/react-hook-form"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.8.0 || ^17 || ^18 || ^19"
|
"react": "^16.8.0 || ^17 || ^18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-markdown": {
|
"node_modules/react-markdown": {
|
||||||
@ -9976,9 +9724,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/zod": {
|
"node_modules/zod": {
|
||||||
"version": "3.24.1",
|
"version": "3.23.8",
|
||||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz",
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
|
||||||
"integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==",
|
"integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
"@clerk/nextjs": "^4.29.12",
|
"@clerk/nextjs": "^4.29.12",
|
||||||
"@clerk/themes": "^1.7.12",
|
"@clerk/themes": "^1.7.12",
|
||||||
"@codemirror/lang-javascript": "^6.2.2",
|
"@codemirror/lang-javascript": "^6.2.2",
|
||||||
"@hookform/resolvers": "^3.9.1",
|
"@hookform/resolvers": "^3.3.4",
|
||||||
"@liveblocks/client": "^1.12.0",
|
"@liveblocks/client": "^1.12.0",
|
||||||
"@liveblocks/node": "^1.12.0",
|
"@liveblocks/node": "^1.12.0",
|
||||||
"@liveblocks/react": "^1.12.0",
|
"@liveblocks/react": "^1.12.0",
|
||||||
@ -28,15 +28,14 @@
|
|||||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||||
"@radix-ui/react-hover-card": "^1.1.2",
|
"@radix-ui/react-hover-card": "^1.1.2",
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.1.1",
|
"@radix-ui/react-label": "^2.0.2",
|
||||||
"@radix-ui/react-popover": "^1.1.1",
|
"@radix-ui/react-popover": "^1.1.1",
|
||||||
"@radix-ui/react-progress": "^1.1.0",
|
"@radix-ui/react-progress": "^1.1.0",
|
||||||
"@radix-ui/react-scroll-area": "^1.2.2",
|
|
||||||
"@radix-ui/react-select": "^2.0.0",
|
"@radix-ui/react-select": "^2.0.0",
|
||||||
"@radix-ui/react-slot": "^1.1.1",
|
"@radix-ui/react-slot": "^1.0.2",
|
||||||
"@radix-ui/react-switch": "^1.0.3",
|
"@radix-ui/react-switch": "^1.0.3",
|
||||||
"@radix-ui/react-tabs": "^1.1.1",
|
"@radix-ui/react-tabs": "^1.1.1",
|
||||||
"@radix-ui/react-tooltip": "^1.1.6",
|
"@radix-ui/react-tooltip": "^1.1.3",
|
||||||
"@react-three/fiber": "^8.16.6",
|
"@react-three/fiber": "^8.16.6",
|
||||||
"@uiw/codemirror-theme-vscode": "^4.23.5",
|
"@uiw/codemirror-theme-vscode": "^4.23.5",
|
||||||
"@uiw/react-codemirror": "^4.23.5",
|
"@uiw/react-codemirror": "^4.23.5",
|
||||||
@ -55,12 +54,12 @@
|
|||||||
"lucide-react": "^0.365.0",
|
"lucide-react": "^0.365.0",
|
||||||
"monaco-themes": "^0.4.4",
|
"monaco-themes": "^0.4.4",
|
||||||
"next": "14.1.3",
|
"next": "14.1.3",
|
||||||
"next-themes": "^0.4.4",
|
"next-themes": "^0.3.0",
|
||||||
"openai": "^4.73.1",
|
"openai": "^4.73.1",
|
||||||
"posthog-js": "^1.147.0",
|
"posthog-js": "^1.147.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.51.3",
|
||||||
"react-markdown": "^9.0.1",
|
"react-markdown": "^9.0.1",
|
||||||
"react-resizable-panels": "^2.0.16",
|
"react-resizable-panels": "^2.0.16",
|
||||||
"react-syntax-highlighter": "^15.5.0",
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
@ -75,7 +74,7 @@
|
|||||||
"y-monaco": "^0.1.5",
|
"y-monaco": "^0.1.5",
|
||||||
"y-protocols": "^1.0.6",
|
"y-protocols": "^1.0.6",
|
||||||
"yjs": "^13.6.15",
|
"yjs": "^13.6.15",
|
||||||
"zod": "^3.24.1"
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/estree": "^1.0.6",
|
"@types/estree": "^1.0.6",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user