@formicoidea/labre-core 0.59.0 → 0.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/architecture/code.c4 +111 -104
- package/architecture/domain.c4 +4 -4
- package/dist/_pkgs/affine-block-attachment/asset-picker.d.ts +8 -0
- package/dist/_pkgs/affine-block-attachment/asset-picker.js +25 -1
- package/dist/_pkgs/affine-block-attachment/attachment-block.js +9 -7
- package/dist/_pkgs/affine-block-database/database-block.js +4 -5
- package/dist/_pkgs/affine-block-database/service/index.d.ts +1 -0
- package/dist/_pkgs/affine-block-database/service/index.js +1 -0
- package/dist/_pkgs/affine-block-database/service/initial-view.d.ts +33 -0
- package/dist/_pkgs/affine-block-database/service/initial-view.js +20 -0
- package/dist/_pkgs/affine-block-database/utils/current-view.d.ts +7 -0
- package/dist/_pkgs/affine-block-database/utils/current-view.js +14 -0
- package/dist/_pkgs/affine-block-embed/common/render-linked-doc.js +2 -0
- package/dist/_pkgs/affine-block-embed-doc/common/child-card.d.ts +25 -0
- package/dist/_pkgs/affine-block-embed-doc/common/child-card.js +27 -0
- package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/commands/insert-embed-linked-doc.js +6 -1
- package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/new-doc.js +2 -2
- package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/embed-linked-doc-block.js +2 -6
- package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-synced-doc-block.js +2 -3
- package/dist/_pkgs/affine-block-embed-doc/page-drop/page-drop.js +3 -3
- package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +1 -0
- package/dist/_pkgs/affine-block-surface/extensions/index.js +1 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend-label.d.ts +11 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend-label.js +16 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend.d.ts +1 -11
- package/dist/_pkgs/affine-block-surface/extensions/legend.js +2 -11
- package/dist/_pkgs/affine-block-surface/extensions/toolbox.d.ts +62 -0
- package/dist/_pkgs/affine-block-surface/extensions/toolbox.js +1 -0
- package/dist/_pkgs/affine-block-surface/interchange-headless.d.ts +2 -0
- package/dist/_pkgs/affine-block-surface/interchange-headless.js +2 -0
- package/dist/_pkgs/affine-components/icons/loading.d.ts +6 -0
- package/dist/_pkgs/affine-components/icons/loading.js +16 -12
- package/dist/_pkgs/affine-fragment-doc-title/title-band/show-here.js +2 -2
- package/dist/_pkgs/affine-fragment-doc-title/title-band/title-band.d.ts +8 -0
- package/dist/_pkgs/affine-fragment-doc-title/title-band/title-band.js +35 -13
- package/dist/_pkgs/affine-fragment-doc-title/translations.d.ts +1 -1
- package/dist/_pkgs/affine-fragment-doc-title/translations.js +1 -1
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/basket-elements.d.ts +12 -0
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/basket-elements.js +44 -5
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/senior-tool.d.ts +3 -2
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/senior-tool.js +3 -2
- package/dist/_pkgs/affine-gfx-template/builtin/slides/build.js +10 -10
- package/dist/_pkgs/affine-gfx-template/builtin/slides/consts.d.ts +48 -64
- package/dist/_pkgs/affine-gfx-template/builtin/slides/consts.js +24 -21
- package/dist/_pkgs/affine-gfx-template/builtin/slides/masks.d.ts +1 -2
- package/dist/_pkgs/affine-gfx-template/builtin/slides/masks.js +0 -34
- package/dist/_pkgs/affine-inline-reference/reference-node/configs/toolbar.js +2 -1
- package/dist/_pkgs/affine-model/elements/c4/board.d.ts +0 -22
- package/dist/_pkgs/affine-model/elements/c4/board.js +1 -22
- package/dist/_pkgs/affine-model/elements/c4/consts.d.ts +29 -0
- package/dist/_pkgs/affine-model/elements/c4/consts.js +29 -0
- package/dist/_pkgs/affine-model/elements/c4/index.d.ts +1 -0
- package/dist/_pkgs/affine-model/elements/c4/index.js +1 -0
- package/dist/_pkgs/affine-model/headless.d.ts +1 -0
- package/dist/_pkgs/affine-model/headless.js +1 -0
- package/dist/_pkgs/affine-shared/consts/index.d.ts +9 -0
- package/dist/_pkgs/affine-shared/consts/index.js +9 -0
- package/dist/_pkgs/affine-shared/services/asset-picker-service.d.ts +7 -6
- package/dist/_pkgs/affine-shared/services/asset-picker-service.js +5 -5
- package/dist/_pkgs/affine-shared/services/title-band-service.d.ts +19 -0
- package/dist/_pkgs/data-view/core/component/cell-status/cell-status-css.d.ts +1 -1
- package/dist/_pkgs/data-view/core/component/cell-status/cell-status-css.js +10 -10
- package/dist/_pkgs/data-view/core/component/cell-status/cell-status.d.ts +1 -1
- package/dist/_pkgs/data-view/core/component/cell-status/cell-status.js +7 -5
- package/dist/_pkgs/data-view/property-presets/number/cell-renderer.d.ts +18 -0
- package/dist/_pkgs/data-view/property-presets/number/cell-renderer.js +51 -10
- package/dist/_pkgs/data-view/property-presets/text/cell-renderer.d.ts +23 -1
- package/dist/_pkgs/data-view/property-presets/text/cell-renderer.js +56 -15
- package/dist/_pkgs/data-view/property-presets/typing-commit.d.ts +16 -0
- package/dist/_pkgs/data-view/property-presets/typing-commit.js +27 -0
- package/dist/_pkgs/data-view/view-presets/list/list-view.js +1 -1
- package/package.json +1 -1
package/architecture/domain.c4
CHANGED
|
@@ -708,7 +708,7 @@ model {
|
|
|
708
708
|
extend features.blocks.surface {
|
|
709
709
|
metadata {
|
|
710
710
|
domain ['canvas', 'file', 'layer']
|
|
711
|
-
domain_canvas '0.
|
|
711
|
+
domain_canvas '0.75'
|
|
712
712
|
domain_file '0.17'
|
|
713
713
|
domain_layer '0.05'
|
|
714
714
|
}
|
|
@@ -770,8 +770,8 @@ model {
|
|
|
770
770
|
extend features.blocks.surface.extensions {
|
|
771
771
|
metadata {
|
|
772
772
|
domain ['canvas', 'file', 'layer']
|
|
773
|
-
domain_canvas '0.
|
|
774
|
-
domain_file '0.
|
|
773
|
+
domain_canvas '0.53'
|
|
774
|
+
domain_file '0.29'
|
|
775
775
|
domain_layer '0.12'
|
|
776
776
|
}
|
|
777
777
|
}
|
|
@@ -2422,7 +2422,7 @@ model {
|
|
|
2422
2422
|
metadata {
|
|
2423
2423
|
domain ['document', 'canvas']
|
|
2424
2424
|
domain_document '0.72'
|
|
2425
|
-
domain_canvas '0.
|
|
2425
|
+
domain_canvas '0.24'
|
|
2426
2426
|
}
|
|
2427
2427
|
}
|
|
2428
2428
|
extend model_.model_.blocks {
|
|
@@ -2,6 +2,7 @@ import { type AssetRef } from '../affine-shared/services/index.js';
|
|
|
2
2
|
import type { IVec } from '../global/gfx/index.js';
|
|
3
3
|
import type { BlockStdScope } from '../std/index.js';
|
|
4
4
|
import type { BlockModel } from '../store/index.js';
|
|
5
|
+
import { type AttachmentBlockSource } from './utils.js';
|
|
5
6
|
/**
|
|
6
7
|
* Adds one attachment card per ref next to `targetModel`, as one undo step.
|
|
7
8
|
* Nothing is written on a read-only document.
|
|
@@ -22,3 +23,10 @@ export declare function addAttachmentsFromAssets(std: BlockStdScope, assets: rea
|
|
|
22
23
|
export declare function pickAndAddSiblingAttachmentBlocks(std: BlockStdScope, targetModel: BlockModel): Promise<string[]>;
|
|
23
24
|
/** The canvas's file button: the host's asset dialog, or the file chooser. */
|
|
24
25
|
export declare function pickAndAddAttachments(std: BlockStdScope): Promise<string[]>;
|
|
26
|
+
/**
|
|
27
|
+
* What the attachment toolbar's "Replace" puts in the card: the host's asset
|
|
28
|
+
* dialog when there is one (`kind: 'file'`, `mode: 'replace'`, first ref
|
|
29
|
+
* used, by reference), the system file chooser otherwise (the file goes up
|
|
30
|
+
* through the blob source, as before). `null` when cancelled.
|
|
31
|
+
*/
|
|
32
|
+
export declare function pickAttachmentSource(std: BlockStdScope): Promise<AttachmentBlockSource | null>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AssetPickerProvider, } from '../affine-shared/services/index.js';
|
|
2
2
|
import { openSingleFileWith } from '../affine-shared/utils/index.js';
|
|
3
|
-
import { addAttachments, addSiblingAttachmentBlocks, placeAttachmentsOnCanvas, } from './utils.js';
|
|
3
|
+
import { addAttachments, addSiblingAttachmentBlocks, getFileType, placeAttachmentsOnCanvas, } from './utils.js';
|
|
4
4
|
/**
|
|
5
5
|
* Attachments from the host's asset library (`AssetPickerProvider`, labre
|
|
6
6
|
* P4): the card references a blob the host already stores, by its
|
|
@@ -85,3 +85,27 @@ export async function pickAndAddAttachments(std) {
|
|
|
85
85
|
return [];
|
|
86
86
|
return addAttachments(std, [file]);
|
|
87
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* What the attachment toolbar's "Replace" puts in the card: the host's asset
|
|
90
|
+
* dialog when there is one (`kind: 'file'`, `mode: 'replace'`, first ref
|
|
91
|
+
* used, by reference), the system file chooser otherwise (the file goes up
|
|
92
|
+
* through the blob source, as before). `null` when cancelled.
|
|
93
|
+
*/
|
|
94
|
+
export async function pickAttachmentSource(std) {
|
|
95
|
+
const picker = std.getOptional(AssetPickerProvider);
|
|
96
|
+
if (picker) {
|
|
97
|
+
const [asset] = (await picker.pick({
|
|
98
|
+
kind: 'file',
|
|
99
|
+
mode: 'replace',
|
|
100
|
+
multiple: false,
|
|
101
|
+
docId: std.store.id,
|
|
102
|
+
})) ?? [];
|
|
103
|
+
return asset ? (attachmentPropsFrom([asset])[0] ?? null) : null;
|
|
104
|
+
}
|
|
105
|
+
const file = await openSingleFileWith();
|
|
106
|
+
if (!file)
|
|
107
|
+
return null;
|
|
108
|
+
const sourceId = await std.store.blobSync.set(file);
|
|
109
|
+
const type = await getFileType(file);
|
|
110
|
+
return { sourceId, name: file.name, type, size: file.size };
|
|
111
|
+
}
|
|
@@ -39,7 +39,7 @@ import { ResourceController, } from '../affine-components/resource/index.js';
|
|
|
39
39
|
import { toast } from '../affine-components/toast/index.js';
|
|
40
40
|
import { AttachmentBlockStyles, } from '../affine-model/index.js';
|
|
41
41
|
import { BlockCommentManager, CitationProvider, DocModeProvider, FileSizeLimitProvider, TelemetryProvider, TOAST_COPIED_TO_CLIPBOARD, translateKey, } from '../affine-shared/services/index.js';
|
|
42
|
-
import { formatSize
|
|
42
|
+
import { formatSize } from '../affine-shared/utils/index.js';
|
|
43
43
|
import { AttachmentIcon, ResetIcon, UpgradeIcon, WarningIcon, } from '@blocksuite/icons/lit';
|
|
44
44
|
import { BlockSelection } from '../std/index.js';
|
|
45
45
|
import { nanoid, Slice } from '../store/index.js';
|
|
@@ -51,9 +51,10 @@ import { guard } from 'lit/directives/guard.js';
|
|
|
51
51
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
52
52
|
import { when } from 'lit/directives/when.js';
|
|
53
53
|
import { filter } from 'rxjs/operators';
|
|
54
|
+
import { pickAttachmentSource } from './asset-picker.js';
|
|
54
55
|
import { AttachmentEmbedProvider } from './embed.js';
|
|
55
56
|
import { styles } from './styles.js';
|
|
56
|
-
import { downloadAttachmentBlob,
|
|
57
|
+
import { downloadAttachmentBlob, refreshData } from './utils.js';
|
|
57
58
|
import { ATTACHMENT_BUTTON_RELOAD, ATTACHMENT_BUTTON_RETRY, ATTACHMENT_BUTTON_UPGRADE, } from './translations.js';
|
|
58
59
|
let AttachmentBlockComponent = (() => {
|
|
59
60
|
let _classDecorators = [Peekable({
|
|
@@ -121,12 +122,13 @@ let AttachmentBlockComponent = (() => {
|
|
|
121
122
|
const state = this.resourceController.state$.peek();
|
|
122
123
|
if (state.uploading)
|
|
123
124
|
return;
|
|
124
|
-
const
|
|
125
|
-
|
|
125
|
+
const source = await pickAttachmentSource(this.std);
|
|
126
|
+
// The dialog is async: the card may be gone, or the page read-only, by now.
|
|
127
|
+
if (!source || this.std.store.readonly)
|
|
126
128
|
return;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const { name, size } =
|
|
129
|
+
if (!this.std.store.getBlock(this.blockId))
|
|
130
|
+
return;
|
|
131
|
+
const { name, size, type, sourceId } = source;
|
|
130
132
|
let embed = this.model.props.embed$.value ?? false;
|
|
131
133
|
this.std.store.captureSync();
|
|
132
134
|
this.std.store.transact(() => {
|
|
@@ -27,9 +27,9 @@ import { databaseBlockStyles, databaseContentStyles, databaseHeaderBarStyles, da
|
|
|
27
27
|
import { BlockRenderer } from './detail-panel/block-renderer.js';
|
|
28
28
|
import { NoteRenderer } from './detail-panel/note-renderer.js';
|
|
29
29
|
import { DatabaseSelection } from './selection.js';
|
|
30
|
-
import { databaseOpenRowRequest, DatabaseDataSourceProvider, DatabaseNewRowMenuProvider, DatabaseOpenRowProvider, openDatabasePropertiesPanel, rowOpenedParams, } from './service/index.js';
|
|
30
|
+
import { databaseOpenRowRequest, DatabaseDataSourceProvider, DatabaseInitialViewProvider, DatabaseNewRowMenuProvider, DatabaseOpenRowProvider, openDatabasePropertiesPanel, rowOpenedParams, } from './service/index.js';
|
|
31
31
|
import { DATABASE_NEW_RECORD_MORE, DATABASE_SOURCE_MISSING, DATABASE_SOURCE_MISSING_HINT, } from './translations.js';
|
|
32
|
-
import { currentViewStorage } from './utils/current-view.js';
|
|
32
|
+
import { currentViewStorage, initialViewId } from './utils/current-view.js';
|
|
33
33
|
import { getSingleDocIdFromText } from './utils/title-doc.js';
|
|
34
34
|
import { DatabaseViewCreationIdentifier } from './view-creation.js';
|
|
35
35
|
export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
@@ -311,10 +311,9 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent {
|
|
|
311
311
|
const dataSource = provider && this.model.props.externalSourceId
|
|
312
312
|
? provider.createDataSource(this.model, initFn)
|
|
313
313
|
: new DatabaseBlockDataSource(this.model, initFn);
|
|
314
|
-
const id =
|
|
315
|
-
if (id
|
|
314
|
+
const id = initialViewId(this.model.id, viewId => dataSource.viewManager.viewGet(viewId) != null, this.std.getOptional(DatabaseInitialViewProvider));
|
|
315
|
+
if (id)
|
|
316
316
|
dataSource.viewManager.setCurrentView(id);
|
|
317
|
-
}
|
|
318
317
|
return dataSource;
|
|
319
318
|
}
|
|
320
319
|
get dataSource() {
|
|
@@ -14,6 +14,7 @@ export interface DatabaseDataSourceProvider {
|
|
|
14
14
|
createDataSource(model: DatabaseBlockModel, init?: (ds: DataSourceBase) => void): DataSourceBase;
|
|
15
15
|
}
|
|
16
16
|
export declare const DatabaseDataSourceProvider: import("../../global/di/types.js").ServiceIdentifier<DatabaseDataSourceProvider> & (<U extends DatabaseDataSourceProvider = DatabaseDataSourceProvider>(variant: import("../../global/di/types.js").ServiceVariant) => import("../../global/di/types.js").ServiceIdentifier<U>);
|
|
17
|
+
export * from './initial-view.js';
|
|
17
18
|
export * from './open-row.js';
|
|
18
19
|
export * from './properties-panel.js';
|
|
19
20
|
export * from './new-row-menu.js';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createIdentifier } from '../../global/di/index.js';
|
|
2
2
|
export const DatabaseBlockConfigService = createIdentifier('AffineDatabaseBlockConfigService');
|
|
3
3
|
export const DatabaseDataSourceProvider = createIdentifier('affine:database-data-source-provider');
|
|
4
|
+
export * from './initial-view.js';
|
|
4
5
|
export * from './open-row.js';
|
|
5
6
|
export * from './properties-panel.js';
|
|
6
7
|
export * from './new-row-menu.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ExtensionType } from '../../store/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Which `affine:database` block asks for the view it opens on. Only widens:
|
|
4
|
+
* a new field is optional.
|
|
5
|
+
*/
|
|
6
|
+
export interface DatabaseInitialViewRequest {
|
|
7
|
+
blockId: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The view a database opens on, chosen by the host (labre: a base's page
|
|
11
|
+
* opened from one of its views in the sidebar, `/base/:id?view=…`). Asked
|
|
12
|
+
* once, when the block builds its data source. An id the block does not
|
|
13
|
+
* have, or `undefined`, falls back to the view this tab last showed for the
|
|
14
|
+
* block (`currentViewStorage`), then to the first view.
|
|
15
|
+
*
|
|
16
|
+
* Nothing is written: the current view is a local signal of the view
|
|
17
|
+
* manager, never a stored prop, so opening on a view leaves the document
|
|
18
|
+
* untouched.
|
|
19
|
+
*/
|
|
20
|
+
export interface DatabaseInitialViewService {
|
|
21
|
+
initialView(request: DatabaseInitialViewRequest): string | undefined;
|
|
22
|
+
}
|
|
23
|
+
export declare const DatabaseInitialViewProvider: import("../../global/di/types.js").ServiceIdentifier<DatabaseInitialViewService> & (<U extends DatabaseInitialViewService = DatabaseInitialViewService>(variant: import("../../global/di/types.js").ServiceVariant) => import("../../global/di/types.js").ServiceIdentifier<U>);
|
|
24
|
+
/**
|
|
25
|
+
* Host seam: the view a database opens on.
|
|
26
|
+
*
|
|
27
|
+
* Absent or `null`, a database opens on the view this tab last showed for
|
|
28
|
+
* it, else its first view, as in 0.59.
|
|
29
|
+
*
|
|
30
|
+
* `di.override`, so a later registration wins and registering twice never
|
|
31
|
+
* throws at boot.
|
|
32
|
+
*/
|
|
33
|
+
export declare function DatabaseInitialViewExtension(service: DatabaseInitialViewService | null): ExtensionType;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createIdentifier } from '../../global/di/index.js';
|
|
2
|
+
export const DatabaseInitialViewProvider = createIdentifier('LabreDatabaseInitialView');
|
|
3
|
+
/**
|
|
4
|
+
* Host seam: the view a database opens on.
|
|
5
|
+
*
|
|
6
|
+
* Absent or `null`, a database opens on the view this tab last showed for
|
|
7
|
+
* it, else its first view, as in 0.59.
|
|
8
|
+
*
|
|
9
|
+
* `di.override`, so a later registration wins and registering twice never
|
|
10
|
+
* throws at boot.
|
|
11
|
+
*/
|
|
12
|
+
export function DatabaseInitialViewExtension(service) {
|
|
13
|
+
return {
|
|
14
|
+
setup: di => {
|
|
15
|
+
// `null` rides through on purpose: `getOptional` then reports no host
|
|
16
|
+
// choice and the block keeps its own.
|
|
17
|
+
di.override(DatabaseInitialViewProvider, () => service);
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import type { DatabaseInitialViewService } from '../service/initial-view.js';
|
|
1
2
|
export declare const currentViewStorage: {
|
|
2
3
|
getCurrentView: (blockId: string) => string | undefined;
|
|
3
4
|
setCurrentView: (blockId: string, viewId: string) => void;
|
|
4
5
|
};
|
|
6
|
+
/**
|
|
7
|
+
* The view a database opens on: the host's choice when the block has it
|
|
8
|
+
* (`DatabaseInitialViewProvider`), else the one this tab last showed, else
|
|
9
|
+
* `undefined` (the view manager's first view). Reads only.
|
|
10
|
+
*/
|
|
11
|
+
export declare function initialViewId(blockId: string, exists: (viewId: string) => boolean, host?: DatabaseInitialViewService | null): string | undefined;
|
|
@@ -45,3 +45,17 @@ const createCurrentViewStorage = () => {
|
|
|
45
45
|
};
|
|
46
46
|
};
|
|
47
47
|
export const currentViewStorage = createCurrentViewStorage();
|
|
48
|
+
/**
|
|
49
|
+
* The view a database opens on: the host's choice when the block has it
|
|
50
|
+
* (`DatabaseInitialViewProvider`), else the one this tab last showed, else
|
|
51
|
+
* `undefined` (the view manager's first view). Reads only.
|
|
52
|
+
*/
|
|
53
|
+
export function initialViewId(blockId, exists, host) {
|
|
54
|
+
const asked = host?.initialView({ blockId });
|
|
55
|
+
if (asked && exists(asked))
|
|
56
|
+
return asked;
|
|
57
|
+
const stored = currentViewStorage.getCurrentView(blockId);
|
|
58
|
+
if (stored && exists(stored))
|
|
59
|
+
return stored;
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getSurfaceBlock } from '../../affine-block-surface/index.js';
|
|
2
2
|
import { ListBlockModel, NoteBlockModel, NoteDisplayMode, ParagraphBlockModel, } from '../../affine-model/index.js';
|
|
3
|
+
import { LINKED_DOC_NOTE_STYLE } from '../../affine-shared/consts/index.js';
|
|
3
4
|
import { CHROME_UNTITLED, NotificationProvider, TOAST_LINKED_DOC_CREATED, TOOLBAR_CREATE_LINKED_DOC, translateKey, } from '../../affine-shared/services/index.js';
|
|
4
5
|
import { matchModels } from '../../affine-shared/utils/index.js';
|
|
5
6
|
import { Slice, Text, } from '../../store/index.js';
|
|
@@ -125,6 +126,7 @@ export async function convertSelectedBlocksToLinkedDoc(std, doc, selectedModels,
|
|
|
125
126
|
{
|
|
126
127
|
flavour: 'affine:embed-linked-doc',
|
|
127
128
|
pageId: linkedDoc.id,
|
|
129
|
+
style: LINKED_DOC_NOTE_STYLE,
|
|
128
130
|
},
|
|
129
131
|
], 'before');
|
|
130
132
|
// delete selected elements
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReferenceParams } from '../../affine-model/index.js';
|
|
2
|
+
import type { BlockStdScope } from '../../std/index.js';
|
|
3
|
+
import type { TemplateResult } from 'lit';
|
|
4
|
+
type CardStd = Pick<BlockStdScope, 'get' | 'getOptional'>;
|
|
5
|
+
/**
|
|
6
|
+
* Whether a card of page `pageId` held by document `docId` is the child's own
|
|
7
|
+
* card rather than a reference (labre ADR-0045, amended 2026-10-27): the host
|
|
8
|
+
* lists the document's children through `TitleBandService.children$`. The
|
|
9
|
+
* library never computes a parent or a child. Read inside a `computed`, so a
|
|
10
|
+
* move in the host's tree redraws the card. Without the seam, or without
|
|
11
|
+
* `children$`, every card is a reference, as in 0.59.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isChildCard(std: Pick<CardStd, 'getOptional'>, docId: string, pageId: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* The icon of a card (`embed-linked-doc`, `embed-synced-doc`): a child's own
|
|
16
|
+
* card shows the plain page or canvas icon; any other card, like an inline
|
|
17
|
+
* `@` reference, keeps the linked icon with its arrow (product owner,
|
|
18
|
+
* recette 3 P2-7c). An alias or a block link keeps its own icon.
|
|
19
|
+
*/
|
|
20
|
+
export declare function cardIcon(std: CardStd, docId: string, info: {
|
|
21
|
+
pageId: string;
|
|
22
|
+
params?: ReferenceParams;
|
|
23
|
+
title?: string;
|
|
24
|
+
}): TemplateResult;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { DocDisplayMetaProvider, TitleBandProvider, } from '../../affine-shared/services/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Whether a card of page `pageId` held by document `docId` is the child's own
|
|
4
|
+
* card rather than a reference (labre ADR-0045, amended 2026-10-27): the host
|
|
5
|
+
* lists the document's children through `TitleBandService.children$`. The
|
|
6
|
+
* library never computes a parent or a child. Read inside a `computed`, so a
|
|
7
|
+
* move in the host's tree redraws the card. Without the seam, or without
|
|
8
|
+
* `children$`, every card is a reference, as in 0.59.
|
|
9
|
+
*/
|
|
10
|
+
export function isChildCard(std, docId, pageId) {
|
|
11
|
+
const children$ = std.getOptional(TitleBandProvider)?.children$?.(docId);
|
|
12
|
+
return children$?.value.includes(pageId) ?? false;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The icon of a card (`embed-linked-doc`, `embed-synced-doc`): a child's own
|
|
16
|
+
* card shows the plain page or canvas icon; any other card, like an inline
|
|
17
|
+
* `@` reference, keeps the linked icon with its arrow (product owner,
|
|
18
|
+
* recette 3 P2-7c). An alias or a block link keeps its own icon.
|
|
19
|
+
*/
|
|
20
|
+
export function cardIcon(std, docId, info) {
|
|
21
|
+
const { pageId, params, title } = info;
|
|
22
|
+
return std.get(DocDisplayMetaProvider).icon(pageId, {
|
|
23
|
+
params,
|
|
24
|
+
title,
|
|
25
|
+
referenced: !isChildCard(std, docId, pageId),
|
|
26
|
+
}).value;
|
|
27
|
+
}
|
package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/commands/insert-embed-linked-doc.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { insertEmbedCard } from '../../../affine-block-embed/index.js';
|
|
2
|
+
import { LINKED_DOC_NOTE_STYLE } from '../../../affine-shared/consts/index.js';
|
|
2
3
|
export const insertEmbedLinkedDocCommand = (ctx, next) => {
|
|
3
4
|
const { docId, params, std } = ctx;
|
|
4
5
|
const flavour = 'affine:embed-linked-doc';
|
|
5
6
|
const targetStyle = 'vertical';
|
|
6
|
-
|
|
7
|
+
// In a note the card is a line; on the canvas `targetStyle` wins.
|
|
8
|
+
const props = {
|
|
9
|
+
pageId: docId,
|
|
10
|
+
style: LINKED_DOC_NOTE_STYLE,
|
|
11
|
+
};
|
|
7
12
|
if (params)
|
|
8
13
|
props.params = params;
|
|
9
14
|
const blockId = insertEmbedCard(std, { flavour, targetStyle, props });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { insertContent } from '../../../affine-rich-text/index.js';
|
|
2
|
-
import { REFERENCE_NODE } from '../../../affine-shared/consts/index.js';
|
|
2
|
+
import { LINKED_DOC_NOTE_STYLE, REFERENCE_NODE, } from '../../../affine-shared/consts/index.js';
|
|
3
3
|
import { LinkedDocCreationProvider, TelemetryProvider, } from '../../../affine-shared/services/index.js';
|
|
4
4
|
import { createDefaultDoc, writeDefaultDocBlocks, } from '../../../affine-shared/utils/index.js';
|
|
5
5
|
const LINKED_DOC = 'affine:embed-linked-doc';
|
|
@@ -63,7 +63,7 @@ function insertCard(store, anchor, pageId) {
|
|
|
63
63
|
if (!parent || !store.schema.isValid(LINKED_DOC, parent.flavour)) {
|
|
64
64
|
return null;
|
|
65
65
|
}
|
|
66
|
-
const cardId = store.addBlock(LINKED_DOC, { pageId }, parent, parent.children.indexOf(anchor) + 1);
|
|
66
|
+
const cardId = store.addBlock(LINKED_DOC, { pageId, style: LINKED_DOC_NOTE_STYLE }, parent, parent.children.indexOf(anchor) + 1);
|
|
67
67
|
if (anchor.flavour === 'affine:paragraph' && anchor.text?.length === 0) {
|
|
68
68
|
store.deleteBlock(anchor);
|
|
69
69
|
}
|
|
@@ -54,6 +54,7 @@ import { when } from 'lit/directives/when.js';
|
|
|
54
54
|
import throttle from 'lodash-es/throttle.js';
|
|
55
55
|
import { filter } from 'rxjs/operators';
|
|
56
56
|
import * as Y from 'yjs';
|
|
57
|
+
import { cardIcon } from '../common/child-card.js';
|
|
57
58
|
import { isDocTrashed } from '../common/doc-trashed.js';
|
|
58
59
|
import { renderLinkedDocInCard } from '../common/render-linked-doc.js';
|
|
59
60
|
import { SyncedDocErrorIcon } from '../embed-synced-doc-block/styles.js';
|
|
@@ -371,12 +372,7 @@ let EmbedLinkedDocBlockComponent = (() => {
|
|
|
371
372
|
description: description$.value,
|
|
372
373
|
});
|
|
373
374
|
});
|
|
374
|
-
this.icon$ = computed(() =>
|
|
375
|
-
const { pageId, params, title } = this.referenceInfo$.value;
|
|
376
|
-
return this.std
|
|
377
|
-
.get(DocDisplayMetaProvider)
|
|
378
|
-
.icon(pageId, { params, title, referenced: true }).value;
|
|
379
|
-
});
|
|
375
|
+
this.icon$ = computed(() => cardIcon(this.std, this.store.id, this.referenceInfo$.value));
|
|
380
376
|
this.open = ({ openMode, event, } = {}) => {
|
|
381
377
|
this.std.getOptional(RefNodeSlotsProvider)?.docLinkClicked.next({
|
|
382
378
|
...this.referenceInfo$.peek(),
|
|
@@ -52,6 +52,7 @@ import { classMap } from 'lit/directives/class-map.js';
|
|
|
52
52
|
import { guard } from 'lit/directives/guard.js';
|
|
53
53
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
54
54
|
import * as Y from 'yjs';
|
|
55
|
+
import { cardIcon } from '../common/child-card.js';
|
|
55
56
|
import { isDocTrashed } from '../common/doc-trashed.js';
|
|
56
57
|
import { EMBED_DOC_CARD_EMPTY_CONTENT } from '../translations.js';
|
|
57
58
|
import { blockStyles } from './styles.js';
|
|
@@ -329,9 +330,7 @@ let EmbedSyncedDocBlockComponent = (() => {
|
|
|
329
330
|
};
|
|
330
331
|
this.icon$ = computed(() => {
|
|
331
332
|
const { pageId, params } = this.model.props;
|
|
332
|
-
return this.std
|
|
333
|
-
.get(DocDisplayMetaProvider)
|
|
334
|
-
.icon(pageId, { params, referenced: true }).value;
|
|
333
|
+
return cardIcon(this.std, this.store.id, { pageId, params });
|
|
335
334
|
});
|
|
336
335
|
this.open = (event) => {
|
|
337
336
|
const pageId = this.model.props.pageId;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EdgelessCRUDIdentifier } from '../../affine-block-surface/index.js';
|
|
2
|
-
import { EMBED_CARD_HEIGHT, EMBED_CARD_WIDTH, } from '../../affine-shared/consts/index.js';
|
|
2
|
+
import { EMBED_CARD_HEIGHT, EMBED_CARD_WIDTH, LINKED_DOC_NOTE_STYLE, } from '../../affine-shared/consts/index.js';
|
|
3
3
|
import { PageDropProvider, pageDropVerdict, TelemetryProvider, } from '../../affine-shared/services/index.js';
|
|
4
4
|
import { calcDropTarget, getClosestBlockComponentByPoint, getLastNoteBlock, isInsideEdgelessEditor, matchModels, } from '../../affine-shared/utils/index.js';
|
|
5
5
|
import { Bound, Point } from '../../global/gfx/index.js';
|
|
@@ -52,7 +52,7 @@ function insertBeside(store, pageId, line) {
|
|
|
52
52
|
if (!parent)
|
|
53
53
|
return null;
|
|
54
54
|
if (store.schema.safeValidate(LINKED_DOC, parent.flavour)) {
|
|
55
|
-
return (store.addSiblingBlocks(model, [{ flavour: LINKED_DOC, pageId }], placement)[0] ?? null);
|
|
55
|
+
return (store.addSiblingBlocks(model, [{ flavour: LINKED_DOC, pageId, style: LINKED_DOC_NOTE_STYLE }], placement)[0] ?? null);
|
|
56
56
|
}
|
|
57
57
|
// Out of a list item or a callout: the card goes after the container.
|
|
58
58
|
model = parent;
|
|
@@ -65,7 +65,7 @@ function insertAtEnd(store, pageId) {
|
|
|
65
65
|
if (!root)
|
|
66
66
|
return null;
|
|
67
67
|
const noteId = getLastNoteBlock(store)?.id ?? store.addBlock('affine:note', {}, root.id);
|
|
68
|
-
return store.addBlock(LINKED_DOC, { pageId }, noteId);
|
|
68
|
+
return store.addBlock(LINKED_DOC, { pageId, style: LINKED_DOC_NOTE_STYLE }, noteId);
|
|
69
69
|
}
|
|
70
70
|
function insertOnCanvas(std, pageId, point) {
|
|
71
71
|
const gfx = std.get(GfxControllerIdentifier);
|
|
@@ -10,6 +10,7 @@ export * from './element-renderer.js';
|
|
|
10
10
|
export * from './export-manager/index.js';
|
|
11
11
|
export * from './export-svg/index.js';
|
|
12
12
|
export * from './interchange.js';
|
|
13
|
+
export * from './toolbox.js';
|
|
13
14
|
export * from './interchange-export.js';
|
|
14
15
|
export * from './interchange-import.js';
|
|
15
16
|
export * from './legacy-slot-extension.js';
|
|
@@ -10,6 +10,7 @@ export * from './element-renderer.js';
|
|
|
10
10
|
export * from './export-manager/index.js';
|
|
11
11
|
export * from './export-svg/index.js';
|
|
12
12
|
export * from './interchange.js';
|
|
13
|
+
export * from './toolbox.js';
|
|
13
14
|
export * from './interchange-export.js';
|
|
14
15
|
export * from './interchange-import.js';
|
|
15
16
|
export * from './legacy-slot-extension.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ink and the type a notation writes its labels in: the legend box's rows,
|
|
3
|
+
* and the words the DDD prefabs set beside a dot or a marker.
|
|
4
|
+
*
|
|
5
|
+
* Declared HERE and re-exported by `@labre/affine-gfx-ddd-shared`, rather than
|
|
6
|
+
* the other way round, because that bundle depends on this one and a legend
|
|
7
|
+
* must not depend on a DDD bundle to be drawn.
|
|
8
|
+
*/
|
|
9
|
+
export declare const LABEL_COLOR: string;
|
|
10
|
+
export declare const LABEL_FONT = "blocksuite:surface:Inter";
|
|
11
|
+
export declare const LABEL_FONT_SIZE = 14;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { NOTATION_NEUTRALS } from '../../affine-shared/headless.js';
|
|
2
|
+
// Its own module so the headless interchange entry (`./interchange`) can read
|
|
3
|
+
// it without the legend's editor graph: the DDD element builders of
|
|
4
|
+
// `@labre/affine-gfx-ddd-shared/headless` write their captions in these three
|
|
5
|
+
// values (`docs/adr/0045`). `legend.ts` re-exports them unchanged.
|
|
6
|
+
/**
|
|
7
|
+
* The ink and the type a notation writes its labels in: the legend box's rows,
|
|
8
|
+
* and the words the DDD prefabs set beside a dot or a marker.
|
|
9
|
+
*
|
|
10
|
+
* Declared HERE and re-exported by `@labre/affine-gfx-ddd-shared`, rather than
|
|
11
|
+
* the other way round, because that bundle depends on this one and a legend
|
|
12
|
+
* must not depend on a DDD bundle to be drawn.
|
|
13
|
+
*/
|
|
14
|
+
export const LABEL_COLOR = NOTATION_NEUTRALS.ink;
|
|
15
|
+
export const LABEL_FONT = 'blocksuite:surface:Inter';
|
|
16
|
+
export const LABEL_FONT_SIZE = 14;
|
|
@@ -46,17 +46,7 @@ export interface LegendLayout {
|
|
|
46
46
|
}
|
|
47
47
|
/** A block of the box that is not a row. See {@link CommandLegendBox.extras}. */
|
|
48
48
|
export type LegendExtra = CommandLegendExtra;
|
|
49
|
-
|
|
50
|
-
* The ink and the type a notation writes its labels in: this box's rows, and
|
|
51
|
-
* the words the DDD prefabs set beside a dot or a marker.
|
|
52
|
-
*
|
|
53
|
-
* Declared HERE and re-exported by `@labre/affine-gfx-ddd-shared`, rather than
|
|
54
|
-
* the other way round, because that bundle depends on this one and a legend
|
|
55
|
-
* must not depend on a DDD bundle to be drawn.
|
|
56
|
-
*/
|
|
57
|
-
export declare const LABEL_COLOR: string;
|
|
58
|
-
export declare const LABEL_FONT = "blocksuite:surface:Inter";
|
|
59
|
-
export declare const LABEL_FONT_SIZE = 14;
|
|
49
|
+
export { LABEL_COLOR, LABEL_FONT, LABEL_FONT_SIZE } from './legend-label.js';
|
|
60
50
|
export { LEGEND_ROLE };
|
|
61
51
|
/**
|
|
62
52
|
* How big the box {@link addLegend} would draw for these sections is — without
|
|
@@ -5,18 +5,9 @@ import { Bound } from '../../global/gfx/index.js';
|
|
|
5
5
|
import { CATALOGUE_CATEGORY_KEY_PREFIX, getRegisteredCommands, humanizeCategory, } from '../../std/index.js';
|
|
6
6
|
import { GfxControllerIdentifier, roleIsA, RoleVocabularyIdentifier, } from '../../std/gfx/index.js';
|
|
7
7
|
import { EdgelessCRUDIdentifier } from './crud-extension.js';
|
|
8
|
+
import { LABEL_COLOR, LABEL_FONT, LABEL_FONT_SIZE } from './legend-label.js';
|
|
8
9
|
import { LEGEND_ROLE } from './legend-role.js';
|
|
9
|
-
|
|
10
|
-
* The ink and the type a notation writes its labels in: this box's rows, and
|
|
11
|
-
* the words the DDD prefabs set beside a dot or a marker.
|
|
12
|
-
*
|
|
13
|
-
* Declared HERE and re-exported by `@labre/affine-gfx-ddd-shared`, rather than
|
|
14
|
-
* the other way round, because that bundle depends on this one and a legend
|
|
15
|
-
* must not depend on a DDD bundle to be drawn.
|
|
16
|
-
*/
|
|
17
|
-
export const LABEL_COLOR = NOTATION_NEUTRALS.ink;
|
|
18
|
-
export const LABEL_FONT = 'blocksuite:surface:Inter';
|
|
19
|
-
export const LABEL_FONT_SIZE = 14;
|
|
10
|
+
export { LABEL_COLOR, LABEL_FONT, LABEL_FONT_SIZE } from './legend-label.js';
|
|
20
11
|
const NO_STROKE = '#00000000';
|
|
21
12
|
/**
|
|
22
13
|
* The box's geometry, in one place because two callers need it: the one that
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { SerializedElementProps } from './interchange.js';
|
|
2
|
+
/**
|
|
3
|
+
* A framework's TOOLBOX, with no editor behind it (`docs/adr/0045`): every
|
|
4
|
+
* item of its toolbar as a pure builder, so a host with no editor — the Labre
|
|
5
|
+
* workspace connector, labre-mcp — places the very elements a user places
|
|
6
|
+
* from the toolbar, never shapes that imitate them.
|
|
7
|
+
*
|
|
8
|
+
* ## The same contract as a reader's result
|
|
9
|
+
*
|
|
10
|
+
* A builder returns what an import capability returns (ADR 0012 D3): element
|
|
11
|
+
* props in painting order, each composite's members before the group that
|
|
12
|
+
* holds them, and LOCAL `id`s the group's `children` and a link's ends name.
|
|
13
|
+
* `surface.addElement` mints the real ids and the materializer
|
|
14
|
+
* (`materializeInterchangeImport`) rewrites the references, so one writer
|
|
15
|
+
* serves a whole file read by a reader and one item built here.
|
|
16
|
+
*
|
|
17
|
+
* ## What a builder does not do
|
|
18
|
+
*
|
|
19
|
+
* It places ONE item at the point it is given: where things go on a board is
|
|
20
|
+
* the caller's. It writes the texts it is given, or the English seed: a seed
|
|
21
|
+
* in the host's language is resolved by the editor's creation site, which has
|
|
22
|
+
* the catalogue (ADR 0023). It persists nothing.
|
|
23
|
+
*/
|
|
24
|
+
/** Where an item lands: the top-left of its box, in canvas units. */
|
|
25
|
+
export interface ToolboxPoint {
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
}
|
|
29
|
+
/** One toolbar item that places elements. */
|
|
30
|
+
export interface ToolboxItem {
|
|
31
|
+
/** Stable within the framework, kebab-case: `container`, `system-boundary`. */
|
|
32
|
+
readonly id: string;
|
|
33
|
+
/** The toolbar command's own label, so a host names it as the toolbar does. */
|
|
34
|
+
readonly labelKey: string;
|
|
35
|
+
readonly labelFallback: string;
|
|
36
|
+
/** The text slots `build` fills, in reading order (`title`, `description`…). */
|
|
37
|
+
readonly texts: readonly string[];
|
|
38
|
+
/** The box the item is born with. */
|
|
39
|
+
readonly size: {
|
|
40
|
+
readonly w: number;
|
|
41
|
+
readonly h: number;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* The elements, with local ids and the group last. `local` prefixes those
|
|
45
|
+
* ids, so two items built for one batch never share a name.
|
|
46
|
+
*/
|
|
47
|
+
build(at: ToolboxPoint, texts?: Readonly<Record<string, string>>, local?: string): SerializedElementProps[];
|
|
48
|
+
}
|
|
49
|
+
/** One relation style of the framework: a connector between two elements. */
|
|
50
|
+
export interface ToolboxLink {
|
|
51
|
+
readonly id: string;
|
|
52
|
+
readonly labelKey: string;
|
|
53
|
+
readonly labelFallback: string;
|
|
54
|
+
/** The connector props; `from` and `to` are element ids or local ids. */
|
|
55
|
+
build(from: string, to: string, label?: string): SerializedElementProps;
|
|
56
|
+
}
|
|
57
|
+
export interface FrameworkToolbox {
|
|
58
|
+
/** The framework's descriptor id (`c4`, `bpmn`…). */
|
|
59
|
+
readonly framework: string;
|
|
60
|
+
readonly items: readonly ToolboxItem[];
|
|
61
|
+
readonly links: readonly ToolboxLink[];
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
*/
|
|
19
19
|
export * from './extensions/export-svg/marker-version.js';
|
|
20
20
|
export * from './extensions/interchange.js';
|
|
21
|
+
export * from './extensions/toolbox.js';
|
|
22
|
+
export * from './extensions/legend-label.js';
|
|
21
23
|
export * from './extensions/legend-role.js';
|
|
22
24
|
export * from './extensions/svg-sanitize.js';
|
|
23
25
|
export * from './extensions/svg-sketch.js';
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
*/
|
|
19
19
|
export * from './extensions/export-svg/marker-version.js';
|
|
20
20
|
export * from './extensions/interchange.js';
|
|
21
|
+
export * from './extensions/toolbox.js';
|
|
22
|
+
export * from './extensions/legend-label.js';
|
|
21
23
|
export * from './extensions/legend-role.js';
|
|
22
24
|
export * from './extensions/svg-sanitize.js';
|
|
23
25
|
export * from './extensions/svg-sketch.js';
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The library's spinner. Rotated by SMIL, not by a `<style>` inside the
|
|
3
|
+
* SVG: that sheet was global in light DOM (any `.spinner` of the page
|
|
4
|
+
* spun), and a binding after it fails to render under happy-dom, so no
|
|
5
|
+
* unit spec could mount a view that draws it.
|
|
6
|
+
*/
|
|
1
7
|
export declare const LoadingIcon: ({ size, progress, ringColor, strokeColor, }?: {
|
|
2
8
|
size?: string;
|
|
3
9
|
progress?: number;
|