Made great progress on monorepo & auth for next. Very happy with work!

This commit is contained in:
gib committed 2026-01-12 11:55:15 -06:00
1 parent 72f11f0b02
commit 321fecb5e1
58 files changed
+1266 -222

No files matched your search

+1 -1
View File
@@ -1 +1 @@
[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15"],{"key":"16","value":"17"},{"key":"18","value":"19"},{"key":"20","value":"21"},{"key":"22","value":"23"},{"key":"24","value":"25"},{"key":"26","value":"27"},{"key":"28","value":"29"},{"key":"30","value":"31"},{"key":"32","value":"33"},{"key":"34","value":"35"},{"key":"36","value":"37"},{"key":"38","value":"39"},{"key":"40","value":"41"},{"key":"42","value":"43"},{"key":"44","value":"45"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/.cache/.prettiercache",{"size":3699,"mtime":1766222924000,"hash":"46"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/dataModel.d.ts",{"size":1726,"mtime":1768155639236,"hash":"47","data":"48"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/.gitignore",{"size":16,"mtime":1766222924000,"hash":"49"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/utils.ts",{"size":635,"mtime":1768155639993,"hash":"50","data":"51"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/tsconfig.json",{"size":732,"mtime":1766222924000,"hash":"52","data":"53"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/package.json",{"size":1120,"mtime":1766223702000,"hash":"54","data":"55"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/server.js",{"size":3453,"mtime":1768155639358,"hash":"56","data":"57"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/auth.config.js",{"size":128,"mtime":1768155639410,"hash":"58","data":"59"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/notes.ts",{"size":1632,"mtime":1768155639618,"hash":"60","data":"61"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/server.d.ts",{"size":5540,"mtime":1768155639312,"hash":"62","data":"63"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/api.d.ts",{"size":845,"mtime":1768155639122,"hash":"64","data":"65"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/api.js",{"size":414,"mtime":1768155639185,"hash":"66","data":"67"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/README.md",{"size":2525,"mtime":1768155639908,"hash":"68","data":"69"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/openai.ts",{"size":2036,"mtime":1768155639718,"hash":"70","data":"71"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/schema.ts",{"size":267,"mtime":1768155639933,"hash":"72","data":"73"},"bf09c6d61dd6a010bca24cb05271176d","ce3275ccdd28673d7e9280b33792057c",{"hashOfOptions":"74"},"175b1a771387d8b7e26145c3d04e0475","6a3198db454396c63e99ee08065726bd",{"hashOfOptions":"75"},"cfa98923457caed911ec68b626ef4234",{"hashOfOptions":"76"},"355d413e63d71e7e2107534f0d82fa31",{"hashOfOptions":"77"},"a8efc7f01f2b2dcb19115187a6f5f935",{"hashOfOptions":"78"},"449225bb5e883c1319e2ade335cdf0ad",{"hashOfOptions":"79"},"4b3c533672165e2af8d66b7149f85e1b",{"hashOfOptions":"80"},"896efcfb7466854312acff830348fec5",{"hashOfOptions":"81"},"8effb22a4ee737ecaeb923db430289f9",{"hashOfOptions":"82"},"0f5f819cfc410629d8ba1209956a037c",{"hashOfOptions":"83"},"f5aa8269478f140adb4ccf0470dd1244",{"hashOfOptions":"84"},"e06978cd8943c0adfa4d2a855c8f3627",{"hashOfOptions":"85"},"0d3d6e28d2429a34e666323218320d74",{"hashOfOptions":"86"},"1690245769","3139400620","2702670119","1723032970","1018051749","1593187711","1215337372","3786452325","2623319630","3362284046","3941219177","30277581","3515117182"]
[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23"],{"key":"24","value":"25"},{"key":"26","value":"27"},{"key":"28","value":"29"},{"key":"30","value":"31"},{"key":"32","value":"33"},{"key":"34","value":"35"},{"key":"36","value":"37"},{"key":"38","value":"39"},{"key":"40","value":"41"},{"key":"42","value":"43"},{"key":"44","value":"45"},{"key":"46","value":"47"},{"key":"48","value":"49"},{"key":"50","value":"51"},{"key":"52","value":"53"},{"key":"54","value":"55"},{"key":"56","value":"57"},{"key":"58","value":"59"},{"key":"60","value":"61"},{"key":"62","value":"63"},{"key":"64","value":"65"},{"key":"66","value":"67"},{"key":"68","value":"69"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/.cache/.prettiercache",{"size":3533,"mtime":1768171236843,"hash":"70"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/crons.ts",{"size":528,"mtime":1768239263662,"hash":"71","data":"72"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/auth.ts",{"size":3630,"mtime":1768239263654,"hash":"73","data":"74"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/custom/auth/providers/password.ts",{"size":900,"mtime":1768239263701,"hash":"75","data":"76"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/dataModel.d.ts",{"size":1726,"mtime":1768239263554,"hash":"77","data":"78"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/.gitignore",{"size":16,"mtime":1766222924000,"hash":"79"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/utils.ts",{"size":635,"mtime":1768155639000,"hash":"80","data":"81"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/auth.config.ts",{"size":127,"mtime":1768156477000,"hash":"82","data":"83"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/tsconfig.json",{"size":732,"mtime":1766222924000,"hash":"84","data":"85"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/package.json",{"size":1300,"mtime":1768239263823,"hash":"86","data":"87"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/custom/auth/providers/usesend.ts",{"size":3115,"mtime":1768164053000,"hash":"88","data":"89"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/server.js",{"size":3474,"mtime":1768239263584,"hash":"90","data":"91"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/server.d.ts",{"size":5695,"mtime":1768239263572,"hash":"92","data":"93"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/types/auth.ts",{"size":174,"mtime":1768188156942,"hash":"94","data":"95"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/files.ts",{"size":582,"mtime":1768239263763,"hash":"96","data":"97"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/scripts/generateKeys.mjs",{"size":520,"mtime":1768239263846,"hash":"98","data":"99"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/api.d.ts",{"size":1521,"mtime":1768239263527,"hash":"100","data":"101"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/types/index.ts",{"size":69,"mtime":1768239263861,"hash":"102","data":"103"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/api.js",{"size":480,"mtime":1768239263542,"hash":"104","data":"105"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/README.md",{"size":2525,"mtime":1768155639000,"hash":"106","data":"107"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/http.ts",{"size":153,"mtime":1768157491000,"hash":"108","data":"109"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/schema.ts",{"size":1197,"mtime":1768239263796,"hash":"110","data":"111"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/custom/auth/index.ts",{"size":142,"mtime":1768157708000,"hash":"112","data":"113"},"e6b51ffddcfeaaeaaf7d1a0453024eff","0d76c3867783aec5435b0c716f1bfc65",{"hashOfOptions":"114"},"bd827d1529ceec8f4804864db994747b",{"hashOfOptions":"115"},"55bcf7d546da727edf2c1b7e52db6c7f",{"hashOfOptions":"116"},"ce3275ccdd28673d7e9280b33792057c",{"hashOfOptions":"117"},"175b1a771387d8b7e26145c3d04e0475","6a3198db454396c63e99ee08065726bd",{"hashOfOptions":"118"},"2d4f4ccfc784af9d668d8c64726c2f6b",{"hashOfOptions":"119"},"cfa98923457caed911ec68b626ef4234",{"hashOfOptions":"120"},"5d96f2526115241c4a37250b0f45ac4d",{"hashOfOptions":"121"},"14f5e2d18e21f65282ac744b382f2d5f",{"hashOfOptions":"122"},"f42d53bd1ba24bfee1407d2098f3b9ff",{"hashOfOptions":"123"},"6719b019702fc173de16b1bdc8e8ed47",{"hashOfOptions":"124"},"f0f9ef72dc6fef350f3521d3fd8adfc7",{"hashOfOptions":"125"},"5ff3856f1a61b946df899f7c9880b72a",{"hashOfOptions":"126"},"ccf5b9105ad4ff66fce0a7133fa3db4b",{"hashOfOptions":"127"},"7c522302bfb45e9cf5f1c271b48fa247",{"hashOfOptions":"128"},"57577de5aadfa618e91739aea3630342",{"hashOfOptions":"129"},"9d0d3b8d30fb1a1207df0584bf0f4c2e",{Line truncated
+4
View File
@@ -9,9 +9,11 @@
*/
import type * as auth from "../auth.js";
import type * as crons from "../crons.js";
import type * as custom_auth_index from "../custom/auth/index.js";
import type * as custom_auth_providers_password from "../custom/auth/providers/password.js";
import type * as custom_auth_providers_usesend from "../custom/auth/providers/usesend.js";
import type * as files from "../files.js";
import type * as http from "../http.js";
import type * as utils from "../utils.js";
@@ -31,9 +33,11 @@ import type {
*/
declare const fullApi: ApiFromModules<{
auth: typeof auth;
crons: typeof crons;
"custom/auth/index": typeof custom_auth_index;
"custom/auth/providers/password": typeof custom_auth_providers_password;
"custom/auth/providers/usesend": typeof custom_auth_providers_usesend;
files: typeof files;
http: typeof http;
utils: typeof utils;
}>;
+3 -7
View File
@@ -14,10 +14,7 @@ import { action, mutation, query } from './_generated/server';
import { Password, validatePassword } from './custom/auth';
export const { auth, signIn, signOut, store, isAuthenticated } = convexAuth({
providers: [
Authentik({ allowDangerousEmailAccountLinking: true }),
Password,
],
providers: [Authentik({ allowDangerousEmailAccountLinking: true }), Password],
});
const getUserById = async (
@@ -39,9 +36,8 @@ const isSignedIn = async (ctx: QueryCtx): Promise<Doc<'users'> | null> => {
export const getUser = query({
args: { userId: v.optional(v.id('users')) },
handler: async (ctx, args) => {
const user = await isSignedIn(ctx);
const userId = args.userId ?? user?._id;
if (!userId) throw new ConvexError('Not authenticated or no ID provided.');
const userId = args.userId ?? (await getAuthUserId(ctx));
if (!userId) return null;
return getUserById(ctx, userId);
},
});
+23
View File
@@ -0,0 +1,23 @@
import { cronJobs } from 'convex/server';
import { api } from './_generated/api';
// Cron order: Minute Hour DayOfMonth Month DayOfWeek
const crons = cronJobs();
/* Example cron jobs
crons.cron(
// Run at 7:00 AM CST / 8:00 AM CDT
// Only on weekdays
'Schedule Automatic Lunches',
'0 13 * * 1-5',
api.statuses.automaticLunch,
);
crons.cron(
// Run at 4:00 PM CST / 5:00 PM CDT
// Only on weekdays
'End of shift (weekdays 5pm CT)',
'0 22 * * 1-5',
api.statuses.endOfShiftUpdate,
);
*/
export default crons;
@@ -1,5 +1,6 @@
import { Password as DefaultPassword } from '@convex-dev/auth/providers/Password';
import { ConvexError } from 'convex/values';
import { UseSendOTP, UseSendOTPPasswordReset } from '..';
import { DataModel } from '../../../_generated/dataModel';
+18
View File
@@ -0,0 +1,18 @@
import { getAuthUserId } from '@convex-dev/auth/server';
import { ConvexError, v } from 'convex/values';
import { mutation, query } from './_generated/server';
export const generateUploadUrl = mutation(async (ctx) => {
const userId = await getAuthUserId(ctx);
if (!userId) throw new ConvexError('Not authenticated.');
return await ctx.storage.generateUploadUrl();
});
export const getImageUrl = query({
args: { storageId: v.id('_storage') },
handler: async (ctx, { storageId }) => {
const url = await ctx.storage.getUrl(storageId);
return url ?? null;
},
});
+4 -5
View File
@@ -1,6 +1,6 @@
import { authTables } from '@convex-dev/auth/server';
import { defineSchema, defineTable } from 'convex/server';
import { v } from 'convex/values';
import { authTables } from '@convex-dev/auth/server';
const applicationTables = {
// Users contains name image & email.
@@ -10,8 +10,7 @@ const applicationTables = {
profiles: defineTable({
userId: v.id('users'),
theme_preference: v.optional(v.string()),
})
.index('userId', ['userId'])
}).index('userId', ['userId']),
};
export default defineSchema({
@@ -29,8 +28,8 @@ export default defineSchema({
phoneVerificationTime: v.optional(v.number()),
isAnonymous: v.optional(v.boolean()),
})
.index("email", ["email"])
.index('email', ['email'])
.index('name', ['name'])
.index("phone", ["phone"]),
.index('phone', ['phone']),
...applicationTables,
});
+3 -1
View File
@@ -7,7 +7,9 @@
"author": "Gib",
"license": "MIT",
"exports": {
"./types" : "./types/index.ts"
"./convex": "./convex/",
"./convex/*": "./convex/*",
"./types": "./types/index.ts"
},
"scripts": {
"dev": "bun with-env convex dev",
+6 -7
View File
@@ -1,17 +1,16 @@
#!/usr/bin/env node
import { exportJWK, exportPKCS8, generateKeyPair } from 'jose';
import { exportJWK, exportPKCS8, generateKeyPair } from "jose";
const keys = await generateKeyPair("RS256", {
const keys = await generateKeyPair('RS256', {
extractable: true,
});
const privateKey = await exportPKCS8(keys.privateKey);
const publicKey = await exportJWK(keys.publicKey);
const jwks = JSON.stringify({ keys: [{ use: "sig", ...publicKey }] });
const jwks = JSON.stringify({ keys: [{ use: 'sig', ...publicKey }] });
process.stdout.write(
`JWT_PRIVATE_KEY="${privateKey.trimEnd().replace(/\n/g, " ")}"`,
`JWT_PRIVATE_KEY="${privateKey.trimEnd().replace(/\n/g, ' ')}"`,
);
process.stdout.write("\n");
process.stdout.write('\n');
process.stdout.write(`JWKS=${jwks}`);
process.stdout.write("\n");
process.stdout.write('\n');
+1 -5
View File
@@ -1,5 +1 @@
export {
PASSWORD_MIN,
PASSWORD_MAX,
PASSWORD_REGEX,
} from './auth';
export { PASSWORD_MIN, PASSWORD_MAX, PASSWORD_REGEX } from './auth';
+1 -1
View File
@@ -1 +1 @@
[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32"],{"key":"33","value":"34"},{"key":"35","value":"36"},{"key":"37","value":"38"},{"key":"39","value":"40"},{"key":"41","value":"42"},{"key":"43","value":"44"},{"key":"45","value":"46"},{"key":"47","value":"48"},{"key":"49","value":"50"},{"key":"51","value":"52"},{"key":"53","value":"54"},{"key":"55","value":"56"},{"key":"57","value":"58"},{"key":"59","value":"60"},{"key":"61","value":"62"},{"key":"63","value":"64"},{"key":"65","value":"66"},{"key":"67","value":"68"},{"key":"69","value":"70"},{"key":"71","value":"72"},{"key":"73","value":"74"},{"key":"75","value":"76"},{"key":"77","value":"78"},{"key":"79","value":"80"},{"key":"81","value":"82"},{"key":"83","value":"84"},{"key":"85","value":"86"},{"key":"87","value":"88"},{"key":"89","value":"90"},{"key":"91","value":"92"},{"key":"93","value":"94"},{"key":"95","value":"96"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/based-avatar.tsx",{"size":1783,"mtime":1768155640183,"hash":"97","data":"98"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/switch.tsx",{"size":1184,"mtime":1768155641096,"hash":"99","data":"100"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/card.tsx",{"size":2001,"mtime":1768155640347,"hash":"101","data":"102"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/table.tsx",{"size":2463,"mtime":1768155641128,"hash":"103","data":"104"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/theme.tsx",{"size":5136,"mtime":1768155641207,"hash":"105","data":"106"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/status-message.tsx",{"size":1620,"mtime":1768155641049,"hash":"107","data":"108"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/drawer.tsx",{"size":4272,"mtime":1768155640435,"hash":"109","data":"110"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/field.tsx",{"size":6143,"mtime":1768155640581,"hash":"111","data":"112"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/input-otp.tsx",{"size":2269,"mtime":1768155640716,"hash":"113","data":"114"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/separator.tsx",{"size":705,"mtime":1768155640895,"hash":"115","data":"116"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/shadcn-io/image-crop/index.tsx",{"size":8265,"mtime":1768155640999,"hash":"117","data":"118"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/avatar.tsx",{"size":1103,"mtime":1768155640108,"hash":"119","data":"120"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/checkbox.tsx",{"size":1233,"mtime":1768155640375,"hash":"121","data":"122"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/submit-button.tsx",{"size":1229,"mtime":1768155641074,"hash":"123","data":"124"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/eslint.config.ts",{"size":254,"mtime":1768155640007,"hash":"125","data":"126"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/scroll-area.tsx",{"size":1652,"mtime":1768155640872,"hash":"127","data":"128"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/toast.tsx",{"size":616,"mtime":1768155641226,"hash":"129","data":"130"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/input.tsx",{"size":971,"mtime":1768155640742,"hash":"131","data":"132"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/progress.tsx",{"size":746,"mtime":1768155640843,"hash":"133","data":"134"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/sonner.tsx",{"size":571,"mtime":1768155641017,"hash":"135","data":"136"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/components.json",{"size":334,"mtime":1768154488750,"hash":"137","data":"138"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/package.json",{"size":2863,"mtime":1768154592304,"hash":"139","data":"140"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/pagination.tsx",{"size":2726,"mtime":1768155640818,"hash":"141","data":"142"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/dropdown-menu.tsx",{"size":8316,"mtime":1768155640501,"hash":"143","data":"144"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/form.tsx",{"size":3820,"mtime":1768155640641,"hash":"145","data":"146"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/index.ts",{"size":358,"mtime":1768155640668,"hash":"147","data":"148"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/label.tsx",{"size":617,"mtime":1768155640773,"hash":"149","data":"150"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/button.tsx",{"size":2175,"mtime":1768155640302,"hash":"151","data":"152"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/tabs.tsx",{"size":1979,"mtime":1768155641150,"hash":"153","data":"154"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/.cache/.prettiercache",{"size":10630,"mtime":1766222924000,"hash":"155"},"/home/gib/DocumLine truncated
[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"],{"key":"32","value":"33"},{"key":"34","value":"35"},{"key":"36","value":"37"},{"key":"38","value":"39"},{"key":"40","value":"41"},{"key":"42","value":"43"},{"key":"44","value":"45"},{"key":"46","value":"47"},{"key":"48","value":"49"},{"key":"50","value":"51"},{"key":"52","value":"53"},{"key":"54","value":"55"},{"key":"56","value":"57"},{"key":"58","value":"59"},{"key":"60","value":"61"},{"key":"62","value":"63"},{"key":"64","value":"65"},{"key":"66","value":"67"},{"key":"68","value":"69"},{"key":"70","value":"71"},{"key":"72","value":"73"},{"key":"74","value":"75"},{"key":"76","value":"77"},{"key":"78","value":"79"},{"key":"80","value":"81"},{"key":"82","value":"83"},{"key":"84","value":"85"},{"key":"86","value":"87"},{"key":"88","value":"89"},{"key":"90","value":"91"},{"key":"92","value":"93"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/based-avatar.tsx",{"size":1738,"mtime":1768239263550,"hash":"94","data":"95"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/switch.tsx",{"size":1186,"mtime":1768239263972,"hash":"96","data":"97"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/card.tsx",{"size":1998,"mtime":1768239263622,"hash":"98","data":"99"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/table.tsx",{"size":2465,"mtime":1768239263980,"hash":"100","data":"101"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/theme.tsx",{"size":1796,"mtime":1768239264008,"hash":"102","data":"103"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/status-message.tsx",{"size":1619,"mtime":1768239263956,"hash":"104","data":"105"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/drawer.tsx",{"size":4269,"mtime":1768239263651,"hash":"106","data":"107"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/field.tsx",{"size":6073,"mtime":1768239263711,"hash":"108","data":"109"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/input-otp.tsx",{"size":2266,"mtime":1768239263796,"hash":"110","data":"111"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/separator.tsx",{"size":702,"mtime":1768239263893,"hash":"112","data":"113"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/shadcn-io/image-crop/index.tsx",{"size":8230,"mtime":1768239263934,"hash":"114","data":"115"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/avatar.tsx",{"size":1102,"mtime":1768155815000,"hash":"116","data":"117"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/checkbox.tsx",{"size":1230,"mtime":1768239263633,"hash":"118","data":"119"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/submit-button.tsx",{"size":1192,"mtime":1768239263964,"hash":"120","data":"121"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/eslint.config.ts",{"size":254,"mtime":1768155640000,"hash":"122","data":"123"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/scroll-area.tsx",{"size":1654,"mtime":1768239263883,"hash":"124","data":"125"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/input.tsx",{"size":968,"mtime":1768239263824,"hash":"126","data":"127"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/progress.tsx",{"size":748,"mtime":1768239263868,"hash":"128","data":"129"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/sonner.tsx",{"size":601,"mtime":1768239263943,"hash":"130","data":"131"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/components.json",{"size":334,"mtime":1768154488000,"hash":"132","data":"133"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/package.json",{"size":2864,"mtime":1768155775000,"hash":"134","data":"135"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/pagination.tsx",{"size":2718,"mtime":1768239263856,"hash":"136","data":"137"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/index.tsx",{"size":2381,"mtime":1768155754000,"hash":"138","data":"139"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/dropdown-menu.tsx",{"size":8313,"mtime":1768239263677,"hash":"140","data":"141"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/form.tsx",{"size":3782,"mtime":1768239263749,"hash":"142","data":"143"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/label.tsx",{"size":614,"mtime":1768239263842,"hash":"144","data":"145"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/button.tsx",{"size":2172,"mtime":1768239263600,"hash":"146","data":"147"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/tabs.tsx",{"size":1981,"mtime":1768239263989,"hash":"148","data":"149"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/.cache/.prettiercache",{"size":7506,"mtime":1768171236843,"hash":"150"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/based-progress.tsx",{"size":1372,"mtime":1768239263575,"hash":"151","data":"152"},"/home/gib/Documents/Code/convex-monoreLine truncated
+2 -1
View File
@@ -1,10 +1,11 @@
'use client';
import type { ComponentProps } from 'react';
import { cn, AvatarImage } from '@gib/ui';
import * as AvatarPrimitive from '@radix-ui/react-avatar';
import { User } from 'lucide-react';
import { AvatarImage, cn } from '@gib/ui';
type BasedAvatarProps = ComponentProps<typeof AvatarPrimitive.Root> & {
src?: string | null;
fullName?: string | null;
+2 -1
View File
@@ -1,9 +1,10 @@
'use client';
import * as React from 'react';
import { cn } from '@gib/ui';
import * as ProgressPrimitive from '@radix-ui/react-progress';
import { cn } from '@gib/ui';
type BasedProgressProps = React.ComponentProps<
typeof ProgressPrimitive.Root
> & {
+2 -1
View File
@@ -1,9 +1,10 @@
import type { VariantProps } from 'class-variance-authority';
import * as React from 'react';
import { cn } from '@gib/ui';
import { Slot } from '@radix-ui/react-slot';
import { cva } from 'class-variance-authority';
import { cn } from '@gib/ui';
const buttonVariants = cva(
"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
{
+1
View File
@@ -1,4 +1,5 @@
import * as React from 'react';
import { cn } from '@gib/ui';
function Card({ className, ...props }: React.ComponentProps<'div'>) {
+2 -1
View File
@@ -1,10 +1,11 @@
'use client';
import * as React from 'react';
import { cn } from '@gib/ui';
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
import { CheckIcon } from 'lucide-react';
import { cn } from '@gib/ui';
function Checkbox({
className,
...props
+2 -1
View File
@@ -1,9 +1,10 @@
'use client';
import * as React from 'react';
import { cn } from '@gib/ui';
import { Drawer as DrawerPrimitive } from 'vaul';
import { cn } from '@gib/ui';
function Drawer({
...props
}: React.ComponentProps<typeof DrawerPrimitive.Root>) {
+2 -1
View File
@@ -1,10 +1,11 @@
'use client';
import * as React from 'react';
import { cn } from '@gib/ui';
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react';
import { cn } from '@gib/ui';
function DropdownMenu({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
+2 -1
View File
@@ -2,9 +2,10 @@
import type { VariantProps } from 'class-variance-authority';
import { useMemo } from 'react';
import { cn, Label, Separator } from '@gib/ui';
import { cva } from 'class-variance-authority';
import { cn, Label, Separator } from '@gib/ui';
export function FieldSet({
className,
...props
+3 -2
View File
@@ -1,9 +1,8 @@
'use client';
import type * as LabelPrimitive from '@radix-ui/react-label';
import type { ControllerProps, FieldPath, FieldValues } from 'react-hook-form';
import * as React from 'react';
import { cn, Label } from '@gib/ui';
import type * as LabelPrimitive from '@radix-ui/react-label';
import { Slot } from '@radix-ui/react-slot';
import {
Controller,
@@ -12,6 +11,8 @@ import {
useFormState,
} from 'react-hook-form';
import { cn, Label } from '@gib/ui';
const Form = FormProvider;
type FormFieldContextValue<
+2 -1
View File
@@ -1,10 +1,11 @@
'use client';
import * as React from 'react';
import { cn } from '@gib/ui';
import { OTPInput, OTPInputContext } from 'input-otp';
import { MinusIcon } from 'lucide-react';
import { cn } from '@gib/ui';
function InputOTP({
className,
containerClassName,
+1
View File
@@ -1,4 +1,5 @@
import * as React from 'react';
import { cn } from '@gib/ui';
function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
+2 -1
View File
@@ -1,9 +1,10 @@
'use client';
import * as React from 'react';
import { cn } from '@gib/ui';
import * as LabelPrimitive from '@radix-ui/react-label';
import { cn } from '@gib/ui';
function Label({
className,
...props
+3 -2
View File
@@ -1,12 +1,13 @@
import type * as React from 'react';
import type { Button } from '@gib/ui';
import { cn, buttonVariants } from '@gib/ui';
import {
ChevronLeftIcon,
ChevronRightIcon,
MoreHorizontalIcon,
} from 'lucide-react';
import type { Button } from '@gib/ui';
import { buttonVariants, cn } from '@gib/ui';
function Pagination({ className, ...props }: React.ComponentProps<'nav'>) {
return (
<nav
+2 -1
View File
@@ -1,9 +1,10 @@
'use client';
import type * as React from 'react';
import { cn } from '@gib/ui';
import * as ProgressPrimitive from '@radix-ui/react-progress';
import { cn } from '@gib/ui';
function Progress({
className,
value,
+2 -1
View File
@@ -1,9 +1,10 @@
'use client';
import type * as React from 'react';
import { cn } from '@gib/ui';
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
import { cn } from '@gib/ui';
function ScrollArea({
className,
children,
+2 -1
View File
@@ -1,9 +1,10 @@
'use client';
import * as React from 'react';
import { cn } from '@gib/ui';
import * as SeparatorPrimitive from '@radix-ui/react-separator';
import { cn } from '@gib/ui';
function Separator({
className,
orientation = 'horizontal',
@@ -17,11 +17,12 @@ import {
useRef,
useState,
} from 'react';
import { cn, Button } from '@gib/ui';
import { CropIcon, RotateCcwIcon } from 'lucide-react';
import { Slot } from 'radix-ui';
import ReactCrop, { centerCrop, makeAspectCrop } from 'react-image-crop';
import { Button, cn } from '@gib/ui';
import 'react-image-crop/dist/ReactCrop.css';
const centerAspectCrop = (
@@ -110,7 +111,7 @@ interface ImageCropContextType {
onImageLoad: (e: SyntheticEvent<HTMLImageElement>) => void;
applyCrop: () => Promise<void>;
resetCrop: () => void;
};
}
const ImageCropContext = createContext<ImageCropContextType | null>(null);
+1 -1
View File
@@ -1,7 +1,7 @@
'use client';
import { useTheme } from 'next-themes';
import type { ToasterProps } from 'sonner';
import { useTheme } from 'next-themes';
import { Toaster as Sonner } from 'sonner';
const Toaster = ({ ...props }: ToasterProps) => {
+2 -1
View File
@@ -1,4 +1,5 @@
import type { ComponentProps } from 'react';
import { cn } from '@gib/ui';
type Message = { success: string } | { error: string } | { message: string };
@@ -7,7 +8,7 @@ interface StatusMessageProps {
message: Message;
containerProps?: ComponentProps<'div'>;
textProps?: ComponentProps<'div'>;
};
}
export const StatusMessage = ({
message,
+2 -1
View File
@@ -1,10 +1,11 @@
'use client';
import type { ComponentProps } from 'react';
import { cn, Button } from '@gib/ui';
import { Loader2 } from 'lucide-react';
import { useFormStatus } from 'react-dom';
import { Button, cn } from '@gib/ui';
export type SubmitButtonProps = Omit<
ComponentProps<typeof Button>,
'type' | 'aria-disabled'
+2 -1
View File
@@ -1,9 +1,10 @@
'use client';
import type * as React from 'react';
import { cn } from '@gib/ui';
import * as SwitchPrimitive from '@radix-ui/react-switch';
import { cn } from '@gib/ui';
function Switch({
className,
...props
+1
View File
@@ -1,6 +1,7 @@
'use client';
import type * as React from 'react';
import { cn } from '@gib/ui';
function Table({ className, ...props }: React.ComponentProps<'table'>) {
+2 -1
View File
@@ -1,9 +1,10 @@
'use client';
import type * as React from 'react';
import { cn } from '@gib/ui';
import * as TabsPrimitive from '@radix-ui/react-tabs';
import { cn } from '@gib/ui';
function Tabs({
className,
...props
+1 -1
View File
@@ -24,7 +24,7 @@ const ThemeProvider = ({
interface ThemeToggleProps {
size?: number;
buttonProps?: Omit<ComponentProps<typeof Button>, 'onClick'>;
};
}
const ThemeToggle = ({ size = 1, buttonProps }: ThemeToggleProps) => {
const { setTheme, resolvedTheme } = useTheme();