Skip to content

Commit

Permalink
feat(playground): add plate to playground
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasnobile committed Apr 17, 2024
1 parent dbc0a18 commit b459b96
Show file tree
Hide file tree
Showing 34 changed files with 3,116 additions and 14 deletions.
2 changes: 1 addition & 1 deletion packages/playground/admin/lib/components/form/ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const FormLabelWrapperUI = uic('div', {
displayName: 'FormLabelWrapper',
})
export const FormLabelUI = uic(Label, {
baseClass: 'data-[invalid]:text-destructive text-right',
baseClass: 'data-[invalid]:text-destructive text-left',
displayName: 'FormLabel',
})
export const FormContainerUI = uic('div', {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { AutoformatBlockRule } from '@udecode/plate-autoformat'
import { ELEMENT_CODE_BLOCK, ELEMENT_CODE_LINE } from '@udecode/plate-code-block'
import { getParentNode, isElement, isType, PlateEditor } from '@udecode/plate-common'
import { toggleList, unwrapList } from '@udecode/plate-list'

export const preFormat: AutoformatBlockRule['preFormat'] = editor =>
unwrapList(editor)

export const format = (editor: PlateEditor, customFormatting: any) => {
if (editor.selection) {
const parentEntry = getParentNode(editor, editor.selection)
if (!parentEntry) return
const [node] = parentEntry
if (
isElement(node) &&
!isType(editor, node, ELEMENT_CODE_BLOCK) &&
!isType(editor, node, ELEMENT_CODE_LINE)
) {
customFormatting()
}
}
}

export const formatList = (editor: PlateEditor, elementType: string) => {
format(editor, () =>
toggleList(editor, {
type: elementType,
}),
)
}

export const formatText = (editor: PlateEditor, text: string) => {
format(editor, () => editor.insertText(text))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { AutoformatRule } from '@udecode/plate-autoformat'
import { MARK_BOLD, MARK_ITALIC, MARK_STRIKETHROUGH, MARK_UNDERLINE } from '@udecode/plate-basic-marks'
import { ELEMENT_H1, ELEMENT_H2, ELEMENT_H3, ELEMENT_H4, ELEMENT_H5, ELEMENT_H6 } from '@udecode/plate-heading'
import { preFormat } from './auto-format-utils'

export const autoFormatBlocks: AutoformatRule[] = [
{
mode: 'block',
type: ELEMENT_H1,
match: '# ',
preFormat,
},
{
mode: 'block',
type: ELEMENT_H2,
match: '## ',
preFormat,
},
{
mode: 'block',
type: ELEMENT_H3,
match: '### ',
preFormat,
},
{
mode: 'block',
type: ELEMENT_H4,
match: '#### ',
preFormat,
},
{
mode: 'block',
type: ELEMENT_H5,
match: '##### ',
preFormat,
},
{
mode: 'block',
type: ELEMENT_H6,
match: '###### ',
preFormat,
},
]

export const autoFormatMarks: AutoformatRule[] = [
{
mode: 'mark',
type: [MARK_BOLD, MARK_ITALIC],
match: '***',
},
{
mode: 'mark',
type: [MARK_UNDERLINE, MARK_ITALIC],
match: '__*',
},
{
mode: 'mark',
type: [MARK_UNDERLINE, MARK_BOLD],
match: '__**',
},
{
mode: 'mark',
type: [MARK_UNDERLINE, MARK_BOLD, MARK_ITALIC],
match: '___***',
},
{
mode: 'mark',
type: MARK_BOLD,
match: '**',
},
{
mode: 'mark',
type: MARK_UNDERLINE,
match: '__',
},
{
mode: 'mark',
type: MARK_ITALIC,
match: '*',
},
{
mode: 'mark',
type: MARK_ITALIC,
match: '_',
},
{
mode: 'mark',
type: MARK_STRIKETHROUGH,
match: '~~',
},
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { findEventRange, PlatePlugin } from '@udecode/plate-common'
import { cursorStore } from '../plate-ui/cursor-overlay'

export const KEY_DRAG_OVER_CURSOR = 'dragOverCursor'

export const dragOverCursorPlugin: PlatePlugin = {
key: KEY_DRAG_OVER_CURSOR,
handlers: {
onDragOver: editor => event => {
if (editor.isDragging) return

const range = findEventRange(editor, event)
if (!range) return

cursorStore.set.cursors({
drag: {
key: 'drag',
data: {
style: {
backgroundColor: 'hsl(222.2 47.4% 11.2%)',
width: 3,
},
},
selection: range,
},
})
},
onDragLeave: () => () => {
cursorStore.set.cursors({})
},
onDragEnd: () => () => {
cursorStore.set.cursors({})
},
onDrop: () => () => {
cursorStore.set.cursors({})
},
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useCallback, useState } from 'react'

export const useOpenState = () => {
const [open, setOpen] = useState(false)

const onOpenChange = useCallback(
(_value = !open) => {
setOpen(_value)
},
[open],
)

return {
open,
onOpenChange,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Component, Field, SugarableRelativeSingleField, useField } from '@contember/interface'
import { cn } from '@udecode/cn'
import { Plate } from '@udecode/plate-common'
import { useRef } from 'react'
import { DndProvider } from 'react-dnd'
import { HTML5Backend } from 'react-dnd-html5-backend'
import { plugins } from './plate-plugins'
import { Editor } from './plate-ui/editor'
import { FixedToolbar } from './plate-ui/fixed-toolbar'
import { FixedToolbarButtons } from './plate-ui/fixed-toolbar-buttons'
import { FloatingToolbar } from './plate-ui/floating-toolbar'
import { FloatingToolbarButtons } from './plate-ui/floating-toolbar-buttons'
import { TooltipProvider } from './plate-ui/tooltip'
import { isJsonContent, isJsonObject } from './utils'


export interface PlateEditorProps {
field: string | SugarableRelativeSingleField
}

export const PlateEditor = Component(
({ field }: PlateEditorProps) => {
const containerRef = useRef(null)
const contentField = useField(field)

const handleEditorOnChange = (value: any) => {
const contentJson = isJsonObject(value) ? { children: value } : null

if (contentJson && contentField.value && (isJsonContent(contentField.value) && contentField.value.children === value)) return

contentField.updateValue(contentJson)
}

return (
<DndProvider backend={HTML5Backend}>
<TooltipProvider>
<Plate
plugins={plugins}
value={isJsonContent(contentField?.value) ? contentField?.value?.children : undefined}
onChange={handleEditorOnChange}
normalizeInitialValue
>
<div
ref={containerRef}
className={cn(
'relative',
'border rounded-md',
'[&_.slate-start-area-left]:!w-[64px] [&_.slate-start-area-right]:!w-[64px] [&_.slate-start-area-top]:!h-4',
)}
>

<div className={'relative'}>
<FixedToolbar>
<FixedToolbarButtons/>
</FixedToolbar>

<Editor
className="px-[96px] py-16"
autoFocus
focusRing={false}
variant="ghost"
size="md"
/>

<FloatingToolbar>
<FloatingToolbarButtons/>
</FloatingToolbar>
</div>
</div>
</Plate>
</TooltipProvider>
</DndProvider>
)
},
({ field }) => (
<>
<Field field={field}/>
</>
),
'PlateEditor',
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { withProps } from '@udecode/cn'
import {
autoformatArrow,
autoformatLegal,
autoformatMath,
autoformatPunctuation,
createAutoformatPlugin,
} from '@udecode/plate-autoformat'
import {
createBoldPlugin,
createItalicPlugin,
createStrikethroughPlugin,
createUnderlinePlugin,
MARK_BOLD,
MARK_ITALIC,
MARK_STRIKETHROUGH,
MARK_UNDERLINE,
} from '@udecode/plate-basic-marks'
import { createPlugins, PlateElement, PlateLeaf, RenderAfterEditable } from '@udecode/plate-common'
import { createDndPlugin } from '@udecode/plate-dnd'
import {
createHeadingPlugin,
ELEMENT_H1,
ELEMENT_H2,
ELEMENT_H3,
ELEMENT_H4,
ELEMENT_H5,
ELEMENT_H6,
} from '@udecode/plate-heading'
import { createLinkPlugin, ELEMENT_LINK } from '@udecode/plate-link'
import { createListPlugin, ELEMENT_LI, ELEMENT_OL, ELEMENT_UL } from '@udecode/plate-list'
import { createNodeIdPlugin } from '@udecode/plate-node-id'
import { createParagraphPlugin, ELEMENT_PARAGRAPH } from '@udecode/plate-paragraph'
import { createDeserializeDocxPlugin } from '@udecode/plate-serializer-docx'
import { createDeserializeMdPlugin } from '@udecode/plate-serializer-md'
import { autoFormatBlocks, autoFormatMarks } from './lib/auto-format'
import { dragOverCursorPlugin } from './lib/drag-over-plugin'
import { HeadingElement } from './plate-ui/heading-element'
import { LinkElement } from './plate-ui/link-element'
import { LinkFloatingToolbar } from './plate-ui/link-floating-toolbar'
import { ListElement } from './plate-ui/list-element'
import { ParagraphElement } from './plate-ui/paragraph-element'
import { withPlaceholders } from './plate-ui/placeholder'
import { withDraggables } from './plate-ui/with-draggables'

export const plugins = createPlugins([
// Nodes
createParagraphPlugin(),
createHeadingPlugin(),
createNodeIdPlugin(),
createDndPlugin({
options: { enableScroller: true },
}),
createLinkPlugin({
renderAfterEditable: LinkFloatingToolbar as RenderAfterEditable,
}),

// Marks
createBoldPlugin(),
createItalicPlugin(),
createStrikethroughPlugin(),
createUnderlinePlugin(),

// Block style
createListPlugin(),

// Functionality
createAutoformatPlugin({
options: {
rules: [
...autoFormatBlocks,
...autoFormatMarks,
...autoformatPunctuation,
...autoformatLegal,
...autoformatArrow,
...autoformatMath,
],
enableUndoOnDelete: true,
},
}),
dragOverCursorPlugin,

// Deserialization
createDeserializeDocxPlugin(),
createDeserializeMdPlugin(),
], {
components: withDraggables(
withPlaceholders({
[ELEMENT_LINK]: LinkElement,
[ELEMENT_H1]: withProps(HeadingElement, { variant: 'h1' }),
[ELEMENT_H2]: withProps(HeadingElement, { variant: 'h2' }),
[ELEMENT_H3]: withProps(HeadingElement, { variant: 'h3' }),
[ELEMENT_H4]: withProps(HeadingElement, { variant: 'h4' }),
[ELEMENT_H5]: withProps(HeadingElement, { variant: 'h5' }),
[ELEMENT_H6]: withProps(HeadingElement, { variant: 'h6' }),
[ELEMENT_PARAGRAPH]: ParagraphElement,
[MARK_BOLD]: withProps(PlateLeaf, { as: 'strong' }),
[MARK_ITALIC]: withProps(PlateLeaf, { as: 'em' }),
[MARK_STRIKETHROUGH]: withProps(PlateLeaf, { as: 's' }),
[MARK_UNDERLINE]: withProps(PlateLeaf, { as: 'u' }),
[ELEMENT_UL]: withProps(ListElement, { variant: 'ul' }),
[ELEMENT_OL]: withProps(ListElement, { variant: 'ol' }),
[ELEMENT_LI]: withProps(PlateElement, { as: 'li' }),
}),
),
})
Loading

0 comments on commit b459b96

Please sign in to comment.