Skip to content

Commit

Permalink
feat: ✨ add color-picker for ui component
Browse files Browse the repository at this point in the history
  • Loading branch information
isboyjc committed Dec 6, 2024
1 parent 3696ece commit fb72ab3
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 0 deletions.
146 changes: 146 additions & 0 deletions packages/vue3/src/components/ui/color-picker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { defineComponent, h, ref, onMounted } from "vue";
import { prefixClass } from "@isle-editor/core";
import { getAllColors, standardColors } from "@/utils";

export default defineComponent({
name: "IColorPicker",
props: {
defaultColorName: {
type: String,
default: "Default Color",
},
baseColorName: {
type: String,
default: "Base Color",
},
standardColorName: {
type: String,
default: "Standard Color",
},
recentColorName: {
type: String,
default: "Recent Use",
},
storageKey: {
type: String,
default: "ICOLORPICKER-RECENTCOLORS",
},
},
emits: ["select"],

setup(props, { emit }) {
const recentColors = ref([]);
const isShowRecentColor = computed(() => recentColors.value.length);

function recentColorsRender() {
return isShowRecentColor.value
? [
h(
"div",
{
class: `${prefixClass}-color-picker__title`,
},
props.recentColorName,
),
h(
"div",
{
class: `${prefixClass}-color-picker__recent`,
},
recentColors.value.map((color) => {
return h("div", {
class: [`${prefixClass}-color-picker__recent-item`],
style: { backgroundColor: color },
onClick: () => handleColorSelect(color),
});
}),
),
]
: [];
}

onMounted(() => {
const stored = localStorage.getItem(props.storageKey);
if (stored && Array.isArray(JSON.parse(stored))) {
recentColors.value = JSON.parse(stored).slice(0, 9);
} else {
recentColors.value = [];
}
});

const handleColorSelect = (color) => {
if (color) {
const colorIndex = recentColors.value.indexOf(color);
if (colorIndex > -1) {
recentColors.value.splice(colorIndex, 1);
}

recentColors.value.unshift(color);

if (recentColors.value.length > 9) {
recentColors.value = recentColors.value.slice(0, 9);
}

localStorage.setItem(
props.storageKey,
JSON.stringify(recentColors.value),
);
}
emit("select", color);
};

const allColors = getAllColors();

return () =>
h(
"div",
{
class: `${prefixClass}-color-picker`,
},
[
h(
"div",
{
class: `${prefixClass}-color-picker__default`,
onClick: () => handleColorSelect(""),
},
props.defaultColorName,
),
h(
"div",
{
class: `${prefixClass}-color-picker__base`,
},
allColors.map((color) =>
h("div", {
class: [`${prefixClass}-color-picker__base-item`],
style: { backgroundColor: color },
onClick: () => handleColorSelect(color),
}),
),
),
h(
"div",
{
class: `${prefixClass}-color-picker__title`,
},
props.standardColorName,
),
h(
"div",
{
class: `${prefixClass}-color-picker__standard`,
},
standardColors.map((color) => {
return h("div", {
class: [`${prefixClass}-color-picker__standard-item`],
style: { backgroundColor: color },
onClick: () => handleColorSelect(color),
});
}),
),
...recentColorsRender(),
],
);
},
});
1 change: 1 addition & 0 deletions packages/vue3/src/components/ui/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { default as IButton } from "./button";
export { default as ITooltip } from "./tooltip";
export { default as ITrigger } from "./trigger";
export { default as IDivider } from "./divider";
export { default as IColorPicker } from "./color-picker";
71 changes: 71 additions & 0 deletions packages/vue3/src/styles/ui/color-picker.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
@use "../config" as *;

.#{$prefix}-color-picker {
position: relative;

&__title {
font-size: 0.85em;
font-weight: 500;
color: var(--#{$prefix}-color-text-2);
margin-top: 0.7rem;
margin-bottom: 0.4rem;
}

&__default {
width: 100%;
height: 28px;
font-size: 0.85em;
border-radius: 0.3rem;
border: 1px solid var(--#{$prefix}-color-border);
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 0.7rem;
color: var(--#{$prefix}-color-text-1);

&:hover {
color: var(--#{$prefix}-color-text);
background-color: rgba(var(--#{$prefix}-color-border-val), 0.5);
}
}

&__base,
&__standard,
&__recent {
display: grid;
grid-template-columns: repeat(9, 20px);
grid-auto-flow: column;
grid-template-rows: repeat(6, 20px);
gap: 0.35rem;

&-item {
width: 20px;
height: 20px;
border-radius: 0.3rem;
cursor: pointer;
transition: transform 0.2s ease;
border: 1px solid rgba(var(--#{$prefix}-color-border-val), 0.5);
box-sizing: border-box;

&:hover {
transform: scale(1.15);
}

&--active {
border: 2px solid var(--#{$prefix}-color-primary);
transform: scale(1.1);
}
}
}

&__standard,
&__recent {
display: grid;
grid-auto-flow: row;
grid-template-columns: repeat(9, 20px);
grid-template-rows: repeat(1, 20px);
gap: 0.35rem;
}
}
1 change: 1 addition & 0 deletions packages/vue3/src/styles/ui/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
@use "button";
@use "divider";
@use "trigger";
@use "color-picker";
73 changes: 73 additions & 0 deletions packages/vue3/src/utils/color.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// https://tailwindcss.com/docs/customizing-colors
export const standardColors = [
"#f03e3e",
"#f76707",
"#f59f00",
"#37b24d",
"#1c7ed6",
"#1098ad",
"#ae3ec9",
"#d6336c",
"#495057",
];
export const baseColors = [
{
name: "black",
shades: ["#000000", "#212529", "#868e96", "#dee2e6", "#f1f3f5", "#ffffff"],
},
{
name: "pink",
shades: ["#a61e4d", "#c2255c", "#f06595", "#faa2c1", "#fcc2d7", "#ffdeeb"],
},
{
name: "red",
shades: ["#c92a2a", "#e03131", "#ff6b6b", "#ffa8a8", "#ffc9c9", "#ffe3e3"],
},
{
name: "orange",
shades: ["#d9480f", "#e8590c", "#ff922b", "#ffc078", "#ffd8a8", "#ffe8cc"],
},
{
name: "yellow",
shades: ["#e67700", "#f59f00", "#ffd43b", "#ffe066", "#ffec99", "#fff3bf"],
},
{
name: "green",
shades: ["#2b8a3e", "#2f9e44", "#51cf66", "#8ce99a", "#b2f2bb", "#d3f9d8"],
},
{
name: "cyan",
shades: ["#0b7285", "#0c8599", "#22b8cf", "#66d9e8", "#99e9f2", "#c5f6fa"],
},
{
name: "blue",
shades: ["#1864ab", "#1971c2", "#339af0", "#74c0fc", "#a5d8ff", "#d0ebff"],
},
{
name: "purple",
shades: ["#862e9c", "#9c36b5", "#cc5de8", "#e599f7", "#eebefa", "#f3d9fa"],
},
];

// 获取所有颜色的扁平数组
export const getAllColors = () => {
return baseColors.reduce((acc, color) => {
return acc.concat(color.shades);
}, []);
};

// 获取特定色阶的所有颜色
export const getColorsByShade = (shade) => {
return baseColors
.map((color) => {
const found = color.shades.find((c) => c === shade);
return found || null;
})
.filter(Boolean);
};

// 获取某个颜色系列的所有色阶
export const getShadesByColor = (colorName) => {
const color = baseColors.find((c) => c.name === colorName);
return color ? color.shades : [];
};
1 change: 1 addition & 0 deletions packages/vue3/src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from "./is.js";
export * from "./render.js";
export * from "./shortcutkey.js";
export * from "./tippy.js";
export * from "./color.js";

0 comments on commit fb72ab3

Please sign in to comment.