@neta-art/cohub 12.1.0 → 12.2.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 (85) hide show
  1. package/README.md +8 -5
  2. package/dist/board/editor/editor.d.ts +1 -0
  3. package/dist/board/editor/editor.js +4 -0
  4. package/dist/board/editor/snapshots.js +5 -57
  5. package/dist/board/export/index.d.ts +2 -2
  6. package/dist/board/export/node/fonts.js +4 -0
  7. package/dist/board/export/node/index.d.ts +3 -0
  8. package/dist/board/export/node/index.js +13 -1
  9. package/dist/board/export/scene.d.ts +2 -2
  10. package/dist/board/export/scene.js +2 -2
  11. package/dist/board/model/asset-key.d.ts +16 -0
  12. package/dist/board/model/asset-key.js +92 -0
  13. package/dist/board/model/export-assets.d.ts +7 -3
  14. package/dist/board/model/export-assets.js +34 -13
  15. package/dist/board/model/index.d.ts +7 -5
  16. package/dist/board/model/index.js +9 -7
  17. package/dist/board/model/items/create.js +1 -1
  18. package/dist/board/model/media-sizes.d.ts +28 -0
  19. package/dist/board/model/media-sizes.js +64 -0
  20. package/dist/board/model/palette.d.ts +1 -0
  21. package/dist/board/model/palette.js +20 -130
  22. package/dist/board/model/text-metrics.d.ts +8 -3
  23. package/dist/board/model/text-metrics.js +13 -2
  24. package/dist/board/model/themes.d.ts +488 -0
  25. package/dist/board/model/themes.js +495 -0
  26. package/dist/board/render/card-tag.js +2 -2
  27. package/dist/board/render/index.d.ts +6 -4
  28. package/dist/board/render/index.js +5 -3
  29. package/dist/board/render/lod.d.ts +22 -0
  30. package/dist/board/render/lod.js +27 -0
  31. package/dist/board/render/media-interaction.js +1 -1
  32. package/dist/board/render/palette.js +2 -25
  33. package/dist/board/render/renderers/audio-card-renderer.js +2 -1
  34. package/dist/board/render/renderers/board-renderer-registry.d.ts +10 -0
  35. package/dist/board/render/renderers/custom-card-renderer.js +5 -5
  36. package/dist/board/render/renderers/far-plate.d.ts +11 -1
  37. package/dist/board/render/renderers/far-plate.js +27 -8
  38. package/dist/board/render/renderers/file-card-renderer.js +3 -5
  39. package/dist/board/render/renderers/image-card-renderer.js +32 -6
  40. package/dist/board/render/renderers/model-card-renderer.js +1 -1
  41. package/dist/board/render/renderers/shape-card-renderer.js +25 -24
  42. package/dist/board/render/renderers/task-card-renderer.js +7 -8
  43. package/dist/board/render/renderers/text-card-renderer.js +86 -41
  44. package/dist/board/render/renderers/video-card-renderer.js +2 -1
  45. package/dist/board/render/style.d.ts +7 -2
  46. package/dist/board/render/style.js +5 -1
  47. package/dist/board/render/surface.d.ts +5 -0
  48. package/dist/board/render/surface.js +13 -3
  49. package/dist/board/render/text-fit.js +8 -12
  50. package/dist/board/render/text-measurement.d.ts +15 -1
  51. package/dist/board/render/text-measurement.js +113 -20
  52. package/dist/board/render/text-resolution.d.ts +1 -6
  53. package/dist/board/render/text-resolution.js +1 -10
  54. package/dist/board/render/theme.d.ts +15 -0
  55. package/dist/board/render/theme.js +15 -0
  56. package/dist/board/stage/assets.d.ts +15 -4
  57. package/dist/board/stage/assets.js +155 -89
  58. package/dist/board/stage/index.d.ts +5 -5
  59. package/dist/board/stage/index.js +4 -4
  60. package/dist/board/stage/lru.d.ts +13 -9
  61. package/dist/board/stage/lru.js +38 -20
  62. package/dist/board/stage/scene.d.ts +11 -1
  63. package/dist/board/stage/scene.js +213 -138
  64. package/dist/board/stage/stage.d.ts +12 -1
  65. package/dist/board/stage/stage.js +97 -24
  66. package/dist/board/stage/texture-pool.d.ts +8 -1
  67. package/dist/board/stage/texture-pool.js +37 -1
  68. package/dist/chunks/app-realtime.js +1 -1
  69. package/dist/chunks/{transport.js → http-error.js} +37 -1
  70. package/dist/chunks/http.js +30 -10
  71. package/dist/http.js +1 -1
  72. package/dist/index.js +139 -131
  73. package/dist/media.d.ts +3 -27
  74. package/dist/media.js +3 -82
  75. package/dist/protocol/dist/board-constants.js +3 -3
  76. package/dist/protocol/dist/board-layout.d.ts +17 -3
  77. package/dist/protocol/dist/board-layout.js +68 -11
  78. package/dist/protocol/dist/core/media.d.ts +35 -1
  79. package/dist/protocol/dist/core/media.js +123 -1
  80. package/dist/protocol/dist/index.d.ts +2 -2
  81. package/dist/websocket.js +951 -1
  82. package/package.json +3 -2
  83. package/dist/board/model/image-key.d.ts +0 -9
  84. package/dist/board/model/image-key.js +0 -33
  85. package/dist/chunks/websocket.js +0 -988
@@ -0,0 +1,28 @@
1
+ import { BoardItem } from "../../protocol/dist/board-model.js";
2
+ import "../../protocol/dist/index.js";
3
+ //#region src/board/model/media-sizes.d.ts
4
+ type BoardMediaSize = {
5
+ width: number;
6
+ height: number;
7
+ };
8
+ type BoardMediaTarget = {
9
+ id: string;
10
+ type: "image" | "video";
11
+ source: {
12
+ kind: "file" | "url";
13
+ value: string;
14
+ };
15
+ };
16
+ type BoardMediaFileResolver = (path: string, type: BoardMediaTarget["type"], signal?: AbortSignal) => Promise<BoardMediaSize | string | null>;
17
+ type BoardMediaSizeOptions = {
18
+ resolveFile?: BoardMediaFileResolver;
19
+ signal?: AbortSignal;
20
+ };
21
+ declare function boardMediaTarget(id: string, item: BoardItem): BoardMediaTarget | null;
22
+ declare function probeBoardMediaSize(target: Omit<BoardMediaTarget, "id">, options?: BoardMediaSizeOptions): Promise<BoardMediaSize | null>;
23
+ /** Probes each unique media source once; unresolved items are left as is. */
24
+ declare function settleBoardMediaSizes(items: Readonly<Record<string, BoardItem>>, options?: Omit<BoardMediaSizeOptions, "signal"> & {
25
+ timeoutMs?: number;
26
+ }): Promise<Record<string, BoardItem>>;
27
+ //#endregion
28
+ export { BoardMediaFileResolver, BoardMediaSize, BoardMediaSizeOptions, BoardMediaTarget, boardMediaTarget, probeBoardMediaSize, settleBoardMediaSizes };
@@ -0,0 +1,64 @@
1
+ import { probeMediaSize } from "../../protocol/dist/core/media.js";
2
+ import { parseBoardMediaSource } from "../../protocol/dist/board-model.js";
3
+ import { featuredTaskArtifact } from "../../protocol/dist/board-task.js";
4
+ import { adoptBoardNaturalSize } from "../../protocol/dist/board-layout.js";
5
+ //#region src/board/model/media-sizes.ts
6
+ function boardMediaTarget(id, item) {
7
+ if (item.type === "image" || item.type === "video") {
8
+ if (item.props.snapshot?.naturalWidth && item.props.snapshot.naturalHeight) return null;
9
+ const source = parseBoardMediaSource(item.props.src);
10
+ return source ? {
11
+ id,
12
+ type: item.type,
13
+ source
14
+ } : null;
15
+ }
16
+ if (item.type !== "task") return null;
17
+ const artifact = featuredTaskArtifact(item.props.snapshot.artifacts);
18
+ if (artifact?.type !== "image" && artifact?.type !== "video" || artifact.naturalWidth && artifact.naturalHeight) return null;
19
+ return {
20
+ id,
21
+ type: artifact.type,
22
+ source: {
23
+ kind: "url",
24
+ value: artifact.url
25
+ }
26
+ };
27
+ }
28
+ async function probeBoardMediaSize(target, options = {}) {
29
+ const { type, source } = target;
30
+ try {
31
+ const resolved = source.kind === "url" ? source.value : await options.resolveFile?.(source.value, type, options.signal);
32
+ if (typeof resolved !== "string") return resolved ?? null;
33
+ return await probeMediaSize(resolved, type, { signal: options.signal });
34
+ } catch {
35
+ return null;
36
+ }
37
+ }
38
+ const CONCURRENCY = 8;
39
+ /** Probes each unique media source once; unresolved items are left as is. */
40
+ async function settleBoardMediaSizes(items, options = {}) {
41
+ const targets = Object.entries(items).flatMap(([id, item]) => boardMediaTarget(id, item) ?? []);
42
+ const signal = AbortSignal.timeout(options.timeoutMs ?? 5e3);
43
+ const probes = /* @__PURE__ */ new Map();
44
+ const settled = {};
45
+ let next = 0;
46
+ const work = async () => {
47
+ for (let target = targets[next++]; target; target = targets[next++]) {
48
+ const key = `${target.type}:${target.source.kind}:${target.source.value}`;
49
+ const probe = probes.get(key) ?? probeBoardMediaSize(target, {
50
+ ...options,
51
+ signal
52
+ });
53
+ probes.set(key, probe);
54
+ const size = await probe;
55
+ const item = items[target.id];
56
+ const adopted = size && item && adoptBoardNaturalSize(item, size);
57
+ if (adopted) settled[target.id] = adopted;
58
+ }
59
+ };
60
+ await Promise.all(Array.from({ length: CONCURRENCY }, work));
61
+ return settled;
62
+ }
63
+ //#endregion
64
+ export { boardMediaTarget, probeBoardMediaSize, settleBoardMediaSizes };
@@ -13,6 +13,7 @@ type BoardColorEntry = {
13
13
  dark: BoardColorValue;
14
14
  light: BoardColorValue;
15
15
  };
16
+ /** Swatches with the colors of the default dark and light themes. */
16
17
  declare const BOARD_COLORS: readonly BoardColorEntry[];
17
18
  declare const DEFAULT_BOARD_COLOR: BoardColorId;
18
19
  declare function isBoardColorId(value: unknown): value is BoardColorId;
@@ -1,134 +1,24 @@
1
+ import { BOARD_COLOR_TOKENS } from "../../protocol/dist/board-model.js";
2
+ import { BOARD_THEME_DATA } from "./themes.js";
1
3
  //#region src/board/model/palette.ts
2
- const LABEL_DARK = 16053492;
3
- const LABEL_LIGHT = 1579035;
4
- const BOARD_COLORS = [
5
- {
6
- id: "brand",
7
- label: "Brand",
8
- dark: {
9
- stroke: 16734751,
10
- fill: 16734751,
11
- label: LABEL_DARK
12
- },
13
- light: {
14
- stroke: 15222030,
15
- fill: 15222030,
16
- label: LABEL_LIGHT
17
- }
18
- },
19
- {
20
- id: "neutral",
21
- label: "Neutral",
22
- dark: {
23
- stroke: 10133670,
24
- fill: 10133670,
25
- label: LABEL_DARK
26
- },
27
- light: {
28
- stroke: 6251368,
29
- fill: 6251368,
30
- label: LABEL_LIGHT
31
- }
32
- },
33
- {
34
- id: "black",
35
- label: "Black",
36
- dark: {
37
- stroke: 0,
38
- fill: 0,
39
- label: LABEL_DARK
40
- },
41
- light: {
42
- stroke: 0,
43
- fill: 0,
44
- label: LABEL_LIGHT
45
- }
46
- },
47
- {
48
- id: "white",
49
- label: "White",
50
- dark: {
51
- stroke: 16777215,
52
- fill: 16777215,
53
- label: LABEL_DARK
54
- },
55
- light: {
56
- stroke: 16777215,
57
- fill: 16777215,
58
- label: LABEL_LIGHT
59
- }
60
- },
61
- {
62
- id: "blue",
63
- label: "Blue",
64
- dark: {
65
- stroke: 3718648,
66
- fill: 3718648,
67
- label: LABEL_DARK
68
- },
69
- light: {
70
- stroke: 2450411,
71
- fill: 2450411,
72
- label: LABEL_LIGHT
73
- }
74
- },
75
- {
76
- id: "green",
77
- label: "Green",
78
- dark: {
79
- stroke: 3462041,
80
- fill: 3462041,
81
- label: LABEL_DARK
82
- },
83
- light: {
84
- stroke: 1483594,
85
- fill: 1483594,
86
- label: LABEL_LIGHT
87
- }
88
- },
89
- {
90
- id: "amber",
91
- label: "Amber",
92
- dark: {
93
- stroke: 16096779,
94
- fill: 16096779,
95
- label: LABEL_DARK
96
- },
97
- light: {
98
- stroke: 14251782,
99
- fill: 14251782,
100
- label: LABEL_LIGHT
101
- }
102
- },
103
- {
104
- id: "violet",
105
- label: "Violet",
106
- dark: {
107
- stroke: 10980346,
108
- fill: 10980346,
109
- label: LABEL_DARK
110
- },
111
- light: {
112
- stroke: 8141549,
113
- fill: 8141549,
114
- label: LABEL_LIGHT
115
- }
116
- },
117
- {
118
- id: "rose",
119
- label: "Rose",
120
- dark: {
121
- stroke: 16478597,
122
- fill: 16478597,
123
- label: LABEL_DARK
124
- },
125
- light: {
126
- stroke: 14753096,
127
- fill: 14753096,
128
- label: LABEL_LIGHT
129
- }
130
- }
131
- ];
4
+ const COLOR_LABELS = {
5
+ brand: "Brand",
6
+ neutral: "Neutral",
7
+ black: "Black",
8
+ white: "White",
9
+ blue: "Blue",
10
+ green: "Green",
11
+ amber: "Amber",
12
+ violet: "Violet",
13
+ rose: "Rose"
14
+ };
15
+ /** Swatches with the colors of the default dark and light themes. */
16
+ const BOARD_COLORS = BOARD_COLOR_TOKENS.map((id) => ({
17
+ id,
18
+ label: COLOR_LABELS[id],
19
+ dark: { ...BOARD_THEME_DATA.dark.colors[id] },
20
+ light: { ...BOARD_THEME_DATA.light.colors[id] }
21
+ }));
132
22
  const DEFAULT_BOARD_COLOR = "brand";
133
23
  const COLOR_INDEX = new Map(BOARD_COLORS.map((entry) => [entry.id, entry]));
134
24
  function isBoardColorId(value) {
@@ -1,7 +1,7 @@
1
- import { clampBoardFontSize } from "../../protocol/dist/board-layout.js";
1
+ import { BoardTextLayout, clampBoardFontSize } from "../../protocol/dist/board-layout.js";
2
2
  import "../../protocol/dist/index.js";
3
3
  //#region src/board/model/text-metrics.d.ts
4
- declare const TEXT_FONT_FAMILY = "Geist";
4
+ declare const TEXT_FONT_FAMILY = "Geist Variable";
5
5
  declare const TEXT_FONT_SIZE = 24;
6
6
  declare const TEXT_LINE_HEIGHT = 32;
7
7
  declare const TEXT_MIN_FONT_SIZE = 2;
@@ -11,5 +11,10 @@ declare function boardFontFamily(font: string, stacks: {
11
11
  serif: string;
12
12
  mono: string;
13
13
  }): string;
14
+ declare const SHAPE_LABEL_PADDING = 8;
15
+ declare function layoutShapeLabel(props: {
16
+ text: string;
17
+ fontSize: number;
18
+ }, width: number): BoardTextLayout;
14
19
  //#endregion
15
- export { TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, boardFontFamily, clampBoardFontSize as clampBoardTextFontSize };
20
+ export { SHAPE_LABEL_PADDING, TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, boardFontFamily, clampBoardFontSize as clampBoardTextFontSize, layoutShapeLabel };
@@ -1,5 +1,5 @@
1
1
  import { BOARD_TEXT_FONT_FAMILY } from "../../protocol/dist/board-constants.js";
2
- import { clampBoardFontSize } from "../../protocol/dist/board-layout.js";
2
+ import { clampBoardFontSize, layoutBoardText } from "../../protocol/dist/board-layout.js";
3
3
  //#region src/board/model/text-metrics.ts
4
4
  const TEXT_FONT_FAMILY = BOARD_TEXT_FONT_FAMILY;
5
5
  const TEXT_FONT_SIZE = 24;
@@ -10,5 +10,16 @@ function boardFontFamily(font, stacks) {
10
10
  if (font === "sans" || font === "serif" || font === "mono") return stacks[font];
11
11
  return `"${font.replaceAll("\"", "")}", ${stacks.sans}`;
12
12
  }
13
+ const SHAPE_LABEL_PADDING = 8;
14
+ function layoutShapeLabel(props, width) {
15
+ return layoutBoardText({
16
+ text: props.text,
17
+ fontSize: props.fontSize,
18
+ fontWeight: 500,
19
+ font: "sans",
20
+ lineHeight: 1.4,
21
+ width: Math.max(1, width - 16)
22
+ });
23
+ }
13
24
  //#endregion
14
- export { TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, boardFontFamily, clampBoardFontSize as clampBoardTextFontSize };
25
+ export { SHAPE_LABEL_PADDING, TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, boardFontFamily, clampBoardFontSize as clampBoardTextFontSize, layoutShapeLabel };