From d97ce6c82df19098ec2ba16a7ef316fdd38f31ec Mon Sep 17 00:00:00 2001 From: Dave Earley Date: Fri, 29 May 2026 18:53:19 +0100 Subject: [PATCH] Feature: Update React + Mantine UI --- frontend/package.json | 59 +- frontend/src/App.tsx | 6 +- .../src/components/common/Accordion/index.tsx | 4 +- .../components/common/AttendeeList/index.tsx | 2 +- .../Controls/InsertImageControl/index.tsx | 2 +- .../Extensions/ImageResizeExtension/index.tsx | 10 +- .../LiquidTokenExtension/TokenComponent.tsx | 16 +- .../Extensions/LiquidVariableExtension.tsx | 8 + .../src/components/common/Editor/index.tsx | 12 +- .../EmailTemplateEditor.module.scss | 2 +- .../EmailTemplatePreviewPane.tsx | 6 +- .../common/InlineOrderSummary/index.tsx | 2 +- .../common/QuestionsTable/index.tsx | 2 +- .../forms/CheckInListForm/index.tsx | 2 +- .../components/forms/ProductForm/index.tsx | 2 +- .../src/components/layouts/AppLayout/types.ts | 6 +- .../components/layouts/AuthLayout/index.tsx | 2 +- .../components/layouts/CheckIn/BottomNav.tsx | 3 +- .../Checkout/CheckoutThemeProvider.tsx | 16 +- .../OrganizerWebhookLogsModal/index.tsx | 2 +- .../modals/SendMessageModal/index.tsx | 3 +- .../modals/WebhookLogsModal/index.tsx | 2 +- .../components/routes/auth/Login/index.tsx | 2 +- .../Settings/Sections/SocialLinks/index.tsx | 2 +- .../product-widget/SelectProducts/index.tsx | 2 +- frontend/src/styles/global.scss | 1 + frontend/yarn.lock | 2080 +++++++++-------- 27 files changed, 1257 insertions(+), 999 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 09e15f7f65..d4c33d32a4 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,19 +23,19 @@ "@dnd-kit/utilities": "^3.2.1", "@lingui/macro": "^4.7.0", "@lingui/react": "^4.7.0", - "@mantine/carousel": "^8.0.1", - "@mantine/charts": "^8.0.1", - "@mantine/colors-generator": "^8.1.0", - "@mantine/core": "^8.0.1", - "@mantine/dates": "^8.0.1", - "@mantine/dropzone": "^8.0.1", - "@mantine/form": "^8.0.1", - "@mantine/hooks": "^8.0.1", - "@mantine/modals": "^8.0.1", - "@mantine/notifications": "^8.0.1", - "@mantine/nprogress": "^8.0.1", - "@mantine/tiptap": "^8.0.1", - "@react-pdf/renderer": "^3.3.4", + "@mantine/carousel": "^9.2.2", + "@mantine/charts": "^9.2.2", + "@mantine/colors-generator": "^9.2.2", + "@mantine/core": "^9.2.2", + "@mantine/dates": "^9.2.2", + "@mantine/dropzone": "^9.2.2", + "@mantine/form": "^9.2.2", + "@mantine/hooks": "^9.2.2", + "@mantine/modals": "^9.2.2", + "@mantine/notifications": "^9.2.2", + "@mantine/nprogress": "^9.2.2", + "@mantine/tiptap": "^9.2.2", + "@react-pdf/renderer": "^4.5.1", "@react-router/node": "^7.1.5", "@remix-run/node": "^2.16.8", "@stripe/react-stripe-js": "^2.1.1", @@ -43,18 +43,14 @@ "@tabler/icons-react": "^3.35.0", "@tanstack/react-query": "5.76.1", "@tanstack/react-table": "^8.21.3", - "@tiptap/core": "^2.7.0", - "@tiptap/extension-color": "^2.11.7", - "@tiptap/extension-image": "^2.11.5", - "@tiptap/extension-link": "^2.12.0", - "@tiptap/extension-task-item": "^2.12.0", - "@tiptap/extension-task-list": "^2.12.0", - "@tiptap/extension-text-align": "^2.12.0", - "@tiptap/extension-text-style": "^2.12.0", - "@tiptap/extension-underline": "^2.12.0", - "@tiptap/pm": "^2.7.0", - "@tiptap/react": "^2.12.0", - "@tiptap/starter-kit": "^2.12.0", + "@tiptap/core": "^3.3.0", + "@tiptap/extension-image": "^3.3.0", + "@tiptap/extension-link": "^3.3.0", + "@tiptap/extension-text-align": "^3.3.0", + "@tiptap/extension-text-style": "^3.3.0", + "@tiptap/pm": "^3.3.0", + "@tiptap/react": "^3.3.0", + "@tiptap/starter-kit": "^3.3.0", "axios": "^1.4.0", "chroma-js": "^3.1.2", "classnames": "^2.3.2", @@ -67,13 +63,13 @@ "express": "^4.19.2", "qr-scanner": "^1.4.2", "query-string": "^8.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "react": "^19.2.0", + "react-dom": "^19.2.0", "react-helmet-async": "^2.0.4", "react-qr-code": "^2.0.12", "react-router": "^7.1.5", "react-router-dom": "^7.1.5", - "recharts": "2", + "recharts": "^3", "sirv": "^2.0.4" }, "devDependencies": { @@ -82,8 +78,8 @@ "@types/express": "^4.17.21", "@types/lodash": "^4.17.0", "@types/node": "^20.12.2", - "@types/react": "^18.0.28", - "@types/react-dom": "^18.0.11", + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.0", "@typescript-eslint/eslint-plugin": "^5.57.1", "@typescript-eslint/parser": "^5.57.1", "@vitejs/plugin-react": "^4.4.1", @@ -101,5 +97,8 @@ "vite": "^5.4.19", "vite-bundle-visualizer": "^1.2.1", "vite-plugin-copy": "^0.1.6" + }, + "resolutions": { + "prosemirror-model": "^1.25.7" } } diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 88dbac4bbf..1a5a647e6c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,5 +1,5 @@ import React, {FC, PropsWithChildren, useCallback, useEffect} from "react"; -import {MantineProvider} from "@mantine/core"; +import {MantineProvider, v8CssVariablesResolver} from "@mantine/core"; import {Notifications} from "@mantine/notifications"; import {i18n} from "@lingui/core"; import {I18nProvider} from "@lingui/react"; @@ -71,6 +71,7 @@ export const App: FC< }} /> @@ -97,7 +99,7 @@ export const App: FC< {props.children} - + {showGlobalConsentBanner && ( )} diff --git a/frontend/src/components/common/Accordion/index.tsx b/frontend/src/components/common/Accordion/index.tsx index 208dd26375..522b757700 100644 --- a/frontend/src/components/common/Accordion/index.tsx +++ b/frontend/src/components/common/Accordion/index.tsx @@ -1,11 +1,11 @@ import {Accordion as MantineAccordion, Group, Text} from '@mantine/core'; -import {TablerIconsProps} from '@tabler/icons-react'; +import {Icon} from '@tabler/icons-react'; import classes from './Accordion.module.scss'; import React from "react"; export interface AccordionItem { value: string; - icon?: (props: TablerIconsProps) => JSX.Element; + icon?: Icon; title: string; count?: number; hidden?: boolean; diff --git a/frontend/src/components/common/AttendeeList/index.tsx b/frontend/src/components/common/AttendeeList/index.tsx index 6a8ebc11ba..346b4d675d 100644 --- a/frontend/src/components/common/AttendeeList/index.tsx +++ b/frontend/src/components/common/AttendeeList/index.tsx @@ -119,7 +119,7 @@ export const AttendeeList = ({order, products, refetchOrder, questionAnswers = [ {/* Collapsible answers section */} - +
{ }} title={t`Insert Image`} > - + setTab(value ?? 'url')} variant="outline"> {t`Paste URL`} {t`Upload Image`} diff --git a/frontend/src/components/common/Editor/Extensions/ImageResizeExtension/index.tsx b/frontend/src/components/common/Editor/Extensions/ImageResizeExtension/index.tsx index 9972a9ed75..27b56460f2 100644 --- a/frontend/src/components/common/Editor/Extensions/ImageResizeExtension/index.tsx +++ b/frontend/src/components/common/Editor/Extensions/ImageResizeExtension/index.tsx @@ -1,5 +1,5 @@ -import Image from '@tiptap/extension-image'; -import { NodeViewProps } from '@tiptap/react'; +import {Image} from '@tiptap/extension-image'; +import {NodeViewRendererProps} from '@tiptap/core'; /** * Adapted from https://github.com/bae-sh/tiptap-extension-resize-image/blob/main/lib/imageResize.ts @@ -22,7 +22,7 @@ export const ImageResize = Image.extend({ }, addNodeView() { - return ({ node, editor, getPos }: NodeViewProps) => { + return ({ node, editor, getPos }: NodeViewRendererProps) => { const { view, options: { editable }, @@ -89,11 +89,13 @@ export const ImageResize = Image.extend({ const dispatchNodeView = () => { if (typeof getPos === 'function') { + const pos = getPos(); + if (pos === undefined) return; const newAttrs = { ...node.attrs, style: `${$img.style.cssText}`, }; - view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, newAttrs)); + view.dispatch(view.state.tr.setNodeMarkup(pos, null, newAttrs)); } }; diff --git a/frontend/src/components/common/Editor/Extensions/LiquidTokenExtension/TokenComponent.tsx b/frontend/src/components/common/Editor/Extensions/LiquidTokenExtension/TokenComponent.tsx index 43affb9c13..726947c557 100644 --- a/frontend/src/components/common/Editor/Extensions/LiquidTokenExtension/TokenComponent.tsx +++ b/frontend/src/components/common/Editor/Extensions/LiquidTokenExtension/TokenComponent.tsx @@ -1,19 +1,9 @@ -import {NodeViewWrapper} from '@tiptap/react'; +import {NodeViewWrapper, ReactNodeViewProps} from '@tiptap/react'; import {Badge, Tooltip} from '@mantine/core'; import {IconCode} from '@tabler/icons-react'; -interface TokenComponentProps { - node: { - attrs: { - tokenName: string; - tokenDescription: string; - }; - }; - selected: boolean; -} - -export const TokenComponent = ({node, selected}: TokenComponentProps) => { - const {tokenName, tokenDescription} = node.attrs; +export const TokenComponent = ({node, selected}: ReactNodeViewProps) => { + const {tokenName, tokenDescription} = node.attrs as { tokenName: string; tokenDescription: string }; const tokenBadge = ( { + liquidVariable: { + insertLiquidVariable: (variable: string) => ReturnType; + }; + } +} + export const LiquidVariable = Node.create({ name: 'liquidVariable', diff --git a/frontend/src/components/common/Editor/index.tsx b/frontend/src/components/common/Editor/index.tsx index e19ee0325f..1cf94d81c0 100644 --- a/frontend/src/components/common/Editor/index.tsx +++ b/frontend/src/components/common/Editor/index.tsx @@ -1,11 +1,9 @@ import {Link, RichTextEditor} from "@mantine/tiptap"; import {useEditor} from "@tiptap/react"; import StarterKit from '@tiptap/starter-kit'; -import Underline from '@tiptap/extension-underline'; -import TextAlign from '@tiptap/extension-text-align'; -import Image from '@tiptap/extension-image'; -import TextStyle from '@tiptap/extension-text-style'; -import Color from '@tiptap/extension-color'; +import {TextAlign} from '@tiptap/extension-text-align'; +import {Image} from '@tiptap/extension-image'; +import {Color, TextStyle} from '@tiptap/extension-text-style'; import React, {useEffect, useState} from "react"; import {InputDescription, InputError, InputLabel, MantineFontSize} from "@mantine/core"; import classes from "./Editor.module.scss"; @@ -49,6 +47,7 @@ export const Editor = ({ const editor = useEditor({ extensions: [ StarterKit.configure({ + link: false, paragraph: { HTMLAttributes: { style: 'margin: 0.5em 0;' @@ -60,7 +59,6 @@ export const Editor = ({ } } }), - Underline, Link, TextAlign.configure({types: ['heading', 'paragraph']}), Image, @@ -86,7 +84,7 @@ export const Editor = ({ useEffect(() => { if (value && editor) { if (value !== editor.getHTML()) { - editor.commands.setContent(value, false, {preserveWhitespace: "full"}); + editor.commands.setContent(value, {emitUpdate: false, parseOptions: {preserveWhitespace: "full"}}); } const htmlLength = value.length; diff --git a/frontend/src/components/common/EmailTemplateEditor/EmailTemplateEditor.module.scss b/frontend/src/components/common/EmailTemplateEditor/EmailTemplateEditor.module.scss index beee7dfb89..a2f93ed0a1 100644 --- a/frontend/src/components/common/EmailTemplateEditor/EmailTemplateEditor.module.scss +++ b/frontend/src/components/common/EmailTemplateEditor/EmailTemplateEditor.module.scss @@ -14,7 +14,7 @@ .previewContent { padding: 1.5rem; - :global(.mantine-TypographyStylesProvider-root) { + :global(.mantine-Typography-root) { line-height: 1.6; h1, h2, h3, h4, h5, h6 { diff --git a/frontend/src/components/common/EmailTemplateEditor/EmailTemplatePreviewPane.tsx b/frontend/src/components/common/EmailTemplateEditor/EmailTemplatePreviewPane.tsx index c2f50380ad..4b84230290 100644 --- a/frontend/src/components/common/EmailTemplateEditor/EmailTemplatePreviewPane.tsx +++ b/frontend/src/components/common/EmailTemplateEditor/EmailTemplatePreviewPane.tsx @@ -1,4 +1,4 @@ -import {Alert, Divider, LoadingOverlay, Stack, Text, TypographyStylesProvider} from '@mantine/core'; +import {Alert, Divider, LoadingOverlay, Stack, Text, Typography} from '@mantine/core'; import {IconAlertCircle, IconEye} from '@tabler/icons-react'; import {Trans} from '@lingui/macro'; import classes from './EmailTemplateEditor.module.scss'; @@ -42,13 +42,13 @@ export const EmailTemplatePreviewPane = ({ )} {!error && hasContent && ( - +
- + )} {!error && !hasContent && !isLoading && ( diff --git a/frontend/src/components/common/InlineOrderSummary/index.tsx b/frontend/src/components/common/InlineOrderSummary/index.tsx index 325a527f35..d105716164 100644 --- a/frontend/src/components/common/InlineOrderSummary/index.tsx +++ b/frontend/src/components/common/InlineOrderSummary/index.tsx @@ -72,7 +72,7 @@ export const InlineOrderSummary = ({
- +
diff --git a/frontend/src/components/common/QuestionsTable/index.tsx b/frontend/src/components/common/QuestionsTable/index.tsx index 28310f5ea9..539039232c 100644 --- a/frontend/src/components/common/QuestionsTable/index.tsx +++ b/frontend/src/components/common/QuestionsTable/index.tsx @@ -287,7 +287,7 @@ const LivePreview = ({ {isOpen ? : } - +
diff --git a/frontend/src/components/forms/CheckInListForm/index.tsx b/frontend/src/components/forms/CheckInListForm/index.tsx index e90058ee0b..5eec6652d7 100644 --- a/frontend/src/components/forms/CheckInListForm/index.tsx +++ b/frontend/src/components/forms/CheckInListForm/index.tsx @@ -154,7 +154,7 @@ export const CheckInListForm = ({ {showAdvanced ? t`Hide advanced options` : t`Show advanced options`} - +