@wodira/browser 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +259 -17
  3. package/dist/index.cjs +38 -5
  4. package/dist/index.d.ts +110 -2
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +38 -4
  7. package/dist/types.d.ts +56 -2
  8. package/dist/types.d.ts.map +1 -1
  9. package/dist/ui/boxes/cdn.d.ts +2 -0
  10. package/dist/ui/boxes/cdn.d.ts.map +1 -0
  11. package/dist/ui/boxes/cdn.js +743 -0
  12. package/dist/ui/boxes/client.d.ts +30 -0
  13. package/dist/ui/boxes/client.d.ts.map +1 -0
  14. package/dist/ui/boxes/components.d.ts +246 -0
  15. package/dist/ui/boxes/components.d.ts.map +1 -0
  16. package/dist/ui/boxes/i18n.d.ts +107 -0
  17. package/dist/ui/boxes/i18n.d.ts.map +1 -0
  18. package/dist/ui/boxes/index.d.ts +16 -0
  19. package/dist/ui/boxes/index.d.ts.map +1 -0
  20. package/dist/ui/boxes/index.js +3071 -0
  21. package/dist/ui/boxes/styles.d.ts +2 -0
  22. package/dist/ui/boxes/styles.d.ts.map +1 -0
  23. package/dist/ui/boxes/types.d.ts +105 -0
  24. package/dist/ui/boxes/types.d.ts.map +1 -0
  25. package/dist/ui/components.d.ts +158 -4
  26. package/dist/ui/components.d.ts.map +1 -1
  27. package/dist/ui/events.d.ts +1 -1
  28. package/dist/ui/events.d.ts.map +1 -1
  29. package/dist/ui/i18n.d.ts +4 -1
  30. package/dist/ui/i18n.d.ts.map +1 -1
  31. package/dist/ui/index-tfej862z.js +3264 -0
  32. package/dist/ui/index-xdhg885t.js +997 -0
  33. package/dist/ui/index.d.ts +19 -3
  34. package/dist/ui/index.d.ts.map +1 -1
  35. package/dist/ui/index.js +9038 -2030
  36. package/dist/ui/layout-styles.d.ts +3 -0
  37. package/dist/ui/layout-styles.d.ts.map +1 -0
  38. package/dist/ui/registration-eligibility.d.ts +52 -0
  39. package/dist/ui/registration-eligibility.d.ts.map +1 -0
  40. package/dist/ui/shirt-3d-renderer-jyks1h8f.js +10 -0
  41. package/dist/ui/shirt-sponsors/cdn.d.ts +2 -0
  42. package/dist/ui/shirt-sponsors/cdn.d.ts.map +1 -0
  43. package/dist/ui/shirt-sponsors/cdn.js +5125 -0
  44. package/dist/ui/shirt-sponsors/index.d.ts +9 -0
  45. package/dist/ui/shirt-sponsors/index.d.ts.map +1 -0
  46. package/dist/ui/shirt-sponsors/index.js +10 -0
  47. package/dist/ui/shirt-sponsors/render/auction-model.d.ts +55 -0
  48. package/dist/ui/shirt-sponsors/render/auction-model.d.ts.map +1 -0
  49. package/dist/ui/shirt-sponsors/render/index.d.ts +7 -0
  50. package/dist/ui/shirt-sponsors/render/index.d.ts.map +1 -0
  51. package/dist/ui/shirt-sponsors/render/index.js +34 -0
  52. package/dist/ui/shirt-sponsors/render/shirt-3d-renderer.d.ts +109 -0
  53. package/dist/ui/shirt-sponsors/render/shirt-3d-renderer.d.ts.map +1 -0
  54. package/dist/ui/shirt-sponsors/render/shirt-artwork-projection.d.ts +13 -0
  55. package/dist/ui/shirt-sponsors/render/shirt-artwork-projection.d.ts.map +1 -0
  56. package/dist/ui/shirt-sponsors/render/shirt-artwork.d.ts +17 -0
  57. package/dist/ui/shirt-sponsors/render/shirt-artwork.d.ts.map +1 -0
  58. package/dist/ui/shirt-sponsors/render/shirt-cloth-motion.d.ts +31 -0
  59. package/dist/ui/shirt-sponsors/render/shirt-cloth-motion.d.ts.map +1 -0
  60. package/dist/ui/shirt-sponsors/render/shirt-silhouette.d.ts +9 -0
  61. package/dist/ui/shirt-sponsors/render/shirt-silhouette.d.ts.map +1 -0
  62. package/dist/ui/shirt-sponsors/shirt-auction.d.ts +137 -0
  63. package/dist/ui/shirt-sponsors/shirt-auction.d.ts.map +1 -0
  64. package/dist/ui/signature-pad.d.ts +29 -0
  65. package/dist/ui/signature-pad.d.ts.map +1 -0
  66. package/dist/ui/styles.d.ts.map +1 -1
  67. package/dist/ui/theme.d.ts +63 -0
  68. package/dist/ui/theme.d.ts.map +1 -0
  69. package/dist/ui/validators.d.ts +1 -1
  70. package/dist/ui/validators.d.ts.map +1 -1
  71. package/package.json +42 -13
@@ -0,0 +1,3264 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __returnValue = (v) => v;
3
+ function __exportSetter(name, newValue) {
4
+ this[name] = __returnValue.bind(null, newValue);
5
+ }
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true,
11
+ configurable: true,
12
+ set: __exportSetter.bind(all, name)
13
+ });
14
+ };
15
+ var __chunkGraphs;
16
+ var __chunkSeen;
17
+ var __chunkNonce;
18
+ var __preload = (id, seenOnly) => {
19
+ for (var [base, graph, ids] of __chunkGraphs || [])
20
+ for (var stack = [id], g = globalThis, d = g.document, head, j, node, k, link;j = stack.pop(); )
21
+ if (!__chunkSeen[j] && (node = graph[j])) {
22
+ __chunkSeen[j] = 1;
23
+ for (k = 1;k < node.length; k++)
24
+ stack.push(ids[node[k]]);
25
+ if (!seenOnly && j !== id && (head = d && d.head)) {
26
+ if (__chunkNonce === undefined)
27
+ __chunkNonce = (k = d.querySelector("meta[property=csp-nonce]")) && (k.nonce || k.getAttribute("nonce")) || "";
28
+ link = d.createElement("link");
29
+ link.rel = "modulepreload";
30
+ link.crossOrigin = "";
31
+ if (__chunkNonce)
32
+ link.nonce = __chunkNonce;
33
+ link.href = new g.URL(node[0], base);
34
+ head.appendChild(link);
35
+ }
36
+ }
37
+ };
38
+ var __chunks = (base, ids, nodes, entry) => {
39
+ for (var graph = {}, i = 0;i < ids.length; i++)
40
+ graph[ids[i]] = nodes[i];
41
+ (__chunkGraphs ||= []).push([base, graph, ids]);
42
+ __chunkSeen ||= {};
43
+ __preload(ids[entry], 1);
44
+ };
45
+
46
+ // ../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/development/css-tag.js
47
+ var NODE_MODE = false;
48
+ var global = globalThis;
49
+ var supportsAdoptingStyleSheets = global.ShadowRoot && (global.ShadyCSS === undefined || global.ShadyCSS.nativeShadow) && "adoptedStyleSheets" in Document.prototype && "replace" in CSSStyleSheet.prototype;
50
+ var constructionToken = Symbol();
51
+ var cssTagCache = new WeakMap;
52
+
53
+ class CSSResult {
54
+ constructor(cssText, strings, safeToken) {
55
+ this["_$cssResult$"] = true;
56
+ if (safeToken !== constructionToken) {
57
+ throw new Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");
58
+ }
59
+ this.cssText = cssText;
60
+ this._strings = strings;
61
+ }
62
+ get styleSheet() {
63
+ let styleSheet = this._styleSheet;
64
+ const strings = this._strings;
65
+ if (supportsAdoptingStyleSheets && styleSheet === undefined) {
66
+ const cacheable = strings !== undefined && strings.length === 1;
67
+ if (cacheable) {
68
+ styleSheet = cssTagCache.get(strings);
69
+ }
70
+ if (styleSheet === undefined) {
71
+ (this._styleSheet = styleSheet = new CSSStyleSheet).replaceSync(this.cssText);
72
+ if (cacheable) {
73
+ cssTagCache.set(strings, styleSheet);
74
+ }
75
+ }
76
+ }
77
+ return styleSheet;
78
+ }
79
+ toString() {
80
+ return this.cssText;
81
+ }
82
+ }
83
+ var textFromCSSResult = (value) => {
84
+ if (value["_$cssResult$"] === true) {
85
+ return value.cssText;
86
+ } else if (typeof value === "number") {
87
+ return value;
88
+ } else {
89
+ throw new Error(`Value passed to 'css' function must be a 'css' function result: ` + `${value}. Use 'unsafeCSS' to pass non-literal values, but take care ` + `to ensure page security.`);
90
+ }
91
+ };
92
+ var unsafeCSS = (value) => new CSSResult(typeof value === "string" ? value : String(value), undefined, constructionToken);
93
+ var css = (strings, ...values) => {
94
+ const cssText = strings.length === 1 ? strings[0] : values.reduce((acc, v, idx) => acc + textFromCSSResult(v) + strings[idx + 1], strings[0]);
95
+ return new CSSResult(cssText, strings, constructionToken);
96
+ };
97
+ var adoptStyles = (renderRoot, styles) => {
98
+ if (supportsAdoptingStyleSheets) {
99
+ renderRoot.adoptedStyleSheets = styles.map((s) => s instanceof CSSStyleSheet ? s : s.styleSheet);
100
+ } else {
101
+ for (const s of styles) {
102
+ const style = document.createElement("style");
103
+ const nonce = global["litNonce"];
104
+ if (nonce !== undefined) {
105
+ style.setAttribute("nonce", nonce);
106
+ }
107
+ style.textContent = s.cssText;
108
+ renderRoot.appendChild(style);
109
+ }
110
+ }
111
+ };
112
+ var cssResultFromStyleSheet = (sheet) => {
113
+ let cssText = "";
114
+ for (const rule of sheet.cssRules) {
115
+ cssText += rule.cssText;
116
+ }
117
+ return unsafeCSS(cssText);
118
+ };
119
+ var getCompatibleStyle = supportsAdoptingStyleSheets || NODE_MODE && global.CSSStyleSheet === undefined ? (s) => s : (s) => s instanceof CSSStyleSheet ? cssResultFromStyleSheet(s) : s;
120
+
121
+ // ../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/development/reactive-element.js
122
+ var { is, defineProperty, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, getPrototypeOf } = Object;
123
+ var NODE_MODE2 = false;
124
+ var global2 = globalThis;
125
+ if (NODE_MODE2) {
126
+ global2.customElements ??= customElements;
127
+ }
128
+ var DEV_MODE = true;
129
+ var issueWarning;
130
+ var trustedTypes = global2.trustedTypes;
131
+ var emptyStringForBooleanAttribute = trustedTypes ? trustedTypes.emptyScript : "";
132
+ var polyfillSupport = DEV_MODE ? global2.reactiveElementPolyfillSupportDevMode : global2.reactiveElementPolyfillSupport;
133
+ if (DEV_MODE) {
134
+ global2.litIssuedWarnings ??= new Set;
135
+ issueWarning = (code, warning) => {
136
+ warning += ` See https://lit.dev/msg/${code} for more information.`;
137
+ if (!global2.litIssuedWarnings.has(warning) && !global2.litIssuedWarnings.has(code)) {
138
+ console.warn(warning);
139
+ global2.litIssuedWarnings.add(warning);
140
+ }
141
+ };
142
+ queueMicrotask(() => {
143
+ issueWarning("dev-mode", `Lit is in dev mode. Not recommended for production!`);
144
+ if (global2.ShadyDOM?.inUse && polyfillSupport === undefined) {
145
+ issueWarning("polyfill-support-missing", `Shadow DOM is being polyfilled via \`ShadyDOM\` but ` + `the \`polyfill-support\` module has not been loaded.`);
146
+ }
147
+ });
148
+ }
149
+ var debugLogEvent = DEV_MODE ? (event) => {
150
+ const shouldEmit = global2.emitLitDebugLogEvents;
151
+ if (!shouldEmit) {
152
+ return;
153
+ }
154
+ global2.dispatchEvent(new CustomEvent("lit-debug", {
155
+ detail: event
156
+ }));
157
+ } : undefined;
158
+ var JSCompiler_renameProperty = (prop, _obj) => prop;
159
+ var defaultConverter = {
160
+ toAttribute(value, type) {
161
+ switch (type) {
162
+ case Boolean:
163
+ value = value ? emptyStringForBooleanAttribute : null;
164
+ break;
165
+ case Object:
166
+ case Array:
167
+ value = value == null ? value : JSON.stringify(value);
168
+ break;
169
+ }
170
+ return value;
171
+ },
172
+ fromAttribute(value, type) {
173
+ let fromValue = value;
174
+ switch (type) {
175
+ case Boolean:
176
+ fromValue = value !== null;
177
+ break;
178
+ case Number:
179
+ fromValue = value === null ? null : Number(value);
180
+ break;
181
+ case Object:
182
+ case Array:
183
+ try {
184
+ fromValue = JSON.parse(value);
185
+ } catch (e) {
186
+ fromValue = null;
187
+ }
188
+ break;
189
+ }
190
+ return fromValue;
191
+ }
192
+ };
193
+ var notEqual = (value, old) => !is(value, old);
194
+ var defaultPropertyDeclaration = {
195
+ attribute: true,
196
+ type: String,
197
+ converter: defaultConverter,
198
+ reflect: false,
199
+ useDefault: false,
200
+ hasChanged: notEqual
201
+ };
202
+ Symbol.metadata ??= Symbol("metadata");
203
+ global2.litPropertyMetadata ??= new WeakMap;
204
+
205
+ class ReactiveElement extends HTMLElement {
206
+ static addInitializer(initializer) {
207
+ this.__prepare();
208
+ (this._initializers ??= []).push(initializer);
209
+ }
210
+ static get observedAttributes() {
211
+ this.finalize();
212
+ return this.__attributeToPropertyMap && [...this.__attributeToPropertyMap.keys()];
213
+ }
214
+ static createProperty(name, options = defaultPropertyDeclaration) {
215
+ if (options.state) {
216
+ options.attribute = false;
217
+ }
218
+ this.__prepare();
219
+ if (this.prototype.hasOwnProperty(name)) {
220
+ options = Object.create(options);
221
+ options.wrapped = true;
222
+ }
223
+ this.elementProperties.set(name, options);
224
+ if (!options.noAccessor) {
225
+ const key = DEV_MODE ? Symbol.for(`${String(name)} (@property() cache)`) : Symbol();
226
+ const descriptor = this.getPropertyDescriptor(name, key, options);
227
+ if (descriptor !== undefined) {
228
+ defineProperty(this.prototype, name, descriptor);
229
+ }
230
+ }
231
+ }
232
+ static getPropertyDescriptor(name, key, options) {
233
+ const { get, set } = getOwnPropertyDescriptor(this.prototype, name) ?? {
234
+ get() {
235
+ return this[key];
236
+ },
237
+ set(v) {
238
+ this[key] = v;
239
+ }
240
+ };
241
+ if (DEV_MODE && get == null) {
242
+ if ("value" in (getOwnPropertyDescriptor(this.prototype, name) ?? {})) {
243
+ throw new Error(`Field ${JSON.stringify(String(name))} on ` + `${this.name} was declared as a reactive property ` + `but it's actually declared as a value on the prototype. ` + `Usually this is due to using @property or @state on a method.`);
244
+ }
245
+ issueWarning("reactive-property-without-getter", `Field ${JSON.stringify(String(name))} on ` + `${this.name} was declared as a reactive property ` + `but it does not have a getter. This will be an error in a ` + `future version of Lit.`);
246
+ }
247
+ return {
248
+ get,
249
+ set(value) {
250
+ const oldValue = get?.call(this);
251
+ set?.call(this, value);
252
+ this.requestUpdate(name, oldValue, options);
253
+ },
254
+ configurable: true,
255
+ enumerable: true
256
+ };
257
+ }
258
+ static getPropertyOptions(name) {
259
+ return this.elementProperties.get(name) ?? defaultPropertyDeclaration;
260
+ }
261
+ static __prepare() {
262
+ if (this.hasOwnProperty(JSCompiler_renameProperty("elementProperties", this))) {
263
+ return;
264
+ }
265
+ const superCtor = getPrototypeOf(this);
266
+ superCtor.finalize();
267
+ if (superCtor._initializers !== undefined) {
268
+ this._initializers = [...superCtor._initializers];
269
+ }
270
+ this.elementProperties = new Map(superCtor.elementProperties);
271
+ }
272
+ static finalize() {
273
+ if (this.hasOwnProperty(JSCompiler_renameProperty("finalized", this))) {
274
+ return;
275
+ }
276
+ this.finalized = true;
277
+ this.__prepare();
278
+ if (this.hasOwnProperty(JSCompiler_renameProperty("properties", this))) {
279
+ const props = this.properties;
280
+ const propKeys = [
281
+ ...getOwnPropertyNames(props),
282
+ ...getOwnPropertySymbols(props)
283
+ ];
284
+ for (const p of propKeys) {
285
+ this.createProperty(p, props[p]);
286
+ }
287
+ }
288
+ const metadata = this[Symbol.metadata];
289
+ if (metadata !== null) {
290
+ const properties = litPropertyMetadata.get(metadata);
291
+ if (properties !== undefined) {
292
+ for (const [p, options] of properties) {
293
+ this.elementProperties.set(p, options);
294
+ }
295
+ }
296
+ }
297
+ this.__attributeToPropertyMap = new Map;
298
+ for (const [p, options] of this.elementProperties) {
299
+ const attr = this.__attributeNameForProperty(p, options);
300
+ if (attr !== undefined) {
301
+ this.__attributeToPropertyMap.set(attr, p);
302
+ }
303
+ }
304
+ this.elementStyles = this.finalizeStyles(this.styles);
305
+ if (DEV_MODE) {
306
+ if (this.hasOwnProperty("createProperty")) {
307
+ issueWarning("no-override-create-property", "Overriding ReactiveElement.createProperty() is deprecated. " + "The override will not be called with standard decorators");
308
+ }
309
+ if (this.hasOwnProperty("getPropertyDescriptor")) {
310
+ issueWarning("no-override-get-property-descriptor", "Overriding ReactiveElement.getPropertyDescriptor() is deprecated. " + "The override will not be called with standard decorators");
311
+ }
312
+ }
313
+ }
314
+ static finalizeStyles(styles) {
315
+ const elementStyles = [];
316
+ if (Array.isArray(styles)) {
317
+ const set = new Set(styles.flat(Infinity).reverse());
318
+ for (const s of set) {
319
+ elementStyles.unshift(getCompatibleStyle(s));
320
+ }
321
+ } else if (styles !== undefined) {
322
+ elementStyles.push(getCompatibleStyle(styles));
323
+ }
324
+ return elementStyles;
325
+ }
326
+ static __attributeNameForProperty(name, options) {
327
+ const attribute = options.attribute;
328
+ return attribute === false ? undefined : typeof attribute === "string" ? attribute : typeof name === "string" ? name.toLowerCase() : undefined;
329
+ }
330
+ constructor() {
331
+ super();
332
+ this.__instanceProperties = undefined;
333
+ this.isUpdatePending = false;
334
+ this.hasUpdated = false;
335
+ this.__reflectingProperty = null;
336
+ this.__initialize();
337
+ }
338
+ __initialize() {
339
+ this.__updatePromise = new Promise((res) => this.enableUpdating = res);
340
+ this._$changedProperties = new Map;
341
+ this.__saveInstanceProperties();
342
+ this.requestUpdate();
343
+ this.constructor._initializers?.forEach((i) => i(this));
344
+ }
345
+ addController(controller) {
346
+ (this.__controllers ??= new Set).add(controller);
347
+ if (this.renderRoot !== undefined && this.isConnected) {
348
+ controller.hostConnected?.();
349
+ }
350
+ }
351
+ removeController(controller) {
352
+ this.__controllers?.delete(controller);
353
+ }
354
+ __saveInstanceProperties() {
355
+ const instanceProperties = new Map;
356
+ const elementProperties = this.constructor.elementProperties;
357
+ for (const p of elementProperties.keys()) {
358
+ if (this.hasOwnProperty(p)) {
359
+ instanceProperties.set(p, this[p]);
360
+ delete this[p];
361
+ }
362
+ }
363
+ if (instanceProperties.size > 0) {
364
+ this.__instanceProperties = instanceProperties;
365
+ }
366
+ }
367
+ createRenderRoot() {
368
+ const renderRoot = this.shadowRoot ?? this.attachShadow(this.constructor.shadowRootOptions);
369
+ adoptStyles(renderRoot, this.constructor.elementStyles);
370
+ return renderRoot;
371
+ }
372
+ connectedCallback() {
373
+ this.renderRoot ??= this.createRenderRoot();
374
+ this.enableUpdating(true);
375
+ this.__controllers?.forEach((c) => c.hostConnected?.());
376
+ }
377
+ enableUpdating(_requestedUpdate) {}
378
+ disconnectedCallback() {
379
+ this.__controllers?.forEach((c) => c.hostDisconnected?.());
380
+ }
381
+ attributeChangedCallback(name, _old, value) {
382
+ this._$attributeToProperty(name, value);
383
+ }
384
+ __propertyToAttribute(name, value) {
385
+ const elemProperties = this.constructor.elementProperties;
386
+ const options = elemProperties.get(name);
387
+ const attr = this.constructor.__attributeNameForProperty(name, options);
388
+ if (attr !== undefined && options.reflect === true) {
389
+ const converter = options.converter?.toAttribute !== undefined ? options.converter : defaultConverter;
390
+ const attrValue = converter.toAttribute(value, options.type);
391
+ if (DEV_MODE && this.constructor.enabledWarnings.includes("migration") && attrValue === undefined) {
392
+ issueWarning("undefined-attribute-value", `The attribute value for the ${name} property is ` + `undefined on element ${this.localName}. The attribute will be ` + `removed, but in the previous version of \`ReactiveElement\`, ` + `the attribute would not have changed.`);
393
+ }
394
+ this.__reflectingProperty = name;
395
+ if (attrValue == null) {
396
+ this.removeAttribute(attr);
397
+ } else {
398
+ this.setAttribute(attr, attrValue);
399
+ }
400
+ this.__reflectingProperty = null;
401
+ }
402
+ }
403
+ _$attributeToProperty(name, value) {
404
+ const ctor = this.constructor;
405
+ const propName = ctor.__attributeToPropertyMap.get(name);
406
+ if (propName !== undefined && this.__reflectingProperty !== propName) {
407
+ const options = ctor.getPropertyOptions(propName);
408
+ const converter = typeof options.converter === "function" ? { fromAttribute: options.converter } : options.converter?.fromAttribute !== undefined ? options.converter : defaultConverter;
409
+ this.__reflectingProperty = propName;
410
+ const convertedValue = converter.fromAttribute(value, options.type);
411
+ this[propName] = convertedValue ?? this.__defaultValues?.get(propName) ?? convertedValue;
412
+ this.__reflectingProperty = null;
413
+ }
414
+ }
415
+ requestUpdate(name, oldValue, options, useNewValue = false, newValue) {
416
+ if (name !== undefined) {
417
+ if (DEV_MODE && name instanceof Event) {
418
+ issueWarning(``, `The requestUpdate() method was called with an Event as the property name. This is probably a mistake caused by binding this.requestUpdate as an event listener. Instead bind a function that will call it with no arguments: () => this.requestUpdate()`);
419
+ }
420
+ const ctor = this.constructor;
421
+ if (useNewValue === false) {
422
+ newValue = this[name];
423
+ }
424
+ options ??= ctor.getPropertyOptions(name);
425
+ const changed = (options.hasChanged ?? notEqual)(newValue, oldValue) || options.useDefault && options.reflect && newValue === this.__defaultValues?.get(name) && !this.hasAttribute(ctor.__attributeNameForProperty(name, options));
426
+ if (changed) {
427
+ this._$changeProperty(name, oldValue, options);
428
+ } else {
429
+ return;
430
+ }
431
+ }
432
+ if (this.isUpdatePending === false) {
433
+ this.__updatePromise = this.__enqueueUpdate();
434
+ }
435
+ }
436
+ _$changeProperty(name, oldValue, { useDefault, reflect, wrapped }, initializeValue) {
437
+ if (useDefault && !(this.__defaultValues ??= new Map).has(name)) {
438
+ this.__defaultValues.set(name, initializeValue ?? oldValue ?? this[name]);
439
+ if (wrapped !== true || initializeValue !== undefined) {
440
+ return;
441
+ }
442
+ }
443
+ if (!this._$changedProperties.has(name)) {
444
+ if (!this.hasUpdated && !useDefault) {
445
+ oldValue = undefined;
446
+ }
447
+ this._$changedProperties.set(name, oldValue);
448
+ }
449
+ if (reflect === true && this.__reflectingProperty !== name) {
450
+ (this.__reflectingProperties ??= new Set).add(name);
451
+ }
452
+ }
453
+ async __enqueueUpdate() {
454
+ this.isUpdatePending = true;
455
+ try {
456
+ await this.__updatePromise;
457
+ } catch (e) {
458
+ Promise.reject(e);
459
+ }
460
+ const result = this.scheduleUpdate();
461
+ if (result != null) {
462
+ await result;
463
+ }
464
+ return !this.isUpdatePending;
465
+ }
466
+ scheduleUpdate() {
467
+ const result = this.performUpdate();
468
+ if (DEV_MODE && this.constructor.enabledWarnings.includes("async-perform-update") && typeof result?.then === "function") {
469
+ issueWarning("async-perform-update", `Element ${this.localName} returned a Promise from performUpdate(). ` + `This behavior is deprecated and will be removed in a future ` + `version of ReactiveElement.`);
470
+ }
471
+ return result;
472
+ }
473
+ performUpdate() {
474
+ if (!this.isUpdatePending) {
475
+ return;
476
+ }
477
+ debugLogEvent?.({ kind: "update" });
478
+ if (!this.hasUpdated) {
479
+ this.renderRoot ??= this.createRenderRoot();
480
+ if (DEV_MODE) {
481
+ const ctor = this.constructor;
482
+ const shadowedProperties = [...ctor.elementProperties.keys()].filter((p) => this.hasOwnProperty(p) && (p in getPrototypeOf(this)));
483
+ if (shadowedProperties.length) {
484
+ throw new Error(`The following properties on element ${this.localName} will not ` + `trigger updates as expected because they are set using class ` + `fields: ${shadowedProperties.join(", ")}. ` + `Native class fields and some compiled output will overwrite ` + `accessors used for detecting changes. See ` + `https://lit.dev/msg/class-field-shadowing ` + `for more information.`);
485
+ }
486
+ }
487
+ if (this.__instanceProperties) {
488
+ for (const [p, value] of this.__instanceProperties) {
489
+ this[p] = value;
490
+ }
491
+ this.__instanceProperties = undefined;
492
+ }
493
+ const elementProperties = this.constructor.elementProperties;
494
+ if (elementProperties.size > 0) {
495
+ for (const [p, options] of elementProperties) {
496
+ const { wrapped } = options;
497
+ const value = this[p];
498
+ if (wrapped === true && !this._$changedProperties.has(p) && value !== undefined) {
499
+ this._$changeProperty(p, undefined, options, value);
500
+ }
501
+ }
502
+ }
503
+ }
504
+ let shouldUpdate = false;
505
+ const changedProperties = this._$changedProperties;
506
+ try {
507
+ shouldUpdate = this.shouldUpdate(changedProperties);
508
+ if (shouldUpdate) {
509
+ this.willUpdate(changedProperties);
510
+ this.__controllers?.forEach((c) => c.hostUpdate?.());
511
+ this.update(changedProperties);
512
+ } else {
513
+ this.__markUpdated();
514
+ }
515
+ } catch (e) {
516
+ shouldUpdate = false;
517
+ this.__markUpdated();
518
+ throw e;
519
+ }
520
+ if (shouldUpdate) {
521
+ this._$didUpdate(changedProperties);
522
+ }
523
+ }
524
+ willUpdate(_changedProperties) {}
525
+ _$didUpdate(changedProperties) {
526
+ this.__controllers?.forEach((c) => c.hostUpdated?.());
527
+ if (!this.hasUpdated) {
528
+ this.hasUpdated = true;
529
+ this.firstUpdated(changedProperties);
530
+ }
531
+ this.updated(changedProperties);
532
+ if (DEV_MODE && this.isUpdatePending && this.constructor.enabledWarnings.includes("change-in-update")) {
533
+ issueWarning("change-in-update", `Element ${this.localName} scheduled an update ` + `(generally because a property was set) ` + `after an update completed, causing a new update to be scheduled. ` + `This is inefficient and should be avoided unless the next update ` + `can only be scheduled as a side effect of the previous update.`);
534
+ }
535
+ }
536
+ __markUpdated() {
537
+ this._$changedProperties = new Map;
538
+ this.isUpdatePending = false;
539
+ }
540
+ get updateComplete() {
541
+ return this.getUpdateComplete();
542
+ }
543
+ getUpdateComplete() {
544
+ return this.__updatePromise;
545
+ }
546
+ shouldUpdate(_changedProperties) {
547
+ return true;
548
+ }
549
+ update(_changedProperties) {
550
+ this.__reflectingProperties &&= this.__reflectingProperties.forEach((p) => this.__propertyToAttribute(p, this[p]));
551
+ this.__markUpdated();
552
+ }
553
+ updated(_changedProperties) {}
554
+ firstUpdated(_changedProperties) {}
555
+ }
556
+ ReactiveElement.elementStyles = [];
557
+ ReactiveElement.shadowRootOptions = { mode: "open" };
558
+ ReactiveElement[JSCompiler_renameProperty("elementProperties", ReactiveElement)] = new Map;
559
+ ReactiveElement[JSCompiler_renameProperty("finalized", ReactiveElement)] = new Map;
560
+ polyfillSupport?.({ ReactiveElement });
561
+ if (DEV_MODE) {
562
+ ReactiveElement.enabledWarnings = [
563
+ "change-in-update",
564
+ "async-perform-update"
565
+ ];
566
+ const ensureOwnWarnings = function(ctor) {
567
+ if (!ctor.hasOwnProperty(JSCompiler_renameProperty("enabledWarnings", ctor))) {
568
+ ctor.enabledWarnings = ctor.enabledWarnings.slice();
569
+ }
570
+ };
571
+ ReactiveElement.enableWarning = function(warning) {
572
+ ensureOwnWarnings(this);
573
+ if (!this.enabledWarnings.includes(warning)) {
574
+ this.enabledWarnings.push(warning);
575
+ }
576
+ };
577
+ ReactiveElement.disableWarning = function(warning) {
578
+ ensureOwnWarnings(this);
579
+ const i = this.enabledWarnings.indexOf(warning);
580
+ if (i >= 0) {
581
+ this.enabledWarnings.splice(i, 1);
582
+ }
583
+ };
584
+ }
585
+ (global2.reactiveElementVersions ??= []).push("2.1.2");
586
+ if (DEV_MODE && global2.reactiveElementVersions.length > 1) {
587
+ queueMicrotask(() => {
588
+ issueWarning("multiple-versions", `Multiple versions of Lit loaded. Loading multiple versions ` + `is not recommended.`);
589
+ });
590
+ }
591
+
592
+ // ../../node_modules/.pnpm/lit-html@3.3.3/node_modules/lit-html/development/lit-html.js
593
+ var DEV_MODE2 = true;
594
+ var ENABLE_EXTRA_SECURITY_HOOKS = true;
595
+ var ENABLE_SHADYDOM_NOPATCH = true;
596
+ var NODE_MODE3 = false;
597
+ var global3 = globalThis;
598
+ var debugLogEvent2 = DEV_MODE2 ? (event) => {
599
+ const shouldEmit = global3.emitLitDebugLogEvents;
600
+ if (!shouldEmit) {
601
+ return;
602
+ }
603
+ global3.dispatchEvent(new CustomEvent("lit-debug", {
604
+ detail: event
605
+ }));
606
+ } : undefined;
607
+ var debugLogRenderId = 0;
608
+ var issueWarning2;
609
+ if (DEV_MODE2) {
610
+ global3.litIssuedWarnings ??= new Set;
611
+ issueWarning2 = (code, warning) => {
612
+ warning += code ? ` See https://lit.dev/msg/${code} for more information.` : "";
613
+ if (!global3.litIssuedWarnings.has(warning) && !global3.litIssuedWarnings.has(code)) {
614
+ console.warn(warning);
615
+ global3.litIssuedWarnings.add(warning);
616
+ }
617
+ };
618
+ queueMicrotask(() => {
619
+ issueWarning2("dev-mode", `Lit is in dev mode. Not recommended for production!`);
620
+ });
621
+ }
622
+ var wrap = ENABLE_SHADYDOM_NOPATCH && global3.ShadyDOM?.inUse && global3.ShadyDOM?.noPatch === true ? global3.ShadyDOM.wrap : (node) => node;
623
+ var trustedTypes2 = global3.trustedTypes;
624
+ var policy = trustedTypes2 ? trustedTypes2.createPolicy("lit-html", {
625
+ createHTML: (s) => s
626
+ }) : undefined;
627
+ var identityFunction = (value) => value;
628
+ var noopSanitizer = (_node, _name, _type) => identityFunction;
629
+ var setSanitizer = (newSanitizer) => {
630
+ if (!ENABLE_EXTRA_SECURITY_HOOKS) {
631
+ return;
632
+ }
633
+ if (sanitizerFactoryInternal !== noopSanitizer) {
634
+ throw new Error(`Attempted to overwrite existing lit-html security policy.` + ` setSanitizeDOMValueFactory should be called at most once.`);
635
+ }
636
+ sanitizerFactoryInternal = newSanitizer;
637
+ };
638
+ var _testOnlyClearSanitizerFactoryDoNotCallOrElse = () => {
639
+ sanitizerFactoryInternal = noopSanitizer;
640
+ };
641
+ var createSanitizer = (node, name, type) => {
642
+ return sanitizerFactoryInternal(node, name, type);
643
+ };
644
+ var boundAttributeSuffix = "$lit$";
645
+ var marker = `lit$${Math.random().toFixed(9).slice(2)}$`;
646
+ var markerMatch = "?" + marker;
647
+ var nodeMarker = `<${markerMatch}>`;
648
+ var d = NODE_MODE3 && global3.document === undefined ? {
649
+ createTreeWalker() {
650
+ return {};
651
+ }
652
+ } : document;
653
+ var createMarker = () => d.createComment("");
654
+ var isPrimitive = (value) => value === null || typeof value != "object" && typeof value != "function";
655
+ var isArray = Array.isArray;
656
+ var isIterable = (value) => isArray(value) || typeof value?.[Symbol.iterator] === "function";
657
+ var SPACE_CHAR = `[
658
+ \f\r]`;
659
+ var ATTR_VALUE_CHAR = `[^
660
+ \f\r"'\`<>=]`;
661
+ var NAME_CHAR = `[^\\s"'>=/]`;
662
+ var textEndRegex = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g;
663
+ var COMMENT_START = 1;
664
+ var TAG_NAME = 2;
665
+ var DYNAMIC_TAG_NAME = 3;
666
+ var commentEndRegex = /-->/g;
667
+ var comment2EndRegex = />/g;
668
+ var tagEndRegex = new RegExp(`>|${SPACE_CHAR}(?:(${NAME_CHAR}+)(${SPACE_CHAR}*=${SPACE_CHAR}*(?:${ATTR_VALUE_CHAR}|("|')|))|$)`, "g");
669
+ var ENTIRE_MATCH = 0;
670
+ var ATTRIBUTE_NAME = 1;
671
+ var SPACES_AND_EQUALS = 2;
672
+ var QUOTE_CHAR = 3;
673
+ var singleQuoteAttrEndRegex = /'/g;
674
+ var doubleQuoteAttrEndRegex = /"/g;
675
+ var rawTextElement = /^(?:script|style|textarea|title)$/i;
676
+ var HTML_RESULT = 1;
677
+ var SVG_RESULT = 2;
678
+ var MATHML_RESULT = 3;
679
+ var ATTRIBUTE_PART = 1;
680
+ var CHILD_PART = 2;
681
+ var PROPERTY_PART = 3;
682
+ var BOOLEAN_ATTRIBUTE_PART = 4;
683
+ var EVENT_PART = 5;
684
+ var ELEMENT_PART = 6;
685
+ var COMMENT_PART = 7;
686
+ var tag = (type) => (strings, ...values) => {
687
+ if (DEV_MODE2 && strings.some((s) => s === undefined)) {
688
+ console.warn(`Some template strings are undefined.
689
+ ` + "This is probably caused by illegal octal escape sequences.");
690
+ }
691
+ if (DEV_MODE2) {
692
+ if (values.some((val) => val?.["_$litStatic$"])) {
693
+ issueWarning2("", `Static values 'literal' or 'unsafeStatic' cannot be used as values to non-static templates.
694
+ ` + `Please use the static 'html' tag function. See https://lit.dev/docs/templates/expressions/#static-expressions`);
695
+ }
696
+ }
697
+ return {
698
+ ["_$litType$"]: type,
699
+ strings,
700
+ values
701
+ };
702
+ };
703
+ var html = tag(HTML_RESULT);
704
+ var svg = tag(SVG_RESULT);
705
+ var mathml = tag(MATHML_RESULT);
706
+ var noChange = Symbol.for("lit-noChange");
707
+ var nothing = Symbol.for("lit-nothing");
708
+ var templateCache = new WeakMap;
709
+ var walker = d.createTreeWalker(d, 129);
710
+ var sanitizerFactoryInternal = noopSanitizer;
711
+ function trustFromTemplateString(tsa, stringFromTSA) {
712
+ if (!isArray(tsa) || !tsa.hasOwnProperty("raw")) {
713
+ let message = "invalid template strings array";
714
+ if (DEV_MODE2) {
715
+ message = `
716
+ Internal Error: expected template strings to be an array
717
+ with a 'raw' field. Faking a template strings array by
718
+ calling html or svg like an ordinary function is effectively
719
+ the same as calling unsafeHtml and can lead to major security
720
+ issues, e.g. opening your code up to XSS attacks.
721
+ If you're using the html or svg tagged template functions normally
722
+ and still seeing this error, please file a bug at
723
+ https://github.com/lit/lit/issues/new?template=bug_report.md
724
+ and include information about your build tooling, if any.
725
+ `.trim().replace(/\n */g, `
726
+ `);
727
+ }
728
+ throw new Error(message);
729
+ }
730
+ return policy !== undefined ? policy.createHTML(stringFromTSA) : stringFromTSA;
731
+ }
732
+ var getTemplateHtml = (strings, type) => {
733
+ const l = strings.length - 1;
734
+ const attrNames = [];
735
+ let html = type === SVG_RESULT ? "<svg>" : type === MATHML_RESULT ? "<math>" : "";
736
+ let rawTextEndRegex;
737
+ let regex = textEndRegex;
738
+ for (let i = 0;i < l; i++) {
739
+ const s = strings[i];
740
+ let attrNameEndIndex = -1;
741
+ let attrName;
742
+ let lastIndex = 0;
743
+ let match;
744
+ while (lastIndex < s.length) {
745
+ regex.lastIndex = lastIndex;
746
+ match = regex.exec(s);
747
+ if (match === null) {
748
+ break;
749
+ }
750
+ lastIndex = regex.lastIndex;
751
+ if (regex === textEndRegex) {
752
+ if (match[COMMENT_START] === "!--") {
753
+ regex = commentEndRegex;
754
+ } else if (match[COMMENT_START] !== undefined) {
755
+ regex = comment2EndRegex;
756
+ } else if (match[TAG_NAME] !== undefined) {
757
+ if (rawTextElement.test(match[TAG_NAME])) {
758
+ rawTextEndRegex = new RegExp(`</${match[TAG_NAME]}`, "g");
759
+ }
760
+ regex = tagEndRegex;
761
+ } else if (match[DYNAMIC_TAG_NAME] !== undefined) {
762
+ if (DEV_MODE2) {
763
+ throw new Error("Bindings in tag names are not supported. Please use static templates instead. " + "See https://lit.dev/docs/templates/expressions/#static-expressions");
764
+ }
765
+ regex = tagEndRegex;
766
+ }
767
+ } else if (regex === tagEndRegex) {
768
+ if (match[ENTIRE_MATCH] === ">") {
769
+ regex = rawTextEndRegex ?? textEndRegex;
770
+ attrNameEndIndex = -1;
771
+ } else if (match[ATTRIBUTE_NAME] === undefined) {
772
+ attrNameEndIndex = -2;
773
+ } else {
774
+ attrNameEndIndex = regex.lastIndex - match[SPACES_AND_EQUALS].length;
775
+ attrName = match[ATTRIBUTE_NAME];
776
+ regex = match[QUOTE_CHAR] === undefined ? tagEndRegex : match[QUOTE_CHAR] === '"' ? doubleQuoteAttrEndRegex : singleQuoteAttrEndRegex;
777
+ }
778
+ } else if (regex === doubleQuoteAttrEndRegex || regex === singleQuoteAttrEndRegex) {
779
+ regex = tagEndRegex;
780
+ } else if (regex === commentEndRegex || regex === comment2EndRegex) {
781
+ regex = textEndRegex;
782
+ } else {
783
+ regex = tagEndRegex;
784
+ rawTextEndRegex = undefined;
785
+ }
786
+ }
787
+ if (DEV_MODE2) {
788
+ console.assert(attrNameEndIndex === -1 || regex === tagEndRegex || regex === singleQuoteAttrEndRegex || regex === doubleQuoteAttrEndRegex, "unexpected parse state B");
789
+ }
790
+ const end = regex === tagEndRegex && strings[i + 1].startsWith("/>") ? " " : "";
791
+ html += regex === textEndRegex ? s + nodeMarker : attrNameEndIndex >= 0 ? (attrNames.push(attrName), s.slice(0, attrNameEndIndex) + boundAttributeSuffix + s.slice(attrNameEndIndex)) + marker + end : s + marker + (attrNameEndIndex === -2 ? i : end);
792
+ }
793
+ const htmlResult = html + (strings[l] || "<?>") + (type === SVG_RESULT ? "</svg>" : type === MATHML_RESULT ? "</math>" : "");
794
+ return [trustFromTemplateString(strings, htmlResult), attrNames];
795
+ };
796
+
797
+ class Template {
798
+ constructor({ strings, ["_$litType$"]: type }, options) {
799
+ this.parts = [];
800
+ let node;
801
+ let nodeIndex = 0;
802
+ let attrNameIndex = 0;
803
+ const partCount = strings.length - 1;
804
+ const parts = this.parts;
805
+ const [html, attrNames] = getTemplateHtml(strings, type);
806
+ this.el = Template.createElement(html, options);
807
+ walker.currentNode = this.el.content;
808
+ if (type === SVG_RESULT || type === MATHML_RESULT) {
809
+ const wrapper = this.el.content.firstChild;
810
+ wrapper.replaceWith(...wrapper.childNodes);
811
+ }
812
+ while ((node = walker.nextNode()) !== null && parts.length < partCount) {
813
+ if (node.nodeType === 1) {
814
+ if (DEV_MODE2) {
815
+ const tag = node.localName;
816
+ if (/^(?:textarea|template)$/i.test(tag) && node.innerHTML.includes(marker)) {
817
+ const m = `Expressions are not supported inside \`${tag}\` ` + `elements. See https://lit.dev/msg/expression-in-${tag} for more ` + `information.`;
818
+ if (tag === "template") {
819
+ throw new Error(m);
820
+ } else
821
+ issueWarning2("", m);
822
+ }
823
+ }
824
+ if (node.hasAttributes()) {
825
+ for (const name of node.getAttributeNames()) {
826
+ if (name.endsWith(boundAttributeSuffix)) {
827
+ const realName = attrNames[attrNameIndex++];
828
+ const value = node.getAttribute(name);
829
+ const statics = value.split(marker);
830
+ const m = /([.?@])?(.*)/.exec(realName);
831
+ parts.push({
832
+ type: ATTRIBUTE_PART,
833
+ index: nodeIndex,
834
+ name: m[2],
835
+ strings: statics,
836
+ ctor: m[1] === "." ? PropertyPart : m[1] === "?" ? BooleanAttributePart : m[1] === "@" ? EventPart : AttributePart
837
+ });
838
+ node.removeAttribute(name);
839
+ } else if (name.startsWith(marker)) {
840
+ parts.push({
841
+ type: ELEMENT_PART,
842
+ index: nodeIndex
843
+ });
844
+ node.removeAttribute(name);
845
+ }
846
+ }
847
+ }
848
+ if (rawTextElement.test(node.tagName)) {
849
+ const strings = node.textContent.split(marker);
850
+ const lastIndex = strings.length - 1;
851
+ if (lastIndex > 0) {
852
+ node.textContent = trustedTypes2 ? trustedTypes2.emptyScript : "";
853
+ for (let i = 0;i < lastIndex; i++) {
854
+ node.append(strings[i], createMarker());
855
+ walker.nextNode();
856
+ parts.push({ type: CHILD_PART, index: ++nodeIndex });
857
+ }
858
+ node.append(strings[lastIndex], createMarker());
859
+ }
860
+ }
861
+ } else if (node.nodeType === 8) {
862
+ const data = node.data;
863
+ if (data === markerMatch) {
864
+ parts.push({ type: CHILD_PART, index: nodeIndex });
865
+ } else {
866
+ let i = -1;
867
+ while ((i = node.data.indexOf(marker, i + 1)) !== -1) {
868
+ parts.push({ type: COMMENT_PART, index: nodeIndex });
869
+ i += marker.length - 1;
870
+ }
871
+ }
872
+ }
873
+ nodeIndex++;
874
+ }
875
+ if (DEV_MODE2) {
876
+ if (attrNames.length !== attrNameIndex) {
877
+ throw new Error(`Detected duplicate attribute bindings. This occurs if your template ` + `has duplicate attributes on an element tag. For example ` + `"<input ?disabled=\${true} ?disabled=\${false}>" contains a ` + `duplicate "disabled" attribute. The error was detected in ` + `the following template:
878
+ ` + "`" + strings.join("${...}") + "`");
879
+ }
880
+ }
881
+ debugLogEvent2 && debugLogEvent2({
882
+ kind: "template prep",
883
+ template: this,
884
+ clonableTemplate: this.el,
885
+ parts: this.parts,
886
+ strings
887
+ });
888
+ }
889
+ static createElement(html, _options) {
890
+ const el = d.createElement("template");
891
+ el.innerHTML = html;
892
+ return el;
893
+ }
894
+ }
895
+ function resolveDirective(part, value, parent = part, attributeIndex) {
896
+ if (value === noChange) {
897
+ return value;
898
+ }
899
+ let currentDirective = attributeIndex !== undefined ? parent.__directives?.[attributeIndex] : parent.__directive;
900
+ const nextDirectiveConstructor = isPrimitive(value) ? undefined : value["_$litDirective$"];
901
+ if (currentDirective?.constructor !== nextDirectiveConstructor) {
902
+ currentDirective?.["_$notifyDirectiveConnectionChanged"]?.(false);
903
+ if (nextDirectiveConstructor === undefined) {
904
+ currentDirective = undefined;
905
+ } else {
906
+ currentDirective = new nextDirectiveConstructor(part);
907
+ currentDirective._$initialize(part, parent, attributeIndex);
908
+ }
909
+ if (attributeIndex !== undefined) {
910
+ (parent.__directives ??= [])[attributeIndex] = currentDirective;
911
+ } else {
912
+ parent.__directive = currentDirective;
913
+ }
914
+ }
915
+ if (currentDirective !== undefined) {
916
+ value = resolveDirective(part, currentDirective._$resolve(part, value.values), currentDirective, attributeIndex);
917
+ }
918
+ return value;
919
+ }
920
+
921
+ class TemplateInstance {
922
+ constructor(template, parent) {
923
+ this._$parts = [];
924
+ this._$disconnectableChildren = undefined;
925
+ this._$template = template;
926
+ this._$parent = parent;
927
+ }
928
+ get parentNode() {
929
+ return this._$parent.parentNode;
930
+ }
931
+ get _$isConnected() {
932
+ return this._$parent._$isConnected;
933
+ }
934
+ _clone(options) {
935
+ const { el: { content }, parts } = this._$template;
936
+ const fragment = (options?.creationScope ?? d).importNode(content, true);
937
+ walker.currentNode = fragment;
938
+ let node = walker.nextNode();
939
+ let nodeIndex = 0;
940
+ let partIndex = 0;
941
+ let templatePart = parts[0];
942
+ while (templatePart !== undefined) {
943
+ if (nodeIndex === templatePart.index) {
944
+ let part;
945
+ if (templatePart.type === CHILD_PART) {
946
+ part = new ChildPart(node, node.nextSibling, this, options);
947
+ } else if (templatePart.type === ATTRIBUTE_PART) {
948
+ part = new templatePart.ctor(node, templatePart.name, templatePart.strings, this, options);
949
+ } else if (templatePart.type === ELEMENT_PART) {
950
+ part = new ElementPart(node, this, options);
951
+ }
952
+ this._$parts.push(part);
953
+ templatePart = parts[++partIndex];
954
+ }
955
+ if (nodeIndex !== templatePart?.index) {
956
+ node = walker.nextNode();
957
+ nodeIndex++;
958
+ }
959
+ }
960
+ walker.currentNode = d;
961
+ return fragment;
962
+ }
963
+ _update(values) {
964
+ let i = 0;
965
+ for (const part of this._$parts) {
966
+ if (part !== undefined) {
967
+ debugLogEvent2 && debugLogEvent2({
968
+ kind: "set part",
969
+ part,
970
+ value: values[i],
971
+ valueIndex: i,
972
+ values,
973
+ templateInstance: this
974
+ });
975
+ if (part.strings !== undefined) {
976
+ part._$setValue(values, part, i);
977
+ i += part.strings.length - 2;
978
+ } else {
979
+ part._$setValue(values[i]);
980
+ }
981
+ }
982
+ i++;
983
+ }
984
+ }
985
+ }
986
+
987
+ class ChildPart {
988
+ get _$isConnected() {
989
+ return this._$parent?._$isConnected ?? this.__isConnected;
990
+ }
991
+ constructor(startNode, endNode, parent, options) {
992
+ this.type = CHILD_PART;
993
+ this._$committedValue = nothing;
994
+ this._$disconnectableChildren = undefined;
995
+ this._$startNode = startNode;
996
+ this._$endNode = endNode;
997
+ this._$parent = parent;
998
+ this.options = options;
999
+ this.__isConnected = options?.isConnected ?? true;
1000
+ if (ENABLE_EXTRA_SECURITY_HOOKS) {
1001
+ this._textSanitizer = undefined;
1002
+ }
1003
+ }
1004
+ get parentNode() {
1005
+ let parentNode = wrap(this._$startNode).parentNode;
1006
+ const parent = this._$parent;
1007
+ if (parent !== undefined && parentNode?.nodeType === 11) {
1008
+ parentNode = parent.parentNode;
1009
+ }
1010
+ return parentNode;
1011
+ }
1012
+ get startNode() {
1013
+ return this._$startNode;
1014
+ }
1015
+ get endNode() {
1016
+ return this._$endNode;
1017
+ }
1018
+ _$setValue(value, directiveParent = this) {
1019
+ if (DEV_MODE2 && this.parentNode === null) {
1020
+ throw new Error(`This \`ChildPart\` has no \`parentNode\` and therefore cannot accept a value. This likely means the element containing the part was manipulated in an unsupported way outside of Lit's control such that the part's marker nodes were ejected from DOM. For example, setting the element's \`innerHTML\` or \`textContent\` can do this.`);
1021
+ }
1022
+ value = resolveDirective(this, value, directiveParent);
1023
+ if (isPrimitive(value)) {
1024
+ if (value === nothing || value == null || value === "") {
1025
+ if (this._$committedValue !== nothing) {
1026
+ debugLogEvent2 && debugLogEvent2({
1027
+ kind: "commit nothing to child",
1028
+ start: this._$startNode,
1029
+ end: this._$endNode,
1030
+ parent: this._$parent,
1031
+ options: this.options
1032
+ });
1033
+ this._$clear();
1034
+ }
1035
+ this._$committedValue = nothing;
1036
+ } else if (value !== this._$committedValue && value !== noChange) {
1037
+ this._commitText(value);
1038
+ }
1039
+ } else if (value["_$litType$"] !== undefined) {
1040
+ this._commitTemplateResult(value);
1041
+ } else if (value.nodeType !== undefined) {
1042
+ if (DEV_MODE2 && this.options?.host === value) {
1043
+ this._commitText(`[probable mistake: rendered a template's host in itself ` + `(commonly caused by writing \${this} in a template]`);
1044
+ console.warn(`Attempted to render the template host`, value, `inside itself. This is almost always a mistake, and in dev mode `, `we render some warning text. In production however, we'll `, `render it, which will usually result in an error, and sometimes `, `in the element disappearing from the DOM.`);
1045
+ return;
1046
+ }
1047
+ this._commitNode(value);
1048
+ } else if (isIterable(value)) {
1049
+ this._commitIterable(value);
1050
+ } else {
1051
+ this._commitText(value);
1052
+ }
1053
+ }
1054
+ _insert(node) {
1055
+ return wrap(wrap(this._$startNode).parentNode).insertBefore(node, this._$endNode);
1056
+ }
1057
+ _commitNode(value) {
1058
+ if (this._$committedValue !== value) {
1059
+ this._$clear();
1060
+ if (ENABLE_EXTRA_SECURITY_HOOKS && sanitizerFactoryInternal !== noopSanitizer) {
1061
+ const parentNodeName = this._$startNode.parentNode?.nodeName;
1062
+ if (parentNodeName === "STYLE" || parentNodeName === "SCRIPT") {
1063
+ let message = "Forbidden";
1064
+ if (DEV_MODE2) {
1065
+ if (parentNodeName === "STYLE") {
1066
+ message = `Lit does not support binding inside style nodes. ` + `This is a security risk, as style injection attacks can ` + `exfiltrate data and spoof UIs. ` + `Consider instead using css\`...\` literals ` + `to compose styles, and do dynamic styling with ` + `css custom properties, ::parts, <slot>s, ` + `and by mutating the DOM rather than stylesheets.`;
1067
+ } else {
1068
+ message = `Lit does not support binding inside script nodes. ` + `This is a security risk, as it could allow arbitrary ` + `code execution.`;
1069
+ }
1070
+ }
1071
+ throw new Error(message);
1072
+ }
1073
+ }
1074
+ debugLogEvent2 && debugLogEvent2({
1075
+ kind: "commit node",
1076
+ start: this._$startNode,
1077
+ parent: this._$parent,
1078
+ value,
1079
+ options: this.options
1080
+ });
1081
+ this._$committedValue = this._insert(value);
1082
+ }
1083
+ }
1084
+ _commitText(value) {
1085
+ if (this._$committedValue !== nothing && isPrimitive(this._$committedValue)) {
1086
+ const node = wrap(this._$startNode).nextSibling;
1087
+ if (ENABLE_EXTRA_SECURITY_HOOKS) {
1088
+ if (this._textSanitizer === undefined) {
1089
+ this._textSanitizer = createSanitizer(node, "data", "property");
1090
+ }
1091
+ value = this._textSanitizer(value);
1092
+ }
1093
+ debugLogEvent2 && debugLogEvent2({
1094
+ kind: "commit text",
1095
+ node,
1096
+ value,
1097
+ options: this.options
1098
+ });
1099
+ node.data = value;
1100
+ } else {
1101
+ if (ENABLE_EXTRA_SECURITY_HOOKS) {
1102
+ const textNode = d.createTextNode("");
1103
+ this._commitNode(textNode);
1104
+ if (this._textSanitizer === undefined) {
1105
+ this._textSanitizer = createSanitizer(textNode, "data", "property");
1106
+ }
1107
+ value = this._textSanitizer(value);
1108
+ debugLogEvent2 && debugLogEvent2({
1109
+ kind: "commit text",
1110
+ node: textNode,
1111
+ value,
1112
+ options: this.options
1113
+ });
1114
+ textNode.data = value;
1115
+ } else {
1116
+ this._commitNode(d.createTextNode(value));
1117
+ debugLogEvent2 && debugLogEvent2({
1118
+ kind: "commit text",
1119
+ node: wrap(this._$startNode).nextSibling,
1120
+ value,
1121
+ options: this.options
1122
+ });
1123
+ }
1124
+ }
1125
+ this._$committedValue = value;
1126
+ }
1127
+ _commitTemplateResult(result) {
1128
+ const { values, ["_$litType$"]: type } = result;
1129
+ const template = typeof type === "number" ? this._$getTemplate(result) : (type.el === undefined && (type.el = Template.createElement(trustFromTemplateString(type.h, type.h[0]), this.options)), type);
1130
+ if (this._$committedValue?._$template === template) {
1131
+ debugLogEvent2 && debugLogEvent2({
1132
+ kind: "template updating",
1133
+ template,
1134
+ instance: this._$committedValue,
1135
+ parts: this._$committedValue._$parts,
1136
+ options: this.options,
1137
+ values
1138
+ });
1139
+ this._$committedValue._update(values);
1140
+ } else {
1141
+ const instance = new TemplateInstance(template, this);
1142
+ const fragment = instance._clone(this.options);
1143
+ debugLogEvent2 && debugLogEvent2({
1144
+ kind: "template instantiated",
1145
+ template,
1146
+ instance,
1147
+ parts: instance._$parts,
1148
+ options: this.options,
1149
+ fragment,
1150
+ values
1151
+ });
1152
+ instance._update(values);
1153
+ debugLogEvent2 && debugLogEvent2({
1154
+ kind: "template instantiated and updated",
1155
+ template,
1156
+ instance,
1157
+ parts: instance._$parts,
1158
+ options: this.options,
1159
+ fragment,
1160
+ values
1161
+ });
1162
+ this._commitNode(fragment);
1163
+ this._$committedValue = instance;
1164
+ }
1165
+ }
1166
+ _$getTemplate(result) {
1167
+ let template = templateCache.get(result.strings);
1168
+ if (template === undefined) {
1169
+ templateCache.set(result.strings, template = new Template(result));
1170
+ }
1171
+ return template;
1172
+ }
1173
+ _commitIterable(value) {
1174
+ if (!isArray(this._$committedValue)) {
1175
+ this._$committedValue = [];
1176
+ this._$clear();
1177
+ }
1178
+ const itemParts = this._$committedValue;
1179
+ let partIndex = 0;
1180
+ let itemPart;
1181
+ for (const item of value) {
1182
+ if (partIndex === itemParts.length) {
1183
+ itemParts.push(itemPart = new ChildPart(this._insert(createMarker()), this._insert(createMarker()), this, this.options));
1184
+ } else {
1185
+ itemPart = itemParts[partIndex];
1186
+ }
1187
+ itemPart._$setValue(item);
1188
+ partIndex++;
1189
+ }
1190
+ if (partIndex < itemParts.length) {
1191
+ this._$clear(itemPart && wrap(itemPart._$endNode).nextSibling, partIndex);
1192
+ itemParts.length = partIndex;
1193
+ }
1194
+ }
1195
+ _$clear(start = wrap(this._$startNode).nextSibling, from) {
1196
+ this._$notifyConnectionChanged?.(false, true, from);
1197
+ while (start !== this._$endNode) {
1198
+ const n = wrap(start).nextSibling;
1199
+ wrap(start).remove();
1200
+ start = n;
1201
+ }
1202
+ }
1203
+ setConnected(isConnected) {
1204
+ if (this._$parent === undefined) {
1205
+ this.__isConnected = isConnected;
1206
+ this._$notifyConnectionChanged?.(isConnected);
1207
+ } else if (DEV_MODE2) {
1208
+ throw new Error("part.setConnected() may only be called on a " + "RootPart returned from render().");
1209
+ }
1210
+ }
1211
+ }
1212
+
1213
+ class AttributePart {
1214
+ get tagName() {
1215
+ return this.element.tagName;
1216
+ }
1217
+ get _$isConnected() {
1218
+ return this._$parent._$isConnected;
1219
+ }
1220
+ constructor(element, name, strings, parent, options) {
1221
+ this.type = ATTRIBUTE_PART;
1222
+ this._$committedValue = nothing;
1223
+ this._$disconnectableChildren = undefined;
1224
+ this.element = element;
1225
+ this.name = name;
1226
+ this._$parent = parent;
1227
+ this.options = options;
1228
+ if (strings.length > 2 || strings[0] !== "" || strings[1] !== "") {
1229
+ this._$committedValue = new Array(strings.length - 1).fill(new String);
1230
+ this.strings = strings;
1231
+ } else {
1232
+ this._$committedValue = nothing;
1233
+ }
1234
+ if (ENABLE_EXTRA_SECURITY_HOOKS) {
1235
+ this._sanitizer = undefined;
1236
+ }
1237
+ }
1238
+ _$setValue(value, directiveParent = this, valueIndex, noCommit) {
1239
+ const strings = this.strings;
1240
+ let change = false;
1241
+ if (strings === undefined) {
1242
+ value = resolveDirective(this, value, directiveParent, 0);
1243
+ change = !isPrimitive(value) || value !== this._$committedValue && value !== noChange;
1244
+ if (change) {
1245
+ this._$committedValue = value;
1246
+ }
1247
+ } else {
1248
+ const values = value;
1249
+ value = strings[0];
1250
+ let i, v;
1251
+ for (i = 0;i < strings.length - 1; i++) {
1252
+ v = resolveDirective(this, values[valueIndex + i], directiveParent, i);
1253
+ if (v === noChange) {
1254
+ v = this._$committedValue[i];
1255
+ }
1256
+ change ||= !isPrimitive(v) || v !== this._$committedValue[i];
1257
+ if (v === nothing) {
1258
+ value = nothing;
1259
+ } else if (value !== nothing) {
1260
+ value += (v ?? "") + strings[i + 1];
1261
+ }
1262
+ this._$committedValue[i] = v;
1263
+ }
1264
+ }
1265
+ if (change && !noCommit) {
1266
+ this._commitValue(value);
1267
+ }
1268
+ }
1269
+ _commitValue(value) {
1270
+ if (value === nothing) {
1271
+ wrap(this.element).removeAttribute(this.name);
1272
+ } else {
1273
+ if (ENABLE_EXTRA_SECURITY_HOOKS) {
1274
+ if (this._sanitizer === undefined) {
1275
+ this._sanitizer = sanitizerFactoryInternal(this.element, this.name, "attribute");
1276
+ }
1277
+ value = this._sanitizer(value ?? "");
1278
+ }
1279
+ debugLogEvent2 && debugLogEvent2({
1280
+ kind: "commit attribute",
1281
+ element: this.element,
1282
+ name: this.name,
1283
+ value,
1284
+ options: this.options
1285
+ });
1286
+ wrap(this.element).setAttribute(this.name, value ?? "");
1287
+ }
1288
+ }
1289
+ }
1290
+
1291
+ class PropertyPart extends AttributePart {
1292
+ constructor() {
1293
+ super(...arguments);
1294
+ this.type = PROPERTY_PART;
1295
+ }
1296
+ _commitValue(value) {
1297
+ if (ENABLE_EXTRA_SECURITY_HOOKS) {
1298
+ if (this._sanitizer === undefined) {
1299
+ this._sanitizer = sanitizerFactoryInternal(this.element, this.name, "property");
1300
+ }
1301
+ value = this._sanitizer(value);
1302
+ }
1303
+ debugLogEvent2 && debugLogEvent2({
1304
+ kind: "commit property",
1305
+ element: this.element,
1306
+ name: this.name,
1307
+ value,
1308
+ options: this.options
1309
+ });
1310
+ this.element[this.name] = value === nothing ? undefined : value;
1311
+ }
1312
+ }
1313
+
1314
+ class BooleanAttributePart extends AttributePart {
1315
+ constructor() {
1316
+ super(...arguments);
1317
+ this.type = BOOLEAN_ATTRIBUTE_PART;
1318
+ }
1319
+ _commitValue(value) {
1320
+ debugLogEvent2 && debugLogEvent2({
1321
+ kind: "commit boolean attribute",
1322
+ element: this.element,
1323
+ name: this.name,
1324
+ value: !!(value && value !== nothing),
1325
+ options: this.options
1326
+ });
1327
+ wrap(this.element).toggleAttribute(this.name, !!value && value !== nothing);
1328
+ }
1329
+ }
1330
+
1331
+ class EventPart extends AttributePart {
1332
+ constructor(element, name, strings, parent, options) {
1333
+ super(element, name, strings, parent, options);
1334
+ this.type = EVENT_PART;
1335
+ if (DEV_MODE2 && this.strings !== undefined) {
1336
+ throw new Error(`A \`<${element.localName}>\` has a \`@${name}=...\` listener with ` + "invalid content. Event listeners in templates must have exactly " + "one expression and no surrounding text.");
1337
+ }
1338
+ }
1339
+ _$setValue(newListener, directiveParent = this) {
1340
+ newListener = resolveDirective(this, newListener, directiveParent, 0) ?? nothing;
1341
+ if (newListener === noChange) {
1342
+ return;
1343
+ }
1344
+ const oldListener = this._$committedValue;
1345
+ const shouldRemoveListener = newListener === nothing && oldListener !== nothing || newListener.capture !== oldListener.capture || newListener.once !== oldListener.once || newListener.passive !== oldListener.passive;
1346
+ const shouldAddListener = newListener !== nothing && (oldListener === nothing || shouldRemoveListener);
1347
+ debugLogEvent2 && debugLogEvent2({
1348
+ kind: "commit event listener",
1349
+ element: this.element,
1350
+ name: this.name,
1351
+ value: newListener,
1352
+ options: this.options,
1353
+ removeListener: shouldRemoveListener,
1354
+ addListener: shouldAddListener,
1355
+ oldListener
1356
+ });
1357
+ if (shouldRemoveListener) {
1358
+ this.element.removeEventListener(this.name, this, oldListener);
1359
+ }
1360
+ if (shouldAddListener) {
1361
+ this.element.addEventListener(this.name, this, newListener);
1362
+ }
1363
+ this._$committedValue = newListener;
1364
+ }
1365
+ handleEvent(event) {
1366
+ if (typeof this._$committedValue === "function") {
1367
+ this._$committedValue.call(this.options?.host ?? this.element, event);
1368
+ } else {
1369
+ this._$committedValue.handleEvent(event);
1370
+ }
1371
+ }
1372
+ }
1373
+
1374
+ class ElementPart {
1375
+ constructor(element, parent, options) {
1376
+ this.element = element;
1377
+ this.type = ELEMENT_PART;
1378
+ this._$disconnectableChildren = undefined;
1379
+ this._$parent = parent;
1380
+ this.options = options;
1381
+ }
1382
+ get _$isConnected() {
1383
+ return this._$parent._$isConnected;
1384
+ }
1385
+ _$setValue(value) {
1386
+ debugLogEvent2 && debugLogEvent2({
1387
+ kind: "commit to element binding",
1388
+ element: this.element,
1389
+ value,
1390
+ options: this.options
1391
+ });
1392
+ resolveDirective(this, value);
1393
+ }
1394
+ }
1395
+ var _$LH = {
1396
+ _boundAttributeSuffix: boundAttributeSuffix,
1397
+ _marker: marker,
1398
+ _markerMatch: markerMatch,
1399
+ _HTML_RESULT: HTML_RESULT,
1400
+ _getTemplateHtml: getTemplateHtml,
1401
+ _TemplateInstance: TemplateInstance,
1402
+ _isIterable: isIterable,
1403
+ _resolveDirective: resolveDirective,
1404
+ _ChildPart: ChildPart,
1405
+ _AttributePart: AttributePart,
1406
+ _BooleanAttributePart: BooleanAttributePart,
1407
+ _EventPart: EventPart,
1408
+ _PropertyPart: PropertyPart,
1409
+ _ElementPart: ElementPart
1410
+ };
1411
+ var polyfillSupport2 = DEV_MODE2 ? global3.litHtmlPolyfillSupportDevMode : global3.litHtmlPolyfillSupport;
1412
+ polyfillSupport2?.(Template, ChildPart);
1413
+ (global3.litHtmlVersions ??= []).push("3.3.3");
1414
+ if (DEV_MODE2 && global3.litHtmlVersions.length > 1) {
1415
+ queueMicrotask(() => {
1416
+ issueWarning2("multiple-versions", `Multiple versions of Lit loaded. ` + `Loading multiple versions is not recommended.`);
1417
+ });
1418
+ }
1419
+ var render = (value, container, options) => {
1420
+ if (DEV_MODE2 && container == null) {
1421
+ throw new TypeError(`The container to render into may not be ${container}`);
1422
+ }
1423
+ const renderId = DEV_MODE2 ? debugLogRenderId++ : 0;
1424
+ const partOwnerNode = options?.renderBefore ?? container;
1425
+ let part = partOwnerNode["_$litPart$"];
1426
+ debugLogEvent2 && debugLogEvent2({
1427
+ kind: "begin render",
1428
+ id: renderId,
1429
+ value,
1430
+ container,
1431
+ options,
1432
+ part
1433
+ });
1434
+ if (part === undefined) {
1435
+ const endNode = options?.renderBefore ?? null;
1436
+ partOwnerNode["_$litPart$"] = part = new ChildPart(container.insertBefore(createMarker(), endNode), endNode, undefined, options ?? {});
1437
+ }
1438
+ part._$setValue(value);
1439
+ debugLogEvent2 && debugLogEvent2({
1440
+ kind: "end render",
1441
+ id: renderId,
1442
+ value,
1443
+ container,
1444
+ options,
1445
+ part
1446
+ });
1447
+ return part;
1448
+ };
1449
+ if (ENABLE_EXTRA_SECURITY_HOOKS) {
1450
+ render.setSanitizer = setSanitizer;
1451
+ render.createSanitizer = createSanitizer;
1452
+ if (DEV_MODE2) {
1453
+ render._testOnlyClearSanitizerFactoryDoNotCallOrElse = _testOnlyClearSanitizerFactoryDoNotCallOrElse;
1454
+ }
1455
+ }
1456
+
1457
+ // ../../node_modules/.pnpm/lit-element@4.2.2/node_modules/lit-element/development/lit-element.js
1458
+ var JSCompiler_renameProperty2 = (prop, _obj) => prop;
1459
+ var DEV_MODE3 = true;
1460
+ var global4 = globalThis;
1461
+ var issueWarning3;
1462
+ if (DEV_MODE3) {
1463
+ global4.litIssuedWarnings ??= new Set;
1464
+ issueWarning3 = (code, warning) => {
1465
+ warning += ` See https://lit.dev/msg/${code} for more information.`;
1466
+ if (!global4.litIssuedWarnings.has(warning) && !global4.litIssuedWarnings.has(code)) {
1467
+ console.warn(warning);
1468
+ global4.litIssuedWarnings.add(warning);
1469
+ }
1470
+ };
1471
+ }
1472
+
1473
+ class LitElement extends ReactiveElement {
1474
+ constructor() {
1475
+ super(...arguments);
1476
+ this.renderOptions = { host: this };
1477
+ this.__childPart = undefined;
1478
+ }
1479
+ createRenderRoot() {
1480
+ const renderRoot = super.createRenderRoot();
1481
+ this.renderOptions.renderBefore ??= renderRoot.firstChild;
1482
+ return renderRoot;
1483
+ }
1484
+ update(changedProperties) {
1485
+ const value = this.render();
1486
+ if (!this.hasUpdated) {
1487
+ this.renderOptions.isConnected = this.isConnected;
1488
+ }
1489
+ super.update(changedProperties);
1490
+ this.__childPart = render(value, this.renderRoot, this.renderOptions);
1491
+ }
1492
+ connectedCallback() {
1493
+ super.connectedCallback();
1494
+ this.__childPart?.setConnected(true);
1495
+ }
1496
+ disconnectedCallback() {
1497
+ super.disconnectedCallback();
1498
+ this.__childPart?.setConnected(false);
1499
+ }
1500
+ render() {
1501
+ return noChange;
1502
+ }
1503
+ }
1504
+ LitElement["_$litElement$"] = true;
1505
+ LitElement[JSCompiler_renameProperty2("finalized", LitElement)] = true;
1506
+ global4.litElementHydrateSupport?.({ LitElement });
1507
+ var polyfillSupport3 = DEV_MODE3 ? global4.litElementPolyfillSupportDevMode : global4.litElementPolyfillSupport;
1508
+ polyfillSupport3?.({ LitElement });
1509
+ (global4.litElementVersions ??= []).push("4.2.2");
1510
+ if (DEV_MODE3 && global4.litElementVersions.length > 1) {
1511
+ queueMicrotask(() => {
1512
+ issueWarning3("multiple-versions", `Multiple versions of Lit loaded. Loading multiple versions ` + `is not recommended.`);
1513
+ });
1514
+ }
1515
+ // ../../node_modules/.pnpm/lit-html@3.3.3/node_modules/lit-html/development/directive.js
1516
+ var directive = (c) => (...values) => ({
1517
+ ["_$litDirective$"]: c,
1518
+ values
1519
+ });
1520
+
1521
+ class Directive {
1522
+ constructor(_partInfo) {}
1523
+ get _$isConnected() {
1524
+ return this._$parent._$isConnected;
1525
+ }
1526
+ _$initialize(part, parent, attributeIndex) {
1527
+ this.__part = part;
1528
+ this._$parent = parent;
1529
+ this.__attributeIndex = attributeIndex;
1530
+ }
1531
+ _$resolve(part, props) {
1532
+ return this.update(part, props);
1533
+ }
1534
+ update(_part, props) {
1535
+ return this.render(...props);
1536
+ }
1537
+ }
1538
+
1539
+ // ../../node_modules/.pnpm/lit-html@3.3.3/node_modules/lit-html/development/directive-helpers.js
1540
+ var { _ChildPart: ChildPart2 } = _$LH;
1541
+ var ENABLE_SHADYDOM_NOPATCH2 = true;
1542
+ var wrap2 = ENABLE_SHADYDOM_NOPATCH2 && window.ShadyDOM?.inUse && window.ShadyDOM?.noPatch === true ? window.ShadyDOM.wrap : (node) => node;
1543
+ var RESET_VALUE = {};
1544
+ var setCommittedValue = (part, value = RESET_VALUE) => part._$committedValue = value;
1545
+
1546
+ // ../../node_modules/.pnpm/lit-html@3.3.3/node_modules/lit-html/development/directives/keyed.js
1547
+ class Keyed extends Directive {
1548
+ constructor() {
1549
+ super(...arguments);
1550
+ this.key = nothing;
1551
+ }
1552
+ render(k, v) {
1553
+ this.key = k;
1554
+ return v;
1555
+ }
1556
+ update(part, [k, v]) {
1557
+ if (k !== this.key) {
1558
+ setCommittedValue(part);
1559
+ this.key = k;
1560
+ }
1561
+ return v;
1562
+ }
1563
+ }
1564
+ var keyed = directive(Keyed);
1565
+ // src/index.ts
1566
+ class WodiraBrowserApiError extends Error {
1567
+ status;
1568
+ statusText;
1569
+ payload;
1570
+ constructor(params) {
1571
+ super(params.message);
1572
+ this.name = "WodiraBrowserApiError";
1573
+ this.status = params.status;
1574
+ this.statusText = params.statusText;
1575
+ this.payload = params.payload;
1576
+ }
1577
+ }
1578
+ var DEFAULT_BASE_URL = "https://api.wodira.app";
1579
+ var BROWSER_API_PREFIX = "/external/v1/browser";
1580
+
1581
+ class WodiraBrowserClient {
1582
+ publishableKey;
1583
+ baseUrl;
1584
+ fetcher;
1585
+ headers;
1586
+ checkoutSecrets = new Map;
1587
+ constructor(options) {
1588
+ if (!options.publishableKey?.trim()) {
1589
+ throw new Error("WodiraBrowserClient requires a publishableKey.");
1590
+ }
1591
+ if (!options.publishableKey.startsWith("wpk_live_")) {
1592
+ throw new Error("Wodira browser publishable keys must start with wpk_live_.");
1593
+ }
1594
+ this.publishableKey = options.publishableKey.trim();
1595
+ this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
1596
+ this.fetcher = options.fetch ?? globalThis.fetch.bind(globalThis);
1597
+ this.headers = options.headers;
1598
+ }
1599
+ searchEvents(input = {}, signal) {
1600
+ return this.request("/events/search", {
1601
+ method: "POST",
1602
+ body: input,
1603
+ signal
1604
+ });
1605
+ }
1606
+ getEvent(eventId, signal) {
1607
+ return this.request(`/events/${encodeURIComponent(eventId)}`, { signal });
1608
+ }
1609
+ getShirtSponsorCampaign(campaignId, signal) {
1610
+ return this.request(`/shirt-sponsors/${encodeURIComponent(campaignId)}`, {
1611
+ signal
1612
+ });
1613
+ }
1614
+ getPricingCards(eventId, signal) {
1615
+ return this.request(`/events/${encodeURIComponent(eventId)}/pricing-cards`, { signal });
1616
+ }
1617
+ getRegistrationSummary(input, signal) {
1618
+ return this.request("/checkout/registration/summary", {
1619
+ method: "POST",
1620
+ body: input,
1621
+ signal
1622
+ });
1623
+ }
1624
+ createRegistrationCheckoutSession(input, signal) {
1625
+ let secret = input.checkoutResumeSecret;
1626
+ if (!secret && input.idempotencyKey) {
1627
+ secret = this.checkoutSecrets.get(input.idempotencyKey);
1628
+ if (!secret) {
1629
+ secret = globalThis.crypto.randomUUID();
1630
+ if (this.checkoutSecrets.size >= 128)
1631
+ this.checkoutSecrets.delete(this.checkoutSecrets.keys().next().value);
1632
+ this.checkoutSecrets.set(input.idempotencyKey, secret);
1633
+ }
1634
+ }
1635
+ return this.request("/checkout/registration/session", {
1636
+ method: "POST",
1637
+ body: serializeRegistrationInput({
1638
+ ...input,
1639
+ ...secret ? { checkoutResumeSecret: secret } : {}
1640
+ }),
1641
+ signal
1642
+ });
1643
+ }
1644
+ lookupRegistrationReceipts(eventId, input, signal) {
1645
+ return this.request(`/events/${encodeURIComponent(eventId)}/registration-receipts/lookup`, {
1646
+ method: "POST",
1647
+ body: input,
1648
+ signal
1649
+ });
1650
+ }
1651
+ sendRegistrationReceipts(eventId, input, signal) {
1652
+ return this.request(`/events/${encodeURIComponent(eventId)}/registration-receipts/send`, {
1653
+ method: "POST",
1654
+ body: input,
1655
+ signal
1656
+ });
1657
+ }
1658
+ async request(path, options = {}) {
1659
+ const headers = new Headers(this.headers);
1660
+ headers.set("accept", "application/json");
1661
+ headers.set("x-publishable-key", this.publishableKey);
1662
+ const init = { method: options.method ?? "GET", headers };
1663
+ if (options.signal)
1664
+ init.signal = options.signal;
1665
+ if (options.body !== undefined) {
1666
+ headers.set("content-type", "application/json");
1667
+ init.body = JSON.stringify(options.body);
1668
+ }
1669
+ const response = await this.fetcher(`${this.baseUrl}${BROWSER_API_PREFIX}${path}`, init);
1670
+ if (!response.ok) {
1671
+ const payload = await readResponsePayload(response);
1672
+ throw new WodiraBrowserApiError({
1673
+ status: response.status,
1674
+ statusText: response.statusText,
1675
+ message: extractErrorMessage(payload, response),
1676
+ payload
1677
+ });
1678
+ }
1679
+ const text = await response.text();
1680
+ return text ? JSON.parse(text) : undefined;
1681
+ }
1682
+ }
1683
+ function createWodiraBrowserClient(options) {
1684
+ return new WodiraBrowserClient(options);
1685
+ }
1686
+ async function readResponsePayload(response) {
1687
+ const text = await response.text();
1688
+ if (!text)
1689
+ return null;
1690
+ try {
1691
+ return JSON.parse(text);
1692
+ } catch {
1693
+ return text;
1694
+ }
1695
+ }
1696
+ function extractErrorMessage(payload, response) {
1697
+ if (typeof payload === "string")
1698
+ return payload;
1699
+ const outerMessage = payload?.message;
1700
+ const message = outerMessage !== null && typeof outerMessage === "object" && "message" in outerMessage ? outerMessage.message : outerMessage;
1701
+ if (typeof message === "string")
1702
+ return message;
1703
+ if (Array.isArray(message))
1704
+ return message.filter((item) => typeof item === "string").join(", ");
1705
+ if (typeof payload?.error === "string")
1706
+ return payload.error;
1707
+ return `WODira browser API request failed with ${response.status} ${response.statusText}`;
1708
+ }
1709
+ function serializeRegistrationInput(input) {
1710
+ return {
1711
+ ...input,
1712
+ athletes: input.athletes.map(serializeAthleteInput),
1713
+ ...input.guestRegistrations ? {
1714
+ guestRegistrations: input.guestRegistrations.map((guest) => ({
1715
+ ...guest,
1716
+ athletes: guest.athletes.map(serializeAthleteInput)
1717
+ }))
1718
+ } : {}
1719
+ };
1720
+ }
1721
+ function serializeAthleteInput(athlete) {
1722
+ return {
1723
+ ...athlete,
1724
+ birthDate: athlete.birthDate instanceof Date ? athlete.birthDate.toISOString().slice(0, 10) : athlete.birthDate
1725
+ };
1726
+ }
1727
+
1728
+ // src/ui/styles.ts
1729
+ var wodiraUiStyles = css`
1730
+ :host {
1731
+ box-sizing: border-box;
1732
+ color: var(--wodira-color-text, #17132e);
1733
+ display: block;
1734
+ font-family: var(--wodira-font-family, inherit);
1735
+ font-size: var(--wodira-font-size, 1rem);
1736
+ line-height: 1.5;
1737
+ container-type: inline-size;
1738
+ min-width: 0;
1739
+ overflow-wrap: anywhere;
1740
+ }
1741
+
1742
+ *,
1743
+ *::before,
1744
+ *::after {
1745
+ box-sizing: inherit;
1746
+ }
1747
+
1748
+ [hidden] {
1749
+ display: none !important;
1750
+ }
1751
+
1752
+ [part~='stack'] {
1753
+ display: grid;
1754
+ gap: var(--wodira-space, 1rem);
1755
+ }
1756
+
1757
+ [part~='grid'] {
1758
+ display: grid;
1759
+ gap: var(--wodira-space, 1rem);
1760
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--wodira-grid-min, 15rem)), 1fr));
1761
+ }
1762
+
1763
+ [part~='card'] {
1764
+ background: var(--wodira-color-surface, #fff);
1765
+ border: 1px solid var(--wodira-color-border, #dcd9e3);
1766
+ border-radius: var(--wodira-radius, 1rem);
1767
+ box-shadow: var(--wodira-shadow, 0 4px 18px rgb(23 19 46 / 0.04));
1768
+ padding: var(--wodira-card-padding, clamp(1rem, 3cqi, 1.75rem));
1769
+ }
1770
+
1771
+ [part~='button'] {
1772
+ align-items: center;
1773
+ background: var(--wodira-color-primary, #17132e);
1774
+ border: 0;
1775
+ border-radius: var(--wodira-radius-sm, 0.625rem);
1776
+ color: var(--wodira-color-primary-contrast, #fff);
1777
+ cursor: pointer;
1778
+ display: inline-flex;
1779
+ font: inherit;
1780
+ font-weight: 700;
1781
+ justify-content: center;
1782
+ min-height: var(--wodira-control-height, 2.75rem);
1783
+ padding: 0.75rem 1rem;
1784
+ transition:
1785
+ opacity 0.2s ease,
1786
+ transform 0.2s ease;
1787
+ }
1788
+
1789
+ [part~='button']:hover:not(:disabled) {
1790
+ transform: translateY(-1px);
1791
+ }
1792
+
1793
+ [part~='button']:focus-visible,
1794
+ [part~='input']:focus-visible,
1795
+ [part~='select']:focus-visible,
1796
+ [part~='textarea']:focus-visible,
1797
+ [part~='checkbox']:focus-visible {
1798
+ outline: 3px solid color-mix(in srgb, var(--wodira-color-accent, #c40072) 35%, transparent);
1799
+ outline-offset: 2px;
1800
+ }
1801
+
1802
+ [part~='button']:disabled {
1803
+ cursor: not-allowed;
1804
+ opacity: 0.6;
1805
+ }
1806
+
1807
+ [part~='button'][part~='secondary'] {
1808
+ background: var(--wodira-color-muted, #f6f5f8);
1809
+ color: var(--wodira-color-text, #17132e);
1810
+ }
1811
+
1812
+ [part~='text-button'] {
1813
+ justify-self: start;
1814
+ min-height: auto;
1815
+ padding: 0.45rem 0.7rem;
1816
+ width: auto;
1817
+ }
1818
+
1819
+ [part~='input'],
1820
+ [part~='select'],
1821
+ [part~='textarea'] {
1822
+ background: var(--wodira-color-surface, #fff);
1823
+ border: 1px solid var(--wodira-color-border, #dcd9e3);
1824
+ border-radius: var(--wodira-radius-sm, 0.625rem);
1825
+ color: var(--wodira-color-text, #17132e);
1826
+ font: inherit;
1827
+ min-height: var(--wodira-control-height, 2.75rem);
1828
+ padding: 0.7rem 0.8rem;
1829
+ width: 100%;
1830
+ }
1831
+
1832
+ [part~='input'][aria-invalid='true'],
1833
+ [part~='select'][aria-invalid='true'],
1834
+ [part~='textarea'][aria-invalid='true'] {
1835
+ border-color: var(--wodira-color-danger, #b42318);
1836
+ }
1837
+
1838
+ [part~='textarea'] {
1839
+ min-height: 5.5rem;
1840
+ resize: vertical;
1841
+ }
1842
+
1843
+ [part~='label'] {
1844
+ display: grid;
1845
+ gap: 0.35rem;
1846
+ font-size: 0.92rem;
1847
+ font-weight: 700;
1848
+ }
1849
+
1850
+ [part~='checkbox'] {
1851
+ margin-inline-end: 0.5rem;
1852
+ }
1853
+
1854
+ [part~='email-field'] {
1855
+ min-width: 0;
1856
+ }
1857
+ [part~='email-suggestion'] {
1858
+ display: flex;
1859
+ flex-wrap: wrap;
1860
+ align-items: center;
1861
+ gap: 0.25rem;
1862
+ margin-top: 0.5rem;
1863
+ }
1864
+ [part~='email-correction'] {
1865
+ background: transparent;
1866
+ color: var(--wodira-color-accent, #c40072);
1867
+ min-height: 2.75rem;
1868
+ max-width: 100%;
1869
+ padding: 0.25rem 0.5rem;
1870
+ overflow-wrap: anywhere;
1871
+ }
1872
+ [part~='email-delivery'] {
1873
+ overflow-wrap: anywhere;
1874
+ margin-top: 0.5rem;
1875
+ }
1876
+
1877
+ [part~='hint'],
1878
+ [part~='meta'],
1879
+ [part~='field-error'] {
1880
+ color: var(--wodira-color-text-muted, #625e70);
1881
+ font-size: 0.875rem;
1882
+ }
1883
+
1884
+ [part~='description'] {
1885
+ color: var(--wodira-color-text-muted, #625e70);
1886
+ display: grid;
1887
+ font-size: 0.95rem;
1888
+ gap: 0.55rem;
1889
+ line-height: 1.65;
1890
+ }
1891
+
1892
+ [part~='description'] p {
1893
+ margin: 0;
1894
+ }
1895
+
1896
+ [part~='description-heading'] {
1897
+ color: var(--wodira-color-text, #17132e);
1898
+ font-weight: 800;
1899
+ }
1900
+
1901
+ [part~='description-list'] {
1902
+ display: grid;
1903
+ gap: 0.3rem;
1904
+ margin: 0;
1905
+ padding-inline-start: 1.15rem;
1906
+ }
1907
+
1908
+ [part~='event-card-description'] {
1909
+ display: -webkit-box;
1910
+ margin: 0;
1911
+ max-width: 65ch;
1912
+ overflow: hidden;
1913
+ -webkit-box-orient: vertical;
1914
+ -webkit-line-clamp: var(--wodira-event-card-description-lines, 4);
1915
+ }
1916
+
1917
+ [part~='event-card-description-full'] {
1918
+ margin: 0;
1919
+ max-width: 65ch;
1920
+ }
1921
+
1922
+ [part~='inline-code'] {
1923
+ background: var(--wodira-color-muted, #f6f5f8);
1924
+ border-radius: 0.35rem;
1925
+ color: var(--wodira-color-text, #17132e);
1926
+ font-family:
1927
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;
1928
+ font-size: 0.9em;
1929
+ padding: 0.08rem 0.28rem;
1930
+ }
1931
+
1932
+ [part~='field-error'] {
1933
+ color: var(--wodira-color-danger, #b42318);
1934
+ }
1935
+
1936
+ [part~='eligibility-summary'] {
1937
+ background: color-mix(
1938
+ in srgb,
1939
+ var(--wodira-color-accent, #c40072) 7%,
1940
+ var(--wodira-color-surface, #fff)
1941
+ );
1942
+ border: 1px solid color-mix(in srgb, var(--wodira-color-accent, #c40072) 24%, transparent);
1943
+ border-radius: var(--wodira-radius-sm, 0.625rem);
1944
+ display: grid;
1945
+ gap: 0.45rem;
1946
+ padding: 0.8rem 0.9rem;
1947
+ }
1948
+
1949
+ [part~='eligibility-summary'] ul {
1950
+ color: var(--wodira-color-text-muted, #625e70);
1951
+ display: grid;
1952
+ font-size: 0.875rem;
1953
+ gap: 0.25rem;
1954
+ margin: 0;
1955
+ padding-inline-start: 1.2rem;
1956
+ }
1957
+
1958
+ [part~='gender-composition'] {
1959
+ border: 0;
1960
+ display: grid;
1961
+ gap: 0.6rem;
1962
+ margin: 0;
1963
+ padding: 0;
1964
+ }
1965
+
1966
+ [part~='gender-composition'] legend {
1967
+ font-weight: 800;
1968
+ padding: 0;
1969
+ }
1970
+
1971
+ [part~='gender-composition'] [part~='hint'] {
1972
+ margin: 0;
1973
+ }
1974
+
1975
+ [part~='composition-options'] {
1976
+ display: grid;
1977
+ gap: 0.6rem;
1978
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 11.25rem), 1fr));
1979
+ }
1980
+
1981
+ [part~='composition-option'] {
1982
+ align-items: center;
1983
+ background: var(--wodira-color-surface, #fff);
1984
+ border: 1px solid var(--wodira-color-border, #dcd9e3);
1985
+ border-radius: var(--wodira-radius-sm, 0.625rem);
1986
+ cursor: pointer;
1987
+ display: flex;
1988
+ font-weight: 700;
1989
+ gap: 0.55rem;
1990
+ min-height: var(--wodira-control-height, 2.75rem);
1991
+ padding: 0.7rem 0.8rem;
1992
+ }
1993
+
1994
+ [part~='composition-option'][part~='selected'] {
1995
+ background: color-mix(
1996
+ in srgb,
1997
+ var(--wodira-color-accent, #c40072) 10%,
1998
+ var(--wodira-color-surface, #fff)
1999
+ );
2000
+ border-color: var(--wodira-color-accent, #c40072);
2001
+ }
2002
+
2003
+ [part~='composition-option']:focus-within {
2004
+ outline: 3px solid color-mix(in srgb, var(--wodira-color-accent, #c40072) 35%, transparent);
2005
+ outline-offset: 2px;
2006
+ }
2007
+
2008
+ [part~='participant-mode'] {
2009
+ background: var(--wodira-color-muted, #f6f5f8);
2010
+ border-radius: var(--wodira-radius-sm, 0.625rem);
2011
+ display: grid;
2012
+ gap: 0.25rem;
2013
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2014
+ margin-block: 0.8rem;
2015
+ padding: 0.25rem;
2016
+ }
2017
+
2018
+ [part~='participant-mode-button'] {
2019
+ background: transparent;
2020
+ border: 1px solid transparent;
2021
+ border-radius: calc(var(--wodira-radius-sm, 0.625rem) * 0.75);
2022
+ color: var(--wodira-color-text-muted, #625e70);
2023
+ cursor: pointer;
2024
+ font: inherit;
2025
+ font-size: 0.875rem;
2026
+ font-weight: 750;
2027
+ min-height: 2.4rem;
2028
+ padding: 0.55rem 0.75rem;
2029
+ }
2030
+
2031
+ [part~='participant-mode-button'][part~='active'] {
2032
+ background: var(--wodira-color-surface, #fff);
2033
+ border-color: var(--wodira-color-border, #dcd9e3);
2034
+ box-shadow: 0 2px 8px rgb(15 23 42 / 0.08);
2035
+ color: var(--wodira-color-text, #17132e);
2036
+ }
2037
+
2038
+ [part~='participant-mode-button']:focus-visible {
2039
+ outline: 3px solid color-mix(in srgb, var(--wodira-color-accent, #c40072) 35%, transparent);
2040
+ outline-offset: 2px;
2041
+ }
2042
+
2043
+ [part~='deferred-participant-hint'] {
2044
+ background: var(--wodira-color-muted, #f6f5f8);
2045
+ border-radius: var(--wodira-radius-sm, 0.625rem);
2046
+ color: var(--wodira-color-text-muted, #625e70);
2047
+ line-height: 1.5;
2048
+ margin: 0.8rem 0 0;
2049
+ padding: 0.8rem 0.9rem;
2050
+ }
2051
+
2052
+ [part~='error'] {
2053
+ background: color-mix(in srgb, var(--wodira-color-danger, #b42318) 10%, transparent);
2054
+ border: 1px solid color-mix(in srgb, var(--wodira-color-danger, #b42318) 35%, transparent);
2055
+ border-radius: var(--wodira-radius-sm, 0.625rem);
2056
+ color: var(--wodira-color-danger, #b42318);
2057
+ padding: 0.75rem 0.9rem;
2058
+ }
2059
+
2060
+ [part~='success'] {
2061
+ background: color-mix(in srgb, var(--wodira-color-success, #16703c) 12%, transparent);
2062
+ border: 1px solid color-mix(in srgb, var(--wodira-color-success, #16703c) 35%, transparent);
2063
+ border-radius: var(--wodira-radius-sm, 0.625rem);
2064
+ color: var(--wodira-color-success, #16703c);
2065
+ padding: 0.75rem 0.9rem;
2066
+ }
2067
+
2068
+ [part~='loader'],
2069
+ [part~='empty'] {
2070
+ color: var(--wodira-color-text-muted, #625e70);
2071
+ padding: var(--wodira-space, 1rem);
2072
+ text-align: center;
2073
+ }
2074
+
2075
+ [part~='title'] {
2076
+ font-size: clamp(1.15rem, 2vw, 1.5rem);
2077
+ font-weight: 800;
2078
+ line-height: 1.15;
2079
+ margin: 0;
2080
+ }
2081
+
2082
+ [part~='price'] {
2083
+ color: var(--wodira-color-accent, #c40072);
2084
+ font-size: 1.35rem;
2085
+ font-weight: 850;
2086
+ }
2087
+
2088
+ [part~='tier-list'] {
2089
+ display: grid;
2090
+ gap: 0.55rem;
2091
+ }
2092
+
2093
+ [part~='tier-row'] {
2094
+ align-items: center;
2095
+ background: var(--wodira-color-muted, #f6f5f8);
2096
+ border: 1px solid transparent;
2097
+ border-radius: var(--wodira-radius-sm, 0.625rem);
2098
+ display: grid;
2099
+ gap: 0.35rem;
2100
+ padding: 0.7rem 0.8rem;
2101
+ }
2102
+
2103
+ [part~='tier-row'][part~='current'] {
2104
+ background: color-mix(
2105
+ in srgb,
2106
+ var(--wodira-color-accent, #c40072) 10%,
2107
+ var(--wodira-color-surface, #fff)
2108
+ );
2109
+ border-color: color-mix(in srgb, var(--wodira-color-accent, #c40072) 45%, transparent);
2110
+ }
2111
+
2112
+ [part~='tier-heading'] {
2113
+ align-items: center;
2114
+ display: flex;
2115
+ gap: 0.5rem;
2116
+ justify-content: space-between;
2117
+ }
2118
+
2119
+ [part~='tier-name'] {
2120
+ font-weight: 800;
2121
+ }
2122
+
2123
+ [part~='tier-price'] {
2124
+ color: var(--wodira-color-accent, #c40072);
2125
+ font-weight: 850;
2126
+ }
2127
+
2128
+ [part~='badge'] {
2129
+ background: var(--wodira-color-accent, #c40072);
2130
+ border-radius: 999px;
2131
+ color: var(--wodira-color-accent-contrast, #fff);
2132
+ display: inline-flex;
2133
+ font-size: 0.72rem;
2134
+ font-weight: 800;
2135
+ letter-spacing: 0.02em;
2136
+ padding: 0.2rem 0.5rem;
2137
+ text-transform: uppercase;
2138
+ }
2139
+
2140
+ [part~='image'] {
2141
+ aspect-ratio: 16 / 9;
2142
+ border-radius: calc(var(--wodira-radius, 1rem) * 0.75);
2143
+ display: block;
2144
+ margin-block-end: var(--wodira-space, 1rem);
2145
+ object-fit: cover;
2146
+ width: 100%;
2147
+ }
2148
+
2149
+ [part~='summary-row'] {
2150
+ display: flex;
2151
+ justify-content: space-between;
2152
+ gap: var(--wodira-space, 1rem);
2153
+ }
2154
+ `;
2155
+
2156
+ // src/ui/shirt-sponsors/shirt-auction.ts
2157
+ var copy = {
2158
+ es: {
2159
+ label: "Patrocina la camiseta del evento",
2160
+ loading: "Cargando camiseta y pujas…",
2161
+ error: "No se ha podido cargar la campaña.",
2162
+ invalid: "Configura una campaña y una clave publicable válidas.",
2163
+ retry: "Reintentar",
2164
+ shirtAria: "Camiseta 3D. Arrástrala para girarla y toca un espacio para elegirlo.",
2165
+ hint: "Arrastra para girar · Toca un espacio para pujar",
2166
+ noModel: "La vista 3D no está disponible en este dispositivo. Elige un espacio en la lista.",
2167
+ zoomIn: "Acercar camiseta",
2168
+ zoomOut: "Alejar camiseta",
2169
+ views: "Vista de la camiseta",
2170
+ slots: "Espacios",
2171
+ closes: "Cierre de pujas",
2172
+ shirts: "camisetas",
2173
+ from: "Desde",
2174
+ current: "Puja actual",
2175
+ reserved: "Reservado por la organización",
2176
+ minimum: "Puja mínima",
2177
+ increments: "Incrementos de",
2178
+ amount: "Tu puja (€)",
2179
+ bid: "Pujar",
2180
+ outbid: "Superar la puja",
2181
+ closed: "Las pujas de esta camiseta están cerradas.",
2182
+ pick: "Elige un espacio en la camiseta o en la lista.",
2183
+ belowMinimum: "La puja debe ser de al menos",
2184
+ step: "Usa múltiplos del incremento a partir de la puja mínima.",
2185
+ note: "Terminarás en WODira: inicio de sesión, logotipo en SVG y pago seguro con Stripe.",
2186
+ popupBlocked: "Tu navegador ha bloqueado la ventana de WODira.",
2187
+ openBid: "Abrir la puja en WODira",
2188
+ waiting: "Completa la puja en la ventana de WODira. Esta camiseta se actualizará sola.",
2189
+ paid: "Puja confirmada. Tu marca ya aparece en la camiseta.",
2190
+ leads: "lidera",
2191
+ sides: {
2192
+ front: "Delantera",
2193
+ back: "Trasera",
2194
+ "left-sleeve": "Manga izquierda",
2195
+ "right-sleeve": "Manga derecha"
2196
+ }
2197
+ },
2198
+ en: {
2199
+ label: "Sponsor the event shirt",
2200
+ loading: "Loading shirt and bids…",
2201
+ error: "The campaign could not be loaded.",
2202
+ invalid: "Set a valid campaign and publishable key.",
2203
+ retry: "Retry",
2204
+ shirtAria: "3D shirt. Drag it to turn it and tap a space to choose it.",
2205
+ hint: "Drag to turn · Tap a space to bid",
2206
+ noModel: "The 3D view is not available on this device. Choose a space from the list.",
2207
+ zoomIn: "Zoom in",
2208
+ zoomOut: "Zoom out",
2209
+ views: "Shirt view",
2210
+ slots: "Spaces",
2211
+ closes: "Bidding closes",
2212
+ shirts: "shirts",
2213
+ from: "From",
2214
+ current: "Current bid",
2215
+ reserved: "Reserved by the organizer",
2216
+ minimum: "Minimum bid",
2217
+ increments: "Increments of",
2218
+ amount: "Your bid (€)",
2219
+ bid: "Bid",
2220
+ outbid: "Outbid",
2221
+ closed: "Bidding for this shirt is closed.",
2222
+ pick: "Choose a space on the shirt or in the list.",
2223
+ belowMinimum: "The bid must be at least",
2224
+ step: "Use multiples of the increment above the minimum bid.",
2225
+ note: "You will finish on WODira: sign-in, SVG logo and secure Stripe payment.",
2226
+ popupBlocked: "Your browser blocked the WODira window.",
2227
+ openBid: "Open the bid on WODira",
2228
+ waiting: "Complete the bid in the WODira window. This shirt will update by itself.",
2229
+ paid: "Bid confirmed. Your brand is now on the shirt.",
2230
+ leads: "leads",
2231
+ sides: {
2232
+ front: "Front",
2233
+ back: "Back",
2234
+ "left-sleeve": "Left sleeve",
2235
+ "right-sleeve": "Right sleeve"
2236
+ }
2237
+ },
2238
+ pt: {
2239
+ label: "Patrocina a camisola do evento",
2240
+ loading: "A carregar camisola e licitações…",
2241
+ error: "Não foi possível carregar a campanha.",
2242
+ invalid: "Configura uma campanha e uma chave publicável válidas.",
2243
+ retry: "Tentar novamente",
2244
+ shirtAria: "Camisola 3D. Arrasta-a para a rodar e toca num espaço para o escolher.",
2245
+ hint: "Arrasta para rodar · Toca num espaço para licitar",
2246
+ noModel: "A vista 3D não está disponível neste dispositivo. Escolhe um espaço na lista.",
2247
+ zoomIn: "Aproximar camisola",
2248
+ zoomOut: "Afastar camisola",
2249
+ views: "Vista da camisola",
2250
+ slots: "Espaços",
2251
+ closes: "Fim das licitações",
2252
+ shirts: "camisolas",
2253
+ from: "Desde",
2254
+ current: "Licitação atual",
2255
+ reserved: "Reservado pela organização",
2256
+ minimum: "Licitação mínima",
2257
+ increments: "Incrementos de",
2258
+ amount: "A tua licitação (€)",
2259
+ bid: "Licitar",
2260
+ outbid: "Superar a licitação",
2261
+ closed: "As licitações desta camisola estão fechadas.",
2262
+ pick: "Escolhe um espaço na camisola ou na lista.",
2263
+ belowMinimum: "A licitação deve ser de pelo menos",
2264
+ step: "Usa múltiplos do incremento a partir da licitação mínima.",
2265
+ note: "Vais terminar na WODira: início de sessão, logótipo em SVG e pagamento seguro com Stripe.",
2266
+ popupBlocked: "O teu navegador bloqueou a janela da WODira.",
2267
+ openBid: "Abrir a licitação na WODira",
2268
+ waiting: "Conclui a licitação na janela da WODira. Esta camisola atualiza-se sozinha.",
2269
+ paid: "Licitação confirmada. A tua marca já aparece na camisola.",
2270
+ leads: "lidera",
2271
+ sides: {
2272
+ front: "Frente",
2273
+ back: "Costas",
2274
+ "left-sleeve": "Manga esquerda",
2275
+ "right-sleeve": "Manga direita"
2276
+ }
2277
+ }
2278
+ };
2279
+ var SIDE_ORDER = ["front", "back", "left-sleeve", "right-sleeve"];
2280
+ var DEFAULT_APP_URL = "https://wodira.app";
2281
+ var SHIRT_MODEL_PATH = "/images/sponsor-studio/white-shirt-realistic-v1.glb?v=7";
2282
+ var CLICK_TOLERANCE_PX = 6;
2283
+ var PALETTE_TOKENS = {
2284
+ slot: ["--wodira-color-accent", "#c40072"],
2285
+ slotPreview: ["--wodira-color-accent", "#c40072"],
2286
+ slotText: ["--wodira-color-accent-contrast", "#ffffff"],
2287
+ priceLeading: ["--wodira-color-accent", "#c40072"],
2288
+ price: ["--wodira-color-primary", "#17132e"],
2289
+ reserved: ["--wodira-color-border", "#dcd9e3"],
2290
+ selected: ["--wodira-color-primary", "#17132e"]
2291
+ };
2292
+ function placement(side) {
2293
+ return side === "left-sleeve" || side === "right-sleeve" ? { side: "front", surface: side } : { side };
2294
+ }
2295
+ function toSponsorSlot(slot) {
2296
+ const result = {
2297
+ id: slot.id,
2298
+ name: slot.name,
2299
+ ...placement(slot.side),
2300
+ x: slot.x,
2301
+ y: slot.y,
2302
+ width: slot.width,
2303
+ height: slot.height,
2304
+ printWidth: slot.printWidthCm,
2305
+ printHeight: slot.printHeightCm,
2306
+ startingPrice: slot.startingPriceCents / 100,
2307
+ bidPrice: slot.minimumBidCents / 100,
2308
+ increment: slot.incrementCents / 100,
2309
+ isReserved: !!slot.isReserved,
2310
+ bids: slot.leadingArtworkUrl ? [
2311
+ {
2312
+ id: slot.id,
2313
+ buyer: slot.leadingBrandName ?? "",
2314
+ amount: (slot.leadingAmountCents ?? 0) / 100,
2315
+ paidAt: 0,
2316
+ status: "leading",
2317
+ logo: slot.leadingArtworkUrl,
2318
+ views: 0,
2319
+ opens: 0,
2320
+ clicks: 0
2321
+ }
2322
+ ] : []
2323
+ };
2324
+ if (slot.reservedArtworkUrl)
2325
+ result.reservedLogo = slot.reservedArtworkUrl;
2326
+ return result;
2327
+ }
2328
+ function safeHttpUrl(value) {
2329
+ try {
2330
+ const url = new URL(value);
2331
+ const local = ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
2332
+ if (url.username || url.password)
2333
+ return null;
2334
+ return url.protocol === "https:" || local && url.protocol === "http:" ? url : null;
2335
+ } catch {
2336
+ return null;
2337
+ }
2338
+ }
2339
+
2340
+ class WodiraShirtAuction2 extends LitElement {
2341
+ static properties = {
2342
+ campaignId: { type: String, attribute: "campaign-id" },
2343
+ publishableKey: { type: String, attribute: "publishable-key" },
2344
+ baseUrl: { type: String, attribute: "base-url" },
2345
+ appUrl: { type: String, attribute: "app-url" },
2346
+ locale: { type: String },
2347
+ campaign: { state: true },
2348
+ loading: { state: true },
2349
+ failed: { state: true },
2350
+ selectedSlotId: { state: true },
2351
+ side: { state: true },
2352
+ amountEuros: { state: true },
2353
+ modelUnavailable: { state: true },
2354
+ modelLoading: { state: true },
2355
+ status: { state: true }
2356
+ };
2357
+ static styles = [
2358
+ wodiraUiStyles,
2359
+ css`
2360
+ :host {
2361
+ /* Earlier releases used these shorter names; they still apply as fallbacks. */
2362
+ --_accent: var(--wodira-color-accent, var(--wodira-primary, #c40072));
2363
+ --_accent-contrast: var(--wodira-color-accent-contrast, #fff);
2364
+ --_surface: var(--wodira-color-surface, var(--wodira-background, #fff));
2365
+ --_muted: var(--wodira-color-muted, #f6f5f8);
2366
+ --_border: var(--wodira-color-border, var(--wodira-border, #dcd9e3));
2367
+ --_text: var(--wodira-color-text, var(--wodira-text, #17132e));
2368
+ --_text-muted: var(--wodira-color-text-muted, #625e70);
2369
+ --_radius: var(--wodira-radius, 1rem);
2370
+ --_radius-sm: var(--wodira-radius-sm, 0.625rem);
2371
+ --_space: var(--wodira-space, 1rem);
2372
+ color: var(--_text);
2373
+ }
2374
+
2375
+ [part~='container'] {
2376
+ background: var(--_surface);
2377
+ border: 1px solid var(--_border);
2378
+ border-radius: var(--_radius);
2379
+ box-shadow: var(--wodira-shadow, none);
2380
+ display: grid;
2381
+ gap: var(--_space);
2382
+ padding: var(--wodira-card-padding, clamp(1rem, 3cqi, 1.75rem));
2383
+ }
2384
+
2385
+ [part~='header'] {
2386
+ display: grid;
2387
+ gap: 0.35rem;
2388
+ }
2389
+
2390
+ [part~='title'] {
2391
+ font-size: clamp(1.25rem, 4cqi, 1.75rem);
2392
+ line-height: 1.15;
2393
+ margin: 0;
2394
+ }
2395
+
2396
+ [part~='meta'] {
2397
+ color: var(--_text-muted);
2398
+ display: flex;
2399
+ flex-wrap: wrap;
2400
+ font-size: 0.875rem;
2401
+ gap: 0.25rem 1rem;
2402
+ margin: 0;
2403
+ }
2404
+
2405
+ [part~='layout'] {
2406
+ display: grid;
2407
+ gap: var(--_space);
2408
+ }
2409
+
2410
+ @container (min-width: 46rem) {
2411
+ [part~='layout'] {
2412
+ align-items: start;
2413
+ grid-template-columns: minmax(0, 1.15fr) minmax(18rem, 0.85fr);
2414
+ }
2415
+ }
2416
+
2417
+ [part~='stage'] {
2418
+ aspect-ratio: 1 / 1;
2419
+ background: var(--wodira-shirt-stage-background, var(--_muted));
2420
+ border-radius: var(--_radius);
2421
+ max-height: min(36rem, 75vh);
2422
+ overflow: hidden;
2423
+ position: relative;
2424
+ width: 100%;
2425
+ }
2426
+
2427
+ [part~='shirt'] {
2428
+ cursor: grab;
2429
+ display: block;
2430
+ height: 100%;
2431
+ /* Vertical swipes keep scrolling the page; horizontal drags turn the shirt. */
2432
+ touch-action: pan-y;
2433
+ width: 100%;
2434
+ }
2435
+
2436
+ [part~='shirt']:active {
2437
+ cursor: grabbing;
2438
+ }
2439
+
2440
+ [part~='shirt']:focus-visible {
2441
+ outline: 3px solid var(--_accent);
2442
+ outline-offset: -3px;
2443
+ }
2444
+
2445
+ [part~='stage-hint'] {
2446
+ background: color-mix(in srgb, var(--_surface) 88%, transparent);
2447
+ border-radius: 999px;
2448
+ bottom: 0.75rem;
2449
+ color: var(--_text-muted);
2450
+ font-size: 0.8125rem;
2451
+ left: 0.75rem;
2452
+ margin: 0;
2453
+ padding: 0.35rem 0.75rem;
2454
+ pointer-events: none;
2455
+ position: absolute;
2456
+ }
2457
+
2458
+ [part~='stage-controls'] {
2459
+ display: flex;
2460
+ gap: 0.5rem;
2461
+ position: absolute;
2462
+ right: 0.75rem;
2463
+ top: 0.75rem;
2464
+ }
2465
+
2466
+ [part~='zoom-button'],
2467
+ [part~='side-button'] {
2468
+ align-items: center;
2469
+ background: var(--_surface);
2470
+ border: 1px solid var(--_border);
2471
+ border-radius: var(--_radius-sm);
2472
+ color: var(--_text);
2473
+ cursor: pointer;
2474
+ display: inline-flex;
2475
+ font: inherit;
2476
+ justify-content: center;
2477
+ min-height: 2.75rem;
2478
+ min-width: 2.75rem;
2479
+ padding: 0 0.75rem;
2480
+ transition:
2481
+ background-color 0.15s ease,
2482
+ border-color 0.15s ease;
2483
+ }
2484
+
2485
+ [part~='side-button'][aria-pressed='true'] {
2486
+ background: var(--_accent);
2487
+ border-color: var(--_accent);
2488
+ color: var(--_accent-contrast);
2489
+ }
2490
+
2491
+ [part~='side-switch'] {
2492
+ display: flex;
2493
+ flex-wrap: wrap;
2494
+ gap: 0.5rem;
2495
+ }
2496
+
2497
+ [part~='stage-fallback'] {
2498
+ align-items: center;
2499
+ color: var(--_text-muted);
2500
+ display: flex;
2501
+ height: 100%;
2502
+ justify-content: center;
2503
+ margin: 0;
2504
+ padding: 1.5rem;
2505
+ text-align: center;
2506
+ }
2507
+
2508
+ [part~='slot-list'] {
2509
+ display: grid;
2510
+ gap: 0.5rem;
2511
+ list-style: none;
2512
+ margin: 0;
2513
+ padding: 0;
2514
+ }
2515
+
2516
+ [part~='slot'] {
2517
+ align-items: center;
2518
+ background: var(--_surface);
2519
+ border: 1px solid var(--_border);
2520
+ border-radius: var(--_radius-sm);
2521
+ color: inherit;
2522
+ cursor: pointer;
2523
+ display: grid;
2524
+ font: inherit;
2525
+ gap: 0.15rem 1rem;
2526
+ grid-template-columns: minmax(0, 1fr) auto;
2527
+ min-height: 3.25rem;
2528
+ padding: 0.75rem 1rem;
2529
+ text-align: start;
2530
+ transition:
2531
+ background-color 0.15s ease,
2532
+ border-color 0.15s ease;
2533
+ width: 100%;
2534
+ }
2535
+
2536
+ [part~='slot-selected'] {
2537
+ background: color-mix(in srgb, var(--_accent) 8%, var(--_surface));
2538
+ border-color: var(--_accent);
2539
+ box-shadow: inset 4px 0 0 var(--_accent);
2540
+ }
2541
+
2542
+ [part~='slot']:disabled {
2543
+ cursor: default;
2544
+ opacity: 0.7;
2545
+ }
2546
+
2547
+ [part~='slot']:focus-visible,
2548
+ [part~='zoom-button']:focus-visible,
2549
+ [part~='side-button']:focus-visible {
2550
+ outline: 3px solid var(--_accent);
2551
+ outline-offset: 2px;
2552
+ }
2553
+
2554
+ @media (hover: hover) {
2555
+ [part~='slot']:not(:disabled):hover,
2556
+ [part~='zoom-button']:hover,
2557
+ [part~='side-button']:hover {
2558
+ border-color: var(--_accent);
2559
+ }
2560
+ }
2561
+
2562
+ [part~='slot-name'] {
2563
+ font-weight: 700;
2564
+ }
2565
+
2566
+ [part~='slot-detail'] {
2567
+ color: var(--_text-muted);
2568
+ font-size: 0.8125rem;
2569
+ grid-column: 1;
2570
+ }
2571
+
2572
+ [part~='slot-price'] {
2573
+ font-variant-numeric: tabular-nums;
2574
+ font-weight: 700;
2575
+ grid-column: 2;
2576
+ grid-row: 1 / span 2;
2577
+ text-align: end;
2578
+ white-space: nowrap;
2579
+ }
2580
+
2581
+ [part~='slot-price'] small {
2582
+ color: var(--_text-muted);
2583
+ display: block;
2584
+ font-size: 0.75rem;
2585
+ font-weight: 500;
2586
+ }
2587
+
2588
+ [part~='section-title'] {
2589
+ font-size: 0.8125rem;
2590
+ letter-spacing: 0.08em;
2591
+ margin: 0;
2592
+ text-transform: uppercase;
2593
+ }
2594
+
2595
+ [part~='bid-panel'] {
2596
+ background: var(--_muted);
2597
+ border-radius: var(--_radius);
2598
+ display: grid;
2599
+ gap: 0.75rem;
2600
+ padding: var(--_space);
2601
+ }
2602
+
2603
+ [part~='bid-title'] {
2604
+ font-size: 1.125rem;
2605
+ margin: 0;
2606
+ }
2607
+
2608
+ [part~='leader'] {
2609
+ align-items: center;
2610
+ display: flex;
2611
+ gap: 0.75rem;
2612
+ margin: 0;
2613
+ }
2614
+
2615
+ [part~='leader-logo'] {
2616
+ background: #fff;
2617
+ border-radius: 0.5rem;
2618
+ height: 2.5rem;
2619
+ object-fit: contain;
2620
+ outline: 1px solid rgb(0 0 0 / 0.1);
2621
+ outline-offset: -1px;
2622
+ padding: 0.25rem;
2623
+ width: 4.5rem;
2624
+ }
2625
+
2626
+ [part~='bid-form'] {
2627
+ display: grid;
2628
+ gap: 0.75rem;
2629
+ }
2630
+
2631
+ [part~='bid-form'] [part~='label'] {
2632
+ display: grid;
2633
+ gap: 0.35rem;
2634
+ }
2635
+
2636
+ [part~='status'] {
2637
+ margin: 0;
2638
+ }
2639
+
2640
+ @media (prefers-reduced-motion: reduce) {
2641
+ [part~='slot'],
2642
+ [part~='zoom-button'],
2643
+ [part~='side-button'] {
2644
+ transition: none;
2645
+ }
2646
+ }
2647
+ `
2648
+ ];
2649
+ client = null;
2650
+ abort = null;
2651
+ renderer = null;
2652
+ rendererCanvas = null;
2653
+ rendererGeneration = 0;
2654
+ canvasRevision = 0;
2655
+ drag = null;
2656
+ bidWindow = null;
2657
+ bidWindowTimer;
2658
+ blockedUrl = "";
2659
+ channel = globalThis.crypto.randomUUID();
2660
+ themeObserver = null;
2661
+ colorScheme = null;
2662
+ constructor() {
2663
+ super();
2664
+ this.campaignId = "";
2665
+ this.publishableKey = "";
2666
+ this.baseUrl = "";
2667
+ this.appUrl = DEFAULT_APP_URL;
2668
+ this.locale = "auto";
2669
+ this.campaign = null;
2670
+ this.loading = false;
2671
+ this.failed = false;
2672
+ this.selectedSlotId = null;
2673
+ this.side = "front";
2674
+ this.amountEuros = null;
2675
+ this.modelUnavailable = false;
2676
+ this.modelLoading = true;
2677
+ this.status = "idle";
2678
+ }
2679
+ refreshTheme() {
2680
+ this.renderer?.setAppearance({ palette: this.palette(), locale: this.numberLocale });
2681
+ }
2682
+ connectedCallback() {
2683
+ super.connectedCallback();
2684
+ window.addEventListener("message", this.onMessage);
2685
+ window.addEventListener("focus", this.onWindowFocus);
2686
+ this.themeObserver = new MutationObserver(() => this.refreshTheme());
2687
+ for (const target of [this, this.ownerDocument.documentElement, this.ownerDocument.body])
2688
+ if (target)
2689
+ this.themeObserver.observe(target, {
2690
+ attributes: true,
2691
+ attributeFilter: ["class", "style", "data-theme"]
2692
+ });
2693
+ this.colorScheme = matchMedia("(prefers-color-scheme: dark)");
2694
+ this.colorScheme.addEventListener("change", this.onColorScheme);
2695
+ if (this.hasUpdated) {
2696
+ this.modelUnavailable = false;
2697
+ this.requestUpdate();
2698
+ this.load(true);
2699
+ this.watchBidWindow();
2700
+ }
2701
+ }
2702
+ disconnectedCallback() {
2703
+ window.removeEventListener("message", this.onMessage);
2704
+ window.removeEventListener("focus", this.onWindowFocus);
2705
+ this.themeObserver?.disconnect();
2706
+ this.colorScheme?.removeEventListener("change", this.onColorScheme);
2707
+ clearInterval(this.bidWindowTimer);
2708
+ this.abort?.abort();
2709
+ this.disposeRenderer();
2710
+ this.canvasRevision++;
2711
+ super.disconnectedCallback();
2712
+ }
2713
+ willUpdate(changes) {
2714
+ if (changes.has("campaignId") || changes.has("publishableKey") || changes.has("baseUrl") || changes.has("appUrl")) {
2715
+ this.client = this.createClient();
2716
+ clearInterval(this.bidWindowTimer);
2717
+ this.bidWindow = null;
2718
+ this.blockedUrl = "";
2719
+ this.canvasRevision++;
2720
+ this.selectedSlotId = null;
2721
+ this.status = "idle";
2722
+ this.modelUnavailable = false;
2723
+ this.disposeRenderer();
2724
+ this.load();
2725
+ }
2726
+ }
2727
+ updated(changes) {
2728
+ const canvas = this.renderRoot.querySelector("canvas");
2729
+ if (canvas !== this.rendererCanvas) {
2730
+ this.disposeRenderer();
2731
+ if (canvas)
2732
+ this.startRenderer(canvas);
2733
+ } else if (changes.has("campaign") || changes.has("side") || changes.has("selectedSlotId"))
2734
+ this.paintShirt();
2735
+ if (changes.has("locale"))
2736
+ this.refreshTheme();
2737
+ }
2738
+ get language() {
2739
+ const locale = this.locale && this.locale !== "auto" ? this.locale : this.ownerDocument.documentElement.lang || navigator.language || "es";
2740
+ const language = locale.toLowerCase().split("-")[0];
2741
+ return language === "en" || language === "pt" ? language : "es";
2742
+ }
2743
+ get numberLocale() {
2744
+ return this.locale && this.locale !== "auto" ? this.locale : this.ownerDocument.documentElement.lang || navigator.language || "es-ES";
2745
+ }
2746
+ get text() {
2747
+ return copy[this.language];
2748
+ }
2749
+ get appOrigin() {
2750
+ return safeHttpUrl(this.appUrl || DEFAULT_APP_URL);
2751
+ }
2752
+ createClient() {
2753
+ if (!/^[a-zA-Z0-9_-]{1,160}$/.test(this.campaignId))
2754
+ return null;
2755
+ if (!this.publishableKey?.startsWith("wpk_live_"))
2756
+ return null;
2757
+ if (!this.appOrigin)
2758
+ return null;
2759
+ const options = { publishableKey: this.publishableKey };
2760
+ if (this.baseUrl) {
2761
+ if (!safeHttpUrl(this.baseUrl))
2762
+ return null;
2763
+ options.baseUrl = this.baseUrl;
2764
+ }
2765
+ try {
2766
+ return createWodiraBrowserClient(options);
2767
+ } catch {
2768
+ return null;
2769
+ }
2770
+ }
2771
+ async load(silent = false) {
2772
+ this.abort?.abort();
2773
+ if (!this.client) {
2774
+ this.campaign = null;
2775
+ this.loading = false;
2776
+ return;
2777
+ }
2778
+ const abort = new AbortController;
2779
+ this.abort = abort;
2780
+ if (!silent)
2781
+ this.loading = true;
2782
+ this.failed = false;
2783
+ try {
2784
+ const campaign = await this.client.getShirtSponsorCampaign(this.campaignId, abort.signal);
2785
+ if (abort.signal.aborted)
2786
+ return;
2787
+ this.campaign = campaign;
2788
+ const current = campaign.slots.find((slot) => slot.id === this.selectedSlotId);
2789
+ const next = current ?? campaign.slots.find((slot) => !slot.isReserved && slot.side === "front") ?? campaign.slots.find((slot) => !slot.isReserved) ?? campaign.slots[0];
2790
+ if (next)
2791
+ this.select(next, false);
2792
+ } catch {
2793
+ if (abort.signal.aborted)
2794
+ return;
2795
+ if (!silent)
2796
+ this.failed = true;
2797
+ } finally {
2798
+ if (!abort.signal.aborted)
2799
+ this.loading = false;
2800
+ }
2801
+ }
2802
+ get biddingOpen() {
2803
+ const campaign = this.campaign;
2804
+ return !!campaign && campaign.status === "PUBLISHED" && new Date(campaign.closesAt) > new Date;
2805
+ }
2806
+ get selectedSlot() {
2807
+ return this.campaign?.slots.find((slot) => slot.id === this.selectedSlotId) ?? null;
2808
+ }
2809
+ get orderedSlots() {
2810
+ return [...this.campaign?.slots ?? []].sort((a, b) => SIDE_ORDER.indexOf(a.side) - SIDE_ORDER.indexOf(b.side));
2811
+ }
2812
+ get sides() {
2813
+ const used = new Set(this.campaign?.slots.map((slot) => slot.side));
2814
+ return SIDE_ORDER.filter((side) => side === "front" || side === "back" || used.has(side));
2815
+ }
2816
+ select(slot, announce = true) {
2817
+ const changed = slot.id !== this.selectedSlotId;
2818
+ this.selectedSlotId = slot.id;
2819
+ if (changed)
2820
+ this.side = slot.side;
2821
+ if (changed || this.amountEuros === null || this.amountEuros * 100 < slot.minimumBidCents)
2822
+ this.amountEuros = slot.minimumBidCents / 100;
2823
+ if (announce && changed)
2824
+ this.dispatchEvent(new CustomEvent("wodira:shirt:slot-selected", {
2825
+ bubbles: true,
2826
+ composed: true,
2827
+ detail: { campaignId: this.campaignId, slotId: slot.id }
2828
+ }));
2829
+ }
2830
+ formatMoney(cents) {
2831
+ const digits = cents % 100 ? 2 : 0;
2832
+ try {
2833
+ return new Intl.NumberFormat(this.numberLocale, {
2834
+ style: "currency",
2835
+ currency: "EUR",
2836
+ minimumFractionDigits: digits,
2837
+ maximumFractionDigits: digits
2838
+ }).format(cents / 100);
2839
+ } catch {
2840
+ return `${(cents / 100).toFixed(digits)} €`;
2841
+ }
2842
+ }
2843
+ formatDate(value) {
2844
+ try {
2845
+ return new Intl.DateTimeFormat(this.numberLocale, {
2846
+ dateStyle: "medium",
2847
+ timeStyle: "short"
2848
+ }).format(new Date(value));
2849
+ } catch {
2850
+ return value;
2851
+ }
2852
+ }
2853
+ palette() {
2854
+ const style = getComputedStyle(this);
2855
+ const palette = {};
2856
+ for (const [key, [token, fallback]] of Object.entries(PALETTE_TOKENS))
2857
+ palette[key] = style.getPropertyValue(token).trim() || fallback;
2858
+ return palette;
2859
+ }
2860
+ async startRenderer(canvas) {
2861
+ const generation = ++this.rendererGeneration;
2862
+ this.rendererCanvas = canvas;
2863
+ this.modelLoading = true;
2864
+ try {
2865
+ const { Shirt3dRenderer } = await (__preload("jyks1h8f"), import("./shirt-3d-renderer-jyks1h8f.js"));
2866
+ if (generation !== this.rendererGeneration)
2867
+ return;
2868
+ const renderer = new Shirt3dRenderer(canvas, () => {
2869
+ if (generation === this.rendererGeneration)
2870
+ this.modelUnavailable = true;
2871
+ }, (loading) => {
2872
+ if (generation === this.rendererGeneration)
2873
+ this.modelLoading = loading;
2874
+ }, {
2875
+ modelUrl: new URL(SHIRT_MODEL_PATH, this.appOrigin ?? DEFAULT_APP_URL).href,
2876
+ locale: this.numberLocale,
2877
+ palette: this.palette()
2878
+ });
2879
+ this.renderer = renderer;
2880
+ this.paintShirt();
2881
+ await renderer.load();
2882
+ if (generation === this.rendererGeneration)
2883
+ this.modelLoading = false;
2884
+ } catch {
2885
+ if (generation === this.rendererGeneration) {
2886
+ this.disposeRenderer();
2887
+ this.modelUnavailable = true;
2888
+ }
2889
+ }
2890
+ }
2891
+ disposeRenderer() {
2892
+ this.rendererGeneration++;
2893
+ this.renderer?.dispose();
2894
+ this.renderer = null;
2895
+ this.rendererCanvas = null;
2896
+ this.drag = null;
2897
+ }
2898
+ paintShirt() {
2899
+ const campaign = this.campaign;
2900
+ if (!this.renderer || !campaign)
2901
+ return;
2902
+ const view = placement(this.side);
2903
+ const design = campaign.shirtDesign;
2904
+ const artwork = design ? {
2905
+ ...design.front ? { front: design.front } : {},
2906
+ ...design.back ? { back: design.back } : {}
2907
+ } : null;
2908
+ this.renderer.setSelectedSlot(this.selectedSlotId);
2909
+ this.renderer.update(campaign.slots.map(toSponsorSlot), view.side, true, campaign.shirtColor || "#ffffff", false, artwork, view.surface);
2910
+ }
2911
+ onPointerDown(event) {
2912
+ if (event.button !== 0)
2913
+ return;
2914
+ this.drag = {
2915
+ id: event.pointerId,
2916
+ x: event.clientX,
2917
+ y: event.clientY,
2918
+ originX: event.clientX,
2919
+ originY: event.clientY
2920
+ };
2921
+ if (event.pointerType !== "touch")
2922
+ event.currentTarget.setPointerCapture(event.pointerId);
2923
+ }
2924
+ onPointerMove(event) {
2925
+ const drag = this.drag;
2926
+ if (!drag || drag.id !== event.pointerId)
2927
+ return;
2928
+ const distance = Math.hypot(event.clientX - drag.originX, event.clientY - drag.originY);
2929
+ if (distance <= CLICK_TOLERANCE_PX)
2930
+ return;
2931
+ this.renderer?.rotate(event.clientX - drag.x, event.clientY - drag.y);
2932
+ drag.x = event.clientX;
2933
+ drag.y = event.clientY;
2934
+ }
2935
+ onPointerUp(event) {
2936
+ const drag = this.drag;
2937
+ this.drag = null;
2938
+ if (!drag || drag.id !== event.pointerId)
2939
+ return;
2940
+ const distance = Math.hypot(event.clientX - drag.originX, event.clientY - drag.originY);
2941
+ if (distance > CLICK_TOLERANCE_PX)
2942
+ return;
2943
+ const picked = this.renderer?.pick(event.clientX, event.clientY);
2944
+ const slot = picked && this.campaign?.slots.find((item) => item.id === picked.id);
2945
+ if (slot && !slot.isReserved)
2946
+ this.select(slot);
2947
+ }
2948
+ onPointerCancel() {
2949
+ this.drag = null;
2950
+ }
2951
+ onShirtKey(event) {
2952
+ if (!this.renderer)
2953
+ return;
2954
+ const turns = {
2955
+ ArrowLeft: [-10, 0],
2956
+ ArrowRight: [10, 0],
2957
+ ArrowUp: [0, -10],
2958
+ ArrowDown: [0, 10]
2959
+ };
2960
+ const turn = turns[event.key];
2961
+ if (turn) {
2962
+ event.preventDefault();
2963
+ this.renderer.rotate(turn[0], turn[1]);
2964
+ } else if (event.key === "+" || event.key === "=") {
2965
+ event.preventDefault();
2966
+ this.renderer.zoomBy(0.1);
2967
+ } else if (event.key === "-") {
2968
+ event.preventDefault();
2969
+ this.renderer.zoomBy(-0.1);
2970
+ }
2971
+ }
2972
+ showSide(side) {
2973
+ this.side = side;
2974
+ this.renderer?.resetView();
2975
+ this.paintShirt();
2976
+ }
2977
+ bidUrl(slot, amountCents) {
2978
+ const app = this.appOrigin;
2979
+ if (!app)
2980
+ return null;
2981
+ const local = ["localhost", "127.0.0.1", "[::1]"].includes(app.hostname);
2982
+ const path = `${local ? "" : `/${this.language}`}/patrocinios/camisetas/${encodeURIComponent(this.campaignId)}`;
2983
+ const url = new URL(path, app.origin);
2984
+ url.searchParams.set("slot", slot.id);
2985
+ url.searchParams.set("amount", String(amountCents));
2986
+ url.searchParams.set("channel", this.channel);
2987
+ url.searchParams.set("parentOrigin", location.origin);
2988
+ return url.href;
2989
+ }
2990
+ amountProblem(slot) {
2991
+ const cents = Math.round((this.amountEuros ?? 0) * 100);
2992
+ if (!Number.isFinite(cents) || cents < slot.minimumBidCents)
2993
+ return `${this.text.belowMinimum} ${this.formatMoney(slot.minimumBidCents)}.`;
2994
+ if (slot.incrementCents > 0 && (cents - slot.minimumBidCents) % slot.incrementCents !== 0)
2995
+ return this.text.step;
2996
+ return null;
2997
+ }
2998
+ submitBid(event) {
2999
+ event.preventDefault();
3000
+ const slot = this.selectedSlot;
3001
+ if (!slot || slot.isReserved || !this.biddingOpen || this.amountProblem(slot))
3002
+ return;
3003
+ const amountCents = Math.round((this.amountEuros ?? 0) * 100);
3004
+ const url = this.bidUrl(slot, amountCents);
3005
+ if (!url)
3006
+ return;
3007
+ this.dispatchEvent(new CustomEvent("wodira:shirt:bid-started", {
3008
+ bubbles: true,
3009
+ composed: true,
3010
+ detail: { campaignId: this.campaignId, slotId: slot.id, amountCents }
3011
+ }));
3012
+ const width = Math.min(1100, screen.availWidth);
3013
+ const height = Math.min(900, screen.availHeight);
3014
+ const left = Math.max(0, Math.round((screen.availWidth - width) / 2));
3015
+ const top = Math.max(0, Math.round((screen.availHeight - height) / 2));
3016
+ const popup = window.open(url, `wodira-shirt-${this.channel}`, `popup,width=${width},height=${height},left=${left},top=${top}`);
3017
+ if (!popup) {
3018
+ this.blockedUrl = url;
3019
+ this.status = "blocked";
3020
+ return;
3021
+ }
3022
+ this.bidWindow = popup;
3023
+ this.status = "waiting";
3024
+ this.watchBidWindow();
3025
+ }
3026
+ watchBidWindow() {
3027
+ clearInterval(this.bidWindowTimer);
3028
+ if (!this.bidWindow)
3029
+ return;
3030
+ this.bidWindowTimer = setInterval(() => {
3031
+ if (!this.bidWindow?.closed)
3032
+ return;
3033
+ clearInterval(this.bidWindowTimer);
3034
+ this.bidWindow = null;
3035
+ if (this.status === "waiting")
3036
+ this.status = "idle";
3037
+ this.load(true);
3038
+ }, 1000);
3039
+ }
3040
+ onMessage = (event) => {
3041
+ const app = this.appOrigin;
3042
+ if (!app || event.origin !== app.origin)
3043
+ return;
3044
+ if (!this.bidWindow || event.source !== this.bidWindow)
3045
+ return;
3046
+ const data = event.data;
3047
+ if (!data || typeof data !== "object" || !("type" in data) || data.type !== "wodira:shirt:paid" || !("channel" in data) || data.channel !== this.channel || !("campaignId" in data) || data.campaignId !== this.campaignId)
3048
+ return;
3049
+ this.status = "paid";
3050
+ this.load(true);
3051
+ this.dispatchEvent(new CustomEvent("wodira:shirt:paid", {
3052
+ bubbles: true,
3053
+ composed: true,
3054
+ detail: { campaignId: this.campaignId }
3055
+ }));
3056
+ };
3057
+ onWindowFocus = () => {
3058
+ if (this.status === "blocked")
3059
+ this.load(true);
3060
+ };
3061
+ onColorScheme = () => this.refreshTheme();
3062
+ render() {
3063
+ const text = this.text;
3064
+ if (!this.client)
3065
+ return html`<section part="container" aria-label=${text.label}>
3066
+ <p part="error" role="alert">${text.invalid}</p>
3067
+ </section>`;
3068
+ if (this.loading && !this.campaign)
3069
+ return html`<section part="container" aria-label=${text.label} aria-busy="true">
3070
+ <p part="loader" role="status">${text.loading}</p>
3071
+ </section>`;
3072
+ if (this.failed || !this.campaign)
3073
+ return html`<section part="container" aria-label=${text.label}>
3074
+ <p part="error" role="alert">${text.error}</p>
3075
+ <button part="button secondary" type="button" @click=${() => this.load()}>
3076
+ ${text.retry}
3077
+ </button>
3078
+ </section>`;
3079
+ const campaign = this.campaign;
3080
+ return html`<section part="container" aria-label=${text.label}>
3081
+ <header part="header">
3082
+ <h2 part="title">${campaign.eventName}</h2>
3083
+ <p part="meta">
3084
+ <span>${[campaign.city, campaign.province].filter(Boolean).join(", ")}</span>
3085
+ <span>${campaign.shirtCount.toLocaleString(this.numberLocale)} ${text.shirts}</span>
3086
+ <span>${text.closes}: ${this.formatDate(campaign.closesAt)}</span>
3087
+ </p>
3088
+ </header>
3089
+ <div part="layout">
3090
+ <div part="stack">${this.renderStage()} ${this.renderSides()}</div>
3091
+ <div part="stack">${this.renderSlots()} ${this.renderBidPanel()}</div>
3092
+ </div>
3093
+ </section>`;
3094
+ }
3095
+ renderStage() {
3096
+ const text = this.text;
3097
+ if (this.modelUnavailable)
3098
+ return html`<div part="stage"><p part="stage-fallback">${text.noModel}</p></div>`;
3099
+ return html`<div part="stage">
3100
+ ${keyed(this.canvasRevision, html`<canvas
3101
+ part="shirt"
3102
+ tabindex="0"
3103
+ role="img"
3104
+ aria-label=${text.shirtAria}
3105
+ @pointerdown=${this.onPointerDown}
3106
+ @pointermove=${this.onPointerMove}
3107
+ @pointerup=${this.onPointerUp}
3108
+ @pointercancel=${this.onPointerCancel}
3109
+ @lostpointercapture=${this.onPointerCancel}
3110
+ @keydown=${this.onShirtKey}
3111
+ ></canvas>`)}
3112
+ ${this.modelLoading ? html`<p part="stage-hint loader" role="status">${text.loading}</p>` : html`<p part="stage-hint">${text.hint}</p>`}
3113
+ <div part="stage-controls">
3114
+ <button
3115
+ part="zoom-button"
3116
+ type="button"
3117
+ aria-label=${text.zoomOut}
3118
+ @click=${() => this.renderer?.zoomBy(-0.1)}
3119
+ >
3120
+ −
3121
+ </button>
3122
+ <button
3123
+ part="zoom-button"
3124
+ type="button"
3125
+ aria-label=${text.zoomIn}
3126
+ @click=${() => this.renderer?.zoomBy(0.1)}
3127
+ >
3128
+ +
3129
+ </button>
3130
+ </div>
3131
+ </div>`;
3132
+ }
3133
+ renderSides() {
3134
+ return html`<div part="side-switch" role="group" aria-label=${this.text.views}>
3135
+ ${this.sides.map((side) => html`<button
3136
+ part=${`side-button${this.side === side ? " side-button-active" : ""}`}
3137
+ type="button"
3138
+ aria-pressed=${String(this.side === side)}
3139
+ @click=${() => this.showSide(side)}
3140
+ >
3141
+ ${this.text.sides[side]}
3142
+ </button>`)}
3143
+ </div>`;
3144
+ }
3145
+ renderSlots() {
3146
+ const text = this.text;
3147
+ return html`<div part="stack">
3148
+ <h3 part="section-title">${text.slots}</h3>
3149
+ <ul part="slot-list">
3150
+ ${this.orderedSlots.map((slot) => {
3151
+ const selected = slot.id === this.selectedSlotId;
3152
+ const leading = slot.leadingAmountCents !== null && !!slot.leadingBrandName;
3153
+ const parts = ["slot", selected && "slot-selected", slot.isReserved && "slot-reserved"].filter(Boolean).join(" ");
3154
+ return html`<li>
3155
+ <button
3156
+ part=${parts}
3157
+ type="button"
3158
+ aria-pressed=${String(selected)}
3159
+ ?disabled=${!!slot.isReserved}
3160
+ @click=${() => this.select(slot)}
3161
+ >
3162
+ <span part="slot-name">${slot.name}</span>
3163
+ <span part="slot-detail"
3164
+ >${text.sides[slot.side]} · ${slot.printWidthCm} × ${slot.printHeightCm} cm</span
3165
+ >
3166
+ <span part="slot-price price">
3167
+ ${slot.isReserved ? html`<small>${text.reserved}</small>` : leading ? html`<small>${slot.leadingBrandName} ${text.leads}</small
3168
+ >${this.formatMoney(slot.leadingAmountCents ?? 0)}` : html`<small>${text.from}</small>${this.formatMoney(slot.minimumBidCents)}`}
3169
+ </span>
3170
+ </button>
3171
+ </li>`;
3172
+ })}
3173
+ </ul>
3174
+ </div>`;
3175
+ }
3176
+ renderBidPanel() {
3177
+ const text = this.text;
3178
+ const slot = this.selectedSlot;
3179
+ if (!slot)
3180
+ return html`<p part="hint">${text.pick}</p>`;
3181
+ if (slot.isReserved)
3182
+ return html`<div part="bid-panel">
3183
+ <h3 part="bid-title">${slot.name}</h3>
3184
+ <p part="hint">${text.reserved}</p>
3185
+ </div>`;
3186
+ const leading = slot.leadingAmountCents !== null && !!slot.leadingBrandName;
3187
+ const problem = this.amountProblem(slot);
3188
+ const amountCents = Math.round((this.amountEuros ?? 0) * 100);
3189
+ return html`<div part="bid-panel">
3190
+ <h3 part="bid-title">${slot.name}</h3>
3191
+ ${leading ? html`<p part="leader">
3192
+ ${slot.leadingArtworkUrl ? html`<img
3193
+ part="leader-logo"
3194
+ src=${slot.leadingArtworkUrl}
3195
+ alt=${slot.leadingBrandName ?? ""}
3196
+ loading="lazy"
3197
+ />` : nothing}
3198
+ <span
3199
+ >${text.current}:
3200
+ <strong part="price">${this.formatMoney(slot.leadingAmountCents ?? 0)}</strong> ·
3201
+ ${slot.leadingBrandName}</span
3202
+ >
3203
+ </p>` : nothing}
3204
+ <p part="hint">
3205
+ ${text.minimum}: <strong>${this.formatMoney(slot.minimumBidCents)}</strong>.
3206
+ ${text.increments} ${this.formatMoney(slot.incrementCents)}.
3207
+ </p>
3208
+ ${this.biddingOpen ? html`<form part="bid-form" novalidate @submit=${this.submitBid}>
3209
+ <label part="label">
3210
+ ${text.amount}
3211
+ <input
3212
+ part="input"
3213
+ type="number"
3214
+ inputmode="decimal"
3215
+ name="amount"
3216
+ .value=${this.amountEuros === null ? "" : String(this.amountEuros)}
3217
+ min=${slot.minimumBidCents / 100}
3218
+ step=${Math.max(1, slot.incrementCents) / 100}
3219
+ aria-invalid=${problem ? "true" : "false"}
3220
+ aria-describedby="bid-problem"
3221
+ @input=${(event) => {
3222
+ const value = event.target.valueAsNumber;
3223
+ this.amountEuros = Number.isFinite(value) ? value : null;
3224
+ }}
3225
+ />
3226
+ </label>
3227
+ <p id="bid-problem" part="field-error" role="alert" ?hidden=${!problem}>
3228
+ ${problem ?? ""}
3229
+ </p>
3230
+ <button part="button submit" type="submit" ?disabled=${!!problem}>
3231
+ ${leading ? text.outbid : text.bid}${problem ? "" : ` · ${this.formatMoney(amountCents)}`}
3232
+ </button>
3233
+ <p part="hint">${text.note}</p>
3234
+ </form>` : html`<p part="hint">${text.closed}</p>`}
3235
+ ${this.renderStatus()}
3236
+ </div>`;
3237
+ }
3238
+ renderStatus() {
3239
+ const text = this.text;
3240
+ switch (this.status) {
3241
+ case "waiting":
3242
+ return html`<p part="status hint" role="status">${text.waiting}</p>`;
3243
+ case "paid":
3244
+ return html`<p part="status success" role="status">${text.paid}</p>`;
3245
+ case "blocked":
3246
+ return html`<p part="status error" role="alert">
3247
+ ${text.popupBlocked}
3248
+ <a href=${this.blockedUrl} target="_blank" rel="opener">${text.openBid}</a>
3249
+ </p>`;
3250
+ default:
3251
+ return nothing;
3252
+ }
3253
+ }
3254
+ }
3255
+
3256
+ // src/ui/shirt-sponsors/index.ts
3257
+ function defineWodiraShirtElements2() {
3258
+ if (!globalThis.customElements)
3259
+ throw new Error("WODira shirt elements require a browser.");
3260
+ if (!customElements.get("wodira-shirt-auction"))
3261
+ customElements.define("wodira-shirt-auction", WodiraShirtAuction2);
3262
+ }
3263
+
3264
+ export { __export, __chunks, css, html, nothing, LitElement, WodiraBrowserApiError, createWodiraBrowserClient, wodiraUiStyles, WodiraShirtAuction2, defineWodiraShirtElements2 };