|
|
@ -1,7 +1,6 @@ |
|
|
|
<script lang="ts" setup> |
|
|
|
<script lang="ts" setup> |
|
|
|
import { Slider } from '@ckpack/vue-color' |
|
|
|
import { Slider } from '@ckpack/vue-color' |
|
|
|
import tinycolor from 'tinycolor2' |
|
|
|
import tinycolor from 'tinycolor2' |
|
|
|
import { ProjectInj } from '#imports' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{ |
|
|
|
const props = defineProps<{ |
|
|
|
hue?: number | undefined |
|
|
|
hue?: number | undefined |
|
|
@ -16,45 +15,34 @@ const { hue, size = 'medium', readonly } = props |
|
|
|
|
|
|
|
|
|
|
|
const hueData = [199, 24, 41, 141, 224, 3, 317, 271, 332] |
|
|
|
const hueData = [199, 24, 41, 141, 224, 3, 317, 271, 332] |
|
|
|
|
|
|
|
|
|
|
|
const base = inject(ProjectInj)! |
|
|
|
const defaultHueValue = { |
|
|
|
|
|
|
|
h: 0, |
|
|
|
const localHue = ref(hue) |
|
|
|
s: 0, |
|
|
|
|
|
|
|
v: 0, |
|
|
|
const clearable = computed(() => { |
|
|
|
} |
|
|
|
return !props.disableClearing && !readonly |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const isOpen = ref(false) |
|
|
|
const isOpen = ref(false) |
|
|
|
|
|
|
|
|
|
|
|
const isOpenHuePicker = ref(false) |
|
|
|
const isOpenHuePicker = ref(false) |
|
|
|
|
|
|
|
|
|
|
|
const colorRefs = ref( |
|
|
|
const colorRef = ref( |
|
|
|
localHue.value !== undefined |
|
|
|
hue !== undefined && hue !== null |
|
|
|
? { |
|
|
|
? { |
|
|
|
h: localHue.value, |
|
|
|
...defaultHueValue, |
|
|
|
s: 0, |
|
|
|
h: hue, |
|
|
|
v: 0, |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
: undefined, |
|
|
|
: undefined, |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const colorRef = computed({ |
|
|
|
function selectColor(value: number | null) { |
|
|
|
get: () => { |
|
|
|
if (value === null) { |
|
|
|
return localHue.value !== undefined |
|
|
|
colorRef.value = undefined |
|
|
|
? { |
|
|
|
} else { |
|
|
|
h: localHue.value, |
|
|
|
colorRef.value = { |
|
|
|
s: 0, |
|
|
|
...defaultHueValue, |
|
|
|
v: 0, |
|
|
|
h: value, |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
: undefined |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
set: (val) => { |
|
|
|
|
|
|
|
localHue.value = val?.hsv?.h |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function selectColor(value: number) { |
|
|
|
|
|
|
|
localHue.value = value |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
emit('colorSelected', value) |
|
|
|
emit('colorSelected', value) |
|
|
|
|
|
|
|
|
|
|
@ -70,15 +58,24 @@ const onClick = (e: Event) => { |
|
|
|
isOpen.value = !isOpen.value |
|
|
|
isOpen.value = !isOpen.value |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const showClearButton = computed(() => { |
|
|
|
watch( |
|
|
|
return colorRef.value?.h !== undefined && clearable.value |
|
|
|
isOpenHuePicker, |
|
|
|
}) |
|
|
|
() => { |
|
|
|
|
|
|
|
if (!isOpenHuePicker.value && colorRef.value?.h !== hue) { |
|
|
|
watch(isOpenHuePicker, () => { |
|
|
|
if (isNaN(parseFloat(`${hue}`))) { |
|
|
|
if (!isOpenHuePicker.value && localHue.value !== parseProp(base.value.meta).iconHue) { |
|
|
|
colorRef.value = undefined |
|
|
|
localHue.value = parseProp(base.value.meta).iconHue |
|
|
|
} else { |
|
|
|
|
|
|
|
colorRef.value = { |
|
|
|
|
|
|
|
...defaultHueValue, |
|
|
|
|
|
|
|
h: hue as number, |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
immediate: true, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
) |
|
|
|
</script> |
|
|
|
</script> |
|
|
|
|
|
|
|
|
|
|
|
<template> |
|
|
|
<template> |
|
|
@ -95,7 +92,7 @@ watch(isOpenHuePicker, () => { |
|
|
|
}" |
|
|
|
}" |
|
|
|
@click="onClick" |
|
|
|
@click="onClick" |
|
|
|
> |
|
|
|
> |
|
|
|
<template v-if="hue === undefined"> |
|
|
|
<template v-if="colorRef?.h === undefined"> |
|
|
|
<slot name="default" /> |
|
|
|
<slot name="default" /> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
<template v-else> |
|
|
|
<template v-else> |
|
|
@ -129,25 +126,25 @@ watch(isOpenHuePicker, () => { |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<template #overlay> |
|
|
|
<template #overlay> |
|
|
|
<div |
|
|
|
<div class="relative bg-white rounded-lg p-3 border-1 border-gray-200 shadow-lg"> |
|
|
|
class="relative bg-white rounded-lg p-3 border-1 border-gray-200 shadow-lg" |
|
|
|
|
|
|
|
:class="{ |
|
|
|
|
|
|
|
clearable: showClearButton, |
|
|
|
|
|
|
|
}" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<div class="w-[164px] flex flex-wrap"> |
|
|
|
<div class="w-[164px] flex flex-wrap"> |
|
|
|
<div |
|
|
|
<div |
|
|
|
v-for="(hue, i) of hueData" |
|
|
|
v-for="(h, i) of hueData" |
|
|
|
:key="i" |
|
|
|
:key="i" |
|
|
|
class="p-1 rounded cursor-pointer hover:bg-gray-200" |
|
|
|
class="nc-pre-defined-hue-item p-1 rounded cursor-pointer hover:bg-gray-200" |
|
|
|
:class="i > 4 ? 'mt-3' : ''" |
|
|
|
:class="{ |
|
|
|
|
|
|
|
'mt-3': i > 4, |
|
|
|
|
|
|
|
}" |
|
|
|
> |
|
|
|
> |
|
|
|
<div |
|
|
|
<div |
|
|
|
class="rounded h-6 w-6" |
|
|
|
class="rounded h-6 w-6" |
|
|
|
|
|
|
|
:class="{ |
|
|
|
|
|
|
|
selected: h === hue, |
|
|
|
|
|
|
|
}" |
|
|
|
:style="{ |
|
|
|
:style="{ |
|
|
|
backgroundColor: tinycolor(`hsv(${hue}, 30%, 100%) `).toHexString(), |
|
|
|
backgroundColor: tinycolor(`hsv(${h}, 30%, 100%) `).toHexString(), |
|
|
|
}" |
|
|
|
}" |
|
|
|
@click="selectColor(hue)" |
|
|
|
@click="selectColor(h)" |
|
|
|
></div> |
|
|
|
></div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
@ -156,11 +153,19 @@ watch(isOpenHuePicker, () => { |
|
|
|
:trigger="['click']" |
|
|
|
:trigger="['click']" |
|
|
|
:disabled="readonly" |
|
|
|
:disabled="readonly" |
|
|
|
placement="bottom" |
|
|
|
placement="bottom" |
|
|
|
overlayClassName="!left-8.5" |
|
|
|
overlayClassName="!left-9" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<div |
|
|
|
|
|
|
|
class="nc-custom-hue-picker-item p-1 rounded cursor-pointer hover:bg-gray-200 mt-3" |
|
|
|
|
|
|
|
:class="{ |
|
|
|
|
|
|
|
'bg-gray-200': isOpenHuePicker, |
|
|
|
|
|
|
|
}" |
|
|
|
> |
|
|
|
> |
|
|
|
<div class="p-1 rounded cursor-pointer hover:bg-gray-200 mt-3"> |
|
|
|
|
|
|
|
<div |
|
|
|
<div |
|
|
|
class="rounded overflow-hidden h-6 w-6" |
|
|
|
class="rounded overflow-hidden h-6 w-6" |
|
|
|
|
|
|
|
:class="{ |
|
|
|
|
|
|
|
selected: hue !== undefined && hue !== null && !hueData.includes(hue), |
|
|
|
|
|
|
|
}" |
|
|
|
:style="{ |
|
|
|
:style="{ |
|
|
|
backgroundColor: tinycolor(`hsv(${hue}, 30%, 100%) `).toHexString(), |
|
|
|
backgroundColor: tinycolor(`hsv(${hue}, 30%, 100%) `).toHexString(), |
|
|
|
}" |
|
|
|
}" |
|
|
@ -169,49 +174,72 @@ watch(isOpenHuePicker, () => { |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<template #overlay> |
|
|
|
<template #overlay> |
|
|
|
<div |
|
|
|
<div class="relative bg-white rounded-lg p-3 border-1 border-gray-200 shadow-lg flex flex-col space-y-4"> |
|
|
|
class="relative bg-white rounded-lg p-3 border-1 border-gray-200 shadow-lg flex flex-col space-y-3" |
|
|
|
<div class="text-sm font-semibold">{{ $t('labels.customHue') }}</div> |
|
|
|
:class="{ |
|
|
|
|
|
|
|
clearable: showClearButton, |
|
|
|
|
|
|
|
}" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<div class="text-sm font-semibold">Custom Hue</div> |
|
|
|
|
|
|
|
<Slider |
|
|
|
<Slider |
|
|
|
:model-value="colorRef" |
|
|
|
:model-value="colorRef" |
|
|
|
class="nc-hue-color-picker" |
|
|
|
class="nc-hue-color-picker" |
|
|
|
|
|
|
|
:style="{ |
|
|
|
|
|
|
|
['--nc-hue-slider-pointer-color']: tinycolor(`hsv(${colorRef?.h}, 100%, 100%)`).toHexString(), |
|
|
|
|
|
|
|
}" |
|
|
|
:disable-fields="true" |
|
|
|
:disable-fields="true" |
|
|
|
@update:model-value=" |
|
|
|
@update:model-value=" |
|
|
|
(value) => { |
|
|
|
(value) => { |
|
|
|
console.log('update', value) |
|
|
|
if (value?.hsv?.h === undefined) return |
|
|
|
|
|
|
|
colorRef = { |
|
|
|
|
|
|
|
...defaultHueValue, |
|
|
|
|
|
|
|
h: +value.hsv.h, |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
" |
|
|
|
" |
|
|
|
/> |
|
|
|
/> |
|
|
|
|
|
|
|
|
|
|
|
<div class="flex items-center justify-end"> |
|
|
|
<div class="flex items-center justify-end"> |
|
|
|
<NcButton type="secondary" size="small" @click="selectColor(localHue)"> Apply </NcButton> |
|
|
|
<NcButton type="secondary" size="small" @click="selectColor(colorRef?.h || 0)"> |
|
|
|
|
|
|
|
{{ $t('general.apply') }} |
|
|
|
|
|
|
|
</NcButton> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
</a-dropdown> |
|
|
|
</a-dropdown> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mt-3 flex items-center justify-end"> |
|
|
|
|
|
|
|
<NcButton type="secondary" size="small" @click.stop="selectColor(null)"> {{ $t('general.remove') }} </NcButton> |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
</a-dropdown> |
|
|
|
</a-dropdown> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss"> |
|
|
|
<style lang="scss" scoped> |
|
|
|
.clearable { |
|
|
|
.nc-pre-defined-hue-item, |
|
|
|
.emoji-mart-search { |
|
|
|
.nc-custom-hue-picker-item { |
|
|
|
@apply pr-22; |
|
|
|
.selected { |
|
|
|
|
|
|
|
box-shadow: 0 0 0 2px #fff, 0 0 0 4px #3069fe; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.nc-hue-color-picker { |
|
|
|
:deep(.nc-hue-color-picker) { |
|
|
|
|
|
|
|
&.vc-slider { |
|
|
|
|
|
|
|
width: 297px; |
|
|
|
|
|
|
|
} |
|
|
|
.vc-slider-swatches { |
|
|
|
.vc-slider-swatches { |
|
|
|
@apply hidden; |
|
|
|
@apply hidden; |
|
|
|
} |
|
|
|
} |
|
|
|
.vc-hue { |
|
|
|
.vc-hue { |
|
|
|
@apply rounded-lg; |
|
|
|
@apply rounded-lg; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.vc-slider-hue-warp { |
|
|
|
|
|
|
|
height: 6px; |
|
|
|
|
|
|
|
.vc-hue-pointer { |
|
|
|
|
|
|
|
top: -3px !important; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
.vc-hue-picker { |
|
|
|
|
|
|
|
background-color: white; |
|
|
|
|
|
|
|
box-shadow: 0 0 0 3px var(--nc-hue-slider-pointer-color) !important; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
</style> |
|
|
|
</style> |
|
|
|