From 7ca8cfd3f8cd116d8a805fe39018713972af1e43 Mon Sep 17 00:00:00 2001 From: melloware Date: Tue, 13 Sep 2022 13:38:25 -0400 Subject: [PATCH] Fix #3312: Tabview add onBeforeTabClose/Change events --- api-generator/components/tabview.js | 48 +++++++++++++++++++++++++++++ components/doc/tabview/index.js | 30 ++++++++++++++++-- components/lib/tabview/TabView.js | 24 +++++++++++---- components/lib/tabview/tabview.d.ts | 8 +++-- 4 files changed, 98 insertions(+), 12 deletions(-) diff --git a/api-generator/components/tabview.js b/api-generator/components/tabview.js index 21463dcdde..44ab41d4e6 100644 --- a/api-generator/components/tabview.js +++ b/api-generator/components/tabview.js @@ -38,6 +38,38 @@ const TabViewProps = [ ]; const TabViewEvents = [ + { + name: 'onBeforeTabChange', + description: 'Callback to invoke before an active tab is changed. Return false to prevent tab from changing.', + arguments: [ + { + name: 'event.originalEvent', + type: 'object', + description: 'Browser event' + }, + { + name: 'event.index', + type: 'number', + description: 'Index of the selected tab' + } + ] + }, + { + name: 'onBeforeTabClose', + description: 'Callback to invoke before an active tab is close. Return false to prevent tab from closing.', + arguments: [ + { + name: 'event.originalEvent', + type: 'object', + description: 'Browser event' + }, + { + name: 'event.index', + type: 'number', + description: 'Index of the selected tab' + } + ] + }, { name: 'onTabChange', description: 'Callback to invoke when an active tab is changed.', @@ -53,6 +85,22 @@ const TabViewEvents = [ description: 'Index of the selected tab' } ] + }, + { + name: 'onTabClose', + description: 'Callback to invoke when an active tab is close.', + arguments: [ + { + name: 'event.originalEvent', + type: 'object', + description: 'Browser event' + }, + { + name: 'event.index', + type: 'number', + description: 'Index of the selected tab' + } + ] } ]; diff --git a/components/doc/tabview/index.js b/components/doc/tabview/index.js index 3de01f6145..d94a5e0af8 100644 --- a/components/doc/tabview/index.js +++ b/components/doc/tabview/index.js @@ -1,9 +1,9 @@ -import React, { memo } from 'react'; import Link from 'next/link'; -import { TabView, TabPanel } from '../../lib/tabview/TabView'; -import { useLiveEditorTabs } from '../common/liveeditor'; +import React, { memo } from 'react'; +import { TabPanel, TabView } from '../../lib/tabview/TabView'; import { CodeHighlight } from '../common/codehighlight'; import { DevelopmentSection } from '../common/developmentsection'; +import { useLiveEditorTabs } from '../common/liveeditor'; const TabViewDoc = memo(() => { const sources = { @@ -1119,6 +1119,22 @@ template: (options) => { + + onBeforeTabChange + + event.originalEvent: Browser event
+ event.index: Index of the selected tab + + Callback to invoke before an active tab is changed. Return false to prevent tab from changing. + + + onBeforeTabClose + + event.originalEvent: Browser event
+ event.index: Index of the selected tab + + Callback to invoke before an active tab is close. Return false to prevent tab from closing. + onTabChange @@ -1127,6 +1143,14 @@ template: (options) => { Callback to invoke when an active tab is changed. + + onTabClose + + event.originalEvent: Browser event
+ event.index: Index of the selected tab + + Callback to invoke when an active tab is closed. + diff --git a/components/lib/tabview/TabView.js b/components/lib/tabview/TabView.js index 4de619f52f..7d83e75bef 100644 --- a/components/lib/tabview/TabView.js +++ b/components/lib/tabview/TabView.js @@ -39,26 +39,36 @@ export const TabView = React.forwardRef((props, ref) => { }; const onTabHeaderClose = (event, index) => { + event.preventDefault(); + + // give caller a chance to stop the selection + if (props.onBeforeTabClose && props.onBeforeTabClose({ originalEvent: event, index }) === false) { + return; + } + setHiddenTabsState([...hiddenTabsState, index]); if (props.onTabClose) { props.onTabClose({ originalEvent: event, index }); } - - event.preventDefault(); }; const onTabHeaderClick = (event, tab, index) => { + if (event) { + event.preventDefault(); + } + if (!tab.props.disabled) { + // give caller a chance to stop the selection + if (props.onBeforeTabChange && props.onBeforeTabChange({ originalEvent: event, index }) === false) { + return; + } + if (props.onTabChange) props.onTabChange({ originalEvent: event, index }); else setActiveIndexState(index); } updateScrollBar(index); - - if (event) { - event.preventDefault(); - } }; const onKeyDown = (event, tab, index) => { @@ -313,6 +323,8 @@ TabView.defaultProps = { style: null, className: null, renderActiveOnly: true, + onBeforeTabClose: null, + onBeforeTabChange: null, onTabChange: null, onTabClose: null, scrollable: false, diff --git a/components/lib/tabview/tabview.d.ts b/components/lib/tabview/tabview.d.ts index 5e6a4a87f9..ccd25f4e05 100644 --- a/components/lib/tabview/tabview.d.ts +++ b/components/lib/tabview/tabview.d.ts @@ -46,13 +46,15 @@ interface TabViewTabCloseParams { export interface TabViewProps extends Omit, HTMLDivElement>, 'ref'> { activeIndex?: number; + children?: React.ReactNode; + panelContainerClassName?: string; + panelContainerStyle?: object; renderActiveOnly?: boolean; scrollable?: boolean; - panelContainerStyle?: object; - panelContainerClassName?: string; + onBeforeTabChange?(e: TabViewTabChangeParams): void; + onBeforeTabClose?(e: TabViewTabCloseParams): void; onTabChange?(e: TabViewTabChangeParams): void; onTabClose?(e: TabViewTabCloseParams): void; - children?: React.ReactNode; } // tslint:disable-next-line:max-classes-per-file