feat(editor): unify block props api (#10888)

Closes: [BS-2707](https://linear.app/affine-design/issue/BS-2707/统一使用props获取和更新block-prop)
This commit is contained in:
Saul-Mirone
2025-03-16 05:48:34 +00:00
parent 8f9e5bf0aa
commit 26285f7dcb
193 changed files with 1019 additions and 891 deletions

View File

@@ -28,7 +28,7 @@ import { checkAttachmentBlob, downloadAttachmentBlob } from './utils';
@Peekable({
enableOn: ({ model }: AttachmentBlockComponent) => {
return model.type.endsWith('pdf');
return model.props.type.endsWith('pdf');
},
})
export class AttachmentBlockComponent extends CaptionedBlockComponent<AttachmentBlockModel> {
@@ -104,7 +104,7 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<Attachment
this.contentEditable = 'false';
if (!this.model.style) {
if (!this.model.props.style) {
this.doc.withoutTransact(() => {
this.doc.updateBlock(this.model, {
style: AttachmentBlockStyles[1],
@@ -170,7 +170,7 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<Attachment
}
override renderBlock() {
const { name, size, style } = this.model;
const { name, size, style } = this.model.props;
const cardStyle = style ?? AttachmentBlockStyles[1];
const theme = this.std.get(ThemeProvider).theme;

View File

@@ -42,7 +42,7 @@ export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent(
}
override renderGfxBlock() {
const { style$ } = this.model;
const { style$ } = this.model.props;
const cardStyle = style$.value ?? AttachmentBlockStyles[1];
const width = EMBED_CARD_WIDTH[cardStyle];
const height = EMBED_CARD_HEIGHT[cardStyle];

View File

@@ -19,7 +19,7 @@ export const RenameModal = ({
const inputRef = createRef<HTMLInputElement>();
// Fix auto focus
setTimeout(() => inputRef.value?.focus());
const originalName = model.name;
const originalName = model.props.name;
const nameWithoutExtension = originalName.slice(
0,
originalName.lastIndexOf('.')

View File

@@ -100,7 +100,7 @@ const createAttachmentViewDropdownMenuWith = <T extends SelectionConstructor>(
const actions = this.actions.map(action => ({ ...action }));
const viewType$ = computed(() => {
const [cardAction, embedAction] = actions;
const embed = model.embed$.value ?? false;
const embed = model.props.embed$.value ?? false;
cardAction.disabled = !embed;
embedAction.disabled = embed && embedProvider.embedded(model);

View File

@@ -113,11 +113,11 @@ export class AttachmentEmbedService extends Extension {
blobUrl?: string,
maxFileSize = this._maxFileSize
) {
if (!model.embed || !blobUrl) return;
if (!model.props.embed || !blobUrl) return;
const config = this.values.find(config => config.check(model, maxFileSize));
if (!config || !config.template) {
console.error('No embed view template found!', model, model.type);
console.error('No embed view template found!', model, model.props.type);
return;
}
@@ -130,7 +130,7 @@ const embedConfig: AttachmentEmbedConfig[] = [
name: 'image',
check: model =>
model.doc.schema.flavourSchemaMap.has('affine:image') &&
model.type.startsWith('image/'),
model.props.type.startsWith('image/'),
async action(model, std) {
const component = std.view.getBlock(model.id);
if (!component) return;
@@ -141,7 +141,7 @@ const embedConfig: AttachmentEmbedConfig[] = [
{
name: 'pdf',
check: (model, maxFileSize) =>
model.type === 'application/pdf' && model.size <= maxFileSize,
model.props.type === 'application/pdf' && model.props.size <= maxFileSize,
template: (_, blobUrl) => {
// More options: https://tinytip.co/tips/html-pdf-params/
// https://chromium.googlesource.com/chromium/src/+/refs/tags/121.0.6153.1/chrome/browser/resources/pdf/open_pdf_params_parser.ts
@@ -162,7 +162,7 @@ const embedConfig: AttachmentEmbedConfig[] = [
{
name: 'video',
check: (model, maxFileSize) =>
model.type.startsWith('video/') && model.size <= maxFileSize,
model.props.type.startsWith('video/') && model.props.size <= maxFileSize,
template: (_, blobUrl) =>
html`<video
style="max-height: max-content;"
@@ -175,7 +175,7 @@ const embedConfig: AttachmentEmbedConfig[] = [
{
name: 'audio',
check: (model, maxFileSize) =>
model.type.startsWith('audio/') && model.size <= maxFileSize,
model.props.type.startsWith('audio/') && model.props.size <= maxFileSize,
template: (_, blobUrl) =>
html`<audio controls src=${blobUrl} style="margin: 4px;"></audio>`,
},
@@ -190,13 +190,15 @@ export async function turnIntoImageBlock(model: AttachmentBlockModel) {
return;
}
const sourceId = model.sourceId;
const sourceId = model.props.sourceId;
if (!sourceId) return;
const { saveAttachmentData, getImageData } = withTempBlobData();
saveAttachmentData(sourceId, { name: model.name });
saveAttachmentData(sourceId, { name: model.props.name });
let imageSize = model.sourceId ? getImageData(model.sourceId) : undefined;
let imageSize = model.props.sourceId
? getImageData(model.props.sourceId)
: undefined;
const bounds = model.xywh
? Bound.fromXYWH(model.deserializedXYWH)
@@ -223,8 +225,8 @@ export async function turnIntoImageBlock(model: AttachmentBlockModel) {
const imageProp: Partial<ImageBlockProps> = {
sourceId,
caption: model.caption,
size: model.size,
caption: model.props.caption,
size: model.props.size,
...imageSize,
...others,
};

View File

@@ -98,7 +98,7 @@ export async function uploadAttachmentBlob(
}
export async function getAttachmentBlob(model: AttachmentBlockModel) {
const sourceId = model.sourceId;
const sourceId = model.props.sourceId;
if (!sourceId) {
return null;
}
@@ -107,7 +107,7 @@ export async function getAttachmentBlob(model: AttachmentBlockModel) {
let blob = await doc.blobSync.get(sourceId);
if (blob) {
blob = new Blob([blob], { type: model.type });
blob = new Blob([blob], { type: model.props.type });
}
return blob;
@@ -115,7 +115,8 @@ export async function getAttachmentBlob(model: AttachmentBlockModel) {
export async function checkAttachmentBlob(block: AttachmentBlockComponent) {
const model = block.model;
const { id, sourceId } = model;
const { id } = model;
const { sourceId } = model.props;
if (isAttachmentUploading(id)) {
block.loading = true;
@@ -174,7 +175,7 @@ export function downloadAttachmentBlob(block: AttachmentBlockComponent) {
return;
}
const name = model.name;
const name = model.props.name;
const shortName = name.length < 20 ? name : name.slice(0, 20) + '...';
if (error || !blobUrl) {

View File

@@ -28,7 +28,7 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent<BookmarkBloc
protected containerStyleMap!: ReturnType<typeof styleMap>;
open = () => {
let link = this.model.url;
let link = this.model.props.url;
if (!link.match(/^[a-zA-Z]+:\/\//)) {
link = 'https://' + link;
}
@@ -57,7 +57,7 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent<BookmarkBloc
this.contentEditable = 'false';
if (!this.model.description && !this.model.title) {
if (!this.model.props.description && !this.model.props.title) {
this.refreshData();
}

View File

@@ -16,7 +16,7 @@ export class BookmarkEdgelessBlockComponent extends toGfxBlockComponent(
override getRenderingRect() {
const elementBound = this.model.elementBound;
const style = this.model.style$.value;
const style = this.model.props.style$.value;
return {
x: elementBound.x,
@@ -28,7 +28,7 @@ export class BookmarkEdgelessBlockComponent extends toGfxBlockComponent(
}
override renderGfxBlock() {
const style = this.model.style$.value;
const style = this.model.props.style$.value;
const width = EMBED_CARD_WIDTH[style];
const height = EMBED_CARD_HEIGHT[style];
const bound = this.model.elementBound;

View File

@@ -54,7 +54,8 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
}
override render() {
const { icon, title, url, description, image, style } = this.bookmark.model;
const { icon, title, url, description, image, style } =
this.bookmark.model.props;
const cardClassMap = classMap({
loading: this.loading,

View File

@@ -43,7 +43,7 @@ export const builtinToolbarConfig = {
);
if (!model) return null;
const { url } = model;
const { url } = model.props;
return html`<affine-link-preview .url=${url}></affine-link-preview>`;
},
@@ -61,7 +61,8 @@ export const builtinToolbarConfig = {
);
if (!model) return;
const { title, caption, url, parent } = model;
const { title, caption, url } = model.props;
const { parent } = model;
const index = parent?.children.indexOf(model);
const yText = new Y.Text();
@@ -103,7 +104,7 @@ export const builtinToolbarConfig = {
const options = ctx.std
.get(EmbedOptionProvider)
.getEmbedBlockOptions(model.url);
.getEmbedBlockOptions(model.props.url);
return options?.viewType !== 'embed';
},
@@ -114,7 +115,8 @@ export const builtinToolbarConfig = {
);
if (!model) return;
const { caption, url, style, parent } = model;
const { caption, url, style } = model.props;
const { parent } = model;
const index = parent?.children.indexOf(model);
const options = ctx.std
@@ -232,7 +234,7 @@ export const builtinToolbarConfig = {
.actions=${actions}
.context=${ctx}
.toggle=${toggle}
.style$=${model.style$}
.style$=${model.props.style$}
></affine-card-style-dropdown-menu>`
)}`;
},

View File

@@ -17,7 +17,7 @@ export async function refreshBookmarkUrlData(
const linkPreviewer = bookmarkElement.doc.get(LinkPreviewerService);
const bookmarkUrlData = await linkPreviewer.query(
bookmarkElement.model.url,
bookmarkElement.model.props.url,
signal
);

View File

@@ -57,7 +57,7 @@ export class CalloutBlockComponent extends CaptionedBlockComponent<CalloutBlockM
template: html`<affine-emoji-menu
.theme=${theme}
.onEmojiSelect=${(data: any) => {
this.model.emoji = data.native;
this.model.props.emoji = data.native;
}}
></affine-emoji-menu>`,
portalStyles: {
@@ -109,7 +109,7 @@ export class CalloutBlockComponent extends CaptionedBlockComponent<CalloutBlockM
contenteditable="false"
class="affine-callout-emoji-container"
>
<span class="affine-callout-emoji">${this.model.emoji}</span>
<span class="affine-callout-emoji">${this.model.props.emoji$}</span>
</div>
<div class="affine-callout-children">
${this.renderChildren(this.model)}

View File

@@ -47,7 +47,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
highlightTokens$: Signal<ThemedToken[][]> = signal([]);
languageName$: Signal<string> = computed(() => {
const lang = this.model.language$.value;
const lang = this.model.props.language$.value;
if (lang === null) {
return 'Plain Text';
}
@@ -83,7 +83,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
}
private _updateHighlightTokens() {
const modelLang = this.model.language$.value;
const modelLang = this.model.props.language$.value;
if (modelLang === null) {
this.highlightTokens$.value = [];
return;
@@ -97,7 +97,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
);
if (matchedInfo) {
this.model.language$.value = matchedInfo.id;
this.model.props.language$.value = matchedInfo.id;
const langImport = matchedInfo.import;
const lang = matchedInfo.id;
@@ -108,8 +108,8 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
return;
}
noop(this.model.text.deltas$.value);
const code = this.model.text.toString();
noop(this.model.props.text.deltas$.value);
const code = this.model.props.text.toString();
const loadedLanguages = highlighter.getLoadedLanguages();
if (!loadedLanguages.includes(lang)) {
@@ -131,7 +131,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
} else {
this.highlightTokens$.value = [];
// clear language if not found
this.model.language$.value = null;
this.model.props.language$.value = null;
}
}
@@ -339,7 +339,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
const inlineEditor = this.inlineEditor;
const inlineRange = inlineEditor?.getInlineRange();
if (!inlineRange || !inlineEditor) return;
const isEnd = model.text.length === inlineRange.index;
const isEnd = model.props.text.length === inlineRange.index;
if (!isEnd) return;
const parent = this.doc.getParent(model);
if (!parent) return;
@@ -389,11 +389,11 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
class=${classMap({
'affine-code-block-container': true,
mobile: IS_MOBILE,
wrap: this.model.wrap,
wrap: this.model.props.wrap,
})}
>
<rich-text
.yText=${this.model.text.yText}
.yText=${this.model.props.text.yText}
.inlineEventSource=${this.topContenteditableElement ?? nothing}
.undoManager=${this.doc.history}
.attributesSchema=${this.inlineManager.getSchema()}
@@ -402,7 +402,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
.inlineRangeProvider=${this._inlineRangeProvider}
.enableClipboard=${false}
.enableUndoRedo=${false}
.wrapText=${this.model.wrap}
.wrapText=${this.model.props.wrap}
.verticalScrollContainerGetter=${() => getViewportElement(this.host)}
.vLineRenderer=${showLineNumbers
? (vLine: VLine) => {

View File

@@ -76,10 +76,10 @@ export class LanguageListButton extends WithDisposable(
sortedBundledLanguages.unshift(item);
}
this.blockComponent.doc.transact(() => {
this.blockComponent.model.language$.value = item.name;
this.blockComponent.model.props.language$.value = item.name;
});
},
active: item => item.name === this.blockComponent.model.language,
active: item => item.name === this.blockComponent.model.props.language,
items: this._sortedBundledLanguages,
};

View File

@@ -110,7 +110,7 @@ export const clipboardGroup: MenuItemGroup<CodeBlockToolbarContext> = {
{
type: 'wrap',
generate: ({ blockComponent, close }) => {
const wrapped = blockComponent.model.wrap;
const wrapped = blockComponent.model.props.wrap;
const label = wrapped ? 'Cancel wrap' : 'Wrap';
const icon = wrapped ? CancelWrapIcon : WrapIcon;

View File

@@ -1,14 +1,14 @@
import type { CodeBlockModel } from '@blocksuite/affine-model';
export const duplicateCodeBlock = (model: CodeBlockModel) => {
const keys = model.keys as (keyof typeof model)[];
const values = keys.map(key => model[key]);
const keys = model.keys as (keyof (typeof model)['props'])[];
const values = keys.map(key => model.props[key]);
const blockProps = Object.fromEntries(keys.map((key, i) => [key, values[i]]));
const { text: _text, ...duplicateProps } = blockProps;
const newProps = {
flavour: model.flavour,
text: model.text.clone(),
text: model.props.text.clone(),
...duplicateProps,
};

View File

@@ -8,6 +8,6 @@ export const todoMeta = createBlockMeta<ListBlockModel>({
return false;
}
return (block.model as ListBlockModel).type === 'todo';
return (block.model as ListBlockModel).props.type === 'todo';
},
});

View File

@@ -47,7 +47,7 @@ export class BlockQueryDataSource extends DataSourceBase {
get properties(): string[] {
return [
...this.meta.properties.map(v => v.key),
...this.block.columns.map(v => v.id),
...this.block.props.columns.map(v => v.id),
];
}
@@ -107,7 +107,9 @@ export class BlockQueryDataSource extends DataSourceBase {
private newColumnName() {
let i = 1;
while (this.block.columns.some(column => column.name === `Column ${i}`)) {
while (
this.block.props.columns.some(column => column.name === `Column ${i}`)
) {
i++;
}
return `Column ${i}`;
@@ -116,8 +118,8 @@ export class BlockQueryDataSource extends DataSourceBase {
cellValueChange(rowId: string, propertyId: string, value: unknown): void {
const viewColumn = this.getViewColumn(propertyId);
if (viewColumn) {
this.block.cells[rowId] = {
...this.block.cells[rowId],
this.block.props.cells[rowId] = {
...this.block.props.cells[rowId],
[propertyId]: value,
};
return;
@@ -133,7 +135,7 @@ export class BlockQueryDataSource extends DataSourceBase {
cellValueGet(rowId: string, propertyId: string): unknown {
const viewColumn = this.getViewColumn(propertyId);
if (viewColumn) {
return this.block.cells[rowId]?.[propertyId];
return this.block.props.cells[rowId]?.[propertyId];
}
const block = this.blockMap.get(rowId);
if (block) {
@@ -143,7 +145,7 @@ export class BlockQueryDataSource extends DataSourceBase {
}
getViewColumn(id: string) {
return this.block.columns.find(v => v.id === id);
return this.block.props.columns.find(v => v.id === id);
}
listenToDoc(doc: Store) {
@@ -174,7 +176,7 @@ export class BlockQueryDataSource extends DataSourceBase {
].create(this.newColumnName());
const id = doc.workspace.idGenerator();
if (this.block.columns.some(v => v.id === id)) {
if (this.block.props.columns.some(v => v.id === id)) {
return id;
}
doc.transact(() => {
@@ -182,8 +184,8 @@ export class BlockQueryDataSource extends DataSourceBase {
...column,
id,
};
this.block.columns.splice(
insertPositionToIndex(insertToPosition, this.block.columns),
this.block.props.columns.splice(
insertPositionToIndex(insertToPosition, this.block.props.columns),
0,
col
);
@@ -211,9 +213,9 @@ export class BlockQueryDataSource extends DataSourceBase {
}
propertyDelete(_id: string): void {
const index = this.block.columns.findIndex(v => v.id === _id);
const index = this.block.props.columns.findIndex(v => v.id === _id);
if (index >= 0) {
this.block.columns.splice(index, 1);
this.block.props.columns.splice(index, 1);
}
}
@@ -293,8 +295,8 @@ export class BlockQueryDataSource extends DataSourceBase {
viewColumn.data = result.property;
currentCells.forEach((value, i) => {
if (value != null || result.cells[i] != null) {
this.block.cells[rows[i]] = {
...this.block.cells[rows[i]],
this.block.props.cells[rows[i]] = {
...this.block.props.cells[rows[i]],
[propertyId]: result.cells[i],
};
}

View File

@@ -96,10 +96,10 @@ export class DataViewBlockComponent extends CaptionedBlockComponent<DataViewBloc
options: {
items: [
menu.input({
initialValue: this.model.title,
initialValue: this.model.props.title,
placeholder: 'Untitled',
onChange: text => {
this.model.title = text;
this.model.props.title = text;
},
}),
menu.action({
@@ -158,7 +158,7 @@ export class DataViewBlockComponent extends CaptionedBlockComponent<DataViewBloc
return html`
<div style="margin-bottom: 16px;display:flex;flex-direction: column">
<div style="display:flex;gap:8px;padding: 0 6px;margin-bottom: 8px;">
<div>${this.model.title}</div>
<div>${this.model.props.title}</div>
${this.renderDatabaseOps()}
</div>
<div

View File

@@ -25,24 +25,24 @@ export class DataViewBlockModel extends BlockModel<Props> {
applyViewsUpdate() {
this.doc.updateBlock(this, {
views: this.views,
views: this.props.views,
});
}
deleteView(id: string) {
this.doc.captureSync();
this.doc.transact(() => {
this.views = this.views.filter(v => v.id !== id);
this.props.views = this.props.views.filter(v => v.id !== id);
});
}
duplicateView(id: string): string {
const newId = this.doc.workspace.idGenerator();
this.doc.transact(() => {
const index = this.views.findIndex(v => v.id === id);
const view = this.views[index];
const index = this.props.views.findIndex(v => v.id === id);
const view = this.props.views[index];
if (view) {
this.views.splice(
this.props.views.splice(
index + 1,
0,
JSON.parse(JSON.stringify({ ...view, id: newId }))
@@ -54,8 +54,8 @@ export class DataViewBlockModel extends BlockModel<Props> {
moveViewTo(id: string, position: InsertToPosition) {
this.doc.transact(() => {
this.views = arrayMove(
this.views,
this.props.views = arrayMove(
this.props.views,
v => v.id === id,
arr => insertPositionToIndex(position, arr)
);
@@ -68,7 +68,7 @@ export class DataViewBlockModel extends BlockModel<Props> {
update: (data: DataViewDataType) => Partial<DataViewDataType>
) {
this.doc.transact(() => {
this.views = this.views.map(v => {
this.props.views = this.props.views.map(v => {
if (v.id !== id) {
return v;
}

View File

@@ -70,7 +70,7 @@ export class DatabaseBlockDataSource extends DataSourceBase {
properties$: ReadonlySignal<string[]> = computed(() => {
const fixedPropertiesSet = new Set(this.fixedProperties$.value);
const properties: string[] = [];
this._model.columns$.value.forEach(column => {
this._model.props.columns$.value.forEach(column => {
if (fixedPropertiesSet.has(column.type)) {
fixedPropertiesSet.delete(column.type);
}
@@ -96,7 +96,7 @@ export class DatabaseBlockDataSource extends DataSourceBase {
viewConverts = databaseBlockViewConverts;
viewDataList$: ReadonlySignal<DataViewDataType[]> = computed(() => {
return this._model.views$.value as DataViewDataType[];
return this._model.props.views$.value as DataViewDataType[];
});
override viewManager: ViewManager = new ViewManagerBase(this);
@@ -140,7 +140,9 @@ export class DatabaseBlockDataSource extends DataSourceBase {
private newPropertyName() {
let i = 1;
while (
this._model.columns$.value.some(column => column.name === `Column ${i}`)
this._model.props.columns$.value.some(
column => column.name === `Column ${i}`
)
) {
i++;
}
@@ -164,7 +166,7 @@ export class DatabaseBlockDataSource extends DataSourceBase {
dataSource: this,
newValue: value,
setValue: newValue => {
if (this._model.columns$.value.some(v => v.id === propertyId)) {
if (this._model.props.columns$.value.some(v => v.id === propertyId)) {
updateCell(this._model, rowId, {
columnId: propertyId,
value: newValue,
@@ -227,11 +229,11 @@ export class DatabaseBlockDataSource extends DataSourceBase {
index: number;
}
| undefined {
const index = this._model.columns$.value.findIndex(
const index = this._model.props.columns$.value.findIndex(
v => v.id === propertyId
);
if (index >= 0) {
const column = this._model.columns$.value[index];
const column = this._model.props.columns$.value[index];
if (!column) {
return;
}
@@ -281,11 +283,11 @@ export class DatabaseBlockDataSource extends DataSourceBase {
this._model.doc.transact(() => {
if (index >= 0) {
const result = updater(prevColumn);
this._model.columns[index] = { ...prevColumn, ...result };
this._model.props.columns[index] = { ...prevColumn, ...result };
} else {
const result = updater(prevColumn);
this._model.columns = [
...this._model.columns,
this._model.props.columns = [
...this._model.props.columns,
{ ...prevColumn, ...result },
];
}
@@ -327,11 +329,13 @@ export class DatabaseBlockDataSource extends DataSourceBase {
return;
}
this.doc.captureSync();
const index = this._model.columns.findIndex(v => v.id === id);
const index = this._model.props.columns.findIndex(v => v.id === id);
if (index < 0) return;
this.doc.transact(() => {
this._model.columns = this._model.columns.filter((_, i) => i !== index);
this._model.props.columns = this._model.props.columns.filter(
(_, i) => i !== index
);
});
}
@@ -345,7 +349,7 @@ export class DatabaseBlockDataSource extends DataSourceBase {
return;
}
const { id: copyId, ...nonIdProps } = currentSchema;
const names = new Set(this._model.columns$.value.map(v => v.name));
const names = new Set(this._model.props.columns$.value.map(v => v.name));
let index = 1;
while (names.has(`${nonIdProps.name}(${index})`)) {
index++;
@@ -476,7 +480,7 @@ export class DatabaseBlockDataSource extends DataSourceBase {
viewDataAdd(viewData: DataViewDataType): string {
this._model.doc.captureSync();
this._model.doc.transact(() => {
this._model.views = [...this._model.views, viewData];
this._model.props.views = [...this._model.props.views, viewData];
});
return viewData.id;
}

View File

@@ -110,10 +110,14 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent<DatabaseBloc
const options = this.optionsConfig.configure(this.model, {
items: [
menu.input({
initialValue: this.model.title.toString(),
initialValue: this.model.props.title.toString(),
placeholder: 'Untitled',
onChange: text => {
this.model.title.replace(0, this.model.title.length, text);
this.model.props.title.replace(
0,
this.model.props.title.length,
text
);
},
}),
menu.action({
@@ -162,7 +166,7 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent<DatabaseBloc
const addRow = () => dataViewMethod.addRow?.('start');
return html` <affine-database-title
style="overflow: hidden"
.titleText="${this.model.title}"
.titleText="${this.model.props.title}"
.readonly="${this.dataSource.readonly$.value}"
.onPressEnterKey="${addRow}"
></affine-database-title>`;

View File

@@ -68,7 +68,7 @@ export class NoteRenderer
);
collection.meta.setDocMeta(note.id, { title: rowContent });
if (note.root) {
(note.root as RootBlockModel).title.insert(rowContent ?? '', 0);
(note.root as RootBlockModel).props.title.insert(rowContent ?? '', 0);
note.root.children
.find(child => child.flavour === 'affine:note')
?.children.find(block =>

View File

@@ -20,7 +20,7 @@ export function addProperty(
}
): string {
const id = column.id ?? model.doc.workspace.idGenerator();
if (model.columns.some(v => v.id === id)) {
if (model.props.columns.some(v => v.id === id)) {
return id;
}
model.doc.transact(() => {
@@ -28,8 +28,8 @@ export function addProperty(
...column,
id,
};
model.columns.splice(
insertPositionToIndex(position, model.columns),
model.props.columns.splice(
insertPositionToIndex(position, model.props.columns),
0,
col
);
@@ -43,10 +43,10 @@ export function copyCellsByProperty(
toId: Column['id']
) {
model.doc.transact(() => {
Object.keys(model.cells).forEach(rowId => {
const cell = model.cells[rowId]?.[fromId];
if (cell && model.cells[rowId]) {
model.cells[rowId][toId] = {
Object.keys(model.props.cells).forEach(rowId => {
const cell = model.props.cells[rowId]?.[fromId];
if (cell && model.props.cells[rowId]) {
model.props.cells[rowId][toId] = {
...cell,
columnId: toId,
};
@@ -59,18 +59,18 @@ export function deleteColumn(
model: DatabaseBlockModel,
columnId: Column['id']
) {
const index = model.columns.findIndex(v => v.id === columnId);
const index = model.props.columns.findIndex(v => v.id === columnId);
if (index < 0) return;
model.doc.transact(() => {
model.columns.splice(index, 1);
model.props.columns.splice(index, 1);
});
}
export function deleteRows(model: DatabaseBlockModel, rowIds: string[]) {
model.doc.transact(() => {
for (const rowId of rowIds) {
delete model.cells[rowId];
delete model.props.cells[rowId];
}
});
}
@@ -78,17 +78,17 @@ export function deleteRows(model: DatabaseBlockModel, rowIds: string[]) {
export function deleteView(model: DatabaseBlockModel, id: string) {
model.doc.captureSync();
model.doc.transact(() => {
model.views = model.views.filter(v => v.id !== id);
model.props.views = model.props.views.filter(v => v.id !== id);
});
}
export function duplicateView(model: DatabaseBlockModel, id: string): string {
const newId = model.doc.workspace.idGenerator();
model.doc.transact(() => {
const index = model.views.findIndex(v => v.id === id);
const view = model.views[index];
const index = model.props.views.findIndex(v => v.id === id);
const view = model.props.views[index];
if (view) {
model.views.splice(
model.props.views.splice(
index + 1,
0,
JSON.parse(JSON.stringify({ ...view, id: newId }))
@@ -109,7 +109,7 @@ export function getCell(
value: rowId,
};
}
const yRow = model.cells$.value[rowId];
const yRow = model.props.cells$.value[rowId];
const yCell = yRow?.[columnId] ?? null;
if (!yCell) return null;
@@ -123,7 +123,7 @@ export function getProperty(
model: DatabaseBlockModel,
id: Column['id']
): Column | undefined {
return model.columns.find(v => v.id === id);
return model.props.columns.find(v => v.id === id);
}
export function moveViewTo(
@@ -132,8 +132,8 @@ export function moveViewTo(
position: InsertToPosition
) {
model.doc.transact(() => {
model.views = arrayMove(
model.views,
model.props.views = arrayMove(
model.props.views,
v => v.id === id,
arr => insertPositionToIndex(position, arr)
);
@@ -163,11 +163,11 @@ export function updateCell(
console.error('Invalid columnId');
return;
}
if (!model.cells[rowId]) {
model.cells[rowId] = Object.create(null);
if (!model.props.cells[rowId]) {
model.props.cells[rowId] = Object.create(null);
}
if (model.cells[rowId]) {
model.cells[rowId][columnId] = {
if (model.props.cells[rowId]) {
model.props.cells[rowId][columnId] = {
columnId: columnId,
value: cell.value,
};
@@ -189,11 +189,11 @@ export function updateCells(
) {
throw new Error('Invalid rowId');
}
if (!model.cells[rowId]) {
model.cells[rowId] = Object.create(null);
if (!model.props.cells[rowId]) {
model.props.cells[rowId] = Object.create(null);
}
if (model.cells[rowId]) {
model.cells[rowId][columnId] = {
if (model.props.cells[rowId]) {
model.props.cells[rowId][columnId] = {
columnId,
value,
};
@@ -208,17 +208,17 @@ export function updateProperty(
updater: ColumnUpdater,
defaultValue?: Record<string, unknown>
) {
const index = model.columns.findIndex(v => v.id === id);
const index = model.props.columns.findIndex(v => v.id === id);
if (index == null) {
return;
}
model.doc.transact(() => {
const column = model.columns[index];
const column = model.props.columns[index];
if (!column) {
return;
}
const result = updater(column);
model.columns[index] = { ...defaultValue, ...column, ...result };
model.props.columns[index] = { ...defaultValue, ...column, ...result };
});
return id;
}
@@ -229,7 +229,7 @@ export const updateView = <ViewData extends ViewBasicDataType>(
update: (data: ViewData) => Partial<ViewData>
) => {
model.doc.transact(() => {
model.views = model.views.map(v => {
model.props.views = model.props.views.map(v => {
if (v.id !== id) {
return v;
}

View File

@@ -60,7 +60,7 @@ export const insertEdgelessTextCommand: Command<
if (!editing || id !== textId) {
const textBlock = host.view.getBlock(textId);
if (textBlock instanceof EdgelessTextBlockComponent) {
textBlock.model.hasMaxWidth = true;
textBlock.model.props.hasMaxWidth = true;
}
disposable.unsubscribe();

View File

@@ -43,7 +43,7 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBl
return;
}
if (!this.model.hasMaxWidth) {
if (!this.model.props.hasMaxWidth) {
this._updateW();
}
@@ -213,14 +213,14 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBl
);
});
disposables.addFromEvent(this, 'compositionend', () => {
if (this.model.hasMaxWidth) {
if (this.model.props.hasMaxWidth) {
composingWidth = EDGELESS_TEXT_BLOCK_MIN_WIDTH;
return;
}
// when IME finish container will crash to a small width, so
// we set a max width to prevent this
this._textContainer.style.width = `${composingWidth}px`;
this.model.hasMaxWidth = true;
this.model.props.hasMaxWidth = true;
requestAnimationFrame(() => {
this._textContainer.style.width = '';
});
@@ -237,11 +237,11 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBl
const deltaX = scaledX - bound.x;
const deltaY = scaledY - bound.y;
return `translate(${translateX + deltaX}px, ${translateY + deltaY}px) scale(${zoom * this.model.scale})`;
return `translate(${translateX + deltaX}px, ${translateY + deltaY}px) scale(${zoom * this.model.props.scale})`;
}
override getRenderingRect() {
const { xywh, scale, rotate, hasMaxWidth } = this.model;
const { xywh, scale, rotate, hasMaxWidth } = this.model.props;
const bound = Bound.deserialize(xywh);
const w = hasMaxWidth ? bound.w / scale : undefined;
@@ -257,7 +257,7 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBl
override renderGfxBlock() {
const { model } = this;
const { rotate, hasMaxWidth } = model;
const { rotate, hasMaxWidth } = model.props;
const editing = this._editing;
const containerStyle: StyleInfo = {
transform: `rotate(${rotate}deg)`,
@@ -291,10 +291,10 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBl
}
override renderPageContent() {
const { fontFamily, fontStyle, fontWeight, textAlign } = this.model;
const { fontFamily, fontStyle, fontWeight, textAlign } = this.model.props;
const color = this.std
.get(ThemeProvider)
.generateColorProperty(this.model.color, '#000000');
.generateColorProperty(this.model.props.color, '#000000');
const style = styleMap({
'--edgeless-text-color': color,

View File

@@ -37,7 +37,7 @@ export function renderLinkedDocInCard(
const linkedDoc = card.linkedDoc;
if (!linkedDoc) {
console.error(
`Trying to load page ${card.model.pageId} in linked page block, but the page is not found.`
`Trying to load page ${card.model.props.pageId} in linked page block, but the page is not found.`
);
return;
}
@@ -62,7 +62,7 @@ async function renderPageAsBanner(card: EmbedSyncedDocCard) {
const linkedDoc = card.linkedDoc;
if (!linkedDoc) {
console.error(
`Trying to load page ${card.model.pageId} in linked page block, but the page is not found.`
`Trying to load page ${card.model.props.pageId} in linked page block, but the page is not found.`
);
return;
}
@@ -89,7 +89,7 @@ async function renderImageAsBanner(
card: EmbedSyncedDocCard,
image: BlockModel
) {
const sourceId = (image as ImageBlockModel).sourceId;
const sourceId = (image as ImageBlockModel).props.sourceId;
if (!sourceId) return;
const storage = card.linkedDoc?.blobSync;
@@ -131,7 +131,7 @@ async function renderNoteContent(
const doc = card.linkedDoc;
if (!doc) {
console.error(
`Trying to load page ${card.model.pageId} in linked page block, but the page is not found.`
`Trying to load page ${card.model.props.pageId} in linked page block, but the page is not found.`
);
return;
}
@@ -141,7 +141,7 @@ async function renderNoteContent(
return;
}
const cardStyle = card.model.style;
const cardStyle = card.model.props.style;
const isHorizontal = cardStyle === 'horizontal';
const allowFlavours = isHorizontal ? [] : [ImageBlockModel];
@@ -230,7 +230,7 @@ export function getNotesFromDoc(doc: Store) {
const notes = doc.root?.children.filter(
child =>
matchModels(child, [NoteBlockModel]) &&
child.displayMode !== NoteDisplayMode.EdgelessOnly
child.props.displayMode !== NoteDisplayMode.EdgelessOnly
);
if (!notes || !notes.length) {
@@ -313,8 +313,8 @@ export function getTitleFromSelectedModels(selectedModels: DraftModel[]) {
model: DraftModel
): model is DraftModel<ParagraphBlockModel> =>
model.flavour === 'affine:paragraph';
if (isParagraph(firstBlock) && firstBlock.type.startsWith('h')) {
return firstBlock.text?.toString();
if (isParagraph(firstBlock) && firstBlock.props.type.startsWith('h')) {
return firstBlock.props.text.toString();
}
return undefined;
}

View File

@@ -55,7 +55,7 @@ export function createBuiltinToolbarConfigForExternal(
const model = ctx.getCurrentBlockBy(BlockSelection)?.model;
if (!model || !isExternalEmbedModel(model)) return null;
const { url } = model;
const { url } = model.props;
const options = ctx.std
.get(EmbedOptionProvider)
.getEmbedBlockOptions(url);
@@ -75,7 +75,8 @@ export function createBuiltinToolbarConfigForExternal(
const model = ctx.getCurrentBlockBy(BlockSelection)?.model;
if (!model || !isExternalEmbedModel(model)) return;
const { title, caption, url: link, parent } = model;
const { title, caption, url: link } = model.props;
const { parent } = model;
const index = parent?.children.indexOf(model);
const yText = new Y.Text();
@@ -107,7 +108,7 @@ export function createBuiltinToolbarConfigForExternal(
const model = ctx.getCurrentBlockBy(BlockSelection)?.model;
if (!model || !isExternalEmbedModel(model)) return true;
const { url } = model;
const { url } = model.props;
const options = ctx.std
.get(EmbedOptionProvider)
.getEmbedBlockOptions(url);
@@ -118,13 +119,14 @@ export function createBuiltinToolbarConfigForExternal(
const model = ctx.getCurrentBlockBy(BlockSelection)?.model;
if (!model || !isExternalEmbedModel(model)) return;
const { url, caption, parent } = model;
const { url, caption } = model.props;
const { parent } = model;
const index = parent?.children.indexOf(model);
const options = ctx.std
.get(EmbedOptionProvider)
.getEmbedBlockOptions(url);
let { style } = model;
let { style } = model.props;
let flavour = 'affine:bookmark';
if (options?.viewType === 'card') {
@@ -166,7 +168,7 @@ export function createBuiltinToolbarConfigForExternal(
const model = ctx.getCurrentBlockBy(BlockSelection)?.model;
if (!model || !isExternalEmbedModel(model)) return false;
const { url } = model;
const { url } = model.props;
const options = ctx.std
.get(EmbedOptionProvider)
.getEmbedBlockOptions(url);
@@ -177,7 +179,7 @@ export function createBuiltinToolbarConfigForExternal(
const model = ctx.getCurrentBlockBy(BlockSelection)?.model;
if (!model || !isExternalEmbedModel(model)) return false;
const { url } = model;
const { url } = model.props;
const options = ctx.std
.get(EmbedOptionProvider)
.getEmbedBlockOptions(url);
@@ -188,7 +190,8 @@ export function createBuiltinToolbarConfigForExternal(
const model = ctx.getCurrentBlockBy(BlockSelection)?.model;
if (!model || !isExternalEmbedModel(model)) return;
const { url, caption, parent } = model;
const { url, caption } = model.props;
const { parent } = model;
const index = parent?.children.indexOf(model);
const options = ctx.std
.get(EmbedOptionProvider)
@@ -197,7 +200,7 @@ export function createBuiltinToolbarConfigForExternal(
if (options?.viewType !== 'embed') return;
const { flavour, styles } = options;
let { style } = model;
let { style } = model.props;
if (!styles.includes(style)) {
style =
@@ -231,7 +234,7 @@ export function createBuiltinToolbarConfigForExternal(
const model = ctx.getCurrentBlockBy(BlockSelection)?.model;
if (!model || !isExternalEmbedModel(model)) return null;
const { url } = model;
const { url } = model.props;
const viewType =
ctx.std.get(EmbedOptionProvider).getEmbedBlockOptions(url)
?.viewType ?? 'card';
@@ -309,7 +312,7 @@ export function createBuiltinToolbarConfigForExternal(
.actions=${actions}
.context=${ctx}
.toggle=${toggle}
.style$=${model.style$}
.style$=${model.props.style$}
></affine-card-style-dropdown-menu>`
)}`;
},

View File

@@ -22,7 +22,7 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<EmbedFigmaMode
protected _isResizing = false;
open = () => {
let link = this.model.url;
let link = this.model.props.url;
if (!link.match(/^[a-zA-Z]+:\/\//)) {
link = 'https://' + link;
}
@@ -51,9 +51,9 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<EmbedFigmaMode
override connectedCallback() {
super.connectedCallback();
this._cardStyle = this.model.style;
this._cardStyle = this.model.props.style;
if (!this.model.title) {
if (!this.model.props.title) {
this.doc.withoutTransact(() => {
this.doc.updateBlock(this.model, {
title: 'Figma',
@@ -90,7 +90,7 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<EmbedFigmaMode
}
override renderBlock() {
const { title, description, url } = this.model;
const { title, description, url } = this.model.props;
const titleText = title ?? 'Figma';
return this.renderEmbed(

View File

@@ -31,7 +31,7 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
override _cardStyle: (typeof EmbedGithubStyles)[number] = 'horizontal';
open = () => {
let link = this.model.url;
let link = this.model.props.url;
if (!link.match(/^[a-zA-Z]+:\/\//)) {
link = 'https://' + link;
}
@@ -75,11 +75,15 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
override connectedCallback() {
super.connectedCallback();
this._cardStyle = this.model.style;
this._cardStyle = this.model.props.style;
if (!this.model.owner || !this.model.repo || !this.model.githubId) {
if (
!this.model.props.owner ||
!this.model.props.repo ||
!this.model.props.githubId
) {
this.doc.withoutTransact(() => {
const url = this.model.url;
const url = this.model.props.url;
const urlMatch = url.match(githubUrlRegex);
if (urlMatch) {
const [, owner, repo, githubType, githubId] = urlMatch;
@@ -94,7 +98,7 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
}
this.doc.withoutTransact(() => {
if (!this.model.description && !this.model.title) {
if (!this.model.props.description && !this.model.props.title) {
this.refreshData();
} else {
this.refreshStatus();
@@ -123,7 +127,7 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
description,
image,
style,
} = this.model;
} = this.model.props;
const loading = this.loading;
const theme = this.std.get(ThemeProvider).theme;

View File

@@ -24,7 +24,7 @@ export async function queryEmbedGithubData(
): Promise<Partial<EmbedGithubBlockUrlData>> {
const [githubApiData, openGraphData] = await Promise.all([
queryEmbedGithubApiData(embedGithubModel, signal),
linkPreviewer.query(embedGithubModel.url, signal),
linkPreviewer.query(embedGithubModel.props.url, signal),
]);
return { ...githubApiData, ...openGraphData };
}
@@ -33,7 +33,7 @@ export async function queryEmbedGithubApiData(
embedGithubModel: EmbedGithubModel,
signal?: AbortSignal
): Promise<Partial<EmbedGithubBlockUrlData>> {
const { owner, repo, githubType, githubId } = embedGithubModel;
const { owner, repo, githubType, githubId } = embedGithubModel.props;
let githubApiData: Partial<EmbedGithubBlockUrlData> = {};
// github's public api has a rate limit of 60 requests per hour

View File

@@ -108,7 +108,7 @@ export class EmbedHtmlFullscreenToolbar extends LitElement {
this.embedHtml.std.clipboard
.writeToClipboard(items => {
items['text/plain'] = this.embedHtml.model.html ?? '';
items['text/plain'] = this.embedHtml.model.props.html ?? '';
return items;
})
.then(() => {

View File

@@ -88,7 +88,7 @@ export const builtinToolbarConfig = {
.actions=${actions}
.context=${ctx}
.toggle=${toggle}
.style$=${model.style$}
.style=${model.props.style$}
></affine-card-style-dropdown-menu>`
)}`;
},

View File

@@ -49,7 +49,7 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent<EmbedHtmlModel>
override connectedCallback() {
super.connectedCallback();
this._cardStyle = this.model.style;
this._cardStyle = this.model.props.style;
// this is required to prevent iframe from capturing pointer events
this.disposables.add(
@@ -80,11 +80,11 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent<EmbedHtmlModel>
margin: 0;
}
</style>
${this.model.html}
${this.model.props.html}
`;
return this.renderEmbed(() => {
if (!this.model.html) {
if (!this.model.props.html) {
return html` <div class="affine-html-empty">Empty</div>`;
}
return html`

View File

@@ -155,7 +155,7 @@ export class EmbedIframeLinkEditPopup extends SignalWatcher(
override render() {
const isInputEmpty = this._isInputEmpty();
const { url$ } = this.model;
const { url$ } = this.model.props;
return html`
<div class="embed-iframe-link-edit-popup">

View File

@@ -49,7 +49,8 @@ export const builtinToolbarConfig = {
);
if (!model) return;
const { title, caption, url, parent } = model;
const { title, caption, url } = model.props;
const { parent } = model;
const index = parent?.children.indexOf(model);
const yText = new Y.Text();
@@ -84,7 +85,8 @@ export const builtinToolbarConfig = {
);
if (!model) return;
const { url, caption, parent } = model;
const { url, caption } = model.props;
const { parent } = model;
const index = parent?.children.indexOf(model);
const flavour = 'affine:bookmark';

View File

@@ -37,8 +37,8 @@ export class EmbedEdgelessIframeBlockComponent extends toGfxBlockComponent(
return nothing;
}
const bound = Bound.deserialize(this.model.xywh$.value);
const scale = this.model.scale$.value;
const bound = Bound.deserialize(this.model.props.xywh$.value);
const scale = this.model.props.scale$.value;
const width = bound.w / scale;
const height = bound.h / scale;
const style = {

View File

@@ -75,7 +75,7 @@ export class EmbedIframeBlockComponent extends CaptionedBlockComponent<EmbedIfra
}
open = () => {
const link = this.model.url;
const link = this.model.props.url;
window.open(link, '_blank');
};
@@ -95,7 +95,7 @@ export class EmbedIframeBlockComponent extends CaptionedBlockComponent<EmbedIfra
);
}
const { url } = this.model;
const { url } = this.model.props;
if (!url) {
throw new BlockSuiteError(
ErrorCode.ValueNotExists,
@@ -110,7 +110,7 @@ export class EmbedIframeBlockComponent extends CaptionedBlockComponent<EmbedIfra
]);
// if the embed data is not found, and the iframeUrl is not set, throw an error
const currentIframeUrl = this.model.iframeUrl;
const currentIframeUrl = this.model.props.iframeUrl;
if (!embedData && !currentIframeUrl) {
throw new BlockSuiteError(
ErrorCode.ValueNotExists,
@@ -172,7 +172,7 @@ export class EmbedIframeBlockComponent extends CaptionedBlockComponent<EmbedIfra
};
private readonly _renderIframe = () => {
const { iframeUrl } = this.model;
const { iframeUrl } = this.model.props;
const {
widthPercent,
heightInNote,
@@ -226,13 +226,13 @@ export class EmbedIframeBlockComponent extends CaptionedBlockComponent<EmbedIfra
this.contentEditable = 'false';
if (!this.model.iframeUrl) {
if (!this.model.props.iframeUrl) {
this.doc.withoutTransact(() => {
this.refreshData().catch(console.error);
});
} else {
// update iframe options, to ensure the iframe is rendered with the correct options
this._updateIframeOptions(this.model.url);
this._updateIframeOptions(this.model.props.url);
this.status$.value = 'success';
}

View File

@@ -44,10 +44,10 @@ export const builtinToolbarConfig = {
if (!component) return null;
const model = component.model;
if (!model.title) return null;
if (!model.props.title) return null;
const originalTitle =
ctx.workspace.getDoc(model.pageId)?.meta?.title || 'Untitled';
ctx.workspace.getDoc(model.props.pageId)?.meta?.title || 'Untitled';
return html`<affine-linked-doc-title
.title=${originalTitle}
@@ -99,10 +99,10 @@ export const builtinToolbarConfig = {
const model = component.model;
// same doc
if (model.pageId === ctx.store.id) return true;
if (model.props.pageId === ctx.store.id) return true;
// linking to block
if (referenceToNode(model)) return true;
if (referenceToNode(model.props)) return true;
return false;
},
@@ -197,7 +197,7 @@ export const builtinToolbarConfig = {
.actions=${actions}
.context=${ctx}
.toggle=${toggle}
.style$=${model.style$}
.style$=${model.props.style$}
></affine-card-style-dropdown-menu>`
)}`;
},

View File

@@ -20,7 +20,8 @@ export class EmbedEdgelessLinkedDocBlockComponent extends toEdgelessEmbedBlock(
EmbedLinkedDocBlockComponent
) {
override convertToEmbed = () => {
const { id, doc, caption, xywh } = this.model;
const { caption, xywh } = this.model.props;
const { doc, id } = this.model;
const style = 'syncedDoc';
const bound = Bound.deserialize(xywh);

View File

@@ -102,7 +102,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
}
if (!this.isError) {
const cardStyle = this.model.style;
const cardStyle = this.model.props.style;
if (cardStyle === 'horizontal' || cardStyle === 'vertical') {
renderLinkedDocInCard(this);
}
@@ -118,7 +118,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
};
private readonly _setDocUpdatedAt = () => {
const meta = this.doc.workspace.meta.getDocMeta(this.model.pageId);
const meta = this.doc.workspace.meta.getDocMeta(this.model.props.pageId);
if (meta) {
const date = meta.updatedDate || meta.createDate;
this._docUpdatedAt = new Date(date);
@@ -130,7 +130,8 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
convertToEmbed = () => {
if (this._referenceToNode) return;
const { doc, caption, parent } = this.model;
const { caption } = this.model.props;
const { parent, doc } = this.model;
const index = parent?.children.indexOf(this.model);
const blockId = doc.addBlock(
@@ -181,7 +182,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
};
referenceInfo$ = computed(() => {
const { pageId, params, title$, description$ } = this.model;
const { pageId, params, title$, description$ } = this.model.props;
return cloneReferenceInfo({
pageId,
params,
@@ -229,7 +230,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
});
get docTitle() {
return this.model.title || this.linkedDoc?.meta?.title || 'Untitled';
return this.model.props.title || this.linkedDoc?.meta?.title || 'Untitled';
}
get editorMode() {
@@ -237,8 +238,8 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
}
get linkedDoc() {
return this.std.workspace.getDoc(this.model.pageId, {
id: this.model.pageId,
return this.std.workspace.getDoc(this.model.props.pageId, {
id: this.model.props.pageId,
});
}
@@ -275,8 +276,8 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
override connectedCallback() {
super.connectedCallback();
this._cardStyle = this.model.style;
this._referenceToNode = referenceToNode(this.model);
this._cardStyle = this.model.props.style;
this._referenceToNode = referenceToNode(this.model.props);
this._load().catch(e => {
console.error(e);
@@ -325,14 +326,14 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
);
if (this._referenceToNode) {
this._linkedDocMode = this.model.params?.mode ?? 'page';
this._linkedDocMode = this.model.props.params?.mode ?? 'page';
} else {
const docMode = this.std.get(DocModeProvider);
this._linkedDocMode = docMode.getPrimaryMode(this.model.pageId);
this._linkedDocMode = docMode.getPrimaryMode(this.model.props.pageId);
this.disposables.add(
docMode.onPrimaryModeChange(mode => {
this._linkedDocMode = mode;
}, this.model.pageId)
}, this.model.props.pageId)
);
}
}
@@ -340,7 +341,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
this.disposables.add(
this.model.propsUpdated.subscribe(({ key }) => {
if (key === 'style') {
this._cardStyle = this.model.style;
this._cardStyle = this.model.props.style;
}
if (key === 'pageId' || key === 'style') {
this._load().catch(e => {
@@ -395,7 +396,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
? LoadingIcon
: this.icon$.value;
const title = isLoading ? 'Loading...' : this.title$;
const description = this.model.description$;
const description = this.model.props.description$;
const showDefaultNoteContent = isError || isLoading || isDeleted || isEmpty;
const defaultNoteContent = isError
@@ -503,7 +504,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
override updated() {
// update card style when linked doc deleted
const linkedDoc = this.linkedDoc;
const { xywh, style } = this.model;
const { xywh, style } = this.model.props;
const bound = Bound.deserialize(xywh);
if (linkedDoc && style === 'horizontalThin') {
bound.w = EMBED_CARD_WIDTH.horizontal;

View File

@@ -27,7 +27,7 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
protected _isResizing = false;
open = () => {
let link = this.model.url;
let link = this.model.props.url;
if (!link.match(/^[a-zA-Z]+:\/\//)) {
link = 'https://' + link;
}
@@ -60,11 +60,11 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
override connectedCallback() {
super.connectedCallback();
this._cardStyle = this.model.style;
this._cardStyle = this.model.props.style;
if (!this.model.videoId) {
if (!this.model.props.videoId) {
this.doc.withoutTransact(() => {
const url = this.model.url;
const url = this.model.props.url;
const urlMatch = url.match(loomUrlRegex);
if (urlMatch) {
const [, videoId] = urlMatch;
@@ -75,7 +75,7 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
});
}
if (!this.model.description && !this.model.title) {
if (!this.model.props.description && !this.model.props.title) {
this.doc.withoutTransact(() => {
this.refreshData();
});
@@ -111,7 +111,7 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
}
override renderBlock() {
const { image, title = 'Loom', description, videoId } = this.model;
const { image, title = 'Loom', description, videoId } = this.model.props;
const loading = this.loading;
const theme = this.std.get(ThemeProvider).theme;

View File

@@ -12,7 +12,7 @@ export async function queryEmbedLoomData(
embedLoomModel: EmbedLoomModel,
signal?: AbortSignal
): Promise<Partial<EmbedLoomBlockUrlData>> {
const url = embedLoomModel.url;
const url = embedLoomModel.props.url;
const loomEmbedData: Partial<EmbedLoomBlockUrlData> =
await queryLoomOEmbedData(url, signal);

View File

@@ -65,7 +65,7 @@ export const builtinToolbarConfig = {
return {
...action,
disabled: shouldOpenInActiveView
? component.model.pageId === ctx.store.id
? component.model.props.pageId === ctx.store.id
: false,
when: allowed,
run: (_ctx: ToolbarContext) =>

View File

@@ -37,7 +37,7 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
position: 'relative',
width: '100%',
});
const modelScale = this.model.scale ?? 1;
const modelScale = this.model.props.scale ?? 1;
const bound = Bound.deserialize(this.model.xywh);
const width = bound.w / modelScale;
const height = bound.h / modelScale;
@@ -58,7 +58,7 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
}
const theme = this.isPageMode ? appTheme : edgelessTheme;
const scale = this.model.scale ?? 1;
const scale = this.model.props.scale ?? 1;
this.dataset.nestedEditor = '';
@@ -121,7 +121,8 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
};
override convertToCard = (aliasInfo?: AliasInfo) => {
const { id, doc, caption, xywh } = this.model;
const { id, doc, xywh } = this.model;
const { caption } = this.model.props;
const style = 'vertical';
const bound = Bound.deserialize(xywh);
@@ -155,7 +156,7 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
};
override renderGfxBlock() {
const { style, xywh } = this.model;
const { style, xywh } = this.model.props;
const bound = Bound.deserialize(xywh);
this.embedContainerStyle.width = `${bound.w}px`;

View File

@@ -280,7 +280,8 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
});
convertToCard = (aliasInfo?: AliasInfo) => {
const { doc, caption } = this.model;
const { doc } = this.model;
const { caption } = this.model.props;
const parent = doc.getParent(this.model);
if (!parent) {
@@ -343,14 +344,14 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
};
icon$ = computed(() => {
const { pageId, params } = this.model;
const { pageId, params } = this.model.props;
return this.std
.get(DocDisplayMetaProvider)
.icon(pageId, { params, referenced: true }).value;
});
open = (event?: Partial<DocLinkClickedEvent>) => {
const pageId = this.model.pageId;
const pageId = this.model.props.pageId;
if (pageId === this.doc.id) return;
this.std
@@ -366,7 +367,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
};
title$ = computed(() => {
const { pageId, params } = this.model;
const { pageId, params } = this.model.props;
return this.std
.get(DocDisplayMetaProvider)
.title(pageId, { params, referenced: true });
@@ -402,19 +403,20 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
}
get referenceInfo(): ReferenceInfo {
return cloneReferenceInfo(this.model);
return cloneReferenceInfo(this.model.props);
}
get syncedDoc() {
const options: GetBlocksOptions = { readonly: true };
if (this.isPageMode) options.query = this._pageFilter;
return this.std.workspace.getDoc(this.model.pageId, options);
return this.std.workspace.getDoc(this.model.props.pageId, options);
}
private _checkCycle() {
let editorHost: EditorHost | null = this.host;
while (editorHost && !this._cycle) {
this._cycle = !!editorHost && editorHost.doc.id === this.model.pageId;
this._cycle =
!!editorHost && editorHost.doc.id === this.model.props.pageId;
editorHost = editorHost.parentElement?.closest('editor-host') ?? null;
}
}
@@ -483,7 +485,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
}
private _setDocUpdatedAt() {
const meta = this.doc.workspace.meta.getDocMeta(this.model.pageId);
const meta = this.doc.workspace.meta.getDocMeta(this.model.props.pageId);
if (meta) {
const date = meta.updatedDate || meta.createDate;
this._docUpdatedAt = new Date(date);
@@ -496,7 +498,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
override connectedCallback() {
super.connectedCallback();
this._cardStyle = this.model.style;
this._cardStyle = this.model.props.style;
this.style.display = 'block';
this._load().catch(e => {
@@ -526,13 +528,13 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
if (!this.linkedMode) {
const docMode = this.std.get(DocModeProvider);
this.syncedDocMode = docMode.getPrimaryMode(this.model.pageId);
this.syncedDocMode = docMode.getPrimaryMode(this.model.props.pageId);
this._isEmptySyncedDoc = isEmptyDoc(this.syncedDoc, this.editorMode);
this.disposables.add(
docMode.onPrimaryModeChange(mode => {
this.syncedDocMode = mode;
this._isEmptySyncedDoc = isEmptyDoc(this.syncedDoc, this.editorMode);
}, this.model.pageId)
}, this.model.props.pageId)
);
}

View File

@@ -30,7 +30,7 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
protected _isResizing = false;
open = () => {
let link = this.model.url;
let link = this.model.props.url;
if (!link.match(/^[a-zA-Z]+:\/\//)) {
link = 'https://' + link;
}
@@ -63,11 +63,11 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
override connectedCallback() {
super.connectedCallback();
this._cardStyle = this.model.style;
this._cardStyle = this.model.props.style;
if (!this.model.videoId) {
if (!this.model.props.videoId) {
this.doc.withoutTransact(() => {
const url = this.model.url;
const url = this.model.props.url;
const urlMatch = url.match(youtubeUrlRegex);
if (urlMatch) {
const [, videoId] = urlMatch;
@@ -78,7 +78,7 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
});
}
if (!this.model.description && !this.model.title) {
if (!this.model.props.description && !this.model.props.title) {
this.doc.withoutTransact(() => {
this.refreshData();
});
@@ -125,7 +125,7 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
creator,
creatorImage,
videoId,
} = this.model;
} = this.model.props;
const loading = this.loading;
const theme = this.std.get(ThemeProvider).theme;

View File

@@ -12,7 +12,7 @@ export async function queryEmbedYoutubeData(
linkPreviewer: LinkPreviewerService,
signal?: AbortSignal
): Promise<Partial<EmbedYoutubeBlockUrlData>> {
const url = embedYoutubeModel.url;
const url = embedYoutubeModel.props.url;
const [videoOpenGraphData, videoOEmbedData] = await Promise.all([
linkPreviewer.query(url, signal),

View File

@@ -56,7 +56,7 @@ export class FrameBlockComponent extends GfxBlockComponent<FrameBlockModel> {
const { model, showBorder, std } = this;
const backgroundColor = std
.get(ThemeProvider)
.generateColorProperty(model.background, DefaultTheme.transparent);
.generateColorProperty(model.props.background, DefaultTheme.transparent);
const _isNavigator =
this.gfx.tool.currentToolName$.value === 'frameNavigator';
const frameIndex = this.gfx.layer.getZIndex(model);

View File

@@ -154,7 +154,9 @@ export class EdgelessFrameManager extends GfxExtension {
}
static framePresentationComparator<
T extends FrameBlockModel | { index: string; presentationIndex?: string },
T extends
| FrameBlockModel
| { props: { index: string; presentationIndex?: string } },
>(a: T, b: T) {
function stringCompare(a: string, b: string) {
if (a < b) return -1;
@@ -162,29 +164,40 @@ export class EdgelessFrameManager extends GfxExtension {
return 0;
}
const isModel = (
x:
| FrameBlockModel
| { props: { index: string; presentationIndex?: string } }
): x is FrameBlockModel => {
return 'presentationIndex$' in x;
};
if (
'presentationIndex$' in a &&
'presentationIndex$' in b &&
a.presentationIndex$.value &&
b.presentationIndex$.value
isModel(a) &&
isModel(b) &&
a.props.presentationIndex$.value &&
b.props.presentationIndex$.value
) {
return stringCompare(
a.presentationIndex$.value,
b.presentationIndex$.value
a.props.presentationIndex$.value,
b.props.presentationIndex$.value
);
} else if (a.presentationIndex && b.presentationIndex) {
return stringCompare(a.presentationIndex, b.presentationIndex);
} else if (a.presentationIndex) {
} else if (a.props.presentationIndex && b.props.presentationIndex) {
return stringCompare(
a.props.presentationIndex,
b.props.presentationIndex
);
} else if (a.props.presentationIndex) {
return -1;
} else if (b.presentationIndex) {
} else if (b.props.presentationIndex) {
return 1;
} else {
return stringCompare(a.index, b.index);
return stringCompare(a.props.index, b.props.index);
}
}
private _addChildrenToLegacyFrame(frame: FrameBlockModel) {
if (frame.childElementIds !== undefined) return;
if (frame.props.childElementIds !== undefined) return;
const elements = this.getElementsInFrameBound(frame);
const childElements = elements.filter(
element => this.getParentFrame(element) === null && element !== frame
@@ -281,7 +294,7 @@ export class EdgelessFrameManager extends GfxExtension {
addElementsToFrame(frame: FrameBlockModel, elements: GfxModel[]) {
if (frame.isLocked()) return;
if (frame.childElementIds === undefined) {
if (frame.props.childElementIds === undefined) {
this._addChildrenToLegacyFrame(frame);
}
@@ -369,7 +382,7 @@ export class EdgelessFrameManager extends GfxExtension {
generatePresentationIndex() {
const before =
this.frames[this.frames.length - 1]?.presentationIndex ?? null;
this.frames[this.frames.length - 1]?.props.presentationIndex ?? null;
return generateKeyBetweenV2(before, null);
}
@@ -380,7 +393,7 @@ export class EdgelessFrameManager extends GfxExtension {
* 2. Return all child elements of the frame if `childElements` exists.
*/
getChildElementsInFrame(frame: FrameBlockModel): GfxModel[] {
if (frame.childElementIds === undefined) {
if (frame.props.childElementIds === undefined) {
return this.getElementsInFrameBound(frame).filter(
element => this.getParentFrame(element) !== null
);
@@ -431,24 +444,25 @@ export class EdgelessFrameManager extends GfxExtension {
refreshLegacyFrameOrder() {
const frames = this.frames.splice(0, this.frames.length);
let splitIndex = frames.findIndex(frame => frame.presentationIndex);
let splitIndex = frames.findIndex(frame => frame.props.presentationIndex);
if (splitIndex === 0) return;
if (splitIndex === -1) splitIndex = frames.length;
let afterPreIndex =
frames[splitIndex]?.presentationIndex || generateKeyBetweenV2(null, null);
frames[splitIndex]?.props.presentationIndex ||
generateKeyBetweenV2(null, null);
for (let index = splitIndex - 1; index >= 0; index--) {
const preIndex = generateKeyBetweenV2(null, afterPreIndex);
frames[index].presentationIndex = preIndex;
frames[index].props.presentationIndex = preIndex;
afterPreIndex = preIndex;
}
}
removeAllChildrenFromFrame(frame: FrameBlockModel) {
this.gfx.doc.transact(() => {
frame.childElementIds = {};
frame.props.childElementIds = {};
});
}

View File

@@ -94,8 +94,8 @@ export class ImageBlockFallbackCard extends WithDisposable(ShadowlessElement) {
: 'Image';
const size =
!!model.size && model.size > 0
? humanFileSize(model.size, true, 0)
!!model.props.size && model.props.size > 0
? humanFileSize(model.props.size, true, 0)
: null;
return html`

View File

@@ -249,7 +249,7 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
};
}
const { width, height } = this._model;
const { width, height } = this._model.props;
if (!width || !height) {
return {
width: 'unset',

View File

@@ -42,7 +42,7 @@ export class ImageEdgelessBlockComponent extends GfxBlockComponent<ImageBlockMod
this.retryCount = 0;
fetchImageBlob(this)
.then(() => {
const { width, height } = this.model;
const { width, height } = this.model.props;
if ((!width || !height) && this.blob) {
return resetImageSize(this);
}

View File

@@ -97,7 +97,7 @@ export async function uploadBlobForImage(
}
async function getImageBlob(model: ImageBlockModel) {
const sourceId = model.sourceId;
const sourceId = model.props.sourceId;
if (!sourceId) {
return null;
}
@@ -131,7 +131,7 @@ export async function fetchImageBlob(
block: ImageBlockComponent | ImageEdgelessBlockComponent
) {
try {
if (block.model.sourceId !== block.lastSourceId || !block.blobUrl) {
if (block.model.props.sourceId !== block.lastSourceId || !block.blobUrl) {
block.loading = true;
block.error = false;
block.blob = undefined;
@@ -145,7 +145,8 @@ export async function fetchImageBlob(
}
const { model } = block;
const { id, sourceId, doc } = model;
const { sourceId } = model.props;
const { id, doc } = model;
if (isImageUploading(id)) {
return;
@@ -405,7 +406,7 @@ export async function turnImageIntoCardView(
}
const model = block.model;
const sourceId = model.sourceId;
const sourceId = model.props.sourceId;
const blob = await getImageBlob(model);
if (!sourceId || !blob) {
console.error('Image data not available');
@@ -413,14 +414,17 @@ export async function turnImageIntoCardView(
}
const { saveImageData, getAttachmentData } = withTempBlobData();
saveImageData(sourceId, { width: model.width, height: model.height });
saveImageData(sourceId, {
width: model.props.width,
height: model.props.height,
});
const attachmentConvertData = getAttachmentData(sourceId);
const attachmentProp: Partial<AttachmentBlockProps> = {
sourceId,
name: DEFAULT_ATTACHMENT_NAME,
size: blob.size,
type: blob.type,
caption: model.caption,
caption: model.props.caption,
...attachmentConvertData,
};
transformModel(model, 'affine:attachment', attachmentProp);

View File

@@ -43,7 +43,7 @@ export class LatexBlockComponent extends CaptionedBlockComponent<LatexBlockModel
disposables.add(
effect(() => {
const latex = this.model.latex$.value;
const latex = this.model.props.latex$.value;
katexContainer.replaceChildren();
// @ts-expect-error lit hack won't fix
@@ -119,7 +119,7 @@ export class LatexBlockComponent extends CaptionedBlockComponent<LatexBlockModel
const portal = createLitPortal({
template: html`<latex-editor-menu
.std=${this.std}
.latexSignal=${this.model.latex$}
.latexSignal=${this.model.props.latex$}
.abortController=${this._editorAbortController}
></latex-editor-menu>`,
container: this.host,

View File

@@ -127,7 +127,7 @@ export const indentListCommand: Command<{
if (
nearestHeading &&
matchModels(nearestHeading, [ParagraphBlockModel]) &&
nearestHeading.collapsed
nearestHeading.props.collapsed
) {
store.updateBlock(nearestHeading, {
collapsed: false,

View File

@@ -35,7 +35,7 @@ export const splitListCommand: Command<{
doc.captureSync();
if (model.text.length === 0) {
if (model.props.text.length === 0) {
/**
* case 1: target is top most, convert the list into a paragraph
*
@@ -65,7 +65,7 @@ export const splitListCommand: Command<{
let base = 1;
nextContinuousNumberedLists.forEach(list => {
doc.transact(() => {
list.order = base;
list.props.order = base;
});
base += 1;
});
@@ -114,8 +114,8 @@ export const splitListCommand: Command<{
let newListId: string | null = null;
if (model.children.length > 0 && !model.collapsed) {
const afterText = model.text.split(inlineIndex);
if (model.children.length > 0 && !model.props.collapsed) {
const afterText = model.props.text.split(inlineIndex);
if (inlineIndex === 0) {
/**
* case 3: list has children (list not collapsed), split the list at the start of line
@@ -132,11 +132,11 @@ export const splitListCommand: Command<{
newListId = doc.addBlock(
'affine:list',
{
type: model.type,
type: model.props.type,
text: afterText,
order:
model.type === 'numbered' && model.order !== null
? model.order + 1
model.props.type === 'numbered' && model.props.order !== null
? model.props.order + 1
: null,
},
parent,
@@ -147,15 +147,15 @@ export const splitListCommand: Command<{
// move children to new list
doc.moveBlocks(model.children, newList);
if (model.type === 'numbered' && model.order !== null) {
if (model.props.type === 'numbered' && model.props.order !== null) {
const nextContinuousNumberedLists = getNextContinuousNumberedLists(
doc,
newListId
);
let base = model.order + 2;
let base = model.props.order + 2;
nextContinuousNumberedLists.forEach(list => {
doc.transact(() => {
list.order = base;
list.props.order = base;
});
base += 1;
});
@@ -176,15 +176,15 @@ export const splitListCommand: Command<{
newListId = doc.addBlock(
'affine:list',
{
type: model.type,
type: model.props.type,
text: afterText,
order: model.type === 'numbered' ? 1 : null,
order: model.props.type === 'numbered' ? 1 : null,
},
model,
0
);
if (model.type === 'numbered') {
if (model.props.type === 'numbered') {
const nextContinuousNumberedLists = getNextContinuousNumberedLists(
doc,
newListId
@@ -192,7 +192,7 @@ export const splitListCommand: Command<{
let base = 2;
nextContinuousNumberedLists.forEach(list => {
doc.transact(() => {
list.order = base;
list.props.order = base;
});
base += 1;
});
@@ -223,11 +223,11 @@ export const splitListCommand: Command<{
* - |a
* - bbb
*/
const afterText = model.text.split(inlineIndex);
const afterText = model.props.text.split(inlineIndex);
newListId = doc.addBlock(
'affine:list',
{
type: model.type,
type: model.props.type,
text: afterText,
order: null,
},

View File

@@ -23,7 +23,7 @@ export function correctNumberedListsOrderToPrev(
if (
!matchModels(model, [ListBlockModel]) ||
model.type$.value !== 'numbered'
model.props.type$.value !== 'numbered'
) {
return;
}
@@ -34,19 +34,19 @@ export function correctNumberedListsOrderToPrev(
if (
previousSibling &&
matchModels(previousSibling, [ListBlockModel]) &&
previousSibling.type === 'numbered'
previousSibling.props.type === 'numbered'
) {
if (!previousSibling.order) previousSibling.order = 1;
model.order = previousSibling.order + 1;
if (!previousSibling.props.order) previousSibling.props.order = 1;
model.props.order = previousSibling.props.order + 1;
} else {
model.order = 1;
model.props.order = 1;
}
// step 2
let base = model.order + 1;
let base = model.props.order + 1;
const continuousNumberedLists = getNextContinuousNumberedLists(doc, model);
continuousNumberedLists.forEach(list => {
list.order = base;
list.props.order = base;
base++;
});
};
@@ -60,11 +60,11 @@ export function correctNumberedListsOrderToPrev(
export function correctListOrder(doc: Store, model: ListBlockModel) {
// old numbered list has no order
if (model.type === 'numbered' && !Number.isInteger(model.order)) {
if (model.props.type === 'numbered' && !Number.isInteger(model.props.order)) {
correctNumberedListsOrderToPrev(doc, model, false);
}
// if list is not numbered, order should be null
if (model.type !== 'numbered') {
model.order = null;
if (model.props.type !== 'numbered') {
model.props.order = null;
}
}

View File

@@ -41,24 +41,24 @@ export class ListBlockComponent extends CaptionedBlockComponent<ListBlockModel>
e.stopPropagation();
e.preventDefault();
if (this.model.type === 'toggle') {
if (this.model.props.type === 'toggle') {
if (this.doc.readonly) {
this._readonlyCollapsed = !this._readonlyCollapsed;
} else {
this.doc.captureSync();
this.doc.updateBlock(this.model, {
collapsed: !this.model.collapsed,
collapsed: !this.model.props.collapsed,
});
}
return;
} else if (this.model.type === 'todo') {
} else if (this.model.props.type === 'todo') {
if (this.doc.readonly) return;
this.doc.captureSync();
const checkedPropObj = { checked: !this.model.checked };
const checkedPropObj = { checked: !this.model.props.checked };
this.doc.updateBlock(this.model, checkedPropObj);
if (this.model.checked) {
if (this.model.props.checked) {
const checkEl = this.querySelector('.affine-list-block__todo-prefix');
if (checkEl) {
playCheckAnimation(checkEl).catch(console.error);
@@ -110,22 +110,22 @@ export class ListBlockComponent extends CaptionedBlockComponent<ListBlockModel>
this.disposables.add(
effect(() => {
const collapsed = this.model.collapsed$.value;
const collapsed = this.model.props.collapsed$.value;
this._readonlyCollapsed = collapsed;
})
);
this.disposables.add(
effect(() => {
const type = this.model.type$.value;
const order = this.model.order$.value;
const type = this.model.props.type$.value;
const order = this.model.props.order$.value;
// old numbered list has no order
if (type === 'numbered' && !Number.isInteger(order)) {
correctNumberedListsOrderToPrev(this.doc, this.model, false);
}
// if list is not numbered, order should be null
if (type !== 'numbered' && order !== null) {
this.model.order = null;
this.model.props.order = null;
}
})
);
@@ -141,7 +141,7 @@ export class ListBlockComponent extends CaptionedBlockComponent<ListBlockModel>
const { model, _onClickIcon } = this;
const collapsed = this.doc.readonly
? this._readonlyCollapsed
: model.collapsed;
: model.props.collapsed;
const listIcon = getListIcon(model, !collapsed, _onClickIcon);
@@ -161,7 +161,7 @@ export class ListBlockComponent extends CaptionedBlockComponent<ListBlockModel>
class=${classMap({
'affine-list-rich-text-wrapper': true,
'affine-list--checked':
this.model.type === 'todo' && this.model.checked,
this.model.props.type === 'todo' && this.model.props.checked,
[TOGGLE_BUTTON_PARENT_CLASS]: true,
})}
>
@@ -184,7 +184,7 @@ export class ListBlockComponent extends CaptionedBlockComponent<ListBlockModel>
: nothing}
${listIcon}
<rich-text
.yText=${this.model.text.yText}
.yText=${this.model.props.text.yText}
.inlineEventSource=${this.topContenteditableElement ?? nothing}
.undoManager=${this.doc.history}
.attributeRenderer=${this.attributeRenderer}

View File

@@ -27,12 +27,12 @@ export function forwardDelete(std: BlockStdScope): true | undefined {
const doc = std.store;
const model = doc.getBlock(text.from.blockId)?.model;
if (!model || !matchModels(model, [ListBlockModel])) return;
const isEnd = isCollapsed && text.from.index === model.text.length;
const isEnd = isCollapsed && text.from.index === model.props.text.length;
if (!isEnd) return;
// Has children in list
const firstChild = model.firstChild();
if (firstChild) {
model.text.join(firstChild.text as Text);
model.props.text.join(firstChild.text as Text);
const grandChildren = firstChild.children;
if (grandChildren) {
doc.moveBlocks(grandChildren, model);
@@ -49,7 +49,7 @@ export function forwardDelete(std: BlockStdScope): true | undefined {
const nextSibling = doc.getNext(model);
const nextText = nextSibling?.text;
if (nextSibling && nextText) {
model.text.join(nextText);
model.props.text.join(nextText);
if (nextSibling.children) {
if (!parent) return;
doc.moveBlocks(nextSibling.children, parent, model, false);
@@ -63,7 +63,7 @@ export function forwardDelete(std: BlockStdScope): true | undefined {
const nextBlock = getNextContentBlock(std.host, model);
const nextBlockText = nextBlock?.text;
if (nextBlock && nextBlockText) {
model.text.join(nextBlock.text as Text);
model.props.text.join(nextBlock.text as Text);
if (nextBlock.children) {
const nextBlockParent = doc.getParent(nextBlock);
if (!nextBlockParent) return;

View File

@@ -36,7 +36,7 @@ export function getListIcon(
onClick: (e: MouseEvent) => void
) {
const deep = getListDeep(model);
switch (model.type) {
switch (model.props.type) {
case 'bulleted':
return html`<div
contenteditable="false"
@@ -51,7 +51,7 @@ export function getListIcon(
class="affine-list-block__prefix affine-list-block__numbered"
@click=${onClick}
>
${model.order ? getNumberPrefix(model.order, deep) : '1.'}
${model.props.order ? getNumberPrefix(model.props.order, deep) : '1.'}
</div>`;
case 'todo':
return html`<div
@@ -59,7 +59,7 @@ export function getListIcon(
class=${`affine-list-block__prefix affine-list-block__todo-prefix ${model.doc.readonly ? 'readonly' : ''}`}
@click=${onClick}
>
${model.checked
${model.props.checked
? CheckBoxCheckSolidIcon({ style: 'color: #1E96EB' })
: CheckBoxUnIcon()}
</div>`;
@@ -72,7 +72,7 @@ export function getListIcon(
${showChildren ? ToggleDownIcon() : ToggleRightIcon()}
</div>`;
default:
console.error('Unknown list type', model.type, model);
console.error('Unknown list type', model.props.type, model);
return null;
}
}

View File

@@ -12,7 +12,7 @@ export const changeNoteDisplayMode: Command<{
const noteBlockModel = std.store.getBlock(noteId)?.model;
if (!noteBlockModel || !matchModels(noteBlockModel, [NoteBlockModel])) return;
const currentMode = noteBlockModel.displayMode;
const currentMode = noteBlockModel.props.displayMode;
if (currentMode === mode) return;
if (stopCapture) std.store.captureSync();
@@ -29,10 +29,10 @@ export const changeNoteDisplayMode: Command<{
matchModels(child, [NoteBlockModel])
);
const firstEdgelessOnlyNote = notes.find(
note => note.displayMode === NoteDisplayMode.EdgelessOnly
note => note.props.displayMode === NoteDisplayMode.EdgelessOnly
);
const lastPageVisibleNote = notes.findLast(
note => note.displayMode !== NoteDisplayMode.EdgelessOnly
note => note.props.displayMode !== NoteDisplayMode.EdgelessOnly
);
if (currentMode === NoteDisplayMode.EdgelessOnly) {

View File

@@ -47,8 +47,8 @@ export const dedentBlock: Command<{
if (
matchModels(model, [ParagraphBlockModel]) &&
model.type.startsWith('h') &&
model.collapsed
model.props.type.startsWith('h') &&
model.props.collapsed
) {
const collapsedSiblings = calculateCollapsedSiblings(model);
store.moveBlocks([model, ...collapsedSiblings], grandParent, parent, false);

View File

@@ -59,8 +59,8 @@ export const dedentBlocks: Command<{
if (!model) return;
if (
matchModels(model, [ParagraphBlockModel]) &&
model.type.startsWith('h') &&
model.collapsed
model.props.type.startsWith('h') &&
model.props.collapsed
) {
const collapsedSiblings = calculateCollapsedSiblings(model);
collapsedIds.push(...collapsedSiblings.map(sibling => sibling.id));

View File

@@ -51,8 +51,8 @@ export const indentBlock: Command<{
if (
matchModels(model, [ParagraphBlockModel]) &&
model.type.startsWith('h') &&
model.collapsed
model.props.type.startsWith('h') &&
model.props.collapsed
) {
const collapsedSiblings = calculateCollapsedSiblings(model);
store.moveBlocks([model, ...collapsedSiblings], previousSibling);
@@ -63,7 +63,7 @@ export const indentBlock: Command<{
// update collapsed state of affine list
if (
matchModels(previousSibling, [ListBlockModel]) &&
previousSibling.collapsed
previousSibling.props.collapsed
) {
store.updateBlock(previousSibling, {
collapsed: false,

View File

@@ -60,8 +60,8 @@ export const indentBlocks: Command<{
if (!model) return;
if (
matchModels(model, [ParagraphBlockModel]) &&
model.type.startsWith('h') &&
model.collapsed
model.props.type.startsWith('h') &&
model.props.collapsed
) {
const collapsedSiblings = calculateCollapsedSiblings(model);
collapsedIds.push(...collapsedSiblings.map(sibling => sibling.id));
@@ -85,7 +85,7 @@ export const indentBlocks: Command<{
if (
nearestHeading &&
matchModels(nearestHeading, [ParagraphBlockModel]) &&
nearestHeading.collapsed
nearestHeading.props.collapsed
) {
store.updateBlock(nearestHeading, { collapsed: false });
}
@@ -106,7 +106,7 @@ export const indentBlocks: Command<{
if (
nearestHeading &&
matchModels(nearestHeading, [ParagraphBlockModel]) &&
nearestHeading.collapsed
nearestHeading.props.collapsed
) {
store.updateBlock(nearestHeading, { collapsed: false });
}

View File

@@ -44,13 +44,13 @@ export class EdgelessNoteBackground extends SignalWatcher(
const themeProvider = this.std.get(ThemeProvider);
const theme = themeProvider.theme$.value;
const backgroundColor = themeProvider.generateColorProperty(
this.note.background$.value,
this.note.props.background$.value,
DefaultTheme.noteBackgrounColor,
theme
);
const { borderRadius, borderSize, borderStyle, shadowType } =
this.note.edgeless$.value.style;
this.note.props.edgeless$.value.style;
return {
borderRadius: borderRadius + 'px',

View File

@@ -15,9 +15,9 @@ export class EdgelessNoteMask extends SignalWatcher(
const maskDOM = this.renderRoot!.querySelector('.affine-note-mask');
const observer = new ResizeObserver(entries => {
for (const entry of entries) {
if (!this.model.edgeless.collapse) {
if (!this.model.props.edgeless.collapse) {
const bound = Bound.deserialize(this.model.xywh);
const scale = this.model.edgeless.scale ?? 1;
const scale = this.model.props.edgeless.scale ?? 1;
const height = entry.contentRect.height * scale;
if (!height || almostEqual(bound.h, height)) {
@@ -53,7 +53,7 @@ export class EdgelessNoteMask extends SignalWatcher(
zIndex: '1',
pointerEvents: this.editing || this.disableMask ? 'none' : 'auto',
borderRadius: `${
this.model.edgeless.style.borderRadius * this.zoom
this.model.props.edgeless.style.borderRadius * this.zoom
}px`,
})}
></div>

View File

@@ -25,7 +25,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
) {
private get _isShowCollapsedContent() {
return (
this.model.edgeless.collapse &&
this.model.props.edgeless.collapse &&
this.gfx.selection.has(this.model.id) &&
!this._dragging &&
(this._isResizing || this._isHover)
@@ -41,7 +41,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
return nothing;
}
const { xywh, edgeless } = this.model;
const { xywh, edgeless } = this.model.props;
const { borderSize } = edgeless.style;
const extraPadding = this._editing ? ACTIVE_NOTE_EXTRA_PADDING : 0;
@@ -100,19 +100,19 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
private _setCollapse(event: MouseEvent) {
event.stopImmediatePropagation();
const { collapse, collapsedHeight } = this.model.edgeless;
const { collapse, collapsedHeight } = this.model.props.edgeless;
if (collapse) {
this.model.doc.updateBlock(this.model, () => {
this.model.edgeless.collapse = false;
this.model.props.edgeless.collapse = false;
});
} else if (collapsedHeight) {
const { xywh, edgeless } = this.model;
const { xywh, edgeless } = this.model.props;
const bound = Bound.deserialize(xywh);
bound.h = collapsedHeight * (edgeless.scale ?? 1);
this.model.doc.updateBlock(this.model, () => {
this.model.edgeless.collapse = true;
this.model.xywh = bound.serialize();
this.model.props.edgeless.collapse = true;
this.model.props.xywh = bound.serialize();
});
}
@@ -164,7 +164,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
const rect = this._noteContent?.getBoundingClientRect();
if (!rect) return;
const zoom = this.gfx.viewport.zoom;
const scale = this.model.edgeless.scale ?? 1;
const scale = this.model.props.edgeless.scale ?? 1;
this._noteFullHeight =
rect.height / scale / zoom + 2 * EDGELESS_BLOCK_CHILD_PADDING;
});
@@ -184,7 +184,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
}
override getRenderingRect() {
const { xywh, edgeless } = this.model;
const { xywh, edgeless } = this.model.props;
const { collapse, scale = 1 } = edgeless;
const bound = Bound.deserialize(xywh);
@@ -202,11 +202,11 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
override renderGfxBlock() {
const { model } = this;
const { displayMode } = model;
const { displayMode } = model.props;
if (!!displayMode && displayMode === NoteDisplayMode.DocOnly)
return nothing;
const { xywh, edgeless } = model;
const { xywh, edgeless } = model.props;
const { borderRadius } = edgeless.style;
const { collapse = false, collapsedHeight, scale = 1 } = edgeless;

View File

@@ -90,8 +90,8 @@ export const dedentParagraphCommand: Command<{
if (
matchModels(model, [ParagraphBlockModel]) &&
model.type.startsWith('h') &&
model.collapsed
model.props.type.startsWith('h') &&
model.props.collapsed
) {
const collapsedSiblings = calculateCollapsedSiblings(model);
store.moveBlocks([model, ...collapsedSiblings], grandParent, parent, false);

View File

@@ -96,7 +96,7 @@ export const indentParagraphCommand: Command<{
if (
nearestHeading &&
matchModels(nearestHeading, [ParagraphBlockModel]) &&
nearestHeading.collapsed
nearestHeading.props.collapsed
) {
store.updateBlock(nearestHeading, {
collapsed: false,
@@ -106,8 +106,8 @@ export const indentParagraphCommand: Command<{
if (
matchModels(model, [ParagraphBlockModel]) &&
model.type.startsWith('h') &&
model.collapsed
model.props.type.startsWith('h') &&
model.props.collapsed
) {
const collapsedSiblings = calculateCollapsedSiblings(model);
store.moveBlocks([model, ...collapsedSiblings], previousSibling);
@@ -125,7 +125,7 @@ export const indentParagraphCommand: Command<{
if (
nearestHeading &&
matchModels(nearestHeading, [ParagraphBlockModel]) &&
nearestHeading.collapsed
nearestHeading.props.collapsed
) {
store.updateBlock(nearestHeading, {
collapsed: false,
@@ -136,7 +136,7 @@ export const indentParagraphCommand: Command<{
// update collapsed state of affine list
if (
matchModels(previousSibling, [ListBlockModel]) &&
previousSibling.collapsed
previousSibling.props.collapsed
) {
store.updateBlock(previousSibling, {
collapsed: false,

View File

@@ -37,16 +37,16 @@ export const splitParagraphCommand: Command<
// be deleted and not counted as model.text.yText.length.
// Example: "`a`[enter]" -> yText[<ContentFormat: Code>, "a", <ContentFormat: Code>]
// In this case, we should not split the block.
if (model.text.yText.length < splitIndex + splitLength) return;
if (model.props.text.yText.length < splitIndex + splitLength) return;
if (model.children.length > 0 && splitIndex > 0) {
store.captureSync();
const right = model.text.split(splitIndex, splitLength);
const right = model.props.text.split(splitIndex, splitLength);
const id = store.addBlock(
model.flavour,
{
text: right,
type: model.type,
type: model.props.type,
},
model,
0
@@ -60,12 +60,12 @@ export const splitParagraphCommand: Command<
const index = parent.children.indexOf(model);
if (index < 0) return;
store.captureSync();
const right = model.text.split(splitIndex, splitLength);
const right = model.props.text.split(splitIndex, splitLength);
const id = store.addBlock(
model.flavour,
{
text: right,
type: model.type,
type: model.props.type,
},
parent,
index + 1

View File

@@ -67,7 +67,7 @@ export class ParagraphHeadingIcon extends SignalWatcher(
`;
override render() {
const type = this.model.type$.value;
const type = this.model.props.type$.value;
if (!type.startsWith('h')) return nothing;
const i = parseInt(type.slice(1));

View File

@@ -148,20 +148,20 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
this.disposables.add(
effect(() => {
const type = this.model.type$.value;
if (!type.startsWith('h') && this.model.collapsed) {
this.model.collapsed = false;
const type = this.model.props.type$.value;
if (!type.startsWith('h') && this.model.props.collapsed) {
this.model.props.collapsed = false;
}
})
);
this.disposables.add(
effect(() => {
const collapsed = this.model.collapsed$.value;
const collapsed = this.model.props.collapsed$.value;
this._readonlyCollapsed = collapsed;
// reset text selection when selected block is collapsed
if (this.model.type$.value.startsWith('h') && collapsed) {
if (this.model.props.type$.value.startsWith('h') && collapsed) {
const collapsedSiblings = this.collapsedSiblings;
const textSelection = this.host.selection.find(TextSelection);
@@ -181,19 +181,19 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
// # 456
//
// we need to update collapsed state of 123 when 456 converted to text
let beforeType = this.model.type$.peek();
let beforeType = this.model.props.type$.peek();
this.disposables.add(
effect(() => {
const type = this.model.type$.value;
const type = this.model.props.type$.value;
if (beforeType !== type && !type.startsWith('h')) {
const nearestHeading = getNearestHeadingBefore(this.model);
if (
nearestHeading &&
nearestHeading.type.startsWith('h') &&
nearestHeading.collapsed &&
nearestHeading.props.type.startsWith('h') &&
nearestHeading.props.collapsed &&
!this.doc.readonly
) {
nearestHeading.collapsed = false;
nearestHeading.props.collapsed = false;
}
}
beforeType = type;
@@ -208,14 +208,14 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
}
override renderBlock(): TemplateResult<1> {
const { type$ } = this.model;
const { type$ } = this.model.props;
const collapsed = this.doc.readonly
? this._readonlyCollapsed
: this.model.collapsed;
: this.model.props.collapsed;
const collapsedSiblings = this.collapsedSiblings;
let style = html``;
if (this.model.type$.value.startsWith('h') && collapsed) {
if (this.model.props.type$.value.startsWith('h') && collapsed) {
style = html`
<style>
${collapsedSiblings.map(sibling =>
@@ -259,14 +259,14 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
[TOGGLE_BUTTON_PARENT_CLASS]: true,
})}
>
${this.model.type$.value.startsWith('h')
${this.model.props.type$.value.startsWith('h')
? html`
<affine-paragraph-heading-icon
.model=${this.model}
></affine-paragraph-heading-icon>
`
: nothing}
${this.model.type$.value.startsWith('h') &&
${this.model.props.type$.value.startsWith('h') &&
collapsedSiblings.length > 0
? html`
<blocksuite-toggle-button
@@ -285,7 +285,7 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
`
: nothing}
<rich-text
.yText=${this.model.text.yText}
.yText=${this.model.props.text.yText}
.inlineEventSource=${this.topContenteditableElement ?? nothing}
.undoManager=${this.doc.history}
.attributesSchema=${this.attributesSchema}

View File

@@ -53,7 +53,7 @@ export const ParagraphKeymapExtension = KeymapExtension(
// When deleting at line start of a paragraph block,
// firstly switch it to normal text, then delete this empty block.
if (model.type !== 'text') {
if (model.props.type !== 'text') {
// Try to switch to normal text
store.captureSync();
store.updateBlock(model, { type: 'text' });
@@ -91,7 +91,7 @@ export const ParagraphKeymapExtension = KeymapExtension(
if (!inlineRange || !inlineEditor) return;
const raw = ctx.get('keyboardState').raw;
raw.preventDefault();
if (model.type === 'quote') {
if (model.props.type === 'quote') {
store.captureSync();
inlineEditor.insertText(inlineRange, '\n');
inlineEditor.setInlineRange({
@@ -123,10 +123,10 @@ export const ParagraphKeymapExtension = KeymapExtension(
if (!inlineRange || !inlineEditor) return;
const raw = ctx.get('keyboardState').raw;
const isEnd = model.text.length === inlineRange.index;
const isEnd = model.props.text.length === inlineRange.index;
if (model.type === 'quote') {
const textStr = model.text.toString();
if (model.props.type === 'quote') {
const textStr = model.props.text.toString();
/**
* If quote block ends with two blank lines, split the block
@@ -145,7 +145,7 @@ export const ParagraphKeymapExtension = KeymapExtension(
if (isEnd && endWithTwoBlankLines) {
raw.preventDefault();
store.captureSync();
model.text.delete(inlineRange.index - 1, 1);
model.props.text.delete(inlineRange.index - 1, 1);
std.command.chain().pipe(addParagraphCommand).run();
return true;
}
@@ -158,17 +158,17 @@ export const ParagraphKeymapExtension = KeymapExtension(
return true;
}
if (model.type.startsWith('h') && model.collapsed) {
if (model.props.type.startsWith('h') && model.props.collapsed) {
const parent = store.getParent(model);
if (!parent) return true;
const index = parent.children.indexOf(model);
if (index === -1) return true;
const collapsedSiblings = calculateCollapsedSiblings(model);
const rightText = model.text.split(inlineRange.index);
const rightText = model.props.text.split(inlineRange.index);
const newId = store.addBlock(
model.flavour,
{ type: model.type, text: rightText },
{ type: model.props.type, text: rightText },
parent,
index + collapsedSiblings.length + 1
);

View File

@@ -8,7 +8,7 @@ export class ParagraphBlockService extends BlockService {
static override readonly flavour = ParagraphBlockSchema.model.flavour;
placeholderGenerator: (model: ParagraphBlockModel) => string = model => {
if (model.type === 'text') {
if (model.props.type === 'text') {
return "Type '/' for commands";
}
@@ -21,6 +21,6 @@ export class ParagraphBlockService extends BlockService {
h6: 'Heading 6',
quote: '',
};
return placeholders[model.type];
return placeholders[model.props.type];
};
}

View File

@@ -32,7 +32,7 @@ export function forwardDelete(std: BlockStdScope) {
matchModels(model.parent, [CalloutBlockModel])
)
return;
const isEnd = isCollapsed && text.from.index === model.text.length;
const isEnd = isCollapsed && text.from.index === model.props.text.length;
if (!isEnd) return;
const parent = store.getParent(model);
if (!parent) return;
@@ -57,7 +57,7 @@ export function forwardDelete(std: BlockStdScope) {
}
if (matchModels(nextSibling, [ParagraphBlockModel, ListBlockModel])) {
model.text.join(nextSibling.text);
model.props.text.join(nextSibling.props.text);
if (nextSibling.children) {
const parent = store.getParent(nextSibling);
if (!parent) return false;
@@ -70,7 +70,7 @@ export function forwardDelete(std: BlockStdScope) {
const nextBlock = getNextContentBlock(host, model);
if (nextBlock?.text) {
model.text.join(nextBlock.text);
model.props.text.join(nextBlock.text);
if (nextBlock.children) {
const parent = store.getParent(nextBlock);
if (!parent) return false;

View File

@@ -72,8 +72,8 @@ export function mergeWithPrev(editorHost: EditorHost, model: BlockModel) {
)
return false;
const lengthBeforeJoin = prevBlock.text?.length ?? 0;
prevBlock.text.join(model.text as Text);
const lengthBeforeJoin = prevBlock.props.text?.length ?? 0;
prevBlock.props.text.join(model.text as Text);
doc.deleteBlock(model, {
bringChildrenTo: parent,
});
@@ -138,7 +138,7 @@ function handleNoPreviousSibling(editorHost: EditorHost, model: ExtendedModel) {
}
const rootModel = model.doc.root as RootBlockModel;
const title = rootModel.title;
const title = rootModel.props.title;
doc.captureSync();
let textLength = 0;

View File

@@ -74,7 +74,7 @@ const conversionsActionGroup = {
textConversionConfigs.find(
({ flavour, type }) =>
flavour === model.flavour &&
(type ? 'type' in model && type === model.type : true)
(type ? 'type' in model.props && type === model.props.type : true)
) ?? textConversionConfigs[0];
const update = (flavour: string, type?: string) => {
chain

View File

@@ -293,9 +293,9 @@ export function createEdgelessElement(
id = doc.addBlock(
'affine:note',
{
background: current.background,
displayMode: current.displayMode,
edgeless: current.edgeless,
background: current.props.background,
displayMode: current.props.displayMode,
edgeless: current.props.edgeless,
xywh: bound.serialize(),
},
edgeless.model.id
@@ -309,7 +309,7 @@ export function createEdgelessElement(
}
assertType<NoteBlockModel>(note);
doc.updateBlock(note, () => {
note.edgeless.collapse = true;
note.props.edgeless.collapse = true;
});
doc.addBlock('affine:paragraph', {}, note.id);

View File

@@ -154,14 +154,14 @@ export class NoteSlicer extends WidgetComponent<
index: originIndex,
xywh,
background,
children,
displayMode,
} = this._anchorNote;
} = this._anchorNote.props;
const { children } = this._anchorNote;
const {
collapse: _,
collapsedHeight: __,
...restOfEdgeless
} = this._anchorNote.edgeless;
} = this._anchorNote.props.edgeless;
const anchorBlockId = this._noteBlockIds[this._activeSlicerIndex];
if (!anchorBlockId) return;
const sliceIndex = children.findIndex(block => block.id === anchorBlockId);

View File

@@ -1009,7 +1009,7 @@ export class EdgelessSelectedRectWidget extends WidgetComponent<
direction === HandleDirection.BottomRight ||
direction === HandleDirection.BottomLeft
) {
const newScale = element.scale * (bound.w / oldXYWH.w);
const newScale = element.props.scale * (bound.w / oldXYWH.w);
this._scalePercent = `${Math.round(newScale * 100)}%`;
this._scaleDirection = direction;
@@ -1030,11 +1030,11 @@ export class EdgelessSelectedRectWidget extends WidgetComponent<
if (!textPortal.checkWidthOverflow(bound.w)) return;
const newRealWidth = clamp(
bound.w / element.scale,
bound.w / element.props.scale,
EDGELESS_TEXT_BLOCK_MIN_WIDTH,
Infinity
);
bound.w = newRealWidth * element.scale;
bound.w = newRealWidth * element.props.scale;
this.gfx.updateElement(element.id, {
xywh: Bound.serialize({
...bound,
@@ -1068,7 +1068,7 @@ export class EdgelessSelectedRectWidget extends WidgetComponent<
) {
const curBound = Bound.deserialize(element.xywh);
let scale = element.scale ?? 1;
let scale = element.props.scale ?? 1;
let width = curBound.w / scale;
let height = curBound.h / scale;
if (this._shiftKey) {
@@ -1123,7 +1123,7 @@ export class EdgelessSelectedRectWidget extends WidgetComponent<
) {
const curBound = Bound.deserialize(element.xywh);
let scale = element.edgeless.scale ?? 1;
let scale = element.props.edgeless.scale ?? 1;
if (this._shiftKey) {
scale = (bound.w / curBound.w) * scale;
this._scalePercent = `${Math.round(scale * 100)}%`;
@@ -1138,14 +1138,14 @@ export class EdgelessSelectedRectWidget extends WidgetComponent<
if (bound.h > NOTE_MIN_HEIGHT * scale) {
this.doc.updateBlock(element, () => {
element.edgeless.collapse = true;
element.edgeless.collapsedHeight = bound.h / scale;
element.props.edgeless.collapse = true;
element.props.edgeless.collapsedHeight = bound.h / scale;
});
}
this.gfx.updateElement(element.id, {
edgeless: {
...element.edgeless,
...element.props.edgeless,
scale,
},
xywh: bound.serialize(),
@@ -1160,13 +1160,13 @@ export class EdgelessSelectedRectWidget extends WidgetComponent<
const curBound = Bound.deserialize(element.xywh);
if (isImageBlock(element)) {
const { height } = element;
const { height } = element.props;
if (height) {
this._scalePercent = `${Math.round((bound.h / height) * 100)}%`;
this._scaleDirection = direction;
}
} else {
const cardStyle = (element as BookmarkBlockModel).style;
const cardStyle = (element as BookmarkBlockModel).props.style;
const height = EMBED_CARD_HEIGHT[cardStyle];
this._scalePercent = `${Math.round((bound.h / height) * 100)}%`;
this._scaleDirection = direction;

View File

@@ -158,7 +158,7 @@ export class EdgelessFrameTitleEditor extends WithDisposable(
return html`<div class="frame-title-editor" style=${inlineEditorStyle}>
<rich-text
.yText=${this.frameModel.title.yText}
.yText=${this.frameModel.props.title.yText}
.enableFormat=${false}
.enableAutoScrollHorizontally=${false}
style=${richTextStyle}

View File

@@ -179,8 +179,9 @@ export class EdgelessFrameOrderMenu extends SignalWatcher(
// Legacy compatibility
frameMgr.refreshLegacyFrameOrder();
const before = this._frames[newIndex - 1]?.presentationIndex || null;
const after = this._frames[newIndex]?.presentationIndex || null;
const before =
this._frames[newIndex - 1]?.props.presentationIndex || null;
const after = this._frames[newIndex]?.props.presentationIndex || null;
const frame = this._frames[index];
@@ -223,7 +224,7 @@ export class EdgelessFrameOrderMenu extends SignalWatcher(
(frame, index) => html`
<div class="item draggable" id=${frame.id} index=${index}>
<div class="drag-indicator"></div>
<div class="title">${frame.title.toString()}</div>
<div class="title">${frame.props.title.toString()}</div>
</div>
`
)}
@@ -232,7 +233,7 @@ export class EdgelessFrameOrderMenu extends SignalWatcher(
${frame
? html`<div class="drag-indicator"></div>
<div class="index">${this._curIndex + 1}</div>
<div class="title">${frame.title.toString()}</div>`
<div class="title">${frame.props.title.toString()}</div>`
: nothing}
</div>
</div>

View File

@@ -345,7 +345,7 @@ export class PresentationToolbar extends EdgelessToolbarToolMixin(
class="edgeless-frame-navigator-title"
@click=${() => this._moveToCurrentFrame()}
>
${frame?.title ?? 'no frame'}
${frame?.props.title ?? 'no frame'}
</span>`}
<span class="edgeless-frame-navigator-count">

View File

@@ -261,7 +261,7 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager {
block.group === null &&
!(
matchModels(block, [NoteBlockModel]) &&
block.displayMode === NoteDisplayMode.DocOnly
block.props.displayMode === NoteDisplayMode.DocOnly
)
)
.map(block => block.id),

View File

@@ -318,10 +318,10 @@ export class EdgelessRootBlockComponent extends BlockComponent<
const note = this.model.children.find(
(child): child is NoteBlockModel =>
matchModels(child, [NoteBlockModel]) &&
child.displayMode !== NoteDisplayMode.EdgelessOnly
child.props.displayMode !== NoteDisplayMode.EdgelessOnly
);
if (primaryMode !== 'page' || !note || note.edgeless.collapse)
if (primaryMode !== 'page' || !note || note.props.edgeless.collapse)
return false;
const leftPadding = parseInt(

View File

@@ -106,9 +106,7 @@ export function createNewPresentationIndexes(
const { data } = BlockSnapshotSchema.safeParse(block);
return data?.flavour === 'affine:frame';
})
.sort((a, b) =>
EdgelessFrameManager.framePresentationComparator(a.props, b.props)
);
.sort((a, b) => EdgelessFrameManager.framePresentationComparator(a, b));
const frameMgr = edgeless.service.frame;
let before = frameMgr.generatePresentationIndex();

View File

@@ -40,8 +40,8 @@ export class PageKeyboardManager {
if (
matchModels(model, [ParagraphBlockModel]) &&
model.type.startsWith('h') &&
model.collapsed
model.props.type.startsWith('h') &&
model.props.collapsed
) {
const component = this.rootComponent.host.view.getBlock(id);
if (!(component instanceof ParagraphBlockComponent)) return;

View File

@@ -238,7 +238,7 @@ export class PageRootBlockComponent extends BlockComponent<
const blocks = this.model.children
.filter(model => {
if (matchModels(model, [NoteBlockModel])) {
if (model.displayMode === NoteDisplayMode.EdgelessOnly)
if (model.props.displayMode === NoteDisplayMode.EdgelessOnly)
return false;
return true;
@@ -332,7 +332,7 @@ export class PageRootBlockComponent extends BlockComponent<
const notes = this.model.children.filter(
(child): child is NoteBlockModel =>
child instanceof NoteBlockModel &&
child.displayMode !== NoteDisplayMode.EdgelessOnly
child.props.displayMode !== NoteDisplayMode.EdgelessOnly
);
// make sure there is a block can be focused
@@ -358,7 +358,7 @@ export class PageRootBlockComponent extends BlockComponent<
if (
!lastBlock ||
!matchModels(lastBlock, [ParagraphBlockModel]) ||
lastBlock.text.length !== 0
lastBlock.props.text.length !== 0
) {
this.std.command.exec(appendParagraphCommand);
}
@@ -436,7 +436,8 @@ export class PageRootBlockComponent extends BlockComponent<
const isNote = matchModels(child, [NoteBlockModel]);
const note = child as NoteBlockModel;
const displayOnEdgeless =
!!note.displayMode && note.displayMode === NoteDisplayMode.EdgelessOnly;
!!note.props.displayMode &&
note.props.displayMode === NoteDisplayMode.EdgelessOnly;
// Should remove deprecated `hidden` property in the future
return !(isNote && displayOnEdgeless);
});

View File

@@ -36,7 +36,8 @@ export class PreviewRootBlockComponent extends BlockComponent {
const isNote = matchModels(child, [NoteBlockModel]);
const note = child as NoteBlockModel;
const displayOnEdgeless =
!!note.displayMode && note.displayMode === NoteDisplayMode.EdgelessOnly;
!!note.props.displayMode &&
note.props.displayMode === NoteDisplayMode.EdgelessOnly;
// Should remove deprecated `hidden` property in the future
return !(isNote && displayOnEdgeless);
});

View File

@@ -85,7 +85,7 @@ export class EdgelessChangeAttachmentButton extends WithDisposable(LitElement) {
override render() {
return join(
[
this.model.style === 'pdf'
this.model.props.style === 'pdf'
? null
: html`
<editor-menu-button
@@ -100,7 +100,7 @@ export class EdgelessChangeAttachmentButton extends WithDisposable(LitElement) {
`}
>
<card-style-panel
.value=${this.model.style}
.value=${this.model.props.style}
.options=${this._getCardStyleOptions}
.onSelect=${this._setCardStyle}
>

View File

@@ -147,7 +147,8 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
return;
}
const { id, url, xywh, style, caption } = this.model;
const { xywh, style, caption } = this.model.props;
const { id, url } = this.model;
let targetFlavour = 'affine:bookmark',
targetStyle = style;
@@ -207,7 +208,8 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
const { flavour, styles } = this._embedOptions;
const { id, url, xywh, style } = this.model;
const { id, url, xywh } = this.model;
const { style } = this.model.props;
const targetStyle = styles.includes(style) ? style : styles[0];
@@ -241,12 +243,12 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
private readonly _copyUrl = () => {
let url!: ReturnType<GenerateDocUrlService['generateDocUrl']>;
if ('url' in this.model) {
url = this.model.url;
if ('url' in this.model.props) {
url = this.model.props.url;
} else if (isInternalEmbedModel(this.model)) {
url = this.std
.getOptional(GenerateDocUrlProvider)
?.generateDocUrl(this.model.pageId, this.model.params);
?.generateDocUrl(this.model.props.pageId, this.model.props.params);
}
if (!url) return;
@@ -263,14 +265,14 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
private _embedOptions: EmbedOptions | null = null;
private readonly _getScale = () => {
if ('scale' in this.model) {
return this.model.scale ?? 1;
if ('scale' in this.model.props) {
return this.model.props.scale ?? 1;
} else if (isEmbedHtmlBlock(this.model)) {
return 1;
}
const bound = Bound.deserialize(this.model.xywh);
return bound.h / EMBED_CARD_HEIGHT[this.model.style];
return bound.h / EMBED_CARD_HEIGHT[this.model.props.style];
};
private readonly _open = ({ openMode }: { openMode?: OpenDocMode } = {}) => {
@@ -343,16 +345,16 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
if (isEmbedHtmlBlock(this.model)) return;
const bound = Bound.deserialize(this.model.xywh);
if ('scale' in this.model) {
const oldScale = this.model.scale ?? 1;
if ('scale' in this.model.props) {
const oldScale = this.model.props.scale ?? 1;
const ratio = scale / oldScale;
bound.w *= ratio;
bound.h *= ratio;
const xywh = bound.serialize();
this.model.doc.updateBlock(this.model, { scale, xywh });
} else {
bound.h = EMBED_CARD_HEIGHT[this.model.style] * scale;
bound.w = EMBED_CARD_WIDTH[this.model.style] * scale;
bound.h = EMBED_CARD_HEIGHT[this.model.props.style] * scale;
bound.w = EMBED_CARD_WIDTH[this.model.props.style] * scale;
const xywh = bound.serialize();
this.model.doc.updateBlock(this.model, { xywh });
}
@@ -456,9 +458,9 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
}
return (
isEmbedLinkedDocBlock(this.model) &&
(referenceToNode(this.model) ||
(referenceToNode(this.model.props) ||
!!this._blockComponent?.closest('affine-embed-synced-doc-block') ||
this.model.pageId === this._doc.id)
this.model.props.pageId === this._doc.id)
);
}
@@ -516,7 +518,7 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
get _originalDocInfo(): AliasInfo | undefined {
const model = this.model;
const doc = isInternalEmbedModel(model)
? this.std.workspace.getDoc(model.pageId)
? this.std.workspace.getDoc(model.props.pageId)
: null;
if (doc) {
@@ -533,7 +535,7 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
get _originalDocTitle() {
const model = this.model;
const doc = isInternalEmbedModel(model)
? this.std.workspace.getDoc(model.pageId)
? this.std.workspace.getDoc(model.props.pageId)
: null;
return doc?.meta?.title || 'Untitled';
@@ -582,7 +584,7 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
type: item.type,
icon: item.icon,
disabled:
this.model.pageId === this._doc.id &&
this.model.props.pageId === this._doc.id &&
item.type === 'open-in-active-view',
action: () => {
if (item.type === 'open-in-center-peek') {
@@ -723,30 +725,30 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
const model = this.model;
const isHtmlBlockModel = isEmbedHtmlBlock(model);
if ('url' in this.model) {
if ('url' in this.model.props) {
this._embedOptions = this.std
.get(EmbedOptionProvider)
.getEmbedBlockOptions(this.model.url);
.getEmbedBlockOptions(this.model.props.url);
}
const buttons = [
this._openMenuButton(),
this._canShowUrlOptions && 'url' in model
this._canShowUrlOptions && 'url' in model.props
? html`
<a
class="affine-link-preview"
href=${model.url}
href=${model.props.url}
rel="noopener noreferrer"
target="_blank"
>
<span>${getHostName(model.url)}</span>
<span>${getHostName(model.props.url)}</span>
</a>
`
: nothing,
// internal embed model
isEmbedLinkedDocBlock(model) && model.title
isEmbedLinkedDocBlock(model) && model.props.title
? html`
<editor-icon-button
class="doc-title"

View File

@@ -34,7 +34,7 @@ function getMostCommonColor(
colorScheme: ColorScheme
): string {
const colors = countBy(elements, (ele: FrameBlockModel) =>
resolveColor(ele.background, colorScheme)
resolveColor(ele.props.background, colorScheme)
);
const max = maxBy(Object.entries(colors), ([_k, count]) => count);
return max ? (max[0] as string) : 'transparent';
@@ -73,7 +73,7 @@ export class EdgelessChangeFrameButton extends WithDisposable(LitElement) {
const notes = rootModel.children.filter(
model =>
matchModels(model, [NoteBlockModel]) &&
model.displayMode !== NoteDisplayMode.EdgelessOnly
model.props.displayMode !== NoteDisplayMode.EdgelessOnly
);
const lastNote = notes[notes.length - 1];
const referenceFrame = this.frames[0];
@@ -180,7 +180,7 @@ export class EdgelessChangeFrameButton extends WithDisposable(LitElement) {
.pick=${this.pickColor}
.color=${background}
.theme=${colorScheme}
.originalColor=${this.frames[0].background}
.originalColor=${this.frames[0].props.background}
.enableCustomColor=${enableCustomColor}
>
</edgeless-color-picker-button>

View File

@@ -25,7 +25,7 @@ export class EdgelessChangeGroupButton extends WithDisposable(LitElement) {
const notes = rootModel.children.filter(
model =>
matchModels(model, [NoteBlockModel]) &&
model.displayMode !== NoteDisplayMode.EdgelessOnly
model.props.displayMode !== NoteDisplayMode.EdgelessOnly
);
const lastNote = notes[notes.length - 1];
const referenceGroup = this.groups[0];

View File

@@ -73,7 +73,7 @@ function getMostCommonBackground(
colorScheme: ColorScheme
): string {
const colors = countBy(elements, (ele: NoteBlockModel) =>
resolveColor(ele.background, colorScheme)
resolveColor(ele.props.background, colorScheme)
);
const max = maxBy(Object.entries(colors), ([_k, count]) => count);
return max
@@ -90,9 +90,9 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
this.notes.forEach(note => {
const props = {
edgeless: {
...note.edgeless,
...note.props.edgeless,
style: {
...note.edgeless.style,
...note.props.edgeless.style,
borderRadius,
},
},
@@ -105,13 +105,13 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
this.notes.forEach(note => {
this.doc.updateBlock(note, () => {
const bound = Bound.deserialize(note.xywh);
const oldScale = note.edgeless.scale ?? 1;
const oldScale = note.props.edgeless.scale ?? 1;
const ratio = scale / oldScale;
bound.w *= ratio;
bound.h *= ratio;
const xywh = bound.serialize();
note.xywh = xywh;
note.edgeless.scale = scale;
note.props.edgeless.scale = scale;
});
});
};
@@ -155,19 +155,19 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
private _setCollapse() {
this.doc.captureSync();
this.notes.forEach(note => {
const { collapse, collapsedHeight } = note.edgeless;
const { collapse, collapsedHeight } = note.props.edgeless;
if (collapse) {
this.doc.updateBlock(note, () => {
note.edgeless.collapse = false;
note.props.edgeless.collapse = false;
});
} else if (collapsedHeight) {
const { xywh, edgeless } = note;
const { xywh, edgeless } = note.props;
const bound = Bound.deserialize(xywh);
bound.h = collapsedHeight * (edgeless.scale ?? 1);
this.doc.updateBlock(note, () => {
note.edgeless.collapse = true;
note.xywh = bound.serialize();
note.props.edgeless.collapse = true;
note.props.xywh = bound.serialize();
});
}
});
@@ -175,7 +175,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
}
private _setDisplayMode(note: NoteBlockModel, newMode: NoteDisplayMode) {
const oldMode = note.displayMode;
const oldMode = note.props.displayMode;
this.edgeless.std.command.exec(changeNoteDisplayMode, {
noteId: note.id,
mode: newMode,
@@ -268,9 +268,9 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
this.notes.forEach(note => {
const props = {
edgeless: {
...note.edgeless,
...note.props.edgeless,
style: {
...note.edgeless.style,
...note.props.edgeless.style,
shadowType,
},
},
@@ -283,9 +283,9 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
this.notes.forEach(note => {
const props = {
edgeless: {
...note.edgeless,
...note.props.edgeless,
style: {
...note.edgeless.style,
...note.props.edgeless.style,
borderStyle,
},
},
@@ -298,9 +298,9 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
this.notes.forEach(note => {
const props = {
edgeless: {
...note.edgeless,
...note.props.edgeless,
style: {
...note.edgeless.style,
...note.props.edgeless.style,
borderSize,
},
},
@@ -322,7 +322,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
override render() {
const len = this.notes.length;
const note = this.notes[0];
const { edgeless, displayMode } = note;
const { edgeless, displayMode } = note.props;
const { shadowType, borderRadius, borderSize, borderStyle } =
edgeless.style;
const colorScheme = this.edgeless.surface.renderer.getColorScheme();
@@ -406,7 +406,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
.colorPanelClass=${'small'}
.theme=${colorScheme}
.palettes=${DefaultTheme.NoteBackgroundColorPalettes}
.originalColor=${note.background}
.originalColor=${note.props.background}
.enableCustomColor=${enableCustomColor}
>
</edgeless-color-picker-button>

View File

@@ -153,7 +153,7 @@ export const openGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
if (!linkedDocBlock) return;
const disabled = linkedDocBlock.pageId === ctx.doc.id;
const disabled = linkedDocBlock.props.pageId === ctx.doc.id;
return {
action: () => {

View File

@@ -86,7 +86,7 @@ export function createLinkedDocFromEdgelessElements(
});
} else {
if (isFrameBlock(model)) {
mapFrameIds(blockProps as unknown as FrameBlockModel, ids);
mapFrameIds(blockProps as FrameBlockModel['props'], ids);
}
newId = linkedDoc.addBlock(model.flavour, blockProps, surfaceId);

View File

@@ -584,7 +584,7 @@ const documentGroupFrameToolGroup: DynamicKeyboardToolPanelGroup = ({
.map(block => block.model) as FrameBlockModel[];
const frameItems = frameModels.map<KeyboardToolbarActionItem>(frameModel => ({
name: 'Frame: ' + frameModel.title.toString(),
name: 'Frame: ' + frameModel.props.title.toString(),
icon: FrameIcon(),
action: ({ std }) => {
std.command

View File

@@ -23,7 +23,7 @@ const surfaceRefSlashMenuConfig: SlashMenuConfig = {
.map(block => block.model as FrameBlockModel);
const frameItems = frameModels.map<SlashMenuActionItem>(frameModel => ({
name: 'Frame: ' + frameModel.title,
name: 'Frame: ' + frameModel.props.title,
icon: FrameIcon(),
group: `5_Document Group & Frame@${index++}`,
tooltip: {

Some files were not shown because too many files have changed in this diff Show More