@ntmats/hc-ui 0.4.0 → 0.6.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
@@ -6,8 +6,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
6
6
  import { cloneElement, createContext, forwardRef, Fragment, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
7
7
  import { createPortal } from "react-dom";
8
8
  import { Fragment as Fragment2, jsx, jsxs } from "react/jsx-runtime";
9
- function Surface({ tone = "content", radius, className, ...props }) {
10
- return /* @__PURE__ */ jsx("div", { ...props, className: ["hc-ui-surface", className].filter(Boolean).join(" "), "data-tone": tone, "data-radius": radius });
9
+ function Surface({ tone = "content", radius, as: Element = "div", className, ...props }) {
10
+ return /* @__PURE__ */ jsx(Element, { ...props, className: ["hc-ui-surface", className].filter(Boolean).join(" "), "data-tone": tone, "data-radius": radius });
11
11
  }
12
12
  function SegmentedControl({
13
13
  label,
@@ -20,6 +20,7 @@ function SegmentedControl({
20
20
  indicator = "static",
21
21
  equalWidth = false,
22
22
  optionWidth,
23
+ optionMinWidth,
23
24
  className,
24
25
  style,
25
26
  ...props
@@ -33,7 +34,8 @@ function SegmentedControl({
33
34
  const layout = {
34
35
  ...equal ? { "--hc-segmented-count": options.length } : {},
35
36
  ...slide ? { "--hc-segmented-index": Math.max(knobIndex, 0) } : {},
36
- ...optionWidth !== void 0 ? { "--hc-segmented-option-width": `${optionWidth}px` } : {}
37
+ ...optionWidth !== void 0 ? { "--hc-segmented-option-width": `${optionWidth}px` } : {},
38
+ ...optionMinWidth !== void 0 ? { "--hc-segmented-option-min-width": `${optionMinWidth}px` } : {}
37
39
  };
38
40
  const move = (index, key) => {
39
41
  if (!["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp", "Home", "End"].includes(key)) return false;
@@ -103,7 +105,7 @@ function SegmentedControl({
103
105
  );
104
106
  }
105
107
  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) {
108
+ var Button = forwardRef(function Button2({ variant = "secondary", tone = "default", size = "md", icon, iconEnd, fullWidth = false, loading = false, wrap = false, type = "button", className, children, onClick, ...props }, ref) {
107
109
  const handleClick = (event) => {
108
110
  if (loading) event.preventDefault();
109
111
  else onClick?.(event);
@@ -120,7 +122,9 @@ var Button = forwardRef(function Button2({ variant = "secondary", size = "md", i
120
122
  "aria-disabled": loading || props["aria-disabled"],
121
123
  "data-variant": variant,
122
124
  "data-size": size,
125
+ "data-tone": tone === "default" ? void 0 : tone,
123
126
  "data-full-width": fullWidth || void 0,
127
+ "data-wrap": wrap || void 0,
124
128
  children: [
125
129
  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
130
  /* @__PURE__ */ jsx("span", { className: "hc-ui-button__label", children }),
@@ -152,31 +156,33 @@ var glyph = (size, d) => /* @__PURE__ */ jsx("svg", { width: size, height: size,
152
156
  var CHEVRON_DOWN = "M6 9L12 15L18 9";
153
157
  var XMARK = "M6.75827 17.2426L12.0009 12M17.2435 6.75736L12.0009 12M12.0009 12L6.75827 6.75736M12.0009 12L17.2435 17.2426";
154
158
  var visible = (node) => node !== void 0 && node !== null && node !== false && node !== "";
155
- var Chip = forwardRef(function Chip2({ selected, icon, size = "md", variant = "outline", applied = false, count, badge, chevron, onClear, clearLabel, type = "button", className, children, ...props }, ref) {
159
+ var Chip = forwardRef(function Chip2({ selected, icon, size = "md", variant = "outline", applied = false, count, badge, badgePlacement = "inline", informative = false, chevron, onClear, clearLabel, type = "button", className, children, ...props }, ref) {
156
160
  const popup = props["aria-haspopup"];
157
161
  const withChevron = chevron ?? (popup !== void 0 && popup !== false && popup !== "false");
158
162
  const look = {
159
163
  "data-size": size === "md" ? void 0 : size,
160
164
  "data-variant": variant === "outline" ? void 0 : variant,
161
- "data-applied": applied || void 0
165
+ "data-applied": applied || void 0,
166
+ "data-icon-only": icon && !visible(children) || void 0,
167
+ "data-informative": informative || void 0
162
168
  };
163
169
  const content = /* @__PURE__ */ jsxs(Fragment2, { children: [
164
170
  icon && /* @__PURE__ */ jsx("span", { className: "hc-ui-chip__icon", "aria-hidden": "true", children: icon }),
165
171
  children,
166
172
  visible(count) && /* @__PURE__ */ jsx("span", { className: "hc-ui-chip__count", children: count }),
167
- visible(badge) && /* @__PURE__ */ jsx("span", { className: "hc-ui-chip__badge", children: badge }),
173
+ visible(badge) && /* @__PURE__ */ jsx("span", { className: "hc-ui-chip__badge", "data-placement": badgePlacement === "corner" ? "corner" : void 0, children: badge }),
168
174
  withChevron && /* @__PURE__ */ jsx("span", { className: "hc-ui-chip__chevron", "aria-hidden": "true", children: glyph(size === "xs" ? 12 : 14, CHEVRON_DOWN) })
169
175
  ] });
170
176
  if (!onClear) {
171
- return /* @__PURE__ */ jsx("button", { ...props, ref, type, "aria-pressed": selected, className: classes("hc-ui-chip", className), ...look, children: content });
177
+ return /* @__PURE__ */ jsx("button", { ...props, ...informative ? { disabled: true } : {}, ref, type, "aria-pressed": selected, className: classes("hc-ui-chip", className), ...look, children: content });
172
178
  }
173
179
  const { style, id, onClick, disabled, ...rest } = props;
174
180
  return /* @__PURE__ */ jsxs("span", { className: classes("hc-ui-chip", className), style, ...look, "data-clearable": "", "data-selected": selected || void 0, "data-disabled": disabled || void 0, children: [
175
- onClick ? /* @__PURE__ */ jsx("button", { ...rest, id, ref, type, disabled, "aria-pressed": selected, className: "hc-ui-chip__main", onClick, children: content }) : /* @__PURE__ */ jsx("span", { id, className: "hc-ui-chip__main", children: content }),
181
+ onClick ? /* @__PURE__ */ jsx("button", { ...rest, id, ref, type, disabled: informative || disabled, "aria-pressed": selected, className: "hc-ui-chip__main", onClick, children: content }) : /* @__PURE__ */ jsx("span", { id, className: "hc-ui-chip__main", children: content }),
176
182
  /* @__PURE__ */ jsx("button", { type: "button", className: "hc-ui-chip__clear", "aria-label": clearLabel, title: clearLabel, disabled, onClick: onClear, children: glyph(12, XMARK) })
177
183
  ] });
178
184
  });
179
- var FilterBar = forwardRef(function FilterBar2({ label, start, end, footer, layout = "auto", density = "comfortable", sticky = false, className, children, ...props }, ref) {
185
+ var FilterBar = forwardRef(function FilterBar2({ label, start, end, footer, layout = "auto", density = "comfortable", sticky = false, bleed = false, rowClassName, className, children, ...props }, ref) {
180
186
  return /* @__PURE__ */ jsxs(
181
187
  "div",
182
188
  {
@@ -188,10 +194,11 @@ var FilterBar = forwardRef(function FilterBar2({ label, start, end, footer, layo
188
194
  "data-layout": layout,
189
195
  "data-density": density === "comfortable" ? void 0 : density,
190
196
  "data-sticky": sticky || void 0,
197
+ "data-bleed": bleed || void 0,
191
198
  children: [
192
199
  /* @__PURE__ */ jsxs("div", { className: "hc-ui-filter-bar__line", children: [
193
200
  start && /* @__PURE__ */ jsx("div", { className: "hc-ui-filter-bar__start", children: start }),
194
- /* @__PURE__ */ jsx("div", { className: "hc-ui-filter-bar__row", children }),
201
+ /* @__PURE__ */ jsx("div", { className: classes("hc-ui-filter-bar__row", rowClassName), children }),
195
202
  end && /* @__PURE__ */ jsx("div", { className: "hc-ui-filter-bar__end", children: end })
196
203
  ] }),
197
204
  footer && /* @__PURE__ */ jsx("div", { className: "hc-ui-filter-bar__footer", children: footer })
@@ -322,7 +329,7 @@ var outside = (element, x, y) => {
322
329
  const box = element.getBoundingClientRect();
323
330
  return x < box.left || x > box.right || y < box.top || y > box.bottom;
324
331
  };
325
- var Dialog = forwardRef(function Dialog2({
332
+ var DialogBase = forwardRef(function Dialog({
326
333
  open,
327
334
  onClose,
328
335
  title,
@@ -333,6 +340,8 @@ var Dialog = forwardRef(function Dialog2({
333
340
  closeIcon,
334
341
  size = "md",
335
342
  dismissible = true,
343
+ bodyClassName,
344
+ headerless = false,
336
345
  className,
337
346
  onClick,
338
347
  onPointerDown,
@@ -347,6 +356,7 @@ var Dialog = forwardRef(function Dialog2({
347
356
  }, [ref]);
348
357
  const id = useId();
349
358
  const titleId = `${id}-title`;
359
+ const bodyId = `${id}-body`;
350
360
  const descriptionId = description ? `${id}-description` : void 0;
351
361
  const [mounted, setMounted] = useState(open);
352
362
  const [closing, setClosing] = useState(false);
@@ -361,7 +371,7 @@ var Dialog = forwardRef(function Dialog2({
361
371
  });
362
372
  const keepFocus = useRef(null);
363
373
  const handleMount = useCallback(() => {
364
- const dialog = document.getElementById(titleId)?.closest("dialog");
374
+ const dialog = (document.getElementById(titleId) ?? document.getElementById(bodyId))?.closest("dialog");
365
375
  if (!dialog) return () => {
366
376
  };
367
377
  const trigger = document.activeElement instanceof HTMLElement ? document.activeElement : null;
@@ -380,7 +390,7 @@ var Dialog = forwardRef(function Dialog2({
380
390
  if (lost && !dialog.open && trigger?.isConnected) trigger.focus({ preventScroll: true });
381
391
  });
382
392
  };
383
- }, [titleId]);
393
+ }, [titleId, bodyId]);
384
394
  useEffect(() => {
385
395
  const dialog = dialogRef.current;
386
396
  if (!closing || !dialog) return;
@@ -427,7 +437,7 @@ var Dialog = forwardRef(function Dialog2({
427
437
  if (fromBackdrop && latest.current.dismissible && !latest.current.closing) latest.current.onClose();
428
438
  };
429
439
  if (!mounted) return null;
430
- const hasBody = Boolean(description) || children !== void 0 && children !== null && children !== false;
440
+ const hasBody = headerless || Boolean(description) || children !== void 0 && children !== null && children !== false;
431
441
  return /* @__PURE__ */ jsxs(
432
442
  "dialog",
433
443
  {
@@ -436,7 +446,8 @@ var Dialog = forwardRef(function Dialog2({
436
446
  className: classes("hc-ui-dialog", className),
437
447
  "data-size": size,
438
448
  "data-closing": closing || void 0,
439
- "aria-labelledby": titleId,
449
+ "data-headerless": headerless || void 0,
450
+ "aria-labelledby": headerless ? void 0 : titleId,
440
451
  "aria-describedby": classes(descriptionId, describedBy) || void 0,
441
452
  onCancel: handleCancel,
442
453
  onClose: handleNativeClose,
@@ -444,11 +455,11 @@ var Dialog = forwardRef(function Dialog2({
444
455
  onClick: handleClick,
445
456
  children: [
446
457
  /* @__PURE__ */ jsx(DialogMount, { onMount: handleMount }),
447
- /* @__PURE__ */ jsxs("div", { className: "hc-ui-dialog__header", children: [
458
+ !headerless && /* @__PURE__ */ jsxs("div", { className: "hc-ui-dialog__header", children: [
448
459
  /* @__PURE__ */ jsx("h2", { className: "hc-ui-dialog__title", id: titleId, children: title }),
449
460
  closeLabel && /* @__PURE__ */ jsx(IconButton, { className: "hc-ui-dialog__close", label: closeLabel, icon: closeIcon ?? closeGlyph, size: "sm", tone: "secondary", onClick: () => latest.current.onClose() })
450
461
  ] }),
451
- hasBody && /* @__PURE__ */ jsxs("div", { className: "hc-ui-dialog__body", children: [
462
+ hasBody && /* @__PURE__ */ jsxs("div", { className: classes("hc-ui-dialog__body", bodyClassName), id: headerless ? bodyId : void 0, children: [
452
463
  description && /* @__PURE__ */ jsx("p", { className: "hc-ui-dialog__description", id: descriptionId, children: description }),
453
464
  children
454
465
  ] }),
@@ -457,8 +468,9 @@ var Dialog = forwardRef(function Dialog2({
457
468
  }
458
469
  );
459
470
  });
471
+ var Dialog2 = DialogBase;
460
472
  var SHEET_EASE = "cubic-bezier(0.32, 0.72, 0, 1)";
461
- var NO_DRAG = 'input, textarea, select, [contenteditable="true"], [data-hc-sheet-nodrag]';
473
+ var NO_DRAG = 'input, textarea, select, [contenteditable="true"], [data-hc-sheet-nodrag], .hc-ui-portal';
462
474
  function useSheetDrag(sheet, latest) {
463
475
  useEffect(() => {
464
476
  const el = sheet;
@@ -590,7 +602,7 @@ function useSheetDrag(sheet, latest) {
590
602
  };
591
603
  }, [sheet, latest]);
592
604
  }
593
- var Sheet = forwardRef(function Sheet2({ presentation = "auto", width = 440, footer, dismissible = true, onClose, className, style, ...props }, ref) {
605
+ var Sheet = forwardRef(function Sheet2({ presentation = "auto", width = 440, footer, dismissible = true, header = true, onClose, className, style, ...props }, ref) {
594
606
  const [node, setNode] = useState(null);
595
607
  const setRef = useCallback((element) => {
596
608
  setNode(element);
@@ -603,7 +615,7 @@ var Sheet = forwardRef(function Sheet2({ presentation = "auto", width = 440, foo
603
615
  useSheetDrag(node, latest);
604
616
  const sized = width === 440 ? style : { ...style, "--hc-sheet-width": `${width}px` };
605
617
  return /* @__PURE__ */ jsx(
606
- Dialog,
618
+ DialogBase,
607
619
  {
608
620
  ...props,
609
621
  ref: setRef,
@@ -611,6 +623,7 @@ var Sheet = forwardRef(function Sheet2({ presentation = "auto", width = 440, foo
611
623
  actions: footer,
612
624
  dismissible,
613
625
  onClose,
626
+ headerless: !header,
614
627
  className: classes("hc-ui-sheet", className),
615
628
  style: sized,
616
629
  "data-presentation": presentation
@@ -647,10 +660,9 @@ function useRovingRadios(options, value) {
647
660
  });
648
661
  return item;
649
662
  }
650
- function SheetOptions({ label, options, value, onChange, variant = "card", className, ...props }) {
663
+ function SheetOptions({ label, options, value, onChange, className, ...props }) {
651
664
  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) => {
665
+ return /* @__PURE__ */ jsx("div", { ...props, className: classes("hc-ui-sheet-options", className), role: "radiogroup", "aria-label": label, children: options.map((option, index) => {
654
666
  const on = option.value === value;
655
667
  return /* @__PURE__ */ jsxs(
656
668
  "button",
@@ -669,14 +681,14 @@ function SheetOptions({ label, options, value, onChange, variant = "card", class
669
681
  /* @__PURE__ */ jsx("span", { className: "hc-ui-sheet-options__label", children: option.label }),
670
682
  option.hint && /* @__PURE__ */ jsx("span", { className: "hc-ui-sheet-options__hint", children: option.hint })
671
683
  ] }),
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" }) }) })
684
+ /* @__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
685
  ]
674
686
  },
675
687
  option.value
676
688
  );
677
689
  }) });
678
690
  }
679
- function SheetChips({ label, options, value, onChange, className, ...props }) {
691
+ function SheetChips({ label, options, value, onChange, size = "md", className, ...props }) {
680
692
  const item = useRovingRadios(options, value);
681
693
  return /* @__PURE__ */ jsx("div", { ...props, className: classes("hc-ui-sheet-chips", className), role: "radiogroup", "aria-label": label, children: options.map((option, index) => /* @__PURE__ */ jsx(
682
694
  "button",
@@ -687,6 +699,7 @@ function SheetChips({ label, options, value, onChange, className, ...props }) {
687
699
  "aria-checked": option.value === value,
688
700
  disabled: option.disabled,
689
701
  className: "hc-ui-chip",
702
+ "data-size": size === "md" ? void 0 : size,
690
703
  onClick: () => onChange(option.value),
691
704
  children: option.label
692
705
  },
@@ -716,6 +729,10 @@ function placePopup(trigger, size, boundary, side, align) {
716
729
  const finalAlign = !fits(align) && fits(align === "end" ? "start" : "end") ? align === "end" ? "start" : "end" : align;
717
730
  return { side: finalSide, align: finalAlign };
718
731
  }
732
+ function portalContainerFor(node) {
733
+ if (typeof document === "undefined") return null;
734
+ return node?.closest("dialog[open]") ?? document.body;
735
+ }
719
736
  var layers = [];
720
737
  function themeOf(element) {
721
738
  const scoped = element?.closest("[data-theme]")?.getAttribute("data-theme");
@@ -761,7 +778,7 @@ function usePopup({ kind, trigger, open: openProp, defaultOpen = false, onOpenCh
761
778
  setContainer(null);
762
779
  return;
763
780
  }
764
- const element = portal instanceof HTMLElement ? portal : triggerRef.current?.closest("dialog[open]") ?? document.body;
781
+ const element = portal instanceof HTMLElement ? portal : portalContainerFor(triggerRef.current) ?? document.body;
765
782
  setContainer({ element, theme: theme ?? themeOf(triggerRef.current) });
766
783
  }, [open, portal, theme]);
767
784
  const place = useCallback(() => {
@@ -1555,6 +1572,7 @@ var CombatDialView = forwardRef(function CombatDialView2({
1555
1572
  currentClick,
1556
1573
  labels,
1557
1574
  presentation = "default",
1575
+ density = "comfortable",
1558
1576
  onClickChange,
1559
1577
  onSelectPoint,
1560
1578
  tip,
@@ -1658,7 +1676,7 @@ var CombatDialView = forwardRef(function CombatDialView2({
1658
1676
  COMBAT_DIAL_STATS.map((stat) => /* @__PURE__ */ jsx("div", { className: "hc-ui-combat-dial__cell", "data-kind": "ko", children: labels.koCell }, stat))
1659
1677
  ] })
1660
1678
  ] }, rowIndex);
1661
- return /* @__PURE__ */ jsxs("section", { ref, className: "hc-ui-combat-dial", "data-presentation": presentation, "data-static": flag(!tracksClick), children: [
1679
+ 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
1680
  presentation !== "printed" && /* @__PURE__ */ jsxs("header", { className: "hc-ui-combat-dial__header", children: [
1663
1681
  /* @__PURE__ */ jsxs("div", { className: "hc-ui-combat-dial__header-top", children: [
1664
1682
  /* @__PURE__ */ jsx("span", { className: "hc-ui-combat-dial__label", children: labels.heading }),
@@ -1693,11 +1711,11 @@ var CombatDialView = forwardRef(function CombatDialView2({
1693
1711
  tip && tipSlot
1694
1712
  ] });
1695
1713
  });
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) {
1714
+ var PHYSICAL_CARD_WIDTH = 375;
1715
+ var PHYSICAL_CARD_HEIGHT = 525;
1716
+ var PHYSICAL_CARD_BACK_TABLE_HEIGHT = 440;
1717
+ var PHYSICAL_CARD_BYSTANDER_DIAL_STEP = { x: 7, y: 24 };
1718
+ function nextPhysicalCardDistribution(pages, overflowing) {
1701
1719
  const last = pages.length ? Math.max(...pages) : 0;
1702
1720
  for (let table = 0; table <= last; table += 1) {
1703
1721
  if (!overflowing(table)) continue;
@@ -1709,7 +1727,7 @@ function nextDistribution(pages, overflowing) {
1709
1727
  }
1710
1728
  return null;
1711
1729
  }
1712
- function backCount(pages) {
1730
+ function physicalCardBackCount(pages) {
1713
1731
  const last = pages.length ? Math.max(...pages) : 0;
1714
1732
  return Math.max(1, Math.ceil(last / 2));
1715
1733
  }
@@ -1721,7 +1739,7 @@ var CAN_DEVICE_TILT = "(hover: none) and (pointer: coarse) and (prefers-reduced-
1721
1739
  var DEVICE_RANGE_DEG = 18;
1722
1740
  var BASELINE_DRIFT = 0.01;
1723
1741
  var DEVICE_SMOOTHING = 0.2;
1724
- function tiltAt(x, y, damping = 1) {
1742
+ function physicalCardTiltAt(x, y, damping = 1) {
1725
1743
  const offsetX = (x - 0.5) * 2 * damping;
1726
1744
  const offsetY = (y - 0.5) * 2 * damping;
1727
1745
  return {
@@ -1736,7 +1754,7 @@ function tiltAt(x, y, damping = 1) {
1736
1754
  var PARALLAX_ART_PX = 4;
1737
1755
  var PARALLAX_HEADER_PX = 1.5;
1738
1756
  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) {
1757
+ function physicalCardTiltStyles(tilt) {
1740
1758
  return {
1741
1759
  card: `perspective(1100px) rotateX(${tilt.rotateX}deg) rotateY(${tilt.rotateY}deg)`,
1742
1760
  art: `${tilt.parallaxX * PARALLAX_ART_PX}px ${tilt.parallaxY * PARALLAX_ART_PX}px`,
@@ -1748,7 +1766,7 @@ var eachIn = (root, selector, write) => {
1748
1766
  root.querySelectorAll(selector).forEach(write);
1749
1767
  };
1750
1768
  function applyTilt(root, tilt) {
1751
- const styles = tiltStyles(tilt);
1769
+ const styles = physicalCardTiltStyles(tilt);
1752
1770
  root.dataset.tilt = "";
1753
1771
  eachIn(root, ".hc-ui-physical-card-tilt", (element) => {
1754
1772
  element.style.transform = styles.card;
@@ -1772,7 +1790,7 @@ function clearTilt(root) {
1772
1790
  element.style.translate = "";
1773
1791
  });
1774
1792
  }
1775
- function devicePosition(beta, gamma, baseline, screenAngle = 0) {
1793
+ function physicalCardDevicePosition(beta, gamma, baseline, screenAngle = 0) {
1776
1794
  const clampAxis = (value) => Math.max(-1, Math.min(1, value / DEVICE_RANGE_DEG));
1777
1795
  const front = clampAxis(beta - baseline.beta);
1778
1796
  const side = clampAxis(gamma - baseline.gamma);
@@ -1780,7 +1798,7 @@ function devicePosition(beta, gamma, baseline, screenAngle = 0) {
1780
1798
  return { x: (horizontal + 1) / 2, y: (vertical + 1) / 2 };
1781
1799
  }
1782
1800
  var motionAsked = false;
1783
- function requestMotionAccess() {
1801
+ function requestPhysicalCardMotionAccess() {
1784
1802
  const request = typeof DeviceOrientationEvent === "undefined" ? void 0 : DeviceOrientationEvent.requestPermission;
1785
1803
  if (motionAsked || !request) return;
1786
1804
  motionAsked = true;
@@ -1801,10 +1819,10 @@ function useDeviceTilt(ref, enabled) {
1801
1819
  baseline ?? (baseline = { beta: event.beta, gamma: event.gamma });
1802
1820
  baseline.beta += (event.beta - baseline.beta) * BASELINE_DRIFT;
1803
1821
  baseline.gamma += (event.gamma - baseline.gamma) * BASELINE_DRIFT;
1804
- const target = devicePosition(event.beta, event.gamma, baseline, screen.orientation?.angle ?? 0);
1822
+ const target = physicalCardDevicePosition(event.beta, event.gamma, baseline, screen.orientation?.angle ?? 0);
1805
1823
  position = { x: position.x + (target.x - position.x) * DEVICE_SMOOTHING, y: position.y + (target.y - position.y) * DEVICE_SMOOTHING };
1806
1824
  cancelAnimationFrame(frame);
1807
- frame = requestAnimationFrame(() => applyTilt(element, tiltAt(position.x, position.y)));
1825
+ frame = requestAnimationFrame(() => applyTilt(element, physicalCardTiltAt(position.x, position.y)));
1808
1826
  };
1809
1827
  const onTouchStart = () => {
1810
1828
  touching = true;
@@ -1835,7 +1853,7 @@ function useCardTilt() {
1835
1853
  const slot = event.currentTarget;
1836
1854
  const rect = slot.getBoundingClientRect();
1837
1855
  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);
1856
+ const tilt = physicalCardTiltAt((event.clientX - rect.left) / rect.width, (event.clientY - rect.top) / rect.height, overDial ? DIAL_DAMPING : 1);
1839
1857
  cancelAnimationFrame(frame.current);
1840
1858
  frame.current = requestAnimationFrame(() => applyTilt(slot, tilt));
1841
1859
  };
@@ -1874,9 +1892,9 @@ function useCardScale(fitHeight, focus, scrollerSelector) {
1874
1892
  if (scroller) observer.observe(scroller);
1875
1893
  return () => observer.disconnect();
1876
1894
  }, [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;
1895
+ const columns = !focus && width >= PHYSICAL_CARD_WIDTH * SIDE_BY_SIDE_MIN_SCALE * 2 + CARD_GAP ? 2 : 1;
1896
+ const byWidth = width ? Math.min(MAX_CARD_SCALE, (width - CARD_GAP * (columns - 1)) / columns / PHYSICAL_CARD_WIDTH) : 1;
1897
+ const scale = (fitHeight || focus) && height > 0 ? Math.max(0.6, Math.min(byWidth, height / PHYSICAL_CARD_HEIGHT)) : byWidth;
1880
1898
  return { ref, scale };
1881
1899
  }
1882
1900
  function useFitText(text, max, min) {
@@ -1951,9 +1969,9 @@ function PhysicalCardFocusView({ label, onClose, children }) {
1951
1969
  }, 0);
1952
1970
  window.addEventListener("pointerup", release, { once: true });
1953
1971
  window.addEventListener("pointercancel", release, { once: true });
1954
- window.addEventListener("touchend", requestMotionAccess);
1972
+ window.addEventListener("touchend", requestPhysicalCardMotionAccess);
1955
1973
  return () => {
1956
- window.removeEventListener("touchend", requestMotionAccess);
1974
+ window.removeEventListener("touchend", requestPhysicalCardMotionAccess);
1957
1975
  window.removeEventListener("pointerup", release);
1958
1976
  window.removeEventListener("pointercancel", release);
1959
1977
  dialog.close();
@@ -2035,7 +2053,7 @@ var PhysicalCardView = forwardRef(function PhysicalCardView2({
2035
2053
  const pages = distribution.key === contentKey && distribution.pages.length === rules.length ? distribution.pages : zeros();
2036
2054
  const tables = useRef([]);
2037
2055
  useLayoutEffect(() => {
2038
- const next = nextDistribution(pages, (table) => {
2056
+ const next = nextPhysicalCardDistribution(pages, (table) => {
2039
2057
  const element = tables.current[table];
2040
2058
  return !!element && element.scrollHeight > element.clientHeight + 1;
2041
2059
  });
@@ -2171,17 +2189,17 @@ var PhysicalCardView = forwardRef(function PhysicalCardView2({
2171
2189
  ] }),
2172
2190
  /* @__PURE__ */ jsx("div", { className: "hc-ui-physical-card__bystander-name", children: bystander.name }),
2173
2191
  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 };
2192
+ const position = { left: row * PHYSICAL_CARD_BYSTANDER_DIAL_STEP.x, top: row * PHYSICAL_CARD_BYSTANDER_DIAL_STEP.y };
2175
2193
  const cellStyle = { ...position, backgroundColor: cell.background, color: cell.color };
2176
2194
  const cellProps = { className: "hc-ui-physical-card__bystander-value", "data-special": flag(cell.special), style: cellStyle, "aria-label": cell.label };
2177
2195
  if (!cell.tip) return /* @__PURE__ */ jsx("span", { ...cellProps, role: "img", children: cell.value }, cell.stat);
2178
2196
  return /* @__PURE__ */ jsx("button", { type: "button", ...cellProps, "data-tip": "", ...tipProps(cell.tip), children: cell.value }, cell.stat);
2179
2197
  }) })
2180
2198
  ] }) });
2181
- const backs = backCount(pages);
2199
+ const backs = physicalCardBackCount(pages);
2182
2200
  const shownSide = Math.min(side, backs);
2183
2201
  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` };
2202
+ 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
2203
  return /* @__PURE__ */ jsxs("div", { className: "hc-ui-physical-cards", "data-focus": flag(focus), ref: setWrapRef, style, ...longPress, children: [
2186
2204
  /* @__PURE__ */ jsxs(CardFrame, { side: "front", backgroundSrc: images.front, legacySrc: images.legacy, label: labels.front, away: focus && shownSide !== 0, children: [
2187
2205
  layout.teamUp && /* @__PURE__ */ jsx("span", { className: "hc-ui-physical-card__team-up", "aria-hidden": true }),
@@ -2238,8 +2256,8 @@ var PhysicalCardView = forwardRef(function PhysicalCardView2({
2238
2256
  tip && tipSlot
2239
2257
  ] });
2240
2258
  });
2241
- var TILE_SIZE = 64;
2242
- var EDGE_SIZE = TILE_SIZE / 16;
2259
+ var MAP_TILE_SIZE = 64;
2260
+ var EDGE_SIZE = MAP_TILE_SIZE / 16;
2243
2261
  var WALL_SIZE = EDGE_SIZE * 2;
2244
2262
  var MAX_EDGES = 4;
2245
2263
  var HINDERING_TILE_COLOR = "#B4ECB4";
@@ -2249,9 +2267,9 @@ var OBSCURING_TILE_COLOR = "#E8E8E8";
2249
2267
  var WINDOW_TILE_COLOR = "#dee8eb";
2250
2268
  var SPECIAL_TILE_COLOR = "#FFD394";
2251
2269
  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],
2270
+ var MAP_ELEVATION_TILE_COLORS = ["#FFFFFF", "#FB7A7F", "#D0424C", "#B02020", "#902020", "#702020"];
2271
+ var MAP_TERRAIN_TILE_COLORS = {
2272
+ clear: MAP_ELEVATION_TILE_COLORS[0],
2255
2273
  hindering: HINDERING_TILE_COLOR,
2256
2274
  blocking: BLOCKING_TILE_COLOR,
2257
2275
  water: WATER_TILE_COLOR,
@@ -2260,7 +2278,7 @@ var TERRAIN_TILE_COLORS = {
2260
2278
  special: SPECIAL_TILE_COLOR,
2261
2279
  special2: SPECIAL_TILE_COLOR
2262
2280
  };
2263
- var TERRAIN_EDGE_COLORS = {
2281
+ var MAP_TERRAIN_EDGE_COLORS = {
2264
2282
  clear: "#FFFFFF",
2265
2283
  hindering: "#3ACE3A",
2266
2284
  blocking: "#76491E",
@@ -2271,9 +2289,9 @@ var TERRAIN_EDGE_COLORS = {
2271
2289
  special2: "#FF7600"
2272
2290
  };
2273
2291
  var STARTING_ZONE_EDGE_COLOR = "#D560A9";
2274
- var ELEVATION_EDGE_COLOR = "#FF0000";
2275
- var INDOOR_EDGE_COLOR = "#FFFF00";
2276
- var WALL_COLORS = {
2292
+ var MAP_ELEVATION_EDGE_COLOR = "#FF0000";
2293
+ var MAP_INDOOR_EDGE_COLOR = "#FFFF00";
2294
+ var MAP_WALL_COLORS = {
2277
2295
  normal: "#000000",
2278
2296
  glass: "#E59400",
2279
2297
  glass2: "#33BBFF",
@@ -2316,8 +2334,8 @@ var Tile = class {
2316
2334
  else if (this.terrain === "window") this.fillStyle = WINDOW_TILE_COLOR;
2317
2335
  else if (this.terrain === "special" || this.terrain === "special2") this.fillStyle = SPECIAL_TILE_COLOR;
2318
2336
  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];
2337
+ else if (typeof this.elevation === "string") this.fillStyle = MAP_ELEVATION_TILE_COLORS[1];
2338
+ else this.fillStyle = MAP_ELEVATION_TILE_COLORS[this.elevation - 1] ?? MAP_ELEVATION_TILE_COLORS[0];
2321
2339
  }
2322
2340
  addEdge(edgeType, strokeStyle, dashed) {
2323
2341
  while (this.edges[edgeType]) edgeType += 4;
@@ -2332,7 +2350,7 @@ var Tile = class {
2332
2350
  }
2333
2351
  draw(ctx) {
2334
2352
  ctx.fillStyle = this.fillStyle;
2335
- ctx.fillRect(this.x * TILE_SIZE, this.y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
2353
+ ctx.fillRect(this.x * MAP_TILE_SIZE, this.y * MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE);
2336
2354
  }
2337
2355
  drawEdges(ctx) {
2338
2356
  const edgeLevels = [-1, -1, -1, -1];
@@ -2366,27 +2384,27 @@ var Tile = class {
2366
2384
  const oBottom = this.hasEdge(3 /* BOTTOM */ + level * 4) ? 0 : overhangSize;
2367
2385
  switch (edgeType) {
2368
2386
  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;
2387
+ x0 = x1 = this.x * MAP_TILE_SIZE + EDGE_SIZE / 2 + EDGE_SIZE * level;
2388
+ y0 = this.y * MAP_TILE_SIZE - oTop;
2389
+ y1 = (this.y + 1) * MAP_TILE_SIZE + oBottom;
2372
2390
  lineDashOffset = oTop;
2373
2391
  break;
2374
2392
  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;
2393
+ x0 = x1 = (this.x + 1) * MAP_TILE_SIZE - EDGE_SIZE / 2 - EDGE_SIZE * level;
2394
+ y0 = this.y * MAP_TILE_SIZE - oTop;
2395
+ y1 = (this.y + 1) * MAP_TILE_SIZE + oBottom;
2378
2396
  lineDashOffset = oTop;
2379
2397
  break;
2380
2398
  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;
2399
+ x0 = this.x * MAP_TILE_SIZE - oLeft;
2400
+ y0 = y1 = this.y * MAP_TILE_SIZE + EDGE_SIZE / 2 + EDGE_SIZE * level;
2401
+ x1 = (this.x + 1) * MAP_TILE_SIZE + oRight;
2384
2402
  lineDashOffset = oLeft;
2385
2403
  break;
2386
2404
  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;
2405
+ x0 = this.x * MAP_TILE_SIZE - oLeft;
2406
+ y0 = y1 = (this.y + 1) * MAP_TILE_SIZE - EDGE_SIZE / 2 - EDGE_SIZE * level;
2407
+ x1 = (this.x + 1) * MAP_TILE_SIZE + oRight;
2390
2408
  lineDashOffset = oLeft;
2391
2409
  break;
2392
2410
  }
@@ -2410,33 +2428,33 @@ var Tile = class {
2410
2428
  }
2411
2429
  drawRamp(ctx, angle) {
2412
2430
  ctx.save();
2413
- ctx.translate(this.x * TILE_SIZE + TILE_SIZE / 2, this.y * TILE_SIZE + TILE_SIZE / 2);
2431
+ ctx.translate(this.x * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, this.y * MAP_TILE_SIZE + MAP_TILE_SIZE / 2);
2414
2432
  ctx.rotate(angle);
2415
2433
  ctx.beginPath();
2416
2434
  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);
2435
+ ctx.lineTo(-(MAP_TILE_SIZE / 2 - EDGE_SIZE * 2), MAP_TILE_SIZE / 2 - EDGE_SIZE);
2436
+ ctx.lineTo(MAP_TILE_SIZE / 2 - EDGE_SIZE * 2, MAP_TILE_SIZE / 2 - EDGE_SIZE);
2419
2437
  ctx.closePath();
2420
2438
  ctx.lineWidth = EDGE_SIZE * 2;
2421
- ctx.strokeStyle = ELEVATION_EDGE_COLOR;
2439
+ ctx.strokeStyle = MAP_ELEVATION_EDGE_COLOR;
2422
2440
  ctx.stroke();
2423
- ctx.fillStyle = ELEVATION_TILE_COLORS[1];
2441
+ ctx.fillStyle = MAP_ELEVATION_TILE_COLORS[1];
2424
2442
  ctx.fill();
2425
2443
  ctx.font = "18px Arial";
2426
2444
  ctx.fillStyle = "#000000";
2427
2445
  ctx.textAlign = "center";
2428
2446
  ctx.textBaseline = "middle";
2429
- ctx.fillText(String(this.elevation), 0, TILE_SIZE / 4 + 4);
2447
+ ctx.fillText(String(this.elevation), 0, MAP_TILE_SIZE / 4 + 4);
2430
2448
  ctx.restore();
2431
2449
  }
2432
2450
  drawLabel(ctx) {
2433
2451
  if (this.hideLabel || this.x !== 0 && this.y !== 0 && !this.label) return;
2434
2452
  let text = "";
2435
2453
  ctx.save();
2436
- ctx.translate(this.x * TILE_SIZE + TILE_SIZE / 2, this.y * TILE_SIZE + TILE_SIZE / 2);
2454
+ ctx.translate(this.x * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, this.y * MAP_TILE_SIZE + MAP_TILE_SIZE / 2);
2437
2455
  if (this.label) {
2438
2456
  text = this.label.text;
2439
- ctx.fillStyle = this.label.color ?? ELEVATION_EDGE_COLOR;
2457
+ ctx.fillStyle = this.label.color ?? MAP_ELEVATION_EDGE_COLOR;
2440
2458
  ctx.rotate((this.label.rotate ?? 0) * Math.PI / 180);
2441
2459
  } else {
2442
2460
  if (this.y === 0) text = String.fromCharCode("A".charCodeAt(0) + this.x);
@@ -2503,10 +2521,10 @@ var HCMap = class {
2503
2521
  }
2504
2522
  tryAddEdge(t0, t1, edgeType) {
2505
2523
  if (this.type === "indoorOutdoor" && t0.type === "indoor" && (t1 == null || t1.type === "outdoor")) {
2506
- t0.addEdge(edgeType, INDOOR_EDGE_COLOR, false);
2524
+ t0.addEdge(edgeType, MAP_INDOOR_EDGE_COLOR, false);
2507
2525
  }
2508
2526
  if (typeof t0.elevation === "number" && t0.elevation > 1 && (t1 == null || t0.elevation !== t1.elevation)) {
2509
- t0.addEdge(edgeType, ELEVATION_EDGE_COLOR, false);
2527
+ t0.addEdge(edgeType, MAP_ELEVATION_EDGE_COLOR, false);
2510
2528
  }
2511
2529
  if (t0.isStartingZone && (t1 == null || !t1.isStartingZone)) {
2512
2530
  t0.addEdge(edgeType, STARTING_ZONE_EDGE_COLOR, false);
@@ -2516,7 +2534,7 @@ var HCMap = class {
2516
2534
  }
2517
2535
  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
2536
  const dashed = t0.terrain === "window" || t0.terrain === "special2";
2519
- t0.addEdge(edgeType, TERRAIN_EDGE_COLORS[t0.terrain] ?? "#FFFFFF", dashed);
2537
+ t0.addEdge(edgeType, MAP_TERRAIN_EDGE_COLORS[t0.terrain] ?? "#FFFFFF", dashed);
2520
2538
  }
2521
2539
  }
2522
2540
  draw(ctx) {
@@ -2531,7 +2549,7 @@ var HCMap = class {
2531
2549
  ctx.lineWidth = 1;
2532
2550
  for (let y = 0; y < this.height; y++) {
2533
2551
  for (let x = 0; x < this.width; x++) {
2534
- ctx.strokeRect(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
2552
+ ctx.strokeRect(x * MAP_TILE_SIZE, y * MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE);
2535
2553
  }
2536
2554
  }
2537
2555
  ctx.restore();
@@ -2542,12 +2560,12 @@ var HCMap = class {
2542
2560
  }
2543
2561
  for (const z of this.ziplines) {
2544
2562
  ctx.save();
2545
- ctx.strokeStyle = WALL_COLORS.normal;
2563
+ ctx.strokeStyle = MAP_WALL_COLORS.normal;
2546
2564
  ctx.lineCap = "round";
2547
2565
  ctx.lineWidth = 4;
2548
2566
  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);
2567
+ ctx.moveTo(z.x0 * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, z.y0 * MAP_TILE_SIZE + MAP_TILE_SIZE / 2);
2568
+ ctx.lineTo(z.x1 * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, z.y1 * MAP_TILE_SIZE + MAP_TILE_SIZE / 2);
2551
2569
  ctx.stroke();
2552
2570
  ctx.restore();
2553
2571
  }
@@ -2556,15 +2574,15 @@ var HCMap = class {
2556
2574
  const type = wall.type ?? "normal";
2557
2575
  ctx.lineWidth = WALL_SIZE;
2558
2576
  if (type === "levelSeparator") {
2559
- ctx.strokeStyle = WALL_COLORS.normal;
2577
+ ctx.strokeStyle = MAP_WALL_COLORS.normal;
2560
2578
  ctx.lineWidth = WALL_SIZE * 2;
2561
2579
  ctx.beginPath();
2562
- ctx.moveTo(wall.x0 * TILE_SIZE, wall.y0 * TILE_SIZE);
2563
- ctx.lineTo(wall.x1 * TILE_SIZE, wall.y1 * TILE_SIZE);
2580
+ ctx.moveTo(wall.x0 * MAP_TILE_SIZE, wall.y0 * MAP_TILE_SIZE);
2581
+ ctx.lineTo(wall.x1 * MAP_TILE_SIZE, wall.y1 * MAP_TILE_SIZE);
2564
2582
  ctx.stroke();
2565
2583
  ctx.lineWidth = WALL_SIZE;
2566
2584
  }
2567
- ctx.strokeStyle = WALL_COLORS[type] ?? WALL_COLORS.normal;
2585
+ ctx.strokeStyle = MAP_WALL_COLORS[type] ?? MAP_WALL_COLORS.normal;
2568
2586
  if (DASHED_WALLS.has(type)) {
2569
2587
  ctx.setLineDash([WALL_SIZE, WALL_SIZE]);
2570
2588
  ctx.lineDashOffset = WALL_SIZE / 2;
@@ -2572,8 +2590,8 @@ var HCMap = class {
2572
2590
  ctx.lineCap = "round";
2573
2591
  }
2574
2592
  ctx.beginPath();
2575
- ctx.moveTo(wall.x0 * TILE_SIZE, wall.y0 * TILE_SIZE);
2576
- ctx.lineTo(wall.x1 * TILE_SIZE, wall.y1 * TILE_SIZE);
2593
+ ctx.moveTo(wall.x0 * MAP_TILE_SIZE, wall.y0 * MAP_TILE_SIZE);
2594
+ ctx.lineTo(wall.x1 * MAP_TILE_SIZE, wall.y1 * MAP_TILE_SIZE);
2577
2595
  ctx.stroke();
2578
2596
  }
2579
2597
  };
@@ -2590,14 +2608,14 @@ function mapSquare(map, x, y) {
2590
2608
  label: tile.label?.text
2591
2609
  };
2592
2610
  }
2593
- function elevationLevel(elevation) {
2611
+ function mapElevationLevel(elevation) {
2594
2612
  const value = typeof elevation === "number" ? elevation : Number.parseInt(elevation, 10);
2595
2613
  return Number.isFinite(value) ? Math.max(1, value) : 2;
2596
2614
  }
2597
2615
  function mapMaxLevel(map) {
2598
2616
  let level = 1;
2599
2617
  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));
2618
+ for (let x = 0; x < map.width; x++) level = Math.max(level, mapElevationLevel(mapSquare(map, x, y).elevation));
2601
2619
  }
2602
2620
  return level;
2603
2621
  }
@@ -2628,7 +2646,7 @@ function inspectMap(map, x, y, tolerance = 0.16) {
2628
2646
  }
2629
2647
  return { square };
2630
2648
  }
2631
- function squareCoordinate(square) {
2649
+ function mapSquareCoordinate(square) {
2632
2650
  let index = square.x + 1, column = "";
2633
2651
  while (index > 0) {
2634
2652
  index--;
@@ -2637,13 +2655,13 @@ function squareCoordinate(square) {
2637
2655
  }
2638
2656
  return `${column}${square.y + 1}`;
2639
2657
  }
2640
- var LEVEL_HEIGHT = 0.62;
2641
- var BASE_Z = -0.34;
2658
+ var MAP_SCENE_LEVEL_HEIGHT = 0.62;
2659
+ var MAP_SCENE_BASE_Z = -0.34;
2642
2660
  var WATER_DROP = 0.1;
2643
2661
  var TERRAIN_VOLUME = { obscuring: 0.42, window: 0.42 };
2644
2662
  var WALL_HEIGHT = { levelSeparator: 0.12, door: 0.62, door2: 0.62 };
2645
2663
  var DEFAULT_WALL_HEIGHT = 0.62;
2646
- function sceneCell(scene, x, y) {
2664
+ function mapSceneCell(scene, x, y) {
2647
2665
  if (x < 0 || y < 0 || x >= scene.width || y >= scene.height) return null;
2648
2666
  return scene.cells[y * scene.width + x];
2649
2667
  }
@@ -2654,9 +2672,9 @@ function buildMapScene(map) {
2654
2672
  for (let y = 0; y < height; y++) {
2655
2673
  for (let x = 0; x < width; x++) {
2656
2674
  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;
2675
+ const level = mapElevationLevel(square.elevation);
2676
+ const floor = (level - 1) * MAP_SCENE_LEVEL_HEIGHT - (square.terrain === "water" ? WATER_DROP : 0);
2677
+ 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
2678
  cells.push({ ...square, level, floor, top });
2661
2679
  }
2662
2680
  }
@@ -2671,7 +2689,7 @@ function buildMapScene(map) {
2671
2689
  const x1 = wall.x0 + (wall.x1 - wall.x0) * (i + 1) / pieces, y1 = wall.y0 + (wall.y1 - wall.y0) * (i + 1) / pieces;
2672
2690
  const mx = (x0 + x1) / 2, my = (y0 + y1) / 2;
2673
2691
  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);
2692
+ 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
2693
  const floors = sides.length ? sides.map((cell) => cell.floor) : [0];
2676
2694
  const z1 = Math.max(...floors) + (WALL_HEIGHT[type] ?? DEFAULT_WALL_HEIGHT);
2677
2695
  walls.push({ x0, y0, x1, y1, type, z0: Math.min(...floors), z1 });
@@ -2679,7 +2697,7 @@ function buildMapScene(map) {
2679
2697
  }
2680
2698
  const ramps = [];
2681
2699
  for (const ramp of map.ramps ?? []) {
2682
- const a = sceneCell(scene, ramp.x0, ramp.y0), b = sceneCell(scene, ramp.x1, ramp.y1);
2700
+ const a = mapSceneCell(scene, ramp.x0, ramp.y0), b = mapSceneCell(scene, ramp.x1, ramp.y1);
2683
2701
  if (!a || !b || Math.abs(a.x - b.x) + Math.abs(a.y - b.y) !== 1 || a.floor === b.floor) continue;
2684
2702
  const [low, high] = a.floor < b.floor ? [a, b] : [b, a];
2685
2703
  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 +2707,21 @@ function buildMapScene(map) {
2689
2707
  y0: line.y0 + 0.5,
2690
2708
  x1: line.x1 + 0.5,
2691
2709
  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
2710
+ z: Math.max(mapSceneCell(scene, line.x0, line.y0)?.top ?? 0, mapSceneCell(scene, line.x1, line.y1)?.top ?? 0) + 0.7
2693
2711
  }));
2694
2712
  const maxTop = Math.max(...cells.map((cell) => cell.top), ...walls.map((wall) => wall.z1), ...ziplines.map((line) => line.z));
2695
2713
  return { width, height, cells, walls, ramps, ziplines, maxTop };
2696
2714
  }
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) {
2715
+ var MAP_DEFAULT_CAMERA = { azimuth: -32, tilt: 52, zoom: 1, panX: 0, panY: 0 };
2716
+ var MAP_TILT_RANGE = [6, 90];
2717
+ var MAP_ZOOM_RANGE = [1, 6];
2718
+ var clampMapValue = (value, min, max) => Math.min(max, Math.max(min, value));
2719
+ function makeMapProjection(scene, camera, viewport) {
2702
2720
  const rad = camera.azimuth * Math.PI / 180, tilt = camera.tilt * Math.PI / 180;
2703
2721
  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;
2722
+ const cx2 = scene.width / 2, cy = scene.height / 2, midZ = (scene.maxTop + MAP_SCENE_BASE_Z) / 2;
2705
2723
  const halfWidth = Math.hypot(cx2, cy);
2706
- const halfHeight = Math.hypot(halfWidth, (scene.maxTop - BASE_Z) / 2);
2724
+ const halfHeight = Math.hypot(halfWidth, (scene.maxTop - MAP_SCENE_BASE_Z) / 2);
2707
2725
  const fit = Math.min(viewport.width / (halfWidth * 2.06), viewport.height / (halfHeight * 2.06));
2708
2726
  const scale = fit * camera.zoom;
2709
2727
  const ox = viewport.width / 2 + camera.panX, oy = viewport.height / 2 + camera.panY;
@@ -2724,21 +2742,21 @@ function makeProjection(scene, camera, viewport) {
2724
2742
  }
2725
2743
  };
2726
2744
  }
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) };
2745
+ function clampMapPan(scene, camera, viewport) {
2746
+ const limit = Math.hypot(scene.width, scene.height) / 2 * makeMapProjection(scene, camera, viewport).scale;
2747
+ return { ...camera, panX: clampMapValue(camera.panX, -limit, limit), panY: clampMapValue(camera.panY, -limit, limit) };
2730
2748
  }
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]);
2749
+ function zoomMapCamera(scene, camera, viewport, factor, anchor = { x: 0, y: 0 }) {
2750
+ const zoom = clampMapValue(camera.zoom * factor, MAP_ZOOM_RANGE[0], MAP_ZOOM_RANGE[1]);
2733
2751
  const applied = zoom / camera.zoom;
2734
- return clampPan(scene, {
2752
+ return clampMapPan(scene, {
2735
2753
  ...camera,
2736
2754
  zoom,
2737
2755
  panX: anchor.x + (camera.panX - anchor.x) * applied,
2738
2756
  panY: anchor.y + (camera.panY - anchor.y) * applied
2739
2757
  }, viewport);
2740
2758
  }
2741
- var CELL_SIDES = [
2759
+ var MAP_CELL_SIDES = [
2742
2760
  { ax: 0, ay: 1, bx: 0, by: 0, dx: -1, dy: 0 },
2743
2761
  { ax: 1, ay: 0, bx: 1, by: 1, dx: 1, dy: 0 },
2744
2762
  { ax: 0, ay: 0, bx: 1, by: 0, dx: 0, dy: -1 },
@@ -2752,7 +2770,7 @@ var inside = (px, py, polygon2) => {
2752
2770
  }
2753
2771
  return hit;
2754
2772
  };
2755
- function pickScene(scene, view, px, py) {
2773
+ function pickMapScene(scene, view, px, py) {
2756
2774
  const items = [];
2757
2775
  for (const wall of scene.walls) {
2758
2776
  items.push({
@@ -2762,7 +2780,7 @@ function pickScene(scene, view, px, py) {
2762
2780
  const c = view.point(wall.x1, wall.y1, wall.z1), d = view.point(wall.x0, wall.y0, wall.z1);
2763
2781
  if (!inside(px, py, [a, b, c, d])) return null;
2764
2782
  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;
2783
+ const t = length2 ? clampMapValue(((px - a[0]) * (b[0] - a[0]) + (py - a[1]) * (b[1] - a[1])) / length2, 0, 1) : 0.5;
2766
2784
  return { x: wall.x0 + (wall.x1 - wall.x0) * t, y: wall.y0 + (wall.y1 - wall.y0) * t };
2767
2785
  }
2768
2786
  });
@@ -2778,12 +2796,12 @@ function pickScene(scene, view, px, py) {
2778
2796
  const det = ax * by - ay * bx;
2779
2797
  if (!det) return { x: cell.x + 0.5, y: cell.y + 0.5 };
2780
2798
  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) };
2799
+ return { x: cell.x + clampMapValue(u, 0, 1), y: cell.y + clampMapValue(v, 0, 1) };
2782
2800
  }
2783
- for (const side of CELL_SIDES) {
2801
+ for (const side of MAP_CELL_SIDES) {
2784
2802
  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;
2803
+ const neighbor = mapSceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2804
+ const low = neighbor ? neighbor.top : MAP_SCENE_BASE_Z;
2787
2805
  if (low >= cell.top) continue;
2788
2806
  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
2807
  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 +2820,7 @@ function pickScene(scene, view, px, py) {
2802
2820
  }
2803
2821
  return null;
2804
2822
  }
2805
- function footprintOutline({ x, y, width, height, cells }, boardWidth, boardHeight) {
2823
+ function mapFootprintOutline({ x, y, width, height, cells }, boardWidth, boardHeight) {
2806
2824
  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
2825
  const squares = [];
2808
2826
  const edges = [];
@@ -2857,27 +2875,27 @@ function face(ctx, points, color) {
2857
2875
  ctx.stroke();
2858
2876
  }
2859
2877
  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;
2878
+ if (cell.terrain === "blocking") return MAP_TERRAIN_EDGE_COLORS.blocking;
2879
+ if (cell.level > 1) return MAP_ELEVATION_TILE_COLORS[Math.min(cell.level, MAP_ELEVATION_TILE_COLORS.length) - 1];
2880
+ if (cell.terrain === "water") return MAP_TERRAIN_EDGE_COLORS.water;
2881
+ if (cell.terrain === "hindering") return MAP_TERRAIN_EDGE_COLORS.hindering;
2882
+ if (cell.terrain === "obscuring") return MAP_TERRAIN_EDGE_COLORS.obscuring;
2883
+ if (cell.terrain === "window") return MAP_TERRAIN_EDGE_COLORS.window;
2866
2884
  return SIDE_COLORS[cell.environment] ?? SIDE_COLORS.unknown;
2867
2885
  }
2868
2886
  function drawCellSides(ctx, scene, view, cell) {
2869
2887
  const { point } = view;
2870
- for (const side of CELL_SIDES) {
2888
+ for (const side of MAP_CELL_SIDES) {
2871
2889
  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;
2890
+ const neighbor = mapSceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2891
+ const low = neighbor ? neighbor.top : MAP_SCENE_BASE_Z;
2874
2892
  if (low >= cell.top) continue;
2875
2893
  const ax = cell.x + side.ax, ay = cell.y + side.ay, bx = cell.x + side.bx, by = cell.y + side.by;
2876
2894
  const light = faceLight(view, side.dx, side.dy);
2877
2895
  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
2896
  ctx.strokeStyle = "rgba(0,0,0,.26)";
2879
2897
  ctx.lineWidth = 1;
2880
- for (let z = 0; z < cell.top - 0.01; z += LEVEL_HEIGHT) {
2898
+ for (let z = 0; z < cell.top - 0.01; z += MAP_SCENE_LEVEL_HEIGHT) {
2881
2899
  if (z <= low + 0.01) continue;
2882
2900
  const [x0, y0] = point(ax, ay, z), [x1, y1] = point(bx, by, z);
2883
2901
  ctx.beginPath();
@@ -2891,13 +2909,13 @@ function drawCellTop(ctx, scene, view, cell, texture, shadows) {
2891
2909
  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
2910
  ctx.save();
2893
2911
  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);
2912
+ 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
2913
  if (cell.environment === "indoor") {
2896
2914
  ctx.fillStyle = (cell.x + cell.y) % 2 ? "rgba(52,62,92,.13)" : "rgba(52,62,92,.07)";
2897
2915
  ctx.fillRect(0, 0, 1, 1);
2898
2916
  }
2899
- CELL_SIDES.forEach((side, index) => {
2900
- const neighbor = sceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2917
+ MAP_CELL_SIDES.forEach((side, index) => {
2918
+ const neighbor = mapSceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2901
2919
  if (!neighbor || neighbor.top <= cell.top + 0.01) return;
2902
2920
  ctx.fillStyle = shadows[index];
2903
2921
  ctx.fillRect(0, 0, 1, 1);
@@ -2938,7 +2956,7 @@ function drawRamp(ctx, view, ramp) {
2938
2956
  const sx = ramp.dy * 0.2, sy = ramp.dx * 0.2, lx = -ramp.dx * 0.38, ly = -ramp.dy * 0.38;
2939
2957
  const a = [cx2 - sx, cy - sy], b = [cx2 + sx, cy + sy];
2940
2958
  const c = [cx2 + sx + lx, cy + sy + ly], d = [cx2 - sx + lx, cy - sy + ly];
2941
- const color = ELEVATION_TILE_COLORS[1];
2959
+ const color = MAP_ELEVATION_TILE_COLORS[1];
2942
2960
  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
2961
  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
2962
  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 +2976,7 @@ function drawWall(ctx, view, wall) {
2958
2976
  const x0 = Math.min(wall.x0, wall.x1) - ox, x1 = Math.max(wall.x0, wall.x1) + ox;
2959
2977
  const y0 = Math.min(wall.y0, wall.y1) - oy, y1 = Math.max(wall.y0, wall.y1) + oy;
2960
2978
  const alpha = TRANSLUCENT_WALLS[wall.type];
2961
- const color = GLASS_COLORS[wall.type] ?? (wall.type === "normal" ? "#30343c" : WALL_COLORS[wall.type] ?? "#30343c");
2979
+ const color = GLASS_COLORS[wall.type] ?? (wall.type === "normal" ? "#30343c" : MAP_WALL_COLORS[wall.type] ?? "#30343c");
2962
2980
  ctx.save();
2963
2981
  if (alpha) ctx.globalAlpha = alpha;
2964
2982
  if (wall.type === "door" || wall.type === "door2") {
@@ -2974,10 +2992,10 @@ function drawWall(ctx, view, wall) {
2974
2992
  ctx.restore();
2975
2993
  }
2976
2994
  function drawIndoorCurb(ctx, scene, view, cell) {
2977
- ctx.strokeStyle = INDOOR_EDGE_COLOR;
2995
+ ctx.strokeStyle = MAP_INDOOR_EDGE_COLOR;
2978
2996
  ctx.lineWidth = 2;
2979
- for (const side of CELL_SIDES) {
2980
- const neighbor = sceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2997
+ for (const side of MAP_CELL_SIDES) {
2998
+ const neighbor = mapSceneCell(scene, cell.x + side.dx, cell.y + side.dy);
2981
2999
  if (neighbor?.environment !== "outdoor") continue;
2982
3000
  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
3001
  ctx.beginPath();
@@ -2987,7 +3005,7 @@ function drawIndoorCurb(ctx, scene, view, cell) {
2987
3005
  }
2988
3006
  }
2989
3007
  function drawFootprint(ctx, scene, view, footprint) {
2990
- const { squares, edges, corners } = footprintOutline(footprint, scene.width, scene.height);
3008
+ const { squares, edges, corners } = mapFootprintOutline(footprint, scene.width, scene.height);
2991
3009
  if (!squares.length) return;
2992
3010
  const { top, valid } = footprint;
2993
3011
  const color = valid ? MOVE_VALID_COLOR : MOVE_INVALID_COLOR;
@@ -3034,7 +3052,7 @@ function drawHighlight(ctx, scene, view, highlight) {
3034
3052
  if (highlight.line) {
3035
3053
  const { x0, y0, x1, y1 } = highlight.line;
3036
3054
  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);
3055
+ 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
3056
  const z = Math.max(...near);
3039
3057
  const [ax, ay] = view.point(x0, y0, z), [bx, by] = view.point(x1, y1, z);
3040
3058
  ctx.strokeStyle = "rgba(0,0,0,.6)";
@@ -3047,7 +3065,7 @@ function drawHighlight(ctx, scene, view, highlight) {
3047
3065
  ctx.lineCap = "butt";
3048
3066
  return;
3049
3067
  }
3050
- const cell = highlight.square && sceneCell(scene, highlight.square.x, highlight.square.y);
3068
+ const cell = highlight.square && mapSceneCell(scene, highlight.square.x, highlight.square.y);
3051
3069
  if (!cell) return;
3052
3070
  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
3071
  ctx.fillStyle = "rgba(0,0,0,.16)";
@@ -3058,7 +3076,7 @@ function drawHighlight(ctx, scene, view, highlight) {
3058
3076
  }
3059
3077
  function drawMapScene(ctx, scene, view, texture, highlight, { tufts = true } = {}) {
3060
3078
  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)]);
3079
+ 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
3080
  ctx.fillStyle = "rgba(0,0,0,.14)";
3063
3081
  ctx.fill();
3064
3082
  const shadowDepth = 0.24;
@@ -3107,8 +3125,8 @@ var MAP_THUMBNAIL_HEIGHT = 192;
3107
3125
  function renderMapThumbnail(json, height = MAP_THUMBNAIL_HEIGHT) {
3108
3126
  if (!json?.width || !json?.height) return null;
3109
3127
  const full = document.createElement("canvas");
3110
- full.width = json.width * TILE_SIZE;
3111
- full.height = json.height * TILE_SIZE;
3128
+ full.width = json.width * MAP_TILE_SIZE;
3129
+ full.height = json.height * MAP_TILE_SIZE;
3112
3130
  const fctx = full.getContext("2d");
3113
3131
  if (!fctx) return null;
3114
3132
  new HCMap(json).draw(fctx);
@@ -3157,7 +3175,7 @@ var MapBoardView = forwardRef(function MapBoardView2({ map, canvasLabel, selecti
3157
3175
  if (event.pointerType !== "touch") onLeave?.();
3158
3176
  },
3159
3177
  children: [
3160
- /* @__PURE__ */ jsx("canvas", { ref: canvasRef, width: map.width * TILE_SIZE, height: map.height * TILE_SIZE, role: "img", "aria-label": canvasLabel }),
3178
+ /* @__PURE__ */ jsx("canvas", { ref: canvasRef, width: map.width * MAP_TILE_SIZE, height: map.height * MAP_TILE_SIZE, role: "img", "aria-label": canvasLabel }),
3161
3179
  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
3180
  ]
3163
3181
  }
@@ -3226,31 +3244,33 @@ function MapEnvironmentView({ types, icons, labels, className }) {
3226
3244
  }
3227
3245
  export {
3228
3246
  AvatarView,
3229
- BACK_TABLE_HEIGHT,
3230
- BASE_Z,
3231
- BYSTANDER_DIAL_STEP,
3232
3247
  Button,
3233
- CARD_HEIGHT,
3234
- CARD_WIDTH,
3235
- CELL_SIDES,
3236
3248
  COMBAT_DIAL_STATS,
3237
3249
  Checkbox,
3238
3250
  Chip,
3239
3251
  CombatDialView,
3240
3252
  CommandPalette,
3241
- DEFAULT_CAMERA,
3242
- Dialog,
3243
- ELEVATION_EDGE_COLOR,
3244
- ELEVATION_TILE_COLORS,
3253
+ Dialog2 as Dialog,
3245
3254
  EquipmentIcon,
3246
3255
  Field,
3247
3256
  FilterBar,
3248
3257
  HCMap,
3249
- INDOOR_EDGE_COLOR,
3250
3258
  IconButton,
3251
- LEVEL_HEIGHT,
3252
3259
  ListRow,
3260
+ MAP_CELL_SIDES,
3261
+ MAP_DEFAULT_CAMERA,
3262
+ MAP_ELEVATION_EDGE_COLOR,
3263
+ MAP_ELEVATION_TILE_COLORS,
3264
+ MAP_INDOOR_EDGE_COLOR,
3265
+ MAP_SCENE_BASE_Z,
3266
+ MAP_SCENE_LEVEL_HEIGHT,
3267
+ MAP_TERRAIN_EDGE_COLORS,
3268
+ MAP_TERRAIN_TILE_COLORS,
3253
3269
  MAP_THUMBNAIL_HEIGHT,
3270
+ MAP_TILE_SIZE,
3271
+ MAP_TILT_RANGE,
3272
+ MAP_WALL_COLORS,
3273
+ MAP_ZOOM_RANGE,
3254
3274
  MINI_DIAL_STATS,
3255
3275
  MapBoardPlaceholder,
3256
3276
  MapBoardView,
@@ -3267,7 +3287,11 @@ export {
3267
3287
  MenuSeparator,
3268
3288
  Meter,
3269
3289
  MiniDialView,
3290
+ PHYSICAL_CARD_BACK_TABLE_HEIGHT,
3291
+ PHYSICAL_CARD_BYSTANDER_DIAL_STEP,
3292
+ PHYSICAL_CARD_HEIGHT,
3270
3293
  PHYSICAL_CARD_STATS,
3294
+ PHYSICAL_CARD_WIDTH,
3271
3295
  PageHeader,
3272
3296
  PanelHeader,
3273
3297
  PhysicalCardFocusView,
@@ -3285,35 +3309,30 @@ export {
3285
3309
  StatGlyphView,
3286
3310
  StatIcon,
3287
3311
  Surface,
3288
- TERRAIN_EDGE_COLORS,
3289
- TERRAIN_TILE_COLORS,
3290
- TILE_SIZE,
3291
- TILT_RANGE,
3292
3312
  Table,
3293
- WALL_COLORS,
3294
- ZOOM_RANGE,
3295
- backCount,
3296
3313
  buildMapScene,
3297
- clamp,
3298
- clampPan,
3299
- devicePosition,
3314
+ clampMapPan,
3315
+ clampMapValue,
3300
3316
  drawMapScene,
3301
- elevationLevel,
3302
- footprintOutline,
3303
3317
  inspectMap,
3304
- makeProjection,
3318
+ makeMapProjection,
3319
+ mapElevationLevel,
3305
3320
  mapEnvironments,
3321
+ mapFootprintOutline,
3306
3322
  mapMaxLevel,
3323
+ mapSceneCell,
3307
3324
  mapSquare,
3308
- nextDistribution,
3309
- pickScene,
3325
+ mapSquareCoordinate,
3326
+ nextPhysicalCardDistribution,
3327
+ physicalCardBackCount,
3328
+ physicalCardDevicePosition,
3329
+ physicalCardTiltAt,
3330
+ physicalCardTiltStyles,
3331
+ pickMapScene,
3310
3332
  placePopup,
3333
+ portalContainerFor,
3311
3334
  renderMapThumbnail,
3312
- requestMotionAccess,
3313
- sceneCell,
3314
- squareCoordinate,
3315
- tiltAt,
3316
- tiltStyles,
3335
+ requestPhysicalCardMotionAccess,
3317
3336
  useImageChain,
3318
- zoomCamera
3337
+ zoomMapCamera
3319
3338
  };