@neta-art/cohub 3.1.0 → 3.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 (93) hide show
  1. package/README.md +33 -2
  2. package/dist/{board.d.ts → board/animation.d.ts} +4 -2
  3. package/dist/{chunks/board.js → board/animation.js} +5 -44
  4. package/dist/board/codec.d.ts +25 -0
  5. package/dist/board/codec.js +252 -0
  6. package/dist/board/core/bindings.d.ts +45 -0
  7. package/dist/board/core/bindings.js +162 -0
  8. package/dist/board/core/draw-geometry.d.ts +31 -0
  9. package/dist/board/core/draw-geometry.js +183 -0
  10. package/dist/board/core/export-assets.d.ts +14 -0
  11. package/dist/board/core/export-assets.js +22 -0
  12. package/dist/board/core/export-plan.d.ts +84 -0
  13. package/dist/board/core/export-plan.js +128 -0
  14. package/dist/board/core/file-preview.d.ts +176 -0
  15. package/dist/board/core/file-preview.js +271 -0
  16. package/dist/board/core/palette.d.ts +42 -0
  17. package/dist/board/core/palette.js +138 -0
  18. package/dist/board/core/shape-definition.d.ts +35 -0
  19. package/dist/board/core/shape-definition.js +64 -0
  20. package/dist/board/core/shape-types.d.ts +144 -0
  21. package/dist/board/core/shape-types.js +27 -0
  22. package/dist/board/core/text-metrics.d.ts +18 -0
  23. package/dist/board/core/text-metrics.js +43 -0
  24. package/dist/board/export/index.d.ts +56 -0
  25. package/dist/board/export/index.js +86 -0
  26. package/dist/board/export/scene.d.ts +35 -0
  27. package/dist/board/export/scene.js +69 -0
  28. package/dist/board/geometry.d.ts +131 -0
  29. package/dist/board/geometry.js +468 -0
  30. package/dist/board/headless/index.d.ts +69 -0
  31. package/dist/board/headless/index.js +150 -0
  32. package/dist/board/image-key.d.ts +19 -0
  33. package/dist/board/image-key.js +34 -0
  34. package/dist/board/index.d.ts +16 -0
  35. package/dist/board/index.js +16 -0
  36. package/dist/board/render/index.d.ts +6 -0
  37. package/dist/board/render/index.js +6 -0
  38. package/dist/board/render/palette.d.ts +5 -0
  39. package/dist/board/render/palette.js +30 -0
  40. package/dist/board/render/renderers/arrow-card-renderer.d.ts +5 -0
  41. package/dist/board/render/renderers/arrow-card-renderer.js +157 -0
  42. package/dist/board/render/renderers/base-card-renderer.d.ts +46 -0
  43. package/dist/board/render/renderers/base-card-renderer.js +153 -0
  44. package/dist/board/render/renderers/board-renderer-registry.d.ts +85 -0
  45. package/dist/board/render/renderers/board-renderer-registry.js +43 -0
  46. package/dist/board/render/renderers/draw-card-renderer.d.ts +5 -0
  47. package/dist/board/render/renderers/draw-card-renderer.js +82 -0
  48. package/dist/board/render/renderers/far-plate.d.ts +39 -0
  49. package/dist/board/render/renderers/far-plate.js +92 -0
  50. package/dist/board/render/renderers/file-card-renderer.d.ts +33 -0
  51. package/dist/board/render/renderers/file-card-renderer.js +371 -0
  52. package/dist/board/render/renderers/frame-card-renderer.d.ts +5 -0
  53. package/dist/board/render/renderers/frame-card-renderer.js +99 -0
  54. package/dist/board/render/renderers/geo-card-renderer.d.ts +5 -0
  55. package/dist/board/render/renderers/geo-card-renderer.js +128 -0
  56. package/dist/board/render/renderers/image-card-renderer.d.ts +8 -0
  57. package/dist/board/render/renderers/image-card-renderer.js +138 -0
  58. package/dist/board/render/renderers/note-card-renderer.d.ts +5 -0
  59. package/dist/board/render/renderers/note-card-renderer.js +112 -0
  60. package/dist/board/render/renderers/text-card-renderer.d.ts +7 -0
  61. package/dist/board/render/renderers/text-card-renderer.js +94 -0
  62. package/dist/board/render/renderers/unknown-card-renderer.d.ts +5 -0
  63. package/dist/board/render/renderers/unknown-card-renderer.js +102 -0
  64. package/dist/board/render/renderers/video-card-renderer.d.ts +7 -0
  65. package/dist/board/render/renderers/video-card-renderer.js +146 -0
  66. package/dist/board/render/text-measurement.d.ts +30 -0
  67. package/dist/board/render/text-measurement.js +57 -0
  68. package/dist/board/render/text-resolution.d.ts +16 -0
  69. package/dist/board/render/text-resolution.js +43 -0
  70. package/dist/board/render/themes/board-theme-registry.d.ts +20 -0
  71. package/dist/board/render/themes/board-theme-registry.js +13 -0
  72. package/dist/board/render/themes/clean-theme.d.ts +5 -0
  73. package/dist/board/render/themes/clean-theme.js +102 -0
  74. package/dist/chunks/http.d.ts +1 -2
  75. package/dist/chunks/websocket.d.ts +798 -352
  76. package/dist/http.d.ts +1 -2
  77. package/dist/index.d.ts +99 -4
  78. package/dist/index.js +391 -1
  79. package/dist/protocol/dist/board-constants.d.ts +23 -0
  80. package/dist/protocol/dist/board-constants.js +60 -0
  81. package/dist/protocol/dist/board-document.d.ts +1124 -0
  82. package/dist/protocol/dist/board-document.js +331 -0
  83. package/dist/protocol/dist/board.d.ts +186 -0
  84. package/dist/protocol/dist/board.js +207 -0
  85. package/dist/protocol/dist/index.d.ts +5 -0
  86. package/dist/protocol/dist/index.js +5 -0
  87. package/dist/protocol/dist/provenance.js +12 -0
  88. package/dist/protocol/dist/realtime/board-awareness.d.ts +1 -0
  89. package/dist/protocol/dist/realtime/board-awareness.js +117 -0
  90. package/dist/protocol/dist/realtime/types.d.ts +2 -0
  91. package/package.json +39 -4
  92. package/dist/board.js +0 -2
  93. package/dist/chunks/board.d.ts +0 -2589
@@ -0,0 +1,34 @@
1
+ //#region src/board/image-key.ts
2
+ /**
3
+ * Stable cache key for an item's image resource, or null when it has none.
4
+ *
5
+ * Space files and remote URLs are namespaced so they can never collide, and file
6
+ * cards contribute their cover image — which means covers ride the exact same
7
+ * reference counting, LRU cooling pool and viewport preloading as image nodes,
8
+ * with no second loader to keep in step. The exporter resolves the same keys, so
9
+ * an exported card shows the same picture the editor does.
10
+ */
11
+ function imageAssetKey(item) {
12
+ if (item.type === "image") return `file:${item.ref.path}`;
13
+ if (item.type === "file") {
14
+ const snapshot = item.snapshot;
15
+ if (snapshot?.coverPath) return `file:${snapshot.coverPath}`;
16
+ if (snapshot?.coverUrl) return `url:${snapshot.coverUrl}`;
17
+ return null;
18
+ }
19
+ return null;
20
+ }
21
+ /** The source a key resolves from, recovered from its namespace prefix. */
22
+ function boardImageKeySource(key) {
23
+ if (key.startsWith("file:")) return {
24
+ kind: "file",
25
+ value: key.slice(5)
26
+ };
27
+ if (key.startsWith("url:")) return {
28
+ kind: "url",
29
+ value: key.slice(4)
30
+ };
31
+ return null;
32
+ }
33
+ //#endregion
34
+ export { boardImageKeySource, imageAssetKey };
@@ -0,0 +1,16 @@
1
+ import { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardManifest, BoardNodeRecord, BoardRecord, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest } from "../protocol/dist/board.js";
2
+ import { BoardExtensionDefinition, BoardExtensionRegistry, BoardPresetDefinition, CompiledSequence, DEFAULT_BOARD_LIMITS, QualityProfile, RenderBounds, TimelineClipInput, TimelineInput, clip, compileSequence, createBoardExtensionRegistry, timeline } from "./animation.js";
3
+ import { ArrowEndpoint, ArrowEndpointSchema, BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardDocument, BoardDocumentSchema, BoardDrawItem, BoardDrawItemSchema, BoardFileItem, BoardFileItemSchema, BoardFileSnapshot, BoardFileSnapshotSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItem, BoardGeoItemSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemSchema, BoardItemStyle, BoardItemStyleSchema, BoardKnownItem, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardNoteItem, BoardNoteItemSchema, BoardTextItem, BoardTextItemSchema, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, DrawPoint, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, SpaceFileRef, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardItemLoose, unknownRealType } from "../protocol/dist/board-document.js";
4
+ import { BOARD_NODE_SOURCE, DEFAULT_BOARD_APPEARANCE, ITEM_BASE_KEYS, WireBackedBoardItem, boardBootstrapToDocument, boardNodeToItem, isRecord, nodeInputFromRecord, sourceForItem } from "./codec.js";
5
+ import { CORNER_RESIZE_HANDLES, EDGE_RESIZE_HANDLES, FIT_PADDING, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, Point, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, Rect, ResizeHandle, ScreenPoint, Size, VIEWPORT_MARGIN_RATIO, WorldPoint, angleFromCenter, clamp, clampZoom, degToRad, expandRect, fitToContent, frameContainsPoint, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, handlePosition, itemBounds, normalizeRotation, normalizeViewport, panBy, pointToWorld, radToDeg, rectCenter, rectContainsPoint, rectsIntersect, resizeFrame, resizeFrameToSize, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, scaleFrames, screenPoint, screenToWorld, selectionBounds, unionRects, visibleWorldRect, worldPoint, worldToScreen, zoomAround } from "./geometry.js";
6
+ import { FrameLookup, ResolvedArrow, anchorToWorld, arrowBounds, bindEndpointAt, distanceToArrow, resolveArrow, resolveEndpoint, sampleQuadratic, translateArrow, worldToAnchor } from "./core/bindings.js";
7
+ import { buildStrokeOutline, computeDrawBounds, distanceToStroke, sampleRadius, simplifyDrawIndices } from "./core/draw-geometry.js";
8
+ import { BOARD_EXPORT_MAX_TEXTURES, BoardExportAssetSelection, selectBoardExportAssets } from "./core/export-assets.js";
9
+ import { BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BoardExportPlan, BoardExportPlanInput, BoardExportRegion, boardFrameLookup, exportItemBounds, normalizeBoardDocument, planBoardExport } from "./core/export-plan.js";
10
+ import { BoardFileSnapshotFacts, BuildSnapshotInput, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FileAvailability, FilePreviewKind, ResolvedCover, availabilityFromError, buildFileExcerpt, buildFileSnapshot, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, formatFileSize, isFileSnapshotFresh, mergeFileSnapshot, readCoverFromFrontmatter, resolveCoverRef, resolveSpacePath, shouldFetchFileExcerpt, splitFrontmatter } from "./core/file-preview.js";
11
+ import { BOARD_COLORS, BoardColorEntry, BoardColorId, BoardColorValue, BoardShapeColors, DEFAULT_BOARD_COLOR, boardColorCssVar, buildFallbackShapeColors, isBoardColorId, pickBoardColor, resolveBoardColor } from "./core/palette.js";
12
+ import { ArrowShapeProps, DrawShapeProps, FULL_CAPABILITIES, GEO_KINDS, GeoKind, GeoShapeProps, HandleDragResult, ImageShapeProps, NoteShapeProps, ShapeCapabilities, ShapeGeometry, ShapeHandle, ShapeHandleId, ShapeResizeMode, TextShapeProps, VideoShapeProps, isGeoKind, resizeModeForCapabilities } from "./core/shape-types.js";
13
+ import { ShapeDefinition, definitionForItem, getShapeDefinition, registerShapeDefinition, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, unknownShapeDefinition } from "./core/shape-definition.js";
14
+ import { TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, boardTextLineHeight, clampBoardTextFontSize, measureBoardText, setBoardTextMeasurer } from "./core/text-metrics.js";
15
+ import { boardImageKeySource, imageAssetKey } from "./image-key.js";
16
+ export { ArrowEndpoint, ArrowEndpointSchema, type ArrowShapeProps, BOARD_COLORS, BOARD_DOCUMENT_KIND, BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BOARD_EXPORT_MAX_TEXTURES, BOARD_EXTENSION, BOARD_NODE_SOURCE, BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardColorEntry, BoardColorId, BoardColorValue, BoardDocument, BoardDocumentSchema, BoardDrawItem, BoardDrawItemSchema, BoardExportAssetSelection, BoardExportPlan, BoardExportPlanInput, BoardExportRegion, BoardExtensionDefinition, BoardExtensionRegistry, BoardFileItem, BoardFileItemSchema, BoardFileSnapshot, BoardFileSnapshotFacts, BoardFileSnapshotSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItem, BoardGeoItemSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemSchema, BoardItemStyle, BoardItemStyleSchema, BoardKnownItem, type BoardManifest, BoardMediaSnapshot, BoardMediaSnapshotSchema, type BoardNodeRecord, BoardNoteItem, BoardNoteItemSchema, BoardPresetDefinition, type BoardRecord, BoardShapeColors, BoardTextItem, BoardTextItemSchema, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, BuildSnapshotInput, CORNER_RESIZE_HANDLES, CompiledSequence, DEFAULT_BOARD_APPEARANCE, DEFAULT_BOARD_COLOR, DEFAULT_BOARD_LIMITS, DrawPoint, DrawPointSchema, type DrawShapeProps, EDGE_RESIZE_HANDLES, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FIT_PADDING, FULL_CAPABILITIES, FileAvailability, FilePreviewKind, FrameLookup, GEO_KINDS, type GeoKind, type GeoShapeProps, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, type HandleDragResult, ITEM_BASE_KEYS, type ImageShapeProps, InvalidBoardFileError, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, type NoteShapeProps, Point, QualityProfile, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, Rect, RenderBounds, ResizeHandle, ResolvedArrow, ResolvedCover, ScreenPoint, type ShapeCapabilities, ShapeDefinition, type ShapeGeometry, type ShapeHandle, type ShapeHandleId, type ShapeResizeMode, Size, SpaceFileRef, SpaceFileRefSchema, TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, type TextShapeProps, TimelineClipInput, TimelineInput, UNKNOWN_BOARD_ITEM_TYPE, VIEWPORT_MARGIN_RATIO, type VideoShapeProps, WireBackedBoardItem, WorldPoint, anchorToWorld, angleFromCenter, arrowBounds, availabilityFromError, bindEndpointAt, boardBootstrapToDocument, boardColorCssVar, boardFrameLookup, boardImageKeySource, boardNodeToItem, boardTextLineHeight, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, clamp, clampBoardTextFontSize, clampZoom, clip, compileSequence, computeDrawBounds, createBoardExtensionRegistry, definitionForItem, degToRad, distanceToArrow, distanceToStroke, expandRect, exportItemBounds, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, fitToContent, formatFileSize, frameContainsPoint, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getShapeDefinition, handlePosition, imageAssetKey, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isRecord, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, nodeInputFromRecord, normalizeBoardDocument, normalizeRotation, normalizeViewport, panBy, parseBoardItemLoose, parseBoardManifest, pickBoardColor, planBoardExport, pointToWorld, radToDeg, readCoverFromFrontmatter, rectCenter, rectContainsPoint, rectsIntersect, registerShapeDefinition, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveCoverRef, resolveEndpoint, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleQuadratic, sampleRadius, scaleFrames, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, sourceForItem, splitFrontmatter, timeline, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, worldPoint, worldToAnchor, worldToScreen, zoomAround };
@@ -0,0 +1,16 @@
1
+ import { BoardExtensionRegistry, DEFAULT_BOARD_LIMITS, clip, compileSequence, createBoardExtensionRegistry, timeline } from "./animation.js";
2
+ import { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest } from "../protocol/dist/board.js";
3
+ import { ArrowEndpointSchema, BoardAppearanceSchema, BoardArrowItemSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardNoteItemSchema, BoardTextItemSchema, BoardVideoItemSchema, BoardViewportSchema, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardItemLoose, unknownRealType } from "../protocol/dist/board-document.js";
4
+ import { TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, boardTextLineHeight, clampBoardTextFontSize, measureBoardText, setBoardTextMeasurer } from "./core/text-metrics.js";
5
+ import { BOARD_NODE_SOURCE, DEFAULT_BOARD_APPEARANCE, ITEM_BASE_KEYS, boardBootstrapToDocument, boardNodeToItem, isRecord, nodeInputFromRecord, sourceForItem } from "./codec.js";
6
+ import { CORNER_RESIZE_HANDLES, EDGE_RESIZE_HANDLES, FIT_PADDING, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, VIEWPORT_MARGIN_RATIO, angleFromCenter, clamp, clampZoom, degToRad, expandRect, fitToContent, frameContainsPoint, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, handlePosition, itemBounds, normalizeRotation, normalizeViewport, panBy, pointToWorld, radToDeg, rectCenter, rectContainsPoint, rectsIntersect, resizeFrame, resizeFrameToSize, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, scaleFrames, screenPoint, screenToWorld, selectionBounds, unionRects, visibleWorldRect, worldPoint, worldToScreen, zoomAround } from "./geometry.js";
7
+ import { boardImageKeySource, imageAssetKey } from "./image-key.js";
8
+ import { anchorToWorld, arrowBounds, bindEndpointAt, distanceToArrow, resolveArrow, resolveEndpoint, sampleQuadratic, translateArrow, worldToAnchor } from "./core/bindings.js";
9
+ import { buildStrokeOutline, computeDrawBounds, distanceToStroke, sampleRadius, simplifyDrawIndices } from "./core/draw-geometry.js";
10
+ import { BOARD_EXPORT_MAX_TEXTURES, selectBoardExportAssets } from "./core/export-assets.js";
11
+ import { BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, boardFrameLookup, exportItemBounds, normalizeBoardDocument, planBoardExport } from "./core/export-plan.js";
12
+ import { FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, availabilityFromError, buildFileExcerpt, buildFileSnapshot, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, formatFileSize, isFileSnapshotFresh, mergeFileSnapshot, readCoverFromFrontmatter, resolveCoverRef, resolveSpacePath, shouldFetchFileExcerpt, splitFrontmatter } from "./core/file-preview.js";
13
+ import { BOARD_COLORS, DEFAULT_BOARD_COLOR, boardColorCssVar, buildFallbackShapeColors, isBoardColorId, pickBoardColor, resolveBoardColor } from "./core/palette.js";
14
+ import { FULL_CAPABILITIES, GEO_KINDS, isGeoKind, resizeModeForCapabilities } from "./core/shape-types.js";
15
+ import { definitionForItem, getShapeDefinition, registerShapeDefinition, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, unknownShapeDefinition } from "./core/shape-definition.js";
16
+ export { ArrowEndpointSchema, BOARD_COLORS, BOARD_DOCUMENT_KIND, BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BOARD_EXPORT_MAX_TEXTURES, BOARD_EXTENSION, BOARD_NODE_SOURCE, BoardAppearanceSchema, BoardArrowItemSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardExtensionRegistry, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardNoteItemSchema, BoardTextItemSchema, BoardVideoItemSchema, BoardViewportSchema, CORNER_RESIZE_HANDLES, DEFAULT_BOARD_APPEARANCE, DEFAULT_BOARD_COLOR, DEFAULT_BOARD_LIMITS, DrawPointSchema, EDGE_RESIZE_HANDLES, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FIT_PADDING, FULL_CAPABILITIES, GEO_KINDS, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, ITEM_BASE_KEYS, InvalidBoardFileError, KNOWN_BOARD_ITEM_TYPES, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, SpaceFileRefSchema, TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, UNKNOWN_BOARD_ITEM_TYPE, VIEWPORT_MARGIN_RATIO, anchorToWorld, angleFromCenter, arrowBounds, availabilityFromError, bindEndpointAt, boardBootstrapToDocument, boardColorCssVar, boardFrameLookup, boardImageKeySource, boardNodeToItem, boardTextLineHeight, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, clamp, clampBoardTextFontSize, clampZoom, clip, compileSequence, computeDrawBounds, createBoardExtensionRegistry, definitionForItem, degToRad, distanceToArrow, distanceToStroke, expandRect, exportItemBounds, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, fitToContent, formatFileSize, frameContainsPoint, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getShapeDefinition, handlePosition, imageAssetKey, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isRecord, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, nodeInputFromRecord, normalizeBoardDocument, normalizeRotation, normalizeViewport, panBy, parseBoardItemLoose, parseBoardManifest, pickBoardColor, planBoardExport, pointToWorld, radToDeg, readCoverFromFrontmatter, rectCenter, rectContainsPoint, rectsIntersect, registerShapeDefinition, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveCoverRef, resolveEndpoint, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleQuadratic, sampleRadius, scaleFrames, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, sourceForItem, splitFrontmatter, timeline, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, worldPoint, worldToAnchor, worldToScreen, zoomAround };
@@ -0,0 +1,6 @@
1
+ import { BoardCardRenderer, BoardRenderContext, BoardRenderPalette, boardCardRenderersForTest, getBoardCardRenderer, registerBoardCardRenderer } from "./renderers/board-renderer-registry.js";
2
+ import { defaultBoardPalette } from "./palette.js";
3
+ import { ensureBoardTextMeasurement, installBoardTextMeasurement } from "./text-measurement.js";
4
+ import { getBoardResolution, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket } from "./text-resolution.js";
5
+ import { BoardThemeContext, BoardThemeRenderer, getBoardThemeRenderer, registerBoardThemeRenderer } from "./themes/board-theme-registry.js";
6
+ export { BoardCardRenderer, BoardRenderContext, BoardRenderPalette, BoardThemeContext, BoardThemeRenderer, boardCardRenderersForTest, defaultBoardPalette, ensureBoardTextMeasurement, getBoardCardRenderer, getBoardResolution, getBoardThemeRenderer, installBoardTextMeasurement, registerBoardCardRenderer, registerBoardThemeRenderer, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket };
@@ -0,0 +1,6 @@
1
+ import { defaultBoardPalette } from "./palette.js";
2
+ import { ensureBoardTextMeasurement, installBoardTextMeasurement } from "./text-measurement.js";
3
+ import { getBoardResolution, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket } from "./text-resolution.js";
4
+ import { boardCardRenderersForTest, getBoardCardRenderer, registerBoardCardRenderer } from "./renderers/board-renderer-registry.js";
5
+ import { getBoardThemeRenderer, registerBoardThemeRenderer } from "./themes/board-theme-registry.js";
6
+ export { boardCardRenderersForTest, defaultBoardPalette, ensureBoardTextMeasurement, getBoardCardRenderer, getBoardResolution, getBoardThemeRenderer, installBoardTextMeasurement, registerBoardCardRenderer, registerBoardThemeRenderer, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket };
@@ -0,0 +1,5 @@
1
+ import { BoardRenderPalette } from "./renderers/board-renderer-registry.js";
2
+ //#region src/board/render/palette.d.ts
3
+ declare function defaultBoardPalette(mode: "dark" | "light"): BoardRenderPalette;
4
+ //#endregion
5
+ export { defaultBoardPalette };
@@ -0,0 +1,30 @@
1
+ //#region src/board/render/palette.ts
2
+ const DARK = {
3
+ bg: 1315860,
4
+ surface: 2105376,
5
+ hover: 2763306,
6
+ border: 3815994,
7
+ brand: 16734751,
8
+ text: 16053492,
9
+ muted: 9211020,
10
+ rare: 3718648,
11
+ epic: 10980346,
12
+ legendary: 16096779
13
+ };
14
+ const LIGHT = {
15
+ bg: 16777215,
16
+ surface: 16053493,
17
+ hover: 15329772,
18
+ border: 14079706,
19
+ brand: 15222030,
20
+ text: 1579035,
21
+ muted: 7041664,
22
+ rare: 2450411,
23
+ epic: 8141549,
24
+ legendary: 11817737
25
+ };
26
+ function defaultBoardPalette(mode) {
27
+ return { ...mode === "light" ? LIGHT : DARK };
28
+ }
29
+ //#endregion
30
+ export { defaultBoardPalette };
@@ -0,0 +1,5 @@
1
+ import { BoardCardRenderer } from "./board-renderer-registry.js";
2
+ //#region src/board/render/renderers/arrow-card-renderer.d.ts
3
+ declare const arrowCardRenderer: BoardCardRenderer;
4
+ //#endregion
5
+ export { arrowCardRenderer };
@@ -0,0 +1,157 @@
1
+ import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
2
+ import { resolveArrow, sampleQuadratic } from "../../core/bindings.js";
3
+ import { pickBoardColor } from "../../core/palette.js";
4
+ import { syncTextResolution, textResolutionForZoom } from "../text-resolution.js";
5
+ import { drawFarStroke } from "./far-plate.js";
6
+ import { Container, Graphics, Text } from "pixi.js";
7
+ //#region src/board/render/renderers/arrow-card-renderer.ts
8
+ const partsByContainer = /* @__PURE__ */ new WeakMap();
9
+ /**
10
+ * Frame lookup for resolving bindings.
11
+ *
12
+ * Routed through the context's id index rather than scanning the document: an
13
+ * arrow re-resolves its endpoints on every sync, and a per-arrow O(items) scan
14
+ * would make a board with many arrows quadratic per frame.
15
+ */
16
+ function frameLookup(context) {
17
+ return (id) => context.getItem(id)?.frame;
18
+ }
19
+ /** Open chevron arrowhead — clearly directional, not a tiny filled nub. */
20
+ function drawArrowhead(graphics, tip, angle, size, color, strokeWidth) {
21
+ const spread = Math.PI / 6;
22
+ const left = {
23
+ x: tip.x - size * Math.cos(angle - spread),
24
+ y: tip.y - size * Math.sin(angle - spread)
25
+ };
26
+ const right = {
27
+ x: tip.x - size * Math.cos(angle + spread),
28
+ y: tip.y - size * Math.sin(angle + spread)
29
+ };
30
+ graphics.moveTo(left.x, left.y).lineTo(tip.x, tip.y).lineTo(right.x, right.y).stroke({
31
+ color,
32
+ width: Math.max(1.5, strokeWidth),
33
+ alpha: 1,
34
+ cap: "round",
35
+ join: "round"
36
+ });
37
+ }
38
+ function sync(container, item, context) {
39
+ const parts = partsByContainer.get(container);
40
+ if (!parts) return;
41
+ parts.root.position.set(0, 0);
42
+ parts.root.rotation = 0;
43
+ const selected = context.selectedIds.has(item.id);
44
+ const hovered = context.hoveredId === item.id;
45
+ const color = pickBoardColor(context.colors, item.color, context.colorScheme);
46
+ syncTextResolution(parts.label, parts, context.zoom);
47
+ const resolved = resolveArrow(item, frameLookup(context));
48
+ const lineSig = resolved ? [
49
+ resolved.start.x,
50
+ resolved.start.y,
51
+ resolved.end.x,
52
+ resolved.end.y,
53
+ resolved.control.x,
54
+ resolved.control.y,
55
+ selected,
56
+ hovered,
57
+ color.stroke,
58
+ item.size,
59
+ item.arrowStart,
60
+ item.arrowEnd
61
+ ].join("|") : `empty|${item.id}`;
62
+ if (lineSig !== parts.lineSig) {
63
+ parts.lineSig = lineSig;
64
+ parts.line.clear();
65
+ if (resolved) {
66
+ const strokeColor = color.stroke;
67
+ const width = selected ? item.size + 1 : item.size;
68
+ const samples = sampleQuadratic(resolved, 24);
69
+ const head = samples[0];
70
+ const tail = samples[samples.length - 1];
71
+ if (head && tail) {
72
+ parts.line.moveTo(head.x, head.y);
73
+ for (let i = 1; i < samples.length; i += 1) {
74
+ const point = samples[i];
75
+ if (point) parts.line.lineTo(point.x, point.y);
76
+ }
77
+ parts.line.stroke({
78
+ color: strokeColor,
79
+ width,
80
+ alpha: selected || hovered ? 1 : .92,
81
+ cap: "round",
82
+ join: "round"
83
+ });
84
+ const span = Math.hypot(tail.x - head.x, tail.y - head.y);
85
+ const headSize = Math.min(Math.max(14, item.size * 5.5), Math.max(10, span * .28));
86
+ if (item.arrowEnd) {
87
+ const prev = samples[samples.length - 2];
88
+ if (prev) drawArrowhead(parts.line, tail, Math.atan2(tail.y - prev.y, tail.x - prev.x), headSize, strokeColor, width);
89
+ }
90
+ if (item.arrowStart) {
91
+ const next = samples[1];
92
+ if (next) drawArrowhead(parts.line, head, Math.atan2(head.y - next.y, head.x - next.x), headSize, strokeColor, width);
93
+ }
94
+ }
95
+ }
96
+ }
97
+ const labelSig = [item.label, color.label].join("|");
98
+ if (labelSig !== parts.labelSig) {
99
+ parts.labelSig = labelSig;
100
+ parts.label.text = item.label;
101
+ parts.label.style.fill = color.label;
102
+ }
103
+ parts.label.visible = Boolean(resolved && item.label.length > 0);
104
+ if (resolved) parts.label.position.copyFrom(resolved.control);
105
+ }
106
+ const arrowCardRenderer = {
107
+ id: "arrow-card",
108
+ canRender: (item) => item.type === "arrow",
109
+ create: (item, context) => {
110
+ const root = new Container();
111
+ const line = new Graphics();
112
+ const resolution = textResolutionForZoom(context.zoom);
113
+ const label = new Text({
114
+ text: "",
115
+ style: {
116
+ fill: 16777215,
117
+ fontFamily: BOARD_FONT_STACK,
118
+ fontSize: 12,
119
+ fontWeight: "500"
120
+ },
121
+ resolution,
122
+ roundPixels: true
123
+ });
124
+ label.anchor.set(.5);
125
+ root.addChild(line, label);
126
+ partsByContainer.set(root, {
127
+ root,
128
+ line,
129
+ label,
130
+ lineSig: "",
131
+ labelSig: "",
132
+ resolution
133
+ });
134
+ if (item.type === "arrow") sync(root, item, context);
135
+ return root;
136
+ },
137
+ update: (container, item, context) => {
138
+ if (item.type === "arrow") sync(container, item, context);
139
+ },
140
+ renderFar: (graphics, item, context) => {
141
+ if (item.type !== "arrow") return;
142
+ const resolved = resolveArrow(item, frameLookup(context));
143
+ if (!resolved) return;
144
+ const color = pickBoardColor(context.colors, item.color, context.colorScheme);
145
+ drawFarStroke(graphics, sampleQuadratic(resolved, 12), {
146
+ color: color.stroke,
147
+ width: item.size,
148
+ alpha: .85
149
+ });
150
+ },
151
+ destroy: (container) => {
152
+ partsByContainer.get(container)?.root.destroy({ children: true });
153
+ partsByContainer.delete(container);
154
+ }
155
+ };
156
+ //#endregion
157
+ export { arrowCardRenderer };
@@ -0,0 +1,46 @@
1
+ import { BoardItem } from "../../../protocol/dist/board-document.js";
2
+ import { BoardRenderPalette } from "./board-renderer-registry.js";
3
+ import { Container, Text } from "pixi.js";
4
+ //#region src/board/render/renderers/base-card-renderer.d.ts
5
+ declare const CARD_RADIUS = 10;
6
+ declare const CARD_PADDING = 12;
7
+ declare const FOOTER_HEIGHT = 34;
8
+ declare function emphasisColor(item: BoardItem, palette: BoardRenderPalette): number;
9
+ declare function createLabel(text: string, style: Record<string, unknown>): Text;
10
+ type CardShellState = {
11
+ width: number;
12
+ height: number;
13
+ selected: boolean;
14
+ hovered: boolean;
15
+ accent: number;
16
+ title: string;
17
+ };
18
+ type CardShell = {
19
+ /** Root container positioned by the item frame. */
20
+ root: Container;
21
+ /** Masked container for renderer-specific content. */
22
+ content: Container;
23
+ /** Rectangle (local coords) available for content. */
24
+ contentRect: () => {
25
+ x: number;
26
+ y: number;
27
+ width: number;
28
+ height: number;
29
+ };
30
+ update: (state: CardShellState, palette: BoardRenderPalette, footer: boolean) => void;
31
+ destroy: () => void;
32
+ };
33
+ /**
34
+ * Shared card chrome: rounded background, selection/hover border, optional
35
+ * footer with title, and a masked content region. Tracks the last rendered
36
+ * state so unchanged attributes are not redrawn.
37
+ */
38
+ declare function createCardShell(): CardShell;
39
+ /**
40
+ * Position a shell root at an item frame. The container pivots around its
41
+ * center so that Pixi's rotation matches the geometry model (which treats
42
+ * `frame.rotation` as a rotation about the frame center).
43
+ */
44
+ declare function positionShell(root: Container, item: BoardItem): void;
45
+ //#endregion
46
+ export { CARD_PADDING, CARD_RADIUS, CardShell, CardShellState, FOOTER_HEIGHT, createCardShell, createLabel, emphasisColor, positionShell };
@@ -0,0 +1,153 @@
1
+ import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
2
+ import { getBoardResolution } from "../text-resolution.js";
3
+ import { Container, DOMAdapter, Graphics, Text } from "pixi.js";
4
+ //#region src/board/render/renderers/base-card-renderer.ts
5
+ const CARD_RADIUS = 10;
6
+ const CARD_PADDING = 12;
7
+ const FOOTER_HEIGHT = 34;
8
+ const TEXT_OPTIONS = {
9
+ resolution: getBoardResolution(),
10
+ roundPixels: true
11
+ };
12
+ function emphasisColor(item, palette) {
13
+ if (item.style?.accentColor) {
14
+ const normalized = parseCssColor(item.style.accentColor);
15
+ if (normalized != null) return normalized;
16
+ }
17
+ switch (item.style?.emphasis) {
18
+ case "rare": return palette.rare;
19
+ case "epic": return palette.epic;
20
+ case "legendary": return palette.legendary;
21
+ default: return palette.brand;
22
+ }
23
+ }
24
+ /**
25
+ * Normalise any CSS color to a number by letting a 2D context parse it.
26
+ *
27
+ * Goes through `DOMAdapter` rather than `document` so a headless export resolves
28
+ * accent colors exactly as the browser does; without it, custom accents would
29
+ * silently fall back to the emphasis palette only when exporting.
30
+ */
31
+ function parseCssColor(value) {
32
+ try {
33
+ const context = DOMAdapter.get().createCanvas(1, 1).getContext("2d");
34
+ if (!context) return null;
35
+ context.fillStyle = value;
36
+ const match = /^#([0-9a-f]{6})$/i.exec(String(context.fillStyle));
37
+ return match?.[1] ? Number.parseInt(match[1], 16) : null;
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+ function createLabel(text, style) {
43
+ return new Text({
44
+ ...TEXT_OPTIONS,
45
+ text,
46
+ style
47
+ });
48
+ }
49
+ /**
50
+ * Shared card chrome: rounded background, selection/hover border, optional
51
+ * footer with title, and a masked content region. Tracks the last rendered
52
+ * state so unchanged attributes are not redrawn.
53
+ */
54
+ function createCardShell() {
55
+ const root = new Container();
56
+ const background = new Graphics();
57
+ const content = new Container();
58
+ const mask = new Graphics();
59
+ const footerBg = new Graphics();
60
+ const title = createLabel("", {
61
+ fill: 16777215,
62
+ fontFamily: BOARD_FONT_STACK,
63
+ fontSize: 12,
64
+ fontWeight: "500",
65
+ wordWrap: true
66
+ });
67
+ content.mask = mask;
68
+ root.addChild(background, mask, content, footerBg, title);
69
+ let last = null;
70
+ function paletteKeyOf(palette) {
71
+ return `${palette.surface}|${palette.border}|${palette.hover}|${palette.text}|${palette.muted}`;
72
+ }
73
+ function contentRectFor(width, height, footer) {
74
+ const bottom = footer ? 34 : 12;
75
+ return {
76
+ x: 12,
77
+ y: 12,
78
+ width: Math.max(1, width - 24),
79
+ height: Math.max(1, height - 12 - bottom)
80
+ };
81
+ }
82
+ function draw(state, palette, footer) {
83
+ const { width, height, selected, hovered, accent } = state;
84
+ background.clear();
85
+ background.roundRect(0, 0, width, height, 10).fill({
86
+ color: palette.surface,
87
+ alpha: .98
88
+ });
89
+ const borderColor = selected ? accent : hovered ? palette.muted : palette.border;
90
+ background.roundRect(0, 0, width, height, 10).stroke({
91
+ color: borderColor,
92
+ width: selected ? 2 : 1,
93
+ alpha: selected ? .95 : hovered ? .9 : .8
94
+ });
95
+ mask.clear();
96
+ const rect = contentRectFor(width, height, footer);
97
+ mask.roundRect(rect.x, rect.y, rect.width, rect.height, 4).fill({ color: 16777215 });
98
+ footerBg.clear();
99
+ footerBg.visible = footer;
100
+ title.visible = footer;
101
+ if (footer) {
102
+ const fx = 1;
103
+ const fy = height - 34;
104
+ const fw = width - 2;
105
+ const fh = 33;
106
+ const r = 9;
107
+ footerBg.moveTo(fx, fy).lineTo(fx + fw, fy).lineTo(fx + fw, fy + fh - r).arcTo(fx + fw, fy + fh, fx + fw - r, fy + fh, r).lineTo(10, fy + fh).arcTo(fx, fy + fh, fx, fy + fh - r, r).lineTo(fx, fy).fill({
108
+ color: palette.hover,
109
+ alpha: .55
110
+ });
111
+ title.text = state.title;
112
+ title.style.fill = palette.text;
113
+ title.style.wordWrapWidth = width - 24;
114
+ title.x = 12;
115
+ title.y = height - 34 + (34 - title.height) / 2;
116
+ }
117
+ }
118
+ function update(state, palette, footer) {
119
+ const paletteKey = paletteKeyOf(palette);
120
+ if (!last || last.width !== state.width || last.height !== state.height || last.selected !== state.selected || last.hovered !== state.hovered || last.accent !== state.accent || last.title !== state.title || last.footer !== footer || last.paletteKey !== paletteKey) {
121
+ draw(state, palette, footer);
122
+ last = {
123
+ ...state,
124
+ footer,
125
+ paletteKey
126
+ };
127
+ }
128
+ }
129
+ function destroy() {
130
+ root.destroy({ children: true });
131
+ }
132
+ return {
133
+ root,
134
+ content,
135
+ contentRect: () => contentRectFor(last?.width ?? 0, last?.height ?? 0, last?.footer ?? true),
136
+ update,
137
+ destroy
138
+ };
139
+ }
140
+ /**
141
+ * Position a shell root at an item frame. The container pivots around its
142
+ * center so that Pixi's rotation matches the geometry model (which treats
143
+ * `frame.rotation` as a rotation about the frame center).
144
+ */
145
+ function positionShell(root, item) {
146
+ const { x, y, width, height, rotation } = item.frame;
147
+ root.pivot.set(width / 2, height / 2);
148
+ root.x = x + width / 2;
149
+ root.y = y + height / 2;
150
+ root.rotation = (rotation || 0) * Math.PI / 180;
151
+ }
152
+ //#endregion
153
+ export { CARD_PADDING, CARD_RADIUS, FOOTER_HEIGHT, createCardShell, createLabel, emphasisColor, positionShell };
@@ -0,0 +1,85 @@
1
+ import { BoardDocument, BoardItem } from "../../../protocol/dist/board-document.js";
2
+ import { BoardShapeColors } from "../../core/palette.js";
3
+ import { Container, Graphics, Texture } from "pixi.js";
4
+ //#region src/board/render/renderers/board-renderer-registry.d.ts
5
+ type BoardRenderPalette = {
6
+ bg: number;
7
+ surface: number;
8
+ hover: number;
9
+ border: number;
10
+ brand: number;
11
+ text: number;
12
+ muted: number;
13
+ rare: number;
14
+ epic: number;
15
+ legendary: number;
16
+ };
17
+ type BoardRenderContext = {
18
+ document: BoardDocument;
19
+ /**
20
+ * O(1) item lookup by id. Renderers that need to resolve references (arrow
21
+ * bindings) must use this rather than scanning `document.items`, which would
22
+ * be O(items) per card per frame.
23
+ */
24
+ getItem: (id: string) => BoardItem | null;
25
+ selectedIds: Set<string>;
26
+ hoveredId: string | null;
27
+ /** Nodes currently receiving a live resize preview. */
28
+ resizingIds: Set<string>;
29
+ palette: BoardRenderPalette;
30
+ /**
31
+ * Live shape colors resolved from CSS tokens (theme + space theme.css).
32
+ * Prefer this over hard-coded light/dark tables at render time.
33
+ */
34
+ colors: BoardShapeColors;
35
+ /** Resolved color mode, for fallback mapping when colors are unavailable. */
36
+ colorScheme: "dark" | "light";
37
+ /** Current camera zoom — used for text re-rasterisation buckets. */
38
+ zoom: number;
39
+ /** Stable preview texture key for an item, or null when it has no preview. */
40
+ assetKey: (item: BoardItem) => string | null;
41
+ /** Currently loaded texture for a key (null while loading). */
42
+ getTexture: (key: string) => Texture | null;
43
+ /** Whether the preview for a key failed to load (for a failure placeholder). */
44
+ hasError: (key: string) => boolean;
45
+ /**
46
+ * Whether a referenced workspace file could not be read, and why. Transient,
47
+ * client-local state — never part of the document — so one client's outage is
48
+ * not shown to everyone.
49
+ */
50
+ fileState: (path: string) => "ok" | "missing" | "unavailable";
51
+ /** Reference-counted texture acquisition and release. */
52
+ acquireTexture: (key: string) => void;
53
+ releaseTexture: (key: string) => void;
54
+ };
55
+ type BoardCardRenderer = {
56
+ id: string;
57
+ canRender: (item: BoardItem, context: BoardRenderContext) => boolean;
58
+ create: (item: BoardItem, context: BoardRenderContext) => Container;
59
+ /** Efficiently sync an existing container to a (possibly changed) item. */
60
+ update: (container: Container, item: BoardItem, context: BoardRenderContext) => void;
61
+ /**
62
+ * Draw the item as flat batched geometry into a shared `Graphics`, for the
63
+ * far LOD used when too many cards are on screen to afford a container each.
64
+ *
65
+ * Implementing this opts the shape into the far layer: past the scene's
66
+ * visible-card threshold it is drawn here instead of being materialised, so
67
+ * cost stops scaling with node count. Omit it for shapes whose whole point is
68
+ * their vector detail (strokes, arrows, frames) — those keep real containers.
69
+ *
70
+ * Must draw in world space and must not allocate per call beyond the path
71
+ * itself; this runs once per far-capable item on every far-layer rebuild.
72
+ */
73
+ renderFar?: (graphics: Graphics, item: BoardItem, context: BoardRenderContext) => void;
74
+ destroy?: (container: Container, context: BoardRenderContext) => void;
75
+ };
76
+ /**
77
+ * Every registered renderer, for invariants that must hold across all of them —
78
+ * notably that each can draw itself at far LOD, which is what keeps the far
79
+ * layer's z-order correct (see board-scene).
80
+ */
81
+ declare function boardCardRenderersForTest(): readonly BoardCardRenderer[];
82
+ declare function getBoardCardRenderer(item: BoardItem, context: BoardRenderContext): BoardCardRenderer;
83
+ declare function registerBoardCardRenderer(renderer: BoardCardRenderer): void;
84
+ //#endregion
85
+ export { BoardCardRenderer, BoardRenderContext, BoardRenderPalette, boardCardRenderersForTest, getBoardCardRenderer, registerBoardCardRenderer };
@@ -0,0 +1,43 @@
1
+ import { ensureBoardTextMeasurement } from "../text-measurement.js";
2
+ import { arrowCardRenderer } from "./arrow-card-renderer.js";
3
+ import { drawCardRenderer } from "./draw-card-renderer.js";
4
+ import { fileCardRenderer } from "./file-card-renderer.js";
5
+ import { frameCardRenderer } from "./frame-card-renderer.js";
6
+ import { geoCardRenderer } from "./geo-card-renderer.js";
7
+ import { imageCardRenderer } from "./image-card-renderer.js";
8
+ import { noteCardRenderer } from "./note-card-renderer.js";
9
+ import { textCardRenderer } from "./text-card-renderer.js";
10
+ import { unknownCardRenderer } from "./unknown-card-renderer.js";
11
+ import { videoCardRenderer } from "./video-card-renderer.js";
12
+ //#region src/board/render/renderers/board-renderer-registry.ts
13
+ const boardCardRenderers = [
14
+ textCardRenderer,
15
+ noteCardRenderer,
16
+ imageCardRenderer,
17
+ videoCardRenderer,
18
+ fileCardRenderer,
19
+ geoCardRenderer,
20
+ drawCardRenderer,
21
+ arrowCardRenderer,
22
+ frameCardRenderer,
23
+ unknownCardRenderer
24
+ ];
25
+ /**
26
+ * Every registered renderer, for invariants that must hold across all of them —
27
+ * notably that each can draw itself at far LOD, which is what keeps the far
28
+ * layer's z-order correct (see board-scene).
29
+ */
30
+ function boardCardRenderersForTest() {
31
+ return boardCardRenderers;
32
+ }
33
+ function getBoardCardRenderer(item, context) {
34
+ ensureBoardTextMeasurement();
35
+ return boardCardRenderers.find((renderer) => renderer.canRender(item, context)) ?? unknownCardRenderer;
36
+ }
37
+ function registerBoardCardRenderer(renderer) {
38
+ const existingIndex = boardCardRenderers.findIndex((candidate) => candidate.id === renderer.id);
39
+ if (existingIndex >= 0) boardCardRenderers.splice(existingIndex, 1, renderer);
40
+ else boardCardRenderers.unshift(renderer);
41
+ }
42
+ //#endregion
43
+ export { boardCardRenderersForTest, getBoardCardRenderer, registerBoardCardRenderer };
@@ -0,0 +1,5 @@
1
+ import { BoardCardRenderer } from "./board-renderer-registry.js";
2
+ //#region src/board/render/renderers/draw-card-renderer.d.ts
3
+ declare const drawCardRenderer: BoardCardRenderer;
4
+ //#endregion
5
+ export { drawCardRenderer };