@indielayer/ui
Version:
Indielayer UI Components with Tailwind CSS build for Vue 3
99 lines (77 loc) • 2.5 kB
text/typescript
import { computed, inject, unref } from 'vue'
import { injectThemeKey } from './keys'
import { isValidColor, tailwindColors, colorShade, setOpacity } from '../common/colors'
import { mergeRightDeep } from '../common/utils'
export type Tone = '50' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | '950'
export interface ColorPalette {
50: string;
100: string;
200: string;
300: string;
400: string;
500: string;
600: string;
700: string;
800: string;
900: string;
950: string;
}
export type ColorLibrary = Record<string, ColorPalette>
export interface ColorsProps {
color?: string;
}
export interface ColorComposition {
getPalette: (color?: string) => ColorPalette;
getColorOpacity: (color: string, opacity: number) => string;
}
const colorCache: ColorLibrary = {}
const defaultColors = {
primary: tailwindColors.emerald,
secondary: tailwindColors.slate,
success: tailwindColors.green,
warning: tailwindColors.yellow,
error: tailwindColors.red,
}
const getTailwindColor = (color: string) => tailwindColors[color]
const getColorOpacity = (color: string, opacity: number) => setOpacity(color, opacity)
export const useColors = (): ColorComposition => {
const globalTheme = inject(injectThemeKey, {})
const customColors = computed(() => mergeRightDeep(defaultColors, unref(globalTheme).colors || {}))
const getPalette = (color?: string): ColorPalette => {
if (!color) return getTailwindColor('gray')
const twColor = getTailwindColor(color)
if (twColor) return twColor
if (colorCache[color]) return colorCache[color]
if (customColors.value[color]) return customColors.value[color]
if (!isValidColor(color)) {
console.warn(`Invalid color: ${color}`)
return getTailwindColor('gray')
}
const palette = {
50: colorShade(color, 0.9),
100: colorShade(color, 0.8),
200: colorShade(color, 0.6),
300: colorShade(color, 0.4),
400: colorShade(color, 0.1),
500: color,
600: colorShade(color, -0.1),
700: colorShade(color, -0.25),
800: colorShade(color, -0.58),
900: colorShade(color, -0.7),
950: colorShade(color, -0.8),
}
colorCache[color] = palette
return palette
}
return {
getPalette,
getColorOpacity,
}
}
export type UseColorsProps = ReturnType<typeof useColors.props>
useColors.props = (defaultColor?: string) => ({
color: {
type: String,
default: defaultColor,
},
} as const)