diff --git a/packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/elements.js b/packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/elements.ts similarity index 88% rename from packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/elements.js rename to packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/elements.ts index 0162e10b455..ba42f955326 100644 --- a/packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/elements.js +++ b/packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/elements.ts @@ -33,6 +33,9 @@ export const TabsContainer = styled.div` } `; +interface IStyledPrettierIconProps { + disabled?: boolean; +} export const StyledPrettierIcon = styled(PrettierIcon)` transition: 0.3s ease opacity; width: 1.125rem; @@ -47,7 +50,7 @@ export const StyledPrettierIcon = styled(PrettierIcon)` opacity: 1; } - ${props => + ${(props: IStyledPrettierIconProps) => props.disabled && css` opacity: 0; @@ -71,6 +74,11 @@ export const Line = styled.div` props.theme['editorGroupHeader.tabsBorder'] || 'rgba(255, 255, 255, 0.3)'}; `; +interface IIconWrapperProps { + active?: boolean; + disabled?: boolean; + theme: any; +} export const IconWrapper = styled.div` svg { transition: 0.3s ease opacity; @@ -86,7 +94,7 @@ export const IconWrapper = styled.div` opacity: 1; } - ${props => + ${(props: IIconWrapperProps) => props.active && css` opacity: 1; diff --git a/packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/index.js b/packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/index.js deleted file mode 100644 index 29091c8ed00..00000000000 --- a/packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/index.js +++ /dev/null @@ -1,228 +0,0 @@ -import React from 'react'; -import { inject, observer } from 'app/componentConnectors'; - -import { canPrettify } from 'app/utils/prettify'; -import Tooltip from '@codesandbox/common/lib/components/Tooltip'; - -import TabContainer from './TabContainer'; -import PreviewIcon from './PreviewIcon'; - -import { - Container, - TabsContainer, - IconContainer, - StyledPrettierIcon, - IconWrapper, - Line, -} from './elements'; - -import ModuleTab from './ModuleTab'; - -class EditorTabs extends React.Component { - componentDidUpdate(prevProps) { - if (this.props.currentModuleId !== prevProps.currentModuleId) { - const currentTab = this.tabEls[this.props.currentModuleId]; - - // We need to scroll to the tab - if (currentTab && this.container) { - const { width } = this.container.getBoundingClientRect(); - const scroll = this.container.scrollLeft; - const { left } = currentTab.getBoundingClientRect(); - - if (left > scroll && left < scroll + width) { - // if it's already in view - return; - } - - currentTab.scrollIntoView(false); - } - } - } - - closeTab = tabIndex => { - this.props.signals.editor.tabClosed({ tabIndex }); - }; - - moveTab = (prevIndex, nextIndex) => { - this.props.signals.editor.tabMoved({ prevIndex, nextIndex }); - }; - - /** - * Mark all tabs not dirty (not cursive) - */ - markNotDirty = () => { - this.props.signals.editor.moduleDoubleClicked(); - }; - - setCurrentModule = moduleId => { - this.props.signals.editor.moduleSelected({ id: moduleId }); - }; - - discardModuleChanges = moduleShortid => { - this.props.signals.editor.discardModuleChanges({ moduleShortid }); - }; - - prettifyModule = () => { - this.props.signals.editor.prettifyClicked({ - moduleShortid: this.props.store.editor.currentModuleShortid, - }); - }; - - canPrettify = module => { - if (!module) { - return false; - } - - return canPrettify(module.title); - }; - - container; - tabEls = {}; - - render() { - const { store, signals } = this.props; - const sandbox = store.editor.currentSandbox; - const moduleObject = {}; - // We keep this object to keep track if there are duplicate titles. - // In that case we need to show which directory the module is in. - const tabNamesObject = {}; - - sandbox.modules.forEach(m => { - moduleObject[m.shortid] = m; - }); - - store.editor.tabs - .filter(tab => tab.type === 'MODULE') - .filter(tab => moduleObject[tab.moduleShortid]) - .forEach(tab => { - const module = moduleObject[tab.moduleShortid]; - - tabNamesObject[module.title] = tabNamesObject[module.title] || []; - tabNamesObject[module.title].push(module.shortid); - }); - - const { currentTab } = store.editor; - const { currentModule } = store.editor; - - const previewVisible = store.editor.previewWindowVisible; - - return ( - - { - this.container = el; - }} - > - {store.editor.tabs - .map(tab => ({ ...tab, module: moduleObject[tab.moduleShortid] })) - .map((tab, i) => { - if (tab.type === 'MODULE') { - if (tab.module == null) { - return null; - } - - const { module } = tab; - const modulesWithName = tabNamesObject[module.title]; - const { id } = tab.module; - let dirName = null; - - if ( - modulesWithName.length > 1 && - module.directoryShortid != null - ) { - const dir = sandbox.directories.find( - d => - d.shortid === module.directoryShortid && - d.sourceId === module.sourceId - ); - - if (dir) { - dirName = dir.title; - } - } - - return ( - error.moduleId === id) - .length - )} - closeTab={this.closeTab} - moveTab={this.moveTab} - markNotDirty={this.markNotDirty} - dirName={dirName} - tabCount={store.editor.tabs.length} - position={i} - dirty={tab.dirty} - isNotSynced={Boolean( - store.editor.changedModuleShortids.includes( - tab.module.shortid - ) - )} - ref={el => { - this.tabEls[id] = el; - }} - /> - ); - } - if (tab.type === 'DIFF') { - return ( - - signals.editor.currentTabChanged({ tabId: tab.id }) - } - closeTab={this.closeTab} - moveTab={this.moveTab} - tabCount={store.editor.tabs.length} - position={i} - dirty={tab.dirty} - ref={el => { - this.tabEls[tab.id] = el; - }} - title={`Diff: ${tab.titleA} - ${tab.titleB}`} - /> - ); - } - - return null; - })} - - - - - - - - - - - - this.props.signals.editor.togglePreviewContent({}) - } - /> - - - - - ); - } -} - -export default inject('signals', 'store')(observer(EditorTabs)); diff --git a/packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/index.tsx b/packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/index.tsx new file mode 100644 index 00000000000..301000b9e7c --- /dev/null +++ b/packages/app/src/app/pages/Sandbox/Editor/Content/Tabs/index.tsx @@ -0,0 +1,233 @@ +import React, { useEffect } from 'react'; +import { useOvermind } from 'app/overmind'; +import Tooltip from '@codesandbox/common/lib/components/Tooltip'; +import TabContainer from './TabContainer'; +import PreviewIcon from './PreviewIcon'; + +import { + Container, + TabsContainer, + IconContainer, + StyledPrettierIcon, + IconWrapper, + Line, +} from './elements'; + +import ModuleTab from './ModuleTab'; + +interface IEditorTabsProps { + currentModuleId: string | number; +} + +interface IOvermindProp { + state: any; + actions: any; +} + +const EditorTabs: React.FunctionComponent = ({ + currentModuleId, +}) => { + const { + state: { editor: editorState }, + actions: { editor: editorAction }, + }: IOvermindProp = useOvermind(); + + let container = null; + const tabEls = {}; + + useEffect(() => { + const currentTab = tabEls[currentModuleId]; + + // We need to scroll to the tab + if (currentTab && container) { + const { width } = container.getBoundingClientRect(); + const scroll = container.scrollLeft; + const { left } = currentTab.getBoundingClientRect(); + + if (left > scroll && left < scroll + width) { + // if it's already in view + return; + } + + currentTab.scrollIntoView(false); + } + }, [container, currentModuleId, tabEls]); + + const closeTab = tabIndex => { + editorAction.tabClosed({ tabIndex }); + }; + + const moveTab = (prevIndex, nextIndex) => { + editorAction.tabMoved({ prevIndex, nextIndex }); + }; + + /** + * Mark all tabs not dirty (not cursive) + */ + const markNotDirty = () => { + editorAction.moduleDoubleClicked(); + }; + + const setCurrentModule = moduleId => { + editorAction.moduleSelected({ id: moduleId }); + }; + + const discardModuleChanges = moduleShortid => { + editorAction.discardModuleChanges({ moduleShortid }); + }; + + const prettifyModule = () => { + editorAction.prettifyClicked({ + moduleShortid: editorState.currentModuleShortid, + }); + }; + + const canPrettify = module => { + if (!module) { + return false; + } + + return canPrettify(module.title); + }; + + const sandbox = editorState.currentSandbox; + const moduleObject = {}; + // We keep this object to keep track if there are duplicate titles. + // In that case we need to show which directory the module is in. + const tabNamesObject = {}; + + sandbox.modules.forEach(m => { + moduleObject[m.shortid] = m; + }); + + editorState.tabs + .filter(tab => tab.type === 'MODULE') + .filter(tab => moduleObject[tab.moduleShortid]) + .forEach(tab => { + const module = moduleObject[tab.moduleShortid]; + + tabNamesObject[module.title] = tabNamesObject[module.title] || []; + tabNamesObject[module.title].push(module.shortid); + }); + + const { currentTab } = editorState; + const { currentModule } = editorState; + + const previewVisible = editorState.previewWindowVisible; + + return ( + + { + container = el; + }} + > + {editorState.tabs + .map(tab => ({ ...tab, module: moduleObject[tab.moduleShortid] })) + .map((tab, i) => { + if (tab.type === 'MODULE') { + if (tab.module == null) { + return null; + } + + const { module } = tab; + const modulesWithName = tabNamesObject[module.title]; + const { id } = tab.module; + let dirName = null; + + if ( + modulesWithName.length > 1 && + module.directoryShortid != null + ) { + const dir = sandbox.directories.find( + d => + d.shortid === module.directoryShortid && + d.sourceId === module.sourceId + ); + + if (dir) { + dirName = dir.title; + } + } + + return ( + error.moduleId === id) + .length + )} + closeTab={closeTab} + moveTab={moveTab} + markNotDirty={markNotDirty} + dirName={dirName} + tabCount={editorState.tabs.length} + position={i} + dirty={tab.dirty} + isNotSynced={Boolean( + editorState.changedModuleShortids.includes( + tab.module.shortid + ) + )} + ref={el => { + tabEls[id] = el; + }} + /> + ); + } + if (tab.type === 'DIFF') { + return ( + + editorAction.currentTabChanged({ tabId: tab.id }) + } + closeTab={closeTab} + moveTab={moveTab} + tabCount={editorState.tabs.length} + position={i} + dirty={tab.dirty} + ref={el => { + tabEls[tab.id] = el; + }} + title={`Diff: ${tab.titleA} - ${tab.titleB}`} + /> + ); + } + + return null; + })} + + + + + + + + + + + editorAction.togglePreviewContent({})} + /> + + + + + ); +}; + +export default EditorTabs;