mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2024-12-21 04:50:14 +08:00
commit
49c1dc912f
@ -2,6 +2,11 @@
|
||||
|
||||
## Pending
|
||||
|
||||
### Feats
|
||||
|
||||
- `n-dropdown` add `disabled` prop
|
||||
- `n-card` add `:target` style
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fix `n-popover` sometimes won't sync position in manual mode.
|
||||
|
@ -2,6 +2,11 @@
|
||||
|
||||
## Pending
|
||||
|
||||
### Feats
|
||||
|
||||
- `n-dropdown` 新增 `disabled` 属性
|
||||
- `n-card` 增加 `:target` 的样式
|
||||
|
||||
### Fixes
|
||||
|
||||
- 修复 `n-popover` 有时在手动模式不会同步位置
|
||||
@ -393,7 +398,7 @@
|
||||
- `n-layout-sider` 新增 `default-collapsed` 属性
|
||||
- `n-modal` 支持自定义位置
|
||||
|
||||
### Fixed
|
||||
### Fixes
|
||||
|
||||
- 修正 `n-menu` 垂直折叠时 `n-menu-item` tooltip 不显示的问题
|
||||
- 修正 `n-menu` `collapsed-icon-size` 不生效的问题
|
||||
|
@ -83,6 +83,7 @@ export default defineComponent({
|
||||
self: {
|
||||
color,
|
||||
colorModal,
|
||||
colorTarget,
|
||||
textColor,
|
||||
titleTextColor,
|
||||
titleFontWeight,
|
||||
@ -113,6 +114,7 @@ export default defineComponent({
|
||||
'--color': color,
|
||||
'--color-modal': colorModal,
|
||||
'--color-popover': colorPopover,
|
||||
'--color-target': colorTarget,
|
||||
'--text-color': textColor,
|
||||
'--line-height': lineHeight,
|
||||
'--action-color': actionColor,
|
||||
|
@ -137,9 +137,11 @@ export default c([
|
||||
width: 100%;
|
||||
`)
|
||||
]),
|
||||
cM('bordered', {
|
||||
border: '1px solid var(--border-color)'
|
||||
}),
|
||||
cM('bordered', `
|
||||
border: 1px solid var(--border-color);
|
||||
`, [
|
||||
c('&:target', 'border-color: var(--color-target);')
|
||||
]),
|
||||
cM('action-segmented', [
|
||||
c('>', [
|
||||
cE('action', [
|
||||
|
@ -5,6 +5,7 @@ import { Theme } from '../../_mixins'
|
||||
|
||||
export const self = (vars: ThemeCommonVars) => {
|
||||
const {
|
||||
primaryColor,
|
||||
borderRadius,
|
||||
lineHeight,
|
||||
fontSize,
|
||||
@ -27,6 +28,7 @@ export const self = (vars: ThemeCommonVars) => {
|
||||
color: cardColor,
|
||||
colorModal: modalColor,
|
||||
colorPopover: popoverColor,
|
||||
colorTarget: primaryColor,
|
||||
textColor: textColor2,
|
||||
titleTextColor: textColor1,
|
||||
borderColor: dividerColor,
|
||||
|
@ -19,7 +19,8 @@ export default defineComponent({
|
||||
options: [
|
||||
{
|
||||
label: 'Marina Bay Sands',
|
||||
key: 'marina bay sands'
|
||||
key: 'marina bay sands',
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
label: "Brown's Hotel, London",
|
||||
|
@ -30,7 +30,8 @@ const options = [
|
||||
default: () => h(CashIcon)
|
||||
})
|
||||
},
|
||||
key: 'daisy buchanan'
|
||||
key: 'daisy buchanan',
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
@ -55,6 +56,7 @@ const options = [
|
||||
{
|
||||
label: 'Others',
|
||||
key: 'others2',
|
||||
disabled: true,
|
||||
children: [
|
||||
{
|
||||
label: 'Chicken',
|
||||
|
@ -33,6 +33,7 @@ For other props, for example `placement`, please see [Popover Props](popover#Pro
|
||||
| icon? | `() => VNodeChild` | |
|
||||
| key | `string \| number` | Should be unique. |
|
||||
| label | `string` | |
|
||||
| disabled | `boolean` | |
|
||||
|
||||
### DropdownDivider Type
|
||||
|
||||
@ -50,6 +51,7 @@ For other props, for example `placement`, please see [Popover Props](popover#Pro
|
||||
| icon? | `() => VNodeChild` | |
|
||||
| key | `string \| number` | Should be unique. |
|
||||
| children | `Array<DropdownOption \| DropdownDivider \| DropdownSubmenu>` | |
|
||||
| disabled | `boolean` | |
|
||||
|
||||
### DropdownGroup Type
|
||||
|
||||
|
@ -30,7 +30,8 @@ export default defineComponent({
|
||||
options: [
|
||||
{
|
||||
label: 'Marina Bay Sands',
|
||||
key: 'Marina Bay Sands'
|
||||
key: 'Marina Bay Sands',
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
label: "Brown's Hotel, London",
|
||||
|
@ -19,7 +19,8 @@ export default defineComponent({
|
||||
options: [
|
||||
{
|
||||
label: '滨海湾金沙,新加坡',
|
||||
key: 'marina bay sands'
|
||||
key: 'marina bay sands',
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
label: '布朗酒店,伦敦',
|
||||
|
@ -30,7 +30,8 @@ const options = [
|
||||
default: () => h(CashIcon)
|
||||
})
|
||||
},
|
||||
key: 'daisy buchanan'
|
||||
key: 'daisy buchanan',
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
@ -55,6 +56,7 @@ const options = [
|
||||
{
|
||||
label: '其他',
|
||||
key: 'others2',
|
||||
disabled: true,
|
||||
children: [
|
||||
{
|
||||
label: '鸡肉',
|
||||
|
@ -29,11 +29,12 @@ group-debug
|
||||
|
||||
### DropdownOption Type
|
||||
|
||||
| 属性 | 类型 | 说明 |
|
||||
| ----- | ------------------ | -------- |
|
||||
| icon? | `() => VNodeChild` | |
|
||||
| key | `string \| number` | 需要唯一 |
|
||||
| label | `string` | |
|
||||
| 属性 | 类型 | 说明 |
|
||||
| -------- | ------------------ | -------- |
|
||||
| icon? | `() => VNodeChild` | |
|
||||
| key | `string \| number` | 需要唯一 |
|
||||
| label | `string` | |
|
||||
| disabled | `boolean` | |
|
||||
|
||||
### DropdownDivider Type
|
||||
|
||||
@ -51,6 +52,7 @@ group-debug
|
||||
| icon? | `() => VNodeChild` | |
|
||||
| key | `string \| number` | 需要唯一 |
|
||||
| children | `Array<DropdownOption \| DropdownDivider \| DropdownGroup \| DropdownSubmenu>` | |
|
||||
| disabled | `boolean` | |
|
||||
|
||||
### DropdownGroup Type
|
||||
|
||||
|
@ -30,7 +30,8 @@ export default defineComponent({
|
||||
options: [
|
||||
{
|
||||
label: '滨海湾金沙,新加坡',
|
||||
key: 'marina bay sands'
|
||||
key: 'marina bay sands',
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
label: '布朗酒店,伦敦',
|
||||
|
@ -307,6 +307,7 @@ export default defineComponent({
|
||||
dividerColor,
|
||||
borderRadius,
|
||||
boxShadow,
|
||||
optionOpacityDisabled,
|
||||
[createKey('optionIconSuffixWidth', size)]: optionIconSuffixWidth,
|
||||
[createKey('optionSuffixWidth', size)]: optionSuffixWidth,
|
||||
[createKey('optionIconPrefixWidth', size)]: optionIconPrefixWidth,
|
||||
@ -327,7 +328,8 @@ export default defineComponent({
|
||||
'--option-suffix-width': optionSuffixWidth,
|
||||
'--option-icon-suffix-width': optionIconSuffixWidth,
|
||||
'--option-icon-size': optionIconSize,
|
||||
'--divider-color': dividerColor
|
||||
'--divider-color': dividerColor,
|
||||
'--option-opacity-disabled': optionOpacityDisabled
|
||||
}
|
||||
// writing like this is the fastest method
|
||||
if (inverted) {
|
||||
|
@ -30,9 +30,8 @@ interface NDropdownOptionInjection {
|
||||
enteringSubmenuRef: Ref<boolean>
|
||||
}
|
||||
|
||||
const dropdownOptionInjectionKey: InjectionKey<NDropdownOptionInjection> = Symbol(
|
||||
'dropdown-option'
|
||||
)
|
||||
const dropdownOptionInjectionKey: InjectionKey<NDropdownOptionInjection> =
|
||||
Symbol('dropdown-option')
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DropdownOption',
|
||||
@ -75,13 +74,18 @@ export default defineComponent({
|
||||
const hasSubmenuRef = computed(() => {
|
||||
return isSubmenuNode(props.tmNode.rawNode)
|
||||
})
|
||||
const mergedDisabledRef = computed(() => {
|
||||
const { disabled } = props.tmNode
|
||||
return disabled
|
||||
})
|
||||
const showSubmenuRef = computed(() => {
|
||||
if (!hasSubmenuRef.value) return false
|
||||
const { key, disabled } = props.tmNode
|
||||
if (disabled) return false
|
||||
const { value: hoverKey } = hoverKeyRef
|
||||
const { value: keyboardKey } = keyboardKeyRef
|
||||
const { value: lastToggledSubmenuKey } = lastToggledSubmenuKeyRef
|
||||
const { value: pendingKeyPath } = pendingKeyPathRef
|
||||
const { key } = props.tmNode
|
||||
if (hoverKey !== null) return pendingKeyPath.includes(key)
|
||||
if (keyboardKey !== null) {
|
||||
return (
|
||||
@ -144,7 +148,7 @@ export default defineComponent({
|
||||
if (!hasSubmenu && !tmNode.disabled) {
|
||||
NDropdown.doSelect(
|
||||
tmNode.key,
|
||||
((tmNode as unknown) as TreeNode<DropdownOption>).rawNode
|
||||
(tmNode as unknown as TreeNode<DropdownOption>).rawNode
|
||||
)
|
||||
NDropdown.doUpdateShow(false)
|
||||
}
|
||||
@ -177,6 +181,7 @@ export default defineComponent({
|
||||
if (index === -1) return false
|
||||
return index === activeKeyPath.length - 1
|
||||
}),
|
||||
mergedDisabled: mergedDisabledRef,
|
||||
handleClick,
|
||||
handleMouseMove,
|
||||
handleMouseEnter,
|
||||
@ -209,8 +214,10 @@ export default defineComponent({
|
||||
{
|
||||
[`${clsPrefix}-dropdown-option-body--pending`]: this.pending,
|
||||
[`${clsPrefix}-dropdown-option-body--active`]: this.active,
|
||||
[`${clsPrefix}-dropdown-option-body--child-active`]: this
|
||||
.childActive
|
||||
[`${clsPrefix}-dropdown-option-body--child-active`]:
|
||||
this.childActive,
|
||||
[`${clsPrefix}-dropdown-option-body--disabled`]:
|
||||
this.mergedDisabled
|
||||
}
|
||||
]}
|
||||
onMousemove={this.handleMouseMove}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { cB, cM, cE } from '../../../_utils/cssr'
|
||||
import { cB, cM, cE, cNotM } from '../../../_utils/cssr'
|
||||
import fadeInScaleUpTransition from '../../../_styles/transitions/fade-in-scale-up.cssr'
|
||||
|
||||
// vars:
|
||||
@ -23,6 +23,8 @@ import fadeInScaleUpTransition from '../../../_styles/transitions/fade-in-scale-
|
||||
// --prefix-color
|
||||
// --suffix-color
|
||||
// --option-icon-size
|
||||
// --option-opacity-disabled
|
||||
|
||||
export default cB('dropdown-menu', `
|
||||
transform-origin: inherit;
|
||||
padding: var(--padding);
|
||||
@ -49,9 +51,11 @@ export default cB('dropdown-menu', `
|
||||
color .3s var(--bezier);
|
||||
`, [
|
||||
cM('pending', {
|
||||
color: 'var(--option-text-color-hover)',
|
||||
backgroundColor: 'var(--option-color-hover)'
|
||||
color: 'var(--option-text-color-hover)'
|
||||
}, [
|
||||
cNotM('disabled', {
|
||||
backgroundColor: 'var(--option-color-hover)'
|
||||
}),
|
||||
cE('prefix, suffix', {
|
||||
color: 'var(--option-text-color-hover)'
|
||||
})
|
||||
@ -64,6 +68,10 @@ export default cB('dropdown-menu', `
|
||||
color: 'var(--option-text-color-active)'
|
||||
})
|
||||
]),
|
||||
cM('disabled', {
|
||||
cursor: 'not-allowed',
|
||||
opacity: 'var(--option-opacity-disabled)'
|
||||
}),
|
||||
cM('child-active', {
|
||||
color: 'var(--option-text-color-child-active)'
|
||||
}, [
|
||||
|
@ -23,7 +23,8 @@ export const self = (vars: ThemeCommonVars) => {
|
||||
heightMedium,
|
||||
heightLarge,
|
||||
heightHuge,
|
||||
textColor3
|
||||
textColor3,
|
||||
opacityDisabled
|
||||
} = vars
|
||||
return {
|
||||
...commonVariables,
|
||||
@ -60,7 +61,8 @@ export const self = (vars: ThemeCommonVars) => {
|
||||
prefixColorInverted: '#BBB',
|
||||
optionColorHoverInverted: primaryColor,
|
||||
optionColorActiveInverted: primaryColor,
|
||||
groupHeaderTextColorInverted: '#AAA'
|
||||
groupHeaderTextColorInverted: '#AAA',
|
||||
optionOpacityDisabled: opacityDisabled
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,4 +9,44 @@ describe('n-dropdown', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('dropdown disabled', async () => {
|
||||
const onSelect = jest.fn()
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: '滨海湾金沙,新加坡',
|
||||
key: 'marina bay sands',
|
||||
disabled: true
|
||||
}
|
||||
]
|
||||
const triggerEvent = 'click'
|
||||
const wrapper = mount(NDropdown, {
|
||||
attachTo: document.body,
|
||||
props: {
|
||||
options,
|
||||
trigger: triggerEvent,
|
||||
onSelect: onSelect
|
||||
},
|
||||
slots: {
|
||||
default: () => 'star kirby'
|
||||
}
|
||||
})
|
||||
|
||||
const triggerNodeWrapper = wrapper.find('span')
|
||||
expect(triggerNodeWrapper.exists()).toBe(true)
|
||||
await triggerNodeWrapper.trigger(triggerEvent)
|
||||
|
||||
const disabledMenu = document.querySelector(
|
||||
'.n-dropdown-option-body--disabled'
|
||||
) as HTMLDivElement
|
||||
|
||||
expect(disabledMenu).not.toEqual(null)
|
||||
|
||||
await disabledMenu.click()
|
||||
|
||||
expect(onSelect).not.toHaveBeenCalledWith()
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user