diff --git a/packages/react-arborist/src/components/default-container.tsx b/packages/react-arborist/src/components/default-container.tsx index 0004a9e3..9296cac4 100644 --- a/packages/react-arborist/src/components/default-container.tsx +++ b/packages/react-arborist/src/components/default-container.tsx @@ -160,9 +160,11 @@ export function DefaultContainer() { return; } if (e.key === "Enter") { - if (!tree.props.onRename) return; + const node = tree.focusedNode; + if (!node) return; + if (!node.isEditable || !tree.props.onRename) return; setTimeout(() => { - if (tree.focusedNode) tree.edit(tree.focusedNode); + if (node) tree.edit(node); }); return; } diff --git a/packages/react-arborist/src/interfaces/node-api.ts b/packages/react-arborist/src/interfaces/node-api.ts index 7e84f143..d49aaa52 100644 --- a/packages/react-arborist/src/interfaces/node-api.ts +++ b/packages/react-arborist/src/interfaces/node-api.ts @@ -58,6 +58,10 @@ export class NodeApi { return this.isLeaf ? false : !this.tree.isOpen(this.id); } + get isEditable() { + return this.tree.isEditable(this.data); + } + get isEditing() { return this.tree.editingId === this.id; } diff --git a/packages/react-arborist/src/interfaces/tree-api.ts b/packages/react-arborist/src/interfaces/tree-api.ts index 7d5a38b1..c53ed109 100644 --- a/packages/react-arborist/src/interfaces/tree-api.ts +++ b/packages/react-arborist/src/interfaces/tree-api.ts @@ -529,6 +529,11 @@ export class TreeApi { } } + isEditable(data: T) { + const check = this.props.disableEdit || (() => false); + return !utils.access(data, check) ?? true; + } + isDraggable(data: T) { const check = this.props.disableDrag || (() => false); return !utils.access(data, check) ?? true; diff --git a/packages/react-arborist/src/types/tree-props.ts b/packages/react-arborist/src/types/tree-props.ts index 3cfa6a1d..1854d79f 100644 --- a/packages/react-arborist/src/types/tree-props.ts +++ b/packages/react-arborist/src/types/tree-props.ts @@ -38,6 +38,7 @@ export interface TreeProps { openByDefault?: boolean; selectionFollowsFocus?: boolean; disableMultiSelection?: boolean; + disableEdit?: string | boolean | BoolFunc; disableDrag?: string | boolean | BoolFunc; disableDrop?: string | boolean | BoolFunc; childrenAccessor?: string | ((d: T) => T[] | null); diff --git a/packages/showcase/data/gmail.ts b/packages/showcase/data/gmail.ts index 5e986851..28695a3a 100644 --- a/packages/showcase/data/gmail.ts +++ b/packages/showcase/data/gmail.ts @@ -6,6 +6,7 @@ export type GmailItem = { name: string; icon: ComponentType; unread?: number; + readOnly: boolean; children?: GmailItem[]; }; @@ -14,95 +15,111 @@ export const gmailData: GmailItem[] = [ id: "1", name: "Inbox", unread: 1, + readOnly: true, icon: icons.MdInbox, }, { id: "2", name: "Starred", unread: 0, + readOnly: true, icon: icons.MdStarOutline, }, { id: "3", name: "Snoozed", unread: 0, + readOnly: true, icon: icons.MdAccessTime, }, { id: "4", name: "Sent", unread: 0, + readOnly: true, icon: icons.MdSend, }, { id: "5", name: "Drafts", unread: 14, + readOnly: true, icon: icons.MdOutlineDrafts, }, { id: "6", name: "Spam", unread: 54, + readOnly: true, icon: icons.MdOutlineReportGmailerrorred, }, { id: "7", name: "Important", unread: 0, + readOnly: true, icon: icons.MdLabelImportantOutline, }, { id: "8", name: "Chats", unread: 0, + readOnly: true, icon: icons.MdOutlineChat, }, { id: "9", name: "Scheduled", unread: 0, + readOnly: true, icon: icons.MdOutlineScheduleSend, }, { id: "10", name: "All Mail", unread: 0, + readOnly: true, icon: icons.MdOutlineMail, }, { id: "11", name: "Trash", unread: 0, + readOnly: true, icon: icons.MdOutlineDelete, }, { id: "12", name: "Categories", icon: icons.MdOutlineLabel, + readOnly: true, children: [ { id: "13", name: "Social", unread: 946, + readOnly: false, icon: icons.MdPeopleOutline, }, { id: "14", name: "Updates", unread: 4580, + readOnly: false, icon: icons.MdOutlineInfo, }, { id: "15", name: "Forums", unread: 312, + readOnly: false, icon: icons.MdChatBubbleOutline, }, { id: "16", name: "Promotions", unread: 312, + readOnly: false, icon: icons.MdOutlineLocalOffer, }, ], diff --git a/packages/showcase/pages/gmail.tsx b/packages/showcase/pages/gmail.tsx index e42062cb..e8c8d2a9 100644 --- a/packages/showcase/pages/gmail.tsx +++ b/packages/showcase/pages/gmail.tsx @@ -35,6 +35,7 @@ export default function GmailSidebar() { renderCursor={Cursor} searchTerm={term} paddingBottom={32} + disableEdit={(data) => data.readOnly} > {Node} @@ -57,7 +58,7 @@ export default function GmailSidebar() {
  • Drag the items around
  • Move focus with the arrow keys
  • Toggle folders (press spacebar)
  • -
  • Rename (press enter)
  • +
  • Rename (press enter, only allowed on items in 'Categories')
  • Create a new item (press A)
  • Create a new folder (press shift+A)
  • Delete items (press delete)