@scrawl-board/board 0.1.0-beta.0 → 0.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.d.ts +49 -7
- package/dist/browser.js +250 -99
- package/dist/core.d.ts +96 -25
- package/dist/core.js +63 -23
- package/dist/index.d.ts +118 -30
- package/dist/index.js +335 -111
- package/dist/react.d.ts +95 -7
- package/dist/react.js +326 -110
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
2
2
|
import { createPortal } from "react-dom";
|
|
3
3
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
-
//#region src/core
|
|
4
|
+
//#region src/core/shapes/assets.ts
|
|
5
5
|
var ASSET_REF_PATTERN = /^asset:[a-z0-9](?:[a-z0-9.-]{0,61}[a-z0-9])?:[A-Za-z0-9._~-]+$/;
|
|
6
6
|
function isAssetRef(value) {
|
|
7
7
|
return typeof value === "string" && ASSET_REF_PATTERN.test(value) && new TextEncoder().encode(value).length <= 512;
|
|
@@ -23,12 +23,17 @@ var AssetResolutionError = class extends Error {
|
|
|
23
23
|
var ASSET_CACHE_BYTES_DEFAULT = 256 * 1024 * 1024;
|
|
24
24
|
var ASSET_CACHE_BYTES_MIN = 64 * 1024 * 1024;
|
|
25
25
|
var ASSET_CACHE_BYTES_MAX = 512 * 1024 * 1024;
|
|
26
|
+
var SUPPORTED_ASSET_MEDIA_TYPES = [
|
|
27
|
+
"image/png",
|
|
28
|
+
"image/jpeg",
|
|
29
|
+
"image/webp"
|
|
30
|
+
];
|
|
26
31
|
function clampAssetCacheBytes(value) {
|
|
27
32
|
if (value === void 0 || !Number.isFinite(value)) return ASSET_CACHE_BYTES_DEFAULT;
|
|
28
33
|
return Math.min(ASSET_CACHE_BYTES_MAX, Math.max(ASSET_CACHE_BYTES_MIN, Math.floor(value)));
|
|
29
34
|
}
|
|
30
35
|
//#endregion
|
|
31
|
-
//#region src/core
|
|
36
|
+
//#region src/core/document/identifiers.ts
|
|
32
37
|
function documentId(value) {
|
|
33
38
|
if (!value) throw new TypeError("DocumentId cannot be empty");
|
|
34
39
|
return value;
|
|
@@ -229,7 +234,7 @@ function validation(message, path) {
|
|
|
229
234
|
return new DocumentRecoveryError("DOCUMENT_VALIDATION_FAILED", message, void 0, path);
|
|
230
235
|
}
|
|
231
236
|
//#endregion
|
|
232
|
-
//#region src/core
|
|
237
|
+
//#region src/core/shapes/affine2d.ts
|
|
233
238
|
var IDENTITY = [
|
|
234
239
|
1,
|
|
235
240
|
0,
|
|
@@ -313,7 +318,7 @@ function avgScale(m) {
|
|
|
313
318
|
return (Math.hypot(m[0], m[1]) + Math.hypot(m[2], m[3])) / 2;
|
|
314
319
|
}
|
|
315
320
|
//#endregion
|
|
316
|
-
//#region src/core
|
|
321
|
+
//#region src/core/document/boardSearch.ts
|
|
317
322
|
function hay(s) {
|
|
318
323
|
return s.toLowerCase();
|
|
319
324
|
}
|
|
@@ -378,7 +383,7 @@ function searchBoard(query, board) {
|
|
|
378
383
|
return hits;
|
|
379
384
|
}
|
|
380
385
|
//#endregion
|
|
381
|
-
//#region src/core
|
|
386
|
+
//#region src/core/shapes/types.ts
|
|
382
387
|
/** Erasure level at which a point counts as fully erased. */
|
|
383
388
|
var ERASE_THRESHOLD = .95;
|
|
384
389
|
function cloneStroke(stroke) {
|
|
@@ -445,13 +450,12 @@ function measureTable(table) {
|
|
|
445
450
|
height: table.rowHeights.reduce((sum, h) => sum + h, 0)
|
|
446
451
|
};
|
|
447
452
|
}
|
|
448
|
-
var BOARD_COLOR = "#FFFFFF";
|
|
449
453
|
var FOG_COLOR = "#FFFFFF";
|
|
450
454
|
function cloneImage(img) {
|
|
451
455
|
return { ...img };
|
|
452
456
|
}
|
|
453
457
|
//#endregion
|
|
454
|
-
//#region src/core
|
|
458
|
+
//#region src/core/document/clusterStore.ts
|
|
455
459
|
/** A stroke joins a cluster last written to within this window at full reach. */
|
|
456
460
|
var RECENT_MS = 8e3;
|
|
457
461
|
/** Older clusters are still joinable, at half the gap threshold. */
|
|
@@ -622,7 +626,7 @@ function clamp$3(v, lo, hi) {
|
|
|
622
626
|
return Math.min(hi, Math.max(lo, v));
|
|
623
627
|
}
|
|
624
628
|
//#endregion
|
|
625
|
-
//#region src/core
|
|
629
|
+
//#region src/core/shapes/extensionTypes.ts
|
|
626
630
|
function cloneCustomObject(object) {
|
|
627
631
|
return {
|
|
628
632
|
...object,
|
|
@@ -632,7 +636,7 @@ function cloneCustomObject(object) {
|
|
|
632
636
|
};
|
|
633
637
|
}
|
|
634
638
|
//#endregion
|
|
635
|
-
//#region src/core
|
|
639
|
+
//#region src/core/shapes/kitchenTimer.ts
|
|
636
640
|
var TIMER_DEFAULT_DURATION_MS = 300 * 1e3;
|
|
637
641
|
var TIMER_PRESETS_MS = [
|
|
638
642
|
6e4,
|
|
@@ -688,7 +692,7 @@ function formatTimer(ms) {
|
|
|
688
692
|
return `${Math.floor(total / 60)}:${(total % 60).toString().padStart(2, "0")}`;
|
|
689
693
|
}
|
|
690
694
|
//#endregion
|
|
691
|
-
//#region src/core
|
|
695
|
+
//#region src/core/shapes/itemLock.ts
|
|
692
696
|
/**
|
|
693
697
|
* Apply or clear a lock in place. Unlock always drops the holder so a stale
|
|
694
698
|
* name cannot linger on an unlocked item.
|
|
@@ -725,7 +729,7 @@ function serializeLock(item) {
|
|
|
725
729
|
};
|
|
726
730
|
}
|
|
727
731
|
//#endregion
|
|
728
|
-
//#region src/core
|
|
732
|
+
//#region src/core/document/document.ts
|
|
729
733
|
/**
|
|
730
734
|
* The one place a live Stroke becomes its wire representation — in
|
|
731
735
|
* particular, points collapse from {x,y,pressure,erase?} objects into
|
|
@@ -1284,7 +1288,7 @@ function computeBBox(stroke) {
|
|
|
1284
1288
|
return world;
|
|
1285
1289
|
}
|
|
1286
1290
|
//#endregion
|
|
1287
|
-
//#region src/core
|
|
1291
|
+
//#region src/core/commands/commands.ts
|
|
1288
1292
|
/** One drawing action — a marker stroke, or a shape's strokes as one unit. */
|
|
1289
1293
|
var AddStrokesCommand = class {
|
|
1290
1294
|
constructor(strokes) {
|
|
@@ -1626,7 +1630,7 @@ var LockItemsCommand = class {
|
|
|
1626
1630
|
}
|
|
1627
1631
|
};
|
|
1628
1632
|
//#endregion
|
|
1629
|
-
//#region src/core
|
|
1633
|
+
//#region src/core/history/history.ts
|
|
1630
1634
|
var LIMIT = 200;
|
|
1631
1635
|
var History = class {
|
|
1632
1636
|
constructor(doc) {
|
|
@@ -1687,7 +1691,7 @@ var History = class {
|
|
|
1687
1691
|
}
|
|
1688
1692
|
};
|
|
1689
1693
|
//#endregion
|
|
1690
|
-
//#region src/core
|
|
1694
|
+
//#region src/core/events/ops.ts
|
|
1691
1695
|
var ADDED = [
|
|
1692
1696
|
["added", "strokes"],
|
|
1693
1697
|
["notesAdded", "notes"],
|
|
@@ -1741,7 +1745,7 @@ function changeToOps(change, restoring = false) {
|
|
|
1741
1745
|
return ops;
|
|
1742
1746
|
}
|
|
1743
1747
|
//#endregion
|
|
1744
|
-
//#region src/core
|
|
1748
|
+
//#region src/core/shapes/ribbonEdges.ts
|
|
1745
1749
|
var MIN_WIDTH_FACTOR = .35;
|
|
1746
1750
|
var END_TAPER = .55;
|
|
1747
1751
|
function ribbonEdges(points, baseWidth) {
|
|
@@ -1773,7 +1777,7 @@ function ribbonEdges(points, baseWidth) {
|
|
|
1773
1777
|
return out;
|
|
1774
1778
|
}
|
|
1775
1779
|
//#endregion
|
|
1776
|
-
//#region src/core
|
|
1780
|
+
//#region src/core/document/spatialIndex.ts
|
|
1777
1781
|
var CELL = 8;
|
|
1778
1782
|
var SpatialIndex = class {
|
|
1779
1783
|
constructor(doc) {
|
|
@@ -1846,7 +1850,7 @@ function cellsOf(box) {
|
|
|
1846
1850
|
return keys;
|
|
1847
1851
|
}
|
|
1848
1852
|
//#endregion
|
|
1849
|
-
//#region src/core
|
|
1853
|
+
//#region src/core/shapes/stamps.ts
|
|
1850
1854
|
var STAMPS = [
|
|
1851
1855
|
{
|
|
1852
1856
|
kind: "star",
|
|
@@ -1891,7 +1895,7 @@ function stampDataUrl(kind) {
|
|
|
1891
1895
|
return `data:image/svg+xml;utf8,${encodeURIComponent(SVG[kind])}`;
|
|
1892
1896
|
}
|
|
1893
1897
|
//#endregion
|
|
1894
|
-
//#region src/
|
|
1898
|
+
//#region src/collaboration/presence/presence.ts
|
|
1895
1899
|
/** Keep beacons clear of typical chrome at the top and bottom of the Board. */
|
|
1896
1900
|
var BEACON_INSET = {
|
|
1897
1901
|
top: 72,
|
|
@@ -1927,7 +1931,7 @@ function clamp$2(value, min, max) {
|
|
|
1927
1931
|
return Math.min(max, Math.max(min, value));
|
|
1928
1932
|
}
|
|
1929
1933
|
//#endregion
|
|
1930
|
-
//#region src/
|
|
1934
|
+
//#region src/persistence/serialization/svg.ts
|
|
1931
1935
|
/** Matches the key light used by the board shader and note shadows. */
|
|
1932
1936
|
var LIGHT = {
|
|
1933
1937
|
x: -.25,
|
|
@@ -1937,12 +1941,19 @@ var LIGHT = {
|
|
|
1937
1941
|
var MARGIN = 4;
|
|
1938
1942
|
var NOTE_FONT_RATIO = 44 / 512;
|
|
1939
1943
|
var NOTE_PAD_RATIO = 40 / 512;
|
|
1944
|
+
/** Matches the theme system's light-preset `boardSurface` default (theme.ts) — kept in sync manually, since core-internal stays decoupled from the theme layer. */
|
|
1945
|
+
var DEFAULT_BACKGROUND_COLOR = "#f5f5f3";
|
|
1940
1946
|
/**
|
|
1941
1947
|
* `registry` is optional and only enables rendering Custom objects through
|
|
1942
1948
|
* their own `describe()` — without it (or for an object whose extension
|
|
1943
1949
|
* isn't in it), Custom objects still export via the standard fallback
|
|
1944
1950
|
* placeholder (`fallback.bounds`/`label`), never silently dropped.
|
|
1945
1951
|
*
|
|
1952
|
+
* `backgroundColor` should be the Host's actual resolved `boardTheme.surface`
|
|
1953
|
+
* so an export matches what was on screen; defaults to the theme system's
|
|
1954
|
+
* own light-preset default when the caller doesn't have one on hand. The
|
|
1955
|
+
* board's reference grid, if any, is a screen-only aid and never exported.
|
|
1956
|
+
*
|
|
1946
1957
|
* `resolvedAssets` (ticket #23) maps an Asset reference to an already-
|
|
1947
1958
|
* resolved `data:` URI — see `assetExport.ts`'s `exportDocumentSVGWithAssets`,
|
|
1948
1959
|
* which is the only intended caller that ever passes one. Without it, every
|
|
@@ -1950,7 +1961,7 @@ var NOTE_PAD_RATIO = 40 / 512;
|
|
|
1950
1961
|
* placeholder instead of guessing at a URL; a legacy `src`-backed image is
|
|
1951
1962
|
* unaffected either way.
|
|
1952
1963
|
*/
|
|
1953
|
-
function documentToSVG(doc, now = 0, registry, resolvedAssets) {
|
|
1964
|
+
function documentToSVG(doc, now = 0, registry, backgroundColor = DEFAULT_BACKGROUND_COLOR, resolvedAssets) {
|
|
1954
1965
|
const notes = doc.notes ?? [];
|
|
1955
1966
|
const texts = doc.textBlocks ?? [];
|
|
1956
1967
|
const tables = doc.tables ?? [];
|
|
@@ -1963,7 +1974,7 @@ function documentToSVG(doc, now = 0, registry, resolvedAssets) {
|
|
|
1963
1974
|
const highlights = doc.strokes.filter((s) => s.tool === "highlighter");
|
|
1964
1975
|
const ink = doc.strokes.filter((s) => s.tool !== "highlighter");
|
|
1965
1976
|
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${view}">\n<defs>\n${defs}\n</defs>\n${[
|
|
1966
|
-
`<rect x="${fmt(bounds.minX)}" y="${fmt(bounds.minY)}" width="${fmt(bounds.width)}" height="${fmt(bounds.height)}" fill="${
|
|
1977
|
+
`<rect x="${fmt(bounds.minX)}" y="${fmt(bounds.minY)}" width="${fmt(bounds.width)}" height="${fmt(bounds.height)}" fill="${backgroundColor}"/>`,
|
|
1967
1978
|
...images.map((image) => imageToElement(image, resolvedAssets)),
|
|
1968
1979
|
...tables.map(tableToGroup),
|
|
1969
1980
|
...highlights.flatMap(strokeToPaths),
|
|
@@ -2287,7 +2298,7 @@ function fmt(n) {
|
|
|
2287
2298
|
return String(Math.round(n * 100) / 100);
|
|
2288
2299
|
}
|
|
2289
2300
|
//#endregion
|
|
2290
|
-
//#region src/core
|
|
2301
|
+
//#region src/core/shapes/sceneGeometry.ts
|
|
2291
2302
|
var EMPTY_BOUNDS = {
|
|
2292
2303
|
x: 0,
|
|
2293
2304
|
y: 0,
|
|
@@ -2351,7 +2362,7 @@ function textCorners(x, y, text, fontSize, align, m) {
|
|
|
2351
2362
|
return rectCorners(x + (align === "center" ? -width / 2 : align === "end" ? -width : 0), y, width, height, m);
|
|
2352
2363
|
}
|
|
2353
2364
|
//#endregion
|
|
2354
|
-
//#region src/core
|
|
2365
|
+
//#region src/core/shapes/customObjects.ts
|
|
2355
2366
|
var FALLBACK_LABEL_MAX_LENGTH = 80;
|
|
2356
2367
|
function toReadonly(object) {
|
|
2357
2368
|
return object;
|
|
@@ -2480,7 +2491,7 @@ function extensionIdFromType(type) {
|
|
|
2480
2491
|
return slash === -1 ? type : type.slice(0, slash);
|
|
2481
2492
|
}
|
|
2482
2493
|
//#endregion
|
|
2483
|
-
//#region src/core
|
|
2494
|
+
//#region src/core/shapes/extensionRegistry.ts
|
|
2484
2495
|
function buildExtensionRegistry(extensions) {
|
|
2485
2496
|
const list = extensions ?? [];
|
|
2486
2497
|
const diagnostics = [];
|
|
@@ -2577,7 +2588,7 @@ function isWellFormedNamespacedId(id) {
|
|
|
2577
2588
|
return isWellFormedId(id) && id.includes("/") && !id.startsWith("/") && !id.endsWith("/");
|
|
2578
2589
|
}
|
|
2579
2590
|
//#endregion
|
|
2580
|
-
//#region src/
|
|
2591
|
+
//#region src/persistence/adapters/assetValidation.ts
|
|
2581
2592
|
function sniffImageMediaType(bytes) {
|
|
2582
2593
|
if (bytes.length >= 8 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71 && bytes[4] === 13 && bytes[5] === 10 && bytes[6] === 26 && bytes[7] === 10) return "image/png";
|
|
2583
2594
|
if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) return "image/jpeg";
|
|
@@ -2664,7 +2675,7 @@ function validateDecodedDimensions(width, height) {
|
|
|
2664
2675
|
};
|
|
2665
2676
|
}
|
|
2666
2677
|
//#endregion
|
|
2667
|
-
//#region src/assetController.ts
|
|
2678
|
+
//#region src/persistence/adapters/assetController.ts
|
|
2668
2679
|
var FAILURE_COALESCE_MS = 4e3;
|
|
2669
2680
|
var AssetController = class {
|
|
2670
2681
|
constructor(resolver, options) {
|
|
@@ -2843,7 +2854,7 @@ function toAssetResolutionError(cause, ref) {
|
|
|
2843
2854
|
return new AssetResolutionError("unknown", true, cause instanceof Error ? cause.message : String(cause), ref);
|
|
2844
2855
|
}
|
|
2845
2856
|
//#endregion
|
|
2846
|
-
//#region src/
|
|
2857
|
+
//#region src/persistence/serialization/assetRefCollector.ts
|
|
2847
2858
|
/** Every unique Asset reference in the document, and which object(s) use it. */
|
|
2848
2859
|
function collectDocumentAssetRefs(doc, registry) {
|
|
2849
2860
|
const refs = /* @__PURE__ */ new Map();
|
|
@@ -2870,7 +2881,7 @@ function collectSceneAssetRefs(node, objectId, add) {
|
|
|
2870
2881
|
if (node.kind === "group") for (const child of node.children) collectSceneAssetRefs(child, objectId, add);
|
|
2871
2882
|
}
|
|
2872
2883
|
//#endregion
|
|
2873
|
-
//#region src/assetExport.ts
|
|
2884
|
+
//#region src/persistence/serialization/assetExport.ts
|
|
2874
2885
|
/** Strict mode's rejection — never contains credentials, a fetchable location, or a raw resolver message. */
|
|
2875
2886
|
var SvgAssetExportError = class extends Error {
|
|
2876
2887
|
constructor(missingAssets) {
|
|
@@ -2879,7 +2890,7 @@ var SvgAssetExportError = class extends Error {
|
|
|
2879
2890
|
this.name = "SvgAssetExportError";
|
|
2880
2891
|
}
|
|
2881
2892
|
};
|
|
2882
|
-
async function exportDocumentSVGWithAssets(doc, now, registry, assetController, options) {
|
|
2893
|
+
async function exportDocumentSVGWithAssets(doc, now, registry, assetController, backgroundColor, options) {
|
|
2883
2894
|
const refs = collectDocumentAssetRefs(doc, registry);
|
|
2884
2895
|
const resolvedAssets = /* @__PURE__ */ new Map();
|
|
2885
2896
|
const missingAssets = [];
|
|
@@ -2915,7 +2926,7 @@ async function exportDocumentSVGWithAssets(doc, now, registry, assetController,
|
|
|
2915
2926
|
}
|
|
2916
2927
|
if (missingAssets.length > 0 && options?.missingAssets !== "placeholder") throw new SvgAssetExportError(missingAssets);
|
|
2917
2928
|
return {
|
|
2918
|
-
svg: documentToSVG(doc, now, registry, resolvedAssets),
|
|
2929
|
+
svg: documentToSVG(doc, now, registry, backgroundColor, resolvedAssets),
|
|
2919
2930
|
missingAssets
|
|
2920
2931
|
};
|
|
2921
2932
|
}
|
|
@@ -2926,7 +2937,7 @@ function toDataUri(bytes, mediaType) {
|
|
|
2926
2937
|
return `data:${mediaType};base64,${btoa(binary)}`;
|
|
2927
2938
|
}
|
|
2928
2939
|
//#endregion
|
|
2929
|
-
//#region src/assetIngestion.ts
|
|
2940
|
+
//#region src/persistence/adapters/assetIngestion.ts
|
|
2930
2941
|
async function decodeDimensionsWithImageBitmap(bytes, mediaType) {
|
|
2931
2942
|
const blob = new Blob([bytes], { type: mediaType });
|
|
2932
2943
|
let bitmap;
|
|
@@ -35572,7 +35583,7 @@ var WebGLRenderer = class {
|
|
|
35572
35583
|
}
|
|
35573
35584
|
};
|
|
35574
35585
|
//#endregion
|
|
35575
|
-
//#region
|
|
35586
|
+
//#region src/core/events/auditEvents.ts
|
|
35576
35587
|
var BY_LABEL = {
|
|
35577
35588
|
draw: {
|
|
35578
35589
|
action: "create",
|
|
@@ -35692,7 +35703,7 @@ function lowerFirst(s) {
|
|
|
35692
35703
|
return s.charAt(0).toLowerCase() + s.slice(1);
|
|
35693
35704
|
}
|
|
35694
35705
|
//#endregion
|
|
35695
|
-
//#region
|
|
35706
|
+
//#region src/renderer/shapes/AssetTextureCache.ts
|
|
35696
35707
|
var AssetTextureCache = class {
|
|
35697
35708
|
constructor(assetController) {
|
|
35698
35709
|
this.assetController = assetController;
|
|
@@ -35783,7 +35794,7 @@ function toDecodeError(cause, ref) {
|
|
|
35783
35794
|
return new AssetResolutionError("decode-failed", false, cause instanceof Error ? cause.message : String(cause), ref);
|
|
35784
35795
|
}
|
|
35785
35796
|
//#endregion
|
|
35786
|
-
//#region
|
|
35797
|
+
//#region src/renderer/canvas/raycast.ts
|
|
35787
35798
|
var origin$1 = new Vector3();
|
|
35788
35799
|
var target = new Vector3();
|
|
35789
35800
|
function pointerToBoard(clientX, clientY, canvas, camera) {
|
|
@@ -35814,7 +35825,7 @@ function pointerToPlane(clientX, clientY, canvas, camera, z) {
|
|
|
35814
35825
|
};
|
|
35815
35826
|
}
|
|
35816
35827
|
//#endregion
|
|
35817
|
-
//#region
|
|
35828
|
+
//#region src/renderer/canvas/fog.ts
|
|
35818
35829
|
function createFogUniforms(color) {
|
|
35819
35830
|
return {
|
|
35820
35831
|
uFogColor: { value: new Color(color) },
|
|
@@ -35835,7 +35846,28 @@ var FOG_GLSL = `
|
|
|
35835
35846
|
}
|
|
35836
35847
|
`;
|
|
35837
35848
|
//#endregion
|
|
35838
|
-
//#region
|
|
35849
|
+
//#region src/renderer/canvas/boardSurface.ts
|
|
35850
|
+
var GRID_MODE_CODE = {
|
|
35851
|
+
none: 0,
|
|
35852
|
+
line: 1,
|
|
35853
|
+
dot: 2
|
|
35854
|
+
};
|
|
35855
|
+
var TEXTURE_CODE = {
|
|
35856
|
+
flat: 0,
|
|
35857
|
+
textured: 1
|
|
35858
|
+
};
|
|
35859
|
+
/** Used when a caller doesn't supply one (e.g. ScrawlEngine constructed without a Host theme). */
|
|
35860
|
+
var DEFAULT_BOARD_SURFACE_THEME = {
|
|
35861
|
+
color: "#f5f5f3",
|
|
35862
|
+
gridMode: "none",
|
|
35863
|
+
gridColor: "#deded8",
|
|
35864
|
+
gridSpacing: 5,
|
|
35865
|
+
gridLineWidth: 1,
|
|
35866
|
+
surfaceTexture: "flat"
|
|
35867
|
+
};
|
|
35868
|
+
/** Grid alpha fades out below this on-screen spacing (px) — otherwise it aliases into a solid wash when zoomed out. */
|
|
35869
|
+
var GRID_FADE_MIN_PX = 3;
|
|
35870
|
+
var GRID_FADE_MAX_PX = 8;
|
|
35839
35871
|
var VERTEX$1 = `
|
|
35840
35872
|
varying vec3 vWorldPos;
|
|
35841
35873
|
void main() {
|
|
@@ -35849,6 +35881,13 @@ var FRAGMENT = `
|
|
|
35849
35881
|
uniform vec3 uFogColor;
|
|
35850
35882
|
uniform float uFogNear;
|
|
35851
35883
|
uniform float uFogFar;
|
|
35884
|
+
uniform float uGridMode;
|
|
35885
|
+
uniform vec3 uGridColor;
|
|
35886
|
+
uniform float uGridSpacing;
|
|
35887
|
+
uniform float uWorldPerPixel;
|
|
35888
|
+
uniform float uGridLineWidthPx;
|
|
35889
|
+
uniform float uGridFade;
|
|
35890
|
+
uniform float uSurfaceTexture;
|
|
35852
35891
|
varying vec3 vWorldPos;
|
|
35853
35892
|
|
|
35854
35893
|
float hash(vec2 p) {
|
|
@@ -35867,33 +35906,69 @@ var FRAGMENT = `
|
|
|
35867
35906
|
|
|
35868
35907
|
${FOG_GLSL}
|
|
35869
35908
|
|
|
35909
|
+
// Distance from p's nearest axis-aligned grid line, in world units.
|
|
35910
|
+
// A crisp, ~uGridLineWidthPx-wide line: full alpha to its half-width, a
|
|
35911
|
+
// ~1px anti-aliased falloff beyond that — not a wide, soft-edged band.
|
|
35912
|
+
float gridLineAlpha(vec2 p) {
|
|
35913
|
+
vec2 cell = mod(p, uGridSpacing);
|
|
35914
|
+
vec2 distToLine = min(cell, uGridSpacing - cell);
|
|
35915
|
+
float halfWidth = 0.5 * uGridLineWidthPx * uWorldPerPixel;
|
|
35916
|
+
float aa = uWorldPerPixel;
|
|
35917
|
+
vec2 lineAlpha2 = 1.0 - smoothstep(halfWidth - aa * 0.5, halfWidth + aa * 0.5, distToLine);
|
|
35918
|
+
return max(lineAlpha2.x, lineAlpha2.y);
|
|
35919
|
+
}
|
|
35920
|
+
|
|
35921
|
+
// Distance from p's nearest grid intersection, in world units. Dot radius
|
|
35922
|
+
// matches the configured line width in pixels, same anti-aliasing.
|
|
35923
|
+
float gridDotAlpha(vec2 p) {
|
|
35924
|
+
vec2 cell = mod(p, uGridSpacing) - uGridSpacing * 0.5;
|
|
35925
|
+
float dist = length(cell);
|
|
35926
|
+
float radius = uGridLineWidthPx * uWorldPerPixel;
|
|
35927
|
+
float aa = uWorldPerPixel;
|
|
35928
|
+
return 1.0 - smoothstep(radius - aa * 0.5, radius + aa * 0.5, dist);
|
|
35929
|
+
}
|
|
35930
|
+
|
|
35870
35931
|
void main() {
|
|
35871
35932
|
vec3 col = uColor;
|
|
35872
35933
|
|
|
35873
|
-
|
|
35874
|
-
|
|
35875
|
-
|
|
35934
|
+
if (uSurfaceTexture > 0.5) {
|
|
35935
|
+
// Melamine micro-texture: two octaves of value noise, +-1.75% brightness.
|
|
35936
|
+
float n = vnoise(vWorldPos.xy * 2.3) * 0.6 + vnoise(vWorldPos.xy * 9.7) * 0.4;
|
|
35937
|
+
col *= 1.0 + (n - 0.5) * 0.035;
|
|
35876
35938
|
|
|
35877
|
-
|
|
35878
|
-
|
|
35879
|
-
|
|
35880
|
-
|
|
35881
|
-
|
|
35882
|
-
|
|
35883
|
-
|
|
35884
|
-
|
|
35885
|
-
|
|
35939
|
+
// Satin sheen: Fresnel rim + a specular band from the key light. Both
|
|
35940
|
+
// are ~zero in the straight-on working view and bloom as the camera tilts.
|
|
35941
|
+
vec3 V = normalize(cameraPosition - vWorldPos);
|
|
35942
|
+
vec3 N = vec3(0.0, 0.0, 1.0);
|
|
35943
|
+
float fres = pow(1.0 - max(dot(N, V), 0.0), 3.0);
|
|
35944
|
+
vec3 L = normalize(vec3(-0.25, 0.4, 0.88));
|
|
35945
|
+
vec3 H = normalize(L + V);
|
|
35946
|
+
float spec = pow(max(dot(N, H), 0.0), 90.0);
|
|
35947
|
+
col += (fres * 0.18 + spec * 0.06) * vec3(1.0);
|
|
35948
|
+
}
|
|
35949
|
+
|
|
35950
|
+
if (uGridMode > 0.5 && uGridFade > 0.001) {
|
|
35951
|
+
float gridAlpha = (uGridMode < 1.5 ? gridLineAlpha(vWorldPos.xy) : gridDotAlpha(vWorldPos.xy)) * uGridFade;
|
|
35952
|
+
col = mix(col, uGridColor, gridAlpha);
|
|
35953
|
+
}
|
|
35886
35954
|
|
|
35887
35955
|
col = applyBoardFog(col, vWorldPos);
|
|
35888
35956
|
gl_FragColor = vec4(col, 1.0);
|
|
35889
35957
|
}
|
|
35890
35958
|
`;
|
|
35891
|
-
function createBoardSurface(fog) {
|
|
35959
|
+
function createBoardSurface(fog, theme) {
|
|
35892
35960
|
const material = new ShaderMaterial({
|
|
35893
35961
|
vertexShader: VERTEX$1,
|
|
35894
35962
|
fragmentShader: FRAGMENT,
|
|
35895
35963
|
uniforms: {
|
|
35896
|
-
uColor: { value: new Color(
|
|
35964
|
+
uColor: { value: new Color(theme.color) },
|
|
35965
|
+
uGridMode: { value: GRID_MODE_CODE[theme.gridMode] },
|
|
35966
|
+
uGridColor: { value: new Color(theme.gridColor) },
|
|
35967
|
+
uGridSpacing: { value: Math.max(.001, theme.gridSpacing) },
|
|
35968
|
+
uGridLineWidthPx: { value: Math.max(.1, theme.gridLineWidth) },
|
|
35969
|
+
uWorldPerPixel: { value: .05 },
|
|
35970
|
+
uGridFade: { value: 0 },
|
|
35971
|
+
uSurfaceTexture: { value: TEXTURE_CODE[theme.surfaceTexture] },
|
|
35897
35972
|
...fog
|
|
35898
35973
|
}
|
|
35899
35974
|
});
|
|
@@ -35901,11 +35976,34 @@ function createBoardSurface(fog) {
|
|
|
35901
35976
|
mesh.name = "board-surface";
|
|
35902
35977
|
return mesh;
|
|
35903
35978
|
}
|
|
35904
|
-
/**
|
|
35905
|
-
function
|
|
35979
|
+
/** Applies a theme change (initial or live) — everything except the per-frame fade/pixel-ratio. */
|
|
35980
|
+
function setBoardSurfaceTheme(mesh, theme) {
|
|
35981
|
+
const uniforms = mesh.material.uniforms;
|
|
35982
|
+
uniforms.uColor.value.set(theme.color);
|
|
35983
|
+
uniforms.uGridMode.value = GRID_MODE_CODE[theme.gridMode];
|
|
35984
|
+
uniforms.uGridColor.value.set(theme.gridColor);
|
|
35985
|
+
uniforms.uGridSpacing.value = Math.max(.001, theme.gridSpacing);
|
|
35986
|
+
uniforms.uGridLineWidthPx.value = Math.max(.1, theme.gridLineWidth);
|
|
35987
|
+
uniforms.uSurfaceTexture.value = TEXTURE_CODE[theme.surfaceTexture];
|
|
35988
|
+
}
|
|
35989
|
+
/** Keep the plane centered under the view, larger than the fog horizon, and the grid's on-screen weight/fade current. */
|
|
35990
|
+
function updateBoardSurface(mesh, centerX, centerY, fogFar, worldPerPixel) {
|
|
35906
35991
|
mesh.position.set(centerX, centerY, 0);
|
|
35907
35992
|
const size = fogFar * 2.5;
|
|
35908
35993
|
mesh.scale.set(size, size, 1);
|
|
35994
|
+
const uniforms = mesh.material.uniforms;
|
|
35995
|
+
uniforms.uWorldPerPixel.value = worldPerPixel;
|
|
35996
|
+
const t = (uniforms.uGridSpacing.value / Math.max(1e-6, worldPerPixel) - GRID_FADE_MIN_PX) / (GRID_FADE_MAX_PX - GRID_FADE_MIN_PX);
|
|
35997
|
+
uniforms.uGridFade.value = MathUtils.clamp(t, 0, 1);
|
|
35998
|
+
}
|
|
35999
|
+
/** Temporarily zeroes the grid's contribution (for export snapshots) and returns a restore function. */
|
|
36000
|
+
function suppressBoardSurfaceGrid(mesh) {
|
|
36001
|
+
const uniforms = mesh.material.uniforms;
|
|
36002
|
+
const previous = uniforms.uGridFade.value;
|
|
36003
|
+
uniforms.uGridFade.value = 0;
|
|
36004
|
+
return () => {
|
|
36005
|
+
uniforms.uGridFade.value = previous;
|
|
36006
|
+
};
|
|
35909
36007
|
}
|
|
35910
36008
|
var MIN_HEIGHT = 40;
|
|
35911
36009
|
var MAX_HEIGHT = 1500;
|
|
@@ -36067,9 +36165,9 @@ var CameraRig = class {
|
|
|
36067
36165
|
}
|
|
36068
36166
|
};
|
|
36069
36167
|
//#endregion
|
|
36070
|
-
//#region
|
|
36168
|
+
//#region src/renderer/canvas/scene.ts
|
|
36071
36169
|
var SceneRig = class {
|
|
36072
|
-
constructor(canvas) {
|
|
36170
|
+
constructor(canvas, boardTheme) {
|
|
36073
36171
|
this.renderer = new WebGLRenderer({
|
|
36074
36172
|
canvas,
|
|
36075
36173
|
antialias: true
|
|
@@ -36079,7 +36177,7 @@ var SceneRig = class {
|
|
|
36079
36177
|
this.scene = new Scene();
|
|
36080
36178
|
this.cameraRig = new CameraRig(canvas.clientWidth / Math.max(1, canvas.clientHeight));
|
|
36081
36179
|
this.fog = createFogUniforms(FOG_COLOR);
|
|
36082
|
-
this.board = createBoardSurface(this.fog);
|
|
36180
|
+
this.board = createBoardSurface(this.fog, boardTheme);
|
|
36083
36181
|
this.scene.add(this.board);
|
|
36084
36182
|
this.inkGroup = new Group();
|
|
36085
36183
|
this.inkGroup.name = "ink";
|
|
@@ -36096,9 +36194,17 @@ var SceneRig = class {
|
|
|
36096
36194
|
renderFrame(dtMs) {
|
|
36097
36195
|
this.cameraRig.update(dtMs);
|
|
36098
36196
|
updateFogForCamera(this.fog, this.cameraRig.height);
|
|
36099
|
-
updateBoardSurface(this.board, this.cameraRig.center.x, this.cameraRig.center.y, this.fog.uFogFar.value);
|
|
36197
|
+
updateBoardSurface(this.board, this.cameraRig.center.x, this.cameraRig.center.y, this.fog.uFogFar.value, this.cameraRig.worldPerPixel());
|
|
36100
36198
|
this.renderer.render(this.scene, this.cameraRig.camera);
|
|
36101
36199
|
}
|
|
36200
|
+
/** Live theme update — the board controller's identity stays fixed across theme changes; this is how a new one reaches the render engine. */
|
|
36201
|
+
applyBoardTheme(theme) {
|
|
36202
|
+
setBoardSurfaceTheme(this.board, theme);
|
|
36203
|
+
}
|
|
36204
|
+
/** Zeroes the grid for one render pass (PNG export never bakes it in) and returns a restore function. */
|
|
36205
|
+
suppressGrid() {
|
|
36206
|
+
return suppressBoardSurfaceGrid(this.board);
|
|
36207
|
+
}
|
|
36102
36208
|
dispose() {
|
|
36103
36209
|
this.board.geometry.dispose();
|
|
36104
36210
|
this.board.material.dispose();
|
|
@@ -36106,7 +36212,7 @@ var SceneRig = class {
|
|
|
36106
36212
|
}
|
|
36107
36213
|
};
|
|
36108
36214
|
//#endregion
|
|
36109
|
-
//#region
|
|
36215
|
+
//#region src/renderer/shapes/inkMaterial.ts
|
|
36110
36216
|
var VERTEX = `
|
|
36111
36217
|
attribute float aAlpha;
|
|
36112
36218
|
varying vec2 vUv;
|
|
@@ -36237,7 +36343,7 @@ var InkMaterials = class {
|
|
|
36237
36343
|
}
|
|
36238
36344
|
};
|
|
36239
36345
|
//#endregion
|
|
36240
|
-
//#region
|
|
36346
|
+
//#region src/renderer/shapes/ribbonGeometry.ts
|
|
36241
36347
|
/** Ink floats a hair above the board to avoid z-fighting with the surface. */
|
|
36242
36348
|
var INK_Z = .02;
|
|
36243
36349
|
/** Highlighter always renders under opaque ink (build prompt §4.1). */
|
|
@@ -36288,7 +36394,7 @@ function buildRibbonGeometry(points, baseWidth, z = INK_Z) {
|
|
|
36288
36394
|
return geometry;
|
|
36289
36395
|
}
|
|
36290
36396
|
//#endregion
|
|
36291
|
-
//#region
|
|
36397
|
+
//#region src/renderer/shapes/strokeRenderer.ts
|
|
36292
36398
|
var strokeZ = (stroke) => stroke.tool === "highlighter" ? HIGHLIGHT_Z : INK_Z;
|
|
36293
36399
|
/**
|
|
36294
36400
|
* Derives ink meshes from the document by subscription — the document never
|
|
@@ -36421,7 +36527,7 @@ function syncMatrix(mesh, stroke) {
|
|
|
36421
36527
|
mesh.matrixWorldNeedsUpdate = true;
|
|
36422
36528
|
}
|
|
36423
36529
|
//#endregion
|
|
36424
|
-
//#region
|
|
36530
|
+
//#region src/renderer/shapes/markerProp.ts
|
|
36425
36531
|
var BODY_LENGTH = 11;
|
|
36426
36532
|
var BODY_RADIUS = .85;
|
|
36427
36533
|
var TIP_LENGTH = 1.6;
|
|
@@ -36517,7 +36623,7 @@ var MarkerProp = class {
|
|
|
36517
36623
|
}
|
|
36518
36624
|
};
|
|
36519
36625
|
//#endregion
|
|
36520
|
-
//#region
|
|
36626
|
+
//#region src/renderer/shapes/noteGeometry.ts
|
|
36521
36627
|
/**
|
|
36522
36628
|
* Height of the sheet above the board at (u, v) ∈ [0,1]².
|
|
36523
36629
|
* v = 1 is the adhesive edge (always 0); u = 1 is the peel corner side.
|
|
@@ -36561,7 +36667,7 @@ function applyCurl(geometry, curl, peel) {
|
|
|
36561
36667
|
color.needsUpdate = true;
|
|
36562
36668
|
}
|
|
36563
36669
|
//#endregion
|
|
36564
|
-
//#region
|
|
36670
|
+
//#region src/renderer/shapes/stickyNotes.ts
|
|
36565
36671
|
var TEXTURE_SIZE = 512;
|
|
36566
36672
|
var FOCUS_COLOR$4 = 2450411;
|
|
36567
36673
|
var CURL = .3;
|
|
@@ -43137,7 +43243,7 @@ SYNCABLE_PROPS.forEach((prop) => {
|
|
|
43137
43243
|
new Box3();
|
|
43138
43244
|
new Color();
|
|
43139
43245
|
//#endregion
|
|
43140
|
-
//#region
|
|
43246
|
+
//#region src/renderer/shapes/tables.ts
|
|
43141
43247
|
var FONT_URL$2 = "/fonts/inter-medium.woff";
|
|
43142
43248
|
var TABLE_Z = .012;
|
|
43143
43249
|
var HEADER_Z = .014;
|
|
@@ -43486,7 +43592,7 @@ var TablesRenderer = class {
|
|
|
43486
43592
|
}
|
|
43487
43593
|
};
|
|
43488
43594
|
//#endregion
|
|
43489
|
-
//#region
|
|
43595
|
+
//#region src/renderer/text/textBlocks.ts
|
|
43490
43596
|
var FONT_URL$1 = "/fonts/inter-medium.woff";
|
|
43491
43597
|
var TEXT_Z = .02;
|
|
43492
43598
|
var FOCUS_COLOR$2 = 2450411;
|
|
@@ -43590,7 +43696,7 @@ var TextBlocksRenderer = class {
|
|
|
43590
43696
|
}
|
|
43591
43697
|
};
|
|
43592
43698
|
//#endregion
|
|
43593
|
-
//#region
|
|
43699
|
+
//#region src/renderer/shapes/comments.ts
|
|
43594
43700
|
var PIN_Z = .04;
|
|
43595
43701
|
var PIN_WIDTH = 3.6;
|
|
43596
43702
|
var PIN_HEIGHT = 3.6;
|
|
@@ -43758,7 +43864,7 @@ function drawBubblePath(ctx, x, y, w, h, r, tailX, tailY, tailW) {
|
|
|
43758
43864
|
ctx.closePath();
|
|
43759
43865
|
}
|
|
43760
43866
|
//#endregion
|
|
43761
|
-
//#region
|
|
43867
|
+
//#region src/renderer/shapes/images.ts
|
|
43762
43868
|
var IMAGE_Z = .015;
|
|
43763
43869
|
var FRAME_BORDER = .4;
|
|
43764
43870
|
var FOCUS_COLOR$1 = 2450411;
|
|
@@ -43968,7 +44074,7 @@ function applyPlaceholderTexture(visual, label) {
|
|
|
43968
44074
|
visual.imageMesh.material.needsUpdate = true;
|
|
43969
44075
|
}
|
|
43970
44076
|
//#endregion
|
|
43971
|
-
//#region
|
|
44077
|
+
//#region src/renderer/shapes/kitchenTimers.ts
|
|
43972
44078
|
var FACE_SIZE = 256;
|
|
43973
44079
|
var BODY_COLOR = 14753096;
|
|
43974
44080
|
var KNOB_COLOR = 16448250;
|
|
@@ -44166,7 +44272,7 @@ function renderTimerFace(timer, canvas, now = Date.now()) {
|
|
|
44166
44272
|
return c;
|
|
44167
44273
|
}
|
|
44168
44274
|
//#endregion
|
|
44169
|
-
//#region
|
|
44275
|
+
//#region src/renderer/shapes/customObjects.ts
|
|
44170
44276
|
var FONT_URL = "/fonts/inter-medium.woff";
|
|
44171
44277
|
var CUSTOM_Z = .02;
|
|
44172
44278
|
var FOCUS_COLOR = 2450411;
|
|
@@ -44528,7 +44634,7 @@ function disposeObject3D(obj) {
|
|
|
44528
44634
|
});
|
|
44529
44635
|
}
|
|
44530
44636
|
//#endregion
|
|
44531
|
-
//#region
|
|
44637
|
+
//#region src/interaction/pointer/hitTest.ts
|
|
44532
44638
|
/** Topmost (most recently added) stroke under the point, or null. */
|
|
44533
44639
|
function hitStroke(doc, index, p, slop) {
|
|
44534
44640
|
const candidates = index.query(p.x - slop, p.y - slop, p.x + slop, p.y + slop);
|
|
@@ -44569,7 +44675,7 @@ function distToSegmentSq(p, a, b) {
|
|
|
44569
44675
|
return dx * dx + dy * dy;
|
|
44570
44676
|
}
|
|
44571
44677
|
//#endregion
|
|
44572
|
-
//#region
|
|
44678
|
+
//#region src/interaction/tools/eraserTool.ts
|
|
44573
44679
|
var DECAY_PER_PASS = .4;
|
|
44574
44680
|
/** A point can take another decay pass after this long — rubbing works. */
|
|
44575
44681
|
var REARM_MS = 250;
|
|
@@ -44697,7 +44803,7 @@ function partitionByErasure(points) {
|
|
|
44697
44803
|
return runs;
|
|
44698
44804
|
}
|
|
44699
44805
|
//#endregion
|
|
44700
|
-
//#region
|
|
44806
|
+
//#region src/interaction/tools/noteDrag.ts
|
|
44701
44807
|
/**
|
|
44702
44808
|
* Drag the focused note in X/Y. The grab is resolved on the note's own
|
|
44703
44809
|
* z-plane, not the board, so the note doesn't jump under a tilted ray.
|
|
@@ -44764,7 +44870,7 @@ var NoteDragState = class {
|
|
|
44764
44870
|
}
|
|
44765
44871
|
};
|
|
44766
44872
|
//#endregion
|
|
44767
|
-
//#region
|
|
44873
|
+
//#region src/interaction/tools/imageDrag.ts
|
|
44768
44874
|
/** Drag the focused image in X/Y; one command per drag. */
|
|
44769
44875
|
var ImageDragState = class {
|
|
44770
44876
|
constructor(ctx) {
|
|
@@ -44816,7 +44922,7 @@ var ImageDragState = class {
|
|
|
44816
44922
|
}
|
|
44817
44923
|
};
|
|
44818
44924
|
//#endregion
|
|
44819
|
-
//#region
|
|
44925
|
+
//#region src/interaction/tools/timerDrag.ts
|
|
44820
44926
|
/** Drag the focused timer in X/Y; one command per drag. */
|
|
44821
44927
|
var TimerDragState = class {
|
|
44822
44928
|
constructor(ctx) {
|
|
@@ -44868,7 +44974,7 @@ var TimerDragState = class {
|
|
|
44868
44974
|
}
|
|
44869
44975
|
};
|
|
44870
44976
|
//#endregion
|
|
44871
|
-
//#region
|
|
44977
|
+
//#region src/interaction/tools/shapeGeometry.ts
|
|
44872
44978
|
/** Uniform synthetic pressure; the ink shader supplies the hand-drawn feel. */
|
|
44873
44979
|
var PRESSURE = .7;
|
|
44874
44980
|
var MIN_ELLIPSE_SEGMENTS = 24;
|
|
@@ -45057,7 +45163,7 @@ function snappedEnd(a, b) {
|
|
|
45057
45163
|
};
|
|
45058
45164
|
}
|
|
45059
45165
|
//#endregion
|
|
45060
|
-
//#region
|
|
45166
|
+
//#region src/interaction/tools/shapeTool.ts
|
|
45061
45167
|
var MIN_DRAG_PX$1 = 4;
|
|
45062
45168
|
/** Drag out a shape; live preview through the real ink material. */
|
|
45063
45169
|
var ShapeTool = class {
|
|
@@ -45088,7 +45194,7 @@ var ShapeTool = class {
|
|
|
45088
45194
|
const strokes = this.polylines.map((points) => ({
|
|
45089
45195
|
id: crypto.randomUUID(),
|
|
45090
45196
|
color: this.ctx.inkColor(),
|
|
45091
|
-
baseWidth: this.ctx.
|
|
45197
|
+
baseWidth: this.ctx.shapeStrokeWidth(),
|
|
45092
45198
|
points
|
|
45093
45199
|
}));
|
|
45094
45200
|
this.ctx.clusters.assign(strokes[0]);
|
|
@@ -45122,13 +45228,13 @@ var ShapeTool = class {
|
|
|
45122
45228
|
this.previews[i].visible = polyline !== void 0;
|
|
45123
45229
|
if (polyline) {
|
|
45124
45230
|
this.previews[i].geometry.dispose();
|
|
45125
|
-
this.previews[i].geometry = buildRibbonGeometry(polyline, this.ctx.
|
|
45231
|
+
this.previews[i].geometry = buildRibbonGeometry(polyline, this.ctx.shapeStrokeWidth());
|
|
45126
45232
|
}
|
|
45127
45233
|
}
|
|
45128
45234
|
}
|
|
45129
45235
|
};
|
|
45130
45236
|
//#endregion
|
|
45131
|
-
//#region
|
|
45237
|
+
//#region src/interaction/tools/tableDrag.ts
|
|
45132
45238
|
function getHandleCursor(handle) {
|
|
45133
45239
|
switch (handle) {
|
|
45134
45240
|
case "nw":
|
|
@@ -45248,7 +45354,7 @@ var TableDragState = class {
|
|
|
45248
45354
|
}
|
|
45249
45355
|
};
|
|
45250
45356
|
//#endregion
|
|
45251
|
-
//#region
|
|
45357
|
+
//#region src/interaction/tools/tableTool.ts
|
|
45252
45358
|
var MIN_DRAG_PX = 6;
|
|
45253
45359
|
var TableTool = class {
|
|
45254
45360
|
constructor(ctx) {
|
|
@@ -45379,7 +45485,7 @@ var TableTool = class {
|
|
|
45379
45485
|
}
|
|
45380
45486
|
};
|
|
45381
45487
|
//#endregion
|
|
45382
|
-
//#region
|
|
45488
|
+
//#region src/interaction/tools/commentTool.ts
|
|
45383
45489
|
/** Click on the board to drop a new comment pin or open an existing one. */
|
|
45384
45490
|
var CommentTool = class {
|
|
45385
45491
|
constructor(ctx) {
|
|
@@ -45414,7 +45520,7 @@ var CommentTool = class {
|
|
|
45414
45520
|
}
|
|
45415
45521
|
};
|
|
45416
45522
|
//#endregion
|
|
45417
|
-
//#region
|
|
45523
|
+
//#region src/interaction/tools/textDrag.ts
|
|
45418
45524
|
/** Drag the focused text block in X/Y; one command per drag. */
|
|
45419
45525
|
var TextDragState = class {
|
|
45420
45526
|
constructor(ctx) {
|
|
@@ -45466,7 +45572,7 @@ var TextDragState = class {
|
|
|
45466
45572
|
}
|
|
45467
45573
|
};
|
|
45468
45574
|
//#endregion
|
|
45469
|
-
//#region
|
|
45575
|
+
//#region src/interaction/tools/fsm.ts
|
|
45470
45576
|
var ToolStateMachine = class {
|
|
45471
45577
|
constructor() {
|
|
45472
45578
|
this.states = /* @__PURE__ */ new Map();
|
|
@@ -45668,7 +45774,7 @@ var IdleState = class {
|
|
|
45668
45774
|
}
|
|
45669
45775
|
};
|
|
45670
45776
|
//#endregion
|
|
45671
|
-
//#region
|
|
45777
|
+
//#region src/renderer/selection/gizmo.ts
|
|
45672
45778
|
var GIZMO_Z = .05;
|
|
45673
45779
|
var HANDLE_PX = 9;
|
|
45674
45780
|
var HANDLE_HIT_PX = 12;
|
|
@@ -45899,7 +46005,7 @@ function boxesEqual(a, b) {
|
|
|
45899
46005
|
return a.minX === b.minX && a.minY === b.minY && a.maxX === b.maxX && a.maxY === b.maxY;
|
|
45900
46006
|
}
|
|
45901
46007
|
//#endregion
|
|
45902
|
-
//#region
|
|
46008
|
+
//#region src/interaction/tools/pressure.ts
|
|
45903
46009
|
var SIM_MAX = 1;
|
|
45904
46010
|
var SIM_MIN = .3;
|
|
45905
46011
|
var SMOOTHING = .25;
|
|
@@ -45921,7 +46027,7 @@ function clamp(v, lo, hi) {
|
|
|
45921
46027
|
return Math.min(hi, Math.max(lo, v));
|
|
45922
46028
|
}
|
|
45923
46029
|
//#endregion
|
|
45924
|
-
//#region
|
|
46030
|
+
//#region src/interaction/tools/strokeBuilder.ts
|
|
45925
46031
|
var StrokeBuilder = class {
|
|
45926
46032
|
constructor() {
|
|
45927
46033
|
this.points = [];
|
|
@@ -45971,7 +46077,7 @@ function catmullRom(v0, v1, v2, v3, t) {
|
|
|
45971
46077
|
return .5 * (2 * v1 + (-v0 + v2) * t + (2 * v0 - 5 * v1 + 4 * v2 - v3) * t2 + (-v0 + 3 * v1 - 3 * v2 + v3) * t3);
|
|
45972
46078
|
}
|
|
45973
46079
|
//#endregion
|
|
45974
|
-
//#region
|
|
46080
|
+
//#region src/interaction/tools/markerTool.ts
|
|
45975
46081
|
/** Sample spacing while drawing, in screen pixels. */
|
|
45976
46082
|
var MIN_SAMPLE_PX = 1.5;
|
|
45977
46083
|
/** A highlighter is a chisel tip: near-constant width, little pressure play. */
|
|
@@ -46074,7 +46180,7 @@ var MarkerTool = class {
|
|
|
46074
46180
|
}
|
|
46075
46181
|
};
|
|
46076
46182
|
//#endregion
|
|
46077
|
-
//#region
|
|
46183
|
+
//#region src/interaction/tools/orbitTool.ts
|
|
46078
46184
|
/**
|
|
46079
46185
|
* Orbit-preview (build prompt §4.2): alt-drag tilts the camera off-axis to
|
|
46080
46186
|
* read the board's material and depth; releasing eases back to the working
|
|
@@ -46109,7 +46215,7 @@ var OrbitTool = class {
|
|
|
46109
46215
|
}
|
|
46110
46216
|
};
|
|
46111
46217
|
//#endregion
|
|
46112
|
-
//#region
|
|
46218
|
+
//#region src/interaction/tools/panTool.ts
|
|
46113
46219
|
/** Grab-pan: content follows the pointer. */
|
|
46114
46220
|
var PanTool = class {
|
|
46115
46221
|
constructor(ctx) {
|
|
@@ -46139,7 +46245,7 @@ var PanTool = class {
|
|
|
46139
46245
|
}
|
|
46140
46246
|
};
|
|
46141
46247
|
//#endregion
|
|
46142
|
-
//#region
|
|
46248
|
+
//#region src/renderer/selection/selection.ts
|
|
46143
46249
|
/** The set of selected stroke ids. Drops ids the document no longer has. */
|
|
46144
46250
|
var SelectionManager = class {
|
|
46145
46251
|
constructor(doc) {
|
|
@@ -46190,7 +46296,7 @@ var SelectionManager = class {
|
|
|
46190
46296
|
}
|
|
46191
46297
|
};
|
|
46192
46298
|
//#endregion
|
|
46193
|
-
//#region
|
|
46299
|
+
//#region src/interaction/tools/selectTool.ts
|
|
46194
46300
|
var HIT_SLOP_PX = 4;
|
|
46195
46301
|
var CLICK_TOLERANCE_PX = 3;
|
|
46196
46302
|
var MIN_SCALE = .05;
|
|
@@ -46406,7 +46512,7 @@ function safeRatio(numerator, denominator) {
|
|
|
46406
46512
|
return raw;
|
|
46407
46513
|
}
|
|
46408
46514
|
//#endregion
|
|
46409
|
-
//#region
|
|
46515
|
+
//#region src/interaction/tools/customTool.ts
|
|
46410
46516
|
function extensionIdFromToolId(toolId) {
|
|
46411
46517
|
const slash = toolId.indexOf("/");
|
|
46412
46518
|
return slash === -1 ? toolId : toolId.slice(0, slash);
|
|
@@ -46521,12 +46627,19 @@ var ExtensionCommandBatch = class {
|
|
|
46521
46627
|
}
|
|
46522
46628
|
};
|
|
46523
46629
|
//#endregion
|
|
46524
|
-
//#region
|
|
46630
|
+
//#region src/composition/ScrawlEngine.ts
|
|
46525
46631
|
/** Marker stroke width in board units (~1% of the default view height). */
|
|
46526
46632
|
var BASE_WIDTH = .5;
|
|
46527
46633
|
/** Highlighter chisel width — wide enough to cover a line of handwriting. */
|
|
46528
46634
|
var HIGHLIGHT_WIDTH = 2.2;
|
|
46529
46635
|
/**
|
|
46636
|
+
* Shape (rectangle, ellipse, arrow, ...) border width in board units.
|
|
46637
|
+
* Deliberately thinner than BASE_WIDTH: a shape border reads as a crisp,
|
|
46638
|
+
* structural line, not an expressive marker stroke — this is also the
|
|
46639
|
+
* fallback when no Host theme configures ScrawlTheme.shapeStrokeWidth.
|
|
46640
|
+
*/
|
|
46641
|
+
var DEFAULT_SHAPE_STROKE_WIDTH = .15;
|
|
46642
|
+
/**
|
|
46530
46643
|
* Identity of a rendered selection badge: which item, its lock state, and
|
|
46531
46644
|
* where it sits on screen (rounded to the pixel, so sub-pixel camera drift
|
|
46532
46645
|
* does not churn React).
|
|
@@ -46547,9 +46660,11 @@ function emptyExtensionRegistry() {
|
|
|
46547
46660
|
* React never reaches past this class.
|
|
46548
46661
|
*/
|
|
46549
46662
|
var ScrawlEngine = class {
|
|
46550
|
-
constructor(canvas, documentId$1, extensionRegistry = emptyExtensionRegistry(), assetController = new AssetController(void 0)) {
|
|
46663
|
+
constructor(canvas, documentId$1, extensionRegistry = emptyExtensionRegistry(), assetController = new AssetController(void 0), boardTheme = DEFAULT_BOARD_SURFACE_THEME, shapeStrokeWidth = DEFAULT_SHAPE_STROKE_WIDTH) {
|
|
46551
46664
|
this.canvas = canvas;
|
|
46552
46665
|
this.extensionRegistry = extensionRegistry;
|
|
46666
|
+
this.boardTheme = boardTheme;
|
|
46667
|
+
this.shapeStrokeWidth = shapeStrokeWidth;
|
|
46553
46668
|
this.onToolChange = null;
|
|
46554
46669
|
this.onZoomChange = null;
|
|
46555
46670
|
this.onAuditEvent = null;
|
|
@@ -46596,7 +46711,7 @@ var ScrawlEngine = class {
|
|
|
46596
46711
|
this.stampKind = "star";
|
|
46597
46712
|
this.timerDurationMs = TIMER_DEFAULT_DURATION_MS;
|
|
46598
46713
|
this.readOnly = false;
|
|
46599
|
-
this.scene = new SceneRig(canvas);
|
|
46714
|
+
this.scene = new SceneRig(canvas, boardTheme);
|
|
46600
46715
|
this.document = new BoardDocument(documentId(documentId$1));
|
|
46601
46716
|
this.history = new History(this.document);
|
|
46602
46717
|
this.history.onCommand = (command, kind) => {
|
|
@@ -46644,6 +46759,7 @@ var ScrawlEngine = class {
|
|
|
46644
46759
|
setTool: (t) => this.setTool(t),
|
|
46645
46760
|
inkColor: () => this.tool === "highlighter" ? this.highlightColor : this.color,
|
|
46646
46761
|
baseWidth: () => this.tool === "highlighter" ? HIGHLIGHT_WIDTH : BASE_WIDTH,
|
|
46762
|
+
shapeStrokeWidth: () => this.shapeStrokeWidth,
|
|
46647
46763
|
activeTool: () => this.tool,
|
|
46648
46764
|
isSpaceHeld: () => this.spaceHeld,
|
|
46649
46765
|
pointerToBoard: (e) => pointerToBoard(e.clientX, e.clientY, canvas, this.scene.cameraRig.camera),
|
|
@@ -46903,6 +47019,15 @@ var ScrawlEngine = class {
|
|
|
46903
47019
|
height: rig.height
|
|
46904
47020
|
};
|
|
46905
47021
|
}
|
|
47022
|
+
/** Live update of the board surface color/grid — the engine's identity stays fixed across theme changes. */
|
|
47023
|
+
applyBoardTheme(theme) {
|
|
47024
|
+
this.boardTheme = theme;
|
|
47025
|
+
this.scene.applyBoardTheme(theme);
|
|
47026
|
+
}
|
|
47027
|
+
/** Live update of the shape tool's border width (board units). Already-drawn shapes keep the width they were drawn with. */
|
|
47028
|
+
setShapeStrokeWidth(width) {
|
|
47029
|
+
this.shapeStrokeWidth = width;
|
|
47030
|
+
}
|
|
46906
47031
|
/**
|
|
46907
47032
|
* Snap to a peer's camera. No-op while drawing so pointer-to-board
|
|
46908
47033
|
* mapping does not warp the in-progress stroke.
|
|
@@ -46921,7 +47046,7 @@ var ScrawlEngine = class {
|
|
|
46921
47046
|
}
|
|
46922
47047
|
/** The saved document as standalone SVG — a pure walk of the wire format. */
|
|
46923
47048
|
exportSVG() {
|
|
46924
|
-
return documentToSVG(this.document.toJSON(), Date.now(), this.extensionRegistry);
|
|
47049
|
+
return documentToSVG(this.document.toJSON(), Date.now(), this.extensionRegistry, this.boardTheme.color);
|
|
46925
47050
|
}
|
|
46926
47051
|
/**
|
|
46927
47052
|
* Content-framed PNG snapshot. Renders once offscreen-style with UI props
|
|
@@ -46957,6 +47082,7 @@ var ScrawlEngine = class {
|
|
|
46957
47082
|
this.notesRenderer.setFocus(null);
|
|
46958
47083
|
this.textsRenderer.setFocus(null);
|
|
46959
47084
|
this.renderer.setGhostsVisible(false);
|
|
47085
|
+
const restoreGrid = this.scene.suppressGrid();
|
|
46960
47086
|
try {
|
|
46961
47087
|
rig.yaw = 0;
|
|
46962
47088
|
rig.pitch = 0;
|
|
@@ -46967,6 +47093,7 @@ var ScrawlEngine = class {
|
|
|
46967
47093
|
const dataUrl = this.scene.renderer.domElement.toDataURL("image/png");
|
|
46968
47094
|
return await (await fetch(dataUrl)).blob();
|
|
46969
47095
|
} finally {
|
|
47096
|
+
restoreGrid();
|
|
46970
47097
|
rig.center.x = saved.x;
|
|
46971
47098
|
rig.center.y = saved.y;
|
|
46972
47099
|
rig.height = saved.height;
|
|
@@ -47962,7 +48089,7 @@ var ScrawlEngine = class {
|
|
|
47962
48089
|
}
|
|
47963
48090
|
};
|
|
47964
48091
|
//#endregion
|
|
47965
|
-
//#region src/controller-internal.ts
|
|
48092
|
+
//#region src/composition/controller-internal.ts
|
|
47966
48093
|
function createBoardController(options) {
|
|
47967
48094
|
return createBoardControllerWithEngine(options);
|
|
47968
48095
|
}
|
|
@@ -47976,7 +48103,16 @@ function createBoardControllerWithEngine(options, existingEngine) {
|
|
|
47976
48103
|
}
|
|
47977
48104
|
const extensionRegistry = registryResult.registry;
|
|
47978
48105
|
const assetController = new AssetController(options.assetResolver, { cacheBytes: options.assetCacheBytes });
|
|
47979
|
-
|
|
48106
|
+
let currentBoardTheme = {
|
|
48107
|
+
color: options.boardTheme?.surface ?? DEFAULT_BOARD_SURFACE_THEME.color,
|
|
48108
|
+
gridMode: options.boardTheme?.gridMode ?? DEFAULT_BOARD_SURFACE_THEME.gridMode,
|
|
48109
|
+
gridColor: options.boardTheme?.gridColor ?? DEFAULT_BOARD_SURFACE_THEME.gridColor,
|
|
48110
|
+
gridSpacing: options.boardTheme?.gridSpacing ?? DEFAULT_BOARD_SURFACE_THEME.gridSpacing,
|
|
48111
|
+
gridLineWidth: options.boardTheme?.gridLineWidth ?? DEFAULT_BOARD_SURFACE_THEME.gridLineWidth,
|
|
48112
|
+
surfaceTexture: options.boardTheme?.surfaceTexture ?? DEFAULT_BOARD_SURFACE_THEME.surfaceTexture
|
|
48113
|
+
};
|
|
48114
|
+
let currentShapeStrokeWidth = options.boardTheme?.shapeStrokeWidth ?? .15;
|
|
48115
|
+
const engine = existingEngine ?? (options.canvas ? new ScrawlEngine(options.canvas, options.document.id, extensionRegistry, assetController, currentBoardTheme, currentShapeStrokeWidth) : null);
|
|
47980
48116
|
const document = engine?.document ?? new BoardDocument(documentId(options.document.id));
|
|
47981
48117
|
const history = engine?.history ?? new History(document);
|
|
47982
48118
|
const createId = options.createId ?? (() => crypto.randomUUID());
|
|
@@ -48460,6 +48596,21 @@ function createBoardControllerWithEngine(options, existingEngine) {
|
|
|
48460
48596
|
changed();
|
|
48461
48597
|
}
|
|
48462
48598
|
},
|
|
48599
|
+
boardTheme: { set(theme) {
|
|
48600
|
+
currentBoardTheme = {
|
|
48601
|
+
color: theme.surface ?? currentBoardTheme.color,
|
|
48602
|
+
gridMode: theme.gridMode ?? currentBoardTheme.gridMode,
|
|
48603
|
+
gridColor: theme.gridColor ?? currentBoardTheme.gridColor,
|
|
48604
|
+
gridSpacing: theme.gridSpacing ?? currentBoardTheme.gridSpacing,
|
|
48605
|
+
gridLineWidth: theme.gridLineWidth ?? currentBoardTheme.gridLineWidth,
|
|
48606
|
+
surfaceTexture: theme.surfaceTexture ?? currentBoardTheme.surfaceTexture
|
|
48607
|
+
};
|
|
48608
|
+
engine?.applyBoardTheme(currentBoardTheme);
|
|
48609
|
+
if (theme.shapeStrokeWidth !== void 0) {
|
|
48610
|
+
currentShapeStrokeWidth = theme.shapeStrokeWidth;
|
|
48611
|
+
engine?.setShapeStrokeWidth(currentShapeStrokeWidth);
|
|
48612
|
+
}
|
|
48613
|
+
} },
|
|
48463
48614
|
view: {
|
|
48464
48615
|
fit() {
|
|
48465
48616
|
assertActive();
|
|
@@ -48764,10 +48915,10 @@ function createBoardControllerWithEngine(options, existingEngine) {
|
|
|
48764
48915
|
gather: (nextView) => engine?.applyGatherView(nextView) ?? false
|
|
48765
48916
|
},
|
|
48766
48917
|
export: {
|
|
48767
|
-
svg: () => engine ? engine.exportSVG() : documentToSVG(document.toJSON(), Date.now(), extensionRegistry),
|
|
48918
|
+
svg: () => engine ? engine.exportSVG() : documentToSVG(document.toJSON(), Date.now(), extensionRegistry, currentBoardTheme.color),
|
|
48768
48919
|
png: (options) => engine ? engine.exportPNG(options?.maxSide, { awaitAssets: options?.awaitAssets }) : Promise.resolve(null),
|
|
48769
48920
|
json: () => document.toJSON(),
|
|
48770
|
-
svgAsync: (svgOptions) => exportDocumentSVGWithAssets(document.toJSON(), Date.now(), extensionRegistry, assetController, svgOptions)
|
|
48921
|
+
svgAsync: (svgOptions) => exportDocumentSVGWithAssets(document.toJSON(), Date.now(), extensionRegistry, assetController, currentBoardTheme.color, svgOptions)
|
|
48771
48922
|
},
|
|
48772
48923
|
assets: { async ingest(bytes, mediaType, name, signal) {
|
|
48773
48924
|
assertActive();
|
|
@@ -49229,7 +49380,7 @@ function createLocalBoard(options) {
|
|
|
49229
49380
|
};
|
|
49230
49381
|
}
|
|
49231
49382
|
//#endregion
|
|
49232
|
-
//#region src/theme.ts
|
|
49383
|
+
//#region src/ui/theme.ts
|
|
49233
49384
|
var scrawlThemePresets = Object.freeze({
|
|
49234
49385
|
light: Object.freeze({
|
|
49235
49386
|
surface: "#ffffff",
|
|
@@ -49254,7 +49405,14 @@ var scrawlThemePresets = Object.freeze({
|
|
|
49254
49405
|
elevationHigh: "0 8px 20px rgba(28, 28, 26, 0.18)",
|
|
49255
49406
|
motionDuration: 140,
|
|
49256
49407
|
motionEasing: "cubic-bezier(0.2, 0, 0, 1)",
|
|
49257
|
-
density: "comfortable"
|
|
49408
|
+
density: "comfortable",
|
|
49409
|
+
boardSurface: "#f5f5f3",
|
|
49410
|
+
boardSurfaceTexture: "flat",
|
|
49411
|
+
gridMode: "none",
|
|
49412
|
+
gridColor: "#deded8",
|
|
49413
|
+
gridSpacing: 5,
|
|
49414
|
+
gridLineWidth: 1,
|
|
49415
|
+
shapeStrokeWidth: .15
|
|
49258
49416
|
}),
|
|
49259
49417
|
dark: Object.freeze({
|
|
49260
49418
|
surface: "#171816",
|
|
@@ -49279,7 +49437,14 @@ var scrawlThemePresets = Object.freeze({
|
|
|
49279
49437
|
elevationHigh: "0 8px 20px rgba(0, 0, 0, 0.38)",
|
|
49280
49438
|
motionDuration: 140,
|
|
49281
49439
|
motionEasing: "cubic-bezier(0.2, 0, 0, 1)",
|
|
49282
|
-
density: "comfortable"
|
|
49440
|
+
density: "comfortable",
|
|
49441
|
+
boardSurface: "#232420",
|
|
49442
|
+
boardSurfaceTexture: "flat",
|
|
49443
|
+
gridMode: "none",
|
|
49444
|
+
gridColor: "#33352f",
|
|
49445
|
+
gridSpacing: 5,
|
|
49446
|
+
gridLineWidth: 1,
|
|
49447
|
+
shapeStrokeWidth: .15
|
|
49283
49448
|
})
|
|
49284
49449
|
});
|
|
49285
49450
|
var variableNames = {
|
|
@@ -49305,7 +49470,14 @@ var variableNames = {
|
|
|
49305
49470
|
elevationHigh: "--scrawl-elevation-high",
|
|
49306
49471
|
motionDuration: "--scrawl-motion-duration",
|
|
49307
49472
|
motionEasing: "--scrawl-motion-easing",
|
|
49308
|
-
density: "--scrawl-density"
|
|
49473
|
+
density: "--scrawl-density",
|
|
49474
|
+
boardSurface: "--scrawl-board-surface",
|
|
49475
|
+
boardSurfaceTexture: "--scrawl-board-surface-texture",
|
|
49476
|
+
gridMode: "--scrawl-grid-mode",
|
|
49477
|
+
gridColor: "--scrawl-grid-color",
|
|
49478
|
+
gridSpacing: "--scrawl-grid-spacing",
|
|
49479
|
+
gridLineWidth: "--scrawl-grid-line-width",
|
|
49480
|
+
shapeStrokeWidth: "--scrawl-shape-stroke-width"
|
|
49309
49481
|
};
|
|
49310
49482
|
var colorTokens = /* @__PURE__ */ new Set([
|
|
49311
49483
|
"surface",
|
|
@@ -49318,7 +49490,9 @@ var colorTokens = /* @__PURE__ */ new Set([
|
|
|
49318
49490
|
"selection",
|
|
49319
49491
|
"danger",
|
|
49320
49492
|
"warning",
|
|
49321
|
-
"success"
|
|
49493
|
+
"success",
|
|
49494
|
+
"boardSurface",
|
|
49495
|
+
"gridColor"
|
|
49322
49496
|
]);
|
|
49323
49497
|
var knownTokens = new Set(Object.keys(scrawlThemePresets.light));
|
|
49324
49498
|
function validateScrawlTheme(theme) {
|
|
@@ -49355,6 +49529,26 @@ function validateScrawlTheme(theme) {
|
|
|
49355
49529
|
token,
|
|
49356
49530
|
message: "Expected comfortable or compact"
|
|
49357
49531
|
});
|
|
49532
|
+
else if (token === "gridMode" && value !== "none" && value !== "line" && value !== "dot") diagnostics.push({
|
|
49533
|
+
token,
|
|
49534
|
+
message: "Expected none, line, or dot"
|
|
49535
|
+
});
|
|
49536
|
+
else if (token === "boardSurfaceTexture" && value !== "flat" && value !== "textured") diagnostics.push({
|
|
49537
|
+
token,
|
|
49538
|
+
message: "Expected flat or textured"
|
|
49539
|
+
});
|
|
49540
|
+
else if (token === "gridSpacing" && (!finiteNumber(value) || value < .5 || value > 50)) diagnostics.push({
|
|
49541
|
+
token,
|
|
49542
|
+
message: "Expected spacing 0.5-50 board units"
|
|
49543
|
+
});
|
|
49544
|
+
else if (token === "gridLineWidth" && (!finiteNumber(value) || value < .5 || value > 8)) diagnostics.push({
|
|
49545
|
+
token,
|
|
49546
|
+
message: "Expected line width 0.5-8px"
|
|
49547
|
+
});
|
|
49548
|
+
else if (token === "shapeStrokeWidth" && (!finiteNumber(value) || value < .01 || value > 5)) diagnostics.push({
|
|
49549
|
+
token,
|
|
49550
|
+
message: "Expected stroke width 0.01-5 board units"
|
|
49551
|
+
});
|
|
49358
49552
|
else if ((token.endsWith("Family") || token.startsWith("elevation") || token === "motionEasing") && (typeof value !== "string" || !value.trim() || /[;{}]/.test(value))) diagnostics.push({
|
|
49359
49553
|
token,
|
|
49360
49554
|
message: "Expected a safe CSS value"
|
|
@@ -49425,12 +49619,12 @@ function luminance(color) {
|
|
|
49425
49619
|
return channels[0] * .2126 + channels[1] * .7152 + channels[2] * .0722;
|
|
49426
49620
|
}
|
|
49427
49621
|
function formatValue(token, value) {
|
|
49428
|
-
if (token === "baseFontSize" || token === "controlRadius" || token === "panelRadius") return `${value}px`;
|
|
49622
|
+
if (token === "baseFontSize" || token === "controlRadius" || token === "panelRadius" || token === "gridLineWidth") return `${value}px`;
|
|
49429
49623
|
if (token === "motionDuration") return `${value}ms`;
|
|
49430
49624
|
return String(value);
|
|
49431
49625
|
}
|
|
49432
49626
|
//#endregion
|
|
49433
|
-
//#region src/inline-editing.tsx
|
|
49627
|
+
//#region src/ui/dialogs/inline-editing.tsx
|
|
49434
49628
|
/** Inline note, text, and table-cell editors — driven entirely by public controller events and commands. */
|
|
49435
49629
|
function InlineEditors({ controller, renderPortal }) {
|
|
49436
49630
|
const [editor, setEditor] = useState(null);
|
|
@@ -49661,7 +49855,7 @@ function InlineEditors({ controller, renderPortal }) {
|
|
|
49661
49855
|
}))] });
|
|
49662
49856
|
}
|
|
49663
49857
|
//#endregion
|
|
49664
|
-
//#region src/style-shelf.tsx
|
|
49858
|
+
//#region src/ui/toolbar/style-shelf.tsx
|
|
49665
49859
|
var ERASER_RADII = [
|
|
49666
49860
|
["Fine", 1],
|
|
49667
49861
|
["Medium", 2],
|
|
@@ -49824,7 +50018,7 @@ function StyleShelf({ controller, snapshot }) {
|
|
|
49824
50018
|
});
|
|
49825
50019
|
}
|
|
49826
50020
|
//#endregion
|
|
49827
|
-
//#region src/default-ui.tsx
|
|
50021
|
+
//#region src/ui/default-ui.tsx
|
|
49828
50022
|
var PRIMARY_TOOLS = [
|
|
49829
50023
|
{
|
|
49830
50024
|
tool: "select",
|
|
@@ -50353,7 +50547,7 @@ function download(blob, name) {
|
|
|
50353
50547
|
URL.revokeObjectURL(url);
|
|
50354
50548
|
}
|
|
50355
50549
|
//#endregion
|
|
50356
|
-
//#region src/presence.tsx
|
|
50550
|
+
//#region src/ui/panels/presence.tsx
|
|
50357
50551
|
var labelStyle = {
|
|
50358
50552
|
borderRadius: 999,
|
|
50359
50553
|
color: "#fff",
|
|
@@ -50510,6 +50704,17 @@ function ScrawlProvider({ controller, children, preset = "light", theme, portalC
|
|
|
50510
50704
|
style
|
|
50511
50705
|
]);
|
|
50512
50706
|
useEffect(() => reportThemeDiagnostics(resolved.diagnostics, onThemeDiagnostic), [resolved, onThemeDiagnostic]);
|
|
50707
|
+
useEffect(() => {
|
|
50708
|
+
controller.boardTheme.set({
|
|
50709
|
+
surface: resolved.values.boardSurface,
|
|
50710
|
+
surfaceTexture: resolved.values.boardSurfaceTexture,
|
|
50711
|
+
gridMode: resolved.values.gridMode,
|
|
50712
|
+
gridColor: resolved.values.gridColor,
|
|
50713
|
+
gridSpacing: resolved.values.gridSpacing,
|
|
50714
|
+
gridLineWidth: resolved.values.gridLineWidth,
|
|
50715
|
+
shapeStrokeWidth: resolved.values.shapeStrokeWidth
|
|
50716
|
+
});
|
|
50717
|
+
}, [controller, resolved]);
|
|
50513
50718
|
useDeferredDisposal(controller, disposeOnUnmount);
|
|
50514
50719
|
const value = useMemo(() => ({
|
|
50515
50720
|
controller,
|
|
@@ -50557,8 +50762,19 @@ function Scrawl({ children, preset, theme, portalContainer, className, style, on
|
|
|
50557
50762
|
try {
|
|
50558
50763
|
if (!runtimeRef.current) {
|
|
50559
50764
|
const canvas = suppliedCanvas === void 0 ? ownedCanvasRef.current : suppliedCanvas;
|
|
50765
|
+
const resolved = resolveScrawlTheme(preset, theme);
|
|
50766
|
+
const boardTheme = {
|
|
50767
|
+
surface: resolved.values.boardSurface,
|
|
50768
|
+
surfaceTexture: resolved.values.boardSurfaceTexture,
|
|
50769
|
+
gridMode: resolved.values.gridMode,
|
|
50770
|
+
gridColor: resolved.values.gridColor,
|
|
50771
|
+
gridSpacing: resolved.values.gridSpacing,
|
|
50772
|
+
gridLineWidth: resolved.values.gridLineWidth,
|
|
50773
|
+
shapeStrokeWidth: resolved.values.shapeStrokeWidth
|
|
50774
|
+
};
|
|
50560
50775
|
controller = createBoardController({
|
|
50561
50776
|
...options,
|
|
50777
|
+
boardTheme,
|
|
50562
50778
|
...canvas ? { canvas } : {}
|
|
50563
50779
|
});
|
|
50564
50780
|
runtimeRef.current = {
|
|
@@ -50794,4 +51010,4 @@ function ScrawlBoard({ documentId, initialDocument, onReady, className, style })
|
|
|
50794
51010
|
});
|
|
50795
51011
|
}
|
|
50796
51012
|
//#endregion
|
|
50797
|
-
export { DefaultBoardChrome, InlineEditors, MultiplayerCursors, Scrawl, ScrawlBoard, ScrawlCanvas, ScrawlDefaultUI, ScrawlPortal, ScrawlProvider, StyleShelf, resolveScrawlTheme, scrawlThemePresets, useScrawlController, useScrawlSnapshot, useScrawlTheme, validateScrawlTheme };
|
|
51013
|
+
export { AssetResolutionError, DefaultBoardChrome, InlineEditors, MultiplayerCursors, SUPPORTED_ASSET_MEDIA_TYPES, Scrawl, ScrawlBoard, ScrawlCanvas, ScrawlDefaultUI, ScrawlPortal, ScrawlProvider, StyleShelf, assetRef, clampAssetCacheBytes, cloneCustomObject, isAssetRef, resolveScrawlTheme, scrawlThemePresets, useScrawlController, useScrawlSnapshot, useScrawlTheme, validateScrawlTheme };
|