mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
feat: add mindmap and connector settings (#8198)
### What changed?
- Add `connector` label settings.
- Add `mindmap` style settings.
- Add skeleton loading placeholder.
<div class='graphite__hidden'>
<div>🎥 Video uploaded on Graphite:</div>
<a href="https://app.graphite.dev/media/video/sJGviKxfE3Ap685cl5bj/31159d74-ef62-4c7f-b1d9-cde73047cf29.mov">
<img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/sJGviKxfE3Ap685cl5bj/31159d74-ef62-4c7f-b1d9-cde73047cf29.mov">
</a>
</div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/31159d74-ef62-4c7f-b1d9-cde73047cf29.mov">录屏2024-09-11 16.30.17.mov</video>
This commit is contained in:
@@ -10,10 +10,15 @@ import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import {
|
||||
ConnectorMode,
|
||||
FontFamily,
|
||||
FontFamilyMap,
|
||||
FontStyle,
|
||||
FontWeightMap,
|
||||
LineColor,
|
||||
LineColorMap,
|
||||
PointStyle,
|
||||
StrokeStyle,
|
||||
TextAlign,
|
||||
} from '@blocksuite/blocks';
|
||||
import type { Doc } from '@blocksuite/store';
|
||||
import { useFramework, useLiveData } from '@toeverything/infra';
|
||||
@@ -21,7 +26,7 @@ import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { DropdownMenu } from '../menu';
|
||||
import { menuTrigger, settingWrapper } from '../style.css';
|
||||
import { useColor } from '../utils';
|
||||
import { sortedFontWeightEntries, useColor } from '../utils';
|
||||
import { Point } from './point';
|
||||
import { EdgelessSnapshot } from './snapshot';
|
||||
import { getSurfaceBlock } from './utils';
|
||||
@@ -31,6 +36,15 @@ enum ConnecterStyle {
|
||||
Scribbled = 'scribbled',
|
||||
}
|
||||
|
||||
enum ConnectorTextFontSize {
|
||||
'16px' = '16',
|
||||
'20px' = '20',
|
||||
'24px' = '24',
|
||||
'32px' = '32',
|
||||
'40px' = '40',
|
||||
'64px' = '64',
|
||||
}
|
||||
|
||||
export const ConnectorSettings = () => {
|
||||
const t = useI18n();
|
||||
const framework = useFramework();
|
||||
@@ -191,6 +205,150 @@ export const ConnectorSettings = () => {
|
||||
});
|
||||
}, [editorSetting, settings]);
|
||||
|
||||
const alignItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: TextAlign.Left,
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.alignment.left'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: TextAlign.Center,
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.alignment.center'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: TextAlign.Right,
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.alignment.right'
|
||||
](),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
const textAlignment = settings.connector.labelStyle.textAlign;
|
||||
const setTextAlignment = useCallback(
|
||||
(value: TextAlign) => {
|
||||
editorSetting.set('connector', {
|
||||
labelStyle: {
|
||||
textAlign: value,
|
||||
},
|
||||
});
|
||||
},
|
||||
[editorSetting]
|
||||
);
|
||||
|
||||
const fontFamilyItems = useMemo(() => {
|
||||
const { fontFamily } = settings.connector.labelStyle;
|
||||
return Object.entries(FontFamily).map(([name, value]) => {
|
||||
const handler = () => {
|
||||
editorSetting.set('connector', {
|
||||
labelStyle: {
|
||||
fontFamily: value,
|
||||
},
|
||||
});
|
||||
};
|
||||
const isSelected = fontFamily === value;
|
||||
return (
|
||||
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
);
|
||||
});
|
||||
}, [editorSetting, settings]);
|
||||
|
||||
const fontStyleItems = useMemo(() => {
|
||||
const { fontStyle } = settings.connector.labelStyle;
|
||||
return Object.entries(FontStyle).map(([name, value]) => {
|
||||
const handler = () => {
|
||||
editorSetting.set('connector', {
|
||||
labelStyle: {
|
||||
fontStyle: value,
|
||||
},
|
||||
});
|
||||
};
|
||||
const isSelected = fontStyle === value;
|
||||
return (
|
||||
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
);
|
||||
});
|
||||
}, [editorSetting, settings]);
|
||||
|
||||
const fontWeightItems = useMemo(() => {
|
||||
const { fontWeight } = settings.connector.labelStyle;
|
||||
return sortedFontWeightEntries.map(([name, value]) => {
|
||||
const handler = () => {
|
||||
editorSetting.set('connector', {
|
||||
labelStyle: {
|
||||
fontWeight: value,
|
||||
},
|
||||
});
|
||||
};
|
||||
const isSelected = fontWeight === value;
|
||||
return (
|
||||
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
);
|
||||
});
|
||||
}, [editorSetting, settings]);
|
||||
|
||||
const fontSizeItems = useMemo(() => {
|
||||
const { fontSize } = settings.connector.labelStyle;
|
||||
return Object.entries(ConnectorTextFontSize).map(([name, value]) => {
|
||||
const handler = () => {
|
||||
editorSetting.set('connector', {
|
||||
labelStyle: {
|
||||
fontSize: Number(value),
|
||||
},
|
||||
});
|
||||
};
|
||||
const isSelected = fontSize === Number(value);
|
||||
return (
|
||||
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
);
|
||||
});
|
||||
}, [editorSetting, settings]);
|
||||
|
||||
const textColorItems = useMemo(() => {
|
||||
const { color } = settings.connector.labelStyle;
|
||||
return Object.entries(LineColor).map(([name, value]) => {
|
||||
const handler = () => {
|
||||
editorSetting.set('connector', {
|
||||
labelStyle: {
|
||||
color: value,
|
||||
},
|
||||
});
|
||||
};
|
||||
const isSelected = color === value;
|
||||
return (
|
||||
<MenuItem
|
||||
key={name}
|
||||
onSelect={handler}
|
||||
selected={isSelected}
|
||||
prefix={<Point color={value} />}
|
||||
>
|
||||
{name}
|
||||
</MenuItem>
|
||||
);
|
||||
});
|
||||
}, [editorSetting, settings]);
|
||||
|
||||
const textColor = useMemo(() => {
|
||||
const { color } = settings.connector.labelStyle;
|
||||
return getColorFromMap(color, LineColorMap);
|
||||
}, [getColorFromMap, settings]);
|
||||
|
||||
const getElements = useCallback((doc: Doc) => {
|
||||
const surface = getSurfaceBlock(doc);
|
||||
return surface?.getElementsByType('connector') || [];
|
||||
@@ -309,6 +467,100 @@ export const ConnectorSettings = () => {
|
||||
}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.text-color'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
{textColor ? (
|
||||
<DropdownMenu
|
||||
items={textColorItems}
|
||||
trigger={
|
||||
<MenuTrigger
|
||||
className={menuTrigger}
|
||||
prefix={<Point color={textColor.value} />}
|
||||
>
|
||||
{textColor.key}
|
||||
</MenuTrigger>
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.font-family'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<DropdownMenu
|
||||
items={fontFamilyItems}
|
||||
trigger={
|
||||
<MenuTrigger className={menuTrigger}>
|
||||
{FontFamilyMap[settings.connector.labelStyle.fontFamily]}
|
||||
</MenuTrigger>
|
||||
}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.font-size'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<DropdownMenu
|
||||
items={fontSizeItems}
|
||||
trigger={
|
||||
<MenuTrigger className={menuTrigger}>
|
||||
{settings.connector.labelStyle.fontSize + 'px'}
|
||||
</MenuTrigger>
|
||||
}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.font-style'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<DropdownMenu
|
||||
items={fontStyleItems}
|
||||
trigger={
|
||||
<MenuTrigger className={menuTrigger}>
|
||||
{settings.connector.labelStyle.fontStyle}
|
||||
</MenuTrigger>
|
||||
}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.font-weight'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<DropdownMenu
|
||||
items={fontWeightItems}
|
||||
trigger={
|
||||
<MenuTrigger className={menuTrigger}>
|
||||
{FontWeightMap[settings.connector.labelStyle.fontWeight]}
|
||||
</MenuTrigger>
|
||||
}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.text-alignment'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<RadioGroup
|
||||
items={alignItems}
|
||||
value={textAlignment}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setTextAlignment}
|
||||
/>
|
||||
</SettingRow>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"type": "page",
|
||||
"meta": {
|
||||
"id": "v4nxnq2Al2",
|
||||
"id": "gJEFfmo4QJ",
|
||||
"title": "",
|
||||
"createDate": 1725459565290,
|
||||
"createDate": 1726038448921,
|
||||
"tags": []
|
||||
},
|
||||
"blocks": {
|
||||
"type": "block",
|
||||
"id": "eDFE5HokPO",
|
||||
"id": "orzKfiHevj",
|
||||
"flavour": "affine:page",
|
||||
"version": 2,
|
||||
"props": {
|
||||
@@ -20,37 +20,58 @@
|
||||
"children": [
|
||||
{
|
||||
"type": "block",
|
||||
"id": "ZksVPLRI0K",
|
||||
"id": "-48EmppaxI",
|
||||
"flavour": "affine:surface",
|
||||
"version": 5,
|
||||
"props": {
|
||||
"elements": {
|
||||
"hdqh5vFnzj": {
|
||||
"m_PwyyI76y": {
|
||||
"index": "a0",
|
||||
"seed": 263456687,
|
||||
"seed": 44330892,
|
||||
"frontEndpointStyle": "None",
|
||||
"labelOffset": {
|
||||
"distance": 0.5,
|
||||
"anchor": "center"
|
||||
},
|
||||
"labelStyle": {
|
||||
"color": "--affine-palette-line-black",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "blocksuite:surface:Inter",
|
||||
"fontWeight": "400",
|
||||
"fontStyle": "normal",
|
||||
"textAlign": "center"
|
||||
},
|
||||
"labelXYWH": [235.6484375, 65.23828125, 200, 20],
|
||||
"mode": 2,
|
||||
"rearEndpointStyle": "Arrow",
|
||||
"rough": false,
|
||||
"roughness": 1.4,
|
||||
"source": {
|
||||
"position": [196.0625, 145.84765625]
|
||||
"position": [120.8515625, 146.44921875]
|
||||
},
|
||||
"stroke": "--affine-palette-line-grey",
|
||||
"strokeStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"target": {
|
||||
"position": [418.5859375, 52.13671875]
|
||||
"position": [387.4453125, 4.02734375]
|
||||
},
|
||||
"text": {
|
||||
"affine:surface:text": true,
|
||||
"delta": [
|
||||
{
|
||||
"insert": "label"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "connector",
|
||||
"id": "hdqh5vFnzj"
|
||||
"id": "m_PwyyI76y"
|
||||
}
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "block",
|
||||
"id": "TNgzGwq6Ct",
|
||||
"id": "-6UhNH7qhy",
|
||||
"flavour": "affine:frame",
|
||||
"version": 1,
|
||||
"props": {
|
||||
@@ -63,10 +84,10 @@
|
||||
]
|
||||
},
|
||||
"background": "--affine-palette-transparent",
|
||||
"xywh": "[-13.38671875,-4.5625,739.3828125,192.51171875]",
|
||||
"index": "a0",
|
||||
"xywh": "[-12.04296875,-49.66796875,542.9765625,248.3984375]",
|
||||
"index": "Zz",
|
||||
"childElementIds": {
|
||||
"hdqh5vFnzj": true
|
||||
"m_PwyyI76y": true
|
||||
}
|
||||
},
|
||||
"children": []
|
||||
|
||||
@@ -69,13 +69,14 @@ export async function getDocByName(name: DocName) {
|
||||
if (docMap.get(name)) {
|
||||
return docMap.get(name);
|
||||
}
|
||||
const snapshot = (await loaders[name]()) as DocSnapshot;
|
||||
const promiseDoc = initDocFromSnapshot(snapshot);
|
||||
docMap.set(name, promiseDoc);
|
||||
return promiseDoc;
|
||||
|
||||
const promise = initDoc(name);
|
||||
docMap.set(name, promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
async function initDocFromSnapshot(snapshot: DocSnapshot) {
|
||||
async function initDoc(name: DocName) {
|
||||
const snapshot = (await loaders[name]()) as DocSnapshot;
|
||||
const collection = await getCollection();
|
||||
const job = new Job({
|
||||
collection,
|
||||
|
||||
@@ -1,61 +1,65 @@
|
||||
{
|
||||
"type": "page",
|
||||
"meta": {
|
||||
"id": "0P4XpxtY1T",
|
||||
"title": "",
|
||||
"createDate": 1725500529462,
|
||||
"id": "_JUmoI_F28",
|
||||
"title": "BlockSuite Playground",
|
||||
"createDate": 1725610677620,
|
||||
"tags": []
|
||||
},
|
||||
"blocks": {
|
||||
"type": "block",
|
||||
"id": "o_kDMq1Y2z",
|
||||
"id": "FnaWN8Zm2_",
|
||||
"flavour": "affine:page",
|
||||
"version": 2,
|
||||
"props": {
|
||||
"title": {
|
||||
"$blocksuite:internal:text$": true,
|
||||
"delta": []
|
||||
"delta": [
|
||||
{
|
||||
"insert": "BlockSuite Playground"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "block",
|
||||
"id": "CX3YRdnn7u",
|
||||
"id": "hevWf4ccWc",
|
||||
"flavour": "affine:surface",
|
||||
"version": 5,
|
||||
"props": {
|
||||
"elements": {
|
||||
"uXwcJ22j4U": {
|
||||
"index": "a1",
|
||||
"seed": 521352102,
|
||||
"MYyOCcLTWN": {
|
||||
"index": "a0",
|
||||
"seed": 739933670,
|
||||
"children": {
|
||||
"affine:surface:ymap": true,
|
||||
"json": {
|
||||
"5Jk9NbvuPN": {
|
||||
"BvanBL7O38": {
|
||||
"index": "a0"
|
||||
},
|
||||
"DqF847301v": {
|
||||
"QkmFfps45U": {
|
||||
"index": "a0",
|
||||
"parent": "5Jk9NbvuPN"
|
||||
"parent": "BvanBL7O38"
|
||||
},
|
||||
"3cpFVUO7z_": {
|
||||
"1IN8YOdsCP": {
|
||||
"index": "a1",
|
||||
"parent": "5Jk9NbvuPN"
|
||||
"parent": "BvanBL7O38"
|
||||
},
|
||||
"cq1V7jb9Nw": {
|
||||
"iFQ9oVR0KN": {
|
||||
"index": "a2",
|
||||
"parent": "5Jk9NbvuPN"
|
||||
"parent": "BvanBL7O38"
|
||||
}
|
||||
}
|
||||
},
|
||||
"layoutType": 0,
|
||||
"style": 1,
|
||||
"type": "mindmap",
|
||||
"id": "uXwcJ22j4U"
|
||||
"id": "MYyOCcLTWN"
|
||||
},
|
||||
"5Jk9NbvuPN": {
|
||||
"BvanBL7O38": {
|
||||
"index": "a0",
|
||||
"seed": 2040865434,
|
||||
"seed": 819595867,
|
||||
"color": "--affine-black",
|
||||
"fillColor": "--affine-white",
|
||||
"filled": true,
|
||||
@@ -87,13 +91,13 @@
|
||||
]
|
||||
},
|
||||
"textResizing": 0,
|
||||
"xywh": "[219.1787109375,-137.21072387695312,144.7799530029297,52]",
|
||||
"xywh": "[-214.85955810546875,-113.65847778320312,144.7799530029297,52]",
|
||||
"type": "shape",
|
||||
"id": "5Jk9NbvuPN"
|
||||
"id": "BvanBL7O38"
|
||||
},
|
||||
"DqF847301v": {
|
||||
"QkmFfps45U": {
|
||||
"index": "a0",
|
||||
"seed": 42391752,
|
||||
"seed": 557026939,
|
||||
"color": "--affine-black",
|
||||
"fillColor": "--affine-white",
|
||||
"filled": true,
|
||||
@@ -125,13 +129,13 @@
|
||||
]
|
||||
},
|
||||
"textResizing": 0,
|
||||
"xywh": "[563.9586639404297,-210.21072387695312,76.83197021484375,36]",
|
||||
"xywh": "[129.92039489746094,-186.65847778320312,76.83197021484375,36]",
|
||||
"type": "shape",
|
||||
"id": "DqF847301v"
|
||||
"id": "QkmFfps45U"
|
||||
},
|
||||
"3cpFVUO7z_": {
|
||||
"1IN8YOdsCP": {
|
||||
"index": "a0",
|
||||
"seed": 1821565231,
|
||||
"seed": 205695803,
|
||||
"color": "--affine-black",
|
||||
"fillColor": "--affine-white",
|
||||
"filled": true,
|
||||
@@ -163,13 +167,13 @@
|
||||
]
|
||||
},
|
||||
"textResizing": 0,
|
||||
"xywh": "[563.9586639404297,-129.21072387695312,76.83197021484375,36]",
|
||||
"xywh": "[129.92039489746094,-105.65847778320312,76.83197021484375,36]",
|
||||
"type": "shape",
|
||||
"id": "3cpFVUO7z_"
|
||||
"id": "1IN8YOdsCP"
|
||||
},
|
||||
"cq1V7jb9Nw": {
|
||||
"iFQ9oVR0KN": {
|
||||
"index": "a0",
|
||||
"seed": 1835053830,
|
||||
"seed": 585656351,
|
||||
"color": "--affine-black",
|
||||
"fillColor": "--affine-white",
|
||||
"filled": true,
|
||||
@@ -201,16 +205,16 @@
|
||||
]
|
||||
},
|
||||
"textResizing": 0,
|
||||
"xywh": "[563.9586639404297,-48.210723876953125,76.83197021484375,36]",
|
||||
"xywh": "[129.92039489746094,-24.658477783203125,76.83197021484375,36]",
|
||||
"type": "shape",
|
||||
"id": "cq1V7jb9Nw"
|
||||
"id": "iFQ9oVR0KN"
|
||||
}
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "block",
|
||||
"id": "yUWjMW5rEZ",
|
||||
"id": "bVYX1z2q3T",
|
||||
"flavour": "affine:frame",
|
||||
"version": 1,
|
||||
"props": {
|
||||
@@ -223,10 +227,10 @@
|
||||
]
|
||||
},
|
||||
"background": "--affine-palette-transparent",
|
||||
"xywh": "[138.3125,-266.609375,602.640625,321.26171875]",
|
||||
"index": "a0",
|
||||
"xywh": "[-542.4695816040039,-292.0061340332031,798.42578125,414.50390625]",
|
||||
"index": "Zz",
|
||||
"childElementIds": {
|
||||
"uXwcJ22j4U": true
|
||||
"MYyOCcLTWN": true
|
||||
}
|
||||
},
|
||||
"children": []
|
||||
|
||||
@@ -5,38 +5,70 @@ import {
|
||||
type RadioItem,
|
||||
} from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { LayoutType, MindmapStyle } from '@blocksuite/blocks';
|
||||
import type { Doc } from '@blocksuite/store';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useFramework, useLiveData } from '@toeverything/infra';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { DropdownMenu } from '../menu';
|
||||
import { menuTrigger, settingWrapper } from '../style.css';
|
||||
import { EdgelessSnapshot } from './snapshot';
|
||||
import { getSurfaceBlock } from './utils';
|
||||
|
||||
const MINDMAP_STYLES = [
|
||||
{
|
||||
value: MindmapStyle.ONE,
|
||||
name: 'Style 1',
|
||||
},
|
||||
{
|
||||
value: MindmapStyle.TWO,
|
||||
name: 'Style 2',
|
||||
},
|
||||
{
|
||||
value: MindmapStyle.THREE,
|
||||
name: 'Style 3',
|
||||
},
|
||||
{
|
||||
value: MindmapStyle.FOUR,
|
||||
name: 'Style 4',
|
||||
},
|
||||
];
|
||||
|
||||
export const MindMapSettings = () => {
|
||||
const t = useI18n();
|
||||
const [layoutValue, setLayoutValue] = useState<'left' | 'radial' | 'right'>(
|
||||
'right'
|
||||
const framework = useFramework();
|
||||
const { editorSetting } = framework.get(EditorSettingService);
|
||||
const settings = useLiveData(editorSetting.settings$);
|
||||
|
||||
const { layoutType } = settings.mindmap;
|
||||
const setLayoutType = useCallback(
|
||||
(value: LayoutType) => {
|
||||
editorSetting.set('mindmap', {
|
||||
layoutType: value,
|
||||
});
|
||||
},
|
||||
[editorSetting]
|
||||
);
|
||||
const layoutValueItems = useMemo<RadioItem[]>(
|
||||
const layoutTypeItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'left',
|
||||
value: LayoutType.LEFT as any,
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.mind-map.layout.left'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: 'radial',
|
||||
value: LayoutType.BALANCE as any,
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.mind-map.layout.radial'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: 'right',
|
||||
value: LayoutType.RIGHT as any,
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.mind-map.layout.right'
|
||||
@@ -46,6 +78,21 @@ export const MindMapSettings = () => {
|
||||
[t]
|
||||
);
|
||||
|
||||
const styleItems = useMemo(() => {
|
||||
const { style } = settings.mindmap;
|
||||
return MINDMAP_STYLES.map(({ name, value }) => {
|
||||
const handler = () => {
|
||||
editorSetting.set('mindmap', { style: value });
|
||||
};
|
||||
const isSelected = style === value;
|
||||
return (
|
||||
<MenuItem key={name} onSelect={handler} selected={isSelected}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
);
|
||||
});
|
||||
}, [editorSetting, settings]);
|
||||
|
||||
const getElements = useCallback((doc: Doc) => {
|
||||
const surface = getSurfaceBlock(doc);
|
||||
return surface?.getElementsByType('mindmap') || [];
|
||||
@@ -65,10 +112,10 @@ export const MindMapSettings = () => {
|
||||
desc={''}
|
||||
>
|
||||
<DropdownMenu
|
||||
items={<MenuItem>Style 1</MenuItem>}
|
||||
items={styleItems}
|
||||
trigger={
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Style 1
|
||||
<MenuTrigger className={menuTrigger}>
|
||||
{`Style ${settings.mindmap.style}`}
|
||||
</MenuTrigger>
|
||||
}
|
||||
/>
|
||||
@@ -80,11 +127,11 @@ export const MindMapSettings = () => {
|
||||
desc={''}
|
||||
>
|
||||
<RadioGroup
|
||||
items={layoutValueItems}
|
||||
value={layoutValue}
|
||||
items={layoutTypeItems}
|
||||
value={layoutType}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setLayoutValue}
|
||||
onChange={setLayoutType}
|
||||
/>
|
||||
</SettingRow>
|
||||
</>
|
||||
|
||||
@@ -47,10 +47,12 @@ import { EdgelessSnapshot } from './snapshot';
|
||||
import { getSurfaceBlock } from './utils';
|
||||
|
||||
enum ShapeTextFontSize {
|
||||
'12px' = '12',
|
||||
'16px' = '16',
|
||||
'20px' = '20',
|
||||
'28px' = '28',
|
||||
'36px' = '36',
|
||||
'24px' = '24',
|
||||
'32px' = '32',
|
||||
'40px' = '40',
|
||||
'64px' = '64',
|
||||
}
|
||||
|
||||
const ShapeFillColorMap = createEnumMap(ShapeFillColor);
|
||||
@@ -557,7 +559,7 @@ export const ShapeSettings = () => {
|
||||
items={fontStyleItems}
|
||||
trigger={
|
||||
<MenuTrigger className={menuTrigger}>
|
||||
{String(settings[`shape:${currentShape}`].fontStyle)}
|
||||
{settings[`shape:${currentShape}`].fontStyle}
|
||||
</MenuTrigger>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Skeleton } from '@affine/component';
|
||||
import type { EditorSettingSchema } from '@affine/core/modules/editor-settting';
|
||||
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
||||
import type { EditorHost } from '@blocksuite/block-std';
|
||||
@@ -12,7 +13,12 @@ import { isEqual } from 'lodash-es';
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { map, pairwise } from 'rxjs';
|
||||
|
||||
import { snapshotContainer, snapshotLabel, snapshotTitle } from '../style.css';
|
||||
import {
|
||||
snapshotContainer,
|
||||
snapshotLabel,
|
||||
snapshotSkeleton,
|
||||
snapshotTitle,
|
||||
} from '../style.css';
|
||||
import { type DocName, getDocByName } from './docs';
|
||||
import { getFrameBlock } from './utils';
|
||||
|
||||
@@ -136,7 +142,13 @@ export const EdgelessSnapshot = (props: Props) => {
|
||||
overflow: 'hidden',
|
||||
height,
|
||||
}}
|
||||
></div>
|
||||
>
|
||||
<Skeleton
|
||||
className={snapshotSkeleton}
|
||||
variant="rounded"
|
||||
height={'100%'}
|
||||
/>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -43,6 +43,12 @@ export const snapshotTitle = style({
|
||||
color: cssVarV2('text/secondary'),
|
||||
});
|
||||
|
||||
export const snapshotSkeleton = style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
});
|
||||
|
||||
export const snapshot = style({
|
||||
width: '100%',
|
||||
height: '180px',
|
||||
|
||||
Reference in New Issue
Block a user