@formicoidea/labre-core 0.57.0 → 0.59.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 +94 -65
- package/architecture/domain.c4 +2510 -0
- package/architecture/likec4.config.json +3 -3
- package/dist/_pkgs/affine-block-attachment/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-attachment/edgeless-clipboard-config.js +18 -13
- package/dist/_pkgs/affine-block-callout/adapters/markdown.js +4 -1
- package/dist/_pkgs/affine-block-code/adapters/html.js +1 -1
- package/dist/_pkgs/affine-block-code/adapters/markdown/preprocessor.js +13 -1
- package/dist/_pkgs/affine-block-code/adapters/notion-html.js +1 -1
- package/dist/_pkgs/affine-block-code/code-block.d.ts +17 -2
- package/dist/_pkgs/affine-block-code/code-block.js +28 -23
- package/dist/_pkgs/affine-block-code/code-toolbar/components/lang-button.js +17 -4
- package/dist/_pkgs/affine-block-code/code-toolbar/components/preview-button.js +1 -1
- package/dist/_pkgs/affine-block-data-view/data-source.js +12 -5
- package/dist/_pkgs/affine-block-edgeless-text/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-edgeless-text/edgeless-clipboard-config.js +8 -5
- package/dist/_pkgs/affine-block-image/asset-picker.d.ts +23 -2
- package/dist/_pkgs/affine-block-image/asset-picker.js +52 -12
- package/dist/_pkgs/affine-block-image/configs/replace-action.d.ts +8 -5
- package/dist/_pkgs/affine-block-image/configs/replace-action.js +8 -8
- package/dist/_pkgs/affine-block-image/configs/toolbar.js +2 -1
- package/dist/_pkgs/affine-block-image/crop/crop-controller.d.ts +15 -0
- package/dist/_pkgs/affine-block-image/crop/crop-controller.js +40 -2
- package/dist/_pkgs/affine-block-image/crop/crop-math.d.ts +22 -0
- package/dist/_pkgs/affine-block-image/crop/crop-math.js +55 -2
- package/dist/_pkgs/affine-block-image/crop/crop-overlay.d.ts +17 -3
- package/dist/_pkgs/affine-block-image/crop/crop-overlay.js +64 -6
- package/dist/_pkgs/affine-block-image/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-image/edgeless-clipboard-config.js +20 -14
- package/dist/_pkgs/affine-block-image/image-block.js +1 -0
- package/dist/_pkgs/affine-block-image/image-edgeless-block.js +3 -0
- package/dist/_pkgs/affine-block-image/index.d.ts +2 -0
- package/dist/_pkgs/affine-block-image/index.js +2 -0
- package/dist/_pkgs/affine-block-image/replace/commands.d.ts +68 -0
- package/dist/_pkgs/affine-block-image/replace/commands.js +200 -0
- package/dist/_pkgs/affine-block-image/replace/replace-model.d.ts +44 -0
- package/dist/_pkgs/affine-block-image/replace/replace-model.js +168 -0
- package/dist/_pkgs/affine-block-image/replace/toolbar.d.ts +21 -0
- package/dist/_pkgs/affine-block-image/replace/toolbar.js +159 -0
- package/dist/_pkgs/affine-block-image/translations.d.ts +15 -2
- package/dist/_pkgs/affine-block-image/translations.js +35 -2
- package/dist/_pkgs/affine-block-image/utils.d.ts +7 -0
- package/dist/_pkgs/affine-block-image/utils.js +13 -0
- package/dist/_pkgs/affine-block-image/view.js +7 -0
- package/dist/_pkgs/affine-block-note/components/edgeless-page-block-title.d.ts +14 -5
- package/dist/_pkgs/affine-block-note/components/edgeless-page-block-title.js +18 -11
- package/dist/_pkgs/affine-block-note/config.d.ts +9 -2
- package/dist/_pkgs/affine-block-note/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-note/edgeless-clipboard-config.js +8 -5
- package/dist/_pkgs/affine-block-paragraph/adapters/markdown.js +11 -0
- package/dist/_pkgs/affine-block-root/commands/invisible-characters-commands.d.ts +17 -0
- package/dist/_pkgs/affine-block-root/commands/invisible-characters-commands.js +123 -0
- package/dist/_pkgs/affine-block-root/edgeless/clipboard/command.js +82 -65
- package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.js +2 -0
- package/dist/_pkgs/affine-block-root/index.d.ts +1 -0
- package/dist/_pkgs/affine-block-root/index.js +1 -0
- package/dist/_pkgs/affine-block-root/translations.d.ts +6 -0
- package/dist/_pkgs/affine-block-root/translations.js +10 -0
- package/dist/_pkgs/affine-block-root/view.js +6 -1
- package/dist/_pkgs/affine-block-surface/commands/index.d.ts +1 -1
- package/dist/_pkgs/affine-block-surface/commands/index.js +1 -1
- package/dist/_pkgs/affine-block-surface/commands/reassociate-connectors.d.ts +9 -0
- package/dist/_pkgs/affine-block-surface/commands/reassociate-connectors.js +21 -12
- package/dist/_pkgs/affine-block-surface/extensions/clipboard-config.d.ts +33 -0
- package/dist/_pkgs/affine-block-surface/extensions/clipboard-config.js +53 -0
- package/dist/_pkgs/affine-block-surface/extensions/reading-toolbar.js +12 -12
- package/dist/_pkgs/affine-block-surface/framework-background/background-view.js +2 -1
- package/dist/_pkgs/affine-block-surface/framework-background/band-widths.d.ts +104 -0
- package/dist/_pkgs/affine-block-surface/framework-background/band-widths.js +156 -0
- package/dist/_pkgs/affine-block-surface/framework-background/def.d.ts +87 -4
- package/dist/_pkgs/affine-block-surface/framework-background/def.js +26 -7
- package/dist/_pkgs/affine-block-surface/framework-background/ellipsis.d.ts +58 -0
- package/dist/_pkgs/affine-block-surface/framework-background/ellipsis.js +110 -0
- package/dist/_pkgs/affine-block-surface/framework-background/index.d.ts +3 -0
- package/dist/_pkgs/affine-block-surface/framework-background/index.js +3 -0
- package/dist/_pkgs/affine-block-surface/framework-background/labels.d.ts +12 -2
- package/dist/_pkgs/affine-block-surface/framework-background/labels.js +29 -5
- package/dist/_pkgs/affine-block-surface/framework-background/measure-text.d.ts +14 -0
- package/dist/_pkgs/affine-block-surface/framework-background/measure-text.js +31 -0
- package/dist/_pkgs/affine-block-surface/framework-background/renderer.d.ts +14 -1
- package/dist/_pkgs/affine-block-surface/framework-background/renderer.js +84 -31
- package/dist/_pkgs/affine-block-table/adapters/html.js +26 -14
- package/dist/_pkgs/affine-block-table/adapters/utils.d.ts +1 -0
- package/dist/_pkgs/affine-block-table/adapters/utils.js +23 -5
- package/dist/_pkgs/affine-block-table/header-menu.d.ts +13 -0
- package/dist/_pkgs/affine-block-table/header-menu.js +25 -0
- package/dist/_pkgs/affine-block-table/selection-controller.d.ts +15 -0
- package/dist/_pkgs/affine-block-table/selection-controller.js +62 -0
- package/dist/_pkgs/affine-block-table/table-cell-css.d.ts +7 -0
- package/dist/_pkgs/affine-block-table/table-cell-css.js +10 -0
- package/dist/_pkgs/affine-block-table/table-cell.d.ts +8 -0
- package/dist/_pkgs/affine-block-table/table-cell.js +35 -3
- package/dist/_pkgs/affine-block-table/table-data-manager.d.ts +14 -0
- package/dist/_pkgs/affine-block-table/table-data-manager.js +44 -3
- package/dist/_pkgs/affine-block-table/translations.d.ts +14 -0
- package/dist/_pkgs/affine-block-table/translations.js +22 -0
- package/dist/_pkgs/affine-components/highlight-dropdown-menu/highlight-duotone-icon.js +8 -8
- package/dist/_pkgs/affine-components/highlight-dropdown-menu/text-duotone-icon.js +11 -11
- package/dist/_pkgs/affine-fragment-doc-title/title-band/title-band.d.ts +3 -1
- package/dist/_pkgs/affine-fragment-doc-title/title-band/title-band.js +15 -2
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/mindmap-tool-button.d.ts +2 -2
- package/dist/_pkgs/affine-gfx-template/builtin/other.d.ts +4 -0
- package/dist/_pkgs/affine-gfx-template/builtin/other.js +1 -1
- package/dist/_pkgs/affine-gfx-template/builtin/slides/build.d.ts +81 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/build.js +276 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/consts.d.ts +126 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/consts.js +101 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/index.d.ts +8 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/index.js +27 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/masks.d.ts +83 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/masks.js +674 -0
- package/dist/_pkgs/affine-gfx-template/contribute.js +12 -17
- package/dist/_pkgs/affine-gfx-template/make-snapshot.d.ts +14 -2
- package/dist/_pkgs/affine-gfx-template/make-snapshot.js +6 -2
- package/dist/_pkgs/affine-gfx-template/services/template-middlewares.d.ts +12 -0
- package/dist/_pkgs/affine-gfx-template/services/template-middlewares.js +48 -0
- package/dist/_pkgs/affine-gfx-template/services/template.js +2 -1
- package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.d.ts +15 -1
- package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.js +33 -37
- package/dist/_pkgs/affine-gfx-template/toolbar/template-type.d.ts +6 -0
- package/dist/_pkgs/affine-gfx-template/translations.d.ts +94 -0
- package/dist/_pkgs/affine-gfx-template/translations.js +441 -2
- package/dist/_pkgs/affine-model/blocks/table/table-model.d.ts +4 -0
- package/dist/_pkgs/affine-model/blocks/table/table-model.js +4 -0
- package/dist/_pkgs/affine-model/elements/bpmn/node.d.ts +46 -3
- package/dist/_pkgs/affine-model/elements/bpmn/node.js +47 -4
- package/dist/_pkgs/affine-model/elements/bpmn/pool.d.ts +20 -0
- package/dist/_pkgs/affine-model/elements/bpmn/pool.js +33 -4
- package/dist/_pkgs/affine-shared/services/edit-props-store.d.ts +3 -16
- package/dist/_pkgs/affine-shared/services/edit-props-store.js +16 -16
- package/dist/_pkgs/affine-shared/services/editor-setting-service.d.ts +3 -0
- package/dist/_pkgs/affine-shared/services/editor-setting-service.js +4 -0
- package/dist/_pkgs/affine-shared/services/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/services/index.js +1 -0
- package/dist/_pkgs/affine-shared/services/invisible-characters.d.ts +33 -0
- package/dist/_pkgs/affine-shared/services/invisible-characters.js +63 -0
- package/dist/_pkgs/affine-shared/services/link-preview-service/link-preview-cache.d.ts +0 -9
- package/dist/_pkgs/affine-shared/services/link-preview-service/link-preview-cache.js +3 -9
- package/dist/_pkgs/affine-shared/services/telemetry-service/lifecycle.d.ts +26 -0
- package/dist/_pkgs/affine-shared/services/telemetry-service/telemetry-service.d.ts +4 -3
- package/dist/_pkgs/affine-shared/services/telemetry-service/types.d.ts +11 -0
- package/dist/_pkgs/affine-shared/utils/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/utils/index.js +1 -0
- package/dist/_pkgs/affine-shared/utils/invisible-characters.d.ts +42 -0
- package/dist/_pkgs/affine-shared/utils/invisible-characters.js +81 -0
- package/dist/_pkgs/affine-widget-edgeless-zoom-toolbar/index.js +26 -26
- package/dist/_pkgs/affine-widget-edgeless-zoom-toolbar/zoom-toolbar.js +13 -2
- package/dist/_pkgs/affine-widget-keyboard-toolbar/icons.js +98 -98
- package/dist/_pkgs/affine-widget-page-dragging-area/index.js +10 -10
- package/dist/_pkgs/affine-widget-viewport-overlay/index.js +13 -13
- package/dist/_pkgs/data-view/core/utils/menu-title.js +17 -17
- package/dist/_pkgs/data-view/view-presets/table/pc/header/column-header.js +6 -0
- package/dist/_pkgs/data-view/view-presets/table/pc/table-view-ui-logic.js +5 -2
- package/dist/_pkgs/std/clipboard/clipboard.d.ts +15 -1
- package/dist/_pkgs/std/clipboard/clipboard.js +18 -0
- package/dist/_pkgs/std/inline/components/embed-gap.js +1 -1
- package/dist/_pkgs/std/inline/components/v-line.js +1 -1
- package/dist/_pkgs/std/inline/components/v-text.d.ts +15 -2
- package/dist/_pkgs/std/inline/components/v-text.js +147 -15
- package/dist/_pkgs/std/inline/consts.d.ts +5 -0
- package/dist/_pkgs/std/inline/consts.js +5 -0
- package/dist/_pkgs/std/inline/utils/index.d.ts +1 -0
- package/dist/_pkgs/std/inline/utils/index.js +1 -0
- package/dist/_pkgs/std/inline/utils/invisible-characters.d.ts +57 -0
- package/dist/_pkgs/std/inline/utils/invisible-characters.js +162 -0
- package/dist/_pkgs/std/inline/utils/point-conversion.js +3 -3
- package/dist/_pkgs/std/inline/utils/text.d.ts +8 -0
- package/dist/_pkgs/std/inline/utils/text.js +11 -2
- package/dist/_pkgs/store/model/store/crud.d.ts +28 -0
- package/dist/_pkgs/store/model/store/crud.js +97 -30
- package/dist/_pkgs/store/model/store/query.js +3 -2
- package/dist/_pkgs/store/model/store/store.d.ts +21 -0
- package/dist/_pkgs/store/model/store/store.js +88 -21
- package/dist/_pkgs/store/transformer/transformer.d.ts +46 -0
- package/dist/_pkgs/store/transformer/transformer.js +72 -0
- package/dist/commands.js +6 -1
- package/dist/translations.js +2 -0
- package/package.json +3 -4
|
@@ -37,10 +37,11 @@ import { DOC_UNTITLED, FeatureFlagService, formatLocale, PropertiesPanelProvider
|
|
|
37
37
|
import { stopPropagation } from '../../affine-shared/utils/index.js';
|
|
38
38
|
import { createStandaloneCell, StandaloneCellMetaProvider, } from '../../data-view/index.js';
|
|
39
39
|
import { SignalWatcher, WithDisposable } from '../../global/lit/index.js';
|
|
40
|
-
import { ShadowlessElement } from '../../std/index.js';
|
|
40
|
+
import { ShadowlessElement, stdContext } from '../../std/index.js';
|
|
41
|
+
import { ContextProvider } from '@lit/context';
|
|
41
42
|
import { LinkedPageIcon, PlusIcon, SidebarIcon, ToggleDownIcon, ToggleRightIcon, } from '@blocksuite/icons/lit';
|
|
42
43
|
import { computed, signal } from '@preact/signals-core';
|
|
43
|
-
import { css, html, nothing } from 'lit';
|
|
44
|
+
import { css, html, nothing, } from 'lit';
|
|
44
45
|
import { property } from 'lit/decorators.js';
|
|
45
46
|
import { repeat } from 'lit/directives/repeat.js';
|
|
46
47
|
import { TITLE_BAND_ADD, TITLE_BAND_COLLAPSE, TITLE_BAND_EMPTY, TITLE_BAND_EXPAND, TITLE_BAND_LABEL, TITLE_BAND_LOADING, TITLE_BAND_NOT_SHOWN, TITLE_BAND_OPEN_PANEL, TITLE_BAND_SHOW_HERE, } from '../translations.js';
|
|
@@ -629,6 +630,11 @@ let TitleBand = (() => {
|
|
|
629
630
|
})}
|
|
630
631
|
</div>`;
|
|
631
632
|
}
|
|
633
|
+
willUpdate(changed) {
|
|
634
|
+
super.willUpdate(changed);
|
|
635
|
+
if (changed.has('std') && this.std)
|
|
636
|
+
this._stdProvider.setValue(this.std);
|
|
637
|
+
}
|
|
632
638
|
connectedCallback() {
|
|
633
639
|
super.connectedCallback();
|
|
634
640
|
// The band lives inside the title and inside the note: a key or a press
|
|
@@ -697,6 +703,13 @@ let TitleBand = (() => {
|
|
|
697
703
|
}
|
|
698
704
|
this._openPanel();
|
|
699
705
|
};
|
|
706
|
+
// The band is drawn in the title, outside `editor-host`, so its cells find
|
|
707
|
+
// no `stdContext` to consume and their tag menu and date picker spoke
|
|
708
|
+
// English under a French host (recette 1, 2026-10-22). The band hands them
|
|
709
|
+
// its own scope.
|
|
710
|
+
this._stdProvider = new ContextProvider(this, {
|
|
711
|
+
context: stdContext,
|
|
712
|
+
});
|
|
700
713
|
this.#std_accessor_storage = __runInitializers(this, _std_initializers, null);
|
|
701
714
|
this.#docId_accessor_storage = (__runInitializers(this, _std_extraInitializers), __runInitializers(this, _docId_initializers, ''));
|
|
702
715
|
this.#surface_accessor_storage = (__runInitializers(this, _docId_extraInitializers), __runInitializers(this, _surface_initializers, 'page'));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TextTool } from '../../affine-gfx-text/index.js';
|
|
2
2
|
import { EdgelessDraggableElementController } from '../../affine-widget-edgeless-toolbar/index.js';
|
|
3
3
|
import { LitElement } from 'lit';
|
|
4
4
|
import { type DraggableTool } from './basket-elements.js';
|
|
@@ -8,7 +8,7 @@ export declare class EdgelessMindmapToolButton extends EdgelessMindmapToolButton
|
|
|
8
8
|
private readonly _style$;
|
|
9
9
|
draggableController: EdgelessDraggableElementController<DraggableTool>;
|
|
10
10
|
enableActiveBackground: boolean;
|
|
11
|
-
type: (typeof
|
|
11
|
+
type: (typeof TextTool)[];
|
|
12
12
|
get draggableTools(): DraggableTool[];
|
|
13
13
|
get mindmaps(): import("./assets.js").ToolbarMindmapItem[];
|
|
14
14
|
get crud(): import("../../affine-block-surface/index.js").EdgelessCRUDExtension;
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
+
import { type ChromeWording, type TranslationParams } from '../../affine-shared/services/index.js';
|
|
2
|
+
import type { BlockStdScope } from '../../std/index.js';
|
|
1
3
|
import type { TemplateCategory } from '../toolbar/template-type.js';
|
|
4
|
+
/** Resolve a wording through the host, or its English fallback with no host. */
|
|
5
|
+
export declare function tr(std: BlockStdScope | undefined, wording: ChromeWording, params?: TranslationParams): string;
|
|
2
6
|
export declare const otherTemplateCategory: TemplateCategory;
|
|
@@ -66,7 +66,7 @@ function line(x1, y1, x2, y2, opts = {}) {
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
/** Resolve a wording through the host, or its English fallback with no host. */
|
|
69
|
-
function tr(std, wording, params) {
|
|
69
|
+
export function tr(std, wording, params) {
|
|
70
70
|
return std
|
|
71
71
|
? translateKey(std, ...wording, params)
|
|
72
72
|
: fillPlaceholders(wording[1], params);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { BlockStdScope } from '../../../std/index.js';
|
|
2
|
+
import { type SurfaceChildBlockJSON, type SurfaceElementsJSON } from '../../make-snapshot.js';
|
|
3
|
+
import { type SlideTextRole } from './consts.js';
|
|
4
|
+
import type { SlideMask } from './masks.js';
|
|
5
|
+
/**
|
|
6
|
+
* The one builder of the slide masks: a mask declaration (`masks.ts`) in, a
|
|
7
|
+
* template snapshot (one 1600 x 900 frame and the elements it holds) and a
|
|
8
|
+
* tile preview out. Nothing here knows a particular mask.
|
|
9
|
+
*/
|
|
10
|
+
/** The map key of the slide number, the LAST element of every mask. */
|
|
11
|
+
export declare const SLIDE_NUMBER_KEY = "number";
|
|
12
|
+
/** The map key of the footer line. */
|
|
13
|
+
export declare const SLIDE_FOOTER_KEY = "footer";
|
|
14
|
+
/** A text box's height for the lines it is sized for. */
|
|
15
|
+
export declare function slideTextHeight(role: SlideTextRole, lines?: number): number;
|
|
16
|
+
/** The elements of one mask, footer and slide number last, in paint order. */
|
|
17
|
+
export declare function slideElements(mask: SlideMask, std?: BlockStdScope): SurfaceElementsJSON;
|
|
18
|
+
/** The template content of one mask: a page, its surface, the frame. */
|
|
19
|
+
export declare function slideSnapshot(mask: SlideMask, std?: BlockStdScope): {
|
|
20
|
+
type: string;
|
|
21
|
+
meta: {
|
|
22
|
+
id: string;
|
|
23
|
+
title: string;
|
|
24
|
+
createDate: number;
|
|
25
|
+
tags: never[];
|
|
26
|
+
};
|
|
27
|
+
blocks: {
|
|
28
|
+
type: string;
|
|
29
|
+
id: string;
|
|
30
|
+
flavour: string;
|
|
31
|
+
props: {
|
|
32
|
+
title: {
|
|
33
|
+
'$blocksuite:internal:text$': boolean;
|
|
34
|
+
delta: {
|
|
35
|
+
insert: string;
|
|
36
|
+
}[];
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
children: {
|
|
40
|
+
type: string;
|
|
41
|
+
id: string;
|
|
42
|
+
flavour: string;
|
|
43
|
+
props: {
|
|
44
|
+
elements: SurfaceElementsJSON;
|
|
45
|
+
};
|
|
46
|
+
children: SurfaceChildBlockJSON[];
|
|
47
|
+
}[];
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Write the slide number once, at placement: the inserted frame's rank among
|
|
52
|
+
* the document's frames in presentation order (`presentationIndex`, the
|
|
53
|
+
* legacy frames without one after the keyed ones, as the frame manager
|
|
54
|
+
* orders them). Later reordering does not renumber: the number is the
|
|
55
|
+
* author's text from then on.
|
|
56
|
+
*
|
|
57
|
+
* ponytail: the template snapshot carries no `presentationIndex`, so the
|
|
58
|
+
* inserted frame takes the schema default, `generateKeyBetweenV2(null,
|
|
59
|
+
* null)`, whose random suffix ranks it anywhere among the frames: the number
|
|
60
|
+
* is the frame's true rank, but that rank is arbitrary until the template
|
|
61
|
+
* job's `presentationIndex` middleware (a key after the last frame) lands,
|
|
62
|
+
* after which the new slide is always last. Nothing here changes then.
|
|
63
|
+
*/
|
|
64
|
+
export declare function numberSlide(std: BlockStdScope, insertedIds: string[]): void;
|
|
65
|
+
/** The fields of a frame the slide number is ranked by. */
|
|
66
|
+
type RankedFrame = {
|
|
67
|
+
props: {
|
|
68
|
+
presentationIndex?: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
/** A frame's 1-based rank among `frames`; ties count as before it. */
|
|
72
|
+
export declare function slideNumberOf<T extends RankedFrame>(own: T, frames: T[]): number;
|
|
73
|
+
/**
|
|
74
|
+
* The tile: the slide itself, drawn from its own declaration at 1/10th, so a
|
|
75
|
+
* preview can never drift from what the mask inserts. Texts are bars, the
|
|
76
|
+
* light side of every colour is used (a tile is chrome on the panel's own
|
|
77
|
+
* paper), and the slide gets a hairline so a white slide shows on a white
|
|
78
|
+
* panel.
|
|
79
|
+
*/
|
|
80
|
+
export declare function slidePreview(mask: SlideMask): string;
|
|
81
|
+
export {};
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { ColorScheme, ConnectorMode, FontFamily, PointStyle, resolveColor, ShapeStyle, StrokeStyle, TextAlign, } from '../../../affine-model/index.js';
|
|
2
|
+
import { GfxControllerIdentifier } from '../../../std/gfx/index.js';
|
|
3
|
+
import * as Y from 'yjs';
|
|
4
|
+
import { makeTemplateSnapshot, surfaceText, } from '../../make-snapshot.js';
|
|
5
|
+
import { SLIDE_SEED_FOOTER, SLIDE_SEED_IMAGE } from '../../translations.js';
|
|
6
|
+
import { tr } from '../other.js';
|
|
7
|
+
import { SLIDE_FOOTER_Y, SLIDE_HAIRLINE_WIDTH, SLIDE_HEIGHT, SLIDE_LINE_HEIGHT, SLIDE_MARGIN, SLIDE_PALETTES, SLIDE_RADIUS, SLIDE_TYPE, SLIDE_WIDTH, SLIDE_ZONE_STROKE_WIDTH, } from './consts.js';
|
|
8
|
+
/**
|
|
9
|
+
* The one builder of the slide masks: a mask declaration (`masks.ts`) in, a
|
|
10
|
+
* template snapshot (one 1600 x 900 frame and the elements it holds) and a
|
|
11
|
+
* tile preview out. Nothing here knows a particular mask.
|
|
12
|
+
*/
|
|
13
|
+
/** The map key of the slide number, the LAST element of every mask. */
|
|
14
|
+
export const SLIDE_NUMBER_KEY = 'number';
|
|
15
|
+
/** The map key of the footer line. */
|
|
16
|
+
export const SLIDE_FOOTER_KEY = 'footer';
|
|
17
|
+
const xywh = (x, y, w, h) => `[${x},${y},${w},${h}]`;
|
|
18
|
+
/** A text box's height for the lines it is sized for. */
|
|
19
|
+
export function slideTextHeight(role, lines = 1) {
|
|
20
|
+
return Math.ceil(lines * SLIDE_TYPE[role].fontSize * SLIDE_LINE_HEIGHT);
|
|
21
|
+
}
|
|
22
|
+
const ALIGN = {
|
|
23
|
+
left: TextAlign.Left,
|
|
24
|
+
center: TextAlign.Center,
|
|
25
|
+
right: TextAlign.Right,
|
|
26
|
+
};
|
|
27
|
+
function textElement(zone, words, palette) {
|
|
28
|
+
const type = SLIDE_TYPE[zone.role];
|
|
29
|
+
return {
|
|
30
|
+
type: 'text',
|
|
31
|
+
text: surfaceText(words),
|
|
32
|
+
color: zone.tone === 'muted' ? palette.muted : palette.ink,
|
|
33
|
+
fontFamily: FontFamily.Inter,
|
|
34
|
+
fontSize: type.fontSize,
|
|
35
|
+
fontWeight: type.fontWeight,
|
|
36
|
+
textAlign: ALIGN[zone.align ?? 'left'],
|
|
37
|
+
hasMaxWidth: true,
|
|
38
|
+
xywh: xywh(zone.x, zone.y, zone.w, slideTextHeight(zone.role, zone.lines)),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function shapeElement(x, y, w, h, opts) {
|
|
42
|
+
const element = {
|
|
43
|
+
type: 'shape',
|
|
44
|
+
shapeType: opts.shapeType,
|
|
45
|
+
filled: opts.fill !== null,
|
|
46
|
+
fillColor: opts.fill ?? SLIDE_PALETTES.paper.paper,
|
|
47
|
+
strokeColor: opts.stroke,
|
|
48
|
+
strokeWidth: opts.dash ? SLIDE_ZONE_STROKE_WIDTH : SLIDE_HAIRLINE_WIDTH,
|
|
49
|
+
strokeStyle: opts.dash ? StrokeStyle.Dash : StrokeStyle.Solid,
|
|
50
|
+
shapeStyle: ShapeStyle.General,
|
|
51
|
+
roughness: 0,
|
|
52
|
+
radius: opts.shapeType === 'rect' ? opts.radius : 0,
|
|
53
|
+
xywh: xywh(x, y, w, h),
|
|
54
|
+
};
|
|
55
|
+
if (opts.label !== undefined) {
|
|
56
|
+
const type = SLIDE_TYPE[opts.labelRole ?? 'caption'];
|
|
57
|
+
element.text = surfaceText(opts.label);
|
|
58
|
+
element.color = opts.labelColor;
|
|
59
|
+
element.fontFamily = FontFamily.Inter;
|
|
60
|
+
element.fontSize = type.fontSize;
|
|
61
|
+
element.fontWeight = type.fontWeight;
|
|
62
|
+
element.textAlign = TextAlign.Center;
|
|
63
|
+
}
|
|
64
|
+
return element;
|
|
65
|
+
}
|
|
66
|
+
/** A fill zone touching the frame's edge bleeds: no rounded corner there. */
|
|
67
|
+
function bleeds(zone) {
|
|
68
|
+
return (zone.x <= 0 ||
|
|
69
|
+
zone.y <= 0 ||
|
|
70
|
+
zone.x + zone.w >= SLIDE_WIDTH ||
|
|
71
|
+
zone.y + zone.h >= SLIDE_HEIGHT);
|
|
72
|
+
}
|
|
73
|
+
function zoneElement(zone, palette, std) {
|
|
74
|
+
switch (zone.kind) {
|
|
75
|
+
case 'text':
|
|
76
|
+
return textElement(zone, zone.seed ? tr(std, zone.seed, zone.params) : (zone.digits ?? ''), palette);
|
|
77
|
+
case 'image':
|
|
78
|
+
return shapeElement(zone.x, zone.y, zone.w, zone.h, {
|
|
79
|
+
shapeType: zone.shape ?? 'rect',
|
|
80
|
+
fill: palette.hairline,
|
|
81
|
+
stroke: palette.zoneStroke,
|
|
82
|
+
dash: true,
|
|
83
|
+
radius: bleeds(zone) ? 0 : SLIDE_RADIUS,
|
|
84
|
+
label: tr(std, zone.label ?? SLIDE_SEED_IMAGE),
|
|
85
|
+
labelRole: 'body',
|
|
86
|
+
labelColor: palette.ink,
|
|
87
|
+
});
|
|
88
|
+
case 'card':
|
|
89
|
+
return shapeElement(zone.x, zone.y, zone.w, zone.h, {
|
|
90
|
+
shapeType: zone.shape ?? 'rect',
|
|
91
|
+
fill: zone.filled ? palette.hairline : null,
|
|
92
|
+
stroke: zone.stroke === 'muted' ? palette.muted : palette.hairline,
|
|
93
|
+
dash: false,
|
|
94
|
+
radius: SLIDE_RADIUS,
|
|
95
|
+
label: zone.label ? tr(std, zone.label, zone.params) : undefined,
|
|
96
|
+
labelRole: 'body',
|
|
97
|
+
labelColor: palette.ink,
|
|
98
|
+
});
|
|
99
|
+
case 'dot':
|
|
100
|
+
return shapeElement(zone.x, zone.y, zone.size, zone.size, {
|
|
101
|
+
shapeType: 'ellipse',
|
|
102
|
+
fill: palette.ink,
|
|
103
|
+
stroke: palette.ink,
|
|
104
|
+
dash: false,
|
|
105
|
+
radius: 0,
|
|
106
|
+
});
|
|
107
|
+
case 'line':
|
|
108
|
+
return {
|
|
109
|
+
type: 'connector',
|
|
110
|
+
mode: ConnectorMode.Straight,
|
|
111
|
+
stroke: palette.muted,
|
|
112
|
+
strokeWidth: SLIDE_HAIRLINE_WIDTH,
|
|
113
|
+
strokeStyle: StrokeStyle.Solid,
|
|
114
|
+
frontEndpointStyle: PointStyle.None,
|
|
115
|
+
rearEndpointStyle: zone.arrow ? PointStyle.Triangle : PointStyle.None,
|
|
116
|
+
source: { position: zone.from },
|
|
117
|
+
target: { position: zone.to },
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/** The elements of one mask, footer and slide number last, in paint order. */
|
|
122
|
+
export function slideElements(mask, std) {
|
|
123
|
+
const palette = SLIDE_PALETTES[mask.variant];
|
|
124
|
+
const elements = {};
|
|
125
|
+
mask.zones.forEach((zone, i) => {
|
|
126
|
+
elements[`z${i}`] = zoneElement(zone, palette, std);
|
|
127
|
+
});
|
|
128
|
+
const footerWidth = 800;
|
|
129
|
+
const numberWidth = 200;
|
|
130
|
+
elements[SLIDE_FOOTER_KEY] = textElement({
|
|
131
|
+
kind: 'text',
|
|
132
|
+
role: 'caption',
|
|
133
|
+
x: SLIDE_MARGIN,
|
|
134
|
+
y: SLIDE_FOOTER_Y,
|
|
135
|
+
w: footerWidth,
|
|
136
|
+
tone: 'muted',
|
|
137
|
+
}, tr(std, SLIDE_SEED_FOOTER), palette);
|
|
138
|
+
// The digits are rewritten at placement by `numberSlide`; "1" is what a
|
|
139
|
+
// copy shows before (and what `content`, the English build, carries).
|
|
140
|
+
elements[SLIDE_NUMBER_KEY] = textElement({
|
|
141
|
+
kind: 'text',
|
|
142
|
+
role: 'caption',
|
|
143
|
+
x: SLIDE_WIDTH - SLIDE_MARGIN - numberWidth,
|
|
144
|
+
y: SLIDE_FOOTER_Y,
|
|
145
|
+
w: numberWidth,
|
|
146
|
+
align: 'right',
|
|
147
|
+
tone: 'muted',
|
|
148
|
+
}, '1', palette);
|
|
149
|
+
return elements;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The mask's frame: the slide itself. Its title is the tile's name, resolved
|
|
153
|
+
* once at placement (a frame title is document content, ADR 0023). No
|
|
154
|
+
* `presentationIndex`: the schema default applies, like a pasted frame.
|
|
155
|
+
*/
|
|
156
|
+
function slideFrame(mask, elements, std) {
|
|
157
|
+
const name = tr(std, mask.name);
|
|
158
|
+
return {
|
|
159
|
+
type: 'block',
|
|
160
|
+
id: `block:slide-${mask.id}`,
|
|
161
|
+
flavour: 'affine:frame',
|
|
162
|
+
props: {
|
|
163
|
+
title: {
|
|
164
|
+
'$blocksuite:internal:text$': true,
|
|
165
|
+
delta: [{ insert: name }],
|
|
166
|
+
},
|
|
167
|
+
background: SLIDE_PALETTES[mask.variant].paper,
|
|
168
|
+
xywh: xywh(0, 0, SLIDE_WIDTH, SLIDE_HEIGHT),
|
|
169
|
+
index: 'a0',
|
|
170
|
+
childElementIds: Object.fromEntries(Object.keys(elements).map(id => [id, true])),
|
|
171
|
+
},
|
|
172
|
+
children: [],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/** The template content of one mask: a page, its surface, the frame. */
|
|
176
|
+
export function slideSnapshot(mask, std) {
|
|
177
|
+
const elements = slideElements(mask, std);
|
|
178
|
+
return makeTemplateSnapshot(elements, mask.name[1], [
|
|
179
|
+
slideFrame(mask, elements, std),
|
|
180
|
+
]);
|
|
181
|
+
}
|
|
182
|
+
/* ── Slide number ─────────────────────────────────────────────────────── */
|
|
183
|
+
/**
|
|
184
|
+
* Write the slide number once, at placement: the inserted frame's rank among
|
|
185
|
+
* the document's frames in presentation order (`presentationIndex`, the
|
|
186
|
+
* legacy frames without one after the keyed ones, as the frame manager
|
|
187
|
+
* orders them). Later reordering does not renumber: the number is the
|
|
188
|
+
* author's text from then on.
|
|
189
|
+
*
|
|
190
|
+
* ponytail: the template snapshot carries no `presentationIndex`, so the
|
|
191
|
+
* inserted frame takes the schema default, `generateKeyBetweenV2(null,
|
|
192
|
+
* null)`, whose random suffix ranks it anywhere among the frames: the number
|
|
193
|
+
* is the frame's true rank, but that rank is arbitrary until the template
|
|
194
|
+
* job's `presentationIndex` middleware (a key after the last frame) lands,
|
|
195
|
+
* after which the new slide is always last. Nothing here changes then.
|
|
196
|
+
*/
|
|
197
|
+
export function numberSlide(std, insertedIds) {
|
|
198
|
+
if (std.store.readonly)
|
|
199
|
+
return;
|
|
200
|
+
const numberId = insertedIds.at(-1);
|
|
201
|
+
if (!numberId)
|
|
202
|
+
return;
|
|
203
|
+
const frames = std.store.getModelsByFlavour('affine:frame');
|
|
204
|
+
const own = frames.find(frame => frame.childIds.includes(numberId));
|
|
205
|
+
if (!own)
|
|
206
|
+
return;
|
|
207
|
+
std.get(GfxControllerIdentifier).updateElement(numberId, {
|
|
208
|
+
text: new Y.Text(String(slideNumberOf(own, frames))),
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
/** A frame's 1-based rank among `frames`; ties count as before it. */
|
|
212
|
+
export function slideNumberOf(own, frames) {
|
|
213
|
+
const rank = (frame) => frame.props.presentationIndex || '\uffff';
|
|
214
|
+
const ownRank = rank(own);
|
|
215
|
+
return (1 + frames.filter(frame => frame !== own && rank(frame) <= ownRank).length);
|
|
216
|
+
}
|
|
217
|
+
/* ── Preview ──────────────────────────────────────────────────────────── */
|
|
218
|
+
const light = (color) => resolveColor(color, ColorScheme.Light);
|
|
219
|
+
/** A text line drawn as a bar, the width of its English words (roughly). */
|
|
220
|
+
function textBars(zone, words, palette) {
|
|
221
|
+
const { fontSize } = SLIDE_TYPE[zone.role];
|
|
222
|
+
const height = Math.max(6, fontSize * 0.55);
|
|
223
|
+
const step = fontSize * SLIDE_LINE_HEIGHT;
|
|
224
|
+
const full = words.length * fontSize * 0.5;
|
|
225
|
+
const lines = Math.max(1, Math.min(zone.lines ?? 1, Math.ceil(full / zone.w)));
|
|
226
|
+
const fill = light(zone.tone === 'muted' ? palette.muted : palette.ink);
|
|
227
|
+
let out = '';
|
|
228
|
+
for (let i = 0; i < lines; i++) {
|
|
229
|
+
const remaining = full - i * zone.w;
|
|
230
|
+
const w = Math.max(fontSize, Math.min(zone.w, remaining));
|
|
231
|
+
const x = zone.align === 'center'
|
|
232
|
+
? zone.x + (zone.w - w) / 2
|
|
233
|
+
: zone.align === 'right'
|
|
234
|
+
? zone.x + zone.w - w
|
|
235
|
+
: zone.x;
|
|
236
|
+
out += `<rect x="${x}" y="${zone.y + i * step + (step - height) / 2}" width="${w}" height="${height}" rx="${height / 2}" fill="${fill}"/>`;
|
|
237
|
+
}
|
|
238
|
+
return out;
|
|
239
|
+
}
|
|
240
|
+
function previewZone(zone, palette) {
|
|
241
|
+
switch (zone.kind) {
|
|
242
|
+
case 'text':
|
|
243
|
+
return textBars(zone, zone.seed?.[1] ?? zone.digits ?? '', palette);
|
|
244
|
+
case 'image':
|
|
245
|
+
case 'card': {
|
|
246
|
+
const filled = zone.kind === 'image' || (zone.kind === 'card' && zone.filled);
|
|
247
|
+
const fill = filled ? light(palette.hairline) : 'none';
|
|
248
|
+
const stroke = light(zone.kind === 'card' && zone.stroke === 'muted'
|
|
249
|
+
? palette.muted
|
|
250
|
+
: zone.kind === 'image'
|
|
251
|
+
? palette.zoneStroke
|
|
252
|
+
: palette.hairline);
|
|
253
|
+
const dash = zone.kind === 'image' ? ' stroke-dasharray="16 12"' : '';
|
|
254
|
+
if (zone.shape === 'ellipse') {
|
|
255
|
+
return `<ellipse cx="${zone.x + zone.w / 2}" cy="${zone.y + zone.h / 2}" rx="${zone.w / 2}" ry="${zone.h / 2}" fill="${fill}" stroke="${stroke}" stroke-width="6"${dash}/>`;
|
|
256
|
+
}
|
|
257
|
+
return `<rect x="${zone.x}" y="${zone.y}" width="${zone.w}" height="${zone.h}" rx="${SLIDE_RADIUS}" fill="${fill}" stroke="${stroke}" stroke-width="6"${dash}/>`;
|
|
258
|
+
}
|
|
259
|
+
case 'dot':
|
|
260
|
+
return `<circle cx="${zone.x + zone.size / 2}" cy="${zone.y + zone.size / 2}" r="${zone.size / 2}" fill="${light(palette.ink)}"/>`;
|
|
261
|
+
case 'line':
|
|
262
|
+
return `<path d="M${zone.from[0]} ${zone.from[1]} L${zone.to[0]} ${zone.to[1]}" stroke="${light(palette.muted)}" stroke-width="6"/>`;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* The tile: the slide itself, drawn from its own declaration at 1/10th, so a
|
|
267
|
+
* preview can never drift from what the mask inserts. Texts are bars, the
|
|
268
|
+
* light side of every colour is used (a tile is chrome on the panel's own
|
|
269
|
+
* paper), and the slide gets a hairline so a white slide shows on a white
|
|
270
|
+
* panel.
|
|
271
|
+
*/
|
|
272
|
+
export function slidePreview(mask) {
|
|
273
|
+
const palette = SLIDE_PALETTES[mask.variant];
|
|
274
|
+
const body = mask.zones.map(zone => previewZone(zone, palette)).join('');
|
|
275
|
+
return `<svg width="100%" height="100%" viewBox="-20 -20 ${SLIDE_WIDTH + 40} ${SLIDE_HEIGHT + 40}" xmlns="http://www.w3.org/2000/svg"><rect x="0" y="0" width="${SLIDE_WIDTH}" height="${SLIDE_HEIGHT}" rx="16" fill="${light(palette.paper)}" stroke="${light(SLIDE_PALETTES.paper.hairline)}" stroke-width="8"/>${body}</svg>`;
|
|
276
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { type Color, FontWeight } from '../../../affine-model/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The slide masks' one system: geometry, typography and the two paper
|
|
4
|
+
* variants. Every mask in `masks.ts` reads these and restates none of them,
|
|
5
|
+
* so a size or a colour changes here, once, for the whole set.
|
|
6
|
+
*/
|
|
7
|
+
/** A 16:9 slide, the frame menu's own `16:9` preset (1600 × 900). */
|
|
8
|
+
export declare const SLIDE_WIDTH = 1600;
|
|
9
|
+
export declare const SLIDE_HEIGHT = 900;
|
|
10
|
+
/** The side margin every mask aligns its content on. */
|
|
11
|
+
export declare const SLIDE_MARGIN = 96;
|
|
12
|
+
/** Where the footer line (footer text, slide number) sits. */
|
|
13
|
+
export declare const SLIDE_FOOTER_Y = 846;
|
|
14
|
+
/**
|
|
15
|
+
* A slide is read from across a room: its type is the document's heading
|
|
16
|
+
* scale (DESIGN.md, The Title-Ratio Rule) times one factor, so the steps
|
|
17
|
+
* between levels stay the editor's own. 1.5 puts the title at 48 model units
|
|
18
|
+
* on a 1600-wide slide, the proportion of the PO's reference deck.
|
|
19
|
+
*/
|
|
20
|
+
export declare const SLIDE_TYPE_FACTOR = 1.5;
|
|
21
|
+
export type SlideTextRole = 'display' | 'title' | 'heading' | 'body' | 'caption' | 'figure';
|
|
22
|
+
export type SlideType = {
|
|
23
|
+
fontSize: number;
|
|
24
|
+
fontWeight: FontWeight;
|
|
25
|
+
};
|
|
26
|
+
export declare const SLIDE_TYPE: Readonly<Record<SlideTextRole, SlideType>>;
|
|
27
|
+
/**
|
|
28
|
+
* What a text box adds to its font size per line. The renderer measures the
|
|
29
|
+
* real line box in the DOM (`getLineHeight`, `gfx/text`); the seeds only need
|
|
30
|
+
* a box tall enough not to overlap the next zone.
|
|
31
|
+
*
|
|
32
|
+
* ponytail: a fixed 1.25 ratio, close to Inter's measured line box. The
|
|
33
|
+
* ceiling is a host font with a taller line box, whose seeds would overlap
|
|
34
|
+
* by a few units until edited; the upgrade is measuring with `wrapText` and
|
|
35
|
+
* `getLineHeight` at placement, which needs a DOM the snapshot build has not.
|
|
36
|
+
*/
|
|
37
|
+
export declare const SLIDE_LINE_HEIGHT = 1.25;
|
|
38
|
+
/**
|
|
39
|
+
* The colours a slide paints with. Only `{ light, dark }` pairs of the base
|
|
40
|
+
* palette or palette values that read on both papers: a mask's elements
|
|
41
|
+
* carry no role and sit on no framework board, so they are painted as stored
|
|
42
|
+
* on a dark canvas (ADR 0039, point 6). A raw hex would leave a white slide
|
|
43
|
+
* on a dark canvas; a pair inverts with the theme.
|
|
44
|
+
*/
|
|
45
|
+
export type SlidePalette = {
|
|
46
|
+
/** The frame's background. */
|
|
47
|
+
paper: Color;
|
|
48
|
+
/** Titles, headings, body text, key figures. */
|
|
49
|
+
ink: Color;
|
|
50
|
+
/** Eyebrows, captions, footer, slide number, axis labels. */
|
|
51
|
+
muted: Color;
|
|
52
|
+
/** Hairlines, card outlines, the fill of a placeholder. */
|
|
53
|
+
hairline: Color;
|
|
54
|
+
/** The dashed outline of a fill zone. */
|
|
55
|
+
zoneStroke: Color;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Two variants, so the set reads as one deck: `paper`, a light slide that
|
|
59
|
+
* turns dark grey on a dark canvas, and `inverse`, the ink slide of a section
|
|
60
|
+
* divider, a statement or a quote, which swaps paper and ink.
|
|
61
|
+
*/
|
|
62
|
+
export declare const SLIDE_PALETTES: {
|
|
63
|
+
readonly paper: {
|
|
64
|
+
readonly paper: Color;
|
|
65
|
+
readonly ink: string | {
|
|
66
|
+
normal: string;
|
|
67
|
+
} | {
|
|
68
|
+
dark: string;
|
|
69
|
+
light: string;
|
|
70
|
+
};
|
|
71
|
+
readonly muted: string | {
|
|
72
|
+
normal: string;
|
|
73
|
+
} | {
|
|
74
|
+
dark: string;
|
|
75
|
+
light: string;
|
|
76
|
+
};
|
|
77
|
+
readonly hairline: {
|
|
78
|
+
dark: string;
|
|
79
|
+
light: string;
|
|
80
|
+
};
|
|
81
|
+
readonly zoneStroke: string | {
|
|
82
|
+
normal: string;
|
|
83
|
+
} | {
|
|
84
|
+
dark: string;
|
|
85
|
+
light: string;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
readonly inverse: {
|
|
89
|
+
readonly paper: string | {
|
|
90
|
+
normal: string;
|
|
91
|
+
} | {
|
|
92
|
+
dark: string;
|
|
93
|
+
light: string;
|
|
94
|
+
};
|
|
95
|
+
readonly ink: string | {
|
|
96
|
+
normal: string;
|
|
97
|
+
} | {
|
|
98
|
+
dark: string;
|
|
99
|
+
light: string;
|
|
100
|
+
};
|
|
101
|
+
readonly muted: string | {
|
|
102
|
+
normal: string;
|
|
103
|
+
} | {
|
|
104
|
+
dark: string;
|
|
105
|
+
light: string;
|
|
106
|
+
};
|
|
107
|
+
readonly hairline: string | {
|
|
108
|
+
normal: string;
|
|
109
|
+
} | {
|
|
110
|
+
dark: string;
|
|
111
|
+
light: string;
|
|
112
|
+
};
|
|
113
|
+
readonly zoneStroke: string | {
|
|
114
|
+
normal: string;
|
|
115
|
+
} | {
|
|
116
|
+
dark: string;
|
|
117
|
+
light: string;
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
export type SlideVariant = keyof typeof SLIDE_PALETTES;
|
|
122
|
+
/** Stroke widths, model units. */
|
|
123
|
+
export declare const SLIDE_HAIRLINE_WIDTH = 2;
|
|
124
|
+
export declare const SLIDE_ZONE_STROKE_WIDTH = 2;
|
|
125
|
+
/** Corner radius of a card or a fill zone. */
|
|
126
|
+
export declare const SLIDE_RADIUS = 12;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { DefaultTheme, FontWeight } from '../../../affine-model/index.js';
|
|
2
|
+
import { HEADING_SCALE } from '../../../affine-shared/consts/index.js';
|
|
3
|
+
import { darkThemeV2, lightThemeV2 } from '@toeverything/theme/v2';
|
|
4
|
+
/**
|
|
5
|
+
* The slide masks' one system: geometry, typography and the two paper
|
|
6
|
+
* variants. Every mask in `masks.ts` reads these and restates none of them,
|
|
7
|
+
* so a size or a colour changes here, once, for the whole set.
|
|
8
|
+
*/
|
|
9
|
+
/** A 16:9 slide, the frame menu's own `16:9` preset (1600 × 900). */
|
|
10
|
+
export const SLIDE_WIDTH = 1600;
|
|
11
|
+
export const SLIDE_HEIGHT = 900;
|
|
12
|
+
/** The side margin every mask aligns its content on. */
|
|
13
|
+
export const SLIDE_MARGIN = 96;
|
|
14
|
+
/** Where the footer line (footer text, slide number) sits. */
|
|
15
|
+
export const SLIDE_FOOTER_Y = 846;
|
|
16
|
+
/**
|
|
17
|
+
* A slide is read from across a room: its type is the document's heading
|
|
18
|
+
* scale (DESIGN.md, The Title-Ratio Rule) times one factor, so the steps
|
|
19
|
+
* between levels stay the editor's own. 1.5 puts the title at 48 model units
|
|
20
|
+
* on a 1600-wide slide, the proportion of the PO's reference deck.
|
|
21
|
+
*/
|
|
22
|
+
export const SLIDE_TYPE_FACTOR = 1.5;
|
|
23
|
+
/**
|
|
24
|
+
* The doc title has no entry in `HEADING_SCALE` (it sits above the scale,
|
|
25
|
+
* DESIGN.md, Hierarchy: 700, 40px); the body is 15px. Both are restated
|
|
26
|
+
* here as the two values the scale does not carry.
|
|
27
|
+
*/
|
|
28
|
+
const DOC_TITLE_SIZE = 40;
|
|
29
|
+
const BODY_SIZE = 15;
|
|
30
|
+
const CAPTION_SIZE = 12;
|
|
31
|
+
const size = (px) => Math.round(px * SLIDE_TYPE_FACTOR);
|
|
32
|
+
const weight = (value) => String(value);
|
|
33
|
+
export const SLIDE_TYPE = {
|
|
34
|
+
/** The cover's and a section's title: the doc title's tier. */
|
|
35
|
+
display: { fontSize: size(DOC_TITLE_SIZE), fontWeight: FontWeight.Bold },
|
|
36
|
+
/** Every slide's own title: H1. */
|
|
37
|
+
title: {
|
|
38
|
+
fontSize: size(HEADING_SCALE.h1.fontSize),
|
|
39
|
+
fontWeight: weight(HEADING_SCALE.h1.fontWeight),
|
|
40
|
+
},
|
|
41
|
+
/** A point's or a column's heading: H3. */
|
|
42
|
+
heading: {
|
|
43
|
+
fontSize: size(HEADING_SCALE.h3.fontSize),
|
|
44
|
+
fontWeight: weight(HEADING_SCALE.h3.fontWeight),
|
|
45
|
+
},
|
|
46
|
+
body: { fontSize: size(BODY_SIZE), fontWeight: FontWeight.Regular },
|
|
47
|
+
/** Footer, slide number, eyebrow, axis and placeholder labels. */
|
|
48
|
+
caption: { fontSize: size(CAPTION_SIZE), fontWeight: FontWeight.Regular },
|
|
49
|
+
/** A key figure: twice the slide title, the one number a slide is about. */
|
|
50
|
+
figure: {
|
|
51
|
+
fontSize: 2 * size(HEADING_SCALE.h1.fontSize),
|
|
52
|
+
fontWeight: FontWeight.Bold,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* What a text box adds to its font size per line. The renderer measures the
|
|
57
|
+
* real line box in the DOM (`getLineHeight`, `gfx/text`); the seeds only need
|
|
58
|
+
* a box tall enough not to overlap the next zone.
|
|
59
|
+
*
|
|
60
|
+
* ponytail: a fixed 1.25 ratio, close to Inter's measured line box. The
|
|
61
|
+
* ceiling is a host font with a taller line box, whose seeds would overlap
|
|
62
|
+
* by a few units until edited; the upgrade is measuring with `wrapText` and
|
|
63
|
+
* `getLineHeight` at placement, which needs a DOM the snapshot build has not.
|
|
64
|
+
*/
|
|
65
|
+
export const SLIDE_LINE_HEIGHT = 1.25;
|
|
66
|
+
const MEDIUM_GREY = DefaultTheme.StrokeColorShortMap['Grey'];
|
|
67
|
+
/**
|
|
68
|
+
* The theme's one grey that has a dark side, the note palette's grey
|
|
69
|
+
* (`#e6e6e6` / `#565656`). `DefaultTheme` maps no grey note, so the pair is
|
|
70
|
+
* read from the same theme tables `getColorByKey` reads.
|
|
71
|
+
*/
|
|
72
|
+
const NOTE_GREY = {
|
|
73
|
+
dark: darkThemeV2['edgeless/note/grey'],
|
|
74
|
+
light: lightThemeV2['edgeless/note/grey'],
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Two variants, so the set reads as one deck: `paper`, a light slide that
|
|
78
|
+
* turns dark grey on a dark canvas, and `inverse`, the ink slide of a section
|
|
79
|
+
* divider, a statement or a quote, which swaps paper and ink.
|
|
80
|
+
*/
|
|
81
|
+
export const SLIDE_PALETTES = {
|
|
82
|
+
paper: {
|
|
83
|
+
paper: DefaultTheme.NoteBackgroundColorMap['White'],
|
|
84
|
+
ink: DefaultTheme.black,
|
|
85
|
+
muted: MEDIUM_GREY,
|
|
86
|
+
hairline: NOTE_GREY,
|
|
87
|
+
zoneStroke: MEDIUM_GREY,
|
|
88
|
+
},
|
|
89
|
+
inverse: {
|
|
90
|
+
paper: DefaultTheme.black,
|
|
91
|
+
ink: DefaultTheme.white,
|
|
92
|
+
muted: MEDIUM_GREY,
|
|
93
|
+
hairline: MEDIUM_GREY,
|
|
94
|
+
zoneStroke: MEDIUM_GREY,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
/** Stroke widths, model units. */
|
|
98
|
+
export const SLIDE_HAIRLINE_WIDTH = 2;
|
|
99
|
+
export const SLIDE_ZONE_STROKE_WIDTH = 2;
|
|
100
|
+
/** Corner radius of a card or a fill zone. */
|
|
101
|
+
export const SLIDE_RADIUS = 12;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TemplateCategory } from '../../toolbar/template-type.js';
|
|
2
|
+
/**
|
|
3
|
+
* The built-in "Slides" category: one 16:9 frame per mask, ready to fill.
|
|
4
|
+
* Built in and ungated like "Other": a frame, shapes, texts and connectors
|
|
5
|
+
* are core, so no flag can take the masks away (ADR 0009 gates a framework's
|
|
6
|
+
* tooling, and a slide belongs to no framework).
|
|
7
|
+
*/
|
|
8
|
+
export declare const slidesTemplateCategory: TemplateCategory;
|