mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2026-04-06 01:25:33 +00:00
flex layout optimizations, text editor fine tuning and markdown rendering
This commit is contained in:
parent
212456e5c2
commit
8b47bba822
7
package-lock.json
generated
7
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^2.0.17",
|
"@heroicons/react": "^2.0.17",
|
||||||
"@tanstack/react-query": "^5.17.8",
|
"@tanstack/react-query": "^5.17.8",
|
||||||
|
"@tiptap/core": "^2.14.0",
|
||||||
"@tiptap/extension-bubble-menu": "^2.14.0",
|
"@tiptap/extension-bubble-menu": "^2.14.0",
|
||||||
"@tiptap/extension-color": "^2.12.0",
|
"@tiptap/extension-color": "^2.12.0",
|
||||||
"@tiptap/extension-image": "^2.14.0",
|
"@tiptap/extension-image": "^2.14.0",
|
||||||
@ -2373,9 +2374,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tiptap/core": {
|
"node_modules/@tiptap/core": {
|
||||||
"version": "2.12.0",
|
"version": "2.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.14.0.tgz",
|
||||||
"integrity": "sha512-3qX8oGVKFFZzQ0vit+ZolR6AJIATBzmEmjAA0llFhWk4vf3v64p1YcXcJsOBsr5scizJu5L6RYWEFatFwqckRg==",
|
"integrity": "sha512-MBSMzGYRFlwYCocvx3dU7zpCBSDQ0qWByNtStaEzuBUgzCJ6wn2DP/xG0cMcLmE3Ia0VLM4nwbLOAAvBXOtylA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
|
|||||||
@ -99,6 +99,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^2.0.17",
|
"@heroicons/react": "^2.0.17",
|
||||||
"@tanstack/react-query": "^5.17.8",
|
"@tanstack/react-query": "^5.17.8",
|
||||||
|
"@tiptap/core": "^2.14.0",
|
||||||
"@tiptap/extension-bubble-menu": "^2.14.0",
|
"@tiptap/extension-bubble-menu": "^2.14.0",
|
||||||
"@tiptap/extension-color": "^2.12.0",
|
"@tiptap/extension-color": "^2.12.0",
|
||||||
"@tiptap/extension-image": "^2.14.0",
|
"@tiptap/extension-image": "^2.14.0",
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const ComboBoxInput = ({ id, options, value, onValueChange }: ComboBoxProps) =>
|
|||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
id={id}
|
id={id}
|
||||||
className='tw:select'
|
className='tw:select tw:w-full'
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
value={value} // ← hier controlled statt defaultValue
|
value={value} // ← hier controlled statt defaultValue
|
||||||
>
|
>
|
||||||
|
|||||||
@ -3,9 +3,8 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
import { Color } from '@tiptap/extension-color'
|
import { Color } from '@tiptap/extension-color'
|
||||||
import { Image } from '@tiptap/extension-image'
|
import { Image } from '@tiptap/extension-image'
|
||||||
import { Placeholder } from '@tiptap/extension-placeholder'
|
|
||||||
import { Youtube } from '@tiptap/extension-youtube'
|
|
||||||
import { Link } from '@tiptap/extension-link'
|
import { Link } from '@tiptap/extension-link'
|
||||||
|
import { Placeholder } from '@tiptap/extension-placeholder'
|
||||||
import { EditorContent, useEditor } from '@tiptap/react'
|
import { EditorContent, useEditor } from '@tiptap/react'
|
||||||
import { StarterKit } from '@tiptap/starter-kit'
|
import { StarterKit } from '@tiptap/starter-kit'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
@ -19,8 +18,7 @@ interface RichTextEditorProps {
|
|||||||
containerStyle?: string
|
containerStyle?: string
|
||||||
defaultValue: string
|
defaultValue: string
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
required?: boolean
|
showMenu?: boolean
|
||||||
size?: string
|
|
||||||
updateFormValue?: (value: string) => void
|
updateFormValue?: (value: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,10 +31,14 @@ export function RichTextEditor({
|
|||||||
containerStyle,
|
containerStyle,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
showMenu = true,
|
||||||
updateFormValue,
|
updateFormValue,
|
||||||
}: RichTextEditorProps) {
|
}: RichTextEditorProps) {
|
||||||
const handleChange = () => {
|
const handleChange = () => {
|
||||||
const newValue: string | undefined = editor?.storage.markdown.getMarkdown()
|
let newValue: string | undefined = editor?.storage.markdown.getMarkdown()
|
||||||
|
|
||||||
|
const regex = /!\[.*?\]\(.*?\)/g
|
||||||
|
newValue = newValue?.replace(regex, (match: string) => match + '\n\n')
|
||||||
if (updateFormValue && newValue) {
|
if (updateFormValue && newValue) {
|
||||||
updateFormValue(newValue)
|
updateFormValue(newValue)
|
||||||
}
|
}
|
||||||
@ -55,13 +57,13 @@ export function RichTextEditor({
|
|||||||
keepAttributes: false,
|
keepAttributes: false,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
Markdown,
|
Markdown.configure({
|
||||||
|
linkify: true,
|
||||||
|
transformCopiedText: true,
|
||||||
|
transformPastedText: true,
|
||||||
|
}),
|
||||||
Image,
|
Image,
|
||||||
Link,
|
Link,
|
||||||
Youtube.configure({
|
|
||||||
controls: false,
|
|
||||||
nocookie: true,
|
|
||||||
}),
|
|
||||||
Placeholder.configure({
|
Placeholder.configure({
|
||||||
placeholder,
|
placeholder,
|
||||||
emptyEditorClass: 'is-editor-empty',
|
emptyEditorClass: 'is-editor-empty',
|
||||||
@ -98,7 +100,7 @@ export function RichTextEditor({
|
|||||||
>
|
>
|
||||||
{editor ? (
|
{editor ? (
|
||||||
<>
|
<>
|
||||||
<TextEditorMenu editor={editor} />
|
{showMenu ? <TextEditorMenu editor={editor} /> : null}
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import LinkIcon from '@heroicons/react/24/outline/LinkIcon'
|
|
||||||
import PhotoIcon from '@heroicons/react/24/outline/PhotoIcon'
|
|
||||||
import BoldIcon from '@heroicons/react/24/solid/BoldIcon'
|
import BoldIcon from '@heroicons/react/24/solid/BoldIcon'
|
||||||
import H1Icon from '@heroicons/react/24/solid/H1Icon'
|
import H1Icon from '@heroicons/react/24/solid/H1Icon'
|
||||||
import H2Icon from '@heroicons/react/24/solid/H2Icon'
|
import H2Icon from '@heroicons/react/24/solid/H2Icon'
|
||||||
@ -8,7 +6,6 @@ import ItalicIcon from '@heroicons/react/24/solid/ItalicIcon'
|
|||||||
import ListBulletIcon from '@heroicons/react/24/solid/ListBulletIcon'
|
import ListBulletIcon from '@heroicons/react/24/solid/ListBulletIcon'
|
||||||
import NumberedListIcon from '@heroicons/react/24/solid/NumberedListIcon'
|
import NumberedListIcon from '@heroicons/react/24/solid/NumberedListIcon'
|
||||||
import { useEditorState } from '@tiptap/react'
|
import { useEditorState } from '@tiptap/react'
|
||||||
import { useCallback, useEffect, useState } from 'react'
|
|
||||||
import { MdUndo, MdRedo, MdHorizontalRule } from 'react-icons/md'
|
import { MdUndo, MdRedo, MdHorizontalRule } from 'react-icons/md'
|
||||||
|
|
||||||
import type { Editor } from '@tiptap/react'
|
import type { Editor } from '@tiptap/react'
|
||||||
@ -45,32 +42,16 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const addImage = useCallback(() => {
|
|
||||||
const url = window.prompt('URL')
|
|
||||||
|
|
||||||
if (url) {
|
|
||||||
editor.chain().focus().setImage({ src: url }).run()
|
|
||||||
}
|
|
||||||
}, [editor])
|
|
||||||
|
|
||||||
const [url, setUrl] = useState<string>('')
|
|
||||||
|
|
||||||
const setLink = (e: React.MouseEvent) => {
|
|
||||||
e.preventDefault()
|
|
||||||
|
|
||||||
editor.chain().focus().extendMarkRange('link').setLink({ href: url }).run()
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ul
|
<ul
|
||||||
className={
|
className={
|
||||||
'tw:menu tw:overflow-x-hidden tw:sm:overflow-visible tw:md:overflow-x-hidden tw:lg:overflow-visible tw:p-1 tw:menu-horizontal tw:flex-nowrap tw:flex-none tw:bg-base-200 tw:rounded-box tw:w-full tw:rounded-b-none'
|
'tw:menu tw:overflow-x-hidden tw:@sm:overflow-visible tw:menu-horizontal tw:flex-nowrap tw:flex-none tw:bg-base-200 tw:rounded-box tw:w-full tw:rounded-b-none'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isHeading1 ? 'tw:bg-base-content/10' : ''}`}
|
className={`tw:@sm:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isHeading1 ? 'tw:bg-base-content/10' : ''}`}
|
||||||
data-tip='Heading 1'
|
data-tip='Heading 1'
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
>
|
>
|
||||||
@ -79,7 +60,7 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isHeading2 ? 'tw:bg-base-content/10' : ''}`}
|
className={`tw:@sm:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isHeading2 ? 'tw:bg-base-content/10' : ''}`}
|
||||||
data-tip='Heading 2'
|
data-tip='Heading 2'
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
>
|
>
|
||||||
@ -88,7 +69,7 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isHeading3 ? 'tw:bg-base-content/10' : ''}`}
|
className={`tw:@sm:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isHeading3 ? 'tw:bg-base-content/10' : ''}`}
|
||||||
data-tip='Heading 3'
|
data-tip='Heading 3'
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
>
|
>
|
||||||
@ -100,7 +81,7 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isBold ? 'tw:bg-base-content/10' : ''}`}
|
className={`tw:@sm:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isBold ? 'tw:bg-base-content/10' : ''}`}
|
||||||
data-tip='Bold'
|
data-tip='Bold'
|
||||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||||
>
|
>
|
||||||
@ -109,7 +90,7 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isItalic ? 'tw:bg-base-content/10' : ''}`}
|
className={`tw:@sm:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isItalic ? 'tw:bg-base-content/10' : ''}`}
|
||||||
data-tip='Italic'
|
data-tip='Italic'
|
||||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||||
>
|
>
|
||||||
@ -121,7 +102,7 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isBulletList ? 'tw:bg-base-content/10' : ''}`}
|
className={`tw:@sm:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isBulletList ? 'tw:bg-base-content/10' : ''}`}
|
||||||
data-tip='List'
|
data-tip='List'
|
||||||
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
>
|
>
|
||||||
@ -130,7 +111,7 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isOrderedList ? 'tw:bg-base-content/10' : ''}`}
|
className={`tw:@sm:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isOrderedList ? 'tw:bg-base-content/10' : ''}`}
|
||||||
data-tip='List'
|
data-tip='List'
|
||||||
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
>
|
>
|
||||||
@ -140,63 +121,14 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
|
|||||||
<li>
|
<li>
|
||||||
<div className='tw:w-[1px] tw:p-0 tw:mx-1 tw:bg-base-content/10 tw:my-1' />
|
<div className='tw:w-[1px] tw:p-0 tw:mx-1 tw:bg-base-content/10 tw:my-1' />
|
||||||
</li>
|
</li>
|
||||||
<li className='tw:hidden tw:sm:block tw:md:hidden tw:lg:block'>
|
{/* <li>
|
||||||
{!editor.isActive('link') ? (
|
<div className='tw:@sm:tooltip tw:px-1.5 tw:mx-0.5' data-tip='Image' onClick={addImage}>
|
||||||
<div
|
|
||||||
tabIndex={0}
|
|
||||||
role='button'
|
|
||||||
className='tw:dropdown tw:dropdown-end tw:px-1.5 tw:mx-0.5 tw:pt-1.5 tw:pb-0 tw:cursor-pointer '
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={`tw:tooltip tw:h-full ${editor.isActive('link') ? 'tw:bg-base-content/10' : ''}`}
|
|
||||||
data-tip='Link'
|
|
||||||
>
|
|
||||||
<LinkIcon className='tw:h-full tw:w-5' />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
tabIndex={0}
|
|
||||||
className='tw:dropdown-content tw:bg-base-200 tw:card tw:card-body tw:card-sm tw:bg-base-100 z-1 w-64 shadow-md'
|
|
||||||
>
|
|
||||||
<div className='tw:join'>
|
|
||||||
<div>
|
|
||||||
<label className='tw:input tw:validator tw:join-item tw:w-58'>
|
|
||||||
<LinkIcon className='tw:h-full tw:w-4' />
|
|
||||||
<input
|
|
||||||
onChange={(e) => setUrl(e.target.value)}
|
|
||||||
type='url'
|
|
||||||
placeholder='https://...'
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
<div className='tw:validator-hint tw:hidden'>Enter valid url</div>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
className='tw:btn tw:btn-neutral tw:join-item'
|
|
||||||
onClick={(e) => setLink(e)}
|
|
||||||
>
|
|
||||||
Set Link
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div
|
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editor.isActive('link') ? 'tw:bg-base-content/10' : ''}`}
|
|
||||||
data-tip='List'
|
|
||||||
onClick={() => editor.chain().focus().extendMarkRange('link').unsetLink().run()}
|
|
||||||
>
|
|
||||||
<LinkIcon className='tw:w-5 tw:h-5' />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<div className='tw:tooltip tw:px-1.5 tw:mx-0.5' data-tip='Image' onClick={addImage}>
|
|
||||||
<PhotoIcon className='tw:w-5 tw:h-5' />
|
<PhotoIcon className='tw:w-5 tw:h-5' />
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li> */}
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
className='tw:tooltip tw:px-1'
|
className='tw:@sm:tooltip tw:px-1'
|
||||||
data-tip='Horizontal Line'
|
data-tip='Horizontal Line'
|
||||||
onClick={() => editor.chain().focus().setHorizontalRule().run()}
|
onClick={() => editor.chain().focus().setHorizontalRule().run()}
|
||||||
>
|
>
|
||||||
@ -206,7 +138,7 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
|
|||||||
<div className='tw:flex-grow'></div>
|
<div className='tw:flex-grow'></div>
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 tw:hidden tw:sm:block tw:md:hidden tw:lg:block ${editorState.canUndo ? '' : 'tw:opacity-50'}`}
|
className={`tw:@sm:tooltip tw:px-1.5 tw:mx-0.5 tw:hidden tw:@sm:block ${editorState.canUndo ? '' : 'tw:opacity-50'}`}
|
||||||
data-tip='Undo'
|
data-tip='Undo'
|
||||||
onClick={() => editor.chain().focus().undo().run()}
|
onClick={() => editor.chain().focus().undo().run()}
|
||||||
>
|
>
|
||||||
@ -215,7 +147,7 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 tw:hidden tw:sm:block tw:md:hidden tw:lg:block ${editorState.canRedo ? '' : 'tw:opacity-50'}`}
|
className={`tw:@sm:tooltip tw:px-1.5 tw:mx-0.5 tw:hidden tw:@sm:block ${editorState.canRedo ? '' : 'tw:opacity-50'}`}
|
||||||
data-tip='Redo'
|
data-tip='Redo'
|
||||||
onClick={() => editor.chain().focus().redo().run()}
|
onClick={() => editor.chain().focus().redo().run()}
|
||||||
>
|
>
|
||||||
@ -223,50 +155,6 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
|
|||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{/** <div className='control-group tiptap-toolbar'>
|
|
||||||
<div className='button-group'>
|
|
||||||
<button id='add' className='btn btn-sm' onClick={addYoutubeVideo}>
|
|
||||||
Add YouTube video
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div> */}
|
|
||||||
{/** <BubbleMenu editor={editor} tippyOptions={{ duration: 100 }}>
|
|
||||||
<div className='bubble-menu tw:card tw:card-body tw:rounded-box tw:border tw:border-base-content/20 tw:bg-base-200 tw:shadow'>
|
|
||||||
<ul
|
|
||||||
className={
|
|
||||||
'tw:menu tw:p-1 tw:menu-horizontal tw:flex-nowrap tw:flex-none tw:bg-base-200 tw:rounded-box tw:w-full tw:rounded-b-none'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<div
|
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 tw:cursor-pointer ${editorState.isBold ? 'tw:bg-base-content/10' : ''}`}
|
|
||||||
data-tip='Bold'
|
|
||||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
|
||||||
>
|
|
||||||
<BoldIcon className='tw:w-4 tw:h-4' />
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div
|
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-1 tw:cursor-pointer ${editorState.isItalic ? 'tw:bg-base-content/10' : ''}`}
|
|
||||||
data-tip='Italic'
|
|
||||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
|
||||||
>
|
|
||||||
<ItalicIcon className='tw:w-4 tw:h-4' />
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div
|
|
||||||
className={`tw:tooltip tw:px-1.5 tw:mx-1 tw:cursor-pointer ${editor.isActive('link') ? 'tw:bg-base-content/10' : ''}`}
|
|
||||||
data-tip='Link'
|
|
||||||
onClick={setLink}
|
|
||||||
>
|
|
||||||
<LinkIcon className='tw:w-4 tw:h-4' />
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</BubbleMenu> */}
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,22 +53,6 @@ export const TextView = ({
|
|||||||
|
|
||||||
if (innerText) replacedText = fixUrls(innerText)
|
if (innerText) replacedText = fixUrls(innerText)
|
||||||
|
|
||||||
if (replacedText) {
|
|
||||||
replacedText = replacedText.replace(/(?<!\]?\()https?:\/\/[^\s)]+(?!\))/g, (url) => {
|
|
||||||
let shortUrl = url
|
|
||||||
|
|
||||||
if (url.match('^https://')) {
|
|
||||||
shortUrl = url.split('https://')[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url.match('^http://')) {
|
|
||||||
shortUrl = url.split('http://')[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return `[${shortUrl}](${url})`
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (replacedText) {
|
if (replacedText) {
|
||||||
replacedText = replacedText.replace(mailRegex, (url) => {
|
replacedText = replacedText.replace(mailRegex, (url) => {
|
||||||
return `[${url}](mailto:${url})`
|
return `[${url}](mailto:${url})`
|
||||||
|
|||||||
@ -158,7 +158,7 @@ export function ProfileForm() {
|
|||||||
<>
|
<>
|
||||||
<MapOverlayPage
|
<MapOverlayPage
|
||||||
backdrop
|
backdrop
|
||||||
className='tw:mx-4 tw:mt-4 tw:mb-4 tw:overflow-x-hidden tw:w-[calc(100%-32px)] tw:md:w-[calc(50%-32px)] tw:max-w-3xl tw:left-auto! tw:top-0 tw:bottom-0 tw:flex tw:flex-col tw:max-h-[calc(1000px)]'
|
className='tw:mx-4 tw:mt-4 tw:mb-4 tw:@container tw:overflow-x-hidden tw:w-[calc(100%-32px)] tw:md:w-[calc(50%-32px)] tw:max-w-3xl tw:left-auto! tw:top-0 tw:bottom-0 tw:flex tw:flex-col'
|
||||||
>
|
>
|
||||||
<form
|
<form
|
||||||
className='tw:flex tw:flex-col tw:flex-1 tw:min-h-0'
|
className='tw:flex tw:flex-col tw:flex-1 tw:min-h-0'
|
||||||
|
|||||||
@ -51,7 +51,7 @@ export const GroupSubheaderForm = ({
|
|||||||
}, [state.group_type, groupTypes])
|
}, [state.group_type, groupTypes])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='tw:grid tw:grid-cols-1 tw:md:grid-cols-2 tw:gap-2'>
|
<div className='tw:grid tw:grid-cols-1 tw:@sm:grid-cols-2 tw:gap-2'>
|
||||||
<div>
|
<div>
|
||||||
<label
|
<label
|
||||||
htmlFor='status'
|
htmlFor='status'
|
||||||
|
|||||||
@ -18,7 +18,6 @@ export const ProfileTextForm = ({
|
|||||||
heading,
|
heading,
|
||||||
size,
|
size,
|
||||||
hideInputLabel,
|
hideInputLabel,
|
||||||
required,
|
|
||||||
}: {
|
}: {
|
||||||
state: FormState
|
state: FormState
|
||||||
setState: React.Dispatch<React.SetStateAction<any>>
|
setState: React.Dispatch<React.SetStateAction<any>>
|
||||||
@ -26,7 +25,6 @@ export const ProfileTextForm = ({
|
|||||||
heading: string
|
heading: string
|
||||||
size: string
|
size: string
|
||||||
hideInputLabel: boolean
|
hideInputLabel: boolean
|
||||||
required?: boolean
|
|
||||||
}) => {
|
}) => {
|
||||||
const [field, setField] = useState<string>(dataField || 'text')
|
const [field, setField] = useState<string>(dataField || 'text')
|
||||||
|
|
||||||
@ -38,7 +36,7 @@ export const ProfileTextForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`tw:min-h-36 tw:max-h-156 tw:flex tw:flex-col tw:mt-2 ${size === 'full' ? 'tw:flex-1' : 'tw:h-36 tw:flex-none'}`}
|
className={`tw:max-h-124 tw:md:max-h-full tw:flex tw:flex-col tw:mt-2 ${size === 'full' ? 'tw:flex-1 tw:min-h-42' : 'tw:h-28 tw:flex-none'}`}
|
||||||
>
|
>
|
||||||
<div className='tw:flex tw:justify-between tw:items-center'>
|
<div className='tw:flex tw:justify-between tw:items-center'>
|
||||||
<label
|
<label
|
||||||
@ -59,9 +57,9 @@ export const ProfileTextForm = ({
|
|||||||
[field]: v,
|
[field]: v,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
showMenu={size === 'full'}
|
||||||
labelStyle={hideInputLabel ? 'tw:hidden' : ''}
|
labelStyle={hideInputLabel ? 'tw:hidden' : ''}
|
||||||
containerStyle={size === 'full' ? 'tw:flex-1' : 'tw:h-32 tw:flex-none'}
|
containerStyle={size === 'full' ? 'tw:flex-1' : 'tw:h-24 tw:flex-none'}
|
||||||
required={required}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -85,7 +85,7 @@ export const TabsForm = ({
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
containerStyle='tw:pt-2 tw:h-36 tw:flex-none'
|
containerStyle='tw:pt-2 tw:h-36 tw:flex-none'
|
||||||
required={false}
|
showMenu={false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user