@crockery/fellowship-components 0.4.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +40 -26
  2. package/RELEASING.md +15 -14
  3. package/THIRD_PARTY_LICENSES.md +12 -0
  4. package/dist/assets/dm-mono-latin-400-normal-4GdczIuU.woff2 +0 -0
  5. package/dist/assets/dm-mono-latin-500-normal-DRMDZjhP.woff2 +0 -0
  6. package/dist/assets/syne-latin-700-normal-AF3Rs61n.woff2 +0 -0
  7. package/dist/assets/syne-latin-800-normal-EehdNYzx.woff2 +0 -0
  8. package/dist/chunks/decorate-DyMgX_Uh.js +9 -0
  9. package/dist/chunks/{dungeon-cast-browser-CSnu3gC5.js → dungeon-cast-browser-DdG8klca.js} +62 -60
  10. package/dist/chunks/{dungeon-map-CutIcCVP.js → dungeon-map-D0-DAjZ9.js} +130 -133
  11. package/dist/chunks/{decorate-B_ZTN9li.js → field-manual-fonts-DTFloVFe.js} +18 -25
  12. package/dist/chunks/gear-planner-Bgt77Ovf.js +1696 -0
  13. package/dist/chunks/{talent-calculator-Dxuc2dZ8.js → talent-calculator-DbU6P1AP.js} +36 -37
  14. package/dist/chunks/tooltip-C3SSJw-t.js +482 -0
  15. package/dist/data/cast-data-source.d.ts +1 -2
  16. package/dist/data/data-source.d.ts +1 -2
  17. package/dist/data/package-cast-data-source.d.ts +1 -6
  18. package/dist/data/package-data-source.d.ts +1 -6
  19. package/dist/data/package-talent-data-source.d.ts +1 -6
  20. package/dist/data/talent-data-source.d.ts +1 -2
  21. package/dist/dungeon-cast-browser/dungeon-cast-browser.d.ts +2 -2
  22. package/dist/dungeon-cast-browser/dungeon-cast-browser.styles.d.ts +0 -1
  23. package/dist/dungeon-cast-browser/index.d.ts +0 -1
  24. package/dist/dungeon-cast-browser/render-model.d.ts +3 -3
  25. package/dist/dungeon-cast-browser/types.d.ts +2 -3
  26. package/dist/dungeon-cast-browser.js +1 -3
  27. package/dist/dungeon-map/dungeon-map.d.ts +2 -2
  28. package/dist/dungeon-map/dungeon-map.styles.d.ts +0 -1
  29. package/dist/dungeon-map/index.d.ts +0 -1
  30. package/dist/dungeon-map/layout.d.ts +0 -1
  31. package/dist/dungeon-map/render-model.d.ts +3 -4
  32. package/dist/dungeon-map/types.d.ts +2 -3
  33. package/dist/dungeon-map/viewport-controller.d.ts +0 -1
  34. package/dist/dungeon-map.js +1 -3
  35. package/dist/gear-planner/gear-planner.d.ts +36 -0
  36. package/dist/gear-planner/gear-planner.styles.d.ts +1 -0
  37. package/dist/gear-planner/gear-position.d.ts +19 -0
  38. package/dist/gear-planner/index.d.ts +2 -0
  39. package/dist/gear-planner/item-workbench.d.ts +18 -0
  40. package/dist/gear-planner/item-workbench.styles.d.ts +1 -0
  41. package/dist/gear-planner/types.d.ts +24 -0
  42. package/dist/gear-planner.js +5 -0
  43. package/dist/index.d.ts +6 -6
  44. package/dist/index.js +9 -7
  45. package/dist/react/dungeon-cast-browser.d.ts +8 -4
  46. package/dist/react/dungeon-cast-browser.js +11 -6
  47. package/dist/react/dungeon-map.d.ts +3 -2
  48. package/dist/react/dungeon-map.js +1 -3
  49. package/dist/react/gear-planner.d.ts +14 -0
  50. package/dist/react/gear-planner.js +23 -0
  51. package/dist/react/index.d.ts +2 -1
  52. package/dist/react/talent-calculator.d.ts +3 -2
  53. package/dist/react/talent-calculator.js +1 -3
  54. package/dist/react/tooltip.d.ts +0 -1
  55. package/dist/react/tooltip.js +1 -3
  56. package/dist/react.js +2 -1
  57. package/dist/styles/dungeon-poster-fonts.d.ts +2 -0
  58. package/dist/styles/dungeon-poster.styles.d.ts +7 -0
  59. package/dist/styles/field-manual-fonts.d.ts +0 -1
  60. package/dist/styles/field-manual.styles.d.ts +0 -1
  61. package/dist/talent-calculator/index.d.ts +0 -1
  62. package/dist/talent-calculator/render-model.d.ts +3 -3
  63. package/dist/talent-calculator/selection-state.d.ts +0 -1
  64. package/dist/talent-calculator/talent-calculator.d.ts +2 -2
  65. package/dist/talent-calculator/talent-calculator.styles.d.ts +0 -1
  66. package/dist/talent-calculator/types.d.ts +2 -3
  67. package/dist/talent-calculator.js +1 -3
  68. package/dist/tooltip/index.d.ts +0 -1
  69. package/dist/tooltip/positioning.d.ts +0 -1
  70. package/dist/tooltip/rich-text.d.ts +0 -1
  71. package/dist/tooltip/tooltip.d.ts +0 -1
  72. package/dist/tooltip/tooltip.styles.d.ts +0 -1
  73. package/dist/tooltip/types.d.ts +0 -1
  74. package/dist/tooltip.js +3 -5
  75. package/package.json +21 -15
  76. package/src/dungeon-cast-browser/README.md +10 -4
  77. package/src/dungeon-map/README.md +5 -6
  78. package/src/gear-planner/README.md +44 -0
  79. package/src/talent-calculator/README.md +5 -6
  80. package/src/tooltip/README.md +5 -6
  81. package/dist/chunks/data-source-XbksqUrw.js +0 -9
  82. package/dist/chunks/data-source-XbksqUrw.js.map +0 -1
  83. package/dist/chunks/decorate-B_ZTN9li.js.map +0 -1
  84. package/dist/chunks/dungeon-cast-browser-CSnu3gC5.js.map +0 -1
  85. package/dist/chunks/dungeon-map-CutIcCVP.js.map +0 -1
  86. package/dist/chunks/talent-calculator-Dxuc2dZ8.js.map +0 -1
  87. package/dist/chunks/tooltip-DoQVSnOn.js +0 -412
  88. package/dist/chunks/tooltip-DoQVSnOn.js.map +0 -1
  89. package/dist/data/cast-data-source.d.ts.map +0 -1
  90. package/dist/data/data-source.d.ts.map +0 -1
  91. package/dist/data/package-cast-data-source.d.ts.map +0 -1
  92. package/dist/data/package-data-source.d.ts.map +0 -1
  93. package/dist/data/package-talent-data-source.d.ts.map +0 -1
  94. package/dist/data/talent-data-source.d.ts.map +0 -1
  95. package/dist/dungeon-cast-browser/dungeon-cast-browser.d.ts.map +0 -1
  96. package/dist/dungeon-cast-browser/dungeon-cast-browser.styles.d.ts.map +0 -1
  97. package/dist/dungeon-cast-browser/index.d.ts.map +0 -1
  98. package/dist/dungeon-cast-browser/render-model.d.ts.map +0 -1
  99. package/dist/dungeon-cast-browser/types.d.ts.map +0 -1
  100. package/dist/dungeon-cast-browser.js.map +0 -1
  101. package/dist/dungeon-map/dungeon-map.d.ts.map +0 -1
  102. package/dist/dungeon-map/dungeon-map.styles.d.ts.map +0 -1
  103. package/dist/dungeon-map/index.d.ts.map +0 -1
  104. package/dist/dungeon-map/layout.d.ts.map +0 -1
  105. package/dist/dungeon-map/render-model.d.ts.map +0 -1
  106. package/dist/dungeon-map/types.d.ts.map +0 -1
  107. package/dist/dungeon-map/viewport-controller.d.ts.map +0 -1
  108. package/dist/dungeon-map.js.map +0 -1
  109. package/dist/index.d.ts.map +0 -1
  110. package/dist/react/dungeon-cast-browser.d.ts.map +0 -1
  111. package/dist/react/dungeon-cast-browser.js.map +0 -1
  112. package/dist/react/dungeon-map.d.ts.map +0 -1
  113. package/dist/react/dungeon-map.js.map +0 -1
  114. package/dist/react/index.d.ts.map +0 -1
  115. package/dist/react/talent-calculator.d.ts.map +0 -1
  116. package/dist/react/talent-calculator.js.map +0 -1
  117. package/dist/react/tooltip.d.ts.map +0 -1
  118. package/dist/react/tooltip.js.map +0 -1
  119. package/dist/styles/field-manual-fonts.d.ts.map +0 -1
  120. package/dist/styles/field-manual.styles.d.ts.map +0 -1
  121. package/dist/talent-calculator/index.d.ts.map +0 -1
  122. package/dist/talent-calculator/render-model.d.ts.map +0 -1
  123. package/dist/talent-calculator/selection-state.d.ts.map +0 -1
  124. package/dist/talent-calculator/talent-calculator.d.ts.map +0 -1
  125. package/dist/talent-calculator/talent-calculator.styles.d.ts.map +0 -1
  126. package/dist/talent-calculator/types.d.ts.map +0 -1
  127. package/dist/talent-calculator.js.map +0 -1
  128. package/dist/tooltip/index.d.ts.map +0 -1
  129. package/dist/tooltip/positioning.d.ts.map +0 -1
  130. package/dist/tooltip/rich-text.d.ts.map +0 -1
  131. package/dist/tooltip/tooltip.d.ts.map +0 -1
  132. package/dist/tooltip/tooltip.styles.d.ts.map +0 -1
  133. package/dist/tooltip/types.d.ts.map +0 -1
  134. package/dist/tooltip.js.map +0 -1
package/README.md CHANGED
@@ -11,17 +11,19 @@ npm install @crockery/fellowship-components
11
11
  pnpm add @crockery/fellowship-components
12
12
  ```
13
13
 
14
- The data package is installed automatically. Components use its shared lazy client, while image
15
- URLs use the installed data package's version-pinned CDN by default. Your application lockfile
16
- therefore selects both the exact data and its matching assets.
14
+ The data package is installed automatically. Components use its shared lazy
15
+ client, while each application supplies a `resolveAssetUrl` callback for images
16
+ it hosts. Components never contact a Fellowship image CDN implicitly.
17
17
 
18
18
  ## Components
19
19
 
20
- | Component | Package entry point | Documentation |
21
- | -------------------------------- | --------------------------------------------------- | ---------------------------------------------------- |
22
- | `<fellowship-dungeon-map>` | `@crockery/fellowship-components/dungeon-map` | [Dungeon map](src/dungeon-map/README.md) |
23
- | `<fellowship-talent-calculator>` | `@crockery/fellowship-components/talent-calculator` | [Talent calculator](src/talent-calculator/README.md) |
24
- | `<fellowship-tooltip>` | `@crockery/fellowship-components/tooltip` | [Tooltip](src/tooltip/README.md) |
20
+ | Component | Package entry point | Documentation |
21
+ | ----------------------------------- | ------------------------------------------------------ | ---------------------------------------------------------- |
22
+ | `<fellowship-dungeon-map>` | `@crockery/fellowship-components/dungeon-map` | [Dungeon map](src/dungeon-map/README.md) |
23
+ | `<fellowship-dungeon-cast-browser>` | `@crockery/fellowship-components/dungeon-cast-browser` | [Dungeon cast browser](src/dungeon-cast-browser/README.md) |
24
+ | `<fellowship-talent-calculator>` | `@crockery/fellowship-components/talent-calculator` | [Talent calculator](src/talent-calculator/README.md) |
25
+ | `<fellowship-tooltip>` | `@crockery/fellowship-components/tooltip` | [Tooltip](src/tooltip/README.md) |
26
+ | `<fellowship-gear-planner>` | `@crockery/fellowship-components/gear-planner` | [Gear planner](src/gear-planner/README.md) |
25
27
 
26
28
  Importing the package root registers every web component:
27
29
 
@@ -36,9 +38,11 @@ Import React wrappers from component-specific entry points so applications only
36
38
  implementations they use:
37
39
 
38
40
  ```tsx
41
+ import { DungeonCastBrowser } from "@crockery/fellowship-components/react/dungeon-cast-browser";
39
42
  import { DungeonMapViewer } from "@crockery/fellowship-components/react/dungeon-map";
40
43
  import { TalentCalculator } from "@crockery/fellowship-components/react/talent-calculator";
41
44
  import { Tooltip } from "@crockery/fellowship-components/react/tooltip";
45
+ import { GearPlanner } from "@crockery/fellowship-components/react/gear-planner";
42
46
  ```
43
47
 
44
48
  Each component entry also provides the component as its default export for `React.lazy`:
@@ -51,7 +55,7 @@ const DungeonMapViewer = lazy(
51
55
  );
52
56
  ```
53
57
 
54
- The `@crockery/fellowship-components/react` convenience entry still exports all three wrappers,
58
+ The `@crockery/fellowship-components/react` convenience entry still exports every wrapper,
55
59
  but importing it registers and loads every component implementation.
56
60
 
57
61
  Each component document covers its Lit and React APIs, custom data sources, events, methods,
@@ -92,41 +96,51 @@ interface and tactical stacks. The package ships six local IBM Plex WOFF2 assets
92
96
  total), registers them as `Fellowship Field` and `Fellowship Tactical`, and makes no remote font
93
97
  request. See `THIRD_PARTY_LICENSES.md` for the SIL Open Font License notice.
94
98
 
99
+ ## Dungeon Poster theme
100
+
101
+ Gear Planner and Tooltip use the flat Dungeon Poster foundation. Override
102
+ `--fellowship-poster-cream`, `--fellowship-poster-violet`,
103
+ `--fellowship-poster-yellow`, `--fellowship-poster-plum`, display/mono font,
104
+ seam, radius, shadow, focus, and motion tokens on an ancestor or component host.
105
+ The package bundles four Syne and DM Mono WOFF2 assets for this foundation.
106
+ Legacy map, cast, and talent surfaces retain Expedition Field Manual.
107
+
95
108
  ## Data and asset versions
96
109
 
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.
110
+ Components declares a normal caret dependency on the corresponding
111
+ `@crockery/fellowship-data` release and requires manifest schema 2. The
112
+ monorepo workspace keeps Components and Data changes atomic; published packages
113
+ retain independent versions.
101
114
 
102
115
  Dataset JSON stays out of the component library's initial JavaScript path and published tarball.
103
116
  Each data-driven component supports:
104
117
 
105
- - `assetBaseUrl` for self-hosted package assets.
118
+ - A required `resolveAssetUrl(asset)` property for application-hosted images.
106
119
  - A component-specific `dataSource` property for remote, filtered, experimental, or
107
120
  application-owned data.
108
121
 
109
122
  See the relevant component document for the provider contract.
110
123
 
111
- The legacy component-specific data-source types and package factories remain available as
112
- deprecated structural adapters for the 0.x release line. New integrations should use
113
- `createPackageFellowshipDataClient` from `@crockery/fellowship-data/client` and pass the relevant
114
- client methods through `dataSource`.
124
+ The component-specific data-source types and package factories remain
125
+ load-only structural adapters. New integrations should use
126
+ `createPackageFellowshipDataClient` from `@crockery/fellowship-data/client` and
127
+ pass the relevant client methods through `dataSource`.
115
128
 
116
129
  ## Development
117
130
 
118
131
  ```sh
119
- pnpm install
120
- pnpm ladle
121
- pnpm test
122
- pnpm build
123
- pnpm pack:check
132
+ pnpm install --frozen-lockfile
133
+ pnpm dev:components
134
+ pnpm --filter @crockery/fellowship-components test
135
+ pnpm --filter @crockery/fellowship-components build
136
+ pnpm --filter @crockery/fellowship-components pack:check
124
137
  ```
125
138
 
126
139
  Current Chromium, Firefox, and Safari/WebKit are supported. Add a Changeset with
127
- `pnpm changeset` for every user-facing change; merging the generated release PR publishes the
128
- package with npm provenance after trusted publishing is enabled. Maintainers should follow
129
- [`RELEASING.md`](RELEASING.md) for the first publish and release automation.
140
+ `pnpm changeset` from the monorepo root for every user-facing change. Merging
141
+ the generated version pull request publishes through trusted OIDC publishing.
142
+ The private repository means npm provenance attestations are unavailable.
143
+ Maintainers should follow [`RELEASING.md`](RELEASING.md).
130
144
 
131
145
  ## License
132
146
 
package/RELEASING.md CHANGED
@@ -1,14 +1,16 @@
1
- # Releasing fellowship-components
1
+ # Releasing Fellowship packages
2
2
 
3
- Changesets owns package versions and changelog entries. Add a changeset for every consumer-facing
4
- change:
3
+ The private `Crockery/fellowscript` monorepo owns Data and Components releases.
4
+ Run Changesets from its root for every consumer-facing change:
5
5
 
6
6
  ```sh
7
7
  pnpm changeset
8
8
  ```
9
9
 
10
- The Release workflow maintains a `changeset-release/main` pull request. Merging that pull request
11
- publishes the new version to npm automatically through trusted publishing.
10
+ The root Release workflow maintains one Changesets version pull request against
11
+ `master`. Merging it publishes independently versioned packages in dependency
12
+ order. If Data is changing, its R2 assets are uploaded and verified before npm
13
+ publishing begins.
12
14
 
13
15
  ## Trusted publishing
14
16
 
@@ -16,23 +18,22 @@ Trusted publishing is enabled on npm with:
16
18
 
17
19
  - Provider: GitHub Actions
18
20
  - Organization or user: `Crockery`
19
- - Repository: `fellowship-components`
21
+ - Repository: `fellowscript`
20
22
  - Workflow filename: `release.yml`
21
23
  - Environment: none
22
24
  - Allowed action: `npm publish`
23
25
 
24
- The GitHub repository variable `NPM_TRUSTED_PUBLISHING_READY` is set to `true`. Keep it enabled and
25
- do not add an `NPM_TOKEN`: npm authenticates the release job through its GitHub OIDC identity and
26
- creates provenance automatically. Maintainers do not need to run `npm login`, `npm publish`, or
27
- create release tags manually.
26
+ Do not add an `NPM_TOKEN`: npm authenticates the release job through its GitHub
27
+ OIDC identity. npm does not create provenance attestations for public packages
28
+ published from a private repository.
28
29
 
29
30
  ## Routine releases
30
31
 
31
- 1. Merge consumer-facing changes and their changesets into `main`.
32
+ 1. Merge consumer-facing changes and their changesets into `master`.
32
33
  2. Review the Changesets version pull request, including its generated changelog.
33
- 3. Merge the version pull request after CI succeeds.
34
- 4. Confirm the Release workflow publishes the expected npm version and creates its tag, GitHub
35
- release, and npm provenance statement.
34
+ 3. Merge the version pull request after the full release verification succeeds.
35
+ 4. Confirm the latest asset archive's build/SHA metadata and the exact npm
36
+ versions before relying on the release.
36
37
 
37
38
  Never reuse a version number. If a release is defective, publish a corrective patch. Deprecate a
38
39
  bad version with `npm deprecate` when consumers need an explicit warning; unpublish only when npm's
@@ -1,5 +1,17 @@
1
1
  # Third-party licenses
2
2
 
3
+ ## Syne
4
+
5
+ The bundled Syne font files are copyright 2019 The Syne Project Authors
6
+ (https://gitlab.com/bonjour-monde/fonderie/syne-typeface) and are distributed
7
+ under the SIL Open Font License, Version 1.1.
8
+
9
+ ## DM Mono
10
+
11
+ The bundled DM Mono font files are copyright 2020 The DM Mono Project Authors
12
+ (https://www.github.com/googlefonts/dm-mono) and are distributed under the SIL
13
+ Open Font License, Version 1.1.
14
+
3
15
  ## IBM Plex
4
16
 
5
17
  The bundled IBM Plex Sans Condensed and IBM Plex Mono font files are copyright IBM Corp. and are
@@ -0,0 +1,9 @@
1
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/decorate.js
2
+ function e(e, t, n, r) {
3
+ var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
4
+ if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
5
+ else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
6
+ return i > 3 && a && Object.defineProperty(t, n, a), a;
7
+ }
8
+ //#endregion
9
+ export { e as t };
@@ -1,16 +1,13 @@
1
- import { n as e, t } from "./data-source-XbksqUrw.js";
2
- import { n, r, t as i } from "./decorate-B_ZTN9li.js";
1
+ import { i as e, n as t, r as n, t as r } from "./field-manual-fonts-DTFloVFe.js";
2
+ import { t as i } from "./decorate-DyMgX_Uh.js";
3
3
  import { createPackageFellowshipDataClient as a } from "@crockery/fellowship-data/client";
4
4
  import { LitElement as o, css as s, html as c, nothing as l } from "lit";
5
5
  import { customElement as u, property as d, state as f } from "lit/decorators.js";
6
6
  import { repeat as p } from "lit/directives/repeat.js";
7
7
  //#region src/data/package-cast-data-source.ts
8
- var m = (e = {}) => {
9
- let t = a(e);
10
- return {
11
- loadDungeonCasts: (e, n) => t.loadDungeonCasts(e, n),
12
- resolveAssetUrl: (e) => t.resolveAssetUrl(e)
13
- };
8
+ var m = () => {
9
+ let e = a();
10
+ return { loadDungeonCasts: (t, n) => e.loadDungeonCasts(t, n) };
14
11
  }, h = s`
15
12
  :host {
16
13
  --fellowship-cast-canvas: var(--_fellowship-field-canvas);
@@ -445,7 +442,7 @@ var m = (e = {}) => {
445
442
  let o = (e.abilitiesByEnemy.get(a.id) ?? []).filter((e) => e.castInterruptibility !== void 0).map((e) => {
446
443
  let n = e.castInterruptibility !== "never", r = e.castInterruptibility === "sometimes", i = a.canBeControlled, o = _(e), s = null;
447
444
  if (o) try {
448
- s = t.resolveAssetUrl(o);
445
+ s = t(o);
449
446
  } catch {
450
447
  s = null;
451
448
  }
@@ -479,14 +476,14 @@ var m = (e = {}) => {
479
476
  composed: !0
480
477
  }, x = class extends o {
481
478
  constructor(...e) {
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) => {
479
+ super(...e), this.dungeonId = "", this.selectedCast = null, this.configuredCasts = [], this.configuredFilter = "all", this.fill = !1, this.resolveAssetUrl = null, this.dataSource = null, this._status = "empty", this._error = null, this._model = null, this._query = "", this.#e = null, this.#t = 0, this.#f = (e) => {
483
480
  this._query = e.currentTarget.value;
484
- }, this.#f = (e) => {
481
+ }, this.#p = (e) => {
485
482
  let t = e.currentTarget;
486
483
  t.hidden = !0;
487
484
  let n = t.nextElementSibling;
488
485
  n instanceof HTMLElement && (n.hidden = !1);
489
- }, this.#p = (e) => {
486
+ }, this.#m = (e) => {
490
487
  let t = e.key === "ArrowDown" || e.key === "ArrowRight" ? 1 : e.key === "ArrowUp" || e.key === "ArrowLeft" ? -1 : 0;
491
488
  if (t === 0 && e.key !== "Home" && e.key !== "End") return;
492
489
  let n = [...this.renderRoot.querySelectorAll(".cast-row:not(:disabled)")];
@@ -496,18 +493,18 @@ var m = (e = {}) => {
496
493
  };
497
494
  }
498
495
  static {
499
- this.styles = [r, h];
496
+ this.styles = [t, h];
500
497
  }
501
498
  #e;
502
499
  #t;
503
500
  connectedCallback() {
504
- super.connectedCallback(), n(this.ownerDocument);
501
+ super.connectedCallback(), r(this.ownerDocument);
505
502
  }
506
503
  disconnectedCallback() {
507
504
  this.#e?.abort(), super.disconnectedCallback();
508
505
  }
509
506
  updated(e) {
510
- super.updated(e), (e.has("dungeonId") || e.has("dataSource") || e.has("assetBaseUrl")) && queueMicrotask(() => {
507
+ super.updated(e), (e.has("dungeonId") || e.has("dataSource") || e.has("resolveAssetUrl")) && queueMicrotask(() => {
511
508
  this.isConnected && this.#n();
512
509
  });
513
510
  }
@@ -518,8 +515,8 @@ var m = (e = {}) => {
518
515
  return this._model;
519
516
  }
520
517
  render() {
521
- if (this._status !== "ready" || !this._model) return c`<section class="browser" aria-label="Dungeon cast browser">${this.#o()}</section>`;
522
- let e = this.#r(this._model);
518
+ if (this._status !== "ready" || !this._model) return c`<section class="browser" aria-label="Dungeon cast browser">${this.#s()}</section>`;
519
+ let e = this.#i(this._model);
523
520
  return c`
524
521
  <section class="browser" aria-label=${`${this._model.dungeon.name ?? this._model.dungeon.id} casts`}>
525
522
  <header class="toolbar" part="toolbar">
@@ -537,53 +534,63 @@ var m = (e = {}) => {
537
534
  type="search"
538
535
  placeholder="Enemy or ability"
539
536
  .value=${this._query}
540
- @input=${this.#d}
537
+ @input=${this.#f}
541
538
  />
542
539
  </label>
543
540
  </header>
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()}
541
+ ${e.length > 0 ? c`<div class="enemy-list" part="enemy-list">${p(e, ({ enemy: e }) => e.id, (e) => this.#a(e))}</div>` : this.#c()}
545
542
  </section>
546
543
  `;
547
544
  }
548
545
  async #n() {
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) {
546
+ let t = this.dungeonId.trim(), n = ++this.#t;
547
+ if (this.#e?.abort(), this.#e = new AbortController(), this._model = null, this._error = null, this._query = "", !t) {
551
548
  this._status = "empty";
552
549
  return;
553
550
  }
551
+ if (!this.resolveAssetUrl) {
552
+ this.#r({
553
+ code: "asset-resolver-missing",
554
+ message: "A resolveAssetUrl callback is required to render Fellowship images."
555
+ });
556
+ return;
557
+ }
554
558
  this._status = "loading";
555
- let i = this.dataSource ?? m(this.assetBaseUrl ? { assetBaseUrl: this.assetBaseUrl } : {});
559
+ let r = this.dataSource ?? m();
556
560
  try {
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
+ let i = await r.loadDungeonCasts(t, this.#e.signal);
562
+ if (n !== this.#t || this.#e.signal.aborted) return;
563
+ e(i.manifest.schemaVersion);
564
+ let a = y(i, this.resolveAssetUrl);
561
565
  this._model = a, this._status = "ready", this.dispatchEvent(new CustomEvent("fellowship-cast-browser-ready", {
562
566
  ...b,
563
567
  detail: {
564
568
  model: a,
565
- data: t
569
+ data: i
566
570
  }
567
571
  }));
568
572
  } 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
- };
575
- this._error = n, this._status = "error", this.dispatchEvent(new CustomEvent("fellowship-cast-browser-error", {
576
- ...b,
577
- detail: n
578
- }));
573
+ if (n !== this.#t || this.#e.signal.aborted) return;
574
+ this.#r(e);
579
575
  }
580
576
  }
581
577
  #r(e) {
578
+ let t = {
579
+ code: e instanceof n ? e.code : e.code ?? "data-load-failed",
580
+ message: typeof e == "object" && e && "message" in e ? String(e.message) : e instanceof Error ? e.message : String(e),
581
+ ...e instanceof Error && e.cause !== void 0 ? { cause: e.cause } : {}
582
+ };
583
+ this._error = t, this._status = "error", this.dispatchEvent(new CustomEvent("fellowship-cast-browser-error", {
584
+ ...b,
585
+ detail: t
586
+ }));
587
+ }
588
+ #i(e) {
582
589
  let t = this._query.trim().toLocaleLowerCase(), n = this.configuredFilter === "configured" || this.configuredFilter === "unconfigured" ? this.configuredFilter : "all";
583
590
  return e.enemies.flatMap((e) => {
584
591
  let r = `${e.enemy.name ?? ""} ${e.enemy.id}`.toLocaleLowerCase().includes(t), i = e.casts.filter((e) => {
585
592
  if (!(!t || r || `${e.ability.name ?? ""} ${e.ability.id}`.toLocaleLowerCase().includes(t))) return !1;
586
- let i = this.configuredCasts.some((t) => this.#l(t, e.identity));
593
+ let i = this.configuredCasts.some((t) => this.#u(t, e.identity));
587
594
  return n === "all" || n === "configured" && i || n === "unconfigured" && !i;
588
595
  });
589
596
  return i.length > 0 ? [{
@@ -592,7 +599,7 @@ var m = (e = {}) => {
592
599
  }] : [];
593
600
  });
594
601
  }
595
- #i(e) {
602
+ #a(e) {
596
603
  return c`
597
604
  <article class="enemy" part="enemy">
598
605
  <header class="enemy-header" part="enemy-header">
@@ -604,13 +611,13 @@ var m = (e = {}) => {
604
611
  <span class="enemy-count">${e.casts.length} ${e.casts.length === 1 ? "cast" : "casts"}</span>
605
612
  </header>
606
613
  <ul class="cast-list">
607
- ${p(e.casts, ({ identity: e }) => g(e), (e) => c`<li>${this.#a(e)}</li>`)}
614
+ ${p(e.casts, ({ identity: e }) => g(e), (e) => c`<li>${this.#o(e)}</li>`)}
608
615
  </ul>
609
616
  </article>
610
617
  `;
611
618
  }
612
- #a(e) {
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();
619
+ #o(e) {
620
+ let t = this.#u(this.selectedCast, e.identity), n = this.configuredCasts.some((t) => this.#u(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
621
  return c`
615
622
  <button
616
623
  class="cast-row"
@@ -619,15 +626,15 @@ var m = (e = {}) => {
619
626
  ?disabled=${!e.actionable}
620
627
  aria-pressed=${String(t)}
621
628
  data-configured=${String(n)}
622
- @click=${() => this.#u(e)}
623
- @keydown=${this.#p}
629
+ @click=${() => this.#d(e)}
630
+ @keydown=${this.#m}
624
631
  >
625
632
  ${e.imageUrl ? c`<img
626
633
  class="ability-image"
627
634
  part="cast-icon"
628
635
  src=${e.imageUrl}
629
636
  alt=""
630
- @error=${this.#f}
637
+ @error=${this.#p}
631
638
  /><span
632
639
  class="ability-fallback"
633
640
  part="cast-icon-fallback"
@@ -644,8 +651,8 @@ var m = (e = {}) => {
644
651
  </button>
645
652
  `;
646
653
  }
647
- #o() {
648
- return this._status === "loading" ? this.#c("Loading cast index", "Joining dungeon enemies with their cast data.") : this._status === "error" ? c`
654
+ #s() {
655
+ return this._status === "loading" ? this.#l("Loading cast index", "Joining dungeon enemies with their cast data.") : this._status === "error" ? c`
649
656
  <div class="status" role="alert">
650
657
  <div class="status-card">
651
658
  <span class="status-mark" aria-hidden="true"></span>
@@ -654,12 +661,12 @@ var m = (e = {}) => {
654
661
  <button class="retry-button" type="button" @click=${this.retry}>Retry</button>
655
662
  </div>
656
663
  </div>
657
- ` : this._status === "ready" ? this.#c("No actionable casts", "This dungeon has no enemies with casts that can be interrupted or stopped.") : this.#c("Select a dungeon", "Choose a dungeon to inspect enemy casts.");
664
+ ` : this._status === "ready" ? this.#l("No actionable casts", "This dungeon has no enemies with casts that can be interrupted or stopped.") : this.#l("Select a dungeon", "Choose a dungeon to inspect enemy casts.");
658
665
  }
659
- #s() {
660
- return this.#c("No matching casts", `No enemy or ability matches “${this._query.trim()}”.`);
666
+ #c() {
667
+ return this.#l("No matching casts", `No enemy or ability matches “${this._query.trim()}”.`);
661
668
  }
662
- #c(e, t) {
669
+ #l(e, t) {
663
670
  return c`
664
671
  <div class="status">
665
672
  <div class="status-card">
@@ -670,18 +677,18 @@ var m = (e = {}) => {
670
677
  </div>
671
678
  `;
672
679
  }
673
- #l(e, t) {
680
+ #u(e, t) {
674
681
  return e?.enemyId === t.enemyId && e.abilityId === t.abilityId;
675
682
  }
676
- #u(e) {
683
+ #d(e) {
677
684
  e.actionable && this.dispatchEvent(new CustomEvent("fellowship-cast-selected", {
678
685
  ...b,
679
686
  detail: { cast: e }
680
687
  }));
681
688
  }
682
- #d;
683
689
  #f;
684
690
  #p;
691
+ #m;
685
692
  };
686
693
  i([d({
687
694
  type: String,
@@ -692,14 +699,9 @@ i([d({
692
699
  })], x.prototype, "configuredFilter", void 0), i([d({
693
700
  type: Boolean,
694
701
  reflect: !0
695
- })], x.prototype, "fill", void 0), i([d({
696
- type: String,
697
- attribute: "asset-base-url"
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);
702
+ })], x.prototype, "fill", void 0), i([d({ attribute: !1 })], x.prototype, "resolveAssetUrl", 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
703
  var S = () => {
700
704
  globalThis.customElements !== void 0 && !globalThis.customElements.get("fellowship-dungeon-cast-browser") && globalThis.customElements.define("fellowship-dungeon-cast-browser", x);
701
705
  };
702
706
  //#endregion
703
707
  export { m as a, y as i, S as n, g as r, x as t };
704
-
705
- //# sourceMappingURL=dungeon-cast-browser-CSnu3gC5.js.map