@formicoidea/labre-core 0.39.1 → 0.40.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 (37) hide show
  1. package/dist/_pkgs/affine-block-callout/emoji-margin.js +19 -11
  2. package/dist/_pkgs/affine-block-list/list-block.d.ts +8 -1
  3. package/dist/_pkgs/affine-block-list/list-block.js +27 -17
  4. package/dist/_pkgs/affine-block-note/configs/tooltips.d.ts +16 -0
  5. package/dist/_pkgs/affine-block-note/configs/tooltips.js +99 -66
  6. package/dist/_pkgs/affine-block-paragraph/paragraph-block.d.ts +8 -1
  7. package/dist/_pkgs/affine-block-paragraph/paragraph-block.js +30 -15
  8. package/dist/_pkgs/affine-block-paragraph/styles.js +30 -83
  9. package/dist/_pkgs/affine-block-paragraph/turbo/paragraph-layout-handler.js +1 -0
  10. package/dist/_pkgs/affine-block-paragraph/turbo/paragraph-painter.worker.d.ts +2 -0
  11. package/dist/_pkgs/affine-block-paragraph/turbo/paragraph-painter.worker.js +6 -1
  12. package/dist/_pkgs/affine-block-root/edgeless/clipboard/clipboard.js +3 -3
  13. package/dist/_pkgs/affine-block-root/keyboard/keymap.js +20 -0
  14. package/dist/_pkgs/affine-block-surface/extensions/export-manager/export-manager.d.ts +6 -4
  15. package/dist/_pkgs/affine-block-surface/extensions/export-manager/export-manager.js +15 -10
  16. package/dist/_pkgs/affine-block-surface/framework-background/def.d.ts +4 -1
  17. package/dist/_pkgs/affine-block-surface/framework-background/def.js +6 -2
  18. package/dist/_pkgs/affine-block-surface/utils/priority-queue.js +2 -2
  19. package/dist/_pkgs/affine-components/toggle-button/toggle-button.d.ts +5 -0
  20. package/dist/_pkgs/affine-components/toggle-button/toggle-button.js +31 -18
  21. package/dist/_pkgs/affine-gfx-template/builtin/other.js +31 -14
  22. package/dist/_pkgs/affine-inline-preset/markdown.d.ts +3 -0
  23. package/dist/_pkgs/affine-inline-preset/markdown.js +19 -0
  24. package/dist/_pkgs/affine-shared/adapters/middlewares/proxy.d.ts +10 -0
  25. package/dist/_pkgs/affine-shared/adapters/middlewares/proxy.js +19 -12
  26. package/dist/_pkgs/affine-shared/adapters/utils/fetch.js +4 -0
  27. package/dist/_pkgs/affine-shared/consts/heading.d.ts +29 -0
  28. package/dist/_pkgs/affine-shared/consts/heading.js +70 -0
  29. package/dist/_pkgs/affine-shared/consts/index.d.ts +2 -0
  30. package/dist/_pkgs/affine-shared/consts/index.js +2 -0
  31. package/dist/_pkgs/affine-shared/consts/notation.d.ts +67 -0
  32. package/dist/_pkgs/affine-shared/consts/notation.js +65 -0
  33. package/dist/_pkgs/std/gfx/model/surface/element-model.d.ts +2 -2
  34. package/dist/_pkgs/std/gfx/model/surface/element-model.js +2 -2
  35. package/dist/_pkgs/std/gfx/model/surface/surface-model.d.ts +1 -1
  36. package/dist/_pkgs/std/gfx/model/surface/surface-model.js +1 -1
  37. package/package.json +1 -1
@@ -5,18 +5,25 @@ export const customImageProxyMiddleware = (imageProxyURL) => {
5
5
  adapterConfigs.set('imageProxy', imageProxyURL);
6
6
  };
7
7
  };
8
- const imageProxyMiddlewareBuilder = () => {
9
- let middleware = customImageProxyMiddleware(DEFAULT_IMAGE_PROXY_ENDPOINT);
10
- return {
11
- get: () => middleware,
12
- set: (url) => {
13
- middleware = customImageProxyMiddleware(url);
14
- },
15
- };
8
+ // Module-wide so that transformer jobs built outside a store (playground
9
+ // panels, host-side importers) follow `setImageProxyURL` too.
10
+ let imageProxyMiddlewareURL = DEFAULT_IMAGE_PROXY_ENDPOINT;
11
+ export const setImageProxyMiddlewareURL = (url) => {
12
+ imageProxyMiddlewareURL = url;
13
+ };
14
+ /**
15
+ * Reads the URL at run time: a `setImageProxyURL` made after module load
16
+ * reaches every job using this middleware.
17
+ */
18
+ export const defaultImageProxyMiddleware = ({ adapterConfigs, }) => {
19
+ adapterConfigs.set('imageProxy', imageProxyMiddlewareURL);
16
20
  };
17
- const defaultImageProxyMiddlewarBuilder = imageProxyMiddlewareBuilder();
18
- export const setImageProxyMiddlewareURL = defaultImageProxyMiddlewarBuilder.set;
19
- export const defaultImageProxyMiddleware = defaultImageProxyMiddlewarBuilder.get();
21
+ /**
22
+ * The ONE seam governing every remote-image fetch the library performs on the
23
+ * host's behalf: link-card favicons and og:images, image import, canvas
24
+ * PNG/PDF export, copy-as-image. An empty URL means « fetch direct ».
25
+ * See `docs/integrate/04-host-seams.md`.
26
+ */
20
27
  // TODO(@mirone): this should be configured when setup instead of runtime
21
28
  export class ImageProxyService extends StoreExtension {
22
29
  constructor() {
@@ -29,7 +36,7 @@ export class ImageProxyService extends StoreExtension {
29
36
  setImageProxyMiddlewareURL(url);
30
37
  }
31
38
  buildUrl(imageUrl) {
32
- if (imageUrl.startsWith(this.imageProxyURL)) {
39
+ if (!this.imageProxyURL || imageUrl.startsWith(this.imageProxyURL)) {
33
40
  return imageUrl;
34
41
  }
35
42
  return `${this.imageProxyURL}?url=${encodeURIComponent(imageUrl)}`;
@@ -12,6 +12,10 @@ const fetchImage = async (url, init, proxy) => {
12
12
  if (url.startsWith(window.location.origin)) {
13
13
  return await fetch(url, init);
14
14
  }
15
+ // Already proxied (a link card renders `buildUrl(...)`): do not wrap twice.
16
+ if (url.startsWith(proxy)) {
17
+ return await fetch(url, init);
18
+ }
15
19
  return await fetch(proxy + '?url=' + encodeURIComponent(url), init)
16
20
  .then(res => {
17
21
  if (!res.ok) {
@@ -0,0 +1,29 @@
1
+ export type HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
2
+ export interface HeadingMetrics {
3
+ /** Font size, px. */
4
+ readonly fontSize: number;
5
+ readonly fontWeight: number;
6
+ /** Letter spacing, em. */
7
+ readonly letterSpacing: number;
8
+ /** What the line box adds to the font size, px: `line-height: calc(1em + Npx)`. */
9
+ readonly lineHeightExtra: number;
10
+ /** Space above the heading, px. */
11
+ readonly marginTop: number;
12
+ }
13
+ export declare const HEADING_LEVELS: readonly HeadingLevel[];
14
+ /**
15
+ * Labre's document heading scale — the single source of truth for H1…H6.
16
+ *
17
+ * The sizes step down by a ratio of about 1.25 from the doc title (40px/700)
18
+ * to H3, so each level reads as clearly smaller than the one above and H1
19
+ * never competes with the title. Below H3 the steps tighten: H4–H6 only need
20
+ * to stay above body text. The paragraph styles, the callout emoji and the
21
+ * slash-menu previews derive from this table rather than from the upstream
22
+ * `--affine-font-h-N` theme variables, which no longer drive document headings.
23
+ * The hover affordances (drag-handle grabber, heading-level icon) keep their
24
+ * upstream tuning on purpose: the PO prefers them aligned with each other as
25
+ * they were (recette 11/09/2026), not re-centred on the text line.
26
+ */
27
+ export declare const HEADING_SCALE: Readonly<Record<HeadingLevel, HeadingMetrics>>;
28
+ /** Height of a heading's (single) line box, px: font size + line-height extra. */
29
+ export declare function headingLineBox(level: HeadingLevel): number;
@@ -0,0 +1,70 @@
1
+ export const HEADING_LEVELS = [
2
+ 'h1',
3
+ 'h2',
4
+ 'h3',
5
+ 'h4',
6
+ 'h5',
7
+ 'h6',
8
+ ];
9
+ /**
10
+ * Labre's document heading scale — the single source of truth for H1…H6.
11
+ *
12
+ * The sizes step down by a ratio of about 1.25 from the doc title (40px/700)
13
+ * to H3, so each level reads as clearly smaller than the one above and H1
14
+ * never competes with the title. Below H3 the steps tighten: H4–H6 only need
15
+ * to stay above body text. The paragraph styles, the callout emoji and the
16
+ * slash-menu previews derive from this table rather than from the upstream
17
+ * `--affine-font-h-N` theme variables, which no longer drive document headings.
18
+ * The hover affordances (drag-handle grabber, heading-level icon) keep their
19
+ * upstream tuning on purpose: the PO prefers them aligned with each other as
20
+ * they were (recette 11/09/2026), not re-centred on the text line.
21
+ */
22
+ export const HEADING_SCALE = {
23
+ h1: {
24
+ fontSize: 32,
25
+ fontWeight: 700,
26
+ letterSpacing: -0.02,
27
+ lineHeightExtra: 8,
28
+ marginTop: 18,
29
+ },
30
+ h2: {
31
+ fontSize: 26,
32
+ fontWeight: 600,
33
+ letterSpacing: -0.02,
34
+ lineHeightExtra: 10,
35
+ marginTop: 14,
36
+ },
37
+ h3: {
38
+ fontSize: 20,
39
+ fontWeight: 600,
40
+ letterSpacing: -0.02,
41
+ lineHeightExtra: 8,
42
+ marginTop: 12,
43
+ },
44
+ h4: {
45
+ fontSize: 18,
46
+ fontWeight: 600,
47
+ letterSpacing: -0.015,
48
+ lineHeightExtra: 8,
49
+ marginTop: 12,
50
+ },
51
+ h5: {
52
+ fontSize: 16,
53
+ fontWeight: 600,
54
+ letterSpacing: -0.015,
55
+ lineHeightExtra: 8,
56
+ marginTop: 12,
57
+ },
58
+ h6: {
59
+ fontSize: 15,
60
+ fontWeight: 600,
61
+ letterSpacing: -0.015,
62
+ lineHeightExtra: 8,
63
+ marginTop: 12,
64
+ },
65
+ };
66
+ /** Height of a heading's (single) line box, px: font size + line-height extra. */
67
+ export function headingLineBox(level) {
68
+ const { fontSize, lineHeightExtra } = HEADING_SCALE[level];
69
+ return fontSize + lineHeightExtra;
70
+ }
@@ -22,5 +22,7 @@ export declare const DEFAULT_IMAGE_PROXY_ENDPOINT = "https://affine-worker.toeve
22
22
  export declare const DEFAULT_LINK_PREVIEW_ENDPOINT = "https://affine-worker.toeverything.workers.dev/api/worker/link-preview";
23
23
  export declare const CANVAS_EXPORT_IGNORE_TAGS: string[];
24
24
  export * from './bracket-pairs.js';
25
+ export * from './heading.js';
26
+ export * from './notation.js';
25
27
  export * from './note.js';
26
28
  export * from './text.js';
@@ -73,5 +73,7 @@ export const CANVAS_EXPORT_IGNORE_TAGS = [
73
73
  'AFFINE-BLOCK-SELECTION',
74
74
  ];
75
75
  export * from './bracket-pairs.js';
76
+ export * from './heading.js';
77
+ export * from './notation.js';
76
78
  export * from './note.js';
77
79
  export * from './text.js';
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The neutral scale every framework notation on the canvas shares: inks,
3
+ * greys, borders and the card fill.
4
+ *
5
+ * **Wardley is the reference.** The values are the Wardley map's own (its
6
+ * background `COLORS`, its node stroke and fill, its legend frame), so a
7
+ * Wardley board is unchanged by this module existing; every other framework
8
+ * (BPMN, C4, EDGY, the DDD notations, the generic templates) reads its neutrals
9
+ * from here instead of restating a near-identical grey of its own. One scale,
10
+ * one place to change it.
11
+ *
12
+ * **Hues stay per framework.** An event ring, a C4 container blue, a sticky
13
+ * colour or an evolution red is the notation's meaning and lives in that
14
+ * framework's `consts.ts`. So do the neutrals a notation borrows from an
15
+ * official source (the C4 stencil's `#444444`, the Cynefin and Estuarine SVGs,
16
+ * the EDGY facet picto) and the greys that carry a meaning (a future bounded
17
+ * context, a Core Domain zone): those are content of the notation, not chrome.
18
+ *
19
+ * **No band tint.** The title or header strip of a board (BPMN participant
20
+ * band, C4 board header, a generic template's column) is plain `cardFill`
21
+ * white, set apart by its divider line (PO, 11/09/2026). The Wardley phase
22
+ * bands are not chrome: a graded wash across four zones is the map's meaning,
23
+ * so they stay Wardley's own.
24
+ *
25
+ * **Stored colours are never rewritten.** A creation default is copied into
26
+ * the element when it is placed, so changing a value here repaints only the
27
+ * render-time chrome of existing boards (backgrounds, cards, frames) and the
28
+ * elements created from now on. Any code that recognises an element by its
29
+ * stored colour must keep accepting the value it was created with.
30
+ */
31
+ declare const SCALE: {
32
+ /**
33
+ * Artefact ink: node strokes, text inside or under an artefact, labels,
34
+ * legend text, the default connector stroke (Wardley `NODE_STROKE`).
35
+ */
36
+ ink: string;
37
+ /**
38
+ * Background structure: axes, frame lines, board titles, pool frames and
39
+ * names, axis titles (Wardley `COLORS.axis`).
40
+ */
41
+ frameInk: string;
42
+ /**
43
+ * Secondary labels drawn on a background: headings, tick labels (Wardley
44
+ * `COLORS.label`).
45
+ */
46
+ label: string;
47
+ /**
48
+ * Dashed dividers, group strokes, secondary strokes (Wardley
49
+ * `COLORS.divider`).
50
+ */
51
+ divider: string;
52
+ /** Board, card and node fill (Wardley `COLORS.card` / `NODE_FILL`). */
53
+ cardFill: string;
54
+ /** The board card's border (Wardley `COLORS.cardBorder`). */
55
+ cardBorder: string;
56
+ /** A legend's frame and separators (the Wardley legend). */
57
+ legendBorder: string;
58
+ };
59
+ /**
60
+ * Typed as plain strings on purpose, not `as const`: a framework constant set
61
+ * from the scale (`NODE_STROKE = NOTATION_NEUTRALS.ink`) must stay a `string`,
62
+ * as the hex literal it replaces was, so it can still be passed wherever any
63
+ * colour is (a helper whose parameter type is inferred from a default).
64
+ */
65
+ export declare const NOTATION_NEUTRALS: Readonly<typeof SCALE>;
66
+ export type NotationNeutral = keyof typeof NOTATION_NEUTRALS;
67
+ export {};
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The neutral scale every framework notation on the canvas shares: inks,
3
+ * greys, borders and the card fill.
4
+ *
5
+ * **Wardley is the reference.** The values are the Wardley map's own (its
6
+ * background `COLORS`, its node stroke and fill, its legend frame), so a
7
+ * Wardley board is unchanged by this module existing; every other framework
8
+ * (BPMN, C4, EDGY, the DDD notations, the generic templates) reads its neutrals
9
+ * from here instead of restating a near-identical grey of its own. One scale,
10
+ * one place to change it.
11
+ *
12
+ * **Hues stay per framework.** An event ring, a C4 container blue, a sticky
13
+ * colour or an evolution red is the notation's meaning and lives in that
14
+ * framework's `consts.ts`. So do the neutrals a notation borrows from an
15
+ * official source (the C4 stencil's `#444444`, the Cynefin and Estuarine SVGs,
16
+ * the EDGY facet picto) and the greys that carry a meaning (a future bounded
17
+ * context, a Core Domain zone): those are content of the notation, not chrome.
18
+ *
19
+ * **No band tint.** The title or header strip of a board (BPMN participant
20
+ * band, C4 board header, a generic template's column) is plain `cardFill`
21
+ * white, set apart by its divider line (PO, 11/09/2026). The Wardley phase
22
+ * bands are not chrome: a graded wash across four zones is the map's meaning,
23
+ * so they stay Wardley's own.
24
+ *
25
+ * **Stored colours are never rewritten.** A creation default is copied into
26
+ * the element when it is placed, so changing a value here repaints only the
27
+ * render-time chrome of existing boards (backgrounds, cards, frames) and the
28
+ * elements created from now on. Any code that recognises an element by its
29
+ * stored colour must keep accepting the value it was created with.
30
+ */
31
+ const SCALE = {
32
+ /**
33
+ * Artefact ink: node strokes, text inside or under an artefact, labels,
34
+ * legend text, the default connector stroke (Wardley `NODE_STROKE`).
35
+ */
36
+ ink: '#1f2328',
37
+ /**
38
+ * Background structure: axes, frame lines, board titles, pool frames and
39
+ * names, axis titles (Wardley `COLORS.axis`).
40
+ */
41
+ frameInk: '#3b3d42',
42
+ /**
43
+ * Secondary labels drawn on a background: headings, tick labels (Wardley
44
+ * `COLORS.label`).
45
+ */
46
+ label: '#6b7280',
47
+ /**
48
+ * Dashed dividers, group strokes, secondary strokes (Wardley
49
+ * `COLORS.divider`).
50
+ */
51
+ divider: '#9aa0a6',
52
+ /** Board, card and node fill (Wardley `COLORS.card` / `NODE_FILL`). */
53
+ cardFill: '#ffffff',
54
+ /** The board card's border (Wardley `COLORS.cardBorder`). */
55
+ cardBorder: '#e3e2e4',
56
+ /** A legend's frame and separators (the Wardley legend). */
57
+ legendBorder: '#cfd2d6',
58
+ };
59
+ /**
60
+ * Typed as plain strings on purpose, not `as const`: a framework constant set
61
+ * from the scale (`NODE_STROKE = NOTATION_NEUTRALS.ink`) must stay a `string`,
62
+ * as the hex literal it replaces was, so it can still be passed wherever any
63
+ * colour is (a helper whose parameter type is inferred from a default).
64
+ */
65
+ export const NOTATION_NEUTRALS = Object.freeze(SCALE);
@@ -227,7 +227,7 @@ export declare abstract class GfxPrimitiveElementModel<Props extends BaseElement
227
227
  * This is a direct write path into the element's Y.Map, on the class that
228
228
  * carries the document format, exported by `@labre/std` and therefore
229
229
  * callable by a host. `_assignElementProp` learned the same lesson in the
230
- * unknown-props change (see `docs/spikes/us-1-8-unknown-props-preservation.md`,
230
+ * unknown-props change (see the unknown-props spike (PR #73),
231
231
  * whose deny-list is explicitly security rather than hygiene); an unguarded
232
232
  * delete re-opens the door from the other side. So:
233
233
  *
@@ -467,7 +467,7 @@ export declare abstract class GfxPrimitiveElementModel<Props extends BaseElement
467
467
  * An element re-created from props (paste, duplicate, alt-drag clone,
468
468
  * template insertion) only reaches the Y.Map through keys that have a
469
469
  * declared accessor, so a payload declared per subclass would be silently
470
- * dropped on copy — the exact loss `docs/spikes/us-1-8-unknown-props-preservation.md`
470
+ * dropped on copy — the exact loss the unknown-props spike (PR #73)
471
471
  * exists to prevent. Declaring it, rather than leaning on that spike's
472
472
  * verbatim fallback for undeclared keys, is what makes it a contract: a field
473
473
  * nothing declares is a field nothing can test, strip or find.
@@ -407,7 +407,7 @@ let GfxPrimitiveElementModel = (() => {
407
407
  * This is a direct write path into the element's Y.Map, on the class that
408
408
  * carries the document format, exported by `@labre/std` and therefore
409
409
  * callable by a host. `_assignElementProp` learned the same lesson in the
410
- * unknown-props change (see `docs/spikes/us-1-8-unknown-props-preservation.md`,
410
+ * unknown-props change (see the unknown-props spike (PR #73),
411
411
  * whose deny-list is explicitly security rather than hygiene); an unguarded
412
412
  * delete re-opens the door from the other side. So:
413
413
  *
@@ -692,7 +692,7 @@ let GfxPrimitiveElementModel = (() => {
692
692
  * An element re-created from props (paste, duplicate, alt-drag clone,
693
693
  * template insertion) only reaches the Y.Map through keys that have a
694
694
  * declared accessor, so a payload declared per subclass would be silently
695
- * dropped on copy — the exact loss `docs/spikes/us-1-8-unknown-props-preservation.md`
695
+ * dropped on copy — the exact loss the unknown-props spike (PR #73)
696
696
  * exists to prevent. Declaring it, rather than leaning on that spike's
697
697
  * verbatim fallback for undeclared keys, is what makes it a contract: a field
698
698
  * nothing declares is a field nothing can test, strip or find.
@@ -134,7 +134,7 @@ export declare class SurfaceBlockModel extends BlockModel<SurfaceBlockProps> {
134
134
  * The value is already Y-converted at this point: both call sites run the
135
135
  * whole props object through {@link _propsToY} first, which is key-agnostic.
136
136
  *
137
- * See `docs/spikes/us-1-8-unknown-props-preservation.md`.
137
+ * See the unknown-props spike (PR #73).
138
138
  */
139
139
  private _assignElementProp;
140
140
  private _createElementFromYMap;
@@ -294,7 +294,7 @@ export class SurfaceBlockModel extends BlockModel {
294
294
  * The value is already Y-converted at this point: both call sites run the
295
295
  * whole props object through {@link _propsToY} first, which is key-agnostic.
296
296
  *
297
- * See `docs/spikes/us-1-8-unknown-props-preservation.md`.
297
+ * See the unknown-props spike (PR #73).
298
298
  */
299
299
  _assignElementProp(element, key, value) {
300
300
  if (UNSAFE_ELEMENT_PROP_KEYS.has(key)) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@formicoidea/labre-core",
3
3
  "description": "Labre editor — the full BlockSuite-derived editor as one package.",
4
- "version": "0.39.1",
4
+ "version": "0.40.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "author": "lajola",