Skip to content

Commit b5aad8e

Browse files
authored
Merge pull request #300 from linx4200/dev/fix-issue-296
v3.0.3
2 parents aef9c33 + 0576761 commit b5aad8e

File tree

6 files changed

+93
-45
lines changed

6 files changed

+93
-45
lines changed

demo/App.vue

Lines changed: 64 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
<script lang="ts">
2+
import { parseSearchParams } from './utils';
3+
const pickers = ['chrome', 'sketch', 'photoshop', 'compact', 'grayscale', 'material', 'slider', 'twitter', 'swatches', 'hue'] as const;
4+
const searchParams = parseSearchParams(location.search);
5+
const manualEnabledPickers = searchParams.picker?.split(',');
6+
7+
function invertColor({ r, g, b, a}: { r: number; g: number; b: number, a: number }): string {
8+
const invert = (val: number, alpha: number) => alpha === 0 ? 0 : 255 - val;
9+
const inverted = {
10+
r: invert(r, a),
11+
g: invert(g, a),
12+
b: invert(b, a),
13+
a: a < 0.5 ? 1 - a : a
14+
};
15+
return `rgba(${inverted.r}, ${inverted.g}, ${inverted.b}, ${inverted.a})`;
16+
}
17+
18+
const hasInitialColor = !!searchParams.hex;
19+
const initialColor = `#${searchParams.hex ?? 'F5F7FA'}`;
20+
</script>
21+
122
<script setup lang="ts">
223
import { watch, computed, reactive } from 'vue';
324
@@ -18,25 +39,30 @@ import {
1839
1940
// import '../dist/vue-color.css'
2041
42+
const showStatus: Record<(typeof pickers)[number], boolean> = {} as Record<(typeof pickers)[number], boolean>;
43+
pickers.forEach((picker) => {
44+
if (!manualEnabledPickers || manualEnabledPickers.length === 0) {
45+
showStatus[picker] = true;
46+
} else {
47+
showStatus[picker] = manualEnabledPickers.indexOf(picker) > -1;
48+
}
49+
});
50+
2151
const tinyColor = defineModel('tinyColor', {
22-
default: tinycolor('#F5F7FA')
52+
default: tinycolor(initialColor)
2353
});
2454
2555
const color = defineModel({
26-
default: () => reactive({r: 0, g: 0, b: 255, a: 1})
56+
default: () => {
57+
if (hasInitialColor) {
58+
return initialColor;
59+
}
60+
// #F5F7FA
61+
return reactive({r: 245, g: 247, b: 250, a: 1})
62+
}
2763
});
2864
29-
watch(tinyColor, () => console.log('color changed ==>', tinyColor.value));
30-
31-
function invertColor(rgba: { r: number; g: number; b: number, a: number }): string {
32-
const inverted = {
33-
r: 255 - rgba.r,
34-
g: 255 - rgba.g,
35-
b: 255 - rgba.b,
36-
a: rgba.a
37-
};
38-
return `rgba(${inverted.r}, ${inverted.g}, ${inverted.b}, ${inverted.a})`;
39-
}
65+
watch(color, () => console.log('changed ==>', color.value));
4066
4167
const hex = computed(() => {
4268
return tinycolor(tinyColor.value).toHex8String();
@@ -69,11 +95,11 @@ const updateHue = (newHue: number) => {
6995
<div class="color-background" :style="[background]"></div>
7096
<div class="wrapper">
7197
<div>
72-
<div class="title text" :style="{color: textColor}">
98+
<div class="title text">
7399
<h1>Vue-color</h1><span class="tag">v3.0</span>
74100
</div>
75101

76-
<main class="intro text" :style="{color: textColor}">
102+
<main class="intro text">
77103
A collection of efficient color pickers designed for modern web development.
78104
<ul class="feature-list text" :style="{color: textColor, opacity: 0.75}">
79105
<li>✅ Modular & Tree-Shakable</li>
@@ -95,64 +121,64 @@ const updateHue = (newHue: number) => {
95121
<div :style="{flex: 0.8}">
96122
<div class="row">
97123
<div class="col">
98-
<div class="text current-color" :style="{color: textColor, opacity: 0.5}">
124+
<div class="text current-color">
99125
{{ hex }}<br />
100126
{{ color }}<br />
101127
{{ hsva }}
102128
</div>
103-
<div class="picker-container">
129+
<div class="picker-container" v-if="showStatus.chrome">
104130
<ChromePicker v-model:tinyColor="tinyColor" v-model="color" />
105-
<div class="picker-title text" :style="{color: textColor, opacity: 0.5}">&lt;ChromePicker /&gt;</div>
131+
<div class="picker-title text">&lt;ChromePicker /&gt;</div>
106132
</div>
107133
</div>
108134

109-
<div class="picker-container">
135+
<div class="picker-container" v-if="showStatus.sketch">
110136
<div><SketchPicker v-model:tinyColor="tinyColor" v-model="color" /></div>
111-
<div class="picker-title text" :style="{color: textColor, opacity: 0.5}">&lt;SketchPicker /&gt;</div>
137+
<div class="picker-title text">&lt;SketchPicker /&gt;</div>
112138
</div>
113139

114-
<div class="picker-container">
140+
<div class="picker-container" v-if="showStatus.photoshop">
115141
<div><PhotoshopPicker v-model:tinyColor="tinyColor" v-model="color" /></div>
116-
<div class="picker-title text" :style="{color: textColor, opacity: 0.5}">&lt;PhotoshopPicker /&gt;</div>
142+
<div class="picker-title text">&lt;PhotoshopPicker /&gt;</div>
117143
</div>
118144
</div>
119145
<div class="row" :style="{marginTop: '5%'}">
120146
<div class="col">
121-
<div class="picker-container">
147+
<div class="picker-container" v-if="showStatus.compact">
122148
<div><CompactPicker v-model:tinyColor="tinyColor" v-model="color" /></div>
123-
<div class="picker-title text" :style="{color: textColor, opacity: 0.5}">&lt;CompactPicker /&gt;</div>
149+
<div class="picker-title text">&lt;CompactPicker /&gt;</div>
124150
</div>
125-
<div class="picker-container">
151+
<div class="picker-container" v-if="showStatus.grayscale">
126152
<div><GrayscalePicker v-model:tinyColor="tinyColor" v-model="color" /></div>
127-
<div class="picker-title text" :style="{color: textColor, opacity: 0.5}">&lt;GrayscalePicker /&gt;</div>
153+
<div class="picker-title text">&lt;GrayscalePicker /&gt;</div>
128154
</div>
129-
<div class="picker-container">
155+
<div class="picker-container" v-if="showStatus.material">
130156
<div><MaterialPicker v-model:tinyColor="tinyColor" v-model="color" /></div>
131-
<div class="picker-title text" :style="{color: textColor, opacity: 0.5}">&lt;MaterialPicker /&gt;</div>
157+
<div class="picker-title text">&lt;MaterialPicker /&gt;</div>
132158
</div>
133159
</div>
134160

135161
<div class="col">
136-
<div class="picker-container">
162+
<div class="picker-container" v-if="showStatus.hue">
137163
<div :style="{width: '410px'}"><HueSlider :modelValue="hsva.h" @update:modelValue="updateHue" /></div>
138-
<div class="picker-title text" :style="{color: textColor, opacity: 0.5}">&lt;HueSlider /&gt;</div>
164+
<div class="picker-title text">&lt;HueSlider /&gt;</div>
139165
</div>
140166

141-
<div class="picker-container">
167+
<div class="picker-container" v-if="showStatus.slider">
142168
<div><SliderPicker v-model:tinyColor="tinyColor" v-model="color" :alpha="true" /></div>
143-
<div class="picker-title text" :style="{color: textColor, opacity: 0.5}">&lt;SliderPicker /&gt;</div>
169+
<div class="picker-title text">&lt;SliderPicker /&gt;</div>
144170
</div>
145171

146-
<div class="picker-container">
172+
<div class="picker-container" v-if="showStatus.twitter">
147173
<div><TwitterPicker v-model:tinyColor="tinyColor" v-model="color" /></div>
148-
<div class="picker-title text" :style="{color: textColor, opacity: 0.5}">&lt;TwitterPicker /&gt;</div>
174+
<div class="picker-title text">&lt;TwitterPicker /&gt;</div>
149175
</div>
150176
</div>
151177

152178
<div class="col">
153-
<div class="picker-container">
179+
<div class="picker-container" v-if="showStatus.swatches">
154180
<div><SwatchesPicker v-model:tinyColor="tinyColor" v-model="color" /></div>
155-
<div class="picker-title text" :style="{color: textColor, opacity: 0.5}">&lt;SwatchesPicker /&gt;</div>
181+
<div class="picker-title text">&lt;SwatchesPicker /&gt;</div>
156182
</div>
157183
</div>
158184
</div>
@@ -166,6 +192,7 @@ const updateHue = (newHue: number) => {
166192
font-optical-sizing: auto;
167193
font-style: normal;
168194
font-variation-settings: "wdth" 100;
195+
color: v-bind(textColor);
169196
}
170197
171198
.placeholder {
@@ -260,6 +287,7 @@ const updateHue = (newHue: number) => {
260287
.picker-title {
261288
margin-top: 10px;
262289
font-size: 14px;
290+
opacity: 0.5;
263291
}
264292
265293
.current-color {

demo/utils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function parseSearchParams(search: string): Record<string, string> {
2+
const params = new URLSearchParams(search);
3+
const result: Record<string, string> = {};
4+
5+
for (const [key, value] of params.entries()) {
6+
result[key] = value;
7+
}
8+
9+
return result;
10+
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-color",
3-
"version": "3.0.2",
3+
"version": "3.0.3",
44
"type": "module",
55
"files": [
66
"dist"

src/composable/colorModel.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { computed, type EmitFn } from 'vue';
22
import tinycolor from 'tinycolor2';
33

4+
/** extracted from function `inputToRGB` of tinycolor2 */
45
type TinyColorFormat = 'name' | 'hex8' | 'hex' | 'prgb' | 'rgb' | 'hsv' | 'hsl';
56

67
const transformToOriginalInputFormat = (color: tinycolor.Instance, originalFormat?: TinyColorFormat, isObjectOriginally = false) => {
@@ -24,7 +25,13 @@ const transformToOriginalInputFormat = (color: tinycolor.Instance, originalForma
2425
}
2526
} else {
2627
// transform back to the original format
27-
let newValue = color.toString(originalFormat);
28+
// Only 'hex' with alpha needs to be handled specifically
29+
// tinycolor2 handles alpha correctly for all other formats internally.
30+
let format = originalFormat;
31+
if (originalFormat === 'hex' && color.getAlpha() < 1) {
32+
format = 'hex8';
33+
}
34+
let newValue = color.toString(format);
2835
try {
2936
newValue = JSON.parse(newValue);
3037
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -47,13 +54,16 @@ export function defineColorModel(props: useTinyColorModelProps, emit: EmitFn) {
4754

4855
const tinyColorRef = computed({
4956
get: () => {
50-
const colorInput = props.tinyColor ?? props.modelValue;
57+
const { modelValue } = props;
58+
const colorInput = props.tinyColor ?? modelValue;
5159
const value = tinycolor(colorInput);
5260
if (typeof originalFormat === 'undefined') {
53-
originalFormat = value.getFormat() as TinyColorFormat;
61+
if (typeof modelValue !== 'undefined') {
62+
originalFormat = tinycolor(modelValue).getFormat() as TinyColorFormat;
63+
}
5464
}
5565
if (typeof isObjectOriginally === 'undefined') {
56-
if (typeof props.modelValue === 'object') {
66+
if (typeof modelValue === 'object') {
5767
isObjectOriginally = true;
5868
}
5969
}

tests/components/SketchPicker.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,11 @@ test('change color by clicking preset color', async () => {
134134
expect((emitted()['update:modelValue'][0] as [string])[0]).toBe('#417505');
135135

136136
await presetColors.last().click();
137-
expect((emitted()['update:modelValue'][1] as [string])[0]).toBe('#000000');
137+
expect((emitted()['update:modelValue'][1] as [string])[0]).toBe('#00000000');
138138

139139
presetColors.nth(10).element().dispatchEvent(new KeyboardEvent('keydown', { key: ' ' }));
140140
expect((emitted()['update:modelValue'][2] as [string])[0]).toBe('#b8e986');
141141

142142
presetColors.last().element().dispatchEvent(new KeyboardEvent('keydown', { key: ' ' }));
143-
expect((emitted()['update:modelValue'][3] as [string])[0]).toBe('#000000');
143+
expect((emitted()['update:modelValue'][3] as [string])[0]).toBe('#00000000');
144144
});

0 commit comments

Comments
 (0)