@formicoidea/labre-core 0.47.0 → 0.48.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.
Files changed (72) hide show
  1. package/dist/_pkgs/affine-block-attachment/configs/slash-menu.js +2 -2
  2. package/dist/_pkgs/affine-block-attachment/translations.js +2 -2
  3. package/dist/_pkgs/affine-block-database/view.js +5 -0
  4. package/dist/_pkgs/affine-block-embed/embed-html-block/configs/toolbar.js +1 -1
  5. package/dist/_pkgs/affine-block-embed/embed-iframe-block/configs/toolbar.d.ts +1 -1
  6. package/dist/_pkgs/affine-block-embed/embed-iframe-block/configs/toolbar.js +1 -1
  7. package/dist/_pkgs/affine-block-embed/translations.d.ts +1 -1
  8. package/dist/_pkgs/affine-block-embed/translations.js +2 -2
  9. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/new-doc.d.ts +25 -0
  10. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/new-doc.js +71 -0
  11. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/slash-menu.js +9 -17
  12. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/toolbar.js +1 -1
  13. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/configs/toolbar.js +3 -3
  14. package/dist/_pkgs/affine-block-embed-doc/translations.d.ts +1 -1
  15. package/dist/_pkgs/affine-block-embed-doc/translations.js +8 -8
  16. package/dist/_pkgs/affine-block-frame/frame-toolbar.js +2 -2
  17. package/dist/_pkgs/affine-block-frame/translations.js +1 -1
  18. package/dist/_pkgs/affine-block-note/translations.js +8 -8
  19. package/dist/_pkgs/affine-block-root/commands/copy-link-commands.js +2 -2
  20. package/dist/_pkgs/affine-block-root/configs/toolbar.d.ts +1 -1
  21. package/dist/_pkgs/affine-block-root/configs/toolbar.js +1 -1
  22. package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/misc.d.ts +1 -1
  23. package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/more.d.ts +1 -1
  24. package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/more.js +1 -1
  25. package/dist/_pkgs/affine-block-root/translations.d.ts +1 -1
  26. package/dist/_pkgs/affine-block-root/translations.js +2 -2
  27. package/dist/_pkgs/affine-block-surface/extensions/canvas-grid/commands.js +1 -1
  28. package/dist/_pkgs/affine-block-surface/extensions/interchange-import.js +1 -1
  29. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/commands.js +1 -1
  30. package/dist/_pkgs/affine-block-surface/renderer/element-highlight-overlay.d.ts +8 -2
  31. package/dist/_pkgs/affine-block-surface/renderer/element-highlight-overlay.js +11 -13
  32. package/dist/_pkgs/affine-block-surface-ref/translations.js +8 -8
  33. package/dist/_pkgs/affine-components/translations.js +6 -6
  34. package/dist/_pkgs/affine-fragment-doc-title/index.d.ts +1 -1
  35. package/dist/_pkgs/affine-fragment-doc-title/index.js +1 -1
  36. package/dist/_pkgs/affine-fragment-doc-title/title-band/band-cell.d.ts +22 -0
  37. package/dist/_pkgs/affine-fragment-doc-title/title-band/band-cell.js +125 -0
  38. package/dist/_pkgs/affine-fragment-doc-title/title-band/format.d.ts +7 -19
  39. package/dist/_pkgs/affine-fragment-doc-title/title-band/format.js +0 -38
  40. package/dist/_pkgs/affine-fragment-doc-title/title-band/show-here.d.ts +19 -0
  41. package/dist/_pkgs/affine-fragment-doc-title/title-band/show-here.js +61 -0
  42. package/dist/_pkgs/affine-fragment-doc-title/title-band/title-band.d.ts +28 -18
  43. package/dist/_pkgs/affine-fragment-doc-title/title-band/title-band.js +225 -207
  44. package/dist/_pkgs/affine-fragment-doc-title/translations.d.ts +7 -4
  45. package/dist/_pkgs/affine-fragment-doc-title/translations.js +12 -9
  46. package/dist/_pkgs/affine-gfx-group/toolbar/config.d.ts +2 -2
  47. package/dist/_pkgs/affine-gfx-group/toolbar/config.js +2 -2
  48. package/dist/_pkgs/affine-gfx-group/translations.js +1 -1
  49. package/dist/_pkgs/affine-gfx-note/translations.js +2 -2
  50. package/dist/_pkgs/affine-shared/services/linked-doc-creation-service.d.ts +15 -6
  51. package/dist/_pkgs/affine-shared/services/title-band-service.d.ts +10 -7
  52. package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +3 -3
  53. package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +17 -17
  54. package/dist/_pkgs/affine-shared/utils/model/doc.d.ts +10 -2
  55. package/dist/_pkgs/affine-shared/utils/model/doc.js +17 -7
  56. package/dist/_pkgs/affine-widget-edgeless-auto-connect/translations.js +2 -2
  57. package/dist/_pkgs/affine-widget-edgeless-selected-rect/translations.js +1 -1
  58. package/dist/_pkgs/affine-widget-linked-doc/translations.js +3 -3
  59. package/dist/_pkgs/affine-widget-slash-menu/translations.js +1 -1
  60. package/dist/_pkgs/data-view/core/component/tags/multi-tag-select.d.ts +7 -2
  61. package/dist/_pkgs/data-view/core/component/tags/multi-tag-select.js +22 -15
  62. package/dist/_pkgs/data-view/core/effect.js +2 -0
  63. package/dist/_pkgs/data-view/core/property/index.d.ts +1 -0
  64. package/dist/_pkgs/data-view/core/property/index.js +1 -0
  65. package/dist/_pkgs/data-view/core/property/standalone-cell.d.ts +95 -0
  66. package/dist/_pkgs/data-view/core/property/standalone-cell.js +306 -0
  67. package/dist/_pkgs/data-view/core/view-manager/property.d.ts +6 -0
  68. package/dist/_pkgs/data-view/property-presets/multi-select/cell-renderer.js +1 -1
  69. package/dist/_pkgs/data-view/property-presets/select/cell-renderer.js +1 -1
  70. package/dist/_pkgs/data-view/property-presets/text/cell-renderer.js +3 -1
  71. package/dist/translations.js +1 -1
  72. package/package.json +1 -1
@@ -13,9 +13,9 @@ export const groupToolbarConfig = {
13
13
  actions: [
14
14
  {
15
15
  id: 'a.insert-into-page',
16
- label: 'Insert into Document',
16
+ label: 'Insert into Page',
17
17
  labelWording: GROUP_TOOLBAR_INSERT_INTO_PAGE,
18
- tooltip: 'Insert into Document',
18
+ tooltip: 'Insert into Page',
19
19
  tooltipWording: GROUP_TOOLBAR_INSERT_INTO_PAGE,
20
20
  icon: InsertIntoPageIcon(),
21
21
  when: ctx => ctx.getSurfaceModelsByType(GroupElementModel).length === 1,
@@ -20,7 +20,7 @@ export const GROUP_WORDINGS = [GROUP_SEED_NAME];
20
20
  export const GROUP_TOOLBAR_INSERT_INTO_PAGE = TOOLBAR_INSERT_INTO_PAGE;
21
21
  export const GROUP_TOAST_INSERTED = [
22
22
  'com.labre.group.toast.inserted',
23
- 'Group has been inserted into doc',
23
+ 'Group has been inserted into page',
24
24
  ];
25
25
  export const GROUP_TOOLBAR_RENAME = TOOLBAR_RENAME;
26
26
  export const GROUP_TOOLBAR_UNGROUP = TOOLBAR_UNGROUP;
@@ -19,7 +19,7 @@ export const GFX_NOTE_SHADOW_FLOATION = [
19
19
  /* ── `./components/note-display-mode-panel.ts` ────────────────────────────
20
20
  * A different wording from `blocks/note`'s own display-mode dropdown (which
21
21
  * says "Both" / "Edgeless" / "Page"): this panel's labels read "In Both" /
22
- * "In Document Only" / "In Canvas Only", so they get their own keys.
22
+ * "In Page Only" / "In Canvas Only", so they get their own keys.
23
23
  */
24
24
  export const GFX_NOTE_DISPLAY_MODE_BOTH = [
25
25
  'com.labre.gfx-note.display-mode.in-both',
@@ -27,7 +27,7 @@ export const GFX_NOTE_DISPLAY_MODE_BOTH = [
27
27
  ];
28
28
  export const GFX_NOTE_DISPLAY_MODE_PAGE_ONLY = [
29
29
  'com.labre.gfx-note.display-mode.in-page-only',
30
- 'In Document Only',
30
+ 'In Page Only',
31
31
  ];
32
32
  export const GFX_NOTE_DISPLAY_MODE_EDGELESS_ONLY = [
33
33
  'com.labre.gfx-note.display-mode.in-edgeless-only',
@@ -2,16 +2,25 @@ import type { EditorHost } from '../../std/index.js';
2
2
  import { type ExtensionType, type Store } from '../../store/index.js';
3
3
  /**
4
4
  * Creates the new doc that the linked-doc features populate (the edgeless
5
- * "Create linked doc" / "Turn into linked doc" actions). By default this is a
6
- * fresh in-workspace doc; a host app can override it to ALSO persist or register
7
- * the doc (assign a stored id, create a metadata row, attach sync) before the
8
- * editor writes blocks into the returned store.
5
+ * "Create linked page" / "Turn into linked page" actions, and the slash menu's
6
+ * "New Page" since 0.48, which leaves a linked-doc card where it was typed). By
7
+ * default this is a fresh in-workspace doc; a host app can override it to ALSO
8
+ * persist or register the doc (assign a stored id, create a metadata row,
9
+ * attach sync) before the editor writes blocks into the returned store.
9
10
  *
10
- * The returned `Store` must be ready for `addBlock`. `title` is forwarded so the
11
- * host can record it; the caller still writes the page block's own title.
11
+ * The returned `Store` is left UNLOADED: the caller writes its blocks in
12
+ * `store.load(initFn)`, and a doc that is already loaded skips `initFn`.
13
+ * `title` is forwarded so the host can record it; the caller still writes the
14
+ * page block's own title.
12
15
  */
13
16
  export interface LinkedDocCreationProvider {
14
17
  createLinkedDoc(host: EditorHost, title?: string): Store;
18
+ /**
19
+ * Whether a doc may be created from this editor at all (a host may refuse
20
+ * it on a doc shared with a guest, for instance). Read by the slash menu's
21
+ * "New Page", which hides itself on `false`. Absent means allowed (since 0.48).
22
+ */
23
+ canCreateLinkedDoc?(host: EditorHost): boolean;
15
24
  }
16
25
  export declare const LinkedDocCreationProvider: import("../../global/di/types.js").ServiceIdentifier<LinkedDocCreationProvider> & (<U extends LinkedDocCreationProvider = LinkedDocCreationProvider>(variant: import("../../global/di/types.js").ServiceVariant) => import("../../global/di/types.js").ServiceIdentifier<U>);
17
26
  /**
@@ -17,7 +17,7 @@ import type { ReadonlySignal } from '@preact/signals-core';
17
17
  * database cell read the same `type`, `data` and value.
18
18
  *
19
19
  * Absent, there is no band at all: no chips, no "+", no panel button, no "Not
20
- * shown in this document" row, and nothing else changes.
20
+ * shown on this page" row, and nothing else changes.
21
21
  */
22
22
  /**
23
23
  * One visible property of a page's sheet, in the order the band draws it.
@@ -103,12 +103,15 @@ export interface TitleBandService {
103
103
  collapsed$?(docId: string): ReadonlySignal<boolean>;
104
104
  setCollapsed?(docId: string, collapsed: boolean): void;
105
105
  /**
106
- * The child pages this document holds but does not display. Read **in the
107
- * canvas view only**, drawn in the note header as a "Not shown in this
108
- * document" row of page links that open through the linked-document path
109
- * (`RefNodeSlotsProvider.docLinkClicked`). In the page view the host draws
110
- * that row under the title itself, so a document never shows two. Absent
111
- * or empty, no row.
106
+ * The child pages this document holds but does not display, drawn in both
107
+ * views (under the title, and in the note header on the canvas) as a "Not
108
+ * shown on this page" row: each page is a link that opens through the
109
+ * linked-document path (`RefNodeSlotsProvider.docLinkClicked`; without it,
110
+ * no row), with a "Show here" button on a writable document that inserts
111
+ * an `affine:embed-linked-doc` card of it (end of the last note in the
112
+ * page view, centre of the visible canvas on the canvas). The library
113
+ * writes only that card: dropping the page from this list once it shows is
114
+ * the host's reading of the document. Absent or empty, no row.
112
115
  */
113
116
  notShown$?(docId: string): ReadonlySignal<readonly TitleBandNotShownPage[]>;
114
117
  }
@@ -457,8 +457,8 @@ export declare const ACTION_CANCEL: ChromeWording;
457
457
  export declare const COLOR_LABEL: ChromeWording;
458
458
  export declare const FILL_COLOR_LABEL: ChromeWording;
459
459
  /**
460
- * "Create Linked Doc" - Title Case, unlike the sentence-case
461
- * {@link TOOLBAR_CREATE_LINKED_DOC} above ("Create linked doc"): a different
460
+ * "Create Linked Page" - Title Case, unlike the sentence-case
461
+ * {@link TOOLBAR_CREATE_LINKED_DOC} above ("Create linked page"): a different
462
462
  * literal, so it keeps its own key. Said identically by the root block's
463
463
  * edgeless "More" sub-menu AND the generic iframe embed's own toolbar. Was
464
464
  * `ROOT_TOOLBAR_CREATE_LINKED_DOC` (`blocks/root`).
@@ -516,7 +516,7 @@ export declare const TOOLBAR_UNGROUP: ChromeWording;
516
516
  */
517
517
  export declare const MINDMAP_NAME: ChromeWording;
518
518
  /**
519
- * "New Doc" — the "@" menu's own popover group, said identically by the
519
+ * "New Page" — the "@" menu's own popover group, said identically by the
520
520
  * linked-doc embed's slash-menu item. Was `LINKED_DOC_NEW_DOC`
521
521
  * (`widgets/linked-doc`).
522
522
  */
@@ -38,15 +38,15 @@ export const TOAST_COPIED_TO_CLIPBOARD = [
38
38
  ];
39
39
  export const TOAST_LINKED_DOC_CREATED = [
40
40
  'com.labre.toast.linked-doc-created',
41
- 'Linked doc created',
41
+ 'Linked page created',
42
42
  ];
43
43
  export const TOAST_NOTE_REMOVED_FROM_PAGE = [
44
44
  'com.labre.toast.note-removed-from-page-mode',
45
- 'Note removed from Document Mode',
45
+ 'Note removed from Page Mode',
46
46
  ];
47
47
  export const TOAST_FRAME_INSERTED_INTO_PAGE = [
48
48
  'com.labre.toast.frame-inserted-into-page',
49
- 'Frame inserted into Document.',
49
+ 'Frame inserted into Page.',
50
50
  ];
51
51
  export const TOAST_NO_LINK_FOUND = [
52
52
  'com.labre.toast.no-link-found',
@@ -90,7 +90,7 @@ export const TOOLBAR_MORE = ['com.labre.toolbar.more', 'More'];
90
90
  export const TOOLBAR_LINK = ['com.labre.toolbar.link', 'Link'];
91
91
  export const TOOLBAR_CREATE_LINKED_DOC = [
92
92
  'com.labre.toolbar.create-linked-doc',
93
- 'Create linked doc',
93
+ 'Create linked page',
94
94
  ];
95
95
  export const TOOLBAR_DRAW_CONNECTOR = [
96
96
  'com.labre.toolbar.draw-connector',
@@ -147,19 +147,19 @@ export const TOOLBAR_EMBED_VIEW = [
147
147
  */
148
148
  export const LINKED_DOC_DELETED = [
149
149
  'com.labre.embed.linked-doc.deleted',
150
- 'This linked doc is deleted.',
150
+ 'This linked page is deleted.',
151
151
  ];
152
152
  export const LINKED_DOC_FAILED = [
153
153
  'com.labre.embed.linked-doc.failed',
154
- 'This linked doc failed to load.',
154
+ 'This linked page failed to load.',
155
155
  ];
156
156
  export const LINKED_DOC_EMPTY_PREVIEW = [
157
157
  'com.labre.embed.linked-doc.empty-preview',
158
- 'Preview of the doc will be displayed here.',
158
+ 'Preview of the page will be displayed here.',
159
159
  ];
160
160
  export const SYNCED_DOC_EMPTY_PREVIEW = [
161
161
  'com.labre.embed.synced-doc.empty-preview',
162
- 'Preview of the document will be displayed here.',
162
+ 'Preview of the page will be displayed here.',
163
163
  ];
164
164
  /* ── The board toolbars every framework shares ────────────────────────── */
165
165
  /**
@@ -615,7 +615,7 @@ export const CHROME_UNTITLED = DOC_UNTITLED;
615
615
  /** The doc-display-meta service's own fallback for a doc that no longer exists. */
616
616
  export const CHROME_DELETED_DOC = [
617
617
  'com.labre.doc.deleted',
618
- 'Deleted doc',
618
+ 'Deleted page',
619
619
  ];
620
620
  /* ── Palette swatch names (default theme) ──────────────────────────────
621
621
  *
@@ -908,7 +908,7 @@ export const TOOLBAR_PLAYBACK_SETTINGS = [
908
908
  ];
909
909
  export const TOOLBAR_OPEN_THIS_DOC = [
910
910
  'com.labre.toolbar.open-this-doc',
911
- 'Open this doc',
911
+ 'Open this page',
912
912
  ];
913
913
  /**
914
914
  * The card-style switcher's four wordings — the bookmark's, the linked-doc
@@ -993,7 +993,7 @@ export const DISPLAY_MODE_EDGELESS = [
993
993
  ];
994
994
  export const DISPLAY_MODE_PAGE = [
995
995
  'com.labre.note.display-mode.page',
996
- 'Document',
996
+ 'Page',
997
997
  ];
998
998
  export const DISPLAY_MODE_SHOW_IN = [
999
999
  'com.labre.note.display-mode.show-in',
@@ -1024,15 +1024,15 @@ export const FILL_COLOR_LABEL = [
1024
1024
  'Fill color',
1025
1025
  ];
1026
1026
  /**
1027
- * "Create Linked Doc" - Title Case, unlike the sentence-case
1028
- * {@link TOOLBAR_CREATE_LINKED_DOC} above ("Create linked doc"): a different
1027
+ * "Create Linked Page" - Title Case, unlike the sentence-case
1028
+ * {@link TOOLBAR_CREATE_LINKED_DOC} above ("Create linked page"): a different
1029
1029
  * literal, so it keeps its own key. Said identically by the root block's
1030
1030
  * edgeless "More" sub-menu AND the generic iframe embed's own toolbar. Was
1031
1031
  * `ROOT_TOOLBAR_CREATE_LINKED_DOC` (`blocks/root`).
1032
1032
  */
1033
1033
  export const TOOLBAR_CREATE_LINKED_DOC_TITLE = [
1034
1034
  'com.labre.root.toolbar.create-linked-doc',
1035
- 'Create Linked Doc',
1035
+ 'Create Linked Page',
1036
1036
  ];
1037
1037
  /**
1038
1038
  * "Turn into" — the block toolbar's conversions dropdown, said identically by
@@ -1090,7 +1090,7 @@ export const IMAGE_LABEL = ['com.labre.image.label', 'Image'];
1090
1090
  */
1091
1091
  export const TOOLBAR_INSERT_INTO_PAGE = [
1092
1092
  'com.labre.frame.toolbar.insert-into-page',
1093
- 'Insert into Document',
1093
+ 'Insert into Page',
1094
1094
  ];
1095
1095
  /**
1096
1096
  * "Ungroup" — a group's own surface-toolbar action, said identically by a
@@ -1110,13 +1110,13 @@ export const MINDMAP_NAME = [
1110
1110
  'Mind Map',
1111
1111
  ];
1112
1112
  /**
1113
- * "New Doc" — the "@" menu's own popover group, said identically by the
1113
+ * "New Page" — the "@" menu's own popover group, said identically by the
1114
1114
  * linked-doc embed's slash-menu item. Was `LINKED_DOC_NEW_DOC`
1115
1115
  * (`widgets/linked-doc`).
1116
1116
  */
1117
1117
  export const NEW_DOC_LABEL = [
1118
1118
  'com.labre.linked-doc.group.new-doc',
1119
- 'New Doc',
1119
+ 'New Page',
1120
1120
  ];
1121
1121
  /**
1122
1122
  * The artefact catalogue sidepanel's "Other" group header (used inline at its
@@ -1,5 +1,13 @@
1
- import type { Workspace } from '../../../store/index.js';
1
+ import type { Store, Workspace } from '../../../store/index.js';
2
2
  export declare function createDefaultDoc(collection: Workspace, options?: {
3
3
  id?: string;
4
4
  title?: string;
5
- }): import("../../../store/index.js").Store;
5
+ }): Store;
6
+ /**
7
+ * The blocks of a blank page, written into an empty store: the page with its
8
+ * title, its surface, and one note holding an empty paragraph. Shared by
9
+ * `createDefaultDoc` and by the creation paths that receive their store from
10
+ * the host (`LinkedDocCreationProvider`), so a page opens the same whoever
11
+ * made it.
12
+ */
13
+ export declare function writeDefaultDocBlocks(store: Store, title?: string): void;
@@ -5,19 +5,29 @@ export function createDefaultDoc(collection, options = {}) {
5
5
  doc.load();
6
6
  const store = doc.getStore();
7
7
  const title = options.title ?? '';
8
- const rootId = store.addBlock('affine:page', {
9
- title: new Text(title),
10
- });
8
+ writeDefaultDocBlocks(store, title);
11
9
  collection.meta.setDocMeta(doc.id, {
12
10
  title,
13
11
  });
12
+ // To make sure the content of new doc would not be clear
13
+ // By undo operation for the first time
14
+ store.resetHistory();
15
+ return store;
16
+ }
17
+ /**
18
+ * The blocks of a blank page, written into an empty store: the page with its
19
+ * title, its surface, and one note holding an empty paragraph. Shared by
20
+ * `createDefaultDoc` and by the creation paths that receive their store from
21
+ * the host (`LinkedDocCreationProvider`), so a page opens the same whoever
22
+ * made it.
23
+ */
24
+ export function writeDefaultDocBlocks(store, title = '') {
25
+ const rootId = store.addBlock('affine:page', {
26
+ title: new Text(title),
27
+ });
14
28
  store.addBlock('affine:surface', {}, rootId);
15
29
  const noteId = store.addBlock('affine:note', {
16
30
  xywh: `[0, 0, ${DEFAULT_PAGE_BLOCK_WIDTH}, ${DEFAULT_PAGE_BLOCK_HEIGHT}]`,
17
31
  }, rootId);
18
32
  store.addBlock('affine:paragraph', {}, noteId);
19
- // To make sure the content of new doc would not be clear
20
- // By undo operation for the first time
21
- store.resetHistory();
22
- return store;
23
33
  }
@@ -1,11 +1,11 @@
1
1
  /** The note-index badge's two tooltips, in page vs. edgeless-only mode. */
2
2
  export const AUTO_CONNECT_HIDDEN_ON_PAGE = [
3
3
  'com.labre.auto-connect.hidden-on-page',
4
- 'Hidden on document',
4
+ 'Hidden on page',
5
5
  ];
6
6
  export const AUTO_CONNECT_PAGE_MODE_INDEX = [
7
7
  'com.labre.auto-connect.page-mode-index',
8
- 'Document mode index',
8
+ 'Page mode index',
9
9
  ];
10
10
  /** Every wording this package declares, in the order it renders them. */
11
11
  export const AUTO_CONNECT_WORDINGS = [
@@ -16,7 +16,7 @@ export const AUTO_COMPLETE_ADD_SAME_OBJECT = [
16
16
  /** The floating "open link" button drawn over a linked element. */
17
17
  export const EDGELESS_LINK_OPEN_DOC = [
18
18
  'com.labre.edgeless-element-link.open-doc',
19
- 'Open linked doc',
19
+ 'Open linked page',
20
20
  ];
21
21
  export const EDGELESS_LINK_OPEN_LINK = [
22
22
  'com.labre.edgeless-element-link.open-link',
@@ -12,7 +12,7 @@ export const LINKED_DOC_FORMAT_HTML = FORMAT_HTML;
12
12
  /* ── Popover groups (config.ts) ─────────────────────────────────────────── */
13
13
  export const LINKED_DOC_LINK_TO_DOC = [
14
14
  'com.labre.linked-doc.group.link-to-doc',
15
- 'Link to Doc',
15
+ 'Link to Page',
16
16
  ];
17
17
  export const LINKED_DOC_NEW_DOC = NEW_DOC_LABEL;
18
18
  /**
@@ -28,7 +28,7 @@ export const LINKED_DOC_IMPORT = [
28
28
  /** The "Create doc" item's own wording, interpolated with the truncated name. */
29
29
  export const LINKED_DOC_CREATE_DOC = [
30
30
  'com.labre.linked-doc.create-doc',
31
- 'Create "{{name}}" doc',
31
+ 'Create "{{name}}" page',
32
32
  ];
33
33
  /**
34
34
  * The import-success toast — `{{count}}` interpolated, the English fallback
@@ -37,7 +37,7 @@ export const LINKED_DOC_CREATE_DOC = [
37
37
  */
38
38
  export const LINKED_DOC_IMPORT_SUCCESS_TOAST = [
39
39
  'com.labre.linked-doc.import-success',
40
- 'Successfully imported {{count}} Doc(s).',
40
+ 'Successfully imported {{count}} Page(s).',
41
41
  ];
42
42
  /**
43
43
  * The overflow item's own fallback label ("N more docs" is a different
@@ -133,7 +133,7 @@ export const SLASH_MENU_GROUP_CONTENT_MEDIA = [
133
133
  ];
134
134
  export const SLASH_MENU_GROUP_PAGE = [
135
135
  'com.labre.slash-menu.group.page',
136
- 'Document',
136
+ 'Page',
137
137
  ];
138
138
  export const SLASH_MENU_GROUP_EDGELESS_ELEMENT = [
139
139
  'com.labre.slash-menu.group.edgeless-element',
@@ -7,7 +7,12 @@ export type TagManagerOptions = {
7
7
  value: ReadonlySignal<string[]>;
8
8
  onChange: (value: string[]) => void;
9
9
  options: ReadonlySignal<SelectTag[]>;
10
- onOptionsChange: (options: SelectTag[]) => void;
10
+ /**
11
+ * Absent, the options are fixed: the menu picks among them and offers no
12
+ * "Create", no option menu and no reordering (a standalone cell whose host
13
+ * cannot write the property's config, `standalone-cell.ts`).
14
+ */
15
+ onOptionsChange?: (options: SelectTag[]) => void;
11
16
  onComplete?: () => void;
12
17
  initialDraftText?: string;
13
18
  };
@@ -32,7 +37,7 @@ export declare class MultiTagSelect extends MultiTagSelect_base {
32
37
  accessor mode: 'multi' | 'single';
33
38
  accessor onChange: (value: string[]) => void;
34
39
  accessor onComplete: () => void;
35
- accessor onOptionsChange: (options: SelectTag[]) => void;
40
+ accessor onOptionsChange: ((options: SelectTag[]) => void) | undefined;
36
41
  accessor options: ReadonlySignal<SelectTag[]>;
37
42
  private readonly selectedIndex$;
38
43
  accessor value: ReadonlySignal<string[]>;
@@ -77,7 +77,7 @@ class TagManager {
77
77
  constructor(ops) {
78
78
  this.ops = ops;
79
79
  this.changeTag = (option) => {
80
- this.ops.onOptionsChange(this.ops.options.value.map(item => {
80
+ this.ops.onOptionsChange?.(this.ops.options.value.map(item => {
81
81
  if (item.id === option.id) {
82
82
  return {
83
83
  ...item,
@@ -90,7 +90,7 @@ class TagManager {
90
90
  this.color$ = signal(getTagColor());
91
91
  this.createOption = () => {
92
92
  const value = this.text$.value.trim();
93
- if (value === '')
93
+ if (value === '' || !this.ops.onOptionsChange)
94
94
  return;
95
95
  const id = nanoid();
96
96
  this.ops.onOptionsChange([
@@ -109,7 +109,7 @@ class TagManager {
109
109
  }
110
110
  };
111
111
  this.deleteOption = (id) => {
112
- this.ops.onOptionsChange(this.ops.options.value.filter(item => item.id !== id));
112
+ this.ops.onOptionsChange?.(this.ops.options.value.filter(item => item.id !== id));
113
113
  };
114
114
  this.filteredOptions$ = computed(() => {
115
115
  let matched = false;
@@ -129,7 +129,7 @@ class TagManager {
129
129
  matched = true;
130
130
  }
131
131
  }
132
- if (this.text$.value && !matched) {
132
+ if (this.text$.value && !matched && this.ops.onOptionsChange) {
133
133
  options.push({
134
134
  id: 'create',
135
135
  color: this.color$.value,
@@ -246,11 +246,16 @@ let MultiTagSelect = (() => {
246
246
  </div>`;
247
247
  }
248
248
  renderTags() {
249
+ const editable = !!this.onOptionsChange;
249
250
  return html `
250
251
  <div
251
252
  style="height: 0.5px;background-color: ${cssVarV2('layer/insideBorder/border')};margin: 4px 0;"
252
253
  ></div>
253
- <div class="${selectOptionsTipsStyle}">Select tag or create one</div>
254
+ ${editable
255
+ ? html `<div class="${selectOptionsTipsStyle}">
256
+ Select tag or create one
257
+ </div>`
258
+ : nothing}
254
259
  <div data-testid="tag-option-list" class="${selectOptionsContainerStyle}">
255
260
  ${repeat(this.tagManager.filteredOptions$.value, select => select.id, (select, index) => {
256
261
  const isSelected = index === this.selectedIndex$.value;
@@ -267,7 +272,7 @@ let MultiTagSelect = (() => {
267
272
  };
268
273
  return html `
269
274
  <div
270
- ${!select.isCreate ? sortable(select.id) : nothing}
275
+ ${editable && !select.isCreate ? sortable(select.id) : nothing}
271
276
  class="${classes}"
272
277
  @mouseenter="${mouseenter}"
273
278
  @click="${select.select}"
@@ -277,15 +282,17 @@ let MultiTagSelect = (() => {
277
282
  ? html ` <div class="${selectOptionNewIconStyle}">
278
283
  Create
279
284
  </div>`
280
- : html `
281
- <div
282
- ${dragHandler(select.id)}
283
- class="${selectOptionDragHandlerStyle}"
284
- ></div>
285
- `}
285
+ : editable
286
+ ? html `
287
+ <div
288
+ ${dragHandler(select.id)}
289
+ class="${selectOptionDragHandlerStyle}"
290
+ ></div>
291
+ `
292
+ : nothing}
286
293
  ${this.renderTag(select.value, select.color)}
287
294
  </div>
288
- ${!select.isCreate
295
+ ${editable && !select.isCreate
289
296
  ? html ` <div
290
297
  class="${selectOptionIconStyle}"
291
298
  @click="${clickOption}"
@@ -445,7 +452,7 @@ let MultiTagSelect = (() => {
445
452
  onDragEnd: evt => {
446
453
  const over = evt.over;
447
454
  const activeId = evt.active.id;
448
- if (over && over.id !== activeId) {
455
+ if (over && over.id !== activeId && this.onOptionsChange) {
449
456
  this.onOptionsChange(arrayMove(this.options.value, this.options.value.findIndex(v => v.id === activeId), this.options.value.findIndex(v => v.id === over.id)));
450
457
  this.requestUpdate();
451
458
  // const properties = this.filteredOptions$.value.map(v=>v.id);
@@ -470,7 +477,7 @@ let MultiTagSelect = (() => {
470
477
  this.#mode_accessor_storage = __runInitializers(this, _mode_initializers, 'multi');
471
478
  this.#onChange_accessor_storage = (__runInitializers(this, _mode_extraInitializers), __runInitializers(this, _onChange_initializers, void 0));
472
479
  this.#onComplete_accessor_storage = (__runInitializers(this, _onChange_extraInitializers), __runInitializers(this, _onComplete_initializers, void 0));
473
- this.#onOptionsChange_accessor_storage = (__runInitializers(this, _onComplete_extraInitializers), __runInitializers(this, _onOptionsChange_initializers, void 0));
480
+ this.#onOptionsChange_accessor_storage = (__runInitializers(this, _onComplete_extraInitializers), __runInitializers(this, _onOptionsChange_initializers, undefined));
474
481
  this.#options_accessor_storage = (__runInitializers(this, _onOptionsChange_extraInitializers), __runInitializers(this, _options_initializers, void 0));
475
482
  this.selectedIndex$ = (__runInitializers(this, _options_extraInitializers), signal(0));
476
483
  this.#value_accessor_storage = __runInitializers(this, _value_initializers, void 0);
@@ -13,6 +13,7 @@ import { SelectGroupView } from './group-by/renderer/select-group.js';
13
13
  import { StringGroupView } from './group-by/renderer/string-group.js';
14
14
  import { GroupSetting } from './group-by/setting.js';
15
15
  import { AffineLitIcon, UniAnyRender, UniLit } from './index.js';
16
+ import { StandaloneCellHost } from './property/standalone-cell.js';
16
17
  import { AnyRender } from './utils/uni-component/render-template.js';
17
18
  export function coreEffects() {
18
19
  customElements.define('affine-data-view-renderer', DataViewRootUI);
@@ -34,4 +35,5 @@ export function coreEffects() {
34
35
  customElements.define('uni-any-render', UniAnyRender);
35
36
  customElements.define('variable-ref-view', VariableRefView);
36
37
  customElements.define('affine-data-view-record-detail', RecordDetail);
38
+ customElements.define('dv-standalone-cell', StandaloneCellHost);
37
39
  }
@@ -3,4 +3,5 @@ export * from './convert.js';
3
3
  export * from './manager.js';
4
4
  export * from './property-config.js';
5
5
  export * from './renderer.js';
6
+ export * from './standalone-cell.js';
6
7
  export * from './types.js';
@@ -3,4 +3,5 @@ export * from './convert.js';
3
3
  export * from './manager.js';
4
4
  export * from './property-config.js';
5
5
  export * from './renderer.js';
6
+ export * from './standalone-cell.js';
6
7
  export * from './types.js';
@@ -0,0 +1,95 @@
1
+ import { type GeneralServiceIdentifier } from '../../../global/di/index.js';
2
+ import { ShadowlessElement } from '../../../std/index.js';
3
+ import type { ExtensionType } from '../../../store/index.js';
4
+ import { type ReadonlySignal } from '@preact/signals-core';
5
+ import { nothing } from 'lit';
6
+ import type { DatabaseFlags } from '../types.js';
7
+ import type { Cell } from '../view-manager/cell.js';
8
+ import type { PropertyMetaConfig } from './property-config.js';
9
+ /**
10
+ * A cell outside any view: one property's value drawn and edited by the very
11
+ * cell renderer a table cell mounts (checkbox, select, multi-select, date,
12
+ * number, text, a link…), for a host that has a value and no table, such as
13
+ * the title band under a page title (ADR 0035 §11).
14
+ *
15
+ * A cell renderer is written against a `Cell` bound to a `SingleView` and a
16
+ * data source. Outside a view there are neither, and building a data source
17
+ * for one value would be a second store. What the presets actually read is
18
+ * small, and this seam provides exactly that and nothing more:
19
+ * - of the property: `name$`, `data$`, `type$`, `readonly$`, `dataUpdate`,
20
+ * `renderer$`, `meta$`, and `dataCanSet`;
21
+ * - of the view: `featureFlags$` (the number format), `serviceGet` (the link
22
+ * cell's editor host) and `readonly$`;
23
+ * - of the cell: `value$` and `valueSet`, with the JSON value the raw one,
24
+ * which holds for every preset a standalone cell is drawn for.
25
+ * The rest of `SingleView` and `Row` is absent: a renderer that starts
26
+ * reading it fails `standalone-cell.unit.spec.ts`, which mounts every preset
27
+ * through this seam, rather than a host at run time.
28
+ */
29
+ export interface StandaloneCellSource<RawValue = unknown, Data extends Record<string, unknown> = Record<string, unknown>> {
30
+ readonly propertyId: string;
31
+ readonly name$: ReadonlySignal<string>;
32
+ readonly data$: ReadonlySignal<Data>;
33
+ readonly value$: ReadonlySignal<RawValue | undefined>;
34
+ readonly readonly$: ReadonlySignal<boolean>;
35
+ /** A value the cell's editor commits; the host decides when it shows. */
36
+ valueSet(value: RawValue | undefined): void;
37
+ /**
38
+ * Writes the property's config (a select's options). Absent, the config is
39
+ * not the host's to write here: a select offers its options and creates,
40
+ * renames, recolours, reorders or deletes none.
41
+ */
42
+ dataSet?(data: Data): void;
43
+ /** The view's flags (`enable_number_formatting`); absent, all off. */
44
+ readonly featureFlags$?: ReadonlySignal<DatabaseFlags>;
45
+ /** What `view.serviceGet` answers; absent, nothing. */
46
+ serviceGet?<T>(key: GeneralServiceIdentifier<T>): T | null;
47
+ }
48
+ /** A `Cell` for one value outside any view, drawn with `meta`'s renderer. */
49
+ export declare function createStandaloneCell<RawValue = unknown, Data extends Record<string, unknown> = Record<string, unknown>>(meta: PropertyMetaConfig, source: StandaloneCellSource<RawValue, Data>): Cell<RawValue, RawValue, Data>;
50
+ /**
51
+ * A property type a standalone cell can be drawn with, registered by the
52
+ * package that owns its renderer when that package sits above the host: the
53
+ * database block registers its `link` cell, which the title band (a fragment
54
+ * the database block depends on) cannot import. The presets of this package
55
+ * need no registration; a host imports them.
56
+ */
57
+ export declare const StandaloneCellMetaProvider: import("../../../global/di/types.js").ServiceIdentifier<PropertyMetaConfig> & (<U extends PropertyMetaConfig = PropertyMetaConfig>(variant: import("../../../global/di/types.js").ServiceVariant) => import("../../../global/di/types.js").ServiceIdentifier<U>);
58
+ export declare function StandaloneCellMetaExtension<Type extends string, Data extends NonNullable<unknown>, RawValue, JsonValue>(meta: PropertyMetaConfig<Type, Data, RawValue, JsonValue>): ExtensionType;
59
+ declare const StandaloneCellHost_base: typeof ShadowlessElement & import("../../../global/utils/types.js").Constructor<import("../../../global/lit/with-disposable.js").DisposableClass>;
60
+ /**
61
+ * The element that hosts a standalone cell: it mounts the cell renderer the
62
+ * way a table cell container does and owns the same edit lifecycle
63
+ * (`beforeEnterEditMode`, `afterEnterEditingMode`, `beforeExitEditingMode`),
64
+ * so a click, Enter or Space starts the renderer's own editor: the checkbox
65
+ * toggles, a select pops its tag menu, the date its picker, a text its input.
66
+ *
67
+ * Leaving: a popup editor (select, date) closes itself on a click away and
68
+ * calls `selectCurrentCell(false)`, as in the table; an editor drawn in place
69
+ * (an input inside this element) leaves when the focus does, Escape included.
70
+ * Either way the renderer's exit hook commits, exactly once.
71
+ */
72
+ export declare class StandaloneCellHost extends StandaloneCellHost_base {
73
+ static styles: import("lit").CSSResult;
74
+ private readonly _cell$;
75
+ private _exiting;
76
+ readonly isEditing$: import("@preact/signals-core").Signal<boolean>;
77
+ /** Opens the renderer's editor; a checkbox toggles instead. */
78
+ edit(): void;
79
+ /** Closes the editor; the renderer's exit hook commits its value. */
80
+ exit(): void;
81
+ private readonly _selectCurrentCell;
82
+ connectedCallback(): void;
83
+ render(): import("lit-html").TemplateResult<1> | typeof nothing;
84
+ accessor cell: Cell;
85
+ /** Drawn while the value is empty and no editor is open. */
86
+ accessor placeholder: string;
87
+ /** Draws the value and opens no editor. */
88
+ accessor readonly: boolean;
89
+ }
90
+ declare global {
91
+ interface HTMLElementTagNameMap {
92
+ 'dv-standalone-cell': StandaloneCellHost;
93
+ }
94
+ }
95
+ export {};