@marver-design/marver 0.12.0 → 0.13.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.
- package/CHANGELOG.md +51 -0
- package/dist/{build-DmfxJc6L.mjs → build-BxGrHFT2.mjs} +1 -1
- package/dist/cli.mjs +5 -5
- package/dist/{collab-BmaOjwP1.mjs → collab-mAiNZlDj.mjs} +232 -43
- package/dist/{comments-pNxjTrGN.mjs → comments-DHB_8BRa.mjs} +3 -3
- package/dist/{daemon-WjonKlPz.mjs → daemon-BChkzDqQ.mjs} +2 -2
- package/dist/{dev-BXq7yE1p.mjs → dev-DLwt3Brb.mjs} +4 -4
- package/dist/{events-C9k-ceOj.mjs → events-B3LBn74P.mjs} +3 -1
- package/dist/{marver-id-gate-DOjnZakC.mjs → marver-id-gate-B2uraTHS.mjs} +8 -5
- package/dist/{plugin-Boy7I_JH.mjs → plugin-DNc4Jpae.mjs} +4 -4
- package/dist/{profile-ChpTPd-X.mjs → profile-BjAPAJSb.mjs} +1 -1
- package/dist/{serve-BeLLizNg.mjs → serve-EjEqsiYa.mjs} +2 -2
- package/dist/{share-C64b1tdN.mjs → share-Gqo_Ygqw.mjs} +14 -15
- package/dist/{summary-Bf9tiGrE.mjs → summary-C7CAypbB.mjs} +1 -1
- package/dist/{sync-WYxDN9IT.mjs → sync-BZaCWqK-.mjs} +1 -1
- package/package.json +1 -1
- package/src/client/shell/App.tsx +19 -3
- package/src/client/shell/Comments.tsx +94 -17
- package/src/client/shell/comments-store.ts +59 -4
- package/src/client/shell/mentions.ts +108 -1
- package/src/client/shell/sound.ts +32 -0
- package/src/client/shell/store.ts +12 -4
- package/src/client/shell/styles.css +41 -0
- package/src/shared/events.ts +12 -3
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
--accent: #0088ff; --accent-ring: rgba(0, 136, 255, .2); --beam: rgba(0, 136, 255, .42); --beam-blur: 6px; --beam-bottom: -13px; --beam-h: 12px; --beam-inset: 12%; --edge-accent: rgba(0, 136, 255, .8); --inner-tint: rgba(0, 136, 255, .13); --tip-bg: #18181b; --tip-ink: #fafafa; --accent-wash: rgba(0, 136, 255, .07);
|
|
8
8
|
|
|
9
9
|
--glass: rgba(255, 255, 255, .64);
|
|
10
|
+
--solid: #ffffff;
|
|
10
11
|
--glass-brd: rgba(24, 24, 27, .1);
|
|
11
12
|
--glass-ink: #18181b;
|
|
12
13
|
--glass-ink-2: rgba(24, 24, 27, .66);
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
--accent: #0088ff; --accent-ring: rgba(0, 136, 255, .32); --beam: rgba(0, 136, 255, .5); --beam-blur: 3px; --beam-bottom: -13px; --beam-h: 16px; --beam-inset: 20%; --edge-accent: rgba(92, 179, 255, .85); --inner-tint: rgba(92, 179, 255, .16); --tip-bg: #f4f4f5; --tip-ink: #18181b; --accent-wash: rgba(0, 136, 255, .14);
|
|
47
48
|
|
|
48
49
|
--glass: rgba(12, 12, 17, .72);
|
|
50
|
+
--solid: #17171b;
|
|
49
51
|
--glass-brd: rgba(255, 255, 255, .16);
|
|
50
52
|
--glass-ink: #f5f5f7;
|
|
51
53
|
--glass-ink-2: rgba(245, 245, 247, .64);
|
|
@@ -1121,6 +1123,21 @@ body.sh-hide-ui .sh-play-hint { display: none !important }
|
|
|
1121
1123
|
.cm-hl .cm-at { font-weight: inherit; -webkit-text-stroke: .4px currentColor }
|
|
1122
1124
|
.cm-at-tip { display: block; max-width: 220px; line-height: 1.4 }
|
|
1123
1125
|
|
|
1126
|
+
/* v1.1: @Person mentions - the comment accent, medium weight (the mirror rule above
|
|
1127
|
+
already keeps composer metrics honest: color + stroke only, never font-weight). */
|
|
1128
|
+
.cm-at.person { color: var(--cm-line, var(--comment)); font-weight: 600 }
|
|
1129
|
+
.cm-hl .cm-at.person { font-weight: inherit }
|
|
1130
|
+
/* The typeahead: a small glass list ABOVE the composer; rows follow the pick. */
|
|
1131
|
+
/* SOLID, never glass: the picker floats over thread text, and translucency
|
|
1132
|
+
made the names unreadable */
|
|
1133
|
+
.cm-mentionlist { position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 5; min-width: 180px; max-width: 260px;
|
|
1134
|
+
display: flex; flex-direction: column; padding: 4px; border-radius: 10px;
|
|
1135
|
+
background: var(--solid); border: 1px solid var(--glass-brd); box-shadow: 0 10px 28px rgba(0,0,0,.22) }
|
|
1136
|
+
.cm-mentionlist button { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border: 0; border-radius: 7px;
|
|
1137
|
+
background: none; color: var(--glass-ink); font: 500 12.5px/1.2 inherit; text-align: left; cursor: pointer; white-space: nowrap }
|
|
1138
|
+
.cm-mentionlist button span { overflow: hidden; text-overflow: ellipsis }
|
|
1139
|
+
.cm-mentionlist button.on { background: var(--glass-hover) }
|
|
1140
|
+
|
|
1124
1141
|
/* Marver identity: the agent's avatar mark + provenance tooltip (§7). Always accent, never a hue. */
|
|
1125
1142
|
.cm-avatar.cm-marver { background: var(--mv-blue); color: rgba(255,255,255,.9); cursor: default } /* white/90 mark, embedded in the accent */
|
|
1126
1143
|
.cm-marver-wrap { display: inline-flex; border-radius: 50% }
|
|
@@ -1208,3 +1225,27 @@ body.sh-hide-ui .sh-play-hint { display: none !important }
|
|
|
1208
1225
|
its children (pins, cards, stacks) fully interactive */
|
|
1209
1226
|
.cm-layer { position: absolute; left: 0; width: 100%; pointer-events: none; z-index: 25 }
|
|
1210
1227
|
.cm-layer > * { pointer-events: auto }
|
|
1228
|
+
|
|
1229
|
+
/* v1.1: an unseen mention of YOU pulses the pin - accent lights until the
|
|
1230
|
+
thread is opened (opening marks it seen). Motion-reduced readers keep a
|
|
1231
|
+
steady accent ring instead of the pulse. */
|
|
1232
|
+
.cm-pin.mention, .cm-stack.mention { outline: 2px solid var(--accent); outline-offset: 1px;
|
|
1233
|
+
animation: cm-mention-pulse 1.7s ease-out infinite }
|
|
1234
|
+
@keyframes cm-mention-pulse {
|
|
1235
|
+
0% { box-shadow: 0 0 0 0 var(--accent-ring), 0 0 0 0 rgba(0, 136, 255, .45) }
|
|
1236
|
+
70% { box-shadow: 0 0 0 6px rgba(0, 136, 255, 0), 0 0 0 12px rgba(0, 136, 255, 0) }
|
|
1237
|
+
100% { box-shadow: 0 0 0 0 rgba(0, 136, 255, 0), 0 0 0 0 rgba(0, 136, 255, 0) }
|
|
1238
|
+
}
|
|
1239
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1240
|
+
.cm-pin.mention, .cm-stack.mention { animation: none }
|
|
1241
|
+
}
|
|
1242
|
+
/* a mention of YOU inside a thread: the loudest chip - accent, heavier */
|
|
1243
|
+
.cm-at.person.me { color: var(--accent); font-weight: 700 }
|
|
1244
|
+
|
|
1245
|
+
/* human notification pill: the author's face, then "name mentioned you".
|
|
1246
|
+
The face outsizes the agent mark (34px) on purpose - a person is the news. */
|
|
1247
|
+
.sh-jam-ava { width: 36px; height: 36px; border-radius: 999px; object-fit: cover; flex: none }
|
|
1248
|
+
.sh-jam-ava.init { display: inline-flex; align-items: center; justify-content: center;
|
|
1249
|
+
color: rgba(255,255,255,.92); font: 700 13px/1 -apple-system, system-ui, sans-serif; letter-spacing: .02em }
|
|
1250
|
+
/* the title row is flex, which swallows the JSX whitespace - the verb carries its own gap */
|
|
1251
|
+
.sh-jam-frame .v { color: var(--glass-ink-2); font-weight: 500; margin-left: 4px; flex: none }
|
package/src/shared/events.ts
CHANGED
|
@@ -10,6 +10,13 @@ export type EventType = 'create' | 'reply' | 'edit' | 'resolve' | 'reopen' | 're
|
|
|
10
10
|
// Live Jam: provenance stamped by the daemon on agent-authored events (who orchestrated the change).
|
|
11
11
|
export interface AgentMeta { devUser?: string; harness?: string; model?: string; effort?: string }
|
|
12
12
|
|
|
13
|
+
/** A person named in a comment (sharing v1.1). Splits exactly like `author`:
|
|
14
|
+
* canonical logs carry `email`, browser transports carry `id` (the same
|
|
15
|
+
* opaque per-canvas HMAC) - exactly one of the two is present. `label` is the
|
|
16
|
+
* display name the composer inserted (bodies stay plain text; rendering
|
|
17
|
+
* highlights `@label` runs by matching it). */
|
|
18
|
+
export interface Mention { email?: string; id?: string; label: string }
|
|
19
|
+
|
|
13
20
|
export interface CommentEvent {
|
|
14
21
|
id: string // client-generated UUID - the idempotency key
|
|
15
22
|
ts: number // ms epoch at creation
|
|
@@ -25,6 +32,7 @@ export interface CommentEvent {
|
|
|
25
32
|
* travels to another viewer's browser. Exactly one of the two is present. */
|
|
26
33
|
author?: { email?: string; id?: string; name?: string; avatar?: string }
|
|
27
34
|
body?: string // plain text in v1
|
|
35
|
+
mentions?: Mention[] // create/reply only - people named in the body (v1.1)
|
|
28
36
|
emoji?: string // react events
|
|
29
37
|
addressedIn?: string // resolve events: the variant frame that answered
|
|
30
38
|
// --- Live Jam additions ---
|
|
@@ -44,7 +52,8 @@ export interface Thread {
|
|
|
44
52
|
addressedIn?: string
|
|
45
53
|
agent?: boolean // root authored by the agent
|
|
46
54
|
agentMeta?: AgentMeta
|
|
47
|
-
|
|
55
|
+
mentions?: Mention[]
|
|
56
|
+
replies: { id: string; author?: CommentEvent['author']; body?: string; ts: number; agent?: boolean; agentMeta?: AgentMeta; mentions?: Mention[] }[]
|
|
48
57
|
reactions: Record<string, string[]> // emoji -> author emails (toggle semantics)
|
|
49
58
|
}
|
|
50
59
|
|
|
@@ -67,7 +76,7 @@ export function replay(events: CommentEvent[]): Thread[] {
|
|
|
67
76
|
threads.set(ev.commentId, {
|
|
68
77
|
id: ev.commentId, board: ev.board, nodeKey: ev.nodeKey, frame: ev.frame,
|
|
69
78
|
anchor: ev.anchor, author: ev.author, body: ev.body, ts: ev.ts,
|
|
70
|
-
resolved: false, agent: ev.agent, agentMeta: ev.agentMeta, replies: [], reactions: {},
|
|
79
|
+
resolved: false, agent: ev.agent, agentMeta: ev.agentMeta, mentions: ev.mentions, replies: [], reactions: {},
|
|
71
80
|
})
|
|
72
81
|
}
|
|
73
82
|
for (const ev of ordered) {
|
|
@@ -75,7 +84,7 @@ export function replay(events: CommentEvent[]): Thread[] {
|
|
|
75
84
|
case 'reply': {
|
|
76
85
|
const t = ev.parentId ? threads.get(ev.parentId) : undefined
|
|
77
86
|
if (!t || !ev.commentId || t.replies.some((r) => r.id === ev.commentId)) break
|
|
78
|
-
t.replies.push({ id: ev.commentId, author: ev.author, body: ev.body, ts: ev.ts, agent: ev.agent, agentMeta: ev.agentMeta })
|
|
87
|
+
t.replies.push({ id: ev.commentId, author: ev.author, body: ev.body, ts: ev.ts, agent: ev.agent, agentMeta: ev.agentMeta, mentions: ev.mentions })
|
|
79
88
|
break
|
|
80
89
|
}
|
|
81
90
|
case 'edit': {
|