From fd0a3b663ca10b062467b9f492dd5679260ac283 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 | 48 ++++++++++++++++++----------- components/lib/tabview/tabview.d.ts | 8 +++-- 4 files changed, 110 insertions(+), 24 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..665dd2c41d 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) => { @@ -291,18 +301,18 @@ export const TabView = React.forwardRef((props, ref) => { TabPanel.displayName = 'TabPanel'; TabPanel.defaultProps = { __TYPE: 'TabPanel', + className: null, + closable: false, + contentClassName: null, + contentStyle: null, + disabled: false, header: null, + headerClassName: null, + headerStyle: null, headerTemplate: null, leftIcon: null, rightIcon: null, - closable: false, - disabled: false, - style: null, - className: null, - headerStyle: null, - headerClassName: null, - contentStyle: null, - contentClassName: null + style: null }; TabView.displayName = 'TabView'; @@ -310,12 +320,14 @@ TabView.defaultProps = { __TYPE: 'TabView', id: null, activeIndex: 0, - style: null, className: null, - renderActiveOnly: true, + onBeforeTabChange: null, + onBeforeTabClose: null, onTabChange: null, onTabClose: null, - scrollable: false, + panelContainerClassName: null, panelContainerStyle: null, - panelContainerClassName: null + renderActiveOnly: true, + scrollable: false, + style: null }; 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