feat(core): shape editor settings (#8122)
<div class='graphite__hidden'>
<div>🎥 Video uploaded on Graphite:</div>
<a href="https://app.graphite.dev/media/video/sJGviKxfE3Ap685cl5bj/cdf4f95c-15b4-4eac-be57-26974f9ca02b.mov">
<img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/sJGviKxfE3Ap685cl5bj/cdf4f95c-15b4-4eac-be57-26974f9ca02b.mov">
</a>
</div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/cdf4f95c-15b4-4eac-be57-26974f9ca02b.mov">录屏2024-09-05 21.20.31.mov</video>
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
|||||||
PointStyle,
|
PointStyle,
|
||||||
StrokeStyle,
|
StrokeStyle,
|
||||||
} from '@blocksuite/blocks';
|
} from '@blocksuite/blocks';
|
||||||
|
import type { Doc } from '@blocksuite/store';
|
||||||
import { useFramework, useLiveData } from '@toeverything/infra';
|
import { useFramework, useLiveData } from '@toeverything/infra';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ import { menuTrigger, settingWrapper } from '../style.css';
|
|||||||
import { useColor } from '../utils';
|
import { useColor } from '../utils';
|
||||||
import { Point } from './point';
|
import { Point } from './point';
|
||||||
import { EdgelessSnapshot } from './snapshot';
|
import { EdgelessSnapshot } from './snapshot';
|
||||||
|
import { getSurfaceBlock } from './utils';
|
||||||
|
|
||||||
enum ConnecterStyle {
|
enum ConnecterStyle {
|
||||||
General = 'general',
|
General = 'general',
|
||||||
@@ -189,13 +191,18 @@ export const ConnectorSettings = () => {
|
|||||||
});
|
});
|
||||||
}, [editorSetting, settings]);
|
}, [editorSetting, settings]);
|
||||||
|
|
||||||
|
const getElements = useCallback((doc: Doc) => {
|
||||||
|
const surface = getSurfaceBlock(doc);
|
||||||
|
return surface?.getElementsByType('connector') || [];
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EdgelessSnapshot
|
<EdgelessSnapshot
|
||||||
title={t['com.affine.settings.editorSettings.edgeless.connecter']()}
|
title={t['com.affine.settings.editorSettings.edgeless.connecter']()}
|
||||||
docName="connector"
|
docName="connector"
|
||||||
keyName="connector"
|
keyName="connector"
|
||||||
flavour="connector"
|
getElements={getElements}
|
||||||
/>
|
/>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
name={t[
|
name={t[
|
||||||
|
|||||||
@@ -0,0 +1,470 @@
|
|||||||
|
{
|
||||||
|
"type": "page",
|
||||||
|
"meta": {
|
||||||
|
"id": "IWDwzafoLh",
|
||||||
|
"title": "BlockSuite Playground",
|
||||||
|
"createDate": 1725541560333,
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"blocks": {
|
||||||
|
"type": "block",
|
||||||
|
"id": "DBwzSu70O4",
|
||||||
|
"flavour": "affine:page",
|
||||||
|
"version": 2,
|
||||||
|
"props": {
|
||||||
|
"title": {
|
||||||
|
"$blocksuite:internal:text$": true,
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "BlockSuite Playground"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"id": "VsLifn6v6J",
|
||||||
|
"flavour": "affine:surface",
|
||||||
|
"version": 5,
|
||||||
|
"props": {
|
||||||
|
"elements": {
|
||||||
|
"03ESqmbu0V": {
|
||||||
|
"index": "aF",
|
||||||
|
"seed": 456881005,
|
||||||
|
"color": "--affine-palette-line-black",
|
||||||
|
"fillColor": "--affine-palette-shape-yellow",
|
||||||
|
"filled": true,
|
||||||
|
"fontFamily": "blocksuite:surface:Inter",
|
||||||
|
"fontSize": 12,
|
||||||
|
"maxWidth": false,
|
||||||
|
"padding": [10, 20],
|
||||||
|
"radius": 0.1,
|
||||||
|
"rotate": 0,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"shadow": null,
|
||||||
|
"shapeStyle": "General",
|
||||||
|
"shapeType": "rect",
|
||||||
|
"strokeColor": "--affine-palette-line-yellow",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"text": {
|
||||||
|
"affine:surface:text": true,
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "Start"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"textResizing": 1,
|
||||||
|
"xywh": "[252.60701568907035,-31.240866187007754,113.98566757331668,46.66666793823242]",
|
||||||
|
"type": "shape",
|
||||||
|
"id": "03ESqmbu0V"
|
||||||
|
},
|
||||||
|
"YQDvi-2y7O": {
|
||||||
|
"index": "aG",
|
||||||
|
"seed": 1257533881,
|
||||||
|
"color": "--affine-palette-line-black",
|
||||||
|
"fillColor": "--affine-palette-shape-yellow",
|
||||||
|
"filled": true,
|
||||||
|
"fontFamily": "blocksuite:surface:Inter",
|
||||||
|
"fontSize": 12,
|
||||||
|
"maxWidth": false,
|
||||||
|
"padding": [10, 20],
|
||||||
|
"radius": 0,
|
||||||
|
"rotate": 0,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"shadow": null,
|
||||||
|
"shapeStyle": "General",
|
||||||
|
"shapeType": "rect",
|
||||||
|
"strokeColor": "--affine-palette-line-yellow",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"text": {
|
||||||
|
"affine:surface:text": true,
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "Action"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"textResizing": 1,
|
||||||
|
"xywh": "[251.34653068910762,63.28169306573089,116.50663757324219,46.66666793823242]",
|
||||||
|
"type": "shape",
|
||||||
|
"id": "YQDvi-2y7O"
|
||||||
|
},
|
||||||
|
"d16Jq63Ef-": {
|
||||||
|
"index": "aH",
|
||||||
|
"seed": 1257533881,
|
||||||
|
"color": "--affine-palette-line-black",
|
||||||
|
"fillColor": "--affine-palette-shape-yellow",
|
||||||
|
"filled": true,
|
||||||
|
"fontFamily": "blocksuite:surface:Inter",
|
||||||
|
"fontSize": 12,
|
||||||
|
"maxWidth": false,
|
||||||
|
"padding": [10, 20],
|
||||||
|
"radius": 0,
|
||||||
|
"rotate": 0,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"shadow": null,
|
||||||
|
"shapeStyle": "General",
|
||||||
|
"shapeType": "rect",
|
||||||
|
"strokeColor": "--affine-palette-line-yellow",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"text": {
|
||||||
|
"affine:surface:text": true,
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "Action"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"textResizing": 1,
|
||||||
|
"xywh": "[480.71602985081984,63.28169306573089,116.50663757324219,46.66666793823242]",
|
||||||
|
"type": "shape",
|
||||||
|
"id": "d16Jq63Ef-"
|
||||||
|
},
|
||||||
|
"pFUd4r8HSb": {
|
||||||
|
"index": "aI",
|
||||||
|
"seed": 666256980,
|
||||||
|
"color": "--affine-palette-line-black",
|
||||||
|
"fillColor": "--affine-palette-shape-yellow",
|
||||||
|
"filled": true,
|
||||||
|
"fontFamily": "blocksuite:surface:Inter",
|
||||||
|
"fontSize": 12,
|
||||||
|
"maxWidth": false,
|
||||||
|
"padding": [10, 20],
|
||||||
|
"radius": 0,
|
||||||
|
"rotate": 0,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"shadow": null,
|
||||||
|
"shapeStyle": "General",
|
||||||
|
"shapeType": "diamond",
|
||||||
|
"strokeColor": "--affine-palette-line-yellow",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"text": {
|
||||||
|
"affine:surface:text": true,
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "Yes/No"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"textResizing": 1,
|
||||||
|
"xywh": "[259.6798856390588,158.60141743948986,99.83992767333984,100]",
|
||||||
|
"type": "shape",
|
||||||
|
"id": "pFUd4r8HSb"
|
||||||
|
},
|
||||||
|
"WC0DtV40eR": {
|
||||||
|
"index": "aJ",
|
||||||
|
"seed": 1257533881,
|
||||||
|
"color": "--affine-palette-line-black",
|
||||||
|
"fillColor": "--affine-palette-shape-yellow",
|
||||||
|
"filled": true,
|
||||||
|
"fontFamily": "blocksuite:surface:Inter",
|
||||||
|
"fontSize": 12,
|
||||||
|
"maxWidth": false,
|
||||||
|
"padding": [10, 20],
|
||||||
|
"radius": 0,
|
||||||
|
"rotate": 0,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"shadow": null,
|
||||||
|
"shapeStyle": "General",
|
||||||
|
"shapeType": "rect",
|
||||||
|
"strokeColor": "--affine-palette-line-yellow",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"text": {
|
||||||
|
"affine:surface:text": true,
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "Action"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"textResizing": 1,
|
||||||
|
"xywh": "[251.3465118415371,306.9211418132488,116.50663757324219,47]",
|
||||||
|
"type": "shape",
|
||||||
|
"id": "WC0DtV40eR"
|
||||||
|
},
|
||||||
|
"L8IRBW8JgC": {
|
||||||
|
"index": "aK",
|
||||||
|
"seed": 456881005,
|
||||||
|
"color": "--affine-palette-line-black",
|
||||||
|
"fillColor": "--affine-palette-shape-yellow",
|
||||||
|
"filled": true,
|
||||||
|
"fontFamily": "blocksuite:surface:Inter",
|
||||||
|
"fontSize": 12,
|
||||||
|
"maxWidth": false,
|
||||||
|
"padding": [10, 20],
|
||||||
|
"radius": 0.1,
|
||||||
|
"rotate": 0,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"shadow": null,
|
||||||
|
"shapeStyle": "General",
|
||||||
|
"shapeType": "rect",
|
||||||
|
"strokeColor": "--affine-palette-line-yellow",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"text": {
|
||||||
|
"affine:surface:text": true,
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "End"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"textResizing": 1,
|
||||||
|
"xywh": "[251.21161577561134,402.2408661870077,116.77642970509373,47]",
|
||||||
|
"type": "shape",
|
||||||
|
"id": "L8IRBW8JgC"
|
||||||
|
},
|
||||||
|
"jnVx3KzCLh": {
|
||||||
|
"index": "aR",
|
||||||
|
"seed": 914130882,
|
||||||
|
"color": "--affine-palette-line-black",
|
||||||
|
"fillColor": "--affine-palette-shape-yellow",
|
||||||
|
"filled": true,
|
||||||
|
"fontFamily": "blocksuite:surface:Inter",
|
||||||
|
"fontSize": 16,
|
||||||
|
"maxWidth": false,
|
||||||
|
"padding": [10, 20],
|
||||||
|
"radius": 0,
|
||||||
|
"rotate": 0,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"shadow": null,
|
||||||
|
"shapeStyle": "General",
|
||||||
|
"shapeType": "triangle",
|
||||||
|
"strokeColor": "--affine-palette-line-yellow",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"textResizing": 1,
|
||||||
|
"xywh": "[16.110706599375533,93.96971522611781,99.95313668402997,80.60737422459296]",
|
||||||
|
"type": "shape",
|
||||||
|
"id": "jnVx3KzCLh"
|
||||||
|
},
|
||||||
|
"hXY08VN1b_": {
|
||||||
|
"index": "aS",
|
||||||
|
"seed": 1037406953,
|
||||||
|
"color": "--affine-palette-line-black",
|
||||||
|
"fillColor": "--affine-palette-shape-yellow",
|
||||||
|
"filled": true,
|
||||||
|
"fontFamily": "blocksuite:surface:Inter",
|
||||||
|
"fontSize": 16,
|
||||||
|
"maxWidth": false,
|
||||||
|
"padding": [10, 20],
|
||||||
|
"radius": 0,
|
||||||
|
"rotate": 0,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"shadow": null,
|
||||||
|
"shapeStyle": "General",
|
||||||
|
"shapeType": "ellipse",
|
||||||
|
"strokeColor": "--affine-palette-line-yellow",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"textResizing": 1,
|
||||||
|
"xywh": "[16.110706599375547,226.48127342070092,97.3493072661882,97.90333942510793]",
|
||||||
|
"type": "shape",
|
||||||
|
"id": "hXY08VN1b_"
|
||||||
|
},
|
||||||
|
"-aHPKrKHll": {
|
||||||
|
"index": "aL",
|
||||||
|
"seed": 1201328314,
|
||||||
|
"frontEndpointStyle": "None",
|
||||||
|
"mode": 1,
|
||||||
|
"rearEndpointStyle": "Arrow",
|
||||||
|
"rough": false,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"source": {
|
||||||
|
"id": "03ESqmbu0V",
|
||||||
|
"position": [0.5, 1]
|
||||||
|
},
|
||||||
|
"stroke": "--affine-palette-line-grey",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"target": {
|
||||||
|
"id": "YQDvi-2y7O",
|
||||||
|
"position": [0.5, 0]
|
||||||
|
},
|
||||||
|
"type": "connector",
|
||||||
|
"id": "-aHPKrKHll"
|
||||||
|
},
|
||||||
|
"9nFcoL2dRX": {
|
||||||
|
"index": "aM",
|
||||||
|
"seed": 1062067961,
|
||||||
|
"frontEndpointStyle": "None",
|
||||||
|
"mode": 1,
|
||||||
|
"rearEndpointStyle": "Arrow",
|
||||||
|
"rough": false,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"source": {
|
||||||
|
"id": "YQDvi-2y7O",
|
||||||
|
"position": [1, 0.5]
|
||||||
|
},
|
||||||
|
"stroke": "--affine-palette-line-grey",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"target": {
|
||||||
|
"id": "d16Jq63Ef-",
|
||||||
|
"position": [0, 0.49997133993897247]
|
||||||
|
},
|
||||||
|
"type": "connector",
|
||||||
|
"id": "9nFcoL2dRX"
|
||||||
|
},
|
||||||
|
"j4pebF9wC1": {
|
||||||
|
"index": "aN",
|
||||||
|
"seed": 970063880,
|
||||||
|
"frontEndpointStyle": "Arrow",
|
||||||
|
"mode": 1,
|
||||||
|
"rearEndpointStyle": "None",
|
||||||
|
"rough": false,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"source": {
|
||||||
|
"id": "d16Jq63Ef-",
|
||||||
|
"position": [0.5, 1]
|
||||||
|
},
|
||||||
|
"stroke": "--affine-palette-line-grey",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"target": {
|
||||||
|
"id": "pFUd4r8HSb",
|
||||||
|
"position": [1, 0.5]
|
||||||
|
},
|
||||||
|
"type": "connector",
|
||||||
|
"id": "j4pebF9wC1"
|
||||||
|
},
|
||||||
|
"WUp1wz3qjl": {
|
||||||
|
"index": "aO",
|
||||||
|
"seed": 628182641,
|
||||||
|
"frontEndpointStyle": "None",
|
||||||
|
"mode": 1,
|
||||||
|
"rearEndpointStyle": "Arrow",
|
||||||
|
"rough": false,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"source": {
|
||||||
|
"id": "YQDvi-2y7O",
|
||||||
|
"position": [0.5, 1]
|
||||||
|
},
|
||||||
|
"stroke": "--affine-palette-line-grey",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"target": {
|
||||||
|
"id": "pFUd4r8HSb",
|
||||||
|
"position": [0.5, 0]
|
||||||
|
},
|
||||||
|
"type": "connector",
|
||||||
|
"id": "WUp1wz3qjl"
|
||||||
|
},
|
||||||
|
"LW-DOsZkzx": {
|
||||||
|
"index": "aP",
|
||||||
|
"seed": 1308365768,
|
||||||
|
"frontEndpointStyle": "None",
|
||||||
|
"mode": 1,
|
||||||
|
"rearEndpointStyle": "Arrow",
|
||||||
|
"rough": false,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"source": {
|
||||||
|
"id": "pFUd4r8HSb",
|
||||||
|
"position": [0.5, 1]
|
||||||
|
},
|
||||||
|
"stroke": "--affine-palette-line-grey",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"target": {
|
||||||
|
"id": "WC0DtV40eR",
|
||||||
|
"position": [0.5, 0]
|
||||||
|
},
|
||||||
|
"type": "connector",
|
||||||
|
"id": "LW-DOsZkzx"
|
||||||
|
},
|
||||||
|
"iFv5piS4UF": {
|
||||||
|
"index": "aQ",
|
||||||
|
"seed": 782147341,
|
||||||
|
"frontEndpointStyle": "None",
|
||||||
|
"mode": 1,
|
||||||
|
"rearEndpointStyle": "Arrow",
|
||||||
|
"rough": false,
|
||||||
|
"roughness": 1.4,
|
||||||
|
"source": {
|
||||||
|
"id": "WC0DtV40eR",
|
||||||
|
"position": [0.5, 1]
|
||||||
|
},
|
||||||
|
"stroke": "--affine-palette-line-grey",
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"target": {
|
||||||
|
"id": "L8IRBW8JgC",
|
||||||
|
"position": [0.5, 0]
|
||||||
|
},
|
||||||
|
"type": "connector",
|
||||||
|
"id": "iFv5piS4UF"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"id": "LHrmmlDo4Q",
|
||||||
|
"flavour": "affine:edgeless-text",
|
||||||
|
"version": 1,
|
||||||
|
"props": {
|
||||||
|
"xywh": "[30.80080405395168,20.987504771361614,71.2421875,56]",
|
||||||
|
"index": "aE",
|
||||||
|
"color": "--affine-palette-line-black",
|
||||||
|
"fontFamily": "blocksuite:surface:Inter",
|
||||||
|
"fontStyle": "normal",
|
||||||
|
"fontWeight": "400",
|
||||||
|
"textAlign": "left",
|
||||||
|
"scale": 1,
|
||||||
|
"rotate": 0,
|
||||||
|
"hasMaxWidth": false
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"id": "qc2TtDkPRq",
|
||||||
|
"flavour": "affine:paragraph",
|
||||||
|
"version": 1,
|
||||||
|
"props": {
|
||||||
|
"type": "text",
|
||||||
|
"text": {
|
||||||
|
"$blocksuite:internal:text$": true,
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "Others"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"id": "cmuL9JhfVH",
|
||||||
|
"flavour": "affine:frame",
|
||||||
|
"version": 1,
|
||||||
|
"props": {
|
||||||
|
"title": {
|
||||||
|
"$blocksuite:internal:text$": true,
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "Frame 1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"background": "--affine-palette-transparent",
|
||||||
|
"xywh": "[-131.27862548828125,-112.8125,880.65234375,645.11328125]",
|
||||||
|
"index": "aEV",
|
||||||
|
"childElementIds": {}
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ export type DocName =
|
|||||||
| 'note'
|
| 'note'
|
||||||
| 'pen'
|
| 'pen'
|
||||||
| 'shape'
|
| 'shape'
|
||||||
|
| 'flow'
|
||||||
| 'text'
|
| 'text'
|
||||||
| 'connector'
|
| 'connector'
|
||||||
| 'mindmap';
|
| 'mindmap';
|
||||||
@@ -31,6 +32,7 @@ export async function getDocByName(name: DocName) {
|
|||||||
note: (await import('./note.json')).default,
|
note: (await import('./note.json')).default,
|
||||||
pen: (await import('./pen.json')).default,
|
pen: (await import('./pen.json')).default,
|
||||||
shape: (await import('./shape.json')).default,
|
shape: (await import('./shape.json')).default,
|
||||||
|
flow: (await import('./flow.json')).default,
|
||||||
text: (await import('./text.json')).default,
|
text: (await import('./text.json')).default,
|
||||||
connector: (await import('./connector.json')).default,
|
connector: (await import('./connector.json')).default,
|
||||||
mindmap: (await import('./mindmap.json')).default,
|
mindmap: (await import('./mindmap.json')).default,
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ import {
|
|||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { SettingRow } from '@affine/component/setting-components';
|
import { SettingRow } from '@affine/component/setting-components';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useMemo, useState } from 'react';
|
import type { Doc } from '@blocksuite/store';
|
||||||
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { DropdownMenu } from '../menu';
|
import { DropdownMenu } from '../menu';
|
||||||
import { menuTrigger, settingWrapper } from '../style.css';
|
import { menuTrigger, settingWrapper } from '../style.css';
|
||||||
import { EdgelessSnapshot } from './snapshot';
|
import { EdgelessSnapshot } from './snapshot';
|
||||||
|
import { getSurfaceBlock } from './utils';
|
||||||
|
|
||||||
export const MindMapSettings = () => {
|
export const MindMapSettings = () => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
@@ -43,13 +45,19 @@ export const MindMapSettings = () => {
|
|||||||
],
|
],
|
||||||
[t]
|
[t]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getElements = useCallback((doc: Doc) => {
|
||||||
|
const surface = getSurfaceBlock(doc);
|
||||||
|
return surface?.getElementsByType('mindmap') || [];
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EdgelessSnapshot
|
<EdgelessSnapshot
|
||||||
title={t['com.affine.settings.editorSettings.edgeless.mind-map']()}
|
title={t['com.affine.settings.editorSettings.edgeless.mind-map']()}
|
||||||
docName="mindmap"
|
docName="mindmap"
|
||||||
keyName={'mindmap' as any}
|
keyName={'mindmap' as any}
|
||||||
flavour="mindmap"
|
getElements={getElements}
|
||||||
height={320}
|
height={320}
|
||||||
/>
|
/>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
NoteShadowMap,
|
NoteShadowMap,
|
||||||
StrokeStyle,
|
StrokeStyle,
|
||||||
} from '@blocksuite/blocks';
|
} from '@blocksuite/blocks';
|
||||||
|
import type { Doc } from '@blocksuite/store';
|
||||||
import { useFramework, useLiveData } from '@toeverything/infra';
|
import { useFramework, useLiveData } from '@toeverything/infra';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
@@ -166,13 +167,17 @@ export const NoteSettings = () => {
|
|||||||
return getColorFromMap(background, NoteBackgroundColorMap);
|
return getColorFromMap(background, NoteBackgroundColorMap);
|
||||||
}, [getColorFromMap, settings]);
|
}, [getColorFromMap, settings]);
|
||||||
|
|
||||||
|
const getElements = useCallback((doc: Doc) => {
|
||||||
|
return doc.getBlocksByFlavour('affine:note') || [];
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EdgelessSnapshot
|
<EdgelessSnapshot
|
||||||
title={t['com.affine.settings.editorSettings.edgeless.note']()}
|
title={t['com.affine.settings.editorSettings.edgeless.note']()}
|
||||||
docName="note"
|
docName="note"
|
||||||
keyName="affine:note"
|
keyName="affine:note"
|
||||||
flavour="affine:note"
|
getElements={getElements}
|
||||||
/>
|
/>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
name={t[
|
name={t[
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { SettingRow } from '@affine/component/setting-components';
|
|||||||
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { LineColor, LineColorMap } from '@blocksuite/blocks';
|
import { LineColor, LineColorMap } from '@blocksuite/blocks';
|
||||||
|
import type { Doc } from '@blocksuite/store';
|
||||||
import { useFramework, useLiveData } from '@toeverything/infra';
|
import { useFramework, useLiveData } from '@toeverything/infra';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
@@ -11,6 +12,7 @@ import { menuTrigger } from '../style.css';
|
|||||||
import { useColor } from '../utils';
|
import { useColor } from '../utils';
|
||||||
import { Point } from './point';
|
import { Point } from './point';
|
||||||
import { EdgelessSnapshot } from './snapshot';
|
import { EdgelessSnapshot } from './snapshot';
|
||||||
|
import { getSurfaceBlock } from './utils';
|
||||||
|
|
||||||
export const PenSettings = () => {
|
export const PenSettings = () => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
@@ -52,13 +54,19 @@ export const PenSettings = () => {
|
|||||||
},
|
},
|
||||||
[editorSetting]
|
[editorSetting]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getElements = useCallback((doc: Doc) => {
|
||||||
|
const surface = getSurfaceBlock(doc);
|
||||||
|
return surface?.getElementsByType('brush') || [];
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EdgelessSnapshot
|
<EdgelessSnapshot
|
||||||
title={t['com.affine.settings.editorSettings.edgeless.pen']()}
|
title={t['com.affine.settings.editorSettings.edgeless.pen']()}
|
||||||
docName="pen"
|
docName="pen"
|
||||||
keyName="brush"
|
keyName="brush"
|
||||||
flavour="brush"
|
getElements={getElements}
|
||||||
/>
|
/>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
name={t['com.affine.settings.editorSettings.edgeless.pen.color']()}
|
name={t['com.affine.settings.editorSettings.edgeless.pen.color']()}
|
||||||
|
|||||||
@@ -6,42 +6,68 @@ import {
|
|||||||
Slider,
|
Slider,
|
||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { SettingRow } from '@affine/component/setting-components';
|
import { SettingRow } from '@affine/component/setting-components';
|
||||||
|
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useMemo, useState } from 'react';
|
import type { EditorHost } from '@blocksuite/block-std';
|
||||||
|
import type {
|
||||||
|
EdgelessRootService,
|
||||||
|
ShapeElementModel,
|
||||||
|
ShapeName,
|
||||||
|
} from '@blocksuite/blocks';
|
||||||
|
import {
|
||||||
|
createEnumMap,
|
||||||
|
FontFamily,
|
||||||
|
FontFamilyMap,
|
||||||
|
FontStyle,
|
||||||
|
FontWeight,
|
||||||
|
FontWeightMap,
|
||||||
|
getShapeName,
|
||||||
|
LineColor,
|
||||||
|
LineColorMap,
|
||||||
|
ShapeFillColor,
|
||||||
|
ShapeStyle,
|
||||||
|
ShapeType,
|
||||||
|
StrokeStyle,
|
||||||
|
TextAlign,
|
||||||
|
} from '@blocksuite/blocks';
|
||||||
|
import type { Doc } from '@blocksuite/store';
|
||||||
|
import { useFramework, useLiveData } from '@toeverything/infra';
|
||||||
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { DropdownMenu } from '../menu';
|
import { DropdownMenu } from '../menu';
|
||||||
import { menuTrigger, settingWrapper, shapeIndicator } from '../style.css';
|
import { menuTrigger, settingWrapper, shapeIndicator } from '../style.css';
|
||||||
|
import { useColor } from '../utils';
|
||||||
|
import type { DocName } from './docs';
|
||||||
|
import { Point } from './point';
|
||||||
import { EdgelessSnapshot } from './snapshot';
|
import { EdgelessSnapshot } from './snapshot';
|
||||||
|
import { getSurfaceBlock } from './utils';
|
||||||
|
|
||||||
type Shape =
|
enum ShapeTextFontSize {
|
||||||
| 'square'
|
'12px' = '12',
|
||||||
| 'ellipse'
|
'20px' = '20',
|
||||||
| 'diamond'
|
'28px' = '28',
|
||||||
| 'triangle'
|
'36px' = '36',
|
||||||
| 'rounded-rectangle';
|
}
|
||||||
|
|
||||||
|
const ShapeFillColorMap = createEnumMap(ShapeFillColor);
|
||||||
|
|
||||||
export const ShapeSettings = () => {
|
export const ShapeSettings = () => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const [currentShape, setCurrentShape] = useState<Shape>('square');
|
const framework = useFramework();
|
||||||
const [shapeStyle, setShapeStyle] = useState<'general' | 'scribbled'>(
|
const { editorSetting } = framework.get(EditorSettingService);
|
||||||
'general'
|
const settings = useLiveData(editorSetting.settings$);
|
||||||
);
|
const getColorFromMap = useColor();
|
||||||
const [borderStyle, setBorderStyle] = useState<'solid' | 'dash' | 'none'>(
|
|
||||||
'solid'
|
const [currentShape, setCurrentShape] = useState<ShapeName>(ShapeType.Rect);
|
||||||
);
|
|
||||||
const [borderThickness, setBorderThickness] = useState<number[]>([3]);
|
|
||||||
const [textAlignment, setTextAlignment] = useState<
|
|
||||||
'left' | 'center' | 'right'
|
|
||||||
>('left');
|
|
||||||
|
|
||||||
const shapeStyleItems = useMemo<RadioItem[]>(
|
const shapeStyleItems = useMemo<RadioItem[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
value: 'general',
|
value: ShapeStyle.General,
|
||||||
label: t['com.affine.settings.editorSettings.edgeless.style.general'](),
|
label: t['com.affine.settings.editorSettings.edgeless.style.general'](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'scribbled',
|
value: ShapeStyle.Scribbled,
|
||||||
label:
|
label:
|
||||||
t['com.affine.settings.editorSettings.edgeless.style.scribbled'](),
|
t['com.affine.settings.editorSettings.edgeless.style.scribbled'](),
|
||||||
},
|
},
|
||||||
@@ -49,20 +75,30 @@ export const ShapeSettings = () => {
|
|||||||
[t]
|
[t]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { shapeStyle } = settings[`shape:${currentShape}`];
|
||||||
|
const setShapeStyle = useCallback(
|
||||||
|
(value: ShapeStyle) => {
|
||||||
|
editorSetting.set(`shape:${currentShape}`, {
|
||||||
|
shapeStyle: value,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[editorSetting, currentShape]
|
||||||
|
);
|
||||||
|
|
||||||
const borderStyleItems = useMemo<RadioItem[]>(
|
const borderStyleItems = useMemo<RadioItem[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
value: 'solid',
|
value: StrokeStyle.Solid,
|
||||||
label:
|
label:
|
||||||
t['com.affine.settings.editorSettings.edgeless.note.border.solid'](),
|
t['com.affine.settings.editorSettings.edgeless.note.border.solid'](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'dash',
|
value: StrokeStyle.Dash,
|
||||||
label:
|
label:
|
||||||
t['com.affine.settings.editorSettings.edgeless.note.border.dash'](),
|
t['com.affine.settings.editorSettings.edgeless.note.border.dash'](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'none',
|
value: StrokeStyle.None,
|
||||||
label:
|
label:
|
||||||
t['com.affine.settings.editorSettings.edgeless.note.border.none'](),
|
t['com.affine.settings.editorSettings.edgeless.note.border.none'](),
|
||||||
},
|
},
|
||||||
@@ -70,24 +106,34 @@ export const ShapeSettings = () => {
|
|||||||
[t]
|
[t]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const borderStyle = settings[`shape:${currentShape}`].strokeStyle;
|
||||||
|
const setBorderStyle = useCallback(
|
||||||
|
(value: StrokeStyle) => {
|
||||||
|
editorSetting.set(`shape:${currentShape}`, {
|
||||||
|
strokeStyle: value,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[editorSetting, currentShape]
|
||||||
|
);
|
||||||
|
|
||||||
const alignItems = useMemo<RadioItem[]>(
|
const alignItems = useMemo<RadioItem[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
value: 'left',
|
value: TextAlign.Left,
|
||||||
label:
|
label:
|
||||||
t[
|
t[
|
||||||
'com.affine.settings.editorSettings.edgeless.text.alignment.left'
|
'com.affine.settings.editorSettings.edgeless.text.alignment.left'
|
||||||
](),
|
](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'center',
|
value: TextAlign.Center,
|
||||||
label:
|
label:
|
||||||
t[
|
t[
|
||||||
'com.affine.settings.editorSettings.edgeless.text.alignment.center'
|
'com.affine.settings.editorSettings.edgeless.text.alignment.center'
|
||||||
](),
|
](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'right',
|
value: TextAlign.Right,
|
||||||
label:
|
label:
|
||||||
t[
|
t[
|
||||||
'com.affine.settings.editorSettings.edgeless.text.alignment.right'
|
'com.affine.settings.editorSettings.edgeless.text.alignment.right'
|
||||||
@@ -97,27 +143,37 @@ export const ShapeSettings = () => {
|
|||||||
[t]
|
[t]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const textAlignment = settings[`shape:${currentShape}`].textAlign;
|
||||||
|
const setTextAlignment = useCallback(
|
||||||
|
(value: TextAlign) => {
|
||||||
|
editorSetting.set(`shape:${currentShape}`, {
|
||||||
|
textAlign: value,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[editorSetting, currentShape]
|
||||||
|
);
|
||||||
|
|
||||||
const shapes = useMemo<RadioItem[]>(
|
const shapes = useMemo<RadioItem[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
value: 'square',
|
value: ShapeType.Rect,
|
||||||
label: t['com.affine.settings.editorSettings.edgeless.shape.square'](),
|
label: t['com.affine.settings.editorSettings.edgeless.shape.square'](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'ellipse',
|
value: ShapeType.Ellipse,
|
||||||
label: t['com.affine.settings.editorSettings.edgeless.shape.ellipse'](),
|
label: t['com.affine.settings.editorSettings.edgeless.shape.ellipse'](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'diamond',
|
value: ShapeType.Diamond,
|
||||||
label: t['com.affine.settings.editorSettings.edgeless.shape.diamond'](),
|
label: t['com.affine.settings.editorSettings.edgeless.shape.diamond'](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'triangle',
|
value: ShapeType.Triangle,
|
||||||
label:
|
label:
|
||||||
t['com.affine.settings.editorSettings.edgeless.shape.triangle'](),
|
t['com.affine.settings.editorSettings.edgeless.shape.triangle'](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'rounded-rectangle',
|
value: 'roundedRect',
|
||||||
label:
|
label:
|
||||||
t[
|
t[
|
||||||
'com.affine.settings.editorSettings.edgeless.shape.rounded-rectangle'
|
'com.affine.settings.editorSettings.edgeless.shape.rounded-rectangle'
|
||||||
@@ -127,14 +183,212 @@ export const ShapeSettings = () => {
|
|||||||
[t]
|
[t]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const docs = useMemo<RadioItem[]>(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
value: 'shape',
|
||||||
|
label: t['com.affine.settings.editorSettings.edgeless.shape.list'](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'flow',
|
||||||
|
label: t['com.affine.settings.editorSettings.edgeless.shape.flow'](),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[t]
|
||||||
|
);
|
||||||
|
const [currentDoc, setCurrentDoc] = useState<DocName>('shape');
|
||||||
|
|
||||||
|
const fillColorItems = useMemo(() => {
|
||||||
|
const { fillColor } = settings[`shape:${currentShape}`];
|
||||||
|
return Object.entries(ShapeFillColor).map(([name, value]) => {
|
||||||
|
const handler = () => {
|
||||||
|
editorSetting.set(`shape:${currentShape}`, { fillColor: value });
|
||||||
|
};
|
||||||
|
const isSelected = fillColor === value;
|
||||||
|
return (
|
||||||
|
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||||
|
{name}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, [editorSetting, settings, currentShape]);
|
||||||
|
|
||||||
|
const borderColorItems = useMemo(() => {
|
||||||
|
const { strokeColor } = settings[`shape:${currentShape}`];
|
||||||
|
return Object.entries(LineColor).map(([name, value]) => {
|
||||||
|
const handler = () => {
|
||||||
|
editorSetting.set(`shape:${currentShape}`, { strokeColor: value });
|
||||||
|
};
|
||||||
|
const isSelected = strokeColor === value;
|
||||||
|
return (
|
||||||
|
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||||
|
{name}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, [editorSetting, settings, currentShape]);
|
||||||
|
|
||||||
|
const borderThickness = settings[`shape:${currentShape}`].strokeWidth;
|
||||||
|
const setBorderThickness = useCallback(
|
||||||
|
(value: number[]) => {
|
||||||
|
editorSetting.set(`shape:${currentShape}`, {
|
||||||
|
strokeWidth: value[0],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[editorSetting, currentShape]
|
||||||
|
);
|
||||||
|
|
||||||
|
const fontFamilyItems = useMemo(() => {
|
||||||
|
const { fontFamily } = settings[`shape:${currentShape}`];
|
||||||
|
return Object.entries(FontFamily).map(([name, value]) => {
|
||||||
|
const handler = () => {
|
||||||
|
editorSetting.set(`shape:${currentShape}`, { fontFamily: value });
|
||||||
|
};
|
||||||
|
const isSelected = fontFamily === value;
|
||||||
|
return (
|
||||||
|
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||||
|
{name}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, [editorSetting, settings, currentShape]);
|
||||||
|
|
||||||
|
const fontStyleItems = useMemo(() => {
|
||||||
|
const { fontStyle } = settings[`shape:${currentShape}`];
|
||||||
|
return Object.entries(FontStyle).map(([name, value]) => {
|
||||||
|
const handler = () => {
|
||||||
|
editorSetting.set(`shape:${currentShape}`, { fontStyle: value });
|
||||||
|
};
|
||||||
|
const isSelected = fontStyle === value;
|
||||||
|
return (
|
||||||
|
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||||
|
{name}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, [editorSetting, settings, currentShape]);
|
||||||
|
|
||||||
|
const fontWeightItems = useMemo(() => {
|
||||||
|
const { fontWeight } = settings[`shape:${currentShape}`];
|
||||||
|
return Object.entries(FontWeight).map(([name, value]) => {
|
||||||
|
const handler = () => {
|
||||||
|
editorSetting.set(`shape:${currentShape}`, { fontWeight: value });
|
||||||
|
};
|
||||||
|
const isSelected = fontWeight === value;
|
||||||
|
return (
|
||||||
|
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||||
|
{name}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, [editorSetting, settings, currentShape]);
|
||||||
|
|
||||||
|
const fontSizeItems = useMemo(() => {
|
||||||
|
const { fontSize } = settings[`shape:${currentShape}`];
|
||||||
|
return Object.entries(ShapeTextFontSize).map(([name, value]) => {
|
||||||
|
const handler = () => {
|
||||||
|
editorSetting.set(`shape:${currentShape}`, { fontSize: Number(value) });
|
||||||
|
};
|
||||||
|
const isSelected = fontSize === Number(value);
|
||||||
|
return (
|
||||||
|
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||||
|
{name}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, [editorSetting, settings, currentShape]);
|
||||||
|
|
||||||
|
const textColorItems = useMemo(() => {
|
||||||
|
const { color } = settings[`shape:${currentShape}`];
|
||||||
|
return Object.entries(LineColor).map(([name, value]) => {
|
||||||
|
const handler = () => {
|
||||||
|
editorSetting.set(`shape:${currentShape}`, { color: value });
|
||||||
|
};
|
||||||
|
const isSelected = color === value;
|
||||||
|
return (
|
||||||
|
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||||
|
{name}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, [editorSetting, settings, currentShape]);
|
||||||
|
|
||||||
|
const getElements = useCallback(
|
||||||
|
(doc: Doc) => {
|
||||||
|
const surface = getSurfaceBlock(doc);
|
||||||
|
if (!surface) return [];
|
||||||
|
return surface.getElementsByType('shape').filter(node => {
|
||||||
|
const shape = node as ShapeElementModel;
|
||||||
|
const { shapeType, radius } = shape;
|
||||||
|
const shapeName = getShapeName(shapeType, radius);
|
||||||
|
return shapeName === currentShape;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[currentShape]
|
||||||
|
);
|
||||||
|
|
||||||
|
const firstUpdate = useCallback(
|
||||||
|
(doc: Doc, editorHost: EditorHost) => {
|
||||||
|
const edgelessService = editorHost.std.getService(
|
||||||
|
'affine:page'
|
||||||
|
) as EdgelessRootService;
|
||||||
|
const surface = getSurfaceBlock(doc);
|
||||||
|
if (!surface) return;
|
||||||
|
surface.getElementsByType('shape').forEach(node => {
|
||||||
|
const shape = node as ShapeElementModel;
|
||||||
|
const { shapeType, radius } = shape;
|
||||||
|
const shapeName = getShapeName(shapeType, radius);
|
||||||
|
const props = editorSetting.get(`shape:${shapeName}`);
|
||||||
|
edgelessService.updateElement(shape.id, props);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[editorSetting]
|
||||||
|
);
|
||||||
|
|
||||||
|
const fillColor = useMemo(() => {
|
||||||
|
const color = settings[`shape:${currentShape}`].fillColor;
|
||||||
|
return getColorFromMap(color, ShapeFillColorMap);
|
||||||
|
}, [currentShape, getColorFromMap, settings]);
|
||||||
|
|
||||||
|
const borderColor = useMemo(() => {
|
||||||
|
const color = settings[`shape:${currentShape}`].strokeColor;
|
||||||
|
return getColorFromMap(color, LineColorMap);
|
||||||
|
}, [currentShape, getColorFromMap, settings]);
|
||||||
|
|
||||||
|
const textColor = useMemo(() => {
|
||||||
|
const color = settings[`shape:${currentShape}`].color;
|
||||||
|
return getColorFromMap(color, LineColorMap);
|
||||||
|
}, [currentShape, getColorFromMap, settings]);
|
||||||
|
|
||||||
|
const height = currentDoc === 'flow' ? 456 : 180;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EdgelessSnapshot
|
<EdgelessSnapshot
|
||||||
|
key={currentDoc}
|
||||||
title={t['com.affine.settings.editorSettings.edgeless.shape']()}
|
title={t['com.affine.settings.editorSettings.edgeless.shape']()}
|
||||||
docName="shape"
|
docName={currentDoc}
|
||||||
keyName="shape"
|
keyName={`shape:${currentShape}`}
|
||||||
flavour="shape"
|
height={height}
|
||||||
/>
|
getElements={getElements}
|
||||||
|
firstUpdate={firstUpdate}
|
||||||
|
>
|
||||||
|
<RadioGroup
|
||||||
|
padding={0}
|
||||||
|
gap={4}
|
||||||
|
itemHeight={28}
|
||||||
|
borderRadius={8}
|
||||||
|
value={currentDoc}
|
||||||
|
items={docs}
|
||||||
|
onChange={setCurrentDoc}
|
||||||
|
style={{
|
||||||
|
background: 'transparent',
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
}}
|
||||||
|
indicatorClassName={shapeIndicator}
|
||||||
|
/>
|
||||||
|
</EdgelessSnapshot>
|
||||||
|
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
padding={0}
|
padding={0}
|
||||||
@@ -165,14 +419,19 @@ export const ShapeSettings = () => {
|
|||||||
]()}
|
]()}
|
||||||
desc={''}
|
desc={''}
|
||||||
>
|
>
|
||||||
<DropdownMenu
|
{fillColor ? (
|
||||||
items={<MenuItem>Yellow</MenuItem>}
|
<DropdownMenu
|
||||||
trigger={
|
items={fillColorItems}
|
||||||
<MenuTrigger className={menuTrigger} disabled>
|
trigger={
|
||||||
Yellow
|
<MenuTrigger
|
||||||
</MenuTrigger>
|
className={menuTrigger}
|
||||||
}
|
prefix={<Point color={fillColor.value} />}
|
||||||
/>
|
>
|
||||||
|
{fillColor.key}
|
||||||
|
</MenuTrigger>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
name={t[
|
name={t[
|
||||||
@@ -180,14 +439,19 @@ export const ShapeSettings = () => {
|
|||||||
]()}
|
]()}
|
||||||
desc={''}
|
desc={''}
|
||||||
>
|
>
|
||||||
<DropdownMenu
|
{borderColor ? (
|
||||||
items={<MenuItem>Yellow</MenuItem>}
|
<DropdownMenu
|
||||||
trigger={
|
items={borderColorItems}
|
||||||
<MenuTrigger className={menuTrigger} disabled>
|
trigger={
|
||||||
Yellow
|
<MenuTrigger
|
||||||
</MenuTrigger>
|
className={menuTrigger}
|
||||||
}
|
prefix={<Point color={borderColor.value} />}
|
||||||
/>
|
>
|
||||||
|
{borderColor.key}
|
||||||
|
</MenuTrigger>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
name={t[
|
name={t[
|
||||||
@@ -210,12 +474,12 @@ export const ShapeSettings = () => {
|
|||||||
desc={''}
|
desc={''}
|
||||||
>
|
>
|
||||||
<Slider
|
<Slider
|
||||||
value={borderThickness}
|
value={[borderThickness]}
|
||||||
onValueChange={setBorderThickness}
|
onValueChange={setBorderThickness}
|
||||||
min={1}
|
min={2}
|
||||||
max={5}
|
max={12}
|
||||||
step={1}
|
step={2}
|
||||||
nodes={[1, 2, 3, 4, 5]}
|
nodes={[2, 4, 6, 8, 10, 12]}
|
||||||
/>
|
/>
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
@@ -224,25 +488,31 @@ export const ShapeSettings = () => {
|
|||||||
]()}
|
]()}
|
||||||
desc={''}
|
desc={''}
|
||||||
>
|
>
|
||||||
<DropdownMenu
|
{textColor ? (
|
||||||
items={<MenuItem>Yellow</MenuItem>}
|
<DropdownMenu
|
||||||
trigger={
|
items={textColorItems}
|
||||||
<MenuTrigger className={menuTrigger} disabled>
|
trigger={
|
||||||
Yellow
|
<MenuTrigger
|
||||||
</MenuTrigger>
|
className={menuTrigger}
|
||||||
}
|
prefix={<Point color={textColor.value} />}
|
||||||
/>
|
>
|
||||||
|
{textColor.key}
|
||||||
|
</MenuTrigger>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
name={t['com.affine.settings.editorSettings.edgeless.shape.font']()}
|
name={t[
|
||||||
|
'com.affine.settings.editorSettings.edgeless.text.font-family'
|
||||||
|
]()}
|
||||||
desc={''}
|
desc={''}
|
||||||
>
|
>
|
||||||
{' '}
|
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
items={<MenuItem>Inter</MenuItem>}
|
items={fontFamilyItems}
|
||||||
trigger={
|
trigger={
|
||||||
<MenuTrigger className={menuTrigger} disabled>
|
<MenuTrigger className={menuTrigger}>
|
||||||
Inter
|
{FontFamilyMap[settings[`shape:${currentShape}`].fontFamily]}
|
||||||
</MenuTrigger>
|
</MenuTrigger>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -254,25 +524,40 @@ export const ShapeSettings = () => {
|
|||||||
desc={''}
|
desc={''}
|
||||||
>
|
>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
items={<MenuItem>15px</MenuItem>}
|
items={fontSizeItems}
|
||||||
trigger={
|
trigger={
|
||||||
<MenuTrigger className={menuTrigger} disabled>
|
<MenuTrigger className={menuTrigger}>
|
||||||
15px
|
{settings[`shape:${currentShape}`].fontSize + 'px'}
|
||||||
</MenuTrigger>
|
</MenuTrigger>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
name={t[
|
name={t[
|
||||||
'com.affine.settings.editorSettings.edgeless.shape.font-style'
|
'com.affine.settings.editorSettings.edgeless.text.font-style'
|
||||||
]()}
|
]()}
|
||||||
desc={''}
|
desc={''}
|
||||||
>
|
>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
items={<MenuItem>Regular</MenuItem>}
|
items={fontStyleItems}
|
||||||
trigger={
|
trigger={
|
||||||
<MenuTrigger className={menuTrigger} disabled>
|
<MenuTrigger className={menuTrigger}>
|
||||||
Regular
|
{String(settings[`shape:${currentShape}`].fontStyle)}
|
||||||
|
</MenuTrigger>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SettingRow>
|
||||||
|
<SettingRow
|
||||||
|
name={t[
|
||||||
|
'com.affine.settings.editorSettings.edgeless.text.font-weight'
|
||||||
|
]()}
|
||||||
|
desc={''}
|
||||||
|
>
|
||||||
|
<DropdownMenu
|
||||||
|
items={fontWeightItems}
|
||||||
|
trigger={
|
||||||
|
<MenuTrigger className={menuTrigger}>
|
||||||
|
{FontWeightMap[settings[`shape:${currentShape}`].fontWeight]}
|
||||||
</MenuTrigger>
|
</MenuTrigger>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import type { EditorSettingSchema } from '@affine/core/modules/editor-settting';
|
|||||||
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
||||||
import type { EditorHost } from '@blocksuite/block-std';
|
import type { EditorHost } from '@blocksuite/block-std';
|
||||||
import { BlockStdScope } from '@blocksuite/block-std';
|
import { BlockStdScope } from '@blocksuite/block-std';
|
||||||
import type { SurfaceBlockModel } from '@blocksuite/block-std/gfx';
|
import type { GfxPrimitiveElementModel } from '@blocksuite/block-std/gfx';
|
||||||
import type { EdgelessRootService, FrameBlockModel } from '@blocksuite/blocks';
|
import type { EdgelessRootService } from '@blocksuite/blocks';
|
||||||
import { SpecProvider } from '@blocksuite/blocks';
|
import { SpecProvider } from '@blocksuite/blocks';
|
||||||
import { Bound } from '@blocksuite/global/utils';
|
import { Bound } from '@blocksuite/global/utils';
|
||||||
import type { Doc } from '@blocksuite/store';
|
import type { Block, Doc } from '@blocksuite/store';
|
||||||
import { useFramework } from '@toeverything/infra';
|
import { useFramework } from '@toeverything/infra';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
import { useCallback, useEffect, useRef } from 'react';
|
import { useCallback, useEffect, useRef } from 'react';
|
||||||
@@ -14,52 +14,49 @@ import { map, pairwise } from 'rxjs';
|
|||||||
|
|
||||||
import { snapshotContainer, snapshotTitle } from '../style.css';
|
import { snapshotContainer, snapshotTitle } from '../style.css';
|
||||||
import { type DocName, getDocByName } from './docs';
|
import { type DocName, getDocByName } from './docs';
|
||||||
|
import { getFrameBlock } from './utils';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
docName: DocName;
|
docName: DocName;
|
||||||
flavour: BlockSuite.EdgelessModelKeys;
|
|
||||||
keyName: keyof EditorSettingSchema;
|
keyName: keyof EditorSettingSchema;
|
||||||
height?: number;
|
height?: number;
|
||||||
}
|
getElements: (doc: Doc) => Array<Block | GfxPrimitiveElementModel>;
|
||||||
|
firstUpdate?: (doc: Doc, editorHost: EditorHost) => void;
|
||||||
export function getSurfaceBlock(doc: Doc) {
|
children?: React.ReactElement;
|
||||||
const blocks = doc.getBlocksByFlavour('affine:surface');
|
|
||||||
return blocks.length !== 0 ? (blocks[0].model as SurfaceBlockModel) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFrameBlock(doc: Doc) {
|
|
||||||
const blocks = doc.getBlocksByFlavour('affine:frame');
|
|
||||||
return blocks.length !== 0 ? (blocks[0].model as FrameBlockModel) : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const boundMap = new Map<DocName, Bound>();
|
const boundMap = new Map<DocName, Bound>();
|
||||||
|
|
||||||
export const EdgelessSnapshot = (props: Props) => {
|
export const EdgelessSnapshot = (props: Props) => {
|
||||||
const { title, docName, flavour, keyName, height = 180 } = props;
|
const {
|
||||||
|
title,
|
||||||
|
docName,
|
||||||
|
keyName,
|
||||||
|
height = 180,
|
||||||
|
getElements,
|
||||||
|
firstUpdate,
|
||||||
|
children,
|
||||||
|
} = props;
|
||||||
const wrapperRef = useRef<HTMLDivElement | null>(null);
|
const wrapperRef = useRef<HTMLDivElement | null>(null);
|
||||||
const docRef = useRef<Doc | null>(null);
|
const docRef = useRef<Doc | null>(null);
|
||||||
const editorHostRef = useRef<EditorHost | null>(null);
|
const editorHostRef = useRef<EditorHost | null>(null);
|
||||||
const framework = useFramework();
|
const framework = useFramework();
|
||||||
const { editorSetting } = framework.get(EditorSettingService);
|
const { editorSetting } = framework.get(EditorSettingService);
|
||||||
|
|
||||||
const updateElement = useCallback(
|
const updateElements = useCallback(() => {
|
||||||
(props: Record<string, unknown>) => {
|
const editorHost = editorHostRef.current;
|
||||||
const editorHost = editorHostRef.current;
|
const doc = docRef.current;
|
||||||
const doc = docRef.current;
|
if (!editorHost || !doc) return;
|
||||||
if (!editorHost || !doc) return;
|
const edgelessService = editorHost.std.getService(
|
||||||
const edgelessService = editorHost.std.getService(
|
'affine:page'
|
||||||
'affine:page'
|
) as EdgelessRootService;
|
||||||
) as EdgelessRootService;
|
const elements = getElements(doc);
|
||||||
const blocks = doc.getBlocksByFlavour(flavour);
|
const props = editorSetting.get(keyName) as any;
|
||||||
const surface = getSurfaceBlock(doc);
|
elements.forEach(element => {
|
||||||
const elements = surface?.getElementsByType(flavour) || [];
|
edgelessService.updateElement(element.id, props);
|
||||||
[...blocks, ...elements].forEach(ele => {
|
});
|
||||||
edgelessService.updateElement(ele.id, props);
|
}, [editorSetting, getElements, keyName]);
|
||||||
});
|
|
||||||
},
|
|
||||||
[flavour]
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderEditor = useCallback(async () => {
|
const renderEditor = useCallback(async () => {
|
||||||
if (!wrapperRef.current) return;
|
if (!wrapperRef.current) return;
|
||||||
@@ -72,8 +69,12 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
}).render();
|
}).render();
|
||||||
docRef.current = doc;
|
docRef.current = doc;
|
||||||
editorHostRef.current = editorHost;
|
editorHostRef.current = editorHost;
|
||||||
const settings = editorSetting.get(keyName);
|
|
||||||
updateElement(settings as any);
|
if (firstUpdate) {
|
||||||
|
firstUpdate(doc, editorHost);
|
||||||
|
} else {
|
||||||
|
updateElements();
|
||||||
|
}
|
||||||
|
|
||||||
// refresh viewport
|
// refresh viewport
|
||||||
const edgelessService = editorHost.std.getService(
|
const edgelessService = editorHost.std.getService(
|
||||||
@@ -82,20 +83,18 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
edgelessService.specSlots.viewConnected.once(({ component }) => {
|
edgelessService.specSlots.viewConnected.once(({ component }) => {
|
||||||
const edgelessBlock = component as any;
|
const edgelessBlock = component as any;
|
||||||
edgelessBlock.editorViewportSelector = 'ref-viewport';
|
edgelessBlock.editorViewportSelector = 'ref-viewport';
|
||||||
edgelessBlock.service.viewport.sizeUpdated.once(() => {
|
const frame = getFrameBlock(doc);
|
||||||
const frame = getFrameBlock(doc);
|
if (frame) {
|
||||||
if (frame) {
|
boundMap.set(docName, Bound.deserialize(frame.xywh));
|
||||||
boundMap.set(docName, Bound.deserialize(frame.xywh));
|
doc.deleteBlock(frame);
|
||||||
doc.deleteBlock(frame);
|
}
|
||||||
}
|
const bound = boundMap.get(docName);
|
||||||
const bound = boundMap.get(docName);
|
bound && edgelessService.viewport.setViewportByBound(bound);
|
||||||
bound && edgelessService.viewport.setViewportByBound(bound);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// append to dom node
|
// append to dom node
|
||||||
wrapperRef.current.append(editorHost);
|
wrapperRef.current.append(editorHost);
|
||||||
}, [docName, editorSetting, keyName, updateElement]);
|
}, [docName, firstUpdate, updateElements]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
@@ -117,11 +116,11 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
)
|
)
|
||||||
.subscribe(([prev, current]) => {
|
.subscribe(([prev, current]) => {
|
||||||
if (!isEqual(prev, current)) {
|
if (!isEqual(prev, current)) {
|
||||||
updateElement(current);
|
updateElements();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return () => sub.unsubscribe();
|
return () => sub.unsubscribe();
|
||||||
}, [editorSetting.provider, flavour, keyName, updateElement]);
|
}, [editorSetting.provider, keyName, updateElements]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={snapshotContainer}>
|
<div className={snapshotContainer}>
|
||||||
@@ -136,6 +135,7 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
height,
|
height,
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
LineColorMap,
|
LineColorMap,
|
||||||
TextAlign,
|
TextAlign,
|
||||||
} from '@blocksuite/blocks';
|
} from '@blocksuite/blocks';
|
||||||
|
import type { Doc } from '@blocksuite/store';
|
||||||
import { useFramework, useLiveData } from '@toeverything/infra';
|
import { useFramework, useLiveData } from '@toeverything/infra';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
@@ -139,13 +140,18 @@ export const TextSettings = () => {
|
|||||||
const { color } = settings['affine:edgeless-text'];
|
const { color } = settings['affine:edgeless-text'];
|
||||||
return getColorFromMap(color, LineColorMap);
|
return getColorFromMap(color, LineColorMap);
|
||||||
}, [getColorFromMap, settings]);
|
}, [getColorFromMap, settings]);
|
||||||
|
|
||||||
|
const getElements = useCallback((doc: Doc) => {
|
||||||
|
return doc.getBlocksByFlavour('affine:edgeless-text') || [];
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EdgelessSnapshot
|
<EdgelessSnapshot
|
||||||
title={t['com.affine.settings.editorSettings.edgeless.text']()}
|
title={t['com.affine.settings.editorSettings.edgeless.text']()}
|
||||||
docName="text"
|
docName="text"
|
||||||
keyName="affine:edgeless-text"
|
keyName="affine:edgeless-text"
|
||||||
flavour="affine:edgeless-text"
|
getElements={getElements}
|
||||||
/>
|
/>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
name={t['com.affine.settings.editorSettings.edgeless.text.color']()}
|
name={t['com.affine.settings.editorSettings.edgeless.text.color']()}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import type { SurfaceBlockModel } from '@blocksuite/block-std/gfx';
|
||||||
|
import type { FrameBlockModel } from '@blocksuite/blocks';
|
||||||
|
import type { Doc } from '@blocksuite/store';
|
||||||
|
|
||||||
|
export function getSurfaceBlock(doc: Doc) {
|
||||||
|
const blocks = doc.getBlocksByFlavour('affine:surface');
|
||||||
|
return blocks.length !== 0 ? (blocks[0].model as SurfaceBlockModel) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFrameBlock(doc: Doc) {
|
||||||
|
const blocks = doc.getBlocksByFlavour('affine:frame');
|
||||||
|
return blocks.length !== 0 ? (blocks[0].model as FrameBlockModel) : null;
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@ export const menuTrigger = style({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const snapshotContainer = style({
|
export const snapshotContainer = style({
|
||||||
|
position: 'relative',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
marginBottom: '24px',
|
marginBottom: '24px',
|
||||||
|
|||||||
@@ -1,20 +1,7 @@
|
|||||||
import {
|
import { NodePropsSchema } from '@blocksuite/affine-shared/utils';
|
||||||
BrushSchema,
|
|
||||||
ConnectorSchema,
|
|
||||||
EdgelessTextSchema,
|
|
||||||
NoteSchema,
|
|
||||||
ShapeSchema,
|
|
||||||
} from '@blocksuite/affine-shared/utils';
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
// TODO import from BlockSuite
|
export const BSEditorSettingSchema = NodePropsSchema;
|
||||||
export const BSEditorSettingSchema = z.object({
|
|
||||||
connector: ConnectorSchema,
|
|
||||||
brush: BrushSchema,
|
|
||||||
shape: ShapeSchema,
|
|
||||||
'affine:edgeless-text': EdgelessTextSchema,
|
|
||||||
'affine:note': NoteSchema,
|
|
||||||
});
|
|
||||||
|
|
||||||
export type FontFamily = 'Sans' | 'Serif' | 'Mono' | 'Custom';
|
export type FontFamily = 'Sans' | 'Serif' | 'Mono' | 'Custom';
|
||||||
|
|
||||||
|
|||||||
@@ -1292,6 +1292,8 @@
|
|||||||
"com.affine.settings.editorSettings.edgeless.shape.text-alignment": "Text alignment",
|
"com.affine.settings.editorSettings.edgeless.shape.text-alignment": "Text alignment",
|
||||||
"com.affine.settings.editorSettings.edgeless.shape.text-color": "Text color",
|
"com.affine.settings.editorSettings.edgeless.shape.text-color": "Text color",
|
||||||
"com.affine.settings.editorSettings.edgeless.shape.triangle": "Triangle",
|
"com.affine.settings.editorSettings.edgeless.shape.triangle": "Triangle",
|
||||||
|
"com.affine.settings.editorSettings.edgeless.shape.list": "List",
|
||||||
|
"com.affine.settings.editorSettings.edgeless.shape.flow": "Flow",
|
||||||
"com.affine.settings.editorSettings.edgeless.style": "Style",
|
"com.affine.settings.editorSettings.edgeless.style": "Style",
|
||||||
"com.affine.settings.editorSettings.edgeless.style.general": "General",
|
"com.affine.settings.editorSettings.edgeless.style.general": "General",
|
||||||
"com.affine.settings.editorSettings.edgeless.style.scribbled": "Scribbled",
|
"com.affine.settings.editorSettings.edgeless.style.scribbled": "Scribbled",
|
||||||
|
|||||||
@@ -1293,6 +1293,8 @@
|
|||||||
"com.affine.settings.editorSettings.edgeless.shape.text-alignment": "文本对齐",
|
"com.affine.settings.editorSettings.edgeless.shape.text-alignment": "文本对齐",
|
||||||
"com.affine.settings.editorSettings.edgeless.shape.text-color": "文本颜色",
|
"com.affine.settings.editorSettings.edgeless.shape.text-color": "文本颜色",
|
||||||
"com.affine.settings.editorSettings.edgeless.shape.triangle": "三角形",
|
"com.affine.settings.editorSettings.edgeless.shape.triangle": "三角形",
|
||||||
|
"com.affine.settings.editorSettings.edgeless.shape.list": "列表",
|
||||||
|
"com.affine.settings.editorSettings.edgeless.shape.flow": "流程图",
|
||||||
"com.affine.settings.editorSettings.edgeless.style": "样式",
|
"com.affine.settings.editorSettings.edgeless.style": "样式",
|
||||||
"com.affine.settings.editorSettings.edgeless.style.general": "常规",
|
"com.affine.settings.editorSettings.edgeless.style.general": "常规",
|
||||||
"com.affine.settings.editorSettings.edgeless.style.scribbled": "涂鸦",
|
"com.affine.settings.editorSettings.edgeless.style.scribbled": "涂鸦",
|
||||||
|
|||||||
Reference in New Issue
Block a user