@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/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
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
|
+
/** Hard ceiling on a reference's own wire length — independent of any resource limit below. */
|
|
7
|
+
var ASSET_REF_MAX_BYTES = 512;
|
|
6
8
|
function isAssetRef(value) {
|
|
7
9
|
return typeof value === "string" && ASSET_REF_PATTERN.test(value) && new TextEncoder().encode(value).length <= 512;
|
|
8
10
|
}
|
|
@@ -20,15 +22,26 @@ var AssetResolutionError = class extends Error {
|
|
|
20
22
|
this.name = "AssetResolutionError";
|
|
21
23
|
}
|
|
22
24
|
};
|
|
25
|
+
var ASSET_MAX_ENCODED_BYTES = 20 * 1024 * 1024;
|
|
26
|
+
var ASSET_MAX_DIMENSION_PX = 8192;
|
|
27
|
+
var ASSET_MAX_DECODED_MEGAPIXELS = 40;
|
|
28
|
+
var ASSET_MAX_CONCURRENT_RESOLUTIONS = 6;
|
|
23
29
|
var ASSET_CACHE_BYTES_DEFAULT = 256 * 1024 * 1024;
|
|
24
30
|
var ASSET_CACHE_BYTES_MIN = 64 * 1024 * 1024;
|
|
25
31
|
var ASSET_CACHE_BYTES_MAX = 512 * 1024 * 1024;
|
|
32
|
+
var ASSET_EXPORT_MAX_ENCODED_BYTES = 100 * 1024 * 1024;
|
|
33
|
+
var ASSET_EXPORT_MAX_DECODED_MEGAPIXELS = 100;
|
|
34
|
+
var SUPPORTED_ASSET_MEDIA_TYPES = [
|
|
35
|
+
"image/png",
|
|
36
|
+
"image/jpeg",
|
|
37
|
+
"image/webp"
|
|
38
|
+
];
|
|
26
39
|
function clampAssetCacheBytes(value) {
|
|
27
40
|
if (value === void 0 || !Number.isFinite(value)) return ASSET_CACHE_BYTES_DEFAULT;
|
|
28
41
|
return Math.min(ASSET_CACHE_BYTES_MAX, Math.max(ASSET_CACHE_BYTES_MIN, Math.floor(value)));
|
|
29
42
|
}
|
|
30
43
|
//#endregion
|
|
31
|
-
//#region src/core
|
|
44
|
+
//#region src/core/document/identifiers.ts
|
|
32
45
|
function documentId(value) {
|
|
33
46
|
if (!value) throw new TypeError("DocumentId cannot be empty");
|
|
34
47
|
return value;
|
|
@@ -38,7 +51,7 @@ function strokeId(value) {
|
|
|
38
51
|
return value;
|
|
39
52
|
}
|
|
40
53
|
//#endregion
|
|
41
|
-
//#region src/document-schema.ts
|
|
54
|
+
//#region src/core/document/document-schema.ts
|
|
42
55
|
var CURRENT_DOCUMENT_SCHEMA_VERSION = 1;
|
|
43
56
|
var DocumentRecoveryError = class extends Error {
|
|
44
57
|
constructor(code, message, originalBytes, path) {
|
|
@@ -246,7 +259,7 @@ function validation(message, path) {
|
|
|
246
259
|
return new DocumentRecoveryError("DOCUMENT_VALIDATION_FAILED", message, void 0, path);
|
|
247
260
|
}
|
|
248
261
|
//#endregion
|
|
249
|
-
//#region src/core
|
|
262
|
+
//#region src/core/shapes/affine2d.ts
|
|
250
263
|
var IDENTITY = [
|
|
251
264
|
1,
|
|
252
265
|
0,
|
|
@@ -330,7 +343,7 @@ function avgScale(m) {
|
|
|
330
343
|
return (Math.hypot(m[0], m[1]) + Math.hypot(m[2], m[3])) / 2;
|
|
331
344
|
}
|
|
332
345
|
//#endregion
|
|
333
|
-
//#region src/core
|
|
346
|
+
//#region src/core/document/boardSearch.ts
|
|
334
347
|
function hay(s) {
|
|
335
348
|
return s.toLowerCase();
|
|
336
349
|
}
|
|
@@ -395,7 +408,7 @@ function searchBoard(query, board) {
|
|
|
395
408
|
return hits;
|
|
396
409
|
}
|
|
397
410
|
//#endregion
|
|
398
|
-
//#region src/core
|
|
411
|
+
//#region src/core/shapes/types.ts
|
|
399
412
|
/** Erasure level at which a point counts as fully erased. */
|
|
400
413
|
var ERASE_THRESHOLD = .95;
|
|
401
414
|
function cloneStroke(stroke) {
|
|
@@ -466,13 +479,12 @@ function measureTable(table) {
|
|
|
466
479
|
height: table.rowHeights.reduce((sum, h) => sum + h, 0)
|
|
467
480
|
};
|
|
468
481
|
}
|
|
469
|
-
var BOARD_COLOR = "#FFFFFF";
|
|
470
482
|
var FOG_COLOR = "#FFFFFF";
|
|
471
483
|
function cloneImage(img) {
|
|
472
484
|
return { ...img };
|
|
473
485
|
}
|
|
474
486
|
//#endregion
|
|
475
|
-
//#region src/core
|
|
487
|
+
//#region src/core/document/clusterStore.ts
|
|
476
488
|
/** A stroke joins a cluster last written to within this window at full reach. */
|
|
477
489
|
var RECENT_MS = 8e3;
|
|
478
490
|
/** Older clusters are still joinable, at half the gap threshold. */
|
|
@@ -643,7 +655,7 @@ function clamp$3(v, lo, hi) {
|
|
|
643
655
|
return Math.min(hi, Math.max(lo, v));
|
|
644
656
|
}
|
|
645
657
|
//#endregion
|
|
646
|
-
//#region src/core
|
|
658
|
+
//#region src/core/shapes/extensionTypes.ts
|
|
647
659
|
function cloneCustomObject(object) {
|
|
648
660
|
return {
|
|
649
661
|
...object,
|
|
@@ -653,7 +665,7 @@ function cloneCustomObject(object) {
|
|
|
653
665
|
};
|
|
654
666
|
}
|
|
655
667
|
//#endregion
|
|
656
|
-
//#region src/core
|
|
668
|
+
//#region src/core/shapes/kitchenTimer.ts
|
|
657
669
|
var TIMER_DEFAULT_SIZE = 12;
|
|
658
670
|
var TIMER_DEFAULT_DURATION_MS = 300 * 1e3;
|
|
659
671
|
var TIMER_PRESETS_MS = [
|
|
@@ -710,7 +722,7 @@ function formatTimer(ms) {
|
|
|
710
722
|
return `${Math.floor(total / 60)}:${(total % 60).toString().padStart(2, "0")}`;
|
|
711
723
|
}
|
|
712
724
|
//#endregion
|
|
713
|
-
//#region src/core
|
|
725
|
+
//#region src/core/shapes/itemLock.ts
|
|
714
726
|
/**
|
|
715
727
|
* Apply or clear a lock in place. Unlock always drops the holder so a stale
|
|
716
728
|
* name cannot linger on an unlocked item.
|
|
@@ -747,7 +759,7 @@ function serializeLock(item) {
|
|
|
747
759
|
};
|
|
748
760
|
}
|
|
749
761
|
//#endregion
|
|
750
|
-
//#region src/core
|
|
762
|
+
//#region src/core/document/document.ts
|
|
751
763
|
/**
|
|
752
764
|
* The one place a live Stroke becomes its wire representation — in
|
|
753
765
|
* particular, points collapse from {x,y,pressure,erase?} objects into
|
|
@@ -1306,7 +1318,7 @@ function computeBBox(stroke) {
|
|
|
1306
1318
|
return world;
|
|
1307
1319
|
}
|
|
1308
1320
|
//#endregion
|
|
1309
|
-
//#region src/core
|
|
1321
|
+
//#region src/core/commands/commands.ts
|
|
1310
1322
|
/** One drawing action — a marker stroke, or a shape's strokes as one unit. */
|
|
1311
1323
|
var AddStrokesCommand = class {
|
|
1312
1324
|
constructor(strokes) {
|
|
@@ -1648,7 +1660,7 @@ var LockItemsCommand = class {
|
|
|
1648
1660
|
}
|
|
1649
1661
|
};
|
|
1650
1662
|
//#endregion
|
|
1651
|
-
//#region src/core
|
|
1663
|
+
//#region src/core/history/history.ts
|
|
1652
1664
|
var LIMIT = 200;
|
|
1653
1665
|
var History = class {
|
|
1654
1666
|
constructor(doc) {
|
|
@@ -1709,7 +1721,7 @@ var History = class {
|
|
|
1709
1721
|
}
|
|
1710
1722
|
};
|
|
1711
1723
|
//#endregion
|
|
1712
|
-
//#region src/core
|
|
1724
|
+
//#region src/core/events/ops.ts
|
|
1713
1725
|
var ADDED = [
|
|
1714
1726
|
["added", "strokes"],
|
|
1715
1727
|
["notesAdded", "notes"],
|
|
@@ -1763,7 +1775,7 @@ function changeToOps(change, restoring = false) {
|
|
|
1763
1775
|
return ops;
|
|
1764
1776
|
}
|
|
1765
1777
|
//#endregion
|
|
1766
|
-
//#region src/core
|
|
1778
|
+
//#region src/core/shapes/ribbonEdges.ts
|
|
1767
1779
|
var MIN_WIDTH_FACTOR = .35;
|
|
1768
1780
|
var END_TAPER = .55;
|
|
1769
1781
|
function ribbonEdges(points, baseWidth) {
|
|
@@ -1795,7 +1807,7 @@ function ribbonEdges(points, baseWidth) {
|
|
|
1795
1807
|
return out;
|
|
1796
1808
|
}
|
|
1797
1809
|
//#endregion
|
|
1798
|
-
//#region src/core
|
|
1810
|
+
//#region src/core/document/spatialIndex.ts
|
|
1799
1811
|
var CELL = 8;
|
|
1800
1812
|
var SpatialIndex = class {
|
|
1801
1813
|
constructor(doc) {
|
|
@@ -1868,7 +1880,7 @@ function cellsOf(box) {
|
|
|
1868
1880
|
return keys;
|
|
1869
1881
|
}
|
|
1870
1882
|
//#endregion
|
|
1871
|
-
//#region src/core
|
|
1883
|
+
//#region src/core/shapes/stamps.ts
|
|
1872
1884
|
var STAMP_SIZE = 6;
|
|
1873
1885
|
var STAMPS = [
|
|
1874
1886
|
{
|
|
@@ -1917,7 +1929,7 @@ function isStampKind(value) {
|
|
|
1917
1929
|
return typeof value === "string" && STAMPS.some((s) => s.kind === value);
|
|
1918
1930
|
}
|
|
1919
1931
|
//#endregion
|
|
1920
|
-
//#region src/
|
|
1932
|
+
//#region src/collaboration/presence/presence.ts
|
|
1921
1933
|
/** Keep beacons clear of typical chrome at the top and bottom of the Board. */
|
|
1922
1934
|
var BEACON_INSET = {
|
|
1923
1935
|
top: 72,
|
|
@@ -1953,7 +1965,7 @@ function clamp$2(value, min, max) {
|
|
|
1953
1965
|
return Math.min(max, Math.max(min, value));
|
|
1954
1966
|
}
|
|
1955
1967
|
//#endregion
|
|
1956
|
-
//#region src/
|
|
1968
|
+
//#region src/persistence/serialization/svg.ts
|
|
1957
1969
|
/** Matches the key light used by the board shader and note shadows. */
|
|
1958
1970
|
var LIGHT = {
|
|
1959
1971
|
x: -.25,
|
|
@@ -1963,12 +1975,19 @@ var LIGHT = {
|
|
|
1963
1975
|
var MARGIN = 4;
|
|
1964
1976
|
var NOTE_FONT_RATIO = 44 / 512;
|
|
1965
1977
|
var NOTE_PAD_RATIO = 40 / 512;
|
|
1978
|
+
/** Matches the theme system's light-preset `boardSurface` default (theme.ts) — kept in sync manually, since core-internal stays decoupled from the theme layer. */
|
|
1979
|
+
var DEFAULT_BACKGROUND_COLOR = "#f5f5f3";
|
|
1966
1980
|
/**
|
|
1967
1981
|
* `registry` is optional and only enables rendering Custom objects through
|
|
1968
1982
|
* their own `describe()` — without it (or for an object whose extension
|
|
1969
1983
|
* isn't in it), Custom objects still export via the standard fallback
|
|
1970
1984
|
* placeholder (`fallback.bounds`/`label`), never silently dropped.
|
|
1971
1985
|
*
|
|
1986
|
+
* `backgroundColor` should be the Host's actual resolved `boardTheme.surface`
|
|
1987
|
+
* so an export matches what was on screen; defaults to the theme system's
|
|
1988
|
+
* own light-preset default when the caller doesn't have one on hand. The
|
|
1989
|
+
* board's reference grid, if any, is a screen-only aid and never exported.
|
|
1990
|
+
*
|
|
1972
1991
|
* `resolvedAssets` (ticket #23) maps an Asset reference to an already-
|
|
1973
1992
|
* resolved `data:` URI — see `assetExport.ts`'s `exportDocumentSVGWithAssets`,
|
|
1974
1993
|
* which is the only intended caller that ever passes one. Without it, every
|
|
@@ -1976,7 +1995,7 @@ var NOTE_PAD_RATIO = 40 / 512;
|
|
|
1976
1995
|
* placeholder instead of guessing at a URL; a legacy `src`-backed image is
|
|
1977
1996
|
* unaffected either way.
|
|
1978
1997
|
*/
|
|
1979
|
-
function documentToSVG(doc, now = 0, registry, resolvedAssets) {
|
|
1998
|
+
function documentToSVG(doc, now = 0, registry, backgroundColor = DEFAULT_BACKGROUND_COLOR, resolvedAssets) {
|
|
1980
1999
|
const notes = doc.notes ?? [];
|
|
1981
2000
|
const texts = doc.textBlocks ?? [];
|
|
1982
2001
|
const tables = doc.tables ?? [];
|
|
@@ -1989,7 +2008,7 @@ function documentToSVG(doc, now = 0, registry, resolvedAssets) {
|
|
|
1989
2008
|
const highlights = doc.strokes.filter((s) => s.tool === "highlighter");
|
|
1990
2009
|
const ink = doc.strokes.filter((s) => s.tool !== "highlighter");
|
|
1991
2010
|
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${view}">\n<defs>\n${defs}\n</defs>\n${[
|
|
1992
|
-
`<rect x="${fmt(bounds.minX)}" y="${fmt(bounds.minY)}" width="${fmt(bounds.width)}" height="${fmt(bounds.height)}" fill="${
|
|
2011
|
+
`<rect x="${fmt(bounds.minX)}" y="${fmt(bounds.minY)}" width="${fmt(bounds.width)}" height="${fmt(bounds.height)}" fill="${backgroundColor}"/>`,
|
|
1993
2012
|
...images.map((image) => imageToElement(image, resolvedAssets)),
|
|
1994
2013
|
...tables.map(tableToGroup),
|
|
1995
2014
|
...highlights.flatMap(strokeToPaths),
|
|
@@ -2317,7 +2336,7 @@ function fmt(n) {
|
|
|
2317
2336
|
var SDK_PACKAGE_NAME = "@scrawl-board/board";
|
|
2318
2337
|
var SDK_DEVELOPMENT_VERSION = "0.0.0-development";
|
|
2319
2338
|
//#endregion
|
|
2320
|
-
//#region src/core
|
|
2339
|
+
//#region src/core/shapes/sceneGeometry.ts
|
|
2321
2340
|
var EMPTY_BOUNDS = {
|
|
2322
2341
|
x: 0,
|
|
2323
2342
|
y: 0,
|
|
@@ -2381,7 +2400,7 @@ function textCorners(x, y, text, fontSize, align, m) {
|
|
|
2381
2400
|
return rectCorners(x + (align === "center" ? -width / 2 : align === "end" ? -width : 0), y, width, height, m);
|
|
2382
2401
|
}
|
|
2383
2402
|
//#endregion
|
|
2384
|
-
//#region src/core
|
|
2403
|
+
//#region src/core/shapes/customObjects.ts
|
|
2385
2404
|
var FALLBACK_LABEL_MAX_LENGTH = 80;
|
|
2386
2405
|
function toReadonly(object) {
|
|
2387
2406
|
return object;
|
|
@@ -2510,7 +2529,7 @@ function extensionIdFromType(type) {
|
|
|
2510
2529
|
return slash === -1 ? type : type.slice(0, slash);
|
|
2511
2530
|
}
|
|
2512
2531
|
//#endregion
|
|
2513
|
-
//#region src/core
|
|
2532
|
+
//#region src/core/shapes/extensionRegistry.ts
|
|
2514
2533
|
function buildExtensionRegistry(extensions) {
|
|
2515
2534
|
const list = extensions ?? [];
|
|
2516
2535
|
const diagnostics = [];
|
|
@@ -2607,7 +2626,7 @@ function isWellFormedNamespacedId(id) {
|
|
|
2607
2626
|
return isWellFormedId(id) && id.includes("/") && !id.startsWith("/") && !id.endsWith("/");
|
|
2608
2627
|
}
|
|
2609
2628
|
//#endregion
|
|
2610
|
-
//#region src/
|
|
2629
|
+
//#region src/persistence/adapters/assetValidation.ts
|
|
2611
2630
|
function sniffImageMediaType(bytes) {
|
|
2612
2631
|
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";
|
|
2613
2632
|
if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) return "image/jpeg";
|
|
@@ -2694,7 +2713,7 @@ function validateDecodedDimensions(width, height) {
|
|
|
2694
2713
|
};
|
|
2695
2714
|
}
|
|
2696
2715
|
//#endregion
|
|
2697
|
-
//#region src/assetController.ts
|
|
2716
|
+
//#region src/persistence/adapters/assetController.ts
|
|
2698
2717
|
var FAILURE_COALESCE_MS = 4e3;
|
|
2699
2718
|
var AssetController = class {
|
|
2700
2719
|
constructor(resolver, options) {
|
|
@@ -2873,7 +2892,7 @@ function toAssetResolutionError(cause, ref) {
|
|
|
2873
2892
|
return new AssetResolutionError("unknown", true, cause instanceof Error ? cause.message : String(cause), ref);
|
|
2874
2893
|
}
|
|
2875
2894
|
//#endregion
|
|
2876
|
-
//#region src/
|
|
2895
|
+
//#region src/persistence/serialization/assetRefCollector.ts
|
|
2877
2896
|
/** Every unique Asset reference in the document, and which object(s) use it. */
|
|
2878
2897
|
function collectDocumentAssetRefs(doc, registry) {
|
|
2879
2898
|
const refs = /* @__PURE__ */ new Map();
|
|
@@ -2900,7 +2919,7 @@ function collectSceneAssetRefs(node, objectId, add) {
|
|
|
2900
2919
|
if (node.kind === "group") for (const child of node.children) collectSceneAssetRefs(child, objectId, add);
|
|
2901
2920
|
}
|
|
2902
2921
|
//#endregion
|
|
2903
|
-
//#region src/assetExport.ts
|
|
2922
|
+
//#region src/persistence/serialization/assetExport.ts
|
|
2904
2923
|
/** Strict mode's rejection — never contains credentials, a fetchable location, or a raw resolver message. */
|
|
2905
2924
|
var SvgAssetExportError = class extends Error {
|
|
2906
2925
|
constructor(missingAssets) {
|
|
@@ -2909,7 +2928,7 @@ var SvgAssetExportError = class extends Error {
|
|
|
2909
2928
|
this.name = "SvgAssetExportError";
|
|
2910
2929
|
}
|
|
2911
2930
|
};
|
|
2912
|
-
async function exportDocumentSVGWithAssets(doc, now, registry, assetController, options) {
|
|
2931
|
+
async function exportDocumentSVGWithAssets(doc, now, registry, assetController, backgroundColor, options) {
|
|
2913
2932
|
const refs = collectDocumentAssetRefs(doc, registry);
|
|
2914
2933
|
const resolvedAssets = /* @__PURE__ */ new Map();
|
|
2915
2934
|
const missingAssets = [];
|
|
@@ -2945,7 +2964,7 @@ async function exportDocumentSVGWithAssets(doc, now, registry, assetController,
|
|
|
2945
2964
|
}
|
|
2946
2965
|
if (missingAssets.length > 0 && options?.missingAssets !== "placeholder") throw new SvgAssetExportError(missingAssets);
|
|
2947
2966
|
return {
|
|
2948
|
-
svg: documentToSVG(doc, now, registry, resolvedAssets),
|
|
2967
|
+
svg: documentToSVG(doc, now, registry, backgroundColor, resolvedAssets),
|
|
2949
2968
|
missingAssets
|
|
2950
2969
|
};
|
|
2951
2970
|
}
|
|
@@ -2956,7 +2975,7 @@ function toDataUri(bytes, mediaType) {
|
|
|
2956
2975
|
return `data:${mediaType};base64,${btoa(binary)}`;
|
|
2957
2976
|
}
|
|
2958
2977
|
//#endregion
|
|
2959
|
-
//#region src/assetIngestion.ts
|
|
2978
|
+
//#region src/persistence/adapters/assetIngestion.ts
|
|
2960
2979
|
async function decodeDimensionsWithImageBitmap(bytes, mediaType) {
|
|
2961
2980
|
const blob = new Blob([bytes], { type: mediaType });
|
|
2962
2981
|
let bitmap;
|
|
@@ -35602,7 +35621,7 @@ var WebGLRenderer = class {
|
|
|
35602
35621
|
}
|
|
35603
35622
|
};
|
|
35604
35623
|
//#endregion
|
|
35605
|
-
//#region
|
|
35624
|
+
//#region src/core/events/auditEvents.ts
|
|
35606
35625
|
var BY_LABEL = {
|
|
35607
35626
|
draw: {
|
|
35608
35627
|
action: "create",
|
|
@@ -35722,7 +35741,7 @@ function lowerFirst(s) {
|
|
|
35722
35741
|
return s.charAt(0).toLowerCase() + s.slice(1);
|
|
35723
35742
|
}
|
|
35724
35743
|
//#endregion
|
|
35725
|
-
//#region
|
|
35744
|
+
//#region src/renderer/shapes/AssetTextureCache.ts
|
|
35726
35745
|
var AssetTextureCache = class {
|
|
35727
35746
|
constructor(assetController) {
|
|
35728
35747
|
this.assetController = assetController;
|
|
@@ -35813,7 +35832,7 @@ function toDecodeError(cause, ref) {
|
|
|
35813
35832
|
return new AssetResolutionError("decode-failed", false, cause instanceof Error ? cause.message : String(cause), ref);
|
|
35814
35833
|
}
|
|
35815
35834
|
//#endregion
|
|
35816
|
-
//#region
|
|
35835
|
+
//#region src/renderer/canvas/raycast.ts
|
|
35817
35836
|
var origin$1 = new Vector3();
|
|
35818
35837
|
var target = new Vector3();
|
|
35819
35838
|
function pointerToBoard(clientX, clientY, canvas, camera) {
|
|
@@ -35844,7 +35863,7 @@ function pointerToPlane(clientX, clientY, canvas, camera, z) {
|
|
|
35844
35863
|
};
|
|
35845
35864
|
}
|
|
35846
35865
|
//#endregion
|
|
35847
|
-
//#region
|
|
35866
|
+
//#region src/renderer/canvas/fog.ts
|
|
35848
35867
|
function createFogUniforms(color) {
|
|
35849
35868
|
return {
|
|
35850
35869
|
uFogColor: { value: new Color(color) },
|
|
@@ -35865,7 +35884,28 @@ var FOG_GLSL = `
|
|
|
35865
35884
|
}
|
|
35866
35885
|
`;
|
|
35867
35886
|
//#endregion
|
|
35868
|
-
//#region
|
|
35887
|
+
//#region src/renderer/canvas/boardSurface.ts
|
|
35888
|
+
var GRID_MODE_CODE = {
|
|
35889
|
+
none: 0,
|
|
35890
|
+
line: 1,
|
|
35891
|
+
dot: 2
|
|
35892
|
+
};
|
|
35893
|
+
var TEXTURE_CODE = {
|
|
35894
|
+
flat: 0,
|
|
35895
|
+
textured: 1
|
|
35896
|
+
};
|
|
35897
|
+
/** Used when a caller doesn't supply one (e.g. ScrawlEngine constructed without a Host theme). */
|
|
35898
|
+
var DEFAULT_BOARD_SURFACE_THEME = {
|
|
35899
|
+
color: "#f5f5f3",
|
|
35900
|
+
gridMode: "none",
|
|
35901
|
+
gridColor: "#deded8",
|
|
35902
|
+
gridSpacing: 5,
|
|
35903
|
+
gridLineWidth: 1,
|
|
35904
|
+
surfaceTexture: "flat"
|
|
35905
|
+
};
|
|
35906
|
+
/** Grid alpha fades out below this on-screen spacing (px) — otherwise it aliases into a solid wash when zoomed out. */
|
|
35907
|
+
var GRID_FADE_MIN_PX = 3;
|
|
35908
|
+
var GRID_FADE_MAX_PX = 8;
|
|
35869
35909
|
var VERTEX$1 = `
|
|
35870
35910
|
varying vec3 vWorldPos;
|
|
35871
35911
|
void main() {
|
|
@@ -35879,6 +35919,13 @@ var FRAGMENT = `
|
|
|
35879
35919
|
uniform vec3 uFogColor;
|
|
35880
35920
|
uniform float uFogNear;
|
|
35881
35921
|
uniform float uFogFar;
|
|
35922
|
+
uniform float uGridMode;
|
|
35923
|
+
uniform vec3 uGridColor;
|
|
35924
|
+
uniform float uGridSpacing;
|
|
35925
|
+
uniform float uWorldPerPixel;
|
|
35926
|
+
uniform float uGridLineWidthPx;
|
|
35927
|
+
uniform float uGridFade;
|
|
35928
|
+
uniform float uSurfaceTexture;
|
|
35882
35929
|
varying vec3 vWorldPos;
|
|
35883
35930
|
|
|
35884
35931
|
float hash(vec2 p) {
|
|
@@ -35897,33 +35944,69 @@ var FRAGMENT = `
|
|
|
35897
35944
|
|
|
35898
35945
|
${FOG_GLSL}
|
|
35899
35946
|
|
|
35947
|
+
// Distance from p's nearest axis-aligned grid line, in world units.
|
|
35948
|
+
// A crisp, ~uGridLineWidthPx-wide line: full alpha to its half-width, a
|
|
35949
|
+
// ~1px anti-aliased falloff beyond that — not a wide, soft-edged band.
|
|
35950
|
+
float gridLineAlpha(vec2 p) {
|
|
35951
|
+
vec2 cell = mod(p, uGridSpacing);
|
|
35952
|
+
vec2 distToLine = min(cell, uGridSpacing - cell);
|
|
35953
|
+
float halfWidth = 0.5 * uGridLineWidthPx * uWorldPerPixel;
|
|
35954
|
+
float aa = uWorldPerPixel;
|
|
35955
|
+
vec2 lineAlpha2 = 1.0 - smoothstep(halfWidth - aa * 0.5, halfWidth + aa * 0.5, distToLine);
|
|
35956
|
+
return max(lineAlpha2.x, lineAlpha2.y);
|
|
35957
|
+
}
|
|
35958
|
+
|
|
35959
|
+
// Distance from p's nearest grid intersection, in world units. Dot radius
|
|
35960
|
+
// matches the configured line width in pixels, same anti-aliasing.
|
|
35961
|
+
float gridDotAlpha(vec2 p) {
|
|
35962
|
+
vec2 cell = mod(p, uGridSpacing) - uGridSpacing * 0.5;
|
|
35963
|
+
float dist = length(cell);
|
|
35964
|
+
float radius = uGridLineWidthPx * uWorldPerPixel;
|
|
35965
|
+
float aa = uWorldPerPixel;
|
|
35966
|
+
return 1.0 - smoothstep(radius - aa * 0.5, radius + aa * 0.5, dist);
|
|
35967
|
+
}
|
|
35968
|
+
|
|
35900
35969
|
void main() {
|
|
35901
35970
|
vec3 col = uColor;
|
|
35902
35971
|
|
|
35903
|
-
|
|
35904
|
-
|
|
35905
|
-
|
|
35972
|
+
if (uSurfaceTexture > 0.5) {
|
|
35973
|
+
// Melamine micro-texture: two octaves of value noise, +-1.75% brightness.
|
|
35974
|
+
float n = vnoise(vWorldPos.xy * 2.3) * 0.6 + vnoise(vWorldPos.xy * 9.7) * 0.4;
|
|
35975
|
+
col *= 1.0 + (n - 0.5) * 0.035;
|
|
35906
35976
|
|
|
35907
|
-
|
|
35908
|
-
|
|
35909
|
-
|
|
35910
|
-
|
|
35911
|
-
|
|
35912
|
-
|
|
35913
|
-
|
|
35914
|
-
|
|
35915
|
-
|
|
35977
|
+
// Satin sheen: Fresnel rim + a specular band from the key light. Both
|
|
35978
|
+
// are ~zero in the straight-on working view and bloom as the camera tilts.
|
|
35979
|
+
vec3 V = normalize(cameraPosition - vWorldPos);
|
|
35980
|
+
vec3 N = vec3(0.0, 0.0, 1.0);
|
|
35981
|
+
float fres = pow(1.0 - max(dot(N, V), 0.0), 3.0);
|
|
35982
|
+
vec3 L = normalize(vec3(-0.25, 0.4, 0.88));
|
|
35983
|
+
vec3 H = normalize(L + V);
|
|
35984
|
+
float spec = pow(max(dot(N, H), 0.0), 90.0);
|
|
35985
|
+
col += (fres * 0.18 + spec * 0.06) * vec3(1.0);
|
|
35986
|
+
}
|
|
35987
|
+
|
|
35988
|
+
if (uGridMode > 0.5 && uGridFade > 0.001) {
|
|
35989
|
+
float gridAlpha = (uGridMode < 1.5 ? gridLineAlpha(vWorldPos.xy) : gridDotAlpha(vWorldPos.xy)) * uGridFade;
|
|
35990
|
+
col = mix(col, uGridColor, gridAlpha);
|
|
35991
|
+
}
|
|
35916
35992
|
|
|
35917
35993
|
col = applyBoardFog(col, vWorldPos);
|
|
35918
35994
|
gl_FragColor = vec4(col, 1.0);
|
|
35919
35995
|
}
|
|
35920
35996
|
`;
|
|
35921
|
-
function createBoardSurface(fog) {
|
|
35997
|
+
function createBoardSurface(fog, theme) {
|
|
35922
35998
|
const material = new ShaderMaterial({
|
|
35923
35999
|
vertexShader: VERTEX$1,
|
|
35924
36000
|
fragmentShader: FRAGMENT,
|
|
35925
36001
|
uniforms: {
|
|
35926
|
-
uColor: { value: new Color(
|
|
36002
|
+
uColor: { value: new Color(theme.color) },
|
|
36003
|
+
uGridMode: { value: GRID_MODE_CODE[theme.gridMode] },
|
|
36004
|
+
uGridColor: { value: new Color(theme.gridColor) },
|
|
36005
|
+
uGridSpacing: { value: Math.max(.001, theme.gridSpacing) },
|
|
36006
|
+
uGridLineWidthPx: { value: Math.max(.1, theme.gridLineWidth) },
|
|
36007
|
+
uWorldPerPixel: { value: .05 },
|
|
36008
|
+
uGridFade: { value: 0 },
|
|
36009
|
+
uSurfaceTexture: { value: TEXTURE_CODE[theme.surfaceTexture] },
|
|
35927
36010
|
...fog
|
|
35928
36011
|
}
|
|
35929
36012
|
});
|
|
@@ -35931,11 +36014,34 @@ function createBoardSurface(fog) {
|
|
|
35931
36014
|
mesh.name = "board-surface";
|
|
35932
36015
|
return mesh;
|
|
35933
36016
|
}
|
|
35934
|
-
/**
|
|
35935
|
-
function
|
|
36017
|
+
/** Applies a theme change (initial or live) — everything except the per-frame fade/pixel-ratio. */
|
|
36018
|
+
function setBoardSurfaceTheme(mesh, theme) {
|
|
36019
|
+
const uniforms = mesh.material.uniforms;
|
|
36020
|
+
uniforms.uColor.value.set(theme.color);
|
|
36021
|
+
uniforms.uGridMode.value = GRID_MODE_CODE[theme.gridMode];
|
|
36022
|
+
uniforms.uGridColor.value.set(theme.gridColor);
|
|
36023
|
+
uniforms.uGridSpacing.value = Math.max(.001, theme.gridSpacing);
|
|
36024
|
+
uniforms.uGridLineWidthPx.value = Math.max(.1, theme.gridLineWidth);
|
|
36025
|
+
uniforms.uSurfaceTexture.value = TEXTURE_CODE[theme.surfaceTexture];
|
|
36026
|
+
}
|
|
36027
|
+
/** Keep the plane centered under the view, larger than the fog horizon, and the grid's on-screen weight/fade current. */
|
|
36028
|
+
function updateBoardSurface(mesh, centerX, centerY, fogFar, worldPerPixel) {
|
|
35936
36029
|
mesh.position.set(centerX, centerY, 0);
|
|
35937
36030
|
const size = fogFar * 2.5;
|
|
35938
36031
|
mesh.scale.set(size, size, 1);
|
|
36032
|
+
const uniforms = mesh.material.uniforms;
|
|
36033
|
+
uniforms.uWorldPerPixel.value = worldPerPixel;
|
|
36034
|
+
const t = (uniforms.uGridSpacing.value / Math.max(1e-6, worldPerPixel) - GRID_FADE_MIN_PX) / (GRID_FADE_MAX_PX - GRID_FADE_MIN_PX);
|
|
36035
|
+
uniforms.uGridFade.value = MathUtils.clamp(t, 0, 1);
|
|
36036
|
+
}
|
|
36037
|
+
/** Temporarily zeroes the grid's contribution (for export snapshots) and returns a restore function. */
|
|
36038
|
+
function suppressBoardSurfaceGrid(mesh) {
|
|
36039
|
+
const uniforms = mesh.material.uniforms;
|
|
36040
|
+
const previous = uniforms.uGridFade.value;
|
|
36041
|
+
uniforms.uGridFade.value = 0;
|
|
36042
|
+
return () => {
|
|
36043
|
+
uniforms.uGridFade.value = previous;
|
|
36044
|
+
};
|
|
35939
36045
|
}
|
|
35940
36046
|
var MIN_HEIGHT = 40;
|
|
35941
36047
|
var MAX_HEIGHT = 1500;
|
|
@@ -36097,9 +36203,9 @@ var CameraRig = class {
|
|
|
36097
36203
|
}
|
|
36098
36204
|
};
|
|
36099
36205
|
//#endregion
|
|
36100
|
-
//#region
|
|
36206
|
+
//#region src/renderer/canvas/scene.ts
|
|
36101
36207
|
var SceneRig = class {
|
|
36102
|
-
constructor(canvas) {
|
|
36208
|
+
constructor(canvas, boardTheme) {
|
|
36103
36209
|
this.renderer = new WebGLRenderer({
|
|
36104
36210
|
canvas,
|
|
36105
36211
|
antialias: true
|
|
@@ -36109,7 +36215,7 @@ var SceneRig = class {
|
|
|
36109
36215
|
this.scene = new Scene();
|
|
36110
36216
|
this.cameraRig = new CameraRig(canvas.clientWidth / Math.max(1, canvas.clientHeight));
|
|
36111
36217
|
this.fog = createFogUniforms(FOG_COLOR);
|
|
36112
|
-
this.board = createBoardSurface(this.fog);
|
|
36218
|
+
this.board = createBoardSurface(this.fog, boardTheme);
|
|
36113
36219
|
this.scene.add(this.board);
|
|
36114
36220
|
this.inkGroup = new Group();
|
|
36115
36221
|
this.inkGroup.name = "ink";
|
|
@@ -36126,9 +36232,17 @@ var SceneRig = class {
|
|
|
36126
36232
|
renderFrame(dtMs) {
|
|
36127
36233
|
this.cameraRig.update(dtMs);
|
|
36128
36234
|
updateFogForCamera(this.fog, this.cameraRig.height);
|
|
36129
|
-
updateBoardSurface(this.board, this.cameraRig.center.x, this.cameraRig.center.y, this.fog.uFogFar.value);
|
|
36235
|
+
updateBoardSurface(this.board, this.cameraRig.center.x, this.cameraRig.center.y, this.fog.uFogFar.value, this.cameraRig.worldPerPixel());
|
|
36130
36236
|
this.renderer.render(this.scene, this.cameraRig.camera);
|
|
36131
36237
|
}
|
|
36238
|
+
/** Live theme update — the board controller's identity stays fixed across theme changes; this is how a new one reaches the render engine. */
|
|
36239
|
+
applyBoardTheme(theme) {
|
|
36240
|
+
setBoardSurfaceTheme(this.board, theme);
|
|
36241
|
+
}
|
|
36242
|
+
/** Zeroes the grid for one render pass (PNG export never bakes it in) and returns a restore function. */
|
|
36243
|
+
suppressGrid() {
|
|
36244
|
+
return suppressBoardSurfaceGrid(this.board);
|
|
36245
|
+
}
|
|
36132
36246
|
dispose() {
|
|
36133
36247
|
this.board.geometry.dispose();
|
|
36134
36248
|
this.board.material.dispose();
|
|
@@ -36136,7 +36250,7 @@ var SceneRig = class {
|
|
|
36136
36250
|
}
|
|
36137
36251
|
};
|
|
36138
36252
|
//#endregion
|
|
36139
|
-
//#region
|
|
36253
|
+
//#region src/renderer/shapes/inkMaterial.ts
|
|
36140
36254
|
var VERTEX = `
|
|
36141
36255
|
attribute float aAlpha;
|
|
36142
36256
|
varying vec2 vUv;
|
|
@@ -36267,7 +36381,7 @@ var InkMaterials = class {
|
|
|
36267
36381
|
}
|
|
36268
36382
|
};
|
|
36269
36383
|
//#endregion
|
|
36270
|
-
//#region
|
|
36384
|
+
//#region src/renderer/shapes/ribbonGeometry.ts
|
|
36271
36385
|
/** Ink floats a hair above the board to avoid z-fighting with the surface. */
|
|
36272
36386
|
var INK_Z = .02;
|
|
36273
36387
|
/** Highlighter always renders under opaque ink (build prompt §4.1). */
|
|
@@ -36318,7 +36432,7 @@ function buildRibbonGeometry(points, baseWidth, z = INK_Z) {
|
|
|
36318
36432
|
return geometry;
|
|
36319
36433
|
}
|
|
36320
36434
|
//#endregion
|
|
36321
|
-
//#region
|
|
36435
|
+
//#region src/renderer/shapes/strokeRenderer.ts
|
|
36322
36436
|
var strokeZ = (stroke) => stroke.tool === "highlighter" ? HIGHLIGHT_Z : INK_Z;
|
|
36323
36437
|
/**
|
|
36324
36438
|
* Derives ink meshes from the document by subscription — the document never
|
|
@@ -36451,7 +36565,7 @@ function syncMatrix(mesh, stroke) {
|
|
|
36451
36565
|
mesh.matrixWorldNeedsUpdate = true;
|
|
36452
36566
|
}
|
|
36453
36567
|
//#endregion
|
|
36454
|
-
//#region
|
|
36568
|
+
//#region src/renderer/shapes/markerProp.ts
|
|
36455
36569
|
var BODY_LENGTH = 11;
|
|
36456
36570
|
var BODY_RADIUS = .85;
|
|
36457
36571
|
var TIP_LENGTH = 1.6;
|
|
@@ -36547,7 +36661,7 @@ var MarkerProp = class {
|
|
|
36547
36661
|
}
|
|
36548
36662
|
};
|
|
36549
36663
|
//#endregion
|
|
36550
|
-
//#region
|
|
36664
|
+
//#region src/renderer/shapes/noteGeometry.ts
|
|
36551
36665
|
/**
|
|
36552
36666
|
* Height of the sheet above the board at (u, v) ∈ [0,1]².
|
|
36553
36667
|
* v = 1 is the adhesive edge (always 0); u = 1 is the peel corner side.
|
|
@@ -36591,7 +36705,7 @@ function applyCurl(geometry, curl, peel) {
|
|
|
36591
36705
|
color.needsUpdate = true;
|
|
36592
36706
|
}
|
|
36593
36707
|
//#endregion
|
|
36594
|
-
//#region
|
|
36708
|
+
//#region src/renderer/shapes/stickyNotes.ts
|
|
36595
36709
|
var TEXTURE_SIZE = 512;
|
|
36596
36710
|
var FOCUS_COLOR$4 = 2450411;
|
|
36597
36711
|
var CURL = .3;
|
|
@@ -43167,7 +43281,7 @@ SYNCABLE_PROPS.forEach((prop) => {
|
|
|
43167
43281
|
new Box3();
|
|
43168
43282
|
new Color();
|
|
43169
43283
|
//#endregion
|
|
43170
|
-
//#region
|
|
43284
|
+
//#region src/renderer/shapes/tables.ts
|
|
43171
43285
|
var FONT_URL$2 = "/fonts/inter-medium.woff";
|
|
43172
43286
|
var TABLE_Z = .012;
|
|
43173
43287
|
var HEADER_Z = .014;
|
|
@@ -43516,7 +43630,7 @@ var TablesRenderer = class {
|
|
|
43516
43630
|
}
|
|
43517
43631
|
};
|
|
43518
43632
|
//#endregion
|
|
43519
|
-
//#region
|
|
43633
|
+
//#region src/renderer/text/textBlocks.ts
|
|
43520
43634
|
var FONT_URL$1 = "/fonts/inter-medium.woff";
|
|
43521
43635
|
var TEXT_Z = .02;
|
|
43522
43636
|
var FOCUS_COLOR$2 = 2450411;
|
|
@@ -43620,7 +43734,7 @@ var TextBlocksRenderer = class {
|
|
|
43620
43734
|
}
|
|
43621
43735
|
};
|
|
43622
43736
|
//#endregion
|
|
43623
|
-
//#region
|
|
43737
|
+
//#region src/renderer/shapes/comments.ts
|
|
43624
43738
|
var PIN_Z = .04;
|
|
43625
43739
|
var PIN_WIDTH = 3.6;
|
|
43626
43740
|
var PIN_HEIGHT = 3.6;
|
|
@@ -43788,7 +43902,7 @@ function drawBubblePath(ctx, x, y, w, h, r, tailX, tailY, tailW) {
|
|
|
43788
43902
|
ctx.closePath();
|
|
43789
43903
|
}
|
|
43790
43904
|
//#endregion
|
|
43791
|
-
//#region
|
|
43905
|
+
//#region src/renderer/shapes/images.ts
|
|
43792
43906
|
var IMAGE_Z = .015;
|
|
43793
43907
|
var FRAME_BORDER = .4;
|
|
43794
43908
|
var FOCUS_COLOR$1 = 2450411;
|
|
@@ -43998,7 +44112,7 @@ function applyPlaceholderTexture(visual, label) {
|
|
|
43998
44112
|
visual.imageMesh.material.needsUpdate = true;
|
|
43999
44113
|
}
|
|
44000
44114
|
//#endregion
|
|
44001
|
-
//#region
|
|
44115
|
+
//#region src/renderer/shapes/kitchenTimers.ts
|
|
44002
44116
|
var FACE_SIZE = 256;
|
|
44003
44117
|
var BODY_COLOR = 14753096;
|
|
44004
44118
|
var KNOB_COLOR = 16448250;
|
|
@@ -44196,7 +44310,7 @@ function renderTimerFace(timer, canvas, now = Date.now()) {
|
|
|
44196
44310
|
return c;
|
|
44197
44311
|
}
|
|
44198
44312
|
//#endregion
|
|
44199
|
-
//#region
|
|
44313
|
+
//#region src/renderer/shapes/customObjects.ts
|
|
44200
44314
|
var FONT_URL = "/fonts/inter-medium.woff";
|
|
44201
44315
|
var CUSTOM_Z = .02;
|
|
44202
44316
|
var FOCUS_COLOR = 2450411;
|
|
@@ -44558,7 +44672,7 @@ function disposeObject3D(obj) {
|
|
|
44558
44672
|
});
|
|
44559
44673
|
}
|
|
44560
44674
|
//#endregion
|
|
44561
|
-
//#region
|
|
44675
|
+
//#region src/interaction/pointer/hitTest.ts
|
|
44562
44676
|
/** Topmost (most recently added) stroke under the point, or null. */
|
|
44563
44677
|
function hitStroke(doc, index, p, slop) {
|
|
44564
44678
|
const candidates = index.query(p.x - slop, p.y - slop, p.x + slop, p.y + slop);
|
|
@@ -44599,7 +44713,7 @@ function distToSegmentSq(p, a, b) {
|
|
|
44599
44713
|
return dx * dx + dy * dy;
|
|
44600
44714
|
}
|
|
44601
44715
|
//#endregion
|
|
44602
|
-
//#region
|
|
44716
|
+
//#region src/interaction/tools/eraserTool.ts
|
|
44603
44717
|
var DECAY_PER_PASS = .4;
|
|
44604
44718
|
/** A point can take another decay pass after this long — rubbing works. */
|
|
44605
44719
|
var REARM_MS = 250;
|
|
@@ -44727,7 +44841,7 @@ function partitionByErasure(points) {
|
|
|
44727
44841
|
return runs;
|
|
44728
44842
|
}
|
|
44729
44843
|
//#endregion
|
|
44730
|
-
//#region
|
|
44844
|
+
//#region src/interaction/tools/noteDrag.ts
|
|
44731
44845
|
/**
|
|
44732
44846
|
* Drag the focused note in X/Y. The grab is resolved on the note's own
|
|
44733
44847
|
* z-plane, not the board, so the note doesn't jump under a tilted ray.
|
|
@@ -44794,7 +44908,7 @@ var NoteDragState = class {
|
|
|
44794
44908
|
}
|
|
44795
44909
|
};
|
|
44796
44910
|
//#endregion
|
|
44797
|
-
//#region
|
|
44911
|
+
//#region src/interaction/tools/imageDrag.ts
|
|
44798
44912
|
/** Drag the focused image in X/Y; one command per drag. */
|
|
44799
44913
|
var ImageDragState = class {
|
|
44800
44914
|
constructor(ctx) {
|
|
@@ -44846,7 +44960,7 @@ var ImageDragState = class {
|
|
|
44846
44960
|
}
|
|
44847
44961
|
};
|
|
44848
44962
|
//#endregion
|
|
44849
|
-
//#region
|
|
44963
|
+
//#region src/interaction/tools/timerDrag.ts
|
|
44850
44964
|
/** Drag the focused timer in X/Y; one command per drag. */
|
|
44851
44965
|
var TimerDragState = class {
|
|
44852
44966
|
constructor(ctx) {
|
|
@@ -44898,7 +45012,7 @@ var TimerDragState = class {
|
|
|
44898
45012
|
}
|
|
44899
45013
|
};
|
|
44900
45014
|
//#endregion
|
|
44901
|
-
//#region
|
|
45015
|
+
//#region src/interaction/tools/shapeGeometry.ts
|
|
44902
45016
|
/** Uniform synthetic pressure; the ink shader supplies the hand-drawn feel. */
|
|
44903
45017
|
var PRESSURE = .7;
|
|
44904
45018
|
var MIN_ELLIPSE_SEGMENTS = 24;
|
|
@@ -45087,7 +45201,7 @@ function snappedEnd(a, b) {
|
|
|
45087
45201
|
};
|
|
45088
45202
|
}
|
|
45089
45203
|
//#endregion
|
|
45090
|
-
//#region
|
|
45204
|
+
//#region src/interaction/tools/shapeTool.ts
|
|
45091
45205
|
var MIN_DRAG_PX$1 = 4;
|
|
45092
45206
|
/** Drag out a shape; live preview through the real ink material. */
|
|
45093
45207
|
var ShapeTool = class {
|
|
@@ -45118,7 +45232,7 @@ var ShapeTool = class {
|
|
|
45118
45232
|
const strokes = this.polylines.map((points) => ({
|
|
45119
45233
|
id: crypto.randomUUID(),
|
|
45120
45234
|
color: this.ctx.inkColor(),
|
|
45121
|
-
baseWidth: this.ctx.
|
|
45235
|
+
baseWidth: this.ctx.shapeStrokeWidth(),
|
|
45122
45236
|
points
|
|
45123
45237
|
}));
|
|
45124
45238
|
this.ctx.clusters.assign(strokes[0]);
|
|
@@ -45152,13 +45266,13 @@ var ShapeTool = class {
|
|
|
45152
45266
|
this.previews[i].visible = polyline !== void 0;
|
|
45153
45267
|
if (polyline) {
|
|
45154
45268
|
this.previews[i].geometry.dispose();
|
|
45155
|
-
this.previews[i].geometry = buildRibbonGeometry(polyline, this.ctx.
|
|
45269
|
+
this.previews[i].geometry = buildRibbonGeometry(polyline, this.ctx.shapeStrokeWidth());
|
|
45156
45270
|
}
|
|
45157
45271
|
}
|
|
45158
45272
|
}
|
|
45159
45273
|
};
|
|
45160
45274
|
//#endregion
|
|
45161
|
-
//#region
|
|
45275
|
+
//#region src/interaction/tools/tableDrag.ts
|
|
45162
45276
|
function getHandleCursor(handle) {
|
|
45163
45277
|
switch (handle) {
|
|
45164
45278
|
case "nw":
|
|
@@ -45278,7 +45392,7 @@ var TableDragState = class {
|
|
|
45278
45392
|
}
|
|
45279
45393
|
};
|
|
45280
45394
|
//#endregion
|
|
45281
|
-
//#region
|
|
45395
|
+
//#region src/interaction/tools/tableTool.ts
|
|
45282
45396
|
var MIN_DRAG_PX = 6;
|
|
45283
45397
|
var TableTool = class {
|
|
45284
45398
|
constructor(ctx) {
|
|
@@ -45409,7 +45523,7 @@ var TableTool = class {
|
|
|
45409
45523
|
}
|
|
45410
45524
|
};
|
|
45411
45525
|
//#endregion
|
|
45412
|
-
//#region
|
|
45526
|
+
//#region src/interaction/tools/commentTool.ts
|
|
45413
45527
|
/** Click on the board to drop a new comment pin or open an existing one. */
|
|
45414
45528
|
var CommentTool = class {
|
|
45415
45529
|
constructor(ctx) {
|
|
@@ -45444,7 +45558,7 @@ var CommentTool = class {
|
|
|
45444
45558
|
}
|
|
45445
45559
|
};
|
|
45446
45560
|
//#endregion
|
|
45447
|
-
//#region
|
|
45561
|
+
//#region src/interaction/tools/textDrag.ts
|
|
45448
45562
|
/** Drag the focused text block in X/Y; one command per drag. */
|
|
45449
45563
|
var TextDragState = class {
|
|
45450
45564
|
constructor(ctx) {
|
|
@@ -45496,7 +45610,7 @@ var TextDragState = class {
|
|
|
45496
45610
|
}
|
|
45497
45611
|
};
|
|
45498
45612
|
//#endregion
|
|
45499
|
-
//#region
|
|
45613
|
+
//#region src/interaction/tools/fsm.ts
|
|
45500
45614
|
var ToolStateMachine = class {
|
|
45501
45615
|
constructor() {
|
|
45502
45616
|
this.states = /* @__PURE__ */ new Map();
|
|
@@ -45698,7 +45812,7 @@ var IdleState = class {
|
|
|
45698
45812
|
}
|
|
45699
45813
|
};
|
|
45700
45814
|
//#endregion
|
|
45701
|
-
//#region
|
|
45815
|
+
//#region src/renderer/selection/gizmo.ts
|
|
45702
45816
|
var GIZMO_Z = .05;
|
|
45703
45817
|
var HANDLE_PX = 9;
|
|
45704
45818
|
var HANDLE_HIT_PX = 12;
|
|
@@ -45929,7 +46043,7 @@ function boxesEqual(a, b) {
|
|
|
45929
46043
|
return a.minX === b.minX && a.minY === b.minY && a.maxX === b.maxX && a.maxY === b.maxY;
|
|
45930
46044
|
}
|
|
45931
46045
|
//#endregion
|
|
45932
|
-
//#region
|
|
46046
|
+
//#region src/interaction/tools/pressure.ts
|
|
45933
46047
|
var SIM_MAX = 1;
|
|
45934
46048
|
var SIM_MIN = .3;
|
|
45935
46049
|
var SMOOTHING = .25;
|
|
@@ -45951,7 +46065,7 @@ function clamp(v, lo, hi) {
|
|
|
45951
46065
|
return Math.min(hi, Math.max(lo, v));
|
|
45952
46066
|
}
|
|
45953
46067
|
//#endregion
|
|
45954
|
-
//#region
|
|
46068
|
+
//#region src/interaction/tools/strokeBuilder.ts
|
|
45955
46069
|
var StrokeBuilder = class {
|
|
45956
46070
|
constructor() {
|
|
45957
46071
|
this.points = [];
|
|
@@ -46001,7 +46115,7 @@ function catmullRom(v0, v1, v2, v3, t) {
|
|
|
46001
46115
|
return .5 * (2 * v1 + (-v0 + v2) * t + (2 * v0 - 5 * v1 + 4 * v2 - v3) * t2 + (-v0 + 3 * v1 - 3 * v2 + v3) * t3);
|
|
46002
46116
|
}
|
|
46003
46117
|
//#endregion
|
|
46004
|
-
//#region
|
|
46118
|
+
//#region src/interaction/tools/markerTool.ts
|
|
46005
46119
|
/** Sample spacing while drawing, in screen pixels. */
|
|
46006
46120
|
var MIN_SAMPLE_PX = 1.5;
|
|
46007
46121
|
/** A highlighter is a chisel tip: near-constant width, little pressure play. */
|
|
@@ -46104,7 +46218,7 @@ var MarkerTool = class {
|
|
|
46104
46218
|
}
|
|
46105
46219
|
};
|
|
46106
46220
|
//#endregion
|
|
46107
|
-
//#region
|
|
46221
|
+
//#region src/interaction/tools/orbitTool.ts
|
|
46108
46222
|
/**
|
|
46109
46223
|
* Orbit-preview (build prompt §4.2): alt-drag tilts the camera off-axis to
|
|
46110
46224
|
* read the board's material and depth; releasing eases back to the working
|
|
@@ -46139,7 +46253,7 @@ var OrbitTool = class {
|
|
|
46139
46253
|
}
|
|
46140
46254
|
};
|
|
46141
46255
|
//#endregion
|
|
46142
|
-
//#region
|
|
46256
|
+
//#region src/interaction/tools/panTool.ts
|
|
46143
46257
|
/** Grab-pan: content follows the pointer. */
|
|
46144
46258
|
var PanTool = class {
|
|
46145
46259
|
constructor(ctx) {
|
|
@@ -46169,7 +46283,7 @@ var PanTool = class {
|
|
|
46169
46283
|
}
|
|
46170
46284
|
};
|
|
46171
46285
|
//#endregion
|
|
46172
|
-
//#region
|
|
46286
|
+
//#region src/renderer/selection/selection.ts
|
|
46173
46287
|
/** The set of selected stroke ids. Drops ids the document no longer has. */
|
|
46174
46288
|
var SelectionManager = class {
|
|
46175
46289
|
constructor(doc) {
|
|
@@ -46220,7 +46334,7 @@ var SelectionManager = class {
|
|
|
46220
46334
|
}
|
|
46221
46335
|
};
|
|
46222
46336
|
//#endregion
|
|
46223
|
-
//#region
|
|
46337
|
+
//#region src/interaction/tools/selectTool.ts
|
|
46224
46338
|
var HIT_SLOP_PX = 4;
|
|
46225
46339
|
var CLICK_TOLERANCE_PX = 3;
|
|
46226
46340
|
var MIN_SCALE = .05;
|
|
@@ -46436,7 +46550,7 @@ function safeRatio(numerator, denominator) {
|
|
|
46436
46550
|
return raw;
|
|
46437
46551
|
}
|
|
46438
46552
|
//#endregion
|
|
46439
|
-
//#region
|
|
46553
|
+
//#region src/interaction/tools/customTool.ts
|
|
46440
46554
|
function extensionIdFromToolId(toolId) {
|
|
46441
46555
|
const slash = toolId.indexOf("/");
|
|
46442
46556
|
return slash === -1 ? toolId : toolId.slice(0, slash);
|
|
@@ -46551,12 +46665,19 @@ var ExtensionCommandBatch = class {
|
|
|
46551
46665
|
}
|
|
46552
46666
|
};
|
|
46553
46667
|
//#endregion
|
|
46554
|
-
//#region
|
|
46668
|
+
//#region src/composition/ScrawlEngine.ts
|
|
46555
46669
|
/** Marker stroke width in board units (~1% of the default view height). */
|
|
46556
46670
|
var BASE_WIDTH = .5;
|
|
46557
46671
|
/** Highlighter chisel width — wide enough to cover a line of handwriting. */
|
|
46558
46672
|
var HIGHLIGHT_WIDTH = 2.2;
|
|
46559
46673
|
/**
|
|
46674
|
+
* Shape (rectangle, ellipse, arrow, ...) border width in board units.
|
|
46675
|
+
* Deliberately thinner than BASE_WIDTH: a shape border reads as a crisp,
|
|
46676
|
+
* structural line, not an expressive marker stroke — this is also the
|
|
46677
|
+
* fallback when no Host theme configures ScrawlTheme.shapeStrokeWidth.
|
|
46678
|
+
*/
|
|
46679
|
+
var DEFAULT_SHAPE_STROKE_WIDTH = .15;
|
|
46680
|
+
/**
|
|
46560
46681
|
* Identity of a rendered selection badge: which item, its lock state, and
|
|
46561
46682
|
* where it sits on screen (rounded to the pixel, so sub-pixel camera drift
|
|
46562
46683
|
* does not churn React).
|
|
@@ -46577,9 +46698,11 @@ function emptyExtensionRegistry() {
|
|
|
46577
46698
|
* React never reaches past this class.
|
|
46578
46699
|
*/
|
|
46579
46700
|
var ScrawlEngine = class {
|
|
46580
|
-
constructor(canvas, documentId$1, extensionRegistry = emptyExtensionRegistry(), assetController = new AssetController(void 0)) {
|
|
46701
|
+
constructor(canvas, documentId$1, extensionRegistry = emptyExtensionRegistry(), assetController = new AssetController(void 0), boardTheme = DEFAULT_BOARD_SURFACE_THEME, shapeStrokeWidth = DEFAULT_SHAPE_STROKE_WIDTH) {
|
|
46581
46702
|
this.canvas = canvas;
|
|
46582
46703
|
this.extensionRegistry = extensionRegistry;
|
|
46704
|
+
this.boardTheme = boardTheme;
|
|
46705
|
+
this.shapeStrokeWidth = shapeStrokeWidth;
|
|
46583
46706
|
this.onToolChange = null;
|
|
46584
46707
|
this.onZoomChange = null;
|
|
46585
46708
|
this.onAuditEvent = null;
|
|
@@ -46626,7 +46749,7 @@ var ScrawlEngine = class {
|
|
|
46626
46749
|
this.stampKind = "star";
|
|
46627
46750
|
this.timerDurationMs = TIMER_DEFAULT_DURATION_MS;
|
|
46628
46751
|
this.readOnly = false;
|
|
46629
|
-
this.scene = new SceneRig(canvas);
|
|
46752
|
+
this.scene = new SceneRig(canvas, boardTheme);
|
|
46630
46753
|
this.document = new BoardDocument(documentId(documentId$1));
|
|
46631
46754
|
this.history = new History(this.document);
|
|
46632
46755
|
this.history.onCommand = (command, kind) => {
|
|
@@ -46674,6 +46797,7 @@ var ScrawlEngine = class {
|
|
|
46674
46797
|
setTool: (t) => this.setTool(t),
|
|
46675
46798
|
inkColor: () => this.tool === "highlighter" ? this.highlightColor : this.color,
|
|
46676
46799
|
baseWidth: () => this.tool === "highlighter" ? HIGHLIGHT_WIDTH : BASE_WIDTH,
|
|
46800
|
+
shapeStrokeWidth: () => this.shapeStrokeWidth,
|
|
46677
46801
|
activeTool: () => this.tool,
|
|
46678
46802
|
isSpaceHeld: () => this.spaceHeld,
|
|
46679
46803
|
pointerToBoard: (e) => pointerToBoard(e.clientX, e.clientY, canvas, this.scene.cameraRig.camera),
|
|
@@ -46933,6 +47057,15 @@ var ScrawlEngine = class {
|
|
|
46933
47057
|
height: rig.height
|
|
46934
47058
|
};
|
|
46935
47059
|
}
|
|
47060
|
+
/** Live update of the board surface color/grid — the engine's identity stays fixed across theme changes. */
|
|
47061
|
+
applyBoardTheme(theme) {
|
|
47062
|
+
this.boardTheme = theme;
|
|
47063
|
+
this.scene.applyBoardTheme(theme);
|
|
47064
|
+
}
|
|
47065
|
+
/** Live update of the shape tool's border width (board units). Already-drawn shapes keep the width they were drawn with. */
|
|
47066
|
+
setShapeStrokeWidth(width) {
|
|
47067
|
+
this.shapeStrokeWidth = width;
|
|
47068
|
+
}
|
|
46936
47069
|
/**
|
|
46937
47070
|
* Snap to a peer's camera. No-op while drawing so pointer-to-board
|
|
46938
47071
|
* mapping does not warp the in-progress stroke.
|
|
@@ -46951,7 +47084,7 @@ var ScrawlEngine = class {
|
|
|
46951
47084
|
}
|
|
46952
47085
|
/** The saved document as standalone SVG — a pure walk of the wire format. */
|
|
46953
47086
|
exportSVG() {
|
|
46954
|
-
return documentToSVG(this.document.toJSON(), Date.now(), this.extensionRegistry);
|
|
47087
|
+
return documentToSVG(this.document.toJSON(), Date.now(), this.extensionRegistry, this.boardTheme.color);
|
|
46955
47088
|
}
|
|
46956
47089
|
/**
|
|
46957
47090
|
* Content-framed PNG snapshot. Renders once offscreen-style with UI props
|
|
@@ -46987,6 +47120,7 @@ var ScrawlEngine = class {
|
|
|
46987
47120
|
this.notesRenderer.setFocus(null);
|
|
46988
47121
|
this.textsRenderer.setFocus(null);
|
|
46989
47122
|
this.renderer.setGhostsVisible(false);
|
|
47123
|
+
const restoreGrid = this.scene.suppressGrid();
|
|
46990
47124
|
try {
|
|
46991
47125
|
rig.yaw = 0;
|
|
46992
47126
|
rig.pitch = 0;
|
|
@@ -46997,6 +47131,7 @@ var ScrawlEngine = class {
|
|
|
46997
47131
|
const dataUrl = this.scene.renderer.domElement.toDataURL("image/png");
|
|
46998
47132
|
return await (await fetch(dataUrl)).blob();
|
|
46999
47133
|
} finally {
|
|
47134
|
+
restoreGrid();
|
|
47000
47135
|
rig.center.x = saved.x;
|
|
47001
47136
|
rig.center.y = saved.y;
|
|
47002
47137
|
rig.height = saved.height;
|
|
@@ -47992,7 +48127,7 @@ var ScrawlEngine = class {
|
|
|
47992
48127
|
}
|
|
47993
48128
|
};
|
|
47994
48129
|
//#endregion
|
|
47995
|
-
//#region src/controller-internal.ts
|
|
48130
|
+
//#region src/composition/controller-internal.ts
|
|
47996
48131
|
function createBoardController(options) {
|
|
47997
48132
|
return createBoardControllerWithEngine(options);
|
|
47998
48133
|
}
|
|
@@ -48006,7 +48141,16 @@ function createBoardControllerWithEngine(options, existingEngine) {
|
|
|
48006
48141
|
}
|
|
48007
48142
|
const extensionRegistry = registryResult.registry;
|
|
48008
48143
|
const assetController = new AssetController(options.assetResolver, { cacheBytes: options.assetCacheBytes });
|
|
48009
|
-
|
|
48144
|
+
let currentBoardTheme = {
|
|
48145
|
+
color: options.boardTheme?.surface ?? DEFAULT_BOARD_SURFACE_THEME.color,
|
|
48146
|
+
gridMode: options.boardTheme?.gridMode ?? DEFAULT_BOARD_SURFACE_THEME.gridMode,
|
|
48147
|
+
gridColor: options.boardTheme?.gridColor ?? DEFAULT_BOARD_SURFACE_THEME.gridColor,
|
|
48148
|
+
gridSpacing: options.boardTheme?.gridSpacing ?? DEFAULT_BOARD_SURFACE_THEME.gridSpacing,
|
|
48149
|
+
gridLineWidth: options.boardTheme?.gridLineWidth ?? DEFAULT_BOARD_SURFACE_THEME.gridLineWidth,
|
|
48150
|
+
surfaceTexture: options.boardTheme?.surfaceTexture ?? DEFAULT_BOARD_SURFACE_THEME.surfaceTexture
|
|
48151
|
+
};
|
|
48152
|
+
let currentShapeStrokeWidth = options.boardTheme?.shapeStrokeWidth ?? .15;
|
|
48153
|
+
const engine = existingEngine ?? (options.canvas ? new ScrawlEngine(options.canvas, options.document.id, extensionRegistry, assetController, currentBoardTheme, currentShapeStrokeWidth) : null);
|
|
48010
48154
|
const document = engine?.document ?? new BoardDocument(documentId(options.document.id));
|
|
48011
48155
|
const history = engine?.history ?? new History(document);
|
|
48012
48156
|
const createId = options.createId ?? (() => crypto.randomUUID());
|
|
@@ -48490,6 +48634,21 @@ function createBoardControllerWithEngine(options, existingEngine) {
|
|
|
48490
48634
|
changed();
|
|
48491
48635
|
}
|
|
48492
48636
|
},
|
|
48637
|
+
boardTheme: { set(theme) {
|
|
48638
|
+
currentBoardTheme = {
|
|
48639
|
+
color: theme.surface ?? currentBoardTheme.color,
|
|
48640
|
+
gridMode: theme.gridMode ?? currentBoardTheme.gridMode,
|
|
48641
|
+
gridColor: theme.gridColor ?? currentBoardTheme.gridColor,
|
|
48642
|
+
gridSpacing: theme.gridSpacing ?? currentBoardTheme.gridSpacing,
|
|
48643
|
+
gridLineWidth: theme.gridLineWidth ?? currentBoardTheme.gridLineWidth,
|
|
48644
|
+
surfaceTexture: theme.surfaceTexture ?? currentBoardTheme.surfaceTexture
|
|
48645
|
+
};
|
|
48646
|
+
engine?.applyBoardTheme(currentBoardTheme);
|
|
48647
|
+
if (theme.shapeStrokeWidth !== void 0) {
|
|
48648
|
+
currentShapeStrokeWidth = theme.shapeStrokeWidth;
|
|
48649
|
+
engine?.setShapeStrokeWidth(currentShapeStrokeWidth);
|
|
48650
|
+
}
|
|
48651
|
+
} },
|
|
48493
48652
|
view: {
|
|
48494
48653
|
fit() {
|
|
48495
48654
|
assertActive();
|
|
@@ -48794,10 +48953,10 @@ function createBoardControllerWithEngine(options, existingEngine) {
|
|
|
48794
48953
|
gather: (nextView) => engine?.applyGatherView(nextView) ?? false
|
|
48795
48954
|
},
|
|
48796
48955
|
export: {
|
|
48797
|
-
svg: () => engine ? engine.exportSVG() : documentToSVG(document.toJSON(), Date.now(), extensionRegistry),
|
|
48956
|
+
svg: () => engine ? engine.exportSVG() : documentToSVG(document.toJSON(), Date.now(), extensionRegistry, currentBoardTheme.color),
|
|
48798
48957
|
png: (options) => engine ? engine.exportPNG(options?.maxSide, { awaitAssets: options?.awaitAssets }) : Promise.resolve(null),
|
|
48799
48958
|
json: () => document.toJSON(),
|
|
48800
|
-
svgAsync: (svgOptions) => exportDocumentSVGWithAssets(document.toJSON(), Date.now(), extensionRegistry, assetController, svgOptions)
|
|
48959
|
+
svgAsync: (svgOptions) => exportDocumentSVGWithAssets(document.toJSON(), Date.now(), extensionRegistry, assetController, currentBoardTheme.color, svgOptions)
|
|
48801
48960
|
},
|
|
48802
48961
|
assets: { async ingest(bytes, mediaType, name, signal) {
|
|
48803
48962
|
assertActive();
|
|
@@ -49259,7 +49418,7 @@ function createLocalBoard(options) {
|
|
|
49259
49418
|
};
|
|
49260
49419
|
}
|
|
49261
49420
|
//#endregion
|
|
49262
|
-
//#region src/theme.ts
|
|
49421
|
+
//#region src/ui/theme.ts
|
|
49263
49422
|
var scrawlThemePresets = Object.freeze({
|
|
49264
49423
|
light: Object.freeze({
|
|
49265
49424
|
surface: "#ffffff",
|
|
@@ -49284,7 +49443,14 @@ var scrawlThemePresets = Object.freeze({
|
|
|
49284
49443
|
elevationHigh: "0 8px 20px rgba(28, 28, 26, 0.18)",
|
|
49285
49444
|
motionDuration: 140,
|
|
49286
49445
|
motionEasing: "cubic-bezier(0.2, 0, 0, 1)",
|
|
49287
|
-
density: "comfortable"
|
|
49446
|
+
density: "comfortable",
|
|
49447
|
+
boardSurface: "#f5f5f3",
|
|
49448
|
+
boardSurfaceTexture: "flat",
|
|
49449
|
+
gridMode: "none",
|
|
49450
|
+
gridColor: "#deded8",
|
|
49451
|
+
gridSpacing: 5,
|
|
49452
|
+
gridLineWidth: 1,
|
|
49453
|
+
shapeStrokeWidth: .15
|
|
49288
49454
|
}),
|
|
49289
49455
|
dark: Object.freeze({
|
|
49290
49456
|
surface: "#171816",
|
|
@@ -49309,7 +49475,14 @@ var scrawlThemePresets = Object.freeze({
|
|
|
49309
49475
|
elevationHigh: "0 8px 20px rgba(0, 0, 0, 0.38)",
|
|
49310
49476
|
motionDuration: 140,
|
|
49311
49477
|
motionEasing: "cubic-bezier(0.2, 0, 0, 1)",
|
|
49312
|
-
density: "comfortable"
|
|
49478
|
+
density: "comfortable",
|
|
49479
|
+
boardSurface: "#232420",
|
|
49480
|
+
boardSurfaceTexture: "flat",
|
|
49481
|
+
gridMode: "none",
|
|
49482
|
+
gridColor: "#33352f",
|
|
49483
|
+
gridSpacing: 5,
|
|
49484
|
+
gridLineWidth: 1,
|
|
49485
|
+
shapeStrokeWidth: .15
|
|
49313
49486
|
})
|
|
49314
49487
|
});
|
|
49315
49488
|
var variableNames = {
|
|
@@ -49335,7 +49508,14 @@ var variableNames = {
|
|
|
49335
49508
|
elevationHigh: "--scrawl-elevation-high",
|
|
49336
49509
|
motionDuration: "--scrawl-motion-duration",
|
|
49337
49510
|
motionEasing: "--scrawl-motion-easing",
|
|
49338
|
-
density: "--scrawl-density"
|
|
49511
|
+
density: "--scrawl-density",
|
|
49512
|
+
boardSurface: "--scrawl-board-surface",
|
|
49513
|
+
boardSurfaceTexture: "--scrawl-board-surface-texture",
|
|
49514
|
+
gridMode: "--scrawl-grid-mode",
|
|
49515
|
+
gridColor: "--scrawl-grid-color",
|
|
49516
|
+
gridSpacing: "--scrawl-grid-spacing",
|
|
49517
|
+
gridLineWidth: "--scrawl-grid-line-width",
|
|
49518
|
+
shapeStrokeWidth: "--scrawl-shape-stroke-width"
|
|
49339
49519
|
};
|
|
49340
49520
|
var colorTokens = /* @__PURE__ */ new Set([
|
|
49341
49521
|
"surface",
|
|
@@ -49348,7 +49528,9 @@ var colorTokens = /* @__PURE__ */ new Set([
|
|
|
49348
49528
|
"selection",
|
|
49349
49529
|
"danger",
|
|
49350
49530
|
"warning",
|
|
49351
|
-
"success"
|
|
49531
|
+
"success",
|
|
49532
|
+
"boardSurface",
|
|
49533
|
+
"gridColor"
|
|
49352
49534
|
]);
|
|
49353
49535
|
var knownTokens = new Set(Object.keys(scrawlThemePresets.light));
|
|
49354
49536
|
function validateScrawlTheme(theme) {
|
|
@@ -49385,6 +49567,26 @@ function validateScrawlTheme(theme) {
|
|
|
49385
49567
|
token,
|
|
49386
49568
|
message: "Expected comfortable or compact"
|
|
49387
49569
|
});
|
|
49570
|
+
else if (token === "gridMode" && value !== "none" && value !== "line" && value !== "dot") diagnostics.push({
|
|
49571
|
+
token,
|
|
49572
|
+
message: "Expected none, line, or dot"
|
|
49573
|
+
});
|
|
49574
|
+
else if (token === "boardSurfaceTexture" && value !== "flat" && value !== "textured") diagnostics.push({
|
|
49575
|
+
token,
|
|
49576
|
+
message: "Expected flat or textured"
|
|
49577
|
+
});
|
|
49578
|
+
else if (token === "gridSpacing" && (!finiteNumber(value) || value < .5 || value > 50)) diagnostics.push({
|
|
49579
|
+
token,
|
|
49580
|
+
message: "Expected spacing 0.5-50 board units"
|
|
49581
|
+
});
|
|
49582
|
+
else if (token === "gridLineWidth" && (!finiteNumber(value) || value < .5 || value > 8)) diagnostics.push({
|
|
49583
|
+
token,
|
|
49584
|
+
message: "Expected line width 0.5-8px"
|
|
49585
|
+
});
|
|
49586
|
+
else if (token === "shapeStrokeWidth" && (!finiteNumber(value) || value < .01 || value > 5)) diagnostics.push({
|
|
49587
|
+
token,
|
|
49588
|
+
message: "Expected stroke width 0.01-5 board units"
|
|
49589
|
+
});
|
|
49388
49590
|
else if ((token.endsWith("Family") || token.startsWith("elevation") || token === "motionEasing") && (typeof value !== "string" || !value.trim() || /[;{}]/.test(value))) diagnostics.push({
|
|
49389
49591
|
token,
|
|
49390
49592
|
message: "Expected a safe CSS value"
|
|
@@ -49455,12 +49657,12 @@ function luminance(color) {
|
|
|
49455
49657
|
return channels[0] * .2126 + channels[1] * .7152 + channels[2] * .0722;
|
|
49456
49658
|
}
|
|
49457
49659
|
function formatValue(token, value) {
|
|
49458
|
-
if (token === "baseFontSize" || token === "controlRadius" || token === "panelRadius") return `${value}px`;
|
|
49660
|
+
if (token === "baseFontSize" || token === "controlRadius" || token === "panelRadius" || token === "gridLineWidth") return `${value}px`;
|
|
49459
49661
|
if (token === "motionDuration") return `${value}ms`;
|
|
49460
49662
|
return String(value);
|
|
49461
49663
|
}
|
|
49462
49664
|
//#endregion
|
|
49463
|
-
//#region src/inline-editing.tsx
|
|
49665
|
+
//#region src/ui/dialogs/inline-editing.tsx
|
|
49464
49666
|
/** Inline note, text, and table-cell editors — driven entirely by public controller events and commands. */
|
|
49465
49667
|
function InlineEditors({ controller, renderPortal }) {
|
|
49466
49668
|
const [editor, setEditor] = useState(null);
|
|
@@ -49691,7 +49893,7 @@ function InlineEditors({ controller, renderPortal }) {
|
|
|
49691
49893
|
}))] });
|
|
49692
49894
|
}
|
|
49693
49895
|
//#endregion
|
|
49694
|
-
//#region src/style-shelf.tsx
|
|
49896
|
+
//#region src/ui/toolbar/style-shelf.tsx
|
|
49695
49897
|
var ERASER_RADII = [
|
|
49696
49898
|
["Fine", 1],
|
|
49697
49899
|
["Medium", 2],
|
|
@@ -49854,7 +50056,7 @@ function StyleShelf({ controller, snapshot }) {
|
|
|
49854
50056
|
});
|
|
49855
50057
|
}
|
|
49856
50058
|
//#endregion
|
|
49857
|
-
//#region src/default-ui.tsx
|
|
50059
|
+
//#region src/ui/default-ui.tsx
|
|
49858
50060
|
var PRIMARY_TOOLS = [
|
|
49859
50061
|
{
|
|
49860
50062
|
tool: "select",
|
|
@@ -50383,7 +50585,7 @@ function download(blob, name) {
|
|
|
50383
50585
|
URL.revokeObjectURL(url);
|
|
50384
50586
|
}
|
|
50385
50587
|
//#endregion
|
|
50386
|
-
//#region src/presence.tsx
|
|
50588
|
+
//#region src/ui/panels/presence.tsx
|
|
50387
50589
|
var labelStyle = {
|
|
50388
50590
|
borderRadius: 999,
|
|
50389
50591
|
color: "#fff",
|
|
@@ -50540,6 +50742,17 @@ function ScrawlProvider({ controller, children, preset = "light", theme, portalC
|
|
|
50540
50742
|
style
|
|
50541
50743
|
]);
|
|
50542
50744
|
useEffect(() => reportThemeDiagnostics(resolved.diagnostics, onThemeDiagnostic), [resolved, onThemeDiagnostic]);
|
|
50745
|
+
useEffect(() => {
|
|
50746
|
+
controller.boardTheme.set({
|
|
50747
|
+
surface: resolved.values.boardSurface,
|
|
50748
|
+
surfaceTexture: resolved.values.boardSurfaceTexture,
|
|
50749
|
+
gridMode: resolved.values.gridMode,
|
|
50750
|
+
gridColor: resolved.values.gridColor,
|
|
50751
|
+
gridSpacing: resolved.values.gridSpacing,
|
|
50752
|
+
gridLineWidth: resolved.values.gridLineWidth,
|
|
50753
|
+
shapeStrokeWidth: resolved.values.shapeStrokeWidth
|
|
50754
|
+
});
|
|
50755
|
+
}, [controller, resolved]);
|
|
50543
50756
|
useDeferredDisposal(controller, disposeOnUnmount);
|
|
50544
50757
|
const value = useMemo(() => ({
|
|
50545
50758
|
controller,
|
|
@@ -50587,8 +50800,19 @@ function Scrawl({ children, preset, theme, portalContainer, className, style, on
|
|
|
50587
50800
|
try {
|
|
50588
50801
|
if (!runtimeRef.current) {
|
|
50589
50802
|
const canvas = suppliedCanvas === void 0 ? ownedCanvasRef.current : suppliedCanvas;
|
|
50803
|
+
const resolved = resolveScrawlTheme(preset, theme);
|
|
50804
|
+
const boardTheme = {
|
|
50805
|
+
surface: resolved.values.boardSurface,
|
|
50806
|
+
surfaceTexture: resolved.values.boardSurfaceTexture,
|
|
50807
|
+
gridMode: resolved.values.gridMode,
|
|
50808
|
+
gridColor: resolved.values.gridColor,
|
|
50809
|
+
gridSpacing: resolved.values.gridSpacing,
|
|
50810
|
+
gridLineWidth: resolved.values.gridLineWidth,
|
|
50811
|
+
shapeStrokeWidth: resolved.values.shapeStrokeWidth
|
|
50812
|
+
};
|
|
50590
50813
|
controller = createBoardController({
|
|
50591
50814
|
...options,
|
|
50815
|
+
boardTheme,
|
|
50592
50816
|
...canvas ? { canvas } : {}
|
|
50593
50817
|
});
|
|
50594
50818
|
runtimeRef.current = {
|
|
@@ -50824,4 +51048,4 @@ function ScrawlBoard({ documentId, initialDocument, onReady, className, style })
|
|
|
50824
51048
|
});
|
|
50825
51049
|
}
|
|
50826
51050
|
//#endregion
|
|
50827
|
-
export { AddImageCommand, AddNoteCommand, AddStrokesCommand, AddTableCommand, AddTextCommand, AddTimerCommand,
|
|
51051
|
+
export { ASSET_CACHE_BYTES_DEFAULT, ASSET_CACHE_BYTES_MAX, ASSET_CACHE_BYTES_MIN, ASSET_EXPORT_MAX_DECODED_MEGAPIXELS, ASSET_EXPORT_MAX_ENCODED_BYTES, ASSET_MAX_CONCURRENT_RESOLUTIONS, ASSET_MAX_DECODED_MEGAPIXELS, ASSET_MAX_DIMENSION_PX, ASSET_MAX_ENCODED_BYTES, ASSET_REF_MAX_BYTES, ASSET_REF_PATTERN, AddImageCommand, AddNoteCommand, AddStrokesCommand, AddTableCommand, AddTextCommand, AddTimerCommand, AssetResolutionError, BEACON_INSET, BoardDocument, CURRENT_DOCUMENT_SCHEMA_VERSION, ClusterStore, DefaultBoardChrome, DeleteImageCommand, DeleteNoteCommand, DeleteStrokesCommand, DeleteTableCommand, DeleteTextCommand, DeleteTimerCommand, DocumentRecoveryError, END_TAPER, ERASE_THRESHOLD, EraseCommand, FOG_COLOR, HIGHLIGHT_COLORS, History, IDENTITY, INK_COLORS, InlineEditors, LockItemsCommand, MIN_WIDTH_FACTOR, MultiplayerCursors, NOTE_COLORS, NOTE_DEFAULT_SIZE, NOTE_DEFAULT_Z, NOTE_MAX_Z, NOTE_MIN_Z, NOTE_PEEL_STEP, SDK_DEVELOPMENT_VERSION, SDK_PACKAGE_NAME, STAMPS, STAMP_SIZE, SUPPORTED_ASSET_MEDIA_TYPES, Scrawl, ScrawlBoard, ScrawlCanvas, ScrawlDefaultUI, ScrawlPortal, ScrawlProvider, SpatialIndex, StyleShelf, TABLE_DEFAULT_CELL_HEIGHT, TABLE_DEFAULT_CELL_WIDTH, TABLE_DEFAULT_FONT_SIZE, TEXT_DEFAULT_SIZE, TIMER_DEFAULT_DURATION_MS, TIMER_DEFAULT_SIZE, TIMER_PRESETS_MS, TransformCommand, UpdateImageCommand, UpdateNoteCommand, UpdateTableCommand, UpdateTextCommand, UpdateTimerCommand, apply, applyItemLock, assetRef, avgScale, canUnlockItem, changeToOps, clampAssetCacheBytes, cloneCustomObject, cloneImage, cloneNote, cloneStroke, cloneTable, cloneText, cloneTimer, createBoardController, createLocalBoard, documentId, documentToSVG, formatTimer, invert, isAssetRef, isIdentity, isStampKind, loadDocumentBytes, measureTable, measureTextBlock, migrateDocument, mul, pauseTimer, placePresenceBeacon, resolveScrawlTheme, ribbonEdges, rotationAbout, scalingAbout, scrawlThemePresets, searchBoard, serializeDocument, serializeLock, serializeStroke, setTimerDuration, stampDataUrl, startTimer, strokeId, timerExpired, timerRemaining, toggleTimer, translation, useScrawlController, useScrawlSnapshot, useScrawlTheme, validateScrawlTheme };
|