From ec40e351d57552de8ae7b06333e2d23b09ae262d Mon Sep 17 00:00:00 2001 From: Daniel Nilsson Date: Mon, 23 Jan 2023 23:37:34 +0100 Subject: [PATCH] Disable edit (#97) * Add tree prop for disabling edit on individual items (#96) * Update Gmail example to only allow editing of items inside Categories folder using disableEdit (#96) --- .../src/components/default-container.tsx | 6 ++++-- .../react-arborist/src/interfaces/node-api.ts | 4 ++++ .../react-arborist/src/interfaces/tree-api.ts | 5 +++++ packages/react-arborist/src/types/tree-props.ts | 1 + packages/showcase/data/gmail.ts | 17 +++++++++++++++++ packages/showcase/pages/gmail.tsx | 3 ++- 6 files changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/react-arborist/src/components/default-container.tsx b/packages/react-arborist/src/components/default-container.tsx index 0004a9e..9296cac 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 7e84f14..d49aaa5 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 7d5a38b..c53ed10 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 3cfa6a1..1854d79 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 5e98685..28695a3 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 e42062c..e8c8d2a 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)