FIX: HSVInput circular update dependencies
This commit is contained in:
@@ -188,9 +188,9 @@ import { MoreHorizontal } from 'lucide-vue-next'
|
|||||||
import { Separator } from '@renderer/components/ui/separator'
|
import { Separator } from '@renderer/components/ui/separator'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
color: {
|
colorNumber: {
|
||||||
type: Color,
|
type: Number,
|
||||||
default: () => Color.rgb(255, 0, 0)
|
default: () => Color('#ff0000').rgbNumber()
|
||||||
},
|
},
|
||||||
roundedTop: {
|
roundedTop: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@@ -198,15 +198,25 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO: Currently color updates are passed up with input events and then passed back down as props
|
|
||||||
// This is the vue way, but that also means that the color is converted into a number and then back into a color
|
|
||||||
// This causes a loss of precision and the sliders to jump around a bit when the color is updated
|
|
||||||
// It would be better to pass the color number here and convert it to a color object here as well
|
|
||||||
// Then we can use the color object to update the sliders and inputs
|
|
||||||
// And only pass the color number up when it actually changes
|
|
||||||
|
|
||||||
const emit = defineEmits(['input'])
|
const emit = defineEmits(['input'])
|
||||||
|
|
||||||
|
const previousColor = ref(Color(props.colorNumber))
|
||||||
|
|
||||||
|
const color = computed({
|
||||||
|
get() {
|
||||||
|
if (previousColor.value.rgbNumber() === props.colorNumber) {
|
||||||
|
return previousColor.value
|
||||||
|
}
|
||||||
|
return Color(props.colorNumber)
|
||||||
|
},
|
||||||
|
set(newColor) {
|
||||||
|
if (newColor.rgbNumber() !== color.value.rgbNumber()) {
|
||||||
|
previousColor.value = newColor
|
||||||
|
emit('input', newColor.rgbNumber())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const hueSliderValue = ref(0)
|
const hueSliderValue = ref(0)
|
||||||
const saturationSliderValue = ref(100)
|
const saturationSliderValue = ref(100)
|
||||||
const valueSliderValue = ref(50)
|
const valueSliderValue = ref(50)
|
||||||
@@ -217,7 +227,7 @@ const hueSliderModel = computed({
|
|||||||
},
|
},
|
||||||
set(hue) {
|
set(hue) {
|
||||||
hueSliderValue.value = hue[0]
|
hueSliderValue.value = hue[0]
|
||||||
emit('input', props.color.hue(hue[0]))
|
color.value = color.value.hue(hue[0])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -227,7 +237,7 @@ const saturationSliderModel = computed({
|
|||||||
},
|
},
|
||||||
set(saturation) {
|
set(saturation) {
|
||||||
saturationSliderValue.value = saturation[0]
|
saturationSliderValue.value = saturation[0]
|
||||||
emit('input', props.color.saturationv(saturation[0]))
|
color.value = color.value.saturationv(saturation[0])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -237,7 +247,7 @@ const valueSliderModel = computed({
|
|||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
valueSliderValue.value = value[0]
|
valueSliderValue.value = value[0]
|
||||||
emit('input', props.color.value(value[0]))
|
color.value = color.value.value(value[0])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -263,7 +273,7 @@ function onSubmitHexInput() {
|
|||||||
input = '#' + input
|
input = '#' + input
|
||||||
}
|
}
|
||||||
if (input.match(/^#[0-9A-F]{6}$/i)) {
|
if (input.match(/^#[0-9A-F]{6}$/i)) {
|
||||||
emit('input', Color(input))
|
color.value = Color(input)
|
||||||
} else shake()
|
} else shake()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,10 +284,10 @@ function onSubmitHueInput() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const newHue = Math.max(0, Math.min(input, 360))
|
const newHue = Math.max(0, Math.min(input, 360))
|
||||||
if (newHue === props.color.hue()) {
|
if (newHue === color.value.hue()) {
|
||||||
updateInputs()
|
updateInputs()
|
||||||
}
|
}
|
||||||
emit('input', props.color.hue(newHue))
|
color.value = color.value.hue(newHue)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSubmitSaturationInput() {
|
function onSubmitSaturationInput() {
|
||||||
@@ -287,10 +297,10 @@ function onSubmitSaturationInput() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const newSaturation = Math.max(0, Math.min(input, 100))
|
const newSaturation = Math.max(0, Math.min(input, 100))
|
||||||
if (newSaturation === props.color.saturationv()) {
|
if (newSaturation === color.value.saturationv()) {
|
||||||
updateInputs()
|
updateInputs()
|
||||||
}
|
}
|
||||||
emit('input', props.color.saturationv(newSaturation))
|
color.value = color.value.saturationv(newSaturation)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSubmitValueInput() {
|
function onSubmitValueInput() {
|
||||||
@@ -300,10 +310,10 @@ function onSubmitValueInput() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const newValue = Math.max(0, Math.min(input, 100))
|
const newValue = Math.max(0, Math.min(input, 100))
|
||||||
if (newValue === props.color.value()) {
|
if (newValue === color.value.value()) {
|
||||||
updateInputs()
|
updateInputs()
|
||||||
}
|
}
|
||||||
emit('input', props.color.value(newValue))
|
color.value = color.value.value(newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSubmitRGBInput() {
|
function onSubmitRGBInput() {
|
||||||
@@ -315,27 +325,26 @@ function onSubmitRGBInput() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const newColor = Color.rgb(r, g, b)
|
const newColor = Color.rgb(r, g, b)
|
||||||
if (newColor.hex() === props.color.hex()) {
|
if (newColor.hex() === color.value.hex()) {
|
||||||
updateInputs()
|
updateInputs()
|
||||||
}
|
}
|
||||||
emit('input', newColor)
|
color.value = newColor
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateInputs() {
|
function updateInputs() {
|
||||||
console.log('COLORRR', props.color)
|
hexInput.value = color.value.hex().substring(1, 7)
|
||||||
hexInput.value = props.color.hex().substring(1, 7)
|
hueInput.value = String(parseInt(color.value.hue())).padStart(3, '0')
|
||||||
hueInput.value = String(parseInt(props.color.hue())).padStart(3, '0')
|
saturationInput.value = String(parseInt(color.value.saturationv())).padStart(3, '0')
|
||||||
saturationInput.value = String(parseInt(props.color.saturationv())).padStart(3, '0')
|
valueInput.value = String(parseInt(color.value.value())).padStart(3, '0')
|
||||||
valueInput.value = String(parseInt(props.color.value())).padStart(3, '0')
|
rInput.value = String(parseInt(color.value.red())).padStart(3, '0')
|
||||||
rInput.value = String(parseInt(props.color.red())).padStart(3, '0')
|
gInput.value = String(parseInt(color.value.green())).padStart(3, '0')
|
||||||
gInput.value = String(parseInt(props.color.green())).padStart(3, '0')
|
bInput.value = String(parseInt(color.value.blue())).padStart(3, '0')
|
||||||
bInput.value = String(parseInt(props.color.blue())).padStart(3, '0')
|
hueSliderValue.value = color.value.hue()
|
||||||
hueSliderValue.value = props.color.hue()
|
saturationSliderValue.value = color.value.saturationv()
|
||||||
saturationSliderValue.value = props.color.saturationv()
|
valueSliderValue.value = color.value.value()
|
||||||
valueSliderValue.value = props.color.value()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => props.color, updateInputs)
|
watch(() => props.colorNumber, updateInputs)
|
||||||
onBeforeMount(updateInputs)
|
onBeforeMount(updateInputs)
|
||||||
|
|
||||||
const colorFieldText = ref(null)
|
const colorFieldText = ref(null)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div
|
<div
|
||||||
class="pt-2"
|
class="pt-2"
|
||||||
:style="{
|
:style="{
|
||||||
background: `linear-gradient(180deg, ${options[currentOption].color.hex() + '11'}, ${options[currentOption].color.hex() + '30'} 25%, ${options[currentOption].color.hex() + '30'} 40%, transparent 60%`
|
background: `linear-gradient(180deg, ${currentColorHex + '11'}, ${currentColorHex + '30'} 25%, ${currentColorHex + '30'} 40%, transparent 60%`
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -28,13 +28,13 @@
|
|||||||
:key="key"
|
:key="key"
|
||||||
class="h-6 flex-1"
|
class="h-6 flex-1"
|
||||||
:class="{ 'color-tab': currentOption === key }"
|
:class="{ 'color-tab': currentOption === key }"
|
||||||
:style="{ background: option.color.hex() }"
|
:style="{ background: Color(option.colorNumber).hex() }"
|
||||||
@click="currentOption = key"
|
@click="currentOption = key"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<HSVInput
|
<HSVInput
|
||||||
:color="options[currentOption].color"
|
:color-number="options[currentOption].colorNumber"
|
||||||
@input="(color) => $emit('input', currentOption, color)"
|
@input="(colorNumber) => $emit('input', currentOption, colorNumber)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -47,7 +47,7 @@ defineEmits(['input'])
|
|||||||
|
|
||||||
const currentOption = ref(null)
|
const currentOption = ref(null)
|
||||||
|
|
||||||
const currentColorHex = computed(() => props.options[currentOption.value].color.hex())
|
const currentColorHex = computed(() => Color(props.options[currentOption.value].colorNumber).hex())
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
options: {
|
options: {
|
||||||
@@ -55,15 +55,15 @@ const props = defineProps({
|
|||||||
default: () => ({
|
default: () => ({
|
||||||
one: {
|
one: {
|
||||||
titleKey: 'One',
|
titleKey: 'One',
|
||||||
color: Color('#ff0000')
|
colorNumber: Color('#ff0000').rgbNumber()
|
||||||
},
|
},
|
||||||
two: {
|
two: {
|
||||||
titleKey: 'Two',
|
titleKey: 'Two',
|
||||||
color: Color('#00ff00')
|
colorNumber: Color('#00ff00').rgbNumber()
|
||||||
},
|
},
|
||||||
three: {
|
three: {
|
||||||
titleKey: 'Three',
|
titleKey: 'Three',
|
||||||
color: Color('#0000ff')
|
colorNumber: Color('#0000ff').rgbNumber()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
<PaletteInput
|
<PaletteInput
|
||||||
:options="keyColors"
|
:options="keyColors"
|
||||||
@input="
|
@input="
|
||||||
(optionKey, color) => {
|
(optionKey, colorNumber) => {
|
||||||
keyColors = {
|
keyColors = {
|
||||||
...keyColors,
|
...keyColors,
|
||||||
[optionKey]: {
|
[optionKey]: {
|
||||||
...keyColors[optionKey],
|
...keyColors[optionKey],
|
||||||
color
|
colorNumber
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,6 @@
|
|||||||
import { Palette } from 'lucide-vue-next'
|
import { Palette } from 'lucide-vue-next'
|
||||||
import ConfigSection from '@renderer/components/common/ConfigSection.vue'
|
import ConfigSection from '@renderer/components/common/ConfigSection.vue'
|
||||||
import PaletteInput from '@renderer/components/common/PaletteInput.vue'
|
import PaletteInput from '@renderer/components/common/PaletteInput.vue'
|
||||||
import Color from 'color'
|
|
||||||
import { useDeviceStore } from '@renderer/deviceStore'
|
import { useDeviceStore } from '@renderer/deviceStore'
|
||||||
import { useAppStore } from '@renderer/appStore'
|
import { useAppStore } from '@renderer/appStore'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
@@ -35,17 +34,17 @@ const keyColors = computed({
|
|||||||
return {
|
return {
|
||||||
default: {
|
default: {
|
||||||
titleKey: 'default',
|
titleKey: 'default',
|
||||||
color: Color(keyColor.value(appStore.selectedKey, false))
|
colorNumber: keyColor.value(appStore.selectedKey, false)
|
||||||
},
|
},
|
||||||
pressed: {
|
pressed: {
|
||||||
titleKey: 'pressed',
|
titleKey: 'pressed',
|
||||||
color: Color(keyColor.value(appStore.selectedKey, true))
|
colorNumber: keyColor.value(appStore.selectedKey, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
set(newValue) {
|
set(newValue) {
|
||||||
deviceStore.setKeyColor(appStore.selectedKey, false, Color(newValue.default.color).rgbNumber())
|
deviceStore.setKeyColor(appStore.selectedKey, false, newValue.default.colorNumber)
|
||||||
deviceStore.setKeyColor(appStore.selectedKey, true, Color(newValue.pressed.color).rgbNumber())
|
deviceStore.setKeyColor(appStore.selectedKey, true, newValue.pressed.colorNumber)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user