From fbf93111000f2719b9ce7053c1743b0f68c266fc Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Mon, 21 Mar 2022 10:59:42 +0800 Subject: [PATCH] refactor: mentions cssinjs (#34536) * refactor: mentions cssinjs * chore: add fixme * chore: code clean --- components/mentions/index.tsx | 12 +- components/mentions/style/index.less | 336 +++++++++++++-------------- components/mentions/style/index.tsx | 224 +++++++++++++++++- 3 files changed, 397 insertions(+), 175 deletions(-) diff --git a/components/mentions/index.tsx b/components/mentions/index.tsx index cff2ba6317..7f58cc2398 100644 --- a/components/mentions/index.tsx +++ b/components/mentions/index.tsx @@ -12,6 +12,7 @@ import { getStatusClassNames, InputStatus, } from '../_util/statusUtils'; +import useStyle from './style'; export const { Option } = RcMentions; @@ -62,6 +63,7 @@ const InternalMentions: React.ForwardRefRenderFunction = children, notFoundContent, status: customStatus, + dropdownClassName, ...restProps }, ref, @@ -69,7 +71,7 @@ const InternalMentions: React.ForwardRefRenderFunction = const [focused, setFocused] = React.useState(false); const innerRef = React.useRef(); const mergedRef = composeRef(ref, innerRef); - const { getPrefixCls, renderEmpty, direction } = React.useContext(ConfigContext); + const { getPrefixCls, renderEmpty, direction, iconPrefixCls } = React.useContext(ConfigContext); const { status: contextStatus, hasFeedback } = React.useContext(FormItemStatusContext); const mergedStatus = getMergedStatus(contextStatus, customStatus); @@ -117,6 +119,9 @@ const InternalMentions: React.ForwardRefRenderFunction = const prefixCls = getPrefixCls('mentions', customizePrefixCls); + // Style + const [wrapSSR, hashId] = useStyle(prefixCls, iconPrefixCls); + const mergedClassName = classNames( { [`${prefixCls}-disabled`]: disabled, @@ -125,6 +130,7 @@ const InternalMentions: React.ForwardRefRenderFunction = }, getStatusClassNames(prefixCls, mergedStatus), !hasFeedback && className, + hashId, ); const mentions = ( @@ -138,6 +144,7 @@ const InternalMentions: React.ForwardRefRenderFunction = filterOption={getFilterOption()} onFocus={onFocus} onBlur={onBlur} + dropdownClassName={classNames(dropdownClassName, hashId)} ref={mergedRef as any} > {getOptions()} @@ -151,6 +158,7 @@ const InternalMentions: React.ForwardRefRenderFunction = `${prefixCls}-affix-wrapper`, getStatusClassNames(`${prefixCls}-affix-wrapper`, mergedStatus, hasFeedback), className, + hashId, )} > {mentions} @@ -159,7 +167,7 @@ const InternalMentions: React.ForwardRefRenderFunction = ); } - return mentions; + return wrapSSR(mentions); }; const Mentions = React.forwardRef(InternalMentions) as CompoundedComponent; diff --git a/components/mentions/style/index.less b/components/mentions/style/index.less index 489a7ad40f..042f42a49c 100644 --- a/components/mentions/style/index.less +++ b/components/mentions/style/index.less @@ -1,168 +1,168 @@ -@import '../../style/themes/index'; -@import '../../style/mixins/index'; -@import '../../input/style/mixin'; -@import './status'; - -@mention-prefix-cls: ~'@{ant-prefix}-mentions'; - -.@{mention-prefix-cls} { - .reset-component(); - .input(); - - position: relative; - display: inline-block; - height: auto; - padding: 0; - overflow: hidden; - line-height: @line-height-base; - white-space: pre-wrap; - vertical-align: bottom; - - // =================== Status =================== - &-disabled { - > textarea { - .disabled(); - } - } - - &-focused { - .active(); - } - - // ================= Input Area ================= - > textarea, - &-measure { - min-height: @input-height-base - 2px; - margin: 0; - padding: @input-padding-vertical-base @input-padding-horizontal-base; - overflow: inherit; - overflow-x: hidden; - overflow-y: auto; - /* stylelint-disable declaration-block-no-redundant-longhand-properties */ - font-weight: inherit; - font-size: inherit; - font-family: inherit; - font-style: inherit; - font-variant: inherit; - font-size-adjust: inherit; - font-stretch: inherit; - line-height: inherit; - /* stylelint-enable declaration-block-no-redundant-longhand-properties */ - direction: inherit; - letter-spacing: inherit; - white-space: inherit; - text-align: inherit; - vertical-align: top; - word-wrap: break-word; - word-break: inherit; - tab-size: inherit; - } - - > textarea { - width: 100%; - border: none; - outline: none; - resize: none; - & when (@theme = dark) { - background-color: transparent; - } - .placeholder(); - } - - &-measure { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: -1; - color: transparent; - pointer-events: none; - - > span { - display: inline-block; - min-height: 1em; - } - } - - // ================== Dropdown ================== - &-dropdown { - // Ref select dropdown style - .reset-component(); - - position: absolute; - top: -9999px; - left: -9999px; - z-index: @zindex-dropdown; - box-sizing: border-box; - font-size: @font-size-base; - font-variant: initial; - background-color: @mentions-dropdown-bg; - border-radius: @border-radius-base; - outline: none; - box-shadow: @box-shadow-base; - - &-hidden { - display: none; - } - - &-menu { - max-height: 250px; - margin-bottom: 0; - padding-left: 0; // Override default ul/ol - overflow: auto; - list-style: none; - outline: none; - - &-item { - position: relative; - display: block; - min-width: 100px; - padding: 5px @control-padding-horizontal; - overflow: hidden; - color: @text-color; - font-weight: normal; - line-height: @line-height-base; - white-space: nowrap; - text-overflow: ellipsis; - cursor: pointer; - transition: background 0.3s ease; - - &:hover { - background-color: @item-hover-bg; - } - - &:first-child { - border-radius: @border-radius-base @border-radius-base 0 0; - } - - &:last-child { - border-radius: 0 0 @border-radius-base @border-radius-base; - } - - &-disabled { - color: @disabled-color; - cursor: not-allowed; - - &:hover { - color: @disabled-color; - background-color: @mentions-dropdown-menu-item-hover-bg; - cursor: not-allowed; - } - } - - &-selected { - color: @text-color; - font-weight: @select-item-selected-font-weight; - background-color: @background-color-light; - } - - &-active { - background-color: @item-hover-bg; - } - } - } - } -} - -@import './rtl'; +//@import '../../style/themes/index'; +//@import '../../style/mixins/index'; +//@import '../../input/style/mixin'; +//@import './status'; +// +//@mention-prefix-cls: ~'@{ant-prefix}-mentions'; +// +//.@{mention-prefix-cls} { +// .reset-component(); +// .input(); +// +// position: relative; +// display: inline-block; +// height: auto; +// padding: 0; +// overflow: hidden; +// line-height: @line-height-base; +// white-space: pre-wrap; +// vertical-align: bottom; +// +// // =================== Status =================== +// &-disabled { +// > textarea { +// .disabled(); +// } +// } +// +// &-focused { +// .active(); +// } +// +// // ================= Input Area ================= +// > textarea, +// &-measure { +// min-height: @input-height-base - 2px; +// margin: 0; +// padding: @input-padding-vertical-base @input-padding-horizontal-base; +// overflow: inherit; +// overflow-x: hidden; +// overflow-y: auto; +// /* stylelint-disable declaration-block-no-redundant-longhand-properties */ +// font-weight: inherit; +// font-size: inherit; +// font-family: inherit; +// font-style: inherit; +// font-variant: inherit; +// font-size-adjust: inherit; +// font-stretch: inherit; +// line-height: inherit; +// /* stylelint-enable declaration-block-no-redundant-longhand-properties */ +// direction: inherit; +// letter-spacing: inherit; +// white-space: inherit; +// text-align: inherit; +// vertical-align: top; +// word-wrap: break-word; +// word-break: inherit; +// tab-size: inherit; +// } +// +// > textarea { +// width: 100%; +// border: none; +// outline: none; +// resize: none; +// & when (@theme = dark) { +// background-color: transparent; +// } +// .placeholder(); +// } +// +// &-measure { +// position: absolute; +// top: 0; +// right: 0; +// bottom: 0; +// left: 0; +// z-index: -1; +// color: transparent; +// pointer-events: none; +// +// > span { +// display: inline-block; +// min-height: 1em; +// } +// } +// +// // ================== Dropdown ================== +// &-dropdown { +// // Ref select dropdown style +// .reset-component(); +// +// position: absolute; +// top: -9999px; +// left: -9999px; +// z-index: @zindex-dropdown; +// box-sizing: border-box; +// font-size: @font-size-base; +// font-variant: initial; +// background-color: @mentions-dropdown-bg; +// border-radius: @border-radius-base; +// outline: none; +// box-shadow: @box-shadow-base; +// +// &-hidden { +// display: none; +// } +// +// &-menu { +// max-height: 250px; +// margin-bottom: 0; +// padding-left: 0; // Override default ul/ol +// overflow: auto; +// list-style: none; +// outline: none; +// +// &-item { +// position: relative; +// display: block; +// min-width: 100px; +// padding: 5px @control-padding-horizontal; +// overflow: hidden; +// color: @text-color; +// font-weight: normal; +// line-height: @line-height-base; +// white-space: nowrap; +// text-overflow: ellipsis; +// cursor: pointer; +// transition: background 0.3s ease; +// +// &:hover { +// background-color: @item-hover-bg; +// } +// +// &:first-child { +// border-radius: @border-radius-base @border-radius-base 0 0; +// } +// +// &:last-child { +// border-radius: 0 0 @border-radius-base @border-radius-base; +// } +// +// &-disabled { +// color: @disabled-color; +// cursor: not-allowed; +// +// &:hover { +// color: @disabled-color; +// background-color: @mentions-dropdown-menu-item-hover-bg; +// cursor: not-allowed; +// } +// } +// +// &-selected { +// color: @text-color; +// font-weight: @select-item-selected-font-weight; +// background-color: @background-color-light; +// } +// +// &-active { +// background-color: @item-hover-bg; +// } +// } +// } +// } +//} +// +//@import './rtl'; diff --git a/components/mentions/style/index.tsx b/components/mentions/style/index.tsx index b39860748d..69f04b5615 100644 --- a/components/mentions/style/index.tsx +++ b/components/mentions/style/index.tsx @@ -1,7 +1,221 @@ -import './index.less'; +// deps-lint-skip-all +import { + GenerateStyle, + resetComponent, + UseComponentStyleResult, + useStyleRegister, + useToken, +} from '../../_util/theme'; +import { + genActiveStyle, + genBasicInputStyle, + genDisabledStyle, + genPlaceholderStyle, + initInputToken, + InputToken, +} from '../../input/style'; -// style dependencies -import '../../empty/style'; -import '../../spin/style'; +interface MentionsToken extends InputToken { + mentionsCls: string; +} -// deps-lint-skip: form +const genMentionsStyle: GenerateStyle = token => { + const { + mentionsCls, + backgroundLight, + textColorDisabled, + itemHoverBackground, + controlPaddingHorizontal, + textColor, + duration, + lineHeight, + controlHeight, + inputPaddingHorizontal, + inputPaddingVertical, + fontSize, + componentBackground, + borderRadius, + boxShadow, + } = token; + + return { + [`${mentionsCls}`]: { + ...resetComponent(token), + ...genBasicInputStyle(token), + + position: 'relative', + display: 'inline-block', + height: 'auto', + padding: 0, + overflow: 'hidden', + lineHeight, + whiteSpace: 'pre-wrap', + verticalAlign: 'bottom', + + '&-disabled': { + '> textarea': { + ...genDisabledStyle(token), + }, + }, + + '&-focused': { + ...genActiveStyle(token), + }, + + // ================= Input Area ================= + [`> textarea, ${mentionsCls}-measure`]: { + minHeight: controlHeight - 2, + margin: 0, + padding: `${inputPaddingVertical}px ${inputPaddingHorizontal}px`, + overflow: 'inherit', + overflowX: 'hidden', + overflowY: 'auto', + fontWeight: 'inherit', + fontSize: 'inherit', + fontFamily: 'inherit', + fontStyle: 'inherit', + fontVariant: 'inherit', + fontSizeAdjust: 'inherit', + fontStretch: 'inherit', + lineHeight: 'inherit', + direction: 'inherit', + letterSpacing: 'inherit', + whiteSpace: 'inherit', + textAlign: 'inherit', + verticalAlign: 'top', + wordWrap: 'break-word', + wordBreak: 'inherit', + tabSize: 'inherit', + }, + + '> textarea': { + width: '100%', + border: 'none', + outline: 'none', + resize: 'none', + ...genPlaceholderStyle(), + }, + + [`${mentionsCls}-measure`]: { + position: 'absolute', + top: 0, + insetInlineEnd: 0, + bottom: 0, + insetInlineStart: 0, + zIndex: -1, + color: 'transparent', + pointerEvents: 'none', + + '> span': { + display: 'inline-block', + minHeight: '1em', + }, + }, + + // ================== Dropdown ================== + '&-dropdown': { + // Ref select dropdown style + ...resetComponent(token), + + position: 'absolute', + top: -9999, + insetInlineStart: -9999, + zIndex: 1050, // FIXME: magic + boxSizing: 'border-box', + fontSize, + fontVariant: 'initial', + backgroundColor: componentBackground, + borderRadius, + outline: 'none', + boxShadow, + + '&-hidden': { + display: 'none', + }, + + [`${mentionsCls}-dropdown-menu`]: { + maxHeight: 250, // FIXME: magic + marginBottom: 0, + paddingInlineStart: 0, // Override default ul/ol + overflow: 'auto', + listStyle: 'none', + outline: 'none', + + '&-item': { + position: 'relative', + display: 'block', + minWidth: 100, // FIXME: magic + padding: `5px ${controlPaddingHorizontal}px`, // FIXME: magic + overflow: 'hidden', + color: textColor, + fontWeight: 'normal', + lineHeight, + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + cursor: 'pointer', + transition: `background ${duration} ease`, + + '&:hover': { + backgroundColor: itemHoverBackground, + }, + + '&:first-child': { + borderStartStartRadius: borderRadius, + borderStartEndRadius: borderRadius, + borderEndStartRadius: 0, + borderEndEndRadius: 0, + }, + + '&:last-child': { + borderStartStartRadius: 0, + borderStartEndRadius: 0, + borderEndStartRadius: borderRadius, + borderEndEndRadius: borderRadius, + }, + + '&-disabled': { + color: textColorDisabled, + cursor: 'not-allowed', + + '&:hover': { + color: textColorDisabled, + backgroundColor: itemHoverBackground, + cursor: 'not-allowed', + }, + }, + + '&-selected': { + color: textColor, + fontWeight: 600, // FIXME: Need design token? + backgroundColor: backgroundLight, + }, + + '&-active': { + backgroundColor: itemHoverBackground, + }, + }, + }, + }, + }, + }; +}; + +// ============================== Export ============================== +export default function useStyle( + prefixCls: string, + iconPrefixCls: string, +): UseComponentStyleResult { + const [theme, token, hashId] = useToken(); + + const mentionsToken: MentionsToken = { + ...initInputToken(token, prefixCls, iconPrefixCls), + mentionsCls: `.${prefixCls}`, + }; + + return [ + useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => [ + genMentionsStyle(mentionsToken), + ]), + hashId, + ]; +}