@crockery/fellowship-components 0.4.1 → 1.1.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.
Files changed (64) hide show
  1. package/README.md +38 -22
  2. package/RELEASING.md +2 -2
  3. package/THIRD_PARTY_LICENSES.md +12 -0
  4. package/dist/assets/dm-mono-latin-400-normal-4GdczIuU.woff2 +0 -0
  5. package/dist/assets/dm-mono-latin-500-normal-DRMDZjhP.woff2 +0 -0
  6. package/dist/assets/syne-latin-700-normal-AF3Rs61n.woff2 +0 -0
  7. package/dist/assets/syne-latin-800-normal-EehdNYzx.woff2 +0 -0
  8. package/dist/chunks/decorate-DyMgX_Uh.js +9 -0
  9. package/dist/chunks/{dungeon-cast-browser-CSnu3gC5.js → dungeon-cast-browser-DdG8klca.js} +62 -58
  10. package/dist/chunks/{dungeon-map-CutIcCVP.js → dungeon-map-D0-DAjZ9.js} +130 -131
  11. package/dist/chunks/{decorate-B_ZTN9li.js → field-manual-fonts-DTFloVFe.js} +18 -23
  12. package/dist/chunks/gear-planner-uQOpm4QI.js +1701 -0
  13. package/dist/chunks/{talent-calculator-Dxuc2dZ8.js → talent-calculator-DbU6P1AP.js} +36 -35
  14. package/dist/chunks/tooltip-C3SSJw-t.js +482 -0
  15. package/dist/data/cast-data-source.d.ts +1 -1
  16. package/dist/data/data-source.d.ts +1 -1
  17. package/dist/data/package-cast-data-source.d.ts +1 -5
  18. package/dist/data/package-data-source.d.ts +1 -5
  19. package/dist/data/package-talent-data-source.d.ts +1 -5
  20. package/dist/data/talent-data-source.d.ts +1 -1
  21. package/dist/dungeon-cast-browser/dungeon-cast-browser.d.ts +2 -1
  22. package/dist/dungeon-cast-browser/render-model.d.ts +3 -2
  23. package/dist/dungeon-cast-browser/types.d.ts +2 -2
  24. package/dist/dungeon-cast-browser.js +1 -1
  25. package/dist/dungeon-map/dungeon-map.d.ts +2 -1
  26. package/dist/dungeon-map/render-model.d.ts +3 -3
  27. package/dist/dungeon-map/types.d.ts +2 -2
  28. package/dist/dungeon-map.js +1 -1
  29. package/dist/gear-planner/gear-planner.d.ts +36 -0
  30. package/dist/gear-planner/gear-planner.styles.d.ts +1 -0
  31. package/dist/gear-planner/gear-position.d.ts +20 -0
  32. package/dist/gear-planner/index.d.ts +2 -0
  33. package/dist/gear-planner/item-workbench.d.ts +18 -0
  34. package/dist/gear-planner/item-workbench.styles.d.ts +1 -0
  35. package/dist/gear-planner/types.d.ts +24 -0
  36. package/dist/gear-planner.js +5 -0
  37. package/dist/index.d.ts +6 -5
  38. package/dist/index.js +9 -7
  39. package/dist/react/dungeon-cast-browser.d.ts +8 -3
  40. package/dist/react/dungeon-cast-browser.js +11 -4
  41. package/dist/react/dungeon-map.d.ts +3 -1
  42. package/dist/react/dungeon-map.js +1 -1
  43. package/dist/react/gear-planner.d.ts +14 -0
  44. package/dist/react/gear-planner.js +23 -0
  45. package/dist/react/index.d.ts +2 -0
  46. package/dist/react/talent-calculator.d.ts +3 -1
  47. package/dist/react/talent-calculator.js +1 -1
  48. package/dist/react/tooltip.js +1 -1
  49. package/dist/react.js +2 -1
  50. package/dist/styles/dungeon-poster-fonts.d.ts +2 -0
  51. package/dist/styles/dungeon-poster.styles.d.ts +7 -0
  52. package/dist/talent-calculator/render-model.d.ts +3 -2
  53. package/dist/talent-calculator/talent-calculator.d.ts +2 -1
  54. package/dist/talent-calculator/types.d.ts +2 -2
  55. package/dist/talent-calculator.js +1 -1
  56. package/dist/tooltip.js +3 -3
  57. package/package.json +15 -4
  58. package/src/dungeon-cast-browser/README.md +10 -4
  59. package/src/dungeon-map/README.md +5 -6
  60. package/src/gear-planner/README.md +44 -0
  61. package/src/talent-calculator/README.md +5 -6
  62. package/src/tooltip/README.md +5 -6
  63. package/dist/chunks/data-source-XbksqUrw.js +0 -7
  64. package/dist/chunks/tooltip-DoQVSnOn.js +0 -410
@@ -1,5 +1,5 @@
1
- import { n as e, t } from "./data-source-XbksqUrw.js";
2
- import { n, r, t as i } from "./decorate-B_ZTN9li.js";
1
+ import { i as e, n as t, r as n, t as r } from "./field-manual-fonts-DTFloVFe.js";
2
+ import { t as i } from "./decorate-DyMgX_Uh.js";
3
3
  import { createPackageFellowshipDataClient as a } from "@crockery/fellowship-data/client";
4
4
  import { LitElement as o, css as s, html as c, nothing as l } from "lit";
5
5
  import { customElement as u, property as d, query as f, state as p } from "lit/decorators.js";
@@ -7,12 +7,9 @@ import { repeat as m } from "lit/directives/repeat.js";
7
7
  import { styleMap as h } from "lit/directives/style-map.js";
8
8
  import { findImage as g } from "@crockery/fellowship-data";
9
9
  //#region src/data/package-data-source.ts
10
- var _ = (e = {}) => {
11
- let t = a(e);
12
- return {
13
- loadDungeon: (e, n) => t.loadDungeon(e, n),
14
- resolveAssetUrl: (e) => t.resolveAssetUrl(e)
15
- };
10
+ var _ = () => {
11
+ let e = a();
12
+ return { loadDungeon: (t, n) => e.loadDungeon(t, n) };
16
13
  }, v = s`
17
14
  :host {
18
15
  --fellowship-map-soot: var(--_fellowship-field-canvas);
@@ -516,7 +513,7 @@ var _ = (e = {}) => {
516
513
  size: "200"
517
514
  }) : null, l = null;
518
515
  if (c) try {
519
- l = n.resolveAssetUrl(c);
516
+ l = n(c);
520
517
  } catch (e) {
521
518
  r.push({
522
519
  code: "asset-url-error",
@@ -599,12 +596,12 @@ var _ = (e = {}) => {
599
596
  composed: !0
600
597
  }, F = class extends o {
601
598
  constructor(...e) {
602
- super(...e), this.dungeonId = "", this.mapImageId = null, this.assetBaseUrl = null, this.dataSource = null, this.renderEnemy = null, this.renderGroup = null, this.mapLabelFormatter = null, this.showControls = !0, this.showMapSelector = !0, this.maxZoom = 8, this.externalOverlay = !1, this._status = "empty", this._error = null, this._data = null, this._model = null, this._selectedMap = null, this._viewportState = {
599
+ super(...e), this.dungeonId = "", this.mapImageId = null, this.resolveAssetUrl = null, this.dataSource = null, this.renderEnemy = null, this.renderGroup = null, this.mapLabelFormatter = null, this.showControls = !0, this.showMapSelector = !0, this.maxZoom = 8, this.externalOverlay = !1, this._status = "empty", this._error = null, this._data = null, this._model = null, this._selectedMap = null, this._viewportState = {
603
600
  zoom: 1,
604
601
  scale: 1,
605
602
  x: 0,
606
603
  y: 0
607
- }, this._isPanning = !1, this._enemyRenderContent = /* @__PURE__ */ new Map(), this._groupRenderContent = /* @__PURE__ */ new Map(), this._mapLabels = /* @__PURE__ */ new Map(), this.#e = null, this.#t = null, this.#n = 0, this.#r = 0, this.#i = null, this.#a = new N(), this.#o = /* @__PURE__ */ new Map(), this.#s = null, this.#c = 0, this.#l = null, this.#u = /* @__PURE__ */ new Set(), this.#d = [], this.#j = (e) => {
604
+ }, this._isPanning = !1, this._enemyRenderContent = /* @__PURE__ */ new Map(), this._groupRenderContent = /* @__PURE__ */ new Map(), this._mapLabels = /* @__PURE__ */ new Map(), this.#e = null, this.#t = 0, this.#n = 0, this.#r = null, this.#i = new N(), this.#a = /* @__PURE__ */ new Map(), this.#o = null, this.#s = 0, this.#c = null, this.#l = /* @__PURE__ */ new Set(), this.#u = [], this.#A = (e) => {
608
605
  if (![
609
606
  "ArrowLeft",
610
607
  "ArrowRight",
@@ -612,30 +609,30 @@ var _ = (e = {}) => {
612
609
  "End"
613
610
  ].includes(e.key)) return;
614
611
  let t = this._data?.dungeon.mapImages ?? [], n = t.findIndex(({ id: e }) => e === this._selectedMap?.id), r = e.key === "Home" ? 0 : e.key === "End" ? t.length - 1 : e.key === "ArrowRight" ? (n + 1) % t.length : (n - 1 + t.length) % t.length, i = t[r];
615
- i && (e.preventDefault(), this.#A(i), this.updateComplete.then(() => {
612
+ i && (e.preventDefault(), this.#k(i), this.updateComplete.then(() => {
616
613
  this.renderRoot.querySelector(`[data-map-index="${r}"]`)?.focus();
617
614
  }));
618
- }, this.#M = (e) => {
615
+ }, this.#j = (e) => {
619
616
  if (!this._model || this._status !== "ready") return;
620
617
  e.preventDefault();
621
618
  let t = this._viewportElement?.getBoundingClientRect();
622
619
  if (!t) return;
623
620
  let n = Math.exp(-e.deltaY * .0015);
624
- this.#a.zoomAt(n, e.clientX - t.left, e.clientY - t.top), this.#z("wheel");
625
- }, this.#N = (e) => {
621
+ this.#i.zoomAt(n, e.clientX - t.left, e.clientY - t.top), this.#R("wheel");
622
+ }, this.#M = (e) => {
626
623
  if (!(e.target !== this._viewportElement || !this._model)) {
627
- if (e.key === "+" || e.key === "=") e.preventDefault(), this.#a.zoomAt(1.35);
628
- else if (e.key === "-") e.preventDefault(), this.#a.zoomAt(1 / 1.35);
629
- else if (e.key === "0") e.preventDefault(), this.#a.fit();
630
- else if (e.key === "ArrowLeft") e.preventDefault(), this.#a.panBy(56, 0);
631
- else if (e.key === "ArrowRight") e.preventDefault(), this.#a.panBy(-56, 0);
632
- else if (e.key === "ArrowUp") e.preventDefault(), this.#a.panBy(0, 56);
633
- else if (e.key === "ArrowDown") e.preventDefault(), this.#a.panBy(0, -56);
624
+ if (e.key === "+" || e.key === "=") e.preventDefault(), this.#i.zoomAt(1.35);
625
+ else if (e.key === "-") e.preventDefault(), this.#i.zoomAt(1 / 1.35);
626
+ else if (e.key === "0") e.preventDefault(), this.#i.fit();
627
+ else if (e.key === "ArrowLeft") e.preventDefault(), this.#i.panBy(56, 0);
628
+ else if (e.key === "ArrowRight") e.preventDefault(), this.#i.panBy(-56, 0);
629
+ else if (e.key === "ArrowUp") e.preventDefault(), this.#i.panBy(0, 56);
630
+ else if (e.key === "ArrowDown") e.preventDefault(), this.#i.panBy(0, -56);
634
631
  else return;
635
- this.#z("keyboard");
632
+ this.#R("keyboard");
636
633
  }
637
- }, this.#P = (e) => {
638
- if (!this._model || this.#L(e)) return;
634
+ }, this.#N = (e) => {
635
+ if (!this._model || this.#I(e)) return;
639
636
  let t = this._viewportElement, n = t?.getBoundingClientRect();
640
637
  if (!t || !n) return;
641
638
  t.setPointerCapture(e.pointerId);
@@ -643,41 +640,41 @@ var _ = (e = {}) => {
643
640
  x: e.clientX - n.left,
644
641
  y: e.clientY - n.top
645
642
  };
646
- if (this.#o.set(e.pointerId, r), this._isPanning = !0, this.#o.size === 1) this.#s = r;
647
- else if (this.#o.size === 2) {
648
- let [e, t] = [...this.#o.values()];
649
- e && t && (this.#c = Math.hypot(t.x - e.x, t.y - e.y), this.#l = {
643
+ if (this.#a.set(e.pointerId, r), this._isPanning = !0, this.#a.size === 1) this.#o = r;
644
+ else if (this.#a.size === 2) {
645
+ let [e, t] = [...this.#a.values()];
646
+ e && t && (this.#s = Math.hypot(t.x - e.x, t.y - e.y), this.#c = {
650
647
  x: (e.x + t.x) / 2,
651
648
  y: (e.y + t.y) / 2
652
649
  });
653
650
  }
654
- }, this.#F = (e) => {
655
- if (!this.#o.has(e.pointerId)) return;
651
+ }, this.#P = (e) => {
652
+ if (!this.#a.has(e.pointerId)) return;
656
653
  let t = this._viewportElement?.getBoundingClientRect();
657
654
  if (!t) return;
658
655
  let n = {
659
656
  x: e.clientX - t.left,
660
657
  y: e.clientY - t.top
661
658
  };
662
- if (this.#o.set(e.pointerId, n), this.#o.size === 1 && this.#s) {
663
- this.#a.panBy(n.x - this.#s.x, n.y - this.#s.y), this.#s = n, this.#z("pan");
659
+ if (this.#a.set(e.pointerId, n), this.#a.size === 1 && this.#o) {
660
+ this.#i.panBy(n.x - this.#o.x, n.y - this.#o.y), this.#o = n, this.#R("pan");
664
661
  return;
665
662
  }
666
- if (this.#o.size === 2) {
667
- let [e, t] = [...this.#o.values()];
663
+ if (this.#a.size === 2) {
664
+ let [e, t] = [...this.#a.values()];
668
665
  if (!e || !t) return;
669
666
  let n = Math.hypot(t.x - e.x, t.y - e.y), r = {
670
667
  x: (e.x + t.x) / 2,
671
668
  y: (e.y + t.y) / 2
672
669
  };
673
- this.#c > 0 && this.#a.zoomAt(n / this.#c, r.x, r.y), this.#l && this.#a.panBy(r.x - this.#l.x, r.y - this.#l.y), this.#c = n, this.#l = r, this.#z("pinch");
670
+ this.#s > 0 && this.#i.zoomAt(n / this.#s, r.x, r.y), this.#c && this.#i.panBy(r.x - this.#c.x, r.y - this.#c.y), this.#s = n, this.#c = r, this.#R("pinch");
674
671
  }
675
- }, this.#I = (e) => {
676
- this.#o.delete(e.pointerId), this.#o.size === 1 ? this.#s = [...this.#o.values()][0] ?? null : this.#o.size === 0 && (this.#s = null, this.#l = null, this.#c = 0, this._isPanning = !1);
672
+ }, this.#F = (e) => {
673
+ this.#a.delete(e.pointerId), this.#a.size === 1 ? this.#o = [...this.#a.values()][0] ?? null : this.#a.size === 0 && (this.#o = null, this.#c = null, this.#s = 0, this._isPanning = !1);
677
674
  };
678
675
  }
679
676
  static {
680
- this.styles = [r, v];
677
+ this.styles = [t, v];
681
678
  }
682
679
  #e;
683
680
  #t;
@@ -690,56 +687,55 @@ var _ = (e = {}) => {
690
687
  #c;
691
688
  #l;
692
689
  #u;
693
- #d;
694
690
  connectedCallback() {
695
- super.connectedCallback(), n(this.ownerDocument), this.#i ??= new ResizeObserver(() => this.#R());
691
+ super.connectedCallback(), r(this.ownerDocument), this.#r ??= new ResizeObserver(() => this.#L());
696
692
  }
697
693
  disconnectedCallback() {
698
- this.#t?.abort(), this.#i?.disconnect(), super.disconnectedCallback();
694
+ this.#e?.abort(), this.#r?.disconnect(), super.disconnectedCallback();
699
695
  }
700
696
  firstUpdated(e) {
701
697
  super.firstUpdated(e);
702
698
  let t = this._viewportElement;
703
- t && this.#i?.observe(t);
699
+ t && this.#r?.observe(t);
704
700
  }
705
701
  updated(e) {
706
- if (super.updated(e), this.#V(), e.has("dungeonId") || e.has("dataSource") || e.has("assetBaseUrl")) {
702
+ if (super.updated(e), this.#B(), e.has("dungeonId") || e.has("dataSource") || e.has("resolveAssetUrl")) {
707
703
  queueMicrotask(() => {
708
- this.isConnected && this.#m();
704
+ this.isConnected && this.#p();
709
705
  });
710
706
  return;
711
707
  }
712
708
  e.has("mapImageId") && this._data && queueMicrotask(() => {
713
- this.isConnected && this.#h(!0);
714
- }), e.has("maxZoom") && e.get("maxZoom") !== void 0 && (this.#a.maxZoom = Math.max(1, this.maxZoom), this.#a.zoomAt(1), queueMicrotask(() => this.#z("button")));
709
+ this.isConnected && this.#m(!0);
710
+ }), e.has("maxZoom") && e.get("maxZoom") !== void 0 && (this.#i.maxZoom = Math.max(1, this.maxZoom), this.#i.zoomAt(1), queueMicrotask(() => this.#R("button")));
715
711
  }
716
712
  willUpdate(e) {
717
- super.willUpdate(e), (e.has("renderEnemy") || e.has("renderGroup") || e.has("mapLabelFormatter")) && this.#u.clear(), (e.has("_model") || e.has("renderEnemy") || e.has("renderGroup")) && this.#v(), (e.has("_data") || e.has("mapLabelFormatter")) && this.#y();
713
+ super.willUpdate(e), (e.has("renderEnemy") || e.has("renderGroup") || e.has("mapLabelFormatter")) && this.#l.clear(), (e.has("_model") || e.has("renderEnemy") || e.has("renderGroup")) && this.#_(), (e.has("_data") || e.has("mapLabelFormatter")) && this.#v();
718
714
  }
719
715
  fitToView() {
720
- this.#a.fit(), this.#z("fit");
716
+ this.#i.fit(), this.#R("fit");
721
717
  }
722
718
  zoomIn() {
723
- this.#a.zoomAt(1.35), this.#z("button");
719
+ this.#i.zoomAt(1.35), this.#R("button");
724
720
  }
725
721
  zoomOut() {
726
- this.#a.zoomAt(1 / 1.35), this.#z("button");
722
+ this.#i.zoomAt(1 / 1.35), this.#R("button");
727
723
  }
728
724
  retry() {
729
- this.#m();
725
+ this.#p();
730
726
  }
731
727
  get renderModel() {
732
728
  return this._model;
733
729
  }
734
730
  render() {
735
- let e = this._model, t = this._viewportState, n = this.#p, r = e ? {
731
+ let e = this._model, t = this._viewportState, n = this.#f, r = e ? {
736
732
  width: `${e.mapImage.width}px`,
737
733
  height: `${e.mapImage.height}px`,
738
734
  transform: `translate3d(${t.x}px, ${t.y}px, 0) scale(${t.scale})`,
739
735
  "--fellowship-map-inverse-scale": String(1 / t.scale)
740
736
  } : {};
741
737
  return c`
742
- <section class="viewer" aria-label=${this.#f}>
738
+ <section class="viewer" aria-label=${this.#d}>
743
739
  <div
744
740
  class="viewport"
745
741
  part="viewport"
@@ -748,12 +744,12 @@ var _ = (e = {}) => {
748
744
  tabindex="0"
749
745
  aria-describedby="map-instructions"
750
746
  data-panning=${String(this._isPanning)}
751
- @wheel=${this.#M}
752
- @keydown=${this.#N}
753
- @pointerdown=${this.#P}
754
- @pointermove=${this.#F}
755
- @pointerup=${this.#I}
756
- @pointercancel=${this.#I}
747
+ @wheel=${this.#j}
748
+ @keydown=${this.#M}
749
+ @pointerdown=${this.#N}
750
+ @pointermove=${this.#P}
751
+ @pointerup=${this.#F}
752
+ @pointercancel=${this.#F}
757
753
  >
758
754
  ${e ? c`
759
755
  <div
@@ -767,18 +763,18 @@ var _ = (e = {}) => {
767
763
  class="map-canvas"
768
764
  part="map-canvas"
769
765
  role="img"
770
- aria-label=${`${e.dungeon.name ?? e.dungeon.id}, ${this.#k(e.mapImage)}`}
766
+ aria-label=${`${e.dungeon.name ?? e.dungeon.id}, ${this.#O(e.mapImage)}`}
771
767
  .width=${e.mapImage.width}
772
768
  .height=${e.mapImage.height}
773
769
  ></canvas>
774
770
  <div class="overlay" part="overlay">
775
- ${this.externalOverlay ? c`<slot name="overlay"></slot>` : this.#b(e)}
771
+ ${this.externalOverlay ? c`<slot name="overlay"></slot>` : this.#y(e)}
776
772
  </div>
777
773
  </div>
778
- ${this.#E(e)} ${this.#D()}
774
+ ${this.#T(e)} ${this.#E()}
779
775
  ${e.groups.length === 0 && this._status === "ready" ? c`<div class="empty-badge">No enemy placements on this map</div>` : l}
780
776
  ` : l}
781
- ${this.#O()}
777
+ ${this.#D()}
782
778
  <p class="visually-hidden" id="map-instructions">
783
779
  Drag to pan. Use the mouse wheel, plus and minus keys, or zoom controls to zoom. Press
784
780
  zero to fit the full map.
@@ -787,49 +783,55 @@ var _ = (e = {}) => {
787
783
  </section>
788
784
  `;
789
785
  }
790
- get #f() {
786
+ get #d() {
791
787
  return this._data ? `${this._data.dungeon.name ?? this._data.dungeon.id} dungeon map` : "Fellowship dungeon map";
792
788
  }
793
- get #p() {
789
+ get #f() {
794
790
  if (!this.showMapSelector || !this._model || this._model.dungeon.mapImages.length <= 1 || !this._selectedMap) return l;
795
791
  let e = this._model.dungeon.mapImages.findIndex((e) => e.id === this._selectedMap?.id);
796
792
  return e >= 0 ? `map-tab-${e}` : l;
797
793
  }
798
- async #m() {
799
- let t = this.dungeonId.trim(), n = ++this.#n;
800
- if (this.#r += 1, this.#t?.abort(), this.#t = new AbortController(), this._data = null, this._model = null, this._selectedMap = null, this._error = null, this.#u.clear(), !t) {
794
+ async #p() {
795
+ let t = this.dungeonId.trim(), n = ++this.#t;
796
+ if (this.#n += 1, this.#e?.abort(), this.#e = new AbortController(), this._data = null, this._model = null, this._selectedMap = null, this._error = null, this.#l.clear(), !t) {
801
797
  this._status = "empty";
802
798
  return;
803
799
  }
800
+ if (!this.resolveAssetUrl) {
801
+ this.#g({
802
+ code: "asset-resolver-missing",
803
+ message: "A resolveAssetUrl callback is required to render Fellowship images."
804
+ });
805
+ return;
806
+ }
804
807
  this._status = "loading";
805
- let r = this.dataSource ?? _(this.assetBaseUrl ? { assetBaseUrl: this.assetBaseUrl } : {});
806
- this.#e = r;
808
+ let r = this.dataSource ?? _();
807
809
  try {
808
- let i = await r.loadDungeon(t, this.#t.signal);
809
- if (n !== this.#n || this.#t.signal.aborted) return;
810
- e(i.manifest.schemaVersion), this._data = i, await this.#h(!0);
810
+ let i = await r.loadDungeon(t, this.#e.signal);
811
+ if (n !== this.#t || this.#e.signal.aborted) return;
812
+ e(i.manifest.schemaVersion), this._data = i, await this.#m(!0);
811
813
  } catch (e) {
812
- if (n !== this.#n || this.#t.signal.aborted) return;
813
- this.#_(e);
814
+ if (n !== this.#t || this.#e.signal.aborted) return;
815
+ this.#g(e);
814
816
  }
815
817
  }
816
- async #h(e) {
817
- let t = this._data, n = this.#e;
818
+ async #m(e) {
819
+ let t = this._data, n = this.resolveAssetUrl;
818
820
  if (!t || !n) return;
819
821
  let r = this.mapImageId ? t.dungeon.mapImages.find(({ id: e }) => e === this.mapImageId) : t.dungeon.mapImages[0];
820
822
  if (!r) {
821
- this.#_({
823
+ this.#g({
822
824
  code: "map-not-found",
823
825
  message: this.mapImageId ? `No map image with ID “${this.mapImageId}” exists for this dungeon.` : "This dungeon does not include a map image."
824
826
  });
825
827
  return;
826
828
  }
827
- let i = ++this.#r, a = A(t, r, n);
829
+ let i = ++this.#n, a = A(t, r, n);
828
830
  this._model = a, this._selectedMap = r, this._status = "loading", this._error = null, await this.updateComplete;
829
831
  let o = this._viewportElement;
830
- o && (this.#a.maxZoom = Math.max(1, this.maxZoom), this.#a.setDimensions(o.clientWidth, o.clientHeight, r.width, r.height), e && this.#a.fit(), this._viewportState = this.#a.state, await this.updateComplete);
832
+ o && (this.#i.maxZoom = Math.max(1, this.maxZoom), this.#i.setDimensions(o.clientWidth, o.clientHeight, r.width, r.height), e && this.#i.fit(), this._viewportState = this.#i.state, await this.updateComplete);
831
833
  try {
832
- if (await this.#g(r, n, i), i !== this.#r) return;
834
+ if (await this.#h(r, n, i), i !== this.#n) return;
833
835
  this._status = "ready", this.dispatchEvent(new CustomEvent("fellowship-map-ready", {
834
836
  ...P,
835
837
  detail: {
@@ -844,35 +846,35 @@ var _ = (e = {}) => {
844
846
  }
845
847
  }));
846
848
  } catch (e) {
847
- i === this.#r && this.#_({
849
+ i === this.#n && this.#g({
848
850
  code: "map-image-error",
849
851
  message: `Unable to load the dungeon map image: ${String(e)}.`,
850
852
  cause: e
851
853
  });
852
854
  }
853
855
  }
854
- async #g(e, t, n) {
856
+ async #h(e, t, n) {
855
857
  let r = new Image();
856
- if (r.crossOrigin = "anonymous", r.src = t.resolveAssetUrl(e), await r.decode(), n !== this.#r) return;
858
+ if (r.crossOrigin = "anonymous", r.src = t(e), await r.decode(), n !== this.#n) return;
857
859
  let i = this._canvasElement, a = i?.getContext("2d");
858
860
  if (!i || !a) throw Error("A 2D canvas context is unavailable.");
859
861
  a.clearRect(0, 0, i.width, i.height), a.drawImage(r, 0, 0, e.width, e.height);
860
862
  }
861
- #_(e) {
862
- let n = typeof e == "object" && e && "code" in e && "message" in e ? {
863
+ #g(e) {
864
+ let t = typeof e == "object" && e && "code" in e && "message" in e ? {
863
865
  code: String(e.code),
864
866
  message: String(e.message),
865
- ...e instanceof t && e.cause !== void 0 ? { cause: e.cause } : {}
867
+ ...e instanceof n && e.cause !== void 0 ? { cause: e.cause } : {}
866
868
  } : {
867
869
  code: "unknown",
868
870
  message: e instanceof Error ? e.message : String(e)
869
871
  };
870
- this._error = n, this._status = "error", this.dispatchEvent(new CustomEvent("fellowship-map-error", {
872
+ this._error = t, this._status = "error", this.dispatchEvent(new CustomEvent("fellowship-map-error", {
871
873
  ...P,
872
- detail: n
874
+ detail: t
873
875
  }));
874
876
  }
875
- #v() {
877
+ #_() {
876
878
  let e = this._model, t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
877
879
  if (!e) {
878
880
  this._enemyRenderContent = t, this._groupRenderContent = n;
@@ -886,10 +888,10 @@ var _ = (e = {}) => {
886
888
  mapImage: e.mapImage
887
889
  }));
888
890
  } catch (e) {
889
- this.#B(`enemy:${r.instanceId}`, "enemy-renderer-error", e);
891
+ this.#z(`enemy:${r.instanceId}`, "enemy-renderer-error", e);
890
892
  }
891
893
  if (this._enemyRenderContent = t, this.renderGroup) for (let t of e.groups) {
892
- let r = t.enemies.map((e) => this.#w(t, e)), i = this.#x(e, t);
894
+ let r = t.enemies.map((e) => this.#C(t, e)), i = this.#b(e, t);
893
895
  try {
894
896
  n.set(i, this.renderGroup({
895
897
  group: t,
@@ -898,49 +900,49 @@ var _ = (e = {}) => {
898
900
  mapImage: e.mapImage
899
901
  }));
900
902
  } catch (e) {
901
- this.#B(`group:${i}`, "group-renderer-error", e);
903
+ this.#z(`group:${i}`, "group-renderer-error", e);
902
904
  }
903
905
  }
904
906
  this._groupRenderContent = n;
905
907
  }
906
- #y() {
908
+ #v() {
907
909
  let e = /* @__PURE__ */ new Map(), t = this._data?.dungeon;
908
910
  if (t) for (let n of t.mapImages) try {
909
911
  e.set(n.id, this.mapLabelFormatter?.(n, t) ?? j(n, t));
910
912
  } catch (r) {
911
- this.#B(`map-label:${n.id}`, "map-label-formatter-error", r), e.set(n.id, j(n, t));
913
+ this.#z(`map-label:${n.id}`, "map-label-formatter-error", r), e.set(n.id, j(n, t));
912
914
  }
913
915
  this._mapLabels = e;
914
916
  }
915
- #b(e) {
916
- return m(e.groups, (t) => this.#x(e, t), (t) => this.#S(e, t));
917
+ #y(e) {
918
+ return m(e.groups, (t) => this.#b(e, t), (t) => this.#x(e, t));
917
919
  }
918
- #x(e, t) {
920
+ #b(e, t) {
919
921
  return `${e.mapImage.id}:${String(t.id)}:${t.enemies[0]?.instanceId ?? "empty"}`;
920
922
  }
921
- #S(e, t) {
923
+ #x(e, t) {
922
924
  let n = t.visualBounds, r = {
923
925
  left: `${n.x * 100}%`,
924
926
  top: `${n.y * 100}%`,
925
927
  width: `${n.width * 100}%`,
926
928
  height: `${n.height * 100}%`
927
- }, i = this.#x(e, t), a = this.renderGroup && this._groupRenderContent.has(i) ? this._groupRenderContent.get(i) ?? l : this.#C(t);
929
+ }, i = this.#b(e, t), a = this.renderGroup && this._groupRenderContent.has(i) ? this._groupRenderContent.get(i) ?? l : this.#S(t);
928
930
  return c` <div class="group-anchor" part="group" style=${h(r)}>${a}</div> `;
929
931
  }
930
- #C(e) {
932
+ #S(e) {
931
933
  return c`
932
934
  <div class="default-group">
933
935
  <div class="group-ring" aria-hidden="true"></div>
934
936
  <span class="group-label">${`G${e.id ?? "–"}${e.dungeonScore === null ? "" : ` · ${e.dungeonScore}`}`}</span>
935
- ${m(e.enemies, (e) => e.instanceId, (t) => this.#w(e, t))}
937
+ ${m(e.enemies, (e) => e.instanceId, (t) => this.#C(e, t))}
936
938
  </div>
937
939
  `;
938
940
  }
939
- #w(e, t) {
941
+ #C(e, t) {
940
942
  let n = e.visualBounds, r = {
941
943
  left: `${(t.position.x - n.x) / n.width * 100}%`,
942
944
  top: `${(t.position.y - n.y) / n.height * 100}%`
943
- }, i = this.renderEnemy && this._enemyRenderContent.has(t.instanceId) ? this._enemyRenderContent.get(t.instanceId) ?? l : this.#T(t), a = t.enemy?.name ?? t.placement.id;
945
+ }, i = this.renderEnemy && this._enemyRenderContent.has(t.instanceId) ? this._enemyRenderContent.get(t.instanceId) ?? l : this.#w(t), a = t.enemy?.name ?? t.placement.id;
944
946
  return c`
945
947
  <div
946
948
  class="enemy-anchor"
@@ -954,7 +956,7 @@ var _ = (e = {}) => {
954
956
  </div>
955
957
  `;
956
958
  }
957
- #T(e) {
959
+ #w(e) {
958
960
  let t = (e.enemy?.name ?? e.placement.id).split(/\s+/).map((e) => e[0]).join("").slice(0, 2).toUpperCase();
959
961
  return c`
960
962
  <span class="enemy-marker" data-boss=${String(e.enemy?.isBoss === !0)}>
@@ -962,7 +964,7 @@ var _ = (e = {}) => {
962
964
  </span>
963
965
  `;
964
966
  }
965
- #E(e) {
967
+ #T(e) {
966
968
  let t = e.dungeon.mapImages;
967
969
  return !this.showMapSelector || t.length <= 1 ? l : c`
968
970
  <div class="map-selector" part="map-selector" role="tablist" aria-label="Dungeon maps">
@@ -977,16 +979,16 @@ var _ = (e = {}) => {
977
979
  aria-selected=${String(e.id === this._selectedMap?.id)}
978
980
  tabindex=${e.id === this._selectedMap?.id ? "0" : "-1"}
979
981
  data-map-index=${String(t)}
980
- @click=${() => this.#A(e)}
981
- @keydown=${this.#j}
982
+ @click=${() => this.#k(e)}
983
+ @keydown=${this.#A}
982
984
  >
983
- ${this.#k(e)}
985
+ ${this.#O(e)}
984
986
  </button>
985
987
  `)}
986
988
  </div>
987
989
  `;
988
990
  }
989
- #D() {
991
+ #E() {
990
992
  return !this.showControls || !this._model ? l : c`
991
993
  <div class="controls" part="controls" role="group" aria-label="Map zoom controls">
992
994
  <button
@@ -1022,7 +1024,7 @@ var _ = (e = {}) => {
1022
1024
  </div>
1023
1025
  `;
1024
1026
  }
1025
- #O() {
1027
+ #D() {
1026
1028
  if (this._status === "ready") return l;
1027
1029
  let e = this._status === "loading", t = this._status === "empty", n = e ? "Charting dungeon" : t ? "Choose a dungeon" : "Map unavailable", r = e ? "Loading Fellowship data and preparing the tactical layer." : t ? "Set the dungeon-id attribute or dungeonId property to render a map." : this._error?.message ?? "An unexpected map error occurred.";
1028
1030
  return c`
@@ -1036,10 +1038,10 @@ var _ = (e = {}) => {
1036
1038
  </div>
1037
1039
  `;
1038
1040
  }
1039
- #k(e) {
1041
+ #O(e) {
1040
1042
  return this._mapLabels.get(e.id) ?? "Map";
1041
1043
  }
1042
- #A(e) {
1044
+ #k(e) {
1043
1045
  e.id !== this._selectedMap?.id && (this.mapImageId = e.id, this.dispatchEvent(new CustomEvent("fellowship-map-image-change", {
1044
1046
  ...P,
1045
1047
  detail: {
@@ -1048,39 +1050,39 @@ var _ = (e = {}) => {
1048
1050
  }
1049
1051
  })));
1050
1052
  }
1053
+ #A;
1051
1054
  #j;
1052
1055
  #M;
1053
1056
  #N;
1054
1057
  #P;
1055
1058
  #F;
1056
- #I;
1057
- #L(e) {
1059
+ #I(e) {
1058
1060
  return e.composedPath().some((e) => e instanceof HTMLElement && e.matches("button, a, input, select, textarea, [contenteditable='true']"));
1059
1061
  }
1060
- #R() {
1062
+ #L() {
1061
1063
  let e = this._viewportElement, t = this._selectedMap;
1062
- !e || !t || (this.#a.setDimensions(e.clientWidth, e.clientHeight, t.width, t.height), this.#z("resize"));
1064
+ !e || !t || (this.#i.setDimensions(e.clientWidth, e.clientHeight, t.width, t.height), this.#R("resize"));
1063
1065
  }
1064
- #z(e) {
1065
- this._viewportState = this.#a.state, this.dispatchEvent(new CustomEvent("fellowship-map-viewport-change", {
1066
+ #R(e) {
1067
+ this._viewportState = this.#i.state, this.dispatchEvent(new CustomEvent("fellowship-map-viewport-change", {
1066
1068
  ...P,
1067
1069
  detail: {
1068
- viewport: this.#a.state,
1070
+ viewport: this.#i.state,
1069
1071
  source: e
1070
1072
  }
1071
1073
  }));
1072
1074
  }
1073
- #B(e, t, n) {
1074
- this.#u.has(e) || (this.#u.add(e), this.#d.push({
1075
+ #z(e, t, n) {
1076
+ this.#l.has(e) || (this.#l.add(e), this.#u.push({
1075
1077
  code: t,
1076
1078
  message: n instanceof Error ? n.message : String(n),
1077
1079
  cause: n
1078
1080
  }));
1079
1081
  }
1080
- #V() {
1081
- if (this.#d.length === 0) return;
1082
- let e = this.#d;
1083
- this.#d = [];
1082
+ #B() {
1083
+ if (this.#u.length === 0) return;
1084
+ let e = this.#u;
1085
+ this.#u = [];
1084
1086
  for (let t of e) this.dispatchEvent(new CustomEvent("fellowship-map-error", {
1085
1087
  ...P,
1086
1088
  detail: t
@@ -1093,10 +1095,7 @@ i([d({
1093
1095
  })], F.prototype, "dungeonId", void 0), i([d({
1094
1096
  type: String,
1095
1097
  attribute: "map-image-id"
1096
- })], F.prototype, "mapImageId", void 0), i([d({
1097
- type: String,
1098
- attribute: "asset-base-url"
1099
- })], F.prototype, "assetBaseUrl", void 0), i([d({ attribute: !1 })], F.prototype, "dataSource", void 0), i([d({ attribute: !1 })], F.prototype, "renderEnemy", void 0), i([d({ attribute: !1 })], F.prototype, "renderGroup", void 0), i([d({ attribute: !1 })], F.prototype, "mapLabelFormatter", void 0), i([d({
1098
+ })], F.prototype, "mapImageId", void 0), i([d({ attribute: !1 })], F.prototype, "resolveAssetUrl", void 0), i([d({ attribute: !1 })], F.prototype, "dataSource", void 0), i([d({ attribute: !1 })], F.prototype, "renderEnemy", void 0), i([d({ attribute: !1 })], F.prototype, "renderGroup", void 0), i([d({ attribute: !1 })], F.prototype, "mapLabelFormatter", void 0), i([d({
1100
1099
  type: Boolean,
1101
1100
  attribute: "show-controls"
1102
1101
  })], F.prototype, "showControls", void 0), i([d({
@@ -1,6 +1,9 @@
1
- import { css as e } from "lit";
2
- //#region src/styles/field-manual.styles.ts
3
- var t = e`
1
+ import { FellowshipDataError as e } from "@crockery/fellowship-data/client";
2
+ import { css as t } from "lit";
3
+ //#region src/data/data-source.ts
4
+ var n = 2, r = (t) => {
5
+ if (t !== n) throw new e("unsupported-schema", `Unsupported fellowship-data schema version: ${String(t)}.`);
6
+ }, i = t`
4
7
  :host {
5
8
  --_fellowship-field-canvas: var(--fellowship-field-canvas, #0b0f13);
6
9
  --_fellowship-field-surface: var(--fellowship-field-surface, #10161c);
@@ -35,56 +38,48 @@ var t = e`
35
38
  );
36
39
  --_fellowship-field-radius: var(--fellowship-field-radius, 6px);
37
40
  }
38
- `, n = new URL("../assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2", import.meta.url).href, r = new URL("../assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2", import.meta.url).href, i = new URL("../assets/ibm-plex-sans-condensed-latin-400-normal-DKyD6XsY.woff2", import.meta.url).href, a = new URL("../assets/ibm-plex-sans-condensed-latin-500-normal-BqaLkUoX.woff2", import.meta.url).href, o = new URL("../assets/ibm-plex-sans-condensed-latin-600-normal-CRd5VyFf.woff2", import.meta.url).href, s = new URL("../assets/ibm-plex-sans-condensed-latin-700-normal-D8r4s4aS.woff2", import.meta.url).href, c = [
41
+ `, a = new URL("../assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2", import.meta.url).href, o = new URL("../assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2", import.meta.url).href, s = new URL("../assets/ibm-plex-sans-condensed-latin-400-normal-DKyD6XsY.woff2", import.meta.url).href, c = new URL("../assets/ibm-plex-sans-condensed-latin-500-normal-BqaLkUoX.woff2", import.meta.url).href, l = new URL("../assets/ibm-plex-sans-condensed-latin-600-normal-CRd5VyFf.woff2", import.meta.url).href, u = new URL("../assets/ibm-plex-sans-condensed-latin-700-normal-D8r4s4aS.woff2", import.meta.url).href, d = [
39
42
  {
40
43
  family: "Fellowship Field",
41
44
  weight: "400",
42
- url: i
45
+ url: s
43
46
  },
44
47
  {
45
48
  family: "Fellowship Field",
46
49
  weight: "500",
47
- url: a
50
+ url: c
48
51
  },
49
52
  {
50
53
  family: "Fellowship Field",
51
54
  weight: "600",
52
- url: o
55
+ url: l
53
56
  },
54
57
  {
55
58
  family: "Fellowship Field",
56
59
  weight: "700",
57
- url: s
60
+ url: u
58
61
  },
59
62
  {
60
63
  family: "Fellowship Tactical",
61
64
  weight: "500",
62
- url: n
65
+ url: a
63
66
  },
64
67
  {
65
68
  family: "Fellowship Tactical",
66
69
  weight: "600",
67
- url: r
70
+ url: o
68
71
  }
69
- ], l = /* @__PURE__ */ new WeakSet(), u = (e) => {
70
- if (l.has(e)) return;
72
+ ], f = /* @__PURE__ */ new WeakSet(), p = (e) => {
73
+ if (f.has(e)) return;
71
74
  let t = e.defaultView?.FontFace;
72
75
  if (!t || !e.fonts) return;
73
- let n = c.map(({ family: e, weight: n, url: r }) => new t(e, `url(${JSON.stringify(r)}) format("woff2")`, {
76
+ let n = d.map(({ family: e, weight: n, url: r }) => new t(e, `url(${JSON.stringify(r)}) format("woff2")`, {
74
77
  display: "swap",
75
78
  style: "normal",
76
79
  weight: n
77
80
  }));
78
81
  for (let t of n) e.fonts.add(t);
79
- l.add(e);
82
+ f.add(e);
80
83
  };
81
84
  //#endregion
82
- //#region \0@oxc-project+runtime@0.139.0/helpers/esm/decorate.js
83
- function d(e, t, n, r) {
84
- var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
85
- if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
86
- else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
87
- return i > 3 && a && Object.defineProperty(t, n, a), a;
88
- }
89
- //#endregion
90
- export { u as n, t as r, d as t };
85
+ export { r as i, i as n, e as r, p as t };