@extclp/vexip-ui
Version:
A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good
1 lines • 5.51 kB
Source Map (JSON)
{"version":3,"file":"color-palette.vue.mjs","sources":["../../../components/color-picker/color-palette.vue"],"sourcesContent":["<template>\n <div\n ref=\"wrapper\"\n :class=\"nh.be('palette')\"\n tabindex=\"-1\"\n role=\"group\"\n :style=\"{\n backgroundColor: `hsl(${hue}, 100%, 50%)`\n }\"\n >\n <div :class=\"nh.be('saturation')\" role=\"none\"></div>\n <div :class=\"nh.be('value')\" role=\"none\"></div>\n <div\n :class=\"nh.be('palette-handler')\"\n :style=\"{\n top: `${currentTop}%`,\n left: `${currentLeft}%`\n }\"\n >\n <div :class=\"nh.be('palette-pointer')\"></div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, ref, watch } from 'vue'\n\nimport { useNameHelper } from '@vexip-ui/config'\nimport { useModifier, useMoving } from '@vexip-ui/hooks'\nimport { boundRange, toFixed } from '@vexip-ui/utils'\n\nexport default defineComponent({\n name: 'ColorPalette',\n props: {\n hue: {\n type: Number,\n default: 0,\n validator: (value: number) => {\n return value >= 0 && value <= 360\n }\n },\n value: {\n type: Number,\n default: 1,\n validator: (value: number) => {\n return value >= 0 && value <= 1\n }\n },\n saturation: {\n type: Number,\n default: 0,\n validator: (value: number) => {\n return value >= 0 && value <= 1\n }\n }\n },\n emits: ['edit-start', 'edit-end', 'change'],\n setup(props, { emit }) {\n const currentTop = ref((1 - props.value) * 100)\n const currentLeft = ref(props.saturation * 100)\n\n let prevTop = currentTop.value\n let prevLeft = currentLeft.value\n let widthLimit: number\n let heightLimit: number\n let topStartAt: number\n let leftStartAt: number\n\n const { target: wrapper } = useModifier({\n passive: false,\n onKeyDown: (event, modifier) => {\n if (modifier.up || modifier.down || modifier.left || modifier.right) {\n event.preventDefault()\n\n const step = event.ctrlKey ? 10 : event.altKey ? 0.5 : 2\n const sign = modifier.up || modifier.left ? -1 : 1\n const delta = step * sign\n\n if (modifier.up || modifier.down) {\n currentTop.value += delta\n } else {\n currentLeft.value += delta\n }\n\n verifyPosition()\n prevTop = currentTop.value\n prevLeft = currentLeft.value\n handleChange()\n }\n }\n })\n\n const { moving: editing } = useMoving({\n target: wrapper,\n onStart: (state, event) => {\n if (!wrapper.value || event.button > 0) {\n return false\n }\n\n const rect = wrapper.value.getBoundingClientRect()\n const { top, left, width, height } = rect\n\n widthLimit = width\n heightLimit = height\n\n currentTop.value = ((topStartAt = state.clientY - top) / height) * 100\n currentLeft.value = ((leftStartAt = state.clientX - left) / width) * 100\n\n verifyPosition()\n emit('edit-start')\n\n let changed = false\n\n if (Math.abs(currentTop.value - prevTop) >= 0.01) {\n prevTop = currentTop.value\n changed = true\n }\n\n if (Math.abs(currentLeft.value - prevLeft) >= 0.01) {\n prevLeft = currentLeft.value\n changed = true\n }\n\n changed && handleChange()\n },\n onMove: state => {\n currentTop.value = ((topStartAt + state.deltaY) / heightLimit) * 100\n currentLeft.value = ((leftStartAt + state.deltaX) / widthLimit) * 100\n\n verifyPosition()\n handleChange()\n },\n onEnd: () => {\n emit('edit-end')\n }\n })\n\n watch(\n () => props.value,\n value => {\n currentTop.value = (1 - value) * 100\n verifyPosition()\n },\n { immediate: true }\n )\n watch(\n () => props.saturation,\n value => {\n currentLeft.value = value * 100\n verifyPosition()\n },\n { immediate: true }\n )\n\n function verifyPosition() {\n currentTop.value = toFixed(boundRange(currentTop.value, 0, 100), 3)\n currentLeft.value = toFixed(boundRange(currentLeft.value, 0, 100), 3)\n }\n\n function handleChange() {\n emit('change', {\n h: props.hue,\n s: currentLeft.value / 100,\n v: toFixed(1 - currentTop.value / 100, 3)\n })\n }\n\n return {\n nh: useNameHelper('color-picker'),\n currentTop,\n currentLeft,\n editing,\n\n wrapper\n\n // handleMouseDown\n }\n }\n})\n</script>\n"],"names":["_sfc_render","_ctx","_cache","$props","$setup","$data","$options","_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","currentTop","currentLeft"],"mappings":";;;SAEQA,EAASC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAA;AACP,SAAAC,EAAA,GAAOC,EAAA,OAAA;AAAA,IACb,KAAA;AAAA,IACA,OAAKC,EAAOR,EAAA,GAAA,GAAA,SAAA,CAAA;AAAA,IACX,UANL;AAAA,IAAA,MAAA;AAAA;;IAUI,CAAA;AAAA,EAAA,GAAA;AAAA,IAA6CS,EAAA,OAAA;AAAA,MAAA,OAAAD,EAAAR,EAAA,GAAA,GAAA,YAAA,CAAA;AAAA,MAC7C,MAAA;AAAA,IAAA,GAAM,MAXV,CAAA;AAAA,IAW4CS,EAAA,OAAA;AAAA,MAAA,OAAAD,EAAAR,EAAA,GAAA,GAAA,OAAA,CAAA;AAAA,MACxC,MAAA;AAAA,IAAA,GACG,MAbP,CAAA;AAAA,IAAAS,EAAA,OAAA;AAAA,MAAA,OAAAD,EAcgCE,EAAU,GAAA,GAAA,iBAAA,CAAA;AAAA,MAAsBC,OAAAA,EAAAA;AAAAA,QAAAA,KAAAA,GAAAA,EAAAA,UAAAA;AAAAA;MAK1D,CAAA;AAAA,IAAA,GAAA;AAAA;;;;;;;"}