@scrawl-board/board 0.1.0-beta.1 → 0.1.0-beta.3
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 +32 -16
- package/dist/browser.js +163 -118
- package/dist/core.d.ts +16 -3
- package/dist/core.js +31 -23
- package/dist/index.d.ts +110 -20
- package/dist/index.js +216 -136
- package/dist/react.d.ts +101 -19
- package/dist/react.js +215 -135
- package/dist/styles.css +2 -1
- 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;
|
|
@@ -33,7 +33,7 @@ function clampAssetCacheBytes(value) {
|
|
|
33
33
|
return Math.min(ASSET_CACHE_BYTES_MAX, Math.max(ASSET_CACHE_BYTES_MIN, Math.floor(value)));
|
|
34
34
|
}
|
|
35
35
|
//#endregion
|
|
36
|
-
//#region src/core
|
|
36
|
+
//#region src/core/document/identifiers.ts
|
|
37
37
|
function documentId(value) {
|
|
38
38
|
if (!value) throw new TypeError("DocumentId cannot be empty");
|
|
39
39
|
return value;
|
|
@@ -234,7 +234,7 @@ function validation(message, path) {
|
|
|
234
234
|
return new DocumentRecoveryError("DOCUMENT_VALIDATION_FAILED", message, void 0, path);
|
|
235
235
|
}
|
|
236
236
|
//#endregion
|
|
237
|
-
//#region src/core
|
|
237
|
+
//#region src/core/shapes/affine2d.ts
|
|
238
238
|
var IDENTITY = [
|
|
239
239
|
1,
|
|
240
240
|
0,
|
|
@@ -318,7 +318,7 @@ function avgScale(m) {
|
|
|
318
318
|
return (Math.hypot(m[0], m[1]) + Math.hypot(m[2], m[3])) / 2;
|
|
319
319
|
}
|
|
320
320
|
//#endregion
|
|
321
|
-
//#region src/core
|
|
321
|
+
//#region src/core/document/boardSearch.ts
|
|
322
322
|
function hay(s) {
|
|
323
323
|
return s.toLowerCase();
|
|
324
324
|
}
|
|
@@ -383,7 +383,7 @@ function searchBoard(query, board) {
|
|
|
383
383
|
return hits;
|
|
384
384
|
}
|
|
385
385
|
//#endregion
|
|
386
|
-
//#region src/core
|
|
386
|
+
//#region src/core/shapes/types.ts
|
|
387
387
|
/** Erasure level at which a point counts as fully erased. */
|
|
388
388
|
var ERASE_THRESHOLD = .95;
|
|
389
389
|
function cloneStroke(stroke) {
|
|
@@ -455,7 +455,7 @@ function cloneImage(img) {
|
|
|
455
455
|
return { ...img };
|
|
456
456
|
}
|
|
457
457
|
//#endregion
|
|
458
|
-
//#region src/core
|
|
458
|
+
//#region src/core/document/clusterStore.ts
|
|
459
459
|
/** A stroke joins a cluster last written to within this window at full reach. */
|
|
460
460
|
var RECENT_MS = 8e3;
|
|
461
461
|
/** Older clusters are still joinable, at half the gap threshold. */
|
|
@@ -626,7 +626,7 @@ function clamp$3(v, lo, hi) {
|
|
|
626
626
|
return Math.min(hi, Math.max(lo, v));
|
|
627
627
|
}
|
|
628
628
|
//#endregion
|
|
629
|
-
//#region src/core
|
|
629
|
+
//#region src/core/shapes/extensionTypes.ts
|
|
630
630
|
function cloneCustomObject(object) {
|
|
631
631
|
return {
|
|
632
632
|
...object,
|
|
@@ -636,7 +636,7 @@ function cloneCustomObject(object) {
|
|
|
636
636
|
};
|
|
637
637
|
}
|
|
638
638
|
//#endregion
|
|
639
|
-
//#region src/core
|
|
639
|
+
//#region src/core/shapes/kitchenTimer.ts
|
|
640
640
|
var TIMER_DEFAULT_DURATION_MS = 300 * 1e3;
|
|
641
641
|
var TIMER_PRESETS_MS = [
|
|
642
642
|
6e4,
|
|
@@ -692,7 +692,7 @@ function formatTimer(ms) {
|
|
|
692
692
|
return `${Math.floor(total / 60)}:${(total % 60).toString().padStart(2, "0")}`;
|
|
693
693
|
}
|
|
694
694
|
//#endregion
|
|
695
|
-
//#region src/core
|
|
695
|
+
//#region src/core/shapes/itemLock.ts
|
|
696
696
|
/**
|
|
697
697
|
* Apply or clear a lock in place. Unlock always drops the holder so a stale
|
|
698
698
|
* name cannot linger on an unlocked item.
|
|
@@ -729,7 +729,7 @@ function serializeLock(item) {
|
|
|
729
729
|
};
|
|
730
730
|
}
|
|
731
731
|
//#endregion
|
|
732
|
-
//#region src/core
|
|
732
|
+
//#region src/core/document/document.ts
|
|
733
733
|
/**
|
|
734
734
|
* The one place a live Stroke becomes its wire representation — in
|
|
735
735
|
* particular, points collapse from {x,y,pressure,erase?} objects into
|
|
@@ -1288,7 +1288,7 @@ function computeBBox(stroke) {
|
|
|
1288
1288
|
return world;
|
|
1289
1289
|
}
|
|
1290
1290
|
//#endregion
|
|
1291
|
-
//#region src/core
|
|
1291
|
+
//#region src/core/commands/commands.ts
|
|
1292
1292
|
/** One drawing action — a marker stroke, or a shape's strokes as one unit. */
|
|
1293
1293
|
var AddStrokesCommand = class {
|
|
1294
1294
|
constructor(strokes) {
|
|
@@ -1630,7 +1630,7 @@ var LockItemsCommand = class {
|
|
|
1630
1630
|
}
|
|
1631
1631
|
};
|
|
1632
1632
|
//#endregion
|
|
1633
|
-
//#region src/core
|
|
1633
|
+
//#region src/core/history/history.ts
|
|
1634
1634
|
var LIMIT = 200;
|
|
1635
1635
|
var History = class {
|
|
1636
1636
|
constructor(doc) {
|
|
@@ -1691,7 +1691,7 @@ var History = class {
|
|
|
1691
1691
|
}
|
|
1692
1692
|
};
|
|
1693
1693
|
//#endregion
|
|
1694
|
-
//#region src/core
|
|
1694
|
+
//#region src/core/events/ops.ts
|
|
1695
1695
|
var ADDED = [
|
|
1696
1696
|
["added", "strokes"],
|
|
1697
1697
|
["notesAdded", "notes"],
|
|
@@ -1745,10 +1745,18 @@ function changeToOps(change, restoring = false) {
|
|
|
1745
1745
|
return ops;
|
|
1746
1746
|
}
|
|
1747
1747
|
//#endregion
|
|
1748
|
-
//#region src/core
|
|
1748
|
+
//#region src/core/shapes/ribbonEdges.ts
|
|
1749
1749
|
var MIN_WIDTH_FACTOR = .35;
|
|
1750
1750
|
var END_TAPER = .55;
|
|
1751
|
-
|
|
1751
|
+
/**
|
|
1752
|
+
* @param handDrawn Default `true`: ink's organic feel — width follows
|
|
1753
|
+
* per-point pressure, and both ends taper. Pass `false` for a geometric
|
|
1754
|
+
* shape outline, which has no real pressure signal and isn't a pen stroke
|
|
1755
|
+
* with a lift-off: it renders at the exact `baseWidth`, uniformly, with no
|
|
1756
|
+
* taper at its start/end (which, for a closed shape, is the same point —
|
|
1757
|
+
* tapering it would visibly pinch just that one corner).
|
|
1758
|
+
*/
|
|
1759
|
+
function ribbonEdges(points, baseWidth, handDrawn = true) {
|
|
1752
1760
|
const pts = points.length === 1 ? [points[0], {
|
|
1753
1761
|
...points[0],
|
|
1754
1762
|
x: points[0].x + baseWidth * .05
|
|
@@ -1763,8 +1771,8 @@ function ribbonEdges(points, baseWidth) {
|
|
|
1763
1771
|
const len = Math.hypot(dx, dy) || 1;
|
|
1764
1772
|
dx /= len;
|
|
1765
1773
|
dy /= len;
|
|
1766
|
-
let width = baseWidth * (MIN_WIDTH_FACTOR + (1 - MIN_WIDTH_FACTOR) * pts[i].pressure);
|
|
1767
|
-
if (i === 0 || i === n - 1) width *= END_TAPER;
|
|
1774
|
+
let width = handDrawn ? baseWidth * (MIN_WIDTH_FACTOR + (1 - MIN_WIDTH_FACTOR) * pts[i].pressure) : baseWidth;
|
|
1775
|
+
if (handDrawn && (i === 0 || i === n - 1)) width *= END_TAPER;
|
|
1768
1776
|
const hw = width / 2;
|
|
1769
1777
|
out[i] = {
|
|
1770
1778
|
lx: pts[i].x - dy * hw,
|
|
@@ -1777,7 +1785,7 @@ function ribbonEdges(points, baseWidth) {
|
|
|
1777
1785
|
return out;
|
|
1778
1786
|
}
|
|
1779
1787
|
//#endregion
|
|
1780
|
-
//#region src/core
|
|
1788
|
+
//#region src/core/document/spatialIndex.ts
|
|
1781
1789
|
var CELL = 8;
|
|
1782
1790
|
var SpatialIndex = class {
|
|
1783
1791
|
constructor(doc) {
|
|
@@ -1850,7 +1858,7 @@ function cellsOf(box) {
|
|
|
1850
1858
|
return keys;
|
|
1851
1859
|
}
|
|
1852
1860
|
//#endregion
|
|
1853
|
-
//#region src/core
|
|
1861
|
+
//#region src/core/shapes/stamps.ts
|
|
1854
1862
|
var STAMPS = [
|
|
1855
1863
|
{
|
|
1856
1864
|
kind: "star",
|
|
@@ -1895,7 +1903,7 @@ function stampDataUrl(kind) {
|
|
|
1895
1903
|
return `data:image/svg+xml;utf8,${encodeURIComponent(SVG[kind])}`;
|
|
1896
1904
|
}
|
|
1897
1905
|
//#endregion
|
|
1898
|
-
//#region src/
|
|
1906
|
+
//#region src/collaboration/presence/presence.ts
|
|
1899
1907
|
/** Keep beacons clear of typical chrome at the top and bottom of the Board. */
|
|
1900
1908
|
var BEACON_INSET = {
|
|
1901
1909
|
top: 72,
|
|
@@ -1931,7 +1939,7 @@ function clamp$2(value, min, max) {
|
|
|
1931
1939
|
return Math.min(max, Math.max(min, value));
|
|
1932
1940
|
}
|
|
1933
1941
|
//#endregion
|
|
1934
|
-
//#region src/
|
|
1942
|
+
//#region src/persistence/serialization/svg.ts
|
|
1935
1943
|
/** Matches the key light used by the board shader and note shadows. */
|
|
1936
1944
|
var LIGHT = {
|
|
1937
1945
|
x: -.25,
|
|
@@ -2073,7 +2081,7 @@ function strokeToPaths(stroke) {
|
|
|
2073
2081
|
y,
|
|
2074
2082
|
pressure,
|
|
2075
2083
|
...erase > 0 ? { erase } : {}
|
|
2076
|
-
})), stroke.baseWidth);
|
|
2084
|
+
})), stroke.baseWidth, stroke.tool !== "shape");
|
|
2077
2085
|
const transform = stroke.matrix ? ` transform="matrix(${fmt(stroke.matrix[0])} ${fmt(-stroke.matrix[1])} ${fmt(-stroke.matrix[2])} ${fmt(stroke.matrix[3])} ${fmt(stroke.matrix[4])} ${fmt(-stroke.matrix[5])})"` : "";
|
|
2078
2086
|
const baseOpacity = stroke.tool === "highlighter" ? .4 : 1;
|
|
2079
2087
|
const paths = [];
|
|
@@ -2298,7 +2306,7 @@ function fmt(n) {
|
|
|
2298
2306
|
return String(Math.round(n * 100) / 100);
|
|
2299
2307
|
}
|
|
2300
2308
|
//#endregion
|
|
2301
|
-
//#region src/core
|
|
2309
|
+
//#region src/core/shapes/sceneGeometry.ts
|
|
2302
2310
|
var EMPTY_BOUNDS = {
|
|
2303
2311
|
x: 0,
|
|
2304
2312
|
y: 0,
|
|
@@ -2362,7 +2370,7 @@ function textCorners(x, y, text, fontSize, align, m) {
|
|
|
2362
2370
|
return rectCorners(x + (align === "center" ? -width / 2 : align === "end" ? -width : 0), y, width, height, m);
|
|
2363
2371
|
}
|
|
2364
2372
|
//#endregion
|
|
2365
|
-
//#region src/core
|
|
2373
|
+
//#region src/core/shapes/customObjects.ts
|
|
2366
2374
|
var FALLBACK_LABEL_MAX_LENGTH = 80;
|
|
2367
2375
|
function toReadonly(object) {
|
|
2368
2376
|
return object;
|
|
@@ -2491,7 +2499,7 @@ function extensionIdFromType(type) {
|
|
|
2491
2499
|
return slash === -1 ? type : type.slice(0, slash);
|
|
2492
2500
|
}
|
|
2493
2501
|
//#endregion
|
|
2494
|
-
//#region src/core
|
|
2502
|
+
//#region src/core/shapes/extensionRegistry.ts
|
|
2495
2503
|
function buildExtensionRegistry(extensions) {
|
|
2496
2504
|
const list = extensions ?? [];
|
|
2497
2505
|
const diagnostics = [];
|
|
@@ -2588,7 +2596,7 @@ function isWellFormedNamespacedId(id) {
|
|
|
2588
2596
|
return isWellFormedId(id) && id.includes("/") && !id.startsWith("/") && !id.endsWith("/");
|
|
2589
2597
|
}
|
|
2590
2598
|
//#endregion
|
|
2591
|
-
//#region src/
|
|
2599
|
+
//#region src/persistence/adapters/assetValidation.ts
|
|
2592
2600
|
function sniffImageMediaType(bytes) {
|
|
2593
2601
|
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";
|
|
2594
2602
|
if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) return "image/jpeg";
|
|
@@ -2675,7 +2683,7 @@ function validateDecodedDimensions(width, height) {
|
|
|
2675
2683
|
};
|
|
2676
2684
|
}
|
|
2677
2685
|
//#endregion
|
|
2678
|
-
//#region src/assetController.ts
|
|
2686
|
+
//#region src/persistence/adapters/assetController.ts
|
|
2679
2687
|
var FAILURE_COALESCE_MS = 4e3;
|
|
2680
2688
|
var AssetController = class {
|
|
2681
2689
|
constructor(resolver, options) {
|
|
@@ -2854,7 +2862,7 @@ function toAssetResolutionError(cause, ref) {
|
|
|
2854
2862
|
return new AssetResolutionError("unknown", true, cause instanceof Error ? cause.message : String(cause), ref);
|
|
2855
2863
|
}
|
|
2856
2864
|
//#endregion
|
|
2857
|
-
//#region src/
|
|
2865
|
+
//#region src/persistence/serialization/assetRefCollector.ts
|
|
2858
2866
|
/** Every unique Asset reference in the document, and which object(s) use it. */
|
|
2859
2867
|
function collectDocumentAssetRefs(doc, registry) {
|
|
2860
2868
|
const refs = /* @__PURE__ */ new Map();
|
|
@@ -2881,7 +2889,7 @@ function collectSceneAssetRefs(node, objectId, add) {
|
|
|
2881
2889
|
if (node.kind === "group") for (const child of node.children) collectSceneAssetRefs(child, objectId, add);
|
|
2882
2890
|
}
|
|
2883
2891
|
//#endregion
|
|
2884
|
-
//#region src/assetExport.ts
|
|
2892
|
+
//#region src/persistence/serialization/assetExport.ts
|
|
2885
2893
|
/** Strict mode's rejection — never contains credentials, a fetchable location, or a raw resolver message. */
|
|
2886
2894
|
var SvgAssetExportError = class extends Error {
|
|
2887
2895
|
constructor(missingAssets) {
|
|
@@ -2937,7 +2945,7 @@ function toDataUri(bytes, mediaType) {
|
|
|
2937
2945
|
return `data:${mediaType};base64,${btoa(binary)}`;
|
|
2938
2946
|
}
|
|
2939
2947
|
//#endregion
|
|
2940
|
-
//#region src/assetIngestion.ts
|
|
2948
|
+
//#region src/persistence/adapters/assetIngestion.ts
|
|
2941
2949
|
async function decodeDimensionsWithImageBitmap(bytes, mediaType) {
|
|
2942
2950
|
const blob = new Blob([bytes], { type: mediaType });
|
|
2943
2951
|
let bitmap;
|
|
@@ -35583,7 +35591,7 @@ var WebGLRenderer = class {
|
|
|
35583
35591
|
}
|
|
35584
35592
|
};
|
|
35585
35593
|
//#endregion
|
|
35586
|
-
//#region
|
|
35594
|
+
//#region src/core/events/auditEvents.ts
|
|
35587
35595
|
var BY_LABEL = {
|
|
35588
35596
|
draw: {
|
|
35589
35597
|
action: "create",
|
|
@@ -35703,7 +35711,7 @@ function lowerFirst(s) {
|
|
|
35703
35711
|
return s.charAt(0).toLowerCase() + s.slice(1);
|
|
35704
35712
|
}
|
|
35705
35713
|
//#endregion
|
|
35706
|
-
//#region
|
|
35714
|
+
//#region src/renderer/shapes/AssetTextureCache.ts
|
|
35707
35715
|
var AssetTextureCache = class {
|
|
35708
35716
|
constructor(assetController) {
|
|
35709
35717
|
this.assetController = assetController;
|
|
@@ -35794,7 +35802,7 @@ function toDecodeError(cause, ref) {
|
|
|
35794
35802
|
return new AssetResolutionError("decode-failed", false, cause instanceof Error ? cause.message : String(cause), ref);
|
|
35795
35803
|
}
|
|
35796
35804
|
//#endregion
|
|
35797
|
-
//#region
|
|
35805
|
+
//#region src/renderer/canvas/raycast.ts
|
|
35798
35806
|
var origin$1 = new Vector3();
|
|
35799
35807
|
var target = new Vector3();
|
|
35800
35808
|
function pointerToBoard(clientX, clientY, canvas, camera) {
|
|
@@ -35825,7 +35833,7 @@ function pointerToPlane(clientX, clientY, canvas, camera, z) {
|
|
|
35825
35833
|
};
|
|
35826
35834
|
}
|
|
35827
35835
|
//#endregion
|
|
35828
|
-
//#region
|
|
35836
|
+
//#region src/renderer/canvas/fog.ts
|
|
35829
35837
|
function createFogUniforms(color) {
|
|
35830
35838
|
return {
|
|
35831
35839
|
uFogColor: { value: new Color(color) },
|
|
@@ -35846,18 +35854,24 @@ var FOG_GLSL = `
|
|
|
35846
35854
|
}
|
|
35847
35855
|
`;
|
|
35848
35856
|
//#endregion
|
|
35849
|
-
//#region
|
|
35857
|
+
//#region src/renderer/canvas/boardSurface.ts
|
|
35850
35858
|
var GRID_MODE_CODE = {
|
|
35851
35859
|
none: 0,
|
|
35852
35860
|
line: 1,
|
|
35853
35861
|
dot: 2
|
|
35854
35862
|
};
|
|
35863
|
+
var TEXTURE_CODE = {
|
|
35864
|
+
flat: 0,
|
|
35865
|
+
textured: 1
|
|
35866
|
+
};
|
|
35855
35867
|
/** Used when a caller doesn't supply one (e.g. ScrawlEngine constructed without a Host theme). */
|
|
35856
35868
|
var DEFAULT_BOARD_SURFACE_THEME = {
|
|
35857
35869
|
color: "#f5f5f3",
|
|
35858
35870
|
gridMode: "none",
|
|
35859
35871
|
gridColor: "#deded8",
|
|
35860
|
-
gridSpacing: 5
|
|
35872
|
+
gridSpacing: 5,
|
|
35873
|
+
gridLineWidth: 1,
|
|
35874
|
+
surfaceTexture: "flat"
|
|
35861
35875
|
};
|
|
35862
35876
|
/** Grid alpha fades out below this on-screen spacing (px) — otherwise it aliases into a solid wash when zoomed out. */
|
|
35863
35877
|
var GRID_FADE_MIN_PX = 3;
|
|
@@ -35878,8 +35892,10 @@ var FRAGMENT = `
|
|
|
35878
35892
|
uniform float uGridMode;
|
|
35879
35893
|
uniform vec3 uGridColor;
|
|
35880
35894
|
uniform float uGridSpacing;
|
|
35881
|
-
uniform float
|
|
35895
|
+
uniform float uWorldPerPixel;
|
|
35896
|
+
uniform float uGridLineWidthPx;
|
|
35882
35897
|
uniform float uGridFade;
|
|
35898
|
+
uniform float uSurfaceTexture;
|
|
35883
35899
|
varying vec3 vWorldPos;
|
|
35884
35900
|
|
|
35885
35901
|
float hash(vec2 p) {
|
|
@@ -35899,37 +35915,45 @@ var FRAGMENT = `
|
|
|
35899
35915
|
${FOG_GLSL}
|
|
35900
35916
|
|
|
35901
35917
|
// Distance from p's nearest axis-aligned grid line, in world units.
|
|
35918
|
+
// A crisp, ~uGridLineWidthPx-wide line: full alpha to its half-width, a
|
|
35919
|
+
// ~1px anti-aliased falloff beyond that — not a wide, soft-edged band.
|
|
35902
35920
|
float gridLineAlpha(vec2 p) {
|
|
35903
35921
|
vec2 cell = mod(p, uGridSpacing);
|
|
35904
35922
|
vec2 distToLine = min(cell, uGridSpacing - cell);
|
|
35905
|
-
|
|
35923
|
+
float halfWidth = 0.5 * uGridLineWidthPx * uWorldPerPixel;
|
|
35924
|
+
float aa = uWorldPerPixel;
|
|
35925
|
+
vec2 lineAlpha2 = 1.0 - smoothstep(halfWidth - aa * 0.5, halfWidth + aa * 0.5, distToLine);
|
|
35906
35926
|
return max(lineAlpha2.x, lineAlpha2.y);
|
|
35907
35927
|
}
|
|
35908
35928
|
|
|
35909
|
-
// Distance from p's nearest grid intersection, in world units.
|
|
35929
|
+
// Distance from p's nearest grid intersection, in world units. Dot radius
|
|
35930
|
+
// matches the configured line width in pixels, same anti-aliasing.
|
|
35910
35931
|
float gridDotAlpha(vec2 p) {
|
|
35911
35932
|
vec2 cell = mod(p, uGridSpacing) - uGridSpacing * 0.5;
|
|
35912
35933
|
float dist = length(cell);
|
|
35913
|
-
float radius =
|
|
35914
|
-
|
|
35934
|
+
float radius = uGridLineWidthPx * uWorldPerPixel;
|
|
35935
|
+
float aa = uWorldPerPixel;
|
|
35936
|
+
return 1.0 - smoothstep(radius - aa * 0.5, radius + aa * 0.5, dist);
|
|
35915
35937
|
}
|
|
35916
35938
|
|
|
35917
35939
|
void main() {
|
|
35918
35940
|
vec3 col = uColor;
|
|
35919
35941
|
|
|
35920
|
-
|
|
35921
|
-
|
|
35922
|
-
|
|
35942
|
+
if (uSurfaceTexture > 0.5) {
|
|
35943
|
+
// Melamine micro-texture: two octaves of value noise, +-1.75% brightness.
|
|
35944
|
+
float n = vnoise(vWorldPos.xy * 2.3) * 0.6 + vnoise(vWorldPos.xy * 9.7) * 0.4;
|
|
35945
|
+
col *= 1.0 + (n - 0.5) * 0.035;
|
|
35923
35946
|
|
|
35924
|
-
|
|
35925
|
-
|
|
35926
|
-
|
|
35927
|
-
|
|
35928
|
-
|
|
35929
|
-
|
|
35930
|
-
|
|
35931
|
-
|
|
35932
|
-
|
|
35947
|
+
// Satin sheen: Fresnel rim + a specular band from the key light. Both
|
|
35948
|
+
// are ~zero in the straight-on working view and bloom as the camera tilts.
|
|
35949
|
+
vec3 V = normalize(cameraPosition - vWorldPos);
|
|
35950
|
+
vec3 N = vec3(0.0, 0.0, 1.0);
|
|
35951
|
+
float fres = pow(1.0 - max(dot(N, V), 0.0), 3.0);
|
|
35952
|
+
vec3 L = normalize(vec3(-0.25, 0.4, 0.88));
|
|
35953
|
+
vec3 H = normalize(L + V);
|
|
35954
|
+
float spec = pow(max(dot(N, H), 0.0), 90.0);
|
|
35955
|
+
col += (fres * 0.18 + spec * 0.06) * vec3(1.0);
|
|
35956
|
+
}
|
|
35933
35957
|
|
|
35934
35958
|
if (uGridMode > 0.5 && uGridFade > 0.001) {
|
|
35935
35959
|
float gridAlpha = (uGridMode < 1.5 ? gridLineAlpha(vWorldPos.xy) : gridDotAlpha(vWorldPos.xy)) * uGridFade;
|
|
@@ -35949,8 +35973,10 @@ function createBoardSurface(fog, theme) {
|
|
|
35949
35973
|
uGridMode: { value: GRID_MODE_CODE[theme.gridMode] },
|
|
35950
35974
|
uGridColor: { value: new Color(theme.gridColor) },
|
|
35951
35975
|
uGridSpacing: { value: Math.max(.001, theme.gridSpacing) },
|
|
35952
|
-
|
|
35976
|
+
uGridLineWidthPx: { value: Math.max(.1, theme.gridLineWidth) },
|
|
35977
|
+
uWorldPerPixel: { value: .05 },
|
|
35953
35978
|
uGridFade: { value: 0 },
|
|
35979
|
+
uSurfaceTexture: { value: TEXTURE_CODE[theme.surfaceTexture] },
|
|
35954
35980
|
...fog
|
|
35955
35981
|
}
|
|
35956
35982
|
});
|
|
@@ -35958,13 +35984,15 @@ function createBoardSurface(fog, theme) {
|
|
|
35958
35984
|
mesh.name = "board-surface";
|
|
35959
35985
|
return mesh;
|
|
35960
35986
|
}
|
|
35961
|
-
/** Applies a theme change (initial or live) — everything except the per-frame fade/
|
|
35987
|
+
/** Applies a theme change (initial or live) — everything except the per-frame fade/pixel-ratio. */
|
|
35962
35988
|
function setBoardSurfaceTheme(mesh, theme) {
|
|
35963
35989
|
const uniforms = mesh.material.uniforms;
|
|
35964
35990
|
uniforms.uColor.value.set(theme.color);
|
|
35965
35991
|
uniforms.uGridMode.value = GRID_MODE_CODE[theme.gridMode];
|
|
35966
35992
|
uniforms.uGridColor.value.set(theme.gridColor);
|
|
35967
35993
|
uniforms.uGridSpacing.value = Math.max(.001, theme.gridSpacing);
|
|
35994
|
+
uniforms.uGridLineWidthPx.value = Math.max(.1, theme.gridLineWidth);
|
|
35995
|
+
uniforms.uSurfaceTexture.value = TEXTURE_CODE[theme.surfaceTexture];
|
|
35968
35996
|
}
|
|
35969
35997
|
/** Keep the plane centered under the view, larger than the fog horizon, and the grid's on-screen weight/fade current. */
|
|
35970
35998
|
function updateBoardSurface(mesh, centerX, centerY, fogFar, worldPerPixel) {
|
|
@@ -35972,7 +36000,7 @@ function updateBoardSurface(mesh, centerX, centerY, fogFar, worldPerPixel) {
|
|
|
35972
36000
|
const size = fogFar * 2.5;
|
|
35973
36001
|
mesh.scale.set(size, size, 1);
|
|
35974
36002
|
const uniforms = mesh.material.uniforms;
|
|
35975
|
-
uniforms.
|
|
36003
|
+
uniforms.uWorldPerPixel.value = worldPerPixel;
|
|
35976
36004
|
const t = (uniforms.uGridSpacing.value / Math.max(1e-6, worldPerPixel) - GRID_FADE_MIN_PX) / (GRID_FADE_MAX_PX - GRID_FADE_MIN_PX);
|
|
35977
36005
|
uniforms.uGridFade.value = MathUtils.clamp(t, 0, 1);
|
|
35978
36006
|
}
|
|
@@ -36145,7 +36173,7 @@ var CameraRig = class {
|
|
|
36145
36173
|
}
|
|
36146
36174
|
};
|
|
36147
36175
|
//#endregion
|
|
36148
|
-
//#region
|
|
36176
|
+
//#region src/renderer/canvas/scene.ts
|
|
36149
36177
|
var SceneRig = class {
|
|
36150
36178
|
constructor(canvas, boardTheme) {
|
|
36151
36179
|
this.renderer = new WebGLRenderer({
|
|
@@ -36192,7 +36220,7 @@ var SceneRig = class {
|
|
|
36192
36220
|
}
|
|
36193
36221
|
};
|
|
36194
36222
|
//#endregion
|
|
36195
|
-
//#region
|
|
36223
|
+
//#region src/renderer/shapes/inkMaterial.ts
|
|
36196
36224
|
var VERTEX = `
|
|
36197
36225
|
attribute float aAlpha;
|
|
36198
36226
|
varying vec2 vUv;
|
|
@@ -36323,15 +36351,15 @@ var InkMaterials = class {
|
|
|
36323
36351
|
}
|
|
36324
36352
|
};
|
|
36325
36353
|
//#endregion
|
|
36326
|
-
//#region
|
|
36354
|
+
//#region src/renderer/shapes/ribbonGeometry.ts
|
|
36327
36355
|
/** Ink floats a hair above the board to avoid z-fighting with the surface. */
|
|
36328
36356
|
var INK_Z = .02;
|
|
36329
36357
|
/** Highlighter always renders under opaque ink (build prompt §4.1). */
|
|
36330
36358
|
var HIGHLIGHT_Z = .016;
|
|
36331
36359
|
/** Ghosts sit under everything so live strokes always read on top. */
|
|
36332
36360
|
var GHOST_Z = .012;
|
|
36333
|
-
function buildRibbonGeometry(points, baseWidth, z = INK_Z) {
|
|
36334
|
-
const edges = ribbonEdges(points, baseWidth);
|
|
36361
|
+
function buildRibbonGeometry(points, baseWidth, z = INK_Z, handDrawn = true) {
|
|
36362
|
+
const edges = ribbonEdges(points, baseWidth, handDrawn);
|
|
36335
36363
|
const n = edges.length;
|
|
36336
36364
|
const positions = new Float32Array(n * 2 * 3);
|
|
36337
36365
|
const uvs = new Float32Array(n * 2 * 2);
|
|
@@ -36374,8 +36402,10 @@ function buildRibbonGeometry(points, baseWidth, z = INK_Z) {
|
|
|
36374
36402
|
return geometry;
|
|
36375
36403
|
}
|
|
36376
36404
|
//#endregion
|
|
36377
|
-
//#region
|
|
36405
|
+
//#region src/renderer/shapes/strokeRenderer.ts
|
|
36378
36406
|
var strokeZ = (stroke) => stroke.tool === "highlighter" ? HIGHLIGHT_Z : INK_Z;
|
|
36407
|
+
/** Shapes (rect/ellipse/line/arrow/...) are geometric outlines, not pressure-sensitive ink. */
|
|
36408
|
+
var handDrawn = (stroke) => stroke.tool !== "shape";
|
|
36379
36409
|
/**
|
|
36380
36410
|
* Derives ink meshes from the document by subscription — the document never
|
|
36381
36411
|
* knows the renderer exists. Also hosts session-only ghosts (decision Q7)
|
|
@@ -36400,12 +36430,12 @@ var StrokeRenderer = class {
|
|
|
36400
36430
|
this.ghostGroup.visible = visible;
|
|
36401
36431
|
}
|
|
36402
36432
|
/** Leave a smeared residue of an erased span (never persisted). */
|
|
36403
|
-
addGhost(points, color, baseWidth) {
|
|
36433
|
+
addGhost(points, color, baseWidth, handDrawn = true) {
|
|
36404
36434
|
if (points.length < 2) return;
|
|
36405
36435
|
const mesh = new Mesh(buildRibbonGeometry(points.map((p) => ({
|
|
36406
36436
|
...p,
|
|
36407
36437
|
erase: 0
|
|
36408
|
-
})), baseWidth * 1.7, GHOST_Z), this.materials.ghost(color));
|
|
36438
|
+
})), baseWidth * 1.7, GHOST_Z, handDrawn), this.materials.ghost(color));
|
|
36409
36439
|
this.ghostGroup.add(mesh);
|
|
36410
36440
|
}
|
|
36411
36441
|
/**
|
|
@@ -36417,7 +36447,7 @@ var StrokeRenderer = class {
|
|
|
36417
36447
|
if (this.meshes.has(stroke.id) || this.retiredLive.has(stroke.id) || stroke.points.length < 2) return;
|
|
36418
36448
|
this.liveUser.set(stroke.id, userId);
|
|
36419
36449
|
const existing = this.liveMeshes.get(stroke.id);
|
|
36420
|
-
const geometry = buildRibbonGeometry(stroke.points, stroke.baseWidth, strokeZ(stroke));
|
|
36450
|
+
const geometry = buildRibbonGeometry(stroke.points, stroke.baseWidth, strokeZ(stroke), handDrawn(stroke));
|
|
36421
36451
|
if (existing) {
|
|
36422
36452
|
existing.geometry.dispose();
|
|
36423
36453
|
existing.geometry = geometry;
|
|
@@ -36477,7 +36507,7 @@ var StrokeRenderer = class {
|
|
|
36477
36507
|
const mesh = this.meshes.get(stroke.id);
|
|
36478
36508
|
if (mesh) {
|
|
36479
36509
|
mesh.geometry.dispose();
|
|
36480
|
-
mesh.geometry = buildRibbonGeometry(stroke.points, stroke.baseWidth, strokeZ(stroke));
|
|
36510
|
+
mesh.geometry = buildRibbonGeometry(stroke.points, stroke.baseWidth, strokeZ(stroke), handDrawn(stroke));
|
|
36481
36511
|
}
|
|
36482
36512
|
}
|
|
36483
36513
|
for (const stroke of change.transformed) {
|
|
@@ -36486,7 +36516,7 @@ var StrokeRenderer = class {
|
|
|
36486
36516
|
}
|
|
36487
36517
|
}
|
|
36488
36518
|
create(stroke) {
|
|
36489
|
-
const mesh = new Mesh(buildRibbonGeometry(stroke.points, stroke.baseWidth, strokeZ(stroke)), stroke.tool === "highlighter" ? this.materials.highlight(stroke.color) : this.materials.get(stroke.color));
|
|
36519
|
+
const mesh = new Mesh(buildRibbonGeometry(stroke.points, stroke.baseWidth, strokeZ(stroke), handDrawn(stroke)), stroke.tool === "highlighter" ? this.materials.highlight(stroke.color) : this.materials.get(stroke.color));
|
|
36490
36520
|
mesh.matrixAutoUpdate = false;
|
|
36491
36521
|
syncMatrix(mesh, stroke);
|
|
36492
36522
|
this.meshes.set(stroke.id, mesh);
|
|
@@ -36507,7 +36537,7 @@ function syncMatrix(mesh, stroke) {
|
|
|
36507
36537
|
mesh.matrixWorldNeedsUpdate = true;
|
|
36508
36538
|
}
|
|
36509
36539
|
//#endregion
|
|
36510
|
-
//#region
|
|
36540
|
+
//#region src/renderer/shapes/markerProp.ts
|
|
36511
36541
|
var BODY_LENGTH = 11;
|
|
36512
36542
|
var BODY_RADIUS = .85;
|
|
36513
36543
|
var TIP_LENGTH = 1.6;
|
|
@@ -36603,7 +36633,7 @@ var MarkerProp = class {
|
|
|
36603
36633
|
}
|
|
36604
36634
|
};
|
|
36605
36635
|
//#endregion
|
|
36606
|
-
//#region
|
|
36636
|
+
//#region src/renderer/shapes/noteGeometry.ts
|
|
36607
36637
|
/**
|
|
36608
36638
|
* Height of the sheet above the board at (u, v) ∈ [0,1]².
|
|
36609
36639
|
* v = 1 is the adhesive edge (always 0); u = 1 is the peel corner side.
|
|
@@ -36647,7 +36677,7 @@ function applyCurl(geometry, curl, peel) {
|
|
|
36647
36677
|
color.needsUpdate = true;
|
|
36648
36678
|
}
|
|
36649
36679
|
//#endregion
|
|
36650
|
-
//#region
|
|
36680
|
+
//#region src/renderer/shapes/stickyNotes.ts
|
|
36651
36681
|
var TEXTURE_SIZE = 512;
|
|
36652
36682
|
var FOCUS_COLOR$4 = 2450411;
|
|
36653
36683
|
var CURL = .3;
|
|
@@ -43223,7 +43253,7 @@ SYNCABLE_PROPS.forEach((prop) => {
|
|
|
43223
43253
|
new Box3();
|
|
43224
43254
|
new Color();
|
|
43225
43255
|
//#endregion
|
|
43226
|
-
//#region
|
|
43256
|
+
//#region src/renderer/shapes/tables.ts
|
|
43227
43257
|
var FONT_URL$2 = "/fonts/inter-medium.woff";
|
|
43228
43258
|
var TABLE_Z = .012;
|
|
43229
43259
|
var HEADER_Z = .014;
|
|
@@ -43572,7 +43602,7 @@ var TablesRenderer = class {
|
|
|
43572
43602
|
}
|
|
43573
43603
|
};
|
|
43574
43604
|
//#endregion
|
|
43575
|
-
//#region
|
|
43605
|
+
//#region src/renderer/text/textBlocks.ts
|
|
43576
43606
|
var FONT_URL$1 = "/fonts/inter-medium.woff";
|
|
43577
43607
|
var TEXT_Z = .02;
|
|
43578
43608
|
var FOCUS_COLOR$2 = 2450411;
|
|
@@ -43676,7 +43706,7 @@ var TextBlocksRenderer = class {
|
|
|
43676
43706
|
}
|
|
43677
43707
|
};
|
|
43678
43708
|
//#endregion
|
|
43679
|
-
//#region
|
|
43709
|
+
//#region src/renderer/shapes/comments.ts
|
|
43680
43710
|
var PIN_Z = .04;
|
|
43681
43711
|
var PIN_WIDTH = 3.6;
|
|
43682
43712
|
var PIN_HEIGHT = 3.6;
|
|
@@ -43844,7 +43874,7 @@ function drawBubblePath(ctx, x, y, w, h, r, tailX, tailY, tailW) {
|
|
|
43844
43874
|
ctx.closePath();
|
|
43845
43875
|
}
|
|
43846
43876
|
//#endregion
|
|
43847
|
-
//#region
|
|
43877
|
+
//#region src/renderer/shapes/images.ts
|
|
43848
43878
|
var IMAGE_Z = .015;
|
|
43849
43879
|
var FRAME_BORDER = .4;
|
|
43850
43880
|
var FOCUS_COLOR$1 = 2450411;
|
|
@@ -44054,7 +44084,7 @@ function applyPlaceholderTexture(visual, label) {
|
|
|
44054
44084
|
visual.imageMesh.material.needsUpdate = true;
|
|
44055
44085
|
}
|
|
44056
44086
|
//#endregion
|
|
44057
|
-
//#region
|
|
44087
|
+
//#region src/renderer/shapes/kitchenTimers.ts
|
|
44058
44088
|
var FACE_SIZE = 256;
|
|
44059
44089
|
var BODY_COLOR = 14753096;
|
|
44060
44090
|
var KNOB_COLOR = 16448250;
|
|
@@ -44252,7 +44282,7 @@ function renderTimerFace(timer, canvas, now = Date.now()) {
|
|
|
44252
44282
|
return c;
|
|
44253
44283
|
}
|
|
44254
44284
|
//#endregion
|
|
44255
|
-
//#region
|
|
44285
|
+
//#region src/renderer/shapes/customObjects.ts
|
|
44256
44286
|
var FONT_URL = "/fonts/inter-medium.woff";
|
|
44257
44287
|
var CUSTOM_Z = .02;
|
|
44258
44288
|
var FOCUS_COLOR = 2450411;
|
|
@@ -44614,7 +44644,7 @@ function disposeObject3D(obj) {
|
|
|
44614
44644
|
});
|
|
44615
44645
|
}
|
|
44616
44646
|
//#endregion
|
|
44617
|
-
//#region
|
|
44647
|
+
//#region src/interaction/pointer/hitTest.ts
|
|
44618
44648
|
/** Topmost (most recently added) stroke under the point, or null. */
|
|
44619
44649
|
function hitStroke(doc, index, p, slop) {
|
|
44620
44650
|
const candidates = index.query(p.x - slop, p.y - slop, p.x + slop, p.y + slop);
|
|
@@ -44625,9 +44655,10 @@ function hitStroke(doc, index, p, slop) {
|
|
|
44625
44655
|
const scale = m ? avgScale(m) : 1;
|
|
44626
44656
|
let prev = null;
|
|
44627
44657
|
let prevWidth = 0;
|
|
44658
|
+
const handDrawn = stroke.tool !== "shape";
|
|
44628
44659
|
for (const point of stroke.points) {
|
|
44629
44660
|
const world = m ? apply(m, point) : point;
|
|
44630
|
-
const width = stroke.baseWidth * (MIN_WIDTH_FACTOR + (1 - MIN_WIDTH_FACTOR) * point.pressure) * scale;
|
|
44661
|
+
const width = (handDrawn ? stroke.baseWidth * (MIN_WIDTH_FACTOR + (1 - MIN_WIDTH_FACTOR) * point.pressure) : stroke.baseWidth) * scale;
|
|
44631
44662
|
if (prev) {
|
|
44632
44663
|
const reach = Math.max(width, prevWidth) / 2 + slop;
|
|
44633
44664
|
if (distToSegmentSq(p, prev, world) <= reach * reach) {
|
|
@@ -44655,7 +44686,7 @@ function distToSegmentSq(p, a, b) {
|
|
|
44655
44686
|
return dx * dx + dy * dy;
|
|
44656
44687
|
}
|
|
44657
44688
|
//#endregion
|
|
44658
|
-
//#region
|
|
44689
|
+
//#region src/interaction/tools/eraserTool.ts
|
|
44659
44690
|
var DECAY_PER_PASS = .4;
|
|
44660
44691
|
/** A point can take another decay pass after this long — rubbing works. */
|
|
44661
44692
|
var REARM_MS = 250;
|
|
@@ -44761,7 +44792,7 @@ var EraserTool = class {
|
|
|
44761
44792
|
...p,
|
|
44762
44793
|
...apply(m, p)
|
|
44763
44794
|
})) : run.points;
|
|
44764
|
-
this.ctx.renderer.addGhost(world, current.color, current.baseWidth * (m ? avgScale(m) : 1));
|
|
44795
|
+
this.ctx.renderer.addGhost(world, current.color, current.baseWidth * (m ? avgScale(m) : 1), current.tool !== "shape");
|
|
44765
44796
|
}
|
|
44766
44797
|
}
|
|
44767
44798
|
doc.removeStrokes(before.map((s) => s.id));
|
|
@@ -44783,7 +44814,7 @@ function partitionByErasure(points) {
|
|
|
44783
44814
|
return runs;
|
|
44784
44815
|
}
|
|
44785
44816
|
//#endregion
|
|
44786
|
-
//#region
|
|
44817
|
+
//#region src/interaction/tools/noteDrag.ts
|
|
44787
44818
|
/**
|
|
44788
44819
|
* Drag the focused note in X/Y. The grab is resolved on the note's own
|
|
44789
44820
|
* z-plane, not the board, so the note doesn't jump under a tilted ray.
|
|
@@ -44850,7 +44881,7 @@ var NoteDragState = class {
|
|
|
44850
44881
|
}
|
|
44851
44882
|
};
|
|
44852
44883
|
//#endregion
|
|
44853
|
-
//#region
|
|
44884
|
+
//#region src/interaction/tools/imageDrag.ts
|
|
44854
44885
|
/** Drag the focused image in X/Y; one command per drag. */
|
|
44855
44886
|
var ImageDragState = class {
|
|
44856
44887
|
constructor(ctx) {
|
|
@@ -44902,7 +44933,7 @@ var ImageDragState = class {
|
|
|
44902
44933
|
}
|
|
44903
44934
|
};
|
|
44904
44935
|
//#endregion
|
|
44905
|
-
//#region
|
|
44936
|
+
//#region src/interaction/tools/timerDrag.ts
|
|
44906
44937
|
/** Drag the focused timer in X/Y; one command per drag. */
|
|
44907
44938
|
var TimerDragState = class {
|
|
44908
44939
|
constructor(ctx) {
|
|
@@ -44954,7 +44985,7 @@ var TimerDragState = class {
|
|
|
44954
44985
|
}
|
|
44955
44986
|
};
|
|
44956
44987
|
//#endregion
|
|
44957
|
-
//#region
|
|
44988
|
+
//#region src/interaction/tools/shapeGeometry.ts
|
|
44958
44989
|
/** Uniform synthetic pressure; the ink shader supplies the hand-drawn feel. */
|
|
44959
44990
|
var PRESSURE = .7;
|
|
44960
44991
|
var MIN_ELLIPSE_SEGMENTS = 24;
|
|
@@ -44994,10 +45025,7 @@ function rect(a, b, step) {
|
|
|
44994
45025
|
a
|
|
44995
45026
|
];
|
|
44996
45027
|
const out = [];
|
|
44997
|
-
for (let i = 0; i < corners.length - 1; i++)
|
|
44998
|
-
const edge = sampleSegment(corners[i], corners[i + 1], step);
|
|
44999
|
-
out.push(...i === 0 ? edge : edge.slice(1));
|
|
45000
|
-
}
|
|
45028
|
+
for (let i = 0; i < corners.length - 1; i++) out.push(...sampleSegment(corners[i], corners[i + 1], step));
|
|
45001
45029
|
return out;
|
|
45002
45030
|
}
|
|
45003
45031
|
function ellipse(a, b, step) {
|
|
@@ -45068,10 +45096,7 @@ function polygon(sides, a, b, step, startAngle = -Math.PI / 2) {
|
|
|
45068
45096
|
}
|
|
45069
45097
|
vertices.push(vertices[0]);
|
|
45070
45098
|
const out = [];
|
|
45071
|
-
for (let i = 0; i < vertices.length - 1; i++)
|
|
45072
|
-
const edge = sampleSegment(vertices[i], vertices[i + 1], step);
|
|
45073
|
-
out.push(...i === 0 ? edge : edge.slice(1));
|
|
45074
|
-
}
|
|
45099
|
+
for (let i = 0; i < vertices.length - 1; i++) out.push(...sampleSegment(vertices[i], vertices[i + 1], step));
|
|
45075
45100
|
return out;
|
|
45076
45101
|
}
|
|
45077
45102
|
function star(points, a, b, step) {
|
|
@@ -45095,10 +45120,7 @@ function star(points, a, b, step) {
|
|
|
45095
45120
|
}
|
|
45096
45121
|
vertices.push(vertices[0]);
|
|
45097
45122
|
const out = [];
|
|
45098
|
-
for (let i = 0; i < vertices.length - 1; i++)
|
|
45099
|
-
const edge = sampleSegment(vertices[i], vertices[i + 1], step);
|
|
45100
|
-
out.push(...i === 0 ? edge : edge.slice(1));
|
|
45101
|
-
}
|
|
45123
|
+
for (let i = 0; i < vertices.length - 1; i++) out.push(...sampleSegment(vertices[i], vertices[i + 1], step));
|
|
45102
45124
|
return out;
|
|
45103
45125
|
}
|
|
45104
45126
|
function heart(a, b, step) {
|
|
@@ -45143,7 +45165,7 @@ function snappedEnd(a, b) {
|
|
|
45143
45165
|
};
|
|
45144
45166
|
}
|
|
45145
45167
|
//#endregion
|
|
45146
|
-
//#region
|
|
45168
|
+
//#region src/interaction/tools/shapeTool.ts
|
|
45147
45169
|
var MIN_DRAG_PX$1 = 4;
|
|
45148
45170
|
/** Drag out a shape; live preview through the real ink material. */
|
|
45149
45171
|
var ShapeTool = class {
|
|
@@ -45174,7 +45196,8 @@ var ShapeTool = class {
|
|
|
45174
45196
|
const strokes = this.polylines.map((points) => ({
|
|
45175
45197
|
id: crypto.randomUUID(),
|
|
45176
45198
|
color: this.ctx.inkColor(),
|
|
45177
|
-
baseWidth: this.ctx.
|
|
45199
|
+
baseWidth: this.ctx.shapeStrokeWidth(),
|
|
45200
|
+
tool: "shape",
|
|
45178
45201
|
points
|
|
45179
45202
|
}));
|
|
45180
45203
|
this.ctx.clusters.assign(strokes[0]);
|
|
@@ -45208,13 +45231,13 @@ var ShapeTool = class {
|
|
|
45208
45231
|
this.previews[i].visible = polyline !== void 0;
|
|
45209
45232
|
if (polyline) {
|
|
45210
45233
|
this.previews[i].geometry.dispose();
|
|
45211
|
-
this.previews[i].geometry = buildRibbonGeometry(polyline, this.ctx.
|
|
45234
|
+
this.previews[i].geometry = buildRibbonGeometry(polyline, this.ctx.shapeStrokeWidth(), void 0, false);
|
|
45212
45235
|
}
|
|
45213
45236
|
}
|
|
45214
45237
|
}
|
|
45215
45238
|
};
|
|
45216
45239
|
//#endregion
|
|
45217
|
-
//#region
|
|
45240
|
+
//#region src/interaction/tools/tableDrag.ts
|
|
45218
45241
|
function getHandleCursor(handle) {
|
|
45219
45242
|
switch (handle) {
|
|
45220
45243
|
case "nw":
|
|
@@ -45334,7 +45357,7 @@ var TableDragState = class {
|
|
|
45334
45357
|
}
|
|
45335
45358
|
};
|
|
45336
45359
|
//#endregion
|
|
45337
|
-
//#region
|
|
45360
|
+
//#region src/interaction/tools/tableTool.ts
|
|
45338
45361
|
var MIN_DRAG_PX = 6;
|
|
45339
45362
|
var TableTool = class {
|
|
45340
45363
|
constructor(ctx) {
|
|
@@ -45465,7 +45488,7 @@ var TableTool = class {
|
|
|
45465
45488
|
}
|
|
45466
45489
|
};
|
|
45467
45490
|
//#endregion
|
|
45468
|
-
//#region
|
|
45491
|
+
//#region src/interaction/tools/commentTool.ts
|
|
45469
45492
|
/** Click on the board to drop a new comment pin or open an existing one. */
|
|
45470
45493
|
var CommentTool = class {
|
|
45471
45494
|
constructor(ctx) {
|
|
@@ -45500,7 +45523,7 @@ var CommentTool = class {
|
|
|
45500
45523
|
}
|
|
45501
45524
|
};
|
|
45502
45525
|
//#endregion
|
|
45503
|
-
//#region
|
|
45526
|
+
//#region src/interaction/tools/textDrag.ts
|
|
45504
45527
|
/** Drag the focused text block in X/Y; one command per drag. */
|
|
45505
45528
|
var TextDragState = class {
|
|
45506
45529
|
constructor(ctx) {
|
|
@@ -45552,7 +45575,7 @@ var TextDragState = class {
|
|
|
45552
45575
|
}
|
|
45553
45576
|
};
|
|
45554
45577
|
//#endregion
|
|
45555
|
-
//#region
|
|
45578
|
+
//#region src/interaction/tools/fsm.ts
|
|
45556
45579
|
var ToolStateMachine = class {
|
|
45557
45580
|
constructor() {
|
|
45558
45581
|
this.states = /* @__PURE__ */ new Map();
|
|
@@ -45754,7 +45777,7 @@ var IdleState = class {
|
|
|
45754
45777
|
}
|
|
45755
45778
|
};
|
|
45756
45779
|
//#endregion
|
|
45757
|
-
//#region
|
|
45780
|
+
//#region src/renderer/selection/gizmo.ts
|
|
45758
45781
|
var GIZMO_Z = .05;
|
|
45759
45782
|
var HANDLE_PX = 9;
|
|
45760
45783
|
var HANDLE_HIT_PX = 12;
|
|
@@ -45985,7 +46008,7 @@ function boxesEqual(a, b) {
|
|
|
45985
46008
|
return a.minX === b.minX && a.minY === b.minY && a.maxX === b.maxX && a.maxY === b.maxY;
|
|
45986
46009
|
}
|
|
45987
46010
|
//#endregion
|
|
45988
|
-
//#region
|
|
46011
|
+
//#region src/interaction/tools/pressure.ts
|
|
45989
46012
|
var SIM_MAX = 1;
|
|
45990
46013
|
var SIM_MIN = .3;
|
|
45991
46014
|
var SMOOTHING = .25;
|
|
@@ -46007,7 +46030,7 @@ function clamp(v, lo, hi) {
|
|
|
46007
46030
|
return Math.min(hi, Math.max(lo, v));
|
|
46008
46031
|
}
|
|
46009
46032
|
//#endregion
|
|
46010
|
-
//#region
|
|
46033
|
+
//#region src/interaction/tools/strokeBuilder.ts
|
|
46011
46034
|
var StrokeBuilder = class {
|
|
46012
46035
|
constructor() {
|
|
46013
46036
|
this.points = [];
|
|
@@ -46057,7 +46080,7 @@ function catmullRom(v0, v1, v2, v3, t) {
|
|
|
46057
46080
|
return .5 * (2 * v1 + (-v0 + v2) * t + (2 * v0 - 5 * v1 + 4 * v2 - v3) * t2 + (-v0 + 3 * v1 - 3 * v2 + v3) * t3);
|
|
46058
46081
|
}
|
|
46059
46082
|
//#endregion
|
|
46060
|
-
//#region
|
|
46083
|
+
//#region src/interaction/tools/markerTool.ts
|
|
46061
46084
|
/** Sample spacing while drawing, in screen pixels. */
|
|
46062
46085
|
var MIN_SAMPLE_PX = 1.5;
|
|
46063
46086
|
/** A highlighter is a chisel tip: near-constant width, little pressure play. */
|
|
@@ -46160,7 +46183,7 @@ var MarkerTool = class {
|
|
|
46160
46183
|
}
|
|
46161
46184
|
};
|
|
46162
46185
|
//#endregion
|
|
46163
|
-
//#region
|
|
46186
|
+
//#region src/interaction/tools/orbitTool.ts
|
|
46164
46187
|
/**
|
|
46165
46188
|
* Orbit-preview (build prompt §4.2): alt-drag tilts the camera off-axis to
|
|
46166
46189
|
* read the board's material and depth; releasing eases back to the working
|
|
@@ -46195,7 +46218,7 @@ var OrbitTool = class {
|
|
|
46195
46218
|
}
|
|
46196
46219
|
};
|
|
46197
46220
|
//#endregion
|
|
46198
|
-
//#region
|
|
46221
|
+
//#region src/interaction/tools/panTool.ts
|
|
46199
46222
|
/** Grab-pan: content follows the pointer. */
|
|
46200
46223
|
var PanTool = class {
|
|
46201
46224
|
constructor(ctx) {
|
|
@@ -46225,7 +46248,7 @@ var PanTool = class {
|
|
|
46225
46248
|
}
|
|
46226
46249
|
};
|
|
46227
46250
|
//#endregion
|
|
46228
|
-
//#region
|
|
46251
|
+
//#region src/renderer/selection/selection.ts
|
|
46229
46252
|
/** The set of selected stroke ids. Drops ids the document no longer has. */
|
|
46230
46253
|
var SelectionManager = class {
|
|
46231
46254
|
constructor(doc) {
|
|
@@ -46276,7 +46299,7 @@ var SelectionManager = class {
|
|
|
46276
46299
|
}
|
|
46277
46300
|
};
|
|
46278
46301
|
//#endregion
|
|
46279
|
-
//#region
|
|
46302
|
+
//#region src/interaction/tools/selectTool.ts
|
|
46280
46303
|
var HIT_SLOP_PX = 4;
|
|
46281
46304
|
var CLICK_TOLERANCE_PX = 3;
|
|
46282
46305
|
var MIN_SCALE = .05;
|
|
@@ -46492,7 +46515,7 @@ function safeRatio(numerator, denominator) {
|
|
|
46492
46515
|
return raw;
|
|
46493
46516
|
}
|
|
46494
46517
|
//#endregion
|
|
46495
|
-
//#region
|
|
46518
|
+
//#region src/interaction/tools/customTool.ts
|
|
46496
46519
|
function extensionIdFromToolId(toolId) {
|
|
46497
46520
|
const slash = toolId.indexOf("/");
|
|
46498
46521
|
return slash === -1 ? toolId : toolId.slice(0, slash);
|
|
@@ -46607,12 +46630,19 @@ var ExtensionCommandBatch = class {
|
|
|
46607
46630
|
}
|
|
46608
46631
|
};
|
|
46609
46632
|
//#endregion
|
|
46610
|
-
//#region
|
|
46633
|
+
//#region src/composition/ScrawlEngine.ts
|
|
46611
46634
|
/** Marker stroke width in board units (~1% of the default view height). */
|
|
46612
46635
|
var BASE_WIDTH = .5;
|
|
46613
46636
|
/** Highlighter chisel width — wide enough to cover a line of handwriting. */
|
|
46614
46637
|
var HIGHLIGHT_WIDTH = 2.2;
|
|
46615
46638
|
/**
|
|
46639
|
+
* Shape (rectangle, ellipse, arrow, ...) border width in board units.
|
|
46640
|
+
* Deliberately thinner than BASE_WIDTH: a shape border reads as a crisp,
|
|
46641
|
+
* structural line, not an expressive marker stroke — this is also the
|
|
46642
|
+
* fallback when no Host theme configures ScrawlTheme.shapeStrokeWidth.
|
|
46643
|
+
*/
|
|
46644
|
+
var DEFAULT_SHAPE_STROKE_WIDTH = .15;
|
|
46645
|
+
/**
|
|
46616
46646
|
* Identity of a rendered selection badge: which item, its lock state, and
|
|
46617
46647
|
* where it sits on screen (rounded to the pixel, so sub-pixel camera drift
|
|
46618
46648
|
* does not churn React).
|
|
@@ -46633,10 +46663,11 @@ function emptyExtensionRegistry() {
|
|
|
46633
46663
|
* React never reaches past this class.
|
|
46634
46664
|
*/
|
|
46635
46665
|
var ScrawlEngine = class {
|
|
46636
|
-
constructor(canvas, documentId$1, extensionRegistry = emptyExtensionRegistry(), assetController = new AssetController(void 0), boardTheme = DEFAULT_BOARD_SURFACE_THEME) {
|
|
46666
|
+
constructor(canvas, documentId$1, extensionRegistry = emptyExtensionRegistry(), assetController = new AssetController(void 0), boardTheme = DEFAULT_BOARD_SURFACE_THEME, shapeStrokeWidth = DEFAULT_SHAPE_STROKE_WIDTH) {
|
|
46637
46667
|
this.canvas = canvas;
|
|
46638
46668
|
this.extensionRegistry = extensionRegistry;
|
|
46639
46669
|
this.boardTheme = boardTheme;
|
|
46670
|
+
this.shapeStrokeWidth = shapeStrokeWidth;
|
|
46640
46671
|
this.onToolChange = null;
|
|
46641
46672
|
this.onZoomChange = null;
|
|
46642
46673
|
this.onAuditEvent = null;
|
|
@@ -46731,6 +46762,7 @@ var ScrawlEngine = class {
|
|
|
46731
46762
|
setTool: (t) => this.setTool(t),
|
|
46732
46763
|
inkColor: () => this.tool === "highlighter" ? this.highlightColor : this.color,
|
|
46733
46764
|
baseWidth: () => this.tool === "highlighter" ? HIGHLIGHT_WIDTH : BASE_WIDTH,
|
|
46765
|
+
shapeStrokeWidth: () => this.shapeStrokeWidth,
|
|
46734
46766
|
activeTool: () => this.tool,
|
|
46735
46767
|
isSpaceHeld: () => this.spaceHeld,
|
|
46736
46768
|
pointerToBoard: (e) => pointerToBoard(e.clientX, e.clientY, canvas, this.scene.cameraRig.camera),
|
|
@@ -46995,6 +47027,10 @@ var ScrawlEngine = class {
|
|
|
46995
47027
|
this.boardTheme = theme;
|
|
46996
47028
|
this.scene.applyBoardTheme(theme);
|
|
46997
47029
|
}
|
|
47030
|
+
/** Live update of the shape tool's border width (board units). Already-drawn shapes keep the width they were drawn with. */
|
|
47031
|
+
setShapeStrokeWidth(width) {
|
|
47032
|
+
this.shapeStrokeWidth = width;
|
|
47033
|
+
}
|
|
46998
47034
|
/**
|
|
46999
47035
|
* Snap to a peer's camera. No-op while drawing so pointer-to-board
|
|
47000
47036
|
* mapping does not warp the in-progress stroke.
|
|
@@ -48056,7 +48092,7 @@ var ScrawlEngine = class {
|
|
|
48056
48092
|
}
|
|
48057
48093
|
};
|
|
48058
48094
|
//#endregion
|
|
48059
|
-
//#region src/controller-internal.ts
|
|
48095
|
+
//#region src/composition/controller-internal.ts
|
|
48060
48096
|
function createBoardController(options) {
|
|
48061
48097
|
return createBoardControllerWithEngine(options);
|
|
48062
48098
|
}
|
|
@@ -48074,9 +48110,12 @@ function createBoardControllerWithEngine(options, existingEngine) {
|
|
|
48074
48110
|
color: options.boardTheme?.surface ?? DEFAULT_BOARD_SURFACE_THEME.color,
|
|
48075
48111
|
gridMode: options.boardTheme?.gridMode ?? DEFAULT_BOARD_SURFACE_THEME.gridMode,
|
|
48076
48112
|
gridColor: options.boardTheme?.gridColor ?? DEFAULT_BOARD_SURFACE_THEME.gridColor,
|
|
48077
|
-
gridSpacing: options.boardTheme?.gridSpacing ?? DEFAULT_BOARD_SURFACE_THEME.gridSpacing
|
|
48113
|
+
gridSpacing: options.boardTheme?.gridSpacing ?? DEFAULT_BOARD_SURFACE_THEME.gridSpacing,
|
|
48114
|
+
gridLineWidth: options.boardTheme?.gridLineWidth ?? DEFAULT_BOARD_SURFACE_THEME.gridLineWidth,
|
|
48115
|
+
surfaceTexture: options.boardTheme?.surfaceTexture ?? DEFAULT_BOARD_SURFACE_THEME.surfaceTexture
|
|
48078
48116
|
};
|
|
48079
|
-
|
|
48117
|
+
let currentShapeStrokeWidth = options.boardTheme?.shapeStrokeWidth ?? .15;
|
|
48118
|
+
const engine = existingEngine ?? (options.canvas ? new ScrawlEngine(options.canvas, options.document.id, extensionRegistry, assetController, currentBoardTheme, currentShapeStrokeWidth) : null);
|
|
48080
48119
|
const document = engine?.document ?? new BoardDocument(documentId(options.document.id));
|
|
48081
48120
|
const history = engine?.history ?? new History(document);
|
|
48082
48121
|
const createId = options.createId ?? (() => crypto.randomUUID());
|
|
@@ -48565,9 +48604,15 @@ function createBoardControllerWithEngine(options, existingEngine) {
|
|
|
48565
48604
|
color: theme.surface ?? currentBoardTheme.color,
|
|
48566
48605
|
gridMode: theme.gridMode ?? currentBoardTheme.gridMode,
|
|
48567
48606
|
gridColor: theme.gridColor ?? currentBoardTheme.gridColor,
|
|
48568
|
-
gridSpacing: theme.gridSpacing ?? currentBoardTheme.gridSpacing
|
|
48607
|
+
gridSpacing: theme.gridSpacing ?? currentBoardTheme.gridSpacing,
|
|
48608
|
+
gridLineWidth: theme.gridLineWidth ?? currentBoardTheme.gridLineWidth,
|
|
48609
|
+
surfaceTexture: theme.surfaceTexture ?? currentBoardTheme.surfaceTexture
|
|
48569
48610
|
};
|
|
48570
48611
|
engine?.applyBoardTheme(currentBoardTheme);
|
|
48612
|
+
if (theme.shapeStrokeWidth !== void 0) {
|
|
48613
|
+
currentShapeStrokeWidth = theme.shapeStrokeWidth;
|
|
48614
|
+
engine?.setShapeStrokeWidth(currentShapeStrokeWidth);
|
|
48615
|
+
}
|
|
48571
48616
|
} },
|
|
48572
48617
|
view: {
|
|
48573
48618
|
fit() {
|
|
@@ -49338,7 +49383,7 @@ function createLocalBoard(options) {
|
|
|
49338
49383
|
};
|
|
49339
49384
|
}
|
|
49340
49385
|
//#endregion
|
|
49341
|
-
//#region src/theme.ts
|
|
49386
|
+
//#region src/ui/theme.ts
|
|
49342
49387
|
var scrawlThemePresets = Object.freeze({
|
|
49343
49388
|
light: Object.freeze({
|
|
49344
49389
|
surface: "#ffffff",
|
|
@@ -49347,6 +49392,7 @@ var scrawlThemePresets = Object.freeze({
|
|
|
49347
49392
|
text: "#1c1c1a",
|
|
49348
49393
|
textMuted: "#62625c",
|
|
49349
49394
|
edge: "#d4d4cc",
|
|
49395
|
+
primary: "#1856a3",
|
|
49350
49396
|
focus: "#1856a3",
|
|
49351
49397
|
selection: "#d9e8f7",
|
|
49352
49398
|
danger: "#a3302b",
|
|
@@ -49365,9 +49411,12 @@ var scrawlThemePresets = Object.freeze({
|
|
|
49365
49411
|
motionEasing: "cubic-bezier(0.2, 0, 0, 1)",
|
|
49366
49412
|
density: "comfortable",
|
|
49367
49413
|
boardSurface: "#f5f5f3",
|
|
49414
|
+
boardSurfaceTexture: "flat",
|
|
49368
49415
|
gridMode: "none",
|
|
49369
49416
|
gridColor: "#deded8",
|
|
49370
|
-
gridSpacing: 5
|
|
49417
|
+
gridSpacing: 5,
|
|
49418
|
+
gridLineWidth: 1,
|
|
49419
|
+
shapeStrokeWidth: .15
|
|
49371
49420
|
}),
|
|
49372
49421
|
dark: Object.freeze({
|
|
49373
49422
|
surface: "#171816",
|
|
@@ -49376,6 +49425,7 @@ var scrawlThemePresets = Object.freeze({
|
|
|
49376
49425
|
text: "#f4f4ee",
|
|
49377
49426
|
textMuted: "#b7b8ae",
|
|
49378
49427
|
edge: "#484a42",
|
|
49428
|
+
primary: "#9dc8ef",
|
|
49379
49429
|
focus: "#9dc8ef",
|
|
49380
49430
|
selection: "#314b63",
|
|
49381
49431
|
danger: "#ffaaa3",
|
|
@@ -49394,9 +49444,12 @@ var scrawlThemePresets = Object.freeze({
|
|
|
49394
49444
|
motionEasing: "cubic-bezier(0.2, 0, 0, 1)",
|
|
49395
49445
|
density: "comfortable",
|
|
49396
49446
|
boardSurface: "#232420",
|
|
49447
|
+
boardSurfaceTexture: "flat",
|
|
49397
49448
|
gridMode: "none",
|
|
49398
49449
|
gridColor: "#33352f",
|
|
49399
|
-
gridSpacing: 5
|
|
49450
|
+
gridSpacing: 5,
|
|
49451
|
+
gridLineWidth: 1,
|
|
49452
|
+
shapeStrokeWidth: .15
|
|
49400
49453
|
})
|
|
49401
49454
|
});
|
|
49402
49455
|
var variableNames = {
|
|
@@ -49406,6 +49459,7 @@ var variableNames = {
|
|
|
49406
49459
|
text: "--scrawl-color-text",
|
|
49407
49460
|
textMuted: "--scrawl-color-text-muted",
|
|
49408
49461
|
edge: "--scrawl-color-edge",
|
|
49462
|
+
primary: "--scrawl-color-primary",
|
|
49409
49463
|
focus: "--scrawl-color-focus",
|
|
49410
49464
|
selection: "--scrawl-color-selection",
|
|
49411
49465
|
danger: "--scrawl-color-danger",
|
|
@@ -49424,9 +49478,12 @@ var variableNames = {
|
|
|
49424
49478
|
motionEasing: "--scrawl-motion-easing",
|
|
49425
49479
|
density: "--scrawl-density",
|
|
49426
49480
|
boardSurface: "--scrawl-board-surface",
|
|
49481
|
+
boardSurfaceTexture: "--scrawl-board-surface-texture",
|
|
49427
49482
|
gridMode: "--scrawl-grid-mode",
|
|
49428
49483
|
gridColor: "--scrawl-grid-color",
|
|
49429
|
-
gridSpacing: "--scrawl-grid-spacing"
|
|
49484
|
+
gridSpacing: "--scrawl-grid-spacing",
|
|
49485
|
+
gridLineWidth: "--scrawl-grid-line-width",
|
|
49486
|
+
shapeStrokeWidth: "--scrawl-shape-stroke-width"
|
|
49430
49487
|
};
|
|
49431
49488
|
var colorTokens = /* @__PURE__ */ new Set([
|
|
49432
49489
|
"surface",
|
|
@@ -49435,6 +49492,7 @@ var colorTokens = /* @__PURE__ */ new Set([
|
|
|
49435
49492
|
"text",
|
|
49436
49493
|
"textMuted",
|
|
49437
49494
|
"edge",
|
|
49495
|
+
"primary",
|
|
49438
49496
|
"focus",
|
|
49439
49497
|
"selection",
|
|
49440
49498
|
"danger",
|
|
@@ -49482,10 +49540,22 @@ function validateScrawlTheme(theme) {
|
|
|
49482
49540
|
token,
|
|
49483
49541
|
message: "Expected none, line, or dot"
|
|
49484
49542
|
});
|
|
49543
|
+
else if (token === "boardSurfaceTexture" && value !== "flat" && value !== "textured") diagnostics.push({
|
|
49544
|
+
token,
|
|
49545
|
+
message: "Expected flat or textured"
|
|
49546
|
+
});
|
|
49485
49547
|
else if (token === "gridSpacing" && (!finiteNumber(value) || value < .5 || value > 50)) diagnostics.push({
|
|
49486
49548
|
token,
|
|
49487
49549
|
message: "Expected spacing 0.5-50 board units"
|
|
49488
49550
|
});
|
|
49551
|
+
else if (token === "gridLineWidth" && (!finiteNumber(value) || value < .5 || value > 8)) diagnostics.push({
|
|
49552
|
+
token,
|
|
49553
|
+
message: "Expected line width 0.5-8px"
|
|
49554
|
+
});
|
|
49555
|
+
else if (token === "shapeStrokeWidth" && (!finiteNumber(value) || value < .01 || value > 5)) diagnostics.push({
|
|
49556
|
+
token,
|
|
49557
|
+
message: "Expected stroke width 0.01-5 board units"
|
|
49558
|
+
});
|
|
49489
49559
|
else if ((token.endsWith("Family") || token.startsWith("elevation") || token === "motionEasing") && (typeof value !== "string" || !value.trim() || /[;{}]/.test(value))) diagnostics.push({
|
|
49490
49560
|
token,
|
|
49491
49561
|
message: "Expected a safe CSS value"
|
|
@@ -49556,12 +49626,12 @@ function luminance(color) {
|
|
|
49556
49626
|
return channels[0] * .2126 + channels[1] * .7152 + channels[2] * .0722;
|
|
49557
49627
|
}
|
|
49558
49628
|
function formatValue(token, value) {
|
|
49559
|
-
if (token === "baseFontSize" || token === "controlRadius" || token === "panelRadius") return `${value}px`;
|
|
49629
|
+
if (token === "baseFontSize" || token === "controlRadius" || token === "panelRadius" || token === "gridLineWidth") return `${value}px`;
|
|
49560
49630
|
if (token === "motionDuration") return `${value}ms`;
|
|
49561
49631
|
return String(value);
|
|
49562
49632
|
}
|
|
49563
49633
|
//#endregion
|
|
49564
|
-
//#region src/inline-editing.tsx
|
|
49634
|
+
//#region src/ui/dialogs/inline-editing.tsx
|
|
49565
49635
|
/** Inline note, text, and table-cell editors — driven entirely by public controller events and commands. */
|
|
49566
49636
|
function InlineEditors({ controller, renderPortal }) {
|
|
49567
49637
|
const [editor, setEditor] = useState(null);
|
|
@@ -49792,7 +49862,7 @@ function InlineEditors({ controller, renderPortal }) {
|
|
|
49792
49862
|
}))] });
|
|
49793
49863
|
}
|
|
49794
49864
|
//#endregion
|
|
49795
|
-
//#region src/style-shelf.tsx
|
|
49865
|
+
//#region src/ui/toolbar/style-shelf.tsx
|
|
49796
49866
|
var ERASER_RADII = [
|
|
49797
49867
|
["Fine", 1],
|
|
49798
49868
|
["Medium", 2],
|
|
@@ -49955,7 +50025,7 @@ function StyleShelf({ controller, snapshot }) {
|
|
|
49955
50025
|
});
|
|
49956
50026
|
}
|
|
49957
50027
|
//#endregion
|
|
49958
|
-
//#region src/default-ui.tsx
|
|
50028
|
+
//#region src/ui/default-ui.tsx
|
|
49959
50029
|
var PRIMARY_TOOLS = [
|
|
49960
50030
|
{
|
|
49961
50031
|
tool: "select",
|
|
@@ -50064,7 +50134,7 @@ var INKS = [
|
|
|
50064
50134
|
["Forest", "#315d46"],
|
|
50065
50135
|
["Oxblood", "#773f3b"]
|
|
50066
50136
|
];
|
|
50067
|
-
function DefaultBoardChrome({ controller, snapshot, renderPortal, className, style, regions, slots }) {
|
|
50137
|
+
function DefaultBoardChrome({ controller, snapshot, renderPortal, className, style, regions, slots, icons }) {
|
|
50068
50138
|
const [panel, setPanel] = useState(null);
|
|
50069
50139
|
const [query, setQuery] = useState("");
|
|
50070
50140
|
const [announcement, setAnnouncement] = useState("Board controls ready");
|
|
@@ -50218,7 +50288,10 @@ function DefaultBoardChrome({ controller, snapshot, renderPortal, className, sty
|
|
|
50218
50288
|
onClick: () => chooseTool(tool),
|
|
50219
50289
|
title: `${label} (${key})`,
|
|
50220
50290
|
type: "button",
|
|
50221
|
-
children:
|
|
50291
|
+
children: icons?.[tool] ? /* @__PURE__ */ jsx("span", {
|
|
50292
|
+
"aria-hidden": "true",
|
|
50293
|
+
children: icons[tool]
|
|
50294
|
+
}) : label
|
|
50222
50295
|
}, tool)), /* @__PURE__ */ jsxs("label", {
|
|
50223
50296
|
className: "scrawl-board__tool-select",
|
|
50224
50297
|
children: [/* @__PURE__ */ jsx("span", { children: "More tools" }), /* @__PURE__ */ jsxs("select", {
|
|
@@ -50484,7 +50557,7 @@ function download(blob, name) {
|
|
|
50484
50557
|
URL.revokeObjectURL(url);
|
|
50485
50558
|
}
|
|
50486
50559
|
//#endregion
|
|
50487
|
-
//#region src/presence.tsx
|
|
50560
|
+
//#region src/ui/panels/presence.tsx
|
|
50488
50561
|
var labelStyle = {
|
|
50489
50562
|
borderRadius: 999,
|
|
50490
50563
|
color: "#fff",
|
|
@@ -50644,9 +50717,12 @@ function ScrawlProvider({ controller, children, preset = "light", theme, portalC
|
|
|
50644
50717
|
useEffect(() => {
|
|
50645
50718
|
controller.boardTheme.set({
|
|
50646
50719
|
surface: resolved.values.boardSurface,
|
|
50720
|
+
surfaceTexture: resolved.values.boardSurfaceTexture,
|
|
50647
50721
|
gridMode: resolved.values.gridMode,
|
|
50648
50722
|
gridColor: resolved.values.gridColor,
|
|
50649
|
-
gridSpacing: resolved.values.gridSpacing
|
|
50723
|
+
gridSpacing: resolved.values.gridSpacing,
|
|
50724
|
+
gridLineWidth: resolved.values.gridLineWidth,
|
|
50725
|
+
shapeStrokeWidth: resolved.values.shapeStrokeWidth
|
|
50650
50726
|
});
|
|
50651
50727
|
}, [controller, resolved]);
|
|
50652
50728
|
useDeferredDisposal(controller, disposeOnUnmount);
|
|
@@ -50678,7 +50754,7 @@ function ScrawlProvider({ controller, children, preset = "light", theme, portalC
|
|
|
50678
50754
|
})
|
|
50679
50755
|
});
|
|
50680
50756
|
}
|
|
50681
|
-
function Scrawl({ children, preset, theme, portalContainer, className, style, onReady, onError, onThemeDiagnostic, canvas: suppliedCanvas, ...options }) {
|
|
50757
|
+
function Scrawl({ children, preset, theme, portalContainer, className, style, onReady, onError, onThemeDiagnostic, canvas: suppliedCanvas, icons, ...options }) {
|
|
50682
50758
|
const [runtime, setRuntime] = useState(null);
|
|
50683
50759
|
const runtimeRef = useRef(null);
|
|
50684
50760
|
const ownedCanvasRef = useRef(null);
|
|
@@ -50699,9 +50775,12 @@ function Scrawl({ children, preset, theme, portalContainer, className, style, on
|
|
|
50699
50775
|
const resolved = resolveScrawlTheme(preset, theme);
|
|
50700
50776
|
const boardTheme = {
|
|
50701
50777
|
surface: resolved.values.boardSurface,
|
|
50778
|
+
surfaceTexture: resolved.values.boardSurfaceTexture,
|
|
50702
50779
|
gridMode: resolved.values.gridMode,
|
|
50703
50780
|
gridColor: resolved.values.gridColor,
|
|
50704
|
-
gridSpacing: resolved.values.gridSpacing
|
|
50781
|
+
gridSpacing: resolved.values.gridSpacing,
|
|
50782
|
+
gridLineWidth: resolved.values.gridLineWidth,
|
|
50783
|
+
shapeStrokeWidth: resolved.values.shapeStrokeWidth
|
|
50705
50784
|
};
|
|
50706
50785
|
controller = createBoardController({
|
|
50707
50786
|
...options,
|
|
@@ -50771,7 +50850,7 @@ function Scrawl({ children, preset, theme, portalContainer, className, style, on
|
|
|
50771
50850
|
onThemeDiagnostic,
|
|
50772
50851
|
className,
|
|
50773
50852
|
style,
|
|
50774
|
-
children: [runtime.canvas && /* @__PURE__ */ jsx(ScrawlCanvas, { element: runtime.canvas }), children ?? /* @__PURE__ */ jsx(ScrawlDefaultUI, {})]
|
|
50853
|
+
children: [runtime.canvas && /* @__PURE__ */ jsx(ScrawlCanvas, { element: runtime.canvas }), children ?? /* @__PURE__ */ jsx(ScrawlDefaultUI, { icons })]
|
|
50775
50854
|
});
|
|
50776
50855
|
}
|
|
50777
50856
|
function ScrawlCanvas({ element, className, style, "aria-label": ariaLabel = "Scrawl Board" }) {
|
|
@@ -50807,10 +50886,11 @@ function ScrawlCanvas({ element, className, style, "aria-label": ariaLabel = "Sc
|
|
|
50807
50886
|
style
|
|
50808
50887
|
});
|
|
50809
50888
|
}
|
|
50810
|
-
function ScrawlDefaultUI({ className, style, regions, slots }) {
|
|
50889
|
+
function ScrawlDefaultUI({ className, style, regions, slots, icons }) {
|
|
50811
50890
|
return /* @__PURE__ */ jsx(DefaultBoardChrome, {
|
|
50812
50891
|
className,
|
|
50813
50892
|
controller: useScrawlController(),
|
|
50893
|
+
icons,
|
|
50814
50894
|
regions,
|
|
50815
50895
|
renderPortal: (children) => /* @__PURE__ */ jsx(ScrawlPortal, { children }),
|
|
50816
50896
|
slots,
|