<!--
|
* @Author: ShawnPhang
|
* @Date: 2023-05-26 17:42:26
|
* @Description: 调色板
|
* @LastEditors: June 1601745371@qq.com
|
* @LastEditTime: 2024-06-20 17:46:09
|
-->
|
<template>
|
<div class="color-picker">
|
<Tabs v-if="modes.length > 1" :value="mode" @update:value="onChangeMode">
|
<TabPanel v-for="label in modes" :key="label" :label="label"></TabPanel>
|
</Tabs>
|
<div v-else class="title">{{ mode }}</div>
|
|
<template v-if="showGradient">
|
<div v-show="mode === '渐变'" class="cp__gradient flex-center">
|
<div class="cp__gradient-bar">
|
<div
|
ref="elGradientTrack"
|
class="cpgb__track"
|
style="width: 100%"
|
:style="{ background: value }"
|
>
|
<!-- tabindex="-1" 是元素可以触发 keydown 事件 -->
|
<div
|
v-for="(gradient, index) in gradients"
|
:key="index"
|
:class="[
|
'cpgb__pointer',
|
{
|
'cpgb__pointer--active': gradient === activeGradient,
|
},
|
]"
|
:data-sort="index"
|
:style="{
|
left: `${gradient.offset * 100}%`,
|
background: gradient.color,
|
}"
|
tabindex="-1"
|
@mousedown="onMousedownGradientPointer(gradient)"
|
@keydown.stop="onKeyupGradientPointer"
|
></div>
|
</div>
|
</div>
|
<AngleHandleVue v-model="angle" @change="angleChange" />
|
</div>
|
</template>
|
|
<div ref="elPalette" class="cp__palette" :style="{ background: paletteBackground }">
|
<div class="cpp__color-saturation"></div>
|
<div class="cpp__color-value"></div>
|
<div ref="elPalettePointer" class="cpp__pointer"></div>
|
</div>
|
|
<div ref="elSliderHux" class="cp__slider cp__slider-hux">
|
<div class="cps__track">
|
<div ref="elSliderHuxPointer" class="cpst__pointer"></div>
|
</div>
|
</div>
|
|
<div ref="elSliderAlpha" class="cp__slider cp__slider-alpha">
|
<div class="cpsa__background" :style="sliderAlphaBackgroundStyle"></div>
|
<div class="cps__track">
|
<div ref="elSliderAlphaPointer" class="cpst__pointer"></div>
|
</div>
|
</div>
|
|
<div class="cp__box">
|
<div class="item" @click="onClickStraw">
|
<xiguan v-if="hasEyeDrop" />
|
<input v-else class="native" type="color" @input="onClickStraw" />
|
</div>
|
<!-- <input :value="value" @input="$emit('update:value', $event.target.value)" class="input" /> -->
|
<input v-if="mode === '渐变'" class="input" :value="activeGradient.color" />
|
<input v-else :value="value" class="input" @blur="onInputBlur" />
|
<template v-if="mode === '纯色'">
|
<div
|
v-for="pc in predefine"
|
:key="pc"
|
class="item item-color"
|
:style="{ background: pc }"
|
@click="onClickStraw({ target: { value: pc } })"
|
></div>
|
</template>
|
<!-- <input :value="alpha" class="w-12" size="small" :min="0" :max="100" @input="onChangeAlpha" @change="onChangeAlpha" /> -->
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import './index.css';
|
export default {
|
name: 'ColorPicker',
|
inheritAttrs: false,
|
};
|
</script>
|
|
<script setup>
|
// import { ref, reactive, computed, watch, onMounted, nextTick, onBeforeUnmount } from 'vue';
|
import { registerMoveableElement } from './utils/moveable.ts';
|
import { hexA2HSLA, HSLA2HexA, hex2RGB, RGB2HSL, hexA2RGBA, RGBA2HexA } from './utils/color.ts';
|
import { toGradientString, parseBackgroundValue, toolTip } from './utils/helper.ts';
|
import Tabs from './comps/Tabs.vue';
|
import xiguan from './comps/svg.vue';
|
import TabPanel from './comps/TabPanel.vue';
|
import { debounce } from 'lodash-es';
|
import AngleHandleVue from './comps/AngleHandle.vue';
|
|
const props = defineProps({
|
value: {
|
type: String,
|
default: '#ffffffff',
|
},
|
|
modes: {
|
type: Array,
|
default: () => ['纯色', '渐变'], // 图案
|
},
|
|
defaultColor: {
|
type: String,
|
default: '#ffffffff',
|
},
|
|
defaultGradient: {
|
type: String,
|
default: 'linear-gradient(90deg, #fffae0ff 0%, #ffd1f1ff 100%)',
|
},
|
|
defaultImage: {
|
type: String,
|
default: 'https://st0.dancf.com/csc/157/material-2d-textures/0/20190714-174653-ed3c.jpg',
|
},
|
});
|
|
const emit = defineEmits(['update:value', 'change', 'native-pick', 'blur']);
|
|
const mode = ref(parseBackgroundValue(props.value)); // 颜色、渐变、图片
|
const angle = ref(90);
|
const gradients = ref([]);
|
const hsla = reactive({ h: 0, s: 0, l: 0, a: 0 });
|
const paletteBackground = ref('#f00');
|
const hex = ref('#000');
|
const alpha = ref(0);
|
let activeGradient = ref({});
|
const hasEyeDrop = 'EyeDropper' in window;
|
|
const elGradientTrack = ref();
|
const elPalette = ref();
|
const elPalettePointer = ref();
|
const elSliderHuxPointer = ref();
|
const elSliderHux = ref();
|
const elSliderAlphaPointer = ref();
|
const elSliderAlpha = ref();
|
// const elStrawCanvas = ref();
|
|
let gradientMoveable = null;
|
let paletteMoveable = null;
|
let sliderHuxMoveable = null;
|
let sliderAlphaMoveable = null;
|
let mousedownGradientPointer = null;
|
let backendHex = null;
|
// 是否可以改变 palette sliderHux sliderAlpha 的 pointer 位置
|
let canChangeHSLAPointerPos = true;
|
let canChangeHSLAPointerPosTimer = null;
|
|
const predefine = ref([]); // 历史记录
|
|
const record = {
|
color: props.defaultColor,
|
gradient: props.defaultGradient,
|
image: props.defaultImage,
|
};
|
|
const showGradient = computed(() => {
|
return props.modes.includes('渐变');
|
});
|
|
const sliderAlphaBackgroundStyle = computed(() => {
|
const rgb = hex2RGB(hex.value).join(',');
|
return {
|
background: `linear-gradient(to right, rgba(${rgb}, 0) 0%, rgb(${rgb}) 100%)`,
|
};
|
});
|
|
watch(activeGradient, (value) => {
|
setColor(value.color);
|
});
|
|
watch(hex, (value) => {
|
onChangeHex(value);
|
});
|
|
watch(
|
() => props.value,
|
(value) => {
|
const _mode = parseBackgroundValue(value);
|
if (_mode !== mode.value) {
|
mode.value = _mode;
|
}
|
changeMode(_mode);
|
recordValue(value);
|
addHistory(value);
|
}
|
);
|
|
// TODO: 添加选择历史记录
|
const addHistory = debounce(async (value) => {
|
const history = predefine.value;
|
// 如果已经存在就提到前面来,避免重复
|
const index = history.indexOf(value);
|
if (index !== -1) {
|
predefine.value.splice(index, 1);
|
}
|
if (history.length >= 4) {
|
predefine.value.splice(history.length - 1, 1);
|
}
|
// 把最新的颜色放在头部
|
const head = [value];
|
predefine.value = head.concat(history);
|
}, 300);
|
|
const unwatchHSLA = watch(hsla, onChangeHSLA, { deep: true });
|
function onChangeHSLA(newHsla) {
|
const hexA = HSLA2HexA(...Object.values(newHsla));
|
|
let value;
|
if (mode.value === '纯色') {
|
value = hexA;
|
} else if (mode.value === '渐变') {
|
activeGradient.value.color = hexA;
|
value = toGradientString(angle.value, gradients.value);
|
}
|
updateColorData(hexA);
|
updateValue(value);
|
}
|
|
onMounted(onMountedCallback);
|
async function onMountedCallback() {
|
elPalettePointer.value.style.left = `${hsla.s}%`;
|
elPalettePointer.value.style.top = `${100 - hsla.l}%`;
|
elSliderHuxPointer.value.style.left = `${(hsla.h / 360) * 100}%`;
|
elSliderAlphaPointer.value.style.left = `${hsla.a * 100}%`;
|
|
if (showGradient.value) {
|
gradientMoveable = registerMoveableElement(elGradientTrack.value, {
|
onmousedown: onMousedownGradient,
|
onmousemove: onMousemoveGradient,
|
onmouseup: onMouseupGradient,
|
});
|
}
|
|
function onMousedownGradient(position) {
|
if (mousedownGradientPointer) {
|
return;
|
}
|
|
const index = gradients.value.findIndex((stop) => stop.offset >= position.x);
|
const start = gradients.value[index - 1];
|
const startRGBA = hexA2RGBA(start.color);
|
const end = gradients.value[index];
|
const endRGBA = hexA2RGBA(end.color);
|
|
const rgb = [];
|
for (let i = 0; i < 3; i += 1) {
|
rgb.push(startRGBA[i] + (endRGBA[i] - startRGBA[i]) * position.x);
|
}
|
|
const a = end.offset - position.x - (position.x - start.offset) > 0 ? startRGBA[3] : endRGBA[3];
|
|
const color = RGBA2HexA(...rgb, a);
|
activeGradient.value = {
|
color,
|
offset: position.x,
|
};
|
|
gradients.value.splice(index, 0, activeGradient.value);
|
}
|
|
function onMousemoveGradient(position) {
|
if (!mousedownGradientPointer) return;
|
|
activeGradient.value.offset = position.x;
|
gradients.value.sort((a, b) => a.offset - b.offset);
|
|
const value = toGradientString(angle.value, gradients.value);
|
updateValue(value);
|
}
|
|
function onMouseupGradient() {
|
mousedownGradientPointer = false;
|
}
|
|
paletteMoveable = registerMoveableElement(elPalette.value, {
|
onmousemove: onChangeSL,
|
onmouseup: onChangeSL,
|
});
|
|
function onChangeSL(position) {
|
disableChangeHSLA();
|
|
try {
|
const x = position.x * 100;
|
const y = position.y * 100;
|
|
hsla.s = Math.round(x);
|
hsla.l = Math.round(100 - y);
|
|
elPalettePointer.value.style.left = `${x}%`;
|
elPalettePointer.value.style.top = `${y}%`;
|
} catch (error) {
|
console.log(error);
|
}
|
}
|
|
sliderHuxMoveable = registerMoveableElement(elSliderHux.value, {
|
onmousemove: onChangeHux,
|
onmouseup: onChangeHux,
|
});
|
|
function onChangeHux(position) {
|
disableChangeHSLA();
|
|
hsla.h = position.x * 360;
|
elSliderHuxPointer.value.style.left = `${position.x * 100}%`;
|
}
|
|
sliderAlphaMoveable = registerMoveableElement(elSliderAlpha.value, {
|
onmousemove: onChangeAlpha,
|
onmouseup: onChangeAlpha,
|
});
|
|
function onChangeAlpha(position) {
|
disableChangeHSLA();
|
|
hsla.a = position.x;
|
elSliderAlphaPointer.value.style.left = `${position.x * 100}%`;
|
}
|
|
changeMode(mode.value);
|
recordValue(props.value);
|
}
|
|
onBeforeUnmount(() => {
|
paletteMoveable?.destroy();
|
sliderHuxMoveable?.destroy();
|
sliderAlphaMoveable?.destroy();
|
unwatchHSLA();
|
|
if (gradientMoveable) {
|
gradientMoveable.destroy();
|
}
|
});
|
|
function recordValue(value) {
|
if (mode.value === '纯色') {
|
record.color = value;
|
} else if (mode.value === '渐变') {
|
record.gradient = value;
|
} else if (mode.value === '图案') {
|
record.image = value;
|
}
|
}
|
|
function updateValue(value) {
|
// 纯色时value和props.value 一样导致不更新
|
// if (value === props.value) return;
|
recordValue(value);
|
emit('update:value', value);
|
|
emit('change', {
|
mode: mode.value,
|
color: value,
|
angle: Number(angle.value),
|
stops: gradients.value,
|
});
|
}
|
|
async function onChangeMode(value) {
|
if (value === mode.value) return;
|
mode.value = value;
|
|
let color;
|
if (value === '纯色') {
|
color = record.color;
|
} else if (value === '渐变') {
|
color = record.gradient;
|
} else if (value === '图案') {
|
color = record.image;
|
}
|
updateValue(color);
|
}
|
|
function changeMode(mode) {
|
if (mode === '纯色') {
|
setColor(props.value);
|
} else if (mode === '渐变') {
|
if (gradients.value.length === 0) {
|
props.value.match(/[^,]+/g).forEach((item, index) => {
|
if (index === 0) {
|
angle.value = Number(item.match(/\d+/)[0]);
|
return;
|
}
|
|
let [color, offset] = item.trim().split(' ');
|
if (!color.startsWith('#')) color = RGBA2HexA(color);
|
|
offset = offset.match(/\d+/)[0] / 100;
|
gradients.value.push({ color, offset });
|
activeGradient.value = gradients.value[0];
|
});
|
} else {
|
setColor(activeGradient.value.color);
|
}
|
}
|
|
// TODO: 图案
|
}
|
|
function updateColorData(hexA) {
|
paletteBackground.value = `hsl(${hsla.h}, 100%, 50%)`;
|
hex.value = hexA.slice(0, 7);
|
backendHex = hex.value;
|
alpha.value = Math.round((hsla.a ?? 1) * 100);
|
}
|
|
function setColor(color) {
|
// 通过 palette sliderHux sliderAlpha 交互改变 pointer 位置
|
// 已经改变 hsla 的值并触发 update:value
|
// watch props.value 再调用当前方法时无需再更新 hsla
|
if (canChangeHSLAPointerPos) {
|
const _hsla = hexA2HSLA(color);
|
hsla.h = _hsla[0];
|
hsla.s = _hsla[1];
|
hsla.l = _hsla[2];
|
hsla.a = _hsla[3];
|
|
updateColorData(color);
|
try {
|
let x = hsla.s;
|
const y = Math.round(100 - hsla.l);
|
elPalettePointer.value.style.left = `${x}%`;
|
elPalettePointer.value.style.top = `${y}%`;
|
|
x = hsla.h / 360;
|
elSliderHuxPointer.value.style.left = `${x * 100}%`;
|
|
elSliderAlphaPointer.value.style.left = `${hsla.a * 100}%`;
|
} catch (error) {
|
console.log(error);
|
}
|
}
|
}
|
|
function onMousedownGradientPointer(stop) {
|
mousedownGradientPointer = true;
|
activeGradient.value = stop;
|
}
|
|
function onKeyupGradientPointer(event) {
|
event.stopPropagation();
|
event.preventDefault();
|
if (!['Backspace', 'Delete'].includes(event.key)) return;
|
if (gradients.value.length === 2) return;
|
|
const index = gradients.value.indexOf(activeGradient.value);
|
gradients.value.splice(index, 1);
|
activeGradient.value = gradients.value[0];
|
}
|
|
function onChangeHex(value) {
|
if (/^#(?:[0-9a-f]{3}){1,2}$/i.test(value)) {
|
const rgb = hex2RGB(value);
|
const [h, s, l] = RGB2HSL(...rgb);
|
hsla.h = h;
|
hsla.s = s;
|
hsla.l = l;
|
|
try {
|
elPalettePointer.value.style.left = `${hsla.s}%`;
|
elPalettePointer.value.style.top = `${100 - hsla.l}%`;
|
elSliderHuxPointer.value.style.left = `${(hsla.h / 360) * 100}%`;
|
|
hex.value = value;
|
} catch (error) {
|
console.log(error);
|
}
|
} else {
|
// hex.value = backendHex
|
}
|
}
|
|
// function onChangeAlpha(value) {
|
// hsla.a = value / 100;
|
// elSliderAlphaPointer.value.style.left = `${value}%`;
|
// }
|
|
function disableChangeHSLA() {
|
canChangeHSLAPointerPos = false;
|
|
if (canChangeHSLAPointerPosTimer) clearTimeout(canChangeHSLAPointerPosTimer);
|
canChangeHSLAPointerPosTimer = setTimeout(() => {
|
canChangeHSLAPointerPos = true;
|
}, 16);
|
}
|
|
async function onClickStraw(val) {
|
let result = '';
|
if (val && val.target.value) {
|
const color = val.target.value;
|
result = color + (color.length === 7 ? 'ff' : '');
|
} else {
|
const eyeDropper = new window.EyeDropper(); // 初始化一个EyeDropper对象
|
toolTip('按Esc可退出');
|
try {
|
const drop = await eyeDropper.open(); // 开始拾取颜色
|
const colorHexValue = drop.sRGBHex;
|
result = colorHexValue + 'ff';
|
} catch (e) {
|
console.log('用户取消了取色');
|
}
|
}
|
if (mode.value === '渐变') {
|
activeGradient.value.color = result;
|
activeGradient.value = { ...activeGradient.value };
|
} else {
|
emit('update:value', result);
|
}
|
emit('native-pick', result);
|
}
|
|
const onInputBlur = (e) => {
|
const fixColor = patchHexColor(e.target.value);
|
emit('blur', fixColor);
|
emit('update:value', fixColor);
|
};
|
|
function patchHexColor(str) {
|
let hex = str.replace(/\s/g, ''); // 移除空格
|
if (!str.startsWith('#')) {
|
hex = '#' + hex;
|
}
|
if (hex.length < 9) {
|
hex = hex.padEnd(9, 'f');
|
}
|
return hex;
|
}
|
|
function angleChange() {
|
updateValue(toGradientString(angle.value, gradients.value));
|
}
|
|
defineExpose({
|
updateValue,
|
});
|
</script>
|
|
<style lang="less" scoped>
|
*,
|
::before,
|
::after {
|
box-sizing: border-box;
|
border-width: 0;
|
border-style: solid;
|
border-color: #e5e7eb;
|
}
|
.flex-center {
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
}
|
.title {
|
margin-bottom: 0.75rem;
|
font-size: 15px;
|
font-weight: 600;
|
}
|
.color-picker {
|
-webkit-user-select: none;
|
user-select: none;
|
min-width: 220px;
|
}
|
|
.cp__gradient {
|
&-bar {
|
display: flex;
|
justify-content: center;
|
height: 16px;
|
width: 100%;
|
padding: 0 8px;
|
}
|
}
|
|
.cpgb__track {
|
position: relative;
|
cursor: pointer;
|
}
|
|
.cpgb__pointer {
|
cursor: grab;
|
position: absolute;
|
top: -0px;
|
top: -0.125rem;
|
height: 1.25rem;
|
--tw-translate-x: -50%;
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate))
|
skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
|
scaleY(var(--tw-scale-y));
|
border-width: 2px;
|
border-style: solid;
|
--tw-border-opacity: 1;
|
border-color: rgb(255 255 255 / var(--tw-border-opacity));
|
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
var(--tw-shadow);
|
outline: 2px solid transparent;
|
outline-offset: 2px;
|
width: 18px;
|
|
&--active {
|
z-index: 1;
|
border-radius: 3px;
|
box-shadow: 0 0 4px 0 rgb(0 0 0 / 20%), 0 0 0 1.2px #2254f4;
|
}
|
}
|
|
.cp__palette {
|
height: 140px;
|
position: relative;
|
margin-top: 0.75rem;
|
margin-top: 0.875rem;
|
cursor: pointer;
|
overflow: hidden;
|
border-radius: 0.25rem;
|
.cpp__color-saturation,
|
.cpp__color-value {
|
position: absolute;
|
bottom: 0px;
|
right: 0px;
|
top: 0px;
|
width: 100%;
|
height: 100%;
|
}
|
|
.cpp__color-saturation {
|
background-image: linear-gradient(to right, var(--tw-gradient-stops));
|
--tw-gradient-from: #fff var(--tw-gradient-from-position);
|
--tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position);
|
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
}
|
|
.cpp__color-value {
|
background-image: linear-gradient(to top, var(--tw-gradient-stops));
|
--tw-gradient-from: #000 var(--tw-gradient-from-position);
|
--tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position);
|
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
}
|
|
.cpp__pointer {
|
position: absolute;
|
height: 0.75rem;
|
width: 0.75rem;
|
--tw-translate-x: -0.25rem;
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate))
|
skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
|
scaleY(var(--tw-scale-y));
|
--tw-translate-x: -0.375rem;
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate))
|
skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
|
scaleY(var(--tw-scale-y));
|
--tw-translate-y: -0.25rem;
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate))
|
skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
|
scaleY(var(--tw-scale-y));
|
border-radius: 9999px;
|
border-width: 2px;
|
--tw-border-opacity: 1;
|
border-color: rgb(255 255 255 / var(--tw-border-opacity));
|
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
var(--tw-shadow);
|
}
|
}
|
|
.cp__slider {
|
position: relative;
|
margin-top: 0.75rem;
|
margin-top: 0.875rem;
|
height: 0.5rem;
|
border-radius: 0.25rem;
|
&-hux {
|
background: linear-gradient(
|
90deg,
|
red 0,
|
#ff0 17%,
|
#0f0 33%,
|
#0ff 50%,
|
#00f 67%,
|
#f0f 83%,
|
red
|
);
|
}
|
|
&-alpha {
|
background: linear-gradient(
|
to top right,
|
hsla(0, 0%, 80%, 0.4) 25%,
|
transparent 0,
|
transparent 75%,
|
hsla(0, 0%, 80%, 0.4) 0,
|
hsla(0, 0%, 80%, 0.4)
|
),
|
linear-gradient(
|
to top right,
|
hsla(0, 0%, 80%, 0.4) 25%,
|
transparent 0,
|
transparent 75%,
|
hsla(0, 0%, 80%, 0.4) 0,
|
hsla(0, 0%, 80%, 0.4)
|
);
|
background-size: 6px 6px;
|
background-position: 0 0, 3px 3px;
|
}
|
|
.cpsa__background {
|
box-shadow: inset 0 0 0 1px rgb(0 0 0 / 6%);
|
height: 100%;
|
border-radius: 0.25rem;
|
}
|
}
|
.cp__box {
|
margin-top: 0.75rem;
|
margin-top: 0.875rem;
|
display: flex;
|
.item {
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
cursor: pointer;
|
margin-left: 6px;
|
width: 24px;
|
height: 24px;
|
box-sizing: border-box;
|
border-radius: 4px;
|
}
|
.item-color {
|
box-shadow: inset 0 0 0 1px rgb(0 0 0 / 6%);
|
}
|
.item:first-of-type {
|
margin: 0;
|
}
|
.item:hover {
|
transform: scale(1.08);
|
}
|
.input {
|
width: 4.7rem;
|
margin-left: 2px;
|
}
|
.native {
|
width: 100%;
|
height: 100%;
|
}
|
}
|
|
.cps__track {
|
position: absolute;
|
left: 0.25rem;
|
right: 0.25rem;
|
top: 0px;
|
}
|
|
.cpst__pointer {
|
cursor: pointer;
|
box-shadow: 0 0 2px rgb(0 0 0 / 60%);
|
position: absolute;
|
top: 0px;
|
box-sizing: content-box;
|
height: 0.5rem;
|
width: 0.5rem;
|
--tw-translate-x: -0.5rem;
|
--tw-translate-y: -0.25rem;
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate))
|
skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
|
scaleY(var(--tw-scale-y));
|
border-radius: 9999px;
|
border-width: 4px;
|
--tw-border-opacity: 1;
|
border-color: rgb(255 255 255 / var(--tw-border-opacity));
|
}
|
</style>
|