@ntmats/hc-ui 0.4.0 → 0.5.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
@@ -103,7 +103,7 @@ function SegmentedControl({
103
103
  );
104
104
  }
105
105
  var classes = (...names) => names.filter(Boolean).join(" ");
106
- var Button = forwardRef(function Button2({ variant = "secondary", size = "md", icon, iconEnd, fullWidth = false, loading = false, type = "button", className, children, onClick, ...props }, ref) {
106
+ var Button = forwardRef(function Button2({ variant = "secondary", size = "md", icon, iconEnd, fullWidth = false, loading = false, wrap = false, type = "button", className, children, onClick, ...props }, ref) {
107
107
  const handleClick = (event) => {
108
108
  if (loading) event.preventDefault();
109
109
  else onClick?.(event);
@@ -121,6 +121,7 @@ var Button = forwardRef(function Button2({ variant = "secondary", size = "md", i
121
121
  "data-variant": variant,
122
122
  "data-size": size,
123
123
  "data-full-width": fullWidth || void 0,
124
+ "data-wrap": wrap || void 0,
124
125
  children: [
125
126
  loading ? /* @__PURE__ */ jsx("span", { className: "hc-ui-button__spinner", "aria-hidden": "true" }) : icon && /* @__PURE__ */ jsx("span", { className: "hc-ui-button__icon", "aria-hidden": "true", children: icon }),
126
127
  /* @__PURE__ */ jsx("span", { className: "hc-ui-button__label", children }),
@@ -647,10 +648,9 @@ function useRovingRadios(options, value) {
647
648
  });
648
649
  return item;
649
650
  }
650
- function SheetOptions({ label, options, value, onChange, variant = "card", className, ...props }) {
651
+ function SheetOptions({ label, options, value, onChange, className, ...props }) {
651
652
  const item = useRovingRadios(options, value);
652
- const list = variant === "list";
653
- return /* @__PURE__ */ jsx("div", { ...props, className: classes("hc-ui-sheet-options", className), role: "radiogroup", "aria-label": label, "data-variant": list ? "list" : void 0, children: options.map((option, index) => {
653
+ return /* @__PURE__ */ jsx("div", { ...props, className: classes("hc-ui-sheet-options", className), role: "radiogroup", "aria-label": label, children: options.map((option, index) => {
654
654
  const on = option.value === value;
655
655
  return /* @__PURE__ */ jsxs(
656
656
  "button",
@@ -669,7 +669,7 @@ function SheetOptions({ label, options, value, onChange, variant = "card", class
669
669
  /* @__PURE__ */ jsx("span", { className: "hc-ui-sheet-options__label", children: option.label }),
670
670
  option.hint && /* @__PURE__ */ jsx("span", { className: "hc-ui-sheet-options__hint", children: option.hint })
671
671
  ] }),
672
- /* @__PURE__ */ jsx("span", { className: "hc-ui-sheet-options__check", "aria-hidden": "true", children: on && /* @__PURE__ */ jsx("svg", { width: list ? 20 : 18, height: list ? 20 : 18, viewBox: "0 0 24 24", fill: "none", strokeWidth: list ? 1.8 : 2.4, "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx("path", { d: "M5 13L9 17L19 7", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
672
+ /* @__PURE__ */ jsx("span", { className: "hc-ui-sheet-options__check", "aria-hidden": "true", children: on && /* @__PURE__ */ jsx("svg", { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", strokeWidth: 2.4, "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx("path", { d: "M5 13L9 17L19 7", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
673
673
  ]
674
674
  },
675
675
  option.value
@@ -1555,6 +1555,7 @@ var CombatDialView = forwardRef(function CombatDialView2({
1555
1555
  currentClick,
1556
1556
  labels,
1557
1557
  presentation = "default",
1558
+ density = "comfortable",
1558
1559
  onClickChange,
1559
1560
  onSelectPoint,
1560
1561
  tip,
@@ -1658,7 +1659,7 @@ var CombatDialView = forwardRef(function CombatDialView2({
1658
1659
  COMBAT_DIAL_STATS.map((stat) => /* @__PURE__ */ jsx("div", { className: "hc-ui-combat-dial__cell", "data-kind": "ko", children: labels.koCell }, stat))
1659
1660
  ] })
1660
1661
  ] }, rowIndex);
1661
- return /* @__PURE__ */ jsxs("section", { ref, className: "hc-ui-combat-dial", "data-presentation": presentation, "data-static": flag(!tracksClick), children: [
1662
+ return /* @__PURE__ */ jsxs("section", { ref, className: "hc-ui-combat-dial", "data-presentation": presentation, "data-density": density === "compact" ? "compact" : void 0, "data-static": flag(!tracksClick), children: [
1662
1663
  presentation !== "printed" && /* @__PURE__ */ jsxs("header", { className: "hc-ui-combat-dial__header", children: [
1663
1664
  /* @__PURE__ */ jsxs("div", { className: "hc-ui-combat-dial__header-top", children: [
1664
1665
  /* @__PURE__ */ jsx("span", { className: "hc-ui-combat-dial__label", children: labels.heading }),
@@ -1693,11 +1694,11 @@ var CombatDialView = forwardRef(function CombatDialView2({
1693
1694
  tip && tipSlot
1694
1695
  ] });
1695
1696
  });
1696
- var CARD_WIDTH = 375;
1697
- var CARD_HEIGHT = 525;
1698
- var BACK_TABLE_HEIGHT = 440;
1699
- var BYSTANDER_DIAL_STEP = { x: 7, y: 24 };
1700
- function nextDistribution(pages, overflowing) {
1697
+ var PHYSICAL_CARD_WIDTH = 375;
1698
+ var PHYSICAL_CARD_HEIGHT = 525;
1699
+ var PHYSICAL_CARD_BACK_TABLE_HEIGHT = 440;
1700
+ var PHYSICAL_CARD_BYSTANDER_DIAL_STEP = { x: 7, y: 24 };
1701
+ function nextPhysicalCardDistribution(pages, overflowing) {
1701
1702
  const last = pages.length ? Math.max(...pages) : 0;
1702
1703
  for (let table = 0; table <= last; table += 1) {
1703
1704
  if (!overflowing(table)) continue;
@@ -1709,7 +1710,7 @@ function nextDistribution(pages, overflowing) {
1709
1710
  }
1710
1711
  return null;
1711
1712
  }
1712
- function backCount(pages) {
1713
+ function physicalCardBackCount(pages) {
1713
1714
  const last = pages.length ? Math.max(...pages) : 0;
1714
1715
  return Math.max(1, Math.ceil(last / 2));
1715
1716
  }
@@ -1721,7 +1722,7 @@ var CAN_DEVICE_TILT = "(hover: none) and (pointer: coarse) and (prefers-reduced-
1721
1722
  var DEVICE_RANGE_DEG = 18;
1722
1723
  var BASELINE_DRIFT = 0.01;
1723
1724
  var DEVICE_SMOOTHING = 0.2;
1724
- function tiltAt(x, y, damping = 1) {
1725
+ function physicalCardTiltAt(x, y, damping = 1) {
1725
1726
  const offsetX = (x - 0.5) * 2 * damping;
1726
1727
  const offsetY = (y - 0.5) * 2 * damping;
1727
1728
  return {
@@ -1736,7 +1737,7 @@ function tiltAt(x, y, damping = 1) {
1736
1737
  var PARALLAX_ART_PX = 4;
1737
1738
  var PARALLAX_HEADER_PX = 1.5;
1738
1739
  var CARD_ART_SELECTOR = ".hc-ui-physical-card__token, .hc-ui-physical-card__terrain-art, .hc-ui-physical-card__bystander-token";
1739
- function tiltStyles(tilt) {
1740
+ function physicalCardTiltStyles(tilt) {
1740
1741
  return {
1741
1742
  card: `perspective(1100px) rotateX(${tilt.rotateX}deg) rotateY(${tilt.rotateY}deg)`,
1742
1743
  art: `${tilt.parallaxX * PARALLAX_ART_PX}px ${tilt.parallaxY * PARALLAX_ART_PX}px`,
@@ -1748,7 +1749,7 @@ var eachIn = (root, selector, write) => {
1748
1749
  root.querySelectorAll(selector).forEach(write);
1749
1750
  };
1750
1751
  function applyTilt(root, tilt) {
1751
- const styles = tiltStyles(tilt);
1752
+ const styles = physicalCardTiltStyles(tilt);
1752
1753
  root.dataset.tilt = "";
1753
1754
  eachIn(root, ".hc-ui-physical-card-tilt", (element) => {
1754
1755
  element.style.transform = styles.card;
@@ -1772,7 +1773,7 @@ function clearTilt(root) {
1772
1773
  element.style.translate = "";
1773
1774
  });
1774
1775
  }
1775
- function devicePosition(beta, gamma, baseline, screenAngle = 0) {
1776
+ function physicalCardDevicePosition(beta, gamma, baseline, screenAngle = 0) {
1776
1777
  const clampAxis = (value) => Math.max(-1, Math.min(1, value / DEVICE_RANGE_DEG));
1777
1778
  const front = clampAxis(beta - baseline.beta);
1778
1779
  const side = clampAxis(gamma - baseline.gamma);
@@ -1780,7 +1781,7 @@ function devicePosition(beta, gamma, baseline, screenAngle = 0) {
1780
1781
  return { x: (horizontal + 1) / 2, y: (vertical + 1) / 2 };
1781
1782
  }
1782
1783
  var motionAsked = false;
1783
- function requestMotionAccess() {
1784
+ function requestPhysicalCardMotionAccess() {
1784
1785
  const request = typeof DeviceOrientationEvent === "undefined" ? void 0 : DeviceOrientationEvent.requestPermission;
1785
1786
  if (motionAsked || !request) return;
1786
1787
  motionAsked = true;
@@ -1801,10 +1802,10 @@ function useDeviceTilt(ref, enabled) {
1801
1802
  baseline ?? (baseline = { beta: event.beta, gamma: event.gamma });
1802
1803
  baseline.beta += (event.beta - baseline.beta) * BASELINE_DRIFT;
1803
1804
  baseline.gamma += (event.gamma - baseline.gamma) * BASELINE_DRIFT;
1804
- const target = devicePosition(event.beta, event.gamma, baseline, screen.orientation?.angle ?? 0);
1805
+ const target = physicalCardDevicePosition(event.beta, event.gamma, baseline, screen.orientation?.angle ?? 0);
1805
1806
  position = { x: position.x + (target.x - position.x) * DEVICE_SMOOTHING, y: position.y + (target.y - position.y) * DEVICE_SMOOTHING };
1806
1807
  cancelAnimationFrame(frame);
1807
- frame = requestAnimationFrame(() => applyTilt(element, tiltAt(position.x, position.y)));
1808
+ frame = requestAnimationFrame(() => applyTilt(element, physicalCardTiltAt(position.x, position.y)));
1808
1809
  };
1809
1810
  const onTouchStart = () => {
1810
1811
  touching = true;
@@ -1835,7 +1836,7 @@ function useCardTilt() {
1835
1836
  const slot = event.currentTarget;
1836
1837
  const rect = slot.getBoundingClientRect();
1837
1838
  const overDial = event.target.closest(CARD_DIAL_SELECTOR);
1838
- const tilt = tiltAt((event.clientX - rect.left) / rect.width, (event.clientY - rect.top) / rect.height, overDial ? DIAL_DAMPING : 1);
1839
+ const tilt = physicalCardTiltAt((event.clientX - rect.left) / rect.width, (event.clientY - rect.top) / rect.height, overDial ? DIAL_DAMPING : 1);
1839
1840
  cancelAnimationFrame(frame.current);
1840
1841
  frame.current = requestAnimationFrame(() => applyTilt(slot, tilt));
1841
1842
  };
@@ -1874,9 +1875,9 @@ function useCardScale(fitHeight, focus, scrollerSelector) {
1874
1875
  if (scroller) observer.observe(scroller);
1875
1876
  return () => observer.disconnect();
1876
1877
  }, [fitHeight, focus, scrollerSelector]);
1877
- const columns = !focus && width >= CARD_WIDTH * SIDE_BY_SIDE_MIN_SCALE * 2 + CARD_GAP ? 2 : 1;
1878
- const byWidth = width ? Math.min(MAX_CARD_SCALE, (width - CARD_GAP * (columns - 1)) / columns / CARD_WIDTH) : 1;
1879
- const scale = (fitHeight || focus) && height > 0 ? Math.max(0.6, Math.min(byWidth, height / CARD_HEIGHT)) : byWidth;
1878
+ const columns = !focus && width >= PHYSICAL_CARD_WIDTH * SIDE_BY_SIDE_MIN_SCALE * 2 + CARD_GAP ? 2 : 1;
1879
+ const byWidth = width ? Math.min(MAX_CARD_SCALE, (width - CARD_GAP * (columns - 1)) / columns / PHYSICAL_CARD_WIDTH) : 1;
1880
+ const scale = (fitHeight || focus) && height > 0 ? Math.max(0.6, Math.min(byWidth, height / PHYSICAL_CARD_HEIGHT)) : byWidth;
1880
1881
  return { ref, scale };
1881
1882
  }
1882
1883
  function useFitText(text, max, min) {
@@ -1951,9 +1952,9 @@ function PhysicalCardFocusView({ label, onClose, children }) {
1951
1952
  }, 0);
1952
1953
  window.addEventListener("pointerup", release, { once: true });
1953
1954
  window.addEventListener("pointercancel", release, { once: true });
1954
- window.addEventListener("touchend", requestMotionAccess);
1955
+ window.addEventListener("touchend", requestPhysicalCardMotionAccess);
1955
1956
  return () => {
1956
- window.removeEventListener("touchend", requestMotionAccess);
1957
+ window.removeEventListener("touchend", requestPhysicalCardMotionAccess);
1957
1958
  window.removeEventListener("pointerup", release);
1958
1959
  window.removeEventListener("pointercancel", release);
1959
1960
  dialog.close();
@@ -2035,7 +2036,7 @@ var PhysicalCardView = forwardRef(function PhysicalCardView2({
2035
2036
  const pages = distribution.key === contentKey && distribution.pages.length === rules.length ? distribution.pages : zeros();
2036
2037
  const tables = useRef([]);
2037
2038
  useLayoutEffect(() => {
2038
- const next = nextDistribution(pages, (table) => {
2039
+ const next = nextPhysicalCardDistribution(pages, (table) => {
2039
2040
  const element = tables.current[table];
2040
2041
  return !!element && element.scrollHeight > element.clientHeight + 1;
2041
2042
  });
@@ -2171,17 +2172,17 @@ var PhysicalCardView = forwardRef(function PhysicalCardView2({
2171
2172
  ] }),
2172
2173
  /* @__PURE__ */ jsx("div", { className: "hc-ui-physical-card__bystander-name", children: bystander.name }),
2173
2174
  bystander.dial && /* @__PURE__ */ jsx("div", { className: "hc-ui-physical-card__bystander-dial", role: "group", "aria-label": bystander.dial.label, children: bystander.dial.cells.map((cell, row) => {
2174
- const position = { left: row * BYSTANDER_DIAL_STEP.x, top: row * BYSTANDER_DIAL_STEP.y };
2175
+ const position = { left: row * PHYSICAL_CARD_BYSTANDER_DIAL_STEP.x, top: row * PHYSICAL_CARD_BYSTANDER_DIAL_STEP.y };
2175
2176
  const cellStyle = { ...position, backgroundColor: cell.background, color: cell.color };
2176
2177
  const cellProps = { className: "hc-ui-physical-card__bystander-value", "data-special": flag(cell.special), style: cellStyle, "aria-label": cell.label };
2177
2178
  if (!cell.tip) return /* @__PURE__ */ jsx("span", { ...cellProps, role: "img", children: cell.value }, cell.stat);
2178
2179
  return /* @__PURE__ */ jsx("button", { type: "button", ...cellProps, "data-tip": "", ...tipProps(cell.tip), children: cell.value }, cell.stat);
2179
2180
  }) })
2180
2181
  ] }) });
2181
- const backs = backCount(pages);
2182
+ const backs = physicalCardBackCount(pages);
2182
2183
  const shownSide = Math.min(side, backs);
2183
2184
  const nextSide = (shownSide + 1) % (backs + 1);
2184
- const style = { "--hc-card-scale": scale, "--hc-card-front-table-height": `${layout.frontTableHeight}px`, "--hc-card-back-table-height": `${BACK_TABLE_HEIGHT}px`, "--hc-card-width": `${CARD_WIDTH}px`, "--hc-card-height": `${CARD_HEIGHT}px` };
2185
+ const style = { "--hc-card-scale": scale, "--hc-card-front-table-height": `${layout.frontTableHeight}px`, "--hc-card-back-table-height": `${PHYSICAL_CARD_BACK_TABLE_HEIGHT}px`, "--hc-card-width": `${PHYSICAL_CARD_WIDTH}px`, "--hc-card-height": `${PHYSICAL_CARD_HEIGHT}px` };
2185
2186
  return /* @__PURE__ */ jsxs("div", { className: "hc-ui-physical-cards", "data-focus": flag(focus), ref: setWrapRef, style, ...longPress, children: [
2186
2187
  /* @__PURE__ */ jsxs(CardFrame, { side: "front", backgroundSrc: images.front, legacySrc: images.legacy, label: labels.front, away: focus && shownSide !== 0, children: [
2187
2188
  layout.teamUp && /* @__PURE__ */ jsx("span", { className: "hc-ui-physical-card__team-up", "aria-hidden": true }),
@@ -2238,8 +2239,8 @@ var PhysicalCardView = forwardRef(function PhysicalCardView2({
2238
2239
  tip && tipSlot
2239
2240
  ] });
2240
2241
  });
2241
- var TILE_SIZE = 64;
2242
- var EDGE_SIZE = TILE_SIZE / 16;
2242
+ var MAP_TILE_SIZE = 64;
2243
+ var EDGE_SIZE = MAP_TILE_SIZE / 16;
2243
2244
  var WALL_SIZE = EDGE_SIZE * 2;
2244
2245
  var MAX_EDGES = 4;
2245
2246
  var HINDERING_TILE_COLOR = "#B4ECB4";
@@ -2249,9 +2250,9 @@ var OBSCURING_TILE_COLOR = "#E8E8E8";
2249
2250
  var WINDOW_TILE_COLOR = "#dee8eb";
2250
2251
  var SPECIAL_TILE_COLOR = "#FFD394";
2251
2252
  var STARTING_ZONE_TILE_COLOR = "#fff8fa";
2252
- var ELEVATION_TILE_COLORS = ["#FFFFFF", "#FB7A7F", "#D0424C", "#B02020", "#902020", "#702020"];
2253
- var TERRAIN_TILE_COLORS = {
2254
- clear: ELEVATION_TILE_COLORS[0],
2253
+ var MAP_ELEVATION_TILE_COLORS = ["#FFFFFF", "#FB7A7F", "#D0424C", "#B02020", "#902020", "#702020"];
2254
+ var MAP_TERRAIN_TILE_COLORS = {
2255
+ clear: MAP_ELEVATION_TILE_COLORS[0],
2255
2256
  hindering: HINDERING_TILE_COLOR,
2256
2257
  blocking: BLOCKING_TILE_COLOR,
2257
2258
  water: WATER_TILE_COLOR,
@@ -2260,7 +2261,7 @@ var TERRAIN_TILE_COLORS = {
2260
2261
  special: SPECIAL_TILE_COLOR,
2261
2262
  special2: SPECIAL_TILE_COLOR
2262
2263
  };
2263
- var TERRAIN_EDGE_COLORS = {
2264
+ var MAP_TERRAIN_EDGE_COLORS = {
2264
2265
  clear: "#FFFFFF",
2265
2266
  hindering: "#3ACE3A",
2266
2267
  blocking: "#76491E",
@@ -2271,9 +2272,9 @@ var TERRAIN_EDGE_COLORS = {
2271
2272
  special2: "#FF7600"
2272
2273
  };
2273
2274
  var STARTING_ZONE_EDGE_COLOR = "#D560A9";
2274
- var ELEVATION_EDGE_COLOR = "#FF0000";
2275
- var INDOOR_EDGE_COLOR = "#FFFF00";
2276
- var WALL_COLORS = {
2275
+ var MAP_ELEVATION_EDGE_COLOR = "#FF0000";
2276
+ var MAP_INDOOR_EDGE_COLOR = "#FFFF00";
2277
+ var MAP_WALL_COLORS = {
2277
2278
  normal: "#000000",
2278
2279
  glass: "#E59400",
2279
2280
  glass2: "#33BBFF",
@@ -2316,8 +2317,8 @@ var Tile = class {
2316
2317
  else if (this.terrain === "window") this.fillStyle = WINDOW_TILE_COLOR;
2317
2318
  else if (this.terrain === "special" || this.terrain === "special2") this.fillStyle = SPECIAL_TILE_COLOR;
2318
2319
  else if (this.isStartingZone || this.isStartingZone4p) this.fillStyle = STARTING_ZONE_TILE_COLOR;
2319
- else if (typeof this.elevation === "string") this.fillStyle = ELEVATION_TILE_COLORS[1];
2320
- else this.fillStyle = ELEVATION_TILE_COLORS[this.elevation - 1] ?? ELEVATION_TILE_COLORS[0];
2320
+ else if (typeof this.elevation === "string") this.fillStyle = MAP_ELEVATION_TILE_COLORS[1];
2321
+ else this.fillStyle = MAP_ELEVATION_TILE_COLORS[this.elevation - 1] ?? MAP_ELEVATION_TILE_COLORS[0];
2321
2322
  }
2322
2323
  addEdge(edgeType, strokeStyle, dashed) {
2323
2324
  while (this.edges[edgeType]) edgeType += 4;
@@ -2332,7 +2333,7 @@ var Tile = class {
2332
2333
  }
2333
2334
  draw(ctx) {
2334
2335
  ctx.fillStyle = this.fillStyle;
2335
- ctx.fillRect(this.x * TILE_SIZE, this.y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
2336
+ ctx.fillRect(this.x * MAP_TILE_SIZE, this.y * MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE);
2336
2337
  }
2337
2338
  drawEdges(ctx) {
2338
2339
  const edgeLevels = [-1, -1, -1, -1];
@@ -2366,27 +2367,27 @@ var Tile = class {
2366
2367
  const oBottom = this.hasEdge(3 /* BOTTOM */ + level * 4) ? 0 : overhangSize;
2367
2368
  switch (edgeType) {
2368
2369
  case 0 /* LEFT */:
2369
- x0 = x1 = this.x * TILE_SIZE + EDGE_SIZE / 2 + EDGE_SIZE * level;
2370
- y0 = this.y * TILE_SIZE - oTop;
2371
- y1 = (this.y + 1) * TILE_SIZE + oBottom;
2370
+ x0 = x1 = this.x * MAP_TILE_SIZE + EDGE_SIZE / 2 + EDGE_SIZE * level;
2371
+ y0 = this.y * MAP_TILE_SIZE - oTop;
2372
+ y1 = (this.y + 1) * MAP_TILE_SIZE + oBottom;
2372
2373
  lineDashOffset = oTop;
2373
2374
  break;
2374
2375
  case 1 /* RIGHT */:
2375
- x0 = x1 = (this.x + 1) * TILE_SIZE - EDGE_SIZE / 2 - EDGE_SIZE * level;
2376
- y0 = this.y * TILE_SIZE - oTop;
2377
- y1 = (this.y + 1) * TILE_SIZE + oBottom;
2376
+ x0 = x1 = (this.x + 1) * MAP_TILE_SIZE - EDGE_SIZE / 2 - EDGE_SIZE * level;
2377
+ y0 = this.y * MAP_TILE_SIZE - oTop;
2378
+ y1 = (this.y + 1) * MAP_TILE_SIZE + oBottom;
2378
2379
  lineDashOffset = oTop;
2379
2380
  break;
2380
2381
  case 2 /* TOP */:
2381
- x0 = this.x * TILE_SIZE - oLeft;
2382
- y0 = y1 = this.y * TILE_SIZE + EDGE_SIZE / 2 + EDGE_SIZE * level;
2383
- x1 = (this.x + 1) * TILE_SIZE + oRight;
2382
+ x0 = this.x * MAP_TILE_SIZE - oLeft;
2383
+ y0 = y1 = this.y * MAP_TILE_SIZE + EDGE_SIZE / 2 + EDGE_SIZE * level;
2384
+ x1 = (this.x + 1) * MAP_TILE_SIZE + oRight;
2384
2385
  lineDashOffset = oLeft;
2385
2386
  break;
2386
2387
  case 3 /* BOTTOM */:
2387
- x0 = this.x * TILE_SIZE - oLeft;
2388
- y0 = y1 = (this.y + 1) * TILE_SIZE - EDGE_SIZE / 2 - EDGE_SIZE * level;
2389
- x1 = (this.x + 1) * TILE_SIZE + oRight;
2388
+ x0 = this.x * MAP_TILE_SIZE - oLeft;
2389
+ y0 = y1 = (this.y + 1) * MAP_TILE_SIZE - EDGE_SIZE / 2 - EDGE_SIZE * level;
2390
+ x1 = (this.x + 1) * MAP_TILE_SIZE + oRight;
2390
2391
  lineDashOffset = oLeft;
2391
2392
  break;
2392
2393
  }
@@ -2410,33 +2411,33 @@ var Tile = class {
2410
2411
  }
2411
2412
  drawRamp(ctx, angle) {
2412
2413
  ctx.save();
2413
- ctx.translate(this.x * TILE_SIZE + TILE_SIZE / 2, this.y * TILE_SIZE + TILE_SIZE / 2);
2414
+ ctx.translate(this.x * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, this.y * MAP_TILE_SIZE + MAP_TILE_SIZE / 2);
2414
2415
  ctx.rotate(angle);
2415
2416
  ctx.beginPath();
2416
2417
  ctx.moveTo(0, EDGE_SIZE);
2417
- ctx.lineTo(-(TILE_SIZE / 2 - EDGE_SIZE * 2), TILE_SIZE / 2 - EDGE_SIZE);
2418
- ctx.lineTo(TILE_SIZE / 2 - EDGE_SIZE * 2, TILE_SIZE / 2 - EDGE_SIZE);
2418
+ ctx.lineTo(-(MAP_TILE_SIZE / 2 - EDGE_SIZE * 2), MAP_TILE_SIZE / 2 - EDGE_SIZE);
2419
+ ctx.lineTo(MAP_TILE_SIZE / 2 - EDGE_SIZE * 2, MAP_TILE_SIZE / 2 - EDGE_SIZE);
2419
2420
  ctx.closePath();
2420
2421
  ctx.lineWidth = EDGE_SIZE * 2;
2421
- ctx.strokeStyle = ELEVATION_EDGE_COLOR;
2422
+ ctx.strokeStyle = MAP_ELEVATION_EDGE_COLOR;
2422
2423
  ctx.stroke();
2423
- ctx.fillStyle = ELEVATION_TILE_COLORS[1];
2424
+ ctx.fillStyle = MAP_ELEVATION_TILE_COLORS[1];
2424
2425
  ctx.fill();
2425
2426
  ctx.font = "18px Arial";
2426
2427
  ctx.fillStyle = "#000000";
2427
2428
  ctx.textAlign = "center";
2428
2429
  ctx.textBaseline = "middle";
2429
- ctx.fillText(String(this.elevation), 0, TILE_SIZE / 4 + 4);
2430
+ ctx.fillText(String(this.elevation), 0, MAP_TILE_SIZE / 4 + 4);
2430
2431
  ctx.restore();
2431
2432
  }
2432
2433
  drawLabel(ctx) {
2433
2434
  if (this.hideLabel || this.x !== 0 && this.y !== 0 && !this.label) return;
2434
2435
  let text = "";
2435
2436
  ctx.save();
2436
- ctx.translate(this.x * TILE_SIZE + TILE_SIZE / 2, this.y * TILE_SIZE + TILE_SIZE / 2);
2437
+ ctx.translate(this.x * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, this.y * MAP_TILE_SIZE + MAP_TILE_SIZE / 2);
2437
2438
  if (this.label) {
2438
2439
  text = this.label.text;
2439
- ctx.fillStyle = this.label.color ?? ELEVATION_EDGE_COLOR;
2440
+ ctx.fillStyle = this.label.color ?? MAP_ELEVATION_EDGE_COLOR;
2440
2441
  ctx.rotate((this.label.rotate ?? 0) * Math.PI / 180);
2441
2442
  } else {
2442
2443
  if (this.y === 0) text = String.fromCharCode("A".charCodeAt(0) + this.x);
@@ -2503,10 +2504,10 @@ var HCMap = class {
2503
2504
  }
2504
2505
  tryAddEdge(t0, t1, edgeType) {
2505
2506
  if (this.type === "indoorOutdoor" && t0.type === "indoor" && (t1 == null || t1.type === "outdoor")) {
2506
- t0.addEdge(edgeType, INDOOR_EDGE_COLOR, false);
2507
+ t0.addEdge(edgeType, MAP_INDOOR_EDGE_COLOR, false);
2507
2508
  }
2508
2509
  if (typeof t0.elevation === "number" && t0.elevation > 1 && (t1 == null || t0.elevation !== t1.elevation)) {
2509
- t0.addEdge(edgeType, ELEVATION_EDGE_COLOR, false);
2510
+ t0.addEdge(edgeType, MAP_ELEVATION_EDGE_COLOR, false);
2510
2511
  }
2511
2512
  if (t0.isStartingZone && (t1 == null || !t1.isStartingZone)) {
2512
2513
  t0.addEdge(edgeType, STARTING_ZONE_EDGE_COLOR, false);
@@ -2516,7 +2517,7 @@ var HCMap = class {
2516
2517
  }
2517
2518
  if (t0.terrain !== "clear" && (t1 == null || t0.terrain !== t1.terrain || t0.type !== t1.type || t0.elevation !== t1.elevation || t0.isStartingZone !== t1.isStartingZone || t0.isStartingZone4p !== t1.isStartingZone4p || t0.group !== t1.group)) {
2518
2519
  const dashed = t0.terrain === "window" || t0.terrain === "special2";
2519
- t0.addEdge(edgeType, TERRAIN_EDGE_COLORS[t0.terrain] ?? "#FFFFFF", dashed);
2520
+ t0.addEdge(edgeType, MAP_TERRAIN_EDGE_COLORS[t0.terrain] ?? "#FFFFFF", dashed);
2520
2521
  }
2521
2522
  }
2522
2523
  draw(ctx) {
@@ -2531,7 +2532,7 @@ var HCMap = class {
2531
2532
  ctx.lineWidth = 1;
2532
2533
  for (let y = 0; y < this.height; y++) {
2533
2534
  for (let x = 0; x < this.width; x++) {
2534
- ctx.strokeRect(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
2535
+ ctx.strokeRect(x * MAP_TILE_SIZE, y * MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE);
2535
2536
  }
2536
2537
  }
2537
2538
  ctx.restore();
@@ -2542,12 +2543,12 @@ var HCMap = class {
2542
2543
  }
2543
2544
  for (const z of this.ziplines) {
2544
2545
  ctx.save();
2545
- ctx.strokeStyle = WALL_COLORS.normal;
2546
+ ctx.strokeStyle = MAP_WALL_COLORS.normal;
2546
2547
  ctx.lineCap = "round";
2547
2548
  ctx.lineWidth = 4;
2548
2549
  ctx.beginPath();
2549
- ctx.moveTo(z.x0 * TILE_SIZE + TILE_SIZE / 2, z.y0 * TILE_SIZE + TILE_SIZE / 2);
2550
- ctx.lineTo(z.x1 * TILE_SIZE + TILE_SIZE / 2, z.y1 * TILE_SIZE + TILE_SIZE / 2);
2550
+ ctx.moveTo(z.x0 * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, z.y0 * MAP_TILE_SIZE + MAP_TILE_SIZE / 2);
2551
+ ctx.lineTo(z.x1 * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, z.y1 * MAP_TILE_SIZE + MAP_TILE_SIZE / 2);
2551
2552
  ctx.stroke();
2552
2553
  ctx.restore();
2553
2554
  }
@@ -2556,15 +2557,15 @@ var HCMap = class {
2556
2557
  const type = wall.type ?? "normal";
2557
2558
  ctx.lineWidth = WALL_SIZE;
2558
2559
  if (type === "levelSeparator") {
2559
- ctx.strokeStyle = WALL_COLORS.normal;
2560
+ ctx.strokeStyle = MAP_WALL_COLORS.normal;
2560
2561
  ctx.lineWidth = WALL_SIZE * 2;
2561
2562
  ctx.beginPath();
2562
- ctx.moveTo(wall.x0 * TILE_SIZE, wall.y0 * TILE_SIZE);
2563
- ctx.lineTo(wall.x1 * TILE_SIZE, wall.y1 * TILE_SIZE);
2563
+ ctx.moveTo(wall.x0 * MAP_TILE_SIZE, wall.y0 * MAP_TILE_SIZE);
2564
+ ctx.lineTo(wall.x1 * MAP_TILE_SIZE, wall.y1 * MAP_TILE_SIZE);
2564
2565
  ctx.stroke();
2565
2566
  ctx.lineWidth = WALL_SIZE;
2566
2567
  }
2567
- ctx.strokeStyle = WALL_COLORS[type] ?? WALL_COLORS.normal;
2568
+ ctx.strokeStyle = MAP_WALL_COLORS[type] ?? MAP_WALL_COLORS.normal;
2568
2569
  if (DASHED_WALLS.has(type)) {
2569
2570
  ctx.setLineDash([WALL_SIZE, WALL_SIZE]);
2570
2571
  ctx.lineDashOffset = WALL_SIZE / 2;
@@ -2572,8 +2573,8 @@ var HCMap = class {
2572
2573
  ctx.lineCap = "round";
2573
2574
  }
2574
2575
  ctx.beginPath();
2575
- ctx.moveTo(wall.x0 * TILE_SIZE, wall.y0 * TILE_SIZE);
2576
- ctx.lineTo(wall.x1 * TILE_SIZE, wall.y1 * TILE_SIZE);
2576
+ ctx.moveTo(wall.x0 * MAP_TILE_SIZE, wall.y0 * MAP_TILE_SIZE);
2577
+ ctx.lineTo(wall.x1 * MAP_TILE_SIZE, wall.y1 * MAP_TILE_SIZE);
2577
2578
  ctx.stroke();
2578
2579
  }
2579
2580
  };
@@ -2590,14 +2591,14 @@ function mapSquare(map, x, y) {
2590
2591
  label: tile.label?.text
2591
2592
  };
2592
2593
  }
2593
- function elevationLevel(elevation) {
2594
+ function mapElevationLevel(elevation) {
2594
2595
  const value = typeof elevation === "number" ? elevation : Number.parseInt(elevation, 10);
2595
2596
  return Number.isFinite(value) ? Math.max(1, value) : 2;
2596
2597
  }
2597
2598
  function mapMaxLevel(map) {
2598
2599
  let level = 1;
2599
2600
  for (let y = 0; y < map.height; y++) {
2600
- for (let x = 0; x < map.width; x++) level = Math.max(level, elevationLevel(mapSquare(map, x, y).elevation));
2601
+ for (let x = 0; x < map.width; x++) level = Math.max(level, mapElevationLevel(mapSquare(map, x, y).elevation));
2601
2602
  }
2602
2603
  return level;
2603
2604
  }
@@ -2628,7 +2629,7 @@ function inspectMap(map, x, y, tolerance = 0.16) {
2628
2629
  }
2629
2630
  return { square };
2630
2631
  }
2631
- function squareCoordinate(square) {
2632
+ function mapSquareCoordinate(square) {
2632
2633
  let index = square.x + 1, column = "";
2633
2634
  while (index > 0) {
2634
2635
  index--;
@@ -2637,13 +2638,13 @@ function squareCoordinate(square) {
2637
2638
  }
2638
2639
  return `${column}${square.y + 1}`;
2639
2640
  }
2640
- var LEVEL_HEIGHT = 0.62;
2641
- var BASE_Z = -0.34;
2641
+ var MAP_SCENE_LEVEL_HEIGHT = 0.62;
2642
+ var MAP_SCENE_BASE_Z = -0.34;
2642
2643
  var WATER_DROP = 0.1;
2643
2644
  var TERRAIN_VOLUME = { obscuring: 0.42, window: 0.42 };
2644
2645
  var WALL_HEIGHT = { levelSeparator: 0.12, door: 0.62, door2: 0.62 };
2645
2646
  var DEFAULT_WALL_HEIGHT = 0.62;
2646
- function sceneCell(scene, x, y) {
2647
+ function mapSceneCell(scene, x, y) {
2647
2648
  if (x < 0 || y < 0 || x >= scene.width || y >= scene.height) return null;
2648
2649
  return scene.cells[y * scene.width + x];
2649
2650
  }
@@ -2654,9 +2655,9 @@ function buildMapScene(map) {
2654
2655
  for (let y = 0; y < height; y++) {
2655
2656
  for (let x = 0; x < width; x++) {
2656
2657
  const square = mapSquare(map, x, y);
2657
- const level = elevationLevel(square.elevation);
2658
- const floor = (level - 1) * LEVEL_HEIGHT - (square.terrain === "water" ? WATER_DROP : 0);
2659
- const top = square.terrain !== "blocking" ? floor + (TERRAIN_VOLUME[square.terrain] ?? 0) : square.environment === "indoor" ? maxLevel * LEVEL_HEIGHT : floor + LEVEL_HEIGHT;
2658
+ const level = mapElevationLevel(square.elevation);
2659
+ const floor = (level - 1) * MAP_SCENE_LEVEL_HEIGHT - (square.terrain === "water" ? WATER_DROP : 0);
2660
+ const top = square.terrain !== "blocking" ? floor + (TERRAIN_VOLUME[square.terrain] ?? 0) : square.environment === "indoor" ? maxLevel * MAP_SCENE_LEVEL_HEIGHT : floor + MAP_SCENE_LEVEL_HEIGHT;
2660
2661
  cells.push({ ...square, level, floor, top });
2661
2662
  }
2662
2663
  }
@@ -2671,7 +2672,7 @@ function buildMapScene(map) {
2671
2672
  const x1 = wall.x0 + (wall.x1 - wall.x0) * (i + 1) / pieces, y1 = wall.y0 + (wall.y1 - wall.y0) * (i + 1) / pieces;
2672
2673
  const mx = (x0 + x1) / 2, my = (y0 + y1) / 2;
2673
2674
  const nx = length ? (y1 - y0) / (length / pieces) : 0, ny = length ? (x0 - x1) / (length / pieces) : 0;
2674
- const sides = [[mx + nx * 0.25, my + ny * 0.25], [mx - nx * 0.25, my - ny * 0.25]].map(([px, py]) => sceneCell(scene, Math.floor(px), Math.floor(py))).filter((cell) => !!cell);
2675
+ const sides = [[mx + nx * 0.25, my + ny * 0.25], [mx - nx * 0.25, my - ny * 0.25]].map(([px, py]) => mapSceneCell(scene, Math.floor(px), Math.floor(py))).filter((cell) => !!cell);
2675
2676
  const floors = sides.length ? sides.map((cell) => cell.floor) : [0];
2676
2677
  const z1 = Math.max(...floors) + (WALL_HEIGHT[type] ?? DEFAULT_WALL_HEIGHT);
2677
2678
  walls.push({ x0, y0, x1, y1, type, z0: Math.min(...floors), z1 });
@@ -2679,7 +2680,7 @@ function buildMapScene(map) {
2679
2680
  }
2680
2681
  const ramps = [];
2681
2682
  for (const ramp of map.ramps ?? []) {
2682
- const a = sceneCell(scene, ramp.x0, ramp.y0), b = sceneCell(scene, ramp.x1, ramp.y1);
2683
+ const a = mapSceneCell(scene, ramp.x0, ramp.y0), b = mapSceneCell(scene, ramp.x1, ramp.y1);
2683
2684
  if (!a || !b || Math.abs(a.x - b.x) + Math.abs(a.y - b.y) !== 1 || a.floor === b.floor) continue;
2684
2685
  const [low, high] = a.floor < b.floor ? [a, b] : [b, a];
2685
2686
  ramps.push({ x: low.x, y: low.y, dx: high.x - low.x, dy: high.y - low.y, from: low.floor, to: high.floor });
@@ -2689,21 +2690,21 @@ function buildMapScene(map) {
2689
2690
  y0: line.y0 + 0.5,
2690
2691
  x1: line.x1 + 0.5,
2691
2692
  y1: line.y1 + 0.5,
2692
- z: Math.max(sceneCell(scene, line.x0, line.y0)?.top ?? 0, sceneCell(scene, line.x1, line.y1)?.top ?? 0) + 0.7
2693
+ z: Math.max(mapSceneCell(scene, line.x0, line.y0)?.top ?? 0, mapSceneCell(scene, line.x1, line.y1)?.top ?? 0) + 0.7
2693
2694
  }));
2694
2695
  const maxTop = Math.max(...cells.map((cell) => cell.top), ...walls.map((wall) => wall.z1), ...ziplines.map((line) => line.z));
2695
2696
  return { width, height, cells, walls, ramps, ziplines, maxTop };
2696
2697
  }
2697
- var DEFAULT_CAMERA = { azimuth: -32, tilt: 52, zoom: 1, panX: 0, panY: 0 };
2698
- var TILT_RANGE = [6, 90];
2699
- var ZOOM_RANGE = [1, 6];
2700
- var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
2701
- function makeProjection(scene, camera, viewport) {
2698
+ var MAP_DEFAULT_CAMERA = { azimuth: -32, tilt: 52, zoom: 1, panX: 0, panY: 0 };
2699
+ var MAP_TILT_RANGE = [6, 90];
2700
+ var MAP_ZOOM_RANGE = [1, 6];
2701
+ var clampMapValue = (value, min, max) => Math.min(max, Math.max(min, value));
2702
+ function makeMapProjection(scene, camera, viewport) {
2702
2703
  const rad = camera.azimuth * Math.PI / 180, tilt = camera.tilt * Math.PI / 180;
2703
2704
  const sin = Math.sin(rad), cos = Math.cos(rad), sinT = Math.sin(tilt), cosT = Math.cos(tilt);
2704
- const cx2 = scene.width / 2, cy = scene.height / 2, midZ = (scene.maxTop + BASE_Z) / 2;
2705
+ const cx2 = scene.width / 2, cy = scene.height / 2, midZ = (scene.maxTop + MAP_SCENE_BASE_Z) / 2;
2705
2706
  const halfWidth = Math.hypot(cx2, cy);
2706
- const halfHeight = Math.hypot(halfWidth, (scene.maxTop - BASE_Z) / 2);
2707
+ const halfHeight = Math.hypot(halfWidth, (scene.maxTop - MAP_SCENE_BASE_Z) / 2);
2707
2708
  const fit = Math.min(viewport.width / (halfWidth * 2.06), viewport.height / (halfHeight * 2.06));
2708
2709
  const scale = fit * camera.zoom;
2709
2710
  const ox = viewport.width / 2 + camera.panX, oy = viewport.height / 2 + camera.panY;
@@ -2724,21 +2725,21 @@ function makeProjection(scene, camera, viewport) {
2724
2725
  }
2725
2726
  };
2726
2727
  }
2727
- function clampPan(scene, camera, viewport) {
2728
- const limit = Math.hypot(scene.width, scene.height) / 2 * makeProjection(scene, camera, viewport).scale;
2729
- return { ...camera, panX: clamp(camera.panX, -limit, limit), panY: clamp(camera.panY, -limit, limit) };
2728
+ function clampMapPan(scene, camera, viewport) {
2729
+ const limit = Math.hypot(scene.width, scene.height) / 2 * makeMapProjection(scene, camera, viewport).scale;
2730
+ return { ...camera, panX: clampMapValue(camera.panX, -limit, limit), panY: clampMapValue(camera.panY, -limit, limit) };
2730
2731
  }
2731
- function zoomCamera(scene, camera, viewport, factor, anchor = { x: 0, y: 0 }) {
2732
- const zoom = clamp(camera.zoom * factor, ZOOM_RANGE[0], ZOOM_RANGE[1]);
2732
+ function zoomMapCamera(scene, camera, viewport, factor, anchor = { x: 0, y: 0 }) {
2733
+ const zoom = clampMapValue(camera.zoom * factor, MAP_ZOOM_RANGE[0], MAP_ZOOM_RANGE[1]);
2733
2734
  const applied = zoom / camera.zoom;
2734
- return clampPan(scene, {
2735
+ return clampMapPan(scene, {
2735
2736
  ...camera,
2736
2737
  zoom,
2737
2738
  panX: anchor.x + (camera.panX - anchor.x) * applied,
2738
2739
  panY: anchor.y + (camera.panY - anchor.y) * applied
2739
2740
  }, viewport);
2740
2741
  }
2741
- var CELL_SIDES = [
2742
+ var MAP_CELL_SIDES = [
2742
2743
  { ax: 0, ay: 1, bx: 0, by: 0, dx: -1, dy: 0 },
2743
2744
  { ax: 1, ay: 0, bx: 1, by: 1, dx: 1, dy: 0 },
2744
2745
  { ax: 0, ay: 0, bx: 1, by: 0, dx: 0, dy: -1 },
@@ -2752,7 +2753,7 @@ var inside = (px, py, polygon2) => {
2752
2753
  }
2753
2754
  return hit;
2754
2755
  };
2755
- function pickScene(scene, view, px, py) {
2756
+ function pickMapScene(scene, view, px, py) {
2756
2757
  const items = [];
2757
2758
  for (const wall of scene.walls) {
2758
2759
  items.push({
@@ -2762,7 +2763,7 @@ function pickScene(scene, view, px, py) {
2762
2763
  const c = view.point(wall.x1, wall.y1, wall.z1), d = view.point(wall.x0, wall.y0, wall.z1);
2763
2764
  if (!inside(px, py, [a, b, c, d])) return null;
2764
2765
  const length2 = (b[0] - a[0]) ** 2 + (b[1] - a[1]) ** 2;
2765
- const t = length2 ? clamp(((px - a[0]) * (b[0] - a[0]) + (py - a[1]) * (b[1] - a[1])) / length2, 0, 1) : 0.5;
2766
+ const t = length2 ? clampMapValue(((px - a[0]) * (b[0] - a[0]) + (py - a[1]) * (b[1] - a[1])) / length2, 0, 1) : 0.5;
2766
2767
  return { x: wall.x0 + (wall.x1 - wall.x0) * t, y: wall.y0 + (wall.y1 - wall.y0) * t };
2767
2768
  }
2768
2769
  });
@@ -2778,12 +2779,12 @@ function pickScene(scene, view, px, py) {
2778
2779
  const det = ax * by - ay * bx;
2779
2780
  if (!det) return { x: cell.x + 0.5, y: cell.y + 0.5 };
2780
2781
  const u = ((px - p00[0]) * by - (py - p00[1]) * bx) / det, v = ((py - p00[1]) * ax - (px - p00[0]) * ay) / det;
2781
- return { x: cell.x + clamp(u, 0, 1), y: cell.y + clamp(v, 0, 1) };
2782
+ return { x: cell.x + clampMapValue(u, 0, 1), y: cell.y + clampMapValue(v, 0, 1) };
2782
2783
  }
2783
- for (const side of CELL_SIDES) {
2784
+ for (const side of MAP_CELL_SIDES) {
2784
2785
  if (side.dx * view.sin + side.dy * view.cos <= 0) continue;
2785
- const neighbor = sceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2786
- const low = neighbor ? neighbor.top : BASE_Z;
2786
+ const neighbor = mapSceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2787
+ const low = neighbor ? neighbor.top : MAP_SCENE_BASE_Z;
2787
2788
  if (low >= cell.top) continue;
2788
2789
  const a = view.point(cell.x + side.ax, cell.y + side.ay, low), b = view.point(cell.x + side.bx, cell.y + side.by, low);
2789
2790
  const c = view.point(cell.x + side.bx, cell.y + side.by, cell.top), d = view.point(cell.x + side.ax, cell.y + side.ay, cell.top);
@@ -2802,7 +2803,7 @@ function pickScene(scene, view, px, py) {
2802
2803
  }
2803
2804
  return null;
2804
2805
  }
2805
- function footprintOutline({ x, y, width, height, cells }, boardWidth, boardHeight) {
2806
+ function mapFootprintOutline({ x, y, width, height, cells }, boardWidth, boardHeight) {
2806
2807
  const inside2 = (cx2, cy) => cx2 >= x && cy >= y && cx2 < x + width && cy < y + height && cx2 >= 0 && cy >= 0 && cx2 < boardWidth && cy < boardHeight && (!cells || !!cells[cy - y]?.[cx2 - x]);
2807
2808
  const squares = [];
2808
2809
  const edges = [];
@@ -2857,27 +2858,27 @@ function face(ctx, points, color) {
2857
2858
  ctx.stroke();
2858
2859
  }
2859
2860
  function sideColor(cell) {
2860
- if (cell.terrain === "blocking") return TERRAIN_EDGE_COLORS.blocking;
2861
- if (cell.level > 1) return ELEVATION_TILE_COLORS[Math.min(cell.level, ELEVATION_TILE_COLORS.length) - 1];
2862
- if (cell.terrain === "water") return TERRAIN_EDGE_COLORS.water;
2863
- if (cell.terrain === "hindering") return TERRAIN_EDGE_COLORS.hindering;
2864
- if (cell.terrain === "obscuring") return TERRAIN_EDGE_COLORS.obscuring;
2865
- if (cell.terrain === "window") return TERRAIN_EDGE_COLORS.window;
2861
+ if (cell.terrain === "blocking") return MAP_TERRAIN_EDGE_COLORS.blocking;
2862
+ if (cell.level > 1) return MAP_ELEVATION_TILE_COLORS[Math.min(cell.level, MAP_ELEVATION_TILE_COLORS.length) - 1];
2863
+ if (cell.terrain === "water") return MAP_TERRAIN_EDGE_COLORS.water;
2864
+ if (cell.terrain === "hindering") return MAP_TERRAIN_EDGE_COLORS.hindering;
2865
+ if (cell.terrain === "obscuring") return MAP_TERRAIN_EDGE_COLORS.obscuring;
2866
+ if (cell.terrain === "window") return MAP_TERRAIN_EDGE_COLORS.window;
2866
2867
  return SIDE_COLORS[cell.environment] ?? SIDE_COLORS.unknown;
2867
2868
  }
2868
2869
  function drawCellSides(ctx, scene, view, cell) {
2869
2870
  const { point } = view;
2870
- for (const side of CELL_SIDES) {
2871
+ for (const side of MAP_CELL_SIDES) {
2871
2872
  if (side.dx * view.sin + side.dy * view.cos <= 0) continue;
2872
- const neighbor = sceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2873
- const low = neighbor ? neighbor.top : BASE_Z;
2873
+ const neighbor = mapSceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2874
+ const low = neighbor ? neighbor.top : MAP_SCENE_BASE_Z;
2874
2875
  if (low >= cell.top) continue;
2875
2876
  const ax = cell.x + side.ax, ay = cell.y + side.ay, bx = cell.x + side.bx, by = cell.y + side.by;
2876
2877
  const light = faceLight(view, side.dx, side.dy);
2877
2878
  face(ctx, [point(ax, ay, low), point(bx, by, low), point(bx, by, cell.top), point(ax, ay, cell.top)], shade(sideColor(cell), light));
2878
2879
  ctx.strokeStyle = "rgba(0,0,0,.26)";
2879
2880
  ctx.lineWidth = 1;
2880
- for (let z = 0; z < cell.top - 0.01; z += LEVEL_HEIGHT) {
2881
+ for (let z = 0; z < cell.top - 0.01; z += MAP_SCENE_LEVEL_HEIGHT) {
2881
2882
  if (z <= low + 0.01) continue;
2882
2883
  const [x0, y0] = point(ax, ay, z), [x1, y1] = point(bx, by, z);
2883
2884
  ctx.beginPath();
@@ -2891,13 +2892,13 @@ function drawCellTop(ctx, scene, view, cell, texture, shadows) {
2891
2892
  const p00 = view.point(cell.x, cell.y, cell.top), p10 = view.point(cell.x + 1, cell.y, cell.top), p01 = view.point(cell.x, cell.y + 1, cell.top);
2892
2893
  ctx.save();
2893
2894
  ctx.transform(p10[0] - p00[0], p10[1] - p00[1], p01[0] - p00[0], p01[1] - p00[1], p00[0], p00[1]);
2894
- ctx.drawImage(texture, cell.x * TILE_SIZE, cell.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, -0.012, -0.012, 1.024, 1.024);
2895
+ ctx.drawImage(texture, cell.x * MAP_TILE_SIZE, cell.y * MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE, -0.012, -0.012, 1.024, 1.024);
2895
2896
  if (cell.environment === "indoor") {
2896
2897
  ctx.fillStyle = (cell.x + cell.y) % 2 ? "rgba(52,62,92,.13)" : "rgba(52,62,92,.07)";
2897
2898
  ctx.fillRect(0, 0, 1, 1);
2898
2899
  }
2899
- CELL_SIDES.forEach((side, index) => {
2900
- const neighbor = sceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2900
+ MAP_CELL_SIDES.forEach((side, index) => {
2901
+ const neighbor = mapSceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2901
2902
  if (!neighbor || neighbor.top <= cell.top + 0.01) return;
2902
2903
  ctx.fillStyle = shadows[index];
2903
2904
  ctx.fillRect(0, 0, 1, 1);
@@ -2938,7 +2939,7 @@ function drawRamp(ctx, view, ramp) {
2938
2939
  const sx = ramp.dy * 0.2, sy = ramp.dx * 0.2, lx = -ramp.dx * 0.38, ly = -ramp.dy * 0.38;
2939
2940
  const a = [cx2 - sx, cy - sy], b = [cx2 + sx, cy + sy];
2940
2941
  const c = [cx2 + sx + lx, cy + sy + ly], d = [cx2 - sx + lx, cy - sy + ly];
2941
- const color = ELEVATION_TILE_COLORS[1];
2942
+ const color = MAP_ELEVATION_TILE_COLORS[1];
2942
2943
  face(ctx, [point(a[0], a[1], ramp.from), point(d[0], d[1], ramp.from), point(a[0], a[1], ramp.to)], shade(color, 0.66));
2943
2944
  face(ctx, [point(b[0], b[1], ramp.from), point(c[0], c[1], ramp.from), point(b[0], b[1], ramp.to)], shade(color, 0.66));
2944
2945
  polygon(ctx, [point(a[0], a[1], ramp.to), point(b[0], b[1], ramp.to), point(c[0], c[1], ramp.from), point(d[0], d[1], ramp.from)]);
@@ -2958,7 +2959,7 @@ function drawWall(ctx, view, wall) {
2958
2959
  const x0 = Math.min(wall.x0, wall.x1) - ox, x1 = Math.max(wall.x0, wall.x1) + ox;
2959
2960
  const y0 = Math.min(wall.y0, wall.y1) - oy, y1 = Math.max(wall.y0, wall.y1) + oy;
2960
2961
  const alpha = TRANSLUCENT_WALLS[wall.type];
2961
- const color = GLASS_COLORS[wall.type] ?? (wall.type === "normal" ? "#30343c" : WALL_COLORS[wall.type] ?? "#30343c");
2962
+ const color = GLASS_COLORS[wall.type] ?? (wall.type === "normal" ? "#30343c" : MAP_WALL_COLORS[wall.type] ?? "#30343c");
2962
2963
  ctx.save();
2963
2964
  if (alpha) ctx.globalAlpha = alpha;
2964
2965
  if (wall.type === "door" || wall.type === "door2") {
@@ -2974,10 +2975,10 @@ function drawWall(ctx, view, wall) {
2974
2975
  ctx.restore();
2975
2976
  }
2976
2977
  function drawIndoorCurb(ctx, scene, view, cell) {
2977
- ctx.strokeStyle = INDOOR_EDGE_COLOR;
2978
+ ctx.strokeStyle = MAP_INDOOR_EDGE_COLOR;
2978
2979
  ctx.lineWidth = 2;
2979
- for (const side of CELL_SIDES) {
2980
- const neighbor = sceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2980
+ for (const side of MAP_CELL_SIDES) {
2981
+ const neighbor = mapSceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2981
2982
  if (neighbor?.environment !== "outdoor") continue;
2982
2983
  const [x0, y0] = view.point(cell.x + side.ax, cell.y + side.ay, cell.top), [x1, y1] = view.point(cell.x + side.bx, cell.y + side.by, cell.top);
2983
2984
  ctx.beginPath();
@@ -2987,7 +2988,7 @@ function drawIndoorCurb(ctx, scene, view, cell) {
2987
2988
  }
2988
2989
  }
2989
2990
  function drawFootprint(ctx, scene, view, footprint) {
2990
- const { squares, edges, corners } = footprintOutline(footprint, scene.width, scene.height);
2991
+ const { squares, edges, corners } = mapFootprintOutline(footprint, scene.width, scene.height);
2991
2992
  if (!squares.length) return;
2992
2993
  const { top, valid } = footprint;
2993
2994
  const color = valid ? MOVE_VALID_COLOR : MOVE_INVALID_COLOR;
@@ -3034,7 +3035,7 @@ function drawHighlight(ctx, scene, view, highlight) {
3034
3035
  if (highlight.line) {
3035
3036
  const { x0, y0, x1, y1 } = highlight.line;
3036
3037
  const mx = (x0 + x1) / 2, my = (y0 + y1) / 2;
3037
- const near = [[Math.floor(mx - 0.01), Math.floor(my - 0.01)], [Math.floor(mx + 0.01), Math.floor(my + 0.01)]].map(([x, y]) => sceneCell(scene, x, y)?.top ?? 0);
3038
+ const near = [[Math.floor(mx - 0.01), Math.floor(my - 0.01)], [Math.floor(mx + 0.01), Math.floor(my + 0.01)]].map(([x, y]) => mapSceneCell(scene, x, y)?.top ?? 0);
3038
3039
  const z = Math.max(...near);
3039
3040
  const [ax, ay] = view.point(x0, y0, z), [bx, by] = view.point(x1, y1, z);
3040
3041
  ctx.strokeStyle = "rgba(0,0,0,.6)";
@@ -3047,7 +3048,7 @@ function drawHighlight(ctx, scene, view, highlight) {
3047
3048
  ctx.lineCap = "butt";
3048
3049
  return;
3049
3050
  }
3050
- const cell = highlight.square && sceneCell(scene, highlight.square.x, highlight.square.y);
3051
+ const cell = highlight.square && mapSceneCell(scene, highlight.square.x, highlight.square.y);
3051
3052
  if (!cell) return;
3052
3053
  polygon(ctx, [view.point(cell.x, cell.y, cell.top), view.point(cell.x + 1, cell.y, cell.top), view.point(cell.x + 1, cell.y + 1, cell.top), view.point(cell.x, cell.y + 1, cell.top)]);
3053
3054
  ctx.fillStyle = "rgba(0,0,0,.16)";
@@ -3058,7 +3059,7 @@ function drawHighlight(ctx, scene, view, highlight) {
3058
3059
  }
3059
3060
  function drawMapScene(ctx, scene, view, texture, highlight, { tufts = true } = {}) {
3060
3061
  const pad = 0.35;
3061
- polygon(ctx, [view.point(-pad, -pad, BASE_Z - 0.16), view.point(scene.width + pad, -pad, BASE_Z - 0.16), view.point(scene.width + pad, scene.height + pad, BASE_Z - 0.16), view.point(-pad, scene.height + pad, BASE_Z - 0.16)]);
3062
+ polygon(ctx, [view.point(-pad, -pad, MAP_SCENE_BASE_Z - 0.16), view.point(scene.width + pad, -pad, MAP_SCENE_BASE_Z - 0.16), view.point(scene.width + pad, scene.height + pad, MAP_SCENE_BASE_Z - 0.16), view.point(-pad, scene.height + pad, MAP_SCENE_BASE_Z - 0.16)]);
3062
3063
  ctx.fillStyle = "rgba(0,0,0,.14)";
3063
3064
  ctx.fill();
3064
3065
  const shadowDepth = 0.24;
@@ -3107,8 +3108,8 @@ var MAP_THUMBNAIL_HEIGHT = 192;
3107
3108
  function renderMapThumbnail(json, height = MAP_THUMBNAIL_HEIGHT) {
3108
3109
  if (!json?.width || !json?.height) return null;
3109
3110
  const full = document.createElement("canvas");
3110
- full.width = json.width * TILE_SIZE;
3111
- full.height = json.height * TILE_SIZE;
3111
+ full.width = json.width * MAP_TILE_SIZE;
3112
+ full.height = json.height * MAP_TILE_SIZE;
3112
3113
  const fctx = full.getContext("2d");
3113
3114
  if (!fctx) return null;
3114
3115
  new HCMap(json).draw(fctx);
@@ -3157,7 +3158,7 @@ var MapBoardView = forwardRef(function MapBoardView2({ map, canvasLabel, selecti
3157
3158
  if (event.pointerType !== "touch") onLeave?.();
3158
3159
  },
3159
3160
  children: [
3160
- /* @__PURE__ */ jsx("canvas", { ref: canvasRef, width: map.width * TILE_SIZE, height: map.height * TILE_SIZE, role: "img", "aria-label": canvasLabel }),
3161
+ /* @__PURE__ */ jsx("canvas", { ref: canvasRef, width: map.width * MAP_TILE_SIZE, height: map.height * MAP_TILE_SIZE, role: "img", "aria-label": canvasLabel }),
3161
3162
  selection && /* @__PURE__ */ jsx("svg", { className: "hc-ui-map-board__selection", viewBox: `0 0 ${map.width} ${map.height}`, "aria-hidden": "true", children: selection.line ? /* @__PURE__ */ jsx("line", { x1: selection.line.x0, y1: selection.line.y0, x2: selection.line.x1, y2: selection.line.y1 }) : /* @__PURE__ */ jsx("rect", { x: selection.square.x, y: selection.square.y, width: "1", height: "1" }) })
3162
3163
  ]
3163
3164
  }
@@ -3226,31 +3227,33 @@ function MapEnvironmentView({ types, icons, labels, className }) {
3226
3227
  }
3227
3228
  export {
3228
3229
  AvatarView,
3229
- BACK_TABLE_HEIGHT,
3230
- BASE_Z,
3231
- BYSTANDER_DIAL_STEP,
3232
3230
  Button,
3233
- CARD_HEIGHT,
3234
- CARD_WIDTH,
3235
- CELL_SIDES,
3236
3231
  COMBAT_DIAL_STATS,
3237
3232
  Checkbox,
3238
3233
  Chip,
3239
3234
  CombatDialView,
3240
3235
  CommandPalette,
3241
- DEFAULT_CAMERA,
3242
3236
  Dialog,
3243
- ELEVATION_EDGE_COLOR,
3244
- ELEVATION_TILE_COLORS,
3245
3237
  EquipmentIcon,
3246
3238
  Field,
3247
3239
  FilterBar,
3248
3240
  HCMap,
3249
- INDOOR_EDGE_COLOR,
3250
3241
  IconButton,
3251
- LEVEL_HEIGHT,
3252
3242
  ListRow,
3243
+ MAP_CELL_SIDES,
3244
+ MAP_DEFAULT_CAMERA,
3245
+ MAP_ELEVATION_EDGE_COLOR,
3246
+ MAP_ELEVATION_TILE_COLORS,
3247
+ MAP_INDOOR_EDGE_COLOR,
3248
+ MAP_SCENE_BASE_Z,
3249
+ MAP_SCENE_LEVEL_HEIGHT,
3250
+ MAP_TERRAIN_EDGE_COLORS,
3251
+ MAP_TERRAIN_TILE_COLORS,
3253
3252
  MAP_THUMBNAIL_HEIGHT,
3253
+ MAP_TILE_SIZE,
3254
+ MAP_TILT_RANGE,
3255
+ MAP_WALL_COLORS,
3256
+ MAP_ZOOM_RANGE,
3254
3257
  MINI_DIAL_STATS,
3255
3258
  MapBoardPlaceholder,
3256
3259
  MapBoardView,
@@ -3267,7 +3270,11 @@ export {
3267
3270
  MenuSeparator,
3268
3271
  Meter,
3269
3272
  MiniDialView,
3273
+ PHYSICAL_CARD_BACK_TABLE_HEIGHT,
3274
+ PHYSICAL_CARD_BYSTANDER_DIAL_STEP,
3275
+ PHYSICAL_CARD_HEIGHT,
3270
3276
  PHYSICAL_CARD_STATS,
3277
+ PHYSICAL_CARD_WIDTH,
3271
3278
  PageHeader,
3272
3279
  PanelHeader,
3273
3280
  PhysicalCardFocusView,
@@ -3285,35 +3292,29 @@ export {
3285
3292
  StatGlyphView,
3286
3293
  StatIcon,
3287
3294
  Surface,
3288
- TERRAIN_EDGE_COLORS,
3289
- TERRAIN_TILE_COLORS,
3290
- TILE_SIZE,
3291
- TILT_RANGE,
3292
3295
  Table,
3293
- WALL_COLORS,
3294
- ZOOM_RANGE,
3295
- backCount,
3296
3296
  buildMapScene,
3297
- clamp,
3298
- clampPan,
3299
- devicePosition,
3297
+ clampMapPan,
3298
+ clampMapValue,
3300
3299
  drawMapScene,
3301
- elevationLevel,
3302
- footprintOutline,
3303
3300
  inspectMap,
3304
- makeProjection,
3301
+ makeMapProjection,
3302
+ mapElevationLevel,
3305
3303
  mapEnvironments,
3304
+ mapFootprintOutline,
3306
3305
  mapMaxLevel,
3306
+ mapSceneCell,
3307
3307
  mapSquare,
3308
- nextDistribution,
3309
- pickScene,
3308
+ mapSquareCoordinate,
3309
+ nextPhysicalCardDistribution,
3310
+ physicalCardBackCount,
3311
+ physicalCardDevicePosition,
3312
+ physicalCardTiltAt,
3313
+ physicalCardTiltStyles,
3314
+ pickMapScene,
3310
3315
  placePopup,
3311
3316
  renderMapThumbnail,
3312
- requestMotionAccess,
3313
- sceneCell,
3314
- squareCoordinate,
3315
- tiltAt,
3316
- tiltStyles,
3317
+ requestPhysicalCardMotionAccess,
3317
3318
  useImageChain,
3318
- zoomCamera
3319
+ zoomMapCamera
3319
3320
  };