@fieldnotes/core 0.66.0 → 0.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7174,19 +7174,181 @@ async function renderHtmlElements(elements, options) {
7174
7174
  return sources;
7175
7175
  }
7176
7176
 
7177
+ // src/fog/fog-style.ts
7178
+ var DEFAULT_PROCEDURAL_OPACITY = 0.6;
7179
+ var DEFAULT_PROCEDURAL_SCALE = 256;
7180
+ var DEFAULT_PROCEDURAL_SEED = 0;
7181
+ var DEFAULT_PROCEDURAL_DETAIL = 2;
7182
+ var DEFAULT_PROCEDURAL_TINT = "#ffffff";
7183
+ var MIN_SCALE = 64;
7184
+ var MAX_SCALE = 1024;
7185
+ var MIN_DETAIL = 1;
7186
+ var MAX_DETAIL = 4;
7187
+ var MAX_SEED = 65535;
7188
+ function clamp(value, min, max) {
7189
+ return Math.max(min, Math.min(max, value));
7190
+ }
7191
+ function finiteOrDefault(value, defaultValue) {
7192
+ return value !== void 0 && Number.isFinite(value) ? value : defaultValue;
7193
+ }
7194
+ function resolveFogStyle(style, legacyColor, defaultColor) {
7195
+ if (style && style.kind === "procedural") {
7196
+ const opacity = clamp(finiteOrDefault(style.opacity, DEFAULT_PROCEDURAL_OPACITY), 0, 1);
7197
+ const scale = clamp(
7198
+ finiteOrDefault(style.scale, DEFAULT_PROCEDURAL_SCALE),
7199
+ MIN_SCALE,
7200
+ MAX_SCALE
7201
+ );
7202
+ const seed = clamp(
7203
+ Math.floor(finiteOrDefault(style.seed, DEFAULT_PROCEDURAL_SEED)),
7204
+ 0,
7205
+ MAX_SEED
7206
+ );
7207
+ const detail = clamp(
7208
+ Math.floor(finiteOrDefault(style.detail, DEFAULT_PROCEDURAL_DETAIL)),
7209
+ MIN_DETAIL,
7210
+ MAX_DETAIL
7211
+ );
7212
+ return {
7213
+ kind: "procedural",
7214
+ backdrop: style.backdrop,
7215
+ // `tint` is required for typed callers. Keep a visible runtime fallback for
7216
+ // untyped/older JavaScript hosts instead of producing a flat same-color overlay.
7217
+ tint: style.tint || DEFAULT_PROCEDURAL_TINT,
7218
+ opacity,
7219
+ scale,
7220
+ seed,
7221
+ detail
7222
+ };
7223
+ }
7224
+ if (style && (!style.kind || style.kind === "solid")) {
7225
+ return { kind: "solid", color: style.color };
7226
+ }
7227
+ return { kind: "solid", color: legacyColor ?? defaultColor };
7228
+ }
7229
+
7230
+ // src/fog/fog-procedural-tile.ts
7231
+ var TILE_PX = 128;
7232
+ function xorshift32(state) {
7233
+ state ^= state << 13;
7234
+ state ^= state >>> 17;
7235
+ state ^= state << 5;
7236
+ return state >>> 0;
7237
+ }
7238
+ function seedState(seed) {
7239
+ return seed * 2654435761 + 1 >>> 0 || 1;
7240
+ }
7241
+ function smoothstep(t) {
7242
+ return t * t * (3 - 2 * t);
7243
+ }
7244
+ function lerp(a, b, t) {
7245
+ return a + (b - a) * t;
7246
+ }
7247
+ function generateGradients(size, prngState) {
7248
+ const count = size * size;
7249
+ const gx = new Float32Array(count);
7250
+ const gy = new Float32Array(count);
7251
+ let s = prngState;
7252
+ for (let i = 0; i < count; i++) {
7253
+ s = xorshift32(s);
7254
+ const angle = (s >>> 0) / 4294967296 * Math.PI * 2;
7255
+ gx[i] = Math.cos(angle);
7256
+ gy[i] = Math.sin(angle);
7257
+ }
7258
+ return { gx, gy, state: s };
7259
+ }
7260
+ function perlinNoise(px, py, gridSize, gx, gy) {
7261
+ const gx0 = Math.floor(px) % gridSize;
7262
+ const gy0 = Math.floor(py) % gridSize;
7263
+ const gx1 = (gx0 + 1) % gridSize;
7264
+ const gy1 = (gy0 + 1) % gridSize;
7265
+ const fx = px - Math.floor(px);
7266
+ const fy = py - Math.floor(py);
7267
+ const sx = smoothstep(fx);
7268
+ const sy = smoothstep(fy);
7269
+ const dot = (ix, iy, dx, dy) => {
7270
+ const idx = iy * gridSize + ix;
7271
+ return gx[idx] * dx + gy[idx] * dy;
7272
+ };
7273
+ const n00 = dot(gx0, gy0, fx, fy);
7274
+ const n10 = dot(gx1, gy0, fx - 1, fy);
7275
+ const n01 = dot(gx0, gy1, fx, fy - 1);
7276
+ const n11 = dot(gx1, gy1, fx - 1, fy - 1);
7277
+ return lerp(lerp(n00, n10, sx), lerp(n01, n11, sx), sy);
7278
+ }
7279
+ function layeredNoise(x, y, octaves, gridSize, gx, gy) {
7280
+ let value = 0;
7281
+ let amplitude = 1;
7282
+ let frequency = 1;
7283
+ let maxAmplitude = 0;
7284
+ for (let o = 0; o < octaves; o++) {
7285
+ value += perlinNoise(x * frequency, y * frequency, gridSize * frequency, gx, gy) * amplitude;
7286
+ maxAmplitude += amplitude;
7287
+ amplitude *= 0.5;
7288
+ frequency *= 2;
7289
+ }
7290
+ return (value / maxAmplitude + 1) * 0.5;
7291
+ }
7292
+ function generateProceduralTile(style) {
7293
+ const gridSize = 8;
7294
+ const maxFreq = gridSize * (1 << style.detail - 1);
7295
+ const { gx, gy } = generateGradients(maxFreq, seedState(style.seed));
7296
+ const data = new Uint8ClampedArray(TILE_PX * TILE_PX * 4);
7297
+ for (let py = 0; py < TILE_PX; py++) {
7298
+ for (let px = 0; px < TILE_PX; px++) {
7299
+ const nx = px / TILE_PX * gridSize;
7300
+ const ny = py / TILE_PX * gridSize;
7301
+ const n2 = layeredNoise(nx, ny, style.detail, gridSize, gx, gy);
7302
+ const alpha = Math.round(n2 * style.opacity * 255);
7303
+ const idx = (py * TILE_PX + px) * 4;
7304
+ data[idx] = 255;
7305
+ data[idx + 1] = 255;
7306
+ data[idx + 2] = 255;
7307
+ data[idx + 3] = alpha;
7308
+ }
7309
+ }
7310
+ return { data, width: TILE_PX, height: TILE_PX };
7311
+ }
7312
+ var tileCache = /* @__PURE__ */ new Map();
7313
+ var MAX_CACHED_TILES = 16;
7314
+ function getCachedProceduralTile(style) {
7315
+ const key = `${style.opacity}\0${style.seed}\0${style.detail}`;
7316
+ const cached = tileCache.get(key);
7317
+ if (cached) return cached;
7318
+ const tile = generateProceduralTile(style);
7319
+ if (tileCache.size >= MAX_CACHED_TILES) {
7320
+ const oldest = tileCache.keys().next().value;
7321
+ if (oldest !== void 0) tileCache.delete(oldest);
7322
+ }
7323
+ tileCache.set(key, tile);
7324
+ return tile;
7325
+ }
7326
+ function clearProceduralTileCache() {
7327
+ tileCache.clear();
7328
+ }
7329
+
7177
7330
  // src/fog/fog-renderer.ts
7178
7331
  var DEFAULT_EDITOR_COLOR = "rgba(30, 40, 60, 0.45)";
7179
7332
  var DEFAULT_PLAYER_COLOR = "#0b1020";
7180
7333
  var FogRenderer = class {
7181
7334
  tileCache = /* @__PURE__ */ new Map();
7335
+ patternCache = /* @__PURE__ */ new Map();
7182
7336
  state = null;
7183
7337
  viewMode = "off";
7184
7338
  dirty = true;
7185
- editorColor;
7186
- playerColor;
7339
+ editorStyle;
7340
+ playerStyle;
7187
7341
  constructor(options = {}) {
7188
- this.editorColor = options.editorColor ?? DEFAULT_EDITOR_COLOR;
7189
- this.playerColor = options.playerColor ?? DEFAULT_PLAYER_COLOR;
7342
+ this.editorStyle = resolveFogStyle(
7343
+ options.editorStyle,
7344
+ options.editorColor,
7345
+ DEFAULT_EDITOR_COLOR
7346
+ );
7347
+ this.playerStyle = resolveFogStyle(
7348
+ options.playerStyle,
7349
+ options.playerColor,
7350
+ DEFAULT_PLAYER_COLOR
7351
+ );
7190
7352
  }
7191
7353
  setState(state) {
7192
7354
  this.state = state;
@@ -7212,12 +7374,23 @@ var FogRenderer = class {
7212
7374
  isVisible() {
7213
7375
  return this.viewMode !== "off" && this.state !== null;
7214
7376
  }
7377
+ getResolvedStyle(mode) {
7378
+ return mode === "editor" ? this.editorStyle : this.playerStyle;
7379
+ }
7215
7380
  render(ctx, camera, viewportWidth, viewportHeight, _dpr) {
7216
7381
  if (!this.state || this.viewMode === "off") return;
7217
7382
  const def = this.state.definition;
7218
7383
  const cellSize = def.cellSize;
7219
7384
  const tileWorldSize = FOG_TILE_CELLS * cellSize;
7220
- const color = this.viewMode === "editor" ? this.editorColor : this.playerColor;
7385
+ const mode = this.viewMode === "editor" ? "editor" : "player";
7386
+ const style = this.getResolvedStyle(mode);
7387
+ const proceduralStyle = style.kind === "procedural" ? style : null;
7388
+ const color = style.kind === "procedural" ? normalizeCanvasColor(
7389
+ ctx,
7390
+ style.backdrop,
7391
+ mode === "player" ? DEFAULT_PLAYER_COLOR : DEFAULT_EDITOR_COLOR
7392
+ ) : style.color;
7393
+ const safetyColor = proceduralStyle && mode === "player" ? DEFAULT_PLAYER_COLOR : null;
7221
7394
  const worldBounds = getVisibleWorld(camera, viewportWidth, viewportHeight);
7222
7395
  const minTX = Math.floor(Math.max(def.bounds.x, worldBounds.x) / tileWorldSize);
7223
7396
  const minTY = Math.floor(Math.max(def.bounds.y, worldBounds.y) / tileWorldSize);
@@ -7248,7 +7421,22 @@ var FogRenderer = class {
7248
7421
  const clipR = Math.min(tileWorldX + tileWorldSize, def.bounds.x + def.bounds.w);
7249
7422
  const clipB = Math.min(tileWorldY + tileWorldSize, def.bounds.y + def.bounds.h);
7250
7423
  if (clipR > clipX && clipB > clipY) {
7424
+ if (safetyColor) {
7425
+ ctx.fillStyle = safetyColor;
7426
+ ctx.fillRect(clipX, clipY, clipR - clipX, clipB - clipY);
7427
+ }
7428
+ ctx.fillStyle = color;
7251
7429
  ctx.fillRect(clipX, clipY, clipR - clipX, clipB - clipY);
7430
+ if (proceduralStyle) {
7431
+ this.paintProceduralOverlay(
7432
+ ctx,
7433
+ proceduralStyle,
7434
+ clipX,
7435
+ clipY,
7436
+ clipR - clipX,
7437
+ clipB - clipY
7438
+ );
7439
+ }
7252
7440
  }
7253
7441
  continue;
7254
7442
  }
@@ -7256,18 +7444,33 @@ var FogRenderer = class {
7256
7444
  continue;
7257
7445
  }
7258
7446
  if (data) {
7447
+ if (safetyColor) this.renderTile(ctx, data, tx, ty, def, safetyColor);
7259
7448
  this.renderTile(ctx, data, tx, ty, def, color);
7449
+ if (proceduralStyle) {
7450
+ this.renderTileProceduralOverlay(ctx, data, tx, ty, def, proceduralStyle);
7451
+ }
7260
7452
  }
7261
7453
  }
7262
7454
  }
7263
7455
  ctx.restore();
7264
7456
  this.dirty = false;
7265
7457
  }
7266
- renderForExport(ctx, state, mode, color) {
7458
+ renderForExport(ctx, state, mode, color, style) {
7267
7459
  const def = state.definition;
7268
7460
  const cellSize = def.cellSize;
7269
7461
  const tileWorldSize = FOG_TILE_CELLS * cellSize;
7270
- const fogColor = color ?? (mode === "editor" ? this.editorColor : this.playerColor);
7462
+ const resolved = style ? resolveFogStyle(
7463
+ style,
7464
+ void 0,
7465
+ mode === "editor" ? DEFAULT_EDITOR_COLOR : DEFAULT_PLAYER_COLOR
7466
+ ) : this.getResolvedStyle(mode);
7467
+ const proceduralStyle = !color && resolved.kind === "procedural" ? resolved : null;
7468
+ const fogColor = color ?? (proceduralStyle ? normalizeCanvasColor(
7469
+ ctx,
7470
+ proceduralStyle.backdrop,
7471
+ mode === "player" ? DEFAULT_PLAYER_COLOR : DEFAULT_EDITOR_COLOR
7472
+ ) : resolved.kind === "solid" ? resolved.color : resolved.backdrop);
7473
+ const safetyColor = proceduralStyle && mode === "player" ? DEFAULT_PLAYER_COLOR : null;
7271
7474
  const baseCovered = def.base === "covered";
7272
7475
  const tileMap = /* @__PURE__ */ new Map();
7273
7476
  for (const tile of state.tiles) {
@@ -7290,20 +7493,129 @@ var FogRenderer = class {
7290
7493
  const clipR = Math.min(tileWorldX + tileWorldSize, def.bounds.x + def.bounds.w);
7291
7494
  const clipB = Math.min(tileWorldY + tileWorldSize, def.bounds.y + def.bounds.h);
7292
7495
  if (clipR > clipX && clipB > clipY) {
7496
+ if (safetyColor) {
7497
+ ctx.fillStyle = safetyColor;
7498
+ ctx.fillRect(clipX, clipY, clipR - clipX, clipB - clipY);
7499
+ }
7500
+ ctx.fillStyle = fogColor;
7293
7501
  ctx.fillRect(clipX, clipY, clipR - clipX, clipB - clipY);
7502
+ if (proceduralStyle) {
7503
+ this.paintProceduralOverlay(
7504
+ ctx,
7505
+ proceduralStyle,
7506
+ clipX,
7507
+ clipY,
7508
+ clipR - clipX,
7509
+ clipB - clipY
7510
+ );
7511
+ }
7294
7512
  }
7295
7513
  continue;
7296
7514
  }
7297
7515
  if (data) {
7516
+ if (safetyColor) this.renderTileForExport(ctx, data, tx, ty, def, safetyColor);
7298
7517
  this.renderTileForExport(ctx, data, tx, ty, def, fogColor);
7518
+ if (proceduralStyle) {
7519
+ this.renderTileProceduralOverlay(ctx, data, tx, ty, def, proceduralStyle);
7520
+ }
7299
7521
  }
7300
7522
  }
7301
7523
  }
7302
7524
  }
7303
7525
  dispose() {
7304
7526
  this.tileCache.clear();
7527
+ this.patternCache.clear();
7528
+ clearProceduralTileCache();
7305
7529
  this.state = null;
7306
7530
  }
7531
+ getOrCreatePattern(ctx, style, worldScale) {
7532
+ const key = `${style.backdrop}\0${style.tint}\0${style.opacity}\0${style.scale}\0${style.seed}\0${style.detail}\0${worldScale}`;
7533
+ const cached = this.patternCache.get(key);
7534
+ if (cached !== void 0) return cached;
7535
+ let pattern = null;
7536
+ try {
7537
+ const tileData = getCachedProceduralTile(style);
7538
+ pattern = this.createPatternFromTileData(ctx, tileData, style, worldScale);
7539
+ } catch {
7540
+ }
7541
+ if (this.patternCache.size >= 32) {
7542
+ const oldest = this.patternCache.keys().next().value;
7543
+ if (oldest !== void 0) this.patternCache.delete(oldest);
7544
+ }
7545
+ this.patternCache.set(key, pattern);
7546
+ return pattern;
7547
+ }
7548
+ createPatternFromTileData(ctx, tileData, style, worldScale) {
7549
+ if (typeof document === "undefined") return null;
7550
+ const sourceCanvas = document.createElement("canvas");
7551
+ sourceCanvas.width = tileData.width;
7552
+ sourceCanvas.height = tileData.height;
7553
+ const sourceCtx = sourceCanvas.getContext("2d");
7554
+ if (!sourceCtx) return null;
7555
+ const imageData = new ImageData(
7556
+ new Uint8ClampedArray(tileData.data),
7557
+ tileData.width,
7558
+ tileData.height
7559
+ );
7560
+ sourceCtx.putImageData(imageData, 0, 0);
7561
+ sourceCtx.globalCompositeOperation = "source-in";
7562
+ sourceCtx.fillStyle = normalizeCanvasColor(sourceCtx, style.tint, "#ffffff");
7563
+ sourceCtx.fillRect(0, 0, tileData.width, tileData.height);
7564
+ sourceCtx.globalCompositeOperation = "source-over";
7565
+ const patternScale = style.scale * worldScale / tileData.width;
7566
+ const pattern = ctx.createPattern(sourceCanvas, "repeat");
7567
+ if (pattern && typeof pattern.setTransform === "function" && typeof DOMMatrix !== "undefined") {
7568
+ try {
7569
+ pattern.setTransform(new DOMMatrix([patternScale, 0, 0, patternScale, 0, 0]));
7570
+ return pattern;
7571
+ } catch {
7572
+ }
7573
+ }
7574
+ const patternPx = Math.round(style.scale * worldScale);
7575
+ if (patternPx < 1) return null;
7576
+ const patternCanvas = document.createElement("canvas");
7577
+ patternCanvas.width = patternPx;
7578
+ patternCanvas.height = patternPx;
7579
+ const patternCtx = patternCanvas.getContext("2d");
7580
+ if (!patternCtx) return null;
7581
+ patternCtx.drawImage(sourceCanvas, 0, 0, patternPx, patternPx);
7582
+ return ctx.createPattern(patternCanvas, "repeat");
7583
+ }
7584
+ paintProceduralOverlay(ctx, style, x, y, w, h) {
7585
+ const pattern = this.getOrCreatePattern(ctx, style, 1);
7586
+ if (!pattern) return;
7587
+ ctx.save();
7588
+ ctx.fillStyle = pattern;
7589
+ ctx.fillRect(x, y, w, h);
7590
+ ctx.restore();
7591
+ }
7592
+ renderTileProceduralOverlay(ctx, data, tx, ty, def, style) {
7593
+ const cellSize = def.cellSize;
7594
+ const tileWorldX = tx * FOG_TILE_CELLS * cellSize;
7595
+ const tileWorldY = ty * FOG_TILE_CELLS * cellSize;
7596
+ const pattern = this.getOrCreatePattern(ctx, style, 1);
7597
+ if (!pattern) return;
7598
+ const bytes = decodeBase64(data);
7599
+ ctx.save();
7600
+ ctx.fillStyle = pattern;
7601
+ for (let row = 0; row < FOG_TILE_CELLS; row++) {
7602
+ for (let col = 0; col < FOG_TILE_CELLS; col++) {
7603
+ const cellWorldX = tileWorldX + col * cellSize;
7604
+ const cellWorldY = tileWorldY + row * cellSize;
7605
+ if (cellWorldX < def.bounds.x || cellWorldY < def.bounds.y || cellWorldX >= def.bounds.x + def.bounds.w || cellWorldY >= def.bounds.y + def.bounds.h) {
7606
+ continue;
7607
+ }
7608
+ const index = row * FOG_TILE_CELLS + col;
7609
+ const byteIndex = index >> 3;
7610
+ const bitIndex = 7 - (index & 7);
7611
+ const revealed = (bytes[byteIndex] >> bitIndex & 1) === 1;
7612
+ if (!revealed) {
7613
+ ctx.fillRect(cellWorldX, cellWorldY, cellSize, cellSize);
7614
+ }
7615
+ }
7616
+ }
7617
+ ctx.restore();
7618
+ }
7307
7619
  tileRaster(data, color) {
7308
7620
  const key = `${color}\0${data}`;
7309
7621
  const cached = this.tileCache.get(key);
@@ -7387,6 +7699,22 @@ function getVisibleWorld(camera, viewportWidth, viewportHeight) {
7387
7699
  h: bottomRight.y - topLeft.y
7388
7700
  };
7389
7701
  }
7702
+ function normalizeCanvasColor(ctx, value, fallback) {
7703
+ const previous = ctx.fillStyle;
7704
+ try {
7705
+ ctx.fillStyle = "#010203";
7706
+ ctx.fillStyle = value;
7707
+ const first = ctx.fillStyle;
7708
+ ctx.fillStyle = "#040506";
7709
+ ctx.fillStyle = value;
7710
+ const second = ctx.fillStyle;
7711
+ return typeof first === "string" && first === second ? first : fallback;
7712
+ } catch {
7713
+ return fallback;
7714
+ } finally {
7715
+ ctx.fillStyle = previous;
7716
+ }
7717
+ }
7390
7718
 
7391
7719
  // src/canvas/export-image.ts
7392
7720
  var DEFAULT_IMAGE_TIMEOUT_MS = 1e4;
@@ -7802,7 +8130,13 @@ async function exportImage(store, options = {}, layerManager) {
7802
8130
  }
7803
8131
  if (options.fog) {
7804
8132
  const fogRenderer = new FogRenderer();
7805
- fogRenderer.renderForExport(ctx, options.fog.state, options.fog.mode, options.fog.color);
8133
+ fogRenderer.renderForExport(
8134
+ ctx,
8135
+ options.fog.state,
8136
+ options.fog.mode,
8137
+ options.fog.color,
8138
+ options.fog.style
8139
+ );
7806
8140
  }
7807
8141
  const mimeType = format === "jpeg" ? "image/jpeg" : "image/png";
7808
8142
  return new Promise((resolve) => {
@@ -8196,7 +8530,13 @@ async function exportSvg(store, options = {}, layerManager) {
8196
8530
  if (fogCtx) {
8197
8531
  fogCtx.translate(-bounds.x, -bounds.y);
8198
8532
  const fogRenderer = new FogRenderer();
8199
- fogRenderer.renderForExport(fogCtx, fogState, options.fog.mode, options.fog.color);
8533
+ fogRenderer.renderForExport(
8534
+ fogCtx,
8535
+ fogState,
8536
+ options.fog.mode,
8537
+ options.fog.color,
8538
+ options.fog.style
8539
+ );
8200
8540
  try {
8201
8541
  const fogDataUri = fogCanvas.toDataURL("image/png");
8202
8542
  if (fogDataUri.startsWith("data:")) {
@@ -11191,26 +11531,35 @@ var Viewport = class _Viewport {
11191
11531
  const expected = base.expectedCanvasTypes ? /* @__PURE__ */ new Set([...declared, ...base.expectedCanvasTypes]) : declared;
11192
11532
  return { ...base, htmlPainters: registry, expectedCanvasTypes: expected };
11193
11533
  }
11194
- async exportImage(options) {
11195
- const opts = this.withHtmlDefaults(options);
11196
- if (opts.fog === void 0 && this.fogRenderer.isVisible()) {
11197
- const state = this.fogManager.getState();
11198
- if (state) {
11199
- const mode = this.fogRenderer.getViewMode();
11200
- opts.fog = { state, mode };
11201
- }
11534
+ /**
11535
+ * Carry constructor-configured fog presentation into both implicit exports and
11536
+ * explicit state/mode exports. Explicit style and legacy color overrides win.
11537
+ */
11538
+ withFogDefaults(options) {
11539
+ const fog = options.fog;
11540
+ if (fog === false) return options;
11541
+ if (fog !== void 0) {
11542
+ if (fog.style !== void 0 || fog.color !== void 0) return options;
11543
+ return {
11544
+ ...options,
11545
+ fog: { ...fog, style: this.fogRenderer.getResolvedStyle(fog.mode) }
11546
+ };
11202
11547
  }
11548
+ if (!this.fogRenderer.isVisible()) return options;
11549
+ const state = this.fogManager.getState();
11550
+ if (!state) return options;
11551
+ const mode = this.fogRenderer.getViewMode();
11552
+ return {
11553
+ ...options,
11554
+ fog: { state, mode, style: this.fogRenderer.getResolvedStyle(mode) }
11555
+ };
11556
+ }
11557
+ async exportImage(options) {
11558
+ const opts = this.withFogDefaults(this.withHtmlDefaults(options));
11203
11559
  return exportImage(this.store, opts, this.layerManager);
11204
11560
  }
11205
11561
  async exportSVG(options) {
11206
- const opts = this.withHtmlDefaults(options);
11207
- if (opts.fog === void 0 && this.fogRenderer.isVisible()) {
11208
- const state = this.fogManager.getState();
11209
- if (state) {
11210
- const mode = this.fogRenderer.getViewMode();
11211
- opts.fog = { state, mode };
11212
- }
11213
- }
11562
+ const opts = this.withFogDefaults(this.withHtmlDefaults(options));
11214
11563
  return exportSvg(this.store, opts, this.layerManager);
11215
11564
  }
11216
11565
  loadState(state) {
@@ -12844,15 +13193,15 @@ function applyCameraView(camera, view, canvasW, canvasH) {
12844
13193
  var DEFAULT_DURATION_MS3 = 400;
12845
13194
  var FRAMED_EPSILON = 1e-6;
12846
13195
  var easeOutCubic2 = (t) => 1 - Math.pow(1 - t, 3);
12847
- function lerp(a, b, k) {
13196
+ function lerp2(a, b, k) {
12848
13197
  return a + (b - a) * k;
12849
13198
  }
12850
13199
  function lerpView(from, to, k) {
12851
13200
  return {
12852
- x: lerp(from.x, to.x, k),
12853
- y: lerp(from.y, to.y, k),
12854
- w: lerp(from.w, to.w, k),
12855
- h: lerp(from.h, to.h, k)
13201
+ x: lerp2(from.x, to.x, k),
13202
+ y: lerp2(from.y, to.y, k),
13203
+ w: lerp2(from.w, to.w, k),
13204
+ h: lerp2(from.h, to.h, k)
12856
13205
  };
12857
13206
  }
12858
13207
  function viewsClose(a, b) {
@@ -14106,7 +14455,7 @@ var PencilTool = class {
14106
14455
  };
14107
14456
 
14108
14457
  // src/elements/stroke-erase.ts
14109
- function lerp2(a, b, t) {
14458
+ function lerp3(a, b, t) {
14110
14459
  return {
14111
14460
  x: a.x + (b.x - a.x) * t,
14112
14461
  y: a.y + (b.y - a.y) * t,
@@ -14165,13 +14514,13 @@ function erasePoints(points, eraser, radius) {
14165
14514
  erased = true;
14166
14515
  if (tLo > 0) {
14167
14516
  if (current.length === 0) current.push(a);
14168
- current.push(lerp2(a, b, tLo));
14517
+ current.push(lerp3(a, b, tLo));
14169
14518
  flush();
14170
14519
  } else {
14171
14520
  flush();
14172
14521
  }
14173
14522
  if (tHi < 1) {
14174
- current = [lerp2(a, b, tHi), b];
14523
+ current = [lerp3(a, b, tHi), b];
14175
14524
  }
14176
14525
  }
14177
14526
  flush();
@@ -16687,7 +17036,7 @@ var FogTool = class {
16687
17036
  };
16688
17037
 
16689
17038
  // src/index.ts
16690
- var VERSION = "0.66.0";
17039
+ var VERSION = "0.67.0";
16691
17040
  export {
16692
17041
  AWARENESS_MAX_SELECTION,
16693
17042
  AWARENESS_PRESENCE_KIND,
@@ -16795,6 +17144,7 @@ export {
16795
17144
  isPingPresence,
16796
17145
  pathDistanceCells,
16797
17146
  recommendedFogCellSize,
17147
+ resolveFogStyle,
16798
17148
  resolveHtmlRouting,
16799
17149
  setFontSize,
16800
17150
  smartSnap,