@unhingged/vizu-core 0.1.19 → 0.1.21

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.
package/dist/index.cjs CHANGED
@@ -2254,7 +2254,7 @@ var Pill = class {
2254
2254
  var Sidebar = class {
2255
2255
  constructor(root, callbacks) {
2256
2256
  this.open = false;
2257
- this.filter = "open";
2257
+ this.filter = "all";
2258
2258
  this.lastComments = [];
2259
2259
  this.lastConfidence = /* @__PURE__ */ new Map();
2260
2260
  this.handleClick = (e) => {
@@ -2274,6 +2274,7 @@ var Sidebar = class {
2274
2274
  if (f && f !== this.filter) {
2275
2275
  this.filter = f;
2276
2276
  this.render(this.lastComments);
2277
+ this.callbacks.onFilterChange?.(f);
2277
2278
  }
2278
2279
  return;
2279
2280
  }
@@ -2338,7 +2339,7 @@ var Sidebar = class {
2338
2339
  const orphans = comments.filter((c) => conf.get(c.id) === "orphaned");
2339
2340
  const anchored = comments.filter((c) => conf.get(c.id) !== "orphaned");
2340
2341
  const statusOf = (c) => c.status ?? "open";
2341
- const visible = this.filter === "open" ? anchored.filter((c) => statusOf(c) === "open") : this.filter === "resolved" ? anchored.filter((c) => statusOf(c) !== "open") : anchored;
2342
+ const visible = this.filter === "all" ? anchored : anchored.filter((c) => statusOf(c) === this.filter);
2342
2343
  const visibleOrphans = this.filter === "all" ? orphans : [];
2343
2344
  const counts = countByStatus(comments);
2344
2345
  if (visible.length === 0 && visibleOrphans.length === 0) {
@@ -2349,7 +2350,9 @@ var Sidebar = class {
2349
2350
  const closed = counts.resolved + counts.wontfix;
2350
2351
  emptyCopy = `<strong>Nothing open.</strong>${closed} closed comment${closed === 1 ? "" : "s"} hidden. Switch to <em>All</em> to see them.`;
2351
2352
  } else if (this.filter === "resolved") {
2352
- emptyCopy = `<strong>Nothing resolved.</strong>${counts.open} still open. Switch to <em>Open</em> or <em>All</em> to see more.`;
2353
+ emptyCopy = `<strong>Nothing resolved.</strong>Switch to <em>Open</em> or <em>All</em> to see more.`;
2354
+ } else if (this.filter === "wontfix") {
2355
+ emptyCopy = `<strong>Nothing marked won&apos;t&nbsp;fix.</strong>Switch to <em>Open</em> or <em>All</em> to see more.`;
2353
2356
  } else {
2354
2357
  emptyCopy = "<strong>No comments yet</strong>Click any element on the page to leave one.";
2355
2358
  }
@@ -2449,7 +2452,10 @@ var Sidebar = class {
2449
2452
  Open <span class="vz-sidebar-filter-count">${counts.open}</span>
2450
2453
  </button>
2451
2454
  <button class="vz-sidebar-filter ${this.filter === "resolved" ? "is-active" : ""}" data-vz="filter" data-filter="resolved" role="tab" aria-selected="${this.filter === "resolved"}">
2452
- Resolved <span class="vz-sidebar-filter-count">${counts.resolved + counts.wontfix}</span>
2455
+ Resolved <span class="vz-sidebar-filter-count">${counts.resolved}</span>
2456
+ </button>
2457
+ <button class="vz-sidebar-filter ${this.filter === "wontfix" ? "is-active" : ""}" data-vz="filter" data-filter="wontfix" role="tab" aria-selected="${this.filter === "wontfix"}">
2458
+ Won&apos;t fix <span class="vz-sidebar-filter-count">${counts.wontfix}</span>
2453
2459
  </button>
2454
2460
  <button class="vz-sidebar-filter ${this.filter === "all" ? "is-active" : ""}" data-vz="filter" data-filter="all" role="tab" aria-selected="${this.filter === "all"}">
2455
2461
  All <span class="vz-sidebar-filter-count">${total}</span>
@@ -3671,6 +3677,14 @@ var Vizu = class {
3671
3677
  this.selfHealedThisSession = /* @__PURE__ */ new Set();
3672
3678
  this.actions = [];
3673
3679
  this.user = null;
3680
+ /**
3681
+ * Status filter shared by the sidebar tabs and the on-page markers.
3682
+ * Picking a tab updates this (via the sidebar's onFilterChange) and
3683
+ * re-renders markers so the page shows the same subset as the panel.
3684
+ * Defaults to 'all' (matching the sidebar's default tab) — every
3685
+ * marker shows until the user narrows to a specific status.
3686
+ */
3687
+ this.statusFilter = "all";
3674
3688
  /**
3675
3689
  * Flipped true once the initial loadComments() at construction has
3676
3690
  * settled (success or failure). The cloud onAuthChanged callback uses
@@ -4202,7 +4216,11 @@ var Vizu = class {
4202
4216
  onJumpToReference: (commentId, refId2) => this.jumpToReference(commentId, refId2),
4203
4217
  onDelete: (id) => void this.removeComment(id),
4204
4218
  onUpdateStatus: (id, status) => void this.updateComment(id, { status }),
4205
- onClose: () => this.closeSidebar()
4219
+ onClose: () => this.closeSidebar(),
4220
+ onFilterChange: (filter) => {
4221
+ this.statusFilter = filter;
4222
+ this.renderAllMarkers();
4223
+ }
4206
4224
  });
4207
4225
  this.pill = new Pill(this.root, {
4208
4226
  onToggleSidebar: () => this.toggleSidebar(),
@@ -4301,6 +4319,18 @@ var Vizu = class {
4301
4319
  if (this.pendingFingerprints.length > 0) this.multiSelectMode = true;
4302
4320
  else this.multiSelectMode = false;
4303
4321
  }
4322
+ /**
4323
+ * Whether a comment (by id) matches the active status filter — the
4324
+ * marker-render counterpart of the sidebar's tab filter. 'all' matches
4325
+ * everything; the named tabs match their exact status. Unknown ids
4326
+ * (shouldn't happen) match so we never silently drop a marker.
4327
+ */
4328
+ commentMatchesStatusFilter(id) {
4329
+ if (this.statusFilter === "all") return true;
4330
+ const c = this.comments.find((x) => x.id === id);
4331
+ if (!c) return true;
4332
+ return (c.status ?? "open") === this.statusFilter;
4333
+ }
4304
4334
  commentsForElement(fp) {
4305
4335
  const key2 = fingerprintKey(fp);
4306
4336
  return this.comments.filter(
@@ -4492,6 +4522,8 @@ var Vizu = class {
4492
4522
  }
4493
4523
  for (const [key2, info] of byElement) {
4494
4524
  if (info.confidence === "orphaned" || !info.target) continue;
4525
+ const idsForFilter = info.commentIds.filter((id) => this.commentMatchesStatusFilter(id));
4526
+ if (idsForFilter.length === 0) continue;
4495
4527
  const outlineEl = document.createElement("div");
4496
4528
  outlineEl.className = "vz-comment-outline";
4497
4529
  if (info.confidence === "drifted") outlineEl.classList.add("vz-comment-outline-drifted");
@@ -4502,13 +4534,13 @@ var Vizu = class {
4502
4534
  if (info.confidence === "drifted") marker.classList.add("vz-marker-drifted");
4503
4535
  marker.setAttribute("data-element-key", key2);
4504
4536
  marker.setAttribute("data-confidence", info.confidence);
4505
- const total = info.commentIds.length;
4537
+ const total = idsForFilter.length;
4506
4538
  if (total > 1) {
4507
4539
  marker.textContent = String(total);
4508
4540
  marker.title = total + " comments";
4509
4541
  } else {
4510
4542
  marker.textContent = "";
4511
- const c = this.comments.find((c2) => c2.id === info.commentIds[0]);
4543
+ const c = this.comments.find((c2) => c2.id === idsForFilter[0]);
4512
4544
  marker.title = c?.author ? "Comment by " + c.author.name : "Comment";
4513
4545
  }
4514
4546
  marker.addEventListener("click", (e) => {
@@ -4519,9 +4551,9 @@ var Vizu = class {
4519
4551
  this.openPopoverFor([info.target], [info.fp], elComments);
4520
4552
  }
4521
4553
  });
4522
- marker.addEventListener("mouseenter", () => this.pulseRelatedElements(info.commentIds, key2));
4554
+ marker.addEventListener("mouseenter", () => this.pulseRelatedElements(idsForFilter, key2));
4523
4555
  this.root.appendChild(marker);
4524
- this.markers.set(key2, { marker, target: info.target, fp: info.fp, commentIds: info.commentIds });
4556
+ this.markers.set(key2, { marker, target: info.target, fp: info.fp, commentIds: idsForFilter });
4525
4557
  if (info.target) {
4526
4558
  this.positionMarker(marker, info.target);
4527
4559
  this.positionOutline(outlineEl, info.target);