Skip to content

Commit bb47677

Browse files
tak-ambosskendelljoseph
authored andcommitted
fix(richtext-lexical): allow to indent and outdent if at least one selected node allows it (#12182)
### What? Enables the indent/outdent button if at least one selected node can be indented/outdented. ### Why? Before, the buttons were disabled e.g. if multiple nodes were selected of which one was not indentable/outdentable or if a child node was not indentable but the parent was, leading to inconsistent behavior. ### How? Checks if the node itself or any parent fulfills the criteria. The change affects only the buttons active state, not the actual indentation logic. Fixes #12042
1 parent bef408a commit bb47677

File tree

1 file changed

+22
-44
lines changed
  • packages/richtext-lexical/src/features/indent/client

1 file changed

+22
-44
lines changed
Lines changed: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
'use client'
22

3-
import type { BaseSelection, ElementNode, LexicalNode } from 'lexical'
3+
import type { ElementNode, LexicalNode } from 'lexical'
44

55
import { $findMatchingParent } from '@lexical/utils'
6-
import {
7-
$isElementNode,
8-
$isRangeSelection,
9-
INDENT_CONTENT_COMMAND,
10-
OUTDENT_CONTENT_COMMAND,
11-
} from 'lexical'
6+
import { $isElementNode, INDENT_CONTENT_COMMAND, OUTDENT_CONTENT_COMMAND } from 'lexical'
127

138
import type { ToolbarGroup } from '../../toolbars/types.js'
149

@@ -25,31 +20,15 @@ const toolbarGroups = ({ disabledNodes }: IndentFeatureProps): ToolbarGroup[] =>
2520
ChildComponent: IndentDecreaseIcon,
2621
isActive: () => false,
2722
isEnabled: ({ selection }) => {
28-
const nodes = selection?.getNodes()
29-
if (!nodes?.length) {
30-
return false
31-
}
32-
let atLeastOneNodeCanOutdent = false
33-
const isIndentable = (node: LexicalNode): node is ElementNode =>
34-
$isElementNode(node) && node.canIndent()
35-
for (const node of nodes) {
36-
if (isIndentable(node)) {
37-
if (node.getIndent() <= 0) {
38-
return false
39-
} else {
40-
atLeastOneNodeCanOutdent = true
41-
}
42-
}
43-
}
23+
const nodes = selection?.getNodes() ?? []
4424

45-
if (!atLeastOneNodeCanOutdent) {
46-
if (
47-
$pointsAncestorMatch(selection, (node) => isIndentable(node) && node.getIndent() > 0)
48-
) {
49-
return true
50-
}
25+
const isOutdentable = (node: LexicalNode) => {
26+
return isIndentable(node) && node.getIndent() > 0
5127
}
52-
return atLeastOneNodeCanOutdent
28+
29+
return nodes.some((node) => {
30+
return isOutdentable(node) || Boolean($findMatchingParent(node, isOutdentable))
31+
})
5332
},
5433
key: 'indentDecrease',
5534
label: ({ i18n }) => {
@@ -64,11 +43,18 @@ const toolbarGroups = ({ disabledNodes }: IndentFeatureProps): ToolbarGroup[] =>
6443
ChildComponent: IndentIncreaseIcon,
6544
isActive: () => false,
6645
isEnabled: ({ selection }) => {
67-
const nodes = selection?.getNodes()
68-
if (!nodes?.length) {
69-
return false
46+
const nodes = selection?.getNodes() ?? []
47+
48+
const isIndentableAndNotDisabled = (node: LexicalNode) => {
49+
return isIndentable(node) && !(disabledNodes ?? []).includes(node.getType())
7050
}
71-
return !nodes.some((node) => disabledNodes?.includes(node.getType()))
51+
52+
return nodes.some((node) => {
53+
return (
54+
isIndentableAndNotDisabled(node) ||
55+
Boolean($findMatchingParent(node, isIndentableAndNotDisabled))
56+
)
57+
})
7258
},
7359
key: 'indentIncrease',
7460
label: ({ i18n }) => {
@@ -101,13 +87,5 @@ export const IndentFeatureClient = createClientFeature<IndentFeatureProps>(({ pr
10187
}
10288
})
10389

104-
function $pointsAncestorMatch(
105-
selection: BaseSelection,
106-
fn: (node: LexicalNode) => boolean,
107-
): boolean {
108-
return (
109-
$isRangeSelection(selection) &&
110-
(!!$findMatchingParent(selection.anchor.getNode(), fn) ||
111-
!!$findMatchingParent(selection.focus.getNode(), fn))
112-
)
113-
}
90+
const isIndentable = (node: LexicalNode): node is ElementNode =>
91+
$isElementNode(node) && node.canIndent()

0 commit comments

Comments
 (0)