mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-02 12:07:54 +08:00
refactor: mentions (#6255)
* refactor: mentions * refactor: mentions menu provider
This commit is contained in:
parent
44e5d09f22
commit
92795a828f
@ -12,6 +12,9 @@ import { optionProps } from '../vc-mentions/src/Option';
|
||||
import type { KeyboardEventHandler } from '../_util/EventInterface';
|
||||
import type { InputStatus } from '../_util/statusUtils';
|
||||
import { getStatusClassNames, getMergedStatus } from '../_util/statusUtils';
|
||||
import useStyle from './style';
|
||||
import { useProvideOverride } from '../menu/src/OverrideContext';
|
||||
import warning from '../_util/warning';
|
||||
|
||||
interface MentionsConfig {
|
||||
prefix?: string | string[];
|
||||
@ -98,12 +101,27 @@ const Mentions = defineComponent({
|
||||
slots: ['notFoundContent', 'option'],
|
||||
setup(props, { slots, emit, attrs, expose }) {
|
||||
const { prefixCls, renderEmpty, direction } = useConfigInject('mentions', props);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
const focused = ref(false);
|
||||
const vcMentions = ref(null);
|
||||
const value = ref(props.value ?? props.defaultValue ?? '');
|
||||
const formItemContext = useInjectFormItemContext();
|
||||
const formItemInputContext = FormItemInputContext.useInject();
|
||||
const mergedStatus = computed(() => getMergedStatus(formItemInputContext.status, props.status));
|
||||
useProvideOverride({
|
||||
prefixCls: computed(() => `${prefixCls.value}-menu`),
|
||||
mode: computed(() => 'vertical'),
|
||||
selectable: computed(() => false),
|
||||
onClick: () => {},
|
||||
validator: ({ mode }) => {
|
||||
// Warning if use other mode
|
||||
warning(
|
||||
!mode || mode === 'vertical',
|
||||
'Mentions',
|
||||
`mode="${mode}" is not supported for Mentions's Menu.`,
|
||||
);
|
||||
},
|
||||
});
|
||||
watch(
|
||||
() => props.value,
|
||||
val => {
|
||||
@ -182,6 +200,7 @@ const Mentions = defineComponent({
|
||||
},
|
||||
getStatusClassNames(prefixCls.value, mergedStatus.value),
|
||||
!hasFeedback && className,
|
||||
hashId.value,
|
||||
);
|
||||
|
||||
const mentionsProps = {
|
||||
@ -206,11 +225,12 @@ const Mentions = defineComponent({
|
||||
const mentions = (
|
||||
<VcMentions
|
||||
{...mentionsProps}
|
||||
dropdownClassName={hashId.value}
|
||||
v-slots={{ notFoundContent: getNotFoundContent, option: slots.option }}
|
||||
></VcMentions>
|
||||
);
|
||||
if (hasFeedback) {
|
||||
return (
|
||||
return wrapSSR(
|
||||
<div
|
||||
class={classNames(
|
||||
`${prefixCls.value}-affix-wrapper`,
|
||||
@ -220,14 +240,15 @@ const Mentions = defineComponent({
|
||||
hasFeedback,
|
||||
),
|
||||
className,
|
||||
hashId.value,
|
||||
)}
|
||||
>
|
||||
{mentions}
|
||||
<span class={`${prefixCls.value}-suffix`}>{feedbackIcon}</span>
|
||||
</div>
|
||||
</div>,
|
||||
);
|
||||
}
|
||||
return mentions;
|
||||
return wrapSSR(mentions);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -1,179 +0,0 @@
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-suffix {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: @input-padding-horizontal-base;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@import './rtl';
|
232
components/mentions/style/index.ts
Normal file
232
components/mentions/style/index.ts
Normal file
@ -0,0 +1,232 @@
|
||||
import type { InputToken } from '../../input/style';
|
||||
import {
|
||||
genActiveStyle,
|
||||
genBasicInputStyle,
|
||||
genDisabledStyle,
|
||||
genPlaceholderStyle,
|
||||
genStatusStyle,
|
||||
initInputToken,
|
||||
} from '../../input/style';
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import { genComponentStyleHook } from '../../theme/internal';
|
||||
import { resetComponent, textEllipsis } from '../../_style';
|
||||
|
||||
export interface ComponentToken {
|
||||
zIndexPopup: number;
|
||||
dropdownHeight: number;
|
||||
controlItemWidth: number;
|
||||
}
|
||||
|
||||
type MentionsToken = InputToken<FullToken<'Mentions'>>;
|
||||
|
||||
const genMentionsStyle: GenerateStyle<MentionsToken> = token => {
|
||||
const {
|
||||
componentCls,
|
||||
colorTextDisabled,
|
||||
controlItemBgHover,
|
||||
controlPaddingHorizontal,
|
||||
colorText,
|
||||
motionDurationSlow,
|
||||
lineHeight,
|
||||
controlHeight,
|
||||
inputPaddingHorizontal,
|
||||
inputPaddingVertical,
|
||||
fontSize,
|
||||
colorBgElevated,
|
||||
borderRadiusLG,
|
||||
boxShadowSecondary,
|
||||
} = token;
|
||||
|
||||
const itemPaddingVertical = Math.round(
|
||||
(token.controlHeight - token.fontSize * token.lineHeight) / 2,
|
||||
);
|
||||
|
||||
return {
|
||||
[componentCls]: {
|
||||
...resetComponent(token),
|
||||
...genBasicInputStyle(token),
|
||||
|
||||
position: 'relative',
|
||||
display: 'inline-block',
|
||||
height: 'auto',
|
||||
padding: 0,
|
||||
overflow: 'hidden',
|
||||
lineHeight,
|
||||
whiteSpace: 'pre-wrap',
|
||||
verticalAlign: 'bottom',
|
||||
|
||||
...genStatusStyle(token, componentCls),
|
||||
|
||||
'&-disabled': {
|
||||
'> textarea': {
|
||||
...genDisabledStyle(token),
|
||||
},
|
||||
},
|
||||
|
||||
'&-focused': {
|
||||
...genActiveStyle(token),
|
||||
},
|
||||
|
||||
[`&-affix-wrapper ${componentCls}-suffix`]: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
insetInlineEnd: inputPaddingHorizontal,
|
||||
bottom: 0,
|
||||
zIndex: 1,
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
margin: 'auto',
|
||||
},
|
||||
|
||||
// ================= Input Area =================
|
||||
[`> textarea, ${componentCls}-measure`]: {
|
||||
color: colorText,
|
||||
boxSizing: 'border-box',
|
||||
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',
|
||||
backgroundColor: 'inherit',
|
||||
...genPlaceholderStyle(token.colorTextPlaceholder),
|
||||
},
|
||||
|
||||
[`${componentCls}-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: token.zIndexPopup,
|
||||
boxSizing: 'border-box',
|
||||
fontSize,
|
||||
fontVariant: 'initial',
|
||||
backgroundColor: colorBgElevated,
|
||||
borderRadius: borderRadiusLG,
|
||||
outline: 'none',
|
||||
boxShadow: boxShadowSecondary,
|
||||
|
||||
'&-hidden': {
|
||||
display: 'none',
|
||||
},
|
||||
|
||||
[`${componentCls}-dropdown-menu`]: {
|
||||
maxHeight: token.dropdownHeight,
|
||||
marginBottom: 0,
|
||||
paddingInlineStart: 0, // Override default ul/ol
|
||||
overflow: 'auto',
|
||||
listStyle: 'none',
|
||||
outline: 'none',
|
||||
|
||||
'&-item': {
|
||||
...textEllipsis,
|
||||
position: 'relative',
|
||||
display: 'block',
|
||||
minWidth: token.controlItemWidth,
|
||||
padding: `${itemPaddingVertical}px ${controlPaddingHorizontal}px`,
|
||||
color: colorText,
|
||||
fontWeight: 'normal',
|
||||
lineHeight,
|
||||
cursor: 'pointer',
|
||||
transition: `background ${motionDurationSlow} ease`,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: controlItemBgHover,
|
||||
},
|
||||
|
||||
'&:first-child': {
|
||||
borderStartStartRadius: borderRadiusLG,
|
||||
borderStartEndRadius: borderRadiusLG,
|
||||
borderEndStartRadius: 0,
|
||||
borderEndEndRadius: 0,
|
||||
},
|
||||
|
||||
'&:last-child': {
|
||||
borderStartStartRadius: 0,
|
||||
borderStartEndRadius: 0,
|
||||
borderEndStartRadius: borderRadiusLG,
|
||||
borderEndEndRadius: borderRadiusLG,
|
||||
},
|
||||
|
||||
'&-disabled': {
|
||||
color: colorTextDisabled,
|
||||
cursor: 'not-allowed',
|
||||
|
||||
'&:hover': {
|
||||
color: colorTextDisabled,
|
||||
backgroundColor: controlItemBgHover,
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
},
|
||||
|
||||
'&-selected': {
|
||||
color: colorText,
|
||||
fontWeight: token.fontWeightStrong,
|
||||
backgroundColor: controlItemBgHover,
|
||||
},
|
||||
|
||||
'&-active': {
|
||||
backgroundColor: controlItemBgHover,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook(
|
||||
'Mentions',
|
||||
token => {
|
||||
const mentionsToken = initInputToken<FullToken<'Mentions'>>(token);
|
||||
return [genMentionsStyle(mentionsToken)];
|
||||
},
|
||||
token => ({
|
||||
dropdownHeight: 250,
|
||||
controlItemWidth: 100,
|
||||
zIndexPopup: token.zIndexPopupBase + 50,
|
||||
}),
|
||||
);
|
@ -1,7 +0,0 @@
|
||||
import './index.less';
|
||||
|
||||
// style dependencies
|
||||
import '../../empty/style';
|
||||
import '../../spin/style';
|
||||
|
||||
// deps-lint-skip: form
|
@ -1,10 +0,0 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
|
||||
@mention-prefix-cls: ~'@{ant-prefix}-mentions';
|
||||
|
||||
.@{mention-prefix-cls} {
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
@import '../../input/style/mixin';
|
||||
|
||||
@mention-prefix-cls: ~'@{ant-prefix}-mentions';
|
||||
@input-prefix-cls: ~'@{ant-prefix}-input';
|
||||
|
||||
.@{mention-prefix-cls} {
|
||||
&-status-error {
|
||||
.status-color(@mention-prefix-cls, @error-color, @error-color, @input-bg, @error-color-hover, @error-color-outline);
|
||||
.status-color-common(@input-prefix-cls, @error-color, @error-color, @input-bg, @error-color-hover, @error-color-outline);
|
||||
}
|
||||
|
||||
&-status-warning {
|
||||
.status-color(@mention-prefix-cls, @warning-color, @warning-color, @input-bg, @warning-color-hover, @warning-color-outline);
|
||||
.status-color-common(@input-prefix-cls, @warning-color, @warning-color, @input-bg, @warning-color-hover, @warning-color-outline);
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ import './tabs/style';
|
||||
// import './popover/style';
|
||||
// import './popconfirm/style';
|
||||
// import './menu/style';
|
||||
import './mentions/style';
|
||||
// import './mentions/style';
|
||||
// import './dropdown/style';
|
||||
// import './divider/style';
|
||||
// import './card/style';
|
||||
|
@ -19,7 +19,7 @@ import type { ComponentToken as EmptyComponentToken } from '../../empty/style';
|
||||
// import type { ComponentToken as InputNumberComponentToken } from '../../input-number/style';
|
||||
import type { ComponentToken as LayoutComponentToken } from '../../layout/style';
|
||||
import type { ComponentToken as ListComponentToken } from '../../list/style';
|
||||
// import type { ComponentToken as MentionsComponentToken } from '../../mentions/style';
|
||||
import type { ComponentToken as MentionsComponentToken } from '../../mentions/style';
|
||||
import type { ComponentToken as MenuComponentToken } from '../../menu/style';
|
||||
import type { ComponentToken as MessageComponentToken } from '../../message/style';
|
||||
import type { ComponentToken as ModalComponentToken } from '../../modal/style';
|
||||
@ -79,7 +79,7 @@ export interface ComponentTokenMap {
|
||||
// InputNumber?: InputNumberComponentToken;
|
||||
Layout?: LayoutComponentToken;
|
||||
List?: ListComponentToken;
|
||||
// Mentions?: MentionsComponentToken;
|
||||
Mentions?: MentionsComponentToken;
|
||||
Notification?: NotificationComponentToken;
|
||||
PageHeader?: {};
|
||||
Pagination?: {};
|
||||
|
@ -54,6 +54,7 @@ export default defineComponent({
|
||||
transitionName: String,
|
||||
getPopupContainer: Function,
|
||||
direction: String,
|
||||
dropdownClassName: String,
|
||||
},
|
||||
slots: ['notFoundContent', 'option'],
|
||||
setup(props, { slots }) {
|
||||
@ -88,6 +89,7 @@ export default defineComponent({
|
||||
prefixCls={getDropdownPrefix()}
|
||||
popupVisible={visible}
|
||||
popup={getDropdownElement()}
|
||||
popupClassName={props.dropdownClassName}
|
||||
popupPlacement={popupPlacement.value}
|
||||
popupTransitionName={transitionName}
|
||||
builtinPlacements={BUILT_IN_PLACEMENTS}
|
||||
|
@ -287,6 +287,7 @@ export default defineComponent({
|
||||
<KeywordTrigger
|
||||
prefixCls={prefixCls}
|
||||
transitionName={transitionName}
|
||||
dropdownClassName={props.dropdownClassName}
|
||||
placement={placement}
|
||||
options={measuring ? options.value : []}
|
||||
visible
|
||||
|
@ -40,6 +40,7 @@ export const mentionsProps = {
|
||||
|
||||
export const vcMentionsProps = {
|
||||
...mentionsProps,
|
||||
dropdownClassName: String,
|
||||
};
|
||||
|
||||
export const defaultProps = {
|
||||
|
Loading…
Reference in New Issue
Block a user