@crockery/fellowship-components 0.3.0 → 0.4.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/README.md CHANGED
@@ -94,8 +94,10 @@ request. See `THIRD_PARTY_LICENSES.md` for the SIL Open Font License notice.
94
94
 
95
95
  ## Data and asset versions
96
96
 
97
- The library accepts `@crockery/fellowship-data@^1.3.0`. Commit the consuming application's
98
- lockfile when reproducible data and image updates matter.
97
+ The next release targets `@crockery/fellowship-data@^2.0.0` and requires manifest schema 2. Until
98
+ Data 2.0 is published, this repository remains installable from the last published Data release;
99
+ the release-dispatch automation updates the dependency and lockfile after publication. Commit a
100
+ consuming application's lockfile when reproducible data and image updates matter.
99
101
 
100
102
  Dataset JSON stays out of the component library's initial JavaScript path and published tarball.
101
103
  Each data-driven component supports:
@@ -0,0 +1,9 @@
1
+ import { FellowshipDataError as e } from "@crockery/fellowship-data/client";
2
+ //#region src/data/data-source.ts
3
+ var t = 2, n = (n) => {
4
+ if (n !== t) throw new e("unsupported-schema", `Unsupported fellowship-data schema version: ${String(n)}.`);
5
+ };
6
+ //#endregion
7
+ export { n, e as t };
8
+
9
+ //# sourceMappingURL=data-source-XbksqUrw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-source-XbksqUrw.js","names":[],"sources":["../../src/data/data-source.ts"],"sourcesContent":["import { FellowshipDataError } from \"@crockery/fellowship-data/client\";\nexport { FellowshipDataError };\nexport type {\n DungeonMapData,\n FellowshipDataErrorCode,\n} from \"@crockery/fellowship-data/client\";\n\nimport type { FellowshipDataClient } from \"@crockery/fellowship-data/client\";\n\nconst supportedSchemaVersion = 2;\n\nexport const assertSupportedFellowshipDataSchema = (schemaVersion: number): void => {\n if (schemaVersion === supportedSchemaVersion) return;\n\n throw new FellowshipDataError(\n \"unsupported-schema\",\n `Unsupported fellowship-data schema version: ${String(schemaVersion)}.`,\n );\n};\n\n/** @deprecated Use the corresponding `FellowshipDataClient` methods. */\nexport type FellowshipDataSource = Pick<FellowshipDataClient, \"loadDungeon\" | \"resolveAssetUrl\">;\n"],"mappings":";;AASA,IAAM,IAAyB,GAElB,KAAuC,MAAgC;CAC9E,UAAkB,GAEtB,MAAM,IAAI,EACR,sBACA,+CAA+C,OAAO,CAAa,EAAE,EACvE;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"decorate-B_ZTN9li.js","names":[],"sources":["../../src/styles/field-manual.styles.ts","../../node_modules/.pnpm/@fontsource+ibm-plex-mono@5.2.7/node_modules/@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-500-normal.woff2?fellowship-font-url","../../node_modules/.pnpm/@fontsource+ibm-plex-mono@5.2.7/node_modules/@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-600-normal.woff2?fellowship-font-url","../../node_modules/.pnpm/@fontsource+ibm-plex-sans-condensed@5.2.8/node_modules/@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-400-normal.woff2?fellowship-font-url","../../node_modules/.pnpm/@fontsource+ibm-plex-sans-condensed@5.2.8/node_modules/@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-500-normal.woff2?fellowship-font-url","../../node_modules/.pnpm/@fontsource+ibm-plex-sans-condensed@5.2.8/node_modules/@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-600-normal.woff2?fellowship-font-url","../../node_modules/.pnpm/@fontsource+ibm-plex-sans-condensed@5.2.8/node_modules/@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-700-normal.woff2?fellowship-font-url","../../src/styles/field-manual-fonts.ts"],"sourcesContent":["import { css } from \"lit\";\n\n/** Shared internal aliases for the public Expedition Field Manual theme tokens. */\nexport const fieldManualStyles = css`\n :host {\n --_fellowship-field-canvas: var(--fellowship-field-canvas, #0b0f13);\n --_fellowship-field-surface: var(--fellowship-field-surface, #10161c);\n --_fellowship-field-surface-raised: var(--fellowship-field-surface-raised, #151c23);\n --_fellowship-field-inset: var(--fellowship-field-inset, #080c10);\n --_fellowship-field-ink: var(--fellowship-field-ink, #f1eee5);\n --_fellowship-field-muted: var(--fellowship-field-muted, #b7b4aa);\n --_fellowship-field-tertiary: var(--fellowship-field-tertiary, #858a8e);\n --_fellowship-field-border: var(\n --fellowship-field-border,\n rgb(241 238 229 / 10%)\n );\n --_fellowship-field-border-strong: var(\n --fellowship-field-border-strong,\n rgb(241 238 229 / 18%)\n );\n --_fellowship-field-accent: var(--fellowship-field-accent, #69c4d4);\n --_fellowship-field-focus: var(--fellowship-field-focus, #a8e6ee);\n --_fellowship-field-ember: var(--fellowship-field-ember, #d9784c);\n --_fellowship-field-brass: var(--fellowship-field-brass, #c1a36a);\n --_fellowship-field-font-family: var(\n --fellowship-field-font-family,\n \"Fellowship Field\",\n \"Arial Narrow\",\n sans-serif\n );\n --_fellowship-field-mono-font-family: var(\n --fellowship-field-mono-font-family,\n \"Fellowship Tactical\",\n ui-monospace,\n monospace\n );\n --_fellowship-field-radius: var(--fellowship-field-radius, 6px);\n }\n`;\n","export default import.meta.ROLLUP_FILE_URL_FKNdLzKnlftW3t_gzo81yw;","export default import.meta.ROLLUP_FILE_URL_VRAku6fjghkApIISiBWPzg;","export default import.meta.ROLLUP_FILE_URL_8HSUfh7cJHNFxCkInNzNXw;","export default import.meta.ROLLUP_FILE_URL_WPGYjwIlzWVNM1bYhOc83w;","export default import.meta.ROLLUP_FILE_URL_P4DPfwIRieI8P6q8r4JZRw;","export default import.meta.ROLLUP_FILE_URL_cn7IAAGY294pWGc7MpElVg;","import mono500Url from \"@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-500-normal.woff2?url\";\nimport mono600Url from \"@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-600-normal.woff2?url\";\nimport field400Url from \"@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-400-normal.woff2?url\";\nimport field500Url from \"@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-500-normal.woff2?url\";\nimport field600Url from \"@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-600-normal.woff2?url\";\nimport field700Url from \"@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-700-normal.woff2?url\";\n\ninterface FieldManualFontAsset {\n readonly family: \"Fellowship Field\" | \"Fellowship Tactical\";\n readonly weight: \"400\" | \"500\" | \"600\" | \"700\";\n readonly url: string;\n}\n\nconst fieldManualFontAssets: readonly FieldManualFontAsset[] = [\n { family: \"Fellowship Field\", weight: \"400\", url: field400Url },\n { family: \"Fellowship Field\", weight: \"500\", url: field500Url },\n { family: \"Fellowship Field\", weight: \"600\", url: field600Url },\n { family: \"Fellowship Field\", weight: \"700\", url: field700Url },\n { family: \"Fellowship Tactical\", weight: \"500\", url: mono500Url },\n { family: \"Fellowship Tactical\", weight: \"600\", url: mono600Url },\n];\n\nconst installedDocuments = new WeakSet<Document>();\n\n/** Makes the bundled field-manual faces available to a component's owner document. */\nexport const installFieldManualFonts = (document: Document): void => {\n if (installedDocuments.has(document)) {\n return;\n }\n\n const FontFaceConstructor = document.defaultView?.FontFace;\n if (!FontFaceConstructor || !document.fonts) {\n return;\n }\n\n const faces = fieldManualFontAssets.map(\n ({ family, weight, url }) =>\n new FontFaceConstructor(family, `url(${JSON.stringify(url)}) format(\"woff2\")`, {\n display: \"swap\",\n style: \"normal\",\n weight,\n }),\n );\n for (const face of faces) {\n document.fonts.add(face);\n }\n installedDocuments.add(document);\n};\n"],"x_google_ignoreList":[1,2,3,4,5,6],"mappings":";;AAGA,IAAa,IAAoB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GCHpC,IAAA,IAAA,IAAA,2DAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCAA,IAAA,IAAA,IAAA,2DAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCAA,IAAA,IAAA,IAAA,qEAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCAA,IAAA,IAAA,IAAA,qEAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCAA,IAAA,IAAA,IAAA,qEAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCAA,IAAA,IAAA,IAAA,qEAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCaM,IAAyD;CAC7D;EAAE,QAAQ;EAAoB,QAAQ;EAAO,KAAK;CAAY;CAC9D;EAAE,QAAQ;EAAoB,QAAQ;EAAO,KAAK;CAAY;CAC9D;EAAE,QAAQ;EAAoB,QAAQ;EAAO,KAAK;CAAY;CAC9D;EAAE,QAAQ;EAAoB,QAAQ;EAAO,KAAK;CAAY;CAC9D;EAAE,QAAQ;EAAuB,QAAQ;EAAO,KAAK;CAAW;CAChE;EAAE,QAAQ;EAAuB,QAAQ;EAAO,KAAK;CAAW;AAClE,GAEM,oBAAqB,IAAI,QAAkB,GAGpC,KAA2B,MAA6B;CACnE,IAAI,EAAmB,IAAI,CAAQ,GACjC;CAGF,IAAM,IAAsB,EAAS,aAAa;CAClD,IAAI,CAAC,KAAuB,CAAC,EAAS,OACpC;CAGF,IAAM,IAAQ,EAAsB,KACjC,EAAE,WAAQ,WAAQ,aACjB,IAAI,EAAoB,GAAQ,OAAO,KAAK,UAAU,CAAG,EAAE,oBAAoB;EAC7E,SAAS;EACT,OAAO;EACP;CACF,CAAC,CACL;CACA,KAAK,IAAM,KAAQ,GACjB,EAAS,MAAM,IAAI,CAAI;CAEzB,EAAmB,IAAI,CAAQ;AACjC"}
1
+ {"version":3,"file":"decorate-B_ZTN9li.js","names":[],"sources":["../../src/styles/field-manual.styles.ts","../../node_modules/.pnpm/@fontsource+ibm-plex-mono@5.2.7/node_modules/@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-500-normal.woff2?fellowship-font-url","../../node_modules/.pnpm/@fontsource+ibm-plex-mono@5.2.7/node_modules/@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-600-normal.woff2?fellowship-font-url","../../node_modules/.pnpm/@fontsource+ibm-plex-sans-condensed@5.2.8/node_modules/@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-400-normal.woff2?fellowship-font-url","../../node_modules/.pnpm/@fontsource+ibm-plex-sans-condensed@5.2.8/node_modules/@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-500-normal.woff2?fellowship-font-url","../../node_modules/.pnpm/@fontsource+ibm-plex-sans-condensed@5.2.8/node_modules/@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-600-normal.woff2?fellowship-font-url","../../node_modules/.pnpm/@fontsource+ibm-plex-sans-condensed@5.2.8/node_modules/@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-700-normal.woff2?fellowship-font-url","../../src/styles/field-manual-fonts.ts"],"sourcesContent":["import { css } from \"lit\";\n\n/** Shared internal aliases for the public Expedition Field Manual theme tokens. */\nexport const fieldManualStyles = css`\n :host {\n --_fellowship-field-canvas: var(--fellowship-field-canvas, #0b0f13);\n --_fellowship-field-surface: var(--fellowship-field-surface, #10161c);\n --_fellowship-field-surface-raised: var(--fellowship-field-surface-raised, #151c23);\n --_fellowship-field-inset: var(--fellowship-field-inset, #080c10);\n --_fellowship-field-ink: var(--fellowship-field-ink, #f1eee5);\n --_fellowship-field-muted: var(--fellowship-field-muted, #b7b4aa);\n --_fellowship-field-tertiary: var(--fellowship-field-tertiary, #858a8e);\n --_fellowship-field-border: var(\n --fellowship-field-border,\n rgb(241 238 229 / 10%)\n );\n --_fellowship-field-border-strong: var(\n --fellowship-field-border-strong,\n rgb(241 238 229 / 18%)\n );\n --_fellowship-field-accent: var(--fellowship-field-accent, #69c4d4);\n --_fellowship-field-focus: var(--fellowship-field-focus, #a8e6ee);\n --_fellowship-field-ember: var(--fellowship-field-ember, #d9784c);\n --_fellowship-field-brass: var(--fellowship-field-brass, #c1a36a);\n --_fellowship-field-font-family: var(\n --fellowship-field-font-family,\n \"Fellowship Field\",\n \"Arial Narrow\",\n sans-serif\n );\n --_fellowship-field-mono-font-family: var(\n --fellowship-field-mono-font-family,\n \"Fellowship Tactical\",\n ui-monospace,\n monospace\n );\n --_fellowship-field-radius: var(--fellowship-field-radius, 6px);\n }\n`;\n","export default import.meta.ROLLUP_FILE_URL_FKNdLzKnlftW3t_gzo81yw;","export default import.meta.ROLLUP_FILE_URL_P4DPfwIRieI8P6q8r4JZRw;","export default import.meta.ROLLUP_FILE_URL_WPGYjwIlzWVNM1bYhOc83w;","export default import.meta.ROLLUP_FILE_URL_cn7IAAGY294pWGc7MpElVg;","export default import.meta.ROLLUP_FILE_URL_8HSUfh7cJHNFxCkInNzNXw;","export default import.meta.ROLLUP_FILE_URL_VRAku6fjghkApIISiBWPzg;","import mono500Url from \"@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-500-normal.woff2?url\";\nimport mono600Url from \"@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-600-normal.woff2?url\";\nimport field400Url from \"@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-400-normal.woff2?url\";\nimport field500Url from \"@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-500-normal.woff2?url\";\nimport field600Url from \"@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-600-normal.woff2?url\";\nimport field700Url from \"@fontsource/ibm-plex-sans-condensed/files/ibm-plex-sans-condensed-latin-700-normal.woff2?url\";\n\ninterface FieldManualFontAsset {\n readonly family: \"Fellowship Field\" | \"Fellowship Tactical\";\n readonly weight: \"400\" | \"500\" | \"600\" | \"700\";\n readonly url: string;\n}\n\nconst fieldManualFontAssets: readonly FieldManualFontAsset[] = [\n { family: \"Fellowship Field\", weight: \"400\", url: field400Url },\n { family: \"Fellowship Field\", weight: \"500\", url: field500Url },\n { family: \"Fellowship Field\", weight: \"600\", url: field600Url },\n { family: \"Fellowship Field\", weight: \"700\", url: field700Url },\n { family: \"Fellowship Tactical\", weight: \"500\", url: mono500Url },\n { family: \"Fellowship Tactical\", weight: \"600\", url: mono600Url },\n];\n\nconst installedDocuments = new WeakSet<Document>();\n\n/** Makes the bundled field-manual faces available to a component's owner document. */\nexport const installFieldManualFonts = (document: Document): void => {\n if (installedDocuments.has(document)) {\n return;\n }\n\n const FontFaceConstructor = document.defaultView?.FontFace;\n if (!FontFaceConstructor || !document.fonts) {\n return;\n }\n\n const faces = fieldManualFontAssets.map(\n ({ family, weight, url }) =>\n new FontFaceConstructor(family, `url(${JSON.stringify(url)}) format(\"woff2\")`, {\n display: \"swap\",\n style: \"normal\",\n weight,\n }),\n );\n for (const face of faces) {\n document.fonts.add(face);\n }\n installedDocuments.add(document);\n};\n"],"x_google_ignoreList":[1,2,3,4,5,6],"mappings":";;AAGA,IAAa,IAAoB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GCHpC,IAAA,IAAA,IAAA,2DAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCAA,IAAA,IAAA,IAAA,2DAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCAA,IAAA,IAAA,IAAA,qEAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCAA,IAAA,IAAA,IAAA,qEAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCAA,IAAA,IAAA,IAAA,qEAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCAA,IAAA,IAAA,IAAA,qEAAA,OAAA,KAAA,GAAA,CAAA,CAAA,MCaM,IAAyD;CAC7D;EAAE,QAAQ;EAAoB,QAAQ;EAAO,KAAK;CAAY;CAC9D;EAAE,QAAQ;EAAoB,QAAQ;EAAO,KAAK;CAAY;CAC9D;EAAE,QAAQ;EAAoB,QAAQ;EAAO,KAAK;CAAY;CAC9D;EAAE,QAAQ;EAAoB,QAAQ;EAAO,KAAK;CAAY;CAC9D;EAAE,QAAQ;EAAuB,QAAQ;EAAO,KAAK;CAAW;CAChE;EAAE,QAAQ;EAAuB,QAAQ;EAAO,KAAK;CAAW;AAClE,GAEM,oBAAqB,IAAI,QAAkB,GAGpC,KAA2B,MAA6B;CACnE,IAAI,EAAmB,IAAI,CAAQ,GACjC;CAGF,IAAM,IAAsB,EAAS,aAAa;CAClD,IAAI,CAAC,KAAuB,CAAC,EAAS,OACpC;CAGF,IAAM,IAAQ,EAAsB,KACjC,EAAE,WAAQ,WAAQ,aACjB,IAAI,EAAoB,GAAQ,OAAO,KAAK,UAAU,CAAG,EAAE,oBAAoB;EAC7E,SAAS;EACT,OAAO;EACP;CACF,CAAC,CACL;CACA,KAAK,IAAM,KAAQ,GACjB,EAAS,MAAM,IAAI,CAAI;CAEzB,EAAmB,IAAI,CAAQ;AACjC"}
@@ -1,17 +1,17 @@
1
- import { t as e } from "./data-source-C-Gs7kRl.js";
2
- import { n as t, r as n, t as r } from "./decorate-B_ZTN9li.js";
3
- import { createPackageFellowshipDataClient as i } from "@crockery/fellowship-data/client";
4
- import { LitElement as a, css as o, html as s, nothing as c } from "lit";
5
- import { customElement as l, property as u, state as d } from "lit/decorators.js";
6
- import { repeat as f } from "lit/directives/repeat.js";
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 { createPackageFellowshipDataClient as a } from "@crockery/fellowship-data/client";
4
+ import { LitElement as o, css as s, html as c, nothing as l } from "lit";
5
+ import { customElement as u, property as d, state as f } from "lit/decorators.js";
6
+ import { repeat as p } from "lit/directives/repeat.js";
7
7
  //#region src/data/package-cast-data-source.ts
8
- var p = (e = {}) => {
9
- let t = i(e);
8
+ var m = (e = {}) => {
9
+ let t = a(e);
10
10
  return {
11
11
  loadDungeonCasts: (e, n) => t.loadDungeonCasts(e, n),
12
12
  resolveAssetUrl: (e) => t.resolveAssetUrl(e)
13
13
  };
14
- }, m = o`
14
+ }, h = s`
15
15
  :host {
16
16
  --fellowship-cast-canvas: var(--_fellowship-field-canvas);
17
17
  --fellowship-cast-surface: var(--_fellowship-field-surface);
@@ -435,7 +435,7 @@ var p = (e = {}) => {
435
435
  transition: none;
436
436
  }
437
437
  }
438
- `, h = ({ enemyId: e, abilityId: t }) => `${e}\u0000${t}`, g = (e) => e.images.find(({ size: e }) => e === "200") ?? e.images[0] ?? null, _ = (e, t, n) => t ? "Interrupt varies" : e ? "Interrupt" : n ? "Stop" : "No response", v = (e, t) => {
438
+ `, g = ({ enemyId: e, abilityId: t }) => `${e}\u0000${t}`, _ = (e) => e.images.find(({ size: e }) => e === "200") ?? e.images[0] ?? null, v = (e, t, n) => t ? "Interrupt varies" : e ? "Interrupt" : n ? "Stop" : "No response", y = (e, t) => {
439
439
  let n = /* @__PURE__ */ new Set(), r = [];
440
440
  for (let i of e.dungeon.enemies) {
441
441
  if (n.has(i.id)) continue;
@@ -443,7 +443,7 @@ var p = (e = {}) => {
443
443
  let a = e.enemies.get(i.id);
444
444
  if (!a) continue;
445
445
  let o = (e.abilitiesByEnemy.get(a.id) ?? []).filter((e) => e.castInterruptibility !== void 0).map((e) => {
446
- let n = e.castInterruptibility !== "never", r = e.castInterruptibility === "sometimes", i = a.canBeControlled, o = g(e), s = null;
446
+ let n = e.castInterruptibility !== "never", r = e.castInterruptibility === "sometimes", i = a.canBeControlled, o = _(e), s = null;
447
447
  if (o) try {
448
448
  s = t.resolveAssetUrl(o);
449
449
  } catch {
@@ -460,7 +460,7 @@ var p = (e = {}) => {
460
460
  interruptVaries: r,
461
461
  canStop: i,
462
462
  actionable: n || i,
463
- capabilityLabel: _(n, r, i),
463
+ capabilityLabel: v(n, r, i),
464
464
  imageUrl: s
465
465
  };
466
466
  });
@@ -474,10 +474,10 @@ var p = (e = {}) => {
474
474
  enemies: r,
475
475
  castCount: r.reduce((e, t) => e + t.casts.length, 0)
476
476
  };
477
- }, y = {
477
+ }, b = {
478
478
  bubbles: !0,
479
479
  composed: !0
480
- }, b = class extends a {
480
+ }, x = class extends o {
481
481
  constructor(...e) {
482
482
  super(...e), this.dungeonId = "", this.selectedCast = null, this.configuredCasts = [], this.configuredFilter = "all", this.fill = !1, this.assetBaseUrl = null, this.dataSource = null, this._status = "empty", this._error = null, this._model = null, this._query = "", this.#e = null, this.#t = 0, this.#d = (e) => {
483
483
  this._query = e.currentTarget.value;
@@ -496,12 +496,12 @@ var p = (e = {}) => {
496
496
  };
497
497
  }
498
498
  static {
499
- this.styles = [n, m];
499
+ this.styles = [r, h];
500
500
  }
501
501
  #e;
502
502
  #t;
503
503
  connectedCallback() {
504
- super.connectedCallback(), t(this.ownerDocument);
504
+ super.connectedCallback(), n(this.ownerDocument);
505
505
  }
506
506
  disconnectedCallback() {
507
507
  this.#e?.abort(), super.disconnectedCallback();
@@ -518,9 +518,9 @@ var p = (e = {}) => {
518
518
  return this._model;
519
519
  }
520
520
  render() {
521
- if (this._status !== "ready" || !this._model) return s`<section class="browser" aria-label="Dungeon cast browser">${this.#o()}</section>`;
521
+ if (this._status !== "ready" || !this._model) return c`<section class="browser" aria-label="Dungeon cast browser">${this.#o()}</section>`;
522
522
  let e = this.#r(this._model);
523
- return s`
523
+ return c`
524
524
  <section class="browser" aria-label=${`${this._model.dungeon.name ?? this._model.dungeon.id} casts`}>
525
525
  <header class="toolbar" part="toolbar">
526
526
  <div>
@@ -541,40 +541,40 @@ var p = (e = {}) => {
541
541
  />
542
542
  </label>
543
543
  </header>
544
- ${e.length > 0 ? s`<div class="enemy-list" part="enemy-list">${f(e, ({ enemy: e }) => e.id, (e) => this.#i(e))}</div>` : this.#s()}
544
+ ${e.length > 0 ? c`<div class="enemy-list" part="enemy-list">${p(e, ({ enemy: e }) => e.id, (e) => this.#i(e))}</div>` : this.#s()}
545
545
  </section>
546
546
  `;
547
547
  }
548
548
  async #n() {
549
- let t = this.dungeonId.trim(), n = ++this.#t;
550
- if (this.#e?.abort(), this.#e = new AbortController(), this._model = null, this._error = null, this._query = "", !t) {
549
+ let n = this.dungeonId.trim(), r = ++this.#t;
550
+ if (this.#e?.abort(), this.#e = new AbortController(), this._model = null, this._error = null, this._query = "", !n) {
551
551
  this._status = "empty";
552
552
  return;
553
553
  }
554
554
  this._status = "loading";
555
- let r = this.dataSource ?? p(this.assetBaseUrl ? { assetBaseUrl: this.assetBaseUrl } : {});
555
+ let i = this.dataSource ?? m(this.assetBaseUrl ? { assetBaseUrl: this.assetBaseUrl } : {});
556
556
  try {
557
- let i = await r.loadDungeonCasts(t, this.#e.signal);
558
- if (n !== this.#t || this.#e.signal.aborted) return;
559
- if (i.manifest.schemaVersion !== 1) throw new e("unsupported-schema", `Unsupported fellowship-data schema version: ${String(i.manifest.schemaVersion)}.`);
560
- let a = v(i, r);
557
+ let t = await i.loadDungeonCasts(n, this.#e.signal);
558
+ if (r !== this.#t || this.#e.signal.aborted) return;
559
+ e(t.manifest.schemaVersion);
560
+ let a = y(t, i);
561
561
  this._model = a, this._status = "ready", this.dispatchEvent(new CustomEvent("fellowship-cast-browser-ready", {
562
- ...y,
562
+ ...b,
563
563
  detail: {
564
564
  model: a,
565
- data: i
565
+ data: t
566
566
  }
567
567
  }));
568
- } catch (t) {
569
- if (n !== this.#t || this.#e.signal.aborted) return;
570
- let r = {
571
- code: t instanceof e ? t.code : t.code ?? "data-load-failed",
572
- message: t instanceof Error ? t.message : String(t),
573
- ...t instanceof Error && t.cause !== void 0 ? { cause: t.cause } : {}
568
+ } catch (e) {
569
+ if (r !== this.#t || this.#e.signal.aborted) return;
570
+ let n = {
571
+ code: e instanceof t ? e.code : e.code ?? "data-load-failed",
572
+ message: e instanceof Error ? e.message : String(e),
573
+ ...e instanceof Error && e.cause !== void 0 ? { cause: e.cause } : {}
574
574
  };
575
- this._error = r, this._status = "error", this.dispatchEvent(new CustomEvent("fellowship-cast-browser-error", {
576
- ...y,
577
- detail: r
575
+ this._error = n, this._status = "error", this.dispatchEvent(new CustomEvent("fellowship-cast-browser-error", {
576
+ ...b,
577
+ detail: n
578
578
  }));
579
579
  }
580
580
  }
@@ -593,7 +593,7 @@ var p = (e = {}) => {
593
593
  });
594
594
  }
595
595
  #i(e) {
596
- return s`
596
+ return c`
597
597
  <article class="enemy" part="enemy">
598
598
  <header class="enemy-header" part="enemy-header">
599
599
  <span class="enemy-rule" aria-hidden="true"></span>
@@ -604,14 +604,14 @@ var p = (e = {}) => {
604
604
  <span class="enemy-count">${e.casts.length} ${e.casts.length === 1 ? "cast" : "casts"}</span>
605
605
  </header>
606
606
  <ul class="cast-list">
607
- ${f(e.casts, ({ identity: e }) => h(e), (e) => s`<li>${this.#a(e)}</li>`)}
607
+ ${p(e.casts, ({ identity: e }) => g(e), (e) => c`<li>${this.#a(e)}</li>`)}
608
608
  </ul>
609
609
  </article>
610
610
  `;
611
611
  }
612
612
  #a(e) {
613
613
  let t = this.#l(this.selectedCast, e.identity), n = this.configuredCasts.some((t) => this.#l(t, e.identity)), r = e.interruptVaries ? "varies" : e.canInterrupt ? "interrupt" : e.canStop ? "stop" : "none", i = (e.ability.name ?? e.ability.id).split(/\s+/).map((e) => e[0]).join("").slice(0, 2).toUpperCase();
614
- return s`
614
+ return c`
615
615
  <button
616
616
  class="cast-row"
617
617
  part="cast"
@@ -622,7 +622,7 @@ var p = (e = {}) => {
622
622
  @click=${() => this.#u(e)}
623
623
  @keydown=${this.#p}
624
624
  >
625
- ${e.imageUrl ? s`<img
625
+ ${e.imageUrl ? c`<img
626
626
  class="ability-image"
627
627
  part="cast-icon"
628
628
  src=${e.imageUrl}
@@ -634,18 +634,18 @@ var p = (e = {}) => {
634
634
  aria-hidden="true"
635
635
  hidden
636
636
  >${i}</span
637
- >` : s`<span class="ability-fallback" part="cast-icon-fallback" aria-hidden="true">${i}</span>`}
637
+ >` : c`<span class="ability-fallback" part="cast-icon-fallback" aria-hidden="true">${i}</span>`}
638
638
  <span class="ability-copy">
639
639
  <span class="ability-name">${e.ability.name ?? e.ability.id}</span>
640
640
  <span class="ability-id">${e.ability.id}</span>
641
641
  </span>
642
642
  <span class="capability" data-kind=${r}>${e.capabilityLabel}</span>
643
- <span class="marker" data-empty=${String(!n)}>${n ? "Configured" : c}</span>
643
+ <span class="marker" data-empty=${String(!n)}>${n ? "Configured" : l}</span>
644
644
  </button>
645
645
  `;
646
646
  }
647
647
  #o() {
648
- return this._status === "loading" ? this.#c("Loading cast index", "Joining dungeon enemies with their cast data.") : this._status === "error" ? s`
648
+ return this._status === "loading" ? this.#c("Loading cast index", "Joining dungeon enemies with their cast data.") : this._status === "error" ? c`
649
649
  <div class="status" role="alert">
650
650
  <div class="status-card">
651
651
  <span class="status-mark" aria-hidden="true"></span>
@@ -660,7 +660,7 @@ var p = (e = {}) => {
660
660
  return this.#c("No matching casts", `No enemy or ability matches “${this._query.trim()}”.`);
661
661
  }
662
662
  #c(e, t) {
663
- return s`
663
+ return c`
664
664
  <div class="status">
665
665
  <div class="status-card">
666
666
  <span class="status-mark" aria-hidden="true"></span>
@@ -675,7 +675,7 @@ var p = (e = {}) => {
675
675
  }
676
676
  #u(e) {
677
677
  e.actionable && this.dispatchEvent(new CustomEvent("fellowship-cast-selected", {
678
- ...y,
678
+ ...b,
679
679
  detail: { cast: e }
680
680
  }));
681
681
  }
@@ -683,23 +683,23 @@ var p = (e = {}) => {
683
683
  #f;
684
684
  #p;
685
685
  };
686
- r([u({
686
+ i([d({
687
687
  type: String,
688
688
  attribute: "dungeon-id"
689
- })], b.prototype, "dungeonId", void 0), r([u({ attribute: !1 })], b.prototype, "selectedCast", void 0), r([u({ attribute: !1 })], b.prototype, "configuredCasts", void 0), r([u({
689
+ })], x.prototype, "dungeonId", void 0), i([d({ attribute: !1 })], x.prototype, "selectedCast", void 0), i([d({ attribute: !1 })], x.prototype, "configuredCasts", void 0), i([d({
690
690
  type: String,
691
691
  attribute: "configured-filter"
692
- })], b.prototype, "configuredFilter", void 0), r([u({
692
+ })], x.prototype, "configuredFilter", void 0), i([d({
693
693
  type: Boolean,
694
694
  reflect: !0
695
- })], b.prototype, "fill", void 0), r([u({
695
+ })], x.prototype, "fill", void 0), i([d({
696
696
  type: String,
697
697
  attribute: "asset-base-url"
698
- })], b.prototype, "assetBaseUrl", void 0), r([u({ attribute: !1 })], b.prototype, "dataSource", void 0), r([d()], b.prototype, "_status", void 0), r([d()], b.prototype, "_error", void 0), r([d()], b.prototype, "_model", void 0), r([d()], b.prototype, "_query", void 0), b = r([l("fellowship-dungeon-cast-browser")], b);
699
- var x = () => {
700
- globalThis.customElements !== void 0 && !globalThis.customElements.get("fellowship-dungeon-cast-browser") && globalThis.customElements.define("fellowship-dungeon-cast-browser", b);
698
+ })], x.prototype, "assetBaseUrl", void 0), i([d({ attribute: !1 })], x.prototype, "dataSource", void 0), i([f()], x.prototype, "_status", void 0), i([f()], x.prototype, "_error", void 0), i([f()], x.prototype, "_model", void 0), i([f()], x.prototype, "_query", void 0), x = i([u("fellowship-dungeon-cast-browser")], x);
699
+ var S = () => {
700
+ globalThis.customElements !== void 0 && !globalThis.customElements.get("fellowship-dungeon-cast-browser") && globalThis.customElements.define("fellowship-dungeon-cast-browser", x);
701
701
  };
702
702
  //#endregion
703
- export { p as a, v as i, x as n, h as r, b as t };
703
+ export { m as a, y as i, S as n, g as r, x as t };
704
704
 
705
- //# sourceMappingURL=dungeon-cast-browser-Cyh519NI.js.map
705
+ //# sourceMappingURL=dungeon-cast-browser-CSnu3gC5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dungeon-cast-browser-CSnu3gC5.js","names":["#abortController","#loadDungeonCasts","#renderStatus","#visibleEnemies","#handleSearch","#renderEnemy","#renderEmptySearch","#loadToken","#sameIdentity","#renderCast","#selectCast","#handleCastKeydown","#handleAbilityImageError","#statusCard"],"sources":["../../src/data/package-cast-data-source.ts","../../src/dungeon-cast-browser/dungeon-cast-browser.styles.ts","../../src/dungeon-cast-browser/render-model.ts","../../src/dungeon-cast-browser/dungeon-cast-browser.ts"],"sourcesContent":["import { createPackageFellowshipDataClient } from \"@crockery/fellowship-data/client\";\n\nimport type { FellowshipCastDataSource } from \"./cast-data-source.js\";\n\n/** @deprecated Create a package Fellowship data client instead. */\nexport interface PackageFellowshipCastDataSourceOptions {\n readonly assetBaseUrl?: string;\n}\n\n/** @deprecated Use `createPackageFellowshipDataClient` from `@crockery/fellowship-data/client`. */\nexport const createPackageFellowshipCastDataSource = (\n options: PackageFellowshipCastDataSourceOptions = {},\n): FellowshipCastDataSource => {\n const client = createPackageFellowshipDataClient(options);\n return {\n loadDungeonCasts: (dungeonId, signal) => client.loadDungeonCasts(dungeonId, signal),\n resolveAssetUrl: (asset) => client.resolveAssetUrl(asset),\n };\n};\n","import { css } from \"lit\";\n\nexport const dungeonCastBrowserStyles = css`\n :host {\n --fellowship-cast-canvas: var(--_fellowship-field-canvas);\n --fellowship-cast-surface: var(--_fellowship-field-surface);\n --fellowship-cast-raised: var(--_fellowship-field-surface-raised);\n --fellowship-cast-ink: var(--_fellowship-field-ink);\n --fellowship-cast-muted: var(--_fellowship-field-muted);\n --fellowship-cast-tertiary: var(--_fellowship-field-tertiary);\n --fellowship-cast-border: var(--_fellowship-field-border);\n --fellowship-cast-border-strong: var(--_fellowship-field-border-strong);\n --fellowship-cast-interrupt: var(--_fellowship-field-accent);\n --fellowship-cast-stop: var(--_fellowship-field-brass);\n --fellowship-cast-focus: var(--_fellowship-field-focus);\n --fellowship-cast-font-family: var(--_fellowship-field-font-family);\n --fellowship-cast-tactical-font-family: var(--_fellowship-field-mono-font-family);\n\n display: block;\n inline-size: 100%;\n min-block-size: 320px;\n color: var(--fellowship-cast-ink);\n font-family: var(--fellowship-cast-font-family);\n container-type: inline-size;\n -webkit-font-smoothing: antialiased;\n }\n\n :host([hidden]) {\n display: none;\n }\n\n :host([fill]) {\n min-block-size: 0;\n block-size: 100%;\n overflow: hidden;\n }\n\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n }\n\n .browser {\n min-block-size: inherit;\n overflow: hidden;\n border: 1px solid var(--fellowship-cast-border);\n border-radius: calc(var(--_fellowship-field-radius) + 2px);\n background: var(--fellowship-cast-canvas);\n }\n\n :host([fill]) .browser {\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n min-block-size: 0;\n block-size: 100%;\n }\n\n .toolbar {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 12px;\n align-items: end;\n padding: 16px;\n border-block-end: 1px solid var(--fellowship-cast-border);\n background: var(--fellowship-cast-surface);\n }\n\n .eyebrow,\n .summary,\n .enemy-id,\n .ability-id,\n .capability,\n .marker {\n font-family: var(--fellowship-cast-tactical-font-family);\n }\n\n .eyebrow {\n margin: 0 0 4px;\n color: var(--fellowship-cast-interrupt);\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.12em;\n text-transform: uppercase;\n }\n\n h2 {\n margin: 0;\n font-size: clamp(18px, 3cqi, 24px);\n font-weight: 600;\n letter-spacing: 0.01em;\n line-height: 1.08;\n }\n\n .summary {\n margin: 6px 0 0;\n color: var(--fellowship-cast-tertiary);\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n letter-spacing: 0.04em;\n }\n\n .search-label {\n display: grid;\n gap: 4px;\n min-inline-size: min(240px, 38cqi);\n color: var(--fellowship-cast-muted);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.04em;\n }\n\n .search-input {\n min-block-size: 44px;\n inline-size: 100%;\n border: 1px solid var(--fellowship-cast-border-strong);\n border-radius: var(--_fellowship-field-radius);\n background: var(--_fellowship-field-inset);\n color: var(--fellowship-cast-ink);\n font: inherit;\n font-size: 14px;\n padding-inline: 12px;\n }\n\n .search-input::placeholder {\n color: var(--fellowship-cast-tertiary);\n }\n\n .search-input:focus-visible,\n .cast-row:focus-visible,\n .retry-button:focus-visible {\n outline: 2px solid var(--fellowship-cast-focus);\n outline-offset: 2px;\n }\n\n .enemy-list {\n display: grid;\n }\n\n :host([fill]) .enemy-list {\n min-block-size: 0;\n align-content: start;\n overflow-y: auto;\n overscroll-behavior: contain;\n }\n\n .enemy {\n min-inline-size: 0;\n border-block-end: 1px solid var(--fellowship-cast-border);\n }\n\n .enemy:last-child {\n border-block-end: 0;\n }\n\n .enemy-header {\n display: grid;\n grid-template-columns: 4px minmax(0, 1fr) auto;\n gap: 12px;\n align-items: center;\n min-block-size: 52px;\n padding: 8px 16px;\n background: color-mix(in srgb, var(--fellowship-cast-raised) 72%, transparent);\n }\n\n .enemy-rule {\n align-self: stretch;\n background: var(--fellowship-cast-interrupt);\n }\n\n .enemy-name {\n overflow: hidden;\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n line-height: 1.15;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .enemy-id {\n overflow: hidden;\n margin: 3px 0 0;\n color: var(--fellowship-cast-tertiary);\n font-size: 10px;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .enemy-count {\n color: var(--fellowship-cast-muted);\n font-family: var(--fellowship-cast-tactical-font-family);\n font-size: 10px;\n font-variant-numeric: tabular-nums;\n }\n\n .cast-list {\n display: grid;\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .cast-list > li + li {\n border-block-start: 1px solid var(--fellowship-cast-border);\n }\n\n .cast-row {\n position: relative;\n display: grid;\n grid-template-columns: 40px minmax(0, 1fr) auto auto;\n gap: 12px;\n align-items: center;\n inline-size: 100%;\n min-block-size: 64px;\n padding: 8px 16px 8px 28px;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: start;\n cursor: pointer;\n transition: background-color 140ms cubic-bezier(0.23, 1, 0.32, 1);\n }\n\n .cast-row:not(:disabled):hover {\n background: color-mix(in srgb, var(--fellowship-cast-interrupt) 7%, transparent);\n }\n\n .cast-row[aria-pressed=\"true\"] {\n background: color-mix(in srgb, var(--fellowship-cast-interrupt) 11%, transparent);\n }\n\n .cast-row[aria-pressed=\"true\"]::before {\n position: absolute;\n inset: 12px auto 12px 0;\n inline-size: 3px;\n background: var(--fellowship-cast-interrupt);\n content: \"\";\n }\n\n .cast-row:disabled {\n color: var(--fellowship-cast-tertiary);\n cursor: not-allowed;\n }\n\n .ability-image,\n .ability-fallback {\n inline-size: 40px;\n block-size: 40px;\n border: 1px solid var(--fellowship-cast-border-strong);\n border-radius: 4px;\n background: var(--fellowship-cast-raised);\n }\n\n .ability-image {\n display: block;\n object-fit: cover;\n }\n\n .ability-fallback {\n display: grid;\n place-items: center;\n color: var(--fellowship-cast-muted);\n font-family: var(--fellowship-cast-tactical-font-family);\n font-size: 11px;\n font-weight: 600;\n }\n\n .ability-image[hidden],\n .ability-fallback[hidden] {\n display: none;\n }\n\n .ability-copy {\n min-inline-size: 0;\n }\n\n .ability-name {\n display: block;\n overflow: hidden;\n font-size: 14px;\n font-weight: 600;\n line-height: 1.15;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .ability-id {\n display: block;\n overflow: hidden;\n margin-block-start: 4px;\n color: var(--fellowship-cast-tertiary);\n font-size: 10px;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .capability {\n min-inline-size: 102px;\n padding: 5px 8px;\n border: 1px solid currentColor;\n border-radius: 999px;\n color: var(--fellowship-cast-interrupt);\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-align: center;\n white-space: nowrap;\n }\n\n .capability[data-kind=\"varies\"] {\n border-style: dashed;\n }\n\n .capability[data-kind=\"stop\"] {\n color: var(--fellowship-cast-stop);\n }\n\n .capability[data-kind=\"none\"] {\n color: var(--fellowship-cast-tertiary);\n }\n\n .marker {\n min-inline-size: 72px;\n color: var(--fellowship-cast-stop);\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.06em;\n text-align: end;\n text-transform: uppercase;\n }\n\n .marker[data-empty=\"true\"] {\n visibility: hidden;\n }\n\n .status {\n display: grid;\n min-block-size: 280px;\n padding: 32px;\n place-items: center;\n text-align: center;\n }\n\n :host([fill]) .status {\n min-block-size: 0;\n }\n\n .status-card {\n display: grid;\n max-inline-size: 360px;\n gap: 8px;\n justify-items: center;\n }\n\n .status-mark {\n inline-size: 32px;\n block-size: 4px;\n margin-block-end: 8px;\n background: var(--fellowship-cast-interrupt);\n }\n\n .status-title {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n }\n\n .status-copy {\n margin: 0;\n color: var(--fellowship-cast-muted);\n font-size: 14px;\n line-height: 1.45;\n }\n\n .retry-button {\n min-block-size: 44px;\n margin-block-start: 8px;\n padding-inline: 16px;\n border: 1px solid var(--fellowship-cast-interrupt);\n border-radius: var(--_fellowship-field-radius);\n background: transparent;\n color: var(--fellowship-cast-ink);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n }\n\n @container (max-width: 560px) {\n .toolbar {\n grid-template-columns: 1fr;\n }\n\n .search-label {\n min-inline-size: 0;\n }\n\n .cast-row {\n grid-template-columns: 40px minmax(0, 1fr) auto;\n padding-inline: 16px;\n }\n\n .marker {\n position: absolute;\n inset: 5px 8px auto auto;\n min-inline-size: 0;\n font-size: 8px;\n }\n\n .ability-id,\n .enemy-id {\n display: none;\n }\n\n .capability {\n min-inline-size: 0;\n padding-inline: 6px;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cast-row {\n transition: none;\n }\n }\n`;\n","import type { Ability, ImageAssetRef } from \"@crockery/fellowship-data\";\n\nimport type { DungeonCastData, FellowshipCastDataSource } from \"../data/cast-data-source.js\";\nimport type {\n CastCapabilityLabel,\n DungeonCastBrowserModel,\n DungeonCastEnemyModel,\n DungeonCastModel,\n FellowshipCastIdentity,\n} from \"./types.js\";\n\nexport const castIdentityKey = ({ enemyId, abilityId }: FellowshipCastIdentity): string =>\n `${enemyId}\\u0000${abilityId}`;\n\nconst abilityImage = (ability: Ability): ImageAssetRef | null =>\n ability.images.find(({ size }) => size === \"200\") ?? ability.images[0] ?? null;\n\nconst capabilityLabel = (\n canInterrupt: boolean,\n interruptVaries: boolean,\n canStop: boolean,\n): CastCapabilityLabel => {\n if (interruptVaries) return \"Interrupt varies\";\n if (canInterrupt) return \"Interrupt\";\n if (canStop) return \"Stop\";\n return \"No response\";\n};\n\nexport const createDungeonCastBrowserModel = (\n data: DungeonCastData,\n source: FellowshipCastDataSource,\n): DungeonCastBrowserModel => {\n const seenEnemyIds = new Set<string>();\n const enemies: DungeonCastEnemyModel[] = [];\n\n for (const placement of data.dungeon.enemies) {\n if (seenEnemyIds.has(placement.id)) continue;\n seenEnemyIds.add(placement.id);\n\n const enemy = data.enemies.get(placement.id);\n if (!enemy) continue;\n\n const casts: DungeonCastModel[] = (data.abilitiesByEnemy.get(enemy.id) ?? [])\n .filter((ability) => ability.castInterruptibility !== undefined)\n .map((ability) => {\n const canInterrupt = ability.castInterruptibility !== \"never\";\n const interruptVaries = ability.castInterruptibility === \"sometimes\";\n const canStop = enemy.canBeControlled;\n const image = abilityImage(ability);\n let imageUrl: string | null = null;\n if (image) {\n try {\n imageUrl = source.resolveAssetUrl(image);\n } catch {\n imageUrl = null;\n }\n }\n return {\n identity: { enemyId: enemy.id, abilityId: ability.id },\n ability,\n enemy,\n canInterrupt,\n interruptVaries,\n canStop,\n actionable: canInterrupt || canStop,\n capabilityLabel: capabilityLabel(canInterrupt, interruptVaries, canStop),\n imageUrl,\n };\n });\n\n if (casts.some(({ actionable }) => actionable)) enemies.push({ enemy, casts });\n }\n\n return {\n dungeon: data.dungeon,\n enemies,\n castCount: enemies.reduce((total, enemy) => total + enemy.casts.length, 0),\n };\n};\n","import { html, LitElement, nothing, type PropertyValues, type TemplateResult } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { repeat } from \"lit/directives/repeat.js\";\n\nimport type { FellowshipCastDataSource } from \"../data/cast-data-source.js\";\nimport { assertSupportedFellowshipDataSchema, FellowshipDataError } from \"../data/data-source.js\";\nimport { createPackageFellowshipCastDataSource } from \"../data/package-cast-data-source.js\";\nimport { installFieldManualFonts } from \"../styles/field-manual-fonts.js\";\nimport { fieldManualStyles } from \"../styles/field-manual.styles.js\";\nimport { dungeonCastBrowserStyles } from \"./dungeon-cast-browser.styles.js\";\nimport { castIdentityKey, createDungeonCastBrowserModel } from \"./render-model.js\";\nimport type {\n ConfiguredCastFilter,\n DungeonCastBrowserModel,\n DungeonCastEnemyModel,\n DungeonCastModel,\n FellowshipCastBrowserErrorDetail,\n FellowshipCastBrowserReadyDetail,\n FellowshipCastIdentity,\n FellowshipCastSelectedDetail,\n} from \"./types.js\";\n\ntype ComponentStatus = \"empty\" | \"loading\" | \"ready\" | \"error\";\n\nconst eventOptions = { bubbles: true, composed: true } as const;\n\n/**\n * @fires fellowship-cast-browser-ready - Fired after dungeon casts have been loaded and joined.\n * @fires fellowship-cast-browser-error - Fired when dungeon cast data cannot be loaded.\n * @fires fellowship-cast-selected - Fired when a user selects an actionable cast.\n */\n@customElement(\"fellowship-dungeon-cast-browser\")\nexport class FellowshipDungeonCastBrowserElement extends LitElement {\n static override styles = [fieldManualStyles, dungeonCastBrowserStyles];\n\n @property({ type: String, attribute: \"dungeon-id\" }) dungeonId = \"\";\n @property({ attribute: false }) selectedCast: FellowshipCastIdentity | null = null;\n @property({ attribute: false }) configuredCasts: readonly FellowshipCastIdentity[] = [];\n @property({ type: String, attribute: \"configured-filter\" })\n configuredFilter: ConfiguredCastFilter = \"all\";\n @property({ type: Boolean, reflect: true }) fill = false;\n @property({ type: String, attribute: \"asset-base-url\" }) assetBaseUrl: string | null = null;\n @property({ attribute: false }) dataSource: FellowshipCastDataSource | null = null;\n\n @state() private _status: ComponentStatus = \"empty\";\n @state() private _error: FellowshipCastBrowserErrorDetail | null = null;\n @state() private _model: DungeonCastBrowserModel | null = null;\n @state() private _query = \"\";\n\n #abortController: AbortController | null = null;\n #loadToken = 0;\n\n override connectedCallback(): void {\n super.connectedCallback();\n installFieldManualFonts(this.ownerDocument);\n }\n\n override disconnectedCallback(): void {\n this.#abortController?.abort();\n super.disconnectedCallback();\n }\n\n protected override updated(changed: PropertyValues<this>): void {\n super.updated(changed);\n if (changed.has(\"dungeonId\") || changed.has(\"dataSource\") || changed.has(\"assetBaseUrl\")) {\n queueMicrotask(() => {\n if (this.isConnected) void this.#loadDungeonCasts();\n });\n }\n }\n\n retry(): void {\n void this.#loadDungeonCasts();\n }\n\n get renderModel(): DungeonCastBrowserModel | null {\n return this._model;\n }\n\n override render(): TemplateResult {\n if (this._status !== \"ready\" || !this._model) {\n return html`<section class=\"browser\" aria-label=\"Dungeon cast browser\">${this.#renderStatus()}</section>`;\n }\n\n const visibleEnemies = this.#visibleEnemies(this._model);\n return html`\n <section class=\"browser\" aria-label=${`${this._model.dungeon.name ?? this._model.dungeon.id} casts`}>\n <header class=\"toolbar\" part=\"toolbar\">\n <div>\n <p class=\"eyebrow\">Dungeon cast index</p>\n <h2>${this._model.dungeon.name ?? this._model.dungeon.id}</h2>\n <p class=\"summary\">\n ${this._model.enemies.length} enemies · ${this._model.castCount} cast-bearing abilities\n </p>\n </div>\n <label class=\"search-label\">\n Search casts\n <input\n class=\"search-input\"\n type=\"search\"\n placeholder=\"Enemy or ability\"\n .value=${this._query}\n @input=${this.#handleSearch}\n />\n </label>\n </header>\n ${\n visibleEnemies.length > 0\n ? html`<div class=\"enemy-list\" part=\"enemy-list\">${repeat(\n visibleEnemies,\n ({ enemy }) => enemy.id,\n (enemy) => this.#renderEnemy(enemy),\n )}</div>`\n : this.#renderEmptySearch()\n }\n </section>\n `;\n }\n\n async #loadDungeonCasts(): Promise<void> {\n const dungeonId = this.dungeonId.trim();\n const token = ++this.#loadToken;\n this.#abortController?.abort();\n this.#abortController = new AbortController();\n this._model = null;\n this._error = null;\n this._query = \"\";\n\n if (!dungeonId) {\n this._status = \"empty\";\n return;\n }\n\n this._status = \"loading\";\n const source =\n this.dataSource ??\n createPackageFellowshipCastDataSource(\n this.assetBaseUrl ? { assetBaseUrl: this.assetBaseUrl } : {},\n );\n\n try {\n const data = await source.loadDungeonCasts(dungeonId, this.#abortController.signal);\n if (token !== this.#loadToken || this.#abortController.signal.aborted) return;\n assertSupportedFellowshipDataSchema(data.manifest.schemaVersion);\n const model = createDungeonCastBrowserModel(data, source);\n this._model = model;\n this._status = \"ready\";\n this.dispatchEvent(\n new CustomEvent<FellowshipCastBrowserReadyDetail>(\"fellowship-cast-browser-ready\", {\n ...eventOptions,\n detail: { model, data },\n }),\n );\n } catch (error: unknown) {\n if (token !== this.#loadToken || this.#abortController.signal.aborted) return;\n const detail: FellowshipCastBrowserErrorDetail = {\n code:\n error instanceof FellowshipDataError\n ? error.code\n : ((error as { code?: string }).code ?? \"data-load-failed\"),\n message: error instanceof Error ? error.message : String(error),\n ...(error instanceof Error && error.cause !== undefined ? { cause: error.cause } : {}),\n };\n this._error = detail;\n this._status = \"error\";\n this.dispatchEvent(\n new CustomEvent<FellowshipCastBrowserErrorDetail>(\"fellowship-cast-browser-error\", {\n ...eventOptions,\n detail,\n }),\n );\n }\n }\n\n #visibleEnemies(model: DungeonCastBrowserModel): readonly DungeonCastEnemyModel[] {\n const query = this._query.trim().toLocaleLowerCase();\n const configuredFilter =\n this.configuredFilter === \"configured\" || this.configuredFilter === \"unconfigured\"\n ? this.configuredFilter\n : \"all\";\n return model.enemies.flatMap((enemy) => {\n const enemyMatches = `${enemy.enemy.name ?? \"\"} ${enemy.enemy.id}`\n .toLocaleLowerCase()\n .includes(query);\n const casts = enemy.casts.filter((cast) => {\n const queryMatches =\n !query ||\n enemyMatches ||\n `${cast.ability.name ?? \"\"} ${cast.ability.id}`.toLocaleLowerCase().includes(query);\n if (!queryMatches) return false;\n const configured = this.configuredCasts.some((identity) =>\n this.#sameIdentity(identity, cast.identity),\n );\n return (\n configuredFilter === \"all\" ||\n (configuredFilter === \"configured\" && configured) ||\n (configuredFilter === \"unconfigured\" && !configured)\n );\n });\n return casts.length > 0 ? [{ ...enemy, casts }] : [];\n });\n }\n\n #renderEnemy(model: DungeonCastEnemyModel): TemplateResult {\n return html`\n <article class=\"enemy\" part=\"enemy\">\n <header class=\"enemy-header\" part=\"enemy-header\">\n <span class=\"enemy-rule\" aria-hidden=\"true\"></span>\n <div>\n <h3 class=\"enemy-name\">${model.enemy.name ?? model.enemy.id}</h3>\n <p class=\"enemy-id\">${model.enemy.id}</p>\n </div>\n <span class=\"enemy-count\">${model.casts.length} ${model.casts.length === 1 ? \"cast\" : \"casts\"}</span>\n </header>\n <ul class=\"cast-list\">\n ${repeat(\n model.casts,\n ({ identity }) => castIdentityKey(identity),\n (cast) => html`<li>${this.#renderCast(cast)}</li>`,\n )}\n </ul>\n </article>\n `;\n }\n\n #renderCast(cast: DungeonCastModel): TemplateResult {\n const selected = this.#sameIdentity(this.selectedCast, cast.identity);\n const configured = this.configuredCasts.some((identity) =>\n this.#sameIdentity(identity, cast.identity),\n );\n const capabilityKind = cast.interruptVaries\n ? \"varies\"\n : cast.canInterrupt\n ? \"interrupt\"\n : cast.canStop\n ? \"stop\"\n : \"none\";\n const fallback = (cast.ability.name ?? cast.ability.id)\n .split(/\\s+/)\n .map((part) => part[0])\n .join(\"\")\n .slice(0, 2)\n .toUpperCase();\n\n return html`\n <button\n class=\"cast-row\"\n part=\"cast\"\n type=\"button\"\n ?disabled=${!cast.actionable}\n aria-pressed=${String(selected)}\n data-configured=${String(configured)}\n @click=${() => this.#selectCast(cast)}\n @keydown=${this.#handleCastKeydown}\n >\n ${\n cast.imageUrl\n ? html`<img\n class=\"ability-image\"\n part=\"cast-icon\"\n src=${cast.imageUrl}\n alt=\"\"\n @error=${this.#handleAbilityImageError}\n /><span\n class=\"ability-fallback\"\n part=\"cast-icon-fallback\"\n aria-hidden=\"true\"\n hidden\n >${fallback}</span\n >`\n : html`<span class=\"ability-fallback\" part=\"cast-icon-fallback\" aria-hidden=\"true\">${fallback}</span>`\n }\n <span class=\"ability-copy\">\n <span class=\"ability-name\">${cast.ability.name ?? cast.ability.id}</span>\n <span class=\"ability-id\">${cast.ability.id}</span>\n </span>\n <span class=\"capability\" data-kind=${capabilityKind}>${cast.capabilityLabel}</span>\n <span class=\"marker\" data-empty=${String(!configured)}>${configured ? \"Configured\" : nothing}</span>\n </button>\n `;\n }\n\n #renderStatus(): TemplateResult {\n if (this._status === \"loading\") {\n return this.#statusCard(\n \"Loading cast index\",\n \"Joining dungeon enemies with their cast data.\",\n );\n }\n if (this._status === \"error\") {\n return html`\n <div class=\"status\" role=\"alert\">\n <div class=\"status-card\">\n <span class=\"status-mark\" aria-hidden=\"true\"></span>\n <h2 class=\"status-title\">Cast data unavailable</h2>\n <p class=\"status-copy\">${this._error?.message ?? \"The dungeon cast index could not be loaded.\"}</p>\n <button class=\"retry-button\" type=\"button\" @click=${this.retry}>Retry</button>\n </div>\n </div>\n `;\n }\n if (this._status === \"ready\") {\n return this.#statusCard(\n \"No actionable casts\",\n \"This dungeon has no enemies with casts that can be interrupted or stopped.\",\n );\n }\n return this.#statusCard(\"Select a dungeon\", \"Choose a dungeon to inspect enemy casts.\");\n }\n\n #renderEmptySearch(): TemplateResult {\n return this.#statusCard(\n \"No matching casts\",\n `No enemy or ability matches “${this._query.trim()}”.`,\n );\n }\n\n #statusCard(title: string, copy: string): TemplateResult {\n return html`\n <div class=\"status\">\n <div class=\"status-card\">\n <span class=\"status-mark\" aria-hidden=\"true\"></span>\n <h2 class=\"status-title\">${title}</h2>\n <p class=\"status-copy\">${copy}</p>\n </div>\n </div>\n `;\n }\n\n #sameIdentity(left: FellowshipCastIdentity | null, right: FellowshipCastIdentity): boolean {\n return left?.enemyId === right.enemyId && left.abilityId === right.abilityId;\n }\n\n #selectCast(cast: DungeonCastModel): void {\n if (!cast.actionable) return;\n this.dispatchEvent(\n new CustomEvent<FellowshipCastSelectedDetail>(\"fellowship-cast-selected\", {\n ...eventOptions,\n detail: { cast },\n }),\n );\n }\n\n #handleSearch = (event: InputEvent): void => {\n this._query = (event.currentTarget as HTMLInputElement).value;\n };\n\n #handleAbilityImageError = (event: Event): void => {\n const image = event.currentTarget as HTMLImageElement;\n image.hidden = true;\n const fallback = image.nextElementSibling;\n if (fallback instanceof HTMLElement) fallback.hidden = false;\n };\n\n #handleCastKeydown = (event: KeyboardEvent): void => {\n const movement =\n event.key === \"ArrowDown\" || event.key === \"ArrowRight\"\n ? 1\n : event.key === \"ArrowUp\" || event.key === \"ArrowLeft\"\n ? -1\n : 0;\n if (movement === 0 && event.key !== \"Home\" && event.key !== \"End\") return;\n const buttons = [\n ...this.renderRoot.querySelectorAll<HTMLButtonElement>(\".cast-row:not(:disabled)\"),\n ];\n if (buttons.length === 0) return;\n const current = buttons.indexOf(event.currentTarget as HTMLButtonElement);\n const nextIndex =\n event.key === \"Home\"\n ? 0\n : event.key === \"End\"\n ? buttons.length - 1\n : (current + movement + buttons.length) % buttons.length;\n buttons[nextIndex]?.focus();\n event.preventDefault();\n };\n}\n\nexport const defineFellowshipDungeonCastBrowser = (): void => {\n if (\n typeof globalThis.customElements !== \"undefined\" &&\n !globalThis.customElements.get(\"fellowship-dungeon-cast-browser\")\n ) {\n globalThis.customElements.define(\n \"fellowship-dungeon-cast-browser\",\n FellowshipDungeonCastBrowserElement,\n );\n }\n};\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"fellowship-dungeon-cast-browser\": FellowshipDungeonCastBrowserElement;\n }\n}\n"],"mappings":"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"}