@crockery/fellowship-components 2.0.0 → 2.1.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.
@@ -5,8 +5,412 @@ import { customElement as c, property as l, query as u, state as d } from "lit/d
5
5
  import { repeat as f } from "lit/directives/repeat.js";
6
6
  import { findImage as p } from "@crockery/fellowship-data";
7
7
  import { calculateGearPlannerBuild as m, getMaxGearPlannerAppliedTempers as h, getValidGearConfiguration as g, getValidGearItems as _, normalizeGearPlannerBuild as v, resolveGearPlannerItemImage as y, resolveGearPlannerItemName as b, validateGearPlannerBuild as x } from "@crockery/fellowship-data/gear-planner";
8
- //#region src/gear-planner/rarity-thumbnail.styles.ts
8
+ //#region src/gear-planner/equipment-selector.styles.ts
9
9
  var S = a`
10
+ :host {
11
+ position: fixed;
12
+ z-index: 1002;
13
+ inset: auto;
14
+ left: var(--_selector-x, 12px);
15
+ top: var(--_selector-y, 12px);
16
+ display: grid;
17
+ width: min(400px, calc(100vw - 24px));
18
+ max-height: min(680px, calc(100dvh - 24px));
19
+ margin: 0;
20
+ padding: 0;
21
+ overflow: hidden;
22
+ border: 3px solid var(--_fellowship-poster-plum);
23
+ border-radius: var(--_fellowship-poster-radius);
24
+ background: var(--_fellowship-poster-cream);
25
+ color: var(--_fellowship-poster-plum);
26
+ box-shadow: 6px 6px 0 var(--_fellowship-poster-yellow);
27
+ font: 400 12px/1.45 var(--_fellowship-poster-mono);
28
+ overscroll-behavior: contain;
29
+ }
30
+
31
+ :host(:focus-visible) {
32
+ outline: 4px solid var(--_fellowship-poster-focus);
33
+ outline-offset: -7px;
34
+ }
35
+
36
+ * {
37
+ box-sizing: border-box;
38
+ }
39
+
40
+ button,
41
+ input {
42
+ font: inherit;
43
+ }
44
+
45
+ .selector {
46
+ display: grid;
47
+ grid-template-rows: auto auto minmax(0, 1fr);
48
+ min-height: 0;
49
+ max-height: inherit;
50
+ }
51
+
52
+ .actions {
53
+ position: relative;
54
+ z-index: 2;
55
+ display: grid;
56
+ grid-template-columns: minmax(0, 1fr) minmax(0, 0.7fr);
57
+ gap: 8px;
58
+ padding: 10px;
59
+ border-bottom: 3px solid var(--_fellowship-poster-plum);
60
+ background: var(--_fellowship-poster-cream);
61
+ }
62
+
63
+ .action,
64
+ .chip,
65
+ .candidate {
66
+ border: 2px solid var(--_fellowship-poster-plum);
67
+ border-radius: var(--_fellowship-poster-radius);
68
+ color: var(--_fellowship-poster-plum);
69
+ cursor: pointer;
70
+ transition:
71
+ background var(--_fellowship-poster-motion) var(--_fellowship-poster-ease),
72
+ color var(--_fellowship-poster-motion) var(--_fellowship-poster-ease),
73
+ box-shadow var(--_fellowship-poster-motion) var(--_fellowship-poster-ease),
74
+ transform var(--_fellowship-poster-motion) var(--_fellowship-poster-ease);
75
+ }
76
+
77
+ .action {
78
+ min-width: 0;
79
+ min-height: 44px;
80
+ padding: 8px 10px;
81
+ background: var(--_fellowship-poster-white);
82
+ font-weight: 500;
83
+ text-transform: uppercase;
84
+ }
85
+
86
+ .action-primary {
87
+ background: var(--_fellowship-poster-yellow);
88
+ font-family: var(--_fellowship-poster-display);
89
+ font-weight: 800;
90
+ }
91
+
92
+ .action-expand {
93
+ display: none;
94
+ background: var(--_fellowship-poster-violet);
95
+ color: var(--_fellowship-poster-cream);
96
+ }
97
+
98
+ .action:hover:not(:disabled),
99
+ .chip:hover,
100
+ .candidate:hover {
101
+ box-shadow: 3px 3px 0 var(--_fellowship-poster-violet);
102
+ transform: translate(-1px, -1px);
103
+ }
104
+
105
+ .action:active:not(:disabled),
106
+ .chip:active,
107
+ .candidate:active {
108
+ box-shadow: none;
109
+ transform: translate(0, 0);
110
+ }
111
+
112
+ .action:disabled {
113
+ cursor: not-allowed;
114
+ opacity: 0.42;
115
+ }
116
+
117
+ .search-and-filters {
118
+ position: relative;
119
+ z-index: 1;
120
+ display: grid;
121
+ gap: 8px;
122
+ padding: 10px;
123
+ border-bottom: 2px solid var(--_fellowship-poster-plum);
124
+ background: var(--_fellowship-poster-white);
125
+ }
126
+
127
+ .search {
128
+ display: block;
129
+ }
130
+
131
+ .search input {
132
+ width: 100%;
133
+ min-height: 44px;
134
+ padding: 9px 12px;
135
+ border: 2px solid var(--_fellowship-poster-plum);
136
+ border-radius: var(--_fellowship-poster-radius);
137
+ background: var(--_fellowship-poster-cream);
138
+ color: var(--_fellowship-poster-plum);
139
+ font-weight: 500;
140
+ }
141
+
142
+ .chips {
143
+ display: flex;
144
+ gap: 6px;
145
+ min-width: 0;
146
+ margin: 0;
147
+ padding: 0 2px 3px 0;
148
+ overflow-x: auto;
149
+ border: 0;
150
+ scrollbar-width: thin;
151
+ }
152
+
153
+ .chip {
154
+ flex: 0 0 auto;
155
+ min-height: 44px;
156
+ padding: 7px 12px;
157
+ background: var(--_fellowship-poster-cream);
158
+ font-size: 10px;
159
+ font-weight: 500;
160
+ letter-spacing: 0.04em;
161
+ text-transform: uppercase;
162
+ }
163
+
164
+ .chip[aria-pressed="true"] {
165
+ background: var(--_fellowship-poster-violet);
166
+ color: var(--_fellowship-poster-cream);
167
+ }
168
+
169
+ .candidate-list {
170
+ display: grid;
171
+ align-content: start;
172
+ min-height: 0;
173
+ overflow: auto;
174
+ padding: 6px;
175
+ background: var(--_fellowship-poster-cream);
176
+ scrollbar-width: thin;
177
+ }
178
+
179
+ .candidate {
180
+ display: grid;
181
+ grid-template-columns: 50px minmax(0, 1fr) auto;
182
+ gap: 3px 10px;
183
+ align-items: center;
184
+ width: 100%;
185
+ min-width: 0;
186
+ min-height: 72px;
187
+ padding: 8px;
188
+ border-width: 0 0 2px;
189
+ background: var(--_fellowship-poster-cream);
190
+ text-align: left;
191
+ }
192
+
193
+ .candidate:last-child {
194
+ border-bottom: 0;
195
+ }
196
+
197
+ .candidate[aria-pressed="true"] {
198
+ background: color-mix(
199
+ in oklch,
200
+ var(--_fellowship-poster-yellow) 52%,
201
+ var(--_fellowship-poster-cream)
202
+ );
203
+ }
204
+
205
+ .choice-image,
206
+ .choice-image img {
207
+ width: 48px;
208
+ height: 48px;
209
+ }
210
+
211
+ .choice-image {
212
+ position: relative;
213
+ grid-row: 1 / span 2;
214
+ display: grid;
215
+ place-items: center;
216
+ overflow: hidden;
217
+ border: 2px solid var(--_fellowship-rarity-border, var(--_fellowship-poster-plum));
218
+ background: var(--_fellowship-rarity-start, var(--_fellowship-poster-violet));
219
+ color: var(--_fellowship-poster-cream);
220
+ font: 800 13px/1 var(--_fellowship-poster-display);
221
+ text-transform: uppercase;
222
+ }
223
+
224
+ .choice-image img {
225
+ position: absolute;
226
+ inset: 0;
227
+ object-fit: cover;
228
+ }
229
+
230
+ .candidate-copy {
231
+ min-width: 0;
232
+ }
233
+
234
+ .candidate-name {
235
+ display: block;
236
+ overflow: hidden;
237
+ font: 800 14px/1.05 var(--_fellowship-poster-display);
238
+ text-overflow: ellipsis;
239
+ text-transform: uppercase;
240
+ white-space: nowrap;
241
+ }
242
+
243
+ .candidate-tags {
244
+ display: flex;
245
+ flex-wrap: wrap;
246
+ gap: 4px;
247
+ margin-top: 5px;
248
+ }
249
+
250
+ .tag {
251
+ padding: 2px 5px;
252
+ background: var(--_fellowship-poster-plum);
253
+ color: var(--_fellowship-poster-cream);
254
+ font-size: 8px;
255
+ font-weight: 500;
256
+ letter-spacing: 0.06em;
257
+ text-transform: uppercase;
258
+ }
259
+
260
+ .candidate-delta {
261
+ align-self: start;
262
+ min-width: max-content;
263
+ padding: 4px 6px;
264
+ background: var(--_fellowship-poster-yellow);
265
+ font-size: 10px;
266
+ font-weight: 500;
267
+ }
268
+
269
+ .candidate[aria-pressed="true"] .candidate-delta {
270
+ background: var(--_fellowship-poster-violet);
271
+ color: var(--_fellowship-poster-cream);
272
+ }
273
+
274
+ .candidate-stats {
275
+ grid-column: 2 / 4;
276
+ display: flex;
277
+ flex-wrap: wrap;
278
+ gap: 3px 8px;
279
+ min-width: 0;
280
+ color: color-mix(
281
+ in oklch,
282
+ var(--_fellowship-poster-plum) 72%,
283
+ var(--_fellowship-poster-cream)
284
+ );
285
+ font-size: 9px;
286
+ }
287
+
288
+ .partial {
289
+ color: var(--_fellowship-poster-violet);
290
+ font-weight: 500;
291
+ text-transform: uppercase;
292
+ }
293
+
294
+ .no-results {
295
+ display: grid;
296
+ min-height: 180px;
297
+ place-items: center;
298
+ padding: 24px;
299
+ border: 2px dashed var(--_fellowship-poster-plum);
300
+ text-align: center;
301
+ }
302
+
303
+ .no-results strong {
304
+ display: block;
305
+ margin-bottom: 6px;
306
+ font: 800 20px/1 var(--_fellowship-poster-display);
307
+ text-transform: uppercase;
308
+ }
309
+
310
+ .action:focus-visible,
311
+ .chip:focus-visible,
312
+ .candidate:focus-visible,
313
+ .search input:focus-visible {
314
+ position: relative;
315
+ z-index: 3;
316
+ outline: 4px solid var(--_fellowship-poster-focus);
317
+ outline-offset: 2px;
318
+ }
319
+
320
+ .sr-only {
321
+ position: absolute;
322
+ width: 1px;
323
+ height: 1px;
324
+ overflow: hidden;
325
+ clip: rect(0, 0, 0, 0);
326
+ white-space: nowrap;
327
+ }
328
+
329
+ [hidden] {
330
+ display: none !important;
331
+ }
332
+
333
+ :host([compact]) {
334
+ inset: auto 0 0;
335
+ width: 100%;
336
+ max-width: none;
337
+ height: 68dvh;
338
+ max-height: calc(100dvh - env(safe-area-inset-top));
339
+ border-width: 3px 0 0;
340
+ box-shadow: 0 -6px 0 var(--_fellowship-poster-yellow);
341
+ transition: height var(--_fellowship-poster-motion) var(--_fellowship-poster-ease);
342
+ }
343
+
344
+ :host([compact][expanded]) {
345
+ height: 92dvh;
346
+ }
347
+
348
+ :host([compact]) .actions {
349
+ grid-template-columns: minmax(0, 1fr) minmax(0, 0.7fr) auto;
350
+ padding-top: 12px;
351
+ }
352
+
353
+ :host([compact]) .action-expand {
354
+ display: block;
355
+ min-width: 72px;
356
+ }
357
+
358
+ :host([compact]) .candidate-list {
359
+ padding-bottom: max(12px, env(safe-area-inset-bottom));
360
+ }
361
+
362
+ @media (max-width: 430px) {
363
+ .candidate {
364
+ grid-template-columns: 46px minmax(0, 1fr) auto;
365
+ gap-inline: 8px;
366
+ min-height: 68px;
367
+ padding-inline: 6px;
368
+ }
369
+
370
+ .choice-image,
371
+ .choice-image img {
372
+ width: 44px;
373
+ height: 44px;
374
+ }
375
+
376
+ .candidate-name {
377
+ font-size: 13px;
378
+ }
379
+
380
+ .candidate-delta {
381
+ font-size: 9px;
382
+ }
383
+
384
+ :host([compact]) .actions {
385
+ gap: 6px;
386
+ padding-inline: 8px;
387
+ }
388
+
389
+ .action {
390
+ padding-inline: 7px;
391
+ font-size: 10px;
392
+ }
393
+
394
+ :host([compact]) .action-expand {
395
+ min-width: 64px;
396
+ }
397
+ }
398
+
399
+ @media (prefers-reduced-motion: reduce) {
400
+ :host,
401
+ .action,
402
+ .chip,
403
+ .candidate {
404
+ transition-duration: 0.01ms !important;
405
+ }
406
+
407
+ .action:hover:not(:disabled),
408
+ .chip:hover,
409
+ .candidate:hover {
410
+ transform: none;
411
+ }
412
+ }
413
+ `, C = a`
10
414
  [data-rarity="Common"] {
11
415
  --_fellowship-rarity-start: var(--fellowship-rarity-common-start, #545456);
12
416
  --_fellowship-rarity-end: var(--fellowship-rarity-common-end, #909291);
@@ -57,11 +461,356 @@ var S = a`
57
461
  var(--_fellowship-rarity-end)
58
462
  );
59
463
  }
60
- `;
464
+ `, w = {
465
+ bubbles: !0,
466
+ composed: !0
467
+ }, T = [
468
+ {
469
+ id: "critical-strike",
470
+ stat: "CritChance",
471
+ label: "Crit"
472
+ },
473
+ {
474
+ id: "expertise",
475
+ stat: "Expertise",
476
+ label: "Expertise"
477
+ },
478
+ {
479
+ id: "haste",
480
+ stat: "Haste",
481
+ label: "Haste"
482
+ },
483
+ {
484
+ id: "spirit",
485
+ stat: "Spirit",
486
+ label: "Spirit"
487
+ },
488
+ {
489
+ id: "armor",
490
+ stat: "Armor",
491
+ label: "Armor"
492
+ }
493
+ ], E = (e) => {
494
+ let t = e.validItemLevels.at(-1), n = e.validRarities.at(-1);
495
+ return t === void 0 || n === void 0 ? null : {
496
+ itemId: e.item.id,
497
+ itemLevel: t,
498
+ rarity: n,
499
+ appliedTempers: 0,
500
+ rolledModifiers: [],
501
+ gems: [],
502
+ traits: [],
503
+ blessings: []
504
+ };
505
+ }, D = (e, t, n) => ({
506
+ ...e,
507
+ positions: e.positions.map((e) => e.positionId === t ? {
508
+ ...e,
509
+ item: n
510
+ } : e)
511
+ }), O = (e) => new Map(e.heroSheet.sections.flatMap((e) => e.rows.map((e) => [e.id, e]))), k = (e, t = 0) => {
512
+ let n = Number(e.toFixed(t));
513
+ return `${n > 0 ? "+" : ""}${new Intl.NumberFormat("en-US", {
514
+ minimumFractionDigits: t,
515
+ maximumFractionDigits: t
516
+ }).format(n)}`;
517
+ }, A = (e, t) => e.displayKind === "percentage" ? `${e.label} ${k(t * 100, e.decimals)}%` : `${e.label} ${k(t, e.decimals)}`, j = (e, t, n, r) => {
518
+ let i = [];
519
+ (e.setBonusIdsByHero[n.hero.id] ?? []).length > 0 && i.push({
520
+ id: "set",
521
+ label: "Set"
522
+ }), e.maxEquipped === 1 && i.push({
523
+ id: "unique",
524
+ label: "Unique"
525
+ });
526
+ let a = new Set(t.fixedItemStats.filter((e) => e.positionId === r && e.stat).map((e) => e.stat));
527
+ for (let e of T) a.has(e.stat) && i.push({
528
+ id: e.id,
529
+ label: e.label
530
+ });
531
+ return e.item.linkedAbilityIds.length > 0 && i.push({
532
+ id: "effect",
533
+ label: "Effect"
534
+ }), e.relicIdsByHero[n.hero.id] && i.push({
535
+ id: "relic",
536
+ label: "Relic"
537
+ }), i;
538
+ }, M = (e, t) => {
539
+ let n = new Map(e.map((e) => [e.id, e]));
540
+ return [
541
+ n.get("set"),
542
+ n.get("unique"),
543
+ ...T.map((e) => n.get(e.id)),
544
+ n.get("effect"),
545
+ n.get("relic")
546
+ ].filter((e) => !!e).map((e) => e.label).concat(t).slice(0, 2);
547
+ }, N = (e, t, n) => {
548
+ let r = e.heroById.get(t.heroId), i = e.positions.find((e) => e.id === n);
549
+ if (!r || !i) return [];
550
+ let a = t.positions.find((e) => e.positionId === n)?.item ?? null, o = m(e, t), s = O(o), c = s.get("power-score")?.value ?? 0, l = o.unsupportedContributions.some((e) => e.positionId === n), u = [
551
+ r.primaryStat?.toLocaleLowerCase(),
552
+ "critical-strike",
553
+ "expertise",
554
+ "haste",
555
+ "spirit",
556
+ "armor"
557
+ ].filter((e) => !!e);
558
+ return _(e, t, n).flatMap((d) => {
559
+ let f = d.item.id === a?.itemId, p = f ? a : E(d);
560
+ if (!p) return [];
561
+ let h = f ? t : D(t, n, p), g = f ? o : m(e, h), _ = O(g), v = j(d, g, r, n), y = u.flatMap((e) => {
562
+ let t = _.get(e), n = s.get(e);
563
+ if (!t) return [];
564
+ let r = t.value - (n?.value ?? 0);
565
+ return Math.abs(r) > 1e-4 ? [A(t, r)] : [];
566
+ });
567
+ return [{
568
+ item: d,
569
+ itemBuild: p,
570
+ name: b(d, r),
571
+ rarity: p.rarity,
572
+ features: v,
573
+ tags: M(v, i.itemType),
574
+ powerDelta: (_.get("power-score")?.value ?? 0) - c,
575
+ statDeltas: y.slice(0, 2),
576
+ partial: l || g.unsupportedContributions.some((e) => e.positionId === n),
577
+ equipped: f
578
+ }];
579
+ });
580
+ }, P = (e) => {
581
+ let t = /* @__PURE__ */ new Map();
582
+ for (let n of e) for (let e of n.features) {
583
+ let n = t.get(e.id) ?? {
584
+ label: e.label,
585
+ count: 0
586
+ };
587
+ t.set(e.id, {
588
+ ...n,
589
+ count: n.count + 1
590
+ });
591
+ }
592
+ let n = [{
593
+ id: "all",
594
+ label: "All"
595
+ }];
596
+ for (let e of ["set", "unique"]) {
597
+ let r = t.get(e);
598
+ r && n.push({
599
+ id: e,
600
+ label: r.label
601
+ });
602
+ }
603
+ let r = [
604
+ ...T.map((e) => e.id),
605
+ "effect",
606
+ "relic"
607
+ ];
608
+ return n.push(...r.flatMap((n) => {
609
+ let r = t.get(n);
610
+ return r && r.count < e.length ? [{
611
+ id: n,
612
+ label: r.label
613
+ }] : [];
614
+ }).slice(0, 2)), n;
615
+ }, F = class extends i {
616
+ constructor(...e) {
617
+ super(...e), this.data = null, this.build = null, this.positionId = null, this.resolveAssetUrl = null, this.compact = !1, this.expanded = !1, this._query = "", this._filterId = "all", this._candidates = [], this._filters = [{
618
+ id: "all",
619
+ label: "All"
620
+ }], this._visibleCandidates = [], this.#n = () => {
621
+ this.dispatchEvent(new CustomEvent("fellowship-equipment-selector-configure", w));
622
+ }, this.#r = () => {
623
+ this.dispatchEvent(new CustomEvent("fellowship-equipment-selector-unequip", w));
624
+ }, this.#i = () => {
625
+ this.expanded = !this.expanded;
626
+ }, this.#a = (e) => {
627
+ this._query = e.currentTarget.value;
628
+ }, this.#o = (e) => {
629
+ if (e.key === "Escape") {
630
+ e.preventDefault(), e.stopPropagation(), this.dispatchEvent(new CustomEvent("fellowship-equipment-selector-dismiss", w));
631
+ return;
632
+ }
633
+ if (e.key !== "Tab") return;
634
+ let t = [...this.shadowRoot.querySelectorAll("button:not([disabled]), input:not([disabled]), [href], [tabindex]:not([tabindex=\"-1\"])")].filter((e) => e.getClientRects().length > 0), n = t[0], r = t.at(-1);
635
+ if (!n || !r) {
636
+ e.preventDefault();
637
+ return;
638
+ }
639
+ e.shiftKey && this.shadowRoot.activeElement === n ? (e.preventDefault(), r.focus()) : !e.shiftKey && this.shadowRoot.activeElement === r && (e.preventDefault(), n.focus());
640
+ };
641
+ }
642
+ static {
643
+ this.styles = [
644
+ n,
645
+ C,
646
+ S
647
+ ];
648
+ }
649
+ willUpdate(e) {
650
+ super.willUpdate(e);
651
+ let t = e.has("data") || e.has("build") || e.has("positionId");
652
+ if (t && (this._candidates = this.data && this.build && this.positionId ? N(this.data, this.build, this.positionId) : [], this._filters = P(this._candidates), e.has("positionId") ? (this._query = "", this._filterId = "all", this.expanded = !1) : this._filters.some((e) => e.id === this._filterId) || (this._filterId = "all")), t || e.has("_query") || e.has("_filterId")) {
653
+ let e = this._query.trim().toLocaleLowerCase();
654
+ this._visibleCandidates = this._candidates.filter((t) => (!e || t.name.toLocaleLowerCase().includes(e)) && (this._filterId === "all" || t.features.some((e) => e.id === this._filterId)));
655
+ }
656
+ }
657
+ focusInitial() {
658
+ if (this.compact) {
659
+ this.focus({ preventScroll: !0 });
660
+ return;
661
+ }
662
+ this._searchInput?.focus({ preventScroll: !0 });
663
+ }
664
+ render() {
665
+ let e = this.data?.positions.find(({ id: e }) => e === this.positionId) ?? null, t = this.build?.positions.find(({ positionId: e }) => e === this.positionId)?.item ?? null;
666
+ return o`
667
+ <section class="selector" @keydown=${this.#o}>
668
+ <div class="actions">
669
+ <button
670
+ class="action action-primary"
671
+ type="button"
672
+ ?disabled=${!t}
673
+ @click=${this.#n}
674
+ >
675
+ Configure current
676
+ </button>
677
+ <button
678
+ class="action"
679
+ type="button"
680
+ ?disabled=${!t}
681
+ @click=${this.#r}
682
+ >
683
+ Unequip
684
+ </button>
685
+ <button
686
+ class="action action-expand"
687
+ type="button"
688
+ aria-expanded=${String(this.expanded)}
689
+ aria-hidden=${String(!this.compact)}
690
+ ?disabled=${!this.compact}
691
+ @click=${this.#i}
692
+ >
693
+ ${this.expanded ? "Collapse" : "Expand"}
694
+ </button>
695
+ </div>
696
+
697
+ <div class="search-and-filters">
698
+ <label class="search">
699
+ <span class="sr-only">Search valid ${e?.label ?? "equipment"} items</span>
700
+ <input
701
+ type="search"
702
+ .value=${this._query}
703
+ placeholder=${`Search ${e?.label?.toLocaleLowerCase() ?? "equipment"}`}
704
+ @input=${this.#a}
705
+ />
706
+ </label>
707
+ <fieldset class="chips">
708
+ <legend class="sr-only">Quick filters</legend>
709
+ ${f(this._filters, (e) => e.id, (e) => o`
710
+ <button
711
+ class="chip"
712
+ type="button"
713
+ aria-pressed=${String(this._filterId === e.id)}
714
+ @click=${() => {
715
+ this._filterId = e.id;
716
+ }}
717
+ >
718
+ ${e.label}
719
+ </button>
720
+ `)}
721
+ </fieldset>
722
+ </div>
723
+
724
+ <section
725
+ class="candidate-list"
726
+ aria-label=${`Alphabetical equipment choices for ${e?.label ?? "this slot"}`}
727
+ >
728
+ ${this._visibleCandidates.length === 0 ? o`
729
+ <div class="no-results" role="status">
730
+ <div>
731
+ <strong>No matching equipment</strong>
732
+ <span>Clear search or filters to see valid items.</span>
733
+ </div>
734
+ </div>
735
+ ` : f(this._visibleCandidates, (e) => e.item.item.id, (e) => this.#e(e))}
736
+ </section>
737
+ </section>
738
+ `;
739
+ }
740
+ #e(e) {
741
+ let t = this.data && this.build ? this.data.heroById.get(this.build.heroId) : null, n = this.data && t ? y(e.item, t, e.rarity, "200") : null, r = null;
742
+ if (n && this.resolveAssetUrl) try {
743
+ r = this.resolveAssetUrl(n);
744
+ } catch {
745
+ r = null;
746
+ }
747
+ return o`
748
+ <button
749
+ class="candidate"
750
+ type="button"
751
+ aria-pressed=${String(e.equipped)}
752
+ aria-label=${`${e.name}. ${e.equipped ? "Equipped" : e.powerDelta === 0 ? "No power change" : `${k(e.powerDelta)} power`}`}
753
+ @click=${() => this.#t(e)}
754
+ >
755
+ <span class="choice-image" data-rarity=${e.rarity} aria-hidden="true">
756
+ <span>${e.name.slice(0, 2)}</span>
757
+ ${r ? o`
758
+ <img
759
+ src=${r}
760
+ alt=""
761
+ @error=${(e) => {
762
+ e.currentTarget.hidden = !0;
763
+ }}
764
+ />
765
+ ` : s}
766
+ </span>
767
+ <span class="candidate-copy">
768
+ <span class="candidate-name">${e.name}</span>
769
+ <span class="candidate-tags">
770
+ ${f(e.tags, (e) => e, (e) => o`<span class="tag">${e}</span>`)}
771
+ </span>
772
+ </span>
773
+ <span class="candidate-delta">
774
+ ${e.equipped ? "Equipped" : e.powerDelta === 0 ? "0 Power" : `${k(e.powerDelta)} Power`}
775
+ </span>
776
+ <span class="candidate-stats">
777
+ <span>
778
+ ${e.statDeltas.length > 0 ? e.statDeltas.join(" · ") : "No key-stat change"}
779
+ </span>
780
+ ${e.partial ? o`<span class="partial">Partial estimate</span>` : s}
781
+ </span>
782
+ </button>
783
+ `;
784
+ }
785
+ #t(e) {
786
+ this.dispatchEvent(new CustomEvent("fellowship-equipment-selector-select", {
787
+ ...w,
788
+ detail: {
789
+ item: e.itemBuild,
790
+ name: e.name
791
+ }
792
+ }));
793
+ }
794
+ #n;
795
+ #r;
796
+ #i;
797
+ #a;
798
+ #o;
799
+ };
800
+ e([l({ attribute: !1 })], F.prototype, "data", void 0), e([l({ attribute: !1 })], F.prototype, "build", void 0), e([l({ type: String })], F.prototype, "positionId", void 0), e([l({ attribute: !1 })], F.prototype, "resolveAssetUrl", void 0), e([l({
801
+ type: Boolean,
802
+ reflect: !0
803
+ })], F.prototype, "compact", void 0), e([l({
804
+ type: Boolean,
805
+ reflect: !0
806
+ })], F.prototype, "expanded", void 0), e([d()], F.prototype, "_query", void 0), e([d()], F.prototype, "_filterId", void 0), e([d()], F.prototype, "_candidates", void 0), e([d()], F.prototype, "_filters", void 0), e([d()], F.prototype, "_visibleCandidates", void 0), e([u("input[type='search']")], F.prototype, "_searchInput", void 0), F = e([c("fellowship-equipment-selector")], F);
807
+ var I = () => {
808
+ customElements.get("fellowship-equipment-selector") || customElements.define("fellowship-equipment-selector", F);
809
+ };
61
810
  //#endregion
62
811
  //#region src/gear-planner/gear-position.ts
63
812
  r();
64
- var C = class extends i {
813
+ var L = class extends i {
65
814
  constructor(...e) {
66
815
  super(...e), this.position = null, this.item = null, this.itemBuild = null, this.itemName = null, this.selected = !1, this.imageUrl = null, this.tooltipDetails = [], this.#e = (e) => {
67
816
  this.dispatchEvent(new CustomEvent("fellowship-gear-position-select", {
@@ -194,7 +943,7 @@ var C = class extends i {
194
943
  transition: none;
195
944
  }
196
945
  }
197
- `, S];
946
+ `, C];
198
947
  }
199
948
  render() {
200
949
  if (!this.position) return o``;
@@ -234,13 +983,13 @@ var C = class extends i {
234
983
  #e;
235
984
  #t;
236
985
  };
237
- e([l({ attribute: !1 })], C.prototype, "position", void 0), e([l({ attribute: !1 })], C.prototype, "item", void 0), e([l({ attribute: !1 })], C.prototype, "itemBuild", void 0), e([l({ type: String })], C.prototype, "itemName", void 0), e([l({
986
+ e([l({ attribute: !1 })], L.prototype, "position", void 0), e([l({ attribute: !1 })], L.prototype, "item", void 0), e([l({ attribute: !1 })], L.prototype, "itemBuild", void 0), e([l({ type: String })], L.prototype, "itemName", void 0), e([l({
238
987
  type: Boolean,
239
988
  reflect: !0
240
- })], C.prototype, "selected", void 0), e([l({ type: String })], C.prototype, "imageUrl", void 0), e([l({ attribute: !1 })], C.prototype, "tooltipDetails", void 0), C = e([c("fellowship-gear-position")], C);
241
- var w = () => {
242
- customElements.get("fellowship-gear-position") || customElements.define("fellowship-gear-position", C);
243
- }, T = a`
989
+ })], L.prototype, "selected", void 0), e([l({ type: String })], L.prototype, "imageUrl", void 0), e([l({ attribute: !1 })], L.prototype, "tooltipDetails", void 0), L = e([c("fellowship-gear-position")], L);
990
+ var R = () => {
991
+ customElements.get("fellowship-gear-position") || customElements.define("fellowship-gear-position", L);
992
+ }, z = a`
244
993
  :host {
245
994
  display: block;
246
995
  min-width: 0;
@@ -288,11 +1037,6 @@ var w = () => {
288
1037
  text-transform: uppercase;
289
1038
  }
290
1039
 
291
- .search {
292
- display: block;
293
- margin-block: 16px 8px;
294
- }
295
-
296
1040
  input,
297
1041
  select {
298
1042
  width: 100%;
@@ -319,74 +1063,6 @@ var w = () => {
319
1063
  outline-offset: 2px;
320
1064
  }
321
1065
 
322
- .item-list {
323
- display: grid;
324
- grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
325
- gap: 6px;
326
- max-height: 196px;
327
- overflow: auto;
328
- padding: 4px 4px 8px 0;
329
- }
330
-
331
- .item-choice {
332
- display: grid;
333
- grid-template-columns: 8px 38px minmax(0, 1fr);
334
- gap: 3px 8px;
335
- align-content: center;
336
- min-height: 52px;
337
- padding: 8px;
338
- border: 2px solid var(--_fellowship-poster-plum);
339
- border-radius: 0;
340
- background: var(--_fellowship-poster-cream);
341
- color: var(--_fellowship-poster-plum);
342
- font: 700 12px/1.2 var(--_fellowship-poster-display);
343
- text-align: left;
344
- cursor: pointer;
345
- }
346
-
347
- .item-choice:hover,
348
- .item-choice[aria-pressed="true"] {
349
- background: var(--_fellowship-poster-yellow);
350
- }
351
-
352
- .item-choice:disabled {
353
- cursor: not-allowed;
354
- opacity: 0.48;
355
- }
356
-
357
- .choice-mark {
358
- grid-row: span 2;
359
- width: 8px;
360
- height: 100%;
361
- background: var(--_fellowship-poster-violet);
362
- }
363
-
364
- .choice-image,
365
- .choice-image img {
366
- width: 36px;
367
- height: 36px;
368
- }
369
-
370
- .choice-image {
371
- grid-row: span 2;
372
- display: grid;
373
- place-items: center;
374
- overflow: hidden;
375
- border: 2px solid currentColor;
376
- background: var(--_fellowship-poster-plum);
377
- color: var(--_fellowship-poster-cream);
378
- }
379
-
380
- .choice-image img {
381
- object-fit: cover;
382
- }
383
-
384
- .item-choice small {
385
- grid-column: 3;
386
- font: 400 9px/1.2 var(--_fellowship-poster-mono);
387
- text-transform: uppercase;
388
- }
389
-
390
1066
  .configuration {
391
1067
  display: grid;
392
1068
  gap: 12px;
@@ -469,8 +1145,7 @@ var w = () => {
469
1145
  margin-top: 6px;
470
1146
  }
471
1147
 
472
- .empty,
473
- .empty-search {
1148
+ .empty {
474
1149
  margin: 0;
475
1150
  padding: 24px 16px;
476
1151
  border: 2px dashed var(--_fellowship-poster-plum);
@@ -492,31 +1167,18 @@ var w = () => {
492
1167
  grid-row: auto;
493
1168
  }
494
1169
  }
495
- `, E = class extends i {
1170
+ `, B = class extends i {
496
1171
  constructor(...e) {
497
- super(...e), this.data = null, this.build = null, this.positionId = null, this.resolveAssetUrl = null, this._query = "", this.#g = (e) => {
498
- this._query = e.currentTarget.value;
499
- };
1172
+ super(...e), this.data = null, this.build = null, this.positionId = null;
500
1173
  }
501
1174
  static {
502
- this.styles = [
503
- n,
504
- T,
505
- S
506
- ];
1175
+ this.styles = [n, z];
507
1176
  }
508
1177
  render() {
509
1178
  if (!this.data || !this.build || !this.positionId) return o`<div class="empty">Select a gear position to begin.</div>`;
510
1179
  let e = this.data.positions.find(({ id: e }) => e === this.positionId), t = this.build.positions.find(({ positionId: e }) => e === this.positionId);
511
1180
  if (!e) return o`<div class="empty">This gear position is unavailable.</div>`;
512
- let n = t?.item ?? null, r = n ? this.data.itemById.get(n.itemId) : null, i = n && r ? g(this.data, this.build, this.positionId, n.itemId) : null, a = this.data.heroById.get(this.build.heroId), s = this._query.trim().toLocaleLowerCase(), c = a ? _(this.data, this.build, this.positionId).map((e) => {
513
- let t = e.validRarities[0] ?? "Common";
514
- return {
515
- item: e,
516
- name: b(e, a),
517
- rarity: t
518
- };
519
- }).filter(({ name: e }) => !s || e.toLocaleLowerCase().includes(s)) : [];
1181
+ let n = t?.item ?? null, r = n ? this.data.itemById.get(n.itemId) : null, i = n && r ? g(this.data, this.build, this.positionId, n.itemId) : null;
520
1182
  return o`
521
1183
  <header class="workbench-header">
522
1184
  <div>
@@ -525,37 +1187,11 @@ var w = () => {
525
1187
  </div>
526
1188
  ${r ? o`<span class="current-rarity">${n?.rarity}</span>` : o`<span class="current-rarity">Empty</span>`}
527
1189
  </header>
528
-
529
- <label class="search">
530
- <span>Search valid ${e.itemType.toLocaleLowerCase()} items</span>
531
- <input
532
- type="search"
533
- .value=${this._query}
534
- placeholder="Type an item name"
535
- @input=${this.#g}
536
- />
537
- </label>
538
- <div class="item-list" aria-label=${`Valid items for ${e.label}`}>
539
- ${c.length === 0 ? o`<p class="empty-search">No valid items match this search.</p>` : f(c, (e) => e.item.item.id, (e) => o`
540
- <button
541
- type="button"
542
- class="item-choice"
543
- aria-pressed=${String(e.item.item.id === n?.itemId)}
544
- ?disabled=${e.item.validItemLevels.length === 0 || e.item.validRarities.length === 0}
545
- @click=${() => this.#l(e.item.item.id)}
546
- >
547
- <span class="choice-mark" aria-hidden="true"></span>
548
- <span class="choice-image" data-rarity=${e.rarity}>
549
- ${this.#o(e.item, a, e.rarity, e.name)}
550
- </span>
551
- <span>${e.name}</span>
552
- <small>
553
- ${e.item.maxEquipped === 1 ? "Unique" : e.item.itemType}
554
- </small>
555
- </button>
556
- `)}
557
- </div>
558
- ${n && r && i ? this.#e(n, i) : o`<div class="empty configure-empty">Choose an item to configure it.</div>`}
1190
+ ${n && r && i ? this.#e(n, i) : o`
1191
+ <div class="empty configure-empty">
1192
+ Choose an item from this slot’s equipment selector to configure it.
1193
+ </div>
1194
+ `}
559
1195
  `;
560
1196
  }
561
1197
  #e(e, t) {
@@ -568,7 +1204,7 @@ var w = () => {
568
1204
  <span>Item level</span>
569
1205
  <select
570
1206
  .value=${String(e.itemLevel)}
571
- @change=${(t) => this.#h({
1207
+ @change=${(t) => this.#p({
572
1208
  ...e,
573
1209
  itemLevel: Number(t.currentTarget.value)
574
1210
  }, "item-level")}
@@ -583,7 +1219,7 @@ var w = () => {
583
1219
  min="0"
584
1220
  max=${r}
585
1221
  .value=${String(e.appliedTempers)}
586
- @change=${(t) => this.#h({
1222
+ @change=${(t) => this.#p({
587
1223
  ...e,
588
1224
  appliedTempers: Math.max(0, Math.min(r, Math.round(Number(t.currentTarget.value))))
589
1225
  }, "tempers")}
@@ -594,7 +1230,7 @@ var w = () => {
594
1230
  <span>Rarity</span>
595
1231
  <select
596
1232
  .value=${e.rarity}
597
- @change=${(t) => this.#h({
1233
+ @change=${(t) => this.#p({
598
1234
  ...e,
599
1235
  rarity: t.currentTarget.value
600
1236
  }, "rarity")}
@@ -628,7 +1264,7 @@ var w = () => {
628
1264
  <select
629
1265
  aria-label=${`Trait node ${t.row + 1}.${t.column + 1}`}
630
1266
  .value=${n?.traitId ?? ""}
631
- @change=${(n) => this.#p(e, t.id, n.currentTarget.value)}
1267
+ @change=${(n) => this.#d(e, t.id, n.currentTarget.value)}
632
1268
  >
633
1269
  <option value="">Unassigned</option>
634
1270
  ${f(t.eligibleTraitIds, (e) => e, (e) => o`
@@ -644,7 +1280,7 @@ var w = () => {
644
1280
  max=${t.maxRank}
645
1281
  .value=${String(n.rank)}
646
1282
  aria-label="Trait rank"
647
- @change=${(n) => this.#m(e, t.id, Number(n.currentTarget.value), t.maxRank)}
1283
+ @change=${(n) => this.#f(e, t.id, Number(n.currentTarget.value), t.maxRank)}
648
1284
  />
649
1285
  ` : s}
650
1286
  </label>
@@ -661,14 +1297,14 @@ var w = () => {
661
1297
  let r = this.#i(e, t);
662
1298
  return o`
663
1299
  <label class="configuration-control">
664
- <span>${this.#s(t.kind)}</span>
1300
+ <span>${this.#o(t.kind)}</span>
665
1301
  <select
666
1302
  .value=${r}
667
- @change=${(r) => this.#u(e, t, r.currentTarget.value, n)}
1303
+ @change=${(r) => this.#c(e, t, r.currentTarget.value, n)}
668
1304
  >
669
1305
  <option value="">${t.required ? "Choose a value" : "None"}</option>
670
1306
  ${f(t.kind === "blessing" ? n.blessings.map((e) => e.id) : t.allowedChoiceIds, (e) => e, (e) => o`
671
- <option value=${e}>${this.#c(t.kind, e)}</option>
1307
+ <option value=${e}>${this.#s(t.kind, e)}</option>
672
1308
  `)}
673
1309
  </select>
674
1310
  </label>
@@ -683,13 +1319,13 @@ var w = () => {
683
1319
  .value=${r ? `${r.id}\u001f${this.#i(e, r)}` : ""}
684
1320
  @change=${(n) => {
685
1321
  let r = n.currentTarget.value;
686
- this.#d(e, t, r);
1322
+ this.#l(e, t, r);
687
1323
  }}
688
1324
  >
689
1325
  <option value="">Choose one roll</option>
690
1326
  ${t.flatMap((e) => e.allowedChoiceIds.map((t) => o`
691
1327
  <option value=${`${e.id}\u001f${t}`}>
692
- ${this.#s(e.kind)} · ${this.#c(e.kind, t)}
1328
+ ${this.#o(e.kind)} · ${this.#s(e.kind, t)}
693
1329
  </option>
694
1330
  `))}
695
1331
  </select>
@@ -703,7 +1339,7 @@ var w = () => {
703
1339
  <span>Socket ${n + 1} · ${t.replace("SocketTier", "Tier ")}</span>
704
1340
  <select
705
1341
  .value=${i}
706
- @change=${(t) => this.#f(e, r, t.currentTarget.value)}
1342
+ @change=${(t) => this.#u(e, r, t.currentTarget.value)}
707
1343
  >
708
1344
  <option value="">Empty socket</option>
709
1345
  ${f(s, (e) => e.id, (e) => o`<option value=${e.id}>${e.name} · ${e.power} power</option>`)}
@@ -725,26 +1361,7 @@ var w = () => {
725
1361
  </aside>
726
1362
  `;
727
1363
  }
728
- #o(e, t, n, r) {
729
- let i = y(e, t, n, "200");
730
- if (!i || !this.resolveAssetUrl) return r.slice(0, 2);
731
- let a;
732
- try {
733
- a = this.resolveAssetUrl(i);
734
- } catch {
735
- return r.slice(0, 2);
736
- }
737
- return o`
738
- <img
739
- src=${a}
740
- alt=""
741
- @error=${(e) => {
742
- e.currentTarget.hidden = !0;
743
- }}
744
- />
745
- `;
746
- }
747
- #s(e) {
1364
+ #o(e) {
748
1365
  return {
749
1366
  "rolled-stat": "Rolled stat",
750
1367
  "gem-power": "Gem power",
@@ -753,30 +1370,17 @@ var w = () => {
753
1370
  "gem-socket": "Gem socket"
754
1371
  }[e];
755
1372
  }
756
- #c(e, t) {
1373
+ #s(e, t) {
757
1374
  return e === "blessing" ? this.data?.blessingById.get(t)?.name ?? t : e === "item-trait" ? this.data?.traitById.get(t)?.name ?? t : t.replaceAll(/([a-z])([A-Z])/g, "$1 $2");
758
1375
  }
759
- #l(e) {
760
- let t = this.data?.itemById.get(e), n = t?.validItemLevels.at(-1), r = t?.validRarities.at(-1);
761
- !t || n === void 0 || r === void 0 || this.#h({
762
- itemId: e,
763
- itemLevel: n,
764
- rarity: r,
765
- appliedTempers: 0,
766
- rolledModifiers: [],
767
- gems: [],
768
- traits: [],
769
- blessings: []
770
- }, "item");
771
- }
772
- #u(e, t, n, r) {
1376
+ #c(e, t, n, r) {
773
1377
  if (t.kind === "blessing") {
774
1378
  let r = e.blessings.filter((e) => e.slotId !== t.id);
775
1379
  n && r.push({
776
1380
  slotId: t.id,
777
1381
  blessingId: n,
778
1382
  rank: 1
779
- }), this.#h({
1383
+ }), this.#p({
780
1384
  ...e,
781
1385
  blessings: r
782
1386
  }, "blessing");
@@ -787,12 +1391,12 @@ var w = () => {
787
1391
  slotId: t.id,
788
1392
  kind: t.kind,
789
1393
  choiceId: n
790
- }), this.#h({
1394
+ }), this.#p({
791
1395
  ...e,
792
1396
  rolledModifiers: i
793
1397
  }, "modifier");
794
1398
  }
795
- #d(e, t, n) {
1399
+ #l(e, t, n) {
796
1400
  let r = new Set(t.map((e) => e.id)), i = e.rolledModifiers.filter((e) => !r.has(e.slotId)), a = e.blessings.filter((e) => !r.has(e.slotId)), [o, s] = n.split(""), c = t.find((e) => e.id === o);
797
1401
  c && s && (c.kind === "blessing" ? a.push({
798
1402
  slotId: c.id,
@@ -802,44 +1406,44 @@ var w = () => {
802
1406
  slotId: c.id,
803
1407
  kind: c.kind,
804
1408
  choiceId: s
805
- })), this.#h({
1409
+ })), this.#p({
806
1410
  ...e,
807
1411
  rolledModifiers: i,
808
1412
  blessings: a
809
1413
  }, c?.kind === "blessing" ? "blessing" : "modifier");
810
1414
  }
811
- #f(e, t, n) {
1415
+ #u(e, t, n) {
812
1416
  let r = e.gems.filter((e) => e.socketId !== t);
813
1417
  n && r.push({
814
1418
  socketId: t,
815
1419
  gemId: n
816
- }), this.#h({
1420
+ }), this.#p({
817
1421
  ...e,
818
1422
  gems: r
819
1423
  }, "gem");
820
1424
  }
821
- #p(e, t, n) {
1425
+ #d(e, t, n) {
822
1426
  let r = e.traits.filter((e) => e.nodeId !== t);
823
1427
  n && r.push({
824
1428
  nodeId: t,
825
1429
  traitId: n,
826
1430
  rank: 1
827
- }), this.#h({
1431
+ }), this.#p({
828
1432
  ...e,
829
1433
  traits: r
830
1434
  }, "trait");
831
1435
  }
832
- #m(e, t, n, r) {
1436
+ #f(e, t, n, r) {
833
1437
  let i = e.traits.map((e) => e.nodeId === t ? {
834
1438
  ...e,
835
1439
  rank: Math.max(1, Math.min(r, Math.round(n)))
836
1440
  } : e);
837
- this.#h({
1441
+ this.#p({
838
1442
  ...e,
839
1443
  traits: i
840
1444
  }, "trait");
841
1445
  }
842
- #h(e, t) {
1446
+ #p(e, t) {
843
1447
  this.dispatchEvent(new CustomEvent("fellowship-workbench-change", {
844
1448
  bubbles: !0,
845
1449
  composed: !0,
@@ -849,12 +1453,11 @@ var w = () => {
849
1453
  }
850
1454
  }));
851
1455
  }
852
- #g;
853
1456
  };
854
- e([l({ attribute: !1 })], E.prototype, "data", void 0), e([l({ attribute: !1 })], E.prototype, "build", void 0), e([l({ type: String })], E.prototype, "positionId", void 0), e([l({ attribute: !1 })], E.prototype, "resolveAssetUrl", void 0), e([d()], E.prototype, "_query", void 0), E = e([c("fellowship-item-workbench")], E);
855
- var D = () => {
856
- customElements.get("fellowship-item-workbench") || customElements.define("fellowship-item-workbench", E);
857
- }, O = a`
1457
+ e([l({ attribute: !1 })], B.prototype, "data", void 0), e([l({ attribute: !1 })], B.prototype, "build", void 0), e([l({ type: String })], B.prototype, "positionId", void 0), B = e([c("fellowship-item-workbench")], B);
1458
+ var V = () => {
1459
+ customElements.get("fellowship-item-workbench") || customElements.define("fellowship-item-workbench", B);
1460
+ }, H = a`
858
1461
  :host {
859
1462
  display: block;
860
1463
  min-width: 0;
@@ -1122,6 +1725,27 @@ var D = () => {
1122
1725
  outline-offset: -4px;
1123
1726
  }
1124
1727
 
1728
+ .selector-backdrop {
1729
+ position: fixed;
1730
+ z-index: 1000;
1731
+ inset: 0;
1732
+ width: 100%;
1733
+ height: 100%;
1734
+ padding: 0;
1735
+ border: 0;
1736
+ background: color-mix(
1737
+ in oklch,
1738
+ var(--_fellowship-poster-plum) 18%,
1739
+ transparent
1740
+ );
1741
+ cursor: default;
1742
+ pointer-events: none;
1743
+ }
1744
+
1745
+ .selector-backdrop[data-compact="true"] {
1746
+ pointer-events: auto;
1747
+ }
1748
+
1125
1749
  .sheet-backdrop,
1126
1750
  .sheet-header {
1127
1751
  display: none;
@@ -1350,71 +1974,89 @@ var D = () => {
1350
1974
  animation-iteration-count: 1 !important;
1351
1975
  }
1352
1976
  }
1353
- `, k = "button:not([disabled]), input:not([disabled]), select:not([disabled]), [href], [tabindex]:not([tabindex=\"-1\"])", A = (e) => {
1977
+ `, U = "button:not([disabled]), input:not([disabled]), select:not([disabled]), [href], [tabindex]:not([tabindex=\"-1\"])", W = (e) => {
1354
1978
  let t = [];
1355
- for (let n of e.children) n instanceof HTMLElement && n.matches(k) && t.push(n), n.shadowRoot && t.push(...A(n.shadowRoot)), t.push(...A(n));
1979
+ for (let n of e.children) n instanceof HTMLElement && n.matches(U) && t.push(n), n.shadowRoot && t.push(...W(n.shadowRoot)), t.push(...W(n));
1356
1980
  return t;
1357
- }, j = (e) => {
1981
+ }, G = (e) => {
1358
1982
  let t = e.activeElement;
1359
1983
  for (; t?.shadowRoot?.activeElement;) t = t.shadowRoot.activeElement;
1360
1984
  return t;
1361
1985
  };
1362
- w(), D();
1363
- var M = class extends i {
1986
+ I(), R(), V();
1987
+ var K = class extends i {
1364
1988
  constructor(...e) {
1365
- super(...e), this.data = null, this.build = null, this.loading = !1, this.error = null, this.resolveAssetUrl = null, this._selectedPositionId = null, this._tab = "gear", this._sheetOpen = !1, this._compact = !1, this._announcement = "", this._calculation = null, this._leftPositionIds = [], this._rightPositionIds = [], this._mobilePositionIds = [], this.#e = null, this.#t = null, this.#n = null, this.#r = null, this.#i = null, this.#a = !1, this.#o = /* @__PURE__ */ new Set(), this.#m = (e) => {
1989
+ super(...e), this.data = null, this.build = null, this.loading = !1, this.error = null, this.resolveAssetUrl = null, this._selectedPositionId = null, this._selectorOpen = !1, this._selectorPosition = {
1990
+ x: 12,
1991
+ y: 12,
1992
+ placement: "right"
1993
+ }, this._tab = "gear", this._sheetOpen = !1, this._compact = !1, this._announcement = "", this._calculation = null, this._leftPositionIds = [], this._rightPositionIds = [], this._mobilePositionIds = [], this.#e = null, this.#t = null, this.#n = null, this.#r = null, this.#i = null, this.#a = !1, this.#o = /* @__PURE__ */ new Set(), this.#h = (e) => {
1366
1994
  if (!this.data || !this.build) return;
1367
1995
  let t = Math.max(0, Math.min(this.data.maxAllocatedTalentPoints, Math.round(Number(e.currentTarget.value))));
1368
- this.#v({
1996
+ this.#C({
1369
1997
  ...this.build,
1370
1998
  allocatedTalentPoints: t
1371
1999
  }, "talent-points", null);
1372
- }, this.#h = (e) => {
1373
- e.stopPropagation(), this._selectedPositionId = e.detail.positionId, this.#i = e.detail.trigger, this._compact && (this._sheetOpen = !0, this.#r !== null && window.clearTimeout(this.#r), this.#r = window.setTimeout(() => {
1374
- this.#r = null, this.shadowRoot?.querySelector(".workbench-panel")?.focus({ preventScroll: !0 });
1375
- }, 0));
1376
2000
  }, this.#g = (e) => {
1377
- if (e.stopPropagation(), !this.data || !this.build || !this._selectedPositionId) return;
1378
- let t = {
1379
- ...this.build,
1380
- positions: this.build.positions.map((t) => t.positionId === this._selectedPositionId ? {
1381
- ...t,
1382
- item: e.detail.item
1383
- } : t)
1384
- }, n = v(this.data, t), r = x(this.data, n.build);
1385
- if (!r.valid || !r.build) {
1386
- let e = r.issues.find(({ severity: e }) => e === "error");
1387
- this.#y({
1388
- code: e?.code ?? "invalid-change",
1389
- message: e?.message ?? "That item choice is not valid.",
1390
- recoverable: !0
1391
- }), this._announcement = e?.message ?? "That item choice was rejected.";
1392
- return;
1393
- }
1394
- let i = e.detail.item.rolledModifiers.length + e.detail.item.gems.length + e.detail.item.traits.length + e.detail.item.blessings.length - (r.build.positions.find(({ positionId: e }) => e === this._selectedPositionId)?.item?.rolledModifiers.length ?? 0) - (r.build.positions.find(({ positionId: e }) => e === this._selectedPositionId)?.item?.gems.length ?? 0) - (r.build.positions.find(({ positionId: e }) => e === this._selectedPositionId)?.item?.traits.length ?? 0) - (r.build.positions.find(({ positionId: e }) => e === this._selectedPositionId)?.item?.blessings.length ?? 0);
1395
- this._announcement = i > 0 ? `${i} incompatible item choice${i === 1 ? " was" : "s were"} reset.` : "Build updated.", this.#v(r.build, e.detail.source, this._selectedPositionId);
1396
- }, this.#b = () => {
1397
- this._sheetOpen = !1, this.updateComplete.then(() => {
1398
- this.#n !== null && window.cancelAnimationFrame(this.#n), this.#n = window.requestAnimationFrame(() => {
1399
- this.#n = null, this.#i?.focus({ preventScroll: !0 });
2001
+ e.stopPropagation(), this.#r !== null && (window.cancelAnimationFrame(this.#r), this.#r = null), this._selectedPositionId = e.detail.positionId, this.#i = e.detail.trigger, this._sheetOpen = !1, this._selectorOpen = !0, this._announcement = `${e.detail.positionId} equipment selector opened.`, this.updateComplete.then(() => this.#T(!0));
2002
+ }, this.#_ = (e) => {
2003
+ e.stopPropagation(), this.#b(e.detail.item, e.detail.source);
2004
+ }, this.#v = (e) => {
2005
+ e.stopPropagation(), this.#b(e.detail.item, "item", `${e.detail.name} equipped.`) && this.#k(!0);
2006
+ }, this.#y = (e) => {
2007
+ e.stopPropagation(), this.#b(null, "item", "Item unequipped.") && this.#k(!0);
2008
+ }, this.#x = (e) => {
2009
+ e.stopPropagation(), !(!this.build || !this._selectedPositionId) && this.build.positions.find(({ positionId: e }) => e === this._selectedPositionId)?.item && (this.#k(!1), this._compact && (this._sheetOpen = !0), this._announcement = "Item configuration focused.", this.updateComplete.then(() => {
2010
+ this.#r !== null && window.cancelAnimationFrame(this.#r), this.#r = window.requestAnimationFrame(() => {
2011
+ this.#r = null, this._workbenchPanel?.focus({ preventScroll: !0 });
1400
2012
  });
2013
+ }));
2014
+ }, this.#E = () => {
2015
+ let e = this._equipmentSelector, t = this.#i, n = this.ownerDocument.defaultView;
2016
+ if (!this._selectorOpen || this._compact || !e || !t || !n) return;
2017
+ let r = t.getBoundingClientRect(), i = e.getBoundingClientRect(), a = n.innerWidth - 12 - r.right - 8, o = r.left - 12 - 8, s = this._leftPositionIds.includes(this._selectedPositionId), c = s ? "right" : "left", l = s ? a : o, u = s ? o : a;
2018
+ i.width > l && u > l && (c = s ? "left" : "right");
2019
+ let d = c === "right" ? r.right + 8 : r.left - 8 - i.width, f = Math.max(12, n.innerWidth - 12 - i.width), p = Math.max(12, n.innerHeight - 12 - i.height), m = Math.round(Math.min(Math.max(d, 12), f)), h = Math.round(Math.min(Math.max(r.top, 12), p));
2020
+ m === this._selectorPosition.x && h === this._selectorPosition.y && c === this._selectorPosition.placement || (this._selectorPosition = {
2021
+ x: m,
2022
+ y: h,
2023
+ placement: c
1401
2024
  });
1402
- }, this.#x = (e) => {
1403
- e.key !== "Escape" || !this._compact || !this._sheetOpen || (e.preventDefault(), this.#b());
1404
- }, this.#S = (e) => {
2025
+ }, this.#M = () => {
2026
+ this._sheetOpen = !1, this.#A();
2027
+ }, this.#N = (e) => {
2028
+ e.key === "Escape" && (this._selectorOpen ? (e.preventDefault(), this.#k(!0)) : this._compact && this._sheetOpen && (e.preventDefault(), this.#M()));
2029
+ }, this.#P = (e) => {
2030
+ if (!this._selectorOpen) return;
2031
+ let t = e.composedPath();
2032
+ t.includes(this._equipmentSelector) || t.includes(this.#i) || t.some((e) => e instanceof HTMLElement && e.tagName === "FELLOWSHIP-GEAR-POSITION") || this.#k(!0);
2033
+ }, this.#F = (e) => {
2034
+ if (!this._selectorOpen || !this._equipmentSelector) return;
2035
+ if (e.key === "Escape") {
2036
+ e.preventDefault(), e.stopPropagation(), this.#k(!0);
2037
+ return;
2038
+ }
2039
+ if (e.key !== "Tab") return;
2040
+ let t = W(this._equipmentSelector), n = t[0], r = t.at(-1), i = G(this.ownerDocument);
2041
+ if (!n || !r) {
2042
+ e.preventDefault();
2043
+ return;
2044
+ }
2045
+ e.shiftKey && (i === n || i === this._equipmentSelector) ? (e.preventDefault(), r.focus()) : !e.shiftKey && i === r && (e.preventDefault(), n.focus());
2046
+ }, this.#I = (e) => {
1405
2047
  if (!this._compact || !this._sheetOpen) return;
1406
2048
  if (e.key === "Escape") {
1407
- e.preventDefault(), this.#b();
2049
+ e.preventDefault(), this.#M();
1408
2050
  return;
1409
2051
  }
1410
2052
  if (e.key !== "Tab" || !this._workbenchPanel) return;
1411
- let t = A(this._workbenchPanel), n = t[0], r = t.at(-1), i = j(this.shadowRoot);
2053
+ let t = W(this._workbenchPanel), n = t[0], r = t.at(-1), i = G(this.shadowRoot);
1412
2054
  if (!n || !r) {
1413
2055
  e.preventDefault();
1414
2056
  return;
1415
2057
  }
1416
2058
  e.shiftKey && (i === n || i === this._workbenchPanel) ? (e.preventDefault(), r.focus()) : !e.shiftKey && i === r && (e.preventDefault(), n.focus());
1417
- }, this.#C = (e) => {
2059
+ }, this.#L = (e) => {
1418
2060
  if (!["ArrowLeft", "ArrowRight"].includes(e.key)) return;
1419
2061
  e.preventDefault();
1420
2062
  let t = [
@@ -1425,12 +2067,12 @@ var M = class extends i {
1425
2067
  this._tab = t[(r + n + t.length) % t.length] ?? "gear", this.updateComplete.then(() => {
1426
2068
  (this.shadowRoot?.querySelector(".tab[aria-selected=\"true\"]"))?.focus();
1427
2069
  });
1428
- }, this.#T = (e) => {
2070
+ }, this.#z = (e) => {
1429
2071
  e.currentTarget.hidden = !0;
1430
2072
  };
1431
2073
  }
1432
2074
  static {
1433
- this.styles = [n, O];
2075
+ this.styles = [n, H];
1434
2076
  }
1435
2077
  #e;
1436
2078
  #t;
@@ -1442,17 +2084,17 @@ var M = class extends i {
1442
2084
  connectedCallback() {
1443
2085
  super.connectedCallback(), t(this.ownerDocument), this.#e ??= new ResizeObserver(() => {
1444
2086
  let e = this.getBoundingClientRect().width < 1200;
1445
- this.#t !== null && window.cancelAnimationFrame(this.#t), this.#t = window.requestAnimationFrame(() => {
1446
- this.#t = null, e !== this._compact && (this._compact = e, e || (this._sheetOpen = !1));
2087
+ this.#n !== null && window.cancelAnimationFrame(this.#n), this.#n = window.requestAnimationFrame(() => {
2088
+ this.#n = null, e !== this._compact && (this._compact = e, e || (this._sheetOpen = !1), this._selectorOpen && this.updateComplete.then(() => this.#T(!1)));
1447
2089
  });
1448
- }), this.#e.observe(this), this.ownerDocument.addEventListener("keydown", this.#x);
2090
+ }), this.#t ??= new ResizeObserver(() => this.#E()), this.#e.observe(this), this.ownerDocument.addEventListener("keydown", this.#N), this.ownerDocument.addEventListener("pointerdown", this.#P);
1449
2091
  }
1450
2092
  disconnectedCallback() {
1451
- this.#e?.disconnect(), this.ownerDocument.removeEventListener("keydown", this.#x), this.#t !== null && (window.cancelAnimationFrame(this.#t), this.#t = null), this.#n !== null && (window.cancelAnimationFrame(this.#n), this.#n = null), this.#r !== null && (window.clearTimeout(this.#r), this.#r = null), super.disconnectedCallback();
2093
+ this.#e?.disconnect(), this.#O(), this.ownerDocument.removeEventListener("keydown", this.#N), this.ownerDocument.removeEventListener("pointerdown", this.#P), this.#n !== null && (window.cancelAnimationFrame(this.#n), this.#n = null), this.#r !== null && (window.cancelAnimationFrame(this.#r), this.#r = null), super.disconnectedCallback();
1452
2094
  }
1453
2095
  willUpdate(e) {
1454
2096
  if (super.willUpdate(e), e.has("data") || e.has("build")) {
1455
- this._calculation = this.data && this.build ? m(this.data, this.build) : null, this.data && this._selectedPositionId && !this.data.positions.some(({ id: e }) => e === this._selectedPositionId) && (this._selectedPositionId = null);
2097
+ this._calculation = this.data && this.build ? m(this.data, this.build) : null, this.data && this._selectedPositionId && !this.data.positions.some(({ id: e }) => e === this._selectedPositionId) && (this._selectedPositionId = null, this._selectorOpen = !1, this.#O());
1456
2098
  let e = [...this.data?.positions ?? []].sort((e, t) => e.order - t.order);
1457
2099
  this._leftPositionIds = e.slice(0, 7).map(({ id: e }) => e), this._rightPositionIds = e.slice(7).map(({ id: e }) => e), this._mobilePositionIds = e.map(({ id: e }) => e);
1458
2100
  }
@@ -1461,7 +2103,7 @@ var M = class extends i {
1461
2103
  if (super.updated(e), e.has("data") || e.has("build") || e.has("resolveAssetUrl")) {
1462
2104
  (e.has("data") || e.has("resolveAssetUrl")) && this.#o.clear();
1463
2105
  let t = !!(this.data && this.build && !this.resolveAssetUrl);
1464
- t && !this.#a ? (this.#a = !0, this.#y({
2106
+ t && !this.#a ? (this.#a = !0, this.#w({
1465
2107
  code: "asset-resolver-missing",
1466
2108
  message: "A resolveAssetUrl callback is required to render Fellowship images.",
1467
2109
  recoverable: !0
@@ -1504,13 +2146,13 @@ var M = class extends i {
1504
2146
  let t = p(e.hero.images, {
1505
2147
  size: "200",
1506
2148
  type: "hero"
1507
- }), n = t ? this.#w(t) : null;
2149
+ }), n = t ? this.#R(t) : null;
1508
2150
  return o`
1509
2151
  <div class="container">
1510
2152
  <section class="planner" aria-label="Fellership Gear Planner">
1511
2153
  <header class="hero">
1512
2154
  <span class="hero-image">
1513
- ${n ? o`<img src=${n} alt="" @error=${this.#T} />` : (e.hero.name ?? e.hero.id).slice(0, 2)}
2155
+ ${n ? o`<img src=${n} alt="" @error=${this.#z} />` : (e.hero.name ?? e.hero.id).slice(0, 2)}
1514
2156
  </span>
1515
2157
  <span>
1516
2158
  <span class="hero-label">Current hero</span>
@@ -1523,7 +2165,7 @@ var M = class extends i {
1523
2165
  min="0"
1524
2166
  max=${this.data.maxAllocatedTalentPoints}
1525
2167
  .value=${String(this.build.allocatedTalentPoints)}
1526
- @change=${this.#m}
2168
+ @change=${this.#h}
1527
2169
  />
1528
2170
  </label>
1529
2171
  </header>
@@ -1535,7 +2177,7 @@ var M = class extends i {
1535
2177
  aria-label="Traits and gems"
1536
2178
  aria-hidden=${String(this._compact && this._tab !== "traits")}
1537
2179
  >
1538
- ${this.#d()}
2180
+ ${this.#f()}
1539
2181
  </aside>
1540
2182
  <div
1541
2183
  class="gear-workspace"
@@ -1558,11 +2200,12 @@ var M = class extends i {
1558
2200
  aria-label="Blessings, sets and results"
1559
2201
  aria-hidden=${String(this._compact && this._tab !== "bonuses")}
1560
2202
  >
1561
- ${this.#f()}
2203
+ ${this.#p()}
1562
2204
  </aside>
1563
2205
  </div>
1564
2206
  <p class="sr-only" aria-live="polite">${this._announcement}</p>
1565
2207
  </section>
2208
+ ${this.#u()}
1566
2209
  </div>
1567
2210
  `;
1568
2211
  }
@@ -1583,7 +2226,7 @@ var M = class extends i {
1583
2226
  @click=${() => {
1584
2227
  this._tab = e;
1585
2228
  }}
1586
- @keydown=${this.#C}
2229
+ @keydown=${this.#L}
1587
2230
  >
1588
2231
  ${t}
1589
2232
  </button>
@@ -1604,9 +2247,9 @@ var M = class extends i {
1604
2247
  .itemBuild=${r?.item ?? null}
1605
2248
  .itemName=${i && t ? b(i, t) : null}
1606
2249
  .selected=${e === this._selectedPositionId}
1607
- .imageUrl=${a ? this.#w(a) : null}
1608
- .tooltipDetails=${this.#u(e, r?.item ?? null)}
1609
- @fellowship-gear-position-select=${this.#h}
2250
+ .imageUrl=${a ? this.#R(a) : null}
2251
+ .tooltipDetails=${this.#d(e, r?.item ?? null)}
2252
+ @fellowship-gear-position-select=${this.#g}
1610
2253
  ></fellowship-gear-position>
1611
2254
  `;
1612
2255
  })}
@@ -1620,24 +2263,56 @@ var M = class extends i {
1620
2263
  role=${this._compact ? "dialog" : "region"}
1621
2264
  aria-modal=${this._compact ? "true" : s}
1622
2265
  aria-label="Item workbench"
1623
- tabindex=${this._compact ? "-1" : s}
1624
- @keydown=${this.#S}
1625
- @fellowship-workbench-change=${this.#g}
2266
+ tabindex="-1"
2267
+ @keydown=${this.#I}
2268
+ @fellowship-workbench-change=${this.#_}
1626
2269
  >
1627
2270
  <header class="sheet-header">
1628
2271
  <strong>Configure item</strong>
1629
- <button class="sheet-close" type="button" @click=${this.#b}>Close</button>
2272
+ <button class="sheet-close" type="button" @click=${this.#M}>Close</button>
1630
2273
  </header>
1631
2274
  <fellowship-item-workbench
1632
2275
  .data=${this.data}
1633
2276
  .build=${this.build}
1634
2277
  .positionId=${this._selectedPositionId}
1635
- .resolveAssetUrl=${this.resolveAssetUrl}
1636
2278
  ></fellowship-item-workbench>
1637
2279
  </section>
1638
2280
  `;
1639
2281
  }
1640
- #u(e, t) {
2282
+ #u() {
2283
+ if (!this._selectorOpen || !this.data || !this.build || !this._selectedPositionId || !this.resolveAssetUrl) return s;
2284
+ let e = this.data.positions.find(({ id: e }) => e === this._selectedPositionId), t = `--_selector-x:${this._selectorPosition.x}px;--_selector-y:${this._selectorPosition.y}px`;
2285
+ return o`
2286
+ <button
2287
+ class="selector-backdrop"
2288
+ type="button"
2289
+ tabindex="-1"
2290
+ aria-label="Dismiss equipment selector"
2291
+ data-compact=${String(this._compact)}
2292
+ @click=${() => this.#k(!0)}
2293
+ ></button>
2294
+ <fellowship-equipment-selector
2295
+ popover="manual"
2296
+ role="dialog"
2297
+ aria-modal="true"
2298
+ aria-label=${`Choose equipment for ${e?.label ?? "this slot"}`}
2299
+ tabindex="-1"
2300
+ data-placement=${this._selectorPosition.placement}
2301
+ style=${t}
2302
+ .data=${this.data}
2303
+ .build=${this.build}
2304
+ .positionId=${this._selectedPositionId}
2305
+ .resolveAssetUrl=${this.resolveAssetUrl}
2306
+ .compact=${this._compact}
2307
+ @keydown=${this.#F}
2308
+ @fellowship-equipment-selector-select=${this.#v}
2309
+ @fellowship-equipment-selector-configure=${this.#x}
2310
+ @fellowship-equipment-selector-unequip=${this.#y}
2311
+ @fellowship-equipment-selector-dismiss=${() => this.#k(!0)}
2312
+ ></fellowship-equipment-selector>
2313
+ `;
2314
+ }
2315
+ #d(e, t) {
1641
2316
  if (!this.data || !this.build || !t) return [];
1642
2317
  let n = this.data.itemById.get(t.itemId);
1643
2318
  if (!n) return [];
@@ -1654,7 +2329,7 @@ var M = class extends i {
1654
2329
  d ? "Some mechanics are excluded from exact totals." : ""
1655
2330
  ].filter(Boolean);
1656
2331
  }
1657
- #d() {
2332
+ #f() {
1658
2333
  if (!this.data || !this.build) return o``;
1659
2334
  let e = /* @__PURE__ */ new Map(), t = /* @__PURE__ */ new Map();
1660
2335
  for (let n of this.build.positions) {
@@ -1695,7 +2370,7 @@ var M = class extends i {
1695
2370
  </ul>
1696
2371
  `;
1697
2372
  }
1698
- #f() {
2373
+ #p() {
1699
2374
  if (!this.data || !this.build || !this._calculation) return o``;
1700
2375
  let e = /* @__PURE__ */ new Map(), t = /* @__PURE__ */ new Map();
1701
2376
  for (let n of this.build.positions) {
@@ -1736,7 +2411,7 @@ var M = class extends i {
1736
2411
  ${f(e.rows, (e) => e.id, (e) => o`
1737
2412
  <li class="total-row">
1738
2413
  <span>${e.label}</span>
1739
- <strong>${this.#p(e)}</strong>
2414
+ <strong>${this.#m(e)}</strong>
1740
2415
  </li>
1741
2416
  `)}
1742
2417
  </ul>
@@ -1750,7 +2425,7 @@ var M = class extends i {
1750
2425
  <input
1751
2426
  type="checkbox"
1752
2427
  .checked=${e.applied}
1753
- @change=${() => this.#_(e.id)}
2428
+ @change=${() => this.#S(e.id)}
1754
2429
  />
1755
2430
  <span>${e.sourceName} · Apply</span>
1756
2431
  </label>
@@ -1767,25 +2442,48 @@ var M = class extends i {
1767
2442
  </ul>
1768
2443
  `;
1769
2444
  }
1770
- #p(e) {
2445
+ #m(e) {
1771
2446
  return new Intl.NumberFormat("en-US", {
1772
2447
  style: e.displayKind === "percentage" ? "percent" : "decimal",
1773
2448
  minimumFractionDigits: e.decimals,
1774
2449
  maximumFractionDigits: e.decimals
1775
2450
  }).format(e.value);
1776
2451
  }
1777
- #m;
1778
2452
  #h;
1779
2453
  #g;
1780
- #_(e) {
2454
+ #_;
2455
+ #v;
2456
+ #y;
2457
+ #b(e, t, n = "Build updated.") {
2458
+ if (!this.data || !this.build || !this._selectedPositionId) return !1;
2459
+ let r = {
2460
+ ...this.build,
2461
+ positions: this.build.positions.map((t) => t.positionId === this._selectedPositionId ? {
2462
+ ...t,
2463
+ item: e
2464
+ } : t)
2465
+ }, i = v(this.data, r), a = x(this.data, i.build);
2466
+ if (!a.valid || !a.build) {
2467
+ let e = a.issues.find(({ severity: e }) => e === "error");
2468
+ return this.#w({
2469
+ code: e?.code ?? "invalid-change",
2470
+ message: e?.message ?? "That item choice is not valid.",
2471
+ recoverable: !0
2472
+ }), this._announcement = e?.message ?? "That item choice was rejected.", !1;
2473
+ }
2474
+ let o = (e) => e ? e.rolledModifiers.length + e.gems.length + e.traits.length + e.blessings.length : 0, s = a.build.positions.find(({ positionId: e }) => e === this._selectedPositionId)?.item ?? null, c = o(e) - o(s);
2475
+ return this._announcement = c > 0 ? `${c} incompatible item choice${c === 1 ? " was" : "s were"} reset.` : n, this.#C(a.build, t, this._selectedPositionId), !0;
2476
+ }
2477
+ #x;
2478
+ #S(e) {
1781
2479
  if (!this.build) return;
1782
2480
  let t = new Set(this.build.disabledConditionalContributionIds);
1783
- t.has(e) ? t.delete(e) : t.add(e), this.#v({
2481
+ t.has(e) ? t.delete(e) : t.add(e), this.#C({
1784
2482
  ...this.build,
1785
2483
  disabledConditionalContributionIds: [...t].sort()
1786
2484
  }, "conditional", null);
1787
2485
  }
1788
- #v(e, t, n) {
2486
+ #C(e, t, n) {
1789
2487
  this.dispatchEvent(new CustomEvent("fellowship-gear-build-change", {
1790
2488
  bubbles: !0,
1791
2489
  composed: !0,
@@ -1796,7 +2494,7 @@ var M = class extends i {
1796
2494
  }
1797
2495
  }));
1798
2496
  }
1799
- #y(e) {
2497
+ #w(e) {
1800
2498
  this.dispatchEvent(new CustomEvent("fellowship-gear-planner-error", {
1801
2499
  bubbles: !0,
1802
2500
  composed: !0,
@@ -1806,17 +2504,49 @@ var M = class extends i {
1806
2504
  }
1807
2505
  }));
1808
2506
  }
1809
- #b;
1810
- #x;
1811
- #S;
1812
- #C;
1813
- #w(e) {
2507
+ async #T(e) {
2508
+ let t = this._equipmentSelector;
2509
+ !this._selectorOpen || !t || (await t.updateComplete, "showPopover" in t && !t.matches(":popover-open") && t.showPopover(), this.#D(), this.#E(), e && t.focusInitial());
2510
+ }
2511
+ #E;
2512
+ #D() {
2513
+ let e = this.ownerDocument.defaultView;
2514
+ e && (this.#O(), e.addEventListener("resize", this.#E), e.addEventListener("scroll", this.#E, !0), this.#i && this.#t?.observe(this.#i), this._equipmentSelector && this.#t?.observe(this._equipmentSelector));
2515
+ }
2516
+ #O() {
2517
+ let e = this.ownerDocument.defaultView;
2518
+ e?.removeEventListener("resize", this.#E), e?.removeEventListener("scroll", this.#E, !0), this.#t?.disconnect();
2519
+ }
2520
+ #k(e) {
2521
+ if (!this._selectorOpen) return;
2522
+ let t = this._equipmentSelector;
2523
+ t && "hidePopover" in t && t.matches(":popover-open") && t.hidePopover(), this.#O(), this._selectorOpen = !1, e && this.#A();
2524
+ }
2525
+ #A() {
2526
+ this.updateComplete.then(() => {
2527
+ this.#r !== null && window.cancelAnimationFrame(this.#r), this.#r = window.requestAnimationFrame(() => {
2528
+ this.#r = null, this.#j()?.focus({ preventScroll: !0 });
2529
+ });
2530
+ });
2531
+ }
2532
+ #j() {
2533
+ if (this.#i instanceof HTMLButtonElement && this.#i.isConnected) return this.#i;
2534
+ let e = [...this.shadowRoot?.querySelectorAll("fellowship-gear-position") ?? []].find(({ position: e }) => e?.id === this._selectedPositionId)?.shadowRoot?.querySelector("button") ?? null;
2535
+ return this.#i = e, e;
2536
+ }
2537
+ #M;
2538
+ #N;
2539
+ #P;
2540
+ #F;
2541
+ #I;
2542
+ #L;
2543
+ #R(e) {
1814
2544
  if (!this.resolveAssetUrl) return null;
1815
2545
  try {
1816
2546
  return this.resolveAssetUrl(e);
1817
2547
  } catch (t) {
1818
2548
  return this.#o.has(e.path) || (this.#o.add(e.path), queueMicrotask(() => {
1819
- this.isConnected && this.#y({
2549
+ this.isConnected && this.#w({
1820
2550
  code: "asset-url-error",
1821
2551
  message: `Could not resolve ${e.path}: ${String(t)}.`,
1822
2552
  recoverable: !0
@@ -1824,14 +2554,14 @@ var M = class extends i {
1824
2554
  })), null;
1825
2555
  }
1826
2556
  }
1827
- #T;
2557
+ #z;
1828
2558
  };
1829
- e([l({ attribute: !1 })], M.prototype, "data", void 0), e([l({ attribute: !1 })], M.prototype, "build", void 0), e([l({
2559
+ e([l({ attribute: !1 })], K.prototype, "data", void 0), e([l({ attribute: !1 })], K.prototype, "build", void 0), e([l({
1830
2560
  type: Boolean,
1831
2561
  reflect: !0
1832
- })], M.prototype, "loading", void 0), e([l({ attribute: !1 })], M.prototype, "error", void 0), e([l({ attribute: !1 })], M.prototype, "resolveAssetUrl", void 0), e([d()], M.prototype, "_selectedPositionId", void 0), e([d()], M.prototype, "_tab", void 0), e([d()], M.prototype, "_sheetOpen", void 0), e([d()], M.prototype, "_compact", void 0), e([d()], M.prototype, "_announcement", void 0), e([d()], M.prototype, "_calculation", void 0), e([u(".workbench-panel")], M.prototype, "_workbenchPanel", void 0), M = e([c("fellowship-gear-planner")], M);
1833
- var N = () => {
1834
- customElements.get("fellowship-gear-planner") || customElements.define("fellowship-gear-planner", M);
2562
+ })], K.prototype, "loading", void 0), e([l({ attribute: !1 })], K.prototype, "error", void 0), e([l({ attribute: !1 })], K.prototype, "resolveAssetUrl", void 0), e([d()], K.prototype, "_selectedPositionId", void 0), e([d()], K.prototype, "_selectorOpen", void 0), e([d()], K.prototype, "_selectorPosition", void 0), e([d()], K.prototype, "_tab", void 0), e([d()], K.prototype, "_sheetOpen", void 0), e([d()], K.prototype, "_compact", void 0), e([d()], K.prototype, "_announcement", void 0), e([d()], K.prototype, "_calculation", void 0), e([u(".workbench-panel")], K.prototype, "_workbenchPanel", void 0), e([u("fellowship-equipment-selector")], K.prototype, "_equipmentSelector", void 0), K = e([c("fellowship-gear-planner")], K);
2563
+ var q = () => {
2564
+ customElements.get("fellowship-gear-planner") || customElements.define("fellowship-gear-planner", K);
1835
2565
  };
1836
2566
  //#endregion
1837
- export { N as n, M as t };
2567
+ export { q as n, K as t };