1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-31 10:51:44 +02:00

Add support for read-only and non-selectable elements (#5374)

* Add `isElementReadOnly`

fix delete while selected

fix type while selected

fix failing test

add tests

add e2e test

linter fixes

add changeset

* fix yarn build:next

* Add `isSelectable`
This commit is contained in:
Joe Anderson
2023-04-03 19:02:26 +01:00
committed by GitHub
parent 26ace0db28
commit b52e08b0ea
22 changed files with 416 additions and 20 deletions

View File

@@ -47,6 +47,8 @@ export type LinkElement = { type: 'link'; url: string; children: Descendant[] }
export type ButtonElement = { type: 'button'; children: Descendant[] }
export type BadgeElement = { type: 'badge'; children: Descendant[] }
export type ListItemElement = { type: 'list-item'; children: Descendant[] }
export type MentionElement = {
@@ -92,6 +94,7 @@ type CustomElement =
| ImageElement
| LinkElement
| ButtonElement
| BadgeElement
| ListItemElement
| MentionElement
| ParagraphElement

View File

@@ -38,7 +38,14 @@ const initialValue: Descendant[] = [
children: [{ text: 'editable button' }],
},
{
text: '!',
text: '! Here is a read-only inline: ',
},
{
type: 'badge',
children: [{ text: 'Approved' }],
},
{
text: '.',
},
],
},
@@ -108,10 +115,22 @@ const InlinesExample = () => {
}
const withInlines = editor => {
const { insertData, insertText, isInline } = editor
const {
insertData,
insertText,
isInline,
isElementReadOnly,
isSelectable,
} = editor
editor.isInline = element =>
['link', 'button'].includes(element.type) || isInline(element)
['link', 'button', 'badge'].includes(element.type) || isInline(element)
editor.isElementReadOnly = element =>
element.type === 'badge' || isElementReadOnly(element)
editor.isSelectable = element =>
element.type !== 'badge' && isSelectable(element)
editor.insertText = text => {
if (text && isUrl(text)) {
@@ -283,6 +302,30 @@ const EditableButtonComponent = ({ attributes, children }) => {
)
}
const BadgeComponent = ({ attributes, children, element }) => {
const selected = useSelected()
return (
<span
{...attributes}
contentEditable={false}
className={css`
background-color: green;
color: white;
padding: 2px 6px;
border-radius: 2px;
font-size: 0.9em;
${selected && 'box-shadow: 0 0 0 3px #ddd;'}
`}
data-playwright-selected={selected}
>
<InlineChromiumBugfix />
{children}
<InlineChromiumBugfix />
</span>
)
}
const Element = props => {
const { attributes, children, element } = props
switch (element.type) {
@@ -290,6 +333,8 @@ const Element = props => {
return <LinkComponent {...props} />
case 'button':
return <EditableButtonComponent {...props} />
case 'badge':
return <BadgeComponent {...props} />
default:
return <p {...attributes}>{children}</p>
}