Merge branch 'develop' into feature/fix-backspace

This commit is contained in:
Qi
2022-08-11 21:49:45 +08:00
committed by GitHub
68 changed files with 1252 additions and 519 deletions

View File

@@ -0,0 +1,107 @@
/* eslint-disable filename-rules/match */
import { useEffect, useState } from 'react';
import { LogoImg } from '@toeverything/components/common';
import {
MuiButton,
MuiBox,
MuiGrid,
MuiSnackbar,
} from '@toeverything/components/ui';
import { services } from '@toeverything/datasource/db-service';
import { useLocalTrigger } from '@toeverything/datasource/state';
import { Error } from './../error';
const requestPermission = async (workspace: string) => {
indexedDB.deleteDatabase(workspace);
const dirHandler = await window.showDirectoryPicker({
id: 'AFFiNE_' + workspace,
mode: 'readwrite',
startIn: 'documents',
});
const fileHandle = await dirHandler.getFileHandle('affine.db', {
create: true,
});
const file = await fileHandle.getFile();
const initialData = new Uint8Array(await file.arrayBuffer());
const exporter = async (contents: Uint8Array) => {
try {
const writable = await fileHandle.createWritable();
await writable.write(contents);
await writable.close();
} catch (e) {
console.log(e);
}
};
await services.api.editorBlock.setupDataExporter(
workspace,
new Uint8Array(initialData),
exporter
);
};
export const FileSystem = () => {
const onSelected = useLocalTrigger();
const [error, setError] = useState(false);
useEffect(() => {
if (process.env['NX_E2E']) {
onSelected();
}
}, []);
return (
<MuiGrid container>
<MuiSnackbar
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
open={error}
message="Login failed, please check if you have permission"
/>
<MuiGrid item xs={8}>
<Error
title="Welcome to AFFiNE"
subTitle="blocks of knowledge to power your team"
action1Text="Login &nbsp; or &nbsp; Register"
/>
</MuiGrid>
<MuiGrid item xs={4}>
<MuiBox
onClick={async () => {
try {
await requestPermission('AFFiNE');
onSelected();
} catch (e) {
setError(true);
onSelected();
setTimeout(() => setError(false), 3000);
}
}}
style={{
textAlign: 'center',
width: '300px',
margin: '300px auto 20px auto',
}}
sx={{ mt: 1 }}
>
<LogoImg
style={{
width: '100px',
}}
/>
<MuiButton
variant="outlined"
fullWidth
style={{ textTransform: 'none' }}
>
Sync to Disk
</MuiButton>
</MuiBox>
</MuiGrid>
</MuiGrid>
);
};

View File

@@ -1,11 +1,13 @@
/* eslint-disable filename-rules/match */
// import { Authing } from './authing';
import { Firebase } from './firebase';
import { FileSystem } from './fs';
export function Login() {
return (
<>
{/* <Authing /> */}
<Firebase />
{process.env['NX_LOCAL'] ? <FileSystem /> : <Firebase />}
</>
);
}

View File

@@ -1,5 +1,13 @@
/* eslint-disable max-lines */
import * as React from 'react';
import {
memo,
useEffect,
useLayoutEffect,
useRef,
useMemo,
useState,
type RefObject,
} from 'react';
import { Renderer } from '@tldraw/core';
import { styled } from '@toeverything/components/ui';
import {
@@ -132,13 +140,13 @@ export function Tldraw({
getSession,
tools,
}: TldrawProps) {
const [sId, set_sid] = React.useState(id);
const [sId, setSid] = useState(id);
const { pageClientWidth } = usePageClientWidth();
// page padding left and right total 300px
const editorShapeInitSize = pageClientWidth - 300;
// Create a new app when the component mounts.
const [app, setApp] = React.useState(() => {
const [app, setApp] = useState(() => {
const app = new TldrawApp({
id,
callbacks,
@@ -151,7 +159,7 @@ export function Tldraw({
});
// Create a new app if the `id` prop changes.
React.useLayoutEffect(() => {
useLayoutEffect(() => {
if (id === sId) return;
const newApp = new TldrawApp({
id,
@@ -161,14 +169,14 @@ export function Tldraw({
tools,
});
set_sid(id);
setSid(id);
setApp(newApp);
}, [sId, id]);
// Update the document if the `document` prop changes but the ids,
// are the same, or else load a new document if the ids are different.
React.useEffect(() => {
useEffect(() => {
if (!document) return;
if (document.id === app.document.id) {
@@ -179,34 +187,34 @@ export function Tldraw({
}, [document, app]);
// Disable assets when the `disableAssets` prop changes.
React.useEffect(() => {
useEffect(() => {
app.setDisableAssets(disableAssets);
}, [app, disableAssets]);
// Change the page when the `currentPageId` prop changes.
React.useEffect(() => {
useEffect(() => {
if (!currentPageId) return;
app.changePage(currentPageId);
}, [currentPageId, app]);
// Toggle the app's readOnly mode when the `readOnly` prop changes.
React.useEffect(() => {
useEffect(() => {
app.readOnly = readOnly;
}, [app, readOnly]);
// Toggle the app's darkMode when the `darkMode` prop changes.
React.useEffect(() => {
useEffect(() => {
if (darkMode !== app.settings.isDarkMode) {
app.toggleDarkMode();
}
}, [app, darkMode]);
// Update the app's callbacks when any callback changes.
React.useEffect(() => {
useEffect(() => {
app.callbacks = callbacks || {};
}, [app, callbacks]);
React.useLayoutEffect(() => {
useLayoutEffect(() => {
if (typeof window === 'undefined') return;
if (!window.document?.fonts) return;
@@ -260,7 +268,7 @@ interface InnerTldrawProps {
showSponsorLink?: boolean;
}
const InnerTldraw = React.memo(function InnerTldraw({
const InnerTldraw = memo(function InnerTldraw({
id,
autofocus,
showPages,
@@ -276,7 +284,7 @@ const InnerTldraw = React.memo(function InnerTldraw({
}: InnerTldrawProps) {
const app = useTldrawApp();
const rWrapper = React.useRef<HTMLDivElement>(null);
const rWrapper = useRef<HTMLDivElement>(null);
const state = app.useStore();
@@ -299,7 +307,7 @@ const InnerTldraw = React.memo(function InnerTldraw({
TLDR.get_shape_util(page.shapes[selectedIds[0]].type).hideResizeHandles;
// Custom rendering meta, with dark mode for shapes
const meta: TDMeta = React.useMemo(() => {
const meta: TDMeta = useMemo(() => {
return { isDarkMode: settings.isDarkMode, app };
}, [settings.isDarkMode, app]);
@@ -308,7 +316,7 @@ const InnerTldraw = React.memo(function InnerTldraw({
: appState.selectByContain;
// Custom theme, based on darkmode
const theme = React.useMemo(() => {
const theme = useMemo(() => {
const { selectByContain } = appState;
const { isDarkMode, isCadSelectMode } = settings;
@@ -373,9 +381,11 @@ const InnerTldraw = React.memo(function InnerTldraw({
!isSelecting ||
!settings.showCloneHandles ||
pageState.camera.zoom < 0.2;
return (
<StyledLayout
ref={rWrapper}
panning={settings.forcePanning}
tabIndex={-0}
penColor={app?.appState?.currentStyle?.stroke}
>
@@ -477,17 +487,17 @@ const InnerTldraw = React.memo(function InnerTldraw({
);
});
const OneOff = React.memo(function OneOff({
const OneOff = memo(function OneOff({
focusableRef,
autofocus,
}: {
autofocus?: boolean;
focusableRef: React.RefObject<HTMLDivElement>;
focusableRef: RefObject<HTMLDivElement>;
}) {
useKeyboardShortcuts(focusableRef);
useStylesheet();
React.useEffect(() => {
useEffect(() => {
if (autofocus) {
focusableRef.current?.focus();
}
@@ -496,8 +506,8 @@ const OneOff = React.memo(function OneOff({
return null;
});
const StyledLayout = styled('div')<{ penColor: string }>(
({ theme, penColor }) => {
const StyledLayout = styled('div')<{ penColor: string; panning: boolean }>(
({ theme, panning, penColor }) => {
return {
position: 'relative',
height: '100%',
@@ -509,6 +519,7 @@ const StyledLayout = styled('div')<{ penColor: string }>(
overflow: 'hidden',
boxSizing: 'border-box',
outline: 'none',
cursor: panning ? 'grab' : 'unset',
'& .tl-container': {
position: 'absolute',

View File

@@ -6,6 +6,7 @@ import {
Tooltip,
PopoverContainer,
IconButton,
useTheme,
} from '@toeverything/components/ui';
import {
FrameIcon,
@@ -71,6 +72,7 @@ export const ToolsPanel: FC<{ app: TldrawApp }> = ({ app }) => {
const activeTool = app.useStore(activeToolSelector);
const isToolLocked = app.useStore(toolLockedSelector);
const theme = useTheme();
return (
<PopoverContainer
@@ -105,7 +107,8 @@ export const ToolsPanel: FC<{ app: TldrawApp }> = ({ app }) => {
style={{
color:
activeTool === type
? 'blue'
? theme.affine.palette
.primary
: '',
}}
onClick={() => {

View File

@@ -219,8 +219,6 @@ export class TldrawApp extends StateManager<TDSnapshot> {
isPointing = false;
isForcePanning = false;
editingStartTime = -1;
fileSystemHandle: FileSystemHandle | null = null;
@@ -262,7 +260,7 @@ export class TldrawApp extends StateManager<TDSnapshot> {
constructor(props: TldrawAppCtorProps) {
super(
TldrawApp.default_state,
TldrawApp.defaultState,
props.id,
TldrawApp.version,
(prev, next, prevVersion) => {
@@ -326,9 +324,9 @@ export class TldrawApp extends StateManager<TDSnapshot> {
);
this.patchState({
...TldrawApp.default_state,
...TldrawApp.defaultState,
appState: {
...TldrawApp.default_state.appState,
...TldrawApp.defaultState.appState,
status: TDStatus.Idle,
},
});
@@ -1473,13 +1471,13 @@ export class TldrawApp extends StateManager<TDSnapshot> {
this.replace_state(
{
...TldrawApp.default_state,
...TldrawApp.defaultState,
settings: {
...this.state.settings,
},
document: migrate(document, TldrawApp.version),
appState: {
...TldrawApp.default_state.appState,
...TldrawApp.defaultState.appState,
...this.state.appState,
currentPageId: Object.keys(document.pages)[0],
disableAssets: this.disableAssets,
@@ -3913,7 +3911,11 @@ export class TldrawApp extends StateManager<TDSnapshot> {
break;
}
case ' ': {
this.isForcePanning = true;
this.patchState({
settings: {
forcePanning: true,
},
});
this.spaceKey = true;
break;
}
@@ -3976,7 +3978,12 @@ export class TldrawApp extends StateManager<TDSnapshot> {
break;
}
case ' ': {
this.isForcePanning = false;
this.patchState({
settings: {
forcePanning:
this.currentTool.type === TDShapeType.HandDraw,
},
});
this.spaceKey = false;
break;
}
@@ -4069,13 +4076,18 @@ export class TldrawApp extends StateManager<TDSnapshot> {
this.pan(delta);
// When panning, we also want to call onPointerMove, except when "force panning" via spacebar / middle wheel button (it's called elsewhere in that case)
if (!this.isForcePanning)
if (!this.useStore.getState().settings.forcePanning)
this.onPointerMove(info, e as unknown as React.PointerEvent);
};
onZoom: TLWheelEventHandler = (info, e) => {
if (this.state.appState.status !== TDStatus.Idle) return;
const delta = info.delta[2] / 50;
// Normalize zoom scroll
// Fix https://github.com/toeverything/AFFiNE/issues/135
const delta =
Math.abs(info.delta[2]) > 10
? 0.2 * Math.sign(info.delta[2])
: info.delta[2] / 50;
this.zoomBy(delta, info.point);
this.onPointerMove(info, e as unknown as React.PointerEvent);
};
@@ -4093,7 +4105,7 @@ export class TldrawApp extends StateManager<TDSnapshot> {
onPointerMove: TLPointerEventHandler = (info, e) => {
this.previousPoint = this.currentPoint;
this.updateInputs(info, e);
if (this.isForcePanning && this.isPointing) {
if (this.useStore.getState().settings.forcePanning && this.isPointing) {
this.onPan?.(
{ ...info, delta: Vec.neg(info.delta) },
e as unknown as WheelEvent
@@ -4117,20 +4129,23 @@ export class TldrawApp extends StateManager<TDSnapshot> {
onPointerDown: TLPointerEventHandler = (info, e) => {
if (e.buttons === 4) {
this.isForcePanning = true;
this.patchState({
settings: {
forcePanning: true,
},
});
} else if (this.isPointing) {
return;
}
this.isPointing = true;
this.originPoint = this.getPagePoint(info.point).concat(info.pressure);
this.updateInputs(info, e);
if (this.isForcePanning) return;
if (this.useStore.getState().settings.forcePanning) return;
this.currentTool.onPointerDown?.(info, e);
};
onPointerUp: TLPointerEventHandler = (info, e) => {
this.isPointing = false;
if (!this.shiftKey) this.isForcePanning = false;
this.updateInputs(info, e);
this.currentTool.onPointerUp?.(info, e);
};
@@ -4517,7 +4532,7 @@ export class TldrawApp extends StateManager<TDSnapshot> {
assets: {},
};
static default_state: TDSnapshot = {
static defaultState: TDSnapshot = {
settings: {
isCadSelectMode: false,
isPenMode: false,
@@ -4527,6 +4542,7 @@ export class TldrawApp extends StateManager<TDSnapshot> {
isSnapping: false,
isDebugMode: false,
isReadonlyMode: false,
forcePanning: false,
keepStyleMenuOpen: false,
nudgeDistanceLarge: 16,
nudgeDistanceSmall: 1,

View File

@@ -18,34 +18,19 @@ export class HandDrawTool extends BaseTool {
/* ----------------- Event Handlers ----------------- */
override onPointerDown: TLPointerEventHandler = () => {
if (this.app.readOnly) return;
if (this.status !== Status.Idle) return;
this.set_status(Status.Pointing);
override onEnter = () => {
this.app.patchState({
settings: {
forcePanning: true,
},
});
};
override onPointerMove: TLPointerEventHandler = (info, e) => {
if (this.app.readOnly) return;
const delta = Vec.div(info.delta, this.app.camera.zoom);
const prev = this.app.camera.point;
const next = Vec.sub(prev, delta);
if (Vec.isEqual(next, prev)) return;
switch (this.status) {
case Status.Pointing: {
this.app.pan(Vec.neg(delta));
break;
}
}
};
override onPointerUp: TLPointerEventHandler = () => {
this.set_status(Status.Idle);
};
override onCancel = () => {
this.set_status(Status.Idle);
override onExit = () => {
this.app.patchState({
settings: {
forcePanning: false,
},
});
};
}

View File

@@ -84,6 +84,7 @@ export interface TDSnapshot {
isPenMode: boolean;
isReadonlyMode: boolean;
isZoomSnap: boolean;
forcePanning: boolean;
keepStyleMenuOpen: boolean;
nudgeDistanceSmall: number;
nudgeDistanceLarge: number;

View File

@@ -13,6 +13,7 @@ const StyledContainer = styled('div')({
display: 'flex',
alignItems: 'center',
cursor: 'pointer',
paddingLeft: '12px',
'&:hover': {
background: '#f5f7f8',
borderRadius: '5px',
@@ -36,11 +37,6 @@ export function CollapsibleTitle(props: CollapsibleTitleProps) {
return (
<>
<StyledContainer onClick={() => setOpen(prev => !prev)}>
{open ? (
<ArrowDropDownIcon sx={{ color: '#566B7D' }} />
) : (
<ArrowRightIcon sx={{ color: '#566B7D' }} />
)}
<div
style={{
color: '#98ACBD',

View File

@@ -36,6 +36,9 @@ export class GridBlock extends BaseView {
}
return block.remove();
}
if (block.childrenIds.length === 0) {
return block.remove();
}
return true;
}
}

View File

@@ -1,6 +1,8 @@
import {
addNewGroup,
LINE_GAP,
RecastScene,
TAG_GAP,
useCurrentView,
useOnSelect,
} from '@toeverything/components/editor-core';
@@ -38,6 +40,7 @@ const GroupActionWrapper = styled('div')(({ theme }) => ({
visibility: 'hidden',
fontSize: theme.affine.typography.xs.fontSize,
color: theme.affine.palette.icons,
opacity: 0.6,
'.line': {
flex: 1,
height: '15px',
@@ -60,7 +63,7 @@ const GroupContainer = styled('div')<{ isSelect?: boolean }>(
({ isSelect, theme }) => ({
background: theme.affine.palette.white,
border: '2px solid rgba(236,241,251,.5)',
padding: `15px 16px 0 16px`,
padding: `15px 16px ${LINE_GAP - TAG_GAP * 2}px 16px`,
borderRadius: '10px',
...(isSelect
? {

View File

@@ -60,6 +60,9 @@ export const CardContext = (props: Props) => {
const StyledCardContainer = styled('div')`
cursor: pointer;
&:hover {
z-index: 1;
}
&:focus-within {
z-index: 1;
}

View File

@@ -109,12 +109,15 @@ export const PageView: FC<CreateView> = ({ block, editor }) => {
);
};
const PageTitleBlock = styled('div')({
'.title': {
fontSize: Theme.typography.page.fontSize,
lineHeight: Theme.typography.page.lineHeight,
},
'.content': {
outline: 'none',
},
const PageTitleBlock = styled('div')(({ theme }) => {
return {
'.title': {
fontSize: theme.affine.typography.page.fontSize,
lineHeight: theme.affine.typography.page.lineHeight,
fontWeight: theme.affine.typography.page.fontWeight,
},
'.content': {
outline: 'none',
},
};
});

View File

@@ -46,6 +46,7 @@ const TextBlock = styled(TextManage)<{ type: string }>(({ theme, type }) => {
return {
fontSize: textStyleMap.text.fontSize,
lineHeight: textStyleMap.text.lineHeight,
fontWeight: textStyleMap.text.fontWeight,
};
}
});

View File

@@ -150,6 +150,7 @@ const TodoBlock = styled('div')({
display: 'flex',
'.checkBoxContainer': {
marginRight: '4px',
padding: '0 4px',
height: '22px',
},
'.textContainer': {

View File

@@ -27,5 +27,6 @@ export const BlockContainer: FC<BlockContainerProps> = function ({
export const Container = styled('div')<{ selected: boolean }>(
({ selected, theme }) => ({
backgroundColor: selected ? theme.affine.palette.textSelected : '',
marginBottom: '2px',
})
);

View File

@@ -39,6 +39,9 @@ export type ExtendedTextUtils = SlateUtils & {
};
const TextBlockContainer = styled(Text)(({ theme }) => ({
lineHeight: theme.affine.typography.body1.lineHeight,
fontFamily: theme.affine.typography.body1.fontFamily,
color: theme.affine.typography.body1.color,
letterSpacing: '0.1px',
}));
const findSlice = (arr: string[], p: string, q: string) => {

View File

@@ -102,6 +102,12 @@ export const RenderRoot: FC<PropsWithChildren<RenderRootProps>> = ({
editor.getHooks().onRootNodeMouseLeave(event);
};
const onContextmenu = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>
) => {
selectionRef.current?.onContextmenu(event);
};
const onKeyDown: React.KeyboardEventHandler<HTMLDivElement> = event => {
// IMP move into keyboard managers?
editor.getHooks().onRootNodeKeyDown(event);
@@ -165,6 +171,7 @@ export const RenderRoot: FC<PropsWithChildren<RenderRootProps>> = ({
onMouseUp={onMouseUp}
onMouseLeave={onMouseLeave}
onMouseOut={onMouseOut}
onContextMenu={onContextmenu}
onKeyDown={onKeyDown}
onKeyDownCapture={onKeyDownCapture}
onKeyUp={onKeyUp}

View File

@@ -29,6 +29,9 @@ export type SelectionRef = {
onMouseDown: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
onMouseMove: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
onMouseUp: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
onContextmenu: (
event: React.MouseEvent<HTMLDivElement, MouseEvent>
) => void;
};
const getFixedPoint = (
@@ -207,10 +210,17 @@ export const SelectionRect = forwardRef<SelectionRef, SelectionProps>(
scrollManager.stopAutoScroll();
};
const onContextmenu = () => {
if (mouseType.current === 'down') {
onMouseUp();
}
};
useImperativeHandle(ref, () => ({
onMouseDown,
onMouseMove,
onMouseUp,
onContextmenu,
}));
useEffect(() => {

View File

@@ -3,6 +3,8 @@ import { styled } from '@toeverything/components/ui';
import type { AsyncBlock } from '../editor';
import { PendantPopover } from './pendant-popover';
import { PendantRender } from './pendant-render';
import { useRef } from 'react';
import { getRecastItemValue, useRecastBlockMeta } from '../recast-block';
/**
* @deprecated
*/
@@ -14,13 +16,27 @@ export const BlockPendantProvider: FC<PropsWithChildren<BlockTagProps>> = ({
block,
children,
}) => {
const triggerRef = useRef<HTMLDivElement>();
const { getProperties } = useRecastBlockMeta();
const properties = getProperties();
const { getValue } = getRecastItemValue(block);
const showTriggerLine =
properties.filter(property => getValue(property.id)).length === 0;
return (
<Container>
{children}
<PendantPopover block={block}>
<StyledTriggerLine />
</PendantPopover>
{showTriggerLine ? (
<StyledPendantContainer ref={triggerRef}>
<PendantPopover
block={block}
container={triggerRef.current}
>
<StyledTriggerLine />
</PendantPopover>
</StyledPendantContainer>
) : null}
<PendantRender block={block} />
</Container>
@@ -28,7 +44,7 @@ export const BlockPendantProvider: FC<PropsWithChildren<BlockTagProps>> = ({
};
export const LINE_GAP = 16;
const TAG_GAP = 4;
export const TAG_GAP = 4;
const StyledTriggerLine = styled('div')({
padding: `${TAG_GAP}px 0`,
@@ -43,10 +59,12 @@ const StyledTriggerLine = styled('div')({
width: '100%',
height: '2px',
background: '#dadada',
display: 'none',
display: 'flex',
position: 'absolute',
left: '0',
top: '4px',
transition: 'opacity .2s',
opacity: '0',
},
'::after': {
content: "''",
@@ -60,18 +78,24 @@ const StyledTriggerLine = styled('div')({
transition: 'width .3s',
},
});
const Container = styled('div')({
position: 'relative',
paddingBottom: `${LINE_GAP - TAG_GAP * 2}px`,
const StyledPendantContainer = styled('div')({
width: '100px',
'&:hover': {
[StyledTriggerLine.toString()]: {
'&::before': {
display: 'flex',
},
[`${StyledTriggerLine}`]: {
'&::after': {
width: '100%',
},
},
},
});
const Container = styled('div')({
position: 'relative',
padding: `${TAG_GAP * 2}px 0 ${LINE_GAP - TAG_GAP * 4}px 0`,
'&:hover': {
[`${StyledTriggerLine}`]: {
'&::before': {
opacity: '1',
},
},
},
});

View File

@@ -29,6 +29,7 @@ export const PendantHistoryPanel = ({
const [history, setHistory] = useState<RecastBlockValue[]>([]);
const popoverHandlerRef = useRef<{ [key: string]: PopperHandler }>({});
const historyPanelRef = useRef<HTMLDivElement>();
const { getValueHistory } = getRecastItemValue(block);
useEffect(() => {
@@ -84,7 +85,7 @@ export const PendantHistoryPanel = ({
}, [block, getProperties, groupBlock, recastBlock]);
return (
<StyledPendantHistoryPanel>
<StyledPendantHistoryPanel ref={historyPanelRef}>
{history.map(item => {
const property = getProperty(item.id);
return (
@@ -116,6 +117,7 @@ export const PendantHistoryPanel = ({
/>
}
trigger="click"
container={historyPanelRef.current}
>
<PendantTag
style={{

View File

@@ -1,5 +1,11 @@
import React, { useState, useEffect } from 'react';
import { Input, Option, Select, Tooltip } from '@toeverything/components/ui';
import {
Input,
message,
Option,
Select,
Tooltip,
} from '@toeverything/components/ui';
import { HelpCenterIcon } from '@toeverything/components/icons';
import { AsyncBlock } from '../../editor';
@@ -18,6 +24,7 @@ import {
generateRandomFieldName,
generateInitialOptions,
getPendantConfigByType,
checkPendantForm,
} from '../utils';
import { useOnCreateSure } from './hooks';
@@ -74,7 +81,7 @@ export const CreatePendantPanel = ({
setFieldName(e.target.value);
}}
endAdornment={
<Tooltip content="Help info here">
<Tooltip content="Help info here" placement="top">
<StyledInputEndAdornment>
<HelpCenterIcon />
</StyledInputEndAdornment>
@@ -98,6 +105,17 @@ export const CreatePendantPanel = ({
)}
iconConfig={getPendantConfigByType(selectedOption.type)}
onSure={async (type, newPropertyItem, newValue) => {
const checkResult = checkPendantForm(
type,
fieldName,
newPropertyItem,
newValue
);
if (!checkResult.passed) {
await message.error(checkResult.message);
return;
}
await onCreateSure({
type,
newPropertyItem,

View File

@@ -1,5 +1,5 @@
import { useState } from 'react';
import { Input, Tooltip } from '@toeverything/components/ui';
import { Input, message, Tooltip } from '@toeverything/components/ui';
import { HelpCenterIcon } from '@toeverything/components/icons';
import { PendantModifyPanel } from '../pendant-modify-panel';
import type { AsyncBlock } from '../../editor';
@@ -8,7 +8,7 @@ import {
type RecastBlockValue,
type RecastMetaProperty,
} from '../../recast-block';
import { getPendantConfigByType } from '../utils';
import { checkPendantForm, getPendantConfigByType } from '../utils';
import {
StyledPopoverWrapper,
StyledOperationLabel,
@@ -70,7 +70,7 @@ export const UpdatePendantPanel = ({
setFieldName(e.target.value);
}}
endAdornment={
<Tooltip content="Help info here">
<Tooltip content="Help info here" placement="top">
<StyledInputEndAdornment>
<HelpCenterIcon />
</StyledInputEndAdornment>
@@ -98,6 +98,17 @@ export const UpdatePendantPanel = ({
property={property}
type={property.type}
onSure={async (type, newPropertyItem, newValue) => {
const checkResult = checkPendantForm(
type,
fieldName,
newPropertyItem,
newValue
);
if (!checkResult.passed) {
await message.error(checkResult.message);
return;
}
await onUpdateSure({
type,
newPropertyItem,

View File

@@ -23,12 +23,7 @@ import {
PendantTypes,
type TempInformationType,
} from '../types';
import {
checkPendantForm,
getOfficialSelected,
getPendantConfigByType,
} from '../utils';
import { message } from '@toeverything/components/ui';
import { getOfficialSelected, getPendantConfigByType } from '../utils';
type SelectPropertyType = MultiSelectProperty | SelectProperty;
type SureParams = {
@@ -56,18 +51,6 @@ export const useOnCreateSure = ({ block }: { block: AsyncBlock }) => {
newPropertyItem,
newValue,
}: SureParams) => {
const checkResult = checkPendantForm(
type,
fieldName,
newPropertyItem,
newValue
);
if (!checkResult.passed) {
await message.error(checkResult.message);
return;
}
if (
type === PendantTypes.MultiSelect ||
type === PendantTypes.Select ||
@@ -181,18 +164,6 @@ export const useOnUpdateSure = ({
newPropertyItem,
newValue,
}: SureParams) => {
const checkResult = checkPendantForm(
type,
fieldName,
newPropertyItem,
newValue
);
if (!checkResult.passed) {
await message.error(checkResult.message);
return;
}
if (
type === PendantTypes.MultiSelect ||
type === PendantTypes.Select ||

View File

@@ -26,6 +26,7 @@ export const PendantPopover: FC<
block={block}
endElement={
<AddPendantPopover
container={popoverProps.container}
block={block}
onSure={() => {
popoverHandlerRef.current?.setVisible(false);

View File

@@ -105,6 +105,8 @@ export const PendantRender = ({ block }: { block: AsyncBlock }) => {
<AddPendantPopover
block={block}
iconStyle={{ marginTop: 4 }}
trigger="click"
// trigger={isKanbanView ? 'hover' : 'click'}
container={blockRenderContainerRef.current}
/>
</div>

View File

@@ -162,7 +162,7 @@ export class BlockCommands {
public async moveInNewGridItem(
blockId: string,
gridItemId: string,
isBefore = false
type = GridDropType.left
) {
const block = await this._editor.getBlockById(blockId);
if (block) {
@@ -175,7 +175,7 @@ export class BlockCommands {
await block.remove();
await gridItemBlock.append(block);
if (targetGridItemBlock && gridItemBlock) {
if (isBefore) {
if (type === GridDropType.left) {
await targetGridItemBlock.before(gridItemBlock);
} else {
await targetGridItemBlock.after(gridItemBlock);

View File

@@ -95,6 +95,9 @@ export class DragDropManager {
}
private async _handleDropBlock(event: React.DragEvent<Element>) {
const targetBlock = await this._editor.getBlockById(
this._blockDragTargetId
);
if (this._blockDragDirection !== BlockDropPlacement.none) {
const blockId = event.dataTransfer.getData(this._blockIdKey);
if (!(await this._canBeDrop(event))) return;
@@ -109,13 +112,24 @@ export class DragDropManager {
this._blockDragDirection
)
) {
await this._editor.commands.blockCommands.createLayoutBlock(
blockId,
this._blockDragTargetId,
const dropType =
this._blockDragDirection === BlockDropPlacement.left
? GridDropType.left
: GridDropType.right
);
: GridDropType.right;
// if target is a grid item create grid item
if (targetBlock.type !== Protocol.Block.Type.gridItem) {
await this._editor.commands.blockCommands.createLayoutBlock(
blockId,
this._blockDragTargetId,
dropType
);
} else {
await this._editor.commands.blockCommands.moveInNewGridItem(
blockId,
this._blockDragTargetId,
dropType
);
}
}
if (
[
@@ -123,9 +137,6 @@ export class DragDropManager {
BlockDropPlacement.outerRight,
].includes(this._blockDragDirection)
) {
const targetBlock = await this._editor.getBlockById(
this._blockDragTargetId
);
if (targetBlock.type !== Protocol.Block.Type.grid) {
await this._editor.commands.blockCommands.createLayoutBlock(
blockId,
@@ -154,7 +165,7 @@ export class DragDropManager {
await this._editor.commands.blockCommands.moveInNewGridItem(
blockId,
gridItems[0].id,
true
GridDropType.right
);
}
}
@@ -347,10 +358,10 @@ export class DragDropManager {
blockId: string
) {
const { clientX, clientY } = event;
this._setBlockDragTargetId(blockId);
const path = await this._editor.getBlockPath(blockId);
const mousePoint = new Point(clientX, clientY);
const rect = domToRect(blockDom);
let targetBlock: AsyncBlock = path[path.length - 1];
/**
* IMP: compute the level of the target block
* future feature drag drop has level support do not delete
@@ -386,13 +397,30 @@ export class DragDropManager {
const gridBlocks = path.filter(
block => block.type === Protocol.Block.Type.grid
);
// limit grid block floor counts, when drag block to init grid
if (gridBlocks.length >= MAX_GRID_BLOCK_FLOOR) {
const parentBlock = path[path.length - 2];
// a new grid should not be grid item`s child
if (
parentBlock &&
parentBlock.type === Protocol.Block.Type.gridItem
) {
targetBlock = parentBlock;
// gridItem`s parent must be grid block
const gridItemCounts = (await path[path.length - 3].children())
.length;
if (
gridItemCounts >=
this._editor.configManager.grid.maxGridItemCount
) {
direction = BlockDropPlacement.none;
}
// limit grid block floor counts, when drag block to init grid
} else if (gridBlocks.length >= MAX_GRID_BLOCK_FLOOR) {
direction = BlockDropPlacement.none;
}
}
this._setBlockDragTargetId(targetBlock.id);
this._setBlockDragDirection(direction);
return direction;
return { direction, block: targetBlock };
}
public handlerEditorDrop(event: React.DragEvent<Element>) {

View File

@@ -18,7 +18,6 @@ import {
menuItemsMap,
} from './config';
import { QueryResult } from '../../search';
export type CommandMenuProps = {
editor: Virgo;
hooks: PluginHooks;
@@ -82,7 +81,6 @@ export const CommandMenu = ({ editor, hooks, style }: CommandMenuProps) => {
const checkIfShowCommandMenu = useCallback(
async (event: React.KeyboardEvent<HTMLDivElement>) => {
const { type, anchorNode } = editor.selection.currentSelectInfo;
// console.log(await editor.getBlockById(anchorNode.id));
if (!anchorNode?.id) {
return;
}
@@ -127,12 +125,12 @@ export const CommandMenu = ({ editor, hooks, style }: CommandMenuProps) => {
const COMMAND_MENU_HEIGHT =
window.innerHeight * 0.4;
const { top, left } =
const { top, left, bottom } =
editor.container.getBoundingClientRect();
if (clientHeight - rectTop <= COMMAND_MENU_HEIGHT) {
setCommandMenuPosition({
left: rect.left - left,
bottom: rectTop - top + 10,
bottom: bottom - rect.bottom + 24,
top: 'initial',
});
} else {

View File

@@ -168,6 +168,12 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) {
useEffect(() => {
setShowMenu(false);
if (groupBlock) {
const unobserve = groupBlock.onUpdate(() => setGroupBlock(null));
return unobserve;
}
return undefined;
}, [groupBlock]);
return (

View File

@@ -15,6 +15,7 @@ import {
BlockDropPlacement,
LINE_GAP,
AsyncBlock,
TAG_GAP,
} from '@toeverything/framework/virgo';
import { Button } from '@toeverything/components/common';
import { styled } from '@toeverything/components/ui';
@@ -78,13 +79,13 @@ function Line(props: { lineInfo: LineInfo; rootRect: DOMRect }) {
};
const bottomLineStyle = {
...horizontalLineStyle,
top: intersectionRect.bottom + 1 - rootRect.y - LINE_GAP,
top: intersectionRect.bottom + 1 - rootRect.y - LINE_GAP + TAG_GAP,
};
const verticalLineStyle = {
...lineStyle,
width: 2,
height: intersectionRect.height - LINE_GAP,
height: intersectionRect.height - LINE_GAP + TAG_GAP,
top: intersectionRect.y - rootRect.y,
};
const leftLineStyle = {
@@ -184,6 +185,14 @@ export const LeftMenuDraggable: FC<LeftMenuProps> = props => {
return () => sub.unsubscribe();
}, [blockInfo, editor]);
useEffect(() => {
if (block?.block != null) {
const unobserve = block.block.onUpdate(() => setBlock(undefined));
return unobserve;
}
return undefined;
}, [block?.block]);
useEffect(() => {
const sub = lineInfo.subscribe(data => {
if (data == null) {
@@ -220,7 +229,7 @@ export const LeftMenuDraggable: FC<LeftMenuProps> = props => {
MENU_WIDTH -
MENU_BUTTON_OFFSET -
rootRect.left,
top: block.rect.top - rootRect.top,
top: block.rect.top - rootRect.top + TAG_GAP * 2,
opacity: visible ? 1 : 0,
zIndex: 1,
}}

View File

@@ -10,7 +10,7 @@ import {
import { PluginRenderRoot } from '../../utils';
import { Subject, throttleTime } from 'rxjs';
import { domToRect, last, Point } from '@toeverything/utils';
const DRAG_THROTTLE_DELAY = 150;
const DRAG_THROTTLE_DELAY = 60;
export class LeftMenuPlugin extends BasePlugin {
private _mousedown?: boolean;
private _root?: PluginRenderRoot;
@@ -105,16 +105,17 @@ export class LeftMenuPlugin extends BasePlugin {
new Point(event.clientX, event.clientY)
);
if (block == null || ignoreBlockTypes.includes(block.type)) return;
const direction = await this.editor.dragDropManager.checkBlockDragTypes(
event,
block.dom,
block.id
);
const { direction, block: targetBlock } =
await this.editor.dragDropManager.checkBlockDragTypes(
event,
block.dom,
block.id
);
this._lineInfo.next({
direction,
blockInfo: {
block,
rect: block.dom.getBoundingClientRect(),
block: targetBlock,
rect: targetBlock.dom.getBoundingClientRect(),
},
});
};

View File

@@ -17,16 +17,20 @@ export const StatusIcon = ({ mode }: StatusIconProps) => {
const IconWrapper = styled('div')<Pick<StatusIconProps, 'mode'>>(
({ theme, mode }) => {
return {
width: '20px',
height: '20px',
width: '24px',
height: '24px',
borderRadius: '5px',
boxShadow: theme.affine.shadows.shadow1,
color: theme.affine.palette.primary,
cursor: 'pointer',
backgroundColor: theme.affine.palette.white,
transform: `translateX(${mode === DocMode.doc ? 0 : 20}px)`,
transform: `translateX(${mode === DocMode.doc ? 0 : 30}px)`,
transition: 'transform 300ms ease',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
'& > svg': {
fontSize: '20px',
},

View File

@@ -2,26 +2,37 @@ import { styled } from '@toeverything/components/ui';
type StatusTextProps = {
children: string;
width?: string;
active?: boolean;
onClick?: () => void;
};
export const StatusText = ({ children, active, onClick }: StatusTextProps) => {
export const StatusText = ({
children,
width,
active,
onClick,
}: StatusTextProps) => {
return (
<StyledText active={active} onClick={onClick}>
<StyledText width={width} active={active} onClick={onClick}>
{children}
</StyledText>
);
};
const StyledText = styled('div')<StatusTextProps>(({ theme, active }) => {
return {
display: 'inline-flex',
alignItems: 'center',
color: theme.affine.palette.primary,
fontWeight: active ? '500' : '300',
fontSize: '15px',
cursor: 'pointer',
padding: '0 6px',
};
});
const StyledText = styled('div')<StatusTextProps>(
({ theme, width, active }) => {
return {
display: 'inline-flex',
alignItems: 'center',
color: active
? theme.affine.palette.primary
: 'rgba(62, 111, 219, 0.6)',
fontWeight: active ? '600' : '400',
fontSize: '16px',
lineHeight: '22px',
cursor: 'pointer',
...(!!width && { width }),
};
}
);

View File

@@ -18,11 +18,14 @@ export const StatusTrack: FC<StatusTrackProps> = ({ mode, onClick }) => {
const Container = styled('div')(({ theme }) => {
return {
backgroundColor: theme.affine.palette.textHover,
borderRadius: '5px',
height: '30px',
width: '50px',
width: '64px',
height: '32px',
border: '1px solid #ECF1FB',
borderRadius: '8px',
cursor: 'pointer',
padding: '5px',
margin: '0 8px',
display: 'flex',
alignItems: 'center',
padding: '0 4px',
};
});

View File

@@ -32,6 +32,7 @@ export const Switcher = () => {
return (
<StyledContainerForSwitcher>
<StatusText
width={'44px'}
active={pageViewMode === DocMode.doc}
onClick={() => switchToPageView(DocMode.doc)}
>
@@ -48,6 +49,7 @@ export const Switcher = () => {
}}
/>
<StatusText
width={'56px'}
active={pageViewMode === DocMode.board}
onClick={() => switchToPageView(DocMode.board)}
>

View File

@@ -1,4 +1,4 @@
import { IconButton, styled } from '@toeverything/components/ui';
import { IconButton, styled, MuiButton } from '@toeverything/components/ui';
import {
LogoIcon,
SideBarViewIcon,
@@ -6,6 +6,7 @@ import {
SideBarViewCloseIcon,
} from '@toeverything/components/icons';
import { useShowSettingsSidebar } from '@toeverything/datasource/state';
import { CurrentPageTitle } from './Title';
import { EditorBoardSwitcher } from './EditorBoardSwitcher';
@@ -24,9 +25,14 @@ export const LayoutHeader = () => {
</FlexContainer>
<FlexContainer>
<StyledHelper>
<StyledShare>Share</StyledShare>
<StyledShare disabled={true}>Share</StyledShare>
<div style={{ margin: '0px 12px' }}>
<IconButton size="large">
<IconButton
size="large"
hoverColor={'transparent'}
disabled={true}
style={{ cursor: 'not-allowed' }}
>
<SearchIcon />
</IconButton>
</div>
@@ -119,17 +125,19 @@ const StyledHelper = styled('div')({
alignItems: 'center',
});
const StyledShare = styled('div')({
const StyledShare = styled('div')<{ disabled?: boolean }>({
padding: '10px 12px',
fontWeight: 600,
fontSize: '14px',
color: '#3E6FDB',
cursor: 'pointer',
'&:hover': {
background: '#F5F7F8',
borderRadius: '5px',
},
cursor: 'not-allowed',
color: '#98ACBD',
textTransform: 'none',
/* disabled for current time */
// color: '#3E6FDB',
// '&:hover': {
// background: '#F5F7F8',
// borderRadius: '5px',
// },
});
const StyledLogoIcon = styled(LogoIcon)(({ theme }) => {
@@ -141,9 +149,7 @@ const StyledLogoIcon = styled(LogoIcon)(({ theme }) => {
const StyledContainerForEditorBoardSwitcher = styled('div')(({ theme }) => {
return {
width: '100%',
position: 'absolute',
display: 'flex',
justifyContent: 'center',
left: '50%',
};
});

View File

@@ -1,4 +1,5 @@
import { useNavigate } from 'react-router-dom';
import { message } from '@toeverything/components/ui';
import { useSettingFlags, type SettingFlags } from './use-setting-flags';
import { copyToClipboard } from '@toeverything/utils';
import {
@@ -91,7 +92,10 @@ export const useSettings = (): SettingItem[] => {
{
type: 'button',
name: 'Copy Page Link',
onClick: () => copyToClipboard(window.location.href),
onClick: () => {
copyToClipboard(window.location.href);
message.success('Page link copied successfully');
},
},
{
type: 'separator',

View File

@@ -10,9 +10,10 @@ import {
} from '@toeverything/components/ui';
import { useNavigate } from 'react-router';
import { formatDistanceToNow } from 'date-fns';
import { DotIcon } from '../dot-icon';
const StyledWrapper = styled('div')({
paddingLeft: '12px',
width: '100%',
span: {
textOverflow: 'ellipsis',
overflow: 'hidden',
@@ -22,8 +23,8 @@ const StyledWrapper = styled('div')({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
paddingRight: '20px',
whiteSpace: 'nowrap',
paddingLeft: '12px',
'&:hover': {
background: '#f5f7f8',
borderRadius: '5px',
@@ -106,6 +107,8 @@ export const Activities = () => {
const { id, title, updated } = item;
return (
<ListItem className="item" key={id}>
<DotIcon />
<StyledItemContent
onClick={() => {
navigate(`/${currentSpaceId}/${id}`);

View File

@@ -0,0 +1,9 @@
import { PageInPageTreeIcon } from '@toeverything/components/icons';
export const DotIcon = () => {
return (
<PageInPageTreeIcon
style={{ fill: '#98ACBD', width: '20px', height: '20px' }}
/>
);
};

View File

@@ -0,0 +1 @@
export { DotIcon } from './DotIcon';

View File

@@ -44,7 +44,7 @@ export type DndTreeProps = {
*/
export function DndTree(props: DndTreeProps) {
const {
indentationWidth = 12,
indentationWidth = 20,
collapsible,
removable,
showDragIndicator,

View File

@@ -3,10 +3,8 @@ import { DndTree } from './DndTree';
import { useDndTreeAutoUpdate } from './use-page-tree';
const Root = styled('div')({
minWidth: 160,
maxWidth: 260,
marginLeft: 18,
marginRight: 6,
minWidth: '160px',
maxWidth: '276px',
});
export const PageTree = () => {

View File

@@ -8,6 +8,7 @@ import { useParams } from 'react-router-dom';
import { useFlag } from '@toeverything/datasource/feature-flags';
import MoreActions from './MoreActions';
import { DotIcon } from '../../dot-icon';
import {
ActionButton,
Counter,
@@ -76,24 +77,25 @@ export const TreeItem = forwardRef<HTMLDivElement, TreeItemProps>(
ghost={ghost}
disableSelection={disableSelection}
disableInteraction={disableInteraction}
spacing={`${indentationWidth * depth}px`}
spacing={`${indentationWidth * depth + 12}px`}
active={pageId === page_id}
{...props}
>
<TreeItemContainer ref={ref} style={style} title={value}>
<ActionButton tabIndex={0} onClick={onCollapse}>
{childCount !== 0 &&
(collapsed ? (
{childCount !== 0 ? (
collapsed ? (
<ArrowRightIcon />
) : (
<ArrowDropDownIcon />
))}
)
) : (
<DotIcon />
)}
</ActionButton>
<TreeItemContent {...handleProps}>
<TextLink
to={`/${workspace_id}/${pageId}`}
active={pageId === page_id}
>
<TextLink to={`/${workspace_id}/${pageId}`}>
{value}
</TextLink>
{BooleanPageTreeItemMoreActions && (

View File

@@ -15,11 +15,14 @@ export const Wrapper = styled('li')<{
indicator?: boolean;
disableSelection?: boolean;
disableInteraction?: boolean;
active?: boolean;
}>`
box-sizing: border-box;
padding-left: ${({ spacing }) => spacing};
list-style: none;
font-size: 14px;
background-color: ${({ active }) => (active ? '#f5f7f8' : 'transparent')};
border-radius: 5px;
${({ clone, disableSelection }) =>
(clone || disableSelection) &&
@@ -126,8 +129,6 @@ export const ActionButton = styled('button')<{
fill?: string;
}>`
display: flex;
width: 12px;
padding: 0 15px;
align-items: center;
justify-content: center;
flex: 0 0 auto;
@@ -141,9 +142,10 @@ export const ActionButton = styled('button')<{
-webkit-tap-highlight-color: transparent;
svg {
width: 20px;
height: 20px;
flex: 0 0 auto;
margin: auto;
height: 100%;
overflow: visible;
fill: #919eab;
}
@@ -168,7 +170,9 @@ export const TreeItemMoreActions = styled('div')`
visibility: hidden;
`;
export const TextLink = styled(Link)<{ active?: boolean }>`
export const TextLink = styled(Link, {
shouldForwardProp: (prop: string) => !['active'].includes(prop),
})<{ active?: boolean }>`
display: flex;
align-items: center;
flex-grow: 1;
@@ -180,8 +184,7 @@ export const TextLink = styled(Link)<{ active?: boolean }>`
appearance: none;
text-decoration: none;
user-select: none;
color: ${({ theme, active }) =>
active ? theme.affine.palette.primary : 'unset'};
color: #4c6275;
`;
export const TreeItemContent = styled('div')`
@@ -193,7 +196,7 @@ export const TreeItemContent = styled('div')`
align-items: center;
justify-content: space-around;
color: #4c6275;
padding-right: 0.5rem;
padding-right: 12px;
overflow: hidden;
&:hover {

View File

@@ -12,6 +12,7 @@ import SelectUnstyled, {
} from '@mui/base/SelectUnstyled';
/* eslint-disable no-restricted-imports */
import PopperUnstyled from '@mui/base/PopperUnstyled';
import { ArrowDropDownIcon } from '@toeverything/components/icons';
import { styled } from '../styled';
type ExtendSelectProps = {
@@ -41,20 +42,29 @@ export const Select = forwardRef(function CustomSelect<TValue>(
const { width = '100%', style, listboxStyle, placeholder } = props;
const components: SelectUnstyledProps<TValue>['components'] = {
// Root: generateStyledRoot({ width, ...style }),
Root: forwardRef((rootProps, rootRef) => (
<StyledRoot
ref={rootRef}
{...rootProps}
style={{
width,
...style,
}}
>
{rootProps.children || (
<StyledPlaceholder>{placeholder}</StyledPlaceholder>
)}
</StyledRoot>
)),
Root: forwardRef((rootProps, rootRef) => {
const {
ownerState: { open },
} = rootProps;
return (
<StyledRoot
ref={rootRef}
{...rootProps}
style={{
width,
...style,
}}
>
{rootProps.children || (
<StyledPlaceholder>{placeholder}</StyledPlaceholder>
)}
<StyledSelectedArrowWrapper open={open}>
<ArrowDropDownIcon />
</StyledSelectedArrowWrapper>
</StyledRoot>
);
}),
Listbox: forwardRef((listboxProps, listboxRef) => (
<StyledListbox
ref={listboxRef}
@@ -73,6 +83,20 @@ export const Select = forwardRef(function CustomSelect<TValue>(
RefAttributes<HTMLUListElement>
) => JSX.Element;
const StyledSelectedArrowWrapper = styled('div')<{ open: boolean }>(
({ open }) => ({
position: 'absolute',
top: '0',
bottom: '0',
right: '12px',
margin: 'auto',
lineHeight: '32px',
display: 'flex',
alignItems: 'center',
transform: `rotate(${open ? '180deg' : '0'})`,
})
);
const StyledRoot = styled('div')(({ theme }) => ({
height: '32px',
border: `1px solid ${theme.affine.palette.borderColor}`,
@@ -95,18 +119,6 @@ const StyledRoot = styled('div')(({ theme }) => ({
[`&.${selectUnstyledClasses.expanded}`]: {
borderColor: `${theme.affine.palette.primary}`,
'&::after': {
content: '"▴"',
},
},
'&::after': {
content: '"▾"',
position: ' absolute',
top: '0',
bottom: '0',
right: '12px',
margin: 'auto',
lineHeight: '32px',
},
}));

View File

@@ -173,26 +173,34 @@ export const Theme = {
body1: {
fontSize: '16px',
lineHeight: '22px',
fontWeight: 400,
fontFamily: 'PingFang SC',
color: '#3A4C5C',
},
h1: {
fontSize: '28px',
lineHeight: '40px',
fontWeight: 600,
},
h2: {
fontSize: '24px',
lineHeight: '34px',
fontWeight: 600,
},
h3: {
fontSize: '20px',
lineHeight: '28px',
fontWeight: 600,
},
h4: {
fontSize: '16px',
lineHeight: '22px',
fontWeight: 600,
},
page: {
fontSize: '36px',
lineHeight: '44px',
fontWeight: 600,
},
callout: {
fontSize: '36px',
@@ -221,6 +229,7 @@ export const Theme = {
articleTitle: {
fontSize: '36px',
lineHeight: '54px',
fontWeight: 600,
},
},
shadows: {