@crockery/fellowship-components 0.4.0 → 0.4.1

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 (107) hide show
  1. package/README.md +12 -12
  2. package/RELEASING.md +15 -14
  3. package/dist/chunks/data-source-XbksqUrw.js +0 -2
  4. package/dist/chunks/decorate-B_ZTN9li.js +0 -2
  5. package/dist/chunks/dungeon-cast-browser-CSnu3gC5.js +0 -2
  6. package/dist/chunks/dungeon-map-CutIcCVP.js +0 -2
  7. package/dist/chunks/talent-calculator-Dxuc2dZ8.js +0 -2
  8. package/dist/chunks/tooltip-DoQVSnOn.js +0 -2
  9. package/dist/data/cast-data-source.d.ts +0 -1
  10. package/dist/data/data-source.d.ts +0 -1
  11. package/dist/data/package-cast-data-source.d.ts +0 -1
  12. package/dist/data/package-data-source.d.ts +0 -1
  13. package/dist/data/package-talent-data-source.d.ts +0 -1
  14. package/dist/data/talent-data-source.d.ts +0 -1
  15. package/dist/dungeon-cast-browser/dungeon-cast-browser.d.ts +0 -1
  16. package/dist/dungeon-cast-browser/dungeon-cast-browser.styles.d.ts +0 -1
  17. package/dist/dungeon-cast-browser/index.d.ts +0 -1
  18. package/dist/dungeon-cast-browser/render-model.d.ts +0 -1
  19. package/dist/dungeon-cast-browser/types.d.ts +0 -1
  20. package/dist/dungeon-cast-browser.js +0 -2
  21. package/dist/dungeon-map/dungeon-map.d.ts +0 -1
  22. package/dist/dungeon-map/dungeon-map.styles.d.ts +0 -1
  23. package/dist/dungeon-map/index.d.ts +0 -1
  24. package/dist/dungeon-map/layout.d.ts +0 -1
  25. package/dist/dungeon-map/render-model.d.ts +0 -1
  26. package/dist/dungeon-map/types.d.ts +0 -1
  27. package/dist/dungeon-map/viewport-controller.d.ts +0 -1
  28. package/dist/dungeon-map.js +0 -2
  29. package/dist/index.d.ts +0 -1
  30. package/dist/react/dungeon-cast-browser.d.ts +0 -1
  31. package/dist/react/dungeon-cast-browser.js +0 -2
  32. package/dist/react/dungeon-map.d.ts +0 -1
  33. package/dist/react/dungeon-map.js +0 -2
  34. package/dist/react/index.d.ts +0 -1
  35. package/dist/react/talent-calculator.d.ts +0 -1
  36. package/dist/react/talent-calculator.js +0 -2
  37. package/dist/react/tooltip.d.ts +0 -1
  38. package/dist/react/tooltip.js +0 -2
  39. package/dist/styles/field-manual-fonts.d.ts +0 -1
  40. package/dist/styles/field-manual.styles.d.ts +0 -1
  41. package/dist/talent-calculator/index.d.ts +0 -1
  42. package/dist/talent-calculator/render-model.d.ts +0 -1
  43. package/dist/talent-calculator/selection-state.d.ts +0 -1
  44. package/dist/talent-calculator/talent-calculator.d.ts +0 -1
  45. package/dist/talent-calculator/talent-calculator.styles.d.ts +0 -1
  46. package/dist/talent-calculator/types.d.ts +0 -1
  47. package/dist/talent-calculator.js +0 -2
  48. package/dist/tooltip/index.d.ts +0 -1
  49. package/dist/tooltip/positioning.d.ts +0 -1
  50. package/dist/tooltip/rich-text.d.ts +0 -1
  51. package/dist/tooltip/tooltip.d.ts +0 -1
  52. package/dist/tooltip/tooltip.styles.d.ts +0 -1
  53. package/dist/tooltip/types.d.ts +0 -1
  54. package/dist/tooltip.js +0 -2
  55. package/package.json +8 -15
  56. package/dist/chunks/data-source-XbksqUrw.js.map +0 -1
  57. package/dist/chunks/decorate-B_ZTN9li.js.map +0 -1
  58. package/dist/chunks/dungeon-cast-browser-CSnu3gC5.js.map +0 -1
  59. package/dist/chunks/dungeon-map-CutIcCVP.js.map +0 -1
  60. package/dist/chunks/talent-calculator-Dxuc2dZ8.js.map +0 -1
  61. package/dist/chunks/tooltip-DoQVSnOn.js.map +0 -1
  62. package/dist/data/cast-data-source.d.ts.map +0 -1
  63. package/dist/data/data-source.d.ts.map +0 -1
  64. package/dist/data/package-cast-data-source.d.ts.map +0 -1
  65. package/dist/data/package-data-source.d.ts.map +0 -1
  66. package/dist/data/package-talent-data-source.d.ts.map +0 -1
  67. package/dist/data/talent-data-source.d.ts.map +0 -1
  68. package/dist/dungeon-cast-browser/dungeon-cast-browser.d.ts.map +0 -1
  69. package/dist/dungeon-cast-browser/dungeon-cast-browser.styles.d.ts.map +0 -1
  70. package/dist/dungeon-cast-browser/index.d.ts.map +0 -1
  71. package/dist/dungeon-cast-browser/render-model.d.ts.map +0 -1
  72. package/dist/dungeon-cast-browser/types.d.ts.map +0 -1
  73. package/dist/dungeon-cast-browser.js.map +0 -1
  74. package/dist/dungeon-map/dungeon-map.d.ts.map +0 -1
  75. package/dist/dungeon-map/dungeon-map.styles.d.ts.map +0 -1
  76. package/dist/dungeon-map/index.d.ts.map +0 -1
  77. package/dist/dungeon-map/layout.d.ts.map +0 -1
  78. package/dist/dungeon-map/render-model.d.ts.map +0 -1
  79. package/dist/dungeon-map/types.d.ts.map +0 -1
  80. package/dist/dungeon-map/viewport-controller.d.ts.map +0 -1
  81. package/dist/dungeon-map.js.map +0 -1
  82. package/dist/index.d.ts.map +0 -1
  83. package/dist/react/dungeon-cast-browser.d.ts.map +0 -1
  84. package/dist/react/dungeon-cast-browser.js.map +0 -1
  85. package/dist/react/dungeon-map.d.ts.map +0 -1
  86. package/dist/react/dungeon-map.js.map +0 -1
  87. package/dist/react/index.d.ts.map +0 -1
  88. package/dist/react/talent-calculator.d.ts.map +0 -1
  89. package/dist/react/talent-calculator.js.map +0 -1
  90. package/dist/react/tooltip.d.ts.map +0 -1
  91. package/dist/react/tooltip.js.map +0 -1
  92. package/dist/styles/field-manual-fonts.d.ts.map +0 -1
  93. package/dist/styles/field-manual.styles.d.ts.map +0 -1
  94. package/dist/talent-calculator/index.d.ts.map +0 -1
  95. package/dist/talent-calculator/render-model.d.ts.map +0 -1
  96. package/dist/talent-calculator/selection-state.d.ts.map +0 -1
  97. package/dist/talent-calculator/talent-calculator.d.ts.map +0 -1
  98. package/dist/talent-calculator/talent-calculator.styles.d.ts.map +0 -1
  99. package/dist/talent-calculator/types.d.ts.map +0 -1
  100. package/dist/talent-calculator.js.map +0 -1
  101. package/dist/tooltip/index.d.ts.map +0 -1
  102. package/dist/tooltip/positioning.d.ts.map +0 -1
  103. package/dist/tooltip/rich-text.d.ts.map +0 -1
  104. package/dist/tooltip/tooltip.d.ts.map +0 -1
  105. package/dist/tooltip/tooltip.styles.d.ts.map +0 -1
  106. package/dist/tooltip/types.d.ts.map +0 -1
  107. package/dist/tooltip.js.map +0 -1
package/README.md CHANGED
@@ -94,10 +94,9 @@ 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 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.
97
+ Version 0.4.1 targets `@crockery/fellowship-data@^2.0.0` and requires manifest
98
+ schema 2. The monorepo workspace keeps Components and Data changes atomic;
99
+ published packages retain independent versions.
101
100
 
102
101
  Dataset JSON stays out of the component library's initial JavaScript path and published tarball.
103
102
  Each data-driven component supports:
@@ -116,17 +115,18 @@ client methods through `dataSource`.
116
115
  ## Development
117
116
 
118
117
  ```sh
119
- pnpm install
120
- pnpm ladle
121
- pnpm test
122
- pnpm build
123
- pnpm pack:check
118
+ pnpm install --frozen-lockfile
119
+ pnpm dev:components
120
+ pnpm --filter @crockery/fellowship-components test
121
+ pnpm --filter @crockery/fellowship-components build
122
+ pnpm --filter @crockery/fellowship-components pack:check
124
123
  ```
125
124
 
126
125
  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.
126
+ `pnpm changeset` from the monorepo root for every user-facing change. Merging
127
+ the generated version pull request publishes through trusted OIDC publishing.
128
+ The private repository means npm provenance attestations are unavailable.
129
+ Maintainers should follow [`RELEASING.md`](RELEASING.md).
130
130
 
131
131
  ## License
132
132
 
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 Data's `_release.json` marker and exact npm versions before relying
36
+ 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
@@ -5,5 +5,3 @@ var t = 2, n = (n) => {
5
5
  };
6
6
  //#endregion
7
7
  export { n, e as t };
8
-
9
- //# sourceMappingURL=data-source-XbksqUrw.js.map
@@ -88,5 +88,3 @@ function d(e, t, n, r) {
88
88
  }
89
89
  //#endregion
90
90
  export { u as n, t as r, d as t };
91
-
92
- //# sourceMappingURL=decorate-B_ZTN9li.js.map
@@ -701,5 +701,3 @@ var S = () => {
701
701
  };
702
702
  //#endregion
703
703
  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
@@ -1114,5 +1114,3 @@ var I = () => {
1114
1114
  };
1115
1115
  //#endregion
1116
1116
  export { j as a, A as i, I as n, _ as o, N as r, F as t };
1117
-
1118
- //# sourceMappingURL=dungeon-map-CutIcCVP.js.map
@@ -1052,5 +1052,3 @@ var N = () => {
1052
1052
  };
1053
1053
  //#endregion
1054
1054
  export { E as a, C as c, _ as d, S as i, x as l, N as n, T as o, A as r, w as s, M as t, y as u };
1055
-
1056
- //# sourceMappingURL=talent-calculator-Dxuc2dZ8.js.map
@@ -408,5 +408,3 @@ var S = () => {
408
408
  };
409
409
  //#endregion
410
410
  export { g as a, h as i, S as n, v as r, x as t };
411
-
412
- //# sourceMappingURL=tooltip-DoQVSnOn.js.map
@@ -2,4 +2,3 @@ export type { DungeonCastData } from "@crockery/fellowship-data/client";
2
2
  import type { FellowshipDataClient } from "@crockery/fellowship-data/client";
3
3
  /** @deprecated Use the corresponding `FellowshipDataClient` methods. */
4
4
  export type FellowshipCastDataSource = Pick<FellowshipDataClient, "loadDungeonCasts" | "resolveAssetUrl">;
5
- //# sourceMappingURL=cast-data-source.d.ts.map
@@ -5,4 +5,3 @@ import type { FellowshipDataClient } from "@crockery/fellowship-data/client";
5
5
  export declare const assertSupportedFellowshipDataSchema: (schemaVersion: number) => void;
6
6
  /** @deprecated Use the corresponding `FellowshipDataClient` methods. */
7
7
  export type FellowshipDataSource = Pick<FellowshipDataClient, "loadDungeon" | "resolveAssetUrl">;
8
- //# sourceMappingURL=data-source.d.ts.map
@@ -5,4 +5,3 @@ export interface PackageFellowshipCastDataSourceOptions {
5
5
  }
6
6
  /** @deprecated Use `createPackageFellowshipDataClient` from `@crockery/fellowship-data/client`. */
7
7
  export declare const createPackageFellowshipCastDataSource: (options?: PackageFellowshipCastDataSourceOptions) => FellowshipCastDataSource;
8
- //# sourceMappingURL=package-cast-data-source.d.ts.map
@@ -5,4 +5,3 @@ export interface PackageFellowshipDataSourceOptions {
5
5
  }
6
6
  /** @deprecated Use `createPackageFellowshipDataClient` from `@crockery/fellowship-data/client`. */
7
7
  export declare const createPackageFellowshipDataSource: (options?: PackageFellowshipDataSourceOptions) => FellowshipDataSource;
8
- //# sourceMappingURL=package-data-source.d.ts.map
@@ -5,4 +5,3 @@ export interface PackageFellowshipTalentDataSourceOptions {
5
5
  }
6
6
  /** @deprecated Use `createPackageFellowshipDataClient` from `@crockery/fellowship-data/client`. */
7
7
  export declare const createPackageFellowshipTalentDataSource: (options?: PackageFellowshipTalentDataSourceOptions) => FellowshipTalentDataSource;
8
- //# sourceMappingURL=package-talent-data-source.d.ts.map
@@ -2,4 +2,3 @@ export type { TalentCalculatorData } from "@crockery/fellowship-data/client";
2
2
  import type { FellowshipDataClient } from "@crockery/fellowship-data/client";
3
3
  /** @deprecated Use the corresponding `FellowshipDataClient` methods. */
4
4
  export type FellowshipTalentDataSource = Pick<FellowshipDataClient, "loadHeroTalents" | "resolveAssetUrl">;
5
- //# sourceMappingURL=talent-data-source.d.ts.map
@@ -33,4 +33,3 @@ declare global {
33
33
  "fellowship-dungeon-cast-browser": FellowshipDungeonCastBrowserElement;
34
34
  }
35
35
  }
36
- //# sourceMappingURL=dungeon-cast-browser.d.ts.map
@@ -1,2 +1 @@
1
1
  export declare const dungeonCastBrowserStyles: import("lit").CSSResult;
2
- //# sourceMappingURL=dungeon-cast-browser.styles.d.ts.map
@@ -1,4 +1,3 @@
1
1
  export { defineFellowshipDungeonCastBrowser, FellowshipDungeonCastBrowserElement, } from "./dungeon-cast-browser.js";
2
2
  export { castIdentityKey, createDungeonCastBrowserModel } from "./render-model.js";
3
3
  export type { CastCapabilityLabel, ConfiguredCastFilter, DungeonCastBrowserModel, DungeonCastEnemyModel, DungeonCastModel, FellowshipCastBrowserErrorDetail, FellowshipCastBrowserErrorEvent, FellowshipCastBrowserReadyDetail, FellowshipCastBrowserReadyEvent, FellowshipCastIdentity, FellowshipCastSelectedDetail, FellowshipCastSelectedEvent, FellowshipDungeonCastBrowserProperties, } from "./types.js";
4
- //# sourceMappingURL=index.d.ts.map
@@ -2,4 +2,3 @@ import type { DungeonCastData, FellowshipCastDataSource } from "../data/cast-dat
2
2
  import type { DungeonCastBrowserModel, FellowshipCastIdentity } from "./types.js";
3
3
  export declare const castIdentityKey: ({ enemyId, abilityId }: FellowshipCastIdentity) => string;
4
4
  export declare const createDungeonCastBrowserModel: (data: DungeonCastData, source: FellowshipCastDataSource) => DungeonCastBrowserModel;
5
- //# sourceMappingURL=render-model.d.ts.map
@@ -57,4 +57,3 @@ declare global {
57
57
  "fellowship-cast-selected": FellowshipCastSelectedEvent;
58
58
  }
59
59
  }
60
- //# sourceMappingURL=types.d.ts.map
@@ -3,5 +3,3 @@ import { i as e, n as t, r as n, t as r } from "./chunks/dungeon-cast-browser-CS
3
3
  t();
4
4
  //#endregion
5
5
  export { r as FellowshipDungeonCastBrowserElement, n as castIdentityKey, e as createDungeonCastBrowserModel, t as defineFellowshipDungeonCastBrowser };
6
-
7
- //# sourceMappingURL=dungeon-cast-browser.js.map
@@ -53,4 +53,3 @@ declare global {
53
53
  "fellowship-dungeon-map": FellowshipDungeonMapElement;
54
54
  }
55
55
  }
56
- //# sourceMappingURL=dungeon-map.d.ts.map
@@ -1,2 +1 @@
1
1
  export declare const dungeonMapStyles: import("lit").CSSResult;
2
- //# sourceMappingURL=dungeon-map.styles.d.ts.map
@@ -2,4 +2,3 @@ export { FellowshipDungeonMapElement, defineFellowshipDungeonMap } from "./dunge
2
2
  export { createDungeonMapRenderModel, humanizeMapLabel } from "./render-model.js";
3
3
  export { ViewportController } from "./viewport-controller.js";
4
4
  export type { DungeonMapEnemyModel, DungeonMapEnemyRenderContext, DungeonMapGroupModel, DungeonMapGroupRenderContext, DungeonMapRenderModel, DungeonMapWarning, FellowshipDungeonMapProperties, FellowshipMapErrorDetail, FellowshipMapImageChangeDetail, FellowshipMapReadyDetail, FellowshipMapViewportChangeDetail, FellowshipMapWarningDetail, LitEnemyRenderer, LitGroupRenderer, MapLabelFormatter, NormalizedRect, ViewportState, } from "./types.js";
5
- //# sourceMappingURL=index.d.ts.map
@@ -1,3 +1,2 @@
1
1
  import type { DungeonMapEnemyModel, DungeonMapGroupModel } from "./types.js";
2
2
  export declare const createDungeonMapGroupModel: (id: number | null, enemies: readonly DungeonMapEnemyModel[]) => DungeonMapGroupModel;
3
- //# sourceMappingURL=layout.d.ts.map
@@ -4,4 +4,3 @@ import type { DungeonMapRenderModel } from "./types.js";
4
4
  export declare const isValidMapPosition: (position: Position2D | null) => position is Position2D;
5
5
  export declare const createDungeonMapRenderModel: (data: DungeonMapData, mapImage: ImageAssetRef, source: FellowshipDataSource) => DungeonMapRenderModel;
6
6
  export declare const humanizeMapLabel: (mapImage: ImageAssetRef, dungeon: Dungeon) => string;
7
- //# sourceMappingURL=render-model.d.ts.map
@@ -104,4 +104,3 @@ declare global {
104
104
  "fellowship-map-viewport-change": FellowshipMapViewportChangeEvent;
105
105
  }
106
106
  }
107
- //# sourceMappingURL=types.d.ts.map
@@ -10,4 +10,3 @@ export declare class ViewportController {
10
10
  zoomAt(factor: number, pointX?: number, pointY?: number): ViewportState;
11
11
  panBy(deltaX: number, deltaY: number): ViewportState;
12
12
  }
13
- //# sourceMappingURL=viewport-controller.d.ts.map
@@ -3,5 +3,3 @@ import { a as e, i as t, n, r, t as i } from "./chunks/dungeon-map-CutIcCVP.js";
3
3
  n();
4
4
  //#endregion
5
5
  export { i as FellowshipDungeonMapElement, r as ViewportController, t as createDungeonMapRenderModel, n as defineFellowshipDungeonMap, e as humanizeMapLabel };
6
-
7
- //# sourceMappingURL=dungeon-map.js.map
package/dist/index.d.ts CHANGED
@@ -11,4 +11,3 @@ export * from "./dungeon-map/index.js";
11
11
  export * from "./dungeon-cast-browser/index.js";
12
12
  export * from "./talent-calculator/index.js";
13
13
  export * from "./tooltip/index.js";
14
- //# sourceMappingURL=index.d.ts.map
@@ -9,4 +9,3 @@ export declare const DungeonCastBrowser: import("@lit/react").ReactWebComponent<
9
9
  }>;
10
10
  export type DungeonCastBrowserProps = ComponentProps<typeof DungeonCastBrowser>;
11
11
  export default DungeonCastBrowser;
12
- //# sourceMappingURL=dungeon-cast-browser.d.ts.map
@@ -15,5 +15,3 @@ var i = n({
15
15
  });
16
16
  //#endregion
17
17
  export { i as DungeonCastBrowser, i as default };
18
-
19
- //# sourceMappingURL=dungeon-cast-browser.js.map
@@ -19,4 +19,3 @@ export interface DungeonMapViewerProps extends Omit<NativeDungeonMapProps, "chil
19
19
  }
20
20
  export declare const DungeonMapViewer: React.ForwardRefExoticComponent<Omit<DungeonMapViewerProps, "ref"> & React.RefAttributes<FellowshipDungeonMapElement>>;
21
21
  export default DungeonMapViewer;
22
- //# sourceMappingURL=dungeon-map.d.ts.map
@@ -176,5 +176,3 @@ var u = n({
176
176
  _.displayName = "DungeonMapViewer";
177
177
  //#endregion
178
178
  export { _ as DungeonMapViewer, _ as default };
179
-
180
- //# sourceMappingURL=dungeon-map.js.map
@@ -6,4 +6,3 @@ export { TalentCalculator } from "./talent-calculator.js";
6
6
  export type { ReactTalentRenderer, TalentCalculatorProps } from "./talent-calculator.js";
7
7
  export { Tooltip } from "./tooltip.js";
8
8
  export type { TooltipProps } from "./tooltip.js";
9
- //# sourceMappingURL=index.d.ts.map
@@ -19,4 +19,3 @@ export interface TalentCalculatorProps extends Omit<NativeTalentCalculatorProps,
19
19
  }
20
20
  export declare const TalentCalculator: React.ForwardRefExoticComponent<Omit<TalentCalculatorProps, "ref"> & React.RefAttributes<FellowshipTalentCalculatorElement>>;
21
21
  export default TalentCalculator;
22
- //# sourceMappingURL=talent-calculator.d.ts.map
@@ -67,5 +67,3 @@ var p = a({
67
67
  m.displayName = "TalentCalculator";
68
68
  //#endregion
69
69
  export { m as TalentCalculator, m as default };
70
-
71
- //# sourceMappingURL=talent-calculator.js.map
@@ -12,4 +12,3 @@ export interface TooltipProps extends Omit<NativeTooltipProps, "children" | "con
12
12
  }
13
13
  export declare const Tooltip: React.ForwardRefExoticComponent<Omit<TooltipProps, "ref"> & React.RefAttributes<FellowshipTooltipElement>>;
14
14
  export default Tooltip;
15
- //# sourceMappingURL=tooltip.d.ts.map
@@ -22,5 +22,3 @@ var s = n({
22
22
  c.displayName = "Tooltip";
23
23
  //#endregion
24
24
  export { c as Tooltip, c as default };
25
-
26
- //# sourceMappingURL=tooltip.js.map
@@ -1,3 +1,2 @@
1
1
  /** Makes the bundled field-manual faces available to a component's owner document. */
2
2
  export declare const installFieldManualFonts: (document: Document) => void;
3
- //# sourceMappingURL=field-manual-fonts.d.ts.map
@@ -1,3 +1,2 @@
1
1
  /** Shared internal aliases for the public Expedition Field Manual theme tokens. */
2
2
  export declare const fieldManualStyles: import("lit").CSSResult;
3
- //# sourceMappingURL=field-manual.styles.d.ts.map
@@ -2,4 +2,3 @@ export { createTalentCalculatorRenderModel, talentRowLabel } from "./render-mode
2
2
  export { canSelectTalent, createTalentCalculatorSelectionState, MAX_TALENT_POINTS, normalizeSelectedTalentIds, normalizeTalentPoints, } from "./selection-state.js";
3
3
  export { FellowshipTalentCalculatorElement, defineFellowshipTalentCalculator, talentSlotName, } from "./talent-calculator.js";
4
4
  export type { FellowshipTalentCalculatorProperties, FellowshipTalentsErrorDetail, FellowshipTalentsErrorEvent, FellowshipTalentsReadyDetail, FellowshipTalentsReadyEvent, FellowshipTalentsWarningDetail, FellowshipTalentsWarningEvent, LitTalentRenderer, TalentCalculatorRenderModel, TalentCalculatorRowModel, TalentCalculatorSelectionState, TalentCalculatorTalentModel, TalentCalculatorTalentRenderContext, TalentCalculatorWarning, TalentCalculatorWarningCode, TalentPointsChangeDetail, TalentPointsChangeEvent, TalentPointsChangeSource, TalentSelectionChangeDetail, TalentSelectionChangeEvent, TalentSelectionChangeSource, } from "./types.js";
5
- //# sourceMappingURL=index.d.ts.map
@@ -2,4 +2,3 @@ import type { FellowshipTalentDataSource, TalentCalculatorData } from "../data/t
2
2
  import type { TalentCalculatorRenderModel } from "./types.js";
3
3
  export declare const talentRowLabel: (row: number) => string;
4
4
  export declare const createTalentCalculatorRenderModel: (data: TalentCalculatorData, source: FellowshipTalentDataSource) => TalentCalculatorRenderModel;
5
- //# sourceMappingURL=render-model.d.ts.map
@@ -7,4 +7,3 @@ export declare const normalizeSelectedTalentIds: (model: TalentCalculatorRenderM
7
7
  };
8
8
  export declare const createTalentCalculatorSelectionState: (model: TalentCalculatorRenderModel, selectedTalentIds: readonly string[], talentPoints: number) => TalentCalculatorSelectionState;
9
9
  export declare const canSelectTalent: (pointCost: number | null, state: TalentCalculatorSelectionState) => boolean;
10
- //# sourceMappingURL=selection-state.d.ts.map
@@ -48,4 +48,3 @@ declare global {
48
48
  "fellowship-talent-calculator": FellowshipTalentCalculatorElement;
49
49
  }
50
50
  }
51
- //# sourceMappingURL=talent-calculator.d.ts.map
@@ -1,2 +1 @@
1
1
  export declare const talentCalculatorStyles: import("lit").CSSResult;
2
- //# sourceMappingURL=talent-calculator.styles.d.ts.map
@@ -89,4 +89,3 @@ declare global {
89
89
  "fellowship-talent-points-change": TalentPointsChangeEvent;
90
90
  }
91
91
  }
92
- //# sourceMappingURL=types.d.ts.map
@@ -3,5 +3,3 @@ import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c, u as
3
3
  i();
4
4
  //#endregion
5
5
  export { c as FellowshipTalentCalculatorElement, n as MAX_TALENT_POINTS, e as canSelectTalent, r as createTalentCalculatorRenderModel, a as createTalentCalculatorSelectionState, i as defineFellowshipTalentCalculator, s as normalizeSelectedTalentIds, t as normalizeTalentPoints, l as talentRowLabel, o as talentSlotName };
6
-
7
- //# sourceMappingURL=talent-calculator.js.map
@@ -3,4 +3,3 @@ export type { TooltipPosition, TooltipPositionOptions, TooltipRect } from "./pos
3
3
  export { resolveFellowshipRichText, stripFellowshipRichText } from "./rich-text.js";
4
4
  export { FellowshipTooltipElement, defineFellowshipTooltip } from "./tooltip.js";
5
5
  export type { FellowshipRichTextDocument, FellowshipRichTextSegment, FellowshipTextTone, FellowshipTooltipPlacement, FellowshipTooltipToggleDetail, FellowshipTooltipToggleEvent, ResolvedTooltipPlacement, } from "./types.js";
6
- //# sourceMappingURL=index.d.ts.map
@@ -20,4 +20,3 @@ export interface TooltipPositionOptions {
20
20
  readonly margin?: number;
21
21
  }
22
22
  export declare const calculateTooltipPosition: (trigger: TooltipRect, tooltip: Pick<TooltipRect, "width" | "height">, options: TooltipPositionOptions) => TooltipPosition;
23
- //# sourceMappingURL=positioning.d.ts.map
@@ -1,4 +1,3 @@
1
1
  import type { FellowshipRichTextDocument } from "./types.js";
2
2
  export declare const resolveFellowshipRichText: (value: string) => FellowshipRichTextDocument;
3
3
  export declare const stripFellowshipRichText: (value: string) => string;
4
- //# sourceMappingURL=rich-text.d.ts.map
@@ -30,4 +30,3 @@ declare global {
30
30
  "fellowship-tooltip": FellowshipTooltipElement;
31
31
  }
32
32
  }
33
- //# sourceMappingURL=tooltip.d.ts.map
@@ -1,2 +1 @@
1
1
  export declare const tooltipStyles: import("lit").CSSResult;
2
- //# sourceMappingURL=tooltip.styles.d.ts.map
@@ -16,4 +16,3 @@ declare global {
16
16
  "fellowship-tooltip-toggle": FellowshipTooltipToggleEvent;
17
17
  }
18
18
  }
19
- //# sourceMappingURL=types.d.ts.map
package/dist/tooltip.js CHANGED
@@ -3,5 +3,3 @@ import { a as e, i as t, n, r, t as i } from "./chunks/tooltip-DoQVSnOn.js";
3
3
  n();
4
4
  //#endregion
5
5
  export { i as FellowshipTooltipElement, r as calculateTooltipPosition, n as defineFellowshipTooltip, t as resolveFellowshipRichText, e as stripFellowshipRichText };
6
-
7
- //# sourceMappingURL=tooltip.js.map
package/package.json CHANGED
@@ -1,15 +1,12 @@
1
1
  {
2
2
  "name": "@crockery/fellowship-components",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Lit web components for rendering Fellowship game data.",
5
5
  "repository": {
6
6
  "type": "git",
7
- "url": "git+https://github.com/Crockery/fellowship-components.git"
7
+ "url": "git+https://github.com/Crockery/fellowscript.git",
8
+ "directory": "packages/fellowship-components"
8
9
  },
9
- "bugs": {
10
- "url": "https://github.com/Crockery/fellowship-components/issues"
11
- },
12
- "homepage": "https://github.com/Crockery/fellowship-components#readme",
13
10
  "keywords": [
14
11
  "fellowship",
15
12
  "web-components",
@@ -99,12 +96,12 @@
99
96
  "access": "public"
100
97
  },
101
98
  "engines": {
102
- "node": "^20.19.0 || >=22.12.0"
99
+ "node": ">=24"
103
100
  },
104
101
  "dependencies": {
105
- "@crockery/fellowship-data": "^1.3.0",
106
102
  "@lit/react": "^1.0.8",
107
- "lit": "^3.3.3"
103
+ "lit": "^3.3.3",
104
+ "@crockery/fellowship-data": "^2.0.0"
108
105
  },
109
106
  "peerDependencies": {
110
107
  "react": ">=18 <20",
@@ -120,8 +117,7 @@
120
117
  },
121
118
  "devDependencies": {
122
119
  "@arethetypeswrong/cli": "^0.18.5",
123
- "@biomejs/biome": "^2.5.3",
124
- "@changesets/cli": "^2.31.0",
120
+ "@biomejs/biome": "2.5.3",
125
121
  "@fontsource/ibm-plex-mono": "5.2.7",
126
122
  "@fontsource/ibm-plex-sans-condensed": "5.2.8",
127
123
  "@ladle/react": "^5.1.1",
@@ -151,9 +147,6 @@
151
147
  "ladle": "ladle serve",
152
148
  "ladle:build": "ladle build",
153
149
  "package:lint": "publint --strict --pack npm && attw --pack . --profile esm-only",
154
- "pack:check": "pnpm build && node scripts/check-build.mjs && pnpm package:lint && pnpm pack --dry-run",
155
- "changeset": "changeset",
156
- "version-packages": "changeset version",
157
- "release": "changeset publish"
150
+ "pack:check": "pnpm build && node scripts/check-build.mjs && node scripts/check-package-files.mjs && pnpm package:lint"
158
151
  }
159
152
  }
@@ -1 +0,0 @@
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 +0,0 @@
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 +0,0 @@
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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"}