From 066be6ed27b1f41a984209f8a5f92541e5aafb67 Mon Sep 17 00:00:00 2001 From: Laurin Quast Date: Fri, 25 Feb 2022 17:13:31 +0100 Subject: [PATCH] make tab feature opt-in --- packages/graphiql/resources/renderExample.js | 4 +- packages/graphiql/src/components/GraphiQL.tsx | 260 ++++++++++-------- 2 files changed, 144 insertions(+), 120 deletions(-) diff --git a/packages/graphiql/resources/renderExample.js b/packages/graphiql/resources/renderExample.js index 363c100d6a8..b0cb0246d7e 100644 --- a/packages/graphiql/resources/renderExample.js +++ b/packages/graphiql/resources/renderExample.js @@ -136,7 +136,9 @@ ReactDOM.render( headerEditorEnabled: true, shouldPersistHeaders: true, inputValueDeprecation: true, - onTabChange: onTabChange, + tabs: { + onTabChange: onTabChange, + }, }), document.getElementById('graphiql'), ); diff --git a/packages/graphiql/src/components/GraphiQL.tsx b/packages/graphiql/src/components/GraphiQL.tsx index e8477ad8ee6..326d14dbe7d 100644 --- a/packages/graphiql/src/components/GraphiQL.tsx +++ b/packages/graphiql/src/components/GraphiQL.tsx @@ -296,10 +296,19 @@ export type GraphiQLProps = { * Content to place before the top bar (logo). */ beforeTopBarContent?: React.ReactElement | null; + /** - * On tab change + * Whether tabs should be enabled. + * default: false */ - onTabChange?: (tab: TabsState) => void; + tabs: + | boolean + | { + /** + * Callback that is invoked onTabChange. + */ + onTabChange?: (tab: TabsState) => void; + }; }; export type GraphiQLState = { @@ -535,7 +544,12 @@ export class GraphiQL extends React.Component { response: undefined, }; - const rawTabState = this._storage.get('tabState'); + let rawTabState: string | null = null; + // only load tab state if tabs are enabled + if (this.props.tabs) { + rawTabState = this._storage.get('tabState'); + } + let tabsState: TabsState; if (rawTabState === null) { tabsState = { @@ -737,13 +751,17 @@ export class GraphiQL extends React.Component { }; private _persistTabsState = () => { - this._storage.set( - 'tabState', - JSON.stringify(this.state.tabs, (key, value) => - key === 'response' ? undefined : value, - ), - ); - this.props.onTabChange?.(this.state.tabs); + if (this.props.tabs) { + this._storage.set( + 'tabState', + JSON.stringify(this.state.tabs, (key, value) => + key === 'response' ? undefined : value, + ), + ); + if (typeof this.props.tabs === 'object') { + this.props.tabs.onTabChange?.(this.state.tabs); + } + } }; render() { @@ -863,130 +881,134 @@ export class GraphiQL extends React.Component { )} - - {this.state.tabs.tabs.map((tab, index) => ( - 1} - onSelect={() => { - this.handleStopQuery(); + {this.props.tabs ? ( + + {this.state.tabs.tabs.map((tab, index) => ( + 1} + onSelect={() => { + this.handleStopQuery(); + this.setState(state => { + const oldActiveTabIndex = state.tabs.activeTabIndex; + const tabs = state.tabs.tabs.map( + (currentTab, tabIndex) => { + if (tabIndex !== oldActiveTabIndex) { + return currentTab; + } + + return { + ...currentTab, + query: state.query, + variables: state.variables, + operationName: state.operationName, + headers: state.headers, + response: state.response, + hash: idFromTabContents({ + query: state.query, + variables: state.variables, + headers: state.headers, + }), + }; + }, + ); + + const newActiveTab = this.state.tabs.tabs[index]; + + return { + ...state, + query: newActiveTab.query, + variables: newActiveTab.variables, + operationName: newActiveTab.operationName, + headers: newActiveTab.headers, + response: newActiveTab.response, + tabs: { ...state.tabs, tabs, activeTabIndex: index }, + }; + }, this._persistTabsState); + }} + onClose={() => { + if (this.state.tabs.activeTabIndex === index) { + this.handleStopQuery(); + } + this.setState(state => { + const newActiveTabIndex = + state.tabs.activeTabIndex > 0 + ? state.tabs.activeTabIndex - 1 + : 0; + const newTabsState = { + ...state.tabs, + activeTabIndex: newActiveTabIndex, + tabs: state.tabs.tabs.filter((_tab, i) => index !== i), + }; + const activeTab = newTabsState.tabs[newActiveTabIndex]; + return { + ...state, + query: activeTab.query, + variables: activeTab.variables, + operationName: activeTab.operationName, + headers: activeTab.headers, + response: activeTab.response, + tabs: newTabsState, + }; + }, this._persistTabsState); + }} + /> + ))} + this.setState(state => { const oldActiveTabIndex = state.tabs.activeTabIndex; - const tabs = state.tabs.tabs.map((currentTab, tabIndex) => { - if (tabIndex !== oldActiveTabIndex) { - return currentTab; + + const newTab: TabState = { + id: guid(), + title: '', + headers: '', + variables: '', + query: '', + operationName: '', + response: '', + hash: idFromTabContents({ + query: '', + variables: '', + headers: '', + }), + }; + + const tabs = state.tabs.tabs.map((tab, index) => { + if (index !== oldActiveTabIndex) { + return tab; } return { - ...currentTab, - query: state.query, + ...tab, + headers: state.headers, variables: state.variables, + query: state.query, operationName: state.operationName, - headers: state.headers, response: state.response, - hash: idFromTabContents({ - query: state.query, - variables: state.variables, - headers: state.headers, - }), }; }); - const newActiveTab = this.state.tabs.tabs[index]; - return { ...state, - query: newActiveTab.query, - variables: newActiveTab.variables, - operationName: newActiveTab.operationName, - headers: newActiveTab.headers, - response: newActiveTab.response, - tabs: { ...state.tabs, tabs, activeTabIndex: index }, + headers: newTab.headers, + variables: newTab.variables, + query: newTab.query, + operationName: newTab.operationName, + response: newTab.response, + tabs: { + ...state.tabs, + activeTabIndex: state.tabs.tabs.length, + tabs: [...tabs, newTab], + }, }; - }, this._persistTabsState); - }} - onClose={() => { - if (this.state.tabs.activeTabIndex === index) { - this.handleStopQuery(); - } - this.setState(state => { - const newActiveTabIndex = - state.tabs.activeTabIndex > 0 - ? state.tabs.activeTabIndex - 1 - : 0; - const newTabsState = { - ...state.tabs, - activeTabIndex: newActiveTabIndex, - tabs: state.tabs.tabs.filter((_tab, i) => index !== i), - }; - const activeTab = newTabsState.tabs[newActiveTabIndex]; - return { - ...state, - query: activeTab.query, - variables: activeTab.variables, - operationName: activeTab.operationName, - headers: activeTab.headers, - response: activeTab.response, - tabs: newTabsState, - }; - }, this._persistTabsState); - }} + }, this._persistTabsState) + } /> - ))} - - this.setState(state => { - const oldActiveTabIndex = state.tabs.activeTabIndex; - - const newTab: TabState = { - id: guid(), - title: '', - headers: '', - variables: '', - query: '', - operationName: '', - response: '', - hash: idFromTabContents({ - query: '', - variables: '', - headers: '', - }), - }; - - const tabs = state.tabs.tabs.map((tab, index) => { - if (index !== oldActiveTabIndex) { - return tab; - } - - return { - ...tab, - headers: state.headers, - variables: state.variables, - query: state.query, - operationName: state.operationName, - response: state.response, - }; - }); - - return { - ...state, - headers: newTab.headers, - variables: newTab.variables, - query: newTab.query, - operationName: newTab.operationName, - response: newTab.response, - tabs: { - ...state.tabs, - activeTabIndex: state.tabs.tabs.length, - tabs: [...tabs, newTab], - }, - }; - }, this._persistTabsState) - } - /> - + + ) : null}
{ this.editorBarComponent = n;