From 875e9f674f46657a8b6b9a1ddda124e548b0ad66 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Tue, 15 Sep 2020 03:30:17 -0400 Subject: [PATCH] Initial tab bar implementation --- chrome/content/zotero/components/tabBar.jsx | 110 ++ .../content/zotero/standalone/standalone.xul | 15 +- chrome/content/zotero/tabs.js | 105 ++ chrome/content/zotero/zoteroPane.js | 5 + chrome/content/zotero/zoteroPane.xul | 981 +++++++++--------- scss/_zotero-react-client.scss | 2 + scss/components/_mainWindow.scss | 149 +++ scss/components/_tabsBar.scss | 42 + scss/mac/_tabsBar.scss | 9 + scss/zotero-react-client-mac.scss | 1 + 10 files changed, 929 insertions(+), 490 deletions(-) create mode 100644 chrome/content/zotero/components/tabBar.jsx create mode 100644 chrome/content/zotero/tabs.js create mode 100644 scss/components/_mainWindow.scss create mode 100644 scss/components/_tabsBar.scss create mode 100644 scss/mac/_tabsBar.scss diff --git a/chrome/content/zotero/components/tabBar.jsx b/chrome/content/zotero/components/tabBar.jsx new file mode 100644 index 0000000000..e88ecabc76 --- /dev/null +++ b/chrome/content/zotero/components/tabBar.jsx @@ -0,0 +1,110 @@ +/* + ***** BEGIN LICENSE BLOCK ***** + + Copyright © 2020 Corporation for Digital Scholarship + Vienna, Virginia, USA + https://www.zotero.org + + This file is part of Zotero. + + Zotero is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Zotero is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with Zotero. If not, see . + + ***** END LICENSE BLOCK ***** +*/ + +"use strict"; + +import React, { forwardRef, useState, useImperativeHandle, useEffect } from 'react'; +import cx from 'classnames'; + +const TabBar = forwardRef(function (props, ref) { + const [tabs, setTabs] = useState(props.initialTabs); + const [selectedIndex, setSelectedIndex] = useState(0); + + useImperativeHandle(ref, () => ({ + addTab({ title, type }) { + var newTabs = [...tabs]; + newTabs.push({ title, type }); + setTabs(newTabs); + setSelectedIndex(newTabs.length - 1); + }, + + renameTab(title, index) { + var newTabs = tabs.map((tab, currentIndex) => { + let newTab = Object.assign({}, tab); + if (index == currentIndex) { + newTab.title = title; + } + return newTab; + }); + setTabs(newTabs); + } + })); + + useEffect(() => { + if (props.onTabSelected) { + props.onTabSelected(selectedIndex); + } + }, [selectedIndex]); + + + function removeTab(index) { + var newTabs = [...tabs]; + newTabs.splice(index, 1); + setTabs(newTabs); + setSelectedIndex(selectedIndex - 1); + if (props.onTabClosed) { + props.onTabClosed(index); + } + } + + function handleTabClick(event, index) { + setSelectedIndex(index); + event.stopPropagation(); + } + + function handleTabClose(event, index) { + removeTab(index); + if (props.onTabClose) { + props.onTabClose(index); + } + event.stopPropagation(); + } + + function renderTab(tab, index) { + return ( +
handleTabClick(event, index)} + > +
{tab.title}
+
handleTabClose(event, index)} + > + X +
+
+ ); + } + + return ( +
+ { tabs.map((tab, index) => renderTab(tab, index)) } +
+ ); +}); + +export default TabBar; \ No newline at end of file diff --git a/chrome/content/zotero/standalone/standalone.xul b/chrome/content/zotero/standalone/standalone.xul index d6f748d1d4..712511567c 100644 --- a/chrome/content/zotero/standalone/standalone.xul +++ b/chrome/content/zotero/standalone/standalone.xul @@ -43,9 +43,13 @@