vxe-pc-ui
Version:
A vue based PC component library
1,110 lines (1,034 loc) • 37.7 kB
text/typescript
import { watch, computed, provide, ref, inject, Teleport, h, nextTick, PropType, reactive, onMounted, onUnmounted } from 'vue'
import { defineVxeComponent } from '../../ui/src/comp'
import XEUtils from 'xe-utils'
import { VxeUI, getIcon, getConfig, getI18n, globalEvents, createEvent, useSize, renderEmptyElement } from '../../ui'
import { getEventTargetNode, toCssUnit, updatePanelPlacement } from '../../ui/src/dom'
import { getLastZIndex, nextZIndex } from '../../ui/src/utils'
import { parseColor, updateColorAlpha, hexToHsv, rgbToHsv, rgbToHex, hexToRgb, hsvToRgb, toRgb } from './util'
import VxeButtonComponent from '../../button/src/button'
import VxeInputComponent from '../../input/src/input'
import VxeNumberInputComponent from '../../number-input/src/number-input'
import type { ColorPickerReactData, VxeColorPickerPropTypes, VxeColorPickerEmits, ColorPickerInternalData, ColorPickerMethods, ColorPickerPrivateMethods, ValueOf, ColorPickerPrivateRef, VxeColorPickerPrivateComputed, VxeColorPickerConstructor, VxeColorPickerPrivateMethods, VxeModalConstructor, VxeModalMethods, VxeDrawerConstructor, VxeDrawerMethods, VxeFormDefines, VxeFormConstructor, VxeFormPrivateMethods } from '../../../types'
import type { VxeTableConstructor, VxeTablePrivateMethods } from '../../../types/components/table'
export default defineVxeComponent({
name: 'VxeColorPicker',
props: {
modelValue: String as PropType<VxeColorPickerPropTypes.ModelValue>,
placeholder: String as PropType<VxeColorPickerPropTypes.Placeholder>,
clearable: {
type: Boolean as PropType<VxeColorPickerPropTypes.Clearable>,
default: () => getConfig().colorPicker.clearable
},
type: {
type: String as PropType<VxeColorPickerPropTypes.Type>,
default: () => getConfig().colorPicker.type
},
size: {
type: String as PropType<VxeColorPickerPropTypes.Size>,
default: () => getConfig().colorPicker.size || getConfig().size
},
className: [String, Function] as PropType<VxeColorPickerPropTypes.ClassName>,
popupClassName: [String, Function] as PropType<VxeColorPickerPropTypes.PopupClassName>,
colors: {
type: Array as PropType<VxeColorPickerPropTypes.Colors>,
default: () => XEUtils.clone(getConfig().colorPicker.colors, true) || []
},
showAlpha: {
type: Boolean as PropType<VxeColorPickerPropTypes.ShowAlpha>,
default: () => getConfig().colorPicker.showAlpha
},
showEyeDropper: {
type: Boolean as PropType<VxeColorPickerPropTypes.ShowEyeDropper>,
default: () => getConfig().colorPicker.showEyeDropper
},
showColorExtractor: {
type: Boolean as PropType<VxeColorPickerPropTypes.ShowColorExtractor>,
default: () => getConfig().colorPicker.showColorExtractor
},
showQuick: {
type: Boolean as PropType<VxeColorPickerPropTypes.ShowQuick>,
default: () => getConfig().colorPicker.showQuick
},
readonly: {
type: Boolean as PropType<VxeColorPickerPropTypes.Readonly>,
default: null
},
disabled: {
type: Boolean as PropType<VxeColorPickerPropTypes.Disabled>,
default: null
},
clickToCopy: {
type: Boolean as PropType<VxeColorPickerPropTypes.ClickToCopy>,
default: () => getConfig().colorPicker.clickToCopy
},
placement: String as PropType<VxeColorPickerPropTypes.Placement>,
transfer: {
type: Boolean as PropType<VxeColorPickerPropTypes.Transfer>,
default: null
},
popupConfig: Object as PropType<VxeColorPickerPropTypes.PopupConfig>
},
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<VxeFormDefines.ProvideItemInfo | null>('xeFormItemInfo', null)
const WinEyeDropper = typeof window !== 'undefined' ? (window as any).EyeDropper : null
const xID = XEUtils.uniqueId()
const { computeSize } = useSize(props)
const refElem = ref<HTMLDivElement>()
const refInputTarget = ref<HTMLInputElement>()
const refOptionPanel = ref<HTMLDivElement>()
const refHueSliderElem = ref<HTMLDivElement>()
const refHueSliderBtnElem = ref<HTMLDivElement>()
const refAlphaSliderElem = ref<HTMLDivElement>()
const refAlphaSliderBtnElem = ref<HTMLDivElement>()
const refColorPanelElem = ref<HTMLDivElement>()
const refColorActiveElem = ref<HTMLDivElement>()
const reactData = reactive<ColorPickerReactData>({
initialized: false,
selectTyle: 'hex',
selectColor: `${props.modelValue || ''}`,
showTypePopup: false,
panelColor: '',
hexValue: '',
rValue: 0,
gValue: 0,
bValue: 0,
aValue: 0,
panelIndex: 0,
panelStyle: {},
panelPlacement: null,
visiblePanel: false,
isAniVisible: false,
isActivated: false
})
const typeList = [
{ label: 'HEX', value: 'hex' },
{ label: 'RGB', value: 'rgb' }
]
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().colorPicker.transfer
if (XEUtils.isBoolean(globalTransfer)) {
return globalTransfer
}
if ($xeTable || $xeModal || $xeDrawer || $xeForm) {
return true
}
}
return transfer
})
const computeColorList = computed(() => {
const { colors } = props
if (colors) {
return colors.map(item => {
if (XEUtils.isString(item)) {
return {
label: item,
value: item
}
}
return {
label: XEUtils.eqNull(item.label) ? item.value : item.label,
value: item.value
}
})
}
return []
})
const computePopupOpts = computed(() => {
return Object.assign({}, getConfig().colorPicker.popupConfig, props.popupConfig)
})
const computeIsRgb = computed(() => {
const { selectTyle } = reactData
return selectTyle === 'rgb'
})
const computeSelectTypeItem = computed(() => {
const { selectTyle } = reactData
return typeList.find(item => item.value === selectTyle)
})
const refMaps: ColorPickerPrivateRef = {
refElem
}
const computeMaps: VxeColorPickerPrivateComputed = {
}
const $xeColorPicker = {
xID,
props,
context,
reactData,
getRefMaps: () => refMaps,
getComputeMaps: () => computeMaps
} as unknown as VxeColorPickerConstructor & VxeColorPickerPrivateMethods
const emitModel = (value: any) => {
emit('update:modelValue', value)
}
const updateMode = () => {
const { modelValue } = props
reactData.selectColor = XEUtils.toValueString(modelValue)
updateModelColor()
}
const updateType = () => {
const { type } = props
let selectTyle: VxeColorPickerPropTypes.Type = 'hex'
if (type === 'rgb' || (type as string) === 'rgba') {
selectTyle = 'rgb'
}
reactData.selectTyle = selectTyle
updateMode()
}
const updateModelColor = () => {
const { selectColor, isAniVisible } = reactData
const isRgb = computeIsRgb.value
const hueSliderEl = refHueSliderElem.value
const alphaSliderEl = refAlphaSliderElem.value
const colorRest = parseColor(selectColor)
reactData.hexValue = colorRest.hex
reactData.rValue = colorRest.r
reactData.gValue = colorRest.g
reactData.bValue = colorRest.b
reactData.aValue = colorRest.a
if (colorRest.value) {
if (isRgb) {
if (colorRest.type === 'hex') {
const rgbRest = hexToRgb(colorRest.hex)
if (rgbRest) {
reactData.rValue = rgbRest.r
reactData.gValue = rgbRest.g
reactData.bValue = rgbRest.b
reactData.aValue = rgbRest.a
}
}
} else {
if (colorRest.type !== 'hex') {
reactData.hexValue = rgbToHex(colorRest)
}
}
}
if (isAniVisible) {
const hsvRest = colorRest.type === 'hex' ? hexToHsv(colorRest.hex) : rgbToHsv(colorRest)
const colorPanelEl = refColorPanelElem.value
if (hsvRest) {
if (colorPanelEl) {
const offsetTop = colorPanelEl.clientHeight * (1 - hsvRest.v)
const offsetLeft = colorPanelEl.clientWidth * hsvRest.s
handlePanelColor(offsetLeft, offsetTop)
}
if (hueSliderEl) {
handleHueColor(XEUtils.ceil((1 - hsvRest.h / 360) * hueSliderEl.clientWidth))
}
}
if (alphaSliderEl) {
handleAlphaColor(alphaSliderEl.clientWidth * colorRest.a)
}
}
}
const updateZindex = () => {
if (reactData.panelIndex < getLastZIndex()) {
reactData.panelIndex = nextZIndex()
}
}
const updatePlacement = () => {
const { placement } = props
const { panelIndex } = reactData
const targetElem = refElem.value
const panelElem = refOptionPanel.value
const btnTransfer = computeBtnTransfer.value
const popupOpts = computePopupOpts.value
const handleStyle = () => {
const ppObj = updatePanelPlacement(targetElem, panelElem, {
placement: popupOpts.placement || placement,
defaultPlacement: popupOpts.defaultPlacement,
teleportTo: btnTransfer
})
const panelStyle: { [key: string]: string | number } = Object.assign(ppObj.style, {
zIndex: panelIndex
})
reactData.panelStyle = panelStyle
reactData.panelPlacement = ppObj.placement
}
handleStyle()
return nextTick().then(handleStyle)
}
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(() => {
updateModelColor()
reactData.visiblePanel = true
}, 10)
updateZindex()
updatePlacement()
}
}
const hideOptionPanel = () => {
reactData.visiblePanel = false
internalData.hpTimeout = setTimeout(() => {
reactData.isAniVisible = false
}, 350)
}
const changeEvent = (evnt: Event, value: any) => {
reactData.selectColor = value
if (value !== props.modelValue) {
emitModel(value)
dispatchEvent('change', { value }, evnt)
// 自动更新校验状态
if ($xeForm && formItemInfo) {
$xeForm.triggerItemEvent(evnt, formItemInfo.itemConfig.field, value)
}
}
}
const clearValueEvent = (evnt: Event, selectValue: any) => {
changeEvent(evnt, selectValue)
dispatchEvent('clear', { value: selectValue }, evnt)
}
const focusEvent = () => {
const isDisabled = computeIsDisabled.value
if (!isDisabled) {
if (!reactData.visiblePanel) {
showOptionPanel()
}
}
}
const blurEvent = () => {
reactData.isActivated = false
}
const clearEvent = (evnt: Event) => {
clearValueEvent(evnt, null)
hideOptionPanel()
}
const confirmEvent = (evnt: MouseEvent) => {
const { selectColor } = reactData
changeEvent(evnt, selectColor)
hideOptionPanel()
}
const togglePanelEvent = (evnt: MouseEvent) => {
evnt.preventDefault()
if (reactData.visiblePanel) {
hideOptionPanel()
} else {
showOptionPanel()
}
}
const clickEvent = (evnt: MouseEvent) => {
togglePanelEvent(evnt)
dispatchEvent('click', {}, evnt)
}
const handlePanelClickEvent = () => {
reactData.showTypePopup = false
}
const toggleTypeVisibleEvent = (evnt: MouseEvent) => {
evnt.stopPropagation()
reactData.showTypePopup = !reactData.showTypePopup
}
const handleChangeType = (type: VxeColorPickerPropTypes.Type) => {
const { selectTyle } = reactData
if (type !== selectTyle) {
reactData.selectTyle = type
updateModelColor()
}
reactData.showTypePopup = false
}
const handleHueColor = (offsetLeft: number) => {
const hueSliderEl = refHueSliderElem.value
const hueSliderBtnEl = refHueSliderBtnElem.value
if (hueSliderEl && hueSliderBtnEl) {
if (offsetLeft < 0) {
offsetLeft = 0
}
const barWidth = XEUtils.toInteger(hueSliderEl.clientWidth)
const itemNum = 255
const countNum = itemNum * 6
const offsetX = XEUtils.ceil(countNum / barWidth * offsetLeft)
const offsetNum = offsetX % itemNum
let rNum = 0
let gNum = 0
let bNum = 0
switch (Math.ceil(offsetX / itemNum)) {
case 1:
rNum = itemNum
bNum = offsetNum
break
case 2:
rNum = itemNum - offsetNum
bNum = itemNum
break
case 3:
gNum = offsetNum
bNum = itemNum
break
case 4:
gNum = itemNum
bNum = itemNum - offsetNum
break
case 5:
rNum = offsetNum
gNum = itemNum
break
case 6:
rNum = itemNum
gNum = itemNum - offsetNum
break
}
reactData.panelColor = toRgb(rNum, gNum, bNum)
hueSliderBtnEl.style.left = toCssUnit(offsetLeft)
}
}
const handleHueBarEvent = (evnt: MouseEvent) => {
const hueSliderEl = refHueSliderElem.value
const hueSliderBtnEl = refHueSliderBtnElem.value
if (hueSliderEl && hueSliderBtnEl) {
const hueSliderRect = hueSliderEl.getBoundingClientRect()
const barWidth = XEUtils.toInteger(hueSliderEl.clientWidth)
const offsetLeft = XEUtils.ceil(Math.min(barWidth - 1, Math.max(1, evnt.clientX - hueSliderRect.x)))
handleHueColor(offsetLeft)
}
}
const handleHueSliderMousedownEvent = (evnt: MouseEvent) => {
evnt.preventDefault()
document.onmousemove = evnt => {
evnt.preventDefault()
handleHueBarEvent(evnt)
}
document.onmouseup = (evnt: MouseEvent) => {
document.onmousemove = null
document.onmouseup = null
handleHueBarEvent(evnt)
}
}
const handleAlphaColor = (offsetLeft: number) => {
const { selectColor } = reactData
const alphaSliderEl = refAlphaSliderElem.value
const alphaSliderBtnEl = refAlphaSliderBtnElem.value
if (alphaSliderEl && alphaSliderBtnEl) {
const alphaSliderRect = alphaSliderEl.getBoundingClientRect()
const barWidth = alphaSliderRect.width
if (offsetLeft < 0) {
offsetLeft = 0
}
if (offsetLeft > barWidth) {
offsetLeft = barWidth
}
const alpha = XEUtils.ceil(100 / barWidth * offsetLeft / 100, 2)
reactData.aValue = alpha
alphaSliderBtnEl.style.left = toCssUnit(offsetLeft)
reactData.selectColor = updateColorAlpha(selectColor, alpha)
}
}
const handleAlphaBarEvent = (evnt: MouseEvent) => {
const alphaSliderEl = refAlphaSliderElem.value
const alphaSliderBtnEl = refAlphaSliderBtnElem.value
if (alphaSliderEl && alphaSliderBtnEl) {
const alphaSliderRect = alphaSliderEl.getBoundingClientRect()
const barWidth = alphaSliderRect.width
const offsetLeft = Math.min(barWidth, Math.max(0, evnt.clientX - alphaSliderRect.x))
handleAlphaColor(offsetLeft)
updateModelColor()
}
}
const handleAlphaSliderMousedownEvent = (evnt: MouseEvent) => {
evnt.preventDefault()
document.onmousemove = evnt => {
evnt.preventDefault()
handleAlphaBarEvent(evnt)
}
document.onmouseup = (evnt: MouseEvent) => {
document.onmousemove = null
document.onmouseup = null
handleAlphaBarEvent(evnt)
}
}
const handleInputRgbEvent = () => {
const { rValue, gValue, bValue, aValue } = reactData
reactData.selectColor = toRgb(rValue, gValue, bValue, aValue)
updateModelColor()
}
const handleInputAlphaEvent = () => {
const { aValue } = reactData
const alphaSliderEl = refAlphaSliderElem.value
const alphaSliderBtnEl = refAlphaSliderBtnElem.value
if (alphaSliderEl && alphaSliderBtnEl) {
const alphaSliderRect = alphaSliderEl.getBoundingClientRect()
const barWidth = alphaSliderRect.width
const offsetLeft = barWidth * aValue
handleAlphaColor(offsetLeft)
}
}
const handleQuickEvent = (evnt: MouseEvent, item: any) => {
const value = item.value
reactData.selectColor = value
updateModelColor()
}
const handlePanelColor = (offsetLeft: number, offsetTop: number) => {
const colorActiveEl = refColorActiveElem.value
if (colorActiveEl) {
colorActiveEl.style.top = toCssUnit(offsetTop)
colorActiveEl.style.left = toCssUnit(offsetLeft)
}
}
const handleEyeDropperEvent = () => {
if (WinEyeDropper) {
try {
const eyeDropper = new WinEyeDropper()
eyeDropper.open().then((rest: any) => {
if (rest && rest.sRGBHex) {
reactData.selectColor = rest.sRGBHex
updateModelColor()
}
}).catch(() => {
})
} catch (e) {}
}
}
const handleSelectColorByXY = (clientX: number, clientY: number) => {
const { showAlpha } = props
const { panelColor, aValue } = reactData
const colorPanelEl = refColorPanelElem.value
const colorActiveEl = refColorActiveElem.value
if (colorPanelEl && colorActiveEl) {
const { clientWidth, clientHeight } = colorPanelEl
const colorPanelRect = colorPanelEl.getBoundingClientRect()
const offsetTop = Math.min(clientHeight, Math.max(0, clientY - colorPanelRect.y))
const offsetLeft = Math.min(clientWidth, Math.max(0, clientX - colorPanelRect.x))
const colorRest = parseColor(panelColor)
if (colorRest) {
const hsvRest = colorRest.type === 'hex' ? hexToHsv(colorRest.hex) : rgbToHsv(colorRest)
if (hsvRest) {
const ragRest = hsvToRgb(hsvRest.h, offsetLeft / clientWidth, (1 - offsetTop / clientHeight))
reactData.selectColor = toRgb(ragRest.r, ragRest.g, ragRest.b, showAlpha ? aValue : null)
updateModelColor()
}
}
handlePanelColor(offsetLeft, offsetTop)
}
}
const handleSelectColorMousedownEvent = (evnt: MouseEvent) => {
evnt.stopPropagation()
evnt.preventDefault()
handleSelectColorByXY(evnt.clientX, evnt.clientY)
document.onmousemove = evnt => {
handleSelectColorByXY(evnt.clientX, evnt.clientY)
}
document.onmouseup = () => {
document.onmousemove = null
document.onmouseup = null
}
}
const handleCopyColorEvent = () => {
const { selectColor } = reactData
if (selectColor) {
if (VxeUI.clipboard.copy(selectColor)) {
if (VxeUI.modal) {
VxeUI.modal.message({
content: getI18n('vxe.colorPicker.copySuccess', [selectColor]),
status: 'success'
})
}
}
}
}
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 = () => {
const { visiblePanel, isActivated } = reactData
if (visiblePanel) {
hideOptionPanel()
}
if (isActivated) {
reactData.isActivated = false
}
if (visiblePanel || isActivated) {
const targetElem = refInputTarget.value
if (targetElem) {
targetElem.blur()
}
}
}
const handleGlobalResizeEvent = () => {
const { visiblePanel } = reactData
if (visiblePanel) {
updatePlacement()
}
}
const dispatchEvent = (type: ValueOf<VxeColorPickerEmits>, params: Record<string, any>, evnt: Event | null) => {
emit(type, createEvent(evnt, { $colorPicker: $xeColorPicker }, params))
}
const colorPickerMethods: ColorPickerMethods = {
dispatchEvent
}
const colorPickerPrivateMethods: ColorPickerPrivateMethods = {
}
Object.assign($xeColorPicker, colorPickerMethods, colorPickerPrivateMethods)
const renderColorWrapper = () => {
const { showColorExtractor } = props
const { panelColor } = reactData
if (showColorExtractor) {
return h('div', {
ref: refColorPanelElem,
class: 'vxe-color-picker--color-wrapper',
onMousedown: handleSelectColorMousedownEvent
}, [
h('div', {
class: 'vxe-color-picker--color-bg',
style: {
backgroundColor: panelColor
}
}),
h('div', {
class: 'vxe-color-picker--white-bg'
}),
h('div', {
class: 'vxe-color-picker--black-bg'
}),
h('div', {
ref: refColorActiveElem,
class: 'vxe-color-picker--color-active'
})
])
}
return renderEmptyElement($xeColorPicker)
}
const renderColorBar = () => {
const { showAlpha, clickToCopy, showEyeDropper } = props
const { selectTyle, showTypePopup, hexValue, rValue, gValue, bValue, aValue, selectColor, panelColor } = reactData
const isRgb = computeIsRgb.value
const selectTypeItem = computeSelectTypeItem.value
return h('div', {
class: 'vxe-color-picker--bar-wrapper'
}, [
h('div', {
class: 'vxe-color-picker--slider-wrapper'
}, [
showEyeDropper && WinEyeDropper
? h('div', {
class: 'vxe-color-picker--color-dropper'
}, [
h('span', {
class: 'vxe-color-picker--color-dropper-btn',
onClick: handleEyeDropperEvent
}, [
h('i', {
class: getIcon().COLOR_PICKER_EYE_DROPPER
})
])
])
: renderEmptyElement($xeColorPicker),
h('div', {
class: 'vxe-color-picker--slider-preview'
}, [
h('div', {
class: 'vxe-color-picker--preview-btn'
}, [
h('div', {
class: 'vxe-color-picker--preview-color',
style: {
backgroundColor: selectColor
}
}, clickToCopy
? [
h('span', {
class: 'vxe-color-picker--preview-copy-btn',
onClick: handleCopyColorEvent
}, [
h('i', {
class: getIcon().COLOR_PICKER_COLOR_COPY
})
])
]
: [])
])
]),
h('div', {
class: 'vxe-color-picker--slider-handle'
}, [
h('div', {
ref: refHueSliderElem,
class: 'vxe-color-picker--bar-hue-slider',
onClick: handleHueBarEvent
}, [
h('div', {
ref: refHueSliderBtnElem,
class: 'vxe-color-picker--bar-hue-btn',
onMousedown: handleHueSliderMousedownEvent
})
]),
showAlpha
? h('div', {
ref: refAlphaSliderElem,
class: 'vxe-color-picker--bar-alpha-slider',
onClick: handleAlphaBarEvent
}, [
h('div', {
class: 'vxe-color-picker--bar-alpha-bg',
style: {
background: `linear-gradient(to right, rgba(0, 0, 0, 0), ${panelColor})`
}
}),
h('div', {
ref: refAlphaSliderBtnElem,
class: 'vxe-color-picker--bar-alpha-btn',
onMousedown: handleAlphaSliderMousedownEvent
})
])
: renderEmptyElement($xeColorPicker)
])
]),
h('div', {
class: 'vxe-color-picker--custom-wrapper'
}, [
h('div', {
class: 'vxe-color-picker--type-switch'
}, [
h('div', {
class: 'vxe-color-picker--type-label',
onClick: toggleTypeVisibleEvent
}, [
h('span', `${selectTypeItem ? selectTypeItem.label : selectTyle}`),
h('span', {
class: 'vxe-color-picker--type-icon'
}, [
h('i', {
class: showTypePopup ? getIcon().COLOR_PICKER_TPTY_OPEN : getIcon().COLOR_PICKER_TPTY_CLOSE
})
])
]),
h('div', {
class: ['vxe-color-picker--type-popup', {
'is--visible': showTypePopup
}]
}, typeList.map(item => {
return h('div', {
class: 'vxe-color-picker--type-item',
onClick (evnt) {
evnt.stopPropagation()
handleChangeType(item.value as VxeColorPickerPropTypes.Type)
}
}, item.label)
}))
]),
h('div', {
class: `vxe-color-picker--${selectTyle}-wrapper`
}, isRgb
? [
h('div', {
class: 'vxe-color-picker--input-wrapper'
}, [
h(VxeNumberInputComponent, {
type: 'integer',
size: 'mini',
align: 'center',
min: 0,
max: 255,
maxLength: 3,
placeholder: '',
modelValue: rValue,
controlConfig: {
showButton: false
},
'onUpdate:modelValue' (val) {
reactData.rValue = val
},
onChange: handleInputRgbEvent
}),
h(VxeNumberInputComponent, {
type: 'integer',
size: 'mini',
align: 'center',
min: 0,
max: 255,
maxLength: 3,
placeholder: '',
modelValue: gValue,
controlConfig: {
showButton: false
},
'onUpdate:modelValue' (val) {
reactData.gValue = val
},
onChange: handleInputRgbEvent
}),
h(VxeNumberInputComponent, {
type: 'integer',
size: 'mini',
align: 'center',
min: 0,
max: 255,
maxLength: 3,
placeholder: '',
modelValue: bValue,
controlConfig: {
showButton: false
},
'onUpdate:modelValue' (val) {
reactData.bValue = val
},
onChange: handleInputRgbEvent
}),
h(VxeNumberInputComponent, {
type: 'number',
size: 'mini',
align: 'center',
min: 0,
max: 1,
step: 0.01,
maxLength: 4,
placeholder: '',
modelValue: aValue,
controlConfig: {
showButton: false
},
'onUpdate:modelValue' (val) {
reactData.aValue = val
},
onChange: handleInputAlphaEvent
})
]),
h('div', {
class: 'vxe-color-picker--input-title'
}, [
h('span', 'R'),
h('span', 'G'),
h('span', 'B'),
h('span', 'A')
])]
: [
h('div', {
class: 'vxe-color-picker--input-wrapper'
}, [
h(VxeInputComponent, {
type: 'text',
size: 'mini',
align: 'center',
maxLength: 9,
placeholder: '',
modelValue: hexValue,
'onUpdate:modelValue' (val) {
reactData.hexValue = val
},
onChange () {
const colorRest = parseColor(reactData.hexValue)
if (colorRest) {
if (colorRest.value) {
reactData.selectColor = colorRest.value
updateModelColor()
}
}
}
})
]),
h('div', {
class: 'vxe-color-picker--input-title'
}, getI18n('vxe.colorPicker.hex'))
])
])
])
}
const renderQuickWrapper = () => {
const { showQuick } = props
const colorList = computeColorList.value
if (showQuick && colorList.length) {
return h('div', {
class: 'vxe-color-picker--quick-wrapper'
}, colorList.map((item, i) => {
return h('div', {
key: i,
class: 'vxe-color-picker--quick-item',
title: item.label || '',
style: {
backgroundColor: item.value
},
onClick (evnt) {
handleQuickEvent(evnt, item)
}
})
}))
}
return renderEmptyElement($xeColorPicker)
}
const renderVN = () => {
const { className, popupClassName, clearable, modelValue } = props
const { initialized, isActivated, isAniVisible, visiblePanel } = 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]
}, [
h('div', {
class: 'vxe-color-picker--readonly-color',
style: {
backgroundColor: modelValue
}
})
])
}
return h('div', {
ref: refElem,
class: ['vxe-color-picker', className ? (XEUtils.isFunction(className) ? className({ $colorPicker: $xeColorPicker }) : className) : '', {
[`size--${vSize}`]: vSize,
'is--selected': !!modelValue,
'is--visible': visiblePanel,
'is--disabled': isDisabled,
'is--active': isActivated
}]
}, [
h('input', {
ref: refInputTarget,
class: 'vxe-color-picker--input',
onFocus: focusEvent,
onBlur: blurEvent
}),
h('div', {
class: 'vxe-color-picker--inner',
onClick: clickEvent
}, [
h('div', {
class: 'vxe-color-picker--inner-color',
style: {
backgroundColor: modelValue
}
})
]),
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',
onClick: handlePanelClickEvent
}, [
renderColorWrapper(),
renderColorBar(),
renderQuickWrapper(),
h('div', {
class: 'vxe-color-picker--footer-wrapper'
}, [
clearable
? h(VxeButtonComponent, {
content: getI18n('vxe.colorPicker.clear'),
size: 'mini',
onClick: clearEvent
})
: renderEmptyElement($xeColorPicker),
h(VxeButtonComponent, {
content: getI18n('vxe.colorPicker.confirm'),
size: 'mini',
status: 'primary',
onClick: confirmEvent
})
])
])
: renderEmptyElement($xeColorPicker)
])
])
])
}
watch(() => props.modelValue, () => {
updateMode()
})
watch(() => props.type, () => {
updateType()
})
onMounted(() => {
globalEvents.on($xeColorPicker, 'mousewheel', handleGlobalMousewheelEvent)
globalEvents.on($xeColorPicker, 'mousedown', handleGlobalMousedownEvent)
globalEvents.on($xeColorPicker, 'blur', handleGlobalBlurEvent)
globalEvents.on($xeColorPicker, 'resize', handleGlobalResizeEvent)
})
onUnmounted(() => {
globalEvents.off($xeColorPicker, 'mousewheel')
globalEvents.off($xeColorPicker, 'mousedown')
globalEvents.off($xeColorPicker, 'blur')
globalEvents.off($xeColorPicker, 'resize')
})
updateType()
provide('$xeColorPicker', $xeColorPicker)
$xeColorPicker.renderVN = renderVN
return $xeColorPicker
},
render () {
return this.renderVN()
}
})