diff --git a/webapp/packages/core-blocks/src/Loader/Loader.m.css b/webapp/packages/core-blocks/src/Loader/Loader.m.css new file mode 100644 index 0000000000..4be77cfcbb --- /dev/null +++ b/webapp/packages/core-blocks/src/Loader/Loader.m.css @@ -0,0 +1,119 @@ +/* + * 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. + */ + +.loader { + margin: auto; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + opacity: 0; + transition: opacity cubic-bezier(0.4, 0, 0.2, 1) 0.3s; + &:global(.animate) { + opacity: 1; + } + & .staticImage { + height: 100%; + width: 100%; + display: none; + } + &.secondary, + &.overlay, + &:global(.secondary), + &:global(.overlay) { + &:not(.small):not(:global(.small)) { + & .staticImage.secondaryIcon { + display: block; + } + } + &.small, + &:global(.small) { + & .staticImage.secondarySmallIcon { + display: block; + } + } + } + &:not(.secondary):not(.overlay):not(:global(.secondary)):not(:global(.overlay)) { + &:not(.small):not(:global(.small)) { + & .staticImage.primaryIcon { + display: block; + } + } + &.small, + &:global(.small) { + & .staticImage.primarySmallIcon { + display: block; + } + } + } +} +.icon { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + animation: rotation 2s infinite linear; +} +.message { + padding: 16px; +} +.actions { + padding-top: 42px; +} +.loader.inline { + height: 38px; + flex-direction: row; + margin: 0; + justify-content: left; + & .icon { + width: 24px; + height: 24px; + } + & .message { + display: block; + padding: 0 16px; + } + & .actions { + padding: 0; + } +} +.loader.small { + & .icon { + width: 16px; + height: 16px; + } + & .message { + display: none; + } +} +.loader.fullSize { + height: 100%; + & .icon { + width: 100%; + height: 100%; + } +} +@keyframes rotation { + from { + transform: rotate(0deg); + } + to { + transform: rotate(359deg); + } +} + +.loaderOverlay { + composes: theme-text-on-primary from global; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.4); +} diff --git a/webapp/packages/core-blocks/src/Loader/Loader.tsx b/webapp/packages/core-blocks/src/Loader/Loader.tsx index 3718146741..b8a4adca70 100644 --- a/webapp/packages/core-blocks/src/Loader/Loader.tsx +++ b/webapp/packages/core-blocks/src/Loader/Loader.tsx @@ -8,19 +8,18 @@ import { observable } from 'mobx'; import { observer } from 'mobx-react-lite'; import { Suspense, useContext, useEffect, useRef, useState } from 'react'; -import styled, { use } from 'reshadow'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import { ILoadableState, uuid } from '@cloudbeaver/core-utils'; import { Button } from '../Button'; import { ErrorBoundary } from '../ErrorBoundary'; import { ExceptionMessage } from '../ExceptionMessage'; import { Translate } from '../localization/Translate'; +import { s } from '../s'; import { StaticImage } from '../StaticImage'; -import { useStyles } from '../useStyles'; +import { useS } from '../useS'; +import styles from './Loader.m.css'; import { ILoaderContext, LoaderContext } from './LoaderContext'; -import { loaderStyles, overlayStyles } from './loaderStyles'; type LoaderState = | ILoadableState @@ -52,7 +51,6 @@ interface Props { className?: string; fullSize?: boolean; state?: LoaderState | LoaderState[]; - style?: ComponentStyle; children?: (() => React.ReactNode) | React.ReactNode; onCancel?: () => void; } @@ -80,7 +78,6 @@ export const Loader = observer(function Loader({ loading, inlineException, state, - style, children, onCancel, }) { @@ -171,7 +168,7 @@ export const Loader = observer(function Loader({ loading = false; } - style = useStyles(loaderStyles, style, overlay && overlayStyles); + const style = useS(styles); const [isVisible, setVisible] = useState(loading); const refLoaderDisplayed = { state: false }; @@ -232,7 +229,6 @@ export const Loader = observer(function Loader({ fullSize={fullSize} className={className} inlineException={inlineException} - style={style} /> } > @@ -251,7 +247,7 @@ export const Loader = observer(function Loader({ if (hideException) { return null; } - return styled(style)(); + return ; } if (children && (!loader || !loading) && !overlay) { @@ -274,31 +270,31 @@ export const Loader = observer(function Loader({ refLoaderDisplayed.state = true; - return styled(style)( + return ( <> {overlay && renderWrappedChildren()} - - - - - - - +
+
+ + + + +
{!hideMessage && ( - +
- +
)} {onCancel && ( - +
- +
)} - +
-
, + ); }); diff --git a/webapp/packages/core-blocks/src/Loader/loaderStyles.ts b/webapp/packages/core-blocks/src/Loader/loaderStyles.ts deleted file mode 100644 index 297bbeafd5..0000000000 --- a/webapp/packages/core-blocks/src/Loader/loaderStyles.ts +++ /dev/null @@ -1,138 +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 loaderStyles = css` - loader { - margin: auto; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - opacity: 0; - transition: opacity cubic-bezier(0.4, 0, 0.2, 1) 0.3s; - - &:global(.animate) { - opacity: 1; - } - - & StaticImage { - height: 100%; - width: 100%; - display: none; - } - - &[|secondary], - &[|overlay], - &:global(.secondary), - &:global(.overlay) { - &:not([|small]):not(:global(.small)) { - & StaticImage[|secondaryIcon] { - display: block; - } - } - - &[|small], - &:global(.small) { - & StaticImage[|secondarySmallIcon] { - display: block; - } - } - } - - &:not([|secondary]):not([|overlay]):not(:global(.secondary)):not(:global(.overlay)) { - &:not([|small]):not(:global(.small)) { - & StaticImage[|primaryIcon] { - display: block; - } - } - - &[|small], - &:global(.small) { - & StaticImage[|primarySmallIcon] { - display: block; - } - } - } - } - - icon { - display: flex; - align-items: center; - justify-content: center; - width: 40px; - height: 40px; - animation: rotation 2s infinite linear; - } - - message { - padding: 16px; - } - - actions { - padding-top: 42px; - } - - loader[|inline] { - height: 38px; - flex-direction: row; - margin: 0; - justify-content: left; - - & icon { - width: 24px; - height: 24px; - } - & message { - display: block; - padding: 0 16px; - } - & actions { - padding: 0; - } - } - - loader[|small] { - & icon { - width: 16px; - height: 16px; - } - & message { - display: none; - } - } - - loader[|fullSize] { - height: 100%; - - & icon { - width: 100%; - height: 100%; - } - } - - @keyframes rotation { - from { - transform: rotate(0deg); - } - to { - transform: rotate(359deg); - } - } -`; -export const overlayStyles = css` - loader { - composes: theme-text-on-primary from global; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.4); - } -`; diff --git a/webapp/packages/core-blocks/src/Menu/MenuBarSmallItem.m.css b/webapp/packages/core-blocks/src/Menu/MenuBarSmallItem.m.css index d7fba02863..983b66aec3 100644 --- a/webapp/packages/core-blocks/src/Menu/MenuBarSmallItem.m.css +++ b/webapp/packages/core-blocks/src/Menu/MenuBarSmallItem.m.css @@ -11,4 +11,25 @@ padding: 0; margin: 0; flex-shrink: 0; -} \ No newline at end of file +} + +.iconBox { + composes: theme-form-element-radius theme-text-primary theme-ripple from global; + box-sizing: border-box; + overflow: hidden; + padding: 4px !important; + margin: 2px !important; + flex-shrink: 0; + height: 24px !important; + display: flex; + cursor: pointer; + align-items: center; + gap: 2px; + user-select: none; + outline: none; + + & .iconLabel { + text-transform: uppercase; + font-weight: 500; + } +} diff --git a/webapp/packages/core-blocks/src/Menu/MenuBarSmallItem.tsx b/webapp/packages/core-blocks/src/Menu/MenuBarSmallItem.tsx index 6cb2a2f38c..8d61cb93e3 100644 --- a/webapp/packages/core-blocks/src/Menu/MenuBarSmallItem.tsx +++ b/webapp/packages/core-blocks/src/Menu/MenuBarSmallItem.tsx @@ -6,43 +6,15 @@ * you may not use this file except in compliance with the License. */ import type { ButtonProps } from 'reakit/ts'; -import styled, { css } from 'reshadow'; - -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import { IconButton } from '../IconButton'; -import { useStyles } from '../useStyles'; -import moduleStyles from './MenuBarSmallItem.m.css'; -import { useS } from '../useS'; import { s } from '../s'; - -export const styles = css` - icon-box { - composes: theme-form-element-radius theme-text-primary theme-ripple from global; - box-sizing: border-box; - overflow: hidden; - padding: 4px !important; - margin: 2px !important; - flex-shrink: 0; - height: 24px !important; - display: flex; - cursor: pointer; - align-items: center; - gap: 2px; - user-select: none; - outline: none; - - & icon-label { - text-transform: uppercase; - font-weight: 500; - } - } -`; +import { useS } from '../useS'; +import moduleStyles from './MenuBarSmallItem.m.css'; interface Props extends Omit { icon?: string; viewBox?: string; - style?: ComponentStyle; onClick?: React.MouseEventHandler; } @@ -51,17 +23,16 @@ export const MenuBarSmallItem: React.FC> = functi viewBox, children, className, - style, onClick, ...rest }) { - const moduleStyle = useS(moduleStyles); + const style = useS(moduleStyles); // TODO: replace IconButton with StaticImage / Icon // TODO: use button for icon-box (maybe) - return styled(useStyles(styles, style))( - - {icon && } - {children && {children}} - , + return ( +
+ {icon && } + {children &&
{children}
} +
); }; diff --git a/webapp/packages/core-blocks/src/MenuPanel/MenuPanelItem.tsx b/webapp/packages/core-blocks/src/MenuPanel/MenuPanelItem.tsx index 65217657e3..4849a3f784 100644 --- a/webapp/packages/core-blocks/src/MenuPanel/MenuPanelItem.tsx +++ b/webapp/packages/core-blocks/src/MenuPanel/MenuPanelItem.tsx @@ -6,10 +6,8 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { use } from 'reshadow'; import type { IMenuItem } from '@cloudbeaver/core-dialogs'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; import { Checkbox } from '../FormControls/Checkboxes/Checkbox'; import { Radio } from '../FormControls/Radio'; @@ -17,16 +15,18 @@ import { Icon } from '../Icon'; import { IconOrImage } from '../IconOrImage'; import { Loader } from '../Loader/Loader'; import { useTranslate } from '../localization/useTranslate'; -import { useStyles } from '../useStyles'; -import { menuPanelStyles } from './menuPanelStyles'; +import { s } from '../s'; +import { useS } from '../useS'; +import MenuPanelItemAndTriggerStyles from './shared/MenuPanelItemAndTrigger.m.css'; interface MenuPanelItemProps { menuItem: IMenuItem; - style?: ComponentStyle; + className?: string; } -export const MenuPanelItem = observer(function MenuPanelItem({ menuItem, style = [] }) { +export const MenuPanelItem = observer(function MenuPanelItem({ menuItem }) { const translate = useTranslate(); + const style = useS(MenuPanelItemAndTriggerStyles); const title = translate(menuItem.title); let control = null; @@ -37,13 +37,22 @@ export const MenuPanelItem = observer(function MenuPanelItem control = ; } - return styled(useStyles(menuPanelStyles, style))( - - {menuItem.icon ? : control} - {title} - - {menuItem.panel && (menuItem.isProcessing ? : )} - - , + return ( +
+
+ {menuItem.icon ? : control} +
+
+ {title} +
+
+ {menuItem.panel && + (menuItem.isProcessing ? ( + + ) : ( + + ))} +
+
); }); diff --git a/webapp/packages/core-blocks/src/MenuPanel/MenuTrigger.tsx b/webapp/packages/core-blocks/src/MenuPanel/MenuTrigger.tsx index 202da37c2e..2268f7c373 100644 --- a/webapp/packages/core-blocks/src/MenuPanel/MenuTrigger.tsx +++ b/webapp/packages/core-blocks/src/MenuPanel/MenuTrigger.tsx @@ -9,15 +9,14 @@ import { computed } from 'mobx'; import { observer } from 'mobx-react-lite'; import React, { ButtonHTMLAttributes, forwardRef, useCallback, useEffect, useMemo } from 'react'; import { Menu, MenuButton, MenuInitialState, MenuItem, MenuItemCheckbox, MenuItemRadio, MenuStateReturn, useMenuState } from 'reakit/Menu'; -import styled, { use } from 'reshadow'; import type { IMenuItem, IMenuPanel } from '@cloudbeaver/core-dialogs'; -import type { ComponentStyle } from '@cloudbeaver/core-theming'; +import { s } from '../s'; import { useObjectRef } from '../useObjectRef'; -import { useStyles } from '../useStyles'; +import { useS } from '../useS'; import { MenuPanelItem } from './MenuPanelItem'; -import { menuPanelStyles } from './menuPanelStyles'; +import MenuPanelItemAndTriggerStyles from './shared/MenuPanelItemAndTrigger.m.css'; export type MenuState = MenuStateReturn; @@ -26,7 +25,6 @@ export type MenuState = MenuStateReturn; */ interface IMenuTriggerBaseProps extends Omit, 'style'> { - style?: ComponentStyle; menuRef?: React.RefObject; disclosure?: boolean; placement?: MenuInitialState['placement']; @@ -44,15 +42,16 @@ interface IMenuTriggerLazyProps extends IMenuTriggerBaseProps { interface IMenuTriggerProps extends IMenuTriggerBaseProps { panel: IMenuPanel; getPanel?: () => IMenuPanel; + className?: string; } export const MenuTrigger = React.forwardRef, IMenuTriggerProps | IMenuTriggerLazyProps>(function MenuTrigger( - { panel, menuRef, getPanel, disclosure, children, style, placement, visible, onVisibleSwitch, modal, rtl, ...props }, + { panel, menuRef, getPanel, disclosure, className, children, placement, visible, onVisibleSwitch, modal, rtl, ...props }, ref, ) { const propsRef = useObjectRef({ onVisibleSwitch, visible }); const menu = useMenuState({ modal, placement, visible, rtl }); - const styles = useStyles(menuPanelStyles, style); + const style = useS(MenuPanelItemAndTriggerStyles); if (menuRef) { //@ts-expect-error ref mutation @@ -73,22 +72,22 @@ export const MenuTrigger = React.forwardRef, IMenuTrig if (React.isValidElement(children) && disclosure) { return ( - <> - +
+ {disclosureProps => React.cloneElement(children, disclosureProps)} - {panel && } - + {panel && } +
); } - return styled(styles)( - <> - - {children} + return ( +
+ +
{children}
- {panel && } - , + {panel && } +
); }); @@ -102,24 +101,22 @@ interface MenuPanelProps { panelAvailable?: boolean; onItemClose?: () => void; rtl?: boolean; - style?: ComponentStyle; } -const MenuPanel = observer(function MenuPanel({ panel, menu, panelAvailable, rtl, onItemClose, style }) { - const styles = useStyles(menuPanelStyles, style); - +const MenuPanel = observer(function MenuPanel({ panel, menu, panelAvailable, rtl, onItemClose }) { + const style = useS(MenuPanelItemAndTriggerStyles); if (!menu.visible) { return null; } - return styled(styles)( - - + return ( + +
{panel.menuItems.map(item => ( - + ))} - -
, + +
); }); @@ -131,11 +128,10 @@ interface IMenuPanelElementProps extends Omit, ' item: IMenuItem; menu: MenuStateReturn; // from reakit useMenuState onItemClose?: () => void; - style?: ComponentStyle; } -const MenuPanelElement = observer(function MenuPanelElement({ item, menu, onItemClose, style }) { - const styles = useStyles(menuPanelStyles, style); +const MenuPanelElement = observer(function MenuPanelElement({ item, menu, onItemClose }) { + const style = useS(MenuPanelItemAndTriggerStyles); const onClick = useCallback(() => { if (item.onClick) { item.onClick(); @@ -152,26 +148,25 @@ const MenuPanelElement = observer(function MenuPanelElem } if (item.panel) { - return styled(styles)( + return ( , + /> ); } if (item.type === 'radio') { - return styled(styles)( + return ( (function MenuPanelElem checked={item.isChecked} onClick={onClick} > - - , + + ); } if (item.type === 'checkbox') { - return styled(styles)( + return ( (function MenuPanelElem checked={item.isChecked} onClick={onClick} > - - , + + ); } - return styled(styles)( - - - , + return ( + + + ); }); @@ -215,13 +216,13 @@ const MenuPanelElement = observer(function MenuPanelElem interface IMenuInnerTriggerProps extends Omit, 'style'> { menuItem: IMenuItem; onItemClose?: () => void; - style?: ComponentStyle; } export const MenuInnerTrigger = observer( forwardRef(function MenuInnerTrigger(props, ref) { - const { menuItem, style, onItemClose, ...rest } = props; + const { menuItem, onItemClose, ...rest } = props; const menu = useMenuState(); + const style = useS(MenuPanelItemAndTriggerStyles); const handleItemClose = useCallback(() => { menu.hide(); @@ -232,17 +233,17 @@ export const MenuInnerTrigger = observer - - - - - +
+ +
+ +
- - - , +
+ + ); }), ); diff --git a/webapp/packages/core-blocks/src/MenuPanel/menuPanelStyles.ts b/webapp/packages/core-blocks/src/MenuPanel/menuPanelStyles.ts deleted file mode 100644 index dc3beb8c31..0000000000 --- a/webapp/packages/core-blocks/src/MenuPanel/menuPanelStyles.ts +++ /dev/null @@ -1,120 +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 menuPanelStyles = css` - menu-box { - composes: theme-background-surface theme-text-on-surface from global; - } - MenuItem, - MenuItemCheckbox, - MenuItemRadio, - MenuButton { - composes: theme-ripple from global; - } - MenuItemElement { - composes: theme-ripple from global; - } - menu-panel-item { - composes: theme-border-color-background from global; - } - MenuButton { - background: none; - border: none; - outline: none !important; - color: inherit; - cursor: pointer; - & box { - display: flex; - align-items: center; - flex: 1; - height: inherit; - } - } - Menu { - outline: none; - z-index: 999; - } - menu-box { - composes: theme-typography--body2 theme-elevation-z5 from global; - min-width: 140px; - padding: 12px 0; - - & menu-box { - margin-top: -12px; - } - } - menu-box, - menu-panel-button-wrapper { - display: flex; - flex-direction: column; - } - MenuItem, - MenuItemCheckbox, - MenuItemRadio { - display: flex; - align-items: center; - border: none; - padding: 0; - background: none; - text-align: left; - outline: none; - color: inherit; - cursor: pointer; - white-space: nowrap; - - &[use|hidden] { - display: none; - } - - &:hover, - &:global([aria-expanded='true']) { - & Icon { - opacity: 1; - } - } - } - - menu-panel-item { - flex: 1; - display: flex; - align-items: center; - height: 30px; - padding: 0 4px; - &[|separator] { - border-bottom: 1px solid; - } - & menu-item-text { - display: block; - padding: 0 4px; - flex: 1; - } - & menu-item-content { - width: 24px; - height: 24px; - overflow: hidden; - display: flex; - align-items: center; - justify-content: center; - } - & Icon { - width: 16px; - height: 16px; - opacity: 0.5; - transform: rotate(-90deg); - } - & IconOrImage { - width: 16px; - height: 16px; - object-fit: contain; - } - & Loader { - width: 16px; - } - } -`; diff --git a/webapp/packages/core-blocks/src/MenuPanel/shared/MenuPanelItemAndTrigger.m.css b/webapp/packages/core-blocks/src/MenuPanel/shared/MenuPanelItemAndTrigger.m.css new file mode 100644 index 0000000000..fb7766696a --- /dev/null +++ b/webapp/packages/core-blocks/src/MenuPanel/shared/MenuPanelItemAndTrigger.m.css @@ -0,0 +1,120 @@ +/* + * 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. + */ + +.menuBox { + composes: theme-background-surface theme-text-on-surface from global; +} + +.menuItem, +.menuItemCheckbox, +.menuItemRadio { + composes: theme-ripple from global; +} +.menuItemElement { + composes: theme-ripple from global; +} +.menuPanelItem { + composes: theme-border-color-background from global; +} +.box { + display: flex; + align-items: center; + flex: 1; + height: inherit; +} + +.menuButton { + background: none; + border: none; + outline: none !important; + color: inherit; + cursor: pointer; +} + +.menu { + outline: none; + z-index: 999; +} + +.menuBox { + composes: theme-typography--body2 theme-elevation-z5 from global; + min-width: 140px; + padding: 12px 0; + & .menuBox { + margin-top: -12px; + } +} +.menuBox, +.menuPanelButtonWrapper { + display: flex; + flex-direction: column; +} + +.menuItem, +.menuItemCheckbox, +.menuItemRadio { + display: flex; + align-items: center; + border: none; + padding: 0; + background: none; + text-align: left; + outline: none; + color: inherit; + cursor: pointer; + white-space: nowrap; + &.use, + &.hidden { + display: none; + } + &:hover, + &:global([aria-expanded='true']) { + & .icon { + opacity: 1; + } + } +} +.menuPanelItem { + flex: 1; + display: flex; + align-items: center; + height: 30px; + padding: 0 4px; + &.separator { + border-bottom: 1px solid; + } + & .menuItemText { + display: block; + padding: 0 4px; + flex: 1; + } + & .menuItemContent { + width: 24px; + height: 24px; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; + } + & .icon { + width: 16px; + height: 16px; + opacity: 0.5; + transform: rotate(-90deg); + } + & .iconOrImage { + width: 16px; + height: 16px; + object-fit: contain; + } + & .loader { + width: 16px; + } +} +.menuTrigger { +} diff --git a/webapp/packages/core-blocks/src/Slide/SlideBox.tsx b/webapp/packages/core-blocks/src/Slide/SlideBox.tsx index 0cca666c0d..03d44ce4f6 100644 --- a/webapp/packages/core-blocks/src/Slide/SlideBox.tsx +++ b/webapp/packages/core-blocks/src/Slide/SlideBox.tsx @@ -49,7 +49,7 @@ export const SlideBox = observer(function SlideBox({ children, open, clas return (
{children}
diff --git a/webapp/packages/core-blocks/src/Slide/SlideBoxStyles.ts b/webapp/packages/core-blocks/src/Slide/SlideBoxStyles.ts deleted file mode 100644 index 238f1e777c..0000000000 --- a/webapp/packages/core-blocks/src/Slide/SlideBoxStyles.ts +++ /dev/null @@ -1,62 +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 slideBoxStyles = css` - SlideBox { - overflow: hidden; - white-space: nowrap; - - & SlideElement { - width: 100%; - height: 100%; - display: inline-block; - vertical-align: top; - white-space: normal; - transition: transform cubic-bezier(0.4, 0, 0.2, 1) 0.6s; - transform: translateX(-100%); - - &:first-child { - transition: width cubic-bezier(0.4, 0, 0.2, 1) 0.6s; - width: 100%; - } - } - - & SlideOverlay { - position: absolute; - cursor: pointer; - display: flex; - align-items: center; - width: 0; - height: 0; - top: 0; - left: 0; - background: rgb(0 0 0 / 0%); - transition: background cubic-bezier(0.4, 0, 0.2, 1) 0.6s; - } - - &[open] { - & SlideOverlay { - width: 100%; - height: 100%; - background: rgb(0 0 0 / 35%); - - & > :global(div) { - display: flex; - } - } - & SlideElement { - transform: translateX(0%); - - &:first-child { - width: calc(100% - 120px); - } - } - } - } -`; diff --git a/webapp/packages/core-blocks/src/index.ts b/webapp/packages/core-blocks/src/index.ts index 297f3307df..3c6631de88 100644 --- a/webapp/packages/core-blocks/src/index.ts +++ b/webapp/packages/core-blocks/src/index.ts @@ -47,6 +47,7 @@ export * from './Menu/MenuBarSmallItem'; export * from './Menu/MenuEmptyItem'; export * from './Menu/MenuItem'; export { default as MenuItemStyles } from './Menu/MenuItem.m.css'; +export { default as MenuPanelItemAndTriggerStyles } from './MenuPanel/shared/MenuPanelItemAndTrigger.m.css'; export * from './Menu/MenuItemCheckbox'; export * from './Menu/MenuItemElement'; export { default as MenuItemElementStyles } from './Menu/MenuItemElement.m.css'; @@ -79,7 +80,6 @@ export * from './PropertiesTable/IProperty'; export * from './Slide/SlideBox'; export * from './Slide/SlideElement'; export * from './Slide/SlideOverlay'; -export { default as SlideBoxStyles } from './Slide/SlideBox.m.css'; export * from './Split/SplitControls'; export * from './Split/Pane'; diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/Formatters/Menu/CellMenu.m.css b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/Formatters/Menu/CellMenu.m.css new file mode 100644 index 0000000000..7ad2141da9 --- /dev/null +++ b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/Formatters/Menu/CellMenu.m.css @@ -0,0 +1,39 @@ +/* + * 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. + */ + +.iconOrImage { + composes: theme-text-primary from global; +} +:global(.rdg-cell):not(:global([aria-selected='true'])):not(:hover) .cellMenu { + display: none; +} +.cellMenu { + flex: 0 0 auto; + height: var(--rdg-row-height); + position: absolute; + top: 0px; + right: 0px; +} +.menuTrigger { + padding: 1px 2px; + height: 100%; + + &:hover { + background: none; + } + + &:before { + display: none; + } + + & .icon { + cursor: pointer; + width: 16px; + height: 10px; + } +} diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/Formatters/Menu/CellMenu.tsx b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/Formatters/Menu/CellMenu.tsx index 169072a322..cc88d1bf3b 100644 --- a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/Formatters/Menu/CellMenu.tsx +++ b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/Formatters/Menu/CellMenu.tsx @@ -6,15 +6,14 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled from 'reshadow'; -import { Icon, MenuTrigger } from '@cloudbeaver/core-blocks'; +import { Icon, MenuPanelItemAndTriggerStyles, MenuTrigger, s, SContext, StyleRegistry, useS } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { EventContext, EventStopPropagationFlag } from '@cloudbeaver/core-events'; import type { IDatabaseDataModel, IDataPresentationActions, IDataTableActions, IResultSetElementKey } from '@cloudbeaver/plugin-data-viewer'; import { DataGridContextMenuService } from '../../DataGridContextMenu/DataGridContextMenuService'; -import { cellMenuStyles } from './cellMenuStyles'; +import styles from './CellMenu.m.css'; interface Props { model: IDatabaseDataModel; @@ -27,6 +26,16 @@ interface Props { onStateSwitch?: (state: boolean) => void; } +const registry: StyleRegistry = [ + [ + MenuPanelItemAndTriggerStyles, + { + mode: 'append', + styles: [styles], + }, + ], +]; + export const CellMenu = observer(function CellMenu({ model, actions, @@ -37,6 +46,7 @@ export const CellMenu = observer(function CellMenu({ onClick, onStateSwitch, }) { + const style = useS(styles); const dataGridContextMenuService = useService(DataGridContextMenuService); const panel = dataGridContextMenuService.constructMenuWithContext(model, actions, spreadsheetActions, resultIndex, cellKey, simple); @@ -58,11 +68,13 @@ export const CellMenu = observer(function CellMenu({ EventContext.set(event, EventStopPropagationFlag); } - return styled(cellMenuStyles)( - - - - - , + return ( + +
+ + + +
+
); }); diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/Formatters/Menu/cellMenuStyles.ts b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/Formatters/Menu/cellMenuStyles.ts deleted file mode 100644 index 239c64f937..0000000000 --- a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/Formatters/Menu/cellMenuStyles.ts +++ /dev/null @@ -1,38 +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 cellMenuStyles = css` - IconOrImage { - composes: theme-text-primary from global; - } - :global(.rdg-cell):not(:global([aria-selected='true'])):not(:hover) cell-menu { - display: none; - } - cell-menu { - flex: 0 0 auto; - height: var(--rdg-row-height); - position: absolute; - top: 0px; - right: 0px; - } - MenuTrigger { - padding: 0 8px; - height: 100%; - - &:before { - display: none; - } - - & Icon { - cursor: pointer; - width: 16px; - height: 10px; - } - } -`; diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuItem.m.css b/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuItem.m.css new file mode 100644 index 0000000000..48856c38ff --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuItem.m.css @@ -0,0 +1,35 @@ +/* + * 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. + */ + +.menu { + composes: theme-text-on-surface from global; +} +.menuTrigger { + composes: theme-ripple from global; + height: 100%; + padding: 0 12px; + display: flex; + align-items: center; + cursor: pointer; + &.hidden { + display: none; + } +} +.toolsAction.hidden { + display: none; +} +.menuTriggerIcon .iconOrImage { + display: block; + width: 16px; +} +.menuTriggerTitle { + display: block; +} +.menuTriggerIcon + .menuTriggerTitle { + padding-left: 8px; +} diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuItem.tsx b/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuItem.tsx index ee6370c34c..9c13fd5dea 100644 --- a/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuItem.tsx +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuItem.tsx @@ -7,80 +7,75 @@ */ import { observer } from 'mobx-react-lite'; import type { ButtonHTMLAttributes } from 'react'; -import styled, { css, use } from 'reshadow'; -import { IconOrImage, MenuTrigger, ToolsAction, useTranslate } from '@cloudbeaver/core-blocks'; +import { + IconOrImage, + MenuPanelItemAndTriggerStyles, + MenuTrigger, + s, + SContext, + StyleRegistry, + ToolsAction, + useS, + useTranslate, +} from '@cloudbeaver/core-blocks'; import type { IMenuItem } from '@cloudbeaver/core-dialogs'; +import styles from './TableFooterMenuItem.m.css'; + type Props = ButtonHTMLAttributes & { menuItem: IMenuItem; }; -export const tableFooterMenuStyles = css` - Menu { - composes: theme-text-on-surface from global; - } - MenuTrigger { - composes: theme-ripple from global; - height: 100%; - padding: 0 12px; - display: flex; - align-items: center; - cursor: pointer; - &[|hidden] { - display: none; - } - } - ToolsAction[|hidden] { - display: none; - } - menu-trigger-icon IconOrImage { - display: block; - width: 16px; - } - menu-trigger-title { - display: block; - } - menu-trigger-icon + menu-trigger-title { - padding-left: 8px; - } -`; +const registry: StyleRegistry = [ + [ + MenuPanelItemAndTriggerStyles, + { + mode: 'append', + styles: [styles], + }, + ], +]; export const TableFooterMenuItem = observer(function TableFooterMenuItem({ menuItem, ...props }) { const translate = useTranslate(); + const style = useS(styles); if (!menuItem.panel) { - return styled(tableFooterMenuStyles)( - menuItem.onClick?.()} - > - {translate(menuItem.title)} - , + return ( + + menuItem.onClick?.()} + > + {translate(menuItem.title)} + + ); } - return styled(tableFooterMenuStyles)( - - {menuItem.icon && ( - - - - )} - {menuItem.title && {translate(menuItem.title)}} - , + return ( + + + {menuItem.icon && ( +
+ +
+ )} + {menuItem.title &&
{translate(menuItem.title)}
} +
+
); }); diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TotalCountAction.tsx b/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TotalCountAction.tsx index 7a4259728d..825efd97db 100644 --- a/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TotalCountAction.tsx +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TotalCountAction.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 { getComputed, ToolsAction, useTranslate } from '@cloudbeaver/core-blocks'; +import { getComputed, s, ToolsAction, useS, useTranslate } from '@cloudbeaver/core-blocks'; import type { IDatabaseDataModel } from '../../DatabaseDataModel/IDatabaseDataModel'; import type { IDatabaseResultSet } from '../../DatabaseDataModel/IDatabaseResultSet'; -import { tableFooterMenuStyles } from './TableFooterMenu/TableFooterMenuItem'; +import TableFooterMenuStyles from './TableFooterMenu/TableFooterMenuItem.m.css'; import classes from './TableFooterRowCount.m.css'; interface Props { @@ -26,6 +25,7 @@ export const TotalCountAction = observer(function TotalCountAction({ onCl const result = model.getResult(resultIndex); const translate = useTranslate(); const disabled = getComputed(() => model.isLoading() || model.isDisabled(resultIndex)); + const style = useS(TableFooterMenuStyles, classes); if (!result) { return null; @@ -34,11 +34,18 @@ export const TotalCountAction = observer(function TotalCountAction({ onCl const currentCount = result.loadedFully ? result.count : `${result.count}+`; const count = result.totalCount ?? currentCount; - return styled(tableFooterMenuStyles)( -
- + return ( +
+ {count} -
, +
); });