mirror of
https://github.com/element-plus/element-plus.git
synced 2025-04-06 16:30:35 +08:00
commit
4ea2be7966
1
.github/workflows/publish-pr-commit-pkg.yml
vendored
1
.github/workflows/publish-pr-commit-pkg.yml
vendored
@ -13,7 +13,6 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository == 'element-plus/element-plus' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
@ -1,5 +1,30 @@
|
||||
## Changelog
|
||||
|
||||
|
||||
### 2.9.1
|
||||
|
||||
_2024-12-13_
|
||||
|
||||
#### Features
|
||||
|
||||
- Components [dropdown] add triggerKeys attribute (#19124 by @hanchao-c0ldwave)
|
||||
- Components [tree-v2] `filter-method` support third parameter (#19177 by @btea)
|
||||
- Components [badge] add content slot (#18922 by @xing403)
|
||||
|
||||
#### Bug fixes
|
||||
|
||||
- Components [input-tag] trigger the add of tag when Chinese is Composing (#19079 by @tolking)
|
||||
- Components [notification] display html as string (#19068 by @Dsaquel)
|
||||
- Components [select] use option.isDisabled as the source of truth (#19137 by @makedopamine)
|
||||
- Components [input] disabled state wrapper cursor style (#19176 by @btea)
|
||||
- Components [select-v2] empty value check error in inputRef (#19140 by @Liao-js)
|
||||
- Components [select] modify the logic of update the watch option (#18931 by @YiMo1)
|
||||
- Components [table-v2] dynamic height causes overall calculation errors (#19082 by @hanchao-c0ldwave)
|
||||
- Revert pkg pr new to main version (#19254 by @Aslemammad)
|
||||
|
||||
#### Refactors
|
||||
|
||||
- Components [alert] introduce hasDesc helper (#19085 by @zhangenming)
|
||||
### 2.9.0
|
||||
|
||||
_2024-11-29_
|
||||
|
@ -100,11 +100,6 @@ You can also try Element Plus out with the components built-in playground.
|
||||
<img width="130px" src="https://user-images.githubusercontent.com/17680888/173179536-30e35fd1-cd5a-482a-bc41-9d5f0aa66fd4.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="http://www.i-renderer.love/home/index" target="_blank">
|
||||
<img width="130px" src="https://github.com/element-plus/element-plus/assets/82012629/0004917d-71ad-48f9-b3ce-9299f0ff78c6">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://bit.dev/?from=element-ui" target="_blank">
|
||||
<img width="130px" src="https://user-images.githubusercontent.com/10095631/41342907-e44e7196-6f2f-11e8-92f2-47702dc8f059.png">
|
||||
|
@ -21,14 +21,6 @@ export const rightLogoSmallSponsors = [
|
||||
slogan: 'Vue3 open source admin system',
|
||||
slogan_cn: 'Vue3企业级开源后台管理系统',
|
||||
},
|
||||
{
|
||||
name: '百搭云',
|
||||
img: '/images/baidayun-logo.png',
|
||||
imgL: '/images/baidayun.png',
|
||||
url: 'http://www.i-renderer.love/home/index',
|
||||
slogan: 'Fast and elegant low-code dev platform',
|
||||
slogan_cn: '快速且优雅的低代码平台',
|
||||
},
|
||||
{
|
||||
name: 'bit',
|
||||
img: '/images/bit.svg',
|
||||
|
@ -72,6 +72,7 @@ import OvTooltip from './ov-tooltip.vue'
|
||||
import OvDivider from './ov-divider.vue'
|
||||
import OvWatermark from './ov-watermark.vue'
|
||||
import OvMention from './ov-mention.vue'
|
||||
import OvInputTag from './ov-input-tag.vue'
|
||||
|
||||
export default {
|
||||
button: OvButton,
|
||||
@ -95,6 +96,7 @@ export default {
|
||||
form: OvForm,
|
||||
input: OvInput,
|
||||
'input-number': OvInputNumber,
|
||||
'input-tag': OvInputTag,
|
||||
radio: OvRadio,
|
||||
rate: OvRate,
|
||||
select: OvSelect,
|
||||
|
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<svg
|
||||
width="270"
|
||||
height="170"
|
||||
viewBox="0 0 270 170"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="270" height="170" rx="6" fill="var(--el-fill-color-light)" />
|
||||
<rect
|
||||
x="85.5"
|
||||
y="75.5"
|
||||
width="99"
|
||||
height="19"
|
||||
rx="1.5"
|
||||
fill="var(--el-fill-color-blank)"
|
||||
stroke="var(--el-color-primary)"
|
||||
/>
|
||||
<rect
|
||||
x="89"
|
||||
y="79"
|
||||
width="25"
|
||||
height="11.111"
|
||||
rx="1.852"
|
||||
fill="var(--el-color-primary-light-8)"
|
||||
/>
|
||||
<path
|
||||
d="M92.787 82.422h3.25v.556h-1.3v3.411h-.65v-3.411h-1.3v-.555zm4.973 1.017c.423 0 .74.106.94.317.177.183.266.45.266.8v1.833h-.589v-.378c-.111.145-.25.25-.411.328a1.56 1.56 0 0 1-.65.128c-.3 0-.533-.078-.706-.228a.746.746 0 0 1-.266-.589c0-.322.122-.572.378-.744.233-.167.56-.256.983-.267l.628-.016v-.112c0-.377-.206-.56-.617-.56-.178 0-.317.027-.422.094a.499.499 0 0 0-.24.333l-.627-.05c.061-.317.217-.55.467-.694.21-.134.5-.195.866-.195zm.573 1.639l-.584.017c-.505.01-.755.189-.755.533 0 .1.039.183.128.25.088.067.2.106.338.106.245 0 .45-.073.617-.212a.701.701 0 0 0 .256-.55v-.144zm2.496-1.639c.355 0 .639.139.85.428v-.35h.633v2.689c0 .905-.45 1.36-1.35 1.36-.406 0-.711-.077-.922-.221-.211-.156-.345-.39-.4-.711h.633c.033.16.1.272.206.338.1.062.261.095.483.095.478 0 .717-.256.717-.767v-.422a.997.997 0 0 1-.85.445c-.389 0-.706-.134-.945-.39-.244-.26-.36-.61-.36-1.044 0-.433.116-.783.36-1.05.239-.266.556-.4.945-.4zm.1.511c-.239 0-.423.084-.556.25-.133.161-.2.39-.2.69 0 .271.05.483.156.638.122.183.316.278.594.278.245 0 .433-.084.567-.24.128-.166.194-.388.194-.677 0-.294-.066-.522-.194-.689-.134-.166-.322-.25-.561-.25zM109.356 83.482l-.912.911-.911-.911a.12.12 0 0 0-.082-.033.108.108 0 0 0-.079.035.11.11 0 0 0-.035.08c0 .03.011.057.033.08l.911.912-.911.912c-.031.03-.042.068-.031.112.011.043.037.07.08.081.042.01.08 0 .114-.03l.911-.912.912.911a.118.118 0 0 0 .081.033.11.11 0 0 0 .08-.035.109.109 0 0 0 .034-.08.117.117 0 0 0-.033-.08l-.911-.912.911-.912a.11.11 0 0 0 .031-.112.105.105 0 0 0-.081-.081.11.11 0 0 0-.112.03z"
|
||||
fill="var(--el-color-primary)"
|
||||
/>
|
||||
<rect
|
||||
x="117"
|
||||
y="79"
|
||||
width="25"
|
||||
height="11.111"
|
||||
rx="1.852"
|
||||
fill="var(--el-color-primary-light-8)"
|
||||
/>
|
||||
<path
|
||||
d="M120.787 82.422h3.25v.556h-1.3v3.411h-.65v-3.411h-1.3v-.555zm4.973 1.017c.423 0 .739.106.939.317.178.183.267.45.267.8v1.833h-.589v-.378c-.111.145-.25.25-.411.328-.183.084-.4.128-.65.128-.3 0-.533-.078-.706-.228a.748.748 0 0 1-.266-.589c0-.322.122-.572.378-.744.233-.167.561-.256.983-.267l.628-.016v-.112c0-.377-.206-.56-.617-.56-.178 0-.317.027-.422.094a.498.498 0 0 0-.239.333l-.628-.05c.061-.317.217-.55.467-.694.211-.134.5-.195.866-.195zm.573 1.639l-.584.017c-.505.01-.755.189-.755.533 0 .1.039.183.128.25.088.067.2.106.338.106.245 0 .45-.073.617-.212a.7.7 0 0 0 .256-.55v-.144zm2.496-1.639c.355 0 .639.139.85.428v-.35h.633v2.689c0 .905-.45 1.36-1.35 1.36-.406 0-.711-.077-.922-.221-.211-.156-.345-.39-.4-.711h.633c.033.16.1.272.206.338.1.062.261.095.483.095.478 0 .717-.256.717-.767v-.422a.997.997 0 0 1-.85.445c-.389 0-.706-.134-.945-.39-.244-.26-.361-.61-.361-1.044 0-.433.117-.783.361-1.05.239-.266.556-.4.945-.4zm.1.511c-.239 0-.423.084-.556.25-.133.161-.2.39-.2.69 0 .271.05.483.156.638.122.183.316.278.594.278.245 0 .433-.084.567-.24.128-.166.194-.388.194-.677 0-.294-.066-.522-.194-.689-.134-.166-.322-.25-.561-.25zM137.356 83.482l-.912.911-.911-.911a.12.12 0 0 0-.082-.033.108.108 0 0 0-.079.035.11.11 0 0 0-.035.08c0 .03.011.057.033.08l.911.912-.911.912c-.031.03-.042.068-.031.112.011.043.037.07.08.081.042.01.08 0 .114-.03l.911-.912.912.911a.118.118 0 0 0 .081.033.11.11 0 0 0 .08-.035.109.109 0 0 0 .034-.08.117.117 0 0 0-.033-.08l-.911-.912.911-.912a.11.11 0 0 0 .031-.112.105.105 0 0 0-.081-.081.11.11 0 0 0-.112.03z"
|
||||
fill="var(--el-color-primary)"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
@ -10,7 +10,7 @@ const sponsor = computed(() => sponsorLocale[lang.value])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page-sidebar-group">
|
||||
<div class="page-sidebar-table">
|
||||
<p class="title">{{ sponsor.sponsoredBy }}</p>
|
||||
<VPSponsorLarge />
|
||||
<VPSponsorSmall />
|
||||
@ -18,7 +18,7 @@ const sponsor = computed(() => sponsorLocale[lang.value])
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-sidebar-group {
|
||||
.page-sidebar-table {
|
||||
padding-bottom: 10px;
|
||||
padding-top: 0;
|
||||
.title {
|
||||
|
1
docs/components.d.ts
vendored
1
docs/components.d.ts
vendored
@ -79,6 +79,7 @@ declare module 'vue' {
|
||||
OvInfiniteScroll: typeof import('./.vitepress/vitepress/components/overview-icons/ov-infinite-scroll.vue')['default']
|
||||
OvInput: typeof import('./.vitepress/vitepress/components/overview-icons/ov-input.vue')['default']
|
||||
OvInputNumber: typeof import('./.vitepress/vitepress/components/overview-icons/ov-input-number.vue')['default']
|
||||
OvInputTag: typeof import('./.vitepress/vitepress/components/overview-icons/ov-input-tag.vue')['default']
|
||||
OvLayout: typeof import('./.vitepress/vitepress/components/overview-icons/ov-layout.vue')['default']
|
||||
OvLink: typeof import('./.vitepress/vitepress/components/overview-icons/ov-link.vue')['default']
|
||||
OvLoading: typeof import('./.vitepress/vitepress/components/overview-icons/ov-loading.vue')['default']
|
||||
|
@ -29,9 +29,9 @@ badge/max
|
||||
|
||||
## Customizations
|
||||
|
||||
Displays text content other than numbers.
|
||||
Displays text content other than numbers. Or you can use the `content` slot to customize content.
|
||||
|
||||
:::demo When value is a String, it can display customized text.
|
||||
:::demo When value is a String, it can display customized text. Or use the `content` slot.
|
||||
|
||||
badge/customize
|
||||
|
||||
@ -74,6 +74,7 @@ badge/offset
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description |
|
||||
| ------- | ------------------------- |
|
||||
| default | customize default content |
|
||||
| Name | Description | Type |
|
||||
| ---------------- | ------------------------- | ---------------------------- |
|
||||
| default | customize default content | - |
|
||||
| content ^(2.9.1) | customize barge content | ^[object]`{ value: string }` |
|
||||
|
@ -31,7 +31,7 @@ card/simple
|
||||
|
||||
Display richer content by adding some configs.
|
||||
|
||||
:::demo The `body-style` attribute defines CSS style of custom `body`. This example also uses `el-col` for layout.
|
||||
:::demo The `body-style` attribute defines CSS style of custom `body`.
|
||||
|
||||
card/with-images
|
||||
|
||||
|
@ -92,7 +92,7 @@ dropdown/sizes
|
||||
### Dropdown Attributes
|
||||
|
||||
| Name | Description | Type | Default |
|
||||
| -------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
|
||||
| -------------------- |-----------------------------------------------------------------------------------------------------------------------| ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
|
||||
| type | menu button type, refer to `Button` Component, only works when `split-button` is true | ^[enum]`'' \| 'default' \| 'primary' \| 'success' \| 'warning' \| 'info' \| 'danger' \| 'text' (deprecated)` | '' |
|
||||
| size | menu size, also works on the split button | ^[enum]`'' \| 'large' \| 'default' \| 'small'` | '' |
|
||||
| max-height | the max height of menu | ^[string] / ^[number] | '' |
|
||||
@ -100,6 +100,7 @@ dropdown/sizes
|
||||
| disabled | whether to disable | ^[boolean] | false |
|
||||
| placement | placement of pop menu | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end'` | bottom |
|
||||
| trigger | how to trigger | ^[enum]`'hover' \| 'click' \| 'contextmenu'` | hover |
|
||||
| triggerKeys ^(2.9.1) | specify whick keys on the keyboard can trigger when pressed | ^[array]`string[]` | `['Enter', 'Space', 'ArrowDown', 'NumpadEnter']`
|
||||
| hide-on-click | whether to hide menu after clicking menu-item | ^[boolean] | true |
|
||||
| show-timeout | delay time before show a dropdown (only works when trigger is `hover`) | ^[number] | 150 |
|
||||
| hide-timeout | delay time before hide a dropdown (only works when trigger is `hover`) | ^[number] | 150 |
|
||||
|
@ -249,7 +249,7 @@ table/table-layout
|
||||
|
||||
| Name | Description | Type | Default |
|
||||
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
||||
| data | table data | ^[object]`any[]` | [] |
|
||||
| data | table data | ^[array]`any[]` | [] |
|
||||
| height | table's height. By default it has an `auto` height. If its value is a number, the height is measured in pixels; if its value is a string, the value will be assigned to element's style.height, the height is affected by external styles | ^[string] / ^[number] | — |
|
||||
| max-height | table's max-height. The legal value is a number or the height in px | ^[string] / ^[number] | — |
|
||||
| stripe | whether Table is striped | ^[boolean] | false |
|
||||
@ -270,7 +270,7 @@ table/table-layout
|
||||
| row-key | key of row data, used for optimizing rendering. Required if `reserve-selection` is on or display tree data. When its type is String, multi-level access is supported, e.g. `user.info.id`, but `user.info[0].id` is not supported, in which case `Function` should be used | ^[function]`(row: any) => string` / ^[string] | — |
|
||||
| empty-text | displayed text when data is empty. You can customize this area with `#empty` | ^[string] | No Data |
|
||||
| default-expand-all | whether expand all rows by default, works when the table has a column type="expand" or contains tree structure data | ^[boolean] | false |
|
||||
| expand-row-keys | set expanded rows by this prop, prop's value is the keys of expand rows, you should set row-key before using this prop | ^[Array]`string[]` | — |
|
||||
| expand-row-keys | set expanded rows by this prop, prop's value is the keys of expand rows, you should set row-key before using this prop | ^[array]`string[]` | — |
|
||||
| default-sort | set the default sort column and order. property `prop` is used to set default sort column, property `order` is used to set default sort order | ^[object]`Sort` | if `prop` is set, and `order` is not set, then `order` is default to ascending |
|
||||
| tooltip-effect | the `effect` of the overflow tooltip | ^[enum]`'dark' \| 'light'` | dark |
|
||||
| tooltip-options ^(2.2.28) | the options for the overflow tooltip, [see the following tooltip component](tooltip.html#attributes) | ^[object]`Pick<ElTooltipProps, 'effect' \| 'enterable' \| 'hideAfter' \| 'offset' \| 'placement' \| 'popperClass' \| 'popperOptions' \| 'showAfter' \| 'showArrow'>` | ^[object]`{ enterable: true, placement: 'top', showArrow: true, hideAfter: 200, popperOptions: { strategy: 'fixed' } }` |
|
||||
@ -370,7 +370,7 @@ table/table-layout
|
||||
| label-class-name | class name of the label of this column | ^[string] | — |
|
||||
| selectable | function that determines if a certain row can be selected, works when `type` is 'selection' | ^[Function]`(row: any, index: number) => boolean` | — |
|
||||
| reserve-selection | whether to reserve selection after data refreshing, works when `type` is 'selection'. Note that `row-key` is required for this to work | ^[boolean] | false |
|
||||
| filters | an array of data filtering options. For each element in this array, `text` and `value` are required | ^[object]`Array<{text: string, value: string}>` | — |
|
||||
| filters | an array of data filtering options. For each element in this array, `text` and `value` are required | ^[array]`Array<{text: string, value: string}>` | — |
|
||||
| filter-placement | placement for the filter dropdown | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | — |
|
||||
| filter-class-name ^(2.5.0) | className for the filter dropdown | ^[string] | — |
|
||||
| filter-multiple | whether data filtering supports multiple options | ^[boolean] | true |
|
||||
|
@ -132,7 +132,13 @@ tooltip/controlled
|
||||
|
||||
## Animations
|
||||
|
||||
Tooltip can be customized animated, you can set the desired animation function as you desired.
|
||||
Tooltip can be customized animated, you can set the desired animation use `transition`.
|
||||
|
||||
:::tip
|
||||
|
||||
Transition Classes, more information can be found at [Vue Transition](https://vuejs.org/guide/built-ins/transition.html#css-based-transitions).
|
||||
|
||||
:::
|
||||
|
||||
:::demo
|
||||
|
||||
|
@ -69,6 +69,9 @@ tree-v2/custom-node-class
|
||||
|
||||
## Tree node filtering
|
||||
|
||||
::: ^(2.9.1)
|
||||
The `filter-method` method can only accept the third parameter after version 2.9.1.
|
||||
:::
|
||||
Tree nodes can be filtered
|
||||
|
||||
:::demo Invoke the `filter` method of the Tree instance to filter tree nodes. Its parameter is the filtering keyword. Note that for it to work, `filter-method` is required, and its value is the filtering method.
|
||||
@ -79,33 +82,33 @@ tree-v2/filter
|
||||
|
||||
## TreeV2 Attributes
|
||||
|
||||
| Name | Description | Type | Default |
|
||||
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ------- |
|
||||
| data | tree data | array | — |
|
||||
| empty-text | text displayed when data is void | string | — |
|
||||
| props | configuration options, see the following table | object | — |
|
||||
| highlight-current | whether current node is highlighted | boolean | false |
|
||||
| expand-on-click-node | whether to expand or collapse node when clicking on the node, if false, then expand or collapse node only when clicking on the arrow icon. | boolean | true |
|
||||
| check-on-click-node | whether to check or uncheck node when clicking on the node, if false, the node can only be checked or unchecked by clicking on the checkbox. | boolean | false |
|
||||
| default-expanded-keys | array of keys of initially expanded nodes | array | — |
|
||||
| show-checkbox | whether node is selectable | boolean | false |
|
||||
| check-strictly | whether checked state of a node not affects its father and child nodes when `show-checkbox` is `true` | boolean | false |
|
||||
| default-checked-keys | array of keys of initially checked nodes | array | — |
|
||||
| current-node-key | key of initially selected node | string / number | — |
|
||||
| filter-method | this function will be executed on each node when use filter method. if return `false`, tree node will be hidden. | Function(value, data) | — |
|
||||
| indent | horizontal indentation of nodes in adjacent levels in pixels | number | 16 |
|
||||
| icon | custom tree node icon | `string \| Component` | — |
|
||||
| item-size ^(2.2.33) | custom tree node height | number | 26 |
|
||||
| Name | Description | Type | Default |
|
||||
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | ------- |
|
||||
| data | tree data | array | — |
|
||||
| empty-text | text displayed when data is void | string | — |
|
||||
| props | configuration options, see the following table | object | — |
|
||||
| highlight-current | whether current node is highlighted | boolean | false |
|
||||
| expand-on-click-node | whether to expand or collapse node when clicking on the node, if false, then expand or collapse node only when clicking on the arrow icon. | boolean | true |
|
||||
| check-on-click-node | whether to check or uncheck node when clicking on the node, if false, the node can only be checked or unchecked by clicking on the checkbox. | boolean | false |
|
||||
| default-expanded-keys | array of keys of initially expanded nodes | array | — |
|
||||
| show-checkbox | whether node is selectable | boolean | false |
|
||||
| check-strictly | whether checked state of a node not affects its father and child nodes when `show-checkbox` is `true` | boolean | false |
|
||||
| default-checked-keys | array of keys of initially checked nodes | array | — |
|
||||
| current-node-key | key of initially selected node | string / number | — |
|
||||
| filter-method | this function will be executed on each node when use filter method. if return `false`, tree node will be hidden. | Function(value, data, node) | — |
|
||||
| indent | horizontal indentation of nodes in adjacent levels in pixels | number | 16 |
|
||||
| icon | custom tree node icon | `string \| Component` | — |
|
||||
| item-size ^(2.2.33) | custom tree node height | number | 26 |
|
||||
|
||||
## props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
| -------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------ | -------- |
|
||||
| value | unique identity key name for nodes, its value should be unique across the whole tree | string | id |
|
||||
| label | specify which key of node object is used as the node's label | string | label |
|
||||
| children | specify which node object is used as the node's subtree | string | children |
|
||||
| disabled | specify which key of node object represents if node's checkbox is disabled | string | disabled |
|
||||
| class ^(2.9.0) | custom node class name | ^[string] \| ^[Function]`(data, node) => string` | — |
|
||||
| Attribute | Description | Type | Default |
|
||||
| -------------- | ------------------------------------------------------------------------------------ | ----------------------------------------------- | -------- |
|
||||
| value | unique identity key name for nodes, its value should be unique across the whole tree | string | id |
|
||||
| label | specify which key of node object is used as the node's label | string | label |
|
||||
| children | specify which node object is used as the node's subtree | string | children |
|
||||
| disabled | specify which key of node object represents if node's checkbox is disabled | string | disabled |
|
||||
| class ^(2.9.0) | custom node class name | ^[string] / ^[Function]`(data, node) => string` | — |
|
||||
|
||||
## TreeV2 Method
|
||||
|
||||
|
@ -5,11 +5,31 @@
|
||||
<el-badge value="hot" class="item">
|
||||
<el-button>replies</el-button>
|
||||
</el-badge>
|
||||
<el-badge value="99" class="item">
|
||||
<el-button>share</el-button>
|
||||
<template #content="{ value }">
|
||||
<div class="custom-content">
|
||||
<el-icon>
|
||||
<Message />
|
||||
</el-icon>
|
||||
<span>{{ value }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-badge>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Message } from '@element-plus/icons-vue'
|
||||
</script>
|
||||
<style scoped>
|
||||
.item {
|
||||
margin-top: 10px;
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
.custom-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
}
|
||||
</style>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<el-container>
|
||||
<el-aside width="200px">Aside</el-aside>
|
||||
<el-main>Main</el-main>
|
||||
<el-aside width="200px">Aside</el-aside>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -16,17 +16,3 @@ import { ref } from 'vue'
|
||||
|
||||
const disabled = ref(false)
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.slide-fade-enter-active {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.slide-fade-leave-active {
|
||||
transition: all 0.3s cubic-bezier(1, 0.5, 0.8, 1);
|
||||
}
|
||||
.slide-fade-enter,
|
||||
.expand-fade-leave-active {
|
||||
margin-left: 20px;
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,7 +1,22 @@
|
||||
<template>
|
||||
<el-tooltip content="I am an el-tooltip">
|
||||
<el-tooltip content="I am an el-tooltip" transition="slide-fade">
|
||||
<el-button>trigger me</el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup></script>
|
||||
<style>
|
||||
.slide-fade-enter-active {
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
|
||||
.slide-fade-leave-active {
|
||||
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
|
||||
}
|
||||
|
||||
.slide-fade-enter-from,
|
||||
.slide-fade-leave-to {
|
||||
transform: translateX(120px);
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -5,18 +5,21 @@
|
||||
:class="[ns.b(), ns.m(type), ns.is('center', center), ns.is(effect)]"
|
||||
role="alert"
|
||||
>
|
||||
<el-icon v-if="showIcon && iconComponent" :class="iconClass">
|
||||
<el-icon
|
||||
v-if="showIcon && iconComponent"
|
||||
:class="[ns.e('icon'), { [ns.is('big')]: hasDesc }]"
|
||||
>
|
||||
<component :is="iconComponent" />
|
||||
</el-icon>
|
||||
|
||||
<div :class="ns.e('content')">
|
||||
<span
|
||||
v-if="title || $slots.title"
|
||||
:class="[ns.e('title'), withDescription]"
|
||||
:class="[ns.e('title'), { 'with-description': hasDesc }]"
|
||||
>
|
||||
<slot name="title">{{ title }}</slot>
|
||||
</span>
|
||||
<p v-if="$slots.default || description" :class="ns.e('description')">
|
||||
<p v-if="hasDesc" :class="ns.e('description')">
|
||||
<slot>
|
||||
{{ description }}
|
||||
</slot>
|
||||
@ -60,14 +63,7 @@ const visible = ref(true)
|
||||
|
||||
const iconComponent = computed(() => TypeComponentsMap[props.type])
|
||||
|
||||
const iconClass = computed(() => [
|
||||
ns.e('icon'),
|
||||
{ [ns.is('big')]: !!props.description || !!slots.default },
|
||||
])
|
||||
|
||||
const withDescription = computed(() => {
|
||||
return { 'with-description': props.description || slots.default }
|
||||
})
|
||||
const hasDesc = computed(() => !!(props.description || slots.default))
|
||||
|
||||
const close = (evt: MouseEvent) => {
|
||||
visible.value = false
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { nextTick, ref } from 'vue'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { describe, expect, test } from 'vitest'
|
||||
import { InfoFilled } from '@element-plus/icons-vue'
|
||||
import { ElIcon } from '@element-plus/components/icon'
|
||||
import Badge from '../src/badge.vue'
|
||||
|
||||
const AXIOM = 'Rem is the best girl'
|
||||
@ -146,4 +148,23 @@ describe('Badge', () => {
|
||||
'margin-top: 10px'
|
||||
)
|
||||
})
|
||||
|
||||
test('content slot', () => {
|
||||
const wrapper = mount(() => (
|
||||
<Badge
|
||||
value={99}
|
||||
v-slots={{
|
||||
content: ({ value }: { value: string }) => (
|
||||
<div class="custom">
|
||||
<ElIcon>
|
||||
<InfoFilled />
|
||||
</ElIcon>
|
||||
<span>{value}</span>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
))
|
||||
expect(wrapper.find('.el-badge__content .custom').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
@ -3,7 +3,7 @@
|
||||
<slot />
|
||||
<transition :name="`${ns.namespace.value}-zoom-in-center`">
|
||||
<sup
|
||||
v-show="!hidden && (content || isDot)"
|
||||
v-show="!hidden && (content || isDot || $slots.content)"
|
||||
:class="[
|
||||
ns.e('content'),
|
||||
ns.em('content', type),
|
||||
@ -13,8 +13,11 @@
|
||||
badgeClass,
|
||||
]"
|
||||
:style="style"
|
||||
v-text="content"
|
||||
/>
|
||||
>
|
||||
<slot name="content" :value="content">
|
||||
{{ content }}
|
||||
</slot>
|
||||
</sup>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -30,6 +30,15 @@ export const dropdownProps = buildProps({
|
||||
* @description how to trigger
|
||||
*/
|
||||
trigger: useTooltipTriggerProps.trigger,
|
||||
triggerKeys: {
|
||||
type: definePropType<string[]>(Array),
|
||||
default: () => [
|
||||
EVENT_CODE.enter,
|
||||
EVENT_CODE.numpadEnter,
|
||||
EVENT_CODE.space,
|
||||
EVENT_CODE.down,
|
||||
],
|
||||
},
|
||||
effect: {
|
||||
...useTooltipContentProps.effect,
|
||||
default: 'light',
|
||||
|
@ -112,7 +112,6 @@ import { ElOnlyChild } from '@element-plus/components/slot'
|
||||
import { useFormSize } from '@element-plus/components/form'
|
||||
import { addUnit, ensureArray } from '@element-plus/utils'
|
||||
import { ArrowDown } from '@element-plus/icons-vue'
|
||||
import { EVENT_CODE } from '@element-plus/constants'
|
||||
import { useId, useLocale, useNamespace } from '@element-plus/hooks'
|
||||
import { ElCollection as ElDropdownCollection, dropdownProps } from './dropdown'
|
||||
import { DROPDOWN_INJECTION_KEY } from './tokens'
|
||||
@ -148,12 +147,6 @@ export default defineComponent({
|
||||
const scrollbar = ref(null)
|
||||
const currentTabId = ref<string | null>(null)
|
||||
const isUsingKeyboard = ref(false)
|
||||
const triggerKeys = [
|
||||
EVENT_CODE.enter,
|
||||
EVENT_CODE.numpadEnter,
|
||||
EVENT_CODE.space,
|
||||
EVENT_CODE.down,
|
||||
]
|
||||
|
||||
const wrapStyle = computed<CSSProperties>(() => ({
|
||||
maxHeight: addUnit(props.maxHeight),
|
||||
@ -300,7 +293,6 @@ export default defineComponent({
|
||||
dropdownTriggerKls,
|
||||
dropdownSize,
|
||||
triggerId,
|
||||
triggerKeys,
|
||||
currentTabId,
|
||||
handleCurrentTabIdChange,
|
||||
handlerMainButtonClick,
|
||||
|
@ -14,7 +14,7 @@ import { rAF } from '@element-plus/test-utils/tick'
|
||||
import Input from '@element-plus/components/input'
|
||||
import Form from '../src/form.vue'
|
||||
import FormItem from '../src/form-item.vue'
|
||||
import DynamicFormItem from '../mocks/mock-data'
|
||||
import DynamicFormItem from './mock-data'
|
||||
|
||||
import type { VueWrapper } from '@vue/test-utils'
|
||||
import type { MockInstance } from 'vitest'
|
||||
|
@ -19,7 +19,7 @@ import {
|
||||
import Input from '@element-plus/components/input'
|
||||
import Form from '../src/form.vue'
|
||||
import FormItem from '../src/form-item.vue'
|
||||
import DynamicDomainForm, { formatDomainError } from '../mocks/mock-data'
|
||||
import DynamicDomainForm, { formatDomainError } from './mock-data'
|
||||
|
||||
import type { VueWrapper } from '@vue/test-utils'
|
||||
import type { FormRules } from '@element-plus/components/form'
|
||||
|
@ -51,6 +51,7 @@ export function useInputTag({ props, emit, formItem }: UseInputTagOptions) {
|
||||
}
|
||||
|
||||
const handleKeydown = (event: KeyboardEvent) => {
|
||||
if (isComposing.value) return
|
||||
switch (event.code) {
|
||||
case props.trigger:
|
||||
event.preventDefault()
|
||||
|
@ -140,7 +140,7 @@ export const menuProps = buildProps({
|
||||
* @description Tooltip theme, built-in theme: `dark` / `light` when menu is collapsed
|
||||
*/
|
||||
popperEffect: {
|
||||
type: definePropType<PopperEffect | string>(String),
|
||||
type: definePropType<PopperEffect>(String),
|
||||
default: 'dark',
|
||||
},
|
||||
/**
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createVNode, render } from 'vue'
|
||||
import { createVNode, isVNode, render } from 'vue'
|
||||
import {
|
||||
debugWarn,
|
||||
hasOwn,
|
||||
@ -8,7 +8,6 @@ import {
|
||||
isObject,
|
||||
isString,
|
||||
isUndefined,
|
||||
isVNode,
|
||||
} from '@element-plus/utils'
|
||||
import MessageBoxConstructor from './index.vue'
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createVNode, render } from 'vue'
|
||||
import { createVNode, isVNode, render } from 'vue'
|
||||
import {
|
||||
debugWarn,
|
||||
isBoolean,
|
||||
@ -7,7 +7,6 @@ import {
|
||||
isFunction,
|
||||
isNumber,
|
||||
isString,
|
||||
isVNode,
|
||||
} from '@element-plus/utils'
|
||||
import { messageConfig } from '@element-plus/components/config-provider'
|
||||
import MessageConstructor from './message.vue'
|
||||
|
@ -40,6 +40,18 @@ describe('Notification on command', () => {
|
||||
close()
|
||||
})
|
||||
|
||||
it('it should be able to render function that return vnode', async () => {
|
||||
const testClassName = 'test-classname'
|
||||
const { close } = Notification({
|
||||
duration: 0,
|
||||
message: () => <div class={testClassName}>test-content</div>,
|
||||
})
|
||||
|
||||
await rAF()
|
||||
expect(document.querySelector(`.${testClassName}`)).toBeTruthy()
|
||||
close()
|
||||
})
|
||||
|
||||
it('it should be able to close notification by manually close', async () => {
|
||||
const { close } = Notification({
|
||||
duration: 0,
|
||||
@ -137,4 +149,31 @@ describe('Notification on command', () => {
|
||||
expect(onClose).toHaveBeenCalledTimes(1)
|
||||
expect(onClose).toHaveLastReturnedWith(localContext)
|
||||
})
|
||||
|
||||
it('set dangerouslyUseHTMLString should render html string', async () => {
|
||||
const htmlString = '<div class="test-html-string">test-html-string</div>'
|
||||
const { close } = Notification({
|
||||
duration: 0,
|
||||
message: htmlString,
|
||||
dangerouslyUseHTMLString: true,
|
||||
})
|
||||
|
||||
await rAF()
|
||||
expect(document.querySelector('.test-html-string')).toBeDefined()
|
||||
close()
|
||||
})
|
||||
|
||||
it('not set dangerouslyUseHTMLString should render text', async () => {
|
||||
const text = '<div class="test-html-string">test-html-string</div>'
|
||||
const { close } = Notification({
|
||||
duration: 0,
|
||||
message: text,
|
||||
})
|
||||
|
||||
await rAF()
|
||||
expect(
|
||||
document.querySelector('.el-notification__content')!.textContent
|
||||
).toBe(text)
|
||||
close()
|
||||
})
|
||||
})
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createVNode, render } from 'vue'
|
||||
import { createVNode, isVNode, render } from 'vue'
|
||||
import {
|
||||
debugWarn,
|
||||
isClient,
|
||||
@ -6,7 +6,6 @@ import {
|
||||
isFunction,
|
||||
isString,
|
||||
isUndefined,
|
||||
isVNode,
|
||||
} from '@element-plus/utils'
|
||||
import NotificationConstructor from './notification.vue'
|
||||
import { notificationTypes } from './notification'
|
||||
@ -82,7 +81,11 @@ const notify: NotifyFn & Partial<Notify> = function (options = {}, context) {
|
||||
const vm = createVNode(
|
||||
NotificationConstructor,
|
||||
props,
|
||||
isFunction(props.message) ? props.message : () => props.message
|
||||
isFunction(props.message)
|
||||
? props.message
|
||||
: isVNode(props.message)
|
||||
? () => props.message
|
||||
: null
|
||||
)
|
||||
vm.appContext = isUndefined(context) ? notify._context : context
|
||||
|
||||
|
@ -74,7 +74,7 @@ export const popperContentProps = buildProps({
|
||||
type: definePropType<ClassType>([String, Array, Object]),
|
||||
},
|
||||
effect: {
|
||||
type: definePropType<PopperEffect | string>(String),
|
||||
type: definePropType<PopperEffect>(String),
|
||||
default: 'dark',
|
||||
},
|
||||
visible: Boolean,
|
||||
|
@ -24,7 +24,9 @@ export const roleTypes = [
|
||||
'tree',
|
||||
] as const
|
||||
|
||||
export type PopperEffect = typeof effects[number]
|
||||
export type PopperEffect =
|
||||
| typeof effects[number]
|
||||
| (string & NonNullable<unknown>)
|
||||
export type PopperTrigger = typeof triggers[number]
|
||||
|
||||
export const popperProps = buildProps({
|
||||
|
@ -1371,6 +1371,31 @@ describe('Select', () => {
|
||||
expect(placeholder.text()).toBe('option_a')
|
||||
})
|
||||
|
||||
it('the scroll position of the dropdown should be correct when value is 0', async () => {
|
||||
const options = Array.from({ length: 1000 }).map((_, idx) => ({
|
||||
value: 999 - idx,
|
||||
label: `options ${999 - idx}`,
|
||||
}))
|
||||
const wrapper = createSelect({
|
||||
data() {
|
||||
return {
|
||||
value: 0,
|
||||
options,
|
||||
}
|
||||
},
|
||||
})
|
||||
await nextTick()
|
||||
await wrapper.find(`.${WRAPPER_CLASS_NAME}`).trigger('click')
|
||||
const optionsDoms = Array.from(
|
||||
document.querySelectorAll(`.${OPTION_ITEM_CLASS_NAME}`)
|
||||
)
|
||||
const result = optionsDoms.some((option) => {
|
||||
const text = option.textContent
|
||||
return text === 'options 0'
|
||||
})
|
||||
expect(result).toBeTruthy()
|
||||
})
|
||||
|
||||
it('emptyText error show', async () => {
|
||||
const wrapper = createSelect({
|
||||
data() {
|
||||
|
@ -57,7 +57,7 @@ export const SelectProps = buildProps({
|
||||
* @description tooltip theme, built-in theme: `dark` / `light`
|
||||
*/
|
||||
effect: {
|
||||
type: definePropType<PopperEffect | string>(String),
|
||||
type: definePropType<PopperEffect>(String),
|
||||
default: 'light',
|
||||
},
|
||||
/**
|
||||
|
@ -330,7 +330,7 @@ const useSelect = (props: ISelectV2Props, emit: SelectEmitFn) => {
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
props.modelValue &&
|
||||
!isEmptyValue(props.modelValue) &&
|
||||
filteredOptionsValueMap.value.has(props.modelValue)
|
||||
) {
|
||||
const { index } = filteredOptionsValueMap.value.get(props.modelValue)
|
||||
|
@ -905,6 +905,23 @@ describe('Select', () => {
|
||||
expect(selectVm.states.hoveringIndex).toBe(4)
|
||||
})
|
||||
|
||||
// #19136
|
||||
test('keyboard operations when options are disabled due to multiple-limit', async () => {
|
||||
wrapper = getSelectVm({ multiple: true, multipleLimit: 2 })
|
||||
const select = wrapper.findComponent({ name: 'ElSelect' })
|
||||
await wrapper.setProps({
|
||||
modelValue: ['选项1', '选项2'],
|
||||
})
|
||||
const selectVm = select.vm as any
|
||||
const input = select.find('input')
|
||||
await input.trigger('click')
|
||||
expect(selectVm.states.hoveringIndex).toBe(0)
|
||||
selectVm.navigateOptions('next')
|
||||
expect(selectVm.states.hoveringIndex).toBe(1)
|
||||
selectVm.navigateOptions('next')
|
||||
expect(selectVm.states.hoveringIndex).toBe(0)
|
||||
})
|
||||
|
||||
test('clearable', async () => {
|
||||
wrapper = getSelectVm({ clearable: true })
|
||||
const select = wrapper.findComponent({ name: 'ElSelect' })
|
||||
|
@ -49,7 +49,7 @@ export const SelectProps = buildProps({
|
||||
* @description tooltip theme, built-in theme: `dark` / `light`
|
||||
*/
|
||||
effect: {
|
||||
type: definePropType<PopperEffect | string>(String),
|
||||
type: definePropType<PopperEffect>(String),
|
||||
default: 'light',
|
||||
},
|
||||
/**
|
||||
|
@ -312,15 +312,7 @@ export const useSelect = (props: ISelectProps, emit) => {
|
||||
() => {
|
||||
if (!isClient) return
|
||||
// tooltipRef.value?.updatePopper?.()
|
||||
const inputs = selectRef.value?.querySelectorAll('input') || []
|
||||
if (
|
||||
(!props.filterable &&
|
||||
!props.defaultFirstOption &&
|
||||
!isUndefined(props.modelValue)) ||
|
||||
!Array.from(inputs).includes(document.activeElement as HTMLInputElement)
|
||||
) {
|
||||
setSelected()
|
||||
}
|
||||
setSelected()
|
||||
if (
|
||||
props.defaultFirstOption &&
|
||||
(props.filterable || props.remote) &&
|
||||
@ -697,7 +689,7 @@ export const useSelect = (props: ISelectProps, emit) => {
|
||||
toggleMenu()
|
||||
} else {
|
||||
const option = optionsArray.value[states.hoveringIndex]
|
||||
if (option && !option.disabled && !option.states.groupDisabled) {
|
||||
if (option && !option.isDisabled) {
|
||||
handleOptionSelect(option)
|
||||
}
|
||||
}
|
||||
@ -710,7 +702,7 @@ export const useSelect = (props: ISelectProps, emit) => {
|
||||
const optionsAllDisabled = computed(() =>
|
||||
optionsArray.value
|
||||
.filter((option) => option.visible)
|
||||
.every((option) => option.disabled)
|
||||
.every((option) => option.isDisabled)
|
||||
)
|
||||
|
||||
const showTagList = computed(() => {
|
||||
@ -756,11 +748,7 @@ export const useSelect = (props: ISelectProps, emit) => {
|
||||
}
|
||||
}
|
||||
const option = optionsArray.value[states.hoveringIndex]
|
||||
if (
|
||||
option.disabled === true ||
|
||||
option.states.groupDisabled === true ||
|
||||
!option.visible
|
||||
) {
|
||||
if (option.isDisabled || !option.visible) {
|
||||
navigateOptions(direction)
|
||||
}
|
||||
nextTick(() => scrollToOption(hoverOption.value))
|
||||
|
@ -1,24 +1,23 @@
|
||||
import { computed, unref } from 'vue'
|
||||
import { ComputedRef, computed, unref } from 'vue'
|
||||
import { addUnit, isNumber } from '@element-plus/utils'
|
||||
import { enforceUnit, sum } from '../utils'
|
||||
|
||||
import type { CSSProperties } from 'vue'
|
||||
import type { TableV2Props } from '../table'
|
||||
import type { UseColumnsReturn } from './use-columns'
|
||||
import type { UseDataReturn } from './use-data'
|
||||
|
||||
type UseStyleProps = {
|
||||
columnsTotalWidth: UseColumnsReturn['columnsTotalWidth']
|
||||
data: UseDataReturn['data']
|
||||
fixedColumnsOnLeft: UseColumnsReturn['fixedColumnsOnLeft']
|
||||
fixedColumnsOnRight: UseColumnsReturn['fixedColumnsOnRight']
|
||||
rowsHeight: ComputedRef<number>
|
||||
}
|
||||
|
||||
export const useStyles = (
|
||||
props: TableV2Props,
|
||||
{
|
||||
columnsTotalWidth,
|
||||
data,
|
||||
rowsHeight,
|
||||
fixedColumnsOnLeft,
|
||||
fixedColumnsOnRight,
|
||||
}: UseStyleProps
|
||||
@ -47,16 +46,6 @@ export const useStyles = (
|
||||
return height - footerHeight
|
||||
})
|
||||
|
||||
const rowsHeight = computed(() => {
|
||||
const { rowHeight, estimatedRowHeight } = props
|
||||
const _data = unref(data)
|
||||
if (isNumber(estimatedRowHeight)) {
|
||||
return _data.length * estimatedRowHeight
|
||||
}
|
||||
|
||||
return _data.length * rowHeight
|
||||
})
|
||||
|
||||
const fixedTableHeight = computed(() => {
|
||||
const { maxHeight } = props
|
||||
const tableHeight = unref(mainTableHeight)
|
||||
@ -114,7 +103,6 @@ export const useStyles = (
|
||||
leftTableWidth,
|
||||
rightTableWidth,
|
||||
headerWidth,
|
||||
rowsHeight,
|
||||
windowHeight,
|
||||
footerHeight,
|
||||
emptyStyle,
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
unref,
|
||||
watch,
|
||||
} from 'vue'
|
||||
import { isArray } from '@element-plus/utils'
|
||||
import { isArray, isNumber } from '@element-plus/utils'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import {
|
||||
useColumns,
|
||||
@ -84,6 +84,20 @@ function useTable(props: TableV2Props) {
|
||||
resetAfterIndex,
|
||||
})
|
||||
|
||||
const rowsHeight = computed(() => {
|
||||
const { estimatedRowHeight, rowHeight } = props
|
||||
const _data = unref(data)
|
||||
if (isNumber(estimatedRowHeight)) {
|
||||
// calculate the actual height
|
||||
return Object.values(unref(rowHeights)).reduce(
|
||||
(acc, curr) => acc + curr,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
return _data.length * rowHeight
|
||||
})
|
||||
|
||||
const {
|
||||
bodyWidth,
|
||||
fixedTableHeight,
|
||||
@ -91,7 +105,6 @@ function useTable(props: TableV2Props) {
|
||||
leftTableWidth,
|
||||
rightTableWidth,
|
||||
headerWidth,
|
||||
rowsHeight,
|
||||
windowHeight,
|
||||
footerHeight,
|
||||
emptyStyle,
|
||||
@ -99,9 +112,9 @@ function useTable(props: TableV2Props) {
|
||||
headerHeight,
|
||||
} = useStyles(props, {
|
||||
columnsTotalWidth,
|
||||
data,
|
||||
fixedColumnsOnLeft,
|
||||
fixedColumnsOnRight,
|
||||
rowsHeight,
|
||||
})
|
||||
|
||||
// DOM/Component refs
|
||||
|
@ -32,7 +32,7 @@ export const timeSelectProps = buildProps({
|
||||
* @description Tooltip theme, built-in theme: `dark` / `light`
|
||||
*/
|
||||
effect: {
|
||||
type: definePropType<PopperEffect | string>(String),
|
||||
type: definePropType<PopperEffect>(String),
|
||||
default: 'light',
|
||||
},
|
||||
/**
|
||||
|
@ -28,7 +28,7 @@ export const tooltipV2ContentProps = buildProps({
|
||||
default: 5,
|
||||
},
|
||||
effect: {
|
||||
type: definePropType<PopperEffect | string>(String),
|
||||
type: definePropType<PopperEffect>(String),
|
||||
default: 'light',
|
||||
},
|
||||
contentClass: String,
|
||||
|
@ -80,7 +80,8 @@ export function useCheck(props: TreeProps, tree: Ref<Tree | undefined>) {
|
||||
const toggleCheckbox = (
|
||||
node: TreeNode,
|
||||
isChecked: CheckboxValueType,
|
||||
nodeClick = true
|
||||
nodeClick = true,
|
||||
immediateUpdate = true
|
||||
) => {
|
||||
const checkedKeySet = checkedKeys.value
|
||||
const toggle = (node: TreeNode, checked: CheckboxValueType) => {
|
||||
@ -97,7 +98,9 @@ export function useCheck(props: TreeProps, tree: Ref<Tree | undefined>) {
|
||||
}
|
||||
}
|
||||
toggle(node, isChecked)
|
||||
updateCheckedKeys()
|
||||
if (immediateUpdate) {
|
||||
updateCheckedKeys()
|
||||
}
|
||||
if (nodeClick) {
|
||||
afterNodeCheck(node, isChecked)
|
||||
}
|
||||
@ -196,13 +199,14 @@ export function useCheck(props: TreeProps, tree: Ref<Tree | undefined>) {
|
||||
function _setCheckedKeys(keys: TreeKey[]) {
|
||||
if (tree?.value) {
|
||||
const { treeNodeMap } = tree.value
|
||||
if (props.showCheckbox && treeNodeMap && keys) {
|
||||
if (props.showCheckbox && treeNodeMap && keys?.length > 0) {
|
||||
for (const key of keys) {
|
||||
const node = treeNodeMap.get(key)
|
||||
if (node && !isChecked(node)) {
|
||||
toggleCheckbox(node, true, false)
|
||||
toggleCheckbox(node, true, false, false)
|
||||
}
|
||||
}
|
||||
updateCheckedKeys()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ export function useFilter(props: TreeProps, tree: Ref<Tree | undefined>) {
|
||||
function traverse(nodes: TreeNode[]) {
|
||||
nodes.forEach((node) => {
|
||||
family.push(node)
|
||||
if (filter?.(query, node.data)) {
|
||||
if (filter?.(query, node.data, node)) {
|
||||
family.forEach((member) => {
|
||||
expandKeySet.add(member.key)
|
||||
})
|
||||
|
@ -48,7 +48,11 @@ export interface Tree {
|
||||
maxLevel: number
|
||||
}
|
||||
|
||||
export type FilterMethod = (query: string, node: TreeNodeData) => boolean
|
||||
export type FilterMethod = (
|
||||
query: string,
|
||||
data: TreeNodeData,
|
||||
node: TreeNode
|
||||
) => boolean
|
||||
|
||||
export interface CheckedInfo {
|
||||
checkedKeys: TreeKey[]
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { shallowRef } from 'vue'
|
||||
import { flattedChildren, isVNode } from '@element-plus/utils'
|
||||
import { isVNode, shallowRef } from 'vue'
|
||||
import { flattedChildren } from '@element-plus/utils'
|
||||
|
||||
import type { ComponentInternalInstance, VNode } from 'vue'
|
||||
|
||||
|
@ -319,6 +319,7 @@
|
||||
|
||||
.#{$namespace}-input__wrapper {
|
||||
background-color: map.get($input-disabled, 'fill');
|
||||
cursor: not-allowed;
|
||||
@include mixed-input-border(map.get($input-disabled, 'border'));
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
import * as vue from 'vue'
|
||||
import * as vueShared from '@vue/shared'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
@ -15,7 +14,6 @@ import {
|
||||
isString,
|
||||
isSymbol,
|
||||
isUndefined,
|
||||
isVNode,
|
||||
} from '..'
|
||||
|
||||
describe('types', () => {
|
||||
@ -29,10 +27,6 @@ describe('types', () => {
|
||||
expect(isSymbol).toBe(vueShared.isSymbol)
|
||||
})
|
||||
|
||||
it('re-export from vue', () => {
|
||||
expect(isVNode).toBe(vue.isVNode)
|
||||
})
|
||||
|
||||
it('isBoolean and isNumber should work', () => {
|
||||
expect(isBoolean(true)).toBe(true)
|
||||
expect(isBoolean(false)).toBe(true)
|
||||
|
@ -11,7 +11,6 @@ export {
|
||||
isSymbol,
|
||||
isPlainObject,
|
||||
} from '@vue/shared'
|
||||
export { isVNode } from 'vue'
|
||||
|
||||
export const isUndefined = (val: any): val is undefined => val === undefined
|
||||
export const isBoolean = (val: any): val is boolean => typeof val === 'boolean'
|
||||
|
@ -8,7 +8,6 @@ import Inspect from 'vite-plugin-inspect'
|
||||
import mkcert from 'vite-plugin-mkcert'
|
||||
import glob from 'fast-glob'
|
||||
import VueMacros from 'unplugin-vue-macros/vite'
|
||||
import esbuild from 'rollup-plugin-esbuild'
|
||||
import {
|
||||
epPackage,
|
||||
epRoot,
|
||||
@ -16,17 +15,6 @@ import {
|
||||
pkgRoot,
|
||||
projRoot,
|
||||
} from '@element-plus/build-utils'
|
||||
import type { Plugin } from 'vite'
|
||||
|
||||
const esbuildPlugin = (): Plugin => ({
|
||||
...esbuild({
|
||||
target: 'chrome64',
|
||||
loaders: {
|
||||
'.vue': 'js',
|
||||
},
|
||||
}),
|
||||
enforce: 'post',
|
||||
})
|
||||
|
||||
export default defineConfig(async ({ mode }) => {
|
||||
const env = loadEnv(mode, process.cwd(), '')
|
||||
@ -74,7 +62,6 @@ export default defineConfig(async ({ mode }) => {
|
||||
vueJsx: vueJsx(),
|
||||
},
|
||||
}),
|
||||
esbuildPlugin(),
|
||||
Components({
|
||||
include: `${__dirname}/**`,
|
||||
resolvers: ElementPlusResolver({
|
||||
|
Loading…
x
Reference in New Issue
Block a user