@closerclick/closer-click-profile 0.2.1 → 0.3.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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +29 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@closerclick/closer-click-profile",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Web Component (custom element) <closer-click-profile> reutilizable por cualquier app del ecosistema Closer Click: tarjeta de perfil + reputación (confianza/afinidad, web-of-trust, reputación de la red). Autohosteado, Shadow DOM, temable por CSS vars.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -245,6 +245,8 @@ const STYLE = `
245
245
  width: fit-content;
246
246
  }
247
247
  .since { font-size: 12px; color: var(--_muted); }
248
+ .ind-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
249
+ .ind-badge { font-size: 12px; font-weight: 700; color: var(--_accent); border: 1px solid var(--_accent); border-radius: 8px; padding: 2px 8px; white-space: nowrap; }
248
250
 
249
251
  /* ----- Sections ----- */
250
252
  .section { display: flex; flex-direction: column; gap: 6px; position: relative; }
@@ -321,7 +323,7 @@ const STYLE = `
321
323
 
322
324
  class CloserClickProfile extends HTMLElement {
323
325
  static get observedAttributes() {
324
- return ['pubkey', 'name', 'since', 'online', 'mode', 'modal', 'heading', 'lang']
326
+ return ['pubkey', 'name', 'since', 'online', 'mode', 'modal', 'heading', 'lang', 'indicators']
325
327
  }
326
328
 
327
329
  constructor() {
@@ -331,6 +333,7 @@ class CloserClickProfile extends HTMLElement {
331
333
  this._my = { confianza: 0, afinidad: 0, notes: '' }
332
334
  this._endorsements = []
333
335
  this._derived = null
336
+ this._indicators = [] // indicadores derivados a mostrar (p. ej. ELO por juego)
334
337
  this._cloud = null
335
338
  this._cloudLoading = true
336
339
  this._hover = 0
@@ -360,9 +363,17 @@ class CloserClickProfile extends HTMLElement {
360
363
  attributeChangedCallback(name, oldV, newV) {
361
364
  if (oldV === newV) return
362
365
  if (name === 'pubkey') { this._resetState(); this.reload(); return }
366
+ if (name === 'indicators') { this._indicators = []; this.reload(); return }
363
367
  if (this.shadowRoot.childElementCount) this._render()
364
368
  }
365
369
 
370
+ // Indicadores derivados a mostrar (atributo `indicators`), p. ej.
371
+ // "elo:cuarenta" o "elo:chess,elo:cuarenta". Formato: nombre[:scope], coma.
372
+ get _indicatorSpecs() {
373
+ return (this.getAttribute('indicators') || '').split(',').map(s => s.trim()).filter(Boolean)
374
+ .map(s => { const [iName, scope] = s.split(':'); return { name: iName, scope: scope || undefined } })
375
+ }
376
+
366
377
  _onKeydown(e) {
367
378
  if (e.key === 'Escape' && this.hasAttribute('modal')) this._close()
368
379
  }
@@ -388,6 +399,7 @@ class CloserClickProfile extends HTMLElement {
388
399
  this._my = { confianza: 0, afinidad: 0, notes: '' }
389
400
  this._endorsements = []
390
401
  this._derived = null
402
+ this._indicators = []
391
403
  this._cloud = null
392
404
  this._cloudLoading = true
393
405
  this._hover = 0
@@ -422,6 +434,17 @@ class CloserClickProfile extends HTMLElement {
422
434
  this._derived = e ? e.derived : null
423
435
  }
424
436
  } catch (_) { /* best-effort */ }
437
+ // Indicadores derivados (p. ej. ELO por juego), vía provider.getDerived.
438
+ try {
439
+ const specs = this._indicatorSpecs
440
+ if (specs.length && typeof p.getDerived === 'function') {
441
+ const vals = await Promise.all(specs.map(async s => {
442
+ try { const d = await p.getDerived(pk, s.name, s.scope); return d ? { ...s, value: (d.value != null ? d.value : d.elo), count: (d.count != null ? d.count : d.games) } : null } catch (_) { return null }
443
+ }))
444
+ if (token !== this._loadToken) return
445
+ this._indicators = vals.filter(v => v && v.value != null)
446
+ }
447
+ } catch (_) { /* best-effort */ }
425
448
  if (token === this._loadToken) this._render()
426
449
 
427
450
  try {
@@ -559,6 +582,11 @@ class CloserClickProfile extends HTMLElement {
559
582
  </label>` : `<div class="name">${this._esc(name)}</div>`}
560
583
  <code class="pubkey">${this._esc(this._shortKey(pk))}</code>
561
584
  ${since ? `<div class="since">${this._esc(t.knownSince)} ${this._esc(this._fmtDate(since))}</div>` : ''}
585
+ ${this._indicators.length ? `<div class="ind-badges">${this._indicators.map(i => {
586
+ const label = this._esc((i.name || '').toUpperCase())
587
+ const tip = label + (i.scope ? ' · ' + this._esc(i.scope) : '') + (i.count != null ? ' · ' + i.count : '')
588
+ return `<span class="ind-badge" title="${tip}">${label} ${this._esc(String(i.value))}</span>`
589
+ }).join('')}</div>` : ''}
562
590
  </div>
563
591
  </div>`
564
592