feat: implementar melhorias em importação, compartilhamento e contas inativas

- Corrigir cálculo de valor na importação de lançamentos parcelados
    - Exibir valor total (parcela × quantidade) ao invés do valor da parcela individual
    - Permite recriar parcelamentos importados com valor correto

  - Permitir que usuários compartilhados se descompartilhem de pagadores
    - Adicionar componente PagadorLeaveShareCard na aba Perfil
    - Usuário filho pode sair do compartilhamento sem precisar do usuário pai
    - Manter autorização bidirecionada na action de remoção de share

  - Implementar submenu "Inativos" para contas bancárias
    - Criar página /contas/inativos seguindo padrão de cartões
    - Filtrar contas ativas e inativas em páginas separadas
    - Adicionar ícone e navegação no sidebar
This commit is contained in:
Felipe Coutinho
2026-01-11 22:44:20 +00:00
parent 147857c5bd
commit 6a45a5110d
26 changed files with 812 additions and 405 deletions

View File

@@ -1,7 +1,7 @@
import { cartoes, contas, lancamentos } from "@/db/schema";
import { db } from "@/lib/db";
import { loadLogoOptions } from "@/lib/logo/options";
import { and, eq, isNull, or, sql } from "drizzle-orm";
import { and, eq, ilike, isNull, not, or, sql } from "drizzle-orm";
export type CardData = {
id: string;
@@ -33,7 +33,91 @@ export async function fetchCardsForUser(userId: string): Promise<{
const [cardRows, accountRows, logoOptions, usageRows] = await Promise.all([
db.query.cartoes.findMany({
orderBy: (card: typeof cartoes.$inferSelect, { desc }: { desc: (field: unknown) => unknown }) => [desc(card.name)],
where: eq(cartoes.userId, userId),
where: and(eq(cartoes.userId, userId), not(ilike(cartoes.status, "inativo"))),
with: {
conta: {
columns: {
id: true,
name: true,
},
},
},
}),
db.query.contas.findMany({
orderBy: (account: typeof contas.$inferSelect, { desc }: { desc: (field: unknown) => unknown }) => [desc(account.name)],
where: eq(contas.userId, userId),
columns: {
id: true,
name: true,
logo: true,
},
}),
loadLogoOptions(),
db
.select({
cartaoId: lancamentos.cartaoId,
total: sql<number>`coalesce(sum(${lancamentos.amount}), 0)`,
})
.from(lancamentos)
.where(
and(
eq(lancamentos.userId, userId),
or(isNull(lancamentos.isSettled), eq(lancamentos.isSettled, false))
)
)
.groupBy(lancamentos.cartaoId),
]);
const usageMap = new Map<string, number>();
usageRows.forEach((row: { cartaoId: string | null; total: number | null }) => {
if (!row.cartaoId) return;
usageMap.set(row.cartaoId, Number(row.total ?? 0));
});
const cards = cardRows.map((card) => ({
id: card.id,
name: card.name,
brand: card.brand,
status: card.status,
closingDay: card.closingDay,
dueDay: card.dueDay,
note: card.note,
logo: card.logo,
limit: card.limit ? Number(card.limit) : null,
limitInUse: (() => {
const total = usageMap.get(card.id) ?? 0;
return total < 0 ? Math.abs(total) : 0;
})(),
limitAvailable: (() => {
if (!card.limit) {
return null;
}
const total = usageMap.get(card.id) ?? 0;
const inUse = total < 0 ? Math.abs(total) : 0;
return Math.max(Number(card.limit) - inUse, 0);
})(),
contaId: card.contaId,
contaName: card.conta?.name ?? "Conta não encontrada",
}));
const accounts = accountRows.map((account) => ({
id: account.id,
name: account.name,
logo: account.logo,
}));
return { cards, accounts, logoOptions };
}
export async function fetchInativosForUser(userId: string): Promise<{
cards: CardData[];
accounts: AccountSimple[];
logoOptions: LogoOption[];
}> {
const [cardRows, accountRows, logoOptions, usageRows] = await Promise.all([
db.query.cartoes.findMany({
orderBy: (card: typeof cartoes.$inferSelect, { desc }: { desc: (field: unknown) => unknown }) => [desc(card.name)],
where: and(eq(cartoes.userId, userId), ilike(cartoes.status, "inativo")),
with: {
conta: {
columns: {

View File

@@ -0,0 +1,19 @@
import { CardsPage } from "@/components/cartoes/cards-page";
import { getUserId } from "@/lib/auth/server";
import { fetchInativosForUser } from "../data";
export default async function InativosPage() {
const userId = await getUserId();
const { cards, accounts, logoOptions } = await fetchInativosForUser(userId);
return (
<main className="flex flex-col items-start gap-6">
<CardsPage
cards={cards}
accounts={accounts}
logoOptions={logoOptions}
isInativos={true}
/>
</main>
);
}

View File

@@ -1,5 +1,5 @@
import PageDescription from "@/components/page-description";
import { RiBankCardLine } from "@remixicon/react";
import { RiBankCard2Line } from "@remixicon/react";
export const metadata = {
title: "Cartões | Opensheets",
@@ -13,7 +13,7 @@ export default function RootLayout({
return (
<section className="space-y-6 px-6">
<PageDescription
icon={<RiBankCardLine />}
icon={<RiBankCard2Line />}
title="Cartões"
subtitle="Acompanhe todas os cartões do mês selecionado incluindo faturas, limites
e transações previstas. Use o seletor abaixo para navegar pelos meses e

View File

@@ -3,7 +3,7 @@ import { INITIAL_BALANCE_NOTE } from "@/lib/accounts/constants";
import { db } from "@/lib/db";
import { loadLogoOptions } from "@/lib/logo/options";
import { PAGADOR_ROLE_ADMIN } from "@/lib/pagadores/constants";
import { and, eq, sql } from "drizzle-orm";
import { and, eq, ilike, not, sql } from "drizzle-orm";
export type AccountData = {
id: string;
@@ -58,6 +58,83 @@ export async function fetchAccountsForUser(
.where(
and(
eq(contas.userId, userId),
not(ilike(contas.status, "inativa")),
sql`(${lancamentos.id} IS NULL OR ${pagadores.role} = ${PAGADOR_ROLE_ADMIN})`
)
)
.groupBy(
contas.id,
contas.name,
contas.accountType,
contas.status,
contas.note,
contas.logo,
contas.initialBalance,
contas.excludeFromBalance,
contas.excludeInitialBalanceFromIncome
),
loadLogoOptions(),
]);
const accounts = accountRows.map((account) => ({
id: account.id,
name: account.name,
accountType: account.accountType,
status: account.status,
note: account.note,
logo: account.logo,
initialBalance: Number(account.initialBalance ?? 0),
balance:
Number(account.initialBalance ?? 0) +
Number(account.balanceMovements ?? 0),
excludeFromBalance: account.excludeFromBalance,
excludeInitialBalanceFromIncome: account.excludeInitialBalanceFromIncome,
}));
return { accounts, logoOptions };
}
export async function fetchInativosForUser(
userId: string
): Promise<{ accounts: AccountData[]; logoOptions: LogoOption[] }> {
const [accountRows, logoOptions] = await Promise.all([
db
.select({
id: contas.id,
name: contas.name,
accountType: contas.accountType,
status: contas.status,
note: contas.note,
logo: contas.logo,
initialBalance: contas.initialBalance,
excludeFromBalance: contas.excludeFromBalance,
excludeInitialBalanceFromIncome: contas.excludeInitialBalanceFromIncome,
balanceMovements: sql<number>`
coalesce(
sum(
case
when ${lancamentos.note} = ${INITIAL_BALANCE_NOTE} then 0
else ${lancamentos.amount}
end
),
0
)
`,
})
.from(contas)
.leftJoin(
lancamentos,
and(
eq(lancamentos.contaId, contas.id),
eq(lancamentos.userId, userId),
eq(lancamentos.isSettled, true)
)
)
.leftJoin(pagadores, eq(lancamentos.pagadorId, pagadores.id))
.where(
and(
eq(contas.userId, userId),
ilike(contas.status, "inativa"),
sql`(${lancamentos.id} IS NULL OR ${pagadores.role} = ${PAGADOR_ROLE_ADMIN})`
)
)

View File

@@ -0,0 +1,14 @@
import { AccountsPage } from "@/components/contas/accounts-page";
import { getUserId } from "@/lib/auth/server";
import { fetchInativosForUser } from "../data";
export default async function InativosPage() {
const userId = await getUserId();
const { accounts, logoOptions } = await fetchInativosForUser(userId);
return (
<main className="flex flex-col items-start gap-6">
<AccountsPage accounts={accounts} logoOptions={logoOptions} isInativos={true} />
</main>
);
}

View File

@@ -33,14 +33,24 @@ export const PROVIDERS = {
* Lista de modelos de IA disponíveis para análise de insights
*/
export const AVAILABLE_MODELS = [
// OpenAI Models (5)
{ id: "gpt-5.1", name: "GPT-5.1 ", provider: "openai" as const },
{ id: "gpt-5.1-chat", name: "GPT-5.1 Chat", provider: "openai" as const },
{ id: "gpt-5", name: "GPT-5", provider: "openai" as const },
{ id: "gpt-5-mini", name: "GPT-5 Mini", provider: "openai" as const },
{ id: "gpt-5-nano", name: "GPT-5 Nano", provider: "openai" as const },
// OpenAI Models - GPT-5.2 Family (Latest)
{ id: "gpt-5.2", name: "GPT-5.2", provider: "openai" as const },
{
id: "gpt-5.2-instant",
name: "GPT-5.2 Instant",
provider: "openai" as const,
},
{
id: "gpt-5.2-thinking",
name: "GPT-5.2 Thinking",
provider: "openai" as const,
},
// Anthropic Models (5)
// OpenAI Models - GPT-5 Family
{ id: "gpt-5", name: "GPT-5", provider: "openai" as const },
{ id: "gpt-5-instant", name: "GPT-5 Instant", provider: "openai" as const },
// Anthropic Models - Claude 4.5
{
id: "claude-4.5-haiku",
name: "Claude 4.5 Haiku",
@@ -57,20 +67,27 @@ export const AVAILABLE_MODELS = [
provider: "anthropic" as const,
},
// Google Models (5)
// Google Models - Gemini 3 (Latest)
{
id: "gemini-2.5-pro",
name: "Gemini 2.5 Pro",
id: "gemini-3-flash-preview",
name: "Gemini 3 Flash",
provider: "google" as const,
},
{
id: "gemini-2.5-flash",
name: "Gemini 2.5 Flash",
id: "gemini-3-pro-preview",
name: "Gemini 3 Pro",
provider: "google" as const,
},
// Google Models - Gemini 2.0
{
id: "gemini-2.0-flash",
name: "Gemini 2.0 Flash",
provider: "google" as const,
},
] as const;
export const DEFAULT_MODEL = "gpt-5.1";
export const DEFAULT_MODEL = "gpt-5.2";
export const DEFAULT_PROVIDER = "openai";
/**

View File

@@ -1,4 +1,4 @@
import { lancamentos, pagadorShares, user as usersTable } from "@/db/schema";
import { lancamentos, pagadorShares, user as usersTable, contas, cartoes, categorias, pagadores } from "@/db/schema";
import { db } from "@/lib/db";
import { and, desc, eq, type SQL } from "drizzle-orm";
@@ -37,17 +37,54 @@ export async function fetchPagadorShares(
}));
}
export async function fetchPagadorLancamentos(filters: SQL[]) {
const lancamentoRows = await db.query.lancamentos.findMany({
where: and(...filters),
with: {
pagador: true,
conta: true,
cartao: true,
categoria: true,
export async function fetchCurrentUserShare(
pagadorId: string,
userId: string
): Promise<{ id: string; createdAt: string } | null> {
const shareRow = await db.query.pagadorShares.findFirst({
columns: {
id: true,
createdAt: true,
},
orderBy: desc(lancamentos.purchaseDate),
where: and(
eq(pagadorShares.pagadorId, pagadorId),
eq(pagadorShares.sharedWithUserId, userId)
),
});
return lancamentoRows;
if (!shareRow) {
return null;
}
return {
id: shareRow.id,
createdAt: shareRow.createdAt?.toISOString() ?? new Date().toISOString(),
};
}
export async function fetchPagadorLancamentos(filters: SQL[]) {
const lancamentoRows = await db
.select({
lancamento: lancamentos,
pagador: pagadores,
conta: contas,
cartao: cartoes,
categoria: categorias,
})
.from(lancamentos)
.leftJoin(pagadores, eq(lancamentos.pagadorId, pagadores.id))
.leftJoin(contas, eq(lancamentos.contaId, contas.id))
.leftJoin(cartoes, eq(lancamentos.cartaoId, cartoes.id))
.leftJoin(categorias, eq(lancamentos.categoriaId, categorias.id))
.where(and(...filters))
.orderBy(desc(lancamentos.purchaseDate), desc(lancamentos.createdAt));
// Transformar resultado para o formato esperado
return lancamentoRows.map((row: any) => ({
...row.lancamento,
pagador: row.pagador,
conta: row.conta,
cartao: row.cartao,
categoria: row.categoria,
}));
}

View File

@@ -5,6 +5,7 @@ import { PagadorInfoCard } from "@/components/pagadores/details/pagador-info-car
import { PagadorMonthlySummaryCard } from "@/components/pagadores/details/pagador-monthly-summary-card";
import { PagadorBoletoCard } from "@/components/pagadores/details/pagador-payment-method-cards";
import { PagadorSharingCard } from "@/components/pagadores/details/pagador-sharing-card";
import { PagadorLeaveShareCard } from "@/components/pagadores/details/pagador-leave-share-card";
import { LancamentosPage as LancamentosSection } from "@/components/lancamentos/page/lancamentos-page";
import type {
ContaCartaoFilterOption,
@@ -39,7 +40,7 @@ import {
fetchPagadorMonthlyBreakdown,
} from "@/lib/pagadores/details";
import { notFound } from "next/navigation";
import { fetchPagadorLancamentos, fetchPagadorShares } from "./data";
import { fetchPagadorLancamentos, fetchPagadorShares, fetchCurrentUserShare } from "./data";
type PageSearchParams = Promise<ResolvedSearchParams>;
@@ -92,9 +93,13 @@ export default async function Page({ params, searchParams }: PageProps) {
} = parsePeriodParam(periodoParamRaw);
const periodLabel = `${capitalize(monthName)} de ${year}`;
const allSearchFilters = extractLancamentoSearchFilters(resolvedSearchParams);
const searchFilters = canEdit
? extractLancamentoSearchFilters(resolvedSearchParams)
: EMPTY_FILTERS;
? allSearchFilters
: {
...EMPTY_FILTERS,
searchFilter: allSearchFilters.searchFilter, // Permitir busca mesmo em modo read-only
};
let filterSources: Awaited<
ReturnType<typeof fetchLancamentoFilterSources>
@@ -133,6 +138,10 @@ export default async function Page({ params, searchParams }: PageProps) {
? fetchPagadorShares(pagador.id)
: Promise.resolve([]);
const currentUserSharePromise = !canEdit
? fetchCurrentUserShare(pagador.id, userId)
: Promise.resolve(null);
const [
lancamentoRows,
monthlyBreakdown,
@@ -140,6 +149,7 @@ export default async function Page({ params, searchParams }: PageProps) {
cardUsage,
boletoStats,
shareRows,
currentUserShare,
estabelecimentos,
] = await Promise.all([
fetchPagadorLancamentos(filters),
@@ -164,6 +174,7 @@ export default async function Page({ params, searchParams }: PageProps) {
period: selectedPeriod,
}),
sharesPromise,
currentUserSharePromise,
getRecentEstablishmentsAction(),
]);
@@ -281,6 +292,13 @@ export default async function Page({ params, searchParams }: PageProps) {
shares={pagadorSharesData}
/>
) : null}
{!canEdit && currentUserShare ? (
<PagadorLeaveShareCard
shareId={currentUserShare.id}
pagadorName={pagadorData.name}
createdAt={currentUserShare.createdAt}
/>
) : null}
</TabsContent>
<TabsContent value="painel" className="space-y-4">

View File

@@ -6,7 +6,7 @@ import { Card, CardContent } from "@/components/ui/card";
import { getOptionalUserSession } from "@/lib/auth/server";
import {
RiArrowRightSLine,
RiBankCardLine,
RiBankCard2Line,
RiBarChartBoxLine,
RiCalendarLine,
RiCodeSSlashLine,
@@ -15,7 +15,6 @@ import {
RiGithubFill,
RiLineChartLine,
RiLockLine,
RiMoneyDollarCircleLine,
RiPieChartLine,
RiShieldCheckLine,
RiTimeLine,
@@ -234,9 +233,9 @@ export default async function Page() {
Parcelamentos avançados
</h3>
<p className="text-sm text-muted-foreground">
Controle completo de compras parceladas. Antecipe parcelas
com cálculo automático de desconto. Veja análise
consolidada de todas as parcelas em aberto.
Controle completo de compras parceladas. Antecipe
parcelas com cálculo automático de desconto. Veja
análise consolidada de todas as parcelas em aberto.
</p>
</div>
</div>
@@ -254,9 +253,9 @@ export default async function Page() {
Insights com IA
</h3>
<p className="text-sm text-muted-foreground">
Análises financeiras geradas por IA (Claude, GPT, Gemini).
Insights personalizados sobre seus padrões de gastos e
recomendações inteligentes.
Análises financeiras geradas por IA (Claude, GPT,
Gemini). Insights personalizados sobre seus padrões de
gastos e recomendações inteligentes.
</p>
</div>
</div>
@@ -287,16 +286,16 @@ export default async function Page() {
<CardContent className="pt-6">
<div className="flex flex-col gap-4">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<RiBankCardLine size={24} className="text-primary" />
<RiBankCard2Line size={24} className="text-primary" />
</div>
<div>
<h3 className="font-semibold text-lg mb-2">
Faturas de cartão
</h3>
<p className="text-sm text-muted-foreground">
Cadastre seus cartões e acompanhe as faturas por período.
Veja o que ainda não foi fechado. Controle limites,
vencimentos e fechamentos.
Cadastre seus cartões e acompanhe as faturas por
período. Veja o que ainda não foi fechado. Controle
limites, vencimentos e fechamentos.
</p>
</div>
</div>
@@ -315,8 +314,8 @@ export default async function Page() {
</h3>
<p className="text-sm text-muted-foreground">
Compartilhe pagadores com permissões granulares (admin/
viewer). Notificações automáticas por e-mail. Colabore em
lançamentos compartilhados.
viewer). Notificações automáticas por e-mail. Colabore
em lançamentos compartilhados.
</p>
</div>
</div>
@@ -334,9 +333,9 @@ export default async function Page() {
Categorias e orçamentos
</h3>
<p className="text-sm text-muted-foreground">
Crie categorias personalizadas. Defina orçamentos mensais
e acompanhe o quanto gastou vs. planejado com indicadores
visuais.
Crie categorias personalizadas. Defina orçamentos
mensais e acompanhe o quanto gastou vs. planejado com
indicadores visuais.
</p>
</div>
</div>
@@ -394,9 +393,9 @@ export default async function Page() {
Importação em massa
</h3>
<p className="text-sm text-muted-foreground">
Cole múltiplos lançamentos de uma vez. Economize tempo ao
registrar várias transações. Formatação inteligente para
facilitar a entrada de dados.
Cole múltiplos lançamentos de uma vez. Economize tempo
ao registrar várias transações. Formatação inteligente
para facilitar a entrada de dados.
</p>
</div>
</div>
@@ -434,9 +433,9 @@ export default async function Page() {
Performance otimizada
</h3>
<p className="text-sm text-muted-foreground">
Dashboard carrega em ~200-500ms com 18+ queries paralelas.
Índices otimizados. Type-safe em toda codebase. Isolamento
completo de dados por usuário.
Dashboard carrega em ~200-500ms com 18+ queries
paralelas. Índices otimizados. Type-safe em toda
codebase. Isolamento completo de dados por usuário.
</p>
</div>
</div>

View File

@@ -5,7 +5,7 @@ import { ConfirmActionDialog } from "@/components/confirm-action-dialog";
import { EmptyState } from "@/components/empty-state";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { RiAddCircleLine, RiBankCardLine } from "@remixicon/react";
import { RiAddCircleLine, RiBankCard2Line } from "@remixicon/react";
import { useRouter } from "next/navigation";
import { useCallback, useMemo, useState } from "react";
import { toast } from "sonner";
@@ -21,9 +21,15 @@ interface CardsPageProps {
cards: Card[];
accounts: AccountOption[];
logoOptions: string[];
isInativos?: boolean;
}
export function CardsPage({ cards, accounts, logoOptions }: CardsPageProps) {
export function CardsPage({
cards,
accounts,
logoOptions,
isInativos = false,
}: CardsPageProps) {
const router = useRouter();
const [editOpen, setEditOpen] = useState(false);
const [selectedCard, setSelectedCard] = useState<Card | null>(null);
@@ -102,19 +108,21 @@ export function CardsPage({ cards, accounts, logoOptions }: CardsPageProps) {
return (
<>
<div className="flex w-full flex-col gap-6">
<div className="flex justify-start">
<CardDialog
mode="create"
accounts={accounts}
logoOptions={logoOptions}
trigger={
<Button>
<RiAddCircleLine className="size-4" />
Novo cartão
</Button>
}
/>
</div>
{!isInativos && (
<div className="flex justify-start">
<CardDialog
mode="create"
accounts={accounts}
logoOptions={logoOptions}
trigger={
<Button>
<RiAddCircleLine className="size-4" />
Novo cartão
</Button>
}
/>
</div>
)}
{hasCards ? (
<div className="flex flex-wrap gap-4">
@@ -141,9 +149,17 @@ export function CardsPage({ cards, accounts, logoOptions }: CardsPageProps) {
) : (
<Card className="flex w-full items-center justify-center py-12">
<EmptyState
media={<RiBankCardLine className="size-6 text-primary" />}
title="Nenhum cartão cadastrado"
description="Adicione seu primeiro cartão para acompanhar limites e faturas com mais controle."
media={<RiBankCard2Line className="size-6 text-primary" />}
title={
isInativos
? "Nenhum cartão inativo"
: "Nenhum cartão cadastrado"
}
description={
isInativos
? "Os cartões inativos aparecerão aqui."
: "Adicione seu primeiro cartão para acompanhar limites e faturas com mais controle."
}
/>
</Card>
)}

View File

@@ -19,6 +19,7 @@ import type { Account } from "./types";
interface AccountsPageProps {
accounts: Account[];
logoOptions: string[];
isInativos?: boolean;
}
const resolveLogoSrc = (logo: string | null) => {
@@ -30,7 +31,7 @@ const resolveLogoSrc = (logo: string | null) => {
return `/logos/${fileName}`;
};
export function AccountsPage({ accounts, logoOptions }: AccountsPageProps) {
export function AccountsPage({ accounts, logoOptions, isInativos = false }: AccountsPageProps) {
const router = useRouter();
const [editOpen, setEditOpen] = useState(false);
const [selectedAccount, setSelectedAccount] = useState<Account | null>(null);
@@ -169,8 +170,8 @@ export function AccountsPage({ accounts, logoOptions }: AccountsPageProps) {
<Card className="flex min-h-[50vh] w-full items-center justify-center py-12">
<EmptyState
media={<RiBankLine className="size-6 text-primary" />}
title="Nenhuma conta cadastrada"
description="Cadastre sua primeira conta para começar a organizar os lançamentos."
title={isInativos ? "Nenhuma conta inativa" : "Nenhuma conta cadastrada"}
description={isInativos ? "Não há contas inativas no momento." : "Cadastre sua primeira conta para começar a organizar os lançamentos."}
/>
</Card>
)}

View File

@@ -1,7 +1,7 @@
import MoneyValues from "@/components/money-values";
import type { PaymentMethodsData } from "@/lib/dashboard/payments/payment-methods";
import { getPaymentMethodIcon } from "@/lib/utils/icons";
import { RiBankCardLine, RiMoneyDollarCircleLine } from "@remixicon/react";
import { RiBankCard2Line, RiMoneyDollarCircleLine } from "@remixicon/react";
import { Progress } from "../ui/progress";
import { WidgetEmptyState } from "../widget-empty-state";
@@ -28,7 +28,7 @@ const resolveIcon = (paymentMethod: string | null | undefined) => {
return icon;
}
return <RiBankCardLine className="size-5" aria-hidden />;
return <RiBankCard2Line className="size-5" aria-hidden />;
};
export function PaymentMethodsWidget({ data }: PaymentMethodsWidgetProps) {

View File

@@ -130,6 +130,7 @@ interface LancamentosFiltersProps {
contaCartaoOptions: ContaCartaoFilterOption[];
className?: string;
exportButton?: ReactNode;
hideAdvancedFilters?: boolean;
}
export function LancamentosFilters({
@@ -138,6 +139,7 @@ export function LancamentosFilters({
contaCartaoOptions,
className,
exportButton,
hideAdvancedFilters = false,
}: LancamentosFiltersProps) {
const router = useRouter();
const pathname = usePathname();
@@ -277,22 +279,31 @@ export function LancamentosFilters({
return (
<div className={cn("flex flex-wrap items-center gap-2", className)}>
<Input
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Buscar"
aria-label="Buscar lançamentos"
className="w-[250px] text-sm border-dashed"
/>
{exportButton}
<Drawer direction="right" open={drawerOpen} onOpenChange={setDrawerOpen}>
<DrawerTrigger asChild>
<Button
variant="outline"
className="text-sm border-dashed relative"
aria-label="Abrir filtros"
>
<RiFilter3Line className="size-4" />
Filtros
{hasActiveFilters && (
<span className="absolute -top-1 -right-1 size-2 rounded-full bg-primary" />
)}
</Button>
</DrawerTrigger>
{!hideAdvancedFilters && (
<Drawer direction="right" open={drawerOpen} onOpenChange={setDrawerOpen}>
<DrawerTrigger asChild>
<Button
variant="outline"
className="text-sm border-dashed relative"
aria-label="Abrir filtros"
>
<RiFilter3Line className="size-4" />
Filtros
{hasActiveFilters && (
<span className="absolute -top-1 -right-1 size-2 rounded-full bg-primary" />
)}
</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Filtros</DrawerTitle>
@@ -319,7 +330,9 @@ export function LancamentosFilters({
</div>
<div className="space-y-2">
<label className="text-sm font-medium">Condição</label>
<label className="text-sm font-medium">
Condição de Lançamento
</label>
<FilterSelect
param="condicao"
placeholder="Todas"
@@ -335,7 +348,7 @@ export function LancamentosFilters({
</div>
<div className="space-y-2">
<label className="text-sm font-medium">Pagamento</label>
<label className="text-sm font-medium">Forma de Pagamento</label>
<FilterSelect
param="pagamento"
placeholder="Todos"
@@ -532,15 +545,8 @@ export function LancamentosFilters({
</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
<Input
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Buscar"
aria-label="Buscar lançamentos"
className="w-[250px] text-sm border-dashed"
/>
</Drawer>
)}
</div>
);
}

View File

@@ -734,9 +734,8 @@ export function LancamentosTable({
0
);
// Check if all data belongs to current user to determine if filters should be shown
const isOwnData = data.every((item) => item.userId === currentUserId);
const shouldShowFilters = showFilters && isOwnData;
// Check if there's any data from other users
const hasOtherUserData = data.some((item) => item.userId !== currentUserId);
const handleBulkDelete = () => {
if (onBulkDelete && selectedCount > 0) {
@@ -755,7 +754,7 @@ export function LancamentosTable({
};
const showTopControls =
Boolean(onCreate) || Boolean(onMassAdd) || shouldShowFilters;
Boolean(onCreate) || Boolean(onMassAdd) || showFilters;
return (
<TooltipProvider>
@@ -791,15 +790,16 @@ export function LancamentosTable({
) : null}
</div>
) : (
<span className={shouldShowFilters ? "hidden sm:block" : ""} />
<span className={showFilters ? "hidden sm:block" : ""} />
)}
{shouldShowFilters ? (
{showFilters ? (
<LancamentosFilters
pagadorOptions={pagadorFilterOptions}
categoriaOptions={categoriaFilterOptions}
contaCartaoOptions={contaCartaoFilterOptions}
className="w-full lg:flex-1 lg:justify-end"
hideAdvancedFilters={hasOtherUserData}
exportButton={
selectedPeriod ? (
<LancamentosExport

View File

@@ -2,7 +2,7 @@ import MoneyValues from "@/components/money-values";
import { WidgetEmptyState } from "@/components/widget-empty-state";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import type { PagadorCardUsageItem } from "@/lib/pagadores/details";
import { RiBankCardLine } from "@remixicon/react";
import { RiBankCard2Line } from "@remixicon/react";
import Image from "next/image";
const resolveLogoPath = (logo?: string | null) => {
@@ -36,7 +36,7 @@ export function PagadorCardUsageCard({ items }: PagadorCardUsageCardProps) {
<CardContent className="space-y-3 pt-2">
{items.length === 0 ? (
<WidgetEmptyState
icon={<RiBankCardLine className="size-6 text-muted-foreground" />}
icon={<RiBankCard2Line className="size-6 text-muted-foreground" />}
title="Nenhum lançamento com cartão de crédito"
description="Quando houver despesas registradas com cartão, elas aparecerão aqui."
/>

View File

@@ -0,0 +1,114 @@
"use client";
import { deletePagadorShareAction } from "@/app/(dashboard)/pagadores/actions";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { RiLogoutBoxLine } from "@remixicon/react";
import { useRouter } from "next/navigation";
import { useState, useTransition } from "react";
import { toast } from "sonner";
interface PagadorLeaveShareCardProps {
shareId: string;
pagadorName: string;
createdAt: string;
}
export function PagadorLeaveShareCard({
shareId,
pagadorName,
createdAt,
}: PagadorLeaveShareCardProps) {
const router = useRouter();
const [isPending, startTransition] = useTransition();
const [showConfirm, setShowConfirm] = useState(false);
const handleLeave = () => {
startTransition(async () => {
const result = await deletePagadorShareAction({ shareId });
if (!result.success) {
toast.error(result.error);
return;
}
toast.success("Você saiu do compartilhamento.");
router.push("/pagadores");
});
};
const formattedDate = new Date(createdAt).toLocaleDateString("pt-BR", {
day: "2-digit",
month: "long",
year: "numeric",
});
return (
<Card className="border">
<CardHeader>
<CardTitle className="text-base font-semibold">
Acesso Compartilhado
</CardTitle>
<p className="text-sm text-muted-foreground">
Você tem acesso somente leitura aos dados de{" "}
<strong>{pagadorName}</strong>.
</p>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex flex-col gap-2 rounded-lg border border-dashed p-4 text-sm">
<span className="text-xs font-semibold uppercase text-muted-foreground/80">
Informações do compartilhamento
</span>
<div className="flex flex-col gap-1">
<p className="text-sm">
<span className="text-muted-foreground">Acesso desde:</span>{" "}
<strong>{formattedDate}</strong>
</p>
<p className="text-sm text-muted-foreground">
Você pode visualizar os lançamentos, mas não pode criar ou editar.
</p>
</div>
</div>
{!showConfirm ? (
<Button
type="button"
variant="outline"
onClick={() => setShowConfirm(true)}
className="w-full"
>
<RiLogoutBoxLine className="size-4" />
Sair do compartilhamento
</Button>
) : (
<div className="space-y-2">
<p className="text-sm font-medium text-destructive">
Tem certeza que deseja sair? Você perderá o acesso aos dados de{" "}
{pagadorName}.
</p>
<div className="flex gap-2">
<Button
type="button"
variant="outline"
onClick={() => setShowConfirm(false)}
disabled={isPending}
className="flex-1"
>
Cancelar
</Button>
<Button
type="button"
variant="destructive"
onClick={handleLeave}
disabled={isPending}
className="flex-1"
>
{isPending ? "Saindo..." : "Confirmar saída"}
</Button>
</div>
</div>
)}
</CardContent>
</Card>
);
}

View File

@@ -1,46 +1,46 @@
"use client";
import { formatCurrency, formatPercentageChange } from "@/lib/relatorios/utils";
import { RiArrowDownLine, RiArrowUpLine } from "@remixicon/react";
import { cn } from "@/lib/utils/ui";
import { RiArrowDownLine, RiArrowUpLine } from "@remixicon/react";
interface CategoryCellProps {
value: number;
previousValue: number;
categoryType: "despesa" | "receita";
isFirstMonth: boolean;
value: number;
previousValue: number;
categoryType: "despesa" | "receita";
isFirstMonth: boolean;
}
export function CategoryCell({
value,
previousValue,
categoryType,
isFirstMonth,
value,
previousValue,
categoryType,
isFirstMonth,
}: CategoryCellProps) {
const percentageChange =
!isFirstMonth && previousValue !== 0
? ((value - previousValue) / previousValue) * 100
: null;
const percentageChange =
!isFirstMonth && previousValue !== 0
? ((value - previousValue) / previousValue) * 100
: null;
const isIncrease = percentageChange !== null && percentageChange > 0;
const isDecrease = percentageChange !== null && percentageChange < 0;
const isIncrease = percentageChange !== null && percentageChange > 0;
const isDecrease = percentageChange !== null && percentageChange < 0;
return (
<div className="flex flex-col items-end gap-0.5">
<span className="font-medium">{formatCurrency(value)}</span>
{!isFirstMonth && percentageChange !== null && (
<div
className={cn(
"flex items-center gap-0.5 text-xs",
isIncrease && "text-red-600 dark:text-red-400",
isDecrease && "text-green-600 dark:text-green-400"
)}
>
{isIncrease && <RiArrowUpLine className="h-3 w-3" />}
{isDecrease && <RiArrowDownLine className="h-3 w-3" />}
<span>{formatPercentageChange(percentageChange)}</span>
</div>
)}
return (
<div className="flex flex-col items-end gap-0.5 min-h-9">
<span className="font-medium">{formatCurrency(value)}</span>
{!isFirstMonth && percentageChange !== null && (
<div
className={cn(
"flex items-center gap-0.5 text-xs",
isIncrease && "text-red-600 dark:text-red-400",
isDecrease && "text-green-600 dark:text-green-400"
)}
>
{isIncrease && <RiArrowUpLine className="h-3 w-3" />}
{isDecrease && <RiArrowDownLine className="h-3 w-3" />}
<span>{formatPercentageChange(percentageChange)}</span>
</div>
);
)}
</div>
);
}

View File

@@ -9,13 +9,12 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table";
import { getIconComponent } from "@/lib/utils/icons";
import { formatPeriodLabel } from "@/lib/relatorios/utils";
import type { CategoryReportData } from "@/lib/relatorios/types";
import { CategoryCell } from "./category-cell";
import { formatCurrency } from "@/lib/relatorios/utils";
import { Card } from "../ui/card";
import { formatCurrency, formatPeriodLabel } from "@/lib/relatorios/utils";
import { getIconComponent } from "@/lib/utils/icons";
import DotIcon from "../dot-icon";
import { Card } from "../ui/card";
import { CategoryCell } from "./category-cell";
interface CategoryReportTableProps {
data: CategoryReportData;
@@ -88,16 +87,19 @@ export function CategoryReportTable({ data }: CategoryReportTableProps) {
<TableFooter>
<TableRow>
<TableCell>Total Geral</TableCell>
<TableCell className="min-h-[2.5rem]">Total Geral</TableCell>
{periods.map((period) => {
const periodTotal = totals.get(period) ?? 0;
return (
<TableCell key={period} className="text-right font-semibold">
<TableCell
key={period}
className="text-right font-semibold min-h-8"
>
{formatCurrency(periodTotal)}
</TableCell>
);
})}
<TableCell className="text-right font-semibold">
<TableCell className="text-right font-semibold min-h-8">
{formatCurrency(grandTotal)}
</TableCell>
</TableRow>

View File

@@ -1,17 +1,19 @@
import {
RiArchiveLine,
RiArrowLeftRightLine,
RiBankCardLine,
RiBankCard2Line,
RiBankLine,
RiCalendarEventLine,
RiDashboardLine,
RiFileChartLine,
RiFundsLine,
RiGroupLine,
RiNoCreditCardLine,
RiPriceTag3Line,
RiSettingsLine,
RiSparklingLine,
RiTodoLine,
RiEyeOffLine,
type RemixiconComponentType,
} from "@remixicon/react";
@@ -98,12 +100,28 @@ export function createSidebarNavData(pagadores: PagadorLike[]): SidebarNavData {
{
title: "Cartões",
url: "/cartoes",
icon: RiBankCardLine,
icon: RiBankCard2Line,
items: [
{
title: "Inativos",
url: "/cartoes/inativos",
key: "cartoes-inativos",
icon: RiNoCreditCardLine,
},
],
},
{
title: "Contas",
url: "/contas",
icon: RiBankLine,
items: [
{
title: "Inativas",
url: "/contas/inativos",
key: "contas-inativos",
icon: RiEyeOffLine,
},
],
},
{
title: "Orçamentos",

View File

@@ -21,7 +21,7 @@ import {
import { getAvatarSrc } from "@/lib/pagadores/utils";
import {
RiArrowRightSLine,
RiStackshareLine,
RiUserSharedLine,
type RemixiconComponentType,
} from "@remixicon/react";
import Link from "next/link";
@@ -182,7 +182,7 @@ export function NavMain({ sections }: { sections: NavSection[] }) {
) : null}
<span>{subItem.title}</span>
{subItem.isShared ? (
<RiStackshareLine className="size-3.5 text-muted-foreground" />
<RiUserSharedLine className="size-3.5 text-muted-foreground" />
) : null}
</Link>
</SidebarMenuSubButton>

View File

@@ -15,7 +15,7 @@ export const CATEGORY_ICON_OPTIONS: CategoryIconOption[] = [
{ label: "Dinheiro", value: "RiMoneyDollarCircleLine" },
{ label: "Carteira", value: "RiWallet3Line" },
{ label: "Carteira 2", value: "RiWalletLine" },
{ label: "Cartão", value: "RiBankCardLine" },
{ label: "Cartão", value: "RiBankCard2Line" },
{ label: "Banco", value: "RiBankLine" },
{ label: "Moedas", value: "RiHandCoinLine" },
{ label: "Gráfico", value: "RiLineChartLine" },

View File

@@ -78,6 +78,19 @@ export function buildLancamentoInitialState(
? getTodayDateString()
: "");
// Calcular o valor correto para importação de parcelados
let amountValue = "";
if (typeof lancamento?.amount === "number") {
let baseAmount = Math.abs(lancamento.amount);
// Se está importando e é parcelado, usar o valor total (parcela * quantidade)
if (isImporting && lancamento.condition === "Parcelado" && lancamento.installmentCount) {
baseAmount = baseAmount * lancamento.installmentCount;
}
amountValue = (Math.round(baseAmount * 100) / 100).toFixed(2);
}
return {
purchaseDate,
period:
@@ -87,10 +100,7 @@ export function buildLancamentoInitialState(
name: lancamento?.name ?? "",
transactionType:
lancamento?.transactionType ?? LANCAMENTO_TRANSACTION_TYPES[0],
amount:
typeof lancamento?.amount === "number"
? (Math.round(Math.abs(lancamento.amount) * 100) / 100).toFixed(2)
: "",
amount: amountValue,
condition: lancamento?.condition ?? LANCAMENTO_CONDITIONS[0],
paymentMethod,
pagadorId: fallbackPagadorId ?? undefined,

View File

@@ -15,7 +15,7 @@ import {
} from "@/lib/lancamentos/constants";
import { PAGADOR_ROLE_ADMIN, PAGADOR_ROLE_TERCEIRO } from "@/lib/pagadores/constants";
import type { SQL } from "drizzle-orm";
import { eq, ilike, or } from "drizzle-orm";
import { and, eq, ilike, isNotNull, or } from "drizzle-orm";
type PagadorRow = typeof pagadores.$inferSelect;
type ContaRow = typeof contas.$inferSelect;
@@ -370,8 +370,12 @@ export const buildLancamentoWhere = ({
where.push(
or(
ilike(lancamentos.name, searchPattern),
ilike(lancamentos.note, searchPattern)
)
ilike(lancamentos.note, searchPattern),
ilike(lancamentos.paymentMethod, searchPattern),
ilike(lancamentos.condition, searchPattern),
and(isNotNull(contas.name), ilike(contas.name, searchPattern)),
and(isNotNull(cartoes.name), ilike(cartoes.name, searchPattern))
)!
);
}

View File

@@ -49,14 +49,16 @@ export const getPaymentMethodIcon = (paymentMethod: string): ReactNode => {
<RemixIcons.RiMoneyDollarCircleLine className={ICON_CLASS} aria-hidden />
),
cartaodecredito: (
<RemixIcons.RiBankCardLine className={ICON_CLASS} aria-hidden />
<RemixIcons.RiBankCard2Line className={ICON_CLASS} aria-hidden />
),
cartaodedebito: (
<RemixIcons.RiBankCardLine className={ICON_CLASS} aria-hidden />
<RemixIcons.RiBankCard2Line className={ICON_CLASS} aria-hidden />
),
debito: <RemixIcons.RiBankCardLine className={ICON_CLASS} aria-hidden />,
debito: <RemixIcons.RiBankCard2Line className={ICON_CLASS} aria-hidden />,
prepagovrva: <RemixIcons.RiCouponLine className={ICON_CLASS} aria-hidden />,
transferenciabancaria: <RemixIcons.RiExchangeLine className={ICON_CLASS} aria-hidden />,
transferenciabancaria: (
<RemixIcons.RiExchangeLine className={ICON_CLASS} aria-hidden />
),
};
return registry[key] ?? null;

View File

@@ -27,9 +27,9 @@
"docker:rebuild": "docker compose up --build --force-recreate"
},
"dependencies": {
"@ai-sdk/anthropic": "^3.0.2",
"@ai-sdk/google": "^3.0.2",
"@ai-sdk/openai": "^3.0.2",
"@ai-sdk/anthropic": "^3.0.9",
"@ai-sdk/google": "^3.0.6",
"@ai-sdk/openai": "^3.0.7",
"@openrouter/ai-sdk-provider": "^1.5.4",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-alert-dialog": "1.1.15",
@@ -56,7 +56,7 @@
"@tanstack/react-table": "8.21.3",
"@vercel/analytics": "^1.6.1",
"@vercel/speed-insights": "^1.3.1",
"ai": "^6.0.7",
"ai": "^6.0.27",
"babel-plugin-react-compiler": "^1.0.0",
"better-auth": "1.4.10",
"class-variance-authority": "0.7.1",
@@ -66,7 +66,7 @@
"drizzle-orm": "0.45.1",
"jspdf": "^4.0.0",
"jspdf-autotable": "^5.0.7",
"motion": "^12.23.27",
"motion": "^12.25.0",
"next": "16.1.1",
"next-themes": "0.4.6",
"pg": "8.16.3",
@@ -74,7 +74,7 @@
"react-day-picker": "^9.13.0",
"react-dom": "19.2.3",
"recharts": "3.6.0",
"resend": "^6.6.0",
"resend": "^6.7.0",
"sonner": "2.0.7",
"tailwind-merge": "3.4.0",
"vaul": "1.1.2",
@@ -88,7 +88,7 @@
"@types/pg": "^8.16.0",
"@types/react": "19.2.7",
"@types/react-dom": "19.2.3",
"baseline-browser-mapping": "^2.9.11",
"baseline-browser-mapping": "^2.9.14",
"depcheck": "^1.4.7",
"dotenv": "^17.2.3",
"drizzle-kit": "0.31.8",

431
pnpm-lock.yaml generated
View File

@@ -9,17 +9,17 @@ importers:
.:
dependencies:
'@ai-sdk/anthropic':
specifier: ^3.0.2
version: 3.0.2(zod@4.3.5)
specifier: ^3.0.9
version: 3.0.9(zod@4.3.5)
'@ai-sdk/google':
specifier: ^3.0.2
version: 3.0.2(zod@4.3.5)
specifier: ^3.0.6
version: 3.0.6(zod@4.3.5)
'@ai-sdk/openai':
specifier: ^3.0.2
version: 3.0.2(zod@4.3.5)
specifier: ^3.0.7
version: 3.0.7(zod@4.3.5)
'@openrouter/ai-sdk-provider':
specifier: ^1.5.4
version: 1.5.4(ai@6.0.7(zod@4.3.5))(zod@4.3.5)
version: 1.5.4(ai@6.0.27(zod@4.3.5))(zod@4.3.5)
'@radix-ui/react-accordion':
specifier: ^1.2.12
version: 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -96,8 +96,8 @@ importers:
specifier: ^1.3.1
version: 1.3.1(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)
ai:
specifier: ^6.0.7
version: 6.0.7(zod@4.3.5)
specifier: ^6.0.27
version: 6.0.27(zod@4.3.5)
babel-plugin-react-compiler:
specifier: ^1.0.0
version: 1.0.0
@@ -126,8 +126,8 @@ importers:
specifier: ^5.0.7
version: 5.0.7(jspdf@4.0.0)
motion:
specifier: ^12.23.27
version: 12.23.27(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
specifier: ^12.25.0
version: 12.25.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
next:
specifier: 16.1.1
version: 16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -150,8 +150,8 @@ importers:
specifier: 3.6.0
version: 3.6.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react-is@16.13.1)(react@19.2.3)(redux@5.0.1)
resend:
specifier: ^6.6.0
version: 6.6.0
specifier: ^6.7.0
version: 6.7.0
sonner:
specifier: 2.0.7
version: 2.0.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -187,8 +187,8 @@ importers:
specifier: 19.2.3
version: 19.2.3(@types/react@19.2.7)
baseline-browser-mapping:
specifier: ^2.9.11
version: 2.9.11
specifier: ^2.9.14
version: 2.9.14
depcheck:
specifier: ^1.4.7
version: 1.4.7
@@ -203,7 +203,7 @@ importers:
version: 9.39.2(jiti@2.6.1)
eslint-config-next:
specifier: 16.1.1
version: 16.1.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
version: 16.1.1(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
tailwindcss:
specifier: 4.1.18
version: 4.1.18
@@ -216,38 +216,38 @@ importers:
packages:
'@ai-sdk/anthropic@3.0.2':
resolution: {integrity: sha512-D6iSsrOYryBSPsFtOiEDv54jnjVCU/flIuXdjuRY7LdikB0KGjpazN8Dt4ONXzL+ux69ds2nzFNKke/w/fgLAA==}
'@ai-sdk/anthropic@3.0.9':
resolution: {integrity: sha512-QBD4qDnwIHd+N5PpjxXOaWJig1aRB43J0PM5ZUe6Yyl9Qq2bUmraQjvNznkuFKy+hMFDgj0AvgGogTiO5TC+qA==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
'@ai-sdk/gateway@3.0.6':
resolution: {integrity: sha512-oEpwjM0PIaSUErtZI8Ag+gQ+ZelysRWA96N5ahvOc5e9d7QkKJWF0POWx0nI1qBxvmUSw7ca0sLTVw+J5yn7Tg==}
'@ai-sdk/gateway@3.0.11':
resolution: {integrity: sha512-gLrgNXA95wdo/zAlA0miX/SJEYKSYCHg+e0Y/uQeABLScZAMjPw3jWaeANta/Db1T4xfi8cBvY3nnV8Pa27z+w==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
'@ai-sdk/google@3.0.2':
resolution: {integrity: sha512-KyV4AR8fBKVCABfav3zGn/PY7cMDMt9m7yYhH+FJ7jLfBrEVdjT4sM0ojPFRHYUelXHl42oOAgpy3GWkeG6vtw==}
'@ai-sdk/google@3.0.6':
resolution: {integrity: sha512-Nr7E+ouWd/bKO9SFlgLnJJ1+fiGHC07KAeFr08faT+lvkECWlxVox3aL0dec8uCgBDUghYbq7f4S5teUrCc+QQ==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
'@ai-sdk/openai@3.0.2':
resolution: {integrity: sha512-GONwavgSWtcWO+t9+GpGK8l7nIYh+zNtCL/NYDSeHxHiw6ksQS9XMRWrZyE5NpJ0EXNxSAWCHIDmb1WvTqhq9Q==}
'@ai-sdk/openai@3.0.7':
resolution: {integrity: sha512-CBoYn1U59Lop8yBL9KuVjHCKc/B06q9Qo0SasRwHoyMEq+X4I8LQZu3a8Ck1jwwcZTTxfyiExB70LtIRSynBDA==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
'@ai-sdk/provider-utils@4.0.2':
resolution: {integrity: sha512-KaykkuRBdF/ffpI5bwpL4aSCmO/99p8/ci+VeHwJO8tmvXtiVAb99QeyvvvXmL61e9Zrvv4GBGoajW19xdjkVQ==}
'@ai-sdk/provider-utils@4.0.4':
resolution: {integrity: sha512-VxhX0B/dWGbpNHxrKCWUAJKXIXV015J4e7qYjdIU9lLWeptk0KMLGcqkB4wFxff5Njqur8dt8wRi1MN9lZtDqg==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
'@ai-sdk/provider@3.0.1':
resolution: {integrity: sha512-2lR4w7mr9XrydzxBSjir4N6YMGdXD+Np1Sh0RXABh7tWdNFFwIeRI1Q+SaYZMbfL8Pg8RRLcrxQm51yxTLhokg==}
'@ai-sdk/provider@3.0.2':
resolution: {integrity: sha512-HrEmNt/BH/hkQ7zpi2o6N3k1ZR1QTb7z85WYhYygiTxOQuaml4CMtHCWRbric5WPU+RNsYI7r1EpyVQMKO1pYw==}
engines: {node: '>=18'}
'@alloc/quick-lru@5.2.0':
@@ -352,11 +352,11 @@ packages:
'@drizzle-team/brocli@0.10.2':
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
'@emnapi/core@1.7.1':
resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}
'@emnapi/core@1.8.1':
resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==}
'@emnapi/runtime@1.7.1':
resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==}
'@emnapi/runtime@1.8.1':
resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==}
'@emnapi/wasi-threads@1.1.0':
resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
@@ -813,8 +813,8 @@ packages:
cpu: [x64]
os: [win32]
'@eslint-community/eslint-utils@4.9.0':
resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==}
'@eslint-community/eslint-utils@4.9.1':
resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
@@ -1880,9 +1880,6 @@ packages:
'@types/minimatch@3.0.5':
resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==}
'@types/node@22.19.3':
resolution: {integrity: sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==}
'@types/node@25.0.3':
resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==}
@@ -1912,63 +1909,63 @@ packages:
'@types/use-sync-external-store@0.0.6':
resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
'@typescript-eslint/eslint-plugin@8.50.1':
resolution: {integrity: sha512-PKhLGDq3JAg0Jk/aK890knnqduuI/Qj+udH7wCf0217IGi4gt+acgCyPVe79qoT+qKUvHMDQkwJeKW9fwl8Cyw==}
'@typescript-eslint/eslint-plugin@8.52.0':
resolution: {integrity: sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
'@typescript-eslint/parser': ^8.50.1
'@typescript-eslint/parser': ^8.52.0
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/parser@8.50.1':
resolution: {integrity: sha512-hM5faZwg7aVNa819m/5r7D0h0c9yC4DUlWAOvHAtISdFTc8xB86VmX5Xqabrama3wIPJ/q9RbGS1worb6JfnMg==}
'@typescript-eslint/parser@8.52.0':
resolution: {integrity: sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/project-service@8.50.1':
resolution: {integrity: sha512-E1ur1MCVf+YiP89+o4Les/oBAVzmSbeRB0MQLfSlYtbWU17HPxZ6Bhs5iYmKZRALvEuBoXIZMOIRRc/P++Ortg==}
'@typescript-eslint/project-service@8.52.0':
resolution: {integrity: sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/scope-manager@8.50.1':
resolution: {integrity: sha512-mfRx06Myt3T4vuoHaKi8ZWNTPdzKPNBhiblze5N50//TSHOAQQevl/aolqA/BcqqbJ88GUnLqjjcBc8EWdBcVw==}
'@typescript-eslint/scope-manager@8.52.0':
resolution: {integrity: sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/tsconfig-utils@8.50.1':
resolution: {integrity: sha512-ooHmotT/lCWLXi55G4mvaUF60aJa012QzvLK0Y+Mp4WdSt17QhMhWOaBWeGTFVkb2gDgBe19Cxy1elPXylslDw==}
'@typescript-eslint/tsconfig-utils@8.52.0':
resolution: {integrity: sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/type-utils@8.50.1':
resolution: {integrity: sha512-7J3bf022QZE42tYMO6SL+6lTPKFk/WphhRPe9Tw/el+cEwzLz1Jjz2PX3GtGQVxooLDKeMVmMt7fWpYRdG5Etg==}
'@typescript-eslint/type-utils@8.52.0':
resolution: {integrity: sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/types@8.50.1':
resolution: {integrity: sha512-v5lFIS2feTkNyMhd7AucE/9j/4V9v5iIbpVRncjk/K0sQ6Sb+Np9fgYS/63n6nwqahHQvbmujeBL7mp07Q9mlA==}
'@typescript-eslint/types@8.52.0':
resolution: {integrity: sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.50.1':
resolution: {integrity: sha512-woHPdW+0gj53aM+cxchymJCrh0cyS7BTIdcDxWUNsclr9VDkOSbqC13juHzxOmQ22dDkMZEpZB+3X1WpUvzgVQ==}
'@typescript-eslint/typescript-estree@8.52.0':
resolution: {integrity: sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/utils@8.50.1':
resolution: {integrity: sha512-lCLp8H1T9T7gPbEuJSnHwnSuO9mDf8mfK/Nion5mZmiEaQD9sWf9W4dfeFqRyqRjF06/kBuTmAqcs9sewM2NbQ==}
'@typescript-eslint/utils@8.52.0':
resolution: {integrity: sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/visitor-keys@8.50.1':
resolution: {integrity: sha512-IrDKrw7pCRUR94zeuCSUWQ+w8JEf5ZX5jl/e6AHGSLi1/zIr0lgutfn/7JpfCey+urpgQEdrZVYzCaVVKiTwhQ==}
'@typescript-eslint/visitor-keys@8.52.0':
resolution: {integrity: sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@unrs/resolver-binding-android-arm-eabi@1.11.1':
@@ -2092,8 +2089,8 @@ packages:
vue-router:
optional: true
'@vercel/oidc@3.0.5':
resolution: {integrity: sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==}
'@vercel/oidc@3.1.0':
resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==}
engines: {node: '>= 20'}
'@vercel/speed-insights@1.3.1':
@@ -2148,8 +2145,8 @@ packages:
resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==}
engines: {node: '>=0.8'}
ai@6.0.7:
resolution: {integrity: sha512-kLzSXHdW6cAcb2mFSIfkbfzxYqqjrUnyhrB1sg855qlC+6XkLI8hmwFE8f/4SnjmtcTDOnkIaVjWoO5i5Ir0bw==}
ai@6.0.27:
resolution: {integrity: sha512-a4ToMt5+4xOzHuYdoTy2GQXuNa2/Tpuhxfs5QESHtEV/Vf2HAzSwmTwikrIs8CDKPuMWV1I9YqAvaN5xexMCiQ==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
@@ -2234,8 +2231,8 @@ packages:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
axe-core@4.11.0:
resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==}
axe-core@4.11.1:
resolution: {integrity: sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==}
engines: {node: '>=4'}
axobject-query@4.1.0:
@@ -2252,8 +2249,8 @@ packages:
resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
engines: {node: '>= 0.6.0'}
baseline-browser-mapping@2.9.11:
resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==}
baseline-browser-mapping@2.9.14:
resolution: {integrity: sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==}
hasBin: true
better-auth@1.4.10:
@@ -2364,8 +2361,8 @@ packages:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'}
caniuse-lite@1.0.30001761:
resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==}
caniuse-lite@1.0.30001763:
resolution: {integrity: sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ==}
canvg@3.0.11:
resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==}
@@ -2721,9 +2718,6 @@ packages:
es-toolkit@1.43.0:
resolution: {integrity: sha512-SKCT8AsWvYzBBuUqMk4NPwFlSdqLpJwmy6AP322ERn8W2YLIB6JBXnwMI2Qsh2gfphT3q7EKAxKb23cvFHFwKA==}
es6-promise@4.2.8:
resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==}
esbuild-register@3.6.0:
resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==}
peerDependencies:
@@ -2857,8 +2851,8 @@ packages:
engines: {node: '>=4'}
hasBin: true
esquery@1.6.0:
resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
esquery@1.7.0:
resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==}
engines: {node: '>=0.10'}
esrecurse@4.3.0:
@@ -2952,8 +2946,8 @@ packages:
resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==}
engines: {node: '>=0.8'}
framer-motion@12.23.27:
resolution: {integrity: sha512-EAcX8FS8jzZ4tSKpj+1GhwbVY+r1gfamPFwXZAsioPqu/ffRwU2otkKg6GEDCR41FVJv3RoBN7Aqep6drL9Itg==}
framer-motion@12.25.0:
resolution: {integrity: sha512-mlWqd0rApIjeyhTCSNCqPYsUAEhkcUukZxH3ke6KbstBRPcxhEpuIjmiUQvB+1E9xkEm5SpNHBgHCapH/QHTWg==}
peerDependencies:
'@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0
@@ -3099,8 +3093,8 @@ packages:
immer@10.2.0:
resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==}
immer@11.1.0:
resolution: {integrity: sha512-dlzb07f5LDY+tzs+iLCSXV2yuhaYfezqyZQc+n6baLECWkOMEWxkECAOnXL0ba7lsA25fM9b2jtzpu/uxo1a7g==}
immer@11.1.3:
resolution: {integrity: sha512-6jQTc5z0KJFtr1UgFpIL3N9XSC3saRaI9PwWtzM2pSqkNGtiNkYY2OSwkOGDK2XcTRcLb1pi/aNkKZz0nxVH4Q==}
import-fresh@3.3.1:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
@@ -3444,14 +3438,14 @@ packages:
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
motion-dom@12.23.23:
resolution: {integrity: sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==}
motion-dom@12.24.11:
resolution: {integrity: sha512-DlWOmsXMJrV8lzZyd+LKjG2CXULUs++bkq8GZ2Sr0R0RRhs30K2wtY+LKiTjhmJU3W61HK+rB0GLz6XmPvTA1A==}
motion-utils@12.23.6:
resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==}
motion-utils@12.24.10:
resolution: {integrity: sha512-x5TFgkCIP4pPsRLpKoI86jv/q8t8FQOiM/0E8QKBzfMozWHfkKap2gA1hOki+B5g3IsBNpxbUnfOum1+dgvYww==}
motion@12.23.27:
resolution: {integrity: sha512-EDb0hAE6jNX8BHpmQK1GBf9Eizx9bg/Tz2KEAJBOGEnIJp8W77QweRpVb05U8R0L0/LXndHmS1Xv3fwXJh/kcQ==}
motion@12.25.0:
resolution: {integrity: sha512-jBFohEYklpZ+TL64zv03sHdqr1Tsc8/yDy7u68hVzi7hTJYtv53AduchqCiY3aWi4vY1hweS8DWtgCuckusYdQ==}
peerDependencies:
'@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0
@@ -3686,9 +3680,6 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
@@ -3793,14 +3784,11 @@ packages:
require-package-name@2.0.1:
resolution: {integrity: sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==}
requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
reselect@5.1.1:
resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==}
resend@6.6.0:
resolution: {integrity: sha512-d1WoOqSxj5x76JtQMrieNAG1kZkh4NU4f+Je1yq4++JsDpLddhEwnJlNfvkCzvUuZy9ZquWmMMAm2mENd2JvRw==}
resend@6.7.0:
resolution: {integrity: sha512-2ZV0NDZsh4Gh+Nd1hvluZIitmGJ59O4+OxMufymG6Y8uz1Jgt2uS1seSENnkIUlmwg7/dwmfIJC9rAufByz7wA==}
engines: {node: '>=20'}
peerDependencies:
'@react-email/render': '*'
@@ -3951,6 +3939,9 @@ packages:
resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==}
engines: {node: '>=0.1.14'}
standardwebhooks@1.0.0:
resolution: {integrity: sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==}
stop-iteration-iterator@1.1.0:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
@@ -4019,8 +4010,8 @@ packages:
resolution: {integrity: sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==}
engines: {node: '>=12.0.0'}
svix@1.76.1:
resolution: {integrity: sha512-CRuDWBTgYfDnBLRaZdKp9VuoPcNUq9An14c/k+4YJ15Qc5Grvf66vp0jvTltd4t7OIRj+8lM1DAgvSgvf7hdLw==}
svix@1.84.1:
resolution: {integrity: sha512-K8DPPSZaW/XqXiz1kEyzSHYgmGLnhB43nQCMeKjWGCUpLIpAMMM8kx3rVVOSm6Bo6EHyK1RQLPT4R06skM/MlQ==}
tailwind-merge@3.4.0:
resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==}
@@ -4046,8 +4037,8 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
ts-api-utils@2.1.0:
resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
ts-api-utils@2.4.0:
resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==}
engines: {node: '>=18.12'}
peerDependencies:
typescript: '>=4.8.4'
@@ -4083,8 +4074,8 @@ packages:
resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
engines: {node: '>= 0.4'}
typescript-eslint@8.50.1:
resolution: {integrity: sha512-ytTHO+SoYSbhAH9CrYnMhiLx8To6PSSvqnvXyPUgPETCvB6eBKmTI9w6XMPS3HsBRGkwTVBX+urA8dYQx6bHfQ==}
typescript-eslint@8.52.0:
resolution: {integrity: sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -4099,9 +4090,6 @@ packages:
resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
engines: {node: '>= 0.4'}
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
@@ -4117,9 +4105,6 @@ packages:
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
url-parse@1.5.10:
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
use-callback-ref@1.3.3:
resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
engines: {node: '>=10'}
@@ -4245,39 +4230,39 @@ packages:
snapshots:
'@ai-sdk/anthropic@3.0.2(zod@4.3.5)':
'@ai-sdk/anthropic@3.0.9(zod@4.3.5)':
dependencies:
'@ai-sdk/provider': 3.0.1
'@ai-sdk/provider-utils': 4.0.2(zod@4.3.5)
'@ai-sdk/provider': 3.0.2
'@ai-sdk/provider-utils': 4.0.4(zod@4.3.5)
zod: 4.3.5
'@ai-sdk/gateway@3.0.6(zod@4.3.5)':
'@ai-sdk/gateway@3.0.11(zod@4.3.5)':
dependencies:
'@ai-sdk/provider': 3.0.1
'@ai-sdk/provider-utils': 4.0.2(zod@4.3.5)
'@vercel/oidc': 3.0.5
'@ai-sdk/provider': 3.0.2
'@ai-sdk/provider-utils': 4.0.4(zod@4.3.5)
'@vercel/oidc': 3.1.0
zod: 4.3.5
'@ai-sdk/google@3.0.2(zod@4.3.5)':
'@ai-sdk/google@3.0.6(zod@4.3.5)':
dependencies:
'@ai-sdk/provider': 3.0.1
'@ai-sdk/provider-utils': 4.0.2(zod@4.3.5)
'@ai-sdk/provider': 3.0.2
'@ai-sdk/provider-utils': 4.0.4(zod@4.3.5)
zod: 4.3.5
'@ai-sdk/openai@3.0.2(zod@4.3.5)':
'@ai-sdk/openai@3.0.7(zod@4.3.5)':
dependencies:
'@ai-sdk/provider': 3.0.1
'@ai-sdk/provider-utils': 4.0.2(zod@4.3.5)
'@ai-sdk/provider': 3.0.2
'@ai-sdk/provider-utils': 4.0.4(zod@4.3.5)
zod: 4.3.5
'@ai-sdk/provider-utils@4.0.2(zod@4.3.5)':
'@ai-sdk/provider-utils@4.0.4(zod@4.3.5)':
dependencies:
'@ai-sdk/provider': 3.0.1
'@ai-sdk/provider': 3.0.2
'@standard-schema/spec': 1.1.0
eventsource-parser: 3.0.6
zod: 4.3.5
'@ai-sdk/provider@3.0.1':
'@ai-sdk/provider@3.0.2':
dependencies:
json-schema: 0.4.0
@@ -4410,13 +4395,13 @@ snapshots:
'@drizzle-team/brocli@0.10.2': {}
'@emnapi/core@1.7.1':
'@emnapi/core@1.8.1':
dependencies:
'@emnapi/wasi-threads': 1.1.0
tslib: 2.8.1
optional: true
'@emnapi/runtime@1.7.1':
'@emnapi/runtime@1.8.1':
dependencies:
tslib: 2.8.1
optional: true
@@ -4658,7 +4643,7 @@ snapshots:
'@esbuild/win32-x64@0.27.2':
optional: true
'@eslint-community/eslint-utils@4.9.0(eslint@9.39.2(jiti@2.6.1))':
'@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))':
dependencies:
eslint: 9.39.2(jiti@2.6.1)
eslint-visitor-keys: 3.4.3
@@ -4817,7 +4802,7 @@ snapshots:
'@img/sharp-wasm32@0.34.5':
dependencies:
'@emnapi/runtime': 1.7.1
'@emnapi/runtime': 1.8.1
optional: true
'@img/sharp-win32-arm64@0.34.5':
@@ -4850,8 +4835,8 @@ snapshots:
'@napi-rs/wasm-runtime@0.2.12':
dependencies:
'@emnapi/core': 1.7.1
'@emnapi/runtime': 1.7.1
'@emnapi/core': 1.8.1
'@emnapi/runtime': 1.8.1
'@tybys/wasm-util': 0.10.1
optional: true
@@ -4903,10 +4888,10 @@ snapshots:
'@nolyfill/is-core-module@1.0.39': {}
'@openrouter/ai-sdk-provider@1.5.4(ai@6.0.7(zod@4.3.5))(zod@4.3.5)':
'@openrouter/ai-sdk-provider@1.5.4(ai@6.0.27(zod@4.3.5))(zod@4.3.5)':
dependencies:
'@openrouter/sdk': 0.1.27
ai: 6.0.7(zod@4.3.5)
ai: 6.0.27(zod@4.3.5)
zod: 4.3.5
'@openrouter/sdk@0.1.27':
@@ -5512,7 +5497,7 @@ snapshots:
dependencies:
'@standard-schema/spec': 1.1.0
'@standard-schema/utils': 0.3.0
immer: 11.1.0
immer: 11.1.3
redux: 5.0.1
redux-thunk: 3.1.0(redux@5.0.1)
reselect: 5.1.1
@@ -5650,10 +5635,6 @@ snapshots:
'@types/minimatch@3.0.5': {}
'@types/node@22.19.3':
dependencies:
undici-types: 6.21.0
'@types/node@25.0.3':
dependencies:
undici-types: 7.16.0
@@ -5684,95 +5665,95 @@ snapshots:
'@types/use-sync-external-store@0.0.6': {}
'@typescript-eslint/eslint-plugin@8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
'@typescript-eslint/eslint-plugin@8.52.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.50.1
'@typescript-eslint/type-utils': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/utils': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.50.1
'@typescript-eslint/parser': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.52.0
'@typescript-eslint/type-utils': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/utils': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.52.0
eslint: 9.39.2(jiti@2.6.1)
ignore: 7.0.5
natural-compare: 1.4.0
ts-api-utils: 2.1.0(typescript@5.9.3)
ts-api-utils: 2.4.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
'@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.50.1
'@typescript-eslint/types': 8.50.1
'@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.50.1
'@typescript-eslint/scope-manager': 8.52.0
'@typescript-eslint/types': 8.52.0
'@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.52.0
debug: 4.4.3
eslint: 9.39.2(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/project-service@8.50.1(typescript@5.9.3)':
'@typescript-eslint/project-service@8.52.0(typescript@5.9.3)':
dependencies:
'@typescript-eslint/tsconfig-utils': 8.50.1(typescript@5.9.3)
'@typescript-eslint/types': 8.50.1
'@typescript-eslint/tsconfig-utils': 8.52.0(typescript@5.9.3)
'@typescript-eslint/types': 8.52.0
debug: 4.4.3
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/scope-manager@8.50.1':
'@typescript-eslint/scope-manager@8.52.0':
dependencies:
'@typescript-eslint/types': 8.50.1
'@typescript-eslint/visitor-keys': 8.50.1
'@typescript-eslint/types': 8.52.0
'@typescript-eslint/visitor-keys': 8.52.0
'@typescript-eslint/tsconfig-utils@8.50.1(typescript@5.9.3)':
'@typescript-eslint/tsconfig-utils@8.52.0(typescript@5.9.3)':
dependencies:
typescript: 5.9.3
'@typescript-eslint/type-utils@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
'@typescript-eslint/type-utils@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/types': 8.50.1
'@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3)
'@typescript-eslint/utils': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/types': 8.52.0
'@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
debug: 4.4.3
eslint: 9.39.2(jiti@2.6.1)
ts-api-utils: 2.1.0(typescript@5.9.3)
ts-api-utils: 2.4.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types@8.50.1': {}
'@typescript-eslint/types@8.52.0': {}
'@typescript-eslint/typescript-estree@8.50.1(typescript@5.9.3)':
'@typescript-eslint/typescript-estree@8.52.0(typescript@5.9.3)':
dependencies:
'@typescript-eslint/project-service': 8.50.1(typescript@5.9.3)
'@typescript-eslint/tsconfig-utils': 8.50.1(typescript@5.9.3)
'@typescript-eslint/types': 8.50.1
'@typescript-eslint/visitor-keys': 8.50.1
'@typescript-eslint/project-service': 8.52.0(typescript@5.9.3)
'@typescript-eslint/tsconfig-utils': 8.52.0(typescript@5.9.3)
'@typescript-eslint/types': 8.52.0
'@typescript-eslint/visitor-keys': 8.52.0
debug: 4.4.3
minimatch: 9.0.5
semver: 7.7.3
tinyglobby: 0.2.15
ts-api-utils: 2.1.0(typescript@5.9.3)
ts-api-utils: 2.4.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
'@typescript-eslint/utils@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1))
'@typescript-eslint/scope-manager': 8.50.1
'@typescript-eslint/types': 8.50.1
'@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3)
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1))
'@typescript-eslint/scope-manager': 8.52.0
'@typescript-eslint/types': 8.52.0
'@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/visitor-keys@8.50.1':
'@typescript-eslint/visitor-keys@8.52.0':
dependencies:
'@typescript-eslint/types': 8.50.1
'@typescript-eslint/types': 8.52.0
eslint-visitor-keys: 4.2.1
'@unrs/resolver-binding-android-arm-eabi@1.11.1':
@@ -5839,7 +5820,7 @@ snapshots:
next: 16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
react: 19.2.3
'@vercel/oidc@3.0.5': {}
'@vercel/oidc@3.1.0': {}
'@vercel/speed-insights@1.3.1(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)':
optionalDependencies:
@@ -5886,11 +5867,11 @@ snapshots:
adler-32@1.3.1: {}
ai@6.0.7(zod@4.3.5):
ai@6.0.27(zod@4.3.5):
dependencies:
'@ai-sdk/gateway': 3.0.6(zod@4.3.5)
'@ai-sdk/provider': 3.0.1
'@ai-sdk/provider-utils': 4.0.2(zod@4.3.5)
'@ai-sdk/gateway': 3.0.11(zod@4.3.5)
'@ai-sdk/provider': 3.0.2
'@ai-sdk/provider-utils': 4.0.4(zod@4.3.5)
'@opentelemetry/api': 1.9.0
zod: 4.3.5
@@ -6000,7 +5981,7 @@ snapshots:
dependencies:
possible-typed-array-names: 1.1.0
axe-core@4.11.0: {}
axe-core@4.11.1: {}
axobject-query@4.1.0: {}
@@ -6013,7 +5994,7 @@ snapshots:
base64-arraybuffer@1.0.2:
optional: true
baseline-browser-mapping@2.9.11: {}
baseline-browser-mapping@2.9.14: {}
better-auth@1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
@@ -6061,8 +6042,8 @@ snapshots:
browserslist@4.28.1:
dependencies:
baseline-browser-mapping: 2.9.11
caniuse-lite: 1.0.30001761
baseline-browser-mapping: 2.9.14
caniuse-lite: 1.0.30001763
electron-to-chromium: 1.5.267
node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1)
@@ -6092,7 +6073,7 @@ snapshots:
camelcase@6.3.0: {}
caniuse-lite@1.0.30001761: {}
caniuse-lite@1.0.30001763: {}
canvg@3.0.11:
dependencies:
@@ -6457,8 +6438,6 @@ snapshots:
es-toolkit@1.43.0: {}
es6-promise@4.2.8: {}
esbuild-register@3.6.0(esbuild@0.25.12):
dependencies:
debug: 4.4.3
@@ -6553,18 +6532,18 @@ snapshots:
escape-string-regexp@4.0.0: {}
eslint-config-next@16.1.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
eslint-config-next@16.1.1(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
dependencies:
'@next/eslint-plugin-next': 16.1.1
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react: 7.37.5(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react-hooks: 7.0.1(eslint@9.39.2(jiti@2.6.1))
globals: 16.4.0
typescript-eslint: 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
typescript-eslint: 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
optionalDependencies:
typescript: 5.9.3
transitivePeerDependencies:
@@ -6592,22 +6571,22 @@ snapshots:
tinyglobby: 0.2.15
unrs-resolver: 1.11.1
optionalDependencies:
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)):
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)):
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -6618,7 +6597,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -6630,7 +6609,7 @@ snapshots:
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
'@typescript-eslint/parser': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
@@ -6642,7 +6621,7 @@ snapshots:
array-includes: 3.1.9
array.prototype.flatmap: 1.3.3
ast-types-flow: 0.0.8
axe-core: 4.11.0
axe-core: 4.11.1
axobject-query: 4.1.0
damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2
@@ -6699,7 +6678,7 @@ snapshots:
eslint@9.39.2(jiti@2.6.1):
dependencies:
'@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1))
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1))
'@eslint-community/regexpp': 4.12.2
'@eslint/config-array': 0.21.1
'@eslint/config-helpers': 0.4.2
@@ -6719,7 +6698,7 @@ snapshots:
eslint-scope: 8.4.0
eslint-visitor-keys: 4.2.1
espree: 10.4.0
esquery: 1.6.0
esquery: 1.7.0
esutils: 2.0.3
fast-deep-equal: 3.1.3
file-entry-cache: 8.0.0
@@ -6746,7 +6725,7 @@ snapshots:
esprima@4.0.1: {}
esquery@1.6.0:
esquery@1.7.0:
dependencies:
estraverse: 5.3.0
@@ -6833,10 +6812,10 @@ snapshots:
frac@1.1.2: {}
framer-motion@12.23.27(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
framer-motion@12.25.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
motion-dom: 12.23.23
motion-utils: 12.23.6
motion-dom: 12.24.11
motion-utils: 12.24.10
tslib: 2.8.1
optionalDependencies:
react: 19.2.3
@@ -6973,7 +6952,7 @@ snapshots:
immer@10.2.0: {}
immer@11.1.0: {}
immer@11.1.3: {}
import-fresh@3.3.1:
dependencies:
@@ -7291,15 +7270,15 @@ snapshots:
minimist@1.2.8: {}
motion-dom@12.23.23:
motion-dom@12.24.11:
dependencies:
motion-utils: 12.23.6
motion-utils: 12.24.10
motion-utils@12.23.6: {}
motion-utils@12.24.10: {}
motion@12.23.27(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
motion@12.25.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
framer-motion: 12.23.27(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
framer-motion: 12.25.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
tslib: 2.8.1
optionalDependencies:
react: 19.2.3
@@ -7332,8 +7311,8 @@ snapshots:
dependencies:
'@next/env': 16.1.1
'@swc/helpers': 0.5.15
baseline-browser-mapping: 2.9.11
caniuse-lite: 1.0.30001761
baseline-browser-mapping: 2.9.14
caniuse-lite: 1.0.30001763
postcss: 8.4.31
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
@@ -7526,8 +7505,6 @@ snapshots:
punycode@2.3.1: {}
querystringify@2.2.0: {}
queue-microtask@1.2.3: {}
raf@3.4.1:
@@ -7644,13 +7621,11 @@ snapshots:
require-package-name@2.0.1: {}
requires-port@1.0.0: {}
reselect@5.1.1: {}
resend@6.6.0:
resend@6.7.0:
dependencies:
svix: 1.76.1
svix: 1.84.1
resolve-dir@1.0.1:
dependencies:
@@ -7830,6 +7805,11 @@ snapshots:
stackblur-canvas@2.7.0:
optional: true
standardwebhooks@1.0.0:
dependencies:
'@stablelib/base64': 1.0.1
fast-sha256: 1.3.0
stop-iteration-iterator@1.1.0:
dependencies:
es-errors: 1.3.0
@@ -7915,13 +7895,9 @@ snapshots:
svg-pathdata@6.0.3:
optional: true
svix@1.76.1:
svix@1.84.1:
dependencies:
'@stablelib/base64': 1.0.1
'@types/node': 22.19.3
es6-promise: 4.2.8
fast-sha256: 1.3.0
url-parse: 1.5.10
standardwebhooks: 1.0.0
uuid: 10.0.0
tailwind-merge@3.4.0: {}
@@ -7946,7 +7922,7 @@ snapshots:
dependencies:
is-number: 7.0.0
ts-api-utils@2.1.0(typescript@5.9.3):
ts-api-utils@2.4.0(typescript@5.9.3):
dependencies:
typescript: 5.9.3
@@ -8003,12 +7979,12 @@ snapshots:
possible-typed-array-names: 1.1.0
reflect.getprototypeof: 1.0.10
typescript-eslint@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
typescript-eslint@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
dependencies:
'@typescript-eslint/eslint-plugin': 8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3)
'@typescript-eslint/utils': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/eslint-plugin': 8.52.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
@@ -8023,8 +7999,6 @@ snapshots:
has-symbols: 1.1.0
which-boxed-primitive: 1.1.1
undici-types@6.21.0: {}
undici-types@7.16.0: {}
unrs-resolver@1.11.1:
@@ -8061,11 +8035,6 @@ snapshots:
dependencies:
punycode: 2.3.1
url-parse@1.5.10:
dependencies:
querystringify: 2.2.0
requires-port: 1.0.0
use-callback-ref@1.3.3(@types/react@19.2.7)(react@19.2.3):
dependencies:
react: 19.2.3