mirror of
https://github.com/documenso/documenso.git
synced 2025-11-16 01:32:06 +10:00
chore: merged main
This commit is contained in:
@ -17,7 +17,8 @@ For the digital signature of your documents you need a signing certificate in .p
|
|||||||
`openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt`
|
`openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt`
|
||||||
|
|
||||||
4. You will be prompted to enter a password for the p12 file. Choose a strong password and remember it, as you will need it to use the certificate (**can be empty for dev certificates**)
|
4. You will be prompted to enter a password for the p12 file. Choose a strong password and remember it, as you will need it to use the certificate (**can be empty for dev certificates**)
|
||||||
5. Place the certificate `/apps/web/resources/certificate.p12`
|
|
||||||
|
5. Place the certificate `/apps/web/resources/certificate.p12` (If the path does not exist, it needs to be created)
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { TClaimPlanRequestSchema, ZClaimPlanResponseSchema } from './types';
|
import type { TClaimPlanRequestSchema } from './types';
|
||||||
|
import { ZClaimPlanResponseSchema } from './types';
|
||||||
|
|
||||||
export const claimPlan = async ({
|
export const claimPlan = async ({
|
||||||
name,
|
name,
|
||||||
|
|||||||
@ -55,6 +55,7 @@ export const BarMetric = <T extends Record<string, Record<keyof T[string], unkno
|
|||||||
cursor={{ fill: 'hsl(var(--primary) / 10%)' }}
|
cursor={{ fill: 'hsl(var(--primary) / 10%)' }}
|
||||||
/>
|
/>
|
||||||
<Bar
|
<Bar
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||||
dataKey={metricKey as string}
|
dataKey={metricKey as string}
|
||||||
maxBarSize={60}
|
maxBarSize={60}
|
||||||
fill="hsl(var(--primary))"
|
fill="hsl(var(--primary))"
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export type FundingRaisedProps = HTMLAttributes<HTMLDivElement> & {
|
|||||||
export const FundingRaised = ({ className, data, ...props }: FundingRaisedProps) => {
|
export const FundingRaised = ({ className, data, ...props }: FundingRaisedProps) => {
|
||||||
const formattedData = data.map((item) => ({
|
const formattedData = data.map((item) => ({
|
||||||
amount: Number(item.amount),
|
amount: Number(item.amount),
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||||
date: formatMonth(item.date as string),
|
date: formatMonth(item.date as string),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { HTMLAttributes } from 'react';
|
import type { HTMLAttributes } from 'react';
|
||||||
|
|
||||||
import { cn } from '@documenso/ui/lib/utils';
|
import { cn } from '@documenso/ui/lib/utils';
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { HTMLAttributes } from 'react';
|
import type { HTMLAttributes } from 'react';
|
||||||
|
|
||||||
import { cn } from '@documenso/ui/lib/utils';
|
import { cn } from '@documenso/ui/lib/utils';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
import { Variants, motion } from 'framer-motion';
|
import type { Variants } from 'framer-motion';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
import { cn } from '@documenso/ui/lib/utils';
|
import { cn } from '@documenso/ui/lib/utils';
|
||||||
import { Button } from '@documenso/ui/primitives/button';
|
import { Button } from '@documenso/ui/primitives/button';
|
||||||
import { Card, CardContent, CardTitle } from '@documenso/ui/primitives/card';
|
import { Card, CardContent, CardTitle } from '@documenso/ui/primitives/card';
|
||||||
|
|
||||||
import { TOSSFriendsSchema } from './schema';
|
import type { TOSSFriendsSchema } from './schema';
|
||||||
|
|
||||||
const ContainerVariants: Variants = {
|
const ContainerVariants: Variants = {
|
||||||
initial: {
|
initial: {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { MetadataRoute } from 'next';
|
import type { MetadataRoute } from 'next';
|
||||||
|
|
||||||
import { getBaseUrl } from '@documenso/lib/universal/get-base-url';
|
import { getBaseUrl } from '@documenso/lib/universal/get-base-url';
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { MetadataRoute } from 'next';
|
import type { MetadataRoute } from 'next';
|
||||||
|
|
||||||
import { allBlogPosts, allGenericPages } from 'contentlayer/generated';
|
import { allBlogPosts, allGenericPages } from 'contentlayer/generated';
|
||||||
|
|
||||||
|
|||||||
@ -96,7 +96,7 @@ export const Hero = ({ className, ...props }: HeroProps) => {
|
|||||||
variants={HeroTitleVariants}
|
variants={HeroTitleVariants}
|
||||||
initial="initial"
|
initial="initial"
|
||||||
animate="animate"
|
animate="animate"
|
||||||
className="text-center text-4xl font-bold leading-tight tracking-tight lg:text-[64px]"
|
className="text-center text-4xl font-bold leading-tight tracking-tight md:text-[48px] lg:text-[64px]"
|
||||||
>
|
>
|
||||||
Document signing,
|
Document signing,
|
||||||
<span className="block" /> finally open source.
|
<span className="block" /> finally open source.
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { HTMLAttributes } from 'react';
|
import type { HTMLAttributes } from 'react';
|
||||||
|
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
|
|
||||||
|
|||||||
@ -346,7 +346,7 @@ export const Widget = ({ className, children, ...props }: WidgetProps) => {
|
|||||||
{signatureText && (
|
{signatureText && (
|
||||||
<p
|
<p
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-foreground text-4xl font-semibold [font-family:var(--font-caveat)]',
|
'text-foreground truncate text-4xl font-semibold [font-family:var(--font-caveat)]',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{signatureText}
|
{signatureText}
|
||||||
@ -360,7 +360,7 @@ export const Widget = ({ className, children, ...props }: WidgetProps) => {
|
|||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
id="signatureText"
|
id="signatureText"
|
||||||
className="text-foreground placeholder:text-muted-foreground border-none p-0 text-sm focus-visible:ring-0"
|
className="text-foreground placeholder:text-muted-foreground truncate border-none p-0 text-sm focus-visible:ring-0"
|
||||||
placeholder="Draw or type name here"
|
placeholder="Draw or type name here"
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
{...register('signatureText', {
|
{...register('signatureText', {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
import { FieldError } from 'react-hook-form';
|
import type { FieldError } from 'react-hook-form';
|
||||||
|
|
||||||
import { cn } from '@documenso/ui/lib/utils';
|
import { cn } from '@documenso/ui/lib/utils';
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { SVGAttributes } from 'react';
|
import type { SVGAttributes } from 'react';
|
||||||
|
|
||||||
export type BackgroundProps = Omit<SVGAttributes<SVGElement>, 'viewBox'>;
|
export type BackgroundProps = Omit<SVGAttributes<SVGElement>, 'viewBox'>;
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { ThemeProvider as NextThemesProvider } from 'next-themes';
|
import { ThemeProvider as NextThemesProvider } from 'next-themes';
|
||||||
import { ThemeProviderProps } from 'next-themes/dist/types';
|
import type { ThemeProviderProps } from 'next-themes/dist/types';
|
||||||
|
|
||||||
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
||||||
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
|
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
|
||||||
|
|||||||
@ -118,7 +118,7 @@ export const DocumentPageViewDropdown = ({ document, team }: DocumentPageViewDro
|
|||||||
<DropdownMenuItem asChild>
|
<DropdownMenuItem asChild>
|
||||||
<Link href={`${documentsPath}/${document.id}/logs`}>
|
<Link href={`${documentsPath}/${document.id}/logs`}>
|
||||||
<ScrollTextIcon className="mr-2 h-4 w-4" />
|
<ScrollTextIcon className="mr-2 h-4 w-4" />
|
||||||
Logs
|
Audit Log
|
||||||
</Link>
|
</Link>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import { useCallback, useMemo, useState } from 'react';
|
|||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
|
||||||
import { Loader, Monitor, Moon, Sun } from 'lucide-react';
|
import { Loader, Monitor, Moon, Sun } from 'lucide-react';
|
||||||
import { useSession } from 'next-auth/react';
|
|
||||||
import { useTheme } from 'next-themes';
|
import { useTheme } from 'next-themes';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
|
|
||||||
@ -18,7 +17,6 @@ import {
|
|||||||
DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||||
SKIP_QUERY_BATCH_META,
|
SKIP_QUERY_BATCH_META,
|
||||||
} from '@documenso/lib/constants/trpc';
|
} from '@documenso/lib/constants/trpc';
|
||||||
import type { Document, Recipient } from '@documenso/prisma/client';
|
|
||||||
import { trpc as trpcReact } from '@documenso/trpc/react';
|
import { trpc as trpcReact } from '@documenso/trpc/react';
|
||||||
import {
|
import {
|
||||||
CommandDialog,
|
CommandDialog,
|
||||||
@ -71,7 +69,6 @@ export type CommandMenuProps = {
|
|||||||
|
|
||||||
export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
|
export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
|
||||||
const { setTheme } = useTheme();
|
const { setTheme } = useTheme();
|
||||||
const { data: session } = useSession();
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@ -93,17 +90,6 @@ export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const isOwner = useCallback(
|
|
||||||
(document: Document) => document.userId === session?.user.id,
|
|
||||||
[session?.user.id],
|
|
||||||
);
|
|
||||||
|
|
||||||
const getSigningLink = useCallback(
|
|
||||||
(recipients: Recipient[]) =>
|
|
||||||
`/sign/${recipients.find((r) => r.email === session?.user.email)?.token}`,
|
|
||||||
[session?.user.email],
|
|
||||||
);
|
|
||||||
|
|
||||||
const searchResults = useMemo(() => {
|
const searchResults = useMemo(() => {
|
||||||
if (!searchDocumentsData) {
|
if (!searchDocumentsData) {
|
||||||
return [];
|
return [];
|
||||||
@ -111,10 +97,10 @@ export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
|
|||||||
|
|
||||||
return searchDocumentsData.map((document) => ({
|
return searchDocumentsData.map((document) => ({
|
||||||
label: document.title,
|
label: document.title,
|
||||||
path: isOwner(document) ? `/documents/${document.id}` : getSigningLink(document.Recipient),
|
path: document.path,
|
||||||
value: [document.id, document.title, ...document.Recipient.map((r) => r.email)].join(' '),
|
value: document.value,
|
||||||
}));
|
}));
|
||||||
}, [searchDocumentsData, isOwner, getSigningLink]);
|
}, [searchDocumentsData]);
|
||||||
|
|
||||||
const currentPage = pages[pages.length - 1];
|
const currentPage = pages[pages.length - 1];
|
||||||
|
|
||||||
|
|||||||
@ -93,7 +93,7 @@ export const MenuSwitcher = ({ user, teams: initialTeamsData }: MenuSwitcherProp
|
|||||||
<Button
|
<Button
|
||||||
data-testid="menu-switcher"
|
data-testid="menu-switcher"
|
||||||
variant="none"
|
variant="none"
|
||||||
className="relative flex h-12 flex-row items-center px-2 py-2 ring-0 focus:outline-none focus-visible:border-0 focus-visible:ring-0 focus-visible:ring-transparent"
|
className="relative flex h-12 flex-row items-center px-0 py-2 ring-0 focus:outline-none focus-visible:border-0 focus-visible:ring-0 focus-visible:ring-transparent md:px-2"
|
||||||
>
|
>
|
||||||
<AvatarWithText
|
<AvatarWithText
|
||||||
avatarFallback={formatAvatarFallback(selectedTeam?.name)}
|
avatarFallback={formatAvatarFallback(selectedTeam?.name)}
|
||||||
@ -102,12 +102,13 @@ export const MenuSwitcher = ({ user, teams: initialTeamsData }: MenuSwitcherProp
|
|||||||
rightSideComponent={
|
rightSideComponent={
|
||||||
<ChevronsUpDown className="text-muted-foreground ml-auto h-4 w-4" />
|
<ChevronsUpDown className="text-muted-foreground ml-auto h-4 w-4" />
|
||||||
}
|
}
|
||||||
|
textSectionClassName="hidden lg:flex"
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
|
|
||||||
<DropdownMenuContent
|
<DropdownMenuContent
|
||||||
className={cn('z-[60] ml-2 w-full md:ml-0', teams ? 'min-w-[20rem]' : 'min-w-[12rem]')}
|
className={cn('z-[60] ml-6 w-full md:ml-0', teams ? 'min-w-[20rem]' : 'min-w-[12rem]')}
|
||||||
align="end"
|
align="end"
|
||||||
forceMount
|
forceMount
|
||||||
>
|
>
|
||||||
|
|||||||
@ -46,7 +46,7 @@ export const MobileNavigation = ({ isMenuOpen, onMenuOpenChange }: MobileNavigat
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Sheet open={isMenuOpen} onOpenChange={onMenuOpenChange}>
|
<Sheet open={isMenuOpen} onOpenChange={onMenuOpenChange}>
|
||||||
<SheetContent className="flex w-full max-w-[400px] flex-col">
|
<SheetContent className="flex w-full max-w-[350px] flex-col">
|
||||||
<Link href="/" onClick={handleMenuItemClick}>
|
<Link href="/" onClick={handleMenuItemClick}>
|
||||||
<Image
|
<Image
|
||||||
src={LogoImage}
|
src={LogoImage}
|
||||||
@ -87,7 +87,7 @@ export const MobileNavigation = ({ isMenuOpen, onMenuOpenChange }: MobileNavigat
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-muted-foreground text-sm">
|
<p className="text-muted-foreground text-sm">
|
||||||
© {new Date().getFullYear()} Documenso, Inc. All rights reserved.
|
© {new Date().getFullYear()} Documenso, Inc. <br /> All rights reserved.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
|
|||||||
@ -2,16 +2,34 @@ import { generateOpenApi } from '@ts-rest/open-api';
|
|||||||
|
|
||||||
import { ApiContractV1 } from './contract';
|
import { ApiContractV1 } from './contract';
|
||||||
|
|
||||||
export const OpenAPIV1 = generateOpenApi(
|
export const OpenAPIV1 = Object.assign(
|
||||||
ApiContractV1,
|
generateOpenApi(
|
||||||
{
|
ApiContractV1,
|
||||||
info: {
|
{
|
||||||
title: 'Documenso API',
|
info: {
|
||||||
version: '1.0.0',
|
title: 'Documenso API',
|
||||||
description: 'The Documenso API for retrieving, creating, updating and deleting documents.',
|
version: '1.0.0',
|
||||||
|
description: 'The Documenso API for retrieving, creating, updating and deleting documents.',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
|
setOperationId: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
{
|
{
|
||||||
setOperationId: true,
|
components: {
|
||||||
|
securitySchemes: {
|
||||||
|
authorization: {
|
||||||
|
type: 'apiKey',
|
||||||
|
in: 'header',
|
||||||
|
name: 'Authorization',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
security: [
|
||||||
|
{
|
||||||
|
authorization: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
import { DocumentStatus } from '@documenso/prisma/client';
|
import { DocumentStatus } from '@documenso/prisma/client';
|
||||||
|
import type { Document, Recipient, User } from '@documenso/prisma/client';
|
||||||
import { maskRecipientTokensForDocument } from '../../utils/mask-recipient-tokens-for-document';
|
|
||||||
|
|
||||||
export type SearchDocumentsWithKeywordOptions = {
|
export type SearchDocumentsWithKeywordOptions = {
|
||||||
query: string;
|
query: string;
|
||||||
@ -79,12 +78,19 @@ export const searchDocumentsWithKeyword = async ({
|
|||||||
take: limit,
|
take: limit,
|
||||||
});
|
});
|
||||||
|
|
||||||
const maskedDocuments = documents.map((document) =>
|
const isOwner = (document: Document, user: User) => document.userId === user.id;
|
||||||
maskRecipientTokensForDocument({
|
const getSigningLink = (recipients: Recipient[], user: User) =>
|
||||||
document,
|
`/sign/${recipients.find((r) => r.email === user.email)?.token}`;
|
||||||
user,
|
|
||||||
}),
|
const maskedDocuments = documents.map((document) => {
|
||||||
);
|
const { Recipient, ...documentWithoutRecipient } = document;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...documentWithoutRecipient,
|
||||||
|
path: isOwner(document, user) ? `/documents/${document.id}` : getSigningLink(Recipient, user),
|
||||||
|
value: [document.id, document.title, ...document.Recipient.map((r) => r.email)].join(' '),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return maskedDocuments;
|
return maskedDocuments;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -358,6 +358,7 @@ export const documentRouter = router({
|
|||||||
query,
|
query,
|
||||||
userId: ctx.user.id,
|
userId: ctx.user.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
return documents;
|
return documents;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|||||||
@ -55,6 +55,8 @@ type AvatarWithTextProps = {
|
|||||||
primaryText: React.ReactNode;
|
primaryText: React.ReactNode;
|
||||||
secondaryText?: React.ReactNode;
|
secondaryText?: React.ReactNode;
|
||||||
rightSideComponent?: React.ReactNode;
|
rightSideComponent?: React.ReactNode;
|
||||||
|
// Optional class to hide/show the text beside avatar
|
||||||
|
textSectionClassName?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const AvatarWithText = ({
|
const AvatarWithText = ({
|
||||||
@ -64,6 +66,7 @@ const AvatarWithText = ({
|
|||||||
primaryText,
|
primaryText,
|
||||||
secondaryText,
|
secondaryText,
|
||||||
rightSideComponent,
|
rightSideComponent,
|
||||||
|
textSectionClassName,
|
||||||
}: AvatarWithTextProps) => (
|
}: AvatarWithTextProps) => (
|
||||||
<div className={cn('flex w-full max-w-xs items-center gap-2', className)}>
|
<div className={cn('flex w-full max-w-xs items-center gap-2', className)}>
|
||||||
<Avatar
|
<Avatar
|
||||||
@ -72,7 +75,7 @@ const AvatarWithText = ({
|
|||||||
<AvatarFallback className="text-xs text-gray-400">{avatarFallback}</AvatarFallback>
|
<AvatarFallback className="text-xs text-gray-400">{avatarFallback}</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
|
|
||||||
<div className="flex flex-col text-left text-sm font-normal">
|
<div className={cn('flex flex-col text-left text-sm font-normal', textSectionClassName)}>
|
||||||
<span className="text-foreground truncate">{primaryText}</span>
|
<span className="text-foreground truncate">{primaryText}</span>
|
||||||
<span className="text-muted-foreground truncate text-xs">{secondaryText}</span>
|
<span className="text-muted-foreground truncate text-xs">{secondaryText}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -32,7 +32,11 @@ type CommandDialogProps = DialogProps & {
|
|||||||
const CommandDialog = ({ children, commandProps, ...props }: CommandDialogProps) => {
|
const CommandDialog = ({ children, commandProps, ...props }: CommandDialogProps) => {
|
||||||
return (
|
return (
|
||||||
<Dialog {...props}>
|
<Dialog {...props}>
|
||||||
<DialogContent className="overflow-hidden p-0 shadow-2xl">
|
<DialogContent
|
||||||
|
className="w-11/12 items-center overflow-hidden rounded-lg p-0 shadow-2xl lg:mt-0"
|
||||||
|
position="center"
|
||||||
|
overlayClassName="bg-background/60"
|
||||||
|
>
|
||||||
<Command
|
<Command
|
||||||
{...commandProps}
|
{...commandProps}
|
||||||
className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-0 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-4 [&_[cmdk-item]_svg]:w-4"
|
className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-0 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-4 [&_[cmdk-item]_svg]:w-4"
|
||||||
|
|||||||
@ -54,28 +54,35 @@ const DialogContent = React.forwardRef<
|
|||||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
|
||||||
position?: 'start' | 'end' | 'center';
|
position?: 'start' | 'end' | 'center';
|
||||||
hideClose?: boolean;
|
hideClose?: boolean;
|
||||||
|
/* Below prop is to add additional classes to the overlay */
|
||||||
|
overlayClassName?: string;
|
||||||
}
|
}
|
||||||
>(({ className, children, position = 'start', hideClose = false, ...props }, ref) => (
|
>(
|
||||||
<DialogPortal position={position}>
|
(
|
||||||
<DialogOverlay />
|
{ className, children, overlayClassName, position = 'start', hideClose = false, ...props },
|
||||||
<DialogPrimitive.Content
|
ref,
|
||||||
ref={ref}
|
) => (
|
||||||
className={cn(
|
<DialogPortal position={position}>
|
||||||
'bg-background animate-in data-[state=open]:fade-in-90 sm:zoom-in-90 data-[state=open]:slide-in-from-bottom-10 data-[state=open]:sm:slide-in-from-bottom-0 fixed z-50 grid w-full gap-4 rounded-b-lg border p-6 shadow-lg sm:max-w-lg sm:rounded-lg',
|
<DialogOverlay className={cn(overlayClassName)} />
|
||||||
className,
|
<DialogPrimitive.Content
|
||||||
)}
|
ref={ref}
|
||||||
{...props}
|
className={cn(
|
||||||
>
|
'bg-background animate-in data-[state=open]:fade-in-90 sm:zoom-in-90 data-[state=open]:slide-in-from-bottom-10 data-[state=open]:sm:slide-in-from-bottom-0 fixed z-50 grid w-full gap-4 rounded-b-lg border p-6 shadow-lg sm:max-w-lg sm:rounded-lg',
|
||||||
{children}
|
className,
|
||||||
{!hideClose && (
|
)}
|
||||||
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
|
{...props}
|
||||||
<X className="h-4 w-4" />
|
>
|
||||||
<span className="sr-only">Close</span>
|
{children}
|
||||||
</DialogPrimitive.Close>
|
{!hideClose && (
|
||||||
)}
|
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
|
||||||
</DialogPrimitive.Content>
|
<X className="h-4 w-4" />
|
||||||
</DialogPortal>
|
<span className="sr-only">Close</span>
|
||||||
));
|
</DialogPrimitive.Close>
|
||||||
|
)}
|
||||||
|
</DialogPrimitive.Content>
|
||||||
|
</DialogPortal>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user