@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 +4 -2
- package/dist/chunks/data-source-XbksqUrw.js +9 -0
- package/dist/chunks/data-source-XbksqUrw.js.map +1 -0
- package/dist/chunks/decorate-B_ZTN9li.js.map +1 -1
- package/dist/chunks/{dungeon-cast-browser-Cyh519NI.js → dungeon-cast-browser-CSnu3gC5.js} +55 -55
- package/dist/chunks/dungeon-cast-browser-CSnu3gC5.js.map +1 -0
- package/dist/chunks/{dungeon-map-xFaPasVr.js → dungeon-map-CutIcCVP.js} +90 -91
- package/dist/chunks/dungeon-map-CutIcCVP.js.map +1 -0
- package/dist/chunks/{talent-calculator-CIPNbqK5.js → talent-calculator-Dxuc2dZ8.js} +89 -89
- package/dist/chunks/talent-calculator-Dxuc2dZ8.js.map +1 -0
- package/dist/data/data-source.d.ts +3 -1
- package/dist/data/data-source.d.ts.map +1 -1
- package/dist/dungeon-cast-browser/dungeon-cast-browser.d.ts.map +1 -1
- package/dist/dungeon-cast-browser.js +1 -1
- package/dist/dungeon-map/dungeon-map.d.ts.map +1 -1
- package/dist/dungeon-map.js +1 -1
- package/dist/index.js +4 -4
- package/dist/react/dungeon-cast-browser.js +1 -1
- package/dist/react/dungeon-map.js +1 -1
- package/dist/react/talent-calculator.js +1 -1
- package/dist/talent-calculator/talent-calculator.d.ts.map +1 -1
- package/dist/talent-calculator.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/data-source-C-Gs7kRl.js +0 -2
- package/dist/chunks/dungeon-cast-browser-Cyh519NI.js.map +0 -1
- package/dist/chunks/dungeon-map-xFaPasVr.js.map +0 -1
- package/dist/chunks/talent-calculator-CIPNbqK5.js.map +0 -1
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
|
|
98
|
-
|
|
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.
|
|
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 {
|
|
2
|
-
import { n
|
|
3
|
-
import { createPackageFellowshipDataClient as
|
|
4
|
-
import { LitElement as
|
|
5
|
-
import { customElement as
|
|
6
|
-
import { repeat as
|
|
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
|
|
9
|
-
let t =
|
|
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
|
-
},
|
|
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
|
-
`,
|
|
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 =
|
|
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:
|
|
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
|
-
},
|
|
477
|
+
}, b = {
|
|
478
478
|
bubbles: !0,
|
|
479
479
|
composed: !0
|
|
480
|
-
},
|
|
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 = [
|
|
499
|
+
this.styles = [r, h];
|
|
500
500
|
}
|
|
501
501
|
#e;
|
|
502
502
|
#t;
|
|
503
503
|
connectedCallback() {
|
|
504
|
-
super.connectedCallback(),
|
|
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
|
|
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
|
|
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 ?
|
|
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
|
|
550
|
-
if (this.#e?.abort(), this.#e = new AbortController(), this._model = null, this._error = null, this._query = "", !
|
|
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
|
|
555
|
+
let i = this.dataSource ?? m(this.assetBaseUrl ? { assetBaseUrl: this.assetBaseUrl } : {});
|
|
556
556
|
try {
|
|
557
|
-
let
|
|
558
|
-
if (
|
|
559
|
-
|
|
560
|
-
let a =
|
|
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
|
-
...
|
|
562
|
+
...b,
|
|
563
563
|
detail: {
|
|
564
564
|
model: a,
|
|
565
|
-
data:
|
|
565
|
+
data: t
|
|
566
566
|
}
|
|
567
567
|
}));
|
|
568
|
-
} catch (
|
|
569
|
-
if (
|
|
570
|
-
let
|
|
571
|
-
code:
|
|
572
|
-
message:
|
|
573
|
-
...
|
|
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 =
|
|
576
|
-
...
|
|
577
|
-
detail:
|
|
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
|
|
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
|
-
${
|
|
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
|
|
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 ?
|
|
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
|
-
>` :
|
|
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" :
|
|
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" ?
|
|
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
|
|
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
|
-
...
|
|
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
|
-
|
|
686
|
+
i([d({
|
|
687
687
|
type: String,
|
|
688
688
|
attribute: "dungeon-id"
|
|
689
|
-
})],
|
|
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
|
-
})],
|
|
692
|
+
})], x.prototype, "configuredFilter", void 0), i([d({
|
|
693
693
|
type: Boolean,
|
|
694
694
|
reflect: !0
|
|
695
|
-
})],
|
|
695
|
+
})], x.prototype, "fill", void 0), i([d({
|
|
696
696
|
type: String,
|
|
697
697
|
attribute: "asset-base-url"
|
|
698
|
-
})],
|
|
699
|
-
var
|
|
700
|
-
globalThis.customElements !== void 0 && !globalThis.customElements.get("fellowship-dungeon-cast-browser") && globalThis.customElements.define("fellowship-dungeon-cast-browser",
|
|
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 {
|
|
703
|
+
export { m as a, y as i, S as n, g as r, x as t };
|
|
704
704
|
|
|
705
|
-
//# sourceMappingURL=dungeon-cast-browser-
|
|
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":";;;;;;;AAUA,IAAa,KACX,IAAkD,CAAC,MACtB;CAC7B,IAAM,IAAS,EAAkC,CAAO;CACxD,OAAO;EACL,mBAAmB,GAAW,MAAW,EAAO,iBAAiB,GAAW,CAAM;EAClF,kBAAkB,MAAU,EAAO,gBAAgB,CAAK;CAC1D;AACF,GChBa,IAA2B,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GCS9B,KAAmB,EAAE,YAAS,mBACzC,GAAG,EAAQ,QAAQ,KAEf,KAAgB,MACpB,EAAQ,OAAO,MAAM,EAAE,cAAW,MAAS,KAAK,KAAK,EAAQ,OAAO,MAAM,MAEtE,KACJ,GACA,GACA,MAEI,IAAwB,qBACxB,IAAqB,cACrB,IAAgB,SACb,eAGI,KACX,GACA,MAC4B;CAC5B,IAAM,oBAAe,IAAI,IAAY,GAC/B,IAAmC,CAAC;CAE1C,KAAK,IAAM,KAAa,EAAK,QAAQ,SAAS;EAC5C,IAAI,EAAa,IAAI,EAAU,EAAE,GAAG;EACpC,EAAa,IAAI,EAAU,EAAE;EAE7B,IAAM,IAAQ,EAAK,QAAQ,IAAI,EAAU,EAAE;EAC3C,IAAI,CAAC,GAAO;EAEZ,IAAM,KAA6B,EAAK,iBAAiB,IAAI,EAAM,EAAE,KAAK,CAAC,EAAA,CACxE,QAAQ,MAAY,EAAQ,yBAAyB,KAAA,CAAS,CAAC,CAC/D,KAAK,MAAY;GAChB,IAAM,IAAe,EAAQ,yBAAyB,SAChD,IAAkB,EAAQ,yBAAyB,aACnD,IAAU,EAAM,iBAChB,IAAQ,EAAa,CAAO,GAC9B,IAA0B;GAC9B,IAAI,GACF,IAAI;IACF,IAAW,EAAO,gBAAgB,CAAK;GACzC,QAAQ;IACN,IAAW;GACb;GAEF,OAAO;IACL,UAAU;KAAE,SAAS,EAAM;KAAI,WAAW,EAAQ;IAAG;IACrD;IACA;IACA;IACA;IACA;IACA,YAAY,KAAgB;IAC5B,iBAAiB,EAAgB,GAAc,GAAiB,CAAO;IACvE;GACF;EACF,CAAC;EAEH,AAAI,EAAM,MAAM,EAAE,oBAAiB,CAAU,KAAG,EAAQ,KAAK;GAAE;GAAO;EAAM,CAAC;CAC/E;CAEA,OAAO;EACL,SAAS,EAAK;EACd;EACA,WAAW,EAAQ,QAAQ,GAAO,MAAU,IAAQ,EAAM,MAAM,QAAQ,CAAC;CAC3E;AACF,GCtDM,IAAe;CAAE,SAAS;CAAM,UAAU;AAAK,GAQ9C,IAAA,cAAkD,EAAW;;gCAGD,wBACa,6BACO,CAAC,2BAE7C,mBACU,wBACoC,wBACT,qBAElC,uBACuB,oBACT,oBAChC,cAEiB,gBAC9B,cAqSI,MAA4B;GAC3C,KAAK,SAAU,EAAM,cAAmC;EAC1D,cAE4B,MAAuB;GACjD,IAAM,IAAQ,EAAM;GACpB,EAAM,SAAS;GACf,IAAM,IAAW,EAAM;GACvB,AAAI,aAAoB,gBAAa,EAAS,SAAS;EACzD,cAEsB,MAA+B;GACnD,IAAM,IACJ,EAAM,QAAQ,eAAe,EAAM,QAAQ,eACvC,IACA,EAAM,QAAQ,aAAa,EAAM,QAAQ,cACvC,KACA;GACR,IAAI,MAAa,KAAK,EAAM,QAAQ,UAAU,EAAM,QAAQ,OAAO;GACnE,IAAM,IAAU,CACd,GAAG,KAAK,WAAW,iBAAoC,0BAA0B,CACnF;GACA,IAAI,EAAQ,WAAW,GAAG;GAC1B,IAAM,IAAU,EAAQ,QAAQ,EAAM,aAAkC;GAQxE,AADA,EALE,EAAM,QAAQ,SACV,IACA,EAAM,QAAQ,QACZ,EAAQ,SAAS,KAChB,IAAU,IAAW,EAAQ,UAAU,EAAQ,OACtC,EAAE,MAAM,GAC1B,EAAM,eAAe;EACvB;;;gBAtVyB,CAAC,GAAmB,CAAwB;;CAgBrE;CACA;CAEA,oBAAmC;EAEjC,AADA,MAAM,kBAAkB,GACxB,EAAwB,KAAK,aAAa;CAC5C;CAEA,uBAAsC;EAEpC,AADA,KAAKA,IAAkB,MAAM,GAC7B,MAAM,qBAAqB;CAC7B;CAEA,QAA2B,GAAqC;EAE9D,AADA,MAAM,QAAQ,CAAO,IACjB,EAAQ,IAAI,WAAW,KAAK,EAAQ,IAAI,YAAY,KAAK,EAAQ,IAAI,cAAc,MACrF,qBAAqB;GACnB,AAAI,KAAK,eAAa,KAAUC,GAAkB;EACpD,CAAC;CAEL;CAEA,QAAc;EACZ,KAAUA,GAAkB;CAC9B;CAEA,IAAI,cAA8C;EAChD,OAAO,KAAK;CACd;CAEA,SAAkC;EAChC,IAAI,KAAK,YAAY,WAAW,CAAC,KAAK,QACpC,OAAO,CAAI,8DAA8D,KAAKC,GAAc,EAAE;EAGhG,IAAM,IAAiB,KAAKC,GAAgB,KAAK,MAAM;EACvD,OAAO,CAAI;4CAC6B,GAAG,KAAK,OAAO,QAAQ,QAAQ,KAAK,OAAO,QAAQ,GAAG,QAAQ;;;;kBAIxF,KAAK,OAAO,QAAQ,QAAQ,KAAK,OAAO,QAAQ,GAAG;;gBAErD,KAAK,OAAO,QAAQ,OAAO,aAAa,KAAK,OAAO,UAAU;;;;;;;;;uBASvD,KAAK,OAAO;uBACZ,KAAKC,GAAc;;;;UAKhC,EAAe,SAAS,IACpB,CAAI,6CAA6C,EAC/C,IACC,EAAE,eAAY,EAAM,KACpB,MAAU,KAAKC,GAAa,CAAK,CACpC,EAAE,UACF,KAAKC,GAAmB,EAC7B;;;CAGP;CAEA,MAAML,KAAmC;EACvC,IAAM,IAAY,KAAK,UAAU,KAAK,GAChC,IAAQ,EAAE,KAAKM;EAOrB,IANA,KAAKP,IAAkB,MAAM,GAC7B,KAAKA,KAAmB,IAAI,gBAAgB,GAC5C,KAAK,SAAS,MACd,KAAK,SAAS,MACd,KAAK,SAAS,IAEV,CAAC,GAAW;GACd,KAAK,UAAU;GACf;EACF;EAEA,KAAK,UAAU;EACf,IAAM,IACJ,KAAK,cACL,EACE,KAAK,eAAe,EAAE,cAAc,KAAK,aAAa,IAAI,CAAC,CAC7D;EAEF,IAAI;GACF,IAAM,IAAO,MAAM,EAAO,iBAAiB,GAAW,KAAKA,GAAiB,MAAM;GAClF,IAAI,MAAU,KAAKO,MAAc,KAAKP,GAAiB,OAAO,SAAS;GACvE,EAAoC,EAAK,SAAS,aAAa;GAC/D,IAAM,IAAQ,EAA8B,GAAM,CAAM;GAGxD,AAFA,KAAK,SAAS,GACd,KAAK,UAAU,SACf,KAAK,cACH,IAAI,YAA8C,iCAAiC;IACjF,GAAG;IACH,QAAQ;KAAE;KAAO;IAAK;GACxB,CAAC,CACH;EACF,SAAS,GAAgB;GACvB,IAAI,MAAU,KAAKO,MAAc,KAAKP,GAAiB,OAAO,SAAS;GACvE,IAAM,IAA2C;IAC/C,MACE,aAAiB,IACb,EAAM,OACJ,EAA4B,QAAQ;IAC5C,SAAS,aAAiB,QAAQ,EAAM,UAAU,OAAO,CAAK;IAC9D,GAAI,aAAiB,SAAS,EAAM,UAAU,KAAA,IAAY,EAAE,OAAO,EAAM,MAAM,IAAI,CAAC;GACtF;GAGA,AAFA,KAAK,SAAS,GACd,KAAK,UAAU,SACf,KAAK,cACH,IAAI,YAA8C,iCAAiC;IACjF,GAAG;IACH;GACF,CAAC,CACH;EACF;CACF;CAEA,GAAgB,GAAkE;EAChF,IAAM,IAAQ,KAAK,OAAO,KAAK,CAAC,CAAC,kBAAkB,GAC7C,IACJ,KAAK,qBAAqB,gBAAgB,KAAK,qBAAqB,iBAChE,KAAK,mBACL;EACN,OAAO,EAAM,QAAQ,SAAS,MAAU;GACtC,IAAM,IAAe,GAAG,EAAM,MAAM,QAAQ,GAAG,GAAG,EAAM,MAAM,KAC3D,kBAAkB,CAAC,CACnB,SAAS,CAAK,GACX,IAAQ,EAAM,MAAM,QAAQ,MAAS;IAKzC,IAAI,EAHF,CAAC,KACD,KACA,GAAG,EAAK,QAAQ,QAAQ,GAAG,GAAG,EAAK,QAAQ,KAAK,kBAAkB,CAAC,CAAC,SAAS,CAAK,IACjE,OAAO;IAC1B,IAAM,IAAa,KAAK,gBAAgB,MAAM,MAC5C,KAAKQ,GAAc,GAAU,EAAK,QAAQ,CAC5C;IACA,OACE,MAAqB,SACpB,MAAqB,gBAAgB,KACrC,MAAqB,kBAAkB,CAAC;GAE7C,CAAC;GACD,OAAO,EAAM,SAAS,IAAI,CAAC;IAAE,GAAG;IAAO;GAAM,CAAC,IAAI,CAAC;EACrD,CAAC;CACH;CAEA,GAAa,GAA8C;EACzD,OAAO,CAAI;;;;;qCAKsB,EAAM,MAAM,QAAQ,EAAM,MAAM,GAAG;kCACtC,EAAM,MAAM,GAAG;;sCAEX,EAAM,MAAM,OAAO,GAAG,EAAM,MAAM,WAAW,IAAI,SAAS,QAAQ;;;YAG5F,EACA,EAAM,QACL,EAAE,kBAAe,EAAgB,CAAQ,IACzC,MAAS,CAAI,OAAO,KAAKC,GAAY,CAAI,EAAE,MAC9C,EAAE;;;;CAIV;CAEA,GAAY,GAAwC;EAClD,IAAM,IAAW,KAAKD,GAAc,KAAK,cAAc,EAAK,QAAQ,GAC9D,IAAa,KAAK,gBAAgB,MAAM,MAC5C,KAAKA,GAAc,GAAU,EAAK,QAAQ,CAC5C,GACM,IAAiB,EAAK,kBACxB,WACA,EAAK,eACH,cACA,EAAK,UACH,SACA,QACF,KAAY,EAAK,QAAQ,QAAQ,EAAK,QAAQ,GAAA,CACjD,MAAM,KAAK,CAAC,CACZ,KAAK,MAAS,EAAK,EAAE,CAAC,CACtB,KAAK,EAAE,CAAC,CACR,MAAM,GAAG,CAAC,CAAC,CACX,YAAY;EAEf,OAAO,CAAI;;;;;oBAKK,CAAC,EAAK,WAAW;uBACd,OAAO,CAAQ,EAAE;0BACd,OAAO,CAAU,EAAE;uBACtB,KAAKE,GAAY,CAAI,EAAE;mBAC3B,KAAKC,GAAmB;;UAGjC,EAAK,WACD,CAAI;;;wBAGM,EAAK,SAAS;;2BAEX,KAAKC,GAAyB;;;;;;qBAMpC,EAAS;qBAEhB,CAAI,+EAA+E,EAAS,SACjG;;uCAE8B,EAAK,QAAQ,QAAQ,EAAK,QAAQ,GAAG;qCACvC,EAAK,QAAQ,GAAG;;6CAER,EAAe,GAAG,EAAK,gBAAgB;0CAC1C,OAAO,CAAC,CAAU,EAAE,GAAG,IAAa,eAAe,EAAQ;;;CAGnG;CAEA,KAAgC;EAyB9B,OAxBI,KAAK,YAAY,YACZ,KAAKC,GACV,sBACA,+CACF,IAEE,KAAK,YAAY,UACZ,CAAI;;;;;qCAKoB,KAAK,QAAQ,WAAW,8CAA8C;gEAC3C,KAAK,MAAM;;;UAKnE,KAAK,YAAY,UACZ,KAAKA,GACV,uBACA,4EACF,IAEK,KAAKA,GAAY,oBAAoB,0CAA0C;CACxF;CAEA,KAAqC;EACnC,OAAO,KAAKA,GACV,qBACA,gCAAgC,KAAK,OAAO,KAAK,EAAE,GACrD;CACF;CAEA,GAAY,GAAe,GAA8B;EACvD,OAAO,CAAI;;;;qCAIsB,EAAM;mCACR,EAAK;;;;CAItC;CAEA,GAAc,GAAqC,GAAwC;EACzF,OAAO,GAAM,YAAY,EAAM,WAAW,EAAK,cAAc,EAAM;CACrE;CAEA,GAAY,GAA8B;EACnC,EAAK,cACV,KAAK,cACH,IAAI,YAA0C,4BAA4B;GACxE,GAAG;GACH,QAAQ,EAAE,QAAK;EACjB,CAAC,CACH;CACF;CAEA;CAIA;CAOA;AAsBF;GArVG,EAAS;CAAE,MAAM;CAAQ,WAAW;AAAa,CAAC,CAAA,GAAA,EAAA,WAAA,aAAA,KAAA,CAAA,MAClD,EAAS,EAAE,WAAW,GAAM,CAAC,CAAA,GAAA,EAAA,WAAA,gBAAA,KAAA,CAAA,MAC7B,EAAS,EAAE,WAAW,GAAM,CAAC,CAAA,GAAA,EAAA,WAAA,mBAAA,KAAA,CAAA,MAC7B,EAAS;CAAE,MAAM;CAAQ,WAAW;AAAoB,CAAC,CAAA,GAAA,EAAA,WAAA,oBAAA,KAAA,CAAA,MAEzD,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,QAAA,KAAA,CAAA,MACzC,EAAS;CAAE,MAAM;CAAQ,WAAW;AAAiB,CAAC,CAAA,GAAA,EAAA,WAAA,gBAAA,KAAA,CAAA,MACtD,EAAS,EAAE,WAAW,GAAM,CAAC,CAAA,GAAA,EAAA,WAAA,cAAA,KAAA,CAAA,MAE7B,EAAM,CAAA,GAAA,EAAA,WAAA,WAAA,KAAA,CAAA,MACN,EAAM,CAAA,GAAA,EAAA,WAAA,UAAA,KAAA,CAAA,MACN,EAAM,CAAA,GAAA,EAAA,WAAA,UAAA,KAAA,CAAA,MACN,EAAM,CAAA,GAAA,EAAA,WAAA,UAAA,KAAA,CAAA,UAhBR,EAAc,iCAAiC,CAAA,GAAA,CAAA;AA2VhD,IAAa,UAAiD;CAC5D,AACS,WAAW,mBAAmB,UACrC,CAAC,WAAW,eAAe,IAAI,iCAAiC,KAEhE,WAAW,eAAe,OACxB,mCACA,CACF;AAEJ"}
|