Bugfix/board style (#321)

* fix style

* fix drag bounds

* fix drag bounds

* delete log

* delete log

* fix:lint

* fix:lint

* fix:lint

* fix:bounds show
This commit is contained in:
DiamondThree
2022-08-24 16:51:19 +08:00
committed by GitHub
parent dad12b2a79
commit 712566ca84
9 changed files with 117 additions and 148 deletions

View File

@@ -51,11 +51,10 @@ const AffineBoard = ({
}; };
}); });
const { shapes, bindings } = useShapes(workspace, rootBlockId); const { shapes } = useShapes(workspace, rootBlockId);
useEffect(() => { useEffect(() => {
if (app) { if (app) {
app.replacePageContent(shapes || {}, bindings, {}); app.replacePageContent(shapes || {}, {}, {});
} }
}, [app, shapes]); }, [app, shapes]);
@@ -69,7 +68,9 @@ const AffineBoard = ({
onMount(app) { onMount(app) {
set_app(app); set_app(app);
}, },
async onPaste(e, data) {
console.log('e,data: ', e, data);
},
async onCopy(e, groupIds) { async onCopy(e, groupIds) {
const clip = await getClipDataOfBlocksById( const clip = await getClipDataOfBlocksById(
editor, editor,
@@ -110,18 +111,6 @@ const AffineBoard = ({
}); });
} }
shape.affineId = block.id; shape.affineId = block.id;
Object.keys(bindings).forEach(bilingKey => {
if (
bindings[bilingKey]?.fromId === shape.id
) {
bindings[bilingKey].fromId = block.id;
}
if (
bindings[bilingKey]?.toId === shape.id
) {
bindings[bilingKey].toId = block.id;
}
});
return await services.api.editorBlock.update({ return await services.api.editorBlock.update({
workspace: shape.workspace, workspace: shape.workspace,
id: block.id, id: block.id,
@@ -134,30 +123,6 @@ const AffineBoard = ({
} }
}) })
); );
const pageBindingsString = (
await services.api.editorBlock.get({
workspace: workspace,
ids: [rootBlockId],
})
)?.[0].properties.bindings?.value;
const pageBindings = JSON.parse(pageBindingsString ?? '{}');
Object.keys(bindings).forEach(bindingsKey => {
if (!bindings[bindingsKey]) {
delete pageBindings[bindingsKey];
} else {
Object.assign(pageBindings, bindings);
}
});
await services.api.editorBlock.update({
workspace: workspace,
id: rootBlockId,
properties: {
bindings: {
value: JSON.stringify(pageBindings),
},
},
});
}, },
}} }}
/> />

View File

@@ -5,24 +5,12 @@ import { services } from '@toeverything/datasource/db-service';
import { usePageClientWidth } from '@toeverything/datasource/state'; import { usePageClientWidth } from '@toeverything/datasource/state';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
const getBindings = (workspace: string, rootBlockId: string) => {
return services.api.editorBlock
.get({
workspace: workspace,
ids: [rootBlockId],
})
.then(blcoks => {
return blcoks[0]?.properties.bindings?.value;
});
};
export const useShapes = (workspace: string, rootBlockId: string) => { export const useShapes = (workspace: string, rootBlockId: string) => {
const { pageClientWidth } = usePageClientWidth(); const { pageClientWidth } = usePageClientWidth();
// page padding left and right total 300px // page padding left and right total 300px
const editorShapeInitSize = pageClientWidth - 300; const editorShapeInitSize = pageClientWidth - 300;
const [blocks, setBlocks] = useState<{ const [blocks, setBlocks] = useState<{
shapes: [ReturnEditorBlock[]]; shapes: [ReturnEditorBlock[]];
bindings: string;
}>(); }>();
useEffect(() => { useEffect(() => {
Promise.all([ Promise.all([
@@ -43,11 +31,8 @@ export const useShapes = (workspace: string, rootBlockId: string) => {
return shapes; return shapes;
}), }),
]).then(shapes => { ]).then(shapes => {
getBindings(workspace, rootBlockId).then(bindings => { setBlocks({
setBlocks({ shapes: shapes,
shapes,
bindings: bindings,
});
}); });
}); });
@@ -65,11 +50,8 @@ export const useShapes = (workspace: string, rootBlockId: string) => {
return childBlock; return childBlock;
}) })
).then(shapes => { ).then(shapes => {
getBindings(workspace, rootBlockId).then(bindings => { setBlocks({
setBlocks({ shapes: [shapes],
shapes: [shapes],
bindings: bindings,
});
}); });
}); });
}) })
@@ -107,6 +89,5 @@ export const useShapes = (workspace: string, rootBlockId: string) => {
return { return {
shapes: blocksShapes, shapes: blocksShapes,
bindings: JSON.parse(blocks?.bindings ?? '{}'),
}; };
}; };

View File

@@ -362,7 +362,7 @@ const InnerTldraw = memo(function InnerTldraw({
// Hide bounds when not using the select tool, or when the only selected shape has handles // Hide bounds when not using the select tool, or when the only selected shape has handles
const hideBounds = const hideBounds =
(isInSession && app.session?.constructor.name !== 'BrushSession') || (isInSession && app.session?.constructor.name === 'BrushSession') ||
!isSelecting || !isSelecting ||
isHideBoundsShape || isHideBoundsShape ||
!!pageState.editingId; !!pageState.editingId;

View File

@@ -56,7 +56,8 @@ const SelectableContainer = styled('div')<{ selected?: boolean }>(
borderRadius: '5px', borderRadius: '5px',
overflow: 'hidden', overflow: 'hidden',
margin: '5px', margin: '5px',
padding: '3px', width: '24px',
height: '24px',
cursor: 'pointer', cursor: 'pointer',
boxSizing: 'border-box', boxSizing: 'border-box',
'&:hover': { '&:hover': {

View File

@@ -2,7 +2,6 @@ import { TLDR, TldrawApp } from '@toeverything/components/board-state';
import { Divider, Popover, styled } from '@toeverything/components/ui'; import { Divider, Popover, styled } from '@toeverything/components/ui';
import { Fragment } from 'react'; import { Fragment } from 'react';
import { AlignOperation } from './AlignOperation'; import { AlignOperation } from './AlignOperation';
import { ArrowTo } from './ArrowTo';
import { BorderColorConfig } from './BorderColorConfig'; import { BorderColorConfig } from './BorderColorConfig';
import { DeleteShapes } from './DeleteOperation'; import { DeleteShapes } from './DeleteOperation';
import { FillColorConfig } from './FillColorConfig'; import { FillColorConfig } from './FillColorConfig';
@@ -107,12 +106,12 @@ export const CommandPanel = ({ app }: { app: TldrawApp }) => {
shapes={config.deleteShapes.selectedShapes} shapes={config.deleteShapes.selectedShapes}
></AlignOperation> ></AlignOperation>
) : null, ) : null,
toNextShap: ( // toNextShap: (
<ArrowTo // <ArrowTo
app={app} // app={app}
shapes={config.deleteShapes.selectedShapes} // shapes={config.deleteShapes.selectedShapes}
></ArrowTo> // ></ArrowTo>
), // ),
}; };
const nodes = Object.entries(configNodes).filter(([key, node]) => !!node); const nodes = Object.entries(configNodes).filter(([key, node]) => !!node);

View File

@@ -42,7 +42,7 @@ type E = HTMLDivElement;
export class ArrowUtil extends TDShapeUtil<T, E> { export class ArrowUtil extends TDShapeUtil<T, E> {
type = TDShapeType.Arrow as const; type = TDShapeType.Arrow as const;
override hideBounds = true; override hideBounds = false;
override canEdit = true; override canEdit = true;

View File

@@ -1,6 +1,8 @@
import { Utils } from '@tldraw/core'; import { Utils } from '@tldraw/core';
import type { ShapeStyles } from '@toeverything/components/board-types'; import {
import { BINDING_DISTANCE } from '@toeverything/components/board-types'; BINDING_DISTANCE,
ShapeStyles,
} from '@toeverything/components/board-types';
import * as React from 'react'; import * as React from 'react';
import { getShapeStyle } from '../../shared'; import { getShapeStyle } from '../../shared';
@@ -56,23 +58,20 @@ export const DashedRectangle = React.memo(function DashedRectangle({
return ( return (
<> <>
<rect <rect
className={ className={'tl-fill-hitarea'}
isSelected || style.isFilled
? 'tl-fill-hitarea'
: 'tl-stroke-hitarea'
}
x={sw / 2} x={sw / 2}
y={sw / 2} y={sw / 2}
width={w} width={w}
height={h} height={h}
opacity={1}
strokeWidth={BINDING_DISTANCE} strokeWidth={BINDING_DISTANCE}
/> />
{style.isFilled && ( {style.isFilled && (
<rect <rect
x={sw / 2} x={sw / 2}
y={sw / 2} y={sw / 2}
width={w} width={w - sw / 2}
height={h} height={h - sw / 2}
fill={fill} fill={fill}
pointerEvents="none" pointerEvents="none"
/> />

View File

@@ -175,6 +175,10 @@ interface TDCallbacks {
* (optional) A callback to run when the shape is copied. * (optional) A callback to run when the shape is copied.
*/ */
onCopy?: (e: ClipboardEvent, ids: string[]) => void; onCopy?: (e: ClipboardEvent, ids: string[]) => void;
/**
* (optional) A callback to run when the shape is paste.
*/
onPaste?: (e: ClipboardEvent, data: any) => void;
} }
export interface TldrawAppCtorProps { export interface TldrawAppCtorProps {
@@ -1956,6 +1960,53 @@ export class TldrawApp extends StateManager<TDSnapshot> {
paste = async (point?: number[], e?: ClipboardEvent) => { paste = async (point?: number[], e?: ClipboardEvent) => {
if (this.readOnly) return; if (this.readOnly) return;
if (e) {
const data = e.clipboardData?.getData('text/html');
const paste_as_html = (html: string) => {
try {
const maybeJson = html.match(/<tldraw>(.*)<\/tldraw>/)?.[1];
if (!maybeJson) return;
const json: {
type: string;
shapes: TDShape[];
bindings: TDBinding[];
assets: TDAsset[];
} = JSON.parse(maybeJson);
return json;
} catch (e) {
return;
}
};
this.callbacks.onPaste?.(e, paste_as_html(data));
return this;
}
const paste_as_html = (html: string) => {
try {
const maybeJson = html.match(/<tldraw>(.*)<\/tldraw>/)?.[1];
if (!maybeJson) return;
const json: {
type: string;
shapes: TDShape[];
bindings: TDBinding[];
assets: TDAsset[];
} = JSON.parse(maybeJson);
if (json.type === 'tldr/clipboard') {
pasteInCurrentPage(json.shapes, json.bindings, json.assets);
return;
} else {
throw Error('Not tldraw data!');
}
} catch (e) {
pasteTextAsShape(html);
return;
}
};
const pasteInCurrentPage = ( const pasteInCurrentPage = (
shapes: TDShape[], shapes: TDShape[],
bindings: TDBinding[], bindings: TDBinding[],
@@ -2107,31 +2158,6 @@ export class TldrawApp extends StateManager<TDSnapshot> {
// this.select(shapeId); // this.select(shapeId);
}; };
const paste_as_html = (html: string) => {
try {
const maybeJson = html.match(/<tldraw>(.*)<\/tldraw>/)?.[1];
if (!maybeJson) return;
const json: {
type: string;
shapes: TDShape[];
bindings: TDBinding[];
assets: TDAsset[];
} = JSON.parse(maybeJson);
if (json.type === 'tldr/clipboard') {
pasteInCurrentPage(json.shapes, json.bindings, json.assets);
return;
} else {
throw Error('Not tldraw data!');
}
} catch (e) {
pasteTextAsShape(html);
return;
}
};
if (e !== undefined) { if (e !== undefined) {
const items: DataTransferItemList = const items: DataTransferItemList =
e.clipboardData?.items ?? ({} as DataTransferItemList); e.clipboardData?.items ?? ({} as DataTransferItemList);

View File

@@ -1,58 +1,54 @@
import { useState, useRef, useEffect } from 'react';
import { StyleWithAtRules } from 'style9';
import { CreateView } from '@toeverything/framework/virgo';
import CodeMirror, { ReactCodeMirrorRef } from './CodeMirror';
import { styled } from '@toeverything/components/ui';
import { javascript } from '@codemirror/lang-javascript';
import { html } from '@codemirror/lang-html';
import { css } from '@codemirror/lang-css';
import { json } from '@codemirror/lang-json';
import { python } from '@codemirror/lang-python';
import { markdown } from '@codemirror/lang-markdown';
import { xml } from '@codemirror/lang-xml';
import { sql, MySQL, PostgreSQL } from '@codemirror/lang-sql';
import { java } from '@codemirror/lang-java';
import { rust } from '@codemirror/lang-rust';
import { cpp } from '@codemirror/lang-cpp'; import { cpp } from '@codemirror/lang-cpp';
import { css } from '@codemirror/lang-css';
import { html } from '@codemirror/lang-html';
import { java } from '@codemirror/lang-java';
import { javascript } from '@codemirror/lang-javascript';
import { json } from '@codemirror/lang-json';
import { lezer } from '@codemirror/lang-lezer'; import { lezer } from '@codemirror/lang-lezer';
import { markdown } from '@codemirror/lang-markdown';
import { php } from '@codemirror/lang-php'; import { php } from '@codemirror/lang-php';
import { python } from '@codemirror/lang-python';
import { rust } from '@codemirror/lang-rust';
import { MySQL, PostgreSQL, sql } from '@codemirror/lang-sql';
import { xml } from '@codemirror/lang-xml';
import { StreamLanguage } from '@codemirror/language'; import { StreamLanguage } from '@codemirror/language';
import { go } from '@codemirror/legacy-modes/mode/go';
import { ruby } from '@codemirror/legacy-modes/mode/ruby';
import { shell } from '@codemirror/legacy-modes/mode/shell';
import { lua } from '@codemirror/legacy-modes/mode/lua';
import { swift } from '@codemirror/legacy-modes/mode/swift';
import { tcl } from '@codemirror/legacy-modes/mode/tcl';
import { yaml } from '@codemirror/legacy-modes/mode/yaml';
import { vb } from '@codemirror/legacy-modes/mode/vb';
import { powerShell } from '@codemirror/legacy-modes/mode/powershell';
import { brainfuck } from '@codemirror/legacy-modes/mode/brainfuck'; import { brainfuck } from '@codemirror/legacy-modes/mode/brainfuck';
import { stylus } from '@codemirror/legacy-modes/mode/stylus';
import { erlang } from '@codemirror/legacy-modes/mode/erlang';
import { elixir } from 'codemirror-lang-elixir';
import { nginx } from '@codemirror/legacy-modes/mode/nginx';
import { perl } from '@codemirror/legacy-modes/mode/perl';
import { pascal } from '@codemirror/legacy-modes/mode/pascal';
import { liveScript } from '@codemirror/legacy-modes/mode/livescript';
import { scheme } from '@codemirror/legacy-modes/mode/scheme';
import { toml } from '@codemirror/legacy-modes/mode/toml';
import { vbScript } from '@codemirror/legacy-modes/mode/vbscript';
import { clojure } from '@codemirror/legacy-modes/mode/clojure'; import { clojure } from '@codemirror/legacy-modes/mode/clojure';
import { coffeeScript } from '@codemirror/legacy-modes/mode/coffeescript'; import { coffeeScript } from '@codemirror/legacy-modes/mode/coffeescript';
import { dockerFile } from '@codemirror/legacy-modes/mode/dockerfile'; import { dockerFile } from '@codemirror/legacy-modes/mode/dockerfile';
import { erlang } from '@codemirror/legacy-modes/mode/erlang';
import { go } from '@codemirror/legacy-modes/mode/go';
import { julia } from '@codemirror/legacy-modes/mode/julia'; import { julia } from '@codemirror/legacy-modes/mode/julia';
import { liveScript } from '@codemirror/legacy-modes/mode/livescript';
import { lua } from '@codemirror/legacy-modes/mode/lua';
import { nginx } from '@codemirror/legacy-modes/mode/nginx';
import { pascal } from '@codemirror/legacy-modes/mode/pascal';
import { perl } from '@codemirror/legacy-modes/mode/perl';
import { powerShell } from '@codemirror/legacy-modes/mode/powershell';
import { r } from '@codemirror/legacy-modes/mode/r'; import { r } from '@codemirror/legacy-modes/mode/r';
import { ruby } from '@codemirror/legacy-modes/mode/ruby';
import { scheme } from '@codemirror/legacy-modes/mode/scheme';
import { shell } from '@codemirror/legacy-modes/mode/shell';
import { stylus } from '@codemirror/legacy-modes/mode/stylus';
import { swift } from '@codemirror/legacy-modes/mode/swift';
import { tcl } from '@codemirror/legacy-modes/mode/tcl';
import { toml } from '@codemirror/legacy-modes/mode/toml';
import { vb } from '@codemirror/legacy-modes/mode/vb';
import { vbScript } from '@codemirror/legacy-modes/mode/vbscript';
import { yaml } from '@codemirror/legacy-modes/mode/yaml';
import { Extension } from '@codemirror/state'; import { Extension } from '@codemirror/state';
import { Option, Select } from '@toeverything/components/ui';
import { import {
useOnSelect,
BlockPendantProvider, BlockPendantProvider,
useOnSelect,
} from '@toeverything/components/editor-core'; } from '@toeverything/components/editor-core';
import { copyToClipboard } from '@toeverything/utils';
import { DuplicateIcon } from '@toeverything/components/icons'; import { DuplicateIcon } from '@toeverything/components/icons';
import { Option, Select, styled } from '@toeverything/components/ui';
import { CreateView } from '@toeverything/framework/virgo';
import { copyToClipboard } from '@toeverything/utils';
import { elixir } from 'codemirror-lang-elixir';
import { useEffect, useRef, useState } from 'react';
import { StyleWithAtRules } from 'style9';
import CodeMirror, { ReactCodeMirrorRef } from './CodeMirror';
interface CreateCodeView extends CreateView { interface CreateCodeView extends CreateView {
style9?: StyleWithAtRules; style9?: StyleWithAtRules;
@@ -110,13 +106,15 @@ const CodeBlock = styled('div')(({ theme }) => ({
borderRadius: theme.affine.shape.borderRadius, borderRadius: theme.affine.shape.borderRadius,
'&:hover': { '&:hover': {
'.operation': { '.operation': {
display: 'flex', opacity: 1,
}, },
}, },
'.operation': { '.operation': {
display: 'flex', display: 'flex',
flexWrap: 'wrap', flexWrap: 'wrap',
justifyContent: 'space-between', justifyContent: 'space-between',
opacity: 0,
transition: 'opacity 1.5s',
}, },
'.copy-block': { '.copy-block': {
padding: '0px 10px', padding: '0px 10px',