@ntmats/hc-ui 0.6.0 → 0.7.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.d.ts CHANGED
@@ -1358,6 +1358,21 @@ export interface HCMapJson {
1358
1358
  ramps?: JsonRamp[];
1359
1359
  ziplines?: JsonWall[];
1360
1360
  }
1361
+ /** The grid's line between squares. */
1362
+ export declare const MAP_GRID_COLOR = "#222222";
1363
+ /** `soft` grid: the line between two plain squares (clear, at floor level). */
1364
+ export declare const MAP_GRID_SOFT_COLOR = "#D4D2CC";
1365
+ /** `soft` grid: between two squares of the same terrain, the fill darkened by this fraction. */
1366
+ export declare const MAP_GRID_TERRAIN_SHADE = 0.22;
1367
+ export interface MapDrawOptions {
1368
+ /**
1369
+ * `dark` (default): every square outlined in the dark grid, as printed. `soft`: the line between
1370
+ * two plain squares (clear terrain at floor level) is light gray; between two squares of the same
1371
+ * terrain, a darker tone of that terrain's color; between different kinds and on the map's edge,
1372
+ * the dark grid.
1373
+ */
1374
+ grid?: 'dark' | 'soft';
1375
+ }
1361
1376
  export declare class HCMap {
1362
1377
  width: number;
1363
1378
  height: number;
@@ -1368,7 +1383,13 @@ export declare class HCMap {
1368
1383
  constructor(json: HCMapJson);
1369
1384
  private getTile;
1370
1385
  private tryAddEdge;
1371
- draw(ctx: CanvasRenderingContext2D): void;
1386
+ /**
1387
+ * The `soft` grid's color for the line between two squares: light gray between plain squares
1388
+ * (clear, floor level, no starting zone), a tone of the terrain's own color between two squares
1389
+ * of the same kind, and the dark grid between different kinds or on the map's edge.
1390
+ */
1391
+ private softGridColor;
1392
+ draw(ctx: CanvasRenderingContext2D, { grid }?: MapDrawOptions): void;
1372
1393
  private drawWall;
1373
1394
  }
1374
1395
  export declare function mapSquare(map: HCMapJson, x: number, y: number): {
@@ -1584,6 +1605,8 @@ export interface MapBoardViewProps extends Omit<HTMLAttributes<HTMLDivElement>,
1584
1605
  onLeave?(): void;
1585
1606
  /** Drawing failed (a JSON outside the expected format). */
1586
1607
  onDrawError?(): void;
1608
+ /** The grid between squares: `dark` (default) or `soft` (light between plain squares). */
1609
+ grid?: MapDrawOptions['grid'];
1587
1610
  }
1588
1611
  /**
1589
1612
  * The map's 2D board: the hcmaps drawing in a canvas and, over it, the inspection's
package/dist/index.js CHANGED
@@ -2468,6 +2468,16 @@ var Tile = class {
2468
2468
  ctx.restore();
2469
2469
  }
2470
2470
  };
2471
+ var MAP_GRID_COLOR = "#222222";
2472
+ var MAP_GRID_SOFT_COLOR = "#D4D2CC";
2473
+ var MAP_GRID_TERRAIN_SHADE = 0.22;
2474
+ function shadeHex(color, amount) {
2475
+ const m = /^#([0-9a-f]{6})$/i.exec(color);
2476
+ if (!m) return null;
2477
+ const n = parseInt(m[1], 16);
2478
+ const ch = (shift) => Math.round((n >> shift & 255) * (1 - amount)).toString(16).padStart(2, "0");
2479
+ return `#${ch(16)}${ch(8)}${ch(0)}`;
2480
+ }
2471
2481
  var HCMap = class {
2472
2482
  constructor(json) {
2473
2483
  __publicField(this, "width");
@@ -2537,7 +2547,19 @@ var HCMap = class {
2537
2547
  t0.addEdge(edgeType, MAP_TERRAIN_EDGE_COLORS[t0.terrain] ?? "#FFFFFF", dashed);
2538
2548
  }
2539
2549
  }
2540
- draw(ctx) {
2550
+ /**
2551
+ * The `soft` grid's color for the line between two squares: light gray between plain squares
2552
+ * (clear, floor level, no starting zone), a tone of the terrain's own color between two squares
2553
+ * of the same kind, and the dark grid between different kinds or on the map's edge.
2554
+ */
2555
+ softGridColor(a, b) {
2556
+ if (!a || !b) return MAP_GRID_COLOR;
2557
+ const same = a.terrain === b.terrain && a.type === b.type && String(a.elevation) === String(b.elevation) && !!a.isStartingZone === !!b.isStartingZone && !!a.isStartingZone4p === !!b.isStartingZone4p && a.fillStyle === b.fillStyle;
2558
+ if (!same) return MAP_GRID_COLOR;
2559
+ if (a.terrain === "clear" && Number(a.elevation) === 1 && !a.isStartingZone && !a.isStartingZone4p) return MAP_GRID_SOFT_COLOR;
2560
+ return shadeHex(a.fillStyle, MAP_GRID_TERRAIN_SHADE) ?? MAP_GRID_COLOR;
2561
+ }
2562
+ draw(ctx, { grid = "dark" } = {}) {
2541
2563
  ctx.save();
2542
2564
  for (const tile of this.tiles) tile.draw(ctx);
2543
2565
  ctx.restore();
@@ -2545,11 +2567,29 @@ var HCMap = class {
2545
2567
  for (const tile of this.tiles) tile.drawEdges(ctx);
2546
2568
  ctx.restore();
2547
2569
  ctx.save();
2548
- ctx.strokeStyle = "#222222";
2570
+ ctx.strokeStyle = MAP_GRID_COLOR;
2549
2571
  ctx.lineWidth = 1;
2550
- for (let y = 0; y < this.height; y++) {
2551
- for (let x = 0; x < this.width; x++) {
2552
- ctx.strokeRect(x * MAP_TILE_SIZE, y * MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE);
2572
+ if (grid === "dark") {
2573
+ for (let y = 0; y < this.height; y++) {
2574
+ for (let x = 0; x < this.width; x++) {
2575
+ ctx.strokeRect(x * MAP_TILE_SIZE, y * MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE);
2576
+ }
2577
+ }
2578
+ } else {
2579
+ const lines = [];
2580
+ for (let y = 0; y <= this.height; y++) {
2581
+ for (let x = 0; x < this.width; x++) lines.push({ x0: x, y0: y, x1: x + 1, y1: y, color: this.softGridColor(this.getTile(x, y - 1), this.getTile(x, y)) });
2582
+ }
2583
+ for (let x = 0; x <= this.width; x++) {
2584
+ for (let y = 0; y < this.height; y++) lines.push({ x0: x, y0: y, x1: x, y1: y + 1, color: this.softGridColor(this.getTile(x - 1, y), this.getTile(x, y)) });
2585
+ }
2586
+ lines.sort((a, b) => Number(a.color === MAP_GRID_COLOR) - Number(b.color === MAP_GRID_COLOR));
2587
+ for (const l of lines) {
2588
+ ctx.strokeStyle = l.color;
2589
+ ctx.beginPath();
2590
+ ctx.moveTo(l.x0 * MAP_TILE_SIZE, l.y0 * MAP_TILE_SIZE);
2591
+ ctx.lineTo(l.x1 * MAP_TILE_SIZE, l.y1 * MAP_TILE_SIZE);
2592
+ ctx.stroke();
2553
2593
  }
2554
2594
  }
2555
2595
  ctx.restore();
@@ -3140,7 +3180,7 @@ function renderMapThumbnail(json, height = MAP_THUMBNAIL_HEIGHT) {
3140
3180
  tctx.drawImage(full, 0, 0, thumb.width, thumb.height);
3141
3181
  return thumb.toDataURL("image/png");
3142
3182
  }
3143
- var MapBoardView = forwardRef(function MapBoardView2({ map, canvasLabel, selection, onInspect, onLeave, onDrawError, className, style, ...rest }, ref) {
3183
+ var MapBoardView = forwardRef(function MapBoardView2({ map, canvasLabel, selection, onInspect, onLeave, onDrawError, grid = "dark", className, style, ...rest }, ref) {
3144
3184
  const canvasRef = useRef(null);
3145
3185
  const failed = useRef(onDrawError);
3146
3186
  failed.current = onDrawError;
@@ -3151,11 +3191,11 @@ var MapBoardView = forwardRef(function MapBoardView2({ map, canvasLabel, selecti
3151
3191
  if (!ctx) return;
3152
3192
  try {
3153
3193
  ctx.clearRect(0, 0, canvas.width, canvas.height);
3154
- new HCMap(map).draw(ctx);
3194
+ new HCMap(map).draw(ctx, { grid });
3155
3195
  } catch {
3156
3196
  failed.current?.();
3157
3197
  }
3158
- }, [map]);
3198
+ }, [map, grid]);
3159
3199
  function pointer(event) {
3160
3200
  const bounds = event.currentTarget.getBoundingClientRect();
3161
3201
  onInspect?.((event.clientX - bounds.left) / bounds.width * map.width, (event.clientY - bounds.top) / bounds.height * map.height, event.clientX, event.clientY);
@@ -3261,6 +3301,9 @@ export {
3261
3301
  MAP_DEFAULT_CAMERA,
3262
3302
  MAP_ELEVATION_EDGE_COLOR,
3263
3303
  MAP_ELEVATION_TILE_COLORS,
3304
+ MAP_GRID_COLOR,
3305
+ MAP_GRID_SOFT_COLOR,
3306
+ MAP_GRID_TERRAIN_SHADE,
3264
3307
  MAP_INDOOR_EDGE_COLOR,
3265
3308
  MAP_SCENE_BASE_Z,
3266
3309
  MAP_SCENE_LEVEL_HEIGHT,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ntmats/hc-ui",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "type": "module",
5
5
  "description": "Shared HCUI/Arena React presentation primitives.",
6
6
  "license": "UNLICENSED",