diff --git a/.gitignore b/.gitignore index d7bb8fd4309..d48a3f09d0a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .vscode .DS_Store *.code-workspace +*.orig node_modules yarn-debug.log diff --git a/packages/react-ui/.styleguide/components/StyleGuideWrapper/StyleGuideWrapper.styles.ts b/packages/react-ui/.styleguide/components/StyleGuideWrapper/StyleGuideWrapper.styles.ts index 8f3715c1251..82063abe2e4 100644 --- a/packages/react-ui/.styleguide/components/StyleGuideWrapper/StyleGuideWrapper.styles.ts +++ b/packages/react-ui/.styleguide/components/StyleGuideWrapper/StyleGuideWrapper.styles.ts @@ -1,9 +1,11 @@ -import { css, memoizeStyle } from '../../../lib/theming/Emotion'; +import { memoizeStyle } from '../../../lib/theming/Emotion'; import { Theme } from '../../../lib/theming/Theme'; +import type { Emotion } from '@emotion/css/create-instance'; -export const styles = memoizeStyle({ - root() { - return css` +export const getStyles = (emotion: Emotion) => + memoizeStyle({ + root() { + return emotion.css` font-weight: 400; font-size: 14px; padding-left: 300px; @@ -41,15 +43,15 @@ export const styles = memoizeStyle({ } } `; - }, - darkRoot(t: Theme) { - return css` + }, + darkRoot(t: Theme) { + return emotion.css` background: ${t.bgDefault}; color: ${t.textColorDefault}; `; - }, - wrapper() { - return css` + }, + wrapper() { + return emotion.css` padding: 30px 40px; margin: 0 auto; max-width: 1000px; @@ -59,12 +61,12 @@ export const styles = memoizeStyle({ padding: 16px; } `; - }, - content() { - return css``; - }, - darkContent(t: Theme) { - return css` + }, + content() { + return emotion.css``; + }, + darkContent(t: Theme) { + return emotion.css` h1, h2, h3, @@ -126,14 +128,14 @@ export const styles = memoizeStyle({ border: 1px solid #444; } `; - }, - header() { - return css` + }, + header() { + return emotion.css` padding: 40px 40px 0 !important; `; - }, - sidebar() { - return css` + }, + sidebar() { + return emotion.css` width: 300px; background: #41464e; font-size: 16px; @@ -165,9 +167,9 @@ export const styles = memoizeStyle({ font-weight: normal; } `; - }, - footer() { - return css` + }, + footer() { + return emotion.css` position: fixed; top: 0; right: 0; @@ -175,9 +177,9 @@ export const styles = memoizeStyle({ height: 149px; z-index: 999; `; - }, - footerLink() { - return css` + }, + footerLink() { + return emotion.css` position: relative; right: -37px; top: -22px; @@ -194,5 +196,5 @@ export const styles = memoizeStyle({ transform: rotate(45deg); cursor: pointer; `; - }, -}); + }, + }); diff --git a/packages/react-ui/.styleguide/components/StyleGuideWrapper/StyleGuideWrapper.tsx b/packages/react-ui/.styleguide/components/StyleGuideWrapper/StyleGuideWrapper.tsx index ad7826ab05b..9c02eddf0e6 100644 --- a/packages/react-ui/.styleguide/components/StyleGuideWrapper/StyleGuideWrapper.tsx +++ b/packages/react-ui/.styleguide/components/StyleGuideWrapper/StyleGuideWrapper.tsx @@ -2,8 +2,8 @@ import React, { useState } from 'react'; import ThemeSwitcher from '../ThemeSwitcher/ThemeSwitcher'; import Context from 'react-styleguidist/lib/client/rsg-components/Context'; import { useStyleGuideContext } from 'react-styleguidist/lib/client/rsg-components/Context/Context'; -import { cx } from '../../../lib/theming/Emotion'; -import { styles } from './StyleGuideWrapper.styles'; +import { useEmotion } from '../../../lib/theming/Emotion'; +import { getStyles } from './StyleGuideWrapper.styles'; import { DARK_THEME } from '../../../lib/theming/themes/DarkTheme'; import { DEFAULT_THEME_WRAPPER } from '../ThemeSwitcher/constants'; @@ -16,6 +16,7 @@ interface StyleGuideRendererProps { } function StyleGuideRenderer({ children, hasSidebar, toc, title, version }: StyleGuideRendererProps) { + const emotion = useEmotion(); const { codeRevision, config, slots, displayMode, cssRevision } = useStyleGuideContext(); const [theme, setTheme] = useState(DEFAULT_THEME_WRAPPER); document.body.style.fontFamily = 'Lab Grotesque, Roboto, Helvetica Neue, Arial, sans-serif'; @@ -31,11 +32,15 @@ function StyleGuideRenderer({ children, hasSidebar, toc, title, version }: Style root.style.height = '100%'; } } + + const styles = getStyles(emotion); return ( -
+
-
{children}
+
+ {children} +
{hasSidebar && (
diff --git a/packages/react-ui/components/Autocomplete/Autocomplete.styles.ts b/packages/react-ui/components/Autocomplete/Autocomplete.styles.ts index de2c5f1f8a1..3554cdddf92 100644 --- a/packages/react-ui/components/Autocomplete/Autocomplete.styles.ts +++ b/packages/react-ui/components/Autocomplete/Autocomplete.styles.ts @@ -1,16 +1,20 @@ -import { css, memoizeStyle } from '../../lib/theming/Emotion'; +import type { Emotion } from '@emotion/css/create-instance'; + +import { memoizeStyle } from '../../lib/theming/Emotion'; import { Theme } from '../../lib/theming/Theme'; -export const styles = memoizeStyle({ - root(t: Theme) { - return css` - display: inline-block; - width: ${t.inputWidth}; - `; - }, - noPortal() { - return css` +export const getStyles = (emotion: Emotion) => + memoizeStyle({ + root(t: Theme) { + return emotion.css` + display: inline-block; + width: ${t.inputWidth}; + `; + }, + + noPortal() { + return emotion.css` position: relative; `; - }, -}); + }, + }); diff --git a/packages/react-ui/components/Autocomplete/Autocomplete.tsx b/packages/react-ui/components/Autocomplete/Autocomplete.tsx index 5a117c23f9a..bd629acced1 100644 --- a/packages/react-ui/components/Autocomplete/Autocomplete.tsx +++ b/packages/react-ui/components/Autocomplete/Autocomplete.tsx @@ -2,11 +2,11 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import React, { AriaAttributes, KeyboardEvent } from 'react'; import PropTypes from 'prop-types'; +import type { Emotion } from '@emotion/css/create-instance'; import { MenuMessage } from '../../internal/MenuMessage'; import { locale } from '../../lib/locale/decorators'; import { getRandomID, isNullable } from '../../lib/utils'; -import { ThemeContext } from '../../lib/theming/ThemeContext'; import { Theme } from '../../lib/theming/Theme'; import { cx } from '../../lib/theming/Emotion'; import { isKeyArrowDown, isKeyArrowUp, isKeyEnter, isKeyEscape } from '../../lib/events/keyboard/identifiers'; @@ -24,10 +24,12 @@ import { responsiveLayout } from '../ResponsiveLayout/decorator'; import { getRootNode, rootNode, TSetRootNode } from '../../lib/rootNode'; import { getDOMRect } from '../../lib/dom/getDOMRect'; import { SizeProp } from '../../lib/types/props'; +import { EmotionConsumer } from '../../lib/theming/Emotion'; +import { ThemeContext } from '../../lib/theming/ThemeContext'; -import { styles } from './Autocomplete.styles'; import { AutocompleteLocale, AutocompleteLocaleHelper } from './locale'; import { getAutocompleteTheme } from './getAutocompleteTheme'; +import { getStyles } from './Autocomplete.styles'; function match(pattern: string, items: string[]) { if (!pattern || !items) { @@ -160,6 +162,7 @@ export class Autocomplete extends React.Component - {(theme) => { - this.theme = getAutocompleteTheme(theme); + + {(emotion) => { + this.emotion = emotion; return ( - - - {this.renderMain} - - + + {(theme) => { + this.theme = getAutocompleteTheme(theme); + return ( + + + {this.renderMain} + + + ); + }} + ); }} - + ); } public renderMain = (props: CommonWrapperRestProps) => { @@ -246,6 +256,7 @@ export class Autocomplete extends React.Component { - const hasGradient = btnBackgroundStart !== btnBackgroundEnd; - return css` +export const buttonUseMixin = + (emotion: Emotion) => + ( + btnBackground: string, + btnBackgroundStart: string, + btnBackgroundEnd: string, + color: string, + borderColor: string, + borderBottomColor: string, + borderWidth: string, + ) => { + const hasGradient = btnBackgroundStart !== btnBackgroundEnd; + return emotion.css` background-color: ${hasGradient ? `initial` : btnBackground}; background-image: ${hasGradient ? `linear-gradient(${btnBackgroundStart}, ${btnBackgroundEnd})` : `none`}; color: ${color}; - box-shadow: 0 0 0 ${borderWidth} ${borderColor}${borderBottomColor ? `, 0 ${borderWidth} 0 0 ${borderBottomColor}` : ``}; + box-shadow: 0 0 0 ${borderWidth} ${borderColor}${ + borderBottomColor ? `, 0 ${borderWidth} 0 0 ${borderBottomColor}` : `` + }; .${globalClasses.arrowHelper} { box-shadow: ${borderWidth} 0 0 0 ${borderColor}; @@ -55,44 +60,52 @@ export const buttonUseMixin = ( } } `; -}; + }; -export const buttonHoverMixin = ( - btnBackground: string, - btnBackgroundStart: string, - btnBackgroundEnd: string, - color: string, - borderColor: string, - borderBottomColor: string, - borderWidth: string, -) => { - const hasGradient = btnBackgroundStart !== btnBackgroundEnd; - return css` +export const buttonHoverMixin = + (emotion: Emotion) => + ( + btnBackground: string, + btnBackgroundStart: string, + btnBackgroundEnd: string, + color: string, + borderColor: string, + borderBottomColor: string, + borderWidth: string, + ) => { + const hasGradient = btnBackgroundStart !== btnBackgroundEnd; + return emotion.css` background-color: ${hasGradient ? `initial` : btnBackground}; background-image: ${hasGradient ? `linear-gradient(${btnBackgroundStart}, ${btnBackgroundEnd})` : `none`}; - box-shadow: 0 0 0 ${borderWidth} ${borderColor}${borderBottomColor ? `, 0 ${borderWidth} 0 0 ${borderBottomColor}` : ``}; + box-shadow: 0 0 0 ${borderWidth} ${borderColor}${ + borderBottomColor ? `, 0 ${borderWidth} 0 0 ${borderBottomColor}` : `` + }; color: ${color}; .${globalClasses.arrowHelper} { box-shadow: ${borderWidth} 0 0 ${borderColor}; } `; -}; + }; -export const buttonActiveMixin = ( - btnBackground: string, - btnShadow: string, - borderColor: string, - borderTopColor: string, - borderWidth: string, - arrowBgImage: string, -) => { - return css` +export const buttonActiveMixin = + (emotion: Emotion) => + ( + btnBackground: string, + btnShadow: string, + borderColor: string, + borderTopColor: string, + borderWidth: string, + arrowBgImage: string, + ) => { + return emotion.css` &, &:hover { background-image: none !important; // override :hover styles background-color: ${btnBackground} !important; // override :hover styles - box-shadow: 0 0 0 ${borderWidth} ${borderColor}${borderTopColor ? `, 0 -${borderWidth} 0 0 ${borderTopColor}` : ``} !important; // override :hover styles + box-shadow: 0 0 0 ${borderWidth} ${borderColor}${ + borderTopColor ? `, 0 -${borderWidth} 0 0 ${borderTopColor}` : `` + } !important; // override :hover styles .${globalClasses.innerShadow} { box-shadow: ${btnShadow}; @@ -107,42 +120,30 @@ export const buttonActiveMixin = ( } } `; -}; + }; -export const buttonSizeMixin = ( - fontSize: string, - lineHeight: string, - paddingX: string, - paddingY: string, - fontFamilyCompensation: string, -) => { - return css` +export const buttonSizeMixin = + (emotion: Emotion) => + (fontSize: string, lineHeight: string, paddingX: string, paddingY: string, fontFamilyCompensation: string) => { + return emotion.css` font-size: ${fontSize}; box-sizing: border-box; padding: ${getBtnPadding(fontSize, paddingY, paddingX, fontFamilyCompensation)}; line-height: ${lineHeight}; `; -}; + }; -export const buttonSizeMixinIE11 = ( - fontSize: string, - paddingX: string, - paddingY: string, - fontFamilyCompensation: string, -) => { - return css` +export const buttonSizeMixinIE11 = + (emotion: Emotion) => (fontSize: string, paddingX: string, paddingY: string, fontFamilyCompensation: string) => { + return emotion.css` padding: ${getBtnPadding(fontSize, paddingY, paddingX, fontFamilyCompensation, 1)}; line-height: normal; `; -}; + }; -export const arrowOutlineMixin = ( - insetWidth: string, - outlineColor: string, - outlineWidth: string, - insetColor: string, -) => { - return css` +export const arrowOutlineMixin = + (emotion: Emotion) => (insetWidth: string, outlineColor: string, outlineWidth: string, insetColor: string) => { + return emotion.css` .${globalClasses.arrowHelper} { &.${globalClasses.arrowHelperTop} { box-shadow: inset -${insetWidth} ${insetWidth} 0 0 ${insetColor}, ${outlineWidth} 0 0 0 ${outlineColor} !important; // override :active styles @@ -164,4 +165,4 @@ export const arrowOutlineMixin = ( } } `; -}; + }; diff --git a/packages/react-ui/components/Button/Button.styles.ts b/packages/react-ui/components/Button/Button.styles.ts index 6ce07792a3a..0518cea7762 100644 --- a/packages/react-ui/components/Button/Button.styles.ts +++ b/packages/react-ui/components/Button/Button.styles.ts @@ -1,15 +1,17 @@ -import { css, memoizeStyle, prefix } from '../../lib/theming/Emotion'; +import type { Emotion } from '@emotion/css/create-instance'; + +import { memoizeStyle, prefix } from '../../lib/theming/Emotion'; import { Theme } from '../../lib/theming/Theme'; import { resetButton, resetText } from '../../lib/styles/Mixins'; import { isFirefox } from '../../lib/client'; import { - buttonUseMixin, - buttonHoverMixin, + arrowOutlineMixin, buttonActiveMixin, + buttonHoverMixin, buttonSizeMixin, - arrowOutlineMixin, buttonSizeMixinIE11, + buttonUseMixin, } from './Button.mixins'; export const globalClasses = prefix('button')({ @@ -23,11 +25,12 @@ export const globalClasses = prefix('button')({ innerShadow: 'inner-shadow', }); -export const styles = memoizeStyle({ - root(t: Theme) { - return css` - ${resetButton()}; - ${resetText()}; +export const getStyles = (emotion: Emotion) => + memoizeStyle({ + root(t: Theme) { + return emotion.css` + ${resetButton(emotion)}; + ${resetText(emotion)}; transition: background-color ${t.transitionDuration} ${t.transitionTimingFunction} ${t.btnBorderColorTransition ? `, ${t.btnBorderColorTransition}` : ''}; @@ -74,58 +77,58 @@ export const styles = memoizeStyle({ color: ${t.btnIconColor}; } `; - }, + }, - withArrowIconRightSmall(t: Theme) { - return css` + withArrowIconRightSmall(t: Theme) { + return emotion.css` padding-right: calc(${t.btnIconSizeSmall} + ${t.btnWithIconPaddingLeftSmall} + ${t.btnWithIconPaddingLeftSmall}); `; - }, + }, - withArrowIconRightMedium(t: Theme) { - return css` + withArrowIconRightMedium(t: Theme) { + return emotion.css` padding-right: calc( ${t.btnIconSizeMedium} + ${t.btnWithIconPaddingLeftMedium} + ${t.btnWithIconPaddingLeftMedium} ); `; - }, + }, - withArrowIconRightLarge(t: Theme) { - return css` + withArrowIconRightLarge(t: Theme) { + return emotion.css` padding-right: calc(${t.btnIconSizeLarge} + ${t.btnWithIconPaddingLeftLarge} + ${t.btnWithIconPaddingLeftLarge}); `; - }, + }, - withArrowIconLeftSmall(t: Theme) { - return css` + withArrowIconLeftSmall(t: Theme) { + return emotion.css` padding-left: calc(${t.btnIconSizeSmall} + ${t.btnWithIconPaddingLeftSmall} + ${t.btnWithIconPaddingLeftSmall}); `; - }, + }, - withArrowIconLeftMedium(t: Theme) { - return css` + withArrowIconLeftMedium(t: Theme) { + return emotion.css` padding-left: calc( ${t.btnIconSizeMedium} + ${t.btnWithIconPaddingLeftMedium} + ${t.btnWithIconPaddingLeftMedium} ); `; - }, + }, - withArrowIconLeftLarge(t: Theme) { - return css` + withArrowIconLeftLarge(t: Theme) { + return emotion.css` padding-left: calc(${t.btnIconSizeLarge} + ${t.btnWithIconPaddingLeftLarge} + ${t.btnWithIconPaddingLeftLarge}); `; - }, + }, - simulatedPress() { - return css` + simulatedPress() { + return emotion.css` &:active .${globalClasses.caption} { transform: translateY(1px); } `; - }, + }, - outline() { - return css` + outline() { + return emotion.css` border-radius: inherit; position: absolute; top: 0; @@ -133,48 +136,48 @@ export const styles = memoizeStyle({ left: 0; right: 0; `; - }, + }, - outlineWarning(t: Theme) { - return css` + outlineWarning(t: Theme) { + return emotion.css` box-shadow: 0 0 0 ${t.btnOutlineWidth} ${t.btnBorderColorWarning}, inset 0 0 0 ${t.btnInsetWidth} ${t.btnInsetColor}; `; - }, + }, - outlineError(t: Theme) { - return css` + outlineError(t: Theme) { + return emotion.css` box-shadow: 0 0 0 ${t.btnOutlineWidth} ${t.btnBorderColorError}, inset 0 0 0 ${t.btnInsetWidth} ${t.btnInsetColor}; `; - }, + }, - outlineLink() { - return css` + outlineLink() { + return emotion.css` box-shadow: none; left: -2px; right: -2px; bottom: -2px; top: -2px; `; - }, + }, - outlineLinkWarning(t: Theme) { - return css` + outlineLinkWarning(t: Theme) { + return emotion.css` background-color: ${t.btnWarningSecondary}; `; - }, + }, - outlineLinkError(t: Theme) { - return css` + outlineLinkError(t: Theme) { + return emotion.css` background-color: ${t.btnErrorSecondary}; `; - }, + }, - sizeSmall(t: Theme) { - return css` + sizeSmall(t: Theme) { + return emotion.css` border-radius: ${t.btnBorderRadiusSmall}; - ${buttonSizeMixin( + ${buttonSizeMixin(emotion)( t.btnFontSizeSmall, t.btnLineHeightSmall, t.btnPaddingXSmall, @@ -182,24 +185,24 @@ export const styles = memoizeStyle({ t.fontFamilyCompensationBaseline, )}; `; - }, + }, - sizeSmallIE11(t: Theme) { - return css` - ${buttonSizeMixinIE11( + sizeSmallIE11(t: Theme) { + return emotion.css` + ${buttonSizeMixinIE11(emotion)( t.btnFontSizeSmall, t.btnPaddingXSmall, t.btnPaddingYSmall, t.fontFamilyCompensationBaseline, )}; `; - }, + }, - sizeMedium(t: Theme) { - return css` + sizeMedium(t: Theme) { + return emotion.css` border-radius: ${t.btnBorderRadiusMedium}; - ${buttonSizeMixin( + ${buttonSizeMixin(emotion)( t.btnFontSizeMedium, t.btnLineHeightMedium, t.btnPaddingXMedium, @@ -207,24 +210,24 @@ export const styles = memoizeStyle({ t.fontFamilyCompensationBaseline, )}; `; - }, + }, - sizeMediumIE11(t: Theme) { - return css` - ${buttonSizeMixinIE11( + sizeMediumIE11(t: Theme) { + return emotion.css` + ${buttonSizeMixinIE11(emotion)( t.btnFontSizeMedium, t.btnPaddingXMedium, t.btnPaddingYMedium, t.fontFamilyCompensationBaseline, )}; `; - }, + }, - sizeLarge(t: Theme) { - return css` + sizeLarge(t: Theme) { + return emotion.css` border-radius: ${t.btnBorderRadiusLarge}; - ${buttonSizeMixin( + ${buttonSizeMixin(emotion)( t.btnFontSizeLarge, t.btnLineHeightLarge, t.btnPaddingXLarge, @@ -232,57 +235,57 @@ export const styles = memoizeStyle({ t.fontFamilyCompensationBaseline, )}; `; - }, + }, - sizeLargeIE11(t: Theme) { - return css` - ${buttonSizeMixinIE11( + sizeLargeIE11(t: Theme) { + return emotion.css` + ${buttonSizeMixinIE11(emotion)( t.btnFontSizeLarge, t.btnPaddingXLarge, t.btnPaddingYLarge, t.fontFamilyCompensationBaseline, )}; `; - }, + }, - sizeSmallWithIcon(t: Theme) { - return css` + sizeSmallWithIcon(t: Theme) { + return emotion.css` padding-left: ${t.btnWithIconPaddingLeftSmall}; `; - }, + }, - sizeMediumWithIcon(t: Theme) { - return css` + sizeMediumWithIcon(t: Theme) { + return emotion.css` padding-left: ${t.btnWithIconPaddingLeftMedium}; `; - }, + }, - sizeLargeWithIcon(t: Theme) { - return css` + sizeLargeWithIcon(t: Theme) { + return emotion.css` padding-left: ${t.btnWithIconPaddingLeftLarge}; `; - }, + }, - sizeSmallWithIconWithoutText(t: Theme) { - return css` + sizeSmallWithIconWithoutText(t: Theme) { + return emotion.css` padding-right: ${t.btnWithIconPaddingLeftSmall}; `; - }, + }, - sizeMediumWithIconWithoutText(t: Theme) { - return css` + sizeMediumWithIconWithoutText(t: Theme) { + return emotion.css` padding-right: ${t.btnWithIconPaddingLeftMedium}; `; - }, + }, - sizeLargeWithIconWithoutText(t: Theme) { - return css` + sizeLargeWithIconWithoutText(t: Theme) { + return emotion.css` padding-right: ${t.btnWithIconPaddingLeftLarge}; `; - }, + }, - link(t: Theme) { - return css` + link(t: Theme) { + return emotion.css` background: none; border-radius: ${t.btnLinkBorderRadius}; border: none; @@ -301,35 +304,35 @@ export const styles = memoizeStyle({ } &:active:enabled { - ${activeStyles.link(t)} + ${getActiveStyles(emotion).link(t)} } `; - }, + }, - linkLineHeight() { - return css` + linkLineHeight() { + return emotion.css` line-height: inherit !important; // override size mixin `; - }, + }, - linkLineHeightSafariFallback() { - return css` + linkLineHeightSafariFallback() { + return emotion.css` /* Safari overrides 'underline' and 'border' if 'line-height' is used */ margin: -1px 0 -2px; `; - }, + }, - linkFocus(t: Theme) { - return css` + linkFocus(t: Theme) { + return emotion.css` & { color: ${t.btnLinkColor}; text-decoration: ${t.btnLinkHoverTextDecoration}; } `; - }, + }, - linkDisabled(t: Theme) { - return css` + linkDisabled(t: Theme) { + return emotion.css` cursor: default; &, @@ -338,10 +341,10 @@ export const styles = memoizeStyle({ color: ${t.btnLinkDisabledColor}; } `; - }, + }, - focus(t: Theme) { - return css` + focus(t: Theme) { + return emotion.css` position: relative; z-index: 2; @@ -353,10 +356,10 @@ export const styles = memoizeStyle({ 0 0 0 ${t.btnFocusShadowWidth} ${t.btnBorderColorFocus} !important; // override root:hover style } `; - }, + }, - disabled(t: Theme) { - return css` + disabled(t: Theme) { + return emotion.css` cursor: default; box-shadow: 0 0 0 ${t.btnBorderWidth} ${t.btnDisabledBorderColor}; @@ -368,40 +371,40 @@ export const styles = memoizeStyle({ box-shadow: ${t.btnBorderWidth} 0 0 0 ${t.btnDisabledBorderColor}; } `; - }, + }, - disabledWithoutOutline(t: Theme) { - return css` + disabledWithoutOutline(t: Theme) { + return emotion.css` box-shadow: 0 0 0 ${t.btnBorderWidth} ${t.btnDisabledBg}; `; - }, + }, - arrowWarning(t: Theme) { - return css` + arrowWarning(t: Theme) { + return emotion.css` box-shadow: inset 0 0 0 ${t.btnInsetWidth} ${t.btnInsetColor}; - ${arrowOutlineMixin(t.btnInsetWidth, t.btnBorderColorWarning, t.btnOutlineWidth, t.btnInsetColor)} + ${arrowOutlineMixin(emotion)(t.btnInsetWidth, t.btnBorderColorWarning, t.btnOutlineWidth, t.btnInsetColor)} `; - }, + }, - arrowError(t: Theme) { - return css` + arrowError(t: Theme) { + return emotion.css` box-shadow: inset 0 0 0 ${t.btnInsetWidth} ${t.btnInsetColor}; - ${arrowOutlineMixin(t.btnInsetWidth, t.btnBorderColorError, t.btnOutlineWidth, t.btnInsetColor)} + ${arrowOutlineMixin(emotion)(t.btnInsetWidth, t.btnBorderColorError, t.btnOutlineWidth, t.btnInsetColor)} `; - }, + }, - arrowFocus(t: Theme) { - return css` + arrowFocus(t: Theme) { + return emotion.css` box-shadow: inset 0 0 0 ${t.btnInsetWidth} ${t.btnOutlineColorFocus}; - ${arrowOutlineMixin(t.btnInsetWidth, t.btnBorderColorFocus, t.btnOutlineWidth, t.btnOutlineColorFocus)} + ${arrowOutlineMixin(emotion)(t.btnInsetWidth, t.btnBorderColorFocus, t.btnOutlineWidth, t.btnOutlineColorFocus)} `; - }, + }, - arrow() { - return css` + arrow() { + return emotion.css` background: inherit; border-radius: inherit; position: absolute; @@ -463,16 +466,16 @@ export const styles = memoizeStyle({ } } `; - }, + }, - arrowLeft() { - return css` + arrowLeft() { + return emotion.css` transform: scaleX(-1); `; - }, + }, - arrowIconRoot() { - return css` + arrowIconRoot() { + return emotion.css` position: absolute; height: 100%; top: 0; @@ -482,38 +485,38 @@ export const styles = memoizeStyle({ justify-content: center; box-sizing: content-box; `; - }, + }, - arrowIconRootSmall(t: Theme) { - return css` + arrowIconRootSmall(t: Theme) { + return emotion.css` padding: 0 ${t.btnWithIconPaddingLeftSmall} 0 ${t.btnWithIconPaddingLeftSmall}; width: ${t.btnIconSizeSmall}; `; - }, + }, - arrowIconRootMedium(t: Theme) { - return css` + arrowIconRootMedium(t: Theme) { + return emotion.css` padding: 0 ${t.btnWithIconPaddingLeftMedium} 0 ${t.btnWithIconPaddingLeftMedium}; width: ${t.btnIconSizeMedium}; `; - }, + }, - arrowIconRootLarge(t: Theme) { - return css` + arrowIconRootLarge(t: Theme) { + return emotion.css` padding: 0 ${t.btnWithIconPaddingLeftLarge} 0 ${t.btnWithIconPaddingLeftLarge}; width: ${t.btnIconSizeLarge}; `; - }, + }, - arrowIconLeft() { - return css` + arrowIconLeft() { + return emotion.css` left: 0; `; - }, + }, - default(t: Theme) { - return css` - ${buttonUseMixin( + default(t: Theme) { + return emotion.css` + ${buttonUseMixin(emotion)( t.btnDefaultBg, t.btnDefaultBgStart, t.btnDefaultBgEnd, @@ -524,7 +527,7 @@ export const styles = memoizeStyle({ )}; &:hover:enabled { - ${buttonHoverMixin( + ${buttonHoverMixin(emotion)( t.btnDefaultHoverBg, t.btnDefaultHoverBgStart, t.btnDefaultHoverBgEnd, @@ -536,14 +539,14 @@ export const styles = memoizeStyle({ } &:active:enabled { - ${activeStyles.default(t)}; + ${getActiveStyles(emotion).default(t)}; } `; - }, + }, - primary(t: Theme) { - return css` - ${buttonUseMixin( + primary(t: Theme) { + return emotion.css` + ${buttonUseMixin(emotion)( t.btnPrimaryBg, t.btnPrimaryBgStart, t.btnPrimaryBgEnd, @@ -554,7 +557,7 @@ export const styles = memoizeStyle({ )}; &:hover:enabled { - ${buttonHoverMixin( + ${buttonHoverMixin(emotion)( t.btnPrimaryHoverBg, t.btnPrimaryHoverBgStart, t.btnPrimaryHoverBgEnd, @@ -566,14 +569,14 @@ export const styles = memoizeStyle({ } &:active:enabled { - ${activeStyles.primary(t)} + ${getActiveStyles(emotion).primary(t)} } `; - }, + }, - success(t: Theme) { - return css` - ${buttonUseMixin( + success(t: Theme) { + return emotion.css` + ${buttonUseMixin(emotion)( t.btnSuccessBg, t.btnSuccessBgStart, t.btnSuccessBgEnd, @@ -584,7 +587,7 @@ export const styles = memoizeStyle({ )}; &:hover:enabled { - ${buttonHoverMixin( + ${buttonHoverMixin(emotion)( t.btnSuccessHoverBg, t.btnSuccessHoverBgStart, t.btnSuccessHoverBgEnd, @@ -596,14 +599,14 @@ export const styles = memoizeStyle({ } &:active:enabled { - ${activeStyles.success(t)} + ${getActiveStyles(emotion).success(t)} } `; - }, + }, - danger(t: Theme) { - return css` - ${buttonUseMixin( + danger(t: Theme) { + return emotion.css` + ${buttonUseMixin(emotion)( t.btnDangerBg, t.btnDangerBgStart, t.btnDangerBgEnd, @@ -614,7 +617,7 @@ export const styles = memoizeStyle({ )}; &:hover:enabled { - ${buttonHoverMixin( + ${buttonHoverMixin(emotion)( t.btnDangerHoverBg, t.btnDangerHoverBgStart, t.btnDangerHoverBgEnd, @@ -626,14 +629,14 @@ export const styles = memoizeStyle({ } &:active:enabled { - ${activeStyles.danger(t)} + ${getActiveStyles(emotion).danger(t)} } `; - }, + }, - pay(t: Theme) { - return css` - ${buttonUseMixin( + pay(t: Theme) { + return emotion.css` + ${buttonUseMixin(emotion)( t.btnPayBg, t.btnPayBgStart, t.btnPayBgEnd, @@ -644,7 +647,7 @@ export const styles = memoizeStyle({ )}; &:hover:enabled { - ${buttonHoverMixin( + ${buttonHoverMixin(emotion)( t.btnPayHoverBg, t.btnPayHoverBgStart, t.btnPayHoverBgEnd, @@ -656,13 +659,13 @@ export const styles = memoizeStyle({ } &:active:enabled { - ${activeStyles.pay(t)} + ${getActiveStyles(emotion).pay(t)} } `; - }, + }, - text(t: Theme) { - return css` + text(t: Theme) { + return emotion.css` &, &:enabled, &:hover:enabled { @@ -672,10 +675,10 @@ export const styles = memoizeStyle({ } } - ${buttonUseMixin(t.btnTextBg, '', '', t.btnTextTextColor, t.btnTextBorderColor, '', t.btnBorderWidth)}; + ${buttonUseMixin(emotion)(t.btnTextBg, '', '', t.btnTextTextColor, t.btnTextBorderColor, '', t.btnBorderWidth)}; &:hover:enabled { - ${buttonHoverMixin( + ${buttonHoverMixin(emotion)( t.btnTextHoverBg, '', '', @@ -687,14 +690,14 @@ export const styles = memoizeStyle({ } &:active:enabled { - ${activeStyles.text(t)} + ${getActiveStyles(emotion).text(t)} } `; - }, + }, - backless(t: Theme) { - return css` - ${buttonUseMixin( + backless(t: Theme) { + return emotion.css` + ${buttonUseMixin(emotion)( t.btnBacklessBg, '', '', @@ -708,7 +711,7 @@ export const styles = memoizeStyle({ background: transparent; &:hover:enabled { - ${buttonHoverMixin( + ${buttonHoverMixin(emotion)( t.btnBacklessHoverBg, '', '', @@ -720,13 +723,13 @@ export const styles = memoizeStyle({ } &:active:enabled { - ${activeStyles.backless(t)} + ${getActiveStyles(emotion).backless(t)} } `; - }, + }, - checked(t: Theme) { - const checkedStyles = ` + checked(t: Theme) { + const checkedStyles = ` background-image: none; box-shadow: 0 0 0 ${t.btnBorderWidth} ${t.btnDefaultCheckedBorderColor}; background-color: ${t.btnCheckedBg}; @@ -745,7 +748,7 @@ export const styles = memoizeStyle({ } `; - return css` + return emotion.css` ${checkedStyles} &:hover:enabled, @@ -754,10 +757,10 @@ export const styles = memoizeStyle({ ${checkedStyles} } `; - }, + }, - checked2022(t: Theme) { - const checkedStyles = ` + checked2022(t: Theme) { + const checkedStyles = ` background-image: none; box-shadow: 0 0 0 ${t.btnBorderWidth} ${t.btnDefaultCheckedBorderColor} !important; background-color: ${t.btnCheckedBg} !important; @@ -783,7 +786,7 @@ export const styles = memoizeStyle({ } `; - return css` + return emotion.css` ${checkedStyles} &:hover:enabled, @@ -792,10 +795,10 @@ export const styles = memoizeStyle({ ${checkedStyles} } `; - }, + }, - checkedFocused(t: Theme) { - return css` + checkedFocused(t: Theme) { + return emotion.css` &:hover:enabled, &:hover:active:enabled { box-shadow: inset 0 0 0 ${t.btnInsetWidth} ${t.btnOutlineColorFocus}, @@ -803,10 +806,10 @@ export const styles = memoizeStyle({ border-color: ${t.btnBorderColorFocus} !important; } `; - }, + }, - checkedDisabled(t: Theme) { - return css` + checkedDisabled(t: Theme) { + return emotion.css` box-shadow: 0 0 0 ${t.btnBorderWidth} ${t.btnCheckedDisabledBorderColor}; background-color: ${t.btnCheckedDisabledBg}; color: ${t.btnCheckedDisabledColor}; @@ -823,113 +826,113 @@ export const styles = memoizeStyle({ } } `; - }, + }, - checkedDisabled2022(t: Theme) { - return css` + checkedDisabled2022(t: Theme) { + return emotion.css` svg { color: ${t.btnCheckedDisabledColor} !important; } `; - }, + }, - caption() { - return css` + caption() { + return emotion.css` position: relative; white-space: nowrap; display: inline-block; width: 100%; vertical-align: top; `; - }, + }, - captionLink() { - return css` + captionLink() { + return emotion.css` display: inline; transform: none !important; // override root:active style `; - }, + }, - captionTranslated() { - return css` + captionTranslated() { + return emotion.css` transform: translateY(1px); `; - }, + }, - captionDisabled() { - return css` + captionDisabled() { + return emotion.css` transform: none !important; // override root:active style `; - }, + }, - wrap(t: Theme) { - return css` + wrap(t: Theme) { + return emotion.css` box-sizing: border-box; display: inline-block; line-height: normal; padding: ${t.btnBorderWidth}; `; - }, + }, - wrapSmall(t: Theme) { - return css` + wrapSmall(t: Theme) { + return emotion.css` height: ${t.btnHeightSmall}; `; - }, + }, - wrapMedium(t: Theme) { - return css` + wrapMedium(t: Theme) { + return emotion.css` height: ${t.btnHeightMedium}; `; - }, + }, - wrapLarge(t: Theme) { - return css` + wrapLarge(t: Theme) { + return emotion.css` height: ${t.btnHeightLarge}; `; - }, + }, - narrow() { - return css` + narrow() { + return emotion.css` padding-left: 5px; padding-right: 5px; `; - }, + }, - noPadding() { - return css` + noPadding() { + return emotion.css` padding-left: 0; padding-right: 0; `; - }, + }, - noRightPadding() { - return css` + noRightPadding() { + return emotion.css` padding-right: 0; `; - }, + }, - wrapLink() { - return css` + wrapLink() { + return emotion.css` padding: 0; `; - }, + }, - wrapArrow() { - return css` + wrapArrow() { + return emotion.css` margin-right: 10px; `; - }, + }, - wrapArrowLeft() { - return css` + wrapArrowLeft() { + return emotion.css` margin-right: 0; margin-left: 10px; `; - }, + }, - borderless() { - return css` + borderless() { + return emotion.css` &:enabled, &:active:hover:enabled, &:hover:enabled { @@ -939,32 +942,32 @@ export const styles = memoizeStyle({ } } `; - }, + }, - borderless2022() { - return css` + borderless2022() { + return emotion.css` &, &:active:hover, &:hover { box-shadow: none !important; // override root:hover style } `; - }, + }, - backlessDisabled2022(t: Theme) { - return css` + backlessDisabled2022(t: Theme) { + return emotion.css` box-shadow: 0 0 0 1px ${t.btnBacklessDisabledBorderColor}; `; - }, + }, - textDisabled2022() { - return css` + textDisabled2022() { + return emotion.css` background-color: transparent; `; - }, + }, - loading() { - return css` + loading() { + return emotion.css` position: absolute; top: 0; bottom: 0; @@ -976,20 +979,21 @@ export const styles = memoizeStyle({ justify-content: center; z-index: 10; `; - }, + }, - visibilityHidden() { - return css` + visibilityHidden() { + return emotion.css` visibility: hidden; `; - }, -}); + }, + }); -export const activeStyles = memoizeStyle({ - default(t: Theme) { - return css` +export const getActiveStyles = (emotion: Emotion) => + memoizeStyle({ + default(t: Theme) { + return emotion.css` & { - ${buttonActiveMixin( + ${buttonActiveMixin(emotion)( t.btnDefaultActiveBg, t.btnDefaultActiveShadow, t.btnDefaultActiveBorderColor, @@ -999,12 +1003,12 @@ export const activeStyles = memoizeStyle({ )}; } `; - }, + }, - primary(t: Theme) { - return css` + primary(t: Theme) { + return emotion.css` & { - ${buttonActiveMixin( + ${buttonActiveMixin(emotion)( t.btnPrimaryActiveBg, t.btnPrimaryActiveShadow, t.btnPrimaryActiveBorderColor, @@ -1014,12 +1018,12 @@ export const activeStyles = memoizeStyle({ )}; } `; - }, + }, - success(t: Theme) { - return css` + success(t: Theme) { + return emotion.css` & { - ${buttonActiveMixin( + ${buttonActiveMixin(emotion)( t.btnSuccessActiveBg, t.btnSuccessActiveShadow, t.btnSuccessActiveBorderColor, @@ -1029,12 +1033,12 @@ export const activeStyles = memoizeStyle({ )}; } `; - }, + }, - danger(t: Theme) { - return css` + danger(t: Theme) { + return emotion.css` & { - ${buttonActiveMixin( + ${buttonActiveMixin(emotion)( t.btnDangerActiveBg, t.btnDangerActiveShadow, t.btnDangerActiveBorderColor, @@ -1044,12 +1048,12 @@ export const activeStyles = memoizeStyle({ )}; } `; - }, + }, - pay(t: Theme) { - return css` + pay(t: Theme) { + return emotion.css` & { - ${buttonActiveMixin( + ${buttonActiveMixin(emotion)( t.btnPayActiveBg, t.btnPayActiveShadow, t.btnPayActiveBorderColor, @@ -1059,30 +1063,37 @@ export const activeStyles = memoizeStyle({ )}; } `; - }, + }, - link(t: Theme) { - return css` + link(t: Theme) { + return emotion.css` & { color: ${t.btnLinkActiveColor}; } `; - }, + }, - text(t: Theme) { - return css` + text(t: Theme) { + return emotion.css` & { - ${buttonActiveMixin(t.btnTextActiveBg, '', t.btnTextActiveBg, '', t.btnBorderWidth, t.btnArrowBgImageActive)}; + ${buttonActiveMixin(emotion)( + t.btnTextActiveBg, + '', + t.btnTextActiveBg, + '', + t.btnBorderWidth, + t.btnArrowBgImageActive, + )}; } `; - }, + }, - backless(t: Theme) { - return css` + backless(t: Theme) { + return emotion.css` &, &:hover { background: ${t.btnBacklessActiveBg}; } `; - }, -}); + }, + }); diff --git a/packages/react-ui/components/Button/Button.tsx b/packages/react-ui/components/Button/Button.tsx index b5c9181f05a..8984229f036 100644 --- a/packages/react-ui/components/Button/Button.tsx +++ b/packages/react-ui/components/Button/Button.tsx @@ -1,22 +1,23 @@ import React, { AriaAttributes, HTMLAttributes } from 'react'; import { globalObject } from '@skbkontur/global-object'; +import type { Emotion } from '@emotion/css/create-instance'; import { HTMLProps } from '../../typings/html'; import { isKonturIcon, isReactUIComponent } from '../../lib/utils'; -import { isIE11, isEdge, isSafari } from '../../lib/client'; +import { isEdge, isIE11, isSafari } from '../../lib/client'; import { keyListener } from '../../lib/events/keyListener'; import { Theme, ThemeIn } from '../../lib/theming/Theme'; import { ThemeContext } from '../../lib/theming/ThemeContext'; -import { CommonWrapper, CommonProps } from '../../internal/CommonWrapper'; -import { cx } from '../../lib/theming/Emotion'; +import { CommonProps, CommonWrapper } from '../../internal/CommonWrapper'; import { rootNode, TSetRootNode } from '../../lib/rootNode'; import { ThemeFactory } from '../../lib/theming/ThemeFactory'; import { createPropsGetter } from '../../lib/createPropsGetter'; import { isTheme2022 } from '../../lib/theming/ThemeHelpers'; import { Link, LinkProps } from '../Link'; import { SizeProp } from '../../lib/types/props'; +import { EmotionConsumer } from '../../lib/theming/Emotion'; -import { styles, activeStyles, globalClasses } from './Button.styles'; +import { getActiveStyles, getStyles, globalClasses } from './Button.styles'; import { ButtonIcon, ButtonIconProps, getButtonIconSizes } from './ButtonIcon'; import { useButtonArrow } from './ButtonArrow'; import { getInnerLinkTheme } from './getInnerLinkTheme'; @@ -221,6 +222,7 @@ export class Button extends React.Component { }; private theme!: Theme; + private emotion!: Emotion; private node: HTMLButtonElement | null = null; private setRootNode!: TSetRootNode; @@ -254,12 +256,19 @@ export class Button extends React.Component { public render(): JSX.Element { return ( - - {(theme) => { - this.theme = this.props.theme ? ThemeFactory.create(this.props.theme as Theme, theme) : theme; - return this.renderMain(); + + {(emotion) => { + this.emotion = emotion; + return ( + + {(theme) => { + this.theme = this.props.theme ? ThemeFactory.create(this.props.theme as Theme, theme) : theme; + return this.renderMain(); + }} + + ); }} - + ); } @@ -315,12 +324,15 @@ export class Button extends React.Component { const [wrapClassNameWithArrow, rootClassNameWithArrow, arrowNode] = useButtonArrow( { ...this.props, isFocused: Boolean(isFocused) }, this.theme, + this.emotion, ); const isUseStateWithoutOutlineInDisabledState = !['default', 'backless'].includes(use); let rootClassName = ''; + const styles = getStyles(this.emotion); + const activeStyles = getActiveStyles(this.emotion); if (_isTheme2022) { const trueDisabled = disabled || loading; - rootClassName = cx( + rootClassName = this.emotion.cx( styles.root(this.theme), styles[use](this.theme), sizeClass, @@ -347,7 +359,7 @@ export class Button extends React.Component { ]), ); } else { - rootClassName = cx({ + rootClassName = this.emotion.cx({ [styles.root(this.theme)]: true, [styles.simulatedPress()]: true, [styles[use](this.theme)]: true, @@ -398,7 +410,7 @@ export class Button extends React.Component { }; const wrapProps = { - className: cx(globalClasses.root, { + className: this.emotion.cx(globalClasses.root, { [styles.wrap(this.theme)]: true, [wrapClassNameWithArrow]: true, [this.getSizeWrapClassName()]: true, @@ -416,7 +428,7 @@ export class Button extends React.Component { outlineNode = (
{ // Force disable all props and features, that cannot be use with Link if (isLink) { - rootProps.className = cx({ + rootProps.className = this.emotion.cx({ [styles.root(this.theme)]: true, [sizeClass]: true, [styles.link(this.theme)]: true, @@ -450,7 +462,7 @@ export class Button extends React.Component { [styles.linkDisabled(this.theme)]: disabled || loading, }); Object.assign(wrapProps, { - className: cx(styles.wrap(this.theme), styles.wrapLink()), + className: this.emotion.cx(styles.wrap(this.theme), styles.wrapLink()), style: { width: wrapProps.style.width }, }); rootProps.style.textAlign = undefined; @@ -461,7 +473,7 @@ export class Button extends React.Component { let captionNode = (
{ {loadingNode} {leftIconNode} @@ -520,23 +532,24 @@ export class Button extends React.Component { } private getSizeClassName() { + const styles = getStyles(this.emotion); const _isTheme2022 = isTheme2022(this.theme); switch (this.getProps().size) { case 'large': - return cx(styles.sizeLarge(this.theme), { + return this.emotion.cx(styles.sizeLarge(this.theme), { [styles.sizeLargeIE11(this.theme)]: isIE11 || isEdge, [styles.sizeLargeWithIcon(this.theme)]: !!this.props.icon, [styles.sizeLargeWithIconWithoutText(this.theme)]: _isTheme2022 && !!this.props.icon && !this.props.children, }); case 'medium': - return cx(styles.sizeMedium(this.theme), { + return this.emotion.cx(styles.sizeMedium(this.theme), { [styles.sizeMediumIE11(this.theme)]: isIE11 || isEdge, [styles.sizeMediumWithIcon(this.theme)]: !!this.props.icon, [styles.sizeMediumWithIconWithoutText(this.theme)]: _isTheme2022 && !!this.props.icon && !this.props.children, }); case 'small': default: - return cx(styles.sizeSmall(this.theme), { + return this.emotion.cx(styles.sizeSmall(this.theme), { [styles.sizeSmallIE11(this.theme)]: isIE11 || isEdge, [styles.sizeSmallWithIcon(this.theme)]: !!this.props.icon, [styles.sizeSmallWithIconWithoutText(this.theme)]: _isTheme2022 && !!this.props.icon && !this.props.children, @@ -545,6 +558,8 @@ export class Button extends React.Component { } private getSizeWrapClassName() { + const styles = getStyles(this.emotion); + switch (this.getProps().size) { case 'large': return styles.wrapLarge(this.theme); diff --git a/packages/react-ui/components/Button/ButtonArrow.tsx b/packages/react-ui/components/Button/ButtonArrow.tsx index 8326f70b38c..199921a066a 100644 --- a/packages/react-ui/components/Button/ButtonArrow.tsx +++ b/packages/react-ui/components/Button/ButtonArrow.tsx @@ -1,14 +1,15 @@ -import React, { useContext } from 'react'; +import React from 'react'; +import type { Emotion } from '@emotion/css/create-instance'; -import { cx } from '../../lib/theming/Emotion'; -import { ThemeContext } from '../../lib/theming/ThemeContext'; +import { useEmotion } from '../../lib/theming/Emotion'; import { isTheme2022 } from '../../lib/theming/ThemeHelpers'; import { Theme } from '../../lib/theming/Theme'; +import { useTheme } from '../../lib/theming/useTheme'; import { ArrowRightIcon } from './ArrowRightIcon'; import { ArrowLeftIcon } from './ArrowLeftIcon'; import { Button, ButtonProps } from './Button'; -import { globalClasses, styles } from './Button.styles'; +import { getStyles, globalClasses } from './Button.styles'; type ButtonArrowProps = Pick & { isFocused: boolean; @@ -23,11 +24,13 @@ const ButtonArrow: React.FunctionComponent = ({ warning, isFocused, }) => { - const theme = useContext(ThemeContext); + const emotion = useEmotion(); + const theme = useTheme(); const _isTheme2022 = isTheme2022(theme); + const styles = getStyles(emotion); const getArrowIconRootClassName = () => { - return cx(styles.arrowIconRoot(), globalClasses.arrow, { + return emotion.cx(styles.arrowIconRoot(), globalClasses.arrow, { [styles.arrowIconRootSmall(theme)]: size === 'small', [styles.arrowIconRootMedium(theme)]: size === 'medium', [styles.arrowIconRootLarge(theme)]: size === 'large', @@ -52,7 +55,7 @@ const ButtonArrow: React.FunctionComponent = ({ } else { arrowNode = (
= ({ [styles.arrowLeft()]: arrow === 'left', })} > -
-
+
+
); } @@ -69,7 +72,13 @@ const ButtonArrow: React.FunctionComponent = ({ return arrowNode; }; -export function useButtonArrow(props: ButtonArrowProps, theme: Theme): [string, string, React.ReactNode] { +export function useButtonArrow( + props: ButtonArrowProps, + theme: Theme, + emotion: Emotion, +): [string, string, React.ReactNode] { + const styles = getStyles(emotion); + const { arrow, size, use } = props; const _isTheme2022 = isTheme2022(theme); const canRender = use !== 'link' && (arrow === true || arrow === 'left'); @@ -77,7 +86,7 @@ export function useButtonArrow(props: ButtonArrowProps, theme: Theme): [string, const rootClassName = !_isTheme2022 && canRender ? '' - : cx( + : emotion.cx( arrow === true && size === 'small' && styles.withArrowIconRightSmall(theme), arrow === true && size === 'medium' && styles.withArrowIconRightMedium(theme), arrow === true && size === 'large' && styles.withArrowIconRightLarge(theme), @@ -89,7 +98,7 @@ export function useButtonArrow(props: ButtonArrowProps, theme: Theme): [string, const wrapClassName = _isTheme2022 && canRender ? '' - : cx({ + : emotion.cx({ [styles.wrapArrow()]: arrow === true, [styles.wrapArrowLeft()]: arrow === 'left', }); diff --git a/packages/react-ui/components/Button/ButtonIcon.styles.ts b/packages/react-ui/components/Button/ButtonIcon.styles.ts index 6560d2ba33f..ec1f71389e3 100644 --- a/packages/react-ui/components/Button/ButtonIcon.styles.ts +++ b/packages/react-ui/components/Button/ButtonIcon.styles.ts @@ -1,90 +1,93 @@ +import type { Emotion } from '@emotion/css/create-instance'; + import { isTheme2022 } from '../../lib/theming/ThemeHelpers'; import { ZERO_WIDTH_SPACE_CSS } from '../../lib/chars'; -import { css, memoizeStyle } from '../../lib/theming/Emotion'; +import { memoizeStyle } from '../../lib/theming/Emotion'; import { Theme } from '../../lib/theming/Theme'; -export const styles = memoizeStyle({ - icon(t: Theme) { - const space = isTheme2022(t) ? `'${ZERO_WIDTH_SPACE_CSS}'` : null; - return css` - display: inline-block; +export const getStyles = (emotion: Emotion) => + memoizeStyle({ + icon(t: Theme) { + const space = isTheme2022(t) ? `'${ZERO_WIDTH_SPACE_CSS}'` : null; + return emotion.css` + display: inline-block; - &::before { - content: ${space}; - } - `; - }, + &::before { + content: ${space}; + } + `; + }, - iconSmall(t: Theme) { - return css` - width: ${t.btnIconSizeSmall}; - `; - }, + iconSmall(t: Theme) { + return emotion.css` + width: ${t.btnIconSizeSmall}; + `; + }, - iconSmallLeft(t: Theme) { - return css` - margin-right: ${t.btnIconGapSmall}; - `; - }, + iconSmallLeft(t: Theme) { + return emotion.css` + margin-right: ${t.btnIconGapSmall}; + `; + }, - iconSmallRight(t: Theme) { - return css` - margin-left: ${t.btnIconGapSmallRight}; - `; - }, + iconSmallRight(t: Theme) { + return emotion.css` + margin-left: ${t.btnIconGapSmallRight}; + `; + }, - iconMedium(t: Theme) { - return css` - width: ${t.btnIconSizeMedium}; - `; - }, + iconMedium(t: Theme) { + return emotion.css` + width: ${t.btnIconSizeMedium}; + `; + }, - iconMediumLeft(t: Theme) { - return css` - margin-right: ${t.btnIconGapMediumRight}; - `; - }, + iconMediumLeft(t: Theme) { + return emotion.css` + margin-right: ${t.btnIconGapMediumRight}; + `; + }, - iconMediumRight(t: Theme) { - return css` - margin-left: ${t.btnIconGapMedium}; - `; - }, + iconMediumRight(t: Theme) { + return emotion.css` + margin-left: ${t.btnIconGapMedium}; + `; + }, - iconLarge(t: Theme) { - return css` - width: ${t.btnIconSizeLarge}; - `; - }, + iconLarge(t: Theme) { + return emotion.css` + width: ${t.btnIconSizeLarge}; + `; + }, - iconLargeLeft(t: Theme) { - return css` - margin-right: ${t.btnIconGapLarge}; - `; - }, + iconLargeLeft(t: Theme) { + return emotion.css` + margin-right: ${t.btnIconGapLarge}; + `; + }, - iconLargeRight(t: Theme) { - return css` - margin-left: ${t.btnIconGapLargeRight}; - `; - }, + iconLargeRight(t: Theme) { + return emotion.css` + margin-left: ${t.btnIconGapLargeRight}; + `; + }, - iconLeftLink(t: Theme) { - return css` - margin-right: ${t.btnLinkIconMarginRight}; - `; - }, + iconLeftLink(t: Theme) { + return emotion.css` + margin-right: ${t.btnLinkIconMarginRight}; + `; + }, - iconRightLink(t: Theme) { - return css` - margin-left: ${t.btnLinkIconMarginLeft}; - `; - }, + iconRightLink(t: Theme) { + return emotion.css` + margin-left: ${t.btnLinkIconMarginLeft}; + `; + }, - iconNoMargin() { - return css` - margin-right: 0; - margin-left: 0; - `; - }, -}); + iconNoMargin() { + return emotion.css` + margin-right: 0; + margin-left: 0; + `; + }, + }); diff --git a/packages/react-ui/components/Button/ButtonIcon.tsx b/packages/react-ui/components/Button/ButtonIcon.tsx index cecec34485c..d2d1f22162b 100644 --- a/packages/react-ui/components/Button/ButtonIcon.tsx +++ b/packages/react-ui/components/Button/ButtonIcon.tsx @@ -1,14 +1,14 @@ -import React, { useContext } from 'react'; +import React from 'react'; import { Theme } from '../../lib/theming/Theme'; import { isKonturIcon } from '../../lib/utils'; -import { cx } from '../../lib/theming/Emotion'; -import { ThemeContext } from '../../lib/theming/ThemeContext'; +import { useEmotion } from '../../lib/theming/Emotion'; import { isTheme2022 } from '../../lib/theming/ThemeHelpers'; import { SizeProp } from '../../lib/types/props'; +import { useTheme } from '../../lib/theming/useTheme'; import { ButtonProps } from './Button'; -import { styles } from './ButtonIcon.styles'; +import { getStyles } from './ButtonIcon.styles'; import { LoadingButtonIcon } from './LoadingButtonIcon'; export interface ButtonIconProps extends Pick { @@ -26,7 +26,7 @@ export const getButtonIconSizes = (theme: Theme): Record => { }; const useIcon = (icon: any, size: SizeProp) => { - const theme = useContext(ThemeContext); + const theme = useTheme(); if (icon && isTheme2022(theme) && isKonturIcon(icon)) { const sizes = getButtonIconSizes(theme); return React.cloneElement(icon, { size: icon.props.size ?? sizes[size] }); @@ -44,7 +44,10 @@ export const ButtonIcon: React.FunctionComponent = ({ hasBothIcons = false, size = 'small', }) => { - const theme = useContext(ThemeContext); + const theme = useTheme(); + const emotion = useEmotion(); + const styles = getStyles(emotion); + const isLink = use === 'link'; const getSizeIconClassName = () => { @@ -80,7 +83,7 @@ export const ButtonIcon: React.FunctionComponent = ({ return ( { - const theme = useContext(ThemeContext); + const theme = useTheme(); + const emotion = useEmotion(); + const styles = getStyles(emotion); return (
diff --git a/packages/react-ui/components/Calendar/Calendar.styles.ts b/packages/react-ui/components/Calendar/Calendar.styles.ts index c34f7a6dfc6..2d0b1a171aa 100644 --- a/packages/react-ui/components/Calendar/Calendar.styles.ts +++ b/packages/react-ui/components/Calendar/Calendar.styles.ts @@ -1,33 +1,36 @@ -import { css, memoizeStyle } from '../../lib/theming/Emotion'; +import type { Emotion } from '@emotion/css/create-instance'; + +import { memoizeStyle } from '../../lib/theming/Emotion'; import { Theme } from '../../lib/theming/Theme'; -export const styles = memoizeStyle({ - root(t: Theme) { - const width = parseInt(t.calendarCellWidth) * 7; - return css` - background: ${t.calendarBg}; - box-sizing: content-box; - border-radius: ${t.pickerBorderRadius}; - color: ${t.textColorDefault}; - display: block; - padding: 0 ${t.calendarPaddingX}; - width: ${width}px; - touch-action: none; - `; - }, +export const getStyles = (emotion: Emotion) => + memoizeStyle({ + root(t: Theme) { + const width = parseInt(t.calendarCellWidth) * 7; + return emotion.css` + background: ${t.calendarBg}; + box-sizing: content-box; + border-radius: ${t.pickerBorderRadius}; + color: ${t.textColorDefault}; + display: block; + padding: 0 ${t.calendarPaddingX}; + width: ${width}px; + touch-action: none; + `; + }, - wrapper() { - return css` - font-size: 14px; - position: relative; - overflow: hidden; - `; - }, + wrapper() { + return emotion.css` + font-size: 14px; + position: relative; + overflow: hidden; + `; + }, - separator(t: Theme) { - return css` - border-bottom: ${t.calendarBottomSeparatorBorder}; - margin: 0 ${t.calendarMonthTitleMarginX}; - `; - }, -}); + separator(t: Theme) { + return emotion.css` + border-bottom: ${t.calendarBottomSeparatorBorder}; + margin: 0 ${t.calendarMonthTitleMarginX}; + `; + }, + }); diff --git a/packages/react-ui/components/Calendar/Calendar.tsx b/packages/react-ui/components/Calendar/Calendar.tsx index 4b50dab03be..dfc9d58f947 100644 --- a/packages/react-ui/components/Calendar/Calendar.tsx +++ b/packages/react-ui/components/Calendar/Calendar.tsx @@ -3,29 +3,30 @@ import normalizeWheel from 'normalize-wheel'; import throttle from 'lodash.throttle'; import shallowEqual from 'shallowequal'; import { globalObject, SafeTimer } from '@skbkontur/global-object'; +import type { Emotion } from '@emotion/css/create-instance'; import { isInstanceOf } from '../../lib/isInstanceOf'; import { InternalDate } from '../../lib/date/InternalDate'; import { rootNode, TSetRootNode } from '../../lib/rootNode'; -import { cx } from '../../lib/theming/Emotion'; +import { EmotionConsumer } from '../../lib/theming/Emotion'; import { CommonProps, CommonWrapper } from '../../internal/CommonWrapper'; import { MAX_DATE, MAX_MONTH, MAX_YEAR, MIN_DATE, MIN_MONTH, MIN_YEAR } from '../../lib/date/constants'; import { Nullable, Range } from '../../typings/utility-types'; import { Theme } from '../../lib/theming/Theme'; -import { ThemeContext } from '../../lib/theming/ThemeContext'; import { animation } from '../../lib/animation'; import { isMobile } from '../../lib/client'; import { createPropsGetter } from '../../lib/createPropsGetter'; import { InternalDateTransformer } from '../../lib/date/InternalDateTransformer'; +import { ThemeContext } from '../../lib/theming/ThemeContext'; import { themeConfig } from './config'; import { MonthViewModel } from './MonthViewModel'; import * as CalendarScrollEvents from './CalendarScrollEvents'; import { Month } from './Month'; -import { styles } from './Calendar.styles'; import { CalendarDateShape, create, isGreater, isLess } from './CalendarDateShape'; import * as CalendarUtils from './CalendarUtils'; import { CalendarContext, CalendarContextProps } from './CalendarContext'; +import { getStyles } from './Calendar.styles'; import { CalendarDay, CalendarDayProps } from './CalendarDay'; export interface CalendarProps extends CommonProps { @@ -135,6 +136,7 @@ export class Calendar extends React.Component { private getProps = createPropsGetter(Calendar.defaultProps); private theme!: Theme; + private emotion!: Emotion; private wheelEndTimeout: SafeTimer; private root: Nullable; private animation = animation(); @@ -198,12 +200,19 @@ export class Calendar extends React.Component { public render() { return ( - - {(theme) => { - this.theme = theme; - return this.renderMain(); + + {(emotion) => { + this.emotion = emotion; + return ( + + {(theme) => { + this.theme = theme; + return this.renderMain(); + }} + + ); }} - + ); } @@ -334,6 +343,7 @@ export class Calendar extends React.Component { const wrapperStyle = { height: themeConfig(this.theme).WRAPPER_HEIGHT }; const props = this.getProps(); + const styles = getStyles(this.emotion); const context: CalendarContextProps = { value: this.getDateInNativeFormat(props.value), @@ -347,7 +357,7 @@ export class Calendar extends React.Component { return ( -
+
{monthsForRender.map(this.renderMonth, this)} diff --git a/packages/react-ui/components/Calendar/CalendarDay.tsx b/packages/react-ui/components/Calendar/CalendarDay.tsx index 347c10368c7..65a25e18fdd 100644 --- a/packages/react-ui/components/Calendar/CalendarDay.tsx +++ b/packages/react-ui/components/Calendar/CalendarDay.tsx @@ -2,7 +2,7 @@ import React, { PropsWithChildren, useContext, memo } from 'react'; import { useLocaleForControl } from '../../lib/locale/useLocaleForControl'; import { ThemeContext } from '../../lib/theming/ThemeContext'; -import { cx } from '../../lib/theming/Emotion'; +import { cx, useEmotion } from '../../lib/theming/Emotion'; import { isTheme2022 } from '../../lib/theming/ThemeHelpers'; import { DatePickerLocaleHelper } from '../DatePicker/locale'; import { InternalDate } from '../../lib/date/InternalDate'; @@ -10,7 +10,7 @@ import { LocaleContext } from '../../lib/locale'; import { getVisualStateDataAttributes } from '../../internal/CommonWrapper/utils/getVisualStateDataAttributes'; import { forwardRefAndName } from '../../lib/forwardRefAndName'; -import { styles } from './DayCellView.styles'; +import { getStyles } from './DayCellView.styles'; import { CalendarDataTids } from './Calendar'; export interface CalendarDayProps extends React.HTMLAttributes { @@ -41,6 +41,7 @@ export const CalendarDay = memo( ref: React.Ref, ) { const theme = useContext(ThemeContext); + const emotion = useEmotion(); const _isTheme2022 = isTheme2022(theme); const { langCode } = useContext(LocaleContext); @@ -51,6 +52,7 @@ export const CalendarDay = memo( const { date: day } = internalDate.getComponentsLikeNumber(); const caption = children ?? day; + const styles = getStyles(emotion); return (