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:
3
site/examples/custom-types.d.ts
vendored
3
site/examples/custom-types.d.ts
vendored
@@ -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
|
||||
|
@@ -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>
|
||||
}
|
||||
|
Reference in New Issue
Block a user