General fixes. Still far from good or working
This commit is contained in:
27
.env.example
27
.env.example
@@ -3,29 +3,22 @@
|
|||||||
# This file will be committed to version control, so make sure not to have any secrets in it.
|
# This file will be committed to version control, so make sure not to have any secrets in it.
|
||||||
# If you are cloning this repo, create a copy of this file named `.env` and populate it with your secrets.
|
# If you are cloning this repo, create a copy of this file named `.env` and populate it with your secrets.
|
||||||
## Next.js ##
|
## Next.js ##
|
||||||
NODE_ENV=development
|
NODE_ENV=
|
||||||
CI=false
|
|
||||||
SITE_URL=
|
|
||||||
SENTRY_AUTH_TOKEN=
|
SENTRY_AUTH_TOKEN=
|
||||||
NEXT_PUBLIC_SITE_URL=
|
NEXT_PUBLIC_SITE_URL=https://example.com
|
||||||
NEXT_PUBLIC_CONVEX_URL=
|
NEXT_PUBLIC_CONVEX_URL=https://api.convex.example.com # convex-backend:3210
|
||||||
NEXT_PUBLIC_PLAUSIBLE_URL=
|
NEXT_PUBLIC_PLAUSIBLE_URL=https://plausible.example.com
|
||||||
NEXT_PUBLIC_SENTRY_DSN=
|
NEXT_PUBLIC_SENTRY_DSN=
|
||||||
NEXT_PUBLIC_SENTRY_URL=
|
NEXT_PUBLIC_SENTRY_URL=https://sentry.example.com
|
||||||
NEXT_PUBLIC_SENTRY_ORG=
|
NEXT_PUBLIC_SENTRY_ORG=sentry
|
||||||
NEXT_PUBLIC_SENTRY_PROJECT_NAME=
|
NEXT_PUBLIC_SENTRY_PROJECT_NAME=example
|
||||||
|
|
||||||
## Convex ##
|
## Convex ##
|
||||||
CONVEX_SELF_HOSTED_URL=
|
CONVEX_SELF_HOSTED_URL=https://api.convex.example.com # convex-backend:3210
|
||||||
CONVEX_SELF_HOSTED_ADMIN_KEY=
|
CONVEX_SELF_HOSTED_ADMIN_KEY= # Generate after hosted on docker
|
||||||
SETUP_SCRIPT_RAN=
|
|
||||||
# Convex Auth
|
# Convex Auth
|
||||||
AUTH_URL=convex.example.com
|
CONVEX_SITE_URL=https://convex.example.com # convex-backend:3211
|
||||||
USESEND_API_KEY=
|
USESEND_API_KEY=
|
||||||
AUTH_AUTHENTIK_ID=
|
AUTH_AUTHENTIK_ID=
|
||||||
AUTH_AUTHENTIK_SECRET=
|
AUTH_AUTHENTIK_SECRET=
|
||||||
AUTH_AUTHENTIK_ISSUER=
|
AUTH_AUTHENTIK_ISSUER=
|
||||||
AUTH_MICROSOFT_ENTRA_ID_ID=
|
|
||||||
AUTH_MICROSOFT_ENTRA_ID_SECRET=
|
|
||||||
AUTH_MICROSOFT_ENTRA_ID_ISSUER=
|
|
||||||
AUTH_MICROSOFT_ENTRA_ID_AUTH_URL=
|
|
||||||
|
|||||||
1
apps/expo/.cache/.prettiercache
Normal file
1
apps/expo/.cache/.prettiercache
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","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"},{"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"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/package.json",{"size":2249,"mtime":1766222924000,"hash":"64","data":"65"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/index.ts",{"size":28,"mtime":1768155639384,"hash":"66","data":"67"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/metro.config.js",{"size":511,"mtime":1768155639442,"hash":"68","data":"69"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/app/index.tsx",{"size":5019,"mtime":1768155639734,"hash":"70","data":"71"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/turbo.json",{"size":163,"mtime":1766222924000,"hash":"72","data":"73"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/postcss.config.js",{"size":66,"mtime":1768155639501,"hash":"74","data":"75"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/eas.json",{"size":567,"mtime":1766222924000,"hash":"76","data":"77"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/.expo-shared/assets.json",{"size":155,"mtime":1766222924000,"hash":"78","data":"79"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/app/_layout.tsx",{"size":927,"mtime":1768155639581,"hash":"80","data":"81"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/nativewind-env.d.ts",{"size":246,"mtime":1766222924000,"hash":"82","data":"83"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/auth.ts",{"size":398,"mtime":1768155639911,"hash":"84","data":"85"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/app/post/[id].tsx",{"size":757,"mtime":1768155639785,"hash":"86","data":"87"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/styles.css",{"size":90,"mtime":1768155639819,"hash":"88","data":"89"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/session-store.ts",{"size":272,"mtime":1768155639965,"hash":"90","data":"91"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/assets/icon-dark.png",{"size":19633,"mtime":1766222924000,"hash":"92"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/eslint.config.mts",{"size":275,"mtime":1768155639360,"hash":"93","data":"94"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/api.tsx",{"size":1326,"mtime":1768155639881,"hash":"95","data":"96"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/base-url.ts",{"size":880,"mtime":1768155639943,"hash":"97","data":"98"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/app.config.ts",{"size":1333,"mtime":1768155639275,"hash":"99","data":"100"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/assets/icon-light.png",{"size":19133,"mtime":1766222924000,"hash":"101"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/tsconfig.json",{"size":387,"mtime":1766228480000,"hash":"102","data":"103"},"d8763702c14cdc382dcfb84f6f9a068f",{"hashOfOptions":"104"},"11cdbef6afa001cd39bc187041ca6865",{"hashOfOptions":"105"},"dbe97bcde588a81538bbcd6a9befdddd",{"hashOfOptions":"106"},"1c10eb388cf5dcbc87d2d63770a227f1",{"hashOfOptions":"107"},"c7d4dcf839dfeaa02e0407adfd5e47a6",{"hashOfOptions":"108"},"b7edffce093c4c84092cc93f3dc208ef",{"hashOfOptions":"109"},"a3c1487f8318513ae7c156acc857fde2",{"hashOfOptions":"110"},"0f7f54c7161b8403d3bc42d91f59cd91",{"hashOfOptions":"111"},"8e407b4b1b0c0bd9c862a00243344be3",{"hashOfOptions":"112"},"d4d589c153ac8b5e7bf0fb130a5b5a7d",{"hashOfOptions":"113"},"cecbed1604a530a7cc099fecddddd76c",{"hashOfOptions":"114"},"4fcefde979d34a7339f7a266d3ec931b",{"hashOfOptions":"115"},"52a1d72379b952dd802f47e1865bd0da",{"hashOfOptions":"116"},"1bc3e15a40c117eecc51294886ea9b38",{"hashOfOptions":"117"},"1e8ac0d261e95efb19d290ffcf70ce36","1c1710ce3de3ce02e8054cc3787c8579",{"hashOfOptions":"118"},"5ff899a601102659dcbd2900e415ce8b",{"hashOfOptions":"119"},"dd2007a211e323deabb3f7fa7d16313f",{"hashOfOptions":"120"},"4f49c6df7733f874fbe72b4e20b3092b",{"hashOfOptions":"121"},"863da15dbd856008b7c24077ca746d91","6937fb7370f1e17491df649888d6ecc9",{"hashOfOptions":"122"},"2742538293","3367041120","3963086909","3173464737","3850474653","3346849767","2045418596","3048291867","3525769784","4000169781","471581913","1427279653","2305419495","818733105","2587128410","1262173017","408469422","2836740315","2315460658"]
|
||||||
@@ -1,32 +1,32 @@
|
|||||||
import type { ConfigContext, ExpoConfig } from "expo/config";
|
import type { ConfigContext, ExpoConfig } from 'expo/config';
|
||||||
|
|
||||||
export default ({ config }: ConfigContext): ExpoConfig => ({
|
export default ({ config }: ConfigContext): ExpoConfig => ({
|
||||||
...config,
|
...config,
|
||||||
name: "expo",
|
name: 'expo',
|
||||||
slug: "expo",
|
slug: 'expo',
|
||||||
scheme: "expo",
|
scheme: 'expo',
|
||||||
version: "0.1.0",
|
version: '0.1.0',
|
||||||
orientation: "portrait",
|
orientation: 'portrait',
|
||||||
icon: "./assets/icon-light.png",
|
icon: './assets/icon-light.png',
|
||||||
userInterfaceStyle: "automatic",
|
userInterfaceStyle: 'automatic',
|
||||||
updates: {
|
updates: {
|
||||||
fallbackToCacheTimeout: 0,
|
fallbackToCacheTimeout: 0,
|
||||||
},
|
},
|
||||||
newArchEnabled: true,
|
newArchEnabled: true,
|
||||||
assetBundlePatterns: ["**/*"],
|
assetBundlePatterns: ['**/*'],
|
||||||
ios: {
|
ios: {
|
||||||
bundleIdentifier: "your.bundle.identifier",
|
bundleIdentifier: 'your.bundle.identifier',
|
||||||
supportsTablet: true,
|
supportsTablet: true,
|
||||||
icon: {
|
icon: {
|
||||||
light: "./assets/icon-light.png",
|
light: './assets/icon-light.png',
|
||||||
dark: "./assets/icon-dark.png",
|
dark: './assets/icon-dark.png',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
android: {
|
android: {
|
||||||
package: "your.bundle.identifier",
|
package: 'your.bundle.identifier',
|
||||||
adaptiveIcon: {
|
adaptiveIcon: {
|
||||||
foregroundImage: "./assets/icon-light.png",
|
foregroundImage: './assets/icon-light.png',
|
||||||
backgroundColor: "#1F104A",
|
backgroundColor: '#1F104A',
|
||||||
},
|
},
|
||||||
edgeToEdgeEnabled: true,
|
edgeToEdgeEnabled: true,
|
||||||
},
|
},
|
||||||
@@ -42,17 +42,17 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
|
|||||||
reactCompiler: true,
|
reactCompiler: true,
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
"expo-router",
|
'expo-router',
|
||||||
"expo-secure-store",
|
'expo-secure-store',
|
||||||
"expo-web-browser",
|
'expo-web-browser',
|
||||||
[
|
[
|
||||||
"expo-splash-screen",
|
'expo-splash-screen',
|
||||||
{
|
{
|
||||||
backgroundColor: "#E4E4E7",
|
backgroundColor: '#E4E4E7',
|
||||||
image: "./assets/icon-light.png",
|
image: './assets/icon-light.png',
|
||||||
dark: {
|
dark: {
|
||||||
backgroundColor: "#18181B",
|
backgroundColor: '#18181B',
|
||||||
image: "./assets/icon-dark.png",
|
image: './assets/icon-dark.png',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { defineConfig } from "eslint/config";
|
import { baseConfig } from '@acme/eslint-config/base';
|
||||||
|
import { reactConfig } from '@acme/eslint-config/react';
|
||||||
import { baseConfig } from "@acme/eslint-config/base";
|
import { defineConfig } from 'eslint/config';
|
||||||
import { reactConfig } from "@acme/eslint-config/react";
|
|
||||||
|
|
||||||
export default defineConfig(
|
export default defineConfig(
|
||||||
{
|
{
|
||||||
ignores: [".expo/**", "expo-plugins/**"],
|
ignores: ['.expo/**', 'expo-plugins/**'],
|
||||||
},
|
},
|
||||||
baseConfig,
|
baseConfig,
|
||||||
reactConfig,
|
reactConfig,
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
import "expo-router/entry";
|
import 'expo-router/entry';
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
// Learn more: https://docs.expo.dev/guides/monorepos/
|
// Learn more: https://docs.expo.dev/guides/monorepos/
|
||||||
const path = require("node:path");
|
const path = require('node:path');
|
||||||
const { getDefaultConfig } = require("expo/metro-config");
|
const { getDefaultConfig } = require('expo/metro-config');
|
||||||
const { FileStore } = require("metro-cache");
|
const { FileStore } = require('metro-cache');
|
||||||
const { withNativewind } = require("nativewind/metro");
|
const { withNativewind } = require('nativewind/metro');
|
||||||
|
|
||||||
const config = getDefaultConfig(__dirname);
|
const config = getDefaultConfig(__dirname);
|
||||||
|
|
||||||
config.cacheStores = [
|
config.cacheStores = [
|
||||||
new FileStore({
|
new FileStore({
|
||||||
root: path.join(__dirname, "node_modules", ".cache", "metro"),
|
root: path.join(__dirname, 'node_modules', '.cache', 'metro'),
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
module.exports = require("@acme/tailwind-config/postcss-config");
|
module.exports = require('@acme/tailwind-config/postcss-config');
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { useColorScheme } from "react-native";
|
import { useColorScheme } from 'react-native';
|
||||||
import { Stack } from "expo-router";
|
import { Stack } from 'expo-router';
|
||||||
import { StatusBar } from "expo-status-bar";
|
import { StatusBar } from 'expo-status-bar';
|
||||||
import { QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { queryClient } from "~/utils/api";
|
import { queryClient } from '~/utils/api';
|
||||||
|
|
||||||
import "../styles.css";
|
import '../styles.css';
|
||||||
|
|
||||||
// This is the main layout of the app
|
// This is the main layout of the app
|
||||||
// It wraps your pages with the providers they need
|
// It wraps your pages with the providers they need
|
||||||
@@ -20,10 +20,10 @@ export default function RootLayout() {
|
|||||||
<Stack
|
<Stack
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
headerStyle: {
|
headerStyle: {
|
||||||
backgroundColor: "#c03484",
|
backgroundColor: '#c03484',
|
||||||
},
|
},
|
||||||
contentStyle: {
|
contentStyle: {
|
||||||
backgroundColor: colorScheme == "dark" ? "#09090B" : "#FFFFFF",
|
backgroundColor: colorScheme == 'dark' ? '#09090B' : '#FFFFFF',
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import { useState } from "react";
|
import { useState } from 'react';
|
||||||
import { Pressable, Text, TextInput, View } from "react-native";
|
import { Pressable, Text, TextInput, View } from 'react-native';
|
||||||
import { SafeAreaView } from "react-native-safe-area-context";
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
import { Link, Stack } from "expo-router";
|
import { Link, Stack } from 'expo-router';
|
||||||
import { LegendList } from "@legendapp/list";
|
import { LegendList } from '@legendapp/list';
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
|
|
||||||
import type { RouterOutputs } from "~/utils/api";
|
import type { RouterOutputs } from '~/utils/api';
|
||||||
import { trpc } from "~/utils/api";
|
import { trpc } from '~/utils/api';
|
||||||
import { authClient } from "~/utils/auth";
|
import { authClient } from '~/utils/auth';
|
||||||
|
|
||||||
function PostCard(props: {
|
function PostCard(props: {
|
||||||
post: RouterOutputs["post"]["all"][number];
|
post: RouterOutputs['post']['all'][number];
|
||||||
onDelete: () => void;
|
onDelete: () => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
@@ -19,7 +19,7 @@ function PostCard(props: {
|
|||||||
<Link
|
<Link
|
||||||
asChild
|
asChild
|
||||||
href={{
|
href={{
|
||||||
pathname: "/post/[id]",
|
pathname: '/post/[id]',
|
||||||
params: { id: props.post.id },
|
params: { id: props.post.id },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -41,14 +41,14 @@ function PostCard(props: {
|
|||||||
function CreatePost() {
|
function CreatePost() {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const [title, setTitle] = useState("");
|
const [title, setTitle] = useState('');
|
||||||
const [content, setContent] = useState("");
|
const [content, setContent] = useState('');
|
||||||
|
|
||||||
const { mutate, error } = useMutation(
|
const { mutate, error } = useMutation(
|
||||||
trpc.post.create.mutationOptions({
|
trpc.post.create.mutationOptions({
|
||||||
async onSuccess() {
|
async onSuccess() {
|
||||||
setTitle("");
|
setTitle('');
|
||||||
setContent("");
|
setContent('');
|
||||||
await queryClient.invalidateQueries(trpc.post.all.queryFilter());
|
await queryClient.invalidateQueries(trpc.post.all.queryFilter());
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -89,7 +89,7 @@ function CreatePost() {
|
|||||||
>
|
>
|
||||||
<Text className="text-foreground">Create</Text>
|
<Text className="text-foreground">Create</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
{error?.data?.code === "UNAUTHORIZED" && (
|
{error?.data?.code === 'UNAUTHORIZED' && (
|
||||||
<Text className="text-destructive mt-2">
|
<Text className="text-destructive mt-2">
|
||||||
You need to be logged in to create a post
|
You need to be logged in to create a post
|
||||||
</Text>
|
</Text>
|
||||||
@@ -104,20 +104,20 @@ function MobileAuth() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Text className="text-foreground pb-2 text-center text-xl font-semibold">
|
<Text className="text-foreground pb-2 text-center text-xl font-semibold">
|
||||||
{session?.user.name ? `Hello, ${session.user.name}` : "Not logged in"}
|
{session?.user.name ? `Hello, ${session.user.name}` : 'Not logged in'}
|
||||||
</Text>
|
</Text>
|
||||||
<Pressable
|
<Pressable
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
session
|
session
|
||||||
? authClient.signOut()
|
? authClient.signOut()
|
||||||
: authClient.signIn.social({
|
: authClient.signIn.social({
|
||||||
provider: "discord",
|
provider: 'discord',
|
||||||
callbackURL: "/",
|
callbackURL: '/',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="bg-primary flex items-center rounded-sm p-2"
|
className="bg-primary flex items-center rounded-sm p-2"
|
||||||
>
|
>
|
||||||
<Text>{session ? "Sign Out" : "Sign In With Discord"}</Text>
|
<Text>{session ? 'Sign Out' : 'Sign In With Discord'}</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -138,7 +138,7 @@ export default function Index() {
|
|||||||
return (
|
return (
|
||||||
<SafeAreaView className="bg-background">
|
<SafeAreaView className="bg-background">
|
||||||
{/* Changes page title visible on the header */}
|
{/* Changes page title visible on the header */}
|
||||||
<Stack.Screen options={{ title: "Home Page" }} />
|
<Stack.Screen options={{ title: 'Home Page' }} />
|
||||||
<View className="bg-background h-full w-full p-4">
|
<View className="bg-background h-full w-full p-4">
|
||||||
<Text className="text-foreground pb-2 text-center text-5xl font-bold">
|
<Text className="text-foreground pb-2 text-center text-5xl font-bold">
|
||||||
Create <Text className="text-primary">T3</Text> Turbo
|
Create <Text className="text-primary">T3</Text> Turbo
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { SafeAreaView, Text, View } from "react-native";
|
import { SafeAreaView, Text, View } from 'react-native';
|
||||||
import { Stack, useGlobalSearchParams } from "expo-router";
|
import { Stack, useGlobalSearchParams } from 'expo-router';
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { trpc } from "~/utils/api";
|
import { trpc } from '~/utils/api';
|
||||||
|
|
||||||
export default function Post() {
|
export default function Post() {
|
||||||
const { id } = useGlobalSearchParams<{ id: string }>();
|
const { id } = useGlobalSearchParams<{ id: string }>();
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
@import "tailwindcss";
|
@import 'tailwindcss';
|
||||||
@import "nativewind/theme";
|
@import 'nativewind/theme';
|
||||||
@import "@acme/tailwind-config/theme";
|
@import '@acme/tailwind-config/theme';
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import { QueryClient } from "@tanstack/react-query";
|
import type { AppRouter } from '@acme/api';
|
||||||
import { createTRPCClient, httpBatchLink, loggerLink } from "@trpc/client";
|
import { QueryClient } from '@tanstack/react-query';
|
||||||
import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query";
|
import { createTRPCClient, httpBatchLink, loggerLink } from '@trpc/client';
|
||||||
import superjson from "superjson";
|
import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query';
|
||||||
|
import superjson from 'superjson';
|
||||||
|
|
||||||
import type { AppRouter } from "@acme/api";
|
import { authClient } from './auth';
|
||||||
|
import { getBaseUrl } from './base-url';
|
||||||
import { authClient } from "./auth";
|
|
||||||
import { getBaseUrl } from "./base-url";
|
|
||||||
|
|
||||||
export const queryClient = new QueryClient({
|
export const queryClient = new QueryClient({
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
@@ -24,20 +23,20 @@ export const trpc = createTRPCOptionsProxy<AppRouter>({
|
|||||||
links: [
|
links: [
|
||||||
loggerLink({
|
loggerLink({
|
||||||
enabled: (opts) =>
|
enabled: (opts) =>
|
||||||
process.env.NODE_ENV === "development" ||
|
process.env.NODE_ENV === 'development' ||
|
||||||
(opts.direction === "down" && opts.result instanceof Error),
|
(opts.direction === 'down' && opts.result instanceof Error),
|
||||||
colorMode: "ansi",
|
colorMode: 'ansi',
|
||||||
}),
|
}),
|
||||||
httpBatchLink({
|
httpBatchLink({
|
||||||
transformer: superjson,
|
transformer: superjson,
|
||||||
url: `${getBaseUrl()}/api/trpc`,
|
url: `${getBaseUrl()}/api/trpc`,
|
||||||
headers() {
|
headers() {
|
||||||
const headers = new Map<string, string>();
|
const headers = new Map<string, string>();
|
||||||
headers.set("x-trpc-source", "expo-react");
|
headers.set('x-trpc-source', 'expo-react');
|
||||||
|
|
||||||
const cookies = authClient.getCookie();
|
const cookies = authClient.getCookie();
|
||||||
if (cookies) {
|
if (cookies) {
|
||||||
headers.set("Cookie", cookies);
|
headers.set('Cookie', cookies);
|
||||||
}
|
}
|
||||||
return headers;
|
return headers;
|
||||||
},
|
},
|
||||||
@@ -47,4 +46,4 @@ export const trpc = createTRPCOptionsProxy<AppRouter>({
|
|||||||
queryClient,
|
queryClient,
|
||||||
});
|
});
|
||||||
|
|
||||||
export type { RouterInputs, RouterOutputs } from "@acme/api";
|
export type { RouterInputs, RouterOutputs } from '@acme/api';
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import * as SecureStore from "expo-secure-store";
|
import * as SecureStore from 'expo-secure-store';
|
||||||
import { expoClient } from "@better-auth/expo/client";
|
import { expoClient } from '@better-auth/expo/client';
|
||||||
import { createAuthClient } from "better-auth/react";
|
import { createAuthClient } from 'better-auth/react';
|
||||||
|
|
||||||
import { getBaseUrl } from "./base-url";
|
import { getBaseUrl } from './base-url';
|
||||||
|
|
||||||
export const authClient = createAuthClient({
|
export const authClient = createAuthClient({
|
||||||
baseURL: getBaseUrl(),
|
baseURL: getBaseUrl(),
|
||||||
plugins: [
|
plugins: [
|
||||||
expoClient({
|
expoClient({
|
||||||
scheme: "expo",
|
scheme: 'expo',
|
||||||
storagePrefix: "expo",
|
storagePrefix: 'expo',
|
||||||
storage: SecureStore,
|
storage: SecureStore,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import Constants from "expo-constants";
|
import Constants from 'expo-constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend this function when going to production by
|
* Extend this function when going to production by
|
||||||
@@ -14,12 +14,12 @@ export const getBaseUrl = () => {
|
|||||||
* baseUrl to your production API URL.
|
* baseUrl to your production API URL.
|
||||||
*/
|
*/
|
||||||
const debuggerHost = Constants.expoConfig?.hostUri;
|
const debuggerHost = Constants.expoConfig?.hostUri;
|
||||||
const localhost = debuggerHost?.split(":")[0];
|
const localhost = debuggerHost?.split(':')[0];
|
||||||
|
|
||||||
if (!localhost) {
|
if (!localhost) {
|
||||||
// return "https://turbo.t3.gg";
|
// return "https://turbo.t3.gg";
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Failed to get localhost. Please point to your production server.",
|
'Failed to get localhost. Please point to your production server.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return `http://${localhost}:3000`;
|
return `http://${localhost}:3000`;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as SecureStore from "expo-secure-store";
|
import * as SecureStore from 'expo-secure-store';
|
||||||
|
|
||||||
const key = "session_token";
|
const key = 'session_token';
|
||||||
|
|
||||||
export const getToken = () => SecureStore.getItem(key);
|
export const getToken = () => SecureStore.getItem(key);
|
||||||
export const deleteToken = () => SecureStore.deleteItemAsync(key);
|
export const deleteToken = () => SecureStore.deleteItemAsync(key);
|
||||||
|
|||||||
1
apps/next/.cache/.prettiercache
Normal file
1
apps/next/.cache/.prettiercache
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[["1","2","3","4","5","6","7","8","9","10","11"],{"key":"12","value":"13"},{"key":"14","value":"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"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/env.ts",{"size":1676,"mtime":1768155639474,"hash":"34","data":"35"},"/home/gib/Documents/Code/convex-monorepo/apps/next/postcss.config.js",{"size":63,"mtime":1766225879000,"hash":"36","data":"37"},"/home/gib/Documents/Code/convex-monorepo/apps/next/public/favicon.ico",{"size":103027,"mtime":1766225172000,"hash":"38"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/layout.tsx",{"size":1885,"mtime":1768155639311,"hash":"39","data":"40"},"/home/gib/Documents/Code/convex-monorepo/apps/next/public/t3-icon.svg",{"size":923,"mtime":1766225172000,"hash":"41"},"/home/gib/Documents/Code/convex-monorepo/apps/next/next.config.js",{"size":2062,"mtime":1768155639139,"hash":"42","data":"43"},"/home/gib/Documents/Code/convex-monorepo/apps/next/package.json",{"size":1506,"mtime":1768154671185,"hash":"44","data":"45"},"/home/gib/Documents/Code/convex-monorepo/apps/next/tsconfig.json",{"size":297,"mtime":1766225936000,"hash":"46","data":"47"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/styles.css",{"size":596,"mtime":1768155639429,"hash":"48","data":"49"},"/home/gib/Documents/Code/convex-monorepo/apps/next/eslint.config.ts",{"size":369,"mtime":1768155639048,"hash":"50","data":"51"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/page.tsx",{"size":1169,"mtime":1768155639357,"hash":"52","data":"53"},"08dcc17ca04632a7262728b699450d5d",{"hashOfOptions":"54"},"d9fa362e836306677416d4e30dfb1528",{"hashOfOptions":"55"},"36aa513994f9883f30ff408fe777cec6","f819b8d99aba405d3975e6e5d3adf796",{"hashOfOptions":"56"},"44418c5550aee51cfdf0a321ad70ae47","1f2ba5c5e807955994fd4dfca4c709be",{"hashOfOptions":"57"},"6dba01a7cb29904291cb3c9930fc1ac3",{"hashOfOptions":"58"},"785dd21512a5bdf43635be77f6a483ae",{"hashOfOptions":"59"},"48e377494d0046d38b923af54e109529",{"hashOfOptions":"60"},"a9eecac327a9c09dd26e82c515134edc",{"hashOfOptions":"61"},"3847ea1421b6ea4079a526d7e44c946d",{"hashOfOptions":"62"},"1049592143","533286024","3492548434","1155092478","4045122132","2138361299","3590205716","4261166930","1190248983"]
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
import { defineConfig } from "eslint/config";
|
import { defineConfig } from 'eslint/config';
|
||||||
|
|
||||||
import { baseConfig, restrictEnvAccess } from "@gib/eslint-config/base";
|
import { baseConfig, restrictEnvAccess } from '@gib/eslint-config/base';
|
||||||
import { nextjsConfig } from "@gib/eslint-config/nextjs";
|
import { nextjsConfig } from '@gib/eslint-config/nextjs';
|
||||||
import { reactConfig } from "@gib/eslint-config/react";
|
import { reactConfig } from '@gib/eslint-config/react';
|
||||||
|
|
||||||
export default defineConfig(
|
export default defineConfig(
|
||||||
{
|
{
|
||||||
ignores: [".next/**"],
|
ignores: ['.next/**'],
|
||||||
},
|
},
|
||||||
baseConfig,
|
baseConfig,
|
||||||
reactConfig,
|
reactConfig,
|
||||||
nextjsConfig,
|
nextjsConfig,
|
||||||
restrictEnvAccess,
|
restrictEnvAccess,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import { env } from './src/env';
|
|
||||||
import { withSentryConfig } from '@sentry/nextjs';
|
import { withSentryConfig } from '@sentry/nextjs';
|
||||||
|
import { createJiti } from 'jiti';
|
||||||
import { withPlausibleProxy } from 'next-plausible';
|
import { withPlausibleProxy } from 'next-plausible';
|
||||||
import { createJiti } from "jiti";
|
|
||||||
|
|
||||||
const jiti = createJiti(import.meta.url);
|
const jiti = createJiti(import.meta.url);
|
||||||
|
|
||||||
// Import env files to validate at build time. Use jiti so we can load .ts files in here.
|
// Import env files to validate at build time. Use jiti so we can load .ts files in here.
|
||||||
await jiti.import("./src/env");
|
await jiti.import('./src/env');
|
||||||
|
|
||||||
/** @type {import("next").NextConfig} */
|
/** @type {import("next").NextConfig} */
|
||||||
const config = withPlausibleProxy({
|
const config = withPlausibleProxy({
|
||||||
@@ -28,15 +27,10 @@ const config = withPlausibleProxy({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
/** Enables hot reloading for local packages without a build step */
|
/** Enables hot reloading for local packages without a build step */
|
||||||
transpilePackages: [
|
transpilePackages: ['@gib/backend', '@gib/ui'],
|
||||||
"@gib/backend",
|
|
||||||
"@gib/ui",
|
|
||||||
],
|
|
||||||
typescript: { ignoreBuildErrors: true },
|
typescript: { ignoreBuildErrors: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const sentryConfig = {
|
const sentryConfig = {
|
||||||
// For all available options, see:
|
// For all available options, see:
|
||||||
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
|
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@gib/nextjs",
|
"name": "@gib/next",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
import { headers } from "next/headers";
|
|
||||||
import { redirect } from "next/navigation";
|
|
||||||
|
|
||||||
import { Button } from "@acme/ui/button";
|
|
||||||
|
|
||||||
import { auth, getSession } from "~/auth/server";
|
|
||||||
|
|
||||||
export async function AuthShowcase() {
|
|
||||||
const session = await getSession();
|
|
||||||
|
|
||||||
if (!session) {
|
|
||||||
return (
|
|
||||||
<form>
|
|
||||||
<Button
|
|
||||||
size="lg"
|
|
||||||
formAction={async () => {
|
|
||||||
"use server";
|
|
||||||
const res = await auth.api.signInSocial({
|
|
||||||
body: {
|
|
||||||
provider: "discord",
|
|
||||||
callbackURL: "/",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!res.url) {
|
|
||||||
throw new Error("No URL returned from signInSocial");
|
|
||||||
}
|
|
||||||
redirect(res.url);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Sign in with Discord
|
|
||||||
</Button>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col items-center justify-center gap-4">
|
|
||||||
<p className="text-center text-2xl">
|
|
||||||
<span>Logged in as {session.user.name}</span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<Button
|
|
||||||
size="lg"
|
|
||||||
formAction={async () => {
|
|
||||||
"use server";
|
|
||||||
await auth.api.signOut({
|
|
||||||
headers: await headers(),
|
|
||||||
});
|
|
||||||
redirect("/");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Sign out
|
|
||||||
</Button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { useForm } from "@tanstack/react-form";
|
|
||||||
import {
|
|
||||||
useMutation,
|
|
||||||
useQueryClient,
|
|
||||||
useSuspenseQuery,
|
|
||||||
} from "@tanstack/react-query";
|
|
||||||
|
|
||||||
import type { RouterOutputs } from "@acme/api";
|
|
||||||
import { CreatePostSchema } from "@acme/db/schema";
|
|
||||||
import { cn } from "@acme/ui";
|
|
||||||
import { Button } from "@acme/ui/button";
|
|
||||||
import {
|
|
||||||
Field,
|
|
||||||
FieldContent,
|
|
||||||
FieldError,
|
|
||||||
FieldGroup,
|
|
||||||
FieldLabel,
|
|
||||||
} from "@acme/ui/field";
|
|
||||||
import { Input } from "@acme/ui/input";
|
|
||||||
import { toast } from "@acme/ui/toast";
|
|
||||||
|
|
||||||
import { useTRPC } from "~/trpc/react";
|
|
||||||
|
|
||||||
export function CreatePostForm() {
|
|
||||||
const trpc = useTRPC();
|
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const createPost = useMutation(
|
|
||||||
trpc.post.create.mutationOptions({
|
|
||||||
onSuccess: async () => {
|
|
||||||
form.reset();
|
|
||||||
await queryClient.invalidateQueries(trpc.post.pathFilter());
|
|
||||||
},
|
|
||||||
onError: (err) => {
|
|
||||||
toast.error(
|
|
||||||
err.data?.code === "UNAUTHORIZED"
|
|
||||||
? "You must be logged in to post"
|
|
||||||
: "Failed to create post",
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const form = useForm({
|
|
||||||
defaultValues: {
|
|
||||||
content: "",
|
|
||||||
title: "",
|
|
||||||
},
|
|
||||||
validators: {
|
|
||||||
onSubmit: CreatePostSchema,
|
|
||||||
},
|
|
||||||
onSubmit: (data) => createPost.mutate(data.value),
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form
|
|
||||||
className="w-full max-w-2xl"
|
|
||||||
onSubmit={(event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
void form.handleSubmit();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FieldGroup>
|
|
||||||
<form.Field
|
|
||||||
name="title"
|
|
||||||
children={(field) => {
|
|
||||||
const isInvalid =
|
|
||||||
field.state.meta.isTouched && !field.state.meta.isValid;
|
|
||||||
return (
|
|
||||||
<Field data-invalid={isInvalid}>
|
|
||||||
<FieldContent>
|
|
||||||
<FieldLabel htmlFor={field.name}>Bug Title</FieldLabel>
|
|
||||||
</FieldContent>
|
|
||||||
<Input
|
|
||||||
id={field.name}
|
|
||||||
name={field.name}
|
|
||||||
value={field.state.value}
|
|
||||||
onBlur={field.handleBlur}
|
|
||||||
onChange={(e) => field.handleChange(e.target.value)}
|
|
||||||
aria-invalid={isInvalid}
|
|
||||||
placeholder="Title"
|
|
||||||
/>
|
|
||||||
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
|
||||||
</Field>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<form.Field
|
|
||||||
name="content"
|
|
||||||
children={(field) => {
|
|
||||||
const isInvalid =
|
|
||||||
field.state.meta.isTouched && !field.state.meta.isValid;
|
|
||||||
return (
|
|
||||||
<Field data-invalid={isInvalid}>
|
|
||||||
<FieldContent>
|
|
||||||
<FieldLabel htmlFor={field.name}>Content</FieldLabel>
|
|
||||||
</FieldContent>
|
|
||||||
<Input
|
|
||||||
id={field.name}
|
|
||||||
name={field.name}
|
|
||||||
value={field.state.value}
|
|
||||||
onBlur={field.handleBlur}
|
|
||||||
onChange={(e) => field.handleChange(e.target.value)}
|
|
||||||
aria-invalid={isInvalid}
|
|
||||||
placeholder="Content"
|
|
||||||
/>
|
|
||||||
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
|
||||||
</Field>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FieldGroup>
|
|
||||||
<Button type="submit">Create</Button>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PostList() {
|
|
||||||
const trpc = useTRPC();
|
|
||||||
const { data: posts } = useSuspenseQuery(trpc.post.all.queryOptions());
|
|
||||||
|
|
||||||
if (posts.length === 0) {
|
|
||||||
return (
|
|
||||||
<div className="relative flex w-full flex-col gap-4">
|
|
||||||
<PostCardSkeleton pulse={false} />
|
|
||||||
<PostCardSkeleton pulse={false} />
|
|
||||||
<PostCardSkeleton pulse={false} />
|
|
||||||
|
|
||||||
<div className="absolute inset-0 flex flex-col items-center justify-center bg-black/10">
|
|
||||||
<p className="text-2xl font-bold text-white">No posts yet</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex w-full flex-col gap-4">
|
|
||||||
{posts.map((p) => {
|
|
||||||
return <PostCard key={p.id} post={p} />;
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PostCard(props: {
|
|
||||||
post: RouterOutputs["post"]["all"][number];
|
|
||||||
}) {
|
|
||||||
const trpc = useTRPC();
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const deletePost = useMutation(
|
|
||||||
trpc.post.delete.mutationOptions({
|
|
||||||
onSuccess: async () => {
|
|
||||||
await queryClient.invalidateQueries(trpc.post.pathFilter());
|
|
||||||
},
|
|
||||||
onError: (err) => {
|
|
||||||
toast.error(
|
|
||||||
err.data?.code === "UNAUTHORIZED"
|
|
||||||
? "You must be logged in to delete a post"
|
|
||||||
: "Failed to delete post",
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="bg-muted flex flex-row rounded-lg p-4">
|
|
||||||
<div className="grow">
|
|
||||||
<h2 className="text-primary text-2xl font-bold">{props.post.title}</h2>
|
|
||||||
<p className="mt-2 text-sm">{props.post.content}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
className="text-primary cursor-pointer text-sm font-bold uppercase hover:bg-transparent hover:text-white"
|
|
||||||
onClick={() => deletePost.mutate(props.post.id)}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PostCardSkeleton(props: { pulse?: boolean }) {
|
|
||||||
const { pulse = true } = props;
|
|
||||||
return (
|
|
||||||
<div className="bg-muted flex flex-row rounded-lg p-4">
|
|
||||||
<div className="grow">
|
|
||||||
<h2
|
|
||||||
className={cn(
|
|
||||||
"bg-primary w-1/4 rounded-sm text-2xl font-bold",
|
|
||||||
pulse && "animate-pulse",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
<p
|
|
||||||
className={cn(
|
|
||||||
"mt-2 w-1/3 rounded-sm bg-current text-sm",
|
|
||||||
pulse && "animate-pulse",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
import { auth } from "~/auth/server";
|
|
||||||
|
|
||||||
export const GET = auth.handler;
|
|
||||||
export const POST = auth.handler;
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import type { NextRequest } from "next/server";
|
|
||||||
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
|
|
||||||
|
|
||||||
import { appRouter, createTRPCContext } from "@acme/api";
|
|
||||||
|
|
||||||
import { auth } from "~/auth/server";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure basic CORS headers
|
|
||||||
* You should extend this to match your needs
|
|
||||||
*/
|
|
||||||
const setCorsHeaders = (res: Response) => {
|
|
||||||
res.headers.set("Access-Control-Allow-Origin", "*");
|
|
||||||
res.headers.set("Access-Control-Request-Method", "*");
|
|
||||||
res.headers.set("Access-Control-Allow-Methods", "OPTIONS, GET, POST");
|
|
||||||
res.headers.set("Access-Control-Allow-Headers", "*");
|
|
||||||
};
|
|
||||||
|
|
||||||
export const OPTIONS = () => {
|
|
||||||
const response = new Response(null, {
|
|
||||||
status: 204,
|
|
||||||
});
|
|
||||||
setCorsHeaders(response);
|
|
||||||
return response;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handler = async (req: NextRequest) => {
|
|
||||||
const response = await fetchRequestHandler({
|
|
||||||
endpoint: "/api/trpc",
|
|
||||||
router: appRouter,
|
|
||||||
req,
|
|
||||||
createContext: () =>
|
|
||||||
createTRPCContext({
|
|
||||||
auth: auth,
|
|
||||||
headers: req.headers,
|
|
||||||
}),
|
|
||||||
onError({ error, path }) {
|
|
||||||
console.error(`>>> tRPC Error on '${path}'`, error);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
setCorsHeaders(response);
|
|
||||||
return response;
|
|
||||||
};
|
|
||||||
|
|
||||||
export { handler as GET, handler as POST };
|
|
||||||
@@ -1,50 +1,49 @@
|
|||||||
import type { Metadata, Viewport } from "next";
|
import type { Metadata, Viewport } from 'next';
|
||||||
import { Geist, Geist_Mono } from "next/font/google";
|
import { Geist, Geist_Mono } from 'next/font/google';
|
||||||
|
import { cn } from '@acme/ui';
|
||||||
|
import { ThemeProvider, ThemeToggle } from '@acme/ui/theme';
|
||||||
|
import { Toaster } from '@acme/ui/toast';
|
||||||
|
|
||||||
import { cn } from "@acme/ui";
|
import { env } from '~/env';
|
||||||
import { ThemeProvider, ThemeToggle } from "@acme/ui/theme";
|
import { TRPCReactProvider } from '~/trpc/react';
|
||||||
import { Toaster } from "@acme/ui/toast";
|
|
||||||
|
|
||||||
import { env } from "~/env";
|
import '~/app/styles.css';
|
||||||
import { TRPCReactProvider } from "~/trpc/react";
|
|
||||||
|
|
||||||
import "~/app/styles.css";
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
metadataBase: new URL(
|
metadataBase: new URL(
|
||||||
env.VERCEL_ENV === "production"
|
env.VERCEL_ENV === 'production'
|
||||||
? "https://turbo.t3.gg"
|
? 'https://turbo.t3.gg'
|
||||||
: "http://localhost:3000",
|
: 'http://localhost:3000',
|
||||||
),
|
),
|
||||||
title: "Create T3 Turbo",
|
title: 'Create T3 Turbo',
|
||||||
description: "Simple monorepo with shared backend for web & mobile apps",
|
description: 'Simple monorepo with shared backend for web & mobile apps',
|
||||||
openGraph: {
|
openGraph: {
|
||||||
title: "Create T3 Turbo",
|
title: 'Create T3 Turbo',
|
||||||
description: "Simple monorepo with shared backend for web & mobile apps",
|
description: 'Simple monorepo with shared backend for web & mobile apps',
|
||||||
url: "https://create-t3-turbo.vercel.app",
|
url: 'https://create-t3-turbo.vercel.app',
|
||||||
siteName: "Create T3 Turbo",
|
siteName: 'Create T3 Turbo',
|
||||||
},
|
},
|
||||||
twitter: {
|
twitter: {
|
||||||
card: "summary_large_image",
|
card: 'summary_large_image',
|
||||||
site: "@jullerino",
|
site: '@jullerino',
|
||||||
creator: "@jullerino",
|
creator: '@jullerino',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const viewport: Viewport = {
|
export const viewport: Viewport = {
|
||||||
themeColor: [
|
themeColor: [
|
||||||
{ media: "(prefers-color-scheme: light)", color: "white" },
|
{ media: '(prefers-color-scheme: light)', color: 'white' },
|
||||||
{ media: "(prefers-color-scheme: dark)", color: "black" },
|
{ media: '(prefers-color-scheme: dark)', color: 'black' },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const geistSans = Geist({
|
const geistSans = Geist({
|
||||||
subsets: ["latin"],
|
subsets: ['latin'],
|
||||||
variable: "--font-geist-sans",
|
variable: '--font-geist-sans',
|
||||||
});
|
});
|
||||||
const geistMono = Geist_Mono({
|
const geistMono = Geist_Mono({
|
||||||
subsets: ["latin"],
|
subsets: ['latin'],
|
||||||
variable: "--font-geist-mono",
|
variable: '--font-geist-mono',
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function RootLayout(props: { children: React.ReactNode }) {
|
export default function RootLayout(props: { children: React.ReactNode }) {
|
||||||
@@ -52,7 +51,7 @@ export default function RootLayout(props: { children: React.ReactNode }) {
|
|||||||
<html lang="en" suppressHydrationWarning>
|
<html lang="en" suppressHydrationWarning>
|
||||||
<body
|
<body
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-background text-foreground min-h-screen font-sans antialiased",
|
'bg-background text-foreground min-h-screen font-sans antialiased',
|
||||||
geistSans.variable,
|
geistSans.variable,
|
||||||
geistMono.variable,
|
geistMono.variable,
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { Suspense } from "react";
|
import { Suspense } from 'react';
|
||||||
|
|
||||||
import { HydrateClient, prefetch, trpc } from "~/trpc/server";
|
import { HydrateClient, prefetch, trpc } from '~/trpc/server';
|
||||||
import { AuthShowcase } from "./_components/auth-showcase";
|
import { AuthShowcase } from './_components/auth-showcase';
|
||||||
import {
|
import {
|
||||||
CreatePostForm,
|
CreatePostForm,
|
||||||
PostCardSkeleton,
|
PostCardSkeleton,
|
||||||
PostList,
|
PostList,
|
||||||
} from "./_components/posts";
|
} from './_components/posts';
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
prefetch(trpc.post.all.queryOptions());
|
prefetch(trpc.post.all.queryOptions());
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
@import "tailwindcss";
|
@import 'tailwindcss';
|
||||||
@import "tw-animate-css";
|
@import 'tw-animate-css';
|
||||||
@import "@acme/tailwind-config/theme";
|
@import '@acme/tailwind-config/theme';
|
||||||
|
|
||||||
@source "../../../../packages/ui/src/*.{ts,tsx}";
|
@source '../../../../packages/ui/src/*.{ts,tsx}';
|
||||||
|
|
||||||
@custom-variant dark (&:where(.dark, .dark *));
|
@custom-variant dark (&:where(.dark, .dark *));
|
||||||
@custom-variant light (&:where(.light, .light *));
|
@custom-variant light (&:where(.light, .light *));
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
import { createEnv } from "@t3-oss/env-nextjs";
|
import { createEnv } from '@t3-oss/env-nextjs';
|
||||||
import { z } from "zod/v4";
|
import { z } from 'zod/v4';
|
||||||
|
|
||||||
export const env = createEnv({
|
export const env = createEnv({
|
||||||
shared: {
|
shared: {
|
||||||
NODE_ENV: z
|
NODE_ENV: z
|
||||||
.enum(["development", "production", "test"])
|
.enum(['development', 'production', 'test'])
|
||||||
.default("development"),
|
.default('development'),
|
||||||
CI: z.boolean().default(false),
|
|
||||||
SITE_URL: z.string().default("http://localhost:3000"),
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Specify your server-side environment variables schema here.
|
* Specify your server-side environment variables schema here.
|
||||||
@@ -22,6 +20,7 @@ export const env = createEnv({
|
|||||||
* For them to be exposed to the client, prefix them with `NEXT_PUBLIC_`.
|
* For them to be exposed to the client, prefix them with `NEXT_PUBLIC_`.
|
||||||
*/
|
*/
|
||||||
client: {
|
client: {
|
||||||
|
NEXT_PUBLIC_SITE_URL: z.url(),
|
||||||
NEXT_PUBLIC_CONVEX_URL: z.url(),
|
NEXT_PUBLIC_CONVEX_URL: z.url(),
|
||||||
NEXT_PUBLIC_PLAUSIBLE_URL: z.url(),
|
NEXT_PUBLIC_PLAUSIBLE_URL: z.url(),
|
||||||
NEXT_PUBLIC_SENTRY_DSN: z.string(),
|
NEXT_PUBLIC_SENTRY_DSN: z.string(),
|
||||||
@@ -36,13 +35,15 @@ export const env = createEnv({
|
|||||||
NODE_ENV: process.env.NODE_ENV,
|
NODE_ENV: process.env.NODE_ENV,
|
||||||
CI: process.env.CI,
|
CI: process.env.CI,
|
||||||
SITE_URL: process.env.SITE_URL,
|
SITE_URL: process.env.SITE_URL,
|
||||||
|
NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL,
|
||||||
NEXT_PUBLIC_CONVEX_URL: process.env.NEXT_PUBLIC_CONVEX_URL,
|
NEXT_PUBLIC_CONVEX_URL: process.env.NEXT_PUBLIC_CONVEX_URL,
|
||||||
NEXT_PUBLIC_PLAUSIBLE_URL: process.env.NEXT_PUBLIC_PLAUSIBLE_URL,
|
NEXT_PUBLIC_PLAUSIBLE_URL: process.env.NEXT_PUBLIC_PLAUSIBLE_URL,
|
||||||
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||||
NEXT_PUBLIC_SENTRY_URL: process.env.NEXT_PUBLIC_SENTRY_URL,
|
NEXT_PUBLIC_SENTRY_URL: process.env.NEXT_PUBLIC_SENTRY_URL,
|
||||||
NEXT_PUBLIC_SENTRY_ORG: process.env.NEXT_PUBLIC_SENTRY_ORG,
|
NEXT_PUBLIC_SENTRY_ORG: process.env.NEXT_PUBLIC_SENTRY_ORG,
|
||||||
NEXT_PUBLIC_SENTRY_PROJECT_NAME: process.env.NEXT_PUBLIC_SENTRY_PROJECT_NAME,
|
NEXT_PUBLIC_SENTRY_PROJECT_NAME:
|
||||||
|
process.env.NEXT_PUBLIC_SENTRY_PROJECT_NAME,
|
||||||
},
|
},
|
||||||
skipValidation:
|
skipValidation:
|
||||||
!!process.env.CI || process.env.npm_lifecycle_event === "lint",
|
!!process.env.CI || process.env.npm_lifecycle_event === 'lint',
|
||||||
});
|
});
|
||||||
|
|||||||
95
bun.lock
95
bun.lock
@@ -1,14 +1,15 @@
|
|||||||
{
|
{
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 0,
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "convex-turbo",
|
"name": "convex-turbo",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@gib/prettier-config": "workspace:",
|
"@gib/prettier-config": "workspace:",
|
||||||
"@turbo/gen": "^2.5.8",
|
"@turbo/gen": "^2.7.3",
|
||||||
"dotenv-cli": "^10.0.0",
|
"dotenv-cli": "^10.0.0",
|
||||||
"prettier": "catalog:",
|
"prettier": "catalog:",
|
||||||
"turbo": "^2.5.8",
|
"turbo": "^2.7.3",
|
||||||
"typescript": "catalog:",
|
"typescript": "catalog:",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -65,7 +66,7 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"apps/next": {
|
"apps/next": {
|
||||||
"name": "@gib/nextjs",
|
"name": "@gib/next",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@convex-dev/auth": "catalog:convex",
|
"@convex-dev/auth": "catalog:convex",
|
||||||
@@ -237,10 +238,10 @@
|
|||||||
"convex": "^1.28.0",
|
"convex": "^1.28.0",
|
||||||
},
|
},
|
||||||
"react19": {
|
"react19": {
|
||||||
"@types/react": "^19.1.12",
|
"@types/react": "~19.1.0",
|
||||||
"@types/react-dom": "^19.1.9",
|
"@types/react-dom": "~19.1.0",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.4",
|
||||||
"react-dom": "19.1.1",
|
"react-dom": "19.1.4",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
@@ -728,7 +729,7 @@
|
|||||||
|
|
||||||
"@gib/expo": ["@gib/expo@workspace:apps/expo"],
|
"@gib/expo": ["@gib/expo@workspace:apps/expo"],
|
||||||
|
|
||||||
"@gib/nextjs": ["@gib/nextjs@workspace:apps/next"],
|
"@gib/next": ["@gib/next@workspace:apps/next"],
|
||||||
|
|
||||||
"@gib/prettier-config": ["@gib/prettier-config@workspace:tools/prettier"],
|
"@gib/prettier-config": ["@gib/prettier-config@workspace:tools/prettier"],
|
||||||
|
|
||||||
@@ -796,8 +797,6 @@
|
|||||||
|
|
||||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.4", "", { "os": "win32", "cpu": "x64" }, "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig=="],
|
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.4", "", { "os": "win32", "cpu": "x64" }, "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig=="],
|
||||||
|
|
||||||
"@inquirer/external-editor": ["@inquirer/external-editor@1.0.2", "", { "dependencies": { "chardet": "^2.1.0", "iconv-lite": "^0.7.0" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ=="],
|
|
||||||
|
|
||||||
"@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="],
|
"@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="],
|
||||||
|
|
||||||
"@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="],
|
"@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="],
|
||||||
@@ -1360,9 +1359,9 @@
|
|||||||
|
|
||||||
"@tsconfig/node16": ["@tsconfig/node16@1.0.4", "", {}, "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="],
|
"@tsconfig/node16": ["@tsconfig/node16@1.0.4", "", {}, "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="],
|
||||||
|
|
||||||
"@turbo/gen": ["@turbo/gen@2.5.8", "", { "dependencies": { "@turbo/workspaces": "2.5.8", "commander": "^10.0.0", "fs-extra": "^10.1.0", "inquirer": "^8.2.4", "minimatch": "^9.0.0", "node-plop": "^0.26.3", "picocolors": "1.0.1", "proxy-agent": "^6.5.0", "ts-node": "^10.9.2", "update-check": "^1.5.4", "validate-npm-package-name": "^5.0.0" }, "bin": { "gen": "dist/cli.js" } }, "sha512-PknlZnl4NzARv9p2KnRIA2q9cGWzrvv2G5moWLoZRTLspoE7jL2XtejzwbclS2iXGbXQWk27BfIugv98tS2s7w=="],
|
"@turbo/gen": ["@turbo/gen@2.7.3", "", { "dependencies": { "@turbo/workspaces": "2.7.3", "commander": "10.0.0", "fs-extra": "10.1.0", "inquirer": "8.2.4", "minimatch": "9.0.0", "node-plop": "0.26.3", "picocolors": "1.0.1", "proxy-agent": "6.5.0", "ts-node": "10.9.2", "update-check": "1.5.4", "validate-npm-package-name": "5.0.0" }, "bin": { "gen": "dist/cli.js" } }, "sha512-lvjv1/fwUewFqew/qdNM//6cC32EIjEAJ2rCx5blL4+BVX16ubHroEGUJRNQegW0hpglTztdJW6DdS3hIuqoCA=="],
|
||||||
|
|
||||||
"@turbo/workspaces": ["@turbo/workspaces@2.5.8", "", { "dependencies": { "commander": "^10.0.0", "execa": "5.1.1", "fast-glob": "^3.2.12", "fs-extra": "^10.1.0", "gradient-string": "^2.0.0", "inquirer": "^8.0.0", "js-yaml": "^4.1.0", "ora": "4.1.1", "picocolors": "1.0.1", "semver": "7.6.2", "update-check": "^1.5.4" }, "bin": { "workspaces": "dist/cli.js" } }, "sha512-EE/27azLteK24It0B0IrjA7yWFC6jYZoTTUzL7R7HgiN0BWBPrTp6Ugpn0iE6+Bn9fFcjSp/IBBG8D8c7vXD1g=="],
|
"@turbo/workspaces": ["@turbo/workspaces@2.7.3", "", { "dependencies": { "commander": "10.0.0", "execa": "5.1.1", "fast-glob": "3.2.12", "fs-extra": "10.1.0", "gradient-string": "2.0.1", "inquirer": "8.2.4", "js-yaml": "4.1.0", "ora": "4.1.1", "picocolors": "1.0.1", "semver": "7.6.2", "update-check": "1.5.4" }, "bin": { "workspaces": "dist/cli.js" } }, "sha512-opYsHNZo3qhGJ+qxLSEhNcnf+e8beha/bfinwUH857NFL7oYHsOpVtNJIiwcJYKjZjJO4XtxTLsvAo3CQ5/R5A=="],
|
||||||
|
|
||||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.8.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Z96T/L6dUFFxgFJ+pQtkPpne9q7i6kIPYCFnQBHSgSPV9idTsKfIhCss0h5iM9irweZCatkrdeP8yi5uM1eX6Q=="],
|
"@tybys/wasm-util": ["@tybys/wasm-util@0.8.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Z96T/L6dUFFxgFJ+pQtkPpne9q7i6kIPYCFnQBHSgSPV9idTsKfIhCss0h5iM9irweZCatkrdeP8yi5uM1eX6Q=="],
|
||||||
|
|
||||||
@@ -1412,9 +1411,9 @@
|
|||||||
|
|
||||||
"@types/pg-pool": ["@types/pg-pool@2.0.6", "", { "dependencies": { "@types/pg": "*" } }, "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ=="],
|
"@types/pg-pool": ["@types/pg-pool@2.0.6", "", { "dependencies": { "@types/pg": "*" } }, "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="],
|
"@types/react": ["@types/react@19.1.17", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA=="],
|
||||||
|
|
||||||
"@types/react-dom": ["@types/react-dom@19.2.2", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw=="],
|
"@types/react-dom": ["@types/react-dom@19.1.11", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-3BKc/yGdNTYQVVw4idqHtSOcFsgGuBbMveKCOgF8wQ5QtrYOc3jDIlzg3jef04zcXFIHLelyGlj0T+BJ8+KN+w=="],
|
||||||
|
|
||||||
"@types/shimmer": ["@types/shimmer@1.2.0", "", {}, "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg=="],
|
"@types/shimmer": ["@types/shimmer@1.2.0", "", {}, "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg=="],
|
||||||
|
|
||||||
@@ -1634,6 +1633,8 @@
|
|||||||
|
|
||||||
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
||||||
|
|
||||||
|
"builtins": ["builtins@5.1.0", "", { "dependencies": { "semver": "^7.0.0" } }, "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg=="],
|
||||||
|
|
||||||
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
||||||
|
|
||||||
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
|
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
|
||||||
@@ -1656,7 +1657,7 @@
|
|||||||
|
|
||||||
"change-case": ["change-case@3.1.0", "", { "dependencies": { "camel-case": "^3.0.0", "constant-case": "^2.0.0", "dot-case": "^2.1.0", "header-case": "^1.0.0", "is-lower-case": "^1.1.0", "is-upper-case": "^1.1.0", "lower-case": "^1.1.1", "lower-case-first": "^1.0.0", "no-case": "^2.3.2", "param-case": "^2.1.0", "pascal-case": "^2.0.0", "path-case": "^2.1.0", "sentence-case": "^2.1.0", "snake-case": "^2.1.0", "swap-case": "^1.1.0", "title-case": "^2.1.0", "upper-case": "^1.1.1", "upper-case-first": "^1.1.0" } }, "sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw=="],
|
"change-case": ["change-case@3.1.0", "", { "dependencies": { "camel-case": "^3.0.0", "constant-case": "^2.0.0", "dot-case": "^2.1.0", "header-case": "^1.0.0", "is-lower-case": "^1.1.0", "is-upper-case": "^1.1.0", "lower-case": "^1.1.1", "lower-case-first": "^1.0.0", "no-case": "^2.3.2", "param-case": "^2.1.0", "pascal-case": "^2.0.0", "path-case": "^2.1.0", "sentence-case": "^2.1.0", "snake-case": "^2.1.0", "swap-case": "^1.1.0", "title-case": "^2.1.0", "upper-case": "^1.1.1", "upper-case-first": "^1.1.0" } }, "sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw=="],
|
||||||
|
|
||||||
"chardet": ["chardet@2.1.0", "", {}, "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA=="],
|
"chardet": ["chardet@0.7.0", "", {}, "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="],
|
||||||
|
|
||||||
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
||||||
|
|
||||||
@@ -1704,7 +1705,7 @@
|
|||||||
|
|
||||||
"colorjs.io": ["colorjs.io@0.6.0-alpha.1", "", {}, "sha512-c/h/8uAmPydQcriRdX8UTAFHj6SpSHFHBA8LvMikvYWAVApPTwg/pyOXNsGmaCBd6L/EeDlRHSNhTtnIFp/qsg=="],
|
"colorjs.io": ["colorjs.io@0.6.0-alpha.1", "", {}, "sha512-c/h/8uAmPydQcriRdX8UTAFHj6SpSHFHBA8LvMikvYWAVApPTwg/pyOXNsGmaCBd6L/EeDlRHSNhTtnIFp/qsg=="],
|
||||||
|
|
||||||
"commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="],
|
"commander": ["commander@10.0.0", "", {}, "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA=="],
|
||||||
|
|
||||||
"comment-json": ["comment-json@4.4.1", "", { "dependencies": { "array-timsort": "^1.0.3", "core-util-is": "^1.0.3", "esprima": "^4.0.1" } }, "sha512-r1To31BQD5060QdkC+Iheai7gHwoSZobzunqkf2/kQ6xIAfJyrKNAFUwdKvkK7Qgu7pVTKQEa7ok7Ed3ycAJgg=="],
|
"comment-json": ["comment-json@4.4.1", "", { "dependencies": { "array-timsort": "^1.0.3", "core-util-is": "^1.0.3", "esprima": "^4.0.1" } }, "sha512-r1To31BQD5060QdkC+Iheai7gHwoSZobzunqkf2/kQ6xIAfJyrKNAFUwdKvkK7Qgu7pVTKQEa7ok7Ed3ycAJgg=="],
|
||||||
|
|
||||||
@@ -2104,7 +2105,7 @@
|
|||||||
|
|
||||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||||
|
|
||||||
"gradient-string": ["gradient-string@2.0.2", "", { "dependencies": { "chalk": "^4.1.2", "tinygradient": "^1.1.5" } }, "sha512-rEDCuqUQ4tbD78TpzsMtt5OIf0cBCSDWSJtUDaF6JsAh+k0v9r++NzxNEG87oDZx9ZwGhD8DaezR2L/yrw0Jdw=="],
|
"gradient-string": ["gradient-string@2.0.1", "", { "dependencies": { "chalk": "^4.1.2", "tinygradient": "^1.1.5" } }, "sha512-+xDOYR2fMa4QHGysTgyQsl8g16mcAKqvvsKI014qYP2XVf1SWUPlD8KhdBJPUM8AVwDUB+ls0NFkqRzAB5URkA=="],
|
||||||
|
|
||||||
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
|
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
|
||||||
|
|
||||||
@@ -2148,7 +2149,7 @@
|
|||||||
|
|
||||||
"hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="],
|
"hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="],
|
||||||
|
|
||||||
"iconv-lite": ["iconv-lite@0.7.0", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ=="],
|
"iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="],
|
||||||
|
|
||||||
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||||
|
|
||||||
@@ -2176,7 +2177,7 @@
|
|||||||
|
|
||||||
"input-otp": ["input-otp@1.4.2", "", { "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA=="],
|
"input-otp": ["input-otp@1.4.2", "", { "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA=="],
|
||||||
|
|
||||||
"inquirer": ["inquirer@8.2.7", "", { "dependencies": { "@inquirer/external-editor": "^1.0.0", "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", "cli-cursor": "^3.1.0", "cli-width": "^3.0.0", "figures": "^3.0.0", "lodash": "^4.17.21", "mute-stream": "0.0.8", "ora": "^5.4.1", "run-async": "^2.4.0", "rxjs": "^7.5.5", "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6", "wrap-ansi": "^6.0.1" } }, "sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA=="],
|
"inquirer": ["inquirer@8.2.4", "", { "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", "cli-cursor": "^3.1.0", "cli-width": "^3.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", "lodash": "^4.17.21", "mute-stream": "0.0.8", "ora": "^5.4.1", "run-async": "^2.4.0", "rxjs": "^7.5.5", "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6", "wrap-ansi": "^7.0.0" } }, "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg=="],
|
||||||
|
|
||||||
"internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
|
"internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
|
||||||
|
|
||||||
@@ -2462,7 +2463,7 @@
|
|||||||
|
|
||||||
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
|
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
|
||||||
|
|
||||||
"minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
"minimatch": ["minimatch@9.0.0", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w=="],
|
||||||
|
|
||||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||||
|
|
||||||
@@ -2692,7 +2693,7 @@
|
|||||||
|
|
||||||
"react-devtools-core": ["react-devtools-core@6.1.5", "", { "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" } }, "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA=="],
|
"react-devtools-core": ["react-devtools-core@6.1.5", "", { "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" } }, "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA=="],
|
||||||
|
|
||||||
"react-dom": ["react-dom@19.1.1", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.1" } }, "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw=="],
|
"react-dom": ["react-dom@19.1.4", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.4" } }, "sha512-s2868ab/xo2SI6H4106A7aFI8Mrqa4xC6HZT/pBzYyQ3cBLqa88hu47xYD8xf+uECleN698Awn7RCWlkTiKnqQ=="],
|
||||||
|
|
||||||
"react-email": ["react-email@4.2.11", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/traverse": "^7.27.0", "chokidar": "^4.0.3", "commander": "^13.0.0", "debounce": "^2.0.0", "esbuild": "^0.25.0", "glob": "^11.0.0", "jiti": "2.4.2", "log-symbols": "^7.0.0", "mime-types": "^3.0.0", "normalize-path": "^3.0.0", "nypm": "0.6.0", "ora": "^8.0.0", "prompts": "2.4.2", "socket.io": "^4.8.1", "tsconfig-paths": "4.2.0" }, "bin": { "email": "dist/index.js" } }, "sha512-/7TXRgsTrXcV1u7kc5ZXDVlPvZqEBaYcflMhE2FgWIJh3OHLjj2FqctFTgYcp0iwzbR59a7gzJLmSKyD0wYJEQ=="],
|
"react-email": ["react-email@4.2.11", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/traverse": "^7.27.0", "chokidar": "^4.0.3", "commander": "^13.0.0", "debounce": "^2.0.0", "esbuild": "^0.25.0", "glob": "^11.0.0", "jiti": "2.4.2", "log-symbols": "^7.0.0", "mime-types": "^3.0.0", "normalize-path": "^3.0.0", "nypm": "0.6.0", "ora": "^8.0.0", "prompts": "2.4.2", "socket.io": "^4.8.1", "tsconfig-paths": "4.2.0" }, "bin": { "email": "dist/index.js" } }, "sha512-/7TXRgsTrXcV1u7kc5ZXDVlPvZqEBaYcflMhE2FgWIJh3OHLjj2FqctFTgYcp0iwzbR59a7gzJLmSKyD0wYJEQ=="],
|
||||||
|
|
||||||
@@ -3012,19 +3013,19 @@
|
|||||||
|
|
||||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"turbo": ["turbo@2.5.8", "", { "optionalDependencies": { "turbo-darwin-64": "2.5.8", "turbo-darwin-arm64": "2.5.8", "turbo-linux-64": "2.5.8", "turbo-linux-arm64": "2.5.8", "turbo-windows-64": "2.5.8", "turbo-windows-arm64": "2.5.8" }, "bin": { "turbo": "bin/turbo" } }, "sha512-5c9Fdsr9qfpT3hA0EyYSFRZj1dVVsb6KIWubA9JBYZ/9ZEAijgUEae0BBR/Xl/wekt4w65/lYLTFaP3JmwSO8w=="],
|
"turbo": ["turbo@2.7.3", "", { "optionalDependencies": { "turbo-darwin-64": "2.7.3", "turbo-darwin-arm64": "2.7.3", "turbo-linux-64": "2.7.3", "turbo-linux-arm64": "2.7.3", "turbo-windows-64": "2.7.3", "turbo-windows-arm64": "2.7.3" }, "bin": { "turbo": "bin/turbo" } }, "sha512-+HjKlP4OfYk+qzvWNETA3cUO5UuK6b5MSc2UJOKyvBceKucQoQGb2g7HlC2H1GHdkfKrk4YF1VPvROkhVZDDLQ=="],
|
||||||
|
|
||||||
"turbo-darwin-64": ["turbo-darwin-64@2.5.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-Dh5bCACiHO8rUXZLpKw+m3FiHtAp2CkanSyJre+SInEvEr5kIxjGvCK/8MFX8SFRjQuhjtvpIvYYZJB4AGCxNQ=="],
|
"turbo-darwin-64": ["turbo-darwin-64@2.7.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-aZHhvRiRHXbJw1EcEAq4aws1hsVVUZ9DPuSFaq9VVFAKCup7niIEwc22glxb7240yYEr1vLafdQ2U294Vcwz+w=="],
|
||||||
|
|
||||||
"turbo-darwin-arm64": ["turbo-darwin-arm64@2.5.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-f1H/tQC9px7+hmXn6Kx/w8Jd/FneIUnvLlcI/7RGHunxfOkKJKvsoiNzySkoHQ8uq1pJnhJ0xNGTlYM48ZaJOQ=="],
|
"turbo-darwin-arm64": ["turbo-darwin-arm64@2.7.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-CkVrHSq+Bnhl9sX2LQgqQYVfLTWC2gvI74C4758OmU0djfrssDKU9d4YQF0AYXXhIIRZipSXfxClQziIMD+EAg=="],
|
||||||
|
|
||||||
"turbo-linux-64": ["turbo-linux-64@2.5.8", "", { "os": "linux", "cpu": "x64" }, "sha512-hMyvc7w7yadBlZBGl/bnR6O+dJTx3XkTeyTTH4zEjERO6ChEs0SrN8jTFj1lueNXKIHh1SnALmy6VctKMGnWfw=="],
|
"turbo-linux-64": ["turbo-linux-64@2.7.3", "", { "os": "linux", "cpu": "x64" }, "sha512-GqDsCNnzzr89kMaLGpRALyigUklzgxIrSy2pHZVXyifgczvYPnLglex78Aj3T2gu+T3trPPH2iJ+pWucVOCC2Q=="],
|
||||||
|
|
||||||
"turbo-linux-arm64": ["turbo-linux-arm64@2.5.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-LQELGa7bAqV2f+3rTMRPnj5G/OHAe2U+0N9BwsZvfMvHSUbsQ3bBMWdSQaYNicok7wOZcHjz2TkESn1hYK6xIQ=="],
|
"turbo-linux-arm64": ["turbo-linux-arm64@2.7.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-NdCDTfIcIo3dWjsiaAHlxu5gW61Ed/8maah1IAF/9E3EtX0aAHNiBMbuYLZaR4vRJ7BeVkYB6xKWRtdFLZ0y3g=="],
|
||||||
|
|
||||||
"turbo-windows-64": ["turbo-windows-64@2.5.8", "", { "os": "win32", "cpu": "x64" }, "sha512-3YdcaW34TrN1AWwqgYL9gUqmZsMT4T7g8Y5Azz+uwwEJW+4sgcJkIi9pYFyU4ZBSjBvkfuPZkGgfStir5BBDJQ=="],
|
"turbo-windows-64": ["turbo-windows-64@2.7.3", "", { "os": "win32", "cpu": "x64" }, "sha512-7bVvO987daXGSJVYBoG8R4Q+csT1pKIgLJYZevXRQ0Hqw0Vv4mKme/TOjYXs9Qb1xMKh51Tb3bXKDbd8/4G08g=="],
|
||||||
|
|
||||||
"turbo-windows-arm64": ["turbo-windows-arm64@2.5.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-eFC5XzLmgXJfnAK3UMTmVECCwuBcORrWdewoiXBnUm934DY6QN8YowC/srhNnROMpaKaqNeRpoB5FxCww3eteQ=="],
|
"turbo-windows-arm64": ["turbo-windows-arm64@2.7.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-nTodweTbPmkvwMu/a55XvjMsPtuyUSC+sV7f/SR57K36rB2I0YG21qNETN+00LOTUW9B3omd8XkiXJkt4kx/cw=="],
|
||||||
|
|
||||||
"tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="],
|
"tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="],
|
||||||
|
|
||||||
@@ -3100,7 +3101,7 @@
|
|||||||
|
|
||||||
"v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="],
|
"v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="],
|
||||||
|
|
||||||
"validate-npm-package-name": ["validate-npm-package-name@5.0.1", "", {}, "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ=="],
|
"validate-npm-package-name": ["validate-npm-package-name@5.0.0", "", { "dependencies": { "builtins": "^5.0.0" } }, "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ=="],
|
||||||
|
|
||||||
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
||||||
|
|
||||||
@@ -3150,7 +3151,7 @@
|
|||||||
|
|
||||||
"wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="],
|
"wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="],
|
||||||
|
|
||||||
"wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
|
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||||
|
|
||||||
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||||
|
|
||||||
@@ -3216,14 +3217,14 @@
|
|||||||
|
|
||||||
"@expo/cli/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
"@expo/cli/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
||||||
|
|
||||||
|
"@expo/cli/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"@expo/cli/ora": ["ora@3.4.0", "", { "dependencies": { "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-spinners": "^2.0.0", "log-symbols": "^2.2.0", "strip-ansi": "^5.2.0", "wcwidth": "^1.0.1" } }, "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg=="],
|
"@expo/cli/ora": ["ora@3.4.0", "", { "dependencies": { "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-spinners": "^2.0.0", "log-symbols": "^2.2.0", "strip-ansi": "^5.2.0", "wcwidth": "^1.0.1" } }, "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg=="],
|
||||||
|
|
||||||
"@expo/cli/resolve": ["resolve@1.22.8", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw=="],
|
"@expo/cli/resolve": ["resolve@1.22.8", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw=="],
|
||||||
|
|
||||||
"@expo/cli/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
"@expo/cli/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||||
|
|
||||||
"@expo/cli/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
|
||||||
|
|
||||||
"@expo/cli/ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
"@expo/cli/ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
||||||
|
|
||||||
"@expo/config/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
"@expo/config/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
||||||
@@ -3246,6 +3247,8 @@
|
|||||||
|
|
||||||
"@expo/fingerprint/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
"@expo/fingerprint/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
||||||
|
|
||||||
|
"@expo/fingerprint/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"@expo/fingerprint/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
"@expo/fingerprint/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||||
|
|
||||||
"@expo/image-utils/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
"@expo/image-utils/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||||
@@ -3266,6 +3269,8 @@
|
|||||||
|
|
||||||
"@expo/metro-config/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
"@expo/metro-config/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
|
"@expo/metro-config/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"@expo/metro-config/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="],
|
"@expo/metro-config/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="],
|
||||||
|
|
||||||
"@expo/package-manager/ora": ["ora@3.4.0", "", { "dependencies": { "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-spinners": "^2.0.0", "log-symbols": "^2.2.0", "strip-ansi": "^5.2.0", "wcwidth": "^1.0.1" } }, "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg=="],
|
"@expo/package-manager/ora": ["ora@3.4.0", "", { "dependencies": { "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-spinners": "^2.0.0", "log-symbols": "^2.2.0", "strip-ansi": "^5.2.0", "wcwidth": "^1.0.1" } }, "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg=="],
|
||||||
@@ -3336,6 +3341,8 @@
|
|||||||
|
|
||||||
"@sentry/node/@sentry/core": ["@sentry/core@10.22.0", "", {}, "sha512-V1oeHbrOKzxadsCmgtPku3v3Emo/Bpb3VSuKmlLrQefiHX98MWtjJ3XDGfduzD5/dCdh0r/OOLwjcmrO/PZ2aw=="],
|
"@sentry/node/@sentry/core": ["@sentry/core@10.22.0", "", {}, "sha512-V1oeHbrOKzxadsCmgtPku3v3Emo/Bpb3VSuKmlLrQefiHX98MWtjJ3XDGfduzD5/dCdh0r/OOLwjcmrO/PZ2aw=="],
|
||||||
|
|
||||||
|
"@sentry/node/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"@sentry/node-core/@sentry/core": ["@sentry/core@10.22.0", "", {}, "sha512-V1oeHbrOKzxadsCmgtPku3v3Emo/Bpb3VSuKmlLrQefiHX98MWtjJ3XDGfduzD5/dCdh0r/OOLwjcmrO/PZ2aw=="],
|
"@sentry/node-core/@sentry/core": ["@sentry/core@10.22.0", "", {}, "sha512-V1oeHbrOKzxadsCmgtPku3v3Emo/Bpb3VSuKmlLrQefiHX98MWtjJ3XDGfduzD5/dCdh0r/OOLwjcmrO/PZ2aw=="],
|
||||||
|
|
||||||
"@sentry/opentelemetry/@sentry/core": ["@sentry/core@10.22.0", "", {}, "sha512-V1oeHbrOKzxadsCmgtPku3v3Emo/Bpb3VSuKmlLrQefiHX98MWtjJ3XDGfduzD5/dCdh0r/OOLwjcmrO/PZ2aw=="],
|
"@sentry/opentelemetry/@sentry/core": ["@sentry/core@10.22.0", "", {}, "sha512-V1oeHbrOKzxadsCmgtPku3v3Emo/Bpb3VSuKmlLrQefiHX98MWtjJ3XDGfduzD5/dCdh0r/OOLwjcmrO/PZ2aw=="],
|
||||||
@@ -3354,7 +3361,7 @@
|
|||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"@turbo/workspaces/fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
|
"@turbo/workspaces/fast-glob": ["fast-glob@3.2.12", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w=="],
|
||||||
|
|
||||||
"@turbo/workspaces/ora": ["ora@4.1.1", "", { "dependencies": { "chalk": "^3.0.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.2.0", "is-interactive": "^1.0.0", "log-symbols": "^3.0.0", "mute-stream": "0.0.8", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A=="],
|
"@turbo/workspaces/ora": ["ora@4.1.1", "", { "dependencies": { "chalk": "^3.0.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.2.0", "is-interactive": "^1.0.0", "log-symbols": "^3.0.0", "mute-stream": "0.0.8", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A=="],
|
||||||
|
|
||||||
@@ -3368,6 +3375,8 @@
|
|||||||
|
|
||||||
"@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
|
"@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||||
|
|
||||||
"accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
"accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||||
@@ -3388,14 +3397,14 @@
|
|||||||
|
|
||||||
"better-opn/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],
|
"better-opn/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],
|
||||||
|
|
||||||
|
"builtins/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||||
|
|
||||||
"chalk-template/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
"chalk-template/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
||||||
|
|
||||||
"chromium-edge-launcher/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
|
"chromium-edge-launcher/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
|
||||||
|
|
||||||
"clear-module/parent-module": ["parent-module@2.0.0", "", { "dependencies": { "callsites": "^3.1.0" } }, "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg=="],
|
"clear-module/parent-module": ["parent-module@2.0.0", "", { "dependencies": { "callsites": "^3.1.0" } }, "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg=="],
|
||||||
|
|
||||||
"cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
|
||||||
|
|
||||||
"compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
"compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||||
|
|
||||||
"compression/negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="],
|
"compression/negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="],
|
||||||
@@ -3452,10 +3461,6 @@
|
|||||||
|
|
||||||
"expo-router/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="],
|
"expo-router/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="],
|
||||||
|
|
||||||
"external-editor/chardet": ["chardet@0.7.0", "", {}, "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="],
|
|
||||||
|
|
||||||
"external-editor/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="],
|
|
||||||
|
|
||||||
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||||
|
|
||||||
"fbjs/promise": ["promise@7.3.1", "", { "dependencies": { "asap": "~2.0.3" } }, "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="],
|
"fbjs/promise": ["promise@7.3.1", "", { "dependencies": { "asap": "~2.0.3" } }, "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="],
|
||||||
@@ -3524,6 +3529,8 @@
|
|||||||
|
|
||||||
"npm-package-arg/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
"npm-package-arg/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||||
|
|
||||||
|
"npm-package-arg/validate-npm-package-name": ["validate-npm-package-name@5.0.1", "", {}, "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ=="],
|
||||||
|
|
||||||
"ora/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
"ora/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
||||||
|
|
||||||
"ora/cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
|
"ora/cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
|
||||||
@@ -3654,14 +3661,20 @@
|
|||||||
|
|
||||||
"@expo/config-plugins/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
"@expo/config-plugins/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||||
|
|
||||||
|
"@expo/config-plugins/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"@expo/config-plugins/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
"@expo/config-plugins/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||||
|
|
||||||
"@expo/config/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
"@expo/config/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||||
|
|
||||||
|
"@expo/config/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"@expo/config/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
"@expo/config/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||||
|
|
||||||
"@expo/devcert/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
"@expo/devcert/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||||
|
|
||||||
|
"@expo/devcert/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"@expo/devcert/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
"@expo/devcert/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||||
|
|
||||||
"@expo/fingerprint/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
"@expo/fingerprint/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||||
@@ -3820,6 +3833,8 @@
|
|||||||
|
|
||||||
"expo-modules-autolinking/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
"expo-modules-autolinking/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||||
|
|
||||||
|
"expo-modules-autolinking/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"expo-modules-autolinking/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
"expo-modules-autolinking/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||||
|
|
||||||
"finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
"finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||||
@@ -3874,6 +3889,8 @@
|
|||||||
|
|
||||||
"sucrase/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
"sucrase/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||||
|
|
||||||
|
"sucrase/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"sucrase/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
"sucrase/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||||
|
|
||||||
"terser-webpack-plugin/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
"terser-webpack-plugin/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
networks:
|
networks:
|
||||||
nginx-bridge: # You need to change this line to your defined network is as well
|
nginx-bridge: # Change to network you plan to use
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|||||||
12
package.json
12
package.json
@@ -26,10 +26,10 @@
|
|||||||
"convex": "^1.28.0"
|
"convex": "^1.28.0"
|
||||||
},
|
},
|
||||||
"react19": {
|
"react19": {
|
||||||
"@types/react": "^19.1.12",
|
"@types/react": "~19.1.0",
|
||||||
"@types/react-dom": "^19.1.9",
|
"@types/react-dom": "~19.1.0",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.4",
|
||||||
"react-dom": "19.1.1"
|
"react-dom": "19.1.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -55,10 +55,10 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@gib/prettier-config": "workspace:",
|
"@gib/prettier-config": "workspace:",
|
||||||
"@turbo/gen": "^2.5.8",
|
"@turbo/gen": "^2.7.3",
|
||||||
"dotenv-cli": "^10.0.0",
|
"dotenv-cli": "^10.0.0",
|
||||||
"prettier": "catalog:",
|
"prettier": "catalog:",
|
||||||
"turbo": "^2.5.8",
|
"turbo": "^2.7.3",
|
||||||
"typescript": "catalog:"
|
"typescript": "catalog:"
|
||||||
},
|
},
|
||||||
"prettier": "@gib/prettier-config"
|
"prettier": "@gib/prettier-config"
|
||||||
|
|||||||
@@ -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/monorepo/convex-monorepo/packages/backend/.gitignore",{"size":16,"mtime":1753933693000,"hash":"46"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/_generated/server.d.ts",{"size":5540,"mtime":1761665487097,"hash":"47","data":"48"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/auth.config.js",{"size":128,"mtime":1753933693000,"hash":"49","data":"50"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/package.json",{"size":1135,"mtime":1761665487290,"hash":"51","data":"52"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/openai.ts",{"size":2036,"mtime":1761665487195,"hash":"53","data":"54"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/README.md",{"size":2525,"mtime":1761665487249,"hash":"55","data":"56"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/_generated/api.js",{"size":414,"mtime":1753933693000,"hash":"57","data":"58"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/tsconfig.json",{"size":732,"mtime":1753933693000,"hash":"59","data":"60"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/_generated/server.js",{"size":3453,"mtime":1761665487114,"hash":"61","data":"62"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/notes.ts",{"size":1632,"mtime":1761665487164,"hash":"63","data":"64"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/env.ts",{"size":219,"mtime":1761665487285,"hash":"65","data":"66"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/_generated/dataModel.d.ts",{"size":1726,"mtime":1761665487061,"hash":"67","data":"68"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/schema.ts",{"size":267,"mtime":1753933693000,"hash":"69","data":"70"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/utils.ts",{"size":635,"mtime":1753933693000,"hash":"71","data":"72"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/_generated/api.d.ts",{"size":845,"mtime":1761665486984,"hash":"73","data":"74"},"175b1a771387d8b7e26145c3d04e0475","da19b68e90524b894bbf1985bcec4d72",{"hashOfOptions":"75"},"a87d36cd21882ed8968ea6138f23acd9",{"hashOfOptions":"76"},"80903421dc266560a15314b96f727e40",{"hashOfOptions":"77"},"2cf34d0dd087d9749396d5f686419f4f",{"hashOfOptions":"78"},"7beaec3443b6db9c1a6b8c1668c98992",{"hashOfOptions":"79"},"c5dea56b7ddd47516cbd4038de020e53",{"hashOfOptions":"80"},"cfa98923457caed911ec68b626ef4234",{"hashOfOptions":"81"},"4a51b371d17b0a9dcc8d3a3d16790eec",{"hashOfOptions":"82"},"99403ed881c0f3caf6c13ad183e06049",{"hashOfOptions":"83"},"d78af64438f2e86a438ce045e0910a1d",{"hashOfOptions":"84"},"1a6eccbe2f9771c5b418adc40d8532c4",{"hashOfOptions":"85"},"9b1b5b82ff06ae9856df10ae91c15946",{"hashOfOptions":"86"},"0a1b4f144561ba1da064a40a2e089f10",{"hashOfOptions":"87"},"26351eae8dc2fa74ce0e3e6f6f0d4a49",{"hashOfOptions":"88"},"2545271053","1384390439","3159514942","514606721","3861339677","511151554","2611213275","1927515469","2174687556","3247610094","3411100989","2670794290","530123092","4075214594"]
|
[["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"]
|
||||||
@@ -7,9 +7,9 @@ A query function that takes two arguments looks like:
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
// functions.js
|
// functions.js
|
||||||
import { v } from "convex/values";
|
import { v } from 'convex/values';
|
||||||
|
|
||||||
import { query } from "./_generated/server";
|
import { query } from './_generated/server';
|
||||||
|
|
||||||
export const myQueryFunction = query({
|
export const myQueryFunction = query({
|
||||||
// Validators for arguments.
|
// Validators for arguments.
|
||||||
@@ -22,7 +22,7 @@ export const myQueryFunction = query({
|
|||||||
handler: async (ctx, args) => {
|
handler: async (ctx, args) => {
|
||||||
// Read the database as many times as you need here.
|
// Read the database as many times as you need here.
|
||||||
// See https://docs.convex.dev/database/reading-data.
|
// See https://docs.convex.dev/database/reading-data.
|
||||||
const documents = await ctx.db.query("tablename").collect();
|
const documents = await ctx.db.query('tablename').collect();
|
||||||
|
|
||||||
// Arguments passed from the client are properties of the args object.
|
// Arguments passed from the client are properties of the args object.
|
||||||
console.log(args.first, args.second);
|
console.log(args.first, args.second);
|
||||||
@@ -39,7 +39,7 @@ Using this query function in a React component looks like:
|
|||||||
```ts
|
```ts
|
||||||
const data = useQuery(api.functions.myQueryFunction, {
|
const data = useQuery(api.functions.myQueryFunction, {
|
||||||
first: 10,
|
first: 10,
|
||||||
second: "hello",
|
second: 'hello',
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -47,9 +47,9 @@ A mutation function looks like:
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
// functions.js
|
// functions.js
|
||||||
import { v } from "convex/values";
|
import { v } from 'convex/values';
|
||||||
|
|
||||||
import { mutation } from "./_generated/server";
|
import { mutation } from './_generated/server';
|
||||||
|
|
||||||
export const myMutationFunction = mutation({
|
export const myMutationFunction = mutation({
|
||||||
// Validators for arguments.
|
// Validators for arguments.
|
||||||
@@ -64,7 +64,7 @@ export const myMutationFunction = mutation({
|
|||||||
// Mutations can also read from the database like queries.
|
// Mutations can also read from the database like queries.
|
||||||
// See https://docs.convex.dev/database/writing-data.
|
// See https://docs.convex.dev/database/writing-data.
|
||||||
const message = { body: args.first, author: args.second };
|
const message = { body: args.first, author: args.second };
|
||||||
const id = await ctx.db.insert("messages", message);
|
const id = await ctx.db.insert('messages', message);
|
||||||
|
|
||||||
// Optionally, return a value from your mutation.
|
// Optionally, return a value from your mutation.
|
||||||
return await ctx.db.get(id);
|
return await ctx.db.get(id);
|
||||||
@@ -78,10 +78,10 @@ Using this mutation function in a React component looks like:
|
|||||||
const mutation = useMutation(api.functions.myMutationFunction);
|
const mutation = useMutation(api.functions.myMutationFunction);
|
||||||
function handleButtonPress() {
|
function handleButtonPress() {
|
||||||
// fire and forget, the most common way to use mutations
|
// fire and forget, the most common way to use mutations
|
||||||
mutation({ first: "Hello!", second: "me" });
|
mutation({ first: 'Hello!', second: 'me' });
|
||||||
// OR
|
// OR
|
||||||
// use the result once the mutation has completed
|
// use the result once the mutation has completed
|
||||||
mutation({ first: "Hello!", second: "me" }).then((result) =>
|
mutation({ first: 'Hello!', second: 'me' }).then((result) =>
|
||||||
console.log(result),
|
console.log(result),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
12
packages/backend/convex/_generated/api.d.ts
vendored
12
packages/backend/convex/_generated/api.d.ts
vendored
@@ -12,11 +12,11 @@ import type {
|
|||||||
ApiFromModules,
|
ApiFromModules,
|
||||||
FilterApi,
|
FilterApi,
|
||||||
FunctionReference,
|
FunctionReference,
|
||||||
} from "convex/server";
|
} from 'convex/server';
|
||||||
|
|
||||||
import type * as notes from "../notes.js";
|
import type * as notes from '../notes.js';
|
||||||
import type * as openai from "../openai.js";
|
import type * as openai from '../openai.js';
|
||||||
import type * as utils from "../utils.js";
|
import type * as utils from '../utils.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility for referencing Convex functions in your app's API.
|
* A utility for referencing Convex functions in your app's API.
|
||||||
@@ -33,9 +33,9 @@ declare const fullApi: ApiFromModules<{
|
|||||||
}>;
|
}>;
|
||||||
export declare const api: FilterApi<
|
export declare const api: FilterApi<
|
||||||
typeof fullApi,
|
typeof fullApi,
|
||||||
FunctionReference<any, "public">
|
FunctionReference<any, 'public'>
|
||||||
>;
|
>;
|
||||||
export declare const internal: FilterApi<
|
export declare const internal: FilterApi<
|
||||||
typeof fullApi,
|
typeof fullApi,
|
||||||
FunctionReference<any, "internal">
|
FunctionReference<any, 'internal'>
|
||||||
>;
|
>;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
* @module
|
* @module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { anyApi } from "convex/server";
|
import { anyApi } from 'convex/server';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility for referencing Convex functions in your app's API.
|
* A utility for referencing Convex functions in your app's API.
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import type {
|
|||||||
DocumentByName,
|
DocumentByName,
|
||||||
SystemTableNames,
|
SystemTableNames,
|
||||||
TableNamesInDataModel,
|
TableNamesInDataModel,
|
||||||
} from "convex/server";
|
} from 'convex/server';
|
||||||
import type { GenericId } from "convex/values";
|
import type { GenericId } from 'convex/values';
|
||||||
|
|
||||||
import schema from "../schema.js";
|
import schema from '../schema.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The names of all of your Convex tables.
|
* The names of all of your Convex tables.
|
||||||
|
|||||||
16
packages/backend/convex/_generated/server.d.ts
vendored
16
packages/backend/convex/_generated/server.d.ts
vendored
@@ -18,9 +18,9 @@ import {
|
|||||||
HttpActionBuilder,
|
HttpActionBuilder,
|
||||||
MutationBuilder,
|
MutationBuilder,
|
||||||
QueryBuilder,
|
QueryBuilder,
|
||||||
} from "convex/server";
|
} from 'convex/server';
|
||||||
|
|
||||||
import type { DataModel } from "./dataModel.js";
|
import type { DataModel } from './dataModel.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a query in this Convex app's public API.
|
* Define a query in this Convex app's public API.
|
||||||
@@ -30,7 +30,7 @@ import type { DataModel } from "./dataModel.js";
|
|||||||
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
||||||
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
||||||
*/
|
*/
|
||||||
export declare const query: QueryBuilder<DataModel, "public">;
|
export declare const query: QueryBuilder<DataModel, 'public'>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a query that is only accessible from other Convex functions (but not from the client).
|
* Define a query that is only accessible from other Convex functions (but not from the client).
|
||||||
@@ -40,7 +40,7 @@ export declare const query: QueryBuilder<DataModel, "public">;
|
|||||||
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
||||||
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
||||||
*/
|
*/
|
||||||
export declare const internalQuery: QueryBuilder<DataModel, "internal">;
|
export declare const internalQuery: QueryBuilder<DataModel, 'internal'>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a mutation in this Convex app's public API.
|
* Define a mutation in this Convex app's public API.
|
||||||
@@ -50,7 +50,7 @@ export declare const internalQuery: QueryBuilder<DataModel, "internal">;
|
|||||||
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
||||||
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
||||||
*/
|
*/
|
||||||
export declare const mutation: MutationBuilder<DataModel, "public">;
|
export declare const mutation: MutationBuilder<DataModel, 'public'>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a mutation that is only accessible from other Convex functions (but not from the client).
|
* Define a mutation that is only accessible from other Convex functions (but not from the client).
|
||||||
@@ -60,7 +60,7 @@ export declare const mutation: MutationBuilder<DataModel, "public">;
|
|||||||
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
||||||
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
||||||
*/
|
*/
|
||||||
export declare const internalMutation: MutationBuilder<DataModel, "internal">;
|
export declare const internalMutation: MutationBuilder<DataModel, 'internal'>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define an action in this Convex app's public API.
|
* Define an action in this Convex app's public API.
|
||||||
@@ -73,7 +73,7 @@ export declare const internalMutation: MutationBuilder<DataModel, "internal">;
|
|||||||
* @param func - The action. It receives an {@link ActionCtx} as its first argument.
|
* @param func - The action. It receives an {@link ActionCtx} as its first argument.
|
||||||
* @returns The wrapped action. Include this as an `export` to name it and make it accessible.
|
* @returns The wrapped action. Include this as an `export` to name it and make it accessible.
|
||||||
*/
|
*/
|
||||||
export declare const action: ActionBuilder<DataModel, "public">;
|
export declare const action: ActionBuilder<DataModel, 'public'>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define an action that is only accessible from other Convex functions (but not from the client).
|
* Define an action that is only accessible from other Convex functions (but not from the client).
|
||||||
@@ -81,7 +81,7 @@ export declare const action: ActionBuilder<DataModel, "public">;
|
|||||||
* @param func - The function. It receives an {@link ActionCtx} as its first argument.
|
* @param func - The function. It receives an {@link ActionCtx} as its first argument.
|
||||||
* @returns The wrapped function. Include this as an `export` to name it and make it accessible.
|
* @returns The wrapped function. Include this as an `export` to name it and make it accessible.
|
||||||
*/
|
*/
|
||||||
export declare const internalAction: ActionBuilder<DataModel, "internal">;
|
export declare const internalAction: ActionBuilder<DataModel, 'internal'>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define an HTTP action.
|
* Define an HTTP action.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
internalQueryGeneric,
|
internalQueryGeneric,
|
||||||
mutationGeneric,
|
mutationGeneric,
|
||||||
queryGeneric,
|
queryGeneric,
|
||||||
} from "convex/server";
|
} from 'convex/server';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a query in this Convex app's public API.
|
* Define a query in this Convex app's public API.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ export default {
|
|||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
domain: process.env.CLERK_ISSUER_URL,
|
domain: process.env.CLERK_ISSUER_URL,
|
||||||
applicationID: "convex",
|
applicationID: 'convex',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Auth } from "convex/server";
|
import { Auth } from 'convex/server';
|
||||||
import { v } from "convex/values";
|
import { v } from 'convex/values';
|
||||||
|
|
||||||
import { internal } from "../convex/_generated/api";
|
import { internal } from '../convex/_generated/api';
|
||||||
import { mutation, query } from "./_generated/server";
|
import { mutation, query } from './_generated/server';
|
||||||
|
|
||||||
export const getUserId = async (ctx: { auth: Auth }) => {
|
export const getUserId = async (ctx: { auth: Auth }) => {
|
||||||
return (await ctx.auth.getUserIdentity())?.subject;
|
return (await ctx.auth.getUserIdentity())?.subject;
|
||||||
@@ -16,8 +16,8 @@ export const getNotes = query({
|
|||||||
if (!userId) return null;
|
if (!userId) return null;
|
||||||
|
|
||||||
const notes = await ctx.db
|
const notes = await ctx.db
|
||||||
.query("notes")
|
.query('notes')
|
||||||
.filter((q) => q.eq(q.field("userId"), userId))
|
.filter((q) => q.eq(q.field('userId'), userId))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
return notes;
|
return notes;
|
||||||
@@ -27,7 +27,7 @@ export const getNotes = query({
|
|||||||
// Get note for a specific note
|
// Get note for a specific note
|
||||||
export const getNote = query({
|
export const getNote = query({
|
||||||
args: {
|
args: {
|
||||||
id: v.optional(v.id("notes")),
|
id: v.optional(v.id('notes')),
|
||||||
},
|
},
|
||||||
handler: async (ctx, args) => {
|
handler: async (ctx, args) => {
|
||||||
const { id } = args;
|
const { id } = args;
|
||||||
@@ -46,8 +46,8 @@ export const createNote = mutation({
|
|||||||
},
|
},
|
||||||
handler: async (ctx, { title, content, isSummary }) => {
|
handler: async (ctx, { title, content, isSummary }) => {
|
||||||
const userId = await getUserId(ctx);
|
const userId = await getUserId(ctx);
|
||||||
if (!userId) throw new Error("User not found");
|
if (!userId) throw new Error('User not found');
|
||||||
const noteId = await ctx.db.insert("notes", { userId, title, content });
|
const noteId = await ctx.db.insert('notes', { userId, title, content });
|
||||||
|
|
||||||
if (isSummary) {
|
if (isSummary) {
|
||||||
await ctx.scheduler.runAfter(0, internal.openai.summary, {
|
await ctx.scheduler.runAfter(0, internal.openai.summary, {
|
||||||
@@ -63,7 +63,7 @@ export const createNote = mutation({
|
|||||||
|
|
||||||
export const deleteNote = mutation({
|
export const deleteNote = mutation({
|
||||||
args: {
|
args: {
|
||||||
noteId: v.id("notes"),
|
noteId: v.id('notes'),
|
||||||
},
|
},
|
||||||
handler: async (ctx, args) => {
|
handler: async (ctx, args) => {
|
||||||
await ctx.db.delete(args.noteId);
|
await ctx.db.delete(args.noteId);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { v } from "convex/values";
|
import { v } from 'convex/values';
|
||||||
import OpenAI from "openai";
|
import OpenAI from 'openai';
|
||||||
|
|
||||||
import { internal } from "./_generated/api";
|
import { internal } from './_generated/api';
|
||||||
import { internalAction, internalMutation, query } from "./_generated/server";
|
import { internalAction, internalMutation, query } from './_generated/server';
|
||||||
import { missingEnvVariableUrl } from "./utils";
|
import { missingEnvVariableUrl } from './utils';
|
||||||
|
|
||||||
export const openaiKeySet = query({
|
export const openaiKeySet = query({
|
||||||
args: {},
|
args: {},
|
||||||
@@ -14,7 +14,7 @@ export const openaiKeySet = query({
|
|||||||
|
|
||||||
export const summary = internalAction({
|
export const summary = internalAction({
|
||||||
args: {
|
args: {
|
||||||
id: v.id("notes"),
|
id: v.id('notes'),
|
||||||
title: v.string(),
|
title: v.string(),
|
||||||
content: v.string(),
|
content: v.string(),
|
||||||
},
|
},
|
||||||
@@ -24,8 +24,8 @@ export const summary = internalAction({
|
|||||||
const apiKey = process.env.OPENAI_API_KEY;
|
const apiKey = process.env.OPENAI_API_KEY;
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
const error = missingEnvVariableUrl(
|
const error = missingEnvVariableUrl(
|
||||||
"OPENAI_API_KEY",
|
'OPENAI_API_KEY',
|
||||||
"https://platform.openai.com/account/api-keys",
|
'https://platform.openai.com/account/api-keys',
|
||||||
);
|
);
|
||||||
console.error(error);
|
console.error(error);
|
||||||
await ctx.runMutation(internal.openai.saveSummary, {
|
await ctx.runMutation(internal.openai.saveSummary, {
|
||||||
@@ -38,14 +38,14 @@ export const summary = internalAction({
|
|||||||
const output = await openai.chat.completions.create({
|
const output = await openai.chat.completions.create({
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
role: "system",
|
role: 'system',
|
||||||
content:
|
content:
|
||||||
"You are a helpful assistant designed to output JSON in this format: {summary: string}",
|
'You are a helpful assistant designed to output JSON in this format: {summary: string}',
|
||||||
},
|
},
|
||||||
{ role: "user", content: prompt },
|
{ role: 'user', content: prompt },
|
||||||
],
|
],
|
||||||
model: "gpt-4-1106-preview",
|
model: 'gpt-4-1106-preview',
|
||||||
response_format: { type: "json_object" },
|
response_format: { type: 'json_object' },
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pull the message content out of the response
|
// Pull the message content out of the response
|
||||||
@@ -65,7 +65,7 @@ export const summary = internalAction({
|
|||||||
|
|
||||||
export const saveSummary = internalMutation({
|
export const saveSummary = internalMutation({
|
||||||
args: {
|
args: {
|
||||||
id: v.id("notes"),
|
id: v.id('notes'),
|
||||||
summary: v.string(),
|
summary: v.string(),
|
||||||
},
|
},
|
||||||
handler: async (ctx, { id, summary }) => {
|
handler: async (ctx, { id, summary }) => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { defineSchema, defineTable } from "convex/server";
|
import { defineSchema, defineTable } from 'convex/server';
|
||||||
import { v } from "convex/values";
|
import { v } from 'convex/values';
|
||||||
|
|
||||||
export default defineSchema({
|
export default defineSchema({
|
||||||
notes: defineTable({
|
notes: defineTable({
|
||||||
|
|||||||
@@ -11,6 +11,6 @@ export function missingEnvVariableUrl(envVarName: string, whereToGet: string) {
|
|||||||
export function deploymentName() {
|
export function deploymentName() {
|
||||||
const url = process.env.CONVEX_CLOUD_URL;
|
const url = process.env.CONVEX_CLOUD_URL;
|
||||||
if (!url) return undefined;
|
if (!url) return undefined;
|
||||||
const regex = new RegExp("https://(.+).convex.cloud");
|
const regex = new RegExp('https://(.+).convex.cloud');
|
||||||
return regex.exec(url)?.[1];
|
return regex.exec(url)?.[1];
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -9,6 +9,7 @@
|
|||||||
"baseColor": "zinc",
|
"baseColor": "zinc",
|
||||||
"cssVariables": true
|
"cssVariables": true
|
||||||
},
|
},
|
||||||
|
"iconLibrary": "lucide",
|
||||||
"aliases": {
|
"aliases": {
|
||||||
"utils": "@gib/ui",
|
"utils": "@gib/ui",
|
||||||
"components": "src/",
|
"components": "src/",
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { defineConfig } from "eslint/config";
|
import { defineConfig } from 'eslint/config';
|
||||||
|
|
||||||
import { baseConfig } from "@gib/eslint-config/base";
|
import { baseConfig } from '@gib/eslint-config/base';
|
||||||
import { reactConfig } from "@gib/eslint-config/react";
|
import { reactConfig } from '@gib/eslint-config/react';
|
||||||
|
|
||||||
export default defineConfig(
|
export default defineConfig(
|
||||||
{
|
{
|
||||||
ignores: ["dist/**"],
|
ignores: ['dist/**'],
|
||||||
},
|
},
|
||||||
baseConfig,
|
baseConfig,
|
||||||
reactConfig,
|
reactConfig,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
".": "./src/index.ts",
|
".": "./src/index.ts",
|
||||||
"./avatar": "./src/avatar.tsx",
|
"./avatar": "./src/avatar.tsx",
|
||||||
"./based-avatar": "./src/based-avatar.tsx",
|
"./based-avatar": "./src/based-avatar.tsx",
|
||||||
"./based-progress": "./src/based-progress.ts",
|
"./based-progress": "./src/based-progress.tsx",
|
||||||
"./button": "./src/button.tsx",
|
"./button": "./src/button.tsx",
|
||||||
"./card": "./src/card.tsx",
|
"./card": "./src/card.tsx",
|
||||||
"./checkbox": "./src/checkbox.tsx",
|
"./checkbox": "./src/checkbox.tsx",
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
"./scroll-area": "./src/scroll-area.tsx",
|
"./scroll-area": "./src/scroll-area.tsx",
|
||||||
"./separator": "./src/separator.tsx",
|
"./separator": "./src/separator.tsx",
|
||||||
"./sonner": "./src/sonner.tsx",
|
"./sonner": "./src/sonner.tsx",
|
||||||
"./status-message": "./src/status-message.ts",
|
"./status-message": "./src/status-message.tsx",
|
||||||
"./submit-button": "./src/submit-button.tsx",
|
"./submit-button": "./src/submit-button.tsx",
|
||||||
"./switch": "./src/switch.tsx",
|
"./switch": "./src/switch.tsx",
|
||||||
"./table": "./src/table.tsx",
|
"./table": "./src/table.tsx",
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
||||||
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
||||||
|
import { cn } from '@gib/ui';
|
||||||
|
|
||||||
function Avatar({
|
function Avatar({
|
||||||
className,
|
className,
|
||||||
@@ -12,7 +13,7 @@ function Avatar({
|
|||||||
<AvatarPrimitive.Root
|
<AvatarPrimitive.Root
|
||||||
data-slot="avatar"
|
data-slot="avatar"
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
|
'relative flex size-8 shrink-0 overflow-hidden rounded-full',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -27,7 +28,7 @@ function AvatarImage({
|
|||||||
return (
|
return (
|
||||||
<AvatarPrimitive.Image
|
<AvatarPrimitive.Image
|
||||||
data-slot="avatar-image"
|
data-slot="avatar-image"
|
||||||
className={cn("aspect-square size-full", className)}
|
className={cn('aspect-square size-full', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -41,7 +42,7 @@ function AvatarFallback({
|
|||||||
<AvatarPrimitive.Fallback
|
<AvatarPrimitive.Fallback
|
||||||
data-slot="avatar-fallback"
|
data-slot="avatar-fallback"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-muted flex size-full items-center justify-center rounded-full",
|
'bg-muted flex size-full items-center justify-center rounded-full',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import { type ComponentProps } from "react";
|
import { type ComponentProps } from 'react';
|
||||||
import { AvatarImage } from "@/components/ui/avatar";
|
import { AvatarImage } from '@/components/ui/avatar';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
||||||
import { User } from "lucide-react";
|
import { User } from 'lucide-react';
|
||||||
|
|
||||||
type BasedAvatarProps = ComponentProps<typeof AvatarPrimitive.Root> & {
|
type BasedAvatarProps = ComponentProps<typeof AvatarPrimitive.Root> & {
|
||||||
src?: string | null;
|
src?: string | null;
|
||||||
fullName?: string | null;
|
fullName?: string | null;
|
||||||
imageProps?: Omit<ComponentProps<typeof AvatarImage>, "data-slot">;
|
imageProps?: Omit<ComponentProps<typeof AvatarImage>, 'data-slot'>;
|
||||||
fallbackProps?: ComponentProps<typeof AvatarPrimitive.Fallback>;
|
fallbackProps?: ComponentProps<typeof AvatarPrimitive.Fallback>;
|
||||||
userIconProps?: ComponentProps<typeof User>;
|
userIconProps?: ComponentProps<typeof User>;
|
||||||
};
|
};
|
||||||
@@ -29,7 +29,7 @@ const BasedAvatar = ({
|
|||||||
<AvatarPrimitive.Root
|
<AvatarPrimitive.Root
|
||||||
data-slot="avatar"
|
data-slot="avatar"
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex size-8 shrink-0 cursor-pointer overflow-hidden rounded-full",
|
'relative flex size-8 shrink-0 cursor-pointer overflow-hidden rounded-full',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -45,20 +45,20 @@ const BasedAvatar = ({
|
|||||||
{...fallbackProps}
|
{...fallbackProps}
|
||||||
data-slot="avatar-fallback"
|
data-slot="avatar-fallback"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-muted flex size-full items-center justify-center rounded-full",
|
'bg-muted flex size-full items-center justify-center rounded-full',
|
||||||
fallbackProps?.className,
|
fallbackProps?.className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{fullName ? (
|
{fullName ? (
|
||||||
fullName
|
fullName
|
||||||
.split(" ")
|
.split(' ')
|
||||||
.map((n) => n[0])
|
.map((n) => n[0])
|
||||||
.join("")
|
.join('')
|
||||||
.toUpperCase()
|
.toUpperCase()
|
||||||
) : (
|
) : (
|
||||||
<User
|
<User
|
||||||
{...userIconProps}
|
{...userIconProps}
|
||||||
className={cn("", userIconProps?.className)}
|
className={cn('', userIconProps?.className)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</AvatarPrimitive.Fallback>
|
</AvatarPrimitive.Fallback>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
import * as ProgressPrimitive from '@radix-ui/react-progress';
|
||||||
|
|
||||||
type BasedProgressProps = React.ComponentProps<
|
type BasedProgressProps = React.ComponentProps<
|
||||||
typeof ProgressPrimitive.Root
|
typeof ProgressPrimitive.Root
|
||||||
@@ -36,7 +36,7 @@ const BasedProgress = ({
|
|||||||
<ProgressPrimitive.Root
|
<ProgressPrimitive.Root
|
||||||
data-slot="progress"
|
data-slot="progress"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-primary/20 relative h-2 w-full overflow-hidden rounded-full",
|
'bg-primary/20 relative h-2 w-full overflow-hidden rounded-full',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { VariantProps } from "class-variance-authority";
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import { Slot } from "@radix-ui/react-slot";
|
import { Slot } from '@radix-ui/react-slot';
|
||||||
import { cva } from "class-variance-authority";
|
import { cva } from 'class-variance-authority';
|
||||||
|
|
||||||
const buttonVariants = cva(
|
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",
|
"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",
|
||||||
@@ -10,27 +10,27 @@ const buttonVariants = cva(
|
|||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default:
|
default:
|
||||||
"bg-primary text-primary-foreground hover:bg-primary/90 shadow-xs",
|
'bg-primary text-primary-foreground hover:bg-primary/90 shadow-xs',
|
||||||
destructive:
|
destructive:
|
||||||
"bg-destructive hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white shadow-xs",
|
'bg-destructive hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white shadow-xs',
|
||||||
outline:
|
outline:
|
||||||
"bg-background hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border shadow-xs",
|
'bg-background hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border shadow-xs',
|
||||||
secondary:
|
secondary:
|
||||||
"bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-xs",
|
'bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-xs',
|
||||||
ghost:
|
ghost:
|
||||||
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
|
||||||
link: "text-primary underline-offset-4 hover:underline",
|
link: 'text-primary underline-offset-4 hover:underline',
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
default: 'h-9 px-4 py-2 has-[>svg]:px-3',
|
||||||
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5',
|
||||||
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
|
||||||
icon: "size-9",
|
icon: 'size-9',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default",
|
variant: 'default',
|
||||||
size: "default",
|
size: 'default',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -41,11 +41,11 @@ function Button({
|
|||||||
size,
|
size,
|
||||||
asChild = false,
|
asChild = false,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"button"> &
|
}: React.ComponentProps<'button'> &
|
||||||
VariantProps<typeof buttonVariants> & {
|
VariantProps<typeof buttonVariants> & {
|
||||||
asChild?: boolean;
|
asChild?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const Comp = asChild ? Slot : "button";
|
const Comp = asChild ? Slot : 'button';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Comp
|
<Comp
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
function Card({ className, ...props }: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="card"
|
data-slot="card"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
'bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -14,12 +14,12 @@ function Card({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="card-header"
|
data-slot="card-header"
|
||||||
className={cn(
|
className={cn(
|
||||||
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
'@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -27,32 +27,32 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="card-title"
|
data-slot="card-title"
|
||||||
className={cn("leading-none font-semibold", className)}
|
className={cn('leading-none font-semibold', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="card-description"
|
data-slot="card-description"
|
||||||
className={cn("text-muted-foreground text-sm", className)}
|
className={cn('text-muted-foreground text-sm', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="card-action"
|
data-slot="card-action"
|
||||||
className={cn(
|
className={cn(
|
||||||
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
'col-start-2 row-span-2 row-start-1 self-start justify-self-end',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -60,21 +60,21 @@ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="card-content"
|
data-slot="card-content"
|
||||||
className={cn("px-6", className)}
|
className={cn('px-6', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="card-footer"
|
data-slot="card-footer"
|
||||||
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
|
className={cn('flex items-center px-6 [.border-t]:pt-6', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
||||||
import { CheckIcon } from "lucide-react";
|
import { CheckIcon } from 'lucide-react';
|
||||||
|
|
||||||
function Checkbox({
|
function Checkbox({
|
||||||
className,
|
className,
|
||||||
@@ -13,7 +13,7 @@ function Checkbox({
|
|||||||
<CheckboxPrimitive.Root
|
<CheckboxPrimitive.Root
|
||||||
data-slot="checkbox"
|
data-slot="checkbox"
|
||||||
className={cn(
|
className={cn(
|
||||||
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
'peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import { Drawer as DrawerPrimitive } from "vaul";
|
import { Drawer as DrawerPrimitive } from 'vaul';
|
||||||
|
|
||||||
function Drawer({
|
function Drawer({
|
||||||
...props
|
...props
|
||||||
@@ -36,7 +36,7 @@ function DrawerOverlay({
|
|||||||
<DrawerPrimitive.Overlay
|
<DrawerPrimitive.Overlay
|
||||||
data-slot="drawer-overlay"
|
data-slot="drawer-overlay"
|
||||||
className={cn(
|
className={cn(
|
||||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -55,11 +55,11 @@ function DrawerContent({
|
|||||||
<DrawerPrimitive.Content
|
<DrawerPrimitive.Content
|
||||||
data-slot="drawer-content"
|
data-slot="drawer-content"
|
||||||
className={cn(
|
className={cn(
|
||||||
"group/drawer-content bg-background fixed z-50 flex h-auto flex-col",
|
'group/drawer-content bg-background fixed z-50 flex h-auto flex-col',
|
||||||
"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b",
|
'data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b',
|
||||||
"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t",
|
'data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t',
|
||||||
"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm",
|
'data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm',
|
||||||
"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm",
|
'data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -71,12 +71,12 @@ function DrawerContent({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
|
function DrawerHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="drawer-header"
|
data-slot="drawer-header"
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left",
|
'flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -84,11 +84,11 @@ function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
|
function DrawerFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="drawer-footer"
|
data-slot="drawer-footer"
|
||||||
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
|
className={cn('mt-auto flex flex-col gap-2 p-4', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -101,7 +101,7 @@ function DrawerTitle({
|
|||||||
return (
|
return (
|
||||||
<DrawerPrimitive.Title
|
<DrawerPrimitive.Title
|
||||||
data-slot="drawer-title"
|
data-slot="drawer-title"
|
||||||
className={cn("text-foreground font-semibold", className)}
|
className={cn('text-foreground font-semibold', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -114,7 +114,7 @@ function DrawerDescription({
|
|||||||
return (
|
return (
|
||||||
<DrawerPrimitive.Description
|
<DrawerPrimitive.Description
|
||||||
data-slot="drawer-description"
|
data-slot="drawer-description"
|
||||||
className={cn("text-muted-foreground text-sm", className)}
|
className={cn('text-muted-foreground text-sm', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
||||||
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react';
|
||||||
|
|
||||||
function DropdownMenu({
|
function DropdownMenu({
|
||||||
...props
|
...props
|
||||||
@@ -41,7 +41,7 @@ function DropdownMenuContent({
|
|||||||
data-slot="dropdown-menu-content"
|
data-slot="dropdown-menu-content"
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
|
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -61,11 +61,11 @@ function DropdownMenuGroup({
|
|||||||
function DropdownMenuItem({
|
function DropdownMenuItem({
|
||||||
className,
|
className,
|
||||||
inset,
|
inset,
|
||||||
variant = "default",
|
variant = 'default',
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
|
||||||
inset?: boolean;
|
inset?: boolean;
|
||||||
variant?: "default" | "destructive";
|
variant?: 'default' | 'destructive';
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.Item
|
<DropdownMenuPrimitive.Item
|
||||||
@@ -154,7 +154,7 @@ function DropdownMenuLabel({
|
|||||||
data-slot="dropdown-menu-label"
|
data-slot="dropdown-menu-label"
|
||||||
data-inset={inset}
|
data-inset={inset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
'px-2 py-1.5 text-sm font-medium data-[inset]:pl-8',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -169,7 +169,7 @@ function DropdownMenuSeparator({
|
|||||||
return (
|
return (
|
||||||
<DropdownMenuPrimitive.Separator
|
<DropdownMenuPrimitive.Separator
|
||||||
data-slot="dropdown-menu-separator"
|
data-slot="dropdown-menu-separator"
|
||||||
className={cn("bg-border -mx-1 my-1 h-px", className)}
|
className={cn('bg-border -mx-1 my-1 h-px', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -178,12 +178,12 @@ function DropdownMenuSeparator({
|
|||||||
function DropdownMenuShortcut({
|
function DropdownMenuShortcut({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"span">) {
|
}: React.ComponentProps<'span'>) {
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
data-slot="dropdown-menu-shortcut"
|
data-slot="dropdown-menu-shortcut"
|
||||||
className={cn(
|
className={cn(
|
||||||
"text-muted-foreground ml-auto text-xs tracking-widest",
|
'text-muted-foreground ml-auto text-xs tracking-widest',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -210,7 +210,7 @@ function DropdownMenuSubTrigger({
|
|||||||
data-slot="dropdown-menu-sub-trigger"
|
data-slot="dropdown-menu-sub-trigger"
|
||||||
data-inset={inset}
|
data-inset={inset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8",
|
'focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -229,7 +229,7 @@ function DropdownMenuSubContent({
|
|||||||
<DropdownMenuPrimitive.SubContent
|
<DropdownMenuPrimitive.SubContent
|
||||||
data-slot="dropdown-menu-sub-content"
|
data-slot="dropdown-menu-sub-content"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
|
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,23 +1,22 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import type { VariantProps } from "class-variance-authority";
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
import { useMemo } from "react";
|
import { useMemo } from 'react';
|
||||||
import { cva } from "class-variance-authority";
|
import { cn } from '@acme/ui';
|
||||||
|
import { Label } from '@acme/ui/label';
|
||||||
import { cn } from "@acme/ui";
|
import { Separator } from '@acme/ui/separator';
|
||||||
import { Label } from "@acme/ui/label";
|
import { cva } from 'class-variance-authority';
|
||||||
import { Separator } from "@acme/ui/separator";
|
|
||||||
|
|
||||||
export function FieldSet({
|
export function FieldSet({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"fieldset">) {
|
}: React.ComponentProps<'fieldset'>) {
|
||||||
return (
|
return (
|
||||||
<fieldset
|
<fieldset
|
||||||
data-slot="field-set"
|
data-slot="field-set"
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex flex-col gap-6",
|
'flex flex-col gap-6',
|
||||||
"has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3",
|
'has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -27,17 +26,17 @@ export function FieldSet({
|
|||||||
|
|
||||||
export function FieldLegend({
|
export function FieldLegend({
|
||||||
className,
|
className,
|
||||||
variant = "legend",
|
variant = 'legend',
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) {
|
}: React.ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {
|
||||||
return (
|
return (
|
||||||
<legend
|
<legend
|
||||||
data-slot="field-legend"
|
data-slot="field-legend"
|
||||||
data-variant={variant}
|
data-variant={variant}
|
||||||
className={cn(
|
className={cn(
|
||||||
"mb-3 font-medium",
|
'mb-3 font-medium',
|
||||||
"data-[variant=legend]:text-base",
|
'data-[variant=legend]:text-base',
|
||||||
"data-[variant=label]:text-sm",
|
'data-[variant=label]:text-sm',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -48,12 +47,12 @@ export function FieldLegend({
|
|||||||
export function FieldGroup({
|
export function FieldGroup({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"div">) {
|
}: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="field-group"
|
data-slot="field-group"
|
||||||
className={cn(
|
className={cn(
|
||||||
"group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4",
|
'group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -62,34 +61,34 @@ export function FieldGroup({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fieldVariants = cva(
|
const fieldVariants = cva(
|
||||||
"group/field data-[invalid=true]:text-destructive flex w-full gap-3",
|
'group/field data-[invalid=true]:text-destructive flex w-full gap-3',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
orientation: {
|
orientation: {
|
||||||
vertical: ["flex-col [&>*]:w-full [&>.sr-only]:w-auto"],
|
vertical: ['flex-col [&>*]:w-full [&>.sr-only]:w-auto'],
|
||||||
horizontal: [
|
horizontal: [
|
||||||
"flex-row items-center",
|
'flex-row items-center',
|
||||||
"[&>[data-slot=field-label]]:flex-auto",
|
'[&>[data-slot=field-label]]:flex-auto',
|
||||||
"has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
|
'has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px',
|
||||||
],
|
],
|
||||||
responsive: [
|
responsive: [
|
||||||
"flex-col @md/field-group:flex-row @md/field-group:items-center [&>*]:w-full @md/field-group:[&>*]:w-auto [&>.sr-only]:w-auto",
|
'flex-col @md/field-group:flex-row @md/field-group:items-center [&>*]:w-full @md/field-group:[&>*]:w-auto [&>.sr-only]:w-auto',
|
||||||
"@md/field-group:[&>[data-slot=field-label]]:flex-auto",
|
'@md/field-group:[&>[data-slot=field-label]]:flex-auto',
|
||||||
"@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
|
'@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
orientation: "vertical",
|
orientation: 'vertical',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export function Field({
|
export function Field({
|
||||||
className,
|
className,
|
||||||
orientation = "vertical",
|
orientation = 'vertical',
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) {
|
}: React.ComponentProps<'div'> & VariantProps<typeof fieldVariants>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
role="group"
|
role="group"
|
||||||
@@ -104,12 +103,12 @@ export function Field({
|
|||||||
export function FieldContent({
|
export function FieldContent({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"div">) {
|
}: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="field-content"
|
data-slot="field-content"
|
||||||
className={cn(
|
className={cn(
|
||||||
"group/field-content flex flex-1 flex-col gap-1.5 leading-snug",
|
'group/field-content flex flex-1 flex-col gap-1.5 leading-snug',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -125,9 +124,9 @@ export function FieldLabel({
|
|||||||
<Label
|
<Label
|
||||||
data-slot="field-label"
|
data-slot="field-label"
|
||||||
className={cn(
|
className={cn(
|
||||||
"group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50",
|
'group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50',
|
||||||
"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4",
|
'has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4',
|
||||||
"has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary dark:has-data-[state=checked]:bg-primary/10",
|
'has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary dark:has-data-[state=checked]:bg-primary/10',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -138,12 +137,12 @@ export function FieldLabel({
|
|||||||
export function FieldTitle({
|
export function FieldTitle({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"div">) {
|
}: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="field-label"
|
data-slot="field-label"
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50",
|
'flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -154,14 +153,14 @@ export function FieldTitle({
|
|||||||
export function FieldDescription({
|
export function FieldDescription({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"p">) {
|
}: React.ComponentProps<'p'>) {
|
||||||
return (
|
return (
|
||||||
<p
|
<p
|
||||||
data-slot="field-description"
|
data-slot="field-description"
|
||||||
className={cn(
|
className={cn(
|
||||||
"text-muted-foreground text-sm leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance",
|
'text-muted-foreground text-sm leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance',
|
||||||
"last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5",
|
'last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5',
|
||||||
"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4",
|
'[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -173,7 +172,7 @@ export function FieldSeparator({
|
|||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"div"> & {
|
}: React.ComponentProps<'div'> & {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
@@ -181,7 +180,7 @@ export function FieldSeparator({
|
|||||||
data-slot="field-separator"
|
data-slot="field-separator"
|
||||||
data-content={!!children}
|
data-content={!!children}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2",
|
'relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -204,7 +203,7 @@ export function FieldError({
|
|||||||
children,
|
children,
|
||||||
errors: maybeErrors,
|
errors: maybeErrors,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"div"> & {
|
}: React.ComponentProps<'div'> & {
|
||||||
errors?: ({ message?: string } | undefined)[];
|
errors?: ({ message?: string } | undefined)[];
|
||||||
}) {
|
}) {
|
||||||
const content = useMemo(() => {
|
const content = useMemo(() => {
|
||||||
@@ -240,7 +239,7 @@ export function FieldError({
|
|||||||
<div
|
<div
|
||||||
role="alert"
|
role="alert"
|
||||||
data-slot="field-error"
|
data-slot="field-error"
|
||||||
className={cn("text-destructive text-sm font-normal", className)}
|
className={cn('text-destructive text-sm font-normal', className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{content}
|
{content}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import type { ControllerProps, FieldPath, FieldValues } from "react-hook-form";
|
import type { ControllerProps, FieldPath, FieldValues } from 'react-hook-form';
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from '@/components/ui/label';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
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 {
|
import {
|
||||||
Controller,
|
Controller,
|
||||||
FormProvider,
|
FormProvider,
|
||||||
useFormContext,
|
useFormContext,
|
||||||
useFormState,
|
useFormState,
|
||||||
} from "react-hook-form";
|
} from 'react-hook-form';
|
||||||
|
|
||||||
const Form = FormProvider;
|
const Form = FormProvider;
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ const useFormField = () => {
|
|||||||
const fieldState = getFieldState(fieldContext.name, formState);
|
const fieldState = getFieldState(fieldContext.name, formState);
|
||||||
|
|
||||||
if (!fieldContext) {
|
if (!fieldContext) {
|
||||||
throw new Error("useFormField should be used within <FormField>");
|
throw new Error('useFormField should be used within <FormField>');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id } = itemContext;
|
const { id } = itemContext;
|
||||||
@@ -70,14 +70,14 @@ const FormItemContext = React.createContext<FormItemContextValue>(
|
|||||||
{} as FormItemContextValue,
|
{} as FormItemContextValue,
|
||||||
);
|
);
|
||||||
|
|
||||||
function FormItem({ className, ...props }: React.ComponentProps<"div">) {
|
function FormItem({ className, ...props }: React.ComponentProps<'div'>) {
|
||||||
const id = React.useId();
|
const id = React.useId();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormItemContext.Provider value={{ id }}>
|
<FormItemContext.Provider value={{ id }}>
|
||||||
<div
|
<div
|
||||||
data-slot="form-item"
|
data-slot="form-item"
|
||||||
className={cn("grid gap-2", className)}
|
className={cn('grid gap-2', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</FormItemContext.Provider>
|
</FormItemContext.Provider>
|
||||||
@@ -94,7 +94,7 @@ function FormLabel({
|
|||||||
<Label
|
<Label
|
||||||
data-slot="form-label"
|
data-slot="form-label"
|
||||||
data-error={!!error}
|
data-error={!!error}
|
||||||
className={cn("data-[error=true]:text-destructive", className)}
|
className={cn('data-[error=true]:text-destructive', className)}
|
||||||
htmlFor={formItemId}
|
htmlFor={formItemId}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
@@ -120,22 +120,22 @@ function FormControl({ ...props }: React.ComponentProps<typeof Slot>) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
|
function FormDescription({ className, ...props }: React.ComponentProps<'p'>) {
|
||||||
const { formDescriptionId } = useFormField();
|
const { formDescriptionId } = useFormField();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p
|
<p
|
||||||
data-slot="form-description"
|
data-slot="form-description"
|
||||||
id={formDescriptionId}
|
id={formDescriptionId}
|
||||||
className={cn("text-muted-foreground text-sm", className)}
|
className={cn('text-muted-foreground text-sm', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
|
function FormMessage({ className, ...props }: React.ComponentProps<'p'>) {
|
||||||
const { error, formMessageId } = useFormField();
|
const { error, formMessageId } = useFormField();
|
||||||
const body = error ? String(error?.message ?? "") : props.children;
|
const body = error ? String(error?.message ?? '') : props.children;
|
||||||
|
|
||||||
if (!body) {
|
if (!body) {
|
||||||
return null;
|
return null;
|
||||||
@@ -145,7 +145,7 @@ function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
|
|||||||
<p
|
<p
|
||||||
data-slot="form-message"
|
data-slot="form-message"
|
||||||
id={formMessageId}
|
id={formMessageId}
|
||||||
className={cn("text-destructive text-sm", className)}
|
className={cn('text-destructive text-sm', className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{body}
|
{body}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { cx } from "class-variance-authority";
|
import { cx } from 'class-variance-authority';
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
export const cn = (...inputs: Parameters<typeof cx>) => twMerge(cx(inputs));
|
export const cn = (...inputs: Parameters<typeof cx>) => twMerge(cx(inputs));
|
||||||
|
|
||||||
export const ccn = ({
|
export const ccn = ({
|
||||||
context,
|
context,
|
||||||
className,
|
className,
|
||||||
on = "",
|
on = '',
|
||||||
off = "",
|
off = '',
|
||||||
}: {
|
}: {
|
||||||
context: boolean;
|
context: boolean;
|
||||||
className: string;
|
className: string;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import { OTPInput, OTPInputContext } from "input-otp";
|
import { OTPInput, OTPInputContext } from 'input-otp';
|
||||||
import { MinusIcon } from "lucide-react";
|
import { MinusIcon } from 'lucide-react';
|
||||||
|
|
||||||
function InputOTP({
|
function InputOTP({
|
||||||
className,
|
className,
|
||||||
@@ -16,20 +16,20 @@ function InputOTP({
|
|||||||
<OTPInput
|
<OTPInput
|
||||||
data-slot="input-otp"
|
data-slot="input-otp"
|
||||||
containerClassName={cn(
|
containerClassName={cn(
|
||||||
"flex items-center gap-2 has-disabled:opacity-50",
|
'flex items-center gap-2 has-disabled:opacity-50',
|
||||||
containerClassName,
|
containerClassName,
|
||||||
)}
|
)}
|
||||||
className={cn("disabled:cursor-not-allowed", className)}
|
className={cn('disabled:cursor-not-allowed', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) {
|
function InputOTPGroup({ className, ...props }: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="input-otp-group"
|
data-slot="input-otp-group"
|
||||||
className={cn("flex items-center", className)}
|
className={cn('flex items-center', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -39,7 +39,7 @@ function InputOTPSlot({
|
|||||||
index,
|
index,
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"div"> & {
|
}: React.ComponentProps<'div'> & {
|
||||||
index: number;
|
index: number;
|
||||||
}) {
|
}) {
|
||||||
const inputOTPContext = React.useContext(OTPInputContext);
|
const inputOTPContext = React.useContext(OTPInputContext);
|
||||||
@@ -50,7 +50,7 @@ function InputOTPSlot({
|
|||||||
data-slot="input-otp-slot"
|
data-slot="input-otp-slot"
|
||||||
data-active={isActive}
|
data-active={isActive}
|
||||||
className={cn(
|
className={cn(
|
||||||
"data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive dark:bg-input/30 border-input relative flex h-9 w-9 items-center justify-center border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]",
|
'data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive dark:bg-input/30 border-input relative flex h-9 w-9 items-center justify-center border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -65,7 +65,7 @@ function InputOTPSlot({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) {
|
function InputOTPSeparator({ ...props }: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div data-slot="input-otp-separator" role="separator" {...props}>
|
<div data-slot="input-otp-separator" role="separator" {...props}>
|
||||||
<MinusIcon />
|
<MinusIcon />
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
type={type}
|
type={type}
|
||||||
data-slot="input"
|
data-slot="input"
|
||||||
className={cn(
|
className={cn(
|
||||||
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||||
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
|
||||||
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import * as LabelPrimitive from "@radix-ui/react-label";
|
import * as LabelPrimitive from '@radix-ui/react-label';
|
||||||
|
|
||||||
function Label({
|
function Label({
|
||||||
className,
|
className,
|
||||||
@@ -12,7 +12,7 @@ function Label({
|
|||||||
<LabelPrimitive.Root
|
<LabelPrimitive.Root
|
||||||
data-slot="label"
|
data-slot="label"
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
'flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Button, buttonVariants } from "@/components/ui/button";
|
import { Button, buttonVariants } from '@/components/ui/button';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import {
|
import {
|
||||||
ChevronLeftIcon,
|
ChevronLeftIcon,
|
||||||
ChevronRightIcon,
|
ChevronRightIcon,
|
||||||
MoreHorizontalIcon,
|
MoreHorizontalIcon,
|
||||||
} from "lucide-react";
|
} from 'lucide-react';
|
||||||
|
|
||||||
function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
|
function Pagination({ className, ...props }: React.ComponentProps<'nav'>) {
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
role="navigation"
|
role="navigation"
|
||||||
aria-label="pagination"
|
aria-label="pagination"
|
||||||
data-slot="pagination"
|
data-slot="pagination"
|
||||||
className={cn("mx-auto flex w-full justify-center", className)}
|
className={cn('mx-auto flex w-full justify-center', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -22,39 +22,39 @@ function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
|
|||||||
function PaginationContent({
|
function PaginationContent({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"ul">) {
|
}: React.ComponentProps<'ul'>) {
|
||||||
return (
|
return (
|
||||||
<ul
|
<ul
|
||||||
data-slot="pagination-content"
|
data-slot="pagination-content"
|
||||||
className={cn("flex flex-row items-center gap-1", className)}
|
className={cn('flex flex-row items-center gap-1', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PaginationItem({ ...props }: React.ComponentProps<"li">) {
|
function PaginationItem({ ...props }: React.ComponentProps<'li'>) {
|
||||||
return <li data-slot="pagination-item" {...props} />;
|
return <li data-slot="pagination-item" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
type PaginationLinkProps = {
|
type PaginationLinkProps = {
|
||||||
isActive?: boolean;
|
isActive?: boolean;
|
||||||
} & Pick<React.ComponentProps<typeof Button>, "size"> &
|
} & Pick<React.ComponentProps<typeof Button>, 'size'> &
|
||||||
React.ComponentProps<"a">;
|
React.ComponentProps<'a'>;
|
||||||
|
|
||||||
function PaginationLink({
|
function PaginationLink({
|
||||||
className,
|
className,
|
||||||
isActive,
|
isActive,
|
||||||
size = "icon",
|
size = 'icon',
|
||||||
...props
|
...props
|
||||||
}: PaginationLinkProps) {
|
}: PaginationLinkProps) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
aria-current={isActive ? "page" : undefined}
|
aria-current={isActive ? 'page' : undefined}
|
||||||
data-slot="pagination-link"
|
data-slot="pagination-link"
|
||||||
data-active={isActive}
|
data-active={isActive}
|
||||||
className={cn(
|
className={cn(
|
||||||
buttonVariants({
|
buttonVariants({
|
||||||
variant: isActive ? "outline" : "ghost",
|
variant: isActive ? 'outline' : 'ghost',
|
||||||
size,
|
size,
|
||||||
}),
|
}),
|
||||||
className,
|
className,
|
||||||
@@ -72,7 +72,7 @@ function PaginationPrevious({
|
|||||||
<PaginationLink
|
<PaginationLink
|
||||||
aria-label="Go to previous page"
|
aria-label="Go to previous page"
|
||||||
size="default"
|
size="default"
|
||||||
className={cn("gap-1 px-2.5 sm:pl-2.5", className)}
|
className={cn('gap-1 px-2.5 sm:pl-2.5', className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ChevronLeftIcon />
|
<ChevronLeftIcon />
|
||||||
@@ -89,7 +89,7 @@ function PaginationNext({
|
|||||||
<PaginationLink
|
<PaginationLink
|
||||||
aria-label="Go to next page"
|
aria-label="Go to next page"
|
||||||
size="default"
|
size="default"
|
||||||
className={cn("gap-1 px-2.5 sm:pr-2.5", className)}
|
className={cn('gap-1 px-2.5 sm:pr-2.5', className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<span className="hidden sm:block">Next</span>
|
<span className="hidden sm:block">Next</span>
|
||||||
@@ -101,12 +101,12 @@ function PaginationNext({
|
|||||||
function PaginationEllipsis({
|
function PaginationEllipsis({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"span">) {
|
}: React.ComponentProps<'span'>) {
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
aria-hidden
|
aria-hidden
|
||||||
data-slot="pagination-ellipsis"
|
data-slot="pagination-ellipsis"
|
||||||
className={cn("flex size-9 items-center justify-center", className)}
|
className={cn('flex size-9 items-center justify-center', className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<MoreHorizontalIcon className="size-4" />
|
<MoreHorizontalIcon className="size-4" />
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
import * as ProgressPrimitive from '@radix-ui/react-progress';
|
||||||
|
|
||||||
function Progress({
|
function Progress({
|
||||||
className,
|
className,
|
||||||
@@ -13,7 +13,7 @@ function Progress({
|
|||||||
<ProgressPrimitive.Root
|
<ProgressPrimitive.Root
|
||||||
data-slot="progress"
|
data-slot="progress"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-primary/20 relative h-2 w-full overflow-hidden rounded-full",
|
'bg-primary/20 relative h-2 w-full overflow-hidden rounded-full',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
||||||
|
|
||||||
function ScrollArea({
|
function ScrollArea({
|
||||||
className,
|
className,
|
||||||
@@ -12,7 +12,7 @@ function ScrollArea({
|
|||||||
return (
|
return (
|
||||||
<ScrollAreaPrimitive.Root
|
<ScrollAreaPrimitive.Root
|
||||||
data-slot="scroll-area"
|
data-slot="scroll-area"
|
||||||
className={cn("relative", className)}
|
className={cn('relative', className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ScrollAreaPrimitive.Viewport
|
<ScrollAreaPrimitive.Viewport
|
||||||
@@ -29,7 +29,7 @@ function ScrollArea({
|
|||||||
|
|
||||||
function ScrollBar({
|
function ScrollBar({
|
||||||
className,
|
className,
|
||||||
orientation = "vertical",
|
orientation = 'vertical',
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
|
}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
|
||||||
return (
|
return (
|
||||||
@@ -37,11 +37,11 @@ function ScrollBar({
|
|||||||
data-slot="scroll-area-scrollbar"
|
data-slot="scroll-area-scrollbar"
|
||||||
orientation={orientation}
|
orientation={orientation}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex touch-none p-px transition-colors select-none",
|
'flex touch-none p-px transition-colors select-none',
|
||||||
orientation === "vertical" &&
|
orientation === 'vertical' &&
|
||||||
"h-full w-2.5 border-l border-l-transparent",
|
'h-full w-2.5 border-l border-l-transparent',
|
||||||
orientation === "horizontal" &&
|
orientation === 'horizontal' &&
|
||||||
"h-2.5 flex-col border-t border-t-transparent",
|
'h-2.5 flex-col border-t border-t-transparent',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
import * as SeparatorPrimitive from '@radix-ui/react-separator';
|
||||||
|
|
||||||
function Separator({
|
function Separator({
|
||||||
className,
|
className,
|
||||||
orientation = "horizontal",
|
orientation = 'horizontal',
|
||||||
decorative = true,
|
decorative = true,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
|
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
|
||||||
@@ -16,7 +16,7 @@ function Separator({
|
|||||||
decorative={decorative}
|
decorative={decorative}
|
||||||
orientation={orientation}
|
orientation={orientation}
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ComponentProps,
|
ComponentProps,
|
||||||
@@ -7,8 +7,8 @@ import type {
|
|||||||
ReactNode,
|
ReactNode,
|
||||||
RefObject,
|
RefObject,
|
||||||
SyntheticEvent,
|
SyntheticEvent,
|
||||||
} from "react";
|
} from 'react';
|
||||||
import type { PercentCrop, PixelCrop, ReactCropProps } from "react-image-crop";
|
import type { PercentCrop, PixelCrop, ReactCropProps } from 'react-image-crop';
|
||||||
import {
|
import {
|
||||||
createContext,
|
createContext,
|
||||||
useCallback,
|
useCallback,
|
||||||
@@ -16,14 +16,14 @@ import {
|
|||||||
useEffect,
|
useEffect,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from 'react';
|
||||||
import { Button } from "@/components/ui";
|
import { Button } from '@/components/ui';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import { CropIcon, RotateCcwIcon } from "lucide-react";
|
import { CropIcon, RotateCcwIcon } from 'lucide-react';
|
||||||
import { Slot } from "radix-ui";
|
import { Slot } from 'radix-ui';
|
||||||
import ReactCrop, { centerCrop, makeAspectCrop } from "react-image-crop";
|
import ReactCrop, { centerCrop, makeAspectCrop } from 'react-image-crop';
|
||||||
|
|
||||||
import "react-image-crop/dist/ReactCrop.css";
|
import 'react-image-crop/dist/ReactCrop.css';
|
||||||
|
|
||||||
const centerAspectCrop = (
|
const centerAspectCrop = (
|
||||||
mediaWidth: number,
|
mediaWidth: number,
|
||||||
@@ -34,14 +34,14 @@ const centerAspectCrop = (
|
|||||||
aspect
|
aspect
|
||||||
? makeAspectCrop(
|
? makeAspectCrop(
|
||||||
{
|
{
|
||||||
unit: "%",
|
unit: '%',
|
||||||
width: 90,
|
width: 90,
|
||||||
},
|
},
|
||||||
aspect,
|
aspect,
|
||||||
mediaWidth,
|
mediaWidth,
|
||||||
mediaHeight,
|
mediaHeight,
|
||||||
)
|
)
|
||||||
: { x: 0, y: 0, width: 90, height: 90, unit: "%" },
|
: { x: 0, y: 0, width: 90, height: 90, unit: '%' },
|
||||||
mediaWidth,
|
mediaWidth,
|
||||||
mediaHeight,
|
mediaHeight,
|
||||||
);
|
);
|
||||||
@@ -52,11 +52,11 @@ const getCroppedPngImage = async (
|
|||||||
pixelCrop: PixelCrop,
|
pixelCrop: PixelCrop,
|
||||||
maxImageSize: number,
|
maxImageSize: number,
|
||||||
): Promise<string> => {
|
): Promise<string> => {
|
||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement('canvas');
|
||||||
const ctx = canvas.getContext("2d");
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
throw new Error("Context is null, this should never happen.");
|
throw new Error('Context is null, this should never happen.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const scaleX = imageSrc.naturalWidth / imageSrc.width;
|
const scaleX = imageSrc.naturalWidth / imageSrc.width;
|
||||||
@@ -78,7 +78,7 @@ const getCroppedPngImage = async (
|
|||||||
canvas.height,
|
canvas.height,
|
||||||
);
|
);
|
||||||
|
|
||||||
const croppedImageUrl = canvas.toDataURL("image/png");
|
const croppedImageUrl = canvas.toDataURL('image/png');
|
||||||
const response = await fetch(croppedImageUrl);
|
const response = await fetch(croppedImageUrl);
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ type ImageCropContextType = {
|
|||||||
completedCrop: PixelCrop | null;
|
completedCrop: PixelCrop | null;
|
||||||
imgRef: RefObject<HTMLImageElement | null>;
|
imgRef: RefObject<HTMLImageElement | null>;
|
||||||
onCrop?: (croppedImage: string) => void;
|
onCrop?: (croppedImage: string) => void;
|
||||||
reactCropProps: Omit<ReactCropProps, "onChange" | "onComplete" | "children">;
|
reactCropProps: Omit<ReactCropProps, 'onChange' | 'onComplete' | 'children'>;
|
||||||
handleChange: (pixelCrop: PixelCrop, percentCrop: PercentCrop) => void;
|
handleChange: (pixelCrop: PixelCrop, percentCrop: PercentCrop) => void;
|
||||||
handleComplete: (
|
handleComplete: (
|
||||||
pixelCrop: PixelCrop,
|
pixelCrop: PixelCrop,
|
||||||
@@ -118,7 +118,7 @@ const ImageCropContext = createContext<ImageCropContextType | null>(null);
|
|||||||
const useImageCrop = () => {
|
const useImageCrop = () => {
|
||||||
const context = useContext(ImageCropContext);
|
const context = useContext(ImageCropContext);
|
||||||
if (!context) {
|
if (!context) {
|
||||||
throw new Error("ImageCrop components must be used within ImageCrop");
|
throw new Error('ImageCrop components must be used within ImageCrop');
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
@@ -128,9 +128,9 @@ export type ImageCropProps = {
|
|||||||
maxImageSize?: number;
|
maxImageSize?: number;
|
||||||
onCrop?: (croppedImage: string) => void;
|
onCrop?: (croppedImage: string) => void;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
onChange?: ReactCropProps["onChange"];
|
onChange?: ReactCropProps['onChange'];
|
||||||
onComplete?: ReactCropProps["onComplete"];
|
onComplete?: ReactCropProps['onComplete'];
|
||||||
} & Omit<ReactCropProps, "onChange" | "onComplete" | "children">;
|
} & Omit<ReactCropProps, 'onChange' | 'onComplete' | 'children'>;
|
||||||
|
|
||||||
export const ImageCrop = ({
|
export const ImageCrop = ({
|
||||||
file,
|
file,
|
||||||
@@ -142,15 +142,15 @@ export const ImageCrop = ({
|
|||||||
...reactCropProps
|
...reactCropProps
|
||||||
}: ImageCropProps) => {
|
}: ImageCropProps) => {
|
||||||
const imgRef = useRef<HTMLImageElement | null>(null);
|
const imgRef = useRef<HTMLImageElement | null>(null);
|
||||||
const [imgSrc, setImgSrc] = useState<string>("");
|
const [imgSrc, setImgSrc] = useState<string>('');
|
||||||
const [crop, setCrop] = useState<PercentCrop>();
|
const [crop, setCrop] = useState<PercentCrop>();
|
||||||
const [completedCrop, setCompletedCrop] = useState<PixelCrop | null>(null);
|
const [completedCrop, setCompletedCrop] = useState<PixelCrop | null>(null);
|
||||||
const [initialCrop, setInitialCrop] = useState<PercentCrop>();
|
const [initialCrop, setInitialCrop] = useState<PercentCrop>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.addEventListener("load", () =>
|
reader.addEventListener('load', () =>
|
||||||
setImgSrc(reader.result?.toString() || ""),
|
setImgSrc(reader.result?.toString() || ''),
|
||||||
);
|
);
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
}, [file]);
|
}, [file]);
|
||||||
@@ -244,13 +244,13 @@ export const ImageCropContent = ({
|
|||||||
} = useImageCrop();
|
} = useImageCrop();
|
||||||
|
|
||||||
const shadcnStyle = {
|
const shadcnStyle = {
|
||||||
"--rc-border-color": "var(--color-border)",
|
'--rc-border-color': 'var(--color-border)',
|
||||||
"--rc-focus-color": "var(--color-primary)",
|
'--rc-focus-color': 'var(--color-primary)',
|
||||||
} as CSSProperties;
|
} as CSSProperties;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactCrop
|
<ReactCrop
|
||||||
className={cn("max-h-[277px] max-w-full", className)}
|
className={cn('max-h-[277px] max-w-full', className)}
|
||||||
crop={crop}
|
crop={crop}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
onComplete={handleComplete}
|
onComplete={handleComplete}
|
||||||
@@ -270,7 +270,7 @@ export const ImageCropContent = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ImageCropApplyProps = ComponentProps<"button"> & {
|
export type ImageCropApplyProps = ComponentProps<'button'> & {
|
||||||
asChild?: boolean;
|
asChild?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -302,7 +302,7 @@ export const ImageCropApply = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ImageCropResetProps = ComponentProps<"button"> & {
|
export type ImageCropResetProps = ComponentProps<'button'> & {
|
||||||
asChild?: boolean;
|
asChild?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -335,11 +335,11 @@ export const ImageCropReset = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Keep the original Cropper component for backward compatibility
|
// Keep the original Cropper component for backward compatibility
|
||||||
export type CropperProps = Omit<ReactCropProps, "onChange"> & {
|
export type CropperProps = Omit<ReactCropProps, 'onChange'> & {
|
||||||
file: File;
|
file: File;
|
||||||
maxImageSize?: number;
|
maxImageSize?: number;
|
||||||
onCrop?: (croppedImage: string) => void;
|
onCrop?: (croppedImage: string) => void;
|
||||||
onChange?: ReactCropProps["onChange"];
|
onChange?: ReactCropProps['onChange'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Cropper = ({
|
export const Cropper = ({
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from 'next-themes';
|
||||||
import { Toaster as Sonner, ToasterProps } from "sonner";
|
import { Toaster as Sonner, ToasterProps } from 'sonner';
|
||||||
|
|
||||||
const Toaster = ({ ...props }: ToasterProps) => {
|
const Toaster = ({ ...props }: ToasterProps) => {
|
||||||
const { theme = "system" } = useTheme();
|
const { theme = 'system' } = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sonner
|
<Sonner
|
||||||
theme={theme as ToasterProps["theme"]}
|
theme={theme as ToasterProps['theme']}
|
||||||
className="toaster group"
|
className="toaster group"
|
||||||
style={
|
style={
|
||||||
{
|
{
|
||||||
"--normal-bg": "var(--popover)",
|
'--normal-bg': 'var(--popover)',
|
||||||
"--normal-text": "var(--popover-foreground)",
|
'--normal-text': 'var(--popover-foreground)',
|
||||||
"--normal-border": "var(--border)",
|
'--normal-border': 'var(--border)',
|
||||||
} as React.CSSProperties
|
} as React.CSSProperties
|
||||||
}
|
}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { type ComponentProps } from "react";
|
import { type ComponentProps } from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
type Message = { success: string } | { error: string } | { message: string };
|
type Message = { success: string } | { error: string } | { message: string };
|
||||||
|
|
||||||
type StatusMessageProps = {
|
type StatusMessageProps = {
|
||||||
message: Message;
|
message: Message;
|
||||||
containerProps?: ComponentProps<"div">;
|
containerProps?: ComponentProps<'div'>;
|
||||||
textProps?: ComponentProps<"div">;
|
textProps?: ComponentProps<'div'>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const StatusMessage = ({
|
export const StatusMessage = ({
|
||||||
@@ -16,37 +16,37 @@ export const StatusMessage = ({
|
|||||||
}: StatusMessageProps) => {
|
}: StatusMessageProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex w-full flex-col items-center">
|
<div className="flex w-full flex-col items-center">
|
||||||
{"success" in message && (
|
{'success' in message && (
|
||||||
<div
|
<div
|
||||||
{...containerProps}
|
{...containerProps}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-11/12 flex-col items-center rounded-md p-2",
|
'flex w-11/12 flex-col items-center rounded-md p-2',
|
||||||
"border-2 bg-green-700/20 dark:bg-green-500/20",
|
'border-2 bg-green-700/20 dark:bg-green-500/20',
|
||||||
"border-green-700/50 dark:border-green-500/50",
|
'border-green-700/50 dark:border-green-500/50',
|
||||||
containerProps?.className,
|
containerProps?.className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<p {...textProps}>{message.success}</p>
|
<p {...textProps}>{message.success}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{"error" in message && (
|
{'error' in message && (
|
||||||
<div
|
<div
|
||||||
{...containerProps}
|
{...containerProps}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-11/12 flex-col items-center rounded-md p-2",
|
'flex w-11/12 flex-col items-center rounded-md p-2',
|
||||||
"bg-destructive/20 border-destructive/80 border-2",
|
'bg-destructive/20 border-destructive/80 border-2',
|
||||||
containerProps?.className,
|
containerProps?.className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<p {...textProps}>{message.error}</p>
|
<p {...textProps}>{message.error}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{"message" in message && (
|
{'message' in message && (
|
||||||
<div
|
<div
|
||||||
{...containerProps}
|
{...containerProps}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-11/12 flex-col items-center rounded-md p-2",
|
'flex w-11/12 flex-col items-center rounded-md p-2',
|
||||||
"bg-accent/20 border-primary/80 border-2",
|
'bg-accent/20 border-primary/80 border-2',
|
||||||
containerProps?.className,
|
containerProps?.className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import { type ComponentProps } from "react";
|
import { type ComponentProps } from 'react';
|
||||||
import { Button } from "@/components/ui";
|
import { Button } from '@/components/ui';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from 'lucide-react';
|
||||||
import { useFormStatus } from "react-dom";
|
import { useFormStatus } from 'react-dom';
|
||||||
|
|
||||||
export type SubmitButtonProps = Omit<
|
export type SubmitButtonProps = Omit<
|
||||||
ComponentProps<typeof Button>,
|
ComponentProps<typeof Button>,
|
||||||
"type" | "aria-disabled"
|
'type' | 'aria-disabled'
|
||||||
> & {
|
> & {
|
||||||
pendingText?: string;
|
pendingText?: string;
|
||||||
pendingTextProps?: ComponentProps<"p">;
|
pendingTextProps?: ComponentProps<'p'>;
|
||||||
loaderProps?: ComponentProps<typeof Loader2>;
|
loaderProps?: ComponentProps<typeof Loader2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SubmitButton = ({
|
export const SubmitButton = ({
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
pendingText = "Submitting...",
|
pendingText = 'Submitting...',
|
||||||
pendingTextProps,
|
pendingTextProps,
|
||||||
loaderProps,
|
loaderProps,
|
||||||
...props
|
...props
|
||||||
@@ -29,17 +29,17 @@ export const SubmitButton = ({
|
|||||||
type="submit"
|
type="submit"
|
||||||
aria-disabled={pending}
|
aria-disabled={pending}
|
||||||
{...props}
|
{...props}
|
||||||
className={cn("cursor-pointer", className)}
|
className={cn('cursor-pointer', className)}
|
||||||
>
|
>
|
||||||
{pending || props.disabled ? (
|
{pending || props.disabled ? (
|
||||||
<>
|
<>
|
||||||
<Loader2
|
<Loader2
|
||||||
{...loaderProps}
|
{...loaderProps}
|
||||||
className={cn("mr-2 h-4 w-4 animate-spin", loaderProps?.className)}
|
className={cn('mr-2 h-4 w-4 animate-spin', loaderProps?.className)}
|
||||||
/>
|
/>
|
||||||
<p
|
<p
|
||||||
{...pendingTextProps}
|
{...pendingTextProps}
|
||||||
className={cn("text-sm font-medium", pendingTextProps?.className)}
|
className={cn('text-sm font-medium', pendingTextProps?.className)}
|
||||||
>
|
>
|
||||||
{pendingText}
|
{pendingText}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import * as SwitchPrimitive from "@radix-ui/react-switch";
|
import * as SwitchPrimitive from '@radix-ui/react-switch';
|
||||||
|
|
||||||
function Switch({
|
function Switch({
|
||||||
className,
|
className,
|
||||||
@@ -12,7 +12,7 @@ function Switch({
|
|||||||
<SwitchPrimitive.Root
|
<SwitchPrimitive.Root
|
||||||
data-slot="switch"
|
data-slot="switch"
|
||||||
className={cn(
|
className={cn(
|
||||||
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
'peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -20,7 +20,7 @@ function Switch({
|
|||||||
<SwitchPrimitive.Thumb
|
<SwitchPrimitive.Thumb
|
||||||
data-slot="switch-thumb"
|
data-slot="switch-thumb"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0",
|
'bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0',
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</SwitchPrimitive.Root>
|
</SwitchPrimitive.Root>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
function Table({ className, ...props }: React.ComponentProps<"table">) {
|
function Table({ className, ...props }: React.ComponentProps<'table'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="table-container"
|
data-slot="table-container"
|
||||||
@@ -11,39 +11,39 @@ function Table({ className, ...props }: React.ComponentProps<"table">) {
|
|||||||
>
|
>
|
||||||
<table
|
<table
|
||||||
data-slot="table"
|
data-slot="table"
|
||||||
className={cn("w-full caption-bottom text-sm", className)}
|
className={cn('w-full caption-bottom text-sm', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
function TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {
|
||||||
return (
|
return (
|
||||||
<thead
|
<thead
|
||||||
data-slot="table-header"
|
data-slot="table-header"
|
||||||
className={cn("[&_tr]:border-b", className)}
|
className={cn('[&_tr]:border-b', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
function TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {
|
||||||
return (
|
return (
|
||||||
<tbody
|
<tbody
|
||||||
data-slot="table-body"
|
data-slot="table-body"
|
||||||
className={cn("[&_tr:last-child]:border-0", className)}
|
className={cn('[&_tr:last-child]:border-0', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
function TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) {
|
||||||
return (
|
return (
|
||||||
<tfoot
|
<tfoot
|
||||||
data-slot="table-footer"
|
data-slot="table-footer"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
|
'bg-muted/50 border-t font-medium [&>tr]:last:border-b-0',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -51,12 +51,12 @@ function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
function TableRow({ className, ...props }: React.ComponentProps<'tr'>) {
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
data-slot="table-row"
|
data-slot="table-row"
|
||||||
className={cn(
|
className={cn(
|
||||||
"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
|
'hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -64,12 +64,12 @@ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
function TableHead({ className, ...props }: React.ComponentProps<'th'>) {
|
||||||
return (
|
return (
|
||||||
<th
|
<th
|
||||||
data-slot="table-head"
|
data-slot="table-head"
|
||||||
className={cn(
|
className={cn(
|
||||||
"text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
'text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -77,12 +77,12 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
function TableCell({ className, ...props }: React.ComponentProps<'td'>) {
|
||||||
return (
|
return (
|
||||||
<td
|
<td
|
||||||
data-slot="table-cell"
|
data-slot="table-cell"
|
||||||
className={cn(
|
className={cn(
|
||||||
"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
'p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -93,11 +93,11 @@ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
|||||||
function TableCaption({
|
function TableCaption({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"caption">) {
|
}: React.ComponentProps<'caption'>) {
|
||||||
return (
|
return (
|
||||||
<caption
|
<caption
|
||||||
data-slot="table-caption"
|
data-slot="table-caption"
|
||||||
className={cn("text-muted-foreground mt-4 text-sm", className)}
|
className={cn('text-muted-foreground mt-4 text-sm', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from '@/lib/utils';
|
||||||
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
||||||
|
|
||||||
function Tabs({
|
function Tabs({
|
||||||
className,
|
className,
|
||||||
@@ -11,7 +11,7 @@ function Tabs({
|
|||||||
return (
|
return (
|
||||||
<TabsPrimitive.Root
|
<TabsPrimitive.Root
|
||||||
data-slot="tabs"
|
data-slot="tabs"
|
||||||
className={cn("flex flex-col gap-2", className)}
|
className={cn('flex flex-col gap-2', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -25,7 +25,7 @@ function TabsList({
|
|||||||
<TabsPrimitive.List
|
<TabsPrimitive.List
|
||||||
data-slot="tabs-list"
|
data-slot="tabs-list"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
|
'bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -56,7 +56,7 @@ function TabsContent({
|
|||||||
return (
|
return (
|
||||||
<TabsPrimitive.Content
|
<TabsPrimitive.Content
|
||||||
data-slot="tabs-content"
|
data-slot="tabs-content"
|
||||||
className={cn("flex-1 outline-none", className)}
|
className={cn('flex-1 outline-none', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { DesktopIcon, MoonIcon, SunIcon } from "@radix-ui/react-icons";
|
import { DesktopIcon, MoonIcon, SunIcon } from '@radix-ui/react-icons';
|
||||||
import * as z from "zod/v4";
|
import * as z from 'zod/v4';
|
||||||
|
|
||||||
import { Button } from "./button";
|
import { Button } from './button';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "./dropdown-menu";
|
} from './dropdown-menu';
|
||||||
|
|
||||||
const ThemeModeSchema = z.enum(["light", "dark", "auto"]);
|
const ThemeModeSchema = z.enum(['light', 'dark', 'auto']);
|
||||||
|
|
||||||
const themeKey = "theme-mode";
|
const themeKey = 'theme-mode';
|
||||||
|
|
||||||
export type ThemeMode = z.output<typeof ThemeModeSchema>;
|
export type ThemeMode = z.output<typeof ThemeModeSchema>;
|
||||||
export type ResolvedTheme = Exclude<ThemeMode, "auto">;
|
export type ResolvedTheme = Exclude<ThemeMode, 'auto'>;
|
||||||
|
|
||||||
const getStoredThemeMode = (): ThemeMode => {
|
const getStoredThemeMode = (): ThemeMode => {
|
||||||
if (typeof window === "undefined") return "auto";
|
if (typeof window === 'undefined') return 'auto';
|
||||||
try {
|
try {
|
||||||
const storedTheme = localStorage.getItem(themeKey);
|
const storedTheme = localStorage.getItem(themeKey);
|
||||||
return ThemeModeSchema.parse(storedTheme);
|
return ThemeModeSchema.parse(storedTheme);
|
||||||
} catch {
|
} catch {
|
||||||
return "auto";
|
return 'auto';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -39,35 +39,35 @@ const setStoredThemeMode = (theme: ThemeMode) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getSystemTheme = () => {
|
const getSystemTheme = () => {
|
||||||
if (typeof window === "undefined") return "light";
|
if (typeof window === 'undefined') return 'light';
|
||||||
return window.matchMedia("(prefers-color-scheme: dark)").matches
|
return window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||||
? "dark"
|
? 'dark'
|
||||||
: "light";
|
: 'light';
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateThemeClass = (themeMode: ThemeMode) => {
|
const updateThemeClass = (themeMode: ThemeMode) => {
|
||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
root.classList.remove("light", "dark", "auto");
|
root.classList.remove('light', 'dark', 'auto');
|
||||||
const newTheme = themeMode === "auto" ? getSystemTheme() : themeMode;
|
const newTheme = themeMode === 'auto' ? getSystemTheme() : themeMode;
|
||||||
root.classList.add(newTheme);
|
root.classList.add(newTheme);
|
||||||
|
|
||||||
if (themeMode === "auto") {
|
if (themeMode === 'auto') {
|
||||||
root.classList.add("auto");
|
root.classList.add('auto');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setupPreferredListener = () => {
|
const setupPreferredListener = () => {
|
||||||
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
const handler = () => updateThemeClass("auto");
|
const handler = () => updateThemeClass('auto');
|
||||||
mediaQuery.addEventListener("change", handler);
|
mediaQuery.addEventListener('change', handler);
|
||||||
return () => mediaQuery.removeEventListener("change", handler);
|
return () => mediaQuery.removeEventListener('change', handler);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getNextTheme = (current: ThemeMode): ThemeMode => {
|
const getNextTheme = (current: ThemeMode): ThemeMode => {
|
||||||
const themes: ThemeMode[] =
|
const themes: ThemeMode[] =
|
||||||
getSystemTheme() === "dark"
|
getSystemTheme() === 'dark'
|
||||||
? ["auto", "light", "dark"]
|
? ['auto', 'light', 'dark']
|
||||||
: ["auto", "dark", "light"];
|
: ['auto', 'dark', 'light'];
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
return themes[(themes.indexOf(current) + 1) % themes.length]!;
|
return themes[(themes.indexOf(current) + 1) % themes.length]!;
|
||||||
};
|
};
|
||||||
@@ -75,19 +75,19 @@ const getNextTheme = (current: ThemeMode): ThemeMode => {
|
|||||||
export const themeDetectorScript = (function () {
|
export const themeDetectorScript = (function () {
|
||||||
function themeFn() {
|
function themeFn() {
|
||||||
const isValidTheme = (theme: string): theme is ThemeMode => {
|
const isValidTheme = (theme: string): theme is ThemeMode => {
|
||||||
const validThemes = ["light", "dark", "auto"] as const;
|
const validThemes = ['light', 'dark', 'auto'] as const;
|
||||||
return validThemes.includes(theme as ThemeMode);
|
return validThemes.includes(theme as ThemeMode);
|
||||||
};
|
};
|
||||||
|
|
||||||
const storedTheme = localStorage.getItem("theme-mode") ?? "auto";
|
const storedTheme = localStorage.getItem('theme-mode') ?? 'auto';
|
||||||
const validTheme = isValidTheme(storedTheme) ? storedTheme : "auto";
|
const validTheme = isValidTheme(storedTheme) ? storedTheme : 'auto';
|
||||||
|
|
||||||
if (validTheme === "auto") {
|
if (validTheme === 'auto') {
|
||||||
const autoTheme = window.matchMedia("(prefers-color-scheme: dark)")
|
const autoTheme = window.matchMedia('(prefers-color-scheme: dark)')
|
||||||
.matches
|
.matches
|
||||||
? "dark"
|
? 'dark'
|
||||||
: "light";
|
: 'light';
|
||||||
document.documentElement.classList.add(autoTheme, "auto");
|
document.documentElement.classList.add(autoTheme, 'auto');
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.classList.add(validTheme);
|
document.documentElement.classList.add(validTheme);
|
||||||
}
|
}
|
||||||
@@ -109,11 +109,11 @@ export function ThemeProvider({ children }: React.PropsWithChildren) {
|
|||||||
const [themeMode, setThemeMode] = React.useState(getStoredThemeMode);
|
const [themeMode, setThemeMode] = React.useState(getStoredThemeMode);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (themeMode !== "auto") return;
|
if (themeMode !== 'auto') return;
|
||||||
return setupPreferredListener();
|
return setupPreferredListener();
|
||||||
}, [themeMode]);
|
}, [themeMode]);
|
||||||
|
|
||||||
const resolvedTheme = themeMode === "auto" ? getSystemTheme() : themeMode;
|
const resolvedTheme = themeMode === 'auto' ? getSystemTheme() : themeMode;
|
||||||
|
|
||||||
const setTheme = (newTheme: ThemeMode) => {
|
const setTheme = (newTheme: ThemeMode) => {
|
||||||
setThemeMode(newTheme);
|
setThemeMode(newTheme);
|
||||||
@@ -146,7 +146,7 @@ export function ThemeProvider({ children }: React.PropsWithChildren) {
|
|||||||
export function useTheme() {
|
export function useTheme() {
|
||||||
const context = React.use(ThemeContext);
|
const context = React.use(ThemeContext);
|
||||||
if (!context) {
|
if (!context) {
|
||||||
throw new Error("useTheme must be used within a ThemeProvider");
|
throw new Error('useTheme must be used within a ThemeProvider');
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
@@ -169,13 +169,13 @@ export function ThemeToggle() {
|
|||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end">
|
<DropdownMenuContent align="end">
|
||||||
<DropdownMenuItem onClick={() => setTheme("light")}>
|
<DropdownMenuItem onClick={() => setTheme('light')}>
|
||||||
Light
|
Light
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem onClick={() => setTheme("dark")}>
|
<DropdownMenuItem onClick={() => setTheme('dark')}>
|
||||||
Dark
|
Dark
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem onClick={() => setTheme("auto")}>
|
<DropdownMenuItem onClick={() => setTheme('auto')}>
|
||||||
System
|
System
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import type { ToasterProps } from "sonner";
|
import type { ToasterProps } from 'sonner';
|
||||||
import { Toaster as Sonner, toast } from "sonner";
|
import { Toaster as Sonner, toast } from 'sonner';
|
||||||
|
|
||||||
import { useTheme } from "./theme";
|
import { useTheme } from './theme';
|
||||||
|
|
||||||
export const Toaster = ({ ...props }: ToasterProps) => {
|
export const Toaster = ({ ...props }: ToasterProps) => {
|
||||||
const { themeMode } = useTheme();
|
const { themeMode } = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sonner
|
<Sonner
|
||||||
theme={themeMode === "auto" ? "system" : themeMode}
|
theme={themeMode === 'auto' ? 'system' : themeMode}
|
||||||
className="toaster group"
|
className="toaster group"
|
||||||
style={
|
style={
|
||||||
{
|
{
|
||||||
"--normal-bg": "var(--popover)",
|
'--normal-bg': 'var(--popover)',
|
||||||
"--normal-text": "var(--popover-foreground)",
|
'--normal-text': 'var(--popover-foreground)',
|
||||||
"--normal-border": "var(--border)",
|
'--normal-border': 'var(--border)',
|
||||||
} as React.CSSProperties
|
} as React.CSSProperties
|
||||||
}
|
}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
1
tools/eslint/.cache/.prettiercache
Normal file
1
tools/eslint/.cache/.prettiercache
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[["1","2","3","4","5"],{"key":"6","value":"7"},{"key":"8","value":"9"},{"key":"10","value":"11"},{"key":"12","value":"13"},{"key":"14","value":"15"},"/home/gib/Documents/Code/convex-monorepo/tools/eslint/package.json",{"size":979,"mtime":1766222924000,"hash":"16","data":"17"},"/home/gib/Documents/Code/convex-monorepo/tools/eslint/nextjs.ts",{"size":440,"mtime":1768155639188,"hash":"18","data":"19"},"/home/gib/Documents/Code/convex-monorepo/tools/eslint/react.ts",{"size":592,"mtime":1768155639239,"hash":"20","data":"21"},"/home/gib/Documents/Code/convex-monorepo/tools/eslint/base.ts",{"size":2511,"mtime":1768155639128,"hash":"22","data":"23"},"/home/gib/Documents/Code/convex-monorepo/tools/eslint/tsconfig.json",{"size":94,"mtime":1766222924000,"hash":"24","data":"25"},"a5326aca75246da261fd2e354257b45a",{"hashOfOptions":"26"},"25c52c46972131dcc296288599ff108d",{"hashOfOptions":"27"},"2292935ede6baf909f6a0c61486e15da",{"hashOfOptions":"28"},"9e432daa1849e911eb3c69df3d068c6d",{"hashOfOptions":"29"},"b3c77d33a30318d89c9c2cafcbe00bbe",{"hashOfOptions":"30"},"1786406903","2477157100","3372054421","3828872695","459831536"]
|
||||||
@@ -1,33 +1,33 @@
|
|||||||
import * as path from "node:path";
|
import * as path from 'node:path';
|
||||||
import { includeIgnoreFile } from "@eslint/compat";
|
import { includeIgnoreFile } from '@eslint/compat';
|
||||||
import eslint from "@eslint/js";
|
import eslint from '@eslint/js';
|
||||||
import importPlugin from "eslint-plugin-import";
|
import importPlugin from 'eslint-plugin-import';
|
||||||
import turboPlugin from "eslint-plugin-turbo";
|
import turboPlugin from 'eslint-plugin-turbo';
|
||||||
import { defineConfig } from "eslint/config";
|
import { defineConfig } from 'eslint/config';
|
||||||
import tseslint from "typescript-eslint";
|
import tseslint from 'typescript-eslint';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All packages that leverage t3-env should use this rule
|
* All packages that leverage t3-env should use this rule
|
||||||
*/
|
*/
|
||||||
export const restrictEnvAccess = defineConfig(
|
export const restrictEnvAccess = defineConfig(
|
||||||
{ ignores: ["**/env.ts"] },
|
{ ignores: ['**/env.ts'] },
|
||||||
{
|
{
|
||||||
files: ["**/*.js", "**/*.ts", "**/*.tsx"],
|
files: ['**/*.js', '**/*.ts', '**/*.tsx'],
|
||||||
rules: {
|
rules: {
|
||||||
"no-restricted-properties": [
|
'no-restricted-properties': [
|
||||||
"error",
|
'error',
|
||||||
{
|
{
|
||||||
object: "process",
|
object: 'process',
|
||||||
property: "env",
|
property: 'env',
|
||||||
message:
|
message:
|
||||||
"Use `import { env } from '@/env'` instead to ensure validated types.",
|
"Use `import { env } from '@/env'` instead to ensure validated types.",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"no-restricted-imports": [
|
'no-restricted-imports': [
|
||||||
"error",
|
'error',
|
||||||
{
|
{
|
||||||
name: "process",
|
name: 'process',
|
||||||
importNames: ["env"],
|
importNames: ['env'],
|
||||||
message:
|
message:
|
||||||
"Use `import { env } from '@/env'` instead to ensure validated types.",
|
"Use `import { env } from '@/env'` instead to ensure validated types.",
|
||||||
},
|
},
|
||||||
@@ -38,10 +38,10 @@ export const restrictEnvAccess = defineConfig(
|
|||||||
|
|
||||||
export const baseConfig = defineConfig(
|
export const baseConfig = defineConfig(
|
||||||
// Ignore files not tracked by VCS and any config files
|
// Ignore files not tracked by VCS and any config files
|
||||||
includeIgnoreFile(path.join(import.meta.dirname, "../../.gitignore")),
|
includeIgnoreFile(path.join(import.meta.dirname, '../../.gitignore')),
|
||||||
{ ignores: ["**/*.config.*"] },
|
{ ignores: ['**/*.config.*'] },
|
||||||
{
|
{
|
||||||
files: ["**/*.js", "**/*.ts", "**/*.tsx"],
|
files: ['**/*.js', '**/*.ts', '**/*.tsx'],
|
||||||
plugins: {
|
plugins: {
|
||||||
import: importPlugin,
|
import: importPlugin,
|
||||||
turbo: turboPlugin,
|
turbo: turboPlugin,
|
||||||
@@ -54,26 +54,26 @@ export const baseConfig = defineConfig(
|
|||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
...turboPlugin.configs.recommended.rules,
|
...turboPlugin.configs.recommended.rules,
|
||||||
"@typescript-eslint/no-unused-vars": [
|
'@typescript-eslint/no-unused-vars': [
|
||||||
"error",
|
'error',
|
||||||
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
|
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
|
||||||
],
|
],
|
||||||
"@typescript-eslint/consistent-type-imports": [
|
'@typescript-eslint/consistent-type-imports': [
|
||||||
"warn",
|
'warn',
|
||||||
{ prefer: "type-imports", fixStyle: "separate-type-imports" },
|
{ prefer: 'type-imports', fixStyle: 'separate-type-imports' },
|
||||||
],
|
],
|
||||||
"@typescript-eslint/no-misused-promises": [
|
'@typescript-eslint/no-misused-promises': [
|
||||||
2,
|
2,
|
||||||
{ checksVoidReturn: { attributes: false } },
|
{ checksVoidReturn: { attributes: false } },
|
||||||
],
|
],
|
||||||
"@typescript-eslint/no-unnecessary-condition": [
|
'@typescript-eslint/no-unnecessary-condition': [
|
||||||
"error",
|
'error',
|
||||||
{
|
{
|
||||||
allowConstantLoopConditions: true,
|
allowConstantLoopConditions: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"@typescript-eslint/no-non-null-assertion": "error",
|
'@typescript-eslint/no-non-null-assertion': 'error',
|
||||||
"import/consistent-type-specifier-style": ["error", "prefer-top-level"],
|
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import nextPlugin from "@next/eslint-plugin-next";
|
import nextPlugin from '@next/eslint-plugin-next';
|
||||||
import { defineConfig } from "eslint/config";
|
import { defineConfig } from 'eslint/config';
|
||||||
|
|
||||||
export const nextjsConfig = defineConfig({
|
export const nextjsConfig = defineConfig({
|
||||||
files: ["**/*.ts", "**/*.tsx"],
|
files: ['**/*.ts', '**/*.tsx'],
|
||||||
plugins: {
|
plugins: {
|
||||||
"@next/next": nextPlugin,
|
'@next/next': nextPlugin,
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
...nextPlugin.configs.recommended.rules,
|
...nextPlugin.configs.recommended.rules,
|
||||||
...nextPlugin.configs["core-web-vitals"].rules,
|
...nextPlugin.configs['core-web-vitals'].rules,
|
||||||
// TypeError: context.getAncestors is not a function
|
// TypeError: context.getAncestors is not a function
|
||||||
"@next/next/no-duplicate-head": "off",
|
'@next/next/no-duplicate-head': 'off',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import reactPlugin from "eslint-plugin-react";
|
import reactPlugin from 'eslint-plugin-react';
|
||||||
import reactHooks from "eslint-plugin-react-hooks";
|
import reactHooks from 'eslint-plugin-react-hooks';
|
||||||
import { defineConfig } from "eslint/config";
|
import { defineConfig } from 'eslint/config';
|
||||||
|
|
||||||
export const reactConfig = defineConfig(
|
export const reactConfig = defineConfig(
|
||||||
{
|
{
|
||||||
files: ["**/*.ts", "**/*.tsx"],
|
files: ['**/*.ts', '**/*.tsx'],
|
||||||
...reactPlugin.configs.flat.recommended,
|
...reactPlugin.configs.flat.recommended,
|
||||||
...reactPlugin.configs.flat["jsx-runtime"],
|
...reactPlugin.configs.flat['jsx-runtime'],
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
...reactPlugin.configs.flat.recommended?.languageOptions,
|
...reactPlugin.configs.flat.recommended?.languageOptions,
|
||||||
...reactPlugin.configs.flat["jsx-runtime"]?.languageOptions,
|
...reactPlugin.configs.flat['jsx-runtime']?.languageOptions,
|
||||||
globals: {
|
globals: {
|
||||||
React: "writable",
|
React: 'writable',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
reactHooks.configs.flat["recommended-latest"]!,
|
reactHooks.configs.flat['recommended-latest']!,
|
||||||
);
|
);
|
||||||
|
|||||||
1
tools/prettier/.cache/.prettiercache
Normal file
1
tools/prettier/.cache/.prettiercache
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[["1","2","3"],{"key":"4","value":"5"},{"key":"6","value":"7"},{"key":"8","value":"9"},"/home/gib/Documents/Code/convex-monorepo/tools/prettier/tsconfig.json",{"size":94,"mtime":1766222924000,"hash":"10","data":"11"},"/home/gib/Documents/Code/convex-monorepo/tools/prettier/package.json",{"size":607,"mtime":1766222924000,"hash":"12","data":"13"},"/home/gib/Documents/Code/convex-monorepo/tools/prettier/index.js",{"size":1170,"mtime":1768155639114,"hash":"14","data":"15"},"b3c77d33a30318d89c9c2cafcbe00bbe",{"hashOfOptions":"16"},"11b634ce56ac720ac9a2860d77fbd2cc",{"hashOfOptions":"17"},"d6f2202018912e47fdd2016f04a4b6eb",{"hashOfOptions":"18"},"1555666866","640383157","507270250"]
|
||||||
@@ -5,42 +5,42 @@
|
|||||||
/** @type { PrettierConfig | SortImportsConfig | TailwindConfig } */
|
/** @type { PrettierConfig | SortImportsConfig | TailwindConfig } */
|
||||||
const config = {
|
const config = {
|
||||||
singleQuote: true,
|
singleQuote: true,
|
||||||
trailingComma: "all",
|
trailingComma: 'all',
|
||||||
tabWidth: 2,
|
tabWidth: 2,
|
||||||
printWidth: 80,
|
printWidth: 80,
|
||||||
plugins: [
|
plugins: [
|
||||||
"@ianvs/prettier-plugin-sort-imports",
|
'@ianvs/prettier-plugin-sort-imports',
|
||||||
"prettier-plugin-tailwindcss",
|
'prettier-plugin-tailwindcss',
|
||||||
],
|
],
|
||||||
tailwindFunctions: ["cn", "cva"],
|
tailwindFunctions: ['cn', 'cva'],
|
||||||
importOrder: [
|
importOrder: [
|
||||||
"<TYPES>",
|
'<TYPES>',
|
||||||
"^(react/(.*)$)|^(react$)|^(react-native(.*)$)",
|
'^(react/(.*)$)|^(react$)|^(react-native(.*)$)',
|
||||||
"^(next/(.*)$)|^(next$)",
|
'^(next/(.*)$)|^(next$)',
|
||||||
"^(expo(.*)$)|^(expo$)",
|
'^(expo(.*)$)|^(expo$)',
|
||||||
"<THIRD_PARTY_MODULES>",
|
'<THIRD_PARTY_MODULES>',
|
||||||
"",
|
'',
|
||||||
"<TYPES>^@gib",
|
'<TYPES>^@gib',
|
||||||
"^@gib/(.*)$",
|
'^@gib/(.*)$',
|
||||||
"",
|
'',
|
||||||
"<TYPES>^[.|..|~]",
|
'<TYPES>^[.|..|~]',
|
||||||
"^~/",
|
'^~/',
|
||||||
"^[../]",
|
'^[../]',
|
||||||
"^[./]",
|
'^[./]',
|
||||||
],
|
],
|
||||||
importOrderParserPlugins: ["typescript", "jsx", "decorators-legacy"],
|
importOrderParserPlugins: ['typescript', 'jsx', 'decorators-legacy'],
|
||||||
importOrderTypeScriptVersion: "5.0.0",
|
importOrderTypeScriptVersion: '5.0.0',
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
files: "*.json.hbs",
|
files: '*.json.hbs',
|
||||||
options: {
|
options: {
|
||||||
parser: "json",
|
parser: 'json',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: "*.ts.hbs",
|
files: '*.ts.hbs',
|
||||||
options: {
|
options: {
|
||||||
parser: "babel",
|
parser: 'babel',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
1
tools/tailwind/.cache/.prettiercache
Normal file
1
tools/tailwind/.cache/.prettiercache
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[["1","2","3","4","5"],{"key":"6","value":"7"},{"key":"8","value":"9"},{"key":"10","value":"11"},{"key":"12","value":"13"},{"key":"14","value":"15"},"/home/gib/Documents/Code/convex-monorepo/tools/tailwind/package.json",{"size":851,"mtime":1766222924000,"hash":"16","data":"17"},"/home/gib/Documents/Code/convex-monorepo/tools/tailwind/postcss-config.js",{"size":70,"mtime":1768155639454,"hash":"18","data":"19"},"/home/gib/Documents/Code/convex-monorepo/tools/tailwind/eslint.config.ts",{"size":143,"mtime":1768155639344,"hash":"20","data":"21"},"/home/gib/Documents/Code/convex-monorepo/tools/tailwind/theme.css",{"size":6741,"mtime":1766222924000,"hash":"22","data":"23"},"/home/gib/Documents/Code/convex-monorepo/tools/tailwind/tsconfig.json",{"size":94,"mtime":1766222924000,"hash":"24","data":"25"},"0d22e47f57739db9de04c6f8420d6fb5",{"hashOfOptions":"26"},"9a944fbda06979be39571bd9bd00b0d9",{"hashOfOptions":"27"},"b8fec960cb32340eea62ca1485093e68",{"hashOfOptions":"28"},"5dd421d25d104c47e1ab36df41ed0f7d",{"hashOfOptions":"29"},"b3c77d33a30318d89c9c2cafcbe00bbe",{"hashOfOptions":"30"},"1821576240","2434669165","2442413358","1994519264","1135731447"]
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { defineConfig } from "eslint/config";
|
import { defineConfig } from 'eslint/config';
|
||||||
|
|
||||||
import { baseConfig } from "@gib/eslint-config/base";
|
import { baseConfig } from '@gib/eslint-config/base';
|
||||||
|
|
||||||
export default defineConfig(baseConfig);
|
export default defineConfig(baseConfig);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export default {
|
export default {
|
||||||
plugins: {
|
plugins: {
|
||||||
"@tailwindcss/postcss": {},
|
'@tailwindcss/postcss': {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
17
turbo.json
17
turbo.json
@@ -3,33 +3,24 @@
|
|||||||
"globalDependencies": ["**/.env.*local"],
|
"globalDependencies": ["**/.env.*local"],
|
||||||
"globalEnv": [
|
"globalEnv": [
|
||||||
"NODE_ENV",
|
"NODE_ENV",
|
||||||
"CI",
|
|
||||||
"SKIP_ENV_VALIDATION",
|
|
||||||
"SITE_URL",
|
|
||||||
"SENTRY_AUTH_TOKEN",
|
"SENTRY_AUTH_TOKEN",
|
||||||
"NEXT_PUBLIC_SITE_URL",
|
"NEXT_PUBLIC_SITE_URL",
|
||||||
"NEXT_PUBLIC_CONVEX_URL",
|
"NEXT_PUBLIC_CONVEX_URL",
|
||||||
|
"NEXT_PUBLIC_PLAUSIBLE_URL",
|
||||||
"NEXT_PUBLIC_SENTRY_DSN",
|
"NEXT_PUBLIC_SENTRY_DSN",
|
||||||
"NEXT_PUBLIC_SENTRY_URL",
|
"NEXT_PUBLIC_SENTRY_URL",
|
||||||
"NEXT_PUBLIC_SENTRY_ORG",
|
"NEXT_PUBLIC_SENTRY_ORG",
|
||||||
"NEXT_PUBLIC_SENTRY_PROJECT_NAME",
|
"NEXT_PUBLIC_SENTRY_PROJECT_NAME",
|
||||||
"CONVEX_SELF_HOSTED_URL",
|
"CONVEX_SELF_HOSTED_URL",
|
||||||
"CONVEX_SELF_HOSTED_ADMIN_KEY",
|
"CONVEX_SELF_HOSTED_ADMIN_KEY",
|
||||||
"SETUP_SCRIPT_RAN",
|
"CONVEX_SITE_URL",
|
||||||
"SITE_URL",
|
|
||||||
"AUTH_URL",
|
|
||||||
"USESEND_API_KEY",
|
"USESEND_API_KEY",
|
||||||
"AUTH_AUTHENTIK_ID",
|
"AUTH_AUTHENTIK_ID",
|
||||||
"AUTH_AUTHENTIK_SECRET",
|
"AUTH_AUTHENTIK_SECRET",
|
||||||
"AUTH_AUTHENTIK_ISSUER",
|
"AUTH_AUTHENTIK_ISSUER"
|
||||||
"AUTH_MICROSOFT_ENTRA_ID_ID",
|
|
||||||
"AUTH_MICROSOFT_ENTRA_ID_SECRET",
|
|
||||||
"AUTH_MICROSOFT_ENTRA_ID_ISSUER",
|
|
||||||
"AUTH_MICROSOFT_ENTRA_ID_AUTH_URL"
|
|
||||||
],
|
],
|
||||||
"globalPassThroughEnv": [
|
"globalPassThroughEnv": [
|
||||||
"NODE_ENV",
|
"NODE_ENV"
|
||||||
"CI"
|
|
||||||
],
|
],
|
||||||
"ui": "tui",
|
"ui": "tui",
|
||||||
"tasks": {
|
"tasks": {
|
||||||
|
|||||||
Reference in New Issue
Block a user