@crockery/fellowship-components 0.4.1 → 1.0.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 +31 -17
  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-Bgt77Ovf.js +1696 -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 +19 -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 -2
  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,18 +1,15 @@
1
- import { n as e, t } from "./data-source-XbksqUrw.js";
2
- import { n, r, t as i } from "./decorate-B_ZTN9li.js";
3
- import { a, n as o } from "./tooltip-DoQVSnOn.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
+ import { n as a, s as o } from "./tooltip-C3SSJw-t.js";
4
4
  import { createPackageFellowshipDataClient as s } from "@crockery/fellowship-data/client";
5
5
  import { LitElement as c, css as l, html as u, nothing as d } from "lit";
6
6
  import { customElement as f, property as p, state as m } from "lit/decorators.js";
7
7
  import { repeat as h } from "lit/directives/repeat.js";
8
8
  import { findImage as g } from "@crockery/fellowship-data";
9
9
  //#region src/data/package-talent-data-source.ts
10
- var _ = (e = {}) => {
11
- let t = s(e);
12
- return {
13
- loadHeroTalents: (e, n) => t.loadHeroTalents(e, n),
14
- resolveAssetUrl: (e) => t.resolveAssetUrl(e)
15
- };
10
+ var _ = () => {
11
+ let e = s();
12
+ return { loadHeroTalents: (t, n) => e.loadHeroTalents(t, n) };
16
13
  }, v = [
17
14
  "I",
18
15
  "II",
@@ -49,7 +46,7 @@ var _ = (e = {}) => {
49
46
  }), c = null;
50
47
  if (!s) n.push(b("missing-image", a, `Talent “${a.id}” has no icon.`));
51
48
  else try {
52
- c = t.resolveAssetUrl(s);
49
+ c = t(s);
53
50
  } catch (e) {
54
51
  n.push(b("asset-url-error", a, `The icon URL for talent “${a.id}” could not be resolved: ${String(e)}.`));
55
52
  }
@@ -645,10 +642,10 @@ var _ = (e = {}) => {
645
642
  overBudget: !1
646
643
  }), M = class extends c {
647
644
  constructor(...e) {
648
- super(...e), this.heroId = "", this.talentPoints = 14, this.selectedTalentIds = [], this.assetBaseUrl = null, this.dataSource = null, this.renderTalent = null, this.showPointControls = !0, this.showTooltips = !0, this._status = "empty", this._error = null, this._model = null, this._failedImages = /* @__PURE__ */ new Set(), this._announcement = "", this._renderSelectionState = j(14), this._talentPresentation = /* @__PURE__ */ new Map(), this._talentRenderContent = /* @__PURE__ */ new Map(), this.#e = null, this.#t = 0, this.#n = null, this.#r = !1, this.#i = /* @__PURE__ */ new Set(), this.#a = [];
645
+ super(...e), this.heroId = "", this.talentPoints = 14, this.selectedTalentIds = [], this.resolveAssetUrl = null, this.dataSource = null, this.renderTalent = null, this.showPointControls = !0, this.showTooltips = !0, this._status = "empty", this._error = null, this._model = null, this._failedImages = /* @__PURE__ */ new Set(), this._announcement = "", this._renderSelectionState = j(14), this._talentPresentation = /* @__PURE__ */ new Map(), this._talentRenderContent = /* @__PURE__ */ new Map(), this.#e = null, this.#t = 0, this.#n = null, this.#r = !1, this.#i = /* @__PURE__ */ new Set(), this.#a = [];
649
646
  }
650
647
  static {
651
- this.styles = [r, D];
648
+ this.styles = [t, D];
652
649
  }
653
650
  #e;
654
651
  #t;
@@ -657,13 +654,13 @@ var _ = (e = {}) => {
657
654
  #i;
658
655
  #a;
659
656
  connectedCallback() {
660
- super.connectedCallback(), n(this.ownerDocument);
657
+ super.connectedCallback(), r(this.ownerDocument);
661
658
  }
662
659
  disconnectedCallback() {
663
660
  this.#e?.abort(), super.disconnectedCallback();
664
661
  }
665
662
  updated(e) {
666
- if (super.updated(e), this.#S(), e.has("heroId") || e.has("dataSource") || e.has("assetBaseUrl")) {
663
+ if (super.updated(e), this.#S(), e.has("heroId") || e.has("dataSource") || e.has("resolveAssetUrl")) {
667
664
  queueMicrotask(() => {
668
665
  this.isConnected && this.#p();
669
666
  });
@@ -835,9 +832,9 @@ var _ = (e = {}) => {
835
832
  }
836
833
  #l(e) {
837
834
  let t = this.renderTalent, n = this._model, r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
838
- if (n) for (let o of n.talentById.values()) {
839
- let s = e.selectedTalentIds.includes(o.talent.id), c = E(o.pointCost, e), l = !s && !c, u = o.talent.name ?? o.talent.id, d = o.pointCost === null ? "This talent has no valid point cost." : l ? `Requires ${o.pointCost} talent points; ${Math.max(0, e.remainingPoints)} remaining.` : `${o.pointCost} talent ${o.pointCost === 1 ? "point" : "points"}.`, f = {
840
- talent: o,
835
+ if (n) for (let a of n.talentById.values()) {
836
+ let s = e.selectedTalentIds.includes(a.talent.id), c = E(a.pointCost, e), l = !s && !c, u = a.talent.name ?? a.talent.id, d = a.pointCost === null ? "This talent has no valid point cost." : l ? `Requires ${a.pointCost} talent points; ${Math.max(0, e.remainingPoints)} remaining.` : `${a.pointCost} talent ${a.pointCost === 1 ? "point" : "points"}.`, f = {
837
+ talent: a,
841
838
  hero: n.hero,
842
839
  selected: s,
843
840
  affordable: c,
@@ -846,19 +843,19 @@ var _ = (e = {}) => {
846
843
  remainingPoints: e.remainingPoints,
847
844
  talentPoints: this.talentPoints
848
845
  };
849
- if (i.set(o.talent.id, {
846
+ if (i.set(a.talent.id, {
850
847
  context: f,
851
848
  name: u,
852
- descriptionId: `talent-description-${o.row}-${o.column}`,
849
+ descriptionId: `talent-description-${a.row}-${a.column}`,
853
850
  affordability: d,
854
- description: [a(o.talent.description ?? ""), d].filter(Boolean).join(" ")
851
+ description: [o(a.talent.description ?? ""), d].filter(Boolean).join(" ")
855
852
  }), t) try {
856
- r.set(o.talent.id, t(f));
853
+ r.set(a.talent.id, t(f));
857
854
  } catch (e) {
858
- this.#i.has(o.talent.id) || (this.#i.add(o.talent.id), this.#a.push({
855
+ this.#i.has(a.talent.id) || (this.#i.add(a.talent.id), this.#a.push({
859
856
  code: "renderer-error",
860
- message: `The talent renderer failed for “${o.talent.id}”: ${String(e)}.`,
861
- talentId: o.talent.id
857
+ message: `The talent renderer failed for “${a.talent.id}”: ${String(e)}.`,
858
+ talentId: a.talent.id
862
859
  }));
863
860
  }
864
861
  }
@@ -909,13 +906,20 @@ var _ = (e = {}) => {
909
906
  this._status = "empty";
910
907
  return;
911
908
  }
909
+ if (!this.resolveAssetUrl) {
910
+ this.#C({
911
+ code: "asset-resolver-missing",
912
+ message: "A resolveAssetUrl callback is required to render Fellowship images."
913
+ });
914
+ return;
915
+ }
912
916
  this._status = "loading";
913
- let r = this.dataSource ?? _(this.assetBaseUrl ? { assetBaseUrl: this.assetBaseUrl } : {});
917
+ let r = this.dataSource ?? _();
914
918
  try {
915
919
  let i = await r.loadHeroTalents(t, this.#e.signal);
916
920
  if (n !== this.#t || this.#e.signal.aborted) return;
917
921
  e(i.manifest.schemaVersion);
918
- let a = x(i, r);
922
+ let a = x(i, this.resolveAssetUrl);
919
923
  this._model = a, this._status = "ready";
920
924
  let o = this.#m(!1);
921
925
  await this.updateComplete;
@@ -1014,17 +1018,17 @@ var _ = (e = {}) => {
1014
1018
  this.#a = [], this.#x(e);
1015
1019
  }
1016
1020
  #C(e) {
1017
- let n = typeof e == "object" && e && "code" in e && "message" in e ? {
1021
+ let t = typeof e == "object" && e && "code" in e && "message" in e ? {
1018
1022
  code: String(e.code),
1019
1023
  message: String(e.message),
1020
- ...e instanceof t && e.cause !== void 0 ? { cause: e.cause } : {}
1024
+ ...e instanceof n && e.cause !== void 0 ? { cause: e.cause } : {}
1021
1025
  } : {
1022
1026
  code: "unknown",
1023
1027
  message: e instanceof Error ? e.message : String(e)
1024
1028
  };
1025
- this._error = n, this._status = "error", this.dispatchEvent(new CustomEvent("fellowship-talents-error", {
1029
+ this._error = t, this._status = "error", this.dispatchEvent(new CustomEvent("fellowship-talents-error", {
1026
1030
  ...O,
1027
- detail: n
1031
+ detail: t
1028
1032
  }));
1029
1033
  }
1030
1034
  };
@@ -1037,10 +1041,7 @@ i([p({
1037
1041
  })], M.prototype, "talentPoints", void 0), i([p({
1038
1042
  attribute: !1,
1039
1043
  hasChanged: k
1040
- })], M.prototype, "selectedTalentIds", void 0), i([p({
1041
- type: String,
1042
- attribute: "asset-base-url"
1043
- })], M.prototype, "assetBaseUrl", void 0), i([p({ attribute: !1 })], M.prototype, "dataSource", void 0), i([p({ attribute: !1 })], M.prototype, "renderTalent", void 0), i([p({
1044
+ })], M.prototype, "selectedTalentIds", void 0), i([p({ attribute: !1 })], M.prototype, "resolveAssetUrl", void 0), i([p({ attribute: !1 })], M.prototype, "dataSource", void 0), i([p({ attribute: !1 })], M.prototype, "renderTalent", void 0), i([p({
1044
1045
  type: Boolean,
1045
1046
  attribute: "show-point-controls"
1046
1047
  })], M.prototype, "showPointControls", void 0), i([p({
@@ -1048,7 +1049,7 @@ i([p({
1048
1049
  attribute: "show-tooltips"
1049
1050
  })], M.prototype, "showTooltips", void 0), i([m()], M.prototype, "_status", void 0), i([m()], M.prototype, "_error", void 0), i([m()], M.prototype, "_model", void 0), i([m()], M.prototype, "_failedImages", void 0), i([m()], M.prototype, "_announcement", void 0), i([m()], M.prototype, "_renderSelectionState", void 0), i([m()], M.prototype, "_talentPresentation", void 0), i([m()], M.prototype, "_talentRenderContent", void 0), M = i([f("fellowship-talent-calculator")], M);
1050
1051
  var N = () => {
1051
- o(), customElements.get("fellowship-talent-calculator") || customElements.define("fellowship-talent-calculator", M);
1052
+ a(), customElements.get("fellowship-talent-calculator") || customElements.define("fellowship-talent-calculator", M);
1052
1053
  };
1053
1054
  //#endregion
1054
1055
  export { E as a, C as c, _ as d, S as i, x as l, N as n, T as o, A as r, w as s, M as t, y as u };
@@ -0,0 +1,482 @@
1
+ import { t as e } from "./decorate-DyMgX_Uh.js";
2
+ import { LitElement as t, css as n, html as r, nothing as i } from "lit";
3
+ import { customElement as a, property as o, query as s, state as c } from "lit/decorators.js";
4
+ import { repeat as l } from "lit/directives/repeat.js";
5
+ import { styleMap as u } from "lit/directives/style-map.js";
6
+ //#region src/tooltip/rich-text.ts
7
+ var d = {
8
+ bold: "strong",
9
+ "rt.bold": "strong",
10
+ "rt.absorb": "ability",
11
+ "rt.warning": "warning",
12
+ "rt.effect": "effect",
13
+ "rt.mana": "resource",
14
+ "rt.heal": "healing",
15
+ "rt.meikoability1": "meiko-primary",
16
+ "rt.meikoability2": "meiko-secondary"
17
+ }, f = (e, t, n) => {
18
+ let r = t.replace(/\r\n?/g, "\n").split(/\n{2,}/);
19
+ r.forEach((t, i) => {
20
+ let a = e.at(-1);
21
+ if (t.length > 0) {
22
+ let e = a.at(-1);
23
+ e?.tone === n ? a[a.length - 1] = {
24
+ text: `${e.text}${t}`,
25
+ tone: n
26
+ } : a.push({
27
+ text: t,
28
+ tone: n
29
+ });
30
+ }
31
+ i < r.length - 1 && e.push([]);
32
+ });
33
+ }, p = (e) => {
34
+ let t = [[]], n = ["default"], r = e.split(/(<\/?[^>]+>|<\/>)/g);
35
+ for (let e of r) {
36
+ if (!e) continue;
37
+ if (e === "</>") {
38
+ n.length > 1 && n.pop();
39
+ continue;
40
+ }
41
+ if (e.match(/^<\/\s*([^>\s]+)\s*>$/)) {
42
+ n.length > 1 && n.pop();
43
+ continue;
44
+ }
45
+ let r = e.match(/^<\s*([^/][^>\s]*)\s*>$/);
46
+ if (r) {
47
+ let e = r[1]?.toLowerCase() ?? "";
48
+ n.push(d[e] ?? "default");
49
+ continue;
50
+ }
51
+ f(t, e, n.at(-1) ?? "default");
52
+ }
53
+ return t;
54
+ }, m = (e) => p(e).map((e) => e.map(({ text: e }) => e).join("")).join("\n\n").trim(), h = new URL("../assets/dm-mono-latin-400-normal-4GdczIuU.woff2", import.meta.url).href, g = new URL("../assets/dm-mono-latin-500-normal-DRMDZjhP.woff2", import.meta.url).href, _ = new URL("../assets/syne-latin-700-normal-AF3Rs61n.woff2", import.meta.url).href, v = new URL("../assets/syne-latin-800-normal-EehdNYzx.woff2", import.meta.url).href, y = [
55
+ {
56
+ family: "Fellowship Poster",
57
+ weight: "700",
58
+ url: _
59
+ },
60
+ {
61
+ family: "Fellowship Poster",
62
+ weight: "800",
63
+ url: v
64
+ },
65
+ {
66
+ family: "Fellowship Utility",
67
+ weight: "400",
68
+ url: h
69
+ },
70
+ {
71
+ family: "Fellowship Utility",
72
+ weight: "500",
73
+ url: g
74
+ }
75
+ ], b = /* @__PURE__ */ new WeakSet(), x = (e) => {
76
+ if (b.has(e)) return;
77
+ let t = e.defaultView?.FontFace;
78
+ if (!(!t || !e.fonts)) {
79
+ for (let { family: n, weight: r, url: i } of y) e.fonts.add(new t(n, `url(${JSON.stringify(i)}) format("woff2")`, {
80
+ display: "swap",
81
+ style: "normal",
82
+ weight: r
83
+ }));
84
+ b.add(e);
85
+ }
86
+ }, S = n`
87
+ :host {
88
+ --_fellowship-poster-cream: var(--fellowship-poster-cream, oklch(96% 0.025 92));
89
+ --_fellowship-poster-violet: var(--fellowship-poster-violet, oklch(48% 0.23 303));
90
+ --_fellowship-poster-yellow: var(--fellowship-poster-yellow, oklch(89% 0.18 103));
91
+ --_fellowship-poster-plum: var(--fellowship-poster-plum, oklch(18% 0.035 320));
92
+ --_fellowship-poster-white: var(--fellowship-poster-white, oklch(98% 0.012 92));
93
+ --_fellowship-poster-display: var(
94
+ --fellowship-poster-display,
95
+ "Fellowship Poster",
96
+ "Syne",
97
+ sans-serif
98
+ );
99
+ --_fellowship-poster-mono: var(
100
+ --fellowship-poster-mono,
101
+ "Fellowship Utility",
102
+ "DM Mono",
103
+ ui-monospace,
104
+ monospace
105
+ );
106
+ --_fellowship-poster-seam: var(--fellowship-poster-seam, 3px);
107
+ --_fellowship-poster-radius: var(--fellowship-poster-radius, 2px);
108
+ --_fellowship-poster-shadow: var(
109
+ --fellowship-poster-shadow,
110
+ 4px 4px 0 var(--_fellowship-poster-yellow)
111
+ );
112
+ --_fellowship-poster-focus: var(--fellowship-poster-focus, var(--_fellowship-poster-yellow));
113
+ --_fellowship-poster-motion: var(--fellowship-poster-motion, 220ms);
114
+ --_fellowship-poster-ease: var(
115
+ --fellowship-poster-ease,
116
+ cubic-bezier(0.22, 1, 0.36, 1)
117
+ );
118
+ }
119
+ `, C = (e, t, n) => Math.min(Math.max(e, t), Math.max(t, n)), w = (e, t, n) => {
120
+ let r = n.gap ?? 8, i = n.margin ?? 8, a = {
121
+ top: e.top - i,
122
+ bottom: n.viewportHeight - e.bottom - i,
123
+ right: n.viewportWidth - e.right - i,
124
+ left: e.left - i
125
+ }, o = {
126
+ top: t.height + r,
127
+ bottom: t.height + r,
128
+ right: t.width + r,
129
+ left: t.width + r
130
+ }, s = [
131
+ "top",
132
+ "bottom",
133
+ "right",
134
+ "left"
135
+ ], c = n.placement ?? "auto", l = c === "auto" ? s.find((e) => a[e] >= o[e]) ?? [...s].sort((e, t) => a[t] - a[e])[0] : c, u = e.left + e.width / 2 - t.width / 2, d = e.top + e.height / 2 - t.height / 2, f = l === "left" ? e.left - t.width - r : l === "right" ? e.right + r : u, p = l === "top" ? e.top - t.height - r : l === "bottom" ? e.bottom + r : d;
136
+ return {
137
+ placement: l,
138
+ x: Math.round(C(f, i, n.viewportWidth - t.width - i)),
139
+ y: Math.round(C(p, i, n.viewportHeight - t.height - i))
140
+ };
141
+ }, T = n`
142
+ :host {
143
+ --fellowship-tooltip-void: var(--_fellowship-poster-plum);
144
+ --fellowship-tooltip-ink: var(--_fellowship-poster-cream);
145
+ --fellowship-tooltip-muted-ink: color-mix(
146
+ in oklch,
147
+ var(--_fellowship-poster-cream) 76%,
148
+ var(--_fellowship-poster-plum)
149
+ );
150
+ --fellowship-tooltip-border: var(--_fellowship-poster-cream);
151
+ --fellowship-tooltip-focus: var(--_fellowship-poster-yellow);
152
+ --fellowship-tooltip-ability: var(--_fellowship-poster-yellow);
153
+ --fellowship-tooltip-warning: var(--_fellowship-poster-yellow);
154
+ --fellowship-tooltip-effect: oklch(80% 0.12 303);
155
+ --fellowship-tooltip-resource: oklch(85% 0.11 213);
156
+ --fellowship-tooltip-healing: oklch(84% 0.13 145);
157
+ --fellowship-tooltip-meiko-primary: oklch(82% 0.11 10);
158
+ --fellowship-tooltip-meiko-secondary: oklch(82% 0.09 190);
159
+ --fellowship-tooltip-font-family: var(--_fellowship-poster-mono);
160
+ --fellowship-tooltip-radius: var(--_fellowship-poster-radius);
161
+ --fellowship-tooltip-max-width: 360px;
162
+
163
+ display: inline-block;
164
+ min-width: 0;
165
+ color: var(--fellowship-tooltip-ink);
166
+ font-family: var(--fellowship-tooltip-font-family);
167
+ -webkit-font-smoothing: antialiased;
168
+ }
169
+
170
+ :host([hidden]) {
171
+ display: none;
172
+ }
173
+
174
+ .trigger {
175
+ display: contents;
176
+ }
177
+
178
+ .surface {
179
+ position: fixed;
180
+ z-index: 2147483647;
181
+ box-sizing: border-box;
182
+ display: none;
183
+ overflow: visible;
184
+ width: max-content;
185
+ max-width: min(var(--fellowship-tooltip-max-width), calc(100vw - 16px));
186
+ margin: 0;
187
+ padding: 12px 16px 16px;
188
+ border: 2px solid var(--fellowship-tooltip-border);
189
+ border-radius: var(--fellowship-tooltip-radius);
190
+ background: var(--fellowship-tooltip-void);
191
+ color: var(--fellowship-tooltip-ink);
192
+ box-shadow: var(--_fellowship-poster-shadow);
193
+ opacity: 0;
194
+ transform: translateY(4px) scale(0.98);
195
+ transform-origin: bottom center;
196
+ transition:
197
+ opacity 180ms var(--_fellowship-poster-ease),
198
+ transform 180ms var(--_fellowship-poster-ease);
199
+ pointer-events: none;
200
+ }
201
+
202
+ .surface[data-open="true"] {
203
+ display: block;
204
+ opacity: 1;
205
+ transform: translateY(0) scale(1);
206
+ }
207
+
208
+ .surface[data-placement="bottom"] {
209
+ transform-origin: top center;
210
+ }
211
+
212
+ .surface[data-placement="left"] {
213
+ transform-origin: center right;
214
+ }
215
+
216
+ .surface[data-placement="right"] {
217
+ transform-origin: center left;
218
+ }
219
+
220
+ .heading {
221
+ position: relative;
222
+ margin: 0 0 6px;
223
+ padding: 2px 0 6px 12px;
224
+ color: var(--fellowship-tooltip-ink);
225
+ font-family: var(--_fellowship-poster-display);
226
+ font-size: 15px;
227
+ font-weight: 800;
228
+ line-height: 20px;
229
+ text-wrap: balance;
230
+ }
231
+
232
+ .heading::before {
233
+ position: absolute;
234
+ inset: 2px auto 6px 0;
235
+ width: 4px;
236
+ background: var(--_fellowship-poster-yellow);
237
+ content: "";
238
+ }
239
+
240
+ .content {
241
+ color: var(--fellowship-tooltip-muted-ink);
242
+ font-size: 13px;
243
+ font-weight: 400;
244
+ line-height: 20px;
245
+ text-wrap: pretty;
246
+ }
247
+
248
+ .paragraph {
249
+ margin: 0;
250
+ white-space: pre-line;
251
+ }
252
+
253
+ .paragraph + .paragraph {
254
+ margin-top: 8px;
255
+ }
256
+
257
+ [data-tone="strong"] {
258
+ color: var(--fellowship-tooltip-ink);
259
+ font-weight: 600;
260
+ }
261
+
262
+ [data-tone="ability"] {
263
+ color: var(--fellowship-tooltip-ability);
264
+ }
265
+
266
+ [data-tone="warning"] {
267
+ color: var(--fellowship-tooltip-warning);
268
+ }
269
+
270
+ [data-tone="effect"] {
271
+ color: var(--fellowship-tooltip-effect);
272
+ }
273
+
274
+ [data-tone="resource"] {
275
+ color: var(--fellowship-tooltip-resource);
276
+ }
277
+
278
+ [data-tone="healing"] {
279
+ color: var(--fellowship-tooltip-healing);
280
+ }
281
+
282
+ [data-tone="meiko-primary"] {
283
+ color: var(--fellowship-tooltip-meiko-primary);
284
+ }
285
+
286
+ [data-tone="meiko-secondary"] {
287
+ color: var(--fellowship-tooltip-meiko-secondary);
288
+ }
289
+
290
+ .arrow {
291
+ position: absolute;
292
+ width: 8px;
293
+ height: 8px;
294
+ border: solid var(--fellowship-tooltip-border);
295
+ background: var(--fellowship-tooltip-void);
296
+ transform: rotate(45deg);
297
+ }
298
+
299
+ .surface[data-placement="top"] .arrow {
300
+ bottom: -5px;
301
+ left: calc(50% - 4px);
302
+ border-width: 0 1px 1px 0;
303
+ }
304
+
305
+ .surface[data-placement="bottom"] .arrow {
306
+ top: -5px;
307
+ left: calc(50% - 4px);
308
+ border-width: 1px 0 0 1px;
309
+ }
310
+
311
+ .surface[data-placement="left"] .arrow {
312
+ top: calc(50% - 4px);
313
+ right: -5px;
314
+ border-width: 1px 1px 0 0;
315
+ }
316
+
317
+ .surface[data-placement="right"] .arrow {
318
+ top: calc(50% - 4px);
319
+ left: -5px;
320
+ border-width: 0 0 1px 1px;
321
+ }
322
+
323
+ @media (prefers-reduced-motion: reduce) {
324
+ .surface {
325
+ transition: opacity 100ms linear;
326
+ transform: none;
327
+ }
328
+ }
329
+ `, E = {
330
+ bubbles: !0,
331
+ composed: !0
332
+ }, D = 0, O = class extends t {
333
+ constructor(...e) {
334
+ super(...e), this.heading = null, this.text = null, this.placement = "auto", this.openDelay = 250, this.disabled = !1, this._open = !1, this._position = {
335
+ x: 0,
336
+ y: 0
337
+ }, this._resolvedPlacement = "top", this._paragraphs = [], this.#e = null, this.#t = null, this.#n = `fellowship-tooltip-${++D}`, this.#r = null, this.#i = !1, this.#a = null, this.#s = () => {
338
+ if (!this._open || !this.#t || !this._surface) return;
339
+ let e = w(this.#t.getBoundingClientRect(), this._surface.getBoundingClientRect(), {
340
+ placement: this.placement,
341
+ viewportWidth: window.innerWidth,
342
+ viewportHeight: window.innerHeight
343
+ });
344
+ e.x === this._position.x && e.y === this._position.y && e.placement === this._resolvedPlacement || (this._position = {
345
+ x: e.x,
346
+ y: e.y
347
+ }, this._resolvedPlacement = e.placement);
348
+ }, this.#u = () => {
349
+ this.disabled || this._open || (this.#v(), this.#e = window.setTimeout(() => {
350
+ this.#e = null, this.#o(!0, "pointer");
351
+ }, Math.max(0, this.openDelay)));
352
+ }, this.#d = () => {
353
+ this.#v(), this._open && this.#o(!1, "pointer");
354
+ }, this.#f = () => {
355
+ this.#v(), !this.disabled && !this._open && this.#o(!0, "focus");
356
+ }, this.#p = (e) => {
357
+ !this.contains(e.relatedTarget) && this._open && this.#o(!1, "focus");
358
+ }, this.#m = (e) => {
359
+ e.key === "Escape" && this._open && (e.stopPropagation(), this.#o(!1, "escape"));
360
+ }, this.#h = (e) => {
361
+ let t = e.currentTarget.assignedElements({ flatten: !0 })[0];
362
+ this.#_(), this.#t = t instanceof HTMLElement ? t : null, this.#g();
363
+ };
364
+ }
365
+ static {
366
+ this.styles = [S, T];
367
+ }
368
+ #e;
369
+ #t;
370
+ #n;
371
+ #r;
372
+ #i;
373
+ #a;
374
+ connectedCallback() {
375
+ super.connectedCallback(), x(this.ownerDocument), this.#a ??= new ResizeObserver(() => this.#s());
376
+ }
377
+ disconnectedCallback() {
378
+ this.#v(), this.#l(), this.#_(), super.disconnectedCallback();
379
+ }
380
+ updated(e) {
381
+ super.updated(e), (e.has("text") || e.has("heading")) && this.#g(), e.has("disabled") && this.disabled && this._open && this.#o(!1, "disabled"), e.has("placement") && this._open && this.#s();
382
+ }
383
+ willUpdate(e) {
384
+ super.willUpdate(e), e.has("text") && (this._paragraphs = p(this.text ?? ""));
385
+ }
386
+ show() {
387
+ this.disabled || this._open || this.#o(!0, "programmatic");
388
+ }
389
+ hide() {
390
+ this.#v(), this._open && this.#o(!1, "programmatic");
391
+ }
392
+ render() {
393
+ let e = {
394
+ left: `${this._position.x}px`,
395
+ top: `${this._position.y}px`
396
+ };
397
+ return r`
398
+ <span
399
+ class="trigger"
400
+ part="trigger"
401
+ @pointerenter=${this.#u}
402
+ @pointerleave=${this.#d}
403
+ @focusin=${this.#f}
404
+ @focusout=${this.#p}
405
+ @keydown=${this.#m}
406
+ >
407
+ <slot @slotchange=${this.#h}></slot>
408
+ </span>
409
+ <div
410
+ id=${this.#n}
411
+ class="surface"
412
+ part="surface"
413
+ role="tooltip"
414
+ popover="manual"
415
+ data-open=${String(this._open)}
416
+ data-placement=${this._resolvedPlacement}
417
+ style=${u(e)}
418
+ >
419
+ <span class="arrow" part="arrow" aria-hidden="true"></span>
420
+ <slot name="content">
421
+ ${this.heading ? r`<p class="heading" part="heading">${this.heading}</p>` : i}
422
+ <div class="content" part="content">
423
+ ${l(this._paragraphs, (e, t) => t, (e, t) => r`
424
+ <p class="paragraph" part="paragraph">
425
+ ${l(e, (e, n) => `${t}:${n}:${e.tone}:${e.text}`, (e) => r`<span data-tone=${e.tone}>${e.text}</span>`)}
426
+ </p>
427
+ `)}
428
+ </div>
429
+ </slot>
430
+ </div>
431
+ `;
432
+ }
433
+ #o(e, t) {
434
+ e !== this._open && (this._open = e, this.updateComplete.then(() => {
435
+ let t = this._surface;
436
+ t && (e ? ("showPopover" in t && !t.matches(":popover-open") && t.showPopover(), this.#c(), this.#s()) : ("hidePopover" in t && t.matches(":popover-open") && t.hidePopover(), this.#l()));
437
+ }), this.dispatchEvent(new CustomEvent("fellowship-tooltip-toggle", {
438
+ ...E,
439
+ detail: {
440
+ open: e,
441
+ reason: t
442
+ }
443
+ })));
444
+ }
445
+ #s;
446
+ #c() {
447
+ window.addEventListener("resize", this.#s), window.addEventListener("scroll", this.#s, !0), this.#t && this.#a?.observe(this.#t), this._surface && this.#a?.observe(this._surface);
448
+ }
449
+ #l() {
450
+ window.removeEventListener("resize", this.#s), window.removeEventListener("scroll", this.#s, !0), this.#a?.disconnect();
451
+ }
452
+ #u;
453
+ #d;
454
+ #f;
455
+ #p;
456
+ #m;
457
+ #h;
458
+ #g() {
459
+ if (!this.#t) return;
460
+ this.#i ||= (this.#r = this.#t.getAttribute("aria-describedby"), !0);
461
+ let e = (this.#r ?? "").split(/\s+/).filter(Boolean);
462
+ this.#t.setAttribute("aria-describedby", [.../* @__PURE__ */ new Set([...e, this.#n])].join(" "));
463
+ }
464
+ #_() {
465
+ this.#t && (this.#r === null ? this.#t.removeAttribute("aria-describedby") : this.#t.setAttribute("aria-describedby", this.#r), this.#t = null, this.#r = null, this.#i = !1);
466
+ }
467
+ #v() {
468
+ this.#e !== null && (window.clearTimeout(this.#e), this.#e = null);
469
+ }
470
+ };
471
+ e([o({ type: String })], O.prototype, "heading", void 0), e([o({ type: String })], O.prototype, "text", void 0), e([o({ type: String })], O.prototype, "placement", void 0), e([o({
472
+ type: Number,
473
+ attribute: "open-delay"
474
+ })], O.prototype, "openDelay", void 0), e([o({
475
+ type: Boolean,
476
+ reflect: !0
477
+ })], O.prototype, "disabled", void 0), e([c()], O.prototype, "_open", void 0), e([c()], O.prototype, "_position", void 0), e([c()], O.prototype, "_resolvedPlacement", void 0), e([c()], O.prototype, "_paragraphs", void 0), e([s(".surface")], O.prototype, "_surface", void 0), O = e([a("fellowship-tooltip")], O);
478
+ var k = () => {
479
+ customElements.get("fellowship-tooltip") || customElements.define("fellowship-tooltip", O);
480
+ };
481
+ //#endregion
482
+ export { x as a, S as i, k as n, p as o, w as r, m as s, O as t };
@@ -1,4 +1,4 @@
1
1
  export type { DungeonCastData } from "@crockery/fellowship-data/client";
2
2
  import type { FellowshipDataClient } from "@crockery/fellowship-data/client";
3
3
  /** @deprecated Use the corresponding `FellowshipDataClient` methods. */
4
- export type FellowshipCastDataSource = Pick<FellowshipDataClient, "loadDungeonCasts" | "resolveAssetUrl">;
4
+ export type FellowshipCastDataSource = Pick<FellowshipDataClient, "loadDungeonCasts">;
@@ -4,4 +4,4 @@ export type { DungeonMapData, FellowshipDataErrorCode, } from "@crockery/fellows
4
4
  import type { FellowshipDataClient } from "@crockery/fellowship-data/client";
5
5
  export declare const assertSupportedFellowshipDataSchema: (schemaVersion: number) => void;
6
6
  /** @deprecated Use the corresponding `FellowshipDataClient` methods. */
7
- export type FellowshipDataSource = Pick<FellowshipDataClient, "loadDungeon" | "resolveAssetUrl">;
7
+ export type FellowshipDataSource = Pick<FellowshipDataClient, "loadDungeon">;
@@ -1,7 +1,3 @@
1
1
  import type { FellowshipCastDataSource } from "./cast-data-source.js";
2
- /** @deprecated Create a package Fellowship data client instead. */
3
- export interface PackageFellowshipCastDataSourceOptions {
4
- readonly assetBaseUrl?: string;
5
- }
6
2
  /** @deprecated Use `createPackageFellowshipDataClient` from `@crockery/fellowship-data/client`. */
7
- export declare const createPackageFellowshipCastDataSource: (options?: PackageFellowshipCastDataSourceOptions) => FellowshipCastDataSource;
3
+ export declare const createPackageFellowshipCastDataSource: () => FellowshipCastDataSource;
@@ -1,7 +1,3 @@
1
1
  import type { FellowshipDataSource } from "./data-source.js";
2
- /** @deprecated Create a package Fellowship data client instead. */
3
- export interface PackageFellowshipDataSourceOptions {
4
- readonly assetBaseUrl?: string;
5
- }
6
2
  /** @deprecated Use `createPackageFellowshipDataClient` from `@crockery/fellowship-data/client`. */
7
- export declare const createPackageFellowshipDataSource: (options?: PackageFellowshipDataSourceOptions) => FellowshipDataSource;
3
+ export declare const createPackageFellowshipDataSource: () => FellowshipDataSource;