Compare commits

..

2 Commits

Author SHA1 Message Date
Lucas Smith 4eceb03ac3 fix: resolve ci failures 2026-07-21 16:23:47 +10:00
Lucas Smith 11970a3659 feat: migrate to react 19 2026-07-21 15:35:50 +10:00
37 changed files with 844 additions and 1473 deletions
-1
View File
@@ -10,7 +10,6 @@
"postinstall": "fumadocs-mdx"
},
"dependencies": {
"@radix-ui/react-tabs": "^1.1.13",
"fumadocs-core": "16.5.0",
"fumadocs-mdx": "14.2.6",
"fumadocs-ui": "16.5.0",
+1 -1
View File
@@ -16,7 +16,7 @@
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "18.3.27",
"@types/react": "^19.2.17",
"typescript": "5.6.2"
}
}
+9 -15
View File
@@ -3,7 +3,7 @@
/* Inter Variable Fonts */
@font-face {
font-family: "Inter";
src: url("/fonts/inter-variablefont_opsz,wght.woff2") format("woff2");
src: url("/fonts/inter-variablefont_opsz,wght.ttf") format("truetype-variations");
font-weight: 100 900;
font-style: normal;
font-display: swap;
@@ -12,7 +12,7 @@
/* Inter Italic Variable Fonts */
@font-face {
font-family: "Inter";
src: url("/fonts/inter-italic-variablefont_opsz,wght.woff2") format("woff2");
src: url("/fonts/inter-italic-variablefont_opsz,wght.ttf") format("truetype-variations");
font-weight: 100 900;
font-style: italic;
font-display: swap;
@@ -21,7 +21,7 @@
/* Caveat Variable Font */
@font-face {
font-family: "Caveat";
src: url("/fonts/caveat-variablefont_wght.woff2") format("woff2");
src: url("/fonts/caveat-variablefont_wght.ttf") format("truetype-variations");
font-weight: 400 600;
font-style: normal;
font-display: swap;
@@ -29,8 +29,8 @@
@font-face {
font-family: "Noto Sans";
src: url("/fonts/noto-sans.woff2") format("woff2");
font-weight: 400;
src: url("/fonts/noto-sans.ttf") format("truetype-variations");
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
@@ -38,7 +38,7 @@
/* Korean noto sans */
@font-face {
font-family: "Noto Sans Korean";
src: url("/fonts/noto-sans-korean.woff2") format("woff2");
src: url("/fonts/noto-sans-korean.ttf") format("truetype-variations");
font-weight: 100 900;
font-style: normal;
font-display: swap;
@@ -47,7 +47,7 @@
/* Japanese noto sans */
@font-face {
font-family: "Noto Sans Japanese";
src: url("/fonts/noto-sans-japanese.woff2") format("woff2");
src: url("/fonts/noto-sans-japanese.ttf") format("truetype-variations");
font-weight: 100 900;
font-style: normal;
font-display: swap;
@@ -56,19 +56,13 @@
/* Chinese noto sans */
@font-face {
font-family: "Noto Sans Chinese";
src: url("/fonts/noto-sans-chinese.woff2") format("woff2");
font-weight: 400;
src: url("/fonts/noto-sans-chinese.ttf") format("truetype-variations");
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
@layer base {
html {
@apply antialiased;
font-optical-sizing: auto;
font-synthesis: style;
}
:root {
--font-sans: "Inter";
--font-signature: "Caveat";
@@ -71,7 +71,7 @@ export const Header = ({ className, ...props }: HeaderProps) => {
<InboxIcon className="h-5 w-5 flex-shrink-0 text-muted-foreground transition-colors hover:text-foreground" />
{unreadCountData && unreadCountData.count > 0 && (
<span className="absolute -top-1.5 -right-1.5 flex h-5 min-w-5 items-center justify-center rounded-full bg-primary px-1 font-semibold text-primary-foreground text-xs tabular-nums leading-none">
<span className="absolute -top-1.5 -right-1.5 flex h-5 w-5 items-center justify-center rounded-full bg-primary font-semibold text-[10px] text-primary-foreground">
{unreadCountData.count > 99 ? '99+' : unreadCountData.count}
</span>
)}
@@ -94,7 +94,7 @@ export const AppNavMobile = ({ isMenuOpen, onMenuOpenChange }: AppNavMobileProps
>
{text}
{href === '/inbox' && unreadCountData && unreadCountData.count > 0 && (
<span className="flex h-6 min-w-[1.5rem] items-center justify-center rounded-full bg-primary px-1.5 font-semibold text-primary-foreground text-xs tabular-nums">
<span className="flex h-6 min-w-[1.5rem] items-center justify-center rounded-full bg-primary px-1.5 font-semibold text-primary-foreground text-xs">
{unreadCountData.count > 99 ? '99+' : unreadCountData.count}
</span>
)}
@@ -146,14 +146,17 @@ export const DocumentSigningRadioField = ({ field, onSignField, onUnsignField }:
{isLoading && <DocumentSigningFieldsLoader />}
{!field.inserted && (
<RadioGroup onValueChange={(value) => handleSelectItem(value)} className="z-10 my-0.5 gap-y-1">
<RadioGroup
value={selectedOption}
onValueChange={(value) => handleSelectItem(value)}
className="z-10 my-0.5 gap-y-1"
>
{values?.map((item, index) => (
<div key={index} className="flex items-center">
<RadioGroupItem
className="h-3 w-3 shrink-0"
value={item.value}
id={`option-${field.id}-${item.id}`}
checked={item.checked}
disabled={isReadOnly}
/>
{!item.value.includes('empty-value-') && item.value && (
@@ -167,14 +170,13 @@ export const DocumentSigningRadioField = ({ field, onSignField, onUnsignField }:
)}
{field.inserted && (
<RadioGroup className="my-0.5 gap-y-1">
<RadioGroup value={field.customText ?? ''} className="my-0.5 gap-y-1">
{values?.map((item, index) => (
<div key={index} className="flex items-center">
<RadioGroupItem
className="h-3 w-3"
value={item.value}
id={`option-${field.id}-${item.id}`}
checked={item.value === field.customText}
disabled={isReadOnly}
/>
{!item.value.includes('empty-value-') && item.value && (
@@ -29,7 +29,7 @@ export const CardMetric = ({ icon: Icon, title, value, className, children }: Ca
</div>
{children || (
<p className="mt-auto font-semibold text-4xl text-foreground tabular-nums leading-8">
<p className="mt-auto font-semibold text-4xl text-foreground leading-8">
{typeof value === 'number' ? value.toLocaleString('en-US') : value}
</p>
)}
@@ -215,7 +215,7 @@ export default function PDFViewer({
type VirtualizedPageListProps = {
scrollParentRef: ScrollTarget;
constraintRef: React.RefObject<HTMLDivElement>;
constraintRef: React.RefObject<HTMLDivElement | null>;
pages: PageMeta[];
numPages: number;
pdf: pdfjsLib.PDFDocumentProxy;
@@ -13,12 +13,10 @@ export const SettingsHeader = ({ children, title, subtitle, className, hideDivid
return (
<>
<div className={cn('flex flex-row items-center justify-between', className)}>
<div className="min-w-0">
<h3 className="font-medium text-lg leading-tight [text-wrap:balance]">{title}</h3>
<div>
<h3 className="font-medium text-lg">{title}</h3>
<p className="mt-1 max-w-[65ch] text-muted-foreground text-sm leading-normal [overflow-wrap:break-word] [text-wrap:pretty] md:mt-2">
{subtitle}
</p>
<p className="text-muted-foreground text-sm md:mt-2">{subtitle}</p>
</div>
{children}
+21
View File
@@ -31,6 +31,26 @@ function initPosthog() {
}
}
/**
* Surfaces hydration recoveries (React 19 discards the server HTML and
* re-renders on the client instead of dying) so we can track how often
* extensions/early clicks interfere with hydration in the wild.
*/
function onRecoverableError(error: unknown, errorInfo: { componentStack?: string }) {
console.error('[hydration] recovered from error', error, errorInfo.componentStack);
if (extractPostHogConfig()) {
void import('posthog-js').then(({ default: posthog }) => {
if (posthog.__loaded) {
posthog.capture('$hydration_recoverable_error', {
message: error instanceof Error ? error.message : String(error),
componentStack: errorInfo.componentStack,
});
}
});
}
}
async function main() {
const locale = detect(fromHtmlTag('lang')) || 'en';
@@ -44,6 +64,7 @@ async function main() {
<HydratedRouter />
</I18nProvider>
</StrictMode>,
{ onRecoverableError },
);
});
@@ -143,9 +143,9 @@ export default function DocumentsPage() {
<AvatarFallback className="text-muted-foreground text-xs">{team.name.slice(0, 1)}</AvatarFallback>
</Avatar>
<h1 className="font-semibold text-2xl leading-tight tracking-tight md:text-3xl">
<h2 className="font-semibold text-4xl">
<Trans>Documents</Trans>
</h1>
</h2>
</div>
<div className="-m-1 flex flex-wrap gap-x-4 gap-y-6 overflow-hidden p-1">
@@ -172,7 +172,7 @@ export default function DocumentsPage() {
<DocumentStatus status={value} />
{value !== ExtendedDocumentStatus.ALL && (
<span className="ml-1 inline-block tabular-nums opacity-50">
<span className="ml-1 inline-block opacity-50">
{stats[value] >= STATS_COUNT_CAP ? `${STATS_COUNT_CAP.toLocaleString()}+` : stats[value]}
</span>
)}
@@ -101,7 +101,7 @@ export default function TemplatesPage() {
<AvatarFallback className="text-muted-foreground text-xs">{team.name.slice(0, 1)}</AvatarFallback>
</Avatar>
<h1 className="font-semibold text-2xl leading-tight tracking-tight md:text-3xl">
<h1 className="truncate font-semibold text-2xl md:text-3xl">
<Trans>Templates</Trans>
</h1>
</div>
@@ -131,15 +131,15 @@ export default function TemplatesPage() {
<div className="mt-8">
{activeQuery.data && activeQuery.data.count === 0 ? (
<div className="flex h-96 flex-col items-center justify-center gap-y-4">
<Bird className="h-12 w-12 text-muted-foreground/60" strokeWidth={1.5} />
<div className="flex h-96 flex-col items-center justify-center gap-y-4 text-muted-foreground/60">
<Bird className="h-12 w-12" strokeWidth={1.5} />
<div className="text-center">
<h3 className="font-semibold text-foreground text-lg">
<h3 className="font-semibold text-lg">
<Trans>We're all empty</Trans>
</h3>
<p className="mt-2 max-w-[50ch] text-muted-foreground [text-wrap:pretty]">
<p className="mt-2 max-w-[50ch]">
{isOrgView ? (
<Trans>No organisation templates are shared with your team yet.</Trans>
) : (
+4 -4
View File
@@ -57,9 +57,9 @@
"papaparse": "^5.5.3",
"posthog-js": "^1.297.2",
"posthog-node": "4.18.0",
"react": "^18",
"react": "^19.2.7",
"react-call": "^1.8.1",
"react-dom": "^18",
"react-dom": "^19.2.7",
"react-dropzone": "^14.3.8",
"react-hook-form": "^7.66.1",
"react-hotkeys-hook": "^4.6.2",
@@ -93,8 +93,8 @@
"@types/luxon": "^3.7.1",
"@types/node": "^20",
"@types/papaparse": "^5.5.0",
"@types/react": "18.3.27",
"@types/react-dom": "^18",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@types/ua-parser-js": "^0.7.39",
"cross-env": "^10.1.0",
"esbuild": "^0.27.0",
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+703 -1353
View File
File diff suppressed because it is too large Load Diff
+38 -4
View File
@@ -48,14 +48,16 @@
},
"devDependencies": {
"@biomejs/biome": "2.4.8",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@commitlint/cli": "^20.1.0",
"@commitlint/config-conventional": "^20.0.0",
"@datadog/pprof": "^5.13.5",
"@lingui/cli": "^5.6.0",
"@prisma/client": "^6.19.0",
"@trpc/client": "11.8.1",
"@trpc/react-query": "11.8.1",
"@trpc/server": "11.8.1",
"@trpc/client": "11.17.0",
"@trpc/react-query": "11.17.0",
"@trpc/server": "11.17.0",
"@ts-rest/core": "^3.52.1",
"@ts-rest/open-api": "^3.52.1",
"@ts-rest/serverless": "^3.52.1",
@@ -92,12 +94,40 @@
"@lingui/conf": "^5.6.0",
"@lingui/core": "^5.6.0",
"@prisma/extension-read-replicas": "^0.4.1",
"@radix-ui/react-accordion": "^1.2.16",
"@radix-ui/react-alert-dialog": "^1.1.19",
"@radix-ui/react-aspect-ratio": "^1.1.11",
"@radix-ui/react-avatar": "^1.2.2",
"@radix-ui/react-checkbox": "^1.3.7",
"@radix-ui/react-collapsible": "^1.1.16",
"@radix-ui/react-context-menu": "^2.3.3",
"@radix-ui/react-dialog": "^1.1.19",
"@radix-ui/react-dropdown-menu": "^2.1.20",
"@radix-ui/react-hover-card": "^1.1.19",
"@radix-ui/react-label": "^2.1.11",
"@radix-ui/react-menubar": "^1.1.20",
"@radix-ui/react-navigation-menu": "^1.2.18",
"@radix-ui/react-popover": "^1.1.19",
"@radix-ui/react-progress": "^1.1.12",
"@radix-ui/react-radio-group": "^1.4.3",
"@radix-ui/react-scroll-area": "^1.2.14",
"@radix-ui/react-select": "^2.3.3",
"@radix-ui/react-separator": "^1.1.11",
"@radix-ui/react-slider": "^1.4.3",
"@radix-ui/react-slot": "^1.3.0",
"@radix-ui/react-switch": "^1.3.3",
"@radix-ui/react-tabs": "^1.1.17",
"@radix-ui/react-toast": "^1.2.19",
"@radix-ui/react-toggle": "^1.1.14",
"@radix-ui/react-toggle-group": "^1.1.15",
"@radix-ui/react-tooltip": "^1.2.12",
"ai": "^5.0.104",
"cron-parser": "^5.5.0",
"luxon": "^3.7.2",
"patch-package": "^8.0.1",
"posthog-node": "4.18.0",
"react": "^18",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"typescript": "5.6.2",
"@marsidev/react-turnstile": "^1.5.0",
"zod": "^3.25.76"
@@ -106,6 +136,10 @@
"lodash": "4.18.1",
"pdfjs-dist": "5.4.296",
"postcss": "^8.5.19",
"react": "$react",
"react-dom": "$react-dom",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"typescript": "5.6.2",
"zod": "$zod",
"fumadocs-mdx": {
+1 -1
View File
@@ -19,7 +19,7 @@
"arctic": "^3.7.0",
"hono": "^4.12.14",
"luxon": "^3.7.2",
"react": "^18",
"react": "^19.2.7",
"ts-pattern": "^5.9.0",
"zod": "^3.25.76"
}
+19 -19
View File
@@ -19,25 +19,25 @@
"dependencies": {
"@documenso/nodemailer-resend": "5.0.0",
"@documenso/tailwind-config": "*",
"@react-email/body": "0.2.0",
"@react-email/button": "0.2.0",
"@react-email/code-block": "0.2.0",
"@react-email/code-inline": "0.0.5",
"@react-email/column": "0.0.13",
"@react-email/container": "0.0.15",
"@react-email/font": "0.0.9",
"@react-email/head": "0.0.12",
"@react-email/heading": "0.0.15",
"@react-email/hr": "0.0.11",
"@react-email/html": "0.0.11",
"@react-email/img": "0.0.11",
"@react-email/link": "0.0.12",
"@react-email/preview": "0.0.13",
"@react-email/render": "2.0.0",
"@react-email/row": "0.0.12",
"@react-email/section": "0.0.16",
"@react-email/tailwind": "^2.0.1",
"@react-email/text": "0.1.5",
"@react-email/body": "0.3.0",
"@react-email/button": "0.2.1",
"@react-email/code-block": "0.2.1",
"@react-email/code-inline": "0.0.6",
"@react-email/column": "0.0.14",
"@react-email/container": "0.0.16",
"@react-email/font": "0.0.10",
"@react-email/head": "0.0.13",
"@react-email/heading": "0.0.16",
"@react-email/hr": "0.0.12",
"@react-email/html": "0.0.12",
"@react-email/img": "0.0.12",
"@react-email/link": "0.0.13",
"@react-email/preview": "0.0.14",
"@react-email/render": "2.0.10",
"@react-email/row": "0.0.13",
"@react-email/section": "0.0.17",
"@react-email/tailwind": "^2.0.7",
"@react-email/text": "0.1.6",
"nodemailer": "^9.0.0",
"react-email": "^5.0.6",
"resend": "^6.5.2"
@@ -8,7 +8,7 @@ type SaveRequest<T, R> = {
export const useAutoSave = <T, R = void>(onSave: (data: T) => Promise<R>, options: { delay?: number } = {}) => {
const { delay = 2000 } = options;
const saveTimeoutRef = useRef<NodeJS.Timeout>();
const saveTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
const saveQueueRef = useRef<SaveRequest<T, R>[]>([]);
const isProcessingRef = useRef(false);
+1 -1
View File
@@ -64,7 +64,7 @@
"postcss-selector-parser": "^7.1.4",
"posthog-js": "^1.297.2",
"posthog-node": "4.18.0",
"react": "^18",
"react": "^19.2.7",
"remeda": "^2.32.0",
"sharp": "0.34.5",
"skia-canvas": "^3.0.8",
+3 -3
View File
@@ -12,9 +12,9 @@
"@documenso/prisma": "*",
"@simplewebauthn/server": "^13.2.2",
"@tanstack/react-query": "5.90.10",
"@trpc/client": "11.8.1",
"@trpc/react-query": "11.8.1",
"@trpc/server": "11.8.1",
"@trpc/client": "11.17.0",
"@trpc/react-query": "11.17.0",
"@trpc/server": "11.17.0",
"@ts-rest/core": "^3.52.1",
"formidable": "^3.5.4",
"luxon": "^3.7.2",
+1 -1
View File
@@ -35,7 +35,7 @@ export const SigningCard3D = ({ className, name, signature, signingCelebrationIm
const [trackMouse, setTrackMouse] = useState(false);
const timeoutRef = useRef<number | undefined>();
const timeoutRef = useRef<number | undefined>(undefined);
const cardX = useMotionValue(0);
const cardY = useMotionValue(0);
+7 -34
View File
@@ -18,59 +18,32 @@
"@documenso/tailwind-config": "*",
"@documenso/tsconfig": "*",
"@types/luxon": "^3.7.1",
"@types/react": "18.3.27",
"@types/react-dom": "^18",
"react": "^18",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"react": "^19.2.7",
"typescript": "5.6.2"
},
"dependencies": {
"@documenso/lib": "*",
"@hello-pangea/dnd": "^16.6.0",
"@hello-pangea/dnd": "^18.0.1",
"@hookform/resolvers": "^3",
"@lingui/macro": "^5.6.0",
"@lingui/react": "^5.6.0",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-aspect-ratio": "^1.1.8",
"@radix-ui/react-avatar": "^1.1.11",
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-context-menu": "^2.2.16",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-hover-card": "^1.1.15",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-menubar": "^1.1.16",
"@radix-ui/react-navigation-menu": "^1.2.14",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-progress": "^1.1.8",
"@radix-ui/react-radio-group": "^1.3.8",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slider": "^1.3.6",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-toast": "^1.2.15",
"@radix-ui/react-toggle": "^1.1.10",
"@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.8",
"@scure/base": "^1.2.6",
"@tanstack/react-table": "^8.21.3",
"class-variance-authority": "^0.7.1",
"clsx": "^1.2.1",
"cmdk": "^0.2.1",
"cmdk": "^1.1.1",
"colord": "^2.9.3",
"framer-motion": "^12.23.24",
"lucide-react": "^0.554.0",
"luxon": "^3.7.2",
"pdfjs-dist": "5.4.296",
"perfect-freehand": "^1.2.2",
"react": "^18",
"react": "^19.2.7",
"react-colorful": "^5.6.1",
"react-day-picker": "^8.10.1",
"react-dom": "^18",
"react-dom": "^19.2.7",
"react-hook-form": "^7.66.1",
"react-rnd": "^10.5.2",
"remeda": "^2.32.0",
+2 -2
View File
@@ -7,7 +7,7 @@ import * as React from 'react';
import { cn } from '../lib/utils';
const buttonVariants = cva(
'inline-flex select-none items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
{
variants: {
variant: {
@@ -17,7 +17,7 @@ const buttonVariants = cva(
outline: 'border border-input hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'underline-offset-4 hover:underline text-primary [text-decoration-skip-ink:auto] [text-decoration-thickness:from-font] [text-underline-position:from-font]',
link: 'underline-offset-4 hover:underline text-primary',
none: '',
},
size: {
+3 -1
View File
@@ -145,7 +145,9 @@ const CommandItem = React.forwardRef<
<CommandPrimitive.Item
ref={ref}
className={cn(
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
// cmdk 1.x always renders data-disabled="true|false", so the variant must
// check the value (bare data-[disabled] matches attribute presence).
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50',
className,
)}
{...props}
@@ -22,7 +22,7 @@ export function DataTablePagination<TData>({
additionalInformation = 'VisibleCount',
}: DataTablePaginationProps<TData>) {
return (
<div className="flex flex-wrap items-center justify-between gap-x-4 gap-y-4 px-2 tabular-nums">
<div className="flex flex-wrap items-center justify-between gap-x-4 gap-y-4 px-2">
<div className="flex-1 text-muted-foreground text-sm">
{match(additionalInformation)
.with('SelectedCount', () => (
@@ -103,15 +103,10 @@ export const FieldContent = ({ field, documentMeta }: FieldIconProps) => {
) {
return (
<div className="flex flex-col gap-y-2 py-0.5">
<RadioGroup className="gap-y-1">
<RadioGroup value={field.customText ?? ''} className="gap-y-1">
{field.fieldMeta.values.map((item, index) => (
<div key={index} className="flex items-center">
<RadioGroupItem
className="pointer-events-none h-3 w-3"
value={item.value}
id={`option-${index}`}
checked={item.value === field.customText}
/>
<RadioGroupItem className="pointer-events-none h-3 w-3" value={item.value} id={`option-${index}`} />
{item.value && (
<Label htmlFor={`option-${index}`} className="ml-1.5 font-normal text-foreground text-xs">
{item.value}
@@ -1,5 +1,6 @@
import type { RecipientRole } from '@prisma/client';
import { BadgeCheck, Copy, Eye, PencilLine, User } from 'lucide-react';
import type { JSX } from 'react';
export const ROLE_ICONS: Record<RecipientRole, JSX.Element> = {
SIGNER: <PencilLine className="h-4 w-4" />,
@@ -13,7 +13,7 @@ import { getSvgPathFromStroke } from './helper';
import { Point } from './point';
import { SignaturePadColorPicker } from './signature-pad-color-picker';
const checkSignatureValidity = (element: RefObject<HTMLCanvasElement>) => {
const checkSignatureValidity = (element: RefObject<HTMLCanvasElement | null>) => {
if (!element.current) {
return false;
}
+1 -1
View File
@@ -8,7 +8,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({ classNa
return (
<textarea
className={cn(
'flex h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
'flex h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className,
{
'!ring-destructive ring-2 transition-all': props['aria-invalid'],
+3 -1
View File
@@ -195,7 +195,9 @@
body {
@apply bg-background text-foreground;
font-variant-ligatures: common-ligatures contextual;
font-feature-settings:
"rlig" 1,
"calt" 1;
}
}