refactor: move component into a single package (#898)

This commit is contained in:
Himself65
2023-02-08 22:19:11 -06:00
committed by GitHub
parent 0984c37cad
commit cc605251a8
145 changed files with 9609 additions and 450 deletions

View File

@@ -0,0 +1,145 @@
import type { CSSProperties } from 'react';
export const displayFlex = (
justifyContent: CSSProperties['justifyContent'] = 'unset',
alignItems: CSSProperties['alignItems'] = 'unset',
alignContent: CSSProperties['alignContent'] = 'unset'
): {
display: CSSProperties['display'];
justifyContent: CSSProperties['justifyContent'];
alignItems: CSSProperties['alignItems'];
alignContent: CSSProperties['alignContent'];
} => {
return {
display: 'flex',
justifyContent,
alignItems,
alignContent,
};
};
export const displayInlineFlex = (
justifyContent: CSSProperties['justifyContent'] = 'unset',
alignItems: CSSProperties['alignContent'] = 'unset',
alignContent: CSSProperties['alignContent'] = 'unset'
): {
display: CSSProperties['display'];
justifyContent: CSSProperties['justifyContent'];
alignItems: CSSProperties['alignContent'];
alignContent: CSSProperties['alignContent'];
} => {
return {
display: 'inline-flex',
justifyContent,
alignItems,
alignContent,
};
};
export const absoluteCenter = ({
horizontal = false,
vertical = false,
position: { left, right, top, bottom } = {},
}: {
horizontal?: boolean;
vertical?: boolean;
position?: {
left?: CSSProperties['left'];
right?: CSSProperties['right'];
top?: CSSProperties['top'];
bottom?: CSSProperties['bottom'];
};
}): {
position: CSSProperties['position'];
left: CSSProperties['left'];
top: CSSProperties['top'];
right: CSSProperties['right'];
bottom: CSSProperties['bottom'];
transform: CSSProperties['transform'];
} => {
return {
position: 'absolute',
left: left ? left : horizontal ? '50%' : 'auto',
top: top ? top : vertical ? '50%' : 'auto',
right: right ? right : horizontal ? 'auto' : 'auto',
bottom: bottom ? bottom : vertical ? 'auto' : 'auto',
transform: `translate(${horizontal ? '-50%' : '0'}, ${
vertical ? '-50%' : '0'
})`,
};
};
export const fixedCenter = ({
horizontal = false,
vertical = false,
position: { left, right, top, bottom } = {},
}: {
horizontal?: boolean;
vertical?: boolean;
position?: {
left?: CSSProperties['left'];
right?: CSSProperties['right'];
top?: CSSProperties['top'];
bottom?: CSSProperties['bottom'];
};
}): {
position: CSSProperties['position'];
left: CSSProperties['left'];
top: CSSProperties['top'];
right: CSSProperties['right'];
bottom: CSSProperties['bottom'];
transform: CSSProperties['transform'];
} => {
return {
position: 'fixed',
left: left ? left : horizontal ? '50%' : 'auto',
top: top ? top : vertical ? '50%' : 'auto',
right: right ? right : horizontal ? 'auto' : 'auto',
bottom: bottom ? bottom : vertical ? 'auto' : 'auto',
transform: `translate(${horizontal ? '-50%' : '0'}, ${
vertical ? '-50%' : '0'
})`,
};
};
export const textEllipsis = (lineNum = 1): CSSProperties => {
if (lineNum > 1) {
return {
display: '-webkit-box',
wordBreak: 'break-all',
WebkitBoxOrient: 'vertical',
WebkitLineClamp: `${lineNum}`, //the number of rows to display
overflow: 'hidden',
textOverflow: 'ellipsis',
};
}
return {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
};
};
export const positionAbsolute = ({
left,
top,
right,
bottom,
}: {
left?: CSSProperties['left'];
top?: CSSProperties['top'];
right?: CSSProperties['right'];
bottom?: CSSProperties['bottom'];
}): {
position: CSSProperties['position'];
left: CSSProperties['left'];
top: CSSProperties['top'];
right: CSSProperties['right'];
bottom: CSSProperties['bottom'];
} => {
return {
position: 'absolute',
left,
top,
right,
bottom,
};
};

View File

@@ -0,0 +1,5 @@
export * from './styled';
export * from './theme';
export * from './helper';
export * from './types';
export * from './utils';

View File

@@ -0,0 +1,15 @@
import { ThemeProvider as EmotionThemeProvider } from '@emotion/react';
import emotionStyled from '@emotion/styled';
import type { PropsWithChildren } from 'react';
import { AffineTheme } from './types';
export { css, keyframes } from '@emotion/react';
export const styled = emotionStyled;
export const ThemeProvider = ({
theme,
children,
}: PropsWithChildren<{
theme: AffineTheme;
}>) => {
return <EmotionThemeProvider theme={theme}>{children}</EmotionThemeProvider>;
};

View File

@@ -0,0 +1,208 @@
import '@emotion/react';
import { AffineTheme, AffineThemeCSSVariables, ThemeMode } from './types';
import type { EditorContainer } from '@blocksuite/editor';
const basicFontFamily =
'apple-system, BlinkMacSystemFont,Helvetica Neue, Tahoma, PingFang SC, Microsoft Yahei, Arial,Hiragino Sans GB, sans-serif, Apple Color Emoji, Segoe UI Emoji,Segoe UI Symbol, Noto Color Emoji';
export const getLightTheme = (
editorMode: EditorContainer['mode']
): AffineTheme => {
return {
mode: 'light',
editorMode,
colors: {
primaryColor: '#6880FF',
pageBackground: '#fff',
hoverBackground: '#F1F3FF',
innerHoverBackground: '#E9E9EC',
popoverBackground: '#fff',
tooltipBackground: '#6880FF',
codeBackground: '#f2f5f9',
codeBlockBackground: '#F9F9FB',
blockHubBackground: '#fbfbfc',
blockHubHoverBackground: '#f8f9ff',
warningBackground: '#FFF9C7',
errorBackground: '#FFDED8',
textColor: '#28293D',
edgelessTextColor: '#3A4C5C',
iconColor: '#555770',
handleColor: '#c7c3d9',
linkColor: '#6880FF',
linkColor2: '#6880FF',
linkVisitedColor: '#ABB8FE',
popoverColor: '#4C6275',
inputColor: '#4C6275',
tooltipColor: '#fff',
codeColor: '#517ea6',
quoteColor: '#4C6275',
placeHolderColor: '#888A9E',
selectedColor: 'rgba(104, 128, 255, 0.1)',
borderColor: '#E3E2E4',
disableColor: '#555770',
warningColor: '#906616',
errorColor: '#EB4335',
lineNumberColor: '#555770',
},
font: {
title: '36px',
h1: '28px',
h2: '26px',
h3: '24px',
h4: '22px',
h5: '20px',
h6: '18px',
base: '16px',
xs: '14px',
sm: '12px',
family: `Avenir Next, Poppins, ${basicFontFamily}`,
numberFamily: `Roboto Mono, ${basicFontFamily}`,
codeFamily: `Space Mono, Consolas, Menlo, Monaco, Courier, monospace, ${basicFontFamily}`,
lineHeight: 'calc(1em + 8px)',
},
zIndex: {
modal: 1000,
popover: 100,
},
shadow: {
popover:
'4px 4px 7px rgba(58, 76, 92, 0.04), -4px -4px 13px rgba(58, 76, 92, 0.02), 6px 6px 36px rgba(58, 76, 92, 0.06);',
modal:
'4px 4px 7px rgba(58, 76, 92, 0.04), -4px -4px 13px rgba(58, 76, 92, 0.02), 6px 6px 36px rgba(58, 76, 92, 0.06);',
tooltip: '1px 1px 4px rgba(0, 0, 0, 0.14)',
},
space: {
paragraph: '8px',
},
radius: {
popover: '10px',
},
};
};
export const getDarkTheme = (
editorMode: EditorContainer['mode']
): AffineTheme => {
const lightTheme = getLightTheme(editorMode);
return {
...lightTheme,
mode: 'dark',
colors: {
primaryColor: '#6880FF',
pageBackground: '#2c2c2c',
hoverBackground: '#3C3C42',
innerHoverBackground: '#E0E6FF',
popoverBackground: '#1F2021',
tooltipBackground: '#1F2021',
codeBackground:
editorMode === 'edgeless'
? lightTheme.colors.codeBackground
: '#505662',
codeBlockBackground: '#36383D',
blockHubBackground: '#272727',
blockHubHoverBackground: '#363636',
warningBackground: '#FFF9C7',
errorBackground: '#FFDED8',
textColor: '#fff',
edgelessTextColor: '#3A4C5C',
iconColor: '#888a9e',
handleColor: '#c7c3d9',
linkColor: '#7D91FF',
linkColor2: '#6880FF',
linkVisitedColor: '#505FAB',
popoverColor: '#C6CBD9',
inputColor: '#C6CBD9',
tooltipColor: '#fff',
codeColor:
editorMode === 'edgeless' ? lightTheme.colors.codeColor : '#BDDBFD',
quoteColor: '#C6CBD9',
placeHolderColor: '#C7C7C7',
selectedColor: 'rgba(104, 128, 255, 0.1)',
borderColor: '#4D4C53',
disableColor: '#4b4b4b',
warningColor: '#906616',
errorColor: '#EB4335',
lineNumberColor: '#888A9E',
},
shadow: {
popover:
'0px 1px 10px -6px rgba(24, 39, 75, 0.08), 0px 3px 16px -6px rgba(24, 39, 75, 0.04)',
modal:
'0px 1px 10px -6px rgba(24, 39, 75, 0.08), 0px 3px 16px -6px rgba(24, 39, 75, 0.04)',
tooltip: '1px 1px 4px rgba(0, 0, 0, 0.14)',
},
};
};
export const globalThemeVariables: (
mode: ThemeMode,
theme: AffineTheme
) => AffineThemeCSSVariables = (mode, theme) => {
return {
'--affine-theme-mode': theme.mode,
'--affine-editor-mode': theme.editorMode,
'--affine-primary-color': theme.colors.primaryColor,
'--affine-page-background': theme.colors.pageBackground,
'--affine-popover-background': theme.colors.popoverBackground,
'--affine-hover-background': theme.colors.hoverBackground,
'--affine-code-background': theme.colors.codeBackground,
'--affine-tooltip-background': theme.colors.tooltipBackground,
'--affine-block-hub-background': theme.colors.blockHubBackground,
'--affine-block-hub-hover-background': theme.colors.blockHubHoverBackground,
'--affine-text-color': theme.colors.textColor,
'--affine-edgeless-text-color': theme.colors.edgelessTextColor,
'--affine-link-color': theme.colors.linkColor,
// In dark mode, normal text`s (not bold) color
'--affine-link-color2': theme.colors.linkColor2,
'--affine-link-visited-color': theme.colors.linkVisitedColor,
'--affine-icon-color': theme.colors.iconColor,
'--affine-block-handle-color': theme.colors.handleColor,
'--affine-popover-color': theme.colors.popoverColor,
'--affine-input-color': theme.colors.inputColor,
'--affine-code-color': theme.colors.codeColor,
'--affine-code-block-background': theme.colors.codeBlockBackground,
'--affine-quote-color': theme.colors.quoteColor,
'--affine-selected-color': theme.colors.selectedColor,
'--affine-placeholder-color': theme.colors.placeHolderColor,
'--affine-border-color': theme.colors.borderColor,
'--affine-disable-color': theme.colors.disableColor,
'--affine-tooltip-color': theme.colors.tooltipColor,
'--affine-line-number-color': theme.colors.lineNumberColor,
'--affine-modal-shadow': theme.shadow.modal,
'--affine-popover-shadow': theme.shadow.popover,
'--affine-tooltip-shadow': theme.shadow.tooltip,
'--affine-font-h1': theme.font.h1,
'--affine-font-h2': theme.font.h2,
'--affine-font-h3': theme.font.h3,
'--affine-font-h4': theme.font.h4,
'--affine-font-h5': theme.font.h5,
'--affine-font-h6': theme.font.h6,
'--affine-font-base': theme.font.base,
'--affine-font-sm': theme.font.sm, // small
'--affine-font-xs': theme.font.xs, // tiny
'--affine-line-height': theme.font.lineHeight,
'--affine-z-index-modal': theme.zIndex.modal,
'--affine-z-index-popover': theme.zIndex.popover,
'--affine-font-family': theme.font.family,
'--affine-font-number-family': theme.font.numberFamily,
'--affine-font-code-family': theme.font.codeFamily,
'--affine-paragraph-space': theme.space.paragraph,
'--affine-popover-radius': theme.radius.popover,
};
};

View File

@@ -0,0 +1,150 @@
import { EditorContainer } from '@blocksuite/editor';
export type Theme = 'light' | 'dark';
export type ThemeMode = Theme | 'auto';
export type ThemeProviderProps = {
defaultTheme?: Theme;
};
export type ThemeProviderValue = {
theme: AffineTheme;
mode: ThemeMode;
changeMode: (newMode: ThemeMode) => void;
};
export interface AffineTheme {
mode: Theme;
editorMode: EditorContainer['mode'];
colors: {
primaryColor: string;
pageBackground: string;
popoverBackground: string;
tooltipBackground: string;
hoverBackground: string;
innerHoverBackground: string;
codeBackground: string;
codeBlockBackground: string;
blockHubBackground: string;
blockHubHoverBackground: string;
warningBackground: string;
errorBackground: string;
// Use for the page`s text
textColor: string;
// Use for the editor`s text, because in edgeless mode text is different form other
edgelessTextColor: string;
linkColor: string;
// In dark mode, normal text`s (not bold) color
linkColor2: string;
linkVisitedColor: string;
iconColor: string;
handleColor: string;
popoverColor: string;
inputColor: string;
tooltipColor: string;
codeColor: string;
quoteColor: string;
placeHolderColor: string;
selectedColor: string;
borderColor: string;
disableColor: string;
warningColor: string;
errorColor: string;
lineNumberColor: string;
};
font: {
title: string;
h1: string;
h2: string;
h3: string;
h4: string;
h5: string;
h6: string;
base: string;
sm: string; // small
xs: string; // tiny
family: string;
numberFamily: string;
codeFamily: string;
lineHeight: string | number;
};
zIndex: {
modal: number;
popover: number;
};
shadow: {
modal: string;
popover: string;
tooltip: string;
};
space: {
paragraph: string;
};
radius: {
popover: string;
};
}
export interface AffineThemeCSSVariables {
'--affine-theme-mode': Theme;
'--affine-editor-mode': EditorContainer['mode'];
'--affine-primary-color': AffineTheme['colors']['primaryColor'];
'--affine-page-background': AffineTheme['colors']['pageBackground'];
'--affine-popover-background': AffineTheme['colors']['popoverBackground'];
'--affine-hover-background': AffineTheme['colors']['hoverBackground'];
'--affine-code-background': AffineTheme['colors']['codeBackground'];
'--affine-code-block-background': AffineTheme['colors']['codeBlockBackground'];
'--affine-tooltip-background': AffineTheme['colors']['tooltipBackground'];
'--affine-text-color': AffineTheme['colors']['textColor'];
'--affine-edgeless-text-color': AffineTheme['colors']['edgelessTextColor'];
'--affine-link-color': AffineTheme['colors']['linkColor'];
// In dark mode, normal text`s (not bold) color
'--affine-link-color2': AffineTheme['colors']['linkColor2'];
'--affine-link-visited-color': AffineTheme['colors']['linkVisitedColor'];
'--affine-icon-color': AffineTheme['colors']['iconColor'];
'--affine-popover-color': AffineTheme['colors']['popoverColor'];
'--affine-code-color': AffineTheme['colors']['codeColor'];
'--affine-quote-color': AffineTheme['colors']['quoteColor'];
'--affine-placeholder-color': AffineTheme['colors']['placeHolderColor'];
'--affine-selected-color': AffineTheme['colors']['selectedColor'];
'--affine-border-color': AffineTheme['colors']['borderColor'];
'--affine-disable-color': AffineTheme['colors']['disableColor'];
'--affine-tooltip-color': AffineTheme['colors']['tooltipColor'];
'--affine-line-number-color': AffineTheme['colors']['lineNumberColor'];
'--affine-modal-shadow': AffineTheme['shadow']['modal'];
'--affine-popover-shadow': AffineTheme['shadow']['popover'];
'--affine-tooltip-shadow': AffineTheme['shadow']['tooltip'];
'--affine-font-h1': AffineTheme['font']['h1'];
'--affine-font-h2': AffineTheme['font']['h2'];
'--affine-font-h3': AffineTheme['font']['h3'];
'--affine-font-h4': AffineTheme['font']['h4'];
'--affine-font-h5': AffineTheme['font']['h5'];
'--affine-font-h6': AffineTheme['font']['h6'];
'--affine-font-base': AffineTheme['font']['base'];
'--affine-font-sm': AffineTheme['font']['sm']; // small
'--affine-font-xs': AffineTheme['font']['xs']; // tiny
'--affine-line-height': AffineTheme['font']['lineHeight'];
'--affine-z-index-modal': AffineTheme['zIndex']['modal'];
'--affine-z-index-popover': AffineTheme['zIndex']['popover'];
'--affine-font-family': AffineTheme['font']['family'];
'--affine-font-number-family': AffineTheme['font']['numberFamily'];
'--affine-font-code-family': AffineTheme['font']['codeFamily'];
'--affine-paragraph-space': AffineTheme['space']['paragraph'];
'--affine-popover-radius': AffineTheme['radius']['popover'];
}
declare module '@emotion/react' {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface Theme extends AffineTheme {}
}

View File

@@ -0,0 +1,2 @@
export * from './systemThemeHelper';
export * from './localStorageThemeHelper';

View File

@@ -0,0 +1,13 @@
import { ThemeMode } from '../types';
export class LocalStorageThemeHelper {
name = 'Affine-theme-mode';
get = (): ThemeMode | null => {
return localStorage.getItem(this.name) as ThemeMode | null;
};
set = (mode: ThemeMode) => {
localStorage.setItem(this.name, mode);
};
}
export const localStorageThemeHelper = new LocalStorageThemeHelper();

View File

@@ -0,0 +1,29 @@
import { Theme } from '../types';
export class SystemThemeHelper {
media: MediaQueryList = window.matchMedia('(prefers-color-scheme: light)');
eventList: Array<(e: Event) => void> = [];
eventHandler = (e: Event) => {
this.eventList.forEach(fn => fn(e));
};
constructor() {
this.media.addEventListener('change', this.eventHandler);
}
get = (): Theme => {
if (typeof window === 'undefined') {
return 'light';
}
return this.media.matches ? 'light' : 'dark';
};
onChange = (callback: () => void) => {
this.eventList.push(callback);
};
dispose = () => {
this.eventList = [];
this.media.removeEventListener('change', this.eventHandler);
};
}