diff --git a/frontend/bun.lockb b/frontend/bun.lockb index c4d29610b..a1ca63c27 100755 Binary files a/frontend/bun.lockb and b/frontend/bun.lockb differ diff --git a/frontend/package.json b/frontend/package.json index 472f76af9..3ab8b8075 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,60 +13,53 @@ "license": "MIT", "devDependencies": { "@biomejs/biome": "1.9.4", - "@happy-dom/global-registrator": "16.5.2", + "@happy-dom/global-registrator": "16.7.3", "@testing-library/dom": "10.4.0", "@testing-library/jest-dom": "6.6.3", - "@testing-library/react": "16.1.0", - "@types/bun": "1.1.15", - "@types/react": "19.0.3", - "@types/react-dom": "19.0.2", + "@testing-library/react": "16.2.0", + "@types/bun": "1.2.1", + "@types/qs": "6.9.18", + "@types/react": "19.0.8", + "@types/react-dom": "19.0.3", "@types/react-redux": "7.1.34", "@vitejs/plugin-react": "4.3.4", - "typescript": "5.7.2", - "vite": "6.0.7", + "typescript": "5.7.3", + "vite": "6.0.11", "vite-tsconfig-paths": "5.1.4" }, "dependencies": { - "@grafana/faro-react": "1.12.2", - "@grafana/faro-web-sdk": "1.12.2", - "@grafana/faro-web-tracing": "1.12.2", - "@hocuspocus/provider": "2.15.0", - "@navikt/aksel-icons": "7.9.1", - "@navikt/ds-css": "7.9.1", - "@navikt/ds-react": "7.9.1", + "@grafana/faro-react": "1.12.3", + "@grafana/faro-web-sdk": "1.12.3", + "@grafana/faro-web-tracing": "1.12.3", + "@navikt/aksel-icons": "7.10.0", + "@navikt/ds-css": "7.10.0", + "@navikt/ds-react": "7.10.0", "@navikt/fnrvalidator": "2.1.5", - "@reduxjs/toolkit": "2.5.0", + "@reduxjs/toolkit": "2.5.1", "@slate-yjs/core": "1.0.2", - "@slate-yjs/react": "1.1.0", "@styled-icons/fluentui-system-regular": "10.47.0", - "@types/qs": "6.9.17", - "@udecode/plate": "41.0.14", - "@udecode/plate-alignment": "41.0.0", - "@udecode/plate-autoformat": "41.0.0", - "@udecode/plate-basic-marks": "41.0.0", - "@udecode/plate-break": "41.0.0", - "@udecode/plate-common": "41.0.13", - "@udecode/plate-core": "41.0.13", - "@udecode/plate-cursor": "41.0.0", - "@udecode/plate-docx": "41.0.10", - "@udecode/plate-font": "41.0.12", - "@udecode/plate-heading": "41.0.0", - "@udecode/plate-indent": "41.0.0", - "@udecode/plate-list": "41.0.0", - "@udecode/plate-resizable": "41.0.0", - "@udecode/plate-table": "41.0.9", - "@udecode/plate-yjs": "41.0.0", - "@udecode/slate-react": "41.0.5", - "qs": "6.13.1", + "@udecode/plate": "43.0.5", + "@udecode/plate-alignment": "43.0.0", + "@udecode/plate-autoformat": "43.0.0", + "@udecode/plate-basic-marks": "43.0.1", + "@udecode/plate-break": "43.0.0", + "@udecode/plate-core": "43.0.5", + "@udecode/plate-cursor": "43.0.0", + "@udecode/plate-docx": "43.0.5", + "@udecode/plate-heading": "43.0.0", + "@udecode/plate-indent": "43.0.0", + "@udecode/plate-list": "43.0.0", + "@udecode/plate-node-id": "43.0.3", + "@udecode/plate-resizable": "43.0.0", + "@udecode/plate-table": "43.0.3", + "@udecode/plate-yjs": "43.0.0", + "qs": "6.14.0", "react": "19.0.0", "react-dom": "19.0.0", "react-redux": "9.2.0", - "react-router": "7.1.1", - "react-router-dom": "7.1.1", - "slate": "0.112.0", - "slate-history": "0.110.3", - "slate-react": "0.112.0", + "react-router": "7.1.3", + "react-router-dom": "7.1.3", "styled-components": "6.1.14", - "yjs": "13.6.21" + "yjs": "13.6.23" } } diff --git a/frontend/src/components/malteksteksjon-references/preview.tsx b/frontend/src/components/malteksteksjon-references/preview.tsx index bbc439c4e..6fbe93a01 100644 --- a/frontend/src/components/malteksteksjon-references/preview.tsx +++ b/frontend/src/components/malteksteksjon-references/preview.tsx @@ -12,7 +12,7 @@ import type { IMaltekstseksjon } from '@app/types/maltekstseksjoner/responses'; import type { IRichText, IText } from '@app/types/texts/responses'; import { Heading, Loader } from '@navikt/ds-react'; import { skipToken } from '@reduxjs/toolkit/query'; -import { Plate, usePlateEditor } from '@udecode/plate-common/react'; +import { Plate, usePlateEditor } from '@udecode/plate/react'; import { useCallback, useEffect, useState } from 'react'; import { styled } from 'styled-components'; diff --git a/frontend/src/components/maltekstseksjoner/texts/text-draft/text-draft.tsx b/frontend/src/components/maltekstseksjoner/texts/text-draft/text-draft.tsx index 7bdc88d1a..655dfa67d 100644 --- a/frontend/src/components/maltekstseksjoner/texts/text-draft/text-draft.tsx +++ b/frontend/src/components/maltekstseksjoner/texts/text-draft/text-draft.tsx @@ -16,8 +16,6 @@ import { RichTextTypes } from '@app/types/common-text-types'; import { LANGUAGES, type Language, isLanguage } from '@app/types/texts/language'; import type { IDraftRichText } from '@app/types/texts/responses'; import { BodyShort, HStack, HelpText, Label, Loader, Switch, Tooltip, VStack } from '@navikt/ds-react'; -import { getEndPoint } from '@udecode/plate-common'; -import { focusEditor, isEditorFocused } from '@udecode/plate-common/react'; import { useCallback, useEffect, useRef, useState } from 'react'; import { areDescendantsEqual } from '../../../../functions/are-descendants-equal'; @@ -50,10 +48,10 @@ export const DraftText = ({ text, isActive, setActive, ...rest }: Props) => { }, [text.richText]); useEffect(() => { - if (isActive && editorRef.current !== null && !isEditorFocused(editorRef.current)) { + if (isActive && editorRef.current !== null && !editorRef.current.api.isFocused()) { setTimeout(() => { if (editorRef.current !== null) { - focusEditor(editorRef.current, getEndPoint(editorRef.current, [])); + editorRef.current.tf.focus({ at: editorRef.current.api.end([]) }); } }, 0); } diff --git a/frontend/src/components/smart-editor/bookmarks/bookmarks.tsx b/frontend/src/components/smart-editor/bookmarks/bookmarks.tsx index de74a2205..6b146abec 100644 --- a/frontend/src/components/smart-editor/bookmarks/bookmarks.tsx +++ b/frontend/src/components/smart-editor/bookmarks/bookmarks.tsx @@ -5,8 +5,7 @@ import { BookmarkPlugin } from '@app/plate/plugins/bookmark'; import { type FormattedText, useMyPlateEditorState } from '@app/plate/types'; import { BookmarkFillIcon, TrashIcon } from '@navikt/aksel-icons'; import { Button } from '@navikt/ds-react'; -import { type TNode, getNodeString, unsetNodes } from '@udecode/plate-common'; -import { toDOMNode } from '@udecode/plate-common/react'; +import { NodeApi, type TNode } from '@udecode/plate'; import { styled } from 'styled-components'; interface Props { @@ -21,7 +20,7 @@ export const Bookmarks = ({ editorId }: Props) => { return null; } - const onClick = (node: TNode) => toDOMNode(editor, node)?.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + const onClick = (node: TNode) => editor.api.toDOMNode(node)?.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); return ( @@ -38,7 +37,7 @@ export const Bookmarks = ({ editorId }: Props) => { return null; } - const content = nodes.map((n) => getNodeString(n)).join(''); + const content = nodes.map((n) => NodeApi.string(n)).join(''); return ( @@ -56,7 +55,7 @@ export const Bookmarks = ({ editorId }: Props) => { variant="tertiary-neutral" onClick={() => { pushEvent('remove-bookmark', 'smart-editor'); - unsetNodes(editor, [BookmarkPlugin.key, key], { + editor.tf.unsetNodes([BookmarkPlugin.key, key], { match: (n) => hasOwn(n, key), mode: 'lowest', at: [], diff --git a/frontend/src/components/smart-editor/bookmarks/positioned.tsx b/frontend/src/components/smart-editor/bookmarks/positioned.tsx index fe052d3b3..0c5aa8c22 100644 --- a/frontend/src/components/smart-editor/bookmarks/positioned.tsx +++ b/frontend/src/components/smart-editor/bookmarks/positioned.tsx @@ -12,7 +12,6 @@ import { BASE_FONT_SIZE } from '@app/plate/components/get-scaled-em'; import { useMyPlateEditorRef } from '@app/plate/types'; import { BookmarkFillIcon, TrashFillIcon } from '@navikt/aksel-icons'; import { Tooltip } from '@navikt/ds-react'; -import { setNodes } from '@udecode/plate-common'; import { useCallback, useContext, useMemo, useState } from 'react'; import { styled } from 'styled-components'; @@ -43,7 +42,7 @@ export const PositionedBookmarks = () => { const onDelete = useCallback( (id: string) => { pushEvent('remove-bookmark', 'smart-editor'); - setNodes(editorRef, { [id]: undefined }, { match: (n) => id in n, mode: 'lowest', at: [] }); + editorRef.tf.setNodes({ [id]: undefined }, { match: (n) => id in n, mode: 'lowest', at: [] }); }, [editorRef], ); diff --git a/frontend/src/components/smart-editor/bookmarks/use-bookmarks.ts b/frontend/src/components/smart-editor/bookmarks/use-bookmarks.ts index ce8f2b5cb..c10bead20 100644 --- a/frontend/src/components/smart-editor/bookmarks/use-bookmarks.ts +++ b/frontend/src/components/smart-editor/bookmarks/use-bookmarks.ts @@ -1,12 +1,12 @@ import { BOOKMARK_PREFIX } from '@app/components/smart-editor/constants'; import { type FormattedText, useMyPlateEditorState } from '@app/plate/types'; -import { isText } from '@udecode/plate-common'; +import { TextApi } from '@udecode/plate'; export const useBookmarks = (): [string, FormattedText[]][] => { const editor = useMyPlateEditorState(); const bookmarkEntries = editor.nodes({ - match: (n) => isText(n) && Object.keys(n).some((k) => k.startsWith(BOOKMARK_PREFIX)), + match: (n) => TextApi.isText(n) && Object.keys(n).some((k) => k.startsWith(BOOKMARK_PREFIX)), at: [], }); diff --git a/frontend/src/components/smart-editor/comments/connect-thread.ts b/frontend/src/components/smart-editor/comments/connect-thread.ts index 7590f8477..3017a2cb7 100644 --- a/frontend/src/components/smart-editor/comments/connect-thread.ts +++ b/frontend/src/components/smart-editor/comments/connect-thread.ts @@ -1,15 +1,14 @@ import { COMMENT_PREFIX } from '@app/components/smart-editor/constants'; import { CommentsPlugin } from '@app/plate/plugins/comments'; import type { RichTextEditor, RootElement } from '@app/plate/types'; -import { isText, setNodes, unsetNodes } from '@udecode/plate-common'; +import { TextApi } from '@udecode/plate'; import type { Selection } from 'slate'; export const connectCommentThread = (editor: RichTextEditor, selection: Selection, threadId: string) => { - setNodes( - editor, + editor.tf.setNodes( { [CommentsPlugin.key]: true, [COMMENT_PREFIX + threadId]: true }, { - match: isText, + match: TextApi.isText, mode: 'lowest', split: true, hanging: true, @@ -21,7 +20,7 @@ export const connectCommentThread = (editor: RichTextEditor, selection: Selectio export const disconnectCommentThread = (editor: RichTextEditor, threadId: string) => { const key = COMMENT_PREFIX + threadId; - unsetNodes(editor, key, { + editor.tf.unsetNodes(key, { match: (node) => Object.hasOwn(node, key), split: true, at: [], diff --git a/frontend/src/components/smart-editor/comments/expandable-thread.tsx b/frontend/src/components/smart-editor/comments/expandable-thread.tsx index 4a4e7da74..bfc5abf3c 100644 --- a/frontend/src/components/smart-editor/comments/expandable-thread.tsx +++ b/frontend/src/components/smart-editor/comments/expandable-thread.tsx @@ -3,8 +3,6 @@ import { SmartEditorContext } from '@app/components/smart-editor/context'; import { useOnClickOutside } from '@app/hooks/use-on-click-outside'; import { useMyPlateEditorRef } from '@app/plate/types'; import type { ISmartEditorComment } from '@app/types/smart-editor/comments'; -import { findNode } from '@udecode/plate-common'; -import { toDOMNode } from '@udecode/plate-common/react'; import { useCallback, useContext, useEffect, useRef } from 'react'; import { COMMENT_PREFIX } from '../constants'; @@ -44,14 +42,14 @@ export const ExpandableThread = ({ thread, isFocused, style, isOrphan = false, i return; } - const leafEntry = findNode(editor, { at: [], match: { [`${COMMENT_PREFIX}${thread.id}`]: true } }); + const leafEntry = editor.api.node({ at: [], match: { [`${COMMENT_PREFIX}${thread.id}`]: true } }); if (leafEntry === undefined) { return; } const [leafNode] = leafEntry; - const domNode = toDOMNode(editor, leafNode); + const domNode = editor.api.toDOMNode(leafNode); if (domNode === undefined) { return; diff --git a/frontend/src/components/smart-editor/comments/new-comment.tsx b/frontend/src/components/smart-editor/comments/new-comment.tsx index 5822656e3..abe0d16b0 100644 --- a/frontend/src/components/smart-editor/comments/new-comment.tsx +++ b/frontend/src/components/smart-editor/comments/new-comment.tsx @@ -8,8 +8,7 @@ import { useGetMySignatureQuery } from '@app/redux-api/bruker'; import { usePostCommentMutation } from '@app/redux-api/smart-editor-comments'; import { Loader } from '@navikt/ds-react'; import { skipToken } from '@reduxjs/toolkit/query'; -import { isCollapsed } from '@udecode/plate-common'; -import { focusEditor } from '@udecode/plate-common/react'; +import { RangeApi } from '@udecode/plate'; import { useCallback, useContext, useEffect, useRef } from 'react'; import { StyledNewThread } from './styled-components'; import { WriteComment } from './write-comment/write-comment'; @@ -31,7 +30,7 @@ export const NewComment = ({ container }: Props) => { const onNewThread = useCallback( (threadId: string) => { - if (editor === null || newCommentSelection === null || isCollapsed(newCommentSelection)) { + if (editor === null || newCommentSelection === null || RangeApi.isCollapsed(newCommentSelection)) { return; } @@ -72,14 +71,14 @@ export const NewComment = ({ container }: Props) => { setNewCommentSelection(null); setTimeout(() => { setFocusedThreadId(id); - focusEditor(editor); + editor.tf.focus(); }, 0); }); }; const close = () => { setNewCommentSelection(null); - focusEditor(editor); + editor.tf.focus(); }; return ( diff --git a/frontend/src/components/smart-editor/comments/use-threads.ts b/frontend/src/components/smart-editor/comments/use-threads.ts index 23d020ae2..d4b4ce278 100644 --- a/frontend/src/components/smart-editor/comments/use-threads.ts +++ b/frontend/src/components/smart-editor/comments/use-threads.ts @@ -5,8 +5,9 @@ import { useMyPlateEditorState } from '@app/plate/types'; import { useGetCommentsQuery } from '@app/redux-api/smart-editor-comments'; import type { ISmartEditorComment } from '@app/types/smart-editor/comments'; import { skipToken } from '@reduxjs/toolkit/query'; +import { ElementApi } from '@udecode/plate'; import { useContext, useMemo } from 'react'; -import { type Descendant, Text } from 'slate'; +import type { Descendant } from 'slate'; import { COMMENT_PREFIX } from '../constants'; export interface FocusedComment extends ISmartEditorComment { @@ -73,7 +74,7 @@ export const useThreads = (): Threads => { const getRichTextThreadIds = (richText: Descendant[]): string[] => richText.flatMap((child) => { - if (Text.isText(child)) { + if (!ElementApi.isElement(child)) { return Object.keys(child) .filter((key) => key.startsWith(COMMENT_PREFIX)) .map((key) => key.replace(COMMENT_PREFIX, '')); diff --git a/frontend/src/components/smart-editor/context.tsx b/frontend/src/components/smart-editor/context.tsx index 089b969c6..3c58326b7 100644 --- a/frontend/src/components/smart-editor/context.tsx +++ b/frontend/src/components/smart-editor/context.tsx @@ -6,7 +6,7 @@ import { } from '@app/hooks/settings/use-setting'; import { DistribusjonsType, type ISmartDocument } from '@app/types/documents/documents'; import { TemplateIdEnum } from '@app/types/smart-editor/template-enums'; -import type { TRange } from '@udecode/plate-common'; +import type { TRange } from '@udecode/plate'; import { type MutableRefObject, createContext, useRef, useState } from 'react'; const noop = () => {}; diff --git a/frontend/src/components/smart-editor/functions/get-positioned-items.ts b/frontend/src/components/smart-editor/functions/get-positioned-items.ts index 4d88ed9fe..814ad4440 100644 --- a/frontend/src/components/smart-editor/functions/get-positioned-items.ts +++ b/frontend/src/components/smart-editor/functions/get-positioned-items.ts @@ -2,7 +2,7 @@ import type { FocusedComment } from '@app/components/smart-editor/comments/use-t import { COMMENT_PREFIX } from '@app/components/smart-editor/constants'; import { calculateRangePosition } from '@app/plate/functions/range-position'; import type { FormattedText, RichTextEditor } from '@app/plate/types'; -import { findNode, isText } from '@udecode/plate-common'; +import { TextApi } from '@udecode/plate'; export enum ItemType { THREAD = 'thread', @@ -49,7 +49,7 @@ export const getPositionedItems = ( const mark = item.type === ItemType.THREAD ? `${COMMENT_PREFIX}${item.id}` : item.id; - const leafEntry = findNode(editor, { at: [], match: (n) => isText(n) && Object.hasOwn(n, mark) }); + const leafEntry = editor.api.node({ at: [], match: (n) => TextApi.isText(n) && Object.hasOwn(n, mark) }); if (leafEntry === undefined) { continue; diff --git a/frontend/src/components/smart-editor/gode-formuleringer/add-button.tsx b/frontend/src/components/smart-editor/gode-formuleringer/add-button.tsx index e6322b6b9..870c90357 100644 --- a/frontend/src/components/smart-editor/gode-formuleringer/add-button.tsx +++ b/frontend/src/components/smart-editor/gode-formuleringer/add-button.tsx @@ -1,8 +1,9 @@ +import { useSelection } from '@app/plate/hooks/use-selection'; import type { RichTextEditor } from '@app/plate/types'; import { Button } from '@navikt/ds-react'; -import type { Value } from '@udecode/plate-common'; +import type { Value } from '@udecode/plate'; import { styled } from 'styled-components'; -import { insertGodFormulering, isAvailable } from './insert'; +import { insertGodFormulering } from './insert'; interface AddButtonProps { editor: RichTextEditor; @@ -13,7 +14,8 @@ interface AddButtonProps { } export const AddButton = ({ editor, content, children, title = children, disabledTitle }: AddButtonProps) => { - const disabled = !isAvailable(editor); + const selection = useSelection(); + const disabled = selection === null; return ( { const ref = useRef(null); const [isExpanded, setIsExpanded] = useState(false); - const mainEditor = useMyPlateEditorState(); + const mainEditor = useMyPlateEditorRef(); const primaryLanguage = useSmartEditorLanguage(); const editor = usePlateEditor({ diff --git a/frontend/src/components/smart-editor/gode-formuleringer/gode-formuleringer.tsx b/frontend/src/components/smart-editor/gode-formuleringer/gode-formuleringer.tsx index 9001e3123..491d23f56 100644 --- a/frontend/src/components/smart-editor/gode-formuleringer/gode-formuleringer.tsx +++ b/frontend/src/components/smart-editor/gode-formuleringer/gode-formuleringer.tsx @@ -20,7 +20,6 @@ import type { TemplateIdEnum } from '@app/types/smart-editor/template-enums'; import type { IConsumerText, NonNullableGodFormulering } from '@app/types/texts/consumer'; import { LightBulbIcon, XMarkIcon } from '@navikt/aksel-icons'; import { Button } from '@navikt/ds-react'; -import { focusEditor } from '@udecode/plate-common/react'; import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import { Filter } from './filter'; import { insertGodFormulering } from './insert'; @@ -136,7 +135,7 @@ export const GodeFormuleringer = ({ templateId }: Props) => { } if (editor !== null) { - focusEditor(editor); + editor.tf.focus(); } return setShowGodeFormuleringer(false); diff --git a/frontend/src/components/smart-editor/gode-formuleringer/insert.ts b/frontend/src/components/smart-editor/gode-formuleringer/insert.ts index 2e8c18071..27c3b3552 100644 --- a/frontend/src/components/smart-editor/gode-formuleringer/insert.ts +++ b/frontend/src/components/smart-editor/gode-formuleringer/insert.ts @@ -1,17 +1,14 @@ import type { RichTextEditor } from '@app/plate/types'; -import { type Value, insertFragment } from '@udecode/plate-common'; -import { focusEditor } from '@udecode/plate-common/react'; +import type { Value } from '@udecode/plate'; export const insertGodFormulering = (editor: RichTextEditor, content: Value) => { - if (!isAvailable(editor)) { + if (editor.selection === null) { return; } - insertFragment(editor, structuredClone(content), { voids: false }); + editor.tf.insertFragment(structuredClone(content), { voids: false }); setTimeout(() => { - focusEditor(editor); + editor.tf.focus(); }); }; - -export const isAvailable = (editor: RichTextEditor): boolean => editor.selection !== null; diff --git a/frontend/src/components/smart-editor/gode-formuleringer/section-select.tsx b/frontend/src/components/smart-editor/gode-formuleringer/section-select.tsx index af83bd945..a7b5fbf10 100644 --- a/frontend/src/components/smart-editor/gode-formuleringer/section-select.tsx +++ b/frontend/src/components/smart-editor/gode-formuleringer/section-select.tsx @@ -20,7 +20,6 @@ import { } from '@app/plate/types'; import { isOfElementTypeFn, isOfElementTypesFn } from '@app/plate/utils/queries'; import { Select } from '@navikt/ds-react'; -import { findNode } from '@udecode/plate-common'; import { useContext, useEffect, useMemo } from 'react'; import type { BasePoint, Range } from 'slate'; @@ -39,11 +38,11 @@ const ANCHOR: BasePoint = { path: [0], offset: 0 }; const getActiveSection = (editor: RichTextEditor, selection: Range): TemplateSections | null => { const entry = - findNode(editor, { + editor.api.node({ at: selection.focus, match: MATCH, }) ?? - findNode(editor, { + editor.api.node({ at: { anchor: ANCHOR, focus: selection.focus }, match: MATCH_SECTION, reverse: true, diff --git a/frontend/src/components/smart-editor/history/history-editor.tsx b/frontend/src/components/smart-editor/history/history-editor.tsx index fea9b339c..07255a181 100644 --- a/frontend/src/components/smart-editor/history/history-editor.tsx +++ b/frontend/src/components/smart-editor/history/history-editor.tsx @@ -12,14 +12,7 @@ import { Sheet } from '@app/plate/sheet'; import { type KabalValue, type RichTextEditor, useMyPlateEditorRef } from '@app/plate/types'; import type { ISmartDocument } from '@app/types/documents/documents'; import { Button } from '@navikt/ds-react'; -import { - type Value, - insertNodes, - removeNodes, - resetEditorChildren, - withoutNormalizing, - withoutSavingHistory, -} from '@udecode/plate-common'; +import type { Value } from '@udecode/plate'; import { Plate, usePlateEditor } from '@udecode/plate-core/react'; import { memo, useContext, useEffect } from 'react'; import { styled } from 'styled-components'; @@ -97,13 +90,13 @@ const HistoryContent = ({ id, version }: HistoryContentProps) => { }; const restore = (editor: RichTextEditor, content: Value) => { - withoutNormalizing(editor, () => { - withoutSavingHistory(editor, () => { - resetEditorChildren(editor); - insertNodes(editor, content, { at: [0] }); + editor.tf.withoutNormalizing(() => { + editor.tf.withoutSaving(() => { + editor.tf.reset({ children: true }); + editor.tf.insertNodes(content, { at: [0] }); // Remove empty paragraph that is added automatically - removeNodes(editor, { at: [content.length] }); + editor.tf.removeNodes({ at: [content.length] }); }); }); }; diff --git a/frontend/src/components/smart-editor/new-document/generated-icon.tsx b/frontend/src/components/smart-editor/new-document/generated-icon.tsx index 5df5faf95..7d848103b 100644 --- a/frontend/src/components/smart-editor/new-document/generated-icon.tsx +++ b/frontend/src/components/smart-editor/new-document/generated-icon.tsx @@ -12,7 +12,7 @@ import { } from '@app/plate/plugins/element-types'; import { LabelContentPlugin } from '@app/plate/plugins/label-content'; import type { ISmartEditorTemplate } from '@app/types/smart-editor/smart-editor'; -import { BaseParagraphPlugin } from '@udecode/plate-common'; +import { BaseParagraphPlugin } from '@udecode/plate'; import { HEADING_KEYS } from '@udecode/plate-heading'; import { BaseBulletedListPlugin, BaseNumberedListPlugin } from '@udecode/plate-list'; import { BaseTablePlugin } from '@udecode/plate-table'; diff --git a/frontend/src/components/smart-editor/tabbed-editors/cursors/cursors.tsx b/frontend/src/components/smart-editor/tabbed-editors/cursors/cursors.tsx index 4b5ce540d..bd570dc7a 100644 --- a/frontend/src/components/smart-editor/tabbed-editors/cursors/cursors.tsx +++ b/frontend/src/components/smart-editor/tabbed-editors/cursors/cursors.tsx @@ -1,6 +1,6 @@ import { getColors } from '@app/components/smart-editor/tabbed-editors/cursors/cursor-colors'; import type { RelativeRange } from '@slate-yjs/core'; -import { type UnknownObject, createZustandStore } from '@udecode/plate-common'; +import { type UnknownObject, createZustandStore } from '@udecode/plate'; import { type CursorData, type CursorProps, type CursorState, useCursorOverlayPositions } from '@udecode/plate-cursor'; import { useEffect, useMemo, useRef } from 'react'; import { styled } from 'styled-components'; @@ -83,7 +83,10 @@ const CaretLabel = styled.div` white-space: nowrap; `; -export const cursorStore = createZustandStore('cursors')>>({}); +export const cursorStore = createZustandStore>>( + {}, + { mutative: true, name: 'cursors' }, +); interface CursorOverlayProps { containerElement: HTMLElement; diff --git a/frontend/src/components/smart-editor/tabbed-editors/editor.tsx b/frontend/src/components/smart-editor/tabbed-editors/editor.tsx index 55c63b6a0..396ffa509 100644 --- a/frontend/src/components/smart-editor/tabbed-editors/editor.tsx +++ b/frontend/src/components/smart-editor/tabbed-editors/editor.tsx @@ -30,7 +30,7 @@ import type { IOppgavebehandling } from '@app/types/oppgavebehandling/oppgavebeh import { isObject } from '@grafana/faro-web-sdk'; import { ClockDashedIcon, CloudFillIcon, CloudSlashFillIcon } from '@navikt/aksel-icons'; import { Tooltip } from '@navikt/ds-react'; -import { isCollapsed, isText } from '@udecode/plate-common'; +import { RangeApi, TextApi } from '@udecode/plate'; import { Plate, useEditorRef, usePlateEditor } from '@udecode/plate-core/react'; import { YjsPlugin } from '@udecode/plate-yjs/react'; import { useContext, useEffect, useState } from 'react'; @@ -80,7 +80,7 @@ const LoadedEditor = ({ oppgave, smartDocument, scalingGroup }: LoadedEditorProp override: { components, }, - value: smartDocument.content, + value: structuredClone(smartDocument.content), }); return ( @@ -90,7 +90,7 @@ const LoadedEditor = ({ oppgave, smartDocument, scalingGroup }: LoadedEditorProp readOnly={!canEdit} decorate={({ entry }) => { const [node, path] = entry; - if (newCommentSelection === null || isCollapsed(newCommentSelection) || !isText(node)) { + if (newCommentSelection === null || RangeApi.isCollapsed(newCommentSelection) || !TextApi.isText(node)) { return []; } diff --git a/frontend/src/functions/are-descendants-equal.test.ts b/frontend/src/functions/are-descendants-equal.test.ts index 6dd476809..25cc86168 100644 --- a/frontend/src/functions/are-descendants-equal.test.ts +++ b/frontend/src/functions/are-descendants-equal.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'bun:test'; import { areDescendantsEqual, areKeysEqual } from '@app/functions/are-descendants-equal'; -import type { TElement, TText } from '@udecode/plate-common'; +import type { TElement, TText } from '@udecode/plate'; describe('are-descendants-equal', () => { it('should return false if the two lists are of different lengths', () => { diff --git a/frontend/src/functions/are-descendants-equal.ts b/frontend/src/functions/are-descendants-equal.ts index 2420ef41c..58c6cfe5c 100644 --- a/frontend/src/functions/are-descendants-equal.ts +++ b/frontend/src/functions/are-descendants-equal.ts @@ -1,8 +1,8 @@ import { removeEmptyCharInText } from '@app/functions/remove-empty-char-in-text'; -import { type TDescendant, isElement } from '@udecode/plate-common'; +import { type Descendant, ElementApi } from '@udecode/plate'; // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: ¯\_(ツ)_/¯ -export const areDescendantsEqual = (listA: TDescendant[], listB: TDescendant[]): boolean => { +export const areDescendantsEqual = (listA: Descendant[], listB: Descendant[]): boolean => { if (listA.length !== listB.length) { return false; } @@ -15,8 +15,8 @@ export const areDescendantsEqual = (listA: TDescendant[], listB: TDescendant[]): return false; } - if (isElement(nodeA)) { - if (!isElement(nodeB)) { + if (ElementApi.isElement(nodeA)) { + if (!ElementApi.isElement(nodeB)) { return false; } @@ -38,7 +38,7 @@ export const areDescendantsEqual = (listA: TDescendant[], listB: TDescendant[]): continue; } - if (isElement(nodeB)) { + if (ElementApi.isElement(nodeB)) { return false; } diff --git a/frontend/src/hooks/use-template-sections.ts b/frontend/src/hooks/use-template-sections.ts index fba7f3e2c..ca29a234a 100644 --- a/frontend/src/hooks/use-template-sections.ts +++ b/frontend/src/hooks/use-template-sections.ts @@ -4,7 +4,7 @@ import { TEMPLATE_MAP } from '@app/plate/templates/templates'; import type { MaltekstseksjonElement } from '@app/plate/types'; import { isOfElementType } from '@app/plate/utils/queries'; import type { TemplateIdEnum } from '@app/types/smart-editor/template-enums'; -import type { TDescendant, Value } from '@udecode/plate-common'; +import type { Descendant, Value } from '@udecode/plate'; import { useMemo } from 'react'; const EMPTY_LIST: TemplateSections[] = []; @@ -27,7 +27,7 @@ export const getTemplateSections = (templateId: TemplateIdEnum): GroupedTemplate return getSections(template.richText as Value); }; -const getSections = (children: TDescendant[]): GroupedTemplateSections => { +const getSections = (children: Descendant[]): GroupedTemplateSections => { const used: TemplateSections[] = []; const unused: TemplateSections[] = []; diff --git a/frontend/src/plate/components/common/add-new-paragraph-buttons.tsx b/frontend/src/plate/components/common/add-new-paragraph-buttons.tsx index a9a5f9fc7..0b59aa851 100644 --- a/frontend/src/plate/components/common/add-new-paragraph-buttons.tsx +++ b/frontend/src/plate/components/common/add-new-paragraph-buttons.tsx @@ -3,8 +3,7 @@ import type { RootElement } from '@app/plate/types'; import { nextPath } from '@app/plate/utils/queries'; import { Button, Tooltip } from '@navikt/ds-react'; import { TextAddSpaceAfter, TextAddSpaceBefore } from '@styled-icons/fluentui-system-regular'; -import { findDescendant, insertElements } from '@udecode/plate-common'; -import { type PlateEditor, useEditorReadOnly } from '@udecode/plate-common/react'; +import { type PlateEditor, useEditorReadOnly } from '@udecode/plate/react'; interface Props { element: RootElement; @@ -29,13 +28,13 @@ export const AddNewParagraphBelow = ({ editor, element }: Props) => (