diff --git a/webapp/packages/core-administration/src/AdministrationItem/IAdministrationItem.ts b/webapp/packages/core-administration/src/AdministrationItem/IAdministrationItem.ts index c269bc94d6..8b1ec7a058 100644 --- a/webapp/packages/core-administration/src/AdministrationItem/IAdministrationItem.ts +++ b/webapp/packages/core-administration/src/AdministrationItem/IAdministrationItem.ts @@ -5,8 +5,6 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import type { ComponentStyle } from '@cloudbeaver/core-theming'; - import type { IRouteParams } from './IRouteParams'; export enum AdministrationItemType { @@ -24,7 +22,6 @@ export interface AdministrationItemDrawerProps { item: IAdministrationItem; configurationWizard: boolean; onSelect: (id: string) => void; - style: ComponentStyle; disabled?: boolean; } export type AdministrationItemDrawerComponent = React.FunctionComponent; diff --git a/webapp/packages/core-ui/src/ContextMenu/ContextMenu.tsx b/webapp/packages/core-ui/src/ContextMenu/ContextMenu.tsx index 43c216f473..ae189ac943 100644 --- a/webapp/packages/core-ui/src/ContextMenu/ContextMenu.tsx +++ b/webapp/packages/core-ui/src/ContextMenu/ContextMenu.tsx @@ -33,6 +33,7 @@ interface IContextMenuProps extends Omit, 'children'> onVisibleSwitch?: (visible: boolean) => void; } +// TODO the click doesn't work for React components as children export const ContextMenu = observer( forwardRef(function ContextMenu( { mouseContextMenu, menu: menuData, disclosure, children, placement, visible, onVisibleSwitch, modal, rtl, ...props }, diff --git a/webapp/packages/core-ui/src/SideBarPanel/SideBarPanel.tsx b/webapp/packages/core-ui/src/SideBarPanel/SideBarPanel.tsx index 105bce650b..d70d9ffa4f 100644 --- a/webapp/packages/core-ui/src/SideBarPanel/SideBarPanel.tsx +++ b/webapp/packages/core-ui/src/SideBarPanel/SideBarPanel.tsx @@ -6,69 +6,55 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { css } from 'reshadow'; -import { useStyles } from '@cloudbeaver/core-blocks'; +import { s, SContext, type StyleRegistry, useS } from '@cloudbeaver/core-blocks'; -import { BASE_TAB_STYLES } from '../Tabs/Tab/BASE_TAB_STYLES'; -import { UNDERLINE_TAB_STYLES } from '../Tabs/Tab/UnderlineTabStyles'; +import TabStyles from '../Tabs/Tab/Tab.m.css'; +import { TabUnderlineStyleRegistry } from '../Tabs/Tab/TabStyleRegistries'; import { TabList } from '../Tabs/TabList'; +import TabPanelStyles from '../Tabs/TabPanel.m.css'; import { TabPanelList } from '../Tabs/TabPanelList'; import type { TabsContainer } from '../Tabs/TabsContainer/TabsContainer'; import { TabsState } from '../Tabs/TabsState'; - -const tabsStyles = css` - TabList { - display: flex; - position: relative; - flex-shrink: 0; - align-items: center; - overflow: auto; - } - TabPanel { - display: flex; - flex-direction: column; - } - tab-outer:only-child { - display: none; - } -`; - -const formStyles = css` - box { - composes: theme-background-surface theme-text-on-surface from global; - width: 100%; - display: flex; - flex-direction: column; - flex: 1; - height: 100%; - overflow: auto; - } - content-box { - composes: theme-border-color-background from global; - position: relative; - display: flex; - flex: 1; - flex-direction: column; - overflow: auto; - } -`; +import styles from './shared/SideBarPanel.m.css'; +import SideBarPanelTab from './shared/SideBarPanelTab.m.css'; +import SideBarPanelTabPanel from './shared/SideBarPanelTabPanel.m.css'; interface Props { container: TabsContainer; } +const sideBarPanelRegistry: StyleRegistry = [ + ...TabUnderlineStyleRegistry, + [ + TabStyles, + { + mode: 'append', + styles: [SideBarPanelTab], + }, + ], + [ + TabPanelStyles, + { + mode: 'append', + styles: [SideBarPanelTabPanel], + }, + ], +]; + export const SideBarPanel = observer(function SideBarPanel({ container }) { - const tabStyle = [BASE_TAB_STYLES, tabsStyles, UNDERLINE_TAB_STYLES]; + const style = useS(styles); - return styled(useStyles(tabStyle, formStyles))( - - - - - - - - , + return ( + + +
+ +
+ +
+
+
+
); }); diff --git a/webapp/packages/core-ui/src/SideBarPanel/shared/SideBarPanel.m.css b/webapp/packages/core-ui/src/SideBarPanel/shared/SideBarPanel.m.css new file mode 100644 index 0000000000..cb41ee470b --- /dev/null +++ b/webapp/packages/core-ui/src/SideBarPanel/shared/SideBarPanel.m.css @@ -0,0 +1,33 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabList { + display: flex; + position: relative; + flex-shrink: 0; + align-items: center; + overflow: auto; +} + +.box { + composes: theme-background-surface theme-text-on-surface from global; + width: 100%; + display: flex; + flex-direction: column; + flex: 1; + height: 100%; + overflow: auto; +} +.contentBox { + composes: theme-border-color-background from global; + position: relative; + display: flex; + flex: 1; + flex-direction: column; + overflow: auto; +} diff --git a/webapp/packages/core-ui/src/SideBarPanel/shared/SideBarPanelTab.m.css b/webapp/packages/core-ui/src/SideBarPanel/shared/SideBarPanelTab.m.css new file mode 100644 index 0000000000..97ac1eb658 --- /dev/null +++ b/webapp/packages/core-ui/src/SideBarPanel/shared/SideBarPanelTab.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabOuter:only-child { + display: none; +} diff --git a/webapp/packages/core-ui/src/SideBarPanel/shared/SideBarPanelTabPanel.m.css b/webapp/packages/core-ui/src/SideBarPanel/shared/SideBarPanelTabPanel.m.css new file mode 100644 index 0000000000..335cd64b3f --- /dev/null +++ b/webapp/packages/core-ui/src/SideBarPanel/shared/SideBarPanelTabPanel.m.css @@ -0,0 +1,12 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabPanel { + display: flex; + flex-direction: column; +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/BASE_TAB_STYLES.ts b/webapp/packages/core-ui/src/Tabs/Tab/BASE_TAB_STYLES.ts deleted file mode 100644 index 52e68024d0..0000000000 --- a/webapp/packages/core-ui/src/Tabs/Tab/BASE_TAB_STYLES.ts +++ /dev/null @@ -1,164 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import { css } from 'reshadow'; - -export const BASE_TAB_STYLES = css` - placeholder { - composes: placeholder from global; - } - BaseTab { - position: relative; - outline: none; - font-weight: normal; - cursor: pointer; - padding: 0; - white-space: nowrap; - - height: 32px; - border-top: solid 2px transparent; - - &:global([aria-selected='true']) { - font-weight: 500; - cursor: auto; - border-top-color: var(--theme-negative); - opacity: 1; - - &:before { - display: none; - } - } - - &:not(:global([aria-selected='true'])) { - background-color: transparent !important; - } - } - - tab-inner { - composes: theme-typography--body2 tab from global; - display: grid; - position: relative; - } - - tab-inner[|selected] portal, - tab-inner portal[|menuOpened], - tab-inner:hover portal, - tab-inner:focus-within portal, - tab-inner[|selected] tab-action, - tab-inner:hover tab-action, - tab-inner:focus-within tab-action { - visibility: visible; - } - - tab-container { - max-width: 240px; - height: 100%; - display: flex; - flex-shrink: 0; - text-align: left; - align-items: center; - - & tab-icon { - display: flex; - height: 24px; - padding-left: 8px; - justify-content: center; - align-items: center; - - & StaticImage, - & IconOrImage, - & img { - width: 16px; - height: 16px; - } - - & placeholder { - width: 16px; - height: 16px; - } - } - - & tab-title { - overflow: hidden; - text-overflow: ellipsis; - padding: 0 8px; - } - - & tab-title placeholder { - width: 80px; - height: 16px; - } - } - - TabList { - box-sizing: border-box; - } - - TabPanel { - flex: 1; - display: flex; - overflow: hidden; - outline: none; - position: relative; - } -`; - -export const BASE_TAB_ACTION_STYLES = css` - tab-actions { - height: 100%; - display: flex; - flex-direction: column; - justify-content: space-between; - position: absolute; - top: 0; - right: 0; - z-index: 1; - overflow: hidden; - - &:not(:empty) + BaseTab { - padding-right: 14px; - } - - &:empty { - display: none; - } - } - - tab-action { - position: relative; - height: 8px; - width: 8px; - align-self: flex-start; - flex-shrink: 0; - padding: 4px; - padding-left: 0; - visibility: hidden; - - &:hover { - opacity: 0.8; - } - - &:before { - content: ''; - display: block; - left: -4px; - top: 0; - height: 16px; - width: 16px; - position: absolute; - cursor: pointer; - } - - & Icon { - display: block; - } - } - - portal { - visibility: hidden; - } -`; diff --git a/webapp/packages/core-ui/src/Tabs/Tab/BorderTabStyles.ts b/webapp/packages/core-ui/src/Tabs/Tab/BorderTabStyles.ts deleted file mode 100644 index 0dcdb4325b..0000000000 --- a/webapp/packages/core-ui/src/Tabs/Tab/BorderTabStyles.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import { css } from 'reshadow'; - -export const BORDER_TAB_STYLES = css` - TabList { - align-items: center; - box-sizing: border-box; - display: inline-flex; - width: 100%; - padding-left: 24px; - outline: none; - } - - TabPanel { - overflow: auto !important; - } - - Tab { - composes: theme-typography--body2 from global; - text-transform: uppercase; - font-weight: normal; - - &:global([aria-selected='true']) { - font-weight: normal !important; - } - - & TabTitle { - padding: 0 24px !important; - } - } -`; diff --git a/webapp/packages/core-ui/src/Tabs/Tab/Tab.m.css b/webapp/packages/core-ui/src/Tabs/Tab/Tab.m.css new file mode 100644 index 0000000000..3b4b8202c2 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/Tab.m.css @@ -0,0 +1,70 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.placeholder { + composes: placeholder from global; +} + +.tab { + position: relative; + outline: none; + font-weight: normal; + cursor: pointer; + padding: 0; + white-space: nowrap; + + height: 32px; + border-top: solid 2px transparent; + + &:global([aria-selected='true']) { + font-weight: 500; + cursor: auto; + border-top-color: var(--theme-negative); + opacity: 1; + + &:before { + display: none; + } + } + + &:not(:global([aria-selected='true'])) { + background-color: transparent !important; + } +} + +.actions:not(:empty) + .tab { + padding-right: 14px; +} + +.tabInner { + composes: theme-typography--body2 tab from global; + display: grid; + position: relative; +} + +.tabInnerSelected .portal, +.tabInner:hover .portal, +.tabInner:focus-within .portal, +.tabInnerSelected .tabAction, +.tabInner:hover .tabAction, +.tabInner:focus-within .tabAction { + visibility: visible; +} + +.tabContainer { + max-width: 240px; + height: 100%; + display: flex; + flex-shrink: 0; + text-align: left; + align-items: center; +} + +.tabOuter { + display: block; +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/Tab.tsx b/webapp/packages/core-ui/src/Tabs/Tab/Tab.tsx index ee85b33a7b..29f92ffb9c 100644 --- a/webapp/packages/core-ui/src/Tabs/Tab/Tab.tsx +++ b/webapp/packages/core-ui/src/Tabs/Tab/Tab.tsx @@ -6,96 +6,53 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import { useMemo, useRef, useState } from 'react'; +import { useMemo, useRef } from 'react'; import { Tab as BaseTab } from 'reakit/Tab'; -import styled, { use } from 'reshadow'; -import { getComputed, Icon, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; -import type { IDataContext } from '@cloudbeaver/core-data-context'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; -import { useMenu } from '@cloudbeaver/core-view'; +import { getComputed, s, useS, useTranslate } from '@cloudbeaver/core-blocks'; -import { ContextMenu } from '../../ContextMenu/ContextMenu'; import { TabContext } from '../TabContext'; -import type { ITabsContext } from '../TabsContext'; -import { BASE_TAB_ACTION_STYLES, BASE_TAB_STYLES } from './BASE_TAB_STYLES'; -import { DATA_CONTEXT_TAB_ID } from './DATA_CONTEXT_TAB_ID'; -import { DATA_CONTEXT_TABS_CONTEXT } from './DATA_CONTEXT_TABS_CONTEXT'; -import { MENU_TAB } from './MENU_TAB'; +import style from './Tab.m.css'; +import { TabActions } from './TabActions'; import type { TabProps } from './TabProps'; import { useTab } from './useTab'; -export const Tab = observer(function Tab({ tabId, title, menuContext, disabled, className, children, style, onOpen, onClose, onClick }) { +export const Tab = observer(function Tab(props) { const translate = useTranslate(); + const { tabId, title, disabled, className, children, onOpen, onClose, onClick } = props; const ref = useRef(null); const tabContext = useMemo(() => ({ tabId }), [tabId]); const tab = useTab(tabId, onOpen, onClose, onClick); const info = tab.getInfo(); - + const styles = useS(style); const canClose = getComputed(() => !!onClose || (tab.closable && tab.state.closable)); - return styled(useStyles(BASE_TAB_STYLES, BASE_TAB_ACTION_STYLES, style))( + return ( - - - - {canClose && ( - - - - )} - - +
+
+ - {children} +
{children}
- - - , - ); -}); - -interface TabMenuProps { - tabId: string; - state: ITabsContext; - menuContext?: IDataContext; - style?: ComponentStyle; -} - -const TabMenu = observer(function TabMenu({ tabId, state, menuContext, style }) { - const styles = useStyles(BASE_TAB_STYLES, BASE_TAB_ACTION_STYLES, style); - - const [menuOpened, switchState] = useState(false); - const menu = useMenu({ - menu: MENU_TAB, - context: menuContext, - }); - - menu.context.set(DATA_CONTEXT_TABS_CONTEXT, state); - menu.context.set(DATA_CONTEXT_TAB_ID, tabId); - - const hidden = getComputed(() => !menu.items.length || menu.items.every(item => item.hidden)); - - if (hidden) { - return null; - } - - return styled(styles)( - - - - - - - , +
+
+
); }); diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabActions.m.css b/webapp/packages/core-ui/src/Tabs/Tab/TabActions.m.css new file mode 100644 index 0000000000..c4f256dace --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabActions.m.css @@ -0,0 +1,53 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabActions { + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + position: absolute; + top: 0; + right: 0; + z-index: 1; + overflow: hidden; + + &:empty { + display: none; + } +} + +.tabAction { + position: relative; + height: 8px; + width: 8px; + align-self: flex-start; + flex-shrink: 0; + padding: 4px; + padding-left: 0; + visibility: hidden; + + &:hover { + opacity: 0.8; + } + + &:before { + content: ''; + display: block; + left: -4px; + top: 0; + height: 16px; + width: 16px; + position: absolute; + cursor: pointer; + } +} + +.icon { + display: block; +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabActions.tsx b/webapp/packages/core-ui/src/Tabs/Tab/TabActions.tsx new file mode 100644 index 0000000000..43b65e9e04 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabActions.tsx @@ -0,0 +1,58 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { observer } from 'mobx-react-lite'; + +import { Icon, s, useS, useTranslate } from '@cloudbeaver/core-blocks'; +import type { IDataContext } from '@cloudbeaver/core-data-context'; + +import type { ITabsContext } from '../TabsContext'; +import TabStyle from './Tab.m.css'; +import style from './TabActions.m.css'; +import { TabMenu } from './TabMenu'; + +interface TabActionsProps { + tabId: string; + canClose: boolean; + state: ITabsContext; + className?: string; + menuContext?: IDataContext; + handleClose: React.MouseEventHandler | undefined; +} + +export const TabActions = observer(function TabActions({ tabId, canClose, state, className, menuContext, handleClose }: TabActionsProps) { + const styles = useS(TabStyle, style); + + return ( +
+ {canClose && } + + {/* TODO use TabAction but resolve ContextMenu issue first */} +
+ +
+
+
+ ); +}); + +interface TabActionProps { + iconName: string; + title?: string; + onClick?: React.MouseEventHandler; +} + +const TabAction = observer(function TabAction({ iconName, title, onClick }: TabActionProps) { + const styles = useS(TabStyle, style); + const translate = useTranslate(); + + return ( +
+ +
+ ); +}); diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabBigUnderlineStyles.m.css b/webapp/packages/core-ui/src/Tabs/Tab/TabBigUnderlineStyles.m.css new file mode 100644 index 0000000000..60009af2b3 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabBigUnderlineStyles.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + font-size: 14px; +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabDefault.tsx b/webapp/packages/core-ui/src/Tabs/Tab/TabDefault.tsx index 2ba57accc3..7c03556574 100644 --- a/webapp/packages/core-ui/src/Tabs/Tab/TabDefault.tsx +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabDefault.tsx @@ -6,10 +6,8 @@ * you may not use this file except in compliance with the License. */ import { useContext, useMemo } from 'react'; -import styled from 'reshadow'; -import { Translate, useStyles } from '@cloudbeaver/core-blocks'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; +import { Translate } from '@cloudbeaver/core-blocks'; import { TabContext } from '../TabContext'; import type { ITabData } from '../TabsContainer/ITabsContainer'; @@ -25,7 +23,6 @@ interface Props> { name?: string; component?: React.FC; className?: string; - style?: ComponentStyle; disabled?: boolean; onOpen?: (tab: ITabData) => void; onClose?: (tab: ITabData) => void; @@ -37,14 +34,12 @@ export function TabDefault>({ name, component, className, - style, disabled, onOpen, onClose, ...rest }: Props & T): React.ReactElement | null { const state = useContext(TabsContext); - const styles = useStyles(style); const tabContext = useMemo(() => ({ tabId }), [tabId]); const selected = state?.state.selectedId === tabId; @@ -56,7 +51,6 @@ export function TabDefault>({ tabId={tabId} className={className} {...(rest as unknown as T)} - style={style} selected={selected} disabled={disabled} onOpen={onOpen} @@ -66,14 +60,14 @@ export function TabDefault>({ ); } - return styled(styles)( - + return ( + {icon && } {name && ( )} - , + ); } diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabIcon.m.css b/webapp/packages/core-ui/src/Tabs/Tab/TabIcon.m.css new file mode 100644 index 0000000000..c19e7c4a92 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabIcon.m.css @@ -0,0 +1,27 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabIcon { + display: flex; + height: 24px; + padding-left: 8px; + justify-content: center; + align-items: center; + + & .staticImage, + & .iconOrImage, + & img { + width: 16px; + height: 16px; + } + + & .placeholder { + width: 16px; + height: 16px; + } +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabIcon.tsx b/webapp/packages/core-ui/src/Tabs/Tab/TabIcon.tsx index 1df45c108d..06d792442d 100644 --- a/webapp/packages/core-ui/src/Tabs/Tab/TabIcon.tsx +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabIcon.tsx @@ -5,11 +5,9 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import styled from 'reshadow'; +import { IconOrImage, s, useS } from '@cloudbeaver/core-blocks'; -import { IconOrImage, useStyles } from '@cloudbeaver/core-blocks'; - -import { BASE_TAB_STYLES } from './BASE_TAB_STYLES'; +import TabIconStyles from './TabIcon.m.css'; interface IProps { icon?: string; @@ -18,7 +16,15 @@ interface IProps { } export const TabIcon: React.FC = function TabIcon({ icon, viewBox, className }) { - return styled(useStyles(BASE_TAB_STYLES))( - {icon ? : }, + const styles = useS(TabIconStyles); + + return ( +
+ {icon ? ( + + ) : ( +
+ )} +
); }; diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabIconVerticalRotated.m.css b/webapp/packages/core-ui/src/Tabs/Tab/TabIconVerticalRotated.m.css new file mode 100644 index 0000000000..3bfec277c6 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabIconVerticalRotated.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabIcon { + padding-left: 6px; +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabMenu.m.css b/webapp/packages/core-ui/src/Tabs/Tab/TabMenu.m.css new file mode 100644 index 0000000000..dd3b9f58df --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabMenu.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.portal { + visibility: hidden; +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabMenu.tsx b/webapp/packages/core-ui/src/Tabs/Tab/TabMenu.tsx new file mode 100644 index 0000000000..1d22ff97eb --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabMenu.tsx @@ -0,0 +1,50 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { observer } from 'mobx-react-lite'; + +import { getComputed, s, useS } from '@cloudbeaver/core-blocks'; +import type { IDataContext } from '@cloudbeaver/core-data-context'; +import { useMenu } from '@cloudbeaver/core-view'; + +import { ContextMenu } from '../../ContextMenu/ContextMenu'; +import type { ITabsContext } from '../TabsContext'; +import { DATA_CONTEXT_TAB_ID } from './DATA_CONTEXT_TAB_ID'; +import { DATA_CONTEXT_TABS_CONTEXT } from './DATA_CONTEXT_TABS_CONTEXT'; +import { MENU_TAB } from './MENU_TAB'; +import style from './TabMenu.m.css'; + +interface TabMenuProps extends React.PropsWithChildren { + tabId: string; + state: ITabsContext; + menuContext?: IDataContext; +} + +export const TabMenu = observer(function TabMenu({ children, tabId, state, menuContext }) { + const styles = useS(style); + const menu = useMenu({ + menu: MENU_TAB, + context: menuContext, + }); + + menu.context.set(DATA_CONTEXT_TABS_CONTEXT, state); + menu.context.set(DATA_CONTEXT_TAB_ID, tabId); + + const hidden = getComputed(() => !menu.items.length || menu.items.every(item => item.hidden)); + + if (hidden) { + return null; + } + + return ( +
+ + {children} + +
+ ); +}); diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabProps.ts b/webapp/packages/core-ui/src/Tabs/Tab/TabProps.ts index 4911cf5b2d..ba0a17ef29 100644 --- a/webapp/packages/core-ui/src/Tabs/Tab/TabProps.ts +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabProps.ts @@ -8,7 +8,6 @@ import type { PropsWithChildren } from 'react'; import type { IDataContext } from '@cloudbeaver/core-data-context'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import type { ITabData } from '../TabsContainer/ITabsContainer'; @@ -19,7 +18,6 @@ export type TabProps = PropsWithChildren<{ selected?: boolean; disabled?: boolean; className?: string; - style?: ComponentStyle; onOpen?: (tab: ITabData) => void; onClose?: (tab: ITabData) => void; onClick?: (tabId: string) => void; diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabStyleRegistries.ts b/webapp/packages/core-ui/src/Tabs/Tab/TabStyleRegistries.ts new file mode 100644 index 0000000000..96423ce322 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabStyleRegistries.ts @@ -0,0 +1,20 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import type { StyleRegistry } from '@cloudbeaver/core-blocks'; + +import TabStyles from './Tab.m.css'; +import TabBigUnderlineStyles from './TabBigUnderlineStyles.m.css'; +import TabTitleStyles from './TabTitle.m.css'; +import TabTitleBigUnderlineStyles from './TabTitleBigUnderlineStyles.m.css'; +import TabUnderlineStyles from './TabUnderline.m.css'; + +export const TabUnderlineStyleRegistry: StyleRegistry = [[TabStyles, { mode: 'append', styles: [TabUnderlineStyles] }]]; +export const TabBigUnderlineStyleRegistry: StyleRegistry = [ + [TabStyles, { mode: 'append', styles: [TabUnderlineStyles, TabBigUnderlineStyles] }], + [TabTitleStyles, { mode: 'append', styles: [TabTitleBigUnderlineStyles] }], +]; diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabTitle.m.css b/webapp/packages/core-ui/src/Tabs/Tab/TabTitle.m.css new file mode 100644 index 0000000000..49d2fe70a7 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabTitle.m.css @@ -0,0 +1,18 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabTitle { + overflow: hidden; + text-overflow: ellipsis; + padding: 0 8px; +} + +.placeholder { + width: 80px; + height: 16px; +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabTitle.tsx b/webapp/packages/core-ui/src/Tabs/Tab/TabTitle.tsx index fd2ec3445e..456e3f82fd 100644 --- a/webapp/packages/core-ui/src/Tabs/Tab/TabTitle.tsx +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabTitle.tsx @@ -5,14 +5,15 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import styled from 'reshadow'; +import { s, useS } from '@cloudbeaver/core-blocks'; -import { BASE_TAB_STYLES } from './BASE_TAB_STYLES'; +import TabTitleStyles from './TabTitle.m.css'; interface IProps { className?: string; } export const TabTitle: React.FC> = function TabTitle({ children, className }) { - return styled(BASE_TAB_STYLES)({children || }); + const styles = useS(TabTitleStyles); + return
{children ||
}
; }; diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabTitleBigUnderlineStyles.m.css b/webapp/packages/core-ui/src/Tabs/Tab/TabTitleBigUnderlineStyles.m.css new file mode 100644 index 0000000000..2ccc7b9341 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabTitleBigUnderlineStyles.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabTitle { + padding: 0 16px; +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabTitleVerticalRotated.m.css b/webapp/packages/core-ui/src/Tabs/Tab/TabTitleVerticalRotated.m.css new file mode 100644 index 0000000000..ab3d34f870 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabTitleVerticalRotated.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabTitle { + padding: 0 6px; +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabUnderline.m.css b/webapp/packages/core-ui/src/Tabs/Tab/TabUnderline.m.css new file mode 100644 index 0000000000..028d625b35 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabUnderline.m.css @@ -0,0 +1,33 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + composes: theme-typography--caption from global; + background: none; + color: inherit; + border: none; + border-bottom: 2px solid var(--theme-primary); + outline: none; + opacity: 1; + border-top: none !important; + font-weight: normal !important; + text-transform: uppercase; + + &:global([aria-selected='false']) { + opacity: 0.8; + border-bottom: 2px solid transparent !important; + } + + &:global([aria-disabled='true']) { + opacity: 0.5; + } + + &:hover { + opacity: 1; + } +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabVertical.m.css b/webapp/packages/core-ui/src/Tabs/Tab/TabVertical.m.css new file mode 100644 index 0000000000..d76dc265aa --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabVertical.m.css @@ -0,0 +1,14 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + overflow: auto; + border: none !important; + flex-shrink: 0; + height: 32px !important; +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/TabVerticalRotated.m.css b/webapp/packages/core-ui/src/Tabs/Tab/TabVerticalRotated.m.css new file mode 100644 index 0000000000..2d8005643b --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/Tab/TabVerticalRotated.m.css @@ -0,0 +1,30 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabOuter { + display: table; +} +.tabInner { + padding: 50% 0; + height: 0; + + & .tab { + transform-origin: top left; + display: block; + box-sizing: border-box; + transform: rotate(-90deg) translate(-100%); + margin-top: -50%; + height: 32px; + border: none; + border-radius: var(--theme-group-element-radius); + + &::before { + border-radius: var(--theme-group-element-radius); + } + } +} diff --git a/webapp/packages/core-ui/src/Tabs/Tab/UnderlineTabStyles.ts b/webapp/packages/core-ui/src/Tabs/Tab/UnderlineTabStyles.ts deleted file mode 100644 index bf0d9be350..0000000000 --- a/webapp/packages/core-ui/src/Tabs/Tab/UnderlineTabStyles.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import { css } from 'reshadow'; - -export const UNDERLINE_TAB_STYLES = css` - TabList { - display: flex; - } - Tab { - composes: theme-typography--caption from global; - background: none; - color: inherit; - border: none; - border-bottom: 2px solid var(--theme-primary); - outline: none; - opacity: 1; - border-top: none !important; - font-weight: normal !important; - text-transform: uppercase; - - &:global([aria-selected='false']) { - opacity: 0.8; - border-bottom: 2px solid transparent !important; - } - - &:global([aria-disabled='true']) { - opacity: 0.5; - } - - &:hover { - opacity: 1; - } - } -`; - -export const UNDERLINE_TAB_BIG_STYLES = css` - Tab { - font-size: 14px; - - & TabTitle { - padding: 0 16px; - } - } -`; diff --git a/webapp/packages/core-ui/src/Tabs/Tab/VERTICAL_ROTATED_TAB_STYLES.ts b/webapp/packages/core-ui/src/Tabs/Tab/VERTICAL_ROTATED_TAB_STYLES.ts deleted file mode 100644 index a151f3eda4..0000000000 --- a/webapp/packages/core-ui/src/Tabs/Tab/VERTICAL_ROTATED_TAB_STYLES.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import { css } from 'reshadow'; - -export const VERTICAL_ROTATED_TAB_STYLES = css` - tab-outer { - display: table; - } - tab-inner { - padding: 50% 0; - height: 0; - - & Tab { - transform-origin: top left; - display: block; - box-sizing: border-box; - transform: rotate(-90deg) translate(-100%); - margin-top: -50%; - height: 32px; - border: none; - border-radius: var(--theme-group-element-radius); - - &::before { - border-radius: var(--theme-group-element-radius); - } - - & TabIcon { - padding-left: 6px; - } - & TabTitle { - padding: 0 6px; - } - } - } - TabList { - display: flex; - gap: 4px; - outline: none; - max-width: 32px; - flex-direction: column; - } -`; diff --git a/webapp/packages/core-ui/src/Tabs/Tab/verticalTabStyles.ts b/webapp/packages/core-ui/src/Tabs/Tab/verticalTabStyles.ts deleted file mode 100644 index d5f44333e7..0000000000 --- a/webapp/packages/core-ui/src/Tabs/Tab/verticalTabStyles.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import { css } from 'reshadow'; - -export const verticalTabStyles = css` - Tab { - overflow: auto; - border: none !important; - flex-shrink: 0; - height: 32px !important; - } - vertical-tabs { - display: flex; - overflow: hidden; - } - TabList { - display: flex; - flex-direction: column; - flex: 0 0 auto; - min-width: 150px; - overflow: auto; - outline: none; - } -`; diff --git a/webapp/packages/core-ui/src/Tabs/TabList.m.css b/webapp/packages/core-ui/src/Tabs/TabList.m.css index c77f81f447..e679aae938 100644 --- a/webapp/packages/core-ui/src/Tabs/TabList.m.css +++ b/webapp/packages/core-ui/src/Tabs/TabList.m.css @@ -8,4 +8,5 @@ .tabList { display: flex; + box-sizing: border-box; } diff --git a/webapp/packages/core-ui/src/Tabs/TabList.tsx b/webapp/packages/core-ui/src/Tabs/TabList.tsx index f1bf46e45a..bfe18e0b1b 100644 --- a/webapp/packages/core-ui/src/Tabs/TabList.tsx +++ b/webapp/packages/core-ui/src/Tabs/TabList.tsx @@ -10,7 +10,6 @@ import { useContext } from 'react'; import { TabList as BaseTabList, TabListOptions, TabStateReturn } from 'reakit/Tab'; import { s, useS, useTranslate } from '@cloudbeaver/core-blocks'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import { generateTabElement } from './generateTabElement'; import { TabDefault } from './Tab/TabDefault'; @@ -19,12 +18,11 @@ import { TabsContext } from './TabsContext'; interface Props extends Omit { 'aria-label'?: string; - style?: ComponentStyle; childrenFirst?: boolean; className?: string; } -export const TabList = observer>(function TabList({ style, className, children, childrenFirst, ...props }) { +export const TabList = observer>(function TabList({ className, children, childrenFirst, ...props }) { const state = useContext(TabsContext); const translate = useTranslate(); const componentStyle = useS(styles); @@ -54,7 +52,6 @@ export const TabList = observer>(function TabList icon={tabInfo.icon} component={tabInfo.tab?.()} {...state.props} - style={style} aria-label={tabInfo.name} disabled={props.disabled || tabInfo.isDisabled?.(tabInfo.key, state.props)} onOpen={tabInfo.onOpen} diff --git a/webapp/packages/core-ui/src/Tabs/TabListStyleRegistries.ts b/webapp/packages/core-ui/src/Tabs/TabListStyleRegistries.ts new file mode 100644 index 0000000000..1dcd0bb54f --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/TabListStyleRegistries.ts @@ -0,0 +1,67 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import type { StyleRegistry } from '@cloudbeaver/core-blocks'; + +import TabStyles from './Tab/Tab.m.css'; +import TabIconStyles from './Tab/TabIcon.m.css'; +import TabIconVerticalRotatedStyles from './Tab/TabIconVerticalRotated.m.css'; +import TabTitleStyles from './Tab/TabTitle.m.css'; +import TabTitleVerticalRotatedStyles from './Tab/TabTitleVerticalRotated.m.css'; +import TabVerticalStyles from './Tab/TabVertical.m.css'; +import TabVerticalRotatedStyles from './Tab/TabVerticalRotated.m.css'; +import TabListStyles from './TabList.m.css'; +import TabListVerticalStyles from './TabListVertical.m.css'; +import TabListVerticalRotatedStyles from './TabListVerticalRotated.m.css'; + +export const TabListVerticalRegistry: StyleRegistry = [ + [ + TabListStyles, + { + mode: 'append', + styles: [TabListVerticalStyles], + }, + ], + [ + TabStyles, + { + mode: 'append', + styles: [TabVerticalStyles], + }, + ], +]; + +export const TabListVerticalRotatedRegistry: StyleRegistry = [ + [ + TabListStyles, + { + mode: 'append', + styles: [TabListVerticalRotatedStyles], + }, + ], + [ + TabStyles, + { + mode: 'append', + styles: [TabVerticalRotatedStyles], + }, + ], + [ + TabIconStyles, + { + mode: 'append', + styles: [TabIconVerticalRotatedStyles], + }, + ], + [ + TabTitleStyles, + { + mode: 'append', + styles: [TabTitleVerticalRotatedStyles], + }, + ], +]; diff --git a/webapp/packages/core-ui/src/Tabs/TabListVertical.m.css b/webapp/packages/core-ui/src/Tabs/TabListVertical.m.css new file mode 100644 index 0000000000..7485490073 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/TabListVertical.m.css @@ -0,0 +1,16 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabList { + display: flex; + flex-direction: column; + flex: 0 0 auto; + min-width: 150px; + overflow: auto; + outline: none; +} diff --git a/webapp/packages/core-ui/src/Tabs/TabListVerticalRotated.m.css b/webapp/packages/core-ui/src/Tabs/TabListVerticalRotated.m.css new file mode 100644 index 0000000000..a9050e8ae2 --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/TabListVerticalRotated.m.css @@ -0,0 +1,15 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabList { + display: flex; + gap: 4px; + outline: none; + max-width: 32px; + flex-direction: column; +} diff --git a/webapp/packages/core-ui/src/Tabs/TabPanel.m.css b/webapp/packages/core-ui/src/Tabs/TabPanel.m.css new file mode 100644 index 0000000000..7cdb7c6e4c --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/TabPanel.m.css @@ -0,0 +1,15 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabPanel { + flex: 1; + display: flex; + overflow: hidden; + outline: none; + position: relative; +} diff --git a/webapp/packages/core-ui/src/Tabs/TabPanel.tsx b/webapp/packages/core-ui/src/Tabs/TabPanel.tsx index 7c007e7104..ad9f937a60 100644 --- a/webapp/packages/core-ui/src/Tabs/TabPanel.tsx +++ b/webapp/packages/core-ui/src/Tabs/TabPanel.tsx @@ -9,15 +9,17 @@ import { observer } from 'mobx-react-lite'; import { useContext, useMemo } from 'react'; import { TabPanel as BaseTabPanel } from 'reakit/Tab'; -import { getComputed, Loader } from '@cloudbeaver/core-blocks'; +import { getComputed, Loader, s, useS } from '@cloudbeaver/core-blocks'; import { TabContext } from './TabContext'; +import tabPanelStyles from './TabPanel.m.css'; import type { TabPanelProps } from './TabPanelProps'; import { TabsContext } from './TabsContext'; import { useTabsValidation } from './useTabsValidation'; export const TabPanel: React.FC = observer(function TabPanel({ tabId, children, className, lazy }) { const tabContextState = useContext(TabsContext); + const styles = useS(tabPanelStyles); if (!tabContextState) { throw new Error('Tabs context was not provided'); @@ -42,7 +44,7 @@ export const TabPanel: React.FC = observer(function TabPanel({ ta return ( - + {renderChildren()} diff --git a/webapp/packages/core-ui/src/Tabs/TabPanelList.tsx b/webapp/packages/core-ui/src/Tabs/TabPanelList.tsx index 5c7596f274..945ca0c96c 100644 --- a/webapp/packages/core-ui/src/Tabs/TabPanelList.tsx +++ b/webapp/packages/core-ui/src/Tabs/TabPanelList.tsx @@ -7,24 +7,14 @@ */ import { observer } from 'mobx-react-lite'; import { useContext } from 'react'; -import styled from 'reshadow'; - -import { useStyles } from '@cloudbeaver/core-blocks'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import { generateTabElement } from './generateTabElement'; -import { BASE_TAB_STYLES } from './Tab/BASE_TAB_STYLES'; import { TabPanel } from './TabPanel'; import type { ITabInfo } from './TabsContainer/ITabsContainer'; import { TabsContext } from './TabsContext'; -interface Props extends React.PropsWithChildren { - style?: ComponentStyle; -} - -export const TabPanelList = observer(function TabPanelList({ style, children }) { +export const TabPanelList = observer(function TabPanelList({ children }) { const state = useContext(TabsContext); - const styles = useStyles(BASE_TAB_STYLES, style); if (!state) { throw new Error('Tabs context was not provided'); @@ -41,7 +31,7 @@ export const TabPanelList = observer(function TabPanelList({ style, child const displayed = state.container.getDisplayed(state.props); - return styled(styles)( + return ( <> {displayed .map( @@ -56,6 +46,6 @@ export const TabPanelList = observer(function TabPanelList({ style, child ) .flat()} {children} - , + ); }); diff --git a/webapp/packages/core-ui/src/Tabs/TabsBox/TabsBox.tsx b/webapp/packages/core-ui/src/Tabs/TabsBox/TabsBox.tsx index 7f7335e7b3..474f81febd 100644 --- a/webapp/packages/core-ui/src/Tabs/TabsBox/TabsBox.tsx +++ b/webapp/packages/core-ui/src/Tabs/TabsBox/TabsBox.tsx @@ -6,41 +6,25 @@ * you may not use this file except in compliance with the License. */ import { forwardRef, PropsWithChildren, ReactNode } from 'react'; -import styled, { css } from 'reshadow'; -import { useStyles } from '@cloudbeaver/core-blocks'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; +import { s, SContext, StyleRegistry, useS } from '@cloudbeaver/core-blocks'; import type { MetadataMap } from '@cloudbeaver/core-utils'; +import tabPanelStyles from '../TabPanel.m.css'; import type { ITabData } from '../TabsContainer/ITabsContainer'; import { TabsState } from '../TabsState'; +import styles from './shared/TabsBox.m.css'; +import moduleTabPanelStyles from './shared/TabsBoxTabPanel.m.css'; -const styles = css` - tabs-box { - display: flex; - flex-direction: column; - flex: 1; - overflow: hidden; - } - tabs { - display: flex; - flex-direction: row; - flex: 0 0 auto; - overflow: auto; - } - tab-panels { - flex: 1; - display: flex; - overflow: hidden; - } - tab-panel { - flex: 1; - display: flex; - overflow: hidden; - outline: none; - position: relative; - } -`; +const tabsBoxRegistry: StyleRegistry = [ + [ + tabPanelStyles, + { + mode: 'append', + styles: [moduleTabPanelStyles], + }, + ], +]; type TabsBoxProps = PropsWithChildren<{ currentTabId: string | null; @@ -48,33 +32,37 @@ type TabsBoxProps = PropsWithChildren<{ tabIndex?: number; localState?: MetadataMap; tabList?: string[]; + tabsClassName?: string; enabledBaseActions?: boolean; autoSelect?: boolean; className?: string; onChange?: (tab: ITabData) => void; - style?: ComponentStyle; }>; +/** + * @deprecated + */ export const TabsBox = forwardRef(function TabsBox( - { currentTabId, tabs, tabIndex, localState, tabList, enabledBaseActions, autoSelect, children, className, onChange, style }, + { currentTabId, tabs, tabIndex, localState, tabsClassName, tabList, enabledBaseActions, autoSelect, children, className, onChange }, ref, ) { - return styled( - styles, - useStyles(style), - )( - - - {tabs && {tabs}} - {children} - - , + const style = useS(styles); + + return ( + + +
+ {tabs &&
{tabs}
} +
{children}
+
+
+
); }); diff --git a/webapp/packages/core-ui/src/Tabs/TabsBox/TabsBoxFromArray.tsx b/webapp/packages/core-ui/src/Tabs/TabsBox/TabsBoxFromArray.tsx deleted file mode 100644 index bcfefc5ae2..0000000000 --- a/webapp/packages/core-ui/src/Tabs/TabsBox/TabsBoxFromArray.tsx +++ /dev/null @@ -1,68 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; - -import { useStyles } from '@cloudbeaver/core-blocks'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; - -import { BASE_TAB_STYLES } from '../Tab/BASE_TAB_STYLES'; -import { Tab } from '../Tab/Tab'; -import { TabPanel } from '../TabPanel'; -import type { ITabData } from '../TabsContainer/ITabsContainer'; -import { TabsBox } from './TabsBox'; - -export interface TabElementProps { - tabId: string; -} - -interface IProps { - currentTabId: string; - tabIdList: string[]; - tab: React.ElementType; - panel: React.ElementType; - hideTabs?: boolean; - onOpen: (tab: ITabData) => void; - onClose?: (tab: ITabData) => void; - className?: string; - style?: ComponentStyle; -} - -export const TabsBoxFromArray = observer(function TabsBoxFromArray({ - currentTabId, - tabIdList, - tab: TabData, - panel: PanelData, - hideTabs, - onOpen, - onClose, - className, - style, -}) { - return styled(useStyles(BASE_TAB_STYLES, style))( - ( - - - - )) - } - className={className} - style={style} - > - {tabIdList.map(tabId => ( - - - - ))} - , - ); -}); diff --git a/webapp/packages/core-ui/src/Tabs/TabsBox/shared/TabsBox.m.css b/webapp/packages/core-ui/src/Tabs/TabsBox/shared/TabsBox.m.css new file mode 100644 index 0000000000..52be08692f --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/TabsBox/shared/TabsBox.m.css @@ -0,0 +1,27 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabsBox { + display: flex; + flex-direction: column; + flex: 1; + overflow: hidden; +} + +.tabs { + display: flex; + flex-direction: row; + flex: 0 0 auto; + overflow: auto; +} + +.tabPanels { + flex: 1; + display: flex; + overflow: hidden; +} diff --git a/webapp/packages/core-ui/src/Tabs/TabsBox/shared/TabsBoxTabPanel.m.css b/webapp/packages/core-ui/src/Tabs/TabsBox/shared/TabsBoxTabPanel.m.css new file mode 100644 index 0000000000..7cdb7c6e4c --- /dev/null +++ b/webapp/packages/core-ui/src/Tabs/TabsBox/shared/TabsBoxTabPanel.m.css @@ -0,0 +1,15 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabPanel { + flex: 1; + display: flex; + overflow: hidden; + outline: none; + position: relative; +} diff --git a/webapp/packages/core-ui/src/index.ts b/webapp/packages/core-ui/src/index.ts index 748cdffefe..bbcdda809c 100644 --- a/webapp/packages/core-ui/src/index.ts +++ b/webapp/packages/core-ui/src/index.ts @@ -45,26 +45,36 @@ export * from './Tabs/TabsContext'; export * from './Tabs/TabsState'; export * from './Tabs/useTabState'; export * from './Tabs/useTabLocalState'; +export { default as TabStyles } from './Tabs/Tab/Tab.m.css'; +export { default as TabTitleStyles } from './Tabs/Tab/TabTitle.m.css'; +export { default as TabVerticalRotatedStyles } from './Tabs/Tab/TabVerticalRotated.m.css'; +export { default as TabIconVerticalRotatedStyles } from './Tabs/Tab/TabIconVerticalRotated.m.css'; +export { default as TabTitleVerticalRotatedStyles } from './Tabs/Tab/TabTitleVerticalRotated.m.css'; +export { default as TabListVerticalRotatedStyles } from './Tabs/TabListVerticalRotated.m.css'; +export { default as TabPanelStyles } from './Tabs/TabPanel.m.css'; +export { default as TabListStyles } from './Tabs/TabList.m.css'; +export { default as TabVertical } from './Tabs/Tab/TabVertical.m.css'; +export { default as TabListVertical } from './Tabs/TabListVertical.m.css'; +export { default as TabUnderlineStyles } from './Tabs/Tab/TabUnderline.m.css'; +export { default as TabBigUnderlineStyles } from './Tabs/Tab/TabBigUnderlineStyles.m.css'; +export { default as TabTitleBigUnderlineStyles } from './Tabs/Tab/TabTitleBigUnderlineStyles.m.css'; +export { default as TabIconStyles } from './Tabs/Tab/TabIcon.m.css'; +export * from './Tabs/Tab/TabStyleRegistries'; +export * from './Tabs/TabListStyleRegistries'; -export * from './Tabs/Tab/BASE_TAB_STYLES'; -export * from './Tabs/Tab/BorderTabStyles'; export * from './Tabs/Tab/DATA_CONTEXT_TAB_ID'; export * from './Tabs/Tab/DATA_CONTEXT_TABS_CONTEXT'; export * from './Tabs/Tab/MENU_TAB'; -export * from './Tabs/Tab/Tab'; + export * from './Tabs/Tab/Tab'; export * from './Tabs/Tab/TabDefault'; export * from './Tabs/Tab/TabIcon'; export * from './Tabs/Tab/TabProps'; export * from './Tabs/Tab/TabTitle'; export * from './Tabs/Tab/useTab'; -export * from './Tabs/Tab/VERTICAL_ROTATED_TAB_STYLES'; -export * from './Tabs/Tab/UnderlineTabStyles'; -export * from './Tabs/Tab/verticalTabStyles'; export * from './Tabs/TabsBootstrap'; export * from './Tabs/TabsBox/TabsBox'; -export * from './Tabs/TabsBox/TabsBoxFromArray'; export * from './SideBarPanel/LeftBarPanelService'; export * from './SideBarPanel/SideBarPanel'; diff --git a/webapp/packages/core-utils/package.json b/webapp/packages/core-utils/package.json index 4fb55ec22d..393acd0621 100644 --- a/webapp/packages/core-utils/package.json +++ b/webapp/packages/core-utils/package.json @@ -34,8 +34,10 @@ "devDependencies": { "@types/jest": "^29.5.12", "@types/md5": "~2.3.5", + "@types/react": "^18.2.63", "@types/underscore": "^1.11.15", "@types/uuid": "~9.0.8", + "react": "^18.2.0", "typescript": "^5.3.3" } } diff --git a/webapp/packages/plugin-administration/src/Administration/Administration.tsx b/webapp/packages/plugin-administration/src/Administration/Administration.tsx index ecd5245585..969fc86c4f 100644 --- a/webapp/packages/plugin-administration/src/Administration/Administration.tsx +++ b/webapp/packages/plugin-administration/src/Administration/Administration.tsx @@ -7,7 +7,6 @@ */ import { observer } from 'mobx-react-lite'; import { useLayoutEffect, useRef } from 'react'; -import styled, { css } from 'reshadow'; import { AdministrationItemService, filterOnlyActive, IAdministrationItemRoute } from '@cloudbeaver/core-administration'; import { @@ -21,63 +20,19 @@ import { ToolsActionStyles, ToolsPanelStyles, useS, - useStyles, } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; -import { BASE_TAB_STYLES, OptionsPanelService, TabList, TabsState, verticalTabStyles } from '@cloudbeaver/core-ui'; +import { OptionsPanelService, TabList, TabListStyles, TabListVerticalRegistry, TabsState, TabStyles } from '@cloudbeaver/core-ui'; import { CaptureView } from '@cloudbeaver/core-view'; import { AdministrationCaptureViewContext } from './AdministrationCaptureViewContext'; -import AdministrationToolbarStyles from './AdministrationToolbarStyles.m.css'; import { AdministrationViewService } from './AdministrationViewService'; import { DrawerItem } from './DrawerItem'; import { ItemContent } from './ItemContent'; - -const tabsStyles = css` - TabList { - composes: theme-background-surface theme-text-on-surface theme-border-color-background from global; - } - Tab { - composes: theme-ripple theme-background-background theme-ripple-selectable from global; - color: inherit; - } -`; - -const administrationStyles = css` - SlideElement { - composes: theme-background-secondary theme-text-on-secondary from global; - } - CaptureView { - composes: theme-background-secondary theme-text-on-secondary from global; - display: flex; - flex-direction: row; - flex: 1; - overflow: hidden; - } - TabList { - width: 240px; - padding-top: 16px; - border-right: 2px solid; - } - content-container { - flex: 1; - display: flex; - flex-direction: column; - overflow: auto; - } - SlideBox { - flex: 1; - } - content { - height: 100%; - display: flex; - flex-direction: column; - overflow: auto; - } - Loader { - height: 100%; - } -`; +import style from './shared/Administration.m.css'; +import AdministrationStylesTab from './shared/AdministrationTab.m.css'; +import AdministrationStylesTabList from './shared/AdministrationTabList.m.css'; +import AdministrationToolsPanelStyles from './shared/AdministrationToolsPanel.m.css'; interface Props { configurationWizard: boolean; @@ -85,19 +40,37 @@ interface Props { onItemSelect: (name: string) => void; } -const registry: StyleRegistry = [ +const adminPageRegistry: StyleRegistry = [ [ ToolsPanelStyles, { mode: 'append', - styles: [AdministrationToolbarStyles], + styles: [AdministrationToolsPanelStyles], }, ], [ ToolsActionStyles, { mode: 'append', - styles: [AdministrationToolbarStyles], + styles: [AdministrationToolsPanelStyles], + }, + ], +]; + +const tabsRegistry: StyleRegistry = [ + ...TabListVerticalRegistry, + [ + TabStyles, + { + mode: 'append', + styles: [AdministrationStylesTab], + }, + ], + [ + TabListStyles, + { + mode: 'append', + styles: [AdministrationStylesTabList], }, ], ]; @@ -108,7 +81,7 @@ export const Administration = observer>(function onItemSelect, children, }) { - const styles = useS(AdministrationToolbarStyles); + const styles = useS(style); const contentRef = useRef(null); const administrationViewService = useService(AdministrationViewService); const administrationItemService = useService(AdministrationItemService); @@ -122,43 +95,44 @@ export const Administration = observer>(function contentRef.current?.scrollTo({ top: 0, left: 0 }); }, [activeScreen?.item]); - return styled(useStyles(BASE_TAB_STYLES, verticalTabStyles, administrationStyles, tabsStyles))( - - - - + return ( + + + + {items.map(item => ( ))} - - {children} - - - - + +
+ {children} + + + + +
- +
- - + +
- +
optionsPanelService.close()} />
- - -
- , + +
+
+
); }); diff --git a/webapp/packages/plugin-administration/src/Administration/AdministrationToolbarStyles.m.css b/webapp/packages/plugin-administration/src/Administration/AdministrationToolbarStyles.m.css deleted file mode 100644 index 67dd8feb3f..0000000000 --- a/webapp/packages/plugin-administration/src/Administration/AdministrationToolbarStyles.m.css +++ /dev/null @@ -1,11 +0,0 @@ -.administration .toolsPanel { - height: 44px; -} - -.administration .buttonLabel { - font-size: 14px; -} - -.administration .button { - padding: 0 16px; -} diff --git a/webapp/packages/plugin-administration/src/Administration/DrawerItem.tsx b/webapp/packages/plugin-administration/src/Administration/DrawerItem.tsx index 4c87aff9d0..03aa00c644 100644 --- a/webapp/packages/plugin-administration/src/Administration/DrawerItem.tsx +++ b/webapp/packages/plugin-administration/src/Administration/DrawerItem.tsx @@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite'; import { type AdministrationItemDrawerProps, ConfigurationWizardService, filterOnlyActive } from '@cloudbeaver/core-administration'; import { useService } from '@cloudbeaver/core-di'; -export const DrawerItem = observer(function DrawerItem({ item, onSelect, style, configurationWizard, disabled }) { +export const DrawerItem = observer(function DrawerItem({ item, onSelect, configurationWizard, disabled }) { const configurationWizardService = useService(ConfigurationWizardService); const Component = item.getDrawerComponent(); @@ -20,5 +20,5 @@ export const DrawerItem = observer(function Drawe const onlyActive = filterOnlyActive(configurationWizard)(item) ? false : disabled; - return ; + return ; }); diff --git a/webapp/packages/plugin-administration/src/Administration/shared/Administration.m.css b/webapp/packages/plugin-administration/src/Administration/shared/Administration.m.css new file mode 100644 index 0000000000..e090128b24 --- /dev/null +++ b/webapp/packages/plugin-administration/src/Administration/shared/Administration.m.css @@ -0,0 +1,40 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +.slideElement { + composes: theme-background-secondary theme-text-on-secondary from global; +} + +.captureView { + composes: theme-background-secondary theme-text-on-secondary from global; + display: flex; + flex-direction: row; + flex: 1; + overflow: hidden; +} + +.contentContainer { + flex: 1; + display: flex; + flex-direction: column; + overflow: auto; +} + +.slideBox { + flex: 1; +} + +.content { + height: 100%; + display: flex; + flex-direction: column; + overflow: auto; +} + +.loader { + height: 100%; +} diff --git a/webapp/packages/plugin-administration/src/Administration/shared/AdministrationTab.m.css b/webapp/packages/plugin-administration/src/Administration/shared/AdministrationTab.m.css new file mode 100644 index 0000000000..f9e74fdd31 --- /dev/null +++ b/webapp/packages/plugin-administration/src/Administration/shared/AdministrationTab.m.css @@ -0,0 +1,12 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + composes: theme-ripple theme-background-background theme-ripple-selectable from global; + color: inherit; +} diff --git a/webapp/packages/plugin-administration/src/Administration/shared/AdministrationTabList.m.css b/webapp/packages/plugin-administration/src/Administration/shared/AdministrationTabList.m.css new file mode 100644 index 0000000000..24ac07ff72 --- /dev/null +++ b/webapp/packages/plugin-administration/src/Administration/shared/AdministrationTabList.m.css @@ -0,0 +1,14 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabList { + composes: theme-background-surface theme-text-on-surface theme-border-color-background from global; + width: 240px; + padding-top: 16px; + border-right: 2px solid; +} diff --git a/webapp/packages/plugin-administration/src/Administration/shared/AdministrationToolsPanel.m.css b/webapp/packages/plugin-administration/src/Administration/shared/AdministrationToolsPanel.m.css new file mode 100644 index 0000000000..ef2d84ba40 --- /dev/null +++ b/webapp/packages/plugin-administration/src/Administration/shared/AdministrationToolsPanel.m.css @@ -0,0 +1,19 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.toolsPanel { + height: 44px !important; +} + +.buttonLabel { + font-size: 14px !important; +} + +.button { + padding: 0 16px !important; +} diff --git a/webapp/packages/plugin-administration/src/ConfigurationWizard/Finish/FinishPageDrawerItem.tsx b/webapp/packages/plugin-administration/src/ConfigurationWizard/Finish/FinishPageDrawerItem.tsx index 920d04e82e..76d2d588a7 100644 --- a/webapp/packages/plugin-administration/src/ConfigurationWizard/Finish/FinishPageDrawerItem.tsx +++ b/webapp/packages/plugin-administration/src/ConfigurationWizard/Finish/FinishPageDrawerItem.tsx @@ -6,19 +6,18 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; import type { AdministrationItemDrawerProps } from '@cloudbeaver/core-administration'; -import { Translate, useStyles } from '@cloudbeaver/core-blocks'; -import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { Translate } from '@cloudbeaver/core-blocks'; +import { TabIcon, Tab, TabTitle } from '@cloudbeaver/core-ui'; -export const FinishPageDrawerItem = observer(function FinishPageDrawerItem({ item, onSelect, style, disabled }) { - return styled(useStyles(style))( +export const FinishPageDrawerItem = observer(function FinishPageDrawerItem({ item, onSelect, disabled }) { + return ( onSelect(item.name)}> - , + ); }); diff --git a/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationDrawerItem.tsx b/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationDrawerItem.tsx index 4a6102e8cd..0e83e06bb2 100644 --- a/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationDrawerItem.tsx +++ b/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationDrawerItem.tsx @@ -5,24 +5,21 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import styled from 'reshadow'; - import type { AdministrationItemDrawerProps } from '@cloudbeaver/core-administration'; -import { Translate, useStyles } from '@cloudbeaver/core-blocks'; -import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { Translate } from '@cloudbeaver/core-blocks'; +import { TabIcon, Tab, TabTitle } from '@cloudbeaver/core-ui'; export const ServerConfigurationDrawerItem: React.FC = function ServerConfigurationDrawerItem({ item, onSelect, - style, disabled, }) { - return styled(useStyles(style))( + return ( onSelect(item.name)}> - , + ); }; diff --git a/webapp/packages/plugin-administration/src/ConfigurationWizard/Welcome/WelcomeDrawerItem.tsx b/webapp/packages/plugin-administration/src/ConfigurationWizard/Welcome/WelcomeDrawerItem.tsx index a7eba34115..d8c647afda 100644 --- a/webapp/packages/plugin-administration/src/ConfigurationWizard/Welcome/WelcomeDrawerItem.tsx +++ b/webapp/packages/plugin-administration/src/ConfigurationWizard/Welcome/WelcomeDrawerItem.tsx @@ -5,19 +5,17 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import styled from 'reshadow'; - import type { AdministrationItemDrawerProps } from '@cloudbeaver/core-administration'; -import { Translate, useStyles } from '@cloudbeaver/core-blocks'; -import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { Translate } from '@cloudbeaver/core-blocks'; +import { TabIcon, Tab, TabTitle } from '@cloudbeaver/core-ui'; -export const WelcomeDrawerItem: React.FC = function WelcomeDrawerItem({ item, onSelect, style, disabled }) { - return styled(useStyles(style))( +export const WelcomeDrawerItem: React.FC = function WelcomeDrawerItem({ item, onSelect, disabled }) { + return ( onSelect(item.name)}> - , + ); }; diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.m.css b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.m.css index cd1956cce4..d1fdd531ef 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.m.css +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.m.css @@ -64,3 +64,8 @@ flex-direction: column; overflow: auto; } +.tabList { + position: relative; + flex-shrink: 0; + align-items: center; +} diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.tsx index bda8e4608c..5d6efd1d82 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.tsx @@ -7,12 +7,23 @@ */ import { observer } from 'mobx-react-lite'; import { useEffect } from 'react'; -import { css } from 'reshadow'; import type { TeamInfo } from '@cloudbeaver/core-authentication'; -import { Form, IconOrImage, Loader, Placeholder, s, useExecutor, useForm, useObjectRef, useS, useTranslate } from '@cloudbeaver/core-blocks'; +import { + Form, + IconOrImage, + Loader, + Placeholder, + s, + SContext, + useExecutor, + useForm, + useObjectRef, + useS, + useTranslate, +} from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; -import { BASE_TAB_STYLES, TabList, TabPanelList, TabsState, UNDERLINE_TAB_BIG_STYLES, UNDERLINE_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { TabBigUnderlineStyleRegistry, TabList, TabPanelList, TabsState } from '@cloudbeaver/core-ui'; import { teamContext } from './Contexts/teamContext'; import type { ITeamFormState } from './ITeamFormProps'; @@ -20,14 +31,6 @@ import style from './TeamForm.m.css'; import { ITeamFormActionsContext, TeamFormActionsContext } from './TeamFormActionsContext'; import { TeamFormService } from './TeamFormService'; -const tabsStyles = css` - TabList { - position: relative; - flex-shrink: 0; - align-items: center; - } -`; - interface Props { state: ITeamFormState; onCancel?: () => void; @@ -38,7 +41,6 @@ interface Props { export const TeamForm = observer(function TeamForm({ state, onCancel, onSave = () => {}, className }) { const translate = useTranslate(); const props = useObjectRef({ onSave }); - const innerTabStyles = [BASE_TAB_STYLES, tabsStyles, UNDERLINE_TAB_STYLES, UNDERLINE_TAB_BIG_STYLES]; const styles = useS(style); const service = useService(TeamFormService); const form = useForm({ @@ -81,7 +83,9 @@ export const TeamForm = observer(function TeamForm({ state, onCancel, onS )}
- + + +
@@ -92,7 +96,7 @@ export const TeamForm = observer(function TeamForm({ state, onCancel, onS
- +
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/AdministrationUserForm.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/AdministrationUserForm.tsx index 339a0e8912..63084cfe54 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/AdministrationUserForm.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/AdministrationUserForm.tsx @@ -7,19 +7,10 @@ */ import { observer } from 'mobx-react-lite'; -import { Button, Container, Form, s, StatusMessage, useAutoLoad, useForm, useS, useTranslate } from '@cloudbeaver/core-blocks'; +import { Button, Container, Form, s, SContext, StatusMessage, useAutoLoad, useForm, useS, useTranslate } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { NotificationService } from '@cloudbeaver/core-events'; -import { - BASE_TAB_STYLES, - FormMode, - IFormState, - TabList, - TabPanelList, - TabsState, - UNDERLINE_TAB_BIG_STYLES, - UNDERLINE_TAB_STYLES, -} from '@cloudbeaver/core-ui'; +import { FormMode, IFormState, TabBigUnderlineStyleRegistry, TabList, TabPanelList, TabsState } from '@cloudbeaver/core-ui'; import { getFirstException } from '@cloudbeaver/core-utils'; import style from './AdministrationUserForm.m.css'; @@ -32,7 +23,6 @@ interface Props { onClose: () => void; } -const deprecatedStyle = [BASE_TAB_STYLES, UNDERLINE_TAB_STYLES, UNDERLINE_TAB_BIG_STYLES]; export const AdministrationUserForm = observer(function AdministrationUserForm({ state, onClose }) { const styles = useS(style); const translate = useTranslate(); @@ -78,7 +68,9 @@ export const AdministrationUserForm = observer(function AdministrationUse - + + + {editing && ( diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Origin/UserFormOriginInfoTab.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Origin/UserFormOriginInfoTab.tsx index 415af3e3a6..15849ae2d7 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Origin/UserFormOriginInfoTab.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Origin/UserFormOriginInfoTab.tsx @@ -6,19 +6,18 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { Translate, useStyles } from '@cloudbeaver/core-blocks'; +import { Translate } from '@cloudbeaver/core-blocks'; import { Tab, TabContainerTabComponent, TabTitle } from '@cloudbeaver/core-ui'; import type { UserFormProps } from '../AdministrationUserFormService'; -export const UserFormOriginInfoTab: TabContainerTabComponent = observer(function UserFormOriginInfoTab({ tabId, style, ...rest }) { - return styled(useStyles(style))( - +export const UserFormOriginInfoTab: TabContainerTabComponent = observer(function UserFormOriginInfoTab(props) { + return ( + - , + ); }); diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministration.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministration.tsx index 16a656ff4b..b747fa5b34 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministration.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministration.tsx @@ -6,29 +6,38 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { css } from 'reshadow'; import type { AdministrationItemContentComponent } from '@cloudbeaver/core-administration'; -import { s, ToolsPanel, useS, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; +import { s, SContext, StyleRegistry, ToolsPanel, useS, useTranslate } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; -import { BASE_TAB_STYLES, ITabData, Tab, TabList, TabPanel, TabsState, TabTitle, UNDERLINE_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { + ITabData, + Tab, + TabList, + TabPanel, + TabPanelStyles, + TabsState, + TabStyles, + TabTitle, + TabTitleStyles, + TabUnderlineStyleRegistry, +} from '@cloudbeaver/core-ui'; +import style from './shared/UsersAdministration.m.css'; +import tabStyle from './shared/UsersAdministrationTab.m.css'; +import tabPanelStyle from './shared/UsersAdministrationTabPanel.m.css'; +import TabTitleModuleStyles from './shared/UsersAdministrationTabTitle.m.css'; import { TeamsPage } from './Teams/TeamsPage'; -import style from './UsersAdministration.m.css'; import { EUsersAdministrationSub, UsersAdministrationNavigationService } from './UsersAdministrationNavigationService'; import { UsersPage } from './UsersTable/UsersPage'; -const tabsStyles = css` - tab-inner { - height: 100%; - } - - tab-outer { - height: 100%; - } -`; +const tabPanelRegistry: StyleRegistry = [[TabPanelStyles, { mode: 'append', styles: [tabPanelStyle] }]]; -const tabStyle = [BASE_TAB_STYLES, tabsStyles, UNDERLINE_TAB_STYLES]; +const mainTabsRegistry: StyleRegistry = [ + ...TabUnderlineStyleRegistry, + [TabStyles, { mode: 'append', styles: [tabStyle] }], + [TabTitleStyles, { mode: 'append', styles: [TabTitleModuleStyles] }], +]; export const UsersAdministration: AdministrationItemContentComponent = observer(function UsersAdministration({ sub, param }) { const translate = useTranslate(); @@ -46,24 +55,28 @@ export const UsersAdministration: AdministrationItemContentComponent = observer( usersAdministrationNavigationService.navToSub(tabId as EUsersAdministrationSub, param || undefined); } - return styled(useStyles(tabStyle))( + return ( - - - - {translate('authentication_administration_item_users')} - - - {translate('administration_teams_tab_title')} - + + + + + {translate('authentication_administration_item_users')} + + + {translate('administration_teams_tab_title')} + + - - - - - - - , + + + + + + + + + ); }); diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersDrawerItem.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersDrawerItem.tsx index 0956258de5..0e37b6f5bb 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersDrawerItem.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersDrawerItem.tsx @@ -5,19 +5,17 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import styled from 'reshadow'; - import type { AdministrationItemDrawerProps } from '@cloudbeaver/core-administration'; -import { Translate, useStyles } from '@cloudbeaver/core-blocks'; -import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { Translate } from '@cloudbeaver/core-blocks'; +import { TabIcon, Tab, TabTitle } from '@cloudbeaver/core-ui'; -export const UsersDrawerItem: React.FC = function UsersDrawerItem({ item, onSelect, style, disabled }) { - return styled(useStyles(style))( +export const UsersDrawerItem: React.FC = function UsersDrawerItem({ item, onSelect, disabled }) { + return ( onSelect(item.name)}> - , + ); }; diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministration.m.css b/webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministration.m.css similarity index 64% rename from webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministration.m.css rename to webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministration.m.css index 3dbe755fdf..6bce98cb8b 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministration.m.css +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministration.m.css @@ -11,19 +11,4 @@ flex-shrink: 0; align-items: center; padding: 0 24px; - - .tab { - height: 100%; - font-size: 14px; - font-weight: 700; - padding: 0 4px; - - .tabTitle { - font-weight: 700; - } - } -} - -.tabPanel { - overflow: auto; } diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministrationTab.m.css b/webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministrationTab.m.css new file mode 100644 index 0000000000..b2851f1ae2 --- /dev/null +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministrationTab.m.css @@ -0,0 +1,22 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + height: 100%; + font-size: 14px; + font-weight: 700; + padding: 0 4px; +} + +.tabInner { + height: 100%; +} + +.tabOuter { + height: 100%; +} diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministrationTabPanel.m.css b/webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministrationTabPanel.m.css new file mode 100644 index 0000000000..efb5f5b439 --- /dev/null +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministrationTabPanel.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabPanel { + overflow: auto; +} diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministrationTabTitle.m.css b/webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministrationTabTitle.m.css new file mode 100644 index 0000000000..f65b7a8527 --- /dev/null +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/shared/UsersAdministrationTabTitle.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabTitle { + font-weight: 700; +} diff --git a/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx b/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx index 95f2ee5a9b..6c5c23d9aa 100644 --- a/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx +++ b/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx @@ -6,7 +6,6 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; import { AuthProvider, AuthProviderConfiguration, UserInfoResource } from '@cloudbeaver/core-authentication'; import { @@ -19,15 +18,15 @@ import { getComputed, Link, s, + SContext, TextPlaceholder, useErrorDetails, useS, - useStyles, useTranslate, } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { CommonDialogService, DialogComponent } from '@cloudbeaver/core-dialogs'; -import { BASE_TAB_STYLES, Tab, TabList, TabsState, TabTitle, UNDERLINE_TAB_BIG_STYLES, UNDERLINE_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { Tab, TabBigUnderlineStyleRegistry, TabList, TabsState, TabTitle } from '@cloudbeaver/core-ui'; import { AuthenticationService } from '../AuthenticationService'; import type { IAuthOptions } from '../IAuthOptions'; @@ -37,7 +36,6 @@ import { AuthProviderForm } from './AuthProviderForm/AuthProviderForm'; import { ConfigurationsList } from './AuthProviderForm/ConfigurationsList'; import { FEDERATED_AUTH } from './FEDERATED_AUTH'; import { getAuthProviderTabId, useAuthDialogState } from './useAuthDialogState'; -import { NotificationService } from '@cloudbeaver/core-events'; export const AuthDialog: DialogComponent = observer(function AuthDialog({ payload: { providerId, configurationId, linkUser = false, accessRequest = false }, @@ -50,7 +48,6 @@ export const AuthDialog: DialogComponent = observer(function const authenticationService = useService(AuthenticationService); const userInfo = useService(UserInfoResource); const commonDialogService = useService(CommonDialogService); - const notificationService = useService(NotificationService); const translate = useTranslate(); const state = dialogData.state; @@ -142,7 +139,7 @@ export const AuthDialog: DialogComponent = observer(function ); } - return styled(useStyles(BASE_TAB_STYLES, UNDERLINE_TAB_STYLES, UNDERLINE_TAB_BIG_STYLES))( + return ( { @@ -158,62 +155,64 @@ export const AuthDialog: DialogComponent = observer(function onReject={options?.persistent ? undefined : rejectDialog} /> - {showTabs && ( - - {dialogData.providers - .map(provider => { - if (provider.configurable) { - return provider.configurations?.map(configuration => { - const tabId = getAuthProviderTabId(provider, configuration); - return ( - { - state.setActiveProvider(provider, configuration); - }} - > - {configuration.displayName} - - ); - }); - } - return ( - { - state.setActiveProvider(provider, null); - }} - > - {provider.label} - - ); - }) - .flat()} - {dialogData.federatedProviders.length > 0 && ( - { - state.setActiveProvider(null, null); - state.setTabId(FEDERATED_AUTH); - }} - > - {translate('authentication_auth_federated')} - - )} - - )} + + {showTabs && ( + + {dialogData.providers + .map(provider => { + if (provider.configurable) { + return provider.configurations?.map(configuration => { + const tabId = getAuthProviderTabId(provider, configuration); + return ( + { + state.setActiveProvider(provider, configuration); + }} + > + {configuration.displayName} + + ); + }); + } + return ( + { + state.setActiveProvider(provider, null); + }} + > + {provider.label} + + ); + }) + .flat()} + {dialogData.federatedProviders.length > 0 && ( + { + state.setActiveProvider(null, null); + state.setTabId(FEDERATED_AUTH); + }} + > + {translate('authentication_auth_federated')} + + )} + + )} + {federate ? ( = observer(function )} - , + ); }); diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsDrawerItem.tsx b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsDrawerItem.tsx index 2bbf1180a5..86552c66fc 100644 --- a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsDrawerItem.tsx +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsDrawerItem.tsx @@ -5,25 +5,22 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import styled from 'reshadow'; - import type { AdministrationItemDrawerProps } from '@cloudbeaver/core-administration'; -import { Translate, useStyles } from '@cloudbeaver/core-blocks'; -import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { Translate } from '@cloudbeaver/core-blocks'; +import { TabIcon, Tab, TabTitle } from '@cloudbeaver/core-ui'; export const ConnectionsDrawerItem: React.FC = function ConnectionsDrawerItem({ item, onSelect, - style, disabled, configurationWizard, }) { - return styled(useStyles(style))( + return ( onSelect(item.name)}> - , + ); }; diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/CreateConnection.tsx b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/CreateConnection.tsx index 910c351d95..695c418661 100644 --- a/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/CreateConnection.tsx +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/CreateConnection.tsx @@ -6,146 +6,64 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { css } from 'reshadow'; -import { Icon, IconButton, Loader, StaticImage, useResource, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; +import { Fill, Icon, IconButton, Loader, s, SContext, StaticImage, StyleRegistry, useResource, useS, useTranslate } from '@cloudbeaver/core-blocks'; import { DBDriverResource } from '@cloudbeaver/core-connections'; import { useService } from '@cloudbeaver/core-di'; -import { BASE_TAB_STYLES, TabPanelList, TabsState, UNDERLINE_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { TabListStyles, TabPanelList, TabPanelStyles, TabsState, TabStyles, TabUnderlineStyleRegistry } from '@cloudbeaver/core-ui'; import { ConnectionFormLoader } from '@cloudbeaver/plugin-connections'; import { CreateConnectionService } from '../CreateConnectionService'; - -const styles = css` - title-bar { - composes: theme-border-color-background from global; - } - - connection-create { - display: flex; - flex-direction: column; - height: 800px; - overflow: hidden; - } - - connection-create-content { - composes: theme-background-secondary theme-text-on-secondary from global; - position: relative; - display: flex; - flex-direction: column; - flex: 1; - overflow: auto; - } - - Tab { - composes: theme-background-secondary theme-text-on-secondary from global; - } - - TabList { - composes: theme-border-color-background theme-background-secondary theme-text-on-secondary from global; - border-top: solid 1px; - position: relative; - flex-shrink: 0; - align-items: center; - - &:before { - content: ''; - position: absolute; - bottom: 0; - width: 100%; - border-bottom: solid 2px; - border-color: inherit; - } - } - - TabPanel, - CustomConnection, - SearchDatabase { - flex-direction: column; - height: 100%; - overflow: auto; - } - - Loader { - z-index: 1; - height: 100%; - } - - title-bar { - composes: theme-typography--headline6 from global; - padding: 16px 24px; - align-items: center; - display: flex; - font-weight: 400; - flex: auto 0 0; - } - - StaticImage { - width: 32px; - max-height: 32px; - margin-right: 16px; - } - - fill { - flex: 1; - } - - back-button { - position: relative; - box-sizing: border-box; - margin-right: 16px; - display: flex; - - & Icon { - box-sizing: border-box; - transform: rotate(90deg); - cursor: pointer; - height: 16px; - width: 16px; - } - } -`; - -const componentStyle = [BASE_TAB_STYLES, styles, UNDERLINE_TAB_STYLES]; +import styles from './shared/CreateConnection.m.css'; +import CreateConnectionTab from './shared/CreateConnectionTab.m.css'; +import CreateConnectionTabList from './shared/CreateConnectionTabList.m.css'; +import CreateConnectionTabPanel from './shared/CreateConnectionTabPanel.m.css'; interface Props { method: string | null | undefined; configurationWizard: boolean; } +const tabsRegistry: StyleRegistry = [ + ...TabUnderlineStyleRegistry, + [TabStyles, { mode: 'append', styles: [CreateConnectionTab] }], + [TabPanelStyles, { mode: 'append', styles: [CreateConnectionTabPanel] }], + [TabListStyles, { mode: 'append', styles: [CreateConnectionTabList] }], +]; + export const CreateConnection = observer(function CreateConnection({ method }) { - const style = useStyles(componentStyle); + const style = useS(styles); const createConnectionService = useService(CreateConnectionService); const translate = useTranslate(); const driver = useResource(CreateConnection, DBDriverResource, createConnectionService.data?.config.driverId || null); if (createConnectionService.data) { - return styled(style)( - - - - - - {driver.data?.icon && } + return ( +
+
+
+ +
+ {driver.data?.icon && } {driver.data?.name ?? translate('connections_administration_connection_create')} - + - - - +
+
+ - - , +
+
); } - return styled(style)( - + return ( +
(function CreateConnection({ meth lazy onChange={({ tabId }) => createConnectionService.setCreateMethod(tabId)} > - +
{translate('connections_administration_connection_create')} - + - - - +
+
+ + + {createConnectionService.disabled && } - +
- , +
); }); diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnection.m.css b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnection.m.css new file mode 100644 index 0000000000..38c6a485f4 --- /dev/null +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnection.m.css @@ -0,0 +1,69 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.titleBar { + composes: theme-border-color-background from global; +} + +.connectionCreate { + display: flex; + flex-direction: column; + height: 800px; + overflow: hidden; +} + +.connectionCreateContent { + composes: theme-background-secondary theme-text-on-secondary from global; + position: relative; + display: flex; + flex-direction: column; + flex: 1; + overflow: auto; +} + +.customConnection, +.searchDatabase { + flex-direction: column; + height: 100%; + overflow: auto; +} + +.loader { + z-index: 1; + height: 100%; +} + +.titleBar { + composes: theme-typography--headline6 from global; + padding: 16px 24px; + align-items: center; + display: flex; + font-weight: 400; + flex: auto 0 0; +} + +.staticImage { + width: 32px; + max-height: 32px; + margin-right: 16px; +} + +.backButton { + position: relative; + box-sizing: border-box; + margin-right: 16px; + display: flex; + + & .icon { + box-sizing: border-box; + transform: rotate(90deg); + cursor: pointer; + height: 16px; + width: 16px; + } +} diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnectionTab.m.css b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnectionTab.m.css new file mode 100644 index 0000000000..1c4f93f620 --- /dev/null +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnectionTab.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + composes: theme-background-secondary theme-text-on-secondary from global; +} diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnectionTabList.m.css b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnectionTabList.m.css new file mode 100644 index 0000000000..0c2c13d30e --- /dev/null +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnectionTabList.m.css @@ -0,0 +1,24 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabList { + composes: theme-border-color-background theme-background-secondary theme-text-on-secondary from global; + border-top: solid 1px; + position: relative; + flex-shrink: 0; + align-items: center; + + &:before { + content: ''; + position: absolute; + bottom: 0; + width: 100%; + border-bottom: solid 2px; + border-color: inherit; + } +} diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnectionTabPanel.m.css b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnectionTabPanel.m.css new file mode 100644 index 0000000000..0123791c63 --- /dev/null +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnection/shared/CreateConnectionTabPanel.m.css @@ -0,0 +1,13 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabPanel { + flex-direction: column; + height: 100%; + overflow: auto; +} diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.m.css b/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.m.css index b3fbf5b933..8445127924 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.m.css +++ b/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.m.css @@ -1,7 +1,83 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + .form { overflow: auto; display: flex; flex-direction: column; flex: 1; height: 100%; -} \ No newline at end of file +} + +.tabList { + position: relative; + flex-shrink: 0; + align-items: center; +} + +.connectionTopBar { + composes: theme-border-color-background theme-background-secondary theme-text-on-secondary from global; +} + +.connectionTopBar { + position: relative; + display: flex; + padding-top: 16px; + + &:before { + content: ''; + position: absolute; + bottom: 0; + width: 100%; + border-bottom: solid 2px; + border-color: inherit; + } +} + +.connectionTopBarTabs { + flex: 1; +} + +.connectionTopBarActions { + display: flex; + align-items: center; + padding: 0 24px; + gap: 16px; +} + +.connectionStatusMessage { + composes: theme-typography--caption from global; + height: 24px; + padding: 0 16px; + display: flex; + align-items: center; + gap: 8px; + + & .iconOrImage { + height: 24px; + width: 24px; + } +} + +.box { + composes: theme-background-secondary theme-text-on-secondary from global; + display: flex; + flex-direction: column; + flex: 1; + height: 100%; + overflow: auto; +} + +.contentBox { + composes: theme-background-secondary theme-border-color-background from global; + position: relative; + display: flex; + flex: 1; + flex-direction: column; + overflow: auto; +} diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.tsx index 429f1a13f4..fa8342d2a3 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.tsx +++ b/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.tsx @@ -7,95 +7,31 @@ */ import { observer } from 'mobx-react-lite'; import { useEffect } from 'react'; -import styled, { css } from 'reshadow'; -import { ExceptionMessage, Form, Loader, Placeholder, StatusMessage, useExecutor, useForm, useObjectRef, useStyles } from '@cloudbeaver/core-blocks'; +import { + ExceptionMessage, + Form, + Loader, + Placeholder, + s, + SContext, + StatusMessage, + useExecutor, + useForm, + useObjectRef, + useS, +} from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { ENotificationType } from '@cloudbeaver/core-events'; import type { ConnectionConfig } from '@cloudbeaver/core-sdk'; -import { BASE_TAB_STYLES, TabList, TabPanelList, TabsState, UNDERLINE_TAB_BIG_STYLES, UNDERLINE_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { TabBigUnderlineStyleRegistry, TabList, TabPanelList, TabsState } from '@cloudbeaver/core-ui'; import { ConnectionFormActionsContext, IConnectionFormActionsContext } from './ConnectFormActionsContext'; -import connectionFormStyles from './ConnectionForm.m.css'; +import style from './ConnectionForm.m.css'; import { ConnectionFormService } from './ConnectionFormService'; import { connectionConfigContext } from './Contexts/connectionConfigContext'; import type { IConnectionFormState } from './IConnectionFormProps'; -const tabsStyles = css` - TabList { - position: relative; - flex-shrink: 0; - align-items: center; - } -`; - -const topBarStyles = css` - connection-top-bar { - composes: theme-border-color-background theme-background-secondary theme-text-on-secondary from global; - } - connection-top-bar { - position: relative; - display: flex; - padding-top: 16px; - - &:before { - content: ''; - position: absolute; - bottom: 0; - width: 100%; - border-bottom: solid 2px; - border-color: inherit; - } - } - connection-top-bar-tabs { - flex: 1; - } - - connection-top-bar-actions { - display: flex; - align-items: center; - padding: 0 24px; - gap: 16px; - } - - /*Button:not(:first-child) { - margin-right: 24px; - }*/ - - connection-status-message { - composes: theme-typography--caption from global; - height: 24px; - padding: 0 16px; - display: flex; - align-items: center; - gap: 8px; - - & IconOrImage { - height: 24px; - width: 24px; - } - } -`; - -const formStyles = css` - box { - composes: theme-background-secondary theme-text-on-secondary from global; - display: flex; - flex-direction: column; - flex: 1; - height: 100%; - overflow: auto; - } - content-box { - composes: theme-background-secondary theme-border-color-background from global; - position: relative; - display: flex; - flex: 1; - flex-direction: column; - overflow: auto; - } -`; - export interface ConnectionFormProps { state: IConnectionFormState; onCancel?: () => void; @@ -105,9 +41,8 @@ export interface ConnectionFormProps { export const ConnectionForm = observer(function ConnectionForm({ state, onCancel, onSave = () => {}, className }) { const props = useObjectRef({ onSave }); - const style = [BASE_TAB_STYLES, tabsStyles, UNDERLINE_TAB_STYLES, UNDERLINE_TAB_BIG_STYLES]; - const styles = useStyles(style, topBarStyles, formStyles); const service = useService(ConnectionFormService); + const styles = useS(style); const form = useForm({ onSubmit: event => { @@ -144,41 +79,43 @@ export const ConnectionForm = observer(function ConnectionF }, [state]); if (state.initError) { - return styled(styles)( state.loadConnectionInfo()} />); + return state.loadConnectionInfo()} />; } if (!state.configured) { - return styled(styles)( - + return ( +
- , +
); } - return styled(styles)( -
+ return ( + - - - - +
+
+
+
- - - - +
+ + + +
+
- - - - - - +
+
+
+ +
+
-
, + ); }); diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfoTab.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfoTab.tsx index 1e140af963..8f918f04eb 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfoTab.tsx +++ b/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfoTab.tsx @@ -6,19 +6,18 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { Translate, useStyles } from '@cloudbeaver/core-blocks'; +import { Translate } from '@cloudbeaver/core-blocks'; import { Tab, TabContainerTabComponent, TabTitle } from '@cloudbeaver/core-ui'; import type { IConnectionFormProps } from '../IConnectionFormProps'; -export const OriginInfoTab: TabContainerTabComponent = observer(function OriginInfoTab({ state: { info }, style, ...rest }) { - return styled(useStyles(style))( - +export const OriginInfoTab: TabContainerTabComponent = observer(function OriginInfoTab({ state: { info }, ...rest }) { + return ( + - , + ); }); diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/SSH/SSHTab.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/SSH/SSHTab.tsx index 259f499c38..363c8f38e4 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/SSH/SSHTab.tsx +++ b/webapp/packages/plugin-connections/src/ConnectionForm/SSH/SSHTab.tsx @@ -6,23 +6,21 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { Translate, useResource, useStyles } from '@cloudbeaver/core-blocks'; +import { Translate, useResource } from '@cloudbeaver/core-blocks'; import { NetworkHandlerResource, SSH_TUNNEL_ID } from '@cloudbeaver/core-connections'; import { Tab, TabContainerTabComponent, TabTitle } from '@cloudbeaver/core-ui'; import type { IConnectionFormProps } from '../IConnectionFormProps'; -export const SSHTab: TabContainerTabComponent = observer(function SSHTab({ style, ...rest }) { - const styles = useStyles(style); +export const SSHTab: TabContainerTabComponent = observer(function SSHTab(props) { const handler = useResource(SSHTab, NetworkHandlerResource, SSH_TUNNEL_ID); - return styled(styles)( - + return ( + - , + ); }); diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/SSL/SSLTab.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/SSL/SSLTab.tsx index c9e192060e..fa805f35a6 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/SSL/SSLTab.tsx +++ b/webapp/packages/plugin-connections/src/ConnectionForm/SSL/SSLTab.tsx @@ -6,9 +6,8 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { Translate, useResource, useStyles } from '@cloudbeaver/core-blocks'; +import { Translate, useResource } from '@cloudbeaver/core-blocks'; import { DBDriverResource, NetworkHandlerResource } from '@cloudbeaver/core-connections'; import { CachedMapAllKey } from '@cloudbeaver/core-resource'; import { Tab, TabContainerTabComponent, TabTitle } from '@cloudbeaver/core-ui'; @@ -16,10 +15,9 @@ import { Tab, TabContainerTabComponent, TabTitle } from '@cloudbeaver/core-ui'; import type { IConnectionFormProps } from '../IConnectionFormProps'; import { getSSLDriverHandler } from './getSSLDriverHandler'; -export const SSLTab: TabContainerTabComponent = observer(function SSLTab({ style, ...rest }) { - const styles = useStyles(style); +export const SSLTab: TabContainerTabComponent = observer(function SSLTab(props) { const networkHandlerResource = useResource(SSLTab, NetworkHandlerResource, CachedMapAllKey); - const dbDriverResource = useResource(SSLTab, DBDriverResource, rest.state.config.driverId ?? null); + const dbDriverResource = useResource(SSLTab, DBDriverResource, props.state.config.driverId ?? null); const handler = getSSLDriverHandler(networkHandlerResource.resource.values, dbDriverResource.data?.applicableNetworkHandlers ?? []); @@ -27,11 +25,11 @@ export const SSLTab: TabContainerTabComponent = observer(f return null; } - return styled(styles)( - + return ( + - , + ); }); diff --git a/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialog.tsx b/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialog.tsx index 0e18958ed5..43504f39e1 100644 --- a/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialog.tsx +++ b/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialog.tsx @@ -7,7 +7,6 @@ */ import { observer } from 'mobx-react-lite'; import { useState } from 'react'; -import styled from 'reshadow'; import { CommonDialogBody, @@ -18,13 +17,13 @@ import { IProperty, PropertiesTable, s, + SContext, useErrorDetails, useS, - useStyles, useTranslate, } from '@cloudbeaver/core-blocks'; -import type { DataTransferOutputSettings, DataTransferProcessorInfo, GQLErrorCatcher } from '@cloudbeaver/core-sdk'; -import { ITabData, Tab, TabList, TabsState, TabTitle, UNDERLINE_TAB_STYLES } from '@cloudbeaver/core-ui'; +import type { DataTransferOutputSettings, DataTransferProcessorInfo } from '@cloudbeaver/core-sdk'; +import { ITabData, Tab, TabList, TabsState, TabTitle, TabUnderlineStyleRegistry } from '@cloudbeaver/core-ui'; import { OutputOptionsForm } from './OutputOptionsForm'; import style from './ProcessorConfigureDialog.m.css'; @@ -81,20 +80,22 @@ export const ProcessorConfigureDialog = observer(function ProcessorConfig } } - return styled(useStyles(UNDERLINE_TAB_STYLES))( + return ( {!processor.isBinary ? ( - - - {translate('data_transfer_format_settings')} - - - {translate('data_transfer_output_settings')} - - + + + + {translate('data_transfer_format_settings')} + + + {translate('data_transfer_output_settings')} + + + ) : null} {currentTabId === SETTINGS_TABS.EXTRACTION ? ( @@ -122,6 +123,6 @@ export const ProcessorConfigureDialog = observer(function ProcessorConfig onNext={handleNextClick} /> - , + ); }); diff --git a/webapp/packages/plugin-data-viewer/src/DataViewerPage/DataViewerTab.tsx b/webapp/packages/plugin-data-viewer/src/DataViewerPage/DataViewerTab.tsx index 6dd9f3c6e6..108a757b73 100644 --- a/webapp/packages/plugin-data-viewer/src/DataViewerPage/DataViewerTab.tsx +++ b/webapp/packages/plugin-data-viewer/src/DataViewerPage/DataViewerTab.tsx @@ -6,9 +6,8 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { Translate, useStyles } from '@cloudbeaver/core-blocks'; +import { Translate } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { NavNodeManagerService } from '@cloudbeaver/core-navigation-tree'; import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; @@ -16,20 +15,19 @@ import type { ObjectPageTabComponent } from '@cloudbeaver/plugin-object-viewer'; import type { IDataViewerPageState } from '../IDataViewerPageState'; -export const DataViewerTab: ObjectPageTabComponent = observer(function DataViewerTab({ tab, page, onSelect, style }) { - const styles = useStyles(style); +export const DataViewerTab: ObjectPageTabComponent = observer(function DataViewerTab({ tab, page, onSelect }) { const navNodeManagerService = useService(NavNodeManagerService); if (!navNodeManagerService.isNodeHasData(tab.handlerState.objectId)) { return null; } - return styled(styles)( - + return ( + - , + ); }); diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/PresentationTab.tsx b/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/PresentationTab.tsx index d0c384743f..63413ab8ca 100644 --- a/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/PresentationTab.tsx +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/PresentationTab.tsx @@ -6,11 +6,9 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { useStyles, useTranslate } from '@cloudbeaver/core-blocks'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; -import { BASE_TAB_STYLES, Tab, TabIcon, TabTitle, VERTICAL_ROTATED_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { useTranslate } from '@cloudbeaver/core-blocks'; +import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; import type { IDatabaseDataModel } from '../../DatabaseDataModel/IDatabaseDataModel'; import type { IDataPresentationOptions } from '../../DataPresentationService'; @@ -20,34 +18,24 @@ interface Props { resultIndex: number; presentation: IDataPresentationOptions; className?: string; - style?: ComponentStyle; onClick: (tabId: string) => void; } -export const PresentationTab = observer(function PresentationTab({ model, presentation, className, style, onClick }) { +export const PresentationTab = observer(function PresentationTab({ model, presentation, className, onClick }) { const translate = useTranslate(); - const styles = useStyles(BASE_TAB_STYLES, VERTICAL_ROTATED_TAB_STYLES, style); if (presentation.getTabComponent) { const Tab = presentation.getTabComponent(); return ( - + ); } - return styled(styles)( - + return ( + {presentation.icon && } {presentation.title && {translate(presentation.title)}} - , + ); }); diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/TablePresentationBar.tsx b/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/TablePresentationBar.tsx index 79c47bef9d..ea00545d01 100644 --- a/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/TablePresentationBar.tsx +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/TablePresentationBar.tsx @@ -6,37 +6,18 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { css, use } from 'reshadow'; -import { useStyles } from '@cloudbeaver/core-blocks'; +import { s, SContext, StyleRegistry, useS } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import type { ResultDataFormat } from '@cloudbeaver/core-sdk'; -import { BASE_TAB_STYLES, TabList, TabsState, VERTICAL_ROTATED_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { TabList, TabListStyles, TabListVerticalRotatedRegistry, TabsState, TabStyles } from '@cloudbeaver/core-ui'; import type { IDatabaseDataModel } from '../../DatabaseDataModel/IDatabaseDataModel'; import { DataPresentationService, DataPresentationType } from '../../DataPresentationService'; import { PresentationTab } from './PresentationTab'; - -const styles = css` - table-left-bar { - display: flex; - } - Tab { - composes: theme-ripple theme-background-background theme-text-text-primary-on-light theme-typography--body2 from global; - text-transform: uppercase; - font-weight: normal; - - &:global([aria-selected='true']) { - font-weight: normal !important; - } - } - TabList { - composes: theme-background-secondary theme-text-on-secondary from global; - } - TabList[|flexible] tab-outer:only-child { - display: none; - } -`; +import styles from './shared/TablePresentationBar.m.css'; +import TablePresentationBarTab from './shared/TablePresentationBarTab.m.css'; +import TablePresentationBarTabList from './shared/TablePresentationBarTabList.m.css'; interface Props { type: DataPresentationType; @@ -50,6 +31,12 @@ interface Props { onClose?: () => void; } +const tablePresentationBarRegistry: StyleRegistry = [ + ...TabListVerticalRotatedRegistry, + [TabListStyles, { mode: 'append', styles: [TablePresentationBarTabList] }], + [TabStyles, { mode: 'append', styles: [TablePresentationBarTab] }], +]; + export const TablePresentationBar = observer(function TablePresentationBar({ type, presentationId, @@ -61,7 +48,7 @@ export const TablePresentationBar = observer(function TablePresentationBa onPresentationChange, onClose, }) { - const style = useStyles(styles, BASE_TAB_STYLES, VERTICAL_ROTATED_TAB_STYLES); + const style = useS(styles); const dataPresentationService = useService(DataPresentationService); const presentations = dataPresentationService.getSupportedList(type, supportedDataFormat, dataFormat, model, resultIndex); const Tab = PresentationTab; // alias for styles matching @@ -79,15 +66,17 @@ export const TablePresentationBar = observer(function TablePresentationBa return null; } - return styled(style)( - + return ( +
- - {presentations.map(presentation => ( - - ))} - + + + {presentations.map(presentation => ( + + ))} + + - , +
); }); diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/shared/TablePresentationBar.m.css b/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/shared/TablePresentationBar.m.css new file mode 100644 index 0000000000..740eb13d7a --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/shared/TablePresentationBar.m.css @@ -0,0 +1,15 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tableLeftBar { + display: flex; +} + +.tabListFlexible .tabOuter:only-child { + display: none; +} diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/shared/TablePresentationBarTab.m.css b/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/shared/TablePresentationBarTab.m.css new file mode 100644 index 0000000000..b9475c5b41 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/shared/TablePresentationBarTab.m.css @@ -0,0 +1,17 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + composes: theme-ripple theme-background-background theme-text-text-primary-on-light theme-typography--body2 from global; + text-transform: uppercase; + font-weight: normal; + + &:global([aria-selected='true']) { + font-weight: normal !important; + } +} diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/shared/TablePresentationBarTabList.m.css b/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/shared/TablePresentationBarTabList.m.css new file mode 100644 index 0000000000..daff16ec73 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TablePresentationBar/shared/TablePresentationBarTabList.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabList { + composes: theme-background-secondary theme-text-on-secondary from global; +} diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TableToolsPanel.m.css b/webapp/packages/plugin-data-viewer/src/TableViewer/TableToolsPanel.m.css new file mode 100644 index 0000000000..79cb87d56d --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TableToolsPanel.m.css @@ -0,0 +1,12 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.presentation { + flex: 1; + overflow: auto; +} diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TableToolsPanel.tsx b/webapp/packages/plugin-data-viewer/src/TableViewer/TableToolsPanel.tsx index 08895e9c56..e0b18e14b5 100644 --- a/webapp/packages/plugin-data-viewer/src/TableViewer/TableToolsPanel.tsx +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TableToolsPanel.tsx @@ -6,14 +6,14 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { css } from 'reshadow'; -import { TextPlaceholder, useTranslate } from '@cloudbeaver/core-blocks'; +import { s, TextPlaceholder, useS, useTranslate } from '@cloudbeaver/core-blocks'; import type { ResultDataFormat } from '@cloudbeaver/core-sdk'; import type { IDatabaseDataModel } from '../DatabaseDataModel/IDatabaseDataModel'; import type { IDataPresentationOptions } from '../DataPresentationService'; import type { IDataTableActions } from './IDataTableActions'; +import styles from './TableToolsPanel.m.css'; interface Props { model: IDatabaseDataModel; @@ -24,15 +24,9 @@ interface Props { simple: boolean; } -const styles = css` - Presentation { - flex: 1; - overflow: auto; - } -`; - export const TableToolsPanel = observer(function TableToolsPanel({ model, actions, dataFormat, presentation, resultIndex, simple }) { const translate = useTranslate(); + const style = useS(styles); const result = model.getResult(resultIndex); @@ -51,5 +45,14 @@ export const TableToolsPanel = observer(function TableToolsPanel({ model, return {translate('data_viewer_nodata_message')}; } - return styled(styles)(); + return ( + + ); }); diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/ValuePanel.tsx b/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/ValuePanel.tsx index a23f407167..5815512a8f 100644 --- a/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/ValuePanel.tsx +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/ValuePanel.tsx @@ -7,10 +7,10 @@ */ import { observable } from 'mobx'; import { observer } from 'mobx-react-lite'; -import styled, { css } from 'reshadow'; +import { s, SContext, type StyleRegistry, useS } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; -import { BASE_TAB_STYLES, TabList, TabPanelList, TabsState, UNDERLINE_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { TabList, TabPanelList, TabPanelStyles, TabsState, TabStyles, TabUnderlineStyleRegistry } from '@cloudbeaver/core-ui'; import { MetadataMap } from '@cloudbeaver/core-utils'; import { DatabaseDataResultAction } from '../../DatabaseDataModel/Actions/DatabaseDataResultAction'; @@ -19,35 +19,18 @@ import { DatabaseSelectAction } from '../../DatabaseDataModel/Actions/DatabaseSe import type { IDatabaseResultSet } from '../../DatabaseDataModel/IDatabaseResultSet'; import type { DataPresentationComponent } from '../../DataPresentationService'; import { DataValuePanelService } from './DataValuePanelService'; +import styles from './shared/ValuePanel.m.css'; +import ValuePanelEditorTabPanel from './shared/ValuePanelEditorTabPanel.m.css'; +import ValuePanelEditorTabs from './shared/ValuePanelEditorTabs.m.css'; +import ValuePanelTab from './shared/ValuePanelTab.m.css'; -const styles = css` - table-left-bar { - display: flex; - } - TabList { - composes: theme-border-color-background from global; - position: relative; +const tabListRegistry: StyleRegistry = [...TabUnderlineStyleRegistry, [TabStyles, { mode: 'append', styles: [ValuePanelTab] }]]; - &:before { - content: ''; - position: absolute; - bottom: 0; - width: 100%; - border-bottom: solid 2px; - border-color: inherit; - } - } - TabList tab-outer:only-child { - display: none; - } - TabPanel { - padding-top: 8px; - } - TabList, - TabPanel { - composes: theme-background-secondary theme-text-on-secondary from global; - } -`; +const tabPanelListRegistry: StyleRegistry = [ + ...TabUnderlineStyleRegistry, + [TabStyles, { mode: 'append', styles: [ValuePanelEditorTabs] }], + [TabPanelStyles, { mode: 'append', styles: [ValuePanelEditorTabPanel] }], +]; export const ValuePanel: DataPresentationComponent = observer(function ValuePanel({ dataFormat, model, resultIndex }) { const service = useService(DataValuePanelService); @@ -56,6 +39,7 @@ export const ValuePanel: DataPresentationComponent = ob const metadataAction = model.source.getAction(resultIndex, DatabaseMetadataAction); const activeElements = selectAction?.getActiveElements(); let elementKey: string | null = null; + const style = useS(styles); if (dataResultAction && activeElements && activeElements.length > 0) { elementKey = dataResultAction.getIdentifier(activeElements[0]); @@ -84,11 +68,7 @@ export const ValuePanel: DataPresentationComponent = ob currentTabId = displayed[0].key; } - return styled( - BASE_TAB_STYLES, - styles, - UNDERLINE_TAB_STYLES, - )( + return ( = ob lazy onChange={tab => state.setCurrentTabId(tab.tabId)} > - - - , + + + + + + + ); }); diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanel.m.css b/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanel.m.css new file mode 100644 index 0000000000..47c092049a --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanel.m.css @@ -0,0 +1,20 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabList { + composes: theme-background-secondary theme-border-color-background theme-text-on-secondary from global; + position: relative; + &:before { + content: ''; + position: absolute; + bottom: 0; + width: 100%; + border-bottom: solid 2px; + border-color: inherit; + } +} diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanelEditorTabPanel.m.css b/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanelEditorTabPanel.m.css new file mode 100644 index 0000000000..fc75ed9253 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanelEditorTabPanel.m.css @@ -0,0 +1,12 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabPanel { + composes: theme-background-secondary theme-text-on-secondary from global; + padding-top: 8px; +} diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanelEditorTabs.m.css b/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanelEditorTabs.m.css new file mode 100644 index 0000000000..0afe075a93 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanelEditorTabs.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + border: none; +} diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanelTab.m.css b/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanelTab.m.css new file mode 100644 index 0000000000..97ac1eb658 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/ValuePanel/shared/ValuePanelTab.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabOuter:only-child { + display: none; +} diff --git a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/TextValuePresentation.tsx b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/TextValuePresentation.tsx index 090cc9ff9d..ecb9672d99 100644 --- a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/TextValuePresentation.tsx +++ b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/TextValuePresentation.tsx @@ -8,12 +8,11 @@ import { observable } from 'mobx'; import { observer } from 'mobx-react-lite'; import { useMemo } from 'react'; -import styled, { css } from 'reshadow'; -import { ActionIconButton, Button, Container, Fill, Group, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; +import { ActionIconButton, Button, Container, Fill, Group, s, SContext, StyleRegistry, useS, useTranslate } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { NotificationService } from '@cloudbeaver/core-events'; -import { BASE_TAB_STYLES, TabContainerPanelComponent, TabList, TabsState, UNDERLINE_TAB_STYLES, useTabLocalState } from '@cloudbeaver/core-ui'; +import { TabContainerPanelComponent, TabList, TabsState, TabStyles, TabUnderlineStyleRegistry, useTabLocalState } from '@cloudbeaver/core-ui'; import { bytesToSize, isNotNullDefined } from '@cloudbeaver/core-utils'; import { EditorLoader, useCodemirrorExtensions } from '@cloudbeaver/plugin-codemirror6'; @@ -24,40 +23,24 @@ import type { IDatabaseResultSet } from '../../DatabaseDataModel/IDatabaseResult import { DataViewerService } from '../../DataViewerService'; import type { IDataValuePanelProps } from '../../TableViewer/ValuePanel/DataValuePanelService'; import { QuotaPlaceholder } from '../QuotaPlaceholder'; -import { VALUE_PANEL_TOOLS_STYLES } from '../ValuePanelTools/VALUE_PANEL_TOOLS_STYLES'; import { getDefaultLineWrapping } from './getDefaultLineWrapping'; import { getTypeExtension } from './getTypeExtension'; +import styles from './shared/TextValuePresentation.m.css'; +import TextValuePresentationTab from './shared/TextValuePresentationTab.m.css'; import { TextValuePresentationService } from './TextValuePresentationService'; import { useTextValue } from './useTextValue'; -const styles = css` - Tab { - composes: theme-ripple theme-background-surface theme-text-text-primary-on-light from global; - } - TabList { - composes: theme-border-color-background theme-background-background from global; - overflow: auto; - border-radius: var(--theme-group-element-radius); - - & Tab { - border-bottom: 0; - - &:global([aria-selected='false']) { - border-bottom: 0 !important; - } - } - } -`; - const DEFAULT_CONTENT_TYPE = 'text/plain'; +const tabRegistry: StyleRegistry = [...TabUnderlineStyleRegistry, [TabStyles, { mode: 'append', styles: [TextValuePresentationTab] }]]; + export const TextValuePresentation: TabContainerPanelComponent> = observer( function TextValuePresentation({ model, resultIndex, dataFormat }) { const translate = useTranslate(); const dataViewerService = useService(DataViewerService); const notificationService = useService(NotificationService); const textValuePresentationService = useService(TextValuePresentationService); - const style = useStyles(styles, UNDERLINE_TAB_STYLES, VALUE_PANEL_TOOLS_STYLES); + const style = useS(styles); const selection = model.source.getAction(resultIndex, ResultSetSelectAction); const activeElements = selection.getActiveElements(); const firstSelectedCell = activeElements.length ? activeElements[0] : undefined; @@ -159,7 +142,7 @@ export const TextValuePresentation: TabContainerPanelComponent @@ -172,7 +155,9 @@ export const TextValuePresentation: TabContainerPanelComponent selectTabHandler(tab.tabId)} > - + + + @@ -212,7 +197,7 @@ export const TextValuePresentation: TabContainerPanelComponent
-
, + ); }, ); diff --git a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/shared/TextValuePresentation.m.css b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/shared/TextValuePresentation.m.css new file mode 100644 index 0000000000..a26001f695 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/shared/TextValuePresentation.m.css @@ -0,0 +1,13 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabList { + composes: theme-border-color-background theme-background-background from global; + overflow: auto; + border-radius: var(--theme-group-element-radius); +} diff --git a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/shared/TextValuePresentationTab.m.css b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/shared/TextValuePresentationTab.m.css new file mode 100644 index 0000000000..378d4d71b5 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/shared/TextValuePresentationTab.m.css @@ -0,0 +1,15 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +.tab { + composes: theme-ripple theme-background-surface theme-text-text-primary-on-light from global; + border-bottom: 0; + + &:global([aria-selected='false']) { + border-bottom: 0 !important; + } +} diff --git a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/ValuePanelTools/VALUE_PANEL_TOOLS_STYLES.ts b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/ValuePanelTools/VALUE_PANEL_TOOLS_STYLES.ts deleted file mode 100644 index df90fd8bcd..0000000000 --- a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/ValuePanelTools/VALUE_PANEL_TOOLS_STYLES.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import { css } from 'reshadow'; - -export const VALUE_PANEL_TOOLS_STYLES = css` - tools-container { - display: flex; - justify-content: space-between; - gap: 8px; - } - tools { - composes: theme-background-surface theme-text-on-surface theme-border-color-background theme-form-element-radius from global; - display: flex; - box-sizing: border-box; - border: 2px solid; - } - tools-action { - composes: theme-ripple from global; - box-sizing: border-box; - background: inherit; - cursor: pointer; - padding: 4px; - width: 24px; - height: auto; - } - IconOrImage { - width: 100%; - height: 100%; - } -`; diff --git a/webapp/packages/plugin-ddl-viewer/src/DdlViewer/DDLViewerTab.tsx b/webapp/packages/plugin-ddl-viewer/src/DdlViewer/DDLViewerTab.tsx index e6e78c7eb8..33ff76ce33 100644 --- a/webapp/packages/plugin-ddl-viewer/src/DdlViewer/DDLViewerTab.tsx +++ b/webapp/packages/plugin-ddl-viewer/src/DdlViewer/DDLViewerTab.tsx @@ -6,21 +6,19 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { useStyles } from '@cloudbeaver/core-blocks'; -import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { TabIcon, Tab, TabTitle } from '@cloudbeaver/core-ui'; import type { NavNodeTransformViewComponent } from '@cloudbeaver/plugin-navigation-tree'; import { NAV_NODE_DDL_ID } from '../NAV_NODE_DDL_ID'; -export const DDLViewerTab: NavNodeTransformViewComponent = observer(function DDLViewerTab({ folderId, style }) { +export const DDLViewerTab: NavNodeTransformViewComponent = observer(function DDLViewerTab({ folderId }) { const title = folderId.startsWith(NAV_NODE_DDL_ID) ? 'DDL' : 'Body'; - return styled(useStyles(style))( + return ( {title} - , + ); }); diff --git a/webapp/packages/plugin-navigation-tabs/package.json b/webapp/packages/plugin-navigation-tabs/package.json index 0d5609e3bf..4cbb293ac1 100644 --- a/webapp/packages/plugin-navigation-tabs/package.json +++ b/webapp/packages/plugin-navigation-tabs/package.json @@ -40,6 +40,7 @@ "peerDependencies": {}, "devDependencies": { "@types/react": "^18.2.63", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "typescript-plugin-css-modules": "^5.1.0" } } diff --git a/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/NavigationTabsBar.tsx b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/NavigationTabsBar.tsx index dd4d045432..d54d761e87 100644 --- a/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/NavigationTabsBar.tsx +++ b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/NavigationTabsBar.tsx @@ -7,48 +7,41 @@ */ import { observer } from 'mobx-react-lite'; import { useCallback, useEffect, useState } from 'react'; -import styled, { css } from 'reshadow'; import { UserInfoResource } from '@cloudbeaver/core-authentication'; -import { Loader, TextPlaceholder, useExecutor, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; +import { Loader, s, SContext, StyleRegistry, TextPlaceholder, useExecutor, useS, useTranslate } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; -import { BASE_TAB_STYLES, ITabData, TabPanel, TabsBox } from '@cloudbeaver/core-ui'; +import { ITabData, TabPanel, TabsBox, TabStyles } from '@cloudbeaver/core-ui'; import { CaptureView } from '@cloudbeaver/core-view'; import { NavigationTabsService } from '../NavigationTabsService'; +import styles from './shared/NavigationTabsBar.m.css'; +import NavigationTabsBarTab from './shared/NavigationTabsBarTab.m.css'; import { TabHandlerPanel } from './Tabs/TabHandlerPanel'; import { TabHandlerTab } from './Tabs/TabHandlerTab'; -const styles = css` - Tab { - composes: theme-ripple theme-background-background theme-text-text-primary-on-light from global; - height: 38px !important; - } - tabs { - composes: theme-background-secondary theme-text-on-secondary from global; - } - TabsBox { - outline: none; - } - CaptureView { - flex: 1; - display: flex; - overflow: auto; - } -`; - interface Props { className?: string; } +const tabsRegistry: StyleRegistry = [ + [ + TabStyles, + { + mode: 'append', + styles: [NavigationTabsBarTab], + }, + ], +]; + export const NavigationTabsBar = observer(function NavigationTabsBar({ className }) { const userInfoResource = useService(UserInfoResource); const navigation = useService(NavigationTabsService); // TODO: we get exception when after closing the restored page trying to open another // it's related to hooks order and state restoration - const style = useStyles(BASE_TAB_STYLES, styles); const [restoring, setRestoring] = useState(false); const translate = useTranslate(); + const style = useS(styles); const handleSelect = useCallback((tabId: string) => navigation.selectTab(tabId), [navigation]); const handleClose = useCallback((tabId: string) => navigation.closeTab(tabId), [navigation]); @@ -89,16 +82,21 @@ export const NavigationTabsBar = observer(function NavigationTabsBar({ cl return {translate('app_shared_navigationTabsBar_placeholder')}; } - return styled(style)( - + return ( + ( - - ))} + className={s(style, { tabsBox: true })} + tabsClassName={s(style, { tabs: true })} + tabs={ + + {navigation.tabIdList.map(tabId => ( + + ))} + + } tabList={navigation.tabIdList} - style={styles} tabIndex={0} autoSelect enabledBaseActions @@ -111,6 +109,6 @@ export const NavigationTabsBar = observer(function NavigationTabsBar({ cl ))} - , + ); }); diff --git a/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/Tabs/TabHandlerPanel.tsx b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/Tabs/TabHandlerPanel.tsx index 0957a5f2be..34f54c333b 100644 --- a/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/Tabs/TabHandlerPanel.tsx +++ b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/Tabs/TabHandlerPanel.tsx @@ -7,12 +7,10 @@ */ import { observer } from 'mobx-react-lite'; -import type { TabElementProps } from '@cloudbeaver/core-ui'; - import { useTab } from './useTab'; import { useTabHandler } from './useTabHandler'; -export const TabHandlerPanel = observer(function TabHandlerPanel({ tabId }) { +export const TabHandlerPanel = observer<{ tabId: string }>(function TabHandlerPanel({ tabId }) { const tab = useTab(tabId); const handler = useTabHandler(tab.handlerId); diff --git a/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/Tabs/TabHandlerTab.tsx b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/Tabs/TabHandlerTab.tsx index 9053615d52..c032ba7459 100644 --- a/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/Tabs/TabHandlerTab.tsx +++ b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/Tabs/TabHandlerTab.tsx @@ -7,8 +7,6 @@ */ import { observer } from 'mobx-react-lite'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; - import { useTab } from './useTab'; import { useTabHandler } from './useTabHandler'; @@ -16,13 +14,12 @@ interface IProps { tabId: string; onSelect: (tabId: string) => void; onClose?: (tabId: string) => void; - style: ComponentStyle; } -export const TabHandlerTab = observer(function TabHandlerTab({ tabId, onSelect, onClose, style }) { +export const TabHandlerTab = observer(function TabHandlerTab({ tabId, onSelect, onClose }) { const tab = useTab(tabId); const handler = useTabHandler(tab.handlerId); const TabHandlerTab = handler.getTabComponent(); - return ; + return ; }); diff --git a/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/shared/NavigationTabsBar.m.css b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/shared/NavigationTabsBar.m.css new file mode 100644 index 0000000000..cc10d12a5c --- /dev/null +++ b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/shared/NavigationTabsBar.m.css @@ -0,0 +1,21 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabs { + composes: theme-background-secondary theme-text-on-secondary from global; +} + +.tabsBox { + outline: none; +} + +.captureView { + flex: 1; + display: flex; + overflow: auto; +} diff --git a/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/shared/NavigationTabsBarTab.m.css b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/shared/NavigationTabsBarTab.m.css new file mode 100644 index 0000000000..f8cfd2cb36 --- /dev/null +++ b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/NavigationTabsBar/shared/NavigationTabsBarTab.m.css @@ -0,0 +1,12 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + composes: theme-ripple theme-background-background theme-text-text-primary-on-light from global; + height: 38px !important; +} diff --git a/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/TabHandler.ts b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/TabHandler.ts index e87b19de26..f1c3491797 100644 --- a/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/TabHandler.ts +++ b/webapp/packages/plugin-navigation-tabs/src/NavigationTabs/TabHandler.ts @@ -6,7 +6,6 @@ * you may not use this file except in compliance with the License. */ import type { IExtension } from '@cloudbeaver/core-extensions'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import type { ITab } from './ITab'; @@ -15,7 +14,6 @@ export interface TabHandlerTabProps { handler: TabHandler; onSelect: (tabId: string) => void; onClose?: (tabId: string) => void; - style: ComponentStyle; } export type TabHandlerTabComponent = React.FunctionComponent>; diff --git a/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeView/IFolderTransform.ts b/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeView/IFolderTransform.ts index 8077c81810..1d708a8f05 100644 --- a/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeView/IFolderTransform.ts +++ b/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeView/IFolderTransform.ts @@ -5,13 +5,11 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import type { ComponentStyle } from '@cloudbeaver/core-theming'; export type NavNodeTransformViewComponent = React.FC<{ nodeId: string; folderId: string; parents: string[]; - style?: ComponentStyle; }>; export type NavNodeTransformView = (nodeId: string, folderId: string, parents: string[]) => NavNodeTransformViewComponent | undefined; diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPage/DBObjectPageTab.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPage/DBObjectPageTab.tsx index ff92e65128..688891573a 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPage/DBObjectPageTab.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPage/DBObjectPageTab.tsx @@ -8,7 +8,6 @@ import { observer } from 'mobx-react-lite'; import { useCallback } from 'react'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import type { ITab } from '@cloudbeaver/plugin-navigation-tabs'; import type { IObjectViewerTabState } from '../IObjectViewerTabState'; @@ -18,11 +17,10 @@ interface IProps { tab: ITab; page: ObjectPage; onSelect: (tab: ITab, page: ObjectPage) => void; - style: ComponentStyle; } -export const DBObjectPageTab = observer(function DBObjectPageTab({ tab, page, onSelect, style }) { +export const DBObjectPageTab = observer(function DBObjectPageTab({ tab, page, onSelect }) { const handleSelect = useCallback(() => onSelect(tab, page), [tab, page, onSelect]); const TabComponent = page.getTabComponent(); - return ; + return ; }); diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPage/ObjectPage.ts b/webapp/packages/plugin-object-viewer/src/ObjectPage/ObjectPage.ts index 21f8c1360f..b45a825114 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPage/ObjectPage.ts +++ b/webapp/packages/plugin-object-viewer/src/ObjectPage/ObjectPage.ts @@ -7,7 +7,6 @@ */ import { makeObservable, observable } from 'mobx'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import type { ITab } from '@cloudbeaver/plugin-navigation-tabs'; import type { IObjectViewerTabState } from '../IObjectViewerTabState'; @@ -16,7 +15,6 @@ export interface ObjectPageTabProps { tab: ITab; page: ObjectPage; onSelect: () => void; - style: ComponentStyle; } export type ObjectPageTabComponent = React.FunctionComponent>; diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/FolderPanelRenderer.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/FolderPanelRenderer.tsx index 9e2b927c9c..011a93f3cc 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/FolderPanelRenderer.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/FolderPanelRenderer.tsx @@ -8,7 +8,6 @@ import { observer } from 'mobx-react-lite'; import { useService } from '@cloudbeaver/core-di'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import { NavNodeViewService, useNode } from '@cloudbeaver/plugin-navigation-tree'; import { ObjectPropertyTable } from './ObjectPropertyTable/ObjectPropertyTable'; @@ -17,27 +16,25 @@ interface IFolderPanelRendererProps { nodeId: string; folderId: string; parents: string[]; - style?: ComponentStyle; } -export const FolderPanelRenderer = observer(function FolderPanelRenderer({ nodeId, folderId, parents, style }) { +export const FolderPanelRenderer = observer(function FolderPanelRenderer({ nodeId, folderId, parents }) { const navNodeViewService = useService(NavNodeViewService); for (const panel of navNodeViewService.panels) { const Panel = panel(nodeId, folderId, parents); if (Panel) { - return ; + return ; } } - return ; + return ; }); interface INavNodePanelProps { nodeId: string; parents: string[]; - style?: ComponentStyle; } const NavNodePanel = observer(function NavNodeTab({ nodeId }) { diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/FolderTabRenderer.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/FolderTabRenderer.tsx index cdf26f155b..0c325a3324 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/FolderTabRenderer.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/FolderTabRenderer.tsx @@ -6,65 +6,28 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { getComputed, Loader, useStateDelay, useStyles } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; -import { DBObjectResource } from '@cloudbeaver/core-navigation-tree'; -import { resourceKeyList } from '@cloudbeaver/core-resource'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; -import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; -import { NavNodeViewService, useChildren, useNode } from '@cloudbeaver/plugin-navigation-tree'; +import { NavNodeViewService } from '@cloudbeaver/plugin-navigation-tree'; + +import { NavNodeTab } from './NavNodeTab'; interface IFolderTabRendererProps { nodeId: string; folderId: string; parents: string[]; - style?: ComponentStyle; } -export const FolderTabRenderer = observer(function FolderTabRenderer({ nodeId, folderId, parents, style }) { +export const FolderTabRenderer = observer(function FolderTabRenderer({ nodeId, folderId, parents }) { const navNodeViewService = useService(NavNodeViewService); for (const tab of navNodeViewService.tabs) { const Tab = tab(nodeId, folderId, parents); if (Tab) { - return ; + return ; } } - return ; -}); - -interface INavNodeTabProps { - nodeId: string; - style?: ComponentStyle; -} - -const NavNodeTab = observer(function NavNodeTab({ nodeId, style }) { - const nodeInfo = useNode(nodeId); - const children = useChildren(nodeId); - const dbObjectResource = useService(DBObjectResource); - const childrenList = resourceKeyList(children.children || []); - - const loading = useStateDelay( - getComputed( - () => - (nodeInfo.isLoaded() && nodeInfo.isLoading()) || - (children.isLoaded() && children.isLoading()) || - (dbObjectResource.isLoaded(childrenList) && dbObjectResource.isLoading(childrenList)), - ), - 300, - ); - - return styled(useStyles(style))( - - {nodeInfo.node?.icon && } - {nodeInfo.node?.name} - - - - , - ); + return ; }); diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeTab.m.css b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeTab.m.css new file mode 100644 index 0000000000..33e3ee9fb9 --- /dev/null +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeTab.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabLoader { + display: block; +} diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeTab.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeTab.tsx new file mode 100644 index 0000000000..34a9d0c10f --- /dev/null +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeTab.tsx @@ -0,0 +1,49 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { observer } from 'mobx-react-lite'; + +import { getComputed, Loader, s, useS, useStateDelay } from '@cloudbeaver/core-blocks'; +import { useService } from '@cloudbeaver/core-di'; +import { DBObjectResource } from '@cloudbeaver/core-navigation-tree'; +import { resourceKeyList } from '@cloudbeaver/core-resource'; +import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { useChildren, useNode } from '@cloudbeaver/plugin-navigation-tree'; + +import style from './NavNodeTab.m.css'; + +interface INavNodeTabProps { + nodeId: string; +} + +export const NavNodeTab = observer(function NavNodeTab({ nodeId }) { + const nodeInfo = useNode(nodeId); + const children = useChildren(nodeId); + const dbObjectResource = useService(DBObjectResource); + const childrenList = resourceKeyList(children.children || []); + const styles = useS(style); + + const loading = useStateDelay( + getComputed( + () => + (nodeInfo.isLoaded() && nodeInfo.isLoading()) || + (children.isLoaded() && children.isLoading()) || + (dbObjectResource.isLoaded(childrenList) && dbObjectResource.isLoading(childrenList)), + ), + 300, + ); + + return ( + + {nodeInfo.node?.icon && } + {nodeInfo.node?.name} +
+ +
+
+ ); +}); diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/NavNodeMetadata/NavNodeMetadataTab.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/NavNodeMetadata/NavNodeMetadataTab.tsx index 7ad3406dfc..3aa05beec6 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/NavNodeMetadata/NavNodeMetadataTab.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/NavNodeMetadata/NavNodeMetadataTab.tsx @@ -6,15 +6,13 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { useStyles, useTranslate } from '@cloudbeaver/core-blocks'; -import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { useTranslate } from '@cloudbeaver/core-blocks'; +import { TabIcon, Tab, TabTitle } from '@cloudbeaver/core-ui'; import { type NavNodeTransformViewComponent, useNode } from '@cloudbeaver/plugin-navigation-tree'; -export const NavNodeMetadataTab: NavNodeTransformViewComponent = observer(function NavNodeMetadataTab({ folderId, nodeId, style }) { +export const NavNodeMetadataTab: NavNodeTransformViewComponent = observer(function NavNodeMetadataTab({ folderId, nodeId }) { const translate = useTranslate(); - const styles = useStyles(style); const nodeInfo = useNode(nodeId); const title = translate('plugin_object_viewer_object_info_tab'); @@ -24,10 +22,10 @@ export const NavNodeMetadataTab: NavNodeTransformViewComponent = observer(functi const icon = 'platform:/plugin/org.jkiss.dbeaver.model/icons/tree/info.png'; - return styled(styles)( + return ( {title} - , +
); }); diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderTab.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderTab.tsx index a2cc68d2cc..b35d156c89 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderTab.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderTab.tsx @@ -5,23 +5,19 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import styled from 'reshadow'; - -import { useStyles } from '@cloudbeaver/core-blocks'; -import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { TabIcon, Tab, TabTitle } from '@cloudbeaver/core-ui'; import type { NavNodeTransformViewComponent } from '@cloudbeaver/plugin-navigation-tree'; import { VirtualFolderUtils } from './VirtualFolderUtils'; -export const VirtualFolderTab: NavNodeTransformViewComponent = function VirtualFolderTab({ folderId, style }) { +export const VirtualFolderTab: NavNodeTransformViewComponent = function VirtualFolderTab({ folderId }) { const nodeType = VirtualFolderUtils.getNodeType(folderId); - const styles = useStyles(style); const icon = 'platform:/plugin/org.jkiss.dbeaver.model/icons/tree/folder.png'; - return styled(styles)( + return ( {nodeType} - , +
); }; diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectFolders.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectFolders.tsx index 32b1811cf9..c267c5fc24 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectFolders.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectFolders.tsx @@ -7,12 +7,22 @@ */ import { observer } from 'mobx-react-lite'; import { useEffect } from 'react'; -import styled, { css } from 'reshadow'; -import { TextPlaceholder, useResource, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; +import { SContext, StyleRegistry, TextPlaceholder, useResource, useTranslate } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { NavNodeManagerService, NavTreeResource } from '@cloudbeaver/core-navigation-tree'; -import { BASE_TAB_STYLES, ITabData, TabList, TabPanel, TabsState, useTabLocalState, verticalTabStyles } from '@cloudbeaver/core-ui'; +import { + ITabData, + TabList, + TabListStyles, + TabListVerticalRegistry, + TabPanel, + TabPanelStyles, + TabsState, + TabStyles, + TabTitleStyles, + useTabLocalState, +} from '@cloudbeaver/core-ui'; import { MetadataMap } from '@cloudbeaver/core-utils'; import type { ITab } from '@cloudbeaver/plugin-navigation-tabs'; import { NavNodeViewService } from '@cloudbeaver/plugin-navigation-tree'; @@ -20,45 +30,58 @@ import { NavNodeViewService } from '@cloudbeaver/plugin-navigation-tree'; import type { IObjectViewerTabState } from '../IObjectViewerTabState'; import { FolderPanelRenderer } from './FolderPanelRenderer'; import { FolderTabRenderer } from './FolderTabRenderer'; - -const styles = css` - Tab { - composes: theme-ripple theme-background-background theme-ripple-selectable from global; - color: inherit; - } - vertical-tabs { - composes: theme-border-color-background from global; - border-top: 1px solid; - flex: 1; - } - TabPanel { - overflow: auto !important; - } - TabList { - composes: theme-background-surface theme-text-on-surface theme-border-color-background from global; - border-right: 1px solid; - } - TabTitle { - flex: 1; - } - tab-loader { - width: 16px; - height: 16px; - flex-shrink: 0; - margin-right: 16px; - overflow: hidden; - } -`; - -const tabStyles = [BASE_TAB_STYLES, verticalTabStyles, styles]; +import NavNodeTabStyle from './NavNodeTab.m.css'; +import ObjectFoldersNavNodeTab from './shared/ObjectFoldersNavNodeTab.m.css'; +import ObjectFoldersTab from './shared/ObjectFoldersTab.m.css'; +import ObjectFoldersTabList from './shared/ObjectFoldersTabList.m.css'; +import ObjectFoldersTabPanel from './shared/ObjectFoldersTabPanel.m.css'; +import ObjectFoldersTabTitle from './shared/ObjectFoldersTabTitle.m.css'; interface IProps { tab: ITab; } +const objectFoldersRegistry: StyleRegistry = [ + ...TabListVerticalRegistry, + [ + NavNodeTabStyle, + { + mode: 'append', + styles: [ObjectFoldersNavNodeTab], + }, + ], + [ + TabStyles, + { + mode: 'append', + styles: [ObjectFoldersTab], + }, + ], + [ + TabListStyles, + { + mode: 'append', + styles: [ObjectFoldersTabList], + }, + ], + [ + TabPanelStyles, + { + mode: 'append', + styles: [ObjectFoldersTabPanel], + }, + ], + [ + TabTitleStyles, + { + mode: 'append', + styles: [ObjectFoldersTabTitle], + }, + ], +]; + export const ObjectFolders = observer(function ObjectFolders({ tab }) { const translate = useTranslate(); - const style = useStyles(BASE_TAB_STYLES, verticalTabStyles, styles); const navNodeManagerService = useService(NavNodeManagerService); const navNodeViewService = useService(NavNodeViewService); const innerTabState = useTabLocalState(() => new MetadataMap()); @@ -91,26 +114,22 @@ export const ObjectFolders = observer(function ObjectFolders({ tab }) { } }); - return styled(style)( - <> - {folders.length > 0 ? ( - - - - {folders.map(folderId => ( - - ))} - - {folders.map(folderId => ( - - - - ))} - - - ) : ( - {translate('plugin_object_viewer_table_no_items')} - )} - , + return folders.length > 0 ? ( + + + + {folders.map(folderId => ( + + ))} + + {folders.map(folderId => ( + + + + ))} + + + ) : ( + {translate('plugin_object_viewer_table_no_items')} ); }); diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertiesPageTab.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertiesPageTab.tsx index 4df10c5037..2e5d275a00 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertiesPageTab.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertiesPageTab.tsx @@ -6,19 +6,18 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { useStyles, useTranslate } from '@cloudbeaver/core-blocks'; +import { useTranslate } from '@cloudbeaver/core-blocks'; import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; import type { ObjectPageTabComponent } from '../ObjectPage/ObjectPage'; -export const ObjectPropertiesPageTab: ObjectPageTabComponent = observer(function ObjectPropertiesPageTab({ page, onSelect, style }) { +export const ObjectPropertiesPageTab: ObjectPageTabComponent = observer(function ObjectPropertiesPageTab({ page, onSelect }) { const translate = useTranslate(); - return styled(useStyles(style))( - + return ( + {translate('plugin_object_viewer_properties_tab')} - , + ); }); diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersNavNodeTab.m.css b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersNavNodeTab.m.css new file mode 100644 index 0000000000..866e8994e2 --- /dev/null +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersNavNodeTab.m.css @@ -0,0 +1,15 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabLoader { + width: 16px; + height: 16px; + flex-shrink: 0; + margin-right: 16px; + overflow: hidden; +} diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTab.m.css b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTab.m.css new file mode 100644 index 0000000000..f9e74fdd31 --- /dev/null +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTab.m.css @@ -0,0 +1,12 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + composes: theme-ripple theme-background-background theme-ripple-selectable from global; + color: inherit; +} diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTabList.m.css b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTabList.m.css new file mode 100644 index 0000000000..f6e1cc9313 --- /dev/null +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTabList.m.css @@ -0,0 +1,13 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabList { + composes: theme-background-surface theme-text-on-surface theme-border-color-background from global; + border-top: 1px solid; + border-right: 1px solid; +} diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTabPanel.m.css b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTabPanel.m.css new file mode 100644 index 0000000000..d582a32939 --- /dev/null +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTabPanel.m.css @@ -0,0 +1,13 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabPanel { + overflow: auto !important; + composes: theme-border-color-background from global; + border-top: 1px solid; +} diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTabTitle.m.css b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTabTitle.m.css new file mode 100644 index 0000000000..8f730dbf77 --- /dev/null +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/shared/ObjectFoldersTabTitle.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabTitle { + flex: 1; +} diff --git a/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel.tsx b/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/ObjectViewerPanel.tsx similarity index 67% rename from webapp/packages/plugin-object-viewer/src/ObjectViewerPanel.tsx rename to webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/ObjectViewerPanel.tsx index 42df480858..e9d6f04bea 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/ObjectViewerPanel.tsx @@ -8,42 +8,52 @@ import { observable, runInAction } from 'mobx'; import { observer } from 'mobx-react-lite'; import { useCallback } from 'react'; -import styled, { css } from 'reshadow'; -import { Button, Loader, TextPlaceholder, useObservableRef, useResource, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; +import { + Button, + Loader, + s, + SContext, + StyleRegistry, + TextPlaceholder, + useObservableRef, + useResource, + useS, + useTranslate, +} from '@cloudbeaver/core-blocks'; import { ConnectionInfoResource, ConnectionsManagerService } from '@cloudbeaver/core-connections'; import { useService } from '@cloudbeaver/core-di'; import { NotificationService } from '@cloudbeaver/core-events'; import { NavNodeInfoResource } from '@cloudbeaver/core-navigation-tree'; -import { BASE_TAB_STYLES, TabPanel, TabsBox, useTabLocalState } from '@cloudbeaver/core-ui'; +import { TabPanel, TabsBox, TabStyles, useTabLocalState } from '@cloudbeaver/core-ui'; import { MetadataMap } from '@cloudbeaver/core-utils'; import type { TabHandlerPanelComponent } from '@cloudbeaver/plugin-navigation-tabs'; -import type { IObjectViewerTabState } from './IObjectViewerTabState'; -import { DBObjectPagePanel } from './ObjectPage/DBObjectPagePanel'; -import { DBObjectPageService } from './ObjectPage/DBObjectPageService'; -import { DBObjectPageTab } from './ObjectPage/DBObjectPageTab'; +import type { IObjectViewerTabState } from '../IObjectViewerTabState'; +import { DBObjectPagePanel } from '../ObjectPage/DBObjectPagePanel'; +import { DBObjectPageService } from '../ObjectPage/DBObjectPageService'; +import { DBObjectPageTab } from '../ObjectPage/DBObjectPageTab'; +import styles from './shared/ObjectViewerPanel.m.css'; +import ObjectViewerPanelTab from './shared/ObjectViewerPanelTab.m.css'; -const styles = css` - Tab { - composes: theme-ripple theme-background-surface theme-text-text-primary-on-light from global; - } - tabs { - composes: theme-background-background theme-text-text-primary-on-light from global; - } - tab-outer:only-child { - display: none; - } -`; +const tabsRegistry: StyleRegistry = [ + [ + TabStyles, + { + mode: 'append', + styles: [ObjectViewerPanelTab], + }, + ], +]; export const ObjectViewerPanel: TabHandlerPanelComponent = observer(function ObjectViewerPanel({ tab }) { const translate = useTranslate(); - const style = useStyles(BASE_TAB_STYLES, styles); const dbObjectPagesService = useService(DBObjectPageService); const connectionsManagerService = useService(ConnectionsManagerService); const navNodeInfoResource = useService(NavNodeInfoResource); const notificationService = useService(NotificationService); const innerTabState = useTabLocalState(() => new MetadataMap()); + const style = useS(styles); const objectId = tab.handlerState.objectId; const connectionKey = tab.handlerState.connectionKey || null; @@ -108,26 +118,26 @@ export const ObjectViewerPanel: TabHandlerPanelComponent return {translate('plugin_object_viewer_error')}; } - return styled(style)( - <> - {node.data ? ( - ( - - ))} - localState={innerTabState} - style={styles} - > + return node.data ? ( + {pages.map(page => ( - - - + ))} - - ) : ( - {translate('plugin_object_viewer_table_no_items')} - )} - , + + } + localState={innerTabState} + > + {pages.map(page => ( + + + + ))} + + ) : ( + {translate('plugin_object_viewer_table_no_items')} ); }); diff --git a/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/shared/ObjectViewerPanel.m.css b/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/shared/ObjectViewerPanel.m.css new file mode 100644 index 0000000000..09b6abfb8c --- /dev/null +++ b/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/shared/ObjectViewerPanel.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabs { + composes: theme-background-background theme-text-text-primary-on-light from global; +} diff --git a/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/shared/ObjectViewerPanelTab.m.css b/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/shared/ObjectViewerPanelTab.m.css new file mode 100644 index 0000000000..fdcfaf9a58 --- /dev/null +++ b/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/shared/ObjectViewerPanelTab.m.css @@ -0,0 +1,15 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + composes: theme-ripple theme-background-surface theme-text-text-primary-on-light from global; +} + +.tabOuter:only-child { + display: none; +} diff --git a/webapp/packages/plugin-object-viewer/src/ObjectViewerTab.tsx b/webapp/packages/plugin-object-viewer/src/ObjectViewerTab.tsx index 74a7a50520..6359e7e05b 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectViewerTab.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectViewerTab.tsx @@ -7,9 +7,7 @@ */ import { observer } from 'mobx-react-lite'; import { useContext } from 'react'; -import styled from 'reshadow'; -import { useStyles } from '@cloudbeaver/core-blocks'; import { useDataContext } from '@cloudbeaver/core-data-context'; import { ITabData, Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; import { CaptureViewContext } from '@cloudbeaver/core-view'; @@ -18,8 +16,7 @@ import { useNode } from '@cloudbeaver/plugin-navigation-tree'; import type { IObjectViewerTabState } from './IObjectViewerTabState'; -export const ObjectViewerTab: TabHandlerTabComponent = observer(function ObjectViewerTab({ tab, onSelect, onClose, style }) { - // const connectionsInfoResource = useService(ConnectionInfoResource); +export const ObjectViewerTab: TabHandlerTabComponent = observer(function ObjectViewerTab({ tab, onSelect, onClose }) { const viewContext = useContext(CaptureViewContext); const tabMenuContext = useDataContext(viewContext); const { node } = useNode(tab.handlerState.objectId); @@ -27,19 +24,10 @@ export const ObjectViewerTab: TabHandlerTabComponent = ob const handleClose = onClose ? ({ tabId }: ITabData) => onClose(tabId) : undefined; const title = node?.name || tab.handlerState.tabTitle; - // if (node){ - // tabMenuContext.set(DATA_CONTEXT_NAV_NODE, node); - // const connection = connectionsInfoResource.getConnectionForNode(node.id); - - // if (connection) { - // tabMenuContext.set(DATA_CONTEXT_CONNECTION, connection); - // } - // } - - return styled(useStyles(style))( - + return ( + {title} - , + ); }); diff --git a/webapp/packages/plugin-object-viewer/src/ObjectViewerTabService.ts b/webapp/packages/plugin-object-viewer/src/ObjectViewerTabService.ts index cf2696bc03..26c9430b64 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectViewerTabService.ts +++ b/webapp/packages/plugin-object-viewer/src/ObjectViewerTabService.ts @@ -40,7 +40,7 @@ import { DBObjectPageService } from './ObjectPage/DBObjectPageService'; import type { ObjectPage } from './ObjectPage/ObjectPage'; import { objectViewerTabHandlerKey } from './objectViewerTabHandlerKey'; -const ObjectViewerPanel = importLazyComponent(() => import('./ObjectViewerPanel').then(m => m.ObjectViewerPanel)); +const ObjectViewerPanel = importLazyComponent(() => import('./ObjectViewerPanel/ObjectViewerPanel').then(m => m.ObjectViewerPanel)); const ObjectViewerTab = importLazyComponent(() => import('./ObjectViewerTab').then(m => m.ObjectViewerTab)); @injectable() diff --git a/webapp/packages/plugin-settings-administration/src/SettingsDrawerItem.tsx b/webapp/packages/plugin-settings-administration/src/SettingsDrawerItem.tsx index 31c8f56f63..7afeb12162 100644 --- a/webapp/packages/plugin-settings-administration/src/SettingsDrawerItem.tsx +++ b/webapp/packages/plugin-settings-administration/src/SettingsDrawerItem.tsx @@ -5,25 +5,17 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import styled from 'reshadow'; - import type { AdministrationItemDrawerProps } from '@cloudbeaver/core-administration'; -import { Translate, useStyles } from '@cloudbeaver/core-blocks'; -import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { Translate } from '@cloudbeaver/core-blocks'; +import { TabIcon, Tab, TabTitle } from '@cloudbeaver/core-ui'; -export const SettingsDrawerItem: React.FC = function SettingsDrawerItem({ - item, - onSelect, - style, - disabled, - configurationWizard, -}) { - return styled(useStyles(style))( +export const SettingsDrawerItem: React.FC = function SettingsDrawerItem({ item, onSelect, disabled }) { + return ( onSelect(item.name)}> - + - , + ); }; diff --git a/webapp/packages/plugin-sql-editor-navigation-tab/src/SqlEditorTab.tsx b/webapp/packages/plugin-sql-editor-navigation-tab/src/SqlEditorTab.tsx index 645fd6e7db..3f1959e405 100644 --- a/webapp/packages/plugin-sql-editor-navigation-tab/src/SqlEditorTab.tsx +++ b/webapp/packages/plugin-sql-editor-navigation-tab/src/SqlEditorTab.tsx @@ -7,13 +7,12 @@ */ import { observer } from 'mobx-react-lite'; import { useContext } from 'react'; -import styled from 'reshadow'; -import { IconOrImage, s, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; +import { IconOrImage, s, useTranslate } from '@cloudbeaver/core-blocks'; import { Connection, ConnectionInfoResource, createConnectionParam } from '@cloudbeaver/core-connections'; import { useDataContext } from '@cloudbeaver/core-data-context'; import { useService } from '@cloudbeaver/core-di'; -import { ITabData, Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { ITabData, TabIcon, Tab, TabTitle } from '@cloudbeaver/core-ui'; import { CaptureViewContext } from '@cloudbeaver/core-view'; import type { TabHandlerTabComponent } from '@cloudbeaver/plugin-navigation-tabs'; import { @@ -27,7 +26,7 @@ import { import { DATA_CONTEXT_SQL_EDITOR_TAB } from './DATA_CONTEXT_SQL_EDITOR_TAB'; import sqlEditorTabStyles from './SqlEditorTab.m.css'; -export const SqlEditorTab: TabHandlerTabComponent = observer(function SqlEditorTab({ tab, onSelect, onClose, style }) { +export const SqlEditorTab: TabHandlerTabComponent = observer(function SqlEditorTab({ tab, onSelect, onClose }) { const viewContext = useContext(CaptureViewContext); const tabMenuContext = useDataContext(viewContext); @@ -57,14 +56,14 @@ export const SqlEditorTab: TabHandlerTabComponent = observer const handleSelect = ({ tabId }: ITabData) => onSelect(tabId); const handleClose = onClose ? ({ tabId }: ITabData) => onClose(tabId) : undefined; - return styled(useStyles(style))( - + return ( + {name} {isReadonly && isScript && ( )} - {hasUnsavedMark && } - , + {hasUnsavedMark &&
} + ); }); diff --git a/webapp/packages/plugin-sql-editor/src/SqlEditor/SqlEditor.tsx b/webapp/packages/plugin-sql-editor/src/SqlEditor/SqlEditor.tsx index b7f7b9a034..dc558ebabc 100644 --- a/webapp/packages/plugin-sql-editor/src/SqlEditor/SqlEditor.tsx +++ b/webapp/packages/plugin-sql-editor/src/SqlEditor/SqlEditor.tsx @@ -7,57 +7,31 @@ */ import { observer } from 'mobx-react-lite'; import { useEffect, useMemo, useState } from 'react'; -import styled, { css } from 'reshadow'; -import { getComputed, useSplit } from '@cloudbeaver/core-blocks'; +import { getComputed, s, SContext, StyleRegistry, useS, useSplit } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; -import { BASE_TAB_STYLES, ITabData, TabList, TabPanelList, TabsState, VERTICAL_ROTATED_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { ITabData, TabList, TabListStyles, TabListVerticalRotatedRegistry, TabPanelList, TabsState, TabStyles } from '@cloudbeaver/core-ui'; import { MetadataMap } from '@cloudbeaver/core-utils'; import { useCaptureViewContext } from '@cloudbeaver/core-view'; import { ISqlEditorModeProps, SqlEditorModeService } from '../SqlEditorModeService'; import { DATA_CONTEXT_SQL_EDITOR_DATA } from './DATA_CONTEXT_SQL_EDITOR_DATA'; import type { ISqlEditorProps } from './ISqlEditorProps'; +import styles from './shared/SqlEditor.m.css'; +import SqlEditorTab from './shared/SqlEditorTab.m.css'; +import SqlEditorTabList from './shared/SqlEditorTabList.m.css'; import { SQLEditorActions } from './SQLEditorActions'; import { useSqlEditor } from './useSqlEditor'; -const styles = css` - sql-editor { - position: relative; - z-index: 0; - flex: 1 auto; - height: 100%; - display: flex; - overflow: auto; - } -`; - -const tabStyles = css` - tabs { - composes: theme-background-secondary theme-text-on-secondary from global; - overflow-x: hidden; - padding-top: 4px; - } - Tab { - composes: theme-ripple theme-background-background theme-text-text-primary-on-light theme-typography--body2 from global; - text-transform: uppercase; - font-weight: normal; - - &:global([aria-selected='true']) { - font-weight: normal !important; - } - } - TabList { - composes: theme-background-secondary theme-text-on-secondary from global; - margin-right: 8px; - margin-left: 4px; - } -`; - -const tabListStyles = [BASE_TAB_STYLES, VERTICAL_ROTATED_TAB_STYLES, tabStyles]; +const sqlEditorRegistry: StyleRegistry = [ + ...TabListVerticalRotatedRegistry, + [TabListStyles, { mode: 'append', styles: [SqlEditorTabList] }], + [TabStyles, { mode: 'append', styles: [SqlEditorTab] }], +]; export const SqlEditor = observer(function SqlEditor({ state, className }) { const split = useSplit(); + const style = useS(styles); const sqlEditorModeService = useService(SqlEditorModeService); const data = useSqlEditor(state); const [modesState] = useState(() => new MetadataMap()); @@ -85,12 +59,7 @@ export const SqlEditor = observer(function SqlEditor({ state, c } }, [isEditorEmpty]); - return styled( - styles, - BASE_TAB_STYLES, - VERTICAL_ROTATED_TAB_STYLES, - tabStyles, - )( + return ( (function SqlEditor({ state, c lazy onChange={handleModeSelect} > - - - - {displayedEditors > 1 ? ( - - - - ) : null} - - , + +
+ + + {displayedEditors > 1 ? ( +
+ +
+ ) : null} +
+
+ ); }); diff --git a/webapp/packages/plugin-sql-editor/src/SqlEditor/shared/SqlEditor.m.css b/webapp/packages/plugin-sql-editor/src/SqlEditor/shared/SqlEditor.m.css new file mode 100644 index 0000000000..bd8cfaca71 --- /dev/null +++ b/webapp/packages/plugin-sql-editor/src/SqlEditor/shared/SqlEditor.m.css @@ -0,0 +1,22 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.sqlEditor { + position: relative; + z-index: 0; + flex: 1 auto; + height: 100%; + display: flex; + overflow: auto; +} + +.tabs { + composes: theme-background-secondary theme-text-on-secondary from global; + overflow-x: hidden; + padding-top: 4px; +} diff --git a/webapp/packages/plugin-sql-editor/src/SqlEditor/shared/SqlEditorTab.m.css b/webapp/packages/plugin-sql-editor/src/SqlEditor/shared/SqlEditorTab.m.css new file mode 100644 index 0000000000..b9475c5b41 --- /dev/null +++ b/webapp/packages/plugin-sql-editor/src/SqlEditor/shared/SqlEditorTab.m.css @@ -0,0 +1,17 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tab { + composes: theme-ripple theme-background-background theme-text-text-primary-on-light theme-typography--body2 from global; + text-transform: uppercase; + font-weight: normal; + + &:global([aria-selected='true']) { + font-weight: normal !important; + } +} diff --git a/webapp/packages/plugin-sql-editor/src/SqlEditor/shared/SqlEditorTabList.m.css b/webapp/packages/plugin-sql-editor/src/SqlEditor/shared/SqlEditorTabList.m.css new file mode 100644 index 0000000000..a57db7c7fb --- /dev/null +++ b/webapp/packages/plugin-sql-editor/src/SqlEditor/shared/SqlEditorTabList.m.css @@ -0,0 +1,13 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabList { + composes: theme-background-secondary theme-text-on-secondary from global; + margin-right: 8px; + margin-left: 4px; +} diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/SqlResultTab.tsx b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/SqlResultTab.tsx index a4cd03c53f..bceffe41ab 100644 --- a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/SqlResultTab.tsx +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/SqlResultTab.tsx @@ -7,11 +7,8 @@ */ import { observer } from 'mobx-react-lite'; import { useContext } from 'react'; -import styled from 'reshadow'; -import { useStyles } from '@cloudbeaver/core-blocks'; import { useDataContext } from '@cloudbeaver/core-data-context'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import { ITabData, Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; import { CaptureViewContext } from '@cloudbeaver/core-view'; @@ -21,20 +18,19 @@ import { DATA_CONTEXT_SQL_EDITOR_RESULT_ID } from './DATA_CONTEXT_SQL_EDITOR_RES interface Props { result: ISqlEditorResultTab; className?: string; - style?: ComponentStyle; onClose?: (tab: ITabData) => Promise; } -export const SqlResultTab = observer(function SqlResultTab({ result, className, style, onClose }) { +export const SqlResultTab = observer(function SqlResultTab({ result, className, onClose }) { const viewContext = useContext(CaptureViewContext); const tabMenuContext = useDataContext(viewContext); tabMenuContext.set(DATA_CONTEXT_SQL_EDITOR_RESULT_ID, result); - return styled(useStyles(style))( - + return ( + {result.name} - , + ); }); diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/SqlResultTabs.tsx b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/SqlResultTabs.tsx index f27dd6c603..6bd6186df7 100644 --- a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/SqlResultTabs.tsx +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/SqlResultTabs.tsx @@ -6,59 +6,36 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { css, use } from 'reshadow'; -import { getComputed, TextPlaceholder, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; +import { getComputed, s, SContext, StyleRegistry, TextPlaceholder, useS, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; -import { BASE_TAB_STYLES, ITabData, TabList, TabPanel, TabsState } from '@cloudbeaver/core-ui'; +import { ITabData, TabIconStyles, TabList, TabListStyles, TabPanel, TabsState, TabStyles } from '@cloudbeaver/core-ui'; import type { ISqlEditorTabState } from '../ISqlEditorTabState'; import { ESqlDataSourceFeatures } from '../SqlDataSource/ESqlDataSourceFeatures'; import { SqlDataSourceService } from '../SqlDataSource/SqlDataSourceService'; +import styles from './shared/SqlResultTabs.m.css'; +import SqlResultTabsTab from './shared/SqlResultTabsTab.m.css'; +import TabIconModuleStyles from './shared/SqlResultTabsTabIcon.m.css'; +import SqlResultTabsTabList from './shared/SqlResultTabsTabList.m.css'; import { SqlResultPanel } from './SqlResultPanel'; import { SqlResultTab } from './SqlResultTab'; import { SqlResultTabsService } from './SqlResultTabsService'; -const styles = css` - Tab { - composes: theme-ripple theme-background-surface theme-text-text-primary-on-light from global; - height: 38px !important; - } - TabIcon { - composes: theme-text-surface from global; - } - wrapper { - overflow: auto; - display: flex; - flex-direction: column; - flex: 1; - height: 100%; - position: relative; - } - TabsBox { - height: 100%; - } - TabList { - composes: theme-background-background theme-text-text-primary-on-light from global; - display: flex; - overflow: auto; - } - TabList:not([|executable]) tab-outer:only-child { - display: none; - } - TextPlaceholder { - padding: 24px; - } -`; - interface Props { state: ISqlEditorTabState; onTabSelect?: (tabId: string) => void; onTabClose?: (tabId: string) => void; } +const registry: StyleRegistry = [ + [TabStyles, { mode: 'append', styles: [SqlResultTabsTab] }], + [TabIconStyles, { mode: 'append', styles: [TabIconModuleStyles] }], + [TabListStyles, { mode: 'append', styles: [SqlResultTabsTabList] }], +]; + export const SqlResultTabs = observer(function SqlDataResult({ state, onTabSelect, onTabClose }) { - const style = useStyles(BASE_TAB_STYLES, styles); + const style = useS(styles); const translate = useTranslate(); const sqlResultTabsService = useService(SqlResultTabsService); const sqlDataSourceService = useService(SqlDataSourceService); @@ -101,14 +78,18 @@ export const SqlResultTabs = observer(function SqlDataResult({ state, onT } if (!state.tabs.length) { - return styled(style)({translate(dataSource?.emptyPlaceholder ?? 'sql_editor_placeholder')}); + return ( + + {translate(dataSource?.emptyPlaceholder ?? 'sql_editor_placeholder')} + + ); } const executable = dataSource?.hasFeature(ESqlDataSourceFeatures.executable); const tabList = orderedTabs.map(tab => tab.id); - return styled(style)( - + return ( +
(function SqlDataResult({ state, onT onChange={handleSelect} onClose={handleClose} > - - {orderedTabs.map(result => ( - - ))} - + + + {orderedTabs.map(result => ( + + ))} + + {orderedTabs.map(result => ( ))} - , +
); }); diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabs.m.css b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabs.m.css new file mode 100644 index 0000000000..24625b4f24 --- /dev/null +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabs.m.css @@ -0,0 +1,24 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.wrapper { + overflow: auto; + display: flex; + flex-direction: column; + flex: 1; + height: 100%; + position: relative; +} + +.tabListNotExecutable .tabOuter:only-child { + display: none; +} + +.textPlaceholder { + padding: 24px; +} diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabsTab.m.css b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabsTab.m.css new file mode 100644 index 0000000000..eb0b75b736 --- /dev/null +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabsTab.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +.tab { + composes: theme-ripple theme-background-surface theme-text-text-primary-on-light from global; + height: 38px !important; +} diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabsTabIcon.m.css b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabsTabIcon.m.css new file mode 100644 index 0000000000..56405d9f09 --- /dev/null +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabsTabIcon.m.css @@ -0,0 +1,11 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabIcon { + composes: theme-text-surface from global; +} diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabsTabList.m.css b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabsTabList.m.css new file mode 100644 index 0000000000..8d81a34c6e --- /dev/null +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/shared/SqlResultTabsTabList.m.css @@ -0,0 +1,13 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.tabList { + composes: theme-background-background theme-text-text-primary-on-light from global; + display: flex; + overflow: auto; +} diff --git a/webapp/packages/plugin-tools-panel/src/ToolsPanel/ToolsPanel.tsx b/webapp/packages/plugin-tools-panel/src/ToolsPanel/ToolsPanel.tsx index 07c471d7d0..796c7a8527 100644 --- a/webapp/packages/plugin-tools-panel/src/ToolsPanel/ToolsPanel.tsx +++ b/webapp/packages/plugin-tools-panel/src/ToolsPanel/ToolsPanel.tsx @@ -8,11 +8,10 @@ import { action, untracked } from 'mobx'; import { observer } from 'mobx-react-lite'; import { useRef } from 'react'; -import styled from 'reshadow'; -import { s, useS, useStyles, useUserData } from '@cloudbeaver/core-blocks'; +import { s, SContext, useS, useUserData } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; -import { BASE_TAB_STYLES, ITabData, TabList, TabPanelList, TabsState, UNDERLINE_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { ITabData, TabList, TabPanelList, TabsState, TabUnderlineStyleRegistry } from '@cloudbeaver/core-ui'; import { isArraysEqual } from '@cloudbeaver/core-utils'; import styles from './ToolsPanel.m.css'; @@ -27,7 +26,6 @@ export const ToolsPanel = observer(function ToolsPanel() { const style = useS(styles); const state = useUserData('tools', () => ({ selectedTabId: undefined })); - const tabStyle = [BASE_TAB_STYLES, UNDERLINE_TAB_STYLES]; const tabs = toolsPanelService.tabsContainer.getIdList(); const prevTabs = useRef(tabs); const equal = isArraysEqual(prevTabs.current, tabs); @@ -61,14 +59,16 @@ export const ToolsPanel = observer(function ToolsPanel() { state.selectedTabId = tab.tabId; } - return styled(useStyles(tabStyle))( + return ( -
- -
- + +
+ +
+ +
-
- , + + ); }); diff --git a/webapp/packages/plugin-user-profile/src/UserProfileForm/Authentication/AuthenticationPanel.tsx b/webapp/packages/plugin-user-profile/src/UserProfileForm/Authentication/AuthenticationPanel.tsx index 8ef0930d79..beade8842c 100644 --- a/webapp/packages/plugin-user-profile/src/UserProfileForm/Authentication/AuthenticationPanel.tsx +++ b/webapp/packages/plugin-user-profile/src/UserProfileForm/Authentication/AuthenticationPanel.tsx @@ -6,29 +6,24 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { ColoredContainer, Container, useStyles } from '@cloudbeaver/core-blocks'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; -import { BASE_TAB_STYLES, TabPanel } from '@cloudbeaver/core-ui'; +import { ColoredContainer, Container } from '@cloudbeaver/core-blocks'; +import { TabPanel } from '@cloudbeaver/core-ui'; import { ChangePassword } from './ChangePassword/ChangePassword'; interface Props { className?: string; - style?: ComponentStyle; } -export const AuthenticationPanel = observer(function AuthenticationPanel({ className, style }) { - const styles = useStyles(BASE_TAB_STYLES, style); - - return styled(styles)( +export const AuthenticationPanel = observer(function AuthenticationPanel({ className }) { + return ( - , + ); }); diff --git a/webapp/packages/plugin-user-profile/src/UserProfileForm/Authentication/AuthenticationTab.tsx b/webapp/packages/plugin-user-profile/src/UserProfileForm/Authentication/AuthenticationTab.tsx index 8a48c21254..850dc7f52e 100644 --- a/webapp/packages/plugin-user-profile/src/UserProfileForm/Authentication/AuthenticationTab.tsx +++ b/webapp/packages/plugin-user-profile/src/UserProfileForm/Authentication/AuthenticationTab.tsx @@ -6,24 +6,20 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { useStyles, useTranslate } from '@cloudbeaver/core-blocks'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; +import { useTranslate } from '@cloudbeaver/core-blocks'; import { Tab, TabTitle } from '@cloudbeaver/core-ui'; interface Props { className?: string; - style?: ComponentStyle; } -export const AuthenticationTab = observer(function AuthenticationTab({ className, style }) { +export const AuthenticationTab = observer(function AuthenticationTab({ className }) { const translate = useTranslate(); - const styles = useStyles(style); - return styled(styles)( - + return ( + {translate('ui_authentication')} - , + ); }); diff --git a/webapp/packages/plugin-user-profile/src/UserProfileForm/UserForm.tsx b/webapp/packages/plugin-user-profile/src/UserProfileForm/UserForm.tsx index 8cac5eece9..f46870ad0e 100644 --- a/webapp/packages/plugin-user-profile/src/UserProfileForm/UserForm.tsx +++ b/webapp/packages/plugin-user-profile/src/UserProfileForm/UserForm.tsx @@ -6,13 +6,12 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; import { AUTH_PROVIDER_LOCAL_ID } from '@cloudbeaver/core-authentication'; -import { Button, s, StatusMessage, useS, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; +import { Button, s, SContext, StatusMessage, useS, useTranslate } from '@cloudbeaver/core-blocks'; import { ENotificationType } from '@cloudbeaver/core-events'; import type { UserInfo } from '@cloudbeaver/core-sdk'; -import { BASE_TAB_STYLES, TabList, TabsState, UNDERLINE_TAB_BIG_STYLES, UNDERLINE_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { TabBigUnderlineStyleRegistry, TabList, TabsState } from '@cloudbeaver/core-ui'; import { AuthenticationPanel } from './Authentication/AuthenticationPanel'; import { AuthenticationTab } from './Authentication/AuthenticationTab'; @@ -29,13 +28,11 @@ interface Props { export const UserForm = observer(function UserForm({ user, state, onClose }) { const translate = useTranslate(); - const style = [BASE_TAB_STYLES, UNDERLINE_TAB_STYLES, UNDERLINE_TAB_BIG_STYLES]; - const styles = useStyles(style); const moduleStyle = useS(userFormStyles); const localProvider = user.linkedAuthProviders.includes(AUTH_PROVIDER_LOCAL_ID); - return styled(styles)( + return (
@@ -43,10 +40,12 @@ export const UserForm = observer(function UserForm({ user, state, onClose
- - - {localProvider && } - + + + + {localProvider && } + +
{onClose && ( @@ -57,10 +56,10 @@ export const UserForm = observer(function UserForm({ user, state, onClose
- - {localProvider && } + + {localProvider && }
-
, +
); }); diff --git a/webapp/packages/plugin-user-profile/src/UserProfileForm/UserInfo/UserInfoPanel.tsx b/webapp/packages/plugin-user-profile/src/UserProfileForm/UserInfo/UserInfoPanel.tsx index 4e9fdb6955..b347d0b3a1 100644 --- a/webapp/packages/plugin-user-profile/src/UserProfileForm/UserInfo/UserInfoPanel.tsx +++ b/webapp/packages/plugin-user-profile/src/UserProfileForm/UserInfo/UserInfoPanel.tsx @@ -6,7 +6,6 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; import { UserMetaParametersResource } from '@cloudbeaver/core-authentication'; import { @@ -18,27 +17,23 @@ import { Loader, ObjectPropertyInfoForm, useResource, - useStyles, useTranslate, } from '@cloudbeaver/core-blocks'; import type { UserInfo } from '@cloudbeaver/core-sdk'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; -import { BASE_TAB_STYLES, TabPanel } from '@cloudbeaver/core-ui'; +import { TabPanel } from '@cloudbeaver/core-ui'; import { AuthTokenList } from '../AuthTokens/AuthTokenList'; interface Props { user: UserInfo; className?: string; - style?: ComponentStyle; } -export const UserInfoPanel = observer(function UserInfoPanel({ user, className, style }) { +export const UserInfoPanel = observer(function UserInfoPanel({ user, className }) { const userMetaParameters = useResource(UserInfoPanel, UserMetaParametersResource, undefined); - const styles = useStyles(BASE_TAB_STYLES, style); const translate = useTranslate(); - return styled(styles)( + return ( @@ -57,11 +52,10 @@ export const UserInfoPanel = observer(function UserInfoPanel({ user, clas {() => - userMetaParameters.data.length > 0 && - styled(styles)( + userMetaParameters.data.length > 0 && ( - , + ) } @@ -72,6 +66,6 @@ export const UserInfoPanel = observer(function UserInfoPanel({ user, clas - , + ); }); diff --git a/webapp/packages/plugin-user-profile/src/UserProfileForm/UserInfo/UserInfoTab.tsx b/webapp/packages/plugin-user-profile/src/UserProfileForm/UserInfo/UserInfoTab.tsx index f3d344c5a2..b2b1dc8564 100644 --- a/webapp/packages/plugin-user-profile/src/UserProfileForm/UserInfo/UserInfoTab.tsx +++ b/webapp/packages/plugin-user-profile/src/UserProfileForm/UserInfo/UserInfoTab.tsx @@ -6,24 +6,20 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { useStyles, useTranslate } from '@cloudbeaver/core-blocks'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; +import { useTranslate } from '@cloudbeaver/core-blocks'; import { Tab, TabTitle } from '@cloudbeaver/core-ui'; interface Props { className?: string; - style?: ComponentStyle; } -export const UserInfoTab = observer(function UserInfoTab({ className, style }) { +export const UserInfoTab = observer(function UserInfoTab({ className }) { const translate = useTranslate(); - const styles = useStyles(style); - return styled(styles)( - + return ( + {translate('plugin_user_profile_info')} - , + ); }); diff --git a/webapp/packages/plugin-version-update-administration/src/VersionUpdateDrawerItem.tsx b/webapp/packages/plugin-version-update-administration/src/VersionUpdateDrawerItem.tsx index f586a71d60..438d422ad7 100644 --- a/webapp/packages/plugin-version-update-administration/src/VersionUpdateDrawerItem.tsx +++ b/webapp/packages/plugin-version-update-administration/src/VersionUpdateDrawerItem.tsx @@ -6,32 +6,25 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { css } from 'reshadow'; import type { AdministrationItemDrawerProps } from '@cloudbeaver/core-administration'; -import { s, Translate, useResource, useS, useStyles, useTranslate } from '@cloudbeaver/core-blocks'; +import { s, Translate, useResource, useS, useTranslate } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { CachedMapAllKey } from '@cloudbeaver/core-resource'; -import { Tab, TabIcon, TabTitle } from '@cloudbeaver/core-ui'; +import { TabIcon, Tab, TabTitle } from '@cloudbeaver/core-ui'; import { VersionResource } from '@cloudbeaver/core-version'; import { VersionUpdateService } from '@cloudbeaver/core-version-update'; import moduleStyles from './VersionUpdateDrawerItem.m.css'; -const styles = css` - tab-container { - justify-content: space-between; - } -`; - -export const VersionUpdateDrawerItem = observer(function VersionUpdateDrawerItem({ item, onSelect, style, disabled }) { +export const VersionUpdateDrawerItem = observer(function VersionUpdateDrawerItem({ item, onSelect, disabled }) { const translate = useTranslate(); const versionUpdateService = useService(VersionUpdateService); const moduleStyle = useS(moduleStyles); useResource(VersionUpdateDrawerItem, VersionResource, CachedMapAllKey, { silent: true }); - return styled(useStyles(style, styles))( + return ( onSelect(item.name)}> @@ -40,6 +33,6 @@ export const VersionUpdateDrawerItem = observer(f {versionUpdateService.newVersionAvailable && (
)} - , + ); });