@formicoidea/labre-core 0.58.0 → 0.60.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 +175 -144
- package/architecture/domain.c4 +15 -9
- 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/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/reading-toolbar.js +12 -12
- 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/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-surface/interchange-headless.d.ts +2 -0
- package/dist/_pkgs/affine-block-surface/interchange-headless.js +2 -0
- 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-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-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/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
|
@@ -46,12 +46,14 @@ import { computed, effect, signal } from '@preact/signals-core';
|
|
|
46
46
|
import { html, nothing } from 'lit';
|
|
47
47
|
import { property, query } from 'lit/decorators.js';
|
|
48
48
|
import { classMap } from 'lit/directives/class-map.js';
|
|
49
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
49
50
|
import { ref } from 'lit/directives/ref.js';
|
|
50
51
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
51
52
|
import { colorList } from './color.js';
|
|
52
53
|
import { ColumnMaxWidth, DefaultColumnWidth } from './consts.js';
|
|
54
|
+
import { headerToggleMenuItem } from './header-menu.js';
|
|
53
55
|
import { TableSelectionData, } from './selection-schema.js';
|
|
54
|
-
import { cellContainerStyle, columnLeftIndicatorStyle, columnOptionsCellStyle, columnOptionsStyle, columnRightIndicatorStyle, rowBottomIndicatorStyle, rowOptionsCellStyle, rowOptionsStyle, rowTopIndicatorStyle, threePointerIconDotStyle, threePointerIconStyle, } from './table-cell-css.js';
|
|
56
|
+
import { cellContainerStyle, columnLeftIndicatorStyle, columnOptionsCellStyle, columnOptionsStyle, columnRightIndicatorStyle, headerCellStyle, rowBottomIndicatorStyle, rowOptionsCellStyle, rowOptionsStyle, rowTopIndicatorStyle, threePointerIconDotStyle, threePointerIconStyle, } from './table-cell-css.js';
|
|
55
57
|
export const TableCellComponentName = 'affine-table-cell';
|
|
56
58
|
let TableCell = (() => {
|
|
57
59
|
let _classSuper = SignalWatcher(WithDisposable(ShadowlessElement));
|
|
@@ -196,6 +198,22 @@ let TableCell = (() => {
|
|
|
196
198
|
return this.closest('affine-table')
|
|
197
199
|
?.topContenteditableElement;
|
|
198
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* The header toggle sits in the first row's / first column's menu only: the
|
|
203
|
+
* header is positional (ADR 0043), so no other row could be the one it
|
|
204
|
+
* marks.
|
|
205
|
+
*/
|
|
206
|
+
headerToggle(kind) {
|
|
207
|
+
const std = this.closest('affine-table')?.std;
|
|
208
|
+
const dataManager = this.dataManager;
|
|
209
|
+
return kind === 'row'
|
|
210
|
+
? headerToggleMenuItem(std, kind, dataManager.headerRow$.peek(), on => dataManager.setHeaderRow(on))
|
|
211
|
+
: headerToggleMenuItem(std, kind, dataManager.headerColumn$.peek(), on => dataManager.setHeaderColumn(on));
|
|
212
|
+
}
|
|
213
|
+
get isHeader() {
|
|
214
|
+
return ((this.rowIndex === 0 && this.dataManager.headerRow$.value) ||
|
|
215
|
+
(this.columnIndex === 0 && this.dataManager.headerColumn$.value));
|
|
216
|
+
}
|
|
199
217
|
openColumnOptions(target, column, columnIndex) {
|
|
200
218
|
this.selectionController.setSelected({
|
|
201
219
|
type: 'column',
|
|
@@ -232,6 +250,7 @@ let TableCell = (() => {
|
|
|
232
250
|
})),
|
|
233
251
|
},
|
|
234
252
|
}),
|
|
253
|
+
...(columnIndex === 0 ? [this.headerToggle('column')] : []),
|
|
235
254
|
...(column.backgroundColor
|
|
236
255
|
? [
|
|
237
256
|
menu.action({
|
|
@@ -345,6 +364,7 @@ let TableCell = (() => {
|
|
|
345
364
|
})),
|
|
346
365
|
},
|
|
347
366
|
}),
|
|
367
|
+
...(rowIndex === 0 ? [this.headerToggle('row')] : []),
|
|
348
368
|
...(row.backgroundColor
|
|
349
369
|
? [
|
|
350
370
|
menu.action({
|
|
@@ -706,9 +726,20 @@ let TableCell = (() => {
|
|
|
706
726
|
})
|
|
707
727
|
.catch(console.error);
|
|
708
728
|
}
|
|
729
|
+
tdClass() {
|
|
730
|
+
return classMap({
|
|
731
|
+
[cellContainerStyle]: true,
|
|
732
|
+
[headerCellStyle]: this.isHeader,
|
|
733
|
+
});
|
|
734
|
+
}
|
|
709
735
|
render() {
|
|
736
|
+
const header = this.isHeader ? '' : undefined;
|
|
710
737
|
if (!this.text) {
|
|
711
|
-
return html `<td
|
|
738
|
+
return html `<td
|
|
739
|
+
class=${this.tdClass()}
|
|
740
|
+
data-header=${ifDefined(header)}
|
|
741
|
+
style=${this.tdStyle()}
|
|
742
|
+
>
|
|
712
743
|
<div
|
|
713
744
|
style=${styleMap({
|
|
714
745
|
padding: '8px 12px',
|
|
@@ -729,7 +760,8 @@ let TableCell = (() => {
|
|
|
729
760
|
this.tdMouseLeave();
|
|
730
761
|
}}
|
|
731
762
|
@contextmenu=${this.onContextMenu}
|
|
732
|
-
class=${
|
|
763
|
+
class=${this.tdClass()}
|
|
764
|
+
data-header=${ifDefined(header)}
|
|
733
765
|
style=${this.tdStyle()}
|
|
734
766
|
>
|
|
735
767
|
<rich-text
|
|
@@ -20,6 +20,9 @@ export declare class TableDataManager {
|
|
|
20
20
|
width: number;
|
|
21
21
|
} | undefined>;
|
|
22
22
|
readonly cellCountTips$: ReadonlySignal<string>;
|
|
23
|
+
/** ADR 0043: anything but a stored `true` reads as off. */
|
|
24
|
+
readonly headerRow$: ReadonlySignal<boolean>;
|
|
25
|
+
readonly headerColumn$: ReadonlySignal<boolean>;
|
|
23
26
|
readonly rows$: ReadonlySignal<import("../affine-model/index.js").TableRow[]>;
|
|
24
27
|
readonly columns$: ReadonlySignal<import("../affine-model/index.js").TableColumn[]>;
|
|
25
28
|
readonly uiRows$: ReadonlySignal<(import("../affine-model/index.js").TableRow | {
|
|
@@ -43,7 +46,18 @@ export declare class TableDataManager {
|
|
|
43
46
|
updateColumnOrder(columnId: string, newOrder: string): void;
|
|
44
47
|
setRowBackgroundColor(rowId: string, color?: string): void;
|
|
45
48
|
setColumnBackgroundColor(columnId: string, color?: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* One call per gesture (a resize drag writes once, on release; a fit writes
|
|
51
|
+
* once), so the `captureSync` here makes each gesture its own undo step.
|
|
52
|
+
*/
|
|
46
53
|
setColumnWidth(columnId: string, width: number): void;
|
|
54
|
+
setHeaderRow(on: boolean): void;
|
|
55
|
+
setHeaderColumn(on: boolean): void;
|
|
56
|
+
/**
|
|
57
|
+
* `true` or absent, never `false` (ADR 0043): turning a header off deletes
|
|
58
|
+
* the key, so an off table stores exactly what a pre-0043 table stored.
|
|
59
|
+
*/
|
|
60
|
+
private setHeader;
|
|
47
61
|
clearRow(rowId: string): void;
|
|
48
62
|
clearColumn(columnId: string): void;
|
|
49
63
|
clearCellsBySelection(selection: TableAreaSelection): void;
|
|
@@ -19,6 +19,9 @@ export class TableDataManager {
|
|
|
19
19
|
this.virtualRowCount$ = signal(0);
|
|
20
20
|
this.virtualWidth$ = signal();
|
|
21
21
|
this.cellCountTips$ = computed(() => `${this.virtualRowCount$.value + this.rows$.value.length} x ${this.virtualColumnCount$.value + this.columns$.value.length}`);
|
|
22
|
+
/** ADR 0043: anything but a stored `true` reads as off. */
|
|
23
|
+
this.headerRow$ = computed(() => this.model.props.headerRow$.value === true);
|
|
24
|
+
this.headerColumn$ = computed(() => this.model.props.headerColumn$.value === true);
|
|
22
25
|
this.rows$ = computed(() => {
|
|
23
26
|
return Object.values(this.model.props.rows$.value).sort((a, b) => a.order > b.order ? 1 : -1);
|
|
24
27
|
});
|
|
@@ -201,10 +204,48 @@ export class TableDataManager {
|
|
|
201
204
|
}
|
|
202
205
|
});
|
|
203
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* One call per gesture (a resize drag writes once, on release; a fit writes
|
|
209
|
+
* once), so the `captureSync` here makes each gesture its own undo step.
|
|
210
|
+
*/
|
|
204
211
|
setColumnWidth(columnId, width) {
|
|
205
|
-
this.model.store
|
|
206
|
-
|
|
207
|
-
|
|
212
|
+
const store = this.model.store;
|
|
213
|
+
if (store.readonly)
|
|
214
|
+
return;
|
|
215
|
+
const column = this.model.props.columns[columnId];
|
|
216
|
+
if (!column || column.width === width)
|
|
217
|
+
return;
|
|
218
|
+
store.captureSync();
|
|
219
|
+
store.transact(() => {
|
|
220
|
+
const target = this.model.props.columns[columnId];
|
|
221
|
+
if (target) {
|
|
222
|
+
target.width = width;
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
setHeaderRow(on) {
|
|
227
|
+
this.setHeader('headerRow', on);
|
|
228
|
+
}
|
|
229
|
+
setHeaderColumn(on) {
|
|
230
|
+
this.setHeader('headerColumn', on);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* `true` or absent, never `false` (ADR 0043): turning a header off deletes
|
|
234
|
+
* the key, so an off table stores exactly what a pre-0043 table stored.
|
|
235
|
+
*/
|
|
236
|
+
setHeader(key, on) {
|
|
237
|
+
const store = this.model.store;
|
|
238
|
+
if (store.readonly)
|
|
239
|
+
return;
|
|
240
|
+
if ((this.model.props[key] === true) === on)
|
|
241
|
+
return;
|
|
242
|
+
store.captureSync();
|
|
243
|
+
store.transact(() => {
|
|
244
|
+
if (on) {
|
|
245
|
+
this.model.props[key] = true;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
delete this.model.props[key];
|
|
208
249
|
}
|
|
209
250
|
});
|
|
210
251
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ChromeWording } from '../affine-shared/services/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* This package's own wordings, declared beside the code that renders them —
|
|
4
|
+
* the two header toggles of the row and column menus (ADR 0043). The menus'
|
|
5
|
+
* older labels ("Insert Left", "Delete"…) are still literals held by
|
|
6
|
+
* `literals.baseline.json`; they move here in their own pass.
|
|
7
|
+
*/
|
|
8
|
+
export declare const TABLE_HEADER_ROW: ChromeWording;
|
|
9
|
+
export declare const TABLE_HEADER_COLUMN: ChromeWording;
|
|
10
|
+
/**
|
|
11
|
+
* Every wording declared above, in declaration order — walked by
|
|
12
|
+
* `PACKAGE_WORDINGS` in `packages/affine/all/src/translations.ts`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const TABLE_WORDINGS: readonly ChromeWording[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This package's own wordings, declared beside the code that renders them —
|
|
3
|
+
* the two header toggles of the row and column menus (ADR 0043). The menus'
|
|
4
|
+
* older labels ("Insert Left", "Delete"…) are still literals held by
|
|
5
|
+
* `literals.baseline.json`; they move here in their own pass.
|
|
6
|
+
*/
|
|
7
|
+
export const TABLE_HEADER_ROW = [
|
|
8
|
+
'com.labre.table.header-row',
|
|
9
|
+
'Header row',
|
|
10
|
+
];
|
|
11
|
+
export const TABLE_HEADER_COLUMN = [
|
|
12
|
+
'com.labre.table.header-column',
|
|
13
|
+
'Header column',
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Every wording declared above, in declaration order — walked by
|
|
17
|
+
* `PACKAGE_WORDINGS` in `packages/affine/all/src/translations.ts`.
|
|
18
|
+
*/
|
|
19
|
+
export const TABLE_WORDINGS = [
|
|
20
|
+
TABLE_HEADER_ROW,
|
|
21
|
+
TABLE_HEADER_COLUMN,
|
|
22
|
+
];
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { HighLightDuotoneIcon } from '@blocksuite/icons/lit';
|
|
2
2
|
import { css, LitElement } from 'lit';
|
|
3
3
|
export class HighlightDuotoneIcon extends LitElement {
|
|
4
|
-
static { this.styles = css `
|
|
5
|
-
svg {
|
|
6
|
-
display: flex;
|
|
7
|
-
font-size: 20px;
|
|
8
|
-
}
|
|
9
|
-
svg > path:nth-child(1) {
|
|
10
|
-
fill: var(--color, unset);
|
|
11
|
-
}
|
|
4
|
+
static { this.styles = css `
|
|
5
|
+
svg {
|
|
6
|
+
display: flex;
|
|
7
|
+
font-size: 20px;
|
|
8
|
+
}
|
|
9
|
+
svg > path:nth-child(1) {
|
|
10
|
+
fill: var(--color, unset);
|
|
11
|
+
}
|
|
12
12
|
`; }
|
|
13
13
|
render() {
|
|
14
14
|
return HighLightDuotoneIcon();
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { TextBackgroundDuotoneIcon } from '@blocksuite/icons/lit';
|
|
2
2
|
import { css, LitElement } from 'lit';
|
|
3
3
|
export class TextDuotoneIcon extends LitElement {
|
|
4
|
-
static { this.styles = css `
|
|
5
|
-
svg {
|
|
6
|
-
display: flex;
|
|
7
|
-
font-size: 20px;
|
|
8
|
-
}
|
|
9
|
-
svg > path:nth-child(1) {
|
|
10
|
-
fill: var(--background, unset);
|
|
11
|
-
}
|
|
12
|
-
svg > path:nth-child(3) {
|
|
13
|
-
fill: var(--color, unset);
|
|
14
|
-
}
|
|
4
|
+
static { this.styles = css `
|
|
5
|
+
svg {
|
|
6
|
+
display: flex;
|
|
7
|
+
font-size: 20px;
|
|
8
|
+
}
|
|
9
|
+
svg > path:nth-child(1) {
|
|
10
|
+
fill: var(--background, unset);
|
|
11
|
+
}
|
|
12
|
+
svg > path:nth-child(3) {
|
|
13
|
+
fill: var(--color, unset);
|
|
14
|
+
}
|
|
15
15
|
`; }
|
|
16
16
|
render() {
|
|
17
17
|
return TextBackgroundDuotoneIcon();
|
|
@@ -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
|
+
}
|