UNPKG

hongluan-ui

Version:
1 lines 13.4 kB
{"version":3,"file":"color-picker.mjs","sources":["../../../../../../packages/components/color-picker/src/color-picker.vue"],"sourcesContent":["<template>\n <hl-tooltip\n ref=\"popper\"\n :visible=\"showPicker\"\n :show-arrow=\"false\"\n :fallback-placements=\"['bottom', 'top', 'right', 'left']\"\n :offset=\"popperOffset\"\n :gpu-acceleration=\"false\"\n :popper-class=\"[namespace + '-picker-popper', popperClass]\"\n :stop-popper-mouse-event=\"false\"\n :teleported=\"teleported\"\n trigger=\"click\"\n transition=\"dropdown\"\n persistent\n @hide=\"setShowPicker(false)\"\n >\n <template #content>\n <hl-group\n v-click-outside=\"handleClickOutside\"\n :class=\"namespace + '-panel'\"\n dir=\"vertical\"\n full=\"full-x\"\n gap=\"var(--xs)\"\n @keydown.esc=\"handleEsc\"\n >\n <sv-panel ref=\"svPanel\" :color=\"color\" />\n <hl-group gap=\"var(--xs)\">\n <hl-group dir=\"vertical\" full=\"full-x\" gap=\"var(--xxs)\">\n <hue-slider ref=\"hue\" :color=\"color\" />\n <alpha-slider v-if=\"showAlpha\" ref=\"alpha\" :color=\"color\" />\n </hl-group>\n <div v-if=\"showAlpha\" class=\"current-color\" :style=\"`background-color: ${customInput}`\"></div>\n </hl-group>\n <predefine\n v-if=\"predefine\"\n ref=\"predefine\"\n :enable-alpha=\"showAlpha\"\n :color=\"color\"\n :colors=\"predefine\"\n class=\"m-t-xs\"\n />\n <hl-group align=\"items-between\" gap=\"var(--xs)\" class=\"m-t-xs\">\n <hl-input\n ref=\"inputRef\"\n v-model=\"customInput\"\n :validate-event=\"false\"\n size=\"sm\"\n fill\n block\n spellcheck=\"false\"\n @keyup.enter=\"handleConfirm\"\n @blur=\"handleConfirm\"\n />\n <hl-group class=\"static\">\n <hl-button size=\"sm\" type=\"link\" @click=\"clear\">{{ t('hl.colorpicker.clear') }}</hl-button>\n <hl-button\n type=\"primary\"\n size=\"sm\"\n @click=\"confirmValue\"\n >\n {{ t('hl.colorpicker.confirm') }}\n </hl-button>\n </hl-group>\n </hl-group>\n </hl-group>\n </template>\n <template #default>\n <div\n :id=\"buttonId\"\n ref=\"triggerRef\"\n v-bind=\"$attrs\"\n :class=\"[\n namespace + '-picker',\n colorDisabled ? 'is-disabled' : '',\n isFocused ? 'is-focused' : '',\n colorSize,\n ]\"\n role=\"button\"\n :aria-label=\"buttonAriaLabel\"\n :aria-labelledby=\"buttonAriaLabelledby\"\n :aria-description=\"\n t('hl.colorpicker.description', { color: modelValue || '' })\n \"\n :aria-disabled=\"colorDisabled\"\n :tabindex=\"colorDisabled ? -1 : tabindex\"\n @keydown=\"handleKeyDown\"\n @focus=\"handleFocus\"\n @blur=\"handleBlur\"\n >\n <div v-if=\"colorDisabled\" class=\"picker-mask\"></div>\n <div class=\"picker-trigger\" @click=\"handleTrigger\">\n <span\n class=\"picker-color\"\n :style=\"{\n backgroundColor: displayedColor,\n }\"\n >\n <hl-icon\n v-show=\"modelValue || showPanelColor\"\n :class=\"['picker-icon']\"\n >\n <system-arrow-down />\n </hl-icon>\n <hl-icon v-show=\"!modelValue && !showPanelColor\" :class=\"['picker-empty', 'icon-close']\">\n <system-close />\n </hl-icon>\n </span>\n </div>\n </div>\n </template>\n </hl-tooltip>\n</template>\n\n<script lang=\"ts\" setup>\nimport {\n computed,\n nextTick,\n onMounted,\n provide,\n reactive,\n ref,\n watch,\n} from 'vue'\nimport { debounce } from 'lodash-unified'\nimport HlButton from '@hongluan-ui/components/button'\nimport HlIcon from '@hongluan-ui/components/icon'\nimport HlGroup from '@hongluan-ui/components/group'\nimport { ClickOutside as vClickOutside } from '@hongluan-ui/directives'\nimport { useFocusController, useLocale, useNamespace, useConsistentProp, useFormItemInputId, useFormItem } from '@hongluan-ui/hooks'\nimport HlTooltip from '@hongluan-ui/components/tooltip'\nimport HlInput from '@hongluan-ui/components/input'\nimport { EVENT_CODE, UPDATE_MODEL_EVENT } from '@hongluan-ui/constants'\nimport { debugWarn } from '@hongluan-ui/utils'\nimport { SystemArrowDown, SystemClose } from '@hongluan-ui/components/system-icon'\nimport AlphaSlider from './components/alpha-slider.vue'\nimport HueSlider from './components/hue-slider.vue'\nimport Predefine from './components/predefine.vue'\nimport SvPanel from './components/sv-panel.vue'\nimport Color from './utils/color'\nimport {\n colorPickerContextKey,\n colorPickerEmits,\n colorPickerProps,\n} from './color-picker'\nimport type { TooltipInstance } from '@hongluan-ui/components/tooltip'\n\ndefineOptions({\n name: 'ColorPicker',\n})\nconst props = defineProps(colorPickerProps)\nconst emit = defineEmits(colorPickerEmits)\n\nconst { t } = useLocale()\nconst { namespace } = useNamespace('color')\nconst { form, formItem } = useFormItem()\nconst { inputId: buttonId, isLabeledByFormItem } = useFormItemInputId(\n props,\n {\n formItemContext: formItem,\n },\n)\nconst hue = ref<InstanceType<typeof HueSlider>>()\nconst svPanel = ref<InstanceType<typeof SvPanel>>()\nconst alpha = ref<InstanceType<typeof AlphaSlider>>()\nconst popper = ref<TooltipInstance>()\nconst triggerRef = ref()\nconst inputRef = ref()\n\nconst {\n isFocused,\n handleFocus: _handleFocus,\n handleBlur,\n} = useFocusController(triggerRef, {\n beforeBlur(event) {\n return popper.value?.isFocusInsideContent(event)\n },\n afterBlur() {\n setShowPicker(false)\n resetColor()\n },\n})\n\nconst handleFocus = (event: FocusEvent) => {\n if (colorDisabled.value) return blur()\n _handleFocus(event)\n}\n\n// active-change is used to prevent modelValue changes from triggering.\nlet shouldActiveChange = true\n\n// data\nconst color = reactive(\n new Color({\n enableAlpha: props.showAlpha,\n format: props.colorFormat || '',\n value: props.modelValue,\n }),\n) as Color\n\nconst showPicker = ref(false)\nconst showPanelColor = ref(false)\nconst customInput = ref('')\n// computed\nconst displayedColor = computed(() => {\n if (!props.modelValue && !showPanelColor.value) {\n return 'transparent'\n }\n return displayedRgb(color, props.showAlpha)\n})\nconst { size: colorSize } = useConsistentProp()\nconst colorDisabled = computed(() => {\n return !!(props.disabled || form?.disabled)\n})\n\nconst currentColor = computed(() => {\n return !props.modelValue && !showPanelColor.value ? '' : color.value\n})\nconst popperPaneRef = computed(() => {\n return popper.value?.popperRef?.contentRef\n})\nconst buttonAriaLabel = computed<string | undefined>(() => {\n return !isLabeledByFormItem.value\n ? props.label || props.ariaLabel || t('hl.colorpicker.defaultLabel')\n : undefined\n})\nconst buttonAriaLabelledby = computed<string | undefined>(() => {\n return isLabeledByFormItem.value ? formItem?.labelId : undefined\n})\n\n// methods\nfunction displayedRgb(color: Color, showAlpha: boolean) {\n if (!(color instanceof Color)) {\n throw new TypeError('color should be instance of _color Class')\n }\n\n const { r, g, b } = color.toRgb()\n return showAlpha\n ? `rgba(${r}, ${g}, ${b}, ${color.get('alpha') / 100})`\n : `rgb(${r}, ${g}, ${b})`\n}\n\nfunction setShowPicker(value: boolean) {\n showPicker.value = value\n}\n\nconst debounceSetShowPicker = debounce(setShowPicker, 100, { leading: true })\n\nfunction show() {\n if (colorDisabled.value) return\n setShowPicker(true)\n}\n\nfunction hide() {\n debounceSetShowPicker(false)\n resetColor()\n}\n\nfunction resetColor() {\n nextTick(() => {\n if (props.modelValue) {\n color.fromString(props.modelValue)\n } else {\n color.value = ''\n nextTick(() => {\n showPanelColor.value = false\n })\n }\n })\n}\n\nfunction handleTrigger() {\n if (colorDisabled.value) return\n debounceSetShowPicker(!showPicker.value)\n}\n\nfunction handleConfirm() {\n color.fromString(customInput.value)\n}\n\nfunction confirmValue() {\n const value = color.value\n emit(UPDATE_MODEL_EVENT, value)\n emit('change', value)\n if (props.validateEvent) {\n formItem?.validate?.('change').catch(err => debugWarn(err))\n }\n debounceSetShowPicker(false)\n // check if modelValue change, if not change, then reset color.\n nextTick(() => {\n const newColor = new Color({\n enableAlpha: props.showAlpha,\n format: props.colorFormat || '',\n value: props.modelValue,\n })\n if (!color.compare(newColor)) {\n resetColor()\n }\n })\n}\n\nfunction clear() {\n debounceSetShowPicker(false)\n emit(UPDATE_MODEL_EVENT, null)\n emit('change', null)\n if (props.modelValue !== null && props.validateEvent) {\n formItem?.validate?.('change').catch(err => debugWarn(err))\n }\n resetColor()\n}\n\nfunction handleClickOutside(event: Event) {\n if (!showPicker.value) return\n hide()\n\n if (isFocused.value) {\n const _event = new FocusEvent('focus', event)\n handleBlur(_event)\n }\n}\n\nfunction handleEsc(event: KeyboardEvent) {\n event.preventDefault()\n event.stopPropagation()\n setShowPicker(false)\n resetColor()\n}\n\nfunction handleKeyDown(event: KeyboardEvent) {\n switch (event.code) {\n case EVENT_CODE.enter:\n case EVENT_CODE.space:\n event.preventDefault()\n event.stopPropagation()\n show()\n inputRef.value.focus()\n break\n case EVENT_CODE.esc:\n handleEsc(event)\n break\n }\n}\n\nfunction focus() {\n triggerRef.value.focus()\n}\n\nfunction blur() {\n triggerRef.value.blur()\n}\n\nonMounted(() => {\n if (props.modelValue) {\n customInput.value = currentColor.value\n }\n})\n\n// watch\nwatch(\n () => props.modelValue,\n newVal => {\n if (!newVal) {\n showPanelColor.value = false\n } else if (newVal && newVal !== color.value) {\n shouldActiveChange = false\n color.fromString(newVal)\n }\n },\n)\nwatch(\n () => currentColor.value,\n val => {\n customInput.value = val\n shouldActiveChange && emit('activeChange', val)\n shouldActiveChange = true\n },\n)\n\nwatch(\n () => color.value,\n () => {\n if (!props.modelValue && !showPanelColor.value) {\n showPanelColor.value = true\n }\n },\n)\n\nwatch(\n () => showPicker.value,\n () => {\n nextTick(() => {\n hue.value?.update()\n svPanel.value?.update()\n alpha.value?.update()\n })\n },\n)\n\nprovide(colorPickerContextKey, {\n currentColor,\n})\n\ndefineExpose({\n /**\n * @description current color object\n */\n color,\n popperPaneRef,\n /**\n * @description manually show ColorPicker\n */\n show,\n /**\n * @description manually hide ColorPicker\n */\n hide,\n /**\n * @description focus the input element\n */\n focus,\n /**\n * @description blur the input element\n */\n blur,\n})\n\n</script>\n"],"names":[],"mappings":"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"}