@neta-art/cohub 12.6.0 → 13.0.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 (68) hide show
  1. package/README.md +19 -4
  2. package/dist/board/editor/editor.d.ts +7 -5
  3. package/dist/board/editor/index.js +1 -1
  4. package/dist/board/editor/interaction.js +1 -1
  5. package/dist/board/export/index.d.ts +1 -6
  6. package/dist/board/export/index.js +16 -10
  7. package/dist/board/export/node/index.d.ts +2 -7
  8. package/dist/board/export/node/index.js +2 -5
  9. package/dist/board/export/scene.d.ts +3 -7
  10. package/dist/board/export/scene.js +22 -26
  11. package/dist/board/model/asset-key.d.ts +5 -2
  12. package/dist/board/model/asset-key.js +13 -5
  13. package/dist/board/model/index.d.ts +5 -4
  14. package/dist/board/model/index.js +4 -3
  15. package/dist/board/model/media-playback.d.ts +3 -6
  16. package/dist/board/model/media-playback.js +4 -4
  17. package/dist/board/model/read.d.ts +7 -0
  18. package/dist/board/model/read.js +18 -0
  19. package/dist/board/model/themes.d.ts +50 -0
  20. package/dist/board/model/themes.js +44 -6
  21. package/dist/board/render/backdrop-layer.d.ts +21 -0
  22. package/dist/board/render/backdrop-layer.js +227 -0
  23. package/dist/board/render/backdrop.d.ts +45 -0
  24. package/dist/board/render/backdrop.js +62 -0
  25. package/dist/board/render/index.d.ts +3 -2
  26. package/dist/board/render/index.js +7 -6
  27. package/dist/board/render/renderers/arrow-card-renderer.js +1 -1
  28. package/dist/board/render/renderers/audio-card-renderer.js +2 -2
  29. package/dist/board/render/renderers/file-card-renderer.js +1 -1
  30. package/dist/board/render/renderers/frame-card-renderer.js +1 -1
  31. package/dist/board/render/renderers/model-card-renderer.js +1 -1
  32. package/dist/board/render/renderers/shape-card-renderer.js +1 -1
  33. package/dist/board/render/renderers/task-card-renderer.js +2 -2
  34. package/dist/board/render/renderers/text-card-renderer.js +2 -2
  35. package/dist/board/render/renderers/video-card-renderer.js +1 -1
  36. package/dist/board/render/theme.d.ts +2 -0
  37. package/dist/board/render/theme.js +4 -2
  38. package/dist/board/replica/index.d.ts +2 -2
  39. package/dist/board/replica/index.js +38 -39
  40. package/dist/board/stage/assets.d.ts +2 -2
  41. package/dist/board/stage/assets.js +136 -65
  42. package/dist/board/stage/backdrop.d.ts +25 -0
  43. package/dist/board/stage/backdrop.js +104 -0
  44. package/dist/board/stage/index.d.ts +2 -1
  45. package/dist/board/stage/scene.js +1 -1
  46. package/dist/board/stage/stage.d.ts +7 -2
  47. package/dist/board/stage/stage.js +45 -25
  48. package/dist/board/stage/texture-pool.d.ts +1 -1
  49. package/dist/board/stage/texture-pool.js +4 -5
  50. package/dist/chunks/environment.d.ts +26 -15
  51. package/dist/chunks/http.d.ts +31 -23
  52. package/dist/chunks/http.js +1205 -46
  53. package/dist/chunks/websocket.d.ts +1 -1
  54. package/dist/http.d.ts +2 -2
  55. package/dist/index.d.ts +3 -3
  56. package/dist/index.js +1 -1077
  57. package/dist/media.d.ts +18 -32
  58. package/dist/media.js +81 -67
  59. package/dist/protocol/dist/board-model.d.ts +33 -26
  60. package/dist/protocol/dist/board-model.js +21 -18
  61. package/dist/protocol/dist/board.d.ts +2 -0
  62. package/dist/protocol/dist/board.js +5 -1
  63. package/dist/protocol/dist/core/media.d.ts +32 -9
  64. package/dist/protocol/dist/core/media.js +203 -48
  65. package/dist/protocol/dist/index.d.ts +2 -2
  66. package/package.json +1 -1
  67. package/dist/board/render/board-background.d.ts +0 -18
  68. package/dist/board/render/board-background.js +0 -104
@@ -5,12 +5,23 @@ const MEDIA_HOSTS = /* @__PURE__ */ new Map([
5
5
  metaHeaders: true
6
6
  }],
7
7
  ["oss.talesofai.com", { transform: "oss" }],
8
- ["public.cohub.live", { transform: "oss" }],
8
+ ["public.cohub.live", {
9
+ transform: "oss",
10
+ metaHeaders: true
11
+ }],
9
12
  ["public.cohub.run", { transform: "oss" }],
10
- ["sessions.cohub.live", { transform: "oss" }],
11
- ["works.cohub.live", { transform: "oss" }],
13
+ ["sessions.cohub.live", {
14
+ transform: "oss",
15
+ metaHeaders: true
16
+ }],
17
+ ["works.cohub.live", {
18
+ transform: "oss",
19
+ metaHeaders: true
20
+ }],
12
21
  ["works.cohub.run", { transform: "oss" }],
13
- ["cca.neta.art", { transform: "cloudflare" }]
22
+ ["cca.neta.art", { transform: "cloudflare" }],
23
+ ["static.neta.art", { transform: "cloudflare" }],
24
+ ["pages-r2.neta.art", { transform: "cloudflare" }]
14
25
  ]);
15
26
  const parseHttpsUrl = (url) => {
16
27
  if (!/^https:\/\//i.test(url)) return null;
@@ -24,6 +35,36 @@ function mediaHost(url) {
24
35
  const parsed = parseHttpsUrl(url);
25
36
  return parsed ? MEDIA_HOSTS.get(parsed.hostname) : void 0;
26
37
  }
38
+ /** Fixed variant edges keep CDN cache hits high; pick one with `mediaVariantSize`. */
39
+ const MEDIA_VARIANT_SIZES = [
40
+ 192,
41
+ 384,
42
+ 768,
43
+ 1536
44
+ ];
45
+ const MEDIA_VARIANT_MAX = 1536;
46
+ /** Smallest variant covering `pixels` device pixels, capped at the largest. */
47
+ function mediaVariantSize(pixels) {
48
+ return MEDIA_VARIANT_SIZES.find((size) => size >= pixels) ?? 1536;
49
+ }
50
+ const VARIANT_QUALITY = 82;
51
+ const FRAME_GUESS_MAX = 768;
52
+ function fitted(natural, edge, fit) {
53
+ const bound = fit === "cover" ? Math.min(natural.width, natural.height) : fit === "width" ? natural.width : Math.max(natural.width, natural.height);
54
+ const scale = Math.min(1, edge / bound);
55
+ return {
56
+ width: Math.max(1, Math.round(natural.width * scale)),
57
+ height: Math.max(1, Math.round(natural.height * scale))
58
+ };
59
+ }
60
+ const guessedBox = (edge, fit) => fit === "cover" ? edge * 2 : edge;
61
+ const aspectSize = (aspect, edge) => aspect >= 1 ? {
62
+ width: edge,
63
+ height: edge / aspect
64
+ } : {
65
+ width: edge * aspect,
66
+ height: edge
67
+ };
27
68
  const OSS_PROCESS_PATTERN = /[?&]x-oss-process=/;
28
69
  /** Append an OSS process to `url`, keeping its query and hash. */
29
70
  function ossProcessUrl(url, process) {
@@ -33,13 +74,107 @@ function ossProcessUrl(url, process) {
33
74
  const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
34
75
  return `${base}${base.includes("?") ? "&" : "?"}x-oss-process=${process}${hash}`;
35
76
  }
36
- const MODEL_IMAGE = {
37
- maxEdge: 1280,
38
- quality: 75
77
+ const ossProcess = (url, process) => OSS_PROCESS_PATTERN.test(url) ? null : ossProcessUrl(url, process);
78
+ const OSS_RESIZE = {
79
+ cover: (edge) => `m_mfit,w_${edge},h_${edge}`,
80
+ contain: (edge) => `m_lfit,w_${edge},h_${edge}`,
81
+ width: (edge) => `w_${edge}`
82
+ };
83
+ const oss = {
84
+ fitsFrames: false,
85
+ image: (url, edge, fit, quality) => ossProcess(url, `image/resize,${OSS_RESIZE[fit](edge)}/quality,q_${quality}/format,webp`),
86
+ frame: (url, { edge, fit, natural, aspect }) => {
87
+ const shape = natural ?? (aspect ? aspectSize(aspect, FRAME_GUESS_MAX) : null);
88
+ const width = shape ? fitted(shape, edge, fit).width : Math.min(guessedBox(edge, fit), FRAME_GUESS_MAX);
89
+ return ossProcess(url, `video/snapshot,t_0,f_jpg,w_${width},m_fast`);
90
+ },
91
+ sizeFrame: (url) => ossProcess(url, "video/snapshot,t_0,f_jpg,w_0,h_0,m_fast"),
92
+ frameLimit: Number.POSITIVE_INFINITY,
93
+ imageInfoUrl: (url) => ossProcess(url, "image/info"),
94
+ readImageInfo: (body) => {
95
+ const fields = body;
96
+ return {
97
+ width: positive(fields.ImageWidth?.value),
98
+ height: positive(fields.ImageHeight?.value),
99
+ bytes: positive(fields.FileSize?.value)
100
+ };
101
+ },
102
+ source: (url) => {
103
+ const match = /([?&])x-oss-process=([^&#]*)/.exec(url);
104
+ if (!match) return null;
105
+ const [segment, separator, process = ""] = match;
106
+ const head = url.slice(0, match.index);
107
+ const tail = url.slice(match.index + segment.length);
108
+ return {
109
+ url: separator === "?" && tail.startsWith("&") ? `${head}?${tail.slice(1)}` : head + tail,
110
+ type: process.startsWith("video/") ? "video" : "image"
111
+ };
112
+ }
113
+ };
114
+ const CLOUDFLARE_DERIVED = /^\/cdn-cgi\/(image|media)\/[^/]+(\/.*)$/;
115
+ function cdnCgi(url, kind, options) {
116
+ const { origin, pathname, search } = new URL(url);
117
+ return pathname.startsWith("/cdn-cgi/") ? null : `${origin}/cdn-cgi/${kind}/${options}${pathname}${search}`;
118
+ }
119
+ function cloudflareBox(edge, fit, natural, limit = Number.POSITIVE_INFINITY) {
120
+ if (natural) return `width=${Math.min(fitted(natural, edge, fit).width, limit)}`;
121
+ if (fit === "width") return `width=${Math.min(edge, limit)}`;
122
+ const box = Math.min(guessedBox(edge, fit), limit);
123
+ return `width=${box},height=${box}`;
124
+ }
125
+ const CLOUDFLARE_FRAME_MAX = 2e3;
126
+ const ADAPTERS = {
127
+ oss,
128
+ cloudflare: {
129
+ fitsFrames: true,
130
+ image: (url, edge, fit, quality, format) => cdnCgi(url, "image", `${cloudflareBox(edge, fit)},fit=scale-down,quality=${quality},format=${format},onerror=redirect`),
131
+ frame: (url, { edge, fit, natural }) => cdnCgi(url, "media", `mode=frame,time=0s,${cloudflareBox(edge, fit, natural, CLOUDFLARE_FRAME_MAX)},fit=scale-down,format=jpg`),
132
+ sizeFrame: (url) => cdnCgi(url, "media", `mode=frame,time=0s,width=${CLOUDFLARE_FRAME_MAX},height=${CLOUDFLARE_FRAME_MAX},fit=scale-down,format=jpg`),
133
+ frameLimit: CLOUDFLARE_FRAME_MAX,
134
+ imageInfoUrl: (url) => cdnCgi(url, "image", "format=json"),
135
+ readImageInfo: (body) => {
136
+ const original = body.original;
137
+ return {
138
+ width: positive(original?.width),
139
+ height: positive(original?.height),
140
+ bytes: positive(original?.file_size)
141
+ };
142
+ },
143
+ source: (url) => {
144
+ const parsed = new URL(url);
145
+ const match = CLOUDFLARE_DERIVED.exec(parsed.pathname);
146
+ return match ? {
147
+ url: `${parsed.origin}${match[2]}${parsed.search}${parsed.hash}`,
148
+ type: match[1] === "media" ? "video" : "image"
149
+ } : null;
150
+ }
151
+ }
39
152
  };
40
- const { maxEdge, quality } = MODEL_IMAGE;
41
- `${maxEdge}${maxEdge}${quality}`;
42
- `${maxEdge}${maxEdge}${quality}`;
153
+ function adapterFor(url) {
154
+ const host = mediaHost(url);
155
+ return host ? ADAPTERS[host.transform] : null;
156
+ }
157
+ const isGif = (url) => /\.gif$/i.test(new URL(url).pathname);
158
+ function resizedImageUrl(url, edge, fit, quality, format) {
159
+ const adapter = adapterFor(url);
160
+ return adapter && !isGif(url) ? adapter.image(url, edge, fit, quality, format) : null;
161
+ }
162
+ function imageVariantUrl(url, size, fit = "contain") {
163
+ return resizedImageUrl(url, size, fit, VARIANT_QUALITY, "auto");
164
+ }
165
+ function videoFrameUrl(url, size, options = {}) {
166
+ return adapterFor(url)?.frame(url, {
167
+ ...options,
168
+ edge: size,
169
+ fit: options.fit ?? "contain"
170
+ }) ?? null;
171
+ }
172
+ function fitsVideoFrames(url) {
173
+ return adapterFor(url)?.fitsFrames ?? false;
174
+ }
175
+ function variantSource(url) {
176
+ return adapterFor(url)?.source(url) ?? null;
177
+ }
43
178
  function positive(value) {
44
179
  const number = typeof value === "string" ? Number(value) : value;
45
180
  return typeof number === "number" && Number.isFinite(number) && number > 0 ? number : void 0;
@@ -56,6 +191,20 @@ function sameOriginUrl(value, origin) {
56
191
  function compact(info) {
57
192
  return Object.fromEntries(Object.entries(info).filter(([, value]) => value !== void 0));
58
193
  }
194
+ const MEDIA_FACTS_LIMITS = {
195
+ edge: 65535,
196
+ durationMs: 6048e5
197
+ };
198
+ const within = (value, max) => Number.isInteger(value) && value > 0 && value <= max;
199
+ function mediaFacts(facts) {
200
+ const { width, height, durationMs } = facts ?? {};
201
+ if (!within(width, MEDIA_FACTS_LIMITS.edge) || !within(height, MEDIA_FACTS_LIMITS.edge)) return null;
202
+ return {
203
+ width,
204
+ height,
205
+ ...within(durationMs, MEDIA_FACTS_LIMITS.durationMs) ? { durationMs } : {}
206
+ };
207
+ }
59
208
  /** Media facts from response headers; `x-oss-meta-*` need CORS exposure in browsers. */
60
209
  function mediaInfoFromHeaders(headers, url) {
61
210
  const origin = new URL(url).origin;
@@ -90,19 +239,15 @@ async function probeHeaders(url, options) {
90
239
  return response.ok ? mediaInfoFromHeaders(response.headers, url) : {};
91
240
  }
92
241
  async function probeImageInfo(url, options) {
93
- if (OSS_PROCESS_PATTERN.test(url)) return {};
94
- const response = await (options.fetch ?? globalThis.fetch)(ossProcessUrl(url, "image/info"), { signal: options.signal });
95
- if (!response.ok) return {};
96
- const body = await response.json();
97
- return compact({
98
- width: positive(body.ImageWidth?.value),
99
- height: positive(body.ImageHeight?.value),
100
- bytes: positive(body.FileSize?.value)
101
- });
242
+ const adapter = adapterFor(url);
243
+ const infoUrl = adapter?.imageInfoUrl(url);
244
+ if (!adapter || !infoUrl) return {};
245
+ const response = await (options.fetch ?? globalThis.fetch)(infoUrl, { signal: options.signal });
246
+ return response.ok ? compact(adapter.readImageInfo(await response.json())) : {};
102
247
  }
103
248
  async function probeMediaInfo(url, options) {
104
249
  const host = mediaHost(url);
105
- if (host?.transform !== "oss") return {};
250
+ if (!host) return {};
106
251
  let info = {};
107
252
  const attempt = async (strategy) => {
108
253
  try {
@@ -113,43 +258,53 @@ async function probeMediaInfo(url, options) {
113
258
  if (options.type === "image" && !hasDimensions(info)) await attempt(() => probeImageInfo(url, options));
114
259
  return info;
115
260
  }
116
- const PNG_SIGNATURE = [
117
- 137,
118
- 80,
119
- 78,
120
- 71,
121
- 13,
122
- 10,
123
- 26,
124
- 10
125
- ];
126
- /**
127
- * A video's dimensions, read from the header of its first frame rendered as a
128
- * full-size PNG by OSS; only the first 24 bytes are read. Throws on failure.
129
- */
261
+ function jpegSize(bytes, length) {
262
+ if (length >= 2 && (bytes[0] !== 255 || bytes[1] !== 216)) return null;
263
+ let index = 2;
264
+ while (index + 9 <= length) {
265
+ if (bytes[index] !== 255) return null;
266
+ const marker = bytes[index + 1];
267
+ if (marker === 255) {
268
+ index += 1;
269
+ continue;
270
+ }
271
+ if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) {
272
+ const height = bytes[index + 5] << 8 | bytes[index + 6];
273
+ const width = bytes[index + 7] << 8 | bytes[index + 8];
274
+ return width && height ? {
275
+ width,
276
+ height
277
+ } : null;
278
+ }
279
+ index += 2 + (bytes[index + 2] << 8 | bytes[index + 3]);
280
+ }
281
+ return length >= bytes.length ? null : void 0;
282
+ }
283
+ const FRAME_HEADER_BYTES = 65536;
130
284
  async function probeVideoFrameSize(url, options = {}) {
131
- if (mediaHost(url)?.transform !== "oss" || OSS_PROCESS_PATTERN.test(url)) return {};
132
- const response = await (options.fetch ?? globalThis.fetch)(ossProcessUrl(url, "video/snapshot,t_0,f_png,w_0,h_0,m_fast"), {
133
- headers: { Range: "bytes=0-23" },
285
+ const adapter = adapterFor(url);
286
+ const frame = adapter?.sizeFrame(url);
287
+ if (!adapter || !frame) return {};
288
+ const response = await (options.fetch ?? globalThis.fetch)(frame, {
289
+ headers: { Range: `bytes=0-65535` },
134
290
  signal: options.signal
135
291
  });
136
292
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
137
- const header = /* @__PURE__ */ new Uint8Array(24);
293
+ const header = new Uint8Array(FRAME_HEADER_BYTES);
138
294
  let length = 0;
295
+ let size;
139
296
  const reader = response.body?.getReader();
140
- while (reader && length < header.length) {
297
+ while (reader && size === void 0) {
141
298
  const { done, value } = await reader.read();
142
299
  if (done) break;
143
- header.set(value.subarray(0, header.length - length), length);
144
- length += Math.min(value.length, header.length - length);
300
+ const take = Math.min(value.length, header.length - length);
301
+ header.set(value.subarray(0, take), length);
302
+ length += take;
303
+ size = jpegSize(header, length);
145
304
  }
146
305
  await reader?.cancel().catch(() => void 0);
147
- if (length < header.length || PNG_SIGNATURE.some((byte, index) => header[index] !== byte)) return {};
148
- const view = new DataView(header.buffer);
149
- return compact({
150
- width: positive(view.getUint32(16)),
151
- height: positive(view.getUint32(20))
152
- });
306
+ if (!size || Math.max(size.width, size.height) >= adapter.frameLimit) return {};
307
+ return size;
153
308
  }
154
309
  async function probeMediaSize(url, type, options = {}) {
155
310
  const info = await probeMediaInfo(url, {
@@ -163,4 +318,4 @@ async function probeMediaSize(url, type, options = {}) {
163
318
  } : null;
164
319
  }
165
320
  //#endregion
166
- export { MODEL_IMAGE, OSS_PROCESS_PATTERN, mediaHost, mediaInfoFromHeaders, mergeMediaInfo, ossProcessUrl, probeMediaInfo, probeMediaSize, probeVideoFrameSize };
321
+ export { MEDIA_FACTS_LIMITS, MEDIA_VARIANT_MAX, MEDIA_VARIANT_SIZES, fitsVideoFrames, imageVariantUrl, mediaFacts, mediaHost, mediaInfoFromHeaders, mediaVariantSize, mergeMediaInfo, ossProcessUrl, probeMediaInfo, probeMediaSize, probeVideoFrameSize, variantSource, videoFrameUrl };
@@ -1,4 +1,4 @@
1
- import { BOARD_ANCHOR_SIDES, BOARD_ARROW_ROUTES, BOARD_CAMERA_TARGET, BOARD_COLOR_TOKENS, BOARD_DASHES, BOARD_DERIVED_SIZE_TYPES, BOARD_EFFECT_KINDS, BOARD_EFFECT_KIND_INFO, BOARD_ENTER_PRESETS, BOARD_EXTENSION_TYPE_PATTERN, BOARD_GRID_DEFAULT_SIZE, BOARD_GRID_MAX_SIZE, BOARD_GRID_MIN_SIZE, BOARD_ID_MAX_LENGTH, BOARD_ITEM_SCHEMAS, BOARD_ITEM_TYPES, BOARD_PLAY_MODES, BOARD_SHAPE_GEOMETRIES, BOARD_TASK_ARTIFACT_LIMIT, BOARD_TEXT_ALIGNS, BoardAnchorSide, BoardAnimation, BoardAnimationHeader, BoardAnimationHeaderSchema, BoardAnimationSchema, BoardArrowAnchor, BoardArrowAnchorSchema, BoardArrowBinding, BoardArrowBindingSchema, BoardArrowEnd, BoardArrowEndSchema, BoardArrowItem, BoardArrowItemSchema, BoardArrowRoute, BoardAudioItem, BoardAudioItemSchema, BoardBackgroundSchema, BoardBuiltinItem, BoardBuiltinItemType, BoardColor, BoardColorSchema, BoardColorToken, BoardCropSchema, BoardCustomItem, BoardCustomItemSchema, BoardDash, BoardDelta, BoardDiagnostic, BoardDocument, BoardDrawItem, BoardDrawItemSchema, BoardDrawPoint, BoardDrawPointSchema, BoardEaseSchema, BoardEffectItem, BoardEffectItemSchema, BoardEffectKind, BoardEnterPreset, BoardExtensionItem, BoardExtensionItemSchema, BoardFileBackedItem, BoardFileItem, BoardFileItemSchema, BoardFrameItem, BoardFrameItemSchema, BoardIdSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemPreview, BoardItemPreviewSchema, BoardItemType, BoardKeySchema, BoardKeyframe, BoardKeyframeSchema, BoardMarker, BoardMarkerSchema, BoardMediaOrigin, BoardMediaOriginSchema, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardMediaSource, BoardMediaSourceSchema, BoardPatch, BoardPatchSchema, BoardPlayMode, BoardScript, BoardScriptSchema, BoardSettings, BoardSettingsSchema, BoardShapeGeometry, BoardShapeItem, BoardShapeItemSchema, BoardSize, BoardSizeSchema, BoardStyle, BoardStyleSchema, BoardTaskArtifact, BoardTaskArtifactSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextItem, BoardTextItemSchema, BoardTrack, BoardTrackSchema, BoardVec2, BoardVec2Schema, BoardVideoItem, BoardVideoItemSchema, boardItemPreview, boardItemSchema, emptyBoardDocument, hasAuthoredSize, isBoardColorString, isBoardEase, isBuiltinItem, isBuiltinItemType, isEmptyBoardDelta, isFileBackedItem, isMediaItem, isSafeBoardSourcePath, parseBoardItem, parseBoardMediaSource } from "./board-model.js";
1
+ import { BOARD_ANCHOR_SIDES, BOARD_ARROW_ROUTES, BOARD_BACKGROUND_FITS, BOARD_BACKGROUND_PATTERNS, BOARD_CAMERA_TARGET, BOARD_COLOR_TOKENS, BOARD_DASHES, BOARD_DERIVED_SIZE_TYPES, BOARD_EFFECT_KINDS, BOARD_EFFECT_KIND_INFO, BOARD_ENTER_PRESETS, BOARD_EXTENSION_TYPE_PATTERN, BOARD_GRID_DEFAULT_SIZE, BOARD_GRID_MAX_SIZE, BOARD_GRID_MIN_SIZE, BOARD_ID_MAX_LENGTH, BOARD_ITEM_SCHEMAS, BOARD_ITEM_TYPES, BOARD_PLAY_MODES, BOARD_SHAPE_GEOMETRIES, BOARD_TASK_ARTIFACT_LIMIT, BOARD_TEXT_ALIGNS, BoardAnchorSide, BoardAnimation, BoardAnimationHeader, BoardAnimationHeaderSchema, BoardAnimationSchema, BoardArrowAnchor, BoardArrowAnchorSchema, BoardArrowBinding, BoardArrowBindingSchema, BoardArrowEnd, BoardArrowEndSchema, BoardArrowItem, BoardArrowItemSchema, BoardArrowRoute, BoardAudioItem, BoardAudioItemSchema, BoardBackground, BoardBackgroundFit, BoardBackgroundPattern, BoardBackgroundSchema, BoardBuiltinItem, BoardBuiltinItemType, BoardColor, BoardColorSchema, BoardColorToken, BoardCropSchema, BoardCustomItem, BoardCustomItemSchema, BoardDash, BoardDelta, BoardDiagnostic, BoardDocument, BoardDrawItem, BoardDrawItemSchema, BoardDrawPoint, BoardDrawPointSchema, BoardEaseSchema, BoardEffectItem, BoardEffectItemSchema, BoardEffectKind, BoardEnterPreset, BoardExtensionItem, BoardExtensionItemSchema, BoardFileBackedItem, BoardFileItem, BoardFileItemSchema, BoardFrameItem, BoardFrameItemSchema, BoardIdSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemPreview, BoardItemPreviewSchema, BoardItemType, BoardKeySchema, BoardKeyframe, BoardKeyframeSchema, BoardMarker, BoardMarkerSchema, BoardMediaOrigin, BoardMediaOriginSchema, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardMediaSource, BoardMediaSourceSchema, BoardPatch, BoardPatchSchema, BoardPlayMode, BoardScript, BoardScriptSchema, BoardSettings, BoardSettingsSchema, BoardShapeGeometry, BoardShapeItem, BoardShapeItemSchema, BoardSize, BoardSizeSchema, BoardStyle, BoardStyleSchema, BoardTaskArtifact, BoardTaskArtifactSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextItem, BoardTextItemSchema, BoardTrack, BoardTrackSchema, BoardVec2, BoardVec2Schema, BoardVideoItem, BoardVideoItemSchema, boardItemPreview, boardItemSchema, emptyBoardDocument, hasAuthoredSize, isBoardColorString, isBoardEase, isBuiltinItem, isBuiltinItemType, isEmptyBoardDelta, isFileBackedItem, isMediaItem, isSafeBoardSourcePath, parseBoardItem, parseBoardMediaSource } from "./board-model.js";
2
2
  import { BoardFrame, BoardItemLookup, BoardLayout, BoardMatrix, BoardRect, BoardTextFont, BoardTextLayout, BoardTextLayouter, BoardTextLines, IDENTITY_MATRIX, adoptBoardNaturalSize, anchorPoint, applyMatrix, arrowBindings, autoAnchorSide, bendControl, clampBoardFontSize, createBoardLayout, createDocumentLayout, drawPointsBounds, drawSampleRadius, estimateTextWidth, fitBoardMediaSize, framePoint, invertMatrix, isArrowBinding, layoutBoardText, multiplyMatrix, pointsRect, rotateAround, scaleVector, setBoardTextLayouter, sideAnchor } from "./board-layout.js";
3
3
  import { BoardApplyOptions, BoardPatchResult, BoardPropertySpec, BoardState, BoardValueKind, applyBoardDelta, applyBoardPatch, applyBoardPatchToDocument, boardPatchTouches, createDocumentState, diffBoardDocuments, diffMergePatch, isEmptyBoardPatch, listBoardProperties, mergePatch, parseBoardDocument, pruneBoardTrack, resolveBoardProperty, trackReferences } from "./board-patch.js";
4
4
  import "./app-authorization.js";
@@ -24,4 +24,4 @@ import "./app.js";
24
24
  import "./realtime/types.js";
25
25
  import "./app-catalog.js";
26
26
  import "./host-bridge.js";
27
- export { BOARD_ANCHOR_SIDES, BOARD_ARROW_ROUTES, BOARD_CAMERA_TARGET, BOARD_CLIPBOARD_KIND, BOARD_CLIPBOARD_MIME, BOARD_COLOR_TOKENS, BOARD_DASHES, BOARD_DERIVED_SIZE_TYPES, BOARD_EFFECT_KINDS, BOARD_EFFECT_KIND_INFO, BOARD_ENTER_PRESETS, BOARD_EXTENSION_TYPE_PATTERN, BOARD_GRID_DEFAULT_SIZE, BOARD_GRID_MAX_SIZE, BOARD_GRID_MIN_SIZE, BOARD_ID_MAX_LENGTH, BOARD_ITEM_SCHEMAS, BOARD_ITEM_TYPES, BOARD_PLAY_MODES, BOARD_SCHEMA_TARGETS, BOARD_SHAPE_GEOMETRIES, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TASK_ARTIFACT_LIMIT, BOARD_TASK_SOURCE_PREFIX, BOARD_TEXT_ALIGNS, BoardAnchorSide, BoardAnimation, BoardAnimationHeader, BoardAnimationHeaderSchema, BoardAnimationSchema, BoardApplyOptions, BoardApplyResult, BoardArrowAnchor, BoardArrowAnchorSchema, BoardArrowBinding, BoardArrowBindingSchema, BoardArrowEnd, BoardArrowEndSchema, BoardArrowItem, BoardArrowItemSchema, BoardArrowRoute, BoardAudioItem, BoardAudioItemSchema, BoardBackgroundSchema, BoardBuiltinItem, BoardBuiltinItemType, BoardChangeSummary, BoardColor, BoardColorSchema, BoardColorToken, BoardCropSchema, BoardCustomItem, BoardCustomItemSchema, BoardDash, BoardDelta, BoardDiagnostic, BoardDocument, BoardDrawItem, BoardDrawItemSchema, BoardDrawPoint, BoardDrawPointSchema, BoardEaseSchema, BoardEffectItem, BoardEffectItemSchema, BoardEffectKind, BoardEnterPreset, BoardExtensionItem, BoardExtensionItemSchema, BoardFileBackedItem, BoardFileItem, BoardFileItemSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardHistoryPage, BoardIdSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemLookup, BoardItemPreview, BoardItemPreviewSchema, BoardItemType, BoardJsonSchemaResult, BoardKeySchema, BoardKeyframe, BoardKeyframeSchema, BoardLayout, BoardManifest, BoardManifestSchema, BoardMarker, BoardMarkerSchema, BoardMatrix, BoardMediaOrigin, BoardMediaOriginSchema, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardMediaSource, BoardMediaSourceSchema, BoardPatch, BoardPatchResult, BoardPatchSchema, BoardPlayMode, BoardPlaybackCommand, BoardPlaybackCommandSchema, BoardPlaybackSnapshot, BoardPlaybackStatus, BoardPropertySpec, BoardReadInput, BoardReadInputSchema, BoardReadResult, BoardRect, BoardScript, BoardScriptSchema, BoardSettings, BoardSettingsSchema, BoardShapeGeometry, BoardShapeItem, BoardShapeItemSchema, BoardSize, BoardSizeSchema, BoardState, BoardStyle, BoardStyleSchema, BoardTaskArtifact, BoardTaskArtifactSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskRunSource, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextFont, BoardTextItem, BoardTextItemSchema, BoardTextLayout, BoardTextLayouter, BoardTextLines, BoardTrack, BoardTrackSchema, BoardTransactionRecord, BoardValueKind, BoardVec2, BoardVec2Schema, BoardVideoItem, BoardVideoItemSchema, GenerationRunPayload, IDENTITY_MATRIX, ModelFormat, RequestSource, RequestSourceVia, TaskRunStatus, adoptBoardNaturalSize, anchorPoint, applyBoardDelta, applyBoardPatch, applyBoardPatchToDocument, applyMatrix, arrowBindings, autoAnchorSide, bendControl, boardItemPreview, boardItemSchema, boardJsonSchema, boardPatchTouches, boardSchemaOverview, boardTaskSource, clampBoardFontSize, clampBoardStrokeSize, createBoardLayout, createDocumentLayout, createDocumentState, diffBoardDocuments, diffMergePatch, drawPointsBounds, drawSampleRadius, emptyBoardDocument, estimateTextWidth, featuredTaskArtifact, fitBoardMediaSize, framePoint, hasAuthoredSize, invertMatrix, isArrowBinding, isBoardColorString, isBoardEase, isBoardPath, isBuiltinItem, isBuiltinItemType, isEmptyBoardDelta, isEmptyBoardPatch, isFileBackedItem, isMediaItem, isPublicBoardRemoteAddress, isSafeBoardSourcePath, layoutBoardText, listBoardProperties, mergePatch, multiplyMatrix, normalizeBoardRemoteUrl, parseBoardDocument, parseBoardItem, parseBoardManifest, parseBoardMediaSource, pointsRect, pruneBoardTrack, rankedTaskArtifacts, resolveBoardProperty, rotateAround, scaleVector, serializeBoardManifest, setBoardTextLayouter, sideAnchor, taskArtifactPreviewUrl, taskArtifacts, taskRunArtifacts, taskRunToBoardTaskSnapshot, trackReferences, withObservedArtifactFacts };
27
+ export { BOARD_ANCHOR_SIDES, BOARD_ARROW_ROUTES, BOARD_BACKGROUND_FITS, BOARD_BACKGROUND_PATTERNS, BOARD_CAMERA_TARGET, BOARD_CLIPBOARD_KIND, BOARD_CLIPBOARD_MIME, BOARD_COLOR_TOKENS, BOARD_DASHES, BOARD_DERIVED_SIZE_TYPES, BOARD_EFFECT_KINDS, BOARD_EFFECT_KIND_INFO, BOARD_ENTER_PRESETS, BOARD_EXTENSION_TYPE_PATTERN, BOARD_GRID_DEFAULT_SIZE, BOARD_GRID_MAX_SIZE, BOARD_GRID_MIN_SIZE, BOARD_ID_MAX_LENGTH, BOARD_ITEM_SCHEMAS, BOARD_ITEM_TYPES, BOARD_PLAY_MODES, BOARD_SCHEMA_TARGETS, BOARD_SHAPE_GEOMETRIES, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TASK_ARTIFACT_LIMIT, BOARD_TASK_SOURCE_PREFIX, BOARD_TEXT_ALIGNS, BoardAnchorSide, BoardAnimation, BoardAnimationHeader, BoardAnimationHeaderSchema, BoardAnimationSchema, BoardApplyOptions, BoardApplyResult, BoardArrowAnchor, BoardArrowAnchorSchema, BoardArrowBinding, BoardArrowBindingSchema, BoardArrowEnd, BoardArrowEndSchema, BoardArrowItem, BoardArrowItemSchema, BoardArrowRoute, BoardAudioItem, BoardAudioItemSchema, BoardBackground, BoardBackgroundFit, BoardBackgroundPattern, BoardBackgroundSchema, BoardBuiltinItem, BoardBuiltinItemType, BoardChangeSummary, BoardColor, BoardColorSchema, BoardColorToken, BoardCropSchema, BoardCustomItem, BoardCustomItemSchema, BoardDash, BoardDelta, BoardDiagnostic, BoardDocument, BoardDrawItem, BoardDrawItemSchema, BoardDrawPoint, BoardDrawPointSchema, BoardEaseSchema, BoardEffectItem, BoardEffectItemSchema, BoardEffectKind, BoardEnterPreset, BoardExtensionItem, BoardExtensionItemSchema, BoardFileBackedItem, BoardFileItem, BoardFileItemSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardHistoryPage, BoardIdSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemLookup, BoardItemPreview, BoardItemPreviewSchema, BoardItemType, BoardJsonSchemaResult, BoardKeySchema, BoardKeyframe, BoardKeyframeSchema, BoardLayout, BoardManifest, BoardManifestSchema, BoardMarker, BoardMarkerSchema, BoardMatrix, BoardMediaOrigin, BoardMediaOriginSchema, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardMediaSource, BoardMediaSourceSchema, BoardPatch, BoardPatchResult, BoardPatchSchema, BoardPlayMode, BoardPlaybackCommand, BoardPlaybackCommandSchema, BoardPlaybackSnapshot, BoardPlaybackStatus, BoardPropertySpec, BoardReadInput, BoardReadInputSchema, BoardReadResult, BoardRect, BoardScript, BoardScriptSchema, BoardSettings, BoardSettingsSchema, BoardShapeGeometry, BoardShapeItem, BoardShapeItemSchema, BoardSize, BoardSizeSchema, BoardState, BoardStyle, BoardStyleSchema, BoardTaskArtifact, BoardTaskArtifactSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskRunSource, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextFont, BoardTextItem, BoardTextItemSchema, BoardTextLayout, BoardTextLayouter, BoardTextLines, BoardTrack, BoardTrackSchema, BoardTransactionRecord, BoardValueKind, BoardVec2, BoardVec2Schema, BoardVideoItem, BoardVideoItemSchema, GenerationRunPayload, IDENTITY_MATRIX, ModelFormat, RequestSource, RequestSourceVia, TaskRunStatus, adoptBoardNaturalSize, anchorPoint, applyBoardDelta, applyBoardPatch, applyBoardPatchToDocument, applyMatrix, arrowBindings, autoAnchorSide, bendControl, boardItemPreview, boardItemSchema, boardJsonSchema, boardPatchTouches, boardSchemaOverview, boardTaskSource, clampBoardFontSize, clampBoardStrokeSize, createBoardLayout, createDocumentLayout, createDocumentState, diffBoardDocuments, diffMergePatch, drawPointsBounds, drawSampleRadius, emptyBoardDocument, estimateTextWidth, featuredTaskArtifact, fitBoardMediaSize, framePoint, hasAuthoredSize, invertMatrix, isArrowBinding, isBoardColorString, isBoardEase, isBoardPath, isBuiltinItem, isBuiltinItemType, isEmptyBoardDelta, isEmptyBoardPatch, isFileBackedItem, isMediaItem, isPublicBoardRemoteAddress, isSafeBoardSourcePath, layoutBoardText, listBoardProperties, mergePatch, multiplyMatrix, normalizeBoardRemoteUrl, parseBoardDocument, parseBoardItem, parseBoardManifest, parseBoardMediaSource, pointsRect, pruneBoardTrack, rankedTaskArtifacts, resolveBoardProperty, rotateAround, scaleVector, serializeBoardManifest, setBoardTextLayouter, sideAnchor, taskArtifactPreviewUrl, taskArtifacts, taskRunArtifacts, taskRunToBoardTaskSnapshot, trackReferences, withObservedArtifactFacts };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub",
3
- "version": "12.6.0",
3
+ "version": "13.0.0",
4
4
  "description": "Cohub SDK for spaces, sessions, boards, and realtime agent collaboration.",
5
5
  "license": "Apache-2.0",
6
6
  "private": false,
@@ -1,18 +0,0 @@
1
- import { BoardSettings } from "../../protocol/dist/board-model.js";
2
- import "../../protocol/dist/index.js";
3
- import { BoardViewport } from "../model/geometry.js";
4
- import { BoardRenderPalette } from "./renderers/board-renderer-registry.js";
5
- import { Application, Container } from "pixi.js";
6
- //#region src/board/render/board-background.d.ts
7
- type BoardBackgroundContext = {
8
- app: Application;
9
- settings: BoardSettings;
10
- viewport: BoardViewport;
11
- colorScheme: "dark" | "light";
12
- palette: BoardRenderPalette;
13
- hasImageBackground?: boolean;
14
- };
15
- declare function createBoardBackground(context: BoardBackgroundContext): Container;
16
- declare function updateBoardBackground(container: Container, context: BoardBackgroundContext): void;
17
- //#endregion
18
- export { BoardBackgroundContext, createBoardBackground, updateBoardBackground };
@@ -1,104 +0,0 @@
1
- import { parseBoardCssColor } from "./css-color.js";
2
- import { Container, Graphics, RenderTexture, TilingSprite } from "pixi.js";
3
- //#region src/board/render/board-background.ts
4
- const partsByContainer = /* @__PURE__ */ new WeakMap();
5
- function wrap(value, period) {
6
- return (value % period + period) % period;
7
- }
8
- function buildGridTexture(context, size, color, opacity, kind) {
9
- const graphics = new Graphics();
10
- if (kind === "grid") graphics.moveTo(0, .5).lineTo(size, .5).moveTo(.5, 0).lineTo(.5, size).stroke({
11
- color,
12
- width: 1,
13
- alpha: opacity
14
- });
15
- else graphics.circle(size / 2, size / 2, 1.1).fill({
16
- color,
17
- alpha: opacity
18
- });
19
- const target = RenderTexture.create({
20
- width: size,
21
- height: size
22
- });
23
- context.app.renderer.render({
24
- container: graphics,
25
- target
26
- });
27
- graphics.destroy();
28
- return target;
29
- }
30
- function sync(parts, context) {
31
- const { app, settings, viewport, palette } = context;
32
- const width = app.screen.width;
33
- const height = app.screen.height;
34
- const declared = settings.background.color;
35
- const cssColor = typeof declared === "object" ? declared[context.colorScheme] : declared;
36
- const bgColor = cssColor ? parseBoardCssColor(cssColor) ?? palette.bg : palette.bg;
37
- const bgAlpha = context.hasImageBackground ? 0 : 1;
38
- if (parts.lastWidth !== width || parts.lastHeight !== height || parts.lastBg !== bgColor || parts.lastBgAlpha !== bgAlpha) {
39
- parts.fill.clear();
40
- parts.fill.rect(0, 0, width, height).fill({
41
- color: bgColor,
42
- alpha: bgAlpha
43
- });
44
- parts.lastWidth = width;
45
- parts.lastHeight = height;
46
- parts.lastBg = bgColor;
47
- parts.lastBgAlpha = bgAlpha;
48
- }
49
- const kind = settings.background.kind === "grid" ? "grid" : "dots";
50
- const visible = settings.grid?.visible === true;
51
- const size = Math.max(4, settings.grid?.size ?? 24);
52
- const color = kind === "grid" ? palette.border : palette.muted;
53
- const opacity = kind === "grid" ? .9 : .4;
54
- const key = `${kind}|${size}|${color}|${opacity}`;
55
- if (!visible) {
56
- if (parts.sprite) parts.sprite.visible = false;
57
- return;
58
- }
59
- if (parts.textureKey !== key || !parts.sprite) {
60
- if (parts.sprite) {
61
- const previousTexture = parts.sprite.texture;
62
- parts.sprite.destroy();
63
- previousTexture.destroy(true);
64
- }
65
- const texture = buildGridTexture(context, size, color, opacity, kind);
66
- parts.sprite = new TilingSprite({
67
- texture,
68
- width,
69
- height
70
- });
71
- parts.textureKey = key;
72
- parts.fill.parent?.addChild(parts.sprite);
73
- }
74
- const sprite = parts.sprite;
75
- if (!sprite) return;
76
- sprite.visible = true;
77
- sprite.width = width;
78
- sprite.height = height;
79
- const step = size * viewport.zoom;
80
- sprite.tileScale.set(viewport.zoom);
81
- sprite.tilePosition.set(wrap(viewport.x, step), wrap(viewport.y, step));
82
- }
83
- function createBoardBackground(context) {
84
- const container = new Container({ label: "board-background" });
85
- const fill = new Graphics();
86
- container.addChild(fill);
87
- partsByContainer.set(container, {
88
- fill,
89
- sprite: null,
90
- textureKey: "",
91
- lastWidth: -1,
92
- lastHeight: -1,
93
- lastBg: NaN,
94
- lastBgAlpha: NaN
95
- });
96
- sync(partsByContainer.get(container), context);
97
- return container;
98
- }
99
- function updateBoardBackground(container, context) {
100
- const parts = partsByContainer.get(container);
101
- if (parts) sync(parts, context);
102
- }
103
- //#endregion
104
- export { createBoardBackground, updateBoardBackground };