diff --git a/examples/App.vue b/examples/App.vue
index e86b6dff..bf09edea 100644
--- a/examples/App.vue
+++ b/examples/App.vue
@@ -87,7 +87,8 @@ const navList = ref([
{ name: 'AvatarTest', routerLink: { name: 'AvatarTest' } },
{ name: 'SliderTest', routerLink: { name: 'SliderTest' } },
{ name: 'RateTest', routerLink: { name: 'RateTest' } },
- { name: 'TableSelect', routerLink: { name: 'TableSelect' } }
+ { name: 'TableSelect', routerLink: { name: 'TableSelect' } },
+ { name: 'ColorPickerTest', routerLink: { name: 'ColorPickerTest' } }
])
const theme = ref((localStorage.getItem('VXE_THEME') as 'light' | 'dark') || 'light')
diff --git a/examples/router/index.ts b/examples/router/index.ts
index bd4b42f9..65dd7f61 100644
--- a/examples/router/index.ts
+++ b/examples/router/index.ts
@@ -284,6 +284,11 @@ const routes: Array = [
path: '/component/table-select',
name: 'TableSelect',
component: () => import('../views/table-select/TableSelect.vue')
+ },
+ {
+ path: '/component/color-picker',
+ name: 'ColorPickerTest',
+ component: () => import('../views/color-picker/ColorPickerTest.vue')
}
]
diff --git a/examples/views/color-picker/ColorPickerTest.vue b/examples/views/color-picker/ColorPickerTest.vue
new file mode 100644
index 00000000..64beafcf
--- /dev/null
+++ b/examples/views/color-picker/ColorPickerTest.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/examples/views/upload/UploadTest.vue b/examples/views/upload/UploadTest.vue
index 03912e1b..ed8433a9 100644
--- a/examples/views/upload/UploadTest.vue
+++ b/examples/views/upload/UploadTest.vue
@@ -19,7 +19,7 @@
-
+
@@ -27,7 +27,7 @@
-
+
diff --git a/package.json b/package.json
index 29550d00..d0b130fd 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "vxe-pc-ui",
- "version": "4.3.37",
+ "version": "4.3.38",
"description": "A vue based PC component library",
"scripts": {
"update": "npm install --legacy-peer-deps",
diff --git a/packages/color-picker/src/color-picker.ts b/packages/color-picker/src/color-picker.ts
index 628db17f..6039af63 100644
--- a/packages/color-picker/src/color-picker.ts
+++ b/packages/color-picker/src/color-picker.ts
@@ -1,23 +1,108 @@
-import { defineComponent, ref, h, reactive } from 'vue'
+import { defineComponent, watch, computed, provide, ref, inject, Teleport, h, nextTick, PropType, reactive, onMounted, onUnmounted } from 'vue'
import XEUtils from 'xe-utils'
-import { createEvent } from '../../ui'
+import { getConfig, globalEvents, createEvent, useSize, renderEmptyElement } from '../../ui'
+import { getEventTargetNode, getAbsolutePos } from '../../ui/src/dom'
+import { getLastZIndex, nextZIndex } from '../../ui/src/utils'
-import type { ColorPickerReactData, VxeColorPickerEmits, ColorPickerMethods, ColorPickerPrivateMethods, ValueOf, ColorPickerPrivateRef, VxeColorPickerPrivateComputed, VxeColorPickerConstructor, VxeColorPickerPrivateMethods } from '../../../types'
+import type { ColorPickerReactData, VxeColorPickerPropTypes, VxeColorPickerEmits, ColorPickerInternalData, ColorPickerMethods, ColorPickerPrivateMethods, ValueOf, ColorPickerPrivateRef, VxeColorPickerPrivateComputed, VxeColorPickerConstructor, VxeColorPickerPrivateMethods, VxeModalConstructor, VxeModalMethods, VxeDrawerConstructor, VxeDrawerMethods, VxeTableConstructor, VxeTablePrivateMethods, VxeFormConstructor, VxeFormPrivateMethods } from '../../../types'
export default defineComponent({
name: 'VxeColorPicker',
props: {
+ modelValue: String as PropType,
+ placeholder: String as PropType,
+ clearable: Boolean as PropType,
+ size: {
+ type: String as PropType,
+ default: () => getConfig().colorPicker.size || getConfig().size
+ },
+ className: [String, Function] as PropType,
+ popupClassName: [String, Function] as PropType,
+ readonly: {
+ type: Boolean as PropType,
+ default: null
+ },
+ disabled: {
+ type: Boolean as PropType,
+ default: null
+ },
+ placement: String as PropType,
+ transfer: {
+ type: Boolean as PropType,
+ default: null
+ }
},
emits: [
+ 'update:modelValue',
+ 'change',
+ 'clear',
+ 'click'
] as VxeColorPickerEmits,
setup (props, context) {
const { emit } = context
+ const $xeModal = inject<(VxeModalConstructor & VxeModalMethods) | null>('$xeModal', null)
+ const $xeDrawer = inject<(VxeDrawerConstructor & VxeDrawerMethods) | null>('$xeDrawer', null)
+ const $xeTable = inject<(VxeTableConstructor & VxeTablePrivateMethods) | null>('$xeTable', null)
+ const $xeForm = inject<(VxeFormConstructor & VxeFormPrivateMethods) | null>('$xeForm', null)
+ // const formItemInfo = inject('xeFormItemInfo', null)
+
const xID = XEUtils.uniqueId()
+ const { computeSize } = useSize(props)
+
const refElem = ref()
+ const refOptionPanel = ref()
const reactData = reactive({
+ initialized: false,
+ selectColor: `${props.modelValue || ''}`,
+ panelIndex: 0,
+ panelStyle: {},
+ panelPlacement: null,
+ visiblePanel: false,
+ isAniVisible: false,
+ isActivated: false
+ })
+
+ const internalData: ColorPickerInternalData = {
+ // hpTimeout: undefined
+ }
+
+ const computeFormReadonly = computed(() => {
+ const { readonly } = props
+ if (readonly === null) {
+ if ($xeForm) {
+ return $xeForm.props.readonly
+ }
+ return false
+ }
+ return readonly
+ })
+
+ const computeIsDisabled = computed(() => {
+ const { disabled } = props
+ if (disabled === null) {
+ if ($xeForm) {
+ return $xeForm.props.disabled
+ }
+ return false
+ }
+ return disabled
+ })
+
+ const computeBtnTransfer = computed(() => {
+ const { transfer } = props
+ if (transfer === null) {
+ const globalTransfer = getConfig().iconPicker.transfer
+ if (XEUtils.isBoolean(globalTransfer)) {
+ return globalTransfer
+ }
+ if ($xeTable || $xeModal || $xeDrawer || $xeForm) {
+ return true
+ }
+ }
+ return transfer
})
const refMaps: ColorPickerPrivateRef = {
@@ -37,6 +122,192 @@ export default defineComponent({
getComputeMaps: () => computeMaps
} as unknown as VxeColorPickerConstructor & VxeColorPickerPrivateMethods
+ const updateZindex = () => {
+ if (reactData.panelIndex < getLastZIndex()) {
+ reactData.panelIndex = nextZIndex()
+ }
+ }
+
+ const updatePlacement = () => {
+ return nextTick().then(() => {
+ const { placement } = props
+ const { panelIndex } = reactData
+ const el = refElem.value
+ const panelElem = refOptionPanel.value
+ const btnTransfer = computeBtnTransfer.value
+ if (panelElem && el) {
+ const targetHeight = el.offsetHeight
+ const targetWidth = el.offsetWidth
+ const panelHeight = panelElem.offsetHeight
+ const panelWidth = panelElem.offsetWidth
+ const marginSize = 5
+ const panelStyle: { [key: string]: any } = {
+ zIndex: panelIndex
+ }
+ const { boundingTop, boundingLeft, visibleHeight, visibleWidth } = getAbsolutePos(el)
+ let panelPlacement = 'bottom'
+ if (btnTransfer) {
+ let left = boundingLeft
+ let top = boundingTop + targetHeight
+ if (placement === 'top') {
+ panelPlacement = 'top'
+ top = boundingTop - panelHeight
+ } else if (!placement) {
+ // 如果下面不够放,则向上
+ if (top + panelHeight + marginSize > visibleHeight) {
+ panelPlacement = 'top'
+ top = boundingTop - panelHeight
+ }
+ // 如果上面不够放,则向下(优先)
+ if (top < marginSize) {
+ panelPlacement = 'bottom'
+ top = boundingTop + targetHeight
+ }
+ }
+ // 如果溢出右边
+ if (left + panelWidth + marginSize > visibleWidth) {
+ left -= left + panelWidth + marginSize - visibleWidth
+ }
+ // 如果溢出左边
+ if (left < marginSize) {
+ left = marginSize
+ }
+ Object.assign(panelStyle, {
+ left: `${left}px`,
+ top: `${top}px`,
+ minWidth: `${targetWidth}px`
+ })
+ } else {
+ if (placement === 'top') {
+ panelPlacement = 'top'
+ panelStyle.bottom = `${targetHeight}px`
+ } else if (!placement) {
+ // 如果下面不够放,则向上
+ if (boundingTop + targetHeight + panelHeight > visibleHeight) {
+ // 如果上面不够放,则向下(优先)
+ if (boundingTop - targetHeight - panelHeight > marginSize) {
+ panelPlacement = 'top'
+ panelStyle.bottom = `${targetHeight}px`
+ }
+ }
+ }
+ }
+ reactData.panelStyle = panelStyle
+ reactData.panelPlacement = panelPlacement
+ return nextTick()
+ }
+ })
+ }
+
+ const showOptionPanel = () => {
+ const { hpTimeout } = internalData
+ const isDisabled = computeIsDisabled.value
+ if (!isDisabled) {
+ if (hpTimeout) {
+ clearTimeout(hpTimeout)
+ internalData.hpTimeout = undefined
+ }
+ if (!reactData.initialized) {
+ reactData.initialized = true
+ }
+ reactData.isActivated = true
+ reactData.isAniVisible = true
+ setTimeout(() => {
+ reactData.visiblePanel = true
+ }, 10)
+ updateZindex()
+ updatePlacement()
+ }
+ }
+
+ const hideOptionPanel = () => {
+ reactData.visiblePanel = false
+ internalData.hpTimeout = window.setTimeout(() => {
+ reactData.isAniVisible = false
+ }, 350)
+ }
+
+ // const changeEvent = (evnt: Event, selectValue: any) => {
+ // reactData.selectColor = selectValue
+ // if (selectValue !== props.modelValue) {
+ // emit('update:modelValue', selectValue)
+ // dispatchEvent('change', { value: selectValue }, evnt)
+ // // 自动更新校验状态
+ // if ($xeForm && formItemInfo) {
+ // $xeForm.triggerItemEvent(evnt, formItemInfo.itemConfig.field, selectValue)
+ // }
+ // }
+ // }
+
+ // const focusEvent = () => {
+ // const isDisabled = computeIsDisabled.value
+ // if (!isDisabled) {
+ // if (!reactData.visiblePanel) {
+ // showOptionPanel()
+ // }
+ // }
+ // }
+
+ // const blurEvent = () => {
+ // reactData.isActivated = false
+ // }
+
+ // const clearValueEvent = (evnt: Event, selectValue: any) => {
+ // changeEvent(evnt, selectValue)
+ // dispatchEvent('clear', { value: selectValue }, evnt)
+ // }
+
+ // const clearEvent = (params: any, evnt: Event) => {
+ // clearValueEvent(evnt, null)
+ // hideOptionPanel()
+ // }
+
+ const togglePanelEvent = (evnt: MouseEvent) => {
+ evnt.preventDefault()
+ if (reactData.visiblePanel) {
+ hideOptionPanel()
+ } else {
+ showOptionPanel()
+ }
+ }
+
+ const clickEvent = (evnt: MouseEvent) => {
+ togglePanelEvent(evnt)
+ dispatchEvent('click', {}, evnt)
+ }
+
+ const handleGlobalMousewheelEvent = (evnt: MouseEvent) => {
+ const { visiblePanel } = reactData
+ const isDisabled = computeIsDisabled.value
+ if (!isDisabled) {
+ if (visiblePanel) {
+ const panelElem = refOptionPanel.value
+ if (getEventTargetNode(evnt, panelElem).flag) {
+ updatePlacement()
+ } else {
+ hideOptionPanel()
+ }
+ }
+ }
+ }
+
+ const handleGlobalMousedownEvent = (evnt: MouseEvent) => {
+ const { visiblePanel } = reactData
+ const isDisabled = computeIsDisabled.value
+ if (!isDisabled) {
+ const el = refElem.value
+ const panelElem = refOptionPanel.value
+ reactData.isActivated = getEventTargetNode(evnt, el).flag || getEventTargetNode(evnt, panelElem).flag
+ if (visiblePanel && !reactData.isActivated) {
+ hideOptionPanel()
+ }
+ }
+ }
+
+ const handleGlobalBlurEvent = () => {
+ hideOptionPanel()
+ }
+
const dispatchEvent = (type: ValueOf, params: Record, evnt: Event | null) => {
emit(type, createEvent(evnt, { $colorPicker: $xeColorPicker }, params))
}
@@ -50,13 +321,93 @@ export default defineComponent({
Object.assign($xeColorPicker, colorPickerMethods, colorPickerPrivateMethods)
+ const renderColorWrapper = () => {
+ return h('div', {}, [
+ h('div', {
+ class: 'vxe-color-picker--view-wrapper'
+ }),
+ h('div', {
+ class: 'vxe-color-picker--convenient-wrapper'
+ }),
+ h('div', {
+ class: ''
+ })
+ ])
+ }
+
const renderVN = () => {
+ const { className, popupClassName, clearable } = props
+ const { initialized, isActivated, isAniVisible, visiblePanel, selectColor } = reactData
+ const vSize = computeSize.value
+ const isDisabled = computeIsDisabled.value
+ const btnTransfer = computeBtnTransfer.value
+ const formReadonly = computeFormReadonly.value
+
+ if (formReadonly) {
+ return h('div', {
+ ref: refElem,
+ class: ['vxe-color-picker--readonly', className]
+ }, 'x')
+ }
return h('div', {
ref: refElem,
- class: 'vxe-color-picker'
- }, [])
+ class: ['vxe-color-picker', className ? (XEUtils.isFunction(className) ? className({ $colorPicker: $xeColorPicker }) : className) : '', {
+ [`size--${vSize}`]: vSize,
+ 'show--clear': clearable && !isDisabled && !!selectColor,
+ 'is--visible': visiblePanel,
+ 'is--disabled': isDisabled,
+ 'is--active': isActivated
+ }]
+ }, [
+ h('div', {
+ class: 'vxe-ico-picker--inner',
+ onClick: clickEvent
+ }, 'x'),
+ h(Teleport, {
+ to: 'body',
+ disabled: btnTransfer ? !initialized : true
+ }, [
+ h('div', {
+ ref: refOptionPanel,
+ class: ['vxe-table--ignore-clear vxe-color-picker--panel', popupClassName ? (XEUtils.isFunction(popupClassName) ? popupClassName({ $colorPicker: $xeColorPicker }) : popupClassName) : '', {
+ [`size--${vSize}`]: vSize,
+ 'is--transfer': btnTransfer,
+ 'ani--leave': isAniVisible,
+ 'ani--enter': visiblePanel
+ }],
+ placement: reactData.panelPlacement,
+ style: reactData.panelStyle
+ }, [
+ initialized && (visiblePanel || isAniVisible)
+ ? h('div', {
+ class: 'vxe-color-picker--panel-wrapper'
+ }, [
+ renderColorWrapper()
+ ])
+ : renderEmptyElement($xeColorPicker)
+ ])
+ ])
+ ])
}
+ watch(() => props.modelValue, (val) => {
+ reactData.selectColor = `${val || ''}`
+ })
+
+ onMounted(() => {
+ globalEvents.on($xeColorPicker, 'mousewheel', handleGlobalMousewheelEvent)
+ globalEvents.on($xeColorPicker, 'mousedown', handleGlobalMousedownEvent)
+ globalEvents.on($xeColorPicker, 'blur', handleGlobalBlurEvent)
+ })
+
+ onUnmounted(() => {
+ globalEvents.off($xeColorPicker, 'mousewheel')
+ globalEvents.off($xeColorPicker, 'mousedown')
+ globalEvents.off($xeColorPicker, 'blur')
+ })
+
+ provide('$xeColorPicker', $xeColorPicker)
+
$xeColorPicker.renderVN = renderVN
return $xeColorPicker
diff --git a/packages/form/src/render.ts b/packages/form/src/render.ts
index fbaff90a..af0d2168 100644
--- a/packages/form/src/render.ts
+++ b/packages/form/src/render.ts
@@ -1,6 +1,6 @@
import { createCommentVNode, h, VNode } from 'vue'
import { getIcon, getI18n, renderer } from '../../ui'
-import { getFuncText, isEnableConf } from '../../ui/src/utils'
+import { eqEmptyValue, getFuncText, isEnableConf } from '../../ui/src/utils'
import { toCssUnit } from '../../ui/src/dom'
import { getSlotVNs } from '../../ui/src/vn'
import { isActiveItem } from './util'
@@ -228,7 +228,8 @@ export const renderItemContent = ($xeForm: VxeFormConstructor & VxeFormPrivateMe
} else if (rftContent) {
contentVNs = getSlotVNs(rftContent(itemRender, params))
} else if (field) {
- contentVNs = [`${XEUtils.get(data, field)}`]
+ const itemValue = XEUtils.get(data, field)
+ contentVNs = [eqEmptyValue(itemValue) ? '' : `${itemValue}`]
}
if (collapseNode) {
contentVNs.push(
diff --git a/packages/icon-picker/src/icon-picker.ts b/packages/icon-picker/src/icon-picker.ts
index 75c4a1dd..39c23641 100644
--- a/packages/icon-picker/src/icon-picker.ts
+++ b/packages/icon-picker/src/icon-picker.ts
@@ -68,7 +68,7 @@ export default defineComponent({
})
const internalData: IconPickerInternalData = {
- hpTimeout: undefined
+ // hpTimeout: undefined
}
const refElem = ref() as Ref
@@ -264,7 +264,7 @@ export default defineComponent({
reactData.selectIcon = selectValue
if (selectValue !== props.modelValue) {
emit('update:modelValue', selectValue)
- iconPickerMethods.dispatchEvent('change', { value: selectValue }, evnt)
+ dispatchEvent('change', { value: selectValue }, evnt)
// 自动更新校验状态
if ($xeForm && formItemInfo) {
$xeForm.triggerItemEvent(evnt, formItemInfo.itemConfig.field, selectValue)
@@ -287,7 +287,7 @@ export default defineComponent({
const clearValueEvent = (evnt: Event, selectValue: any) => {
changeEvent(evnt, selectValue)
- iconPickerMethods.dispatchEvent('clear', { value: selectValue }, evnt)
+ dispatchEvent('clear', { value: selectValue }, evnt)
}
const clearEvent = (params: any, evnt: Event) => {
@@ -306,7 +306,7 @@ export default defineComponent({
const clickEvent = (evnt: MouseEvent) => {
togglePanelEvent(evnt)
- iconPickerMethods.dispatchEvent('click', {}, evnt)
+ dispatchEvent('click', {}, evnt)
}
const handleGlobalMousewheelEvent = (evnt: MouseEvent) => {
diff --git a/packages/ui/index.ts b/packages/ui/index.ts
index 610c0074..03dbfe79 100644
--- a/packages/ui/index.ts
+++ b/packages/ui/index.ts
@@ -79,6 +79,7 @@ setConfig({
},
collapsePane: {},
countdown: {},
+ colorPicker: {},
datePicker: {
// size: null,
// transfer: false
diff --git a/packages/upload/src/upload.ts b/packages/upload/src/upload.ts
index 08aa9ba4..81a7fa83 100644
--- a/packages/upload/src/upload.ts
+++ b/packages/upload/src/upload.ts
@@ -874,7 +874,7 @@ export default defineComponent({
slots: {
default () {
const { showErrorStatus, dragToUpload, dragSort } = props
- const { isDragMove, isDragUploadStatus, dragIndex } = reactData
+ const { isActivated, isDragMove, isDragUploadStatus, dragIndex } = reactData
const { fileList } = reactData
const isDisabled = computeIsDisabled.value
@@ -890,6 +890,7 @@ export default defineComponent({
class: ['vxe-upload--more-popup', {
'is--readonly': formReadonly,
'is--disabled': isDisabled,
+ 'is--active': isActivated,
'show--error': showErrorStatus,
'is--drag': isDragUploadStatus
}],
@@ -1079,7 +1080,13 @@ export default defineComponent({
const handleGlobalMousedownEvent = (evnt: MouseEvent) => {
const el = refElem.value
- const isActivated = getEventTargetNode(evnt, el).flag
+ const popupEl = refPopupElem.value
+ let isActivated = getEventTargetNode(evnt, el).flag
+ if (!isActivated && popupEl) {
+ const parentEl = popupEl.parentElement || popupEl
+ const modalEl = parentEl ? parentEl.parentElement : parentEl
+ isActivated = getEventTargetNode(evnt, modalEl).flag
+ }
reactData.isActivated = isActivated
}
diff --git a/styles/components/color-picker.scss b/styles/components/color-picker.scss
index e69de29b..18d4c0c2 100644
--- a/styles/components/color-picker.scss
+++ b/styles/components/color-picker.scss
@@ -0,0 +1,201 @@
+@use '../helpers/baseMixin.scss';
+
+.vxe-color-picker {
+ position: relative;
+ display: inline-block;
+ color: var(--vxe-ui-font-color);
+ width: 100px;
+ border: 1px solid var(--vxe-ui-input-border-color);
+ border-radius: var(--vxe-ui-base-border-radius);
+ background-color: var(--vxe-ui-layout-background-color);
+ &.show--clear {
+ &:hover {
+ .vxe-color-picker--clear-icon {
+ display: block;
+ }
+ }
+ }
+ &.is--active {
+ border-color: var(--vxe-ui-font-primary-color);
+ }
+}
+
+.vxe-color-picker--inner {
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+ padding: 0 0.5em;
+}
+.vxe-color-picker--input {
+ position: absolute;
+ z-index: -1;
+ width: 1px;
+ height: 1px;
+ outline: 0;
+ border: 0;
+}
+.vxe-color-picker--icon {
+ flex-grow: 1;
+ display: inline-flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: left;
+ padding: 0 0.5em;
+}
+.vxe-color-picker--placeholder {
+ flex-grow: 1;
+ color: var(--vxe-ui-input-placeholder-color);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.vxe-color-picker--suffix {
+ display: flex;
+ flex-direction: row;
+ flex-shrink: 0;
+ color: var(--vxe-ui-input-placeholder-color);
+ cursor: pointer;
+ .vxe-color-picker--suffix-icon > i {
+ display: inline-block;
+ @include baseMixin.createAnimationTransition(transform, .2s);
+ }
+}
+
+.vxe-color-picker--readonly {
+ color: var(--vxe-ui-font-color);
+ display: inline-flex;
+}
+
+.vxe-color-picker--clear-icon {
+ display: none;
+ padding-right: 0.5em;
+ height: 100%;
+ color: var(--vxe-ui-input-placeholder-color);
+ cursor: pointer;
+ &:hover {
+ color: var(--vxe-ui-font-color);
+ }
+ &:active {
+ color: var(--vxe-ui-font-primary-color);
+ }
+}
+
+.vxe-color-picker--list-wrapper {
+ overflow-x: hidden;
+ overflow-y: auto;
+ max-height: 22.3em;
+ padding: var(--vxe-ui-layout-padding-qtr);
+}
+.vxe-color-picker--list {
+ display: flex;
+ flex-direction: row;
+}
+.vxe-color-picker--item {
+ display: flex;
+ flex-direction: column;
+ width: 4.8em;
+ padding: 0.2em;
+ border: 1px solid var(--vxe-ui-input-border-color);
+ border-radius: var(--vxe-ui-base-border-radius);
+ margin: var(--vxe-ui-layout-padding-half);
+ cursor: pointer;
+ &:hover {
+ background-color: var(--vxe-ui-base-hover-background-color);
+ }
+ &.is--selected {
+ color: var(--vxe-ui-font-primary-color);
+ border-color: var(--vxe-ui-font-primary-color);
+ }
+}
+.vxe-color-picker--item-icon {
+ flex-grow: 1;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ height: 1.5em;
+ font-size: 1.4em
+}
+.vxe-color-picker--item-title {
+ padding: 0 0.2em;
+ line-height: 1.3em;
+ flex-shrink: 0;
+ text-align: center;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ font-size: 0.9em;
+}
+.vxe-color-picker--item-title,
+.vxe-color-picker--item-icon {
+ width: 100%;
+}
+
+.vxe-color-picker--panel-wrapper {
+ position: relative;
+ border-radius: var(--vxe-ui-base-border-radius);
+ border: 1px solid var(--vxe-ui-base-popup-border-color);
+ box-shadow: var(--vxe-ui-base-popup-box-shadow);
+ background-color: var(--vxe-ui-layout-background-color);
+}
+
+.vxe-color-picker--panel {
+ display: none;
+ position: absolute;
+ left: 0;
+ padding: 4px 0;
+ color: var(--vxe-ui-font-color);
+ text-align: left;
+ &:not(.is--transfer) {
+ min-width: 100%;
+ }
+ &.is--transfer {
+ position: fixed;
+ }
+ &.ani--leave {
+ display: block;
+ opacity: 0;
+ transform: scaleY(0.5);
+ transition: transform .3s cubic-bezier(.23,1,.32,1), opacity .3s cubic-bezier(.23,1,.32,1);
+ transform-origin: center top;
+ backface-visibility: hidden;
+ &[placement="top"] {
+ transform-origin: center bottom;
+ }
+ }
+ &.ani--enter {
+ opacity: 1;
+ transform: scaleY(1);
+ }
+}
+
+.vxe-color-picker {
+ height: var(--vxe-ui-input-height-default);
+ line-height: var(--vxe-ui-input-height-default);
+ &.size--medium {
+ height: var(--vxe-ui-input-height-medium);
+ line-height: var(--vxe-ui-input-height-medium);
+ }
+ &.size--small {
+ height: var(--vxe-ui-input-height-small);
+ line-height: var(--vxe-ui-input-height-small);
+ }
+ &.size--mini {
+ height: var(--vxe-ui-input-height-mini);
+ line-height: var(--vxe-ui-input-height-mini);
+ }
+}
+
+.vxe-color-picker,
+.vxe-color-picker--panel {
+ font-size: var(--vxe-ui-font-size-default);
+ &.size--medium {
+ font-size: var(--vxe-ui-font-size-medium);
+ }
+ &.size--small {
+ font-size: var(--vxe-ui-font-size-small);
+ }
+ &.size--mini {
+ font-size: var(--vxe-ui-font-size-mini);
+ }
+}
\ No newline at end of file
diff --git a/styles/components/upload.scss b/styles/components/upload.scss
index 179f3413..3847709a 100644
--- a/styles/components/upload.scss
+++ b/styles/components/upload.scss
@@ -2,17 +2,6 @@
position: relative;
color: var(--vxe-ui-font-color);
font-family: var(--vxe-ui-font-family);
- &.is--active {
- .vxe-upload--image-action-box {
- border-color: var(--vxe-ui-font-primary-color);
- }
- .vxe-upload--file-action-btn {
- & > .vxe-button {
- border-color: var(--vxe-ui-font-primary-color);
- border-style: var(--vxe-ui-upload-file-button-border-style);
- }
- }
- }
&.show--error {
.vxe-upload--file-item {
&.is--error {
@@ -29,8 +18,20 @@
}
}
}
+
.vxe-upload,
.vxe-upload--more-popup {
+ &.is--active {
+ .vxe-upload--image-action-box {
+ border-color: var(--vxe-ui-font-primary-color);
+ }
+ .vxe-upload--file-action-btn {
+ & > .vxe-button {
+ border-color: var(--vxe-ui-font-primary-color);
+ border-style: var(--vxe-ui-upload-file-button-border-style);
+ }
+ }
+ }
&.is--disabled {
.vxe-upload--file-action-btn,
.vxe-upload--image-action-box {
diff --git a/types/components/color-picker.d.ts b/types/components/color-picker.d.ts
index 0e1ed81a..1df46fb4 100644
--- a/types/components/color-picker.d.ts
+++ b/types/components/color-picker.d.ts
@@ -1,5 +1,5 @@
import { RenderFunction, SetupContext, Ref } from 'vue'
-import { DefineVxeComponentApp, DefineVxeComponentOptions, DefineVxeComponentInstance, VxeComponentBaseOptions, VxeComponentEventParams } from '@vxe-ui/core'
+import { DefineVxeComponentApp, DefineVxeComponentOptions, DefineVxeComponentInstance, VxeComponentBaseOptions, VxeComponentEventParams, VxeComponentSizeType, VxeComponentStyleType } from '@vxe-ui/core'
/* eslint-disable no-use-before-define,@typescript-eslint/ban-types */
@@ -23,9 +23,32 @@ export interface ColorPickerPrivateRef {
export interface VxeColorPickerPrivateRef extends ColorPickerPrivateRef { }
export namespace VxeColorPickerPropTypes {
+ export type ModelValue = string
+ export type Size = VxeComponentSizeType
+ export type ClassName = string | ((params: { $colorPicker: VxeColorPickerConstructor }) => string)
+ export type PopupClassName = string | ((params: {$colorPicker: VxeColorPickerConstructor }) => string)
+ export type Readonly = boolean
+ export type Disabled = boolean
+ export type Placeholder = string
+ export type Clearable = boolean
+ export type Placement = 'top' | 'bottom' | '' | null
+ export type Transfer = boolean
}
export interface VxeColorPickerProps {
+ /**
+ * 绑定值
+ */
+ modelValue?: VxeColorPickerPropTypes.ModelValue
+ size?: VxeColorPickerPropTypes.Size
+ className?: VxeColorPickerPropTypes.ClassName
+ popupClassName?: VxeColorPickerPropTypes.PopupClassName
+ readonly?: VxeColorPickerPropTypes.Readonly
+ disabled?: VxeColorPickerPropTypes.Disabled
+ placeholder?: VxeColorPickerPropTypes.Placeholder
+ clearable?: VxeColorPickerPropTypes.Clearable
+ placement?: VxeColorPickerPropTypes.Placement
+ transfer?: VxeColorPickerPropTypes.Transfer
}
export interface ColorPickerPrivateComputed {
@@ -33,6 +56,18 @@ export interface ColorPickerPrivateComputed {
export interface VxeColorPickerPrivateComputed extends ColorPickerPrivateComputed { }
export interface ColorPickerReactData {
+ initialized: boolean
+ selectColor: string
+ panelIndex: number
+ panelStyle: VxeComponentStyleType
+ panelPlacement: any
+ visiblePanel: boolean
+ isAniVisible: boolean
+ isActivated: boolean
+}
+
+export interface ColorPickerInternalData {
+ hpTimeout?: undefined | number
}
export interface ColorPickerMethods {
@@ -42,7 +77,12 @@ export interface VxeColorPickerMethods extends ColorPickerMethods { }
export interface ColorPickerPrivateMethods { }
export interface VxeColorPickerPrivateMethods extends ColorPickerPrivateMethods { }
-export type VxeColorPickerEmits = []
+export type VxeColorPickerEmits = [
+ 'update:modelValue',
+ 'change',
+ 'clear',
+ 'click'
+]
export namespace VxeColorPickerDefines {
export interface ColorPickerEventParams extends VxeComponentEventParams {
diff --git a/types/components/table-module/edit.d.ts b/types/components/table-module/edit.d.ts
index cfd6734e..1822752d 100644
--- a/types/components/table-module/edit.d.ts
+++ b/types/components/table-module/edit.d.ts
@@ -14,18 +14,37 @@ export interface TableEditMethods {
* 如果 row 为 -1 则从插入到底部,如果为树结构,则插入到目标节点底部
* 如果 row 为有效行则插入到该行的位置,如果为树结构,则有插入到效的目标节点该行的位置
* @param {Object/Array} records 新的数据
- * @param {Row} row 指定行
+ * @param {Row} targetRow 指定行
*/
- insertAt(records: any, row: any | -1 | null): Promise<{ row: D, rows: D[] }>
+ insertAt(records: any, targetRow: any | -1 | null): Promise<{ row: D, rows: D[] }>
/**
- * 往表格在指定行中的下一行插入临时数据
+ * 与 insertAt 行为一致,区别就是会插入指定目标的到下一行
+ * @param records records 新的数据
+ * @param targetRow row 指定行
+ */
+ insertNextAt(records: any, targetRow: any | -1 | null): Promise<{ row: D, rows: D[] }>
+ /**
+ * 用于树结构,往指定节点插入子级临时数据,从子级的第一行新增一行或多行新数据
+ * @param records 新数据
+ */
+ insertChild(records: any, parentRow: any): Promise<{ row: D, rows: D[] }>
+ /**
+ * 用于树结构,往指定节点插入子级临时数据
* 如果 row 为空则从插入到顶部,如果为树结构,则插入到目标节点顶部
* 如果 row 为 -1 则从插入到底部,如果为树结构,则插入到目标节点底部
- * 如果 row 为有效行则插入到该行的下一行位置,如果为树结构,则有插入到效的目标节点该行的下一行位置
- * @param records records 新的数据
- * @param row row 指定行
+ * 如果 row 为有效行则插入到该行的位置,如果为树结构,则有插入到效的目标节点该行的位置
+ * @param records 新的数据
+ * @param parentRow 父节点
+ * @param targetRow 指定子节点
+ */
+ insertChildAt(records: any, parentRow: any, targetRow: any | -1 | null): Promise<{ row: D, rows: D[] }>
+ /**
+ * 与 insertChildAt 行为一致,区别就是会插入指定目标子级的到下一行
+ * @param records 新的数据
+ * @param parentRow 父节点
+ * @param targetRow 指定子节点
*/
- insertNextAt(records: any, row: any | -1 | null): Promise<{ row: D, rows: D[] }>
+ insertChildNextAt(records: any, parentRow: any, targetRow: any | -1 | null): Promise<{ row: D, rows: D[] }>
/**
* 删除指定行数据,指定 row 或 [row, ...] 删除多条数据,如果为空则删除所有数据
* @param rows 指定行