@unhingged/vizu-core 0.1.9 → 0.1.11
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/auto.cjs +44 -7
- package/dist/auto.cjs.map +1 -1
- package/dist/auto.js +44 -7
- package/dist/auto.js.map +1 -1
- package/dist/index.cjs +44 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +44 -7
- package/dist/index.js.map +1 -1
- package/dist/vizu.min.js +19 -19
- package/dist/vizu.min.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -48,7 +48,8 @@ function isInside(target, selector) {
|
|
|
48
48
|
return !!target.closest(selector);
|
|
49
49
|
}
|
|
50
50
|
function escapeHtml(s) {
|
|
51
|
-
|
|
51
|
+
if (s == null) return "";
|
|
52
|
+
return String(s).replace(/[&<>"']/g, (ch) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[ch]);
|
|
52
53
|
}
|
|
53
54
|
function formatTime(ts) {
|
|
54
55
|
const d = new Date(ts);
|
|
@@ -60,14 +61,16 @@ function formatTime(ts) {
|
|
|
60
61
|
return d.toLocaleDateString() + " " + d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
61
62
|
}
|
|
62
63
|
function initials(name) {
|
|
63
|
-
|
|
64
|
+
if (!name) return "";
|
|
65
|
+
return String(name).split(/\s+/).filter(Boolean).slice(0, 2).map((p) => p[0].toUpperCase()).join("");
|
|
64
66
|
}
|
|
65
67
|
function avatarHtml(user, className = "vz-comment-author-avatar") {
|
|
66
68
|
if (!user) return `<span class="${className}">\xB7</span>`;
|
|
69
|
+
const displayName = user.name || user.id || "User";
|
|
67
70
|
if (user.avatarUrl) {
|
|
68
|
-
return `<span class="${className}"><img src="${escapeHtml(user.avatarUrl)}" alt="${escapeHtml(
|
|
71
|
+
return `<span class="${className}"><img src="${escapeHtml(user.avatarUrl)}" alt="${escapeHtml(displayName)}" /></span>`;
|
|
69
72
|
}
|
|
70
|
-
return `<span class="${className}">${escapeHtml(initials(
|
|
73
|
+
return `<span class="${className}">${escapeHtml(initials(displayName) || "?")}</span>`;
|
|
71
74
|
}
|
|
72
75
|
function refId() {
|
|
73
76
|
return Math.random().toString(36).slice(2, 10);
|
|
@@ -470,6 +473,26 @@ var CloudStorageAdapter = class {
|
|
|
470
473
|
accessDenialReason() {
|
|
471
474
|
return this.accessDeniedReason;
|
|
472
475
|
}
|
|
476
|
+
/**
|
|
477
|
+
* Fetch the list of users who can be @-mentioned on this workspace.
|
|
478
|
+
* Used by the popover's mention dropdown — returns owner + joined
|
|
479
|
+
* editors/viewers, sorted owner-first. Silent on no auth (returns [])
|
|
480
|
+
* so popover doesn't open a popup just to render an empty dropdown.
|
|
481
|
+
*/
|
|
482
|
+
async searchMentionable() {
|
|
483
|
+
if (!this.cachedToken || this.isExpired(this.cachedToken)) return [];
|
|
484
|
+
try {
|
|
485
|
+
const res = await this.fetchAuthed(
|
|
486
|
+
this.apiUrl + "/api/workspaces/" + encodeURIComponent(this.workspace) + "/mentionable",
|
|
487
|
+
{ method: "GET" }
|
|
488
|
+
);
|
|
489
|
+
if (!res.ok) return [];
|
|
490
|
+
const json = await this.parseJson(res);
|
|
491
|
+
return Array.isArray(json?.users) ? json.users : [];
|
|
492
|
+
} catch {
|
|
493
|
+
return [];
|
|
494
|
+
}
|
|
495
|
+
}
|
|
473
496
|
/* ─── StorageAdapter v2 ───────────────────────────────────────────── */
|
|
474
497
|
async load(_namespace) {
|
|
475
498
|
if (!this.cachedToken || this.isExpired(this.cachedToken)) {
|
|
@@ -1219,7 +1242,7 @@ function renderRepliesHtml(c) {
|
|
|
1219
1242
|
const items = replies.map(
|
|
1220
1243
|
(r) => `
|
|
1221
1244
|
<div class="vz-reply" data-reply-id="${escapeHtml(r.id)}">
|
|
1222
|
-
${r.author ? `<div class="vz-comment-author">${avatarHtml(r.author)} <span class="vz-comment-author-name">${escapeHtml(r.author.name)}</span></div>` : ""}
|
|
1245
|
+
${r.author ? `<div class="vz-comment-author">${avatarHtml(r.author)} <span class="vz-comment-author-name">${escapeHtml(r.author.name || r.author.id || "User")}</span></div>` : ""}
|
|
1223
1246
|
<div class="vz-reply-text">${escapeHtml(r.text)}</div>
|
|
1224
1247
|
<div class="vz-comment-meta">
|
|
1225
1248
|
<span>${escapeHtml(formatTime(typeof r.createdAt === "number" ? r.createdAt : new Date(r.createdAt).getTime()))}</span>
|
|
@@ -1496,7 +1519,7 @@ var Popover = class {
|
|
|
1496
1519
|
${comments.length === 0 ? '<div class="vz-empty">No comments yet.</div>' : comments.map(
|
|
1497
1520
|
(c) => `
|
|
1498
1521
|
<div class="vz-comment" data-comment-id="${escapeHtml(c.id)}">
|
|
1499
|
-
${c.author ? `<div class="vz-comment-author">${avatarHtml(c.author)} <span class="vz-comment-author-name">${escapeHtml(c.author.name)}</span></div>` : ""}
|
|
1522
|
+
${c.author ? `<div class="vz-comment-author">${avatarHtml(c.author)} <span class="vz-comment-author-name">${escapeHtml(c.author.name || c.author.id || "User")}</span></div>` : ""}
|
|
1500
1523
|
<div>${renderCommentText(c.text, c.id)}</div>
|
|
1501
1524
|
${renderAttachmentsHtml(c.attachments)}
|
|
1502
1525
|
<div class="vz-comment-meta">
|
|
@@ -3307,11 +3330,25 @@ var Vizu = class {
|
|
|
3307
3330
|
this.user = user;
|
|
3308
3331
|
this.popover?.setUser(user);
|
|
3309
3332
|
this.pill?.setUser(user);
|
|
3333
|
+
if (this.pill) {
|
|
3334
|
+
if (this.shouldShowPill()) this.pill.show();
|
|
3335
|
+
else this.pill.hide();
|
|
3336
|
+
}
|
|
3310
3337
|
this.bus.emit("user:changed", { user });
|
|
3311
3338
|
}
|
|
3312
3339
|
getUser() {
|
|
3313
3340
|
return this.user;
|
|
3314
3341
|
}
|
|
3342
|
+
/**
|
|
3343
|
+
* Whether the pill belongs on-screen right now. Cloud-mode workspaces
|
|
3344
|
+
* keep it hidden until the user is signed in; non-cloud usage (local /
|
|
3345
|
+
* memory storage) has no auth and always shows it. Recomputed on every
|
|
3346
|
+
* setUser and on mount.
|
|
3347
|
+
*/
|
|
3348
|
+
shouldShowPill() {
|
|
3349
|
+
if (!(this.storage instanceof CloudStorageAdapter)) return true;
|
|
3350
|
+
return this.user !== null;
|
|
3351
|
+
}
|
|
3315
3352
|
/**
|
|
3316
3353
|
* Cloud-mode write gate. Every entry point that creates or modifies a
|
|
3317
3354
|
* comment first checks that we have a known user. Without one, the
|
|
@@ -3675,7 +3712,7 @@ var Vizu = class {
|
|
|
3675
3712
|
this.pill.setUser(this.user);
|
|
3676
3713
|
this.pill.setComments(this.comments);
|
|
3677
3714
|
this.pill.setMultiSelectState(this.multiSelectMode, this.pendingFingerprints.length);
|
|
3678
|
-
this.pill.show();
|
|
3715
|
+
if (this.shouldShowPill()) this.pill.show();
|
|
3679
3716
|
this.highlighter = new Highlighter(
|
|
3680
3717
|
this.root,
|
|
3681
3718
|
this.opts.ignoreSelectors ?? [],
|