diff --git a/examples/ui-playground/src/components/slot-before.tsx b/examples/ui-playground/src/components/slot-before.tsx
new file mode 100644
index 00000000..bcbdd159
--- /dev/null
+++ b/examples/ui-playground/src/components/slot-before.tsx
@@ -0,0 +1,173 @@
+'use client'
+import type React from 'react'
+
+import Color from '@tiptap/extension-color'
+import Link from '@tiptap/extension-link'
+import TextAlign from '@tiptap/extension-text-align'
+import TextStyle from '@tiptap/extension-text-style'
+import Underline from '@tiptap/extension-underline'
+import StarterKit from '@tiptap/starter-kit'
+
+import {
+ EditorBar,
+ EditorTextColorPicker,
+ MarkButton,
+ RedoButton,
+ SelectTextStyle,
+ TextAlignButton,
+ TextAlignButtonsGroup,
+ ToolbarGroup,
+ ToolbarSeparator,
+ UndoButton,
+ UploadImageButton,
+} from '@genseki/react'
+import {
+ BackColorExtension,
+ CustomImageExtension,
+ ImageUploadNodeExtension,
+ SelectionExtension,
+} from '@genseki/react'
+
+export const EditorSlotBefore = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export const editorProviderProps = {
+ immediatelyRender: false,
+ shouldRerenderOnTransaction: true,
+ content: {
+ type: 'doc',
+ content: [
+ {
+ type: 'paragraph',
+ content: [
+ {
+ type: 'text',
+ text: '',
+ },
+ ],
+ },
+ ],
+ },
+ slotBefore:
,
+ extensions: [
+ Color,
+ BackColorExtension,
+ Underline.configure({ HTMLAttributes: { class: 'earth-underline' } }),
+ SelectionExtension,
+ TextStyle,
+ TextAlign.configure({
+ types: ['heading', 'paragraph'],
+ alignments: ['left', 'center', 'right', 'justify'],
+ defaultAlignment: 'left',
+ }),
+ StarterKit.configure({
+ bold: { HTMLAttributes: { class: 'bold large-black' } },
+ paragraph: { HTMLAttributes: { class: 'paragraph-custom' } },
+ heading: { HTMLAttributes: { class: 'heading-custom' } },
+ bulletList: { HTMLAttributes: { class: 'list-custom' } },
+ orderedList: { HTMLAttributes: { class: 'ordered-list' } },
+ code: { HTMLAttributes: { class: 'code' } },
+ codeBlock: { HTMLAttributes: { class: 'code-block' } },
+ horizontalRule: { HTMLAttributes: { class: 'hr-custom' } },
+ italic: { HTMLAttributes: { class: 'italic-text' } },
+ strike: { HTMLAttributes: { class: 'strikethrough' } },
+ blockquote: { HTMLAttributes: { class: 'blockquote-custom' } },
+ }),
+ CustomImageExtension.configure({ HTMLAttributes: { className: 'image-displayer' } }),
+ ImageUploadNodeExtension.configure({
+ showProgress: false,
+ accept: 'image/*',
+ maxSize: 1024 * 1024 * 10, // 10MB
+ limit: 3,
+ pathName: 'posts/rich-text',
+ }),
+ Link.configure({
+ openOnClick: false,
+ autolink: true,
+ defaultProtocol: 'https',
+ protocols: ['http', 'https'],
+ isAllowedUri: (url, ctx) => {
+ try {
+ // construct URL
+ const parsedUrl = url.includes(':')
+ ? new URL(url)
+ : new URL(`${ctx.defaultProtocol}://${url}`)
+
+ // use default validation
+ if (!ctx.defaultValidate(parsedUrl.href)) {
+ return false
+ }
+
+ // disallowed protocols
+ const disallowedProtocols = ['ftp', 'file', 'mailto']
+ const protocol = parsedUrl.protocol.replace(':', '')
+
+ if (disallowedProtocols.includes(protocol)) {
+ return false
+ }
+
+ // only allow protocols specified in ctx.protocols
+ const allowedProtocols = ctx.protocols.map((p) => (typeof p === 'string' ? p : p.scheme))
+
+ if (!allowedProtocols.includes(protocol)) {
+ return false
+ }
+
+ // disallowed domains
+ const disallowedDomains = ['example-phishing.com', 'malicious-site.net']
+ const domain = parsedUrl.hostname
+
+ if (disallowedDomains.includes(domain)) {
+ return false
+ }
+
+ // all checks have passed
+ return true
+ } catch {
+ return false
+ }
+ },
+ shouldAutoLink: (url) => {
+ try {
+ // construct URL
+ const parsedUrl = url.includes(':') ? new URL(url) : new URL(`https://${url}`)
+
+ // only auto-link if the domain is not in the disallowed list
+ const disallowedDomains = ['example-no-autolink.com', 'another-no-autolink.com']
+ const domain = parsedUrl.hostname
+
+ return !disallowedDomains.includes(domain)
+ } catch {
+ return false
+ }
+ },
+ }),
+ ],
+}
diff --git a/examples/ui-playground/src/styles/tailwind.css b/examples/ui-playground/src/styles/tailwind.css
index cd514763..77f3d1c2 100644
--- a/examples/ui-playground/src/styles/tailwind.css
+++ b/examples/ui-playground/src/styles/tailwind.css
@@ -2,3 +2,11 @@
@import './tiptap-style.css';
@source "../../node_modules/@genseki/react";
+
+.tiptap.ProseMirror {
+ height: 100%;
+ min-height: 240px;
+ padding: 16px;
+ outline: none;
+ background-color: var(--color-bluegray-50);
+}
diff --git a/packages/react/package.json b/packages/react/package.json
index 90ade73d..79532879 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -73,6 +73,7 @@
"@tiptap/core": "^2.26.3",
"@tiptap/extension-color": "^2.26.3",
"@tiptap/extension-image": "^2.26.3",
+ "@tiptap/extension-link": "2.26.3",
"@tiptap/extension-text-align": "^2.26.3",
"@tiptap/extension-text-style": "^2.26.3",
"@tiptap/extension-typography": "^2.26.3",
diff --git a/packages/react/src/core/richtext/index.ts b/packages/react/src/core/richtext/index.ts
index 7caf7f50..a6341051 100644
--- a/packages/react/src/core/richtext/index.ts
+++ b/packages/react/src/core/richtext/index.ts
@@ -39,6 +39,7 @@ const getSanitizedExtensions = (unSanitizedExtensions: Extensions): SanitizedExt
case 'color':
case 'image':
case 'imageUpload':
+ case 'link':
return R.omit(extension, ['config'])
default:
throw new Error(`Unknown extension name: ${extension.name}`)
diff --git a/packages/react/src/react/components/compound/editor/components/editor-bar.tsx b/packages/react/src/react/components/compound/editor/components/editor-bar.tsx
index 8e4597b1..2166f8cc 100644
--- a/packages/react/src/react/components/compound/editor/components/editor-bar.tsx
+++ b/packages/react/src/react/components/compound/editor/components/editor-bar.tsx
@@ -17,8 +17,13 @@ export const EditorBar: React.FC<{ className?: string; children?: React.ReactNod
if (!editor) throw new Error('Editor not found')
return (
-
-
{children}
+
+ {children}
)
}
diff --git a/packages/react/src/react/components/compound/editor/components/editor-color-picker.tsx b/packages/react/src/react/components/compound/editor/components/editor-color-picker.tsx
index 20f1bb92..e707d49f 100644
--- a/packages/react/src/react/components/compound/editor/components/editor-color-picker.tsx
+++ b/packages/react/src/react/components/compound/editor/components/editor-color-picker.tsx
@@ -2,7 +2,7 @@
import React, { useState } from 'react'
import { type Color as ReactAriaColor, parseColor } from 'react-aria-components'
-import { SelectionBackgroundIcon, TextAaIcon } from '@phosphor-icons/react'
+import { SelectionBackgroundIcon } from '@phosphor-icons/react'
import { useCurrentEditor } from '@tiptap/react'
import { BaseIcon } from '../../../primitives'
@@ -55,8 +55,7 @@ export const EditorTextColorPicker = () => {
onPopupClose={(color) => {
editor.chain().setColor(color.toString('hex')).run()
}}
- label={
}
- buttonClassName="p-4 border border-border/50 bg-secondary/25"
+ buttonClassName="p-4 bg-secondary/25"
/>
)
}
diff --git a/packages/react/src/react/components/compound/editor/components/mark-button.tsx b/packages/react/src/react/components/compound/editor/components/mark-button.tsx
index a2c3629c..608ffb4d 100644
--- a/packages/react/src/react/components/compound/editor/components/mark-button.tsx
+++ b/packages/react/src/react/components/compound/editor/components/mark-button.tsx
@@ -2,6 +2,7 @@
import {
type Icon,
+ LinkIcon,
ListBulletsIcon,
TextBolderIcon,
TextItalicIcon,
@@ -13,7 +14,7 @@ import { useCurrentEditor } from '@tiptap/react'
import { BaseIcon } from '../../../primitives/base-icon'
import { ToolbarItem } from '../../../primitives/toolbar'
-type MarkType = 'bold' | 'italic' | 'underline' | 'strike' | 'bulletList'
+type MarkType = 'bold' | 'italic' | 'underline' | 'strike' | 'bulletList' | 'link'
type MarkOptions = Record<
MarkType,
@@ -66,6 +67,27 @@ const useMark = (type: MarkType) => {
editor.chain().focus().toggleBulletList().run()
},
},
+ link: {
+ label: 'Link',
+ icon: LinkIcon,
+ isSelected: editor.isActive('link'),
+ onClick() {
+ if (!editor.isActive('link')) {
+ const { state } = editor
+ const { from, to } = state.selection
+ const currentText = state.doc.textBetween(from, to, '')
+
+ editor.chain().focus().extendMarkRange('link').run()
+ editor
+ .chain()
+ .focus()
+ .setMark('link', { href: currentText || 'https://' })
+ .run()
+ return
+ }
+ editor.chain().focus().unsetMark('link').run()
+ },
+ },
}
return options[type]
@@ -80,8 +102,9 @@ export const MarkButton = (props: { type: MarkType }) => {
return (
diff --git a/packages/react/src/react/components/compound/editor/components/redo-undo-buttons.tsx b/packages/react/src/react/components/compound/editor/components/redo-undo-buttons.tsx
index 37697aa6..20aeafb0 100644
--- a/packages/react/src/react/components/compound/editor/components/redo-undo-buttons.tsx
+++ b/packages/react/src/react/components/compound/editor/components/redo-undo-buttons.tsx
@@ -2,8 +2,8 @@
import { ArrowClockwiseIcon, ArrowCounterClockwiseIcon } from '@phosphor-icons/react'
import { useCurrentEditor } from '@tiptap/react'
+import { Button } from '../../../../../../v2'
import { BaseIcon } from '../../../primitives/base-icon'
-import { Button } from '../../../primitives/button'
export const UndoButton = () => {
const { editor } = useCurrentEditor()
@@ -12,14 +12,14 @@ export const UndoButton = () => {
return (
@@ -33,14 +33,14 @@ export const RedoButton = () => {
return (
diff --git a/packages/react/src/react/components/compound/editor/components/rich-text-editor.tsx b/packages/react/src/react/components/compound/editor/components/rich-text-editor.tsx
index 8fdf2732..b9e100c7 100644
--- a/packages/react/src/react/components/compound/editor/components/rich-text-editor.tsx
+++ b/packages/react/src/react/components/compound/editor/components/rich-text-editor.tsx
@@ -7,10 +7,8 @@ import { isDeepEqual } from 'remeda'
import { EditorProvider } from './rich-text-provider'
-import { cn } from '../../../../utils/cn'
-import { focusStyles } from '../../../primitives'
import { CustomFieldError } from '../../../primitives/custom-field-error'
-import { Description, FieldGroup } from '../../../primitives/field'
+import { Description } from '../../../primitives/field'
export interface RichTextEditorProps {
editorProviderProps: EditorProviderProps
value?: string | Content | Content[]
@@ -24,8 +22,6 @@ export interface RichTextEditorProps {
}
export const RichTextEditor = (props: RichTextEditorProps) => {
- const isInvalid = !!props.errorMessage
-
const editor = useEditor({
...props.editorProviderProps,
content: props.value,
@@ -42,22 +38,14 @@ export const RichTextEditor = (props: RichTextEditorProps) => {
return (
-
-
-
-
-
+
{props.description &&
{props.description}}
diff --git a/packages/react/src/react/components/compound/editor/components/rich-text-provider.tsx b/packages/react/src/react/components/compound/editor/components/rich-text-provider.tsx
index c94de9bc..b840f9fa 100644
--- a/packages/react/src/react/components/compound/editor/components/rich-text-provider.tsx
+++ b/packages/react/src/react/components/compound/editor/components/rich-text-provider.tsx
@@ -8,9 +8,15 @@ import {
} from '@tiptap/react'
import { cn } from '../../../../utils/cn'
+import { InputGroup, InputGroupControl } from '../../../primitives'
interface EditorProviderPropsWithEditor extends EditorProviderProps {
editor?: Editor | null
+ inputGroupProps?: {
+ isInvalid?: boolean
+ isDisabled?: boolean
+ isPending?: boolean
+ }
}
export function EditorProvider({
@@ -19,6 +25,7 @@ export function EditorProvider({
slotBefore,
editorContainerProps = {},
editor,
+ inputGroupProps,
...editorOptions
}: EditorProviderPropsWithEditor) {
const editorInstance = editor ?? useEditor(editorOptions)
@@ -32,11 +39,24 @@ export function EditorProvider({
{slotBefore}
{() => (
-
+
+
+
+
+
)}
{children}
diff --git a/packages/react/src/react/components/compound/editor/components/select-text-style.tsx b/packages/react/src/react/components/compound/editor/components/select-text-style.tsx
index b76d41d1..2978b14c 100644
--- a/packages/react/src/react/components/compound/editor/components/select-text-style.tsx
+++ b/packages/react/src/react/components/compound/editor/components/select-text-style.tsx
@@ -3,12 +3,12 @@ import React from 'react'
import type { Key } from 'react-aria-components'
import {
- ParagraphIcon,
TextHFiveIcon,
TextHFourIcon,
TextHOneIcon,
TextHThreeIcon,
TextHTwoIcon,
+ TextTIcon,
} from '@phosphor-icons/react'
import type { Editor } from '@tiptap/core'
import { useCurrentEditor } from '@tiptap/react'
@@ -17,7 +17,7 @@ import { BaseIcon } from '../../../primitives/base-icon'
import { Select, SelectList, SelectOption, SelectTrigger } from '../../../primitives/select'
const textStylesList = [
- { icon: ParagraphIcon, label: 'Normal', value: 'p', type: 'paragraph' },
+ { icon: TextTIcon, label: 'Normal', value: 'p', type: 'paragraph' },
{ icon: TextHOneIcon, label: 'Heading 1', value: 'h1', type: 'heading', level: 1 },
{ icon: TextHTwoIcon, label: 'Heading 2', value: 'h2', type: 'heading', level: 2 },
{ icon: TextHThreeIcon, label: 'Heading 3', value: 'h3', type: 'heading', level: 3 },
@@ -79,7 +79,7 @@ export const SelectTextStyle = () => {
aria-label="Select text style"
onSelectionChange={selectChange}
>
-
+
{(item) => (
diff --git a/packages/react/src/react/components/compound/editor/components/text-align-buttons.tsx b/packages/react/src/react/components/compound/editor/components/text-align-buttons.tsx
index d780c30a..773a3c8f 100644
--- a/packages/react/src/react/components/compound/editor/components/text-align-buttons.tsx
+++ b/packages/react/src/react/components/compound/editor/components/text-align-buttons.tsx
@@ -1,6 +1,6 @@
'use client'
-import React from 'react'
-import type { Key } from 'react-aria-components'
+
+import React, { createContext, useContext } from 'react'
import {
TextAlignCenterIcon,
@@ -10,8 +10,8 @@ import {
} from '@phosphor-icons/react'
import { useCurrentEditor } from '@tiptap/react'
+import { ToggleGroup, ToggleGroupItem } from '../../../../../../v2'
import { BaseIcon } from '../../../primitives/base-icon'
-import { ToggleGroup } from '../../../primitives/toggle'
import { ToolbarItem } from '../../../primitives/toolbar'
type TextAlignType = 'left' | 'center' | 'right' | 'justify'
@@ -23,54 +23,68 @@ const justifyOptions = {
justify: { icon: TextAlignJustifyIcon },
} as const satisfies Record
-const useCurrentTextAlign = (): TextAlignType => {
- const { editor } = useCurrentEditor()
+interface TextAlignGroupContextValue {
+ currentAlign: TextAlignType
+ setAlign: (value: TextAlignType) => void
+}
+const TextAlignGroupContext = createContext(null)
+
+const useTextAlignGroup = () => {
+ const ctx = useContext(TextAlignGroupContext)
+ if (!ctx) throw new Error('TextAlignButton must be used inside TextAlignButtonsGroup')
+ return ctx
+}
+
+const useCurrentTextAlign = (editor: any): TextAlignType => {
if (!editor) throw new Error('Editor provider is missing')
- if (editor.isActive({ textAlign: 'left' })) return 'left'
if (editor.isActive({ textAlign: 'right' })) return 'right'
if (editor.isActive({ textAlign: 'center' })) return 'center'
if (editor.isActive({ textAlign: 'justify' })) return 'justify'
-
return 'left'
}
-export const TextAlignButton = (props: { type: TextAlignType }) => {
- const currentTextAlign = useCurrentTextAlign()
+export const TextAlignButtonsGroup = ({ children }: { children: React.ReactNode }) => {
+ const { editor } = useCurrentEditor()
+ if (!editor) throw new Error('Editor provider is missing')
+
+ const currentAlign = useCurrentTextAlign(editor)
- const isSelected = currentTextAlign === props.type
+ const handleValueChange = (value: string) => {
+ if (!value) return
+ editor.chain().focus().setTextAlign(value).run()
+ }
return (
-
-
-
+
+
+ {children}
+
+
)
}
-export const TextAlignButtonsGroup = ({ children }: { children: React.ReactNode }) => {
- const { editor } = useCurrentEditor()
- const currentTextAlign = useCurrentTextAlign()
-
- if (!editor) throw new Error('Editor provider is missing')
-
- const selectionChange = (value: Set) => {
- editor.commands.setTextAlign(value.keys().next().value as string)
- }
+export const TextAlignButton = ({ type }: { type: TextAlignType }) => {
+ const { currentAlign } = useTextAlignGroup()
+ const Icon = justifyOptions[type].icon
+ const isSelected = currentAlign === type
return (
-
- {children}
-
+
+
+
+
+
)
}
diff --git a/packages/react/src/react/components/compound/editor/components/upload-image-button.tsx b/packages/react/src/react/components/compound/editor/components/upload-image-button.tsx
index 47aa7344..209c3475 100644
--- a/packages/react/src/react/components/compound/editor/components/upload-image-button.tsx
+++ b/packages/react/src/react/components/compound/editor/components/upload-image-button.tsx
@@ -2,8 +2,8 @@
import { ImageIcon } from '@phosphor-icons/react'
import { useCurrentEditor } from '@tiptap/react'
+import { Button } from '../../../../../../v2'
import { BaseIcon } from '../../../primitives/base-icon'
-import { Button } from '../../../primitives/button'
export const UploadImageButton = () => {
const { editor } = useCurrentEditor()
@@ -12,9 +12,9 @@ export const UploadImageButton = () => {
return (
({
orientation: 'horizontal',
@@ -55,13 +58,17 @@ const ToolbarGroup = ({ isDisabled, className, ...props }: ToolbarGroupProps) =>
)
}
-type ToggleItemProps = ToggleProps
-const ToolbarItem = ({ isDisabled, ref, ...props }: ToggleItemProps) => {
+interface ToggleItemProps
+ extends React.ComponentProps,
+ VariantProps {}
+
+const ToolbarItem = ({ disabled, ref, ...props }: ToggleItemProps) => {
const context = useContext(ToolbarGroupContext)
- const effectiveIsDisabled = isDisabled || context.isDisabled
+ const effectiveIsDisabled = disabled || context.isDisabled
- return
+ return
}
+
type ToolbarSeparatorProps = SeparatorProps
const ToolbarSeparator = ({ className, ...props }: ToolbarSeparatorProps) => {
const { orientation } = useContext(ToolbarContext)
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4c5c954f..eeaeecdc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -74,6 +74,9 @@ importers:
'@tiptap/extension-image':
specifier: ^2.26.3
version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))
+ '@tiptap/extension-link':
+ specifier: 2.26.3
+ version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)
'@tiptap/extension-text-align':
specifier: ^2.26.3
version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))
@@ -168,6 +171,21 @@ importers:
'@tanstack/react-query':
specifier: ^5.71.5
version: 5.76.1(react@19.1.0)
+ '@tiptap/extension-color':
+ specifier: ^2.26.3
+ version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/extension-text-style@2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))
+ '@tiptap/extension-link':
+ specifier: 2.26.3
+ version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)
+ '@tiptap/extension-text-align':
+ specifier: ^2.26.3
+ version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))
+ '@tiptap/extension-text-style':
+ specifier: ^2.26.3
+ version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))
+ '@tiptap/extension-underline':
+ specifier: ^2.26.3
+ version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))
'@tiptap/starter-kit':
specifier: ^2.26.3
version: 2.26.3
@@ -294,7 +312,7 @@ importers:
version: 15.2.2(@babel/core@7.27.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
nuqs:
specifier: ^2.4.3
- version: 2.4.3(next@15.2.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)
+ version: 2.4.3(next@15.2.2(@babel/core@7.27.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)
radix3:
specifier: ^1.1.2
version: 1.1.2
@@ -493,6 +511,9 @@ importers:
'@tiptap/extension-image':
specifier: ^2.26.3
version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))
+ '@tiptap/extension-link':
+ specifier: 2.26.3
+ version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)
'@tiptap/extension-text-align':
specifier: ^2.26.3
version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))
@@ -546,7 +567,7 @@ importers:
version: 12.11.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
nuqs:
specifier: ^2.4.3
- version: 2.4.3(next@15.2.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)
+ version: 2.4.3(next@15.2.2(@babel/core@7.27.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)
radix3:
specifier: ^1.1.2
version: 1.1.2
@@ -3072,6 +3093,12 @@ packages:
peerDependencies:
'@tiptap/core': ^2.7.0
+ '@tiptap/extension-link@2.26.3':
+ resolution: {integrity: sha512-cNYqAeiaG/65ctVEUOHt1MQnTF1JcdZqBkN9pLf3grzcmkmdr3w1/JbKOphZc84vOB2rxuhGZx9NFV2lrC5Qwg==}
+ peerDependencies:
+ '@tiptap/core': ^2.7.0
+ '@tiptap/pm': ^2.7.0
+
'@tiptap/extension-list-item@2.26.3':
resolution: {integrity: sha512-9qU0SoC+tDSKYhfdWFS3dkioEk3ml1ycBeRmOxh7h+w0ezmTomiT5yvc9t3KM30ps8n1p78sIPo19GF65u1dFQ==}
peerDependencies:
@@ -4391,6 +4418,9 @@ packages:
linkify-it@5.0.0:
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
+ linkifyjs@4.3.2:
+ resolution: {integrity: sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==}
+
load-tsconfig@0.2.5:
resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -8977,6 +9007,12 @@ snapshots:
dependencies:
'@tiptap/core': 2.26.3(@tiptap/pm@2.26.3)
+ '@tiptap/extension-link@2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)':
+ dependencies:
+ '@tiptap/core': 2.26.3(@tiptap/pm@2.26.3)
+ '@tiptap/pm': 2.26.3
+ linkifyjs: 4.3.2
+
'@tiptap/extension-list-item@2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))':
dependencies:
'@tiptap/core': 2.26.3(@tiptap/pm@2.26.3)
@@ -10555,6 +10591,8 @@ snapshots:
dependencies:
uc.micro: 2.1.0
+ linkifyjs@4.3.2: {}
+
load-tsconfig@0.2.5: {}
locate-path@5.0.0:
@@ -10712,7 +10750,7 @@ snapshots:
node-releases@2.0.19: {}
- nuqs@2.4.3(next@15.2.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0):
+ nuqs@2.4.3(next@15.2.2(@babel/core@7.27.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0):
dependencies:
mitt: 3.0.1
react: 19.1.0