mirror of
https://github.com/thatmattlove/hyperglass.git
synced 2026-01-17 08:48:05 +00:00
migrate theme functions to typescript [skip ci]
This commit is contained in:
parent
4bbf5cde12
commit
bbbfe9423b
16 changed files with 257 additions and 256 deletions
|
|
@ -5,8 +5,8 @@ import type { ICardBody } from './types';
|
|||
|
||||
export const CardBody = (props: ICardBody) => {
|
||||
const { onClick, ...rest } = props;
|
||||
const bg = useColorValue('white', 'original.dark');
|
||||
const color = useColorValue('original.dark', 'white');
|
||||
const bg = useColorValue('white', 'dark.500');
|
||||
const color = useColorValue('dark.500', 'white');
|
||||
return (
|
||||
<Flex
|
||||
bg={bg}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ export const TableRow = (props: TTableRow) => {
|
|||
let bg;
|
||||
|
||||
if (highlight) {
|
||||
bg = `${highlightBg}.${alpha}`;
|
||||
hoverBg = `${highlightBg}.${alphaHover}`;
|
||||
bg = `${String(highlightBg)}.${alpha}`;
|
||||
hoverBg = `${String(highlightBg)}.${alphaHover}`;
|
||||
} else if (doStripe && index % 2 !== 0) {
|
||||
bg = bgStripe;
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ export const TableRow = (props: TTableRow) => {
|
|||
fontWeight={highlight ? 'bold' : undefined}
|
||||
_hover={{
|
||||
cursor: 'pointer',
|
||||
backgroundColor: highlight ? `${highlightBg}.${alphaHover}` : hoverBg,
|
||||
backgroundColor: highlight ? `${String(highlightBg)}.${alphaHover}` : hoverBg,
|
||||
}}
|
||||
{...borderProps}
|
||||
{...rest}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import type { BoxProps, IconButtonProps } from '@chakra-ui/react';
|
||||
|
||||
import type { Colors, TColumn, TCellRender } from '~/types';
|
||||
import type { Theme, TColumn, TCellRender } from '~/types';
|
||||
|
||||
export interface TTable {
|
||||
columns: TColumn[];
|
||||
data: TRoute[];
|
||||
heading?: React.ReactNode;
|
||||
striped?: boolean;
|
||||
columns: TColumn[];
|
||||
heading?: React.ReactNode;
|
||||
bordersVertical?: boolean;
|
||||
bordersHorizontal?: boolean;
|
||||
Cell?: React.FC<TCellRender>;
|
||||
rowHighlightProp?: keyof IRoute;
|
||||
rowHighlightBg?: keyof Colors;
|
||||
rowHighlightBg?: Theme.ColorNames;
|
||||
}
|
||||
|
||||
export interface TTableCell extends Omit<BoxProps, 'align'> {
|
||||
|
|
@ -20,10 +20,10 @@ export interface TTableCell extends Omit<BoxProps, 'align'> {
|
|||
}
|
||||
|
||||
export interface TTableRow extends BoxProps {
|
||||
highlight?: boolean;
|
||||
highlightBg?: keyof Colors;
|
||||
doStripe?: boolean;
|
||||
highlightBg?: Theme.ColorNames;
|
||||
doHorizontalBorders?: boolean;
|
||||
highlight?: boolean;
|
||||
doStripe?: boolean;
|
||||
index: number;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ export const Logo = (props: TLogo) => {
|
|||
const { web } = useConfig();
|
||||
const { width } = web.logo;
|
||||
|
||||
const skeletonA = useColorValue('whiteFaded.100', 'blackFaded.800');
|
||||
const skeletonB = useColorValue('original.light', 'original.dark');
|
||||
const skeletonA = useColorValue('whiteSolid.100', 'blackSolid.800');
|
||||
const skeletonB = useColorValue('light.500', 'dark.500');
|
||||
|
||||
const [source, setFallback] = useLogo();
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const Info = dynamic<MeronexIcon>(() => import('@meronex/icons/fi').then(i => i.
|
|||
export const HelpModal = (props: THelpModal) => {
|
||||
const { visible, item, name, ...rest } = props;
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const bg = useColorValue('whiteFaded.50', 'blackFaded.800');
|
||||
const bg = useColorValue('whiteSolid.50', 'blackSolid.800');
|
||||
const color = useColorValue('black', 'white');
|
||||
if (!isQueryContent(item)) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export const Path = (props: TPath) => {
|
|||
const { isOpen, onClose, onOpen } = useDisclosure();
|
||||
const response = getResponse(device);
|
||||
const output = response?.output as TStructuredResponse;
|
||||
const bg = useColorValue('whiteFaded.50', 'blackFaded.900');
|
||||
const bg = useColorValue('whiteSolid.50', 'blackSolid.900');
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export const useControlStyle = (base: TStyles, state: TControl): TStyles => {
|
|||
|
||||
export const useMenuStyle = (base: TStyles, _: TMenu): TStyles => {
|
||||
const { colorMode, isOpen } = useSelectContext();
|
||||
const backgroundColor = useColorToken('colors', 'white', 'blackFaded.800');
|
||||
const backgroundColor = useColorToken('colors', 'white', 'blackSolid.700');
|
||||
const borderRadius = useToken('radii', 'md');
|
||||
const styles = { borderRadius, backgroundColor };
|
||||
return useMemo(() => mergeWith({}, base, styles), [colorMode, isOpen]);
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ import type {
|
|||
OptionProps,
|
||||
MultiValueProps,
|
||||
IndicatorProps,
|
||||
Theme,
|
||||
Theme as RSTheme,
|
||||
PlaceholderProps,
|
||||
} from 'react-select';
|
||||
import type { BoxProps } from '@chakra-ui/react';
|
||||
import type { ColorNames, TSelectOption, TSelectOptionMulti, TSelectOptionGroup } from '~/types';
|
||||
import type { Theme, TSelectOption, TSelectOptionMulti, TSelectOptionGroup } from '~/types';
|
||||
|
||||
export interface TSelectState {
|
||||
[k: string]: string[];
|
||||
|
|
@ -29,7 +29,7 @@ export interface TSelectBase extends TReactSelectChakra {
|
|||
required?: boolean;
|
||||
onSelect?: (s: TSelectOption[]) => void;
|
||||
onChange?: (c: TSelectOption | TSelectOptionMulti) => void;
|
||||
colorScheme?: ColorNames;
|
||||
colorScheme?: Theme.ColorNames;
|
||||
}
|
||||
|
||||
export interface TSelectContext {
|
||||
|
|
@ -50,7 +50,7 @@ export interface TMultiValueRemoveProps {
|
|||
selectProps: any;
|
||||
}
|
||||
|
||||
export interface TRSTheme extends Omit<Theme, 'borderRadius'> {
|
||||
export interface TRSTheme extends Omit<RSTheme, 'borderRadius'> {
|
||||
borderRadius: string | number;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import {
|
|||
import { FiSearch } from '@meronex/icons/fi';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { If, ResolvedTarget } from '~/components';
|
||||
import { useMobile } from '~/context';
|
||||
import { useMobile, useColorValue } from '~/context';
|
||||
import { useLGState, useLGMethods } from '~/hooks';
|
||||
|
||||
import type { IconButtonProps } from '@chakra-ui/react';
|
||||
|
|
@ -47,6 +47,7 @@ const SubmitIcon = forwardRef<HTMLButtonElement, Omit<IconButtonProps, 'aria-lab
|
|||
*/
|
||||
const MSubmitButton = (props: TRSubmitButton) => {
|
||||
const { children, isOpen, onClose, onChange } = props;
|
||||
const bg = useColorValue('white', 'gray.900');
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
|
|
@ -59,7 +60,7 @@ const MSubmitButton = (props: TRSubmitButton) => {
|
|||
closeOnOverlayClick={false}
|
||||
motionPreset="slideInBottom">
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalContent bg={bg}>
|
||||
<ModalCloseButton />
|
||||
<ModalBody px={4} py={10}>
|
||||
{isOpen && <ResolvedTarget setTarget={onChange} />}
|
||||
|
|
@ -75,11 +76,12 @@ const MSubmitButton = (props: TRSubmitButton) => {
|
|||
*/
|
||||
const DSubmitButton = (props: TRSubmitButton) => {
|
||||
const { children, isOpen, onClose, onChange } = props;
|
||||
const bg = useColorValue('white', 'gray.900');
|
||||
return (
|
||||
<Popover isOpen={isOpen} onClose={onClose} closeOnBlur={false}>
|
||||
<PopoverTrigger>{children}</PopoverTrigger>
|
||||
<PopoverContent>
|
||||
<PopoverArrow />
|
||||
<PopoverContent bg={bg}>
|
||||
<PopoverArrow bg={bg} />
|
||||
<PopoverCloseButton />
|
||||
<PopoverBody p={6}>{isOpen && <ResolvedTarget setTarget={onChange} />}</PopoverBody>
|
||||
</PopoverContent>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
import { makeTheme, defaultTheme } from '~/util';
|
||||
|
||||
import type { IConfig, ITheme } from '~/types';
|
||||
import type { IConfig, Theme } from '~/types';
|
||||
import type { THyperglassProvider } from './types';
|
||||
|
||||
const HyperglassContext = createContext<IConfig>(Object());
|
||||
|
|
@ -38,7 +38,7 @@ export const useConfig = (): IConfig => useContext(HyperglassContext);
|
|||
/**
|
||||
* Get the current theme object.
|
||||
*/
|
||||
export const useTheme = (): ITheme => useChakraTheme();
|
||||
export const useTheme = (): Theme.Full => useChakraTheme();
|
||||
|
||||
/**
|
||||
* Determine if device is mobile or desktop based on Chakra UI theme breakpoints.
|
||||
|
|
@ -50,7 +50,7 @@ export const useMobile = (): boolean =>
|
|||
* Convenience function to combine Chakra UI's useToken & useColorModeValue.
|
||||
*/
|
||||
export const useColorToken = <L extends string, D extends string>(
|
||||
token: keyof ITheme,
|
||||
token: keyof Theme.Full,
|
||||
light: L,
|
||||
dark: D,
|
||||
): L | D => useColorModeValue(useToken(token, light), useToken(token, dark));
|
||||
|
|
|
|||
2
hyperglass/ui/package.json
vendored
2
hyperglass/ui/package.json
vendored
|
|
@ -23,7 +23,7 @@
|
|||
"@hookstate/core": "^3.0.1",
|
||||
"@hookstate/persistence": "^3.0.0",
|
||||
"@meronex/icons": "^4.0.0",
|
||||
"chroma-js": "^2.1.0",
|
||||
"color2k": "^1.1.1",
|
||||
"dayjs": "^1.8.25",
|
||||
"framer-motion": "^3.1.1",
|
||||
"lodash": "^4.17.15",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Colors, Fonts } from './theme';
|
||||
import type { Theme } from './theme';
|
||||
|
||||
export type TQueryFields = 'query_type' | 'query_target' | 'query_location' | 'query_vrf';
|
||||
|
||||
|
|
@ -21,9 +21,9 @@ export interface IConfigMessages {
|
|||
}
|
||||
|
||||
export interface IConfigTheme {
|
||||
colors: Colors;
|
||||
colors: { [k: string]: string };
|
||||
default_color_mode: 'light' | 'dark' | null;
|
||||
fonts: Fonts;
|
||||
fonts: Theme.Fonts;
|
||||
}
|
||||
|
||||
export interface IConfigWebText {
|
||||
|
|
|
|||
|
|
@ -1,52 +1,30 @@
|
|||
import type { Theme as DefaultTheme } from '@chakra-ui/theme';
|
||||
import type { ColorHues } from '@chakra-ui/theme/dist/types/foundations/colors';
|
||||
|
||||
interface ChakraColors {
|
||||
transparent: string;
|
||||
current: string;
|
||||
black: string;
|
||||
white: string;
|
||||
whiteAlpha: ColorHues;
|
||||
blackAlpha: ColorHues;
|
||||
gray: ColorHues;
|
||||
red: ColorHues;
|
||||
orange: ColorHues;
|
||||
yellow: ColorHues;
|
||||
green: ColorHues;
|
||||
teal: ColorHues;
|
||||
blue: ColorHues;
|
||||
cyan: ColorHues;
|
||||
purple: ColorHues;
|
||||
pink: ColorHues;
|
||||
linkedin: ColorHues;
|
||||
facebook: ColorHues;
|
||||
messenger: ColorHues;
|
||||
whatsapp: ColorHues;
|
||||
twitter: ColorHues;
|
||||
telegram: ColorHues;
|
||||
}
|
||||
export namespace Theme {
|
||||
type ExtraColors = {
|
||||
primary: ColorHues;
|
||||
secondary: ColorHues;
|
||||
tertiary: ColorHues;
|
||||
dark: ColorHues;
|
||||
light: ColorHues;
|
||||
success: ColorHues;
|
||||
blackSolid: ColorHues;
|
||||
whiteSolid: ColorHues;
|
||||
};
|
||||
|
||||
interface CustomColors {
|
||||
primary: ColorHues;
|
||||
secondary: ColorHues;
|
||||
tertiary: ColorHues;
|
||||
dark: ColorHues;
|
||||
light: ColorHues;
|
||||
success: ColorHues;
|
||||
}
|
||||
export type Colors = ExtraColors & DefaultTheme['colors'];
|
||||
|
||||
type AllColors = CustomColors & ChakraColors;
|
||||
export type ColorNames = keyof AllColors;
|
||||
export type ColorNames = keyof Colors;
|
||||
|
||||
export interface Colors extends AllColors {
|
||||
original: { [key in ColorNames]: string };
|
||||
}
|
||||
export type Fonts = {
|
||||
body: string;
|
||||
mono: string;
|
||||
};
|
||||
|
||||
export interface Fonts {
|
||||
body: string;
|
||||
mono: string;
|
||||
}
|
||||
export type FontWeights = Partial<DefaultTheme['fontWeights']>;
|
||||
|
||||
export interface ITheme extends Omit<DefaultTheme, 'colors'> {
|
||||
colors: CustomColors;
|
||||
export interface Full extends Omit<DefaultTheme, 'colors'> {
|
||||
colors: Colors;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,134 +0,0 @@
|
|||
import { theme as chakraTheme } from '@chakra-ui/react';
|
||||
import chroma from 'chroma-js';
|
||||
|
||||
const alphaColors = color => ({
|
||||
900: chroma(color).alpha(0.92).css(),
|
||||
800: chroma(color).alpha(0.8).css(),
|
||||
700: chroma(color).alpha(0.6).css(),
|
||||
600: chroma(color).alpha(0.48).css(),
|
||||
500: chroma(color).alpha(0.38).css(),
|
||||
400: chroma(color).alpha(0.24).css(),
|
||||
300: chroma(color).alpha(0.16).css(),
|
||||
200: chroma(color).alpha(0.12).css(),
|
||||
100: chroma(color).alpha(0.08).css(),
|
||||
50: chroma(color).alpha(0.04).css(),
|
||||
});
|
||||
|
||||
const generateColors = colorInput => {
|
||||
const colorMap = {};
|
||||
|
||||
const lightnessMap = [0.95, 0.85, 0.75, 0.65, 0.55, 0.45, 0.35, 0.25, 0.15, 0.05];
|
||||
const saturationMap = [0.32, 0.16, 0.08, 0.04, 0, 0, 0.04, 0.08, 0.16, 0.32];
|
||||
|
||||
const validColor = chroma.valid(colorInput.trim()) ? chroma(colorInput.trim()) : chroma('#000');
|
||||
|
||||
const lightnessGoal = validColor.get('hsl.l');
|
||||
const closestLightness = lightnessMap.reduce((prev, curr) =>
|
||||
Math.abs(curr - lightnessGoal) < Math.abs(prev - lightnessGoal) ? curr : prev,
|
||||
);
|
||||
|
||||
const baseColorIndex = lightnessMap.findIndex(l => l === closestLightness);
|
||||
|
||||
const colors = lightnessMap
|
||||
.map(l => validColor.set('hsl.l', l))
|
||||
.map(color => chroma(color))
|
||||
.map((color, i) => {
|
||||
const saturationDelta = saturationMap[i] - saturationMap[baseColorIndex];
|
||||
return saturationDelta >= 0
|
||||
? color.saturate(saturationDelta)
|
||||
: color.desaturate(saturationDelta * -1);
|
||||
});
|
||||
|
||||
const getColorNumber = index => (index === 0 ? 50 : index * 100);
|
||||
|
||||
colors.map((color, i) => {
|
||||
const colorIndex = getColorNumber(i);
|
||||
colorMap[colorIndex] = color.hex();
|
||||
});
|
||||
return colorMap;
|
||||
};
|
||||
|
||||
const defaultBodyFonts = [
|
||||
'-apple-system',
|
||||
'BlinkMacSystemFont',
|
||||
'"Segoe UI"',
|
||||
'Helvetica',
|
||||
'Arial',
|
||||
'sans-serif',
|
||||
'"Apple Color Emoji"',
|
||||
'"Segoe UI Emoji"',
|
||||
'"Segoe UI Symbol"',
|
||||
];
|
||||
|
||||
const defaultMonoFonts = [
|
||||
'SFMono-Regular',
|
||||
'Melno',
|
||||
'Monaco',
|
||||
'Consolas',
|
||||
'"Liberation Mono"',
|
||||
'"Courier New"',
|
||||
'monospace',
|
||||
];
|
||||
|
||||
const generatePalette = palette => {
|
||||
const generatedPalette = {};
|
||||
Object.keys(palette).map(color => {
|
||||
if (!['black', 'white'].includes(color)) {
|
||||
generatedPalette[color] = generateColors(palette[color]);
|
||||
} else {
|
||||
generatedPalette[color] = palette[color];
|
||||
generatedPalette[`${color}Alpha`] = alphaColors(palette[color]);
|
||||
generatedPalette[`${color}Faded`] = generateColors(palette[color]);
|
||||
}
|
||||
});
|
||||
return generatedPalette;
|
||||
};
|
||||
|
||||
const formatFont = font => {
|
||||
const fontList = font.split(' ');
|
||||
const fontFmt = fontList.length >= 2 ? `'${fontList.join(' ')}'` : fontList.join(' ');
|
||||
return fontFmt;
|
||||
};
|
||||
|
||||
const importFonts = userFonts => {
|
||||
const [body, mono] = [defaultBodyFonts, defaultMonoFonts];
|
||||
const bodyFmt = formatFont(userFonts.body);
|
||||
const monoFmt = formatFont(userFonts.mono);
|
||||
if (userFonts.body && !body.includes(bodyFmt)) {
|
||||
body.unshift(bodyFmt);
|
||||
}
|
||||
if (userFonts.mono && !mono.includes(monoFmt)) {
|
||||
mono.unshift(monoFmt);
|
||||
}
|
||||
return {
|
||||
body: body.join(', '),
|
||||
heading: body.join(', '),
|
||||
mono: mono.join(', '),
|
||||
};
|
||||
};
|
||||
|
||||
const importColors = (userColors = {}) => {
|
||||
const generatedColors = generatePalette(userColors);
|
||||
return {
|
||||
transparent: 'transparent',
|
||||
current: 'currentColor',
|
||||
...generatedColors,
|
||||
};
|
||||
};
|
||||
|
||||
export const makeTheme = userTheme => ({
|
||||
...chakraTheme,
|
||||
colors: importColors(userTheme.colors),
|
||||
fonts: importFonts(userTheme.fonts),
|
||||
global: () => ({ body: { overflow: 'hidden' } }),
|
||||
});
|
||||
|
||||
export const googleFontUrl = (fontFamily, weights = [300, 400, 700]) => {
|
||||
const urlWeights = weights.join(',');
|
||||
const fontName = fontFamily.split(/, /)[0].trim().replace(/'|"/g, '');
|
||||
const urlFont = fontName.split(/ /).join('+');
|
||||
const urlBase = `https://fonts.googleapis.com/css?family=${urlFont}:${urlWeights}&display=swap`;
|
||||
return urlBase;
|
||||
};
|
||||
|
||||
export { theme as defaultTheme } from '@chakra-ui/react';
|
||||
197
hyperglass/ui/util/theme.ts
Normal file
197
hyperglass/ui/util/theme.ts
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
import {
|
||||
hsla,
|
||||
saturate,
|
||||
desaturate,
|
||||
parseToHsla,
|
||||
transparentize,
|
||||
readableColorIsBlack,
|
||||
} from 'color2k';
|
||||
import { extendTheme } from '@chakra-ui/react';
|
||||
|
||||
import type { Theme as ChakraTheme } from '@chakra-ui/react';
|
||||
import type { IConfigTheme, Theme } from '~/types';
|
||||
|
||||
export function isLight(color: string) {
|
||||
return readableColorIsBlack(color);
|
||||
}
|
||||
|
||||
export function isDark(color: string) {
|
||||
return !readableColorIsBlack(color);
|
||||
}
|
||||
|
||||
function alphaColors(color: string) {
|
||||
return {
|
||||
50: transparentize(color, Number((1 - 0.04).toFixed(2))),
|
||||
100: transparentize(color, Number((1 - 0.08).toFixed(2))),
|
||||
200: transparentize(color, Number((1 - 0.12).toFixed(2))),
|
||||
300: transparentize(color, Number((1 - 0.16).toFixed(2))),
|
||||
400: transparentize(color, Number((1 - 0.24).toFixed(2))),
|
||||
500: transparentize(color, Number((1 - 0.38).toFixed(2))),
|
||||
600: transparentize(color, Number((1 - 0.48).toFixed(2))),
|
||||
700: transparentize(color, Number((1 - 0.6).toFixed(2))),
|
||||
800: transparentize(color, Number((1 - 0.8).toFixed(2))),
|
||||
900: transparentize(color, Number((1 - 0.92).toFixed(2))),
|
||||
};
|
||||
}
|
||||
|
||||
function generateColors(colorInput: string) {
|
||||
const colorMap = Object();
|
||||
|
||||
const lightnessMap = [0.95, 0.85, 0.75, 0.65, 0.55, 0.45, 0.35, 0.25, 0.15, 0.05];
|
||||
const saturationMap = [0.32, 0.16, 0.08, 0.04, 0, 0, 0.04, 0.08, 0.16, 0.32];
|
||||
|
||||
const colorHsla = parseToHsla(colorInput);
|
||||
const lightnessGoal = colorHsla[2];
|
||||
|
||||
const closestLightness = lightnessMap.reduce((prev, curr) =>
|
||||
Math.abs(curr - lightnessGoal) < Math.abs(prev - lightnessGoal) ? curr : prev,
|
||||
);
|
||||
|
||||
const baseColorIndex = lightnessMap.findIndex(l => l === closestLightness);
|
||||
|
||||
const colors = lightnessMap
|
||||
.map(l => {
|
||||
const [h, s, _, a] = colorHsla;
|
||||
return hsla(h, s, l, a);
|
||||
})
|
||||
.map((color, i) => {
|
||||
const saturationDelta = saturationMap[i] - saturationMap[baseColorIndex];
|
||||
return saturationDelta >= 0
|
||||
? saturate(color, saturationDelta)
|
||||
: desaturate(color, saturationDelta * -1);
|
||||
});
|
||||
|
||||
const getColorNumber = (index: number) => (index === 0 ? 50 : index * 100);
|
||||
|
||||
colors.map((color, i) => {
|
||||
const colorIndex = getColorNumber(i);
|
||||
if (colorIndex === 500) {
|
||||
colorMap[500] = colorInput;
|
||||
} else {
|
||||
colorMap[colorIndex] = color;
|
||||
}
|
||||
});
|
||||
return colorMap;
|
||||
}
|
||||
|
||||
const defaultBodyFonts = [
|
||||
'-apple-system',
|
||||
'BlinkMacSystemFont',
|
||||
'"Segoe UI"',
|
||||
'Helvetica',
|
||||
'Arial',
|
||||
'sans-serif',
|
||||
'"Apple Color Emoji"',
|
||||
'"Segoe UI Emoji"',
|
||||
'"Segoe UI Symbol"',
|
||||
];
|
||||
|
||||
const defaultMonoFonts = [
|
||||
'SFMono-Regular',
|
||||
'Melno',
|
||||
'Monaco',
|
||||
'Consolas',
|
||||
'"Liberation Mono"',
|
||||
'"Courier New"',
|
||||
'monospace',
|
||||
];
|
||||
|
||||
function generatePalette(palette: IConfigTheme['colors']): Theme.Colors {
|
||||
const generatedPalette = Object();
|
||||
|
||||
for (const color of Object.keys(palette)) {
|
||||
if (!['black', 'white'].includes(color)) {
|
||||
generatedPalette[color] = generateColors(palette[color]);
|
||||
} else {
|
||||
generatedPalette[color] = palette[color];
|
||||
generatedPalette[`${color}Alpha`] = alphaColors(palette[color]);
|
||||
}
|
||||
}
|
||||
|
||||
generatedPalette.blackSolid = {
|
||||
50: '#444444',
|
||||
100: '#3c3c3c',
|
||||
200: '#353535',
|
||||
300: '#2d2d2d',
|
||||
400: '#262626',
|
||||
500: '#1e1e1e',
|
||||
600: '#171717',
|
||||
700: '#0f0f0f',
|
||||
800: '#080808',
|
||||
900: '#000000',
|
||||
};
|
||||
generatedPalette.whiteSolid = {
|
||||
50: '#ffffff',
|
||||
100: '#f7f7f7',
|
||||
200: '#f0f0f0',
|
||||
300: '#e8e8e8',
|
||||
400: '#e1e1e1',
|
||||
500: '#d9d9d9',
|
||||
600: '#d2d2d2',
|
||||
700: '#cacaca',
|
||||
800: '#c3c3c3',
|
||||
900: '#bbbbbb',
|
||||
};
|
||||
return generatedPalette;
|
||||
}
|
||||
|
||||
function formatFont(font: string): string {
|
||||
const fontList = font.split(' ');
|
||||
const fontFmt = fontList.length >= 2 ? `'${fontList.join(' ')}'` : fontList.join(' ');
|
||||
return fontFmt;
|
||||
}
|
||||
|
||||
function importFonts(userFonts: Theme.Fonts): [ChakraTheme['fonts'], Theme.FontWeights] {
|
||||
const [body, mono] = [defaultBodyFonts, defaultMonoFonts];
|
||||
const { body: userBody, mono: userMono, ...fontWeights } = userFonts;
|
||||
const bodyFmt = formatFont(userBody);
|
||||
const monoFmt = formatFont(userMono);
|
||||
if (userFonts.body && !body.includes(bodyFmt)) {
|
||||
body.unshift(bodyFmt);
|
||||
}
|
||||
if (userFonts.mono && !mono.includes(monoFmt)) {
|
||||
mono.unshift(monoFmt);
|
||||
}
|
||||
return [
|
||||
{
|
||||
body: body.join(', '),
|
||||
heading: body.join(', '),
|
||||
mono: mono.join(', '),
|
||||
},
|
||||
fontWeights,
|
||||
];
|
||||
}
|
||||
|
||||
function importColors(userColors: IConfigTheme['colors']): Theme.Colors {
|
||||
const generatedColors = generatePalette(userColors);
|
||||
|
||||
return {
|
||||
...generatedColors,
|
||||
transparent: 'transparent',
|
||||
current: 'currentColor',
|
||||
};
|
||||
}
|
||||
|
||||
export function makeTheme(userTheme: IConfigTheme): Theme.Full {
|
||||
const [fonts, fontWeights] = importFonts(userTheme.fonts);
|
||||
|
||||
const defaultTheme = extendTheme({
|
||||
colors: importColors(userTheme.colors),
|
||||
fonts,
|
||||
fontWeights,
|
||||
styles: {
|
||||
global: () => ({ html: { scrollBehavior: 'smooth' }, body: { overflow: 'hidden' } }),
|
||||
},
|
||||
});
|
||||
|
||||
return defaultTheme;
|
||||
}
|
||||
|
||||
export function googleFontUrl(fontFamily: string, weights: number[] = [300, 400, 700]): string {
|
||||
const urlWeights = weights.join(',');
|
||||
const fontName = fontFamily.split(/, /)[0].trim().replace(/'|"/g, '');
|
||||
const urlFont = fontName.split(/ /).join('+');
|
||||
return `https://fonts.googleapis.com/css?family=${urlFont}:${urlWeights}&display=swap`;
|
||||
}
|
||||
|
||||
export { theme as defaultTheme } from '@chakra-ui/react';
|
||||
52
hyperglass/ui/yarn.lock
vendored
52
hyperglass/ui/yarn.lock
vendored
|
|
@ -2046,13 +2046,6 @@ chownr@^1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
||||
|
||||
chroma-js@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.1.0.tgz#c0be48a21fe797ef8965608c1c4f911ef2da49d5"
|
||||
integrity sha512-uiRdh4ZZy+UTPSrAdp8hqEdVb1EllLtTHOt5TMaOjJUvi+O54/83Fc5K2ld1P+TJX+dw5B+8/sCgzI6eaur/lg==
|
||||
dependencies:
|
||||
cross-env "^6.0.3"
|
||||
|
||||
chrome-trace-event@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
|
||||
|
|
@ -2150,6 +2143,11 @@ color-string@^1.5.4:
|
|||
color-name "^1.0.0"
|
||||
simple-swizzle "^0.2.2"
|
||||
|
||||
color2k@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/color2k/-/color2k-1.1.1.tgz#f9703fab6693e2a407962211f1ab7e8e0602d5d7"
|
||||
integrity sha512-pkIVqioT1tEJOwfN5O/ZNLMG55H1GhA5WlvasHR2Zj07pIDgA5JDxkqqLIz2PfZOJC8IvuJbdp1YIRbeo+MlMQ==
|
||||
|
||||
color@^3.1.2:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e"
|
||||
|
|
@ -2335,13 +2333,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
|
|||
safe-buffer "^5.0.1"
|
||||
sha.js "^2.4.8"
|
||||
|
||||
cross-env@^6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-6.0.3.tgz#4256b71e49b3a40637a0ce70768a6ef5c72ae941"
|
||||
integrity sha512-+KqxF6LCvfhWvADcDPqo64yVIB31gv/jQulX2NGzKS/g3GEVz6/pt4wjHFtFWsHMddebWD/sDthJemzM4MaAag==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.0"
|
||||
|
||||
cross-fetch@3.0.6:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.6.tgz#3a4040bc8941e653e0e9cf17f29ebcd177d3365c"
|
||||
|
|
@ -2360,15 +2351,6 @@ cross-spawn@^6.0.5:
|
|||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
cross-spawn@^7.0.0:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
|
||||
dependencies:
|
||||
path-key "^3.1.0"
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
crypto-browserify@3.12.0, crypto-browserify@^3.11.0:
|
||||
version "3.12.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
|
||||
|
|
@ -5088,11 +5070,6 @@ path-key@^2.0.1:
|
|||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
|
||||
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
|
||||
|
||||
path-key@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||
|
||||
path-parse@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
||||
|
|
@ -6054,23 +6031,11 @@ shebang-command@^1.2.0:
|
|||
dependencies:
|
||||
shebang-regex "^1.0.0"
|
||||
|
||||
shebang-command@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
|
||||
integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
|
||||
dependencies:
|
||||
shebang-regex "^3.0.0"
|
||||
|
||||
shebang-regex@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
|
||||
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
|
||||
|
||||
shebang-regex@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||
|
||||
shell-quote@1.7.2:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2"
|
||||
|
|
@ -7103,13 +7068,6 @@ which@^1.2.9:
|
|||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
which@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
|
||||
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
|
||||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
wide-align@^1.1.0:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue