{"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;;;;;;;"}