@parhelia/core 0.1.12836 → 0.1.12839
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/components/ui/avatar.d.ts +30 -0
- package/dist/components/ui/avatar.js +46 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/config/config.js +9 -2
- package/dist/config/config.js.map +1 -1
- package/dist/editor/GlobalMenuBar.js +2 -1
- package/dist/editor/GlobalMenuBar.js.map +1 -1
- package/dist/editor/client/EditorShell.js +67 -18
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +8 -0
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/hooks/useEditorWebSocket.d.ts +2 -0
- package/dist/editor/client/hooks/useEditorWebSocket.js +214 -10
- package/dist/editor/client/hooks/useEditorWebSocket.js.map +1 -1
- package/dist/editor/client/hooks/useWorkbox.js +19 -2
- package/dist/editor/client/hooks/useWorkbox.js.map +1 -1
- package/dist/editor/client/realtime/realtimeTransport.d.ts +56 -0
- package/dist/editor/client/realtime/realtimeTransport.js +197 -0
- package/dist/editor/client/realtime/realtimeTransport.js.map +1 -0
- package/dist/editor/menubar/ActiveUsers.js +17 -31
- package/dist/editor/menubar/ActiveUsers.js.map +1 -1
- package/dist/editor/menubar/OpenInNewTabButton.d.ts +15 -0
- package/dist/editor/menubar/OpenInNewTabButton.js +42 -0
- package/dist/editor/menubar/OpenInNewTabButton.js.map +1 -0
- package/dist/editor/menubar/User.js +2 -7
- package/dist/editor/menubar/User.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/ViewportControls.js +48 -3
- package/dist/editor/menubar/toolbar-sections/ViewportControls.js.map +1 -1
- package/dist/editor/page-editor-chrome/CommentHighlightings.js +180 -44
- package/dist/editor/page-editor-chrome/CommentHighlightings.js.map +1 -1
- package/dist/editor/page-editor-chrome/InlineEditor.js +145 -6
- package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
- package/dist/editor/page-editor-chrome/LockedFieldIndicator.js +40 -53
- package/dist/editor/page-editor-chrome/LockedFieldIndicator.js.map +1 -1
- package/dist/editor/page-editor-chrome/overlay/geometry.d.ts +2 -0
- package/dist/editor/page-editor-chrome/overlay/geometry.js +45 -5
- package/dist/editor/page-editor-chrome/overlay/geometry.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +45 -10
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/pageViewContext.js +7 -1
- package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
- package/dist/editor/reviews/CommentView.js +7 -2
- package/dist/editor/reviews/CommentView.js.map +1 -1
- package/dist/editor/reviews/SuggestedEdit.js +7 -2
- package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
- package/dist/editor/reviews/SuggestionDisplayPopover.js +7 -2
- package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
- package/dist/editor/services/agentSubscriptionRegistry.js +12 -13
- package/dist/editor/services/agentSubscriptionRegistry.js.map +1 -1
- package/dist/editor/services/editService.d.ts +2 -0
- package/dist/editor/services/editService.js.map +1 -1
- package/dist/editor/services/systemService.d.ts +9 -0
- package/dist/editor/services/systemService.js +7 -0
- package/dist/editor/services/systemService.js.map +1 -1
- package/dist/editor/services/userResolution.d.ts +18 -0
- package/dist/editor/services/userResolution.js +86 -0
- package/dist/editor/services/userResolution.js.map +1 -0
- package/dist/editor/services/userService.d.ts +8 -0
- package/dist/editor/services/userService.js +26 -0
- package/dist/editor/services/userService.js.map +1 -1
- package/dist/editor/settings/panels/SystemSettingsPanel.d.ts +2 -0
- package/dist/editor/settings/panels/SystemSettingsPanel.js +69 -0
- package/dist/editor/settings/panels/SystemSettingsPanel.js.map +1 -0
- package/dist/editor/settings/panels/UserPreferencesPanel.js +50 -2
- package/dist/editor/settings/panels/UserPreferencesPanel.js.map +1 -1
- package/dist/editor/settings/panels/index.d.ts +1 -0
- package/dist/editor/settings/panels/index.js +1 -0
- package/dist/editor/settings/panels/index.js.map +1 -1
- package/dist/editor/settings/status/coreStatusChecks.js +65 -5
- package/dist/editor/settings/status/coreStatusChecks.js.map +1 -1
- package/dist/editor/setup-wizard/steps/ProviderStep.js +4 -4
- package/dist/editor/setup-wizard/steps/ProviderStep.js.map +1 -1
- package/dist/editor/ui/Section.js +5 -7
- package/dist/editor/ui/Section.js.map +1 -1
- package/dist/editor/ui/SimpleMenu.js +1 -1
- package/dist/editor/ui/SimpleMenu.js.map +1 -1
- package/dist/editor/views/editorSlotContext.js +5 -0
- package/dist/editor/views/editorSlotContext.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/ModernSplashScreen.js +2 -1
- package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// Transport-agnostic realtime handle for the editor.
|
|
2
|
+
//
|
|
3
|
+
// WebSockets remain the preferred transport. When a WebSocket cannot be opened (IIS without
|
|
4
|
+
// the WebSocket feature, a proxy that strips the Upgrade header, etc.) the editor falls back
|
|
5
|
+
// to Server-Sent Events for server->client messages plus HTTP POST for client->server messages.
|
|
6
|
+
//
|
|
7
|
+
// Consumers (EditorShell send paths, agentSubscriptionRegistry, recovery code) talk to the
|
|
8
|
+
// `editorRealtime` handle instead of `globalThis.editorSocket` so they work in either mode.
|
|
9
|
+
import { post } from "../../services/serviceHelper";
|
|
10
|
+
let activeTransport = null;
|
|
11
|
+
// Registered by the connection hook so recovery paths (watchdog, presence recovery) can force a
|
|
12
|
+
// fresh connection in either transport mode. For SSE this must re-create the EventSource, since a
|
|
13
|
+
// deliberate close() does not auto-reconnect.
|
|
14
|
+
let reconnectHandler = null;
|
|
15
|
+
export function setReconnectHandler(fn) {
|
|
16
|
+
reconnectHandler = fn;
|
|
17
|
+
}
|
|
18
|
+
function getHandle() {
|
|
19
|
+
return {
|
|
20
|
+
send(message) {
|
|
21
|
+
const transport = activeTransport;
|
|
22
|
+
if (!transport || !transport.isOpen())
|
|
23
|
+
return false;
|
|
24
|
+
transport.send(message);
|
|
25
|
+
return true;
|
|
26
|
+
},
|
|
27
|
+
sendWithAck(message) {
|
|
28
|
+
const transport = activeTransport;
|
|
29
|
+
if (!transport || !transport.isOpen())
|
|
30
|
+
return Promise.resolve(false);
|
|
31
|
+
return transport.sendWithAck(message);
|
|
32
|
+
},
|
|
33
|
+
isOpen() {
|
|
34
|
+
return !!activeTransport && activeTransport.isOpen();
|
|
35
|
+
},
|
|
36
|
+
mode() {
|
|
37
|
+
return activeTransport ? activeTransport.mode : null;
|
|
38
|
+
},
|
|
39
|
+
reconnect(reason) {
|
|
40
|
+
if (reconnectHandler) {
|
|
41
|
+
reconnectHandler(reason);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
activeTransport?.close();
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** Installs the global handle. Idempotent; call once at module load. */
|
|
49
|
+
export function ensureEditorRealtimeHandle() {
|
|
50
|
+
const existing = globalThis
|
|
51
|
+
.editorRealtime;
|
|
52
|
+
if (existing)
|
|
53
|
+
return existing;
|
|
54
|
+
const handle = getHandle();
|
|
55
|
+
globalThis.editorRealtime =
|
|
56
|
+
handle;
|
|
57
|
+
return handle;
|
|
58
|
+
}
|
|
59
|
+
export function getEditorRealtime() {
|
|
60
|
+
return ensureEditorRealtimeHandle();
|
|
61
|
+
}
|
|
62
|
+
/** Sets the active transport (called by the connection hook when WS/SSE attaches). */
|
|
63
|
+
export function setActiveTransport(transport) {
|
|
64
|
+
activeTransport = transport;
|
|
65
|
+
}
|
|
66
|
+
export function getActiveTransport() {
|
|
67
|
+
return activeTransport;
|
|
68
|
+
}
|
|
69
|
+
// --- WebSocket adapter --------------------------------------------------------------------
|
|
70
|
+
export function createWebSocketAdapter(socket) {
|
|
71
|
+
return {
|
|
72
|
+
mode: "websocket",
|
|
73
|
+
isOpen: () => socket.readyState === WebSocket.OPEN,
|
|
74
|
+
send: (message) => socket.send(JSON.stringify(message)),
|
|
75
|
+
sendWithAck: (message) => {
|
|
76
|
+
if (socket.readyState !== WebSocket.OPEN)
|
|
77
|
+
return Promise.resolve(false);
|
|
78
|
+
socket.send(JSON.stringify(message));
|
|
79
|
+
return Promise.resolve(true);
|
|
80
|
+
},
|
|
81
|
+
close: () => {
|
|
82
|
+
try {
|
|
83
|
+
socket.close();
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
/* ignore */
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// --- SSE adapter --------------------------------------------------------------------------
|
|
92
|
+
const SSE_STREAM_URL = "/parhelia/realtime/stream";
|
|
93
|
+
const SSE_SEND_URL = "/parhelia/realtime/send";
|
|
94
|
+
/**
|
|
95
|
+
* Opens an EventSource to the SSE stream and returns an adapter whose `send` POSTs client->server
|
|
96
|
+
* messages through a per-session FIFO queue (HTTP POSTs have no ordering guarantee, unlike a
|
|
97
|
+
* WebSocket). Consecutive pending `caret-position` messages collapse to the latest (the server
|
|
98
|
+
* coalesces them anyway); all other message types preserve strict order.
|
|
99
|
+
*/
|
|
100
|
+
export function createSseTransport(sessionId, callbacks) {
|
|
101
|
+
const url = `${SSE_STREAM_URL}?sessionId=${encodeURIComponent(sessionId)}`;
|
|
102
|
+
const eventSource = new EventSource(url, { withCredentials: true });
|
|
103
|
+
let closed = false;
|
|
104
|
+
eventSource.addEventListener("open", () => {
|
|
105
|
+
if (!closed)
|
|
106
|
+
callbacks.onOpen();
|
|
107
|
+
});
|
|
108
|
+
eventSource.addEventListener("message", (event) => {
|
|
109
|
+
if (closed)
|
|
110
|
+
return;
|
|
111
|
+
// An in-band session:revoked event must stop EventSource auto-reconnect.
|
|
112
|
+
if (typeof event.data === "string" &&
|
|
113
|
+
event.data.includes('"session:revoked"')) {
|
|
114
|
+
try {
|
|
115
|
+
const parsed = JSON.parse(event.data);
|
|
116
|
+
if (parsed?.type === "session:revoked") {
|
|
117
|
+
callbacks.onMessage(event);
|
|
118
|
+
callbacks.onSessionRevoked();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
/* fall through to normal dispatch */
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
callbacks.onMessage(event);
|
|
127
|
+
});
|
|
128
|
+
eventSource.addEventListener("error", (event) => {
|
|
129
|
+
if (!closed)
|
|
130
|
+
callbacks.onError(event);
|
|
131
|
+
});
|
|
132
|
+
const queue = [];
|
|
133
|
+
let draining = false;
|
|
134
|
+
const drain = async () => {
|
|
135
|
+
if (draining)
|
|
136
|
+
return;
|
|
137
|
+
draining = true;
|
|
138
|
+
try {
|
|
139
|
+
while (queue.length > 0) {
|
|
140
|
+
const entry = queue.shift();
|
|
141
|
+
const result = await post(SSE_SEND_URL, entry.message, sessionId);
|
|
142
|
+
if (result.type === "unauthorized") {
|
|
143
|
+
// 403 + session-revoked header — surface revocation even if the in-band event was missed.
|
|
144
|
+
entry.resolve(false);
|
|
145
|
+
callbacks.onSessionRevoked();
|
|
146
|
+
// Fail any further queued sends; the session is gone.
|
|
147
|
+
while (queue.length > 0)
|
|
148
|
+
queue.shift().resolve(false);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
entry.resolve(result.type !== "error");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
draining = false;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
const enqueue = (message) => {
|
|
159
|
+
if (closed)
|
|
160
|
+
return Promise.resolve(false);
|
|
161
|
+
return new Promise((resolve) => {
|
|
162
|
+
if (message.type === "caret-position") {
|
|
163
|
+
// Collapse consecutive pending caret-position updates to the latest; the superseded one is
|
|
164
|
+
// resolved true (a newer position replaces it — callers ignore caret acks anyway).
|
|
165
|
+
const lastIndex = queue.length - 1;
|
|
166
|
+
const lastEntry = queue[lastIndex];
|
|
167
|
+
if (lastEntry && lastEntry.message.type === "caret-position") {
|
|
168
|
+
lastEntry.resolve(true);
|
|
169
|
+
queue[lastIndex] = { message, resolve };
|
|
170
|
+
void drain();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
queue.push({ message, resolve });
|
|
175
|
+
void drain();
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
return {
|
|
179
|
+
mode: "sse",
|
|
180
|
+
eventSource,
|
|
181
|
+
isOpen: () => !closed && eventSource.readyState !== EventSource.CLOSED,
|
|
182
|
+
send: (message) => {
|
|
183
|
+
void enqueue(message);
|
|
184
|
+
},
|
|
185
|
+
sendWithAck: enqueue,
|
|
186
|
+
close: () => {
|
|
187
|
+
closed = true;
|
|
188
|
+
try {
|
|
189
|
+
eventSource.close();
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
/* ignore */
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=realtimeTransport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtimeTransport.js","sourceRoot":"","sources":["../../../../src/editor/client/realtime/realtimeTransport.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,4FAA4F;AAC5F,6FAA6F;AAC7F,gGAAgG;AAChG,EAAE;AACF,2FAA2F;AAC3F,4FAA4F;AAE5F,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AAyBpD,IAAI,eAAe,GAAoC,IAAI,CAAC;AAE5D,gGAAgG;AAChG,kGAAkG;AAClG,8CAA8C;AAC9C,IAAI,gBAAgB,GAAsC,IAAI,CAAC;AAE/D,MAAM,UAAU,mBAAmB,CAAC,EAAqC;IACvE,gBAAgB,GAAG,EAAE,CAAC;AACxB,CAAC;AAeD,SAAS,SAAS;IAChB,OAAO;QACL,IAAI,CAAC,OAAO;YACV,MAAM,SAAS,GAAG,eAAe,CAAC;YAClC,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE;gBAAE,OAAO,KAAK,CAAC;YACpD,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,WAAW,CAAC,OAAO;YACjB,MAAM,SAAS,GAAG,eAAe,CAAC;YAClC,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACrE,OAAO,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,MAAM;YACJ,OAAO,CAAC,CAAC,eAAe,IAAI,eAAe,CAAC,MAAM,EAAE,CAAC;QACvD,CAAC;QACD,IAAI;YACF,OAAO,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QACvD,CAAC;QACD,SAAS,CAAC,MAAM;YACd,IAAI,gBAAgB,EAAE,CAAC;gBACrB,gBAAgB,CAAC,MAAM,CAAC,CAAC;gBACzB,OAAO;YACT,CAAC;YACD,eAAe,EAAE,KAAK,EAAE,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,0BAA0B;IACxC,MAAM,QAAQ,GAAI,UAAwD;SACvE,cAAc,CAAC;IAClB,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC1B,UAAwD,CAAC,cAAc;QACtE,MAAM,CAAC;IACT,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,0BAA0B,EAAE,CAAC;AACtC,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,kBAAkB,CAAC,SAA0C;IAC3E,eAAe,GAAG,SAAS,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,6FAA6F;AAE7F,MAAM,UAAU,sBAAsB,CAAC,MAAiB;IACtD,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;QAClD,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACvD,WAAW,EAAE,CAAC,OAAO,EAAE,EAAE;YACvB,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACxE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YACrC,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QACD,KAAK,EAAE,GAAG,EAAE;YACV,IAAI,CAAC;gBACH,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,6FAA6F;AAE7F,MAAM,cAAc,GAAG,2BAA2B,CAAC;AACnD,MAAM,YAAY,GAAG,yBAAyB,CAAC;AAa/C;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAAiB,EACjB,SAAgC;IAEhC,MAAM,GAAG,GAAG,GAAG,cAAc,cAAc,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;IAC3E,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,GAAG,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;QACxC,IAAI,CAAC,MAAM;YAAE,SAAS,CAAC,MAAM,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IACH,WAAW,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;QAChD,IAAI,MAAM;YAAE,OAAO;QACnB,yEAAyE;QACzE,IACE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;YAC9B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EACxC,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAsB,CAAC;gBAC3D,IAAI,MAAM,EAAE,IAAI,KAAK,iBAAiB,EAAE,CAAC;oBACvC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;oBAC3B,SAAS,CAAC,gBAAgB,EAAE,CAAC;oBAC7B,OAAO;gBACT,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,qCAAqC;YACvC,CAAC;QACH,CAAC;QACD,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IACH,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC9C,IAAI,CAAC,MAAM;YAAE,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAQH,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,KAAK,GAAG,KAAK,IAAI,EAAE;QACvB,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,CAAC;YACH,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAgB,CAAC;gBAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;gBAClE,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;oBACnC,0FAA0F;oBAC1F,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;oBACrB,SAAS,CAAC,gBAAgB,EAAE,CAAC;oBAC7B,sDAAsD;oBACtD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC;wBAAG,KAAK,CAAC,KAAK,EAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;oBACtE,OAAO;gBACT,CAAC;gBACD,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,QAAQ,GAAG,KAAK,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,OAAwB,EAAoB,EAAE;QAC7D,IAAI,MAAM;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1C,OAAO,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;YACtC,IAAI,OAAO,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;gBACtC,2FAA2F;gBAC3F,mFAAmF;gBACnF,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;gBACnC,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;gBACnC,IAAI,SAAS,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;oBAC7D,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBACxB,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;oBACxC,KAAK,KAAK,EAAE,CAAC;oBACb,OAAO;gBACT,CAAC;YACH,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YACjC,KAAK,KAAK,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,KAAK;QACX,WAAW;QACX,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,IAAI,WAAW,CAAC,UAAU,KAAK,WAAW,CAAC,MAAM;QACtE,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;YAChB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QACD,WAAW,EAAE,OAAO;QACpB,KAAK,EAAE,GAAG,EAAE;YACV,MAAM,GAAG,IAAI,CAAC;YACd,IAAI,CAAC;gBACH,WAAW,CAAC,KAAK,EAAE,CAAC;YACtB,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEditContext } from "../client/editContext";
|
|
3
3
|
import { User } from "./User";
|
|
4
|
+
import { Avatar } from "../../components/ui/avatar";
|
|
4
5
|
import { Popover, PopoverContent, PopoverTrigger, } from "../../components/ui/popover";
|
|
5
6
|
import { useEffect, useState } from "react";
|
|
6
7
|
import { getItemVisitors } from "../services/editService";
|
|
8
|
+
import { useResolvedUser } from "../services/userResolution";
|
|
7
9
|
import { AboutDialog } from "../client/AboutDialog";
|
|
8
10
|
import { formatDateOnly } from "../utils";
|
|
9
11
|
import { ChevronDown, Info, LogOut } from "lucide-react";
|
|
@@ -64,29 +66,14 @@ export function ActiveUsers() {
|
|
|
64
66
|
editContext?.currentItemDescriptor?.language,
|
|
65
67
|
editContext?.currentItemDescriptor?.version,
|
|
66
68
|
]);
|
|
67
|
-
//
|
|
68
|
-
const activeUsers = activeSessions.map((session) => ({
|
|
69
|
-
type: "active",
|
|
70
|
-
sessionId: session.sessionId,
|
|
71
|
-
user: session.user,
|
|
72
|
-
isCurrentUser: session.sessionId === editContext?.sessionId,
|
|
73
|
-
}));
|
|
74
|
-
// Convert visitors to unified format, excluding those who are currently active
|
|
69
|
+
// Recent visitors = visited the item but not currently active (limit 10).
|
|
75
70
|
const activeUserNames = new Set(activeSessions.map((s) => s.user.name.toLowerCase()));
|
|
76
71
|
const recentVisitors = visitors
|
|
77
72
|
.filter((visitor) => !activeUserNames.has(visitor.userName.toLowerCase()))
|
|
78
|
-
.slice(0, 10)
|
|
79
|
-
.map((visitor) => ({
|
|
80
|
-
type: "visitor",
|
|
81
|
-
user: {
|
|
82
|
-
name: visitor.userName,
|
|
83
|
-
displayName: visitor.userName,
|
|
84
|
-
},
|
|
85
|
-
visitedAt: visitor.visitedAt,
|
|
86
|
-
}));
|
|
87
|
-
const allUsers = [...activeUsers, ...recentVisitors];
|
|
73
|
+
.slice(0, 10);
|
|
88
74
|
const visibleUsers = activeSessions.slice(0, 3); // Only show active users in the avatar stack
|
|
89
75
|
const remainingActiveCount = Math.max(0, activeSessions.length - 3);
|
|
76
|
+
const hasAnyUsers = activeSessions.length > 0 || recentVisitors.length > 0;
|
|
90
77
|
const handleAbout = () => {
|
|
91
78
|
editContext?.openDialog(AboutDialog, {});
|
|
92
79
|
};
|
|
@@ -100,19 +87,18 @@ export function ActiveUsers() {
|
|
|
100
87
|
? userName.substring(idxBackslash + 1)
|
|
101
88
|
: userName;
|
|
102
89
|
const userEmail = session.user.email?.trim();
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
})] })), (activeSessions.length > 0 || recentVisitors.length > 0) && (_jsx("div", { className: "border-border-default my-2 border-t" })), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "hover:bg-neutral-grey-5 flex cursor-pointer items-center gap-3 rounded p-1", onClick: handleAbout, children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center", children: _jsx(Info, { className: "text-neutral-grey-50 h-4 w-4" }) }), _jsx("div", { className: "min-w-0 flex-1", children: _jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", children: "About" }) })] }), _jsxs("div", { className: "hover:bg-neutral-grey-5 flex cursor-pointer items-center gap-3 rounded p-1", onClick: handleLogout, children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center", children: _jsx(LogOut, { className: "text-neutral-grey-50 h-4 w-4" }) }), _jsx("div", { className: "min-w-0 flex-1", children: _jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", children: "Log Out" }) })] })] }), allUsers.length === 0 && !isLoadingVisitors && (_jsx("div", { className: "text-neutral-grey-50 p-1 text-sm", children: "No users found" }))] })] })] }));
|
|
90
|
+
const isCurrentUser = session.sessionId === editContext?.sessionId;
|
|
91
|
+
return (_jsxs("div", { className: "hover:bg-neutral-grey-5 flex items-center gap-3 rounded p-1", children: [_jsxs("div", { className: "relative", children: [_jsx(User, { session: session }), _jsx("div", { className: "bg-feedback-green absolute -right-0.5 -bottom-0.5 h-3 w-3 rounded-full border-2 border-white" })] }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-neutral-grey-100 truncate text-xs font-medium", children: displayName }), userEmail && (_jsx("div", { className: "text-neutral-grey-50 truncate text-xs", children: userEmail }))] }), isCurrentUser && (_jsx("div", { className: "text-feedback-blue text-xs font-medium", children: "You" }))] }, session.sessionId));
|
|
92
|
+
}) })), recentVisitors.length > 0 && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "text-neutral-grey-50 mt-3 mb-1 px-2 text-xs font-medium", children: ["Recent Visitors (", recentVisitors.length, ")"] }), recentVisitors.map((visitor, index) => (_jsx(VisitorRow, { visitor: visitor }, `visitor-${index}`)))] })), hasAnyUsers && (_jsx("div", { className: "border-border-default my-2 border-t" })), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "hover:bg-neutral-grey-5 flex cursor-pointer items-center gap-3 rounded p-1", onClick: handleAbout, children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center", children: _jsx(Info, { className: "text-neutral-grey-50 h-4 w-4" }) }), _jsx("div", { className: "min-w-0 flex-1", children: _jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", children: "About" }) })] }), _jsxs("div", { className: "hover:bg-neutral-grey-5 flex cursor-pointer items-center gap-3 rounded p-1", onClick: handleLogout, children: [_jsx("div", { className: "flex h-8 w-8 items-center justify-center", children: _jsx(LogOut, { className: "text-neutral-grey-50 h-4 w-4" }) }), _jsx("div", { className: "min-w-0 flex-1", children: _jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", children: "Log Out" }) })] })] }), !hasAnyUsers && !isLoadingVisitors && (_jsx("div", { className: "text-neutral-grey-50 p-1 text-sm", children: "No users found" }))] })] })] }));
|
|
93
|
+
}
|
|
94
|
+
function VisitorRow({ visitor }) {
|
|
95
|
+
const resolved = useResolvedUser(visitor.userName, {
|
|
96
|
+
fullName: visitor.userFullName,
|
|
97
|
+
avatarUrl: visitor.avatarUrl,
|
|
98
|
+
});
|
|
99
|
+
const visitedAt = visitor.visitedAt ? new Date(visitor.visitedAt) : null;
|
|
100
|
+
const timeAgo = visitedAt ? formatTimeAgo(visitedAt) : "";
|
|
101
|
+
return (_jsxs("div", { className: "hover:bg-neutral-grey-5 flex items-center gap-3 rounded p-1 opacity-75", children: [_jsx(Avatar, { src: resolved.avatarUrl, name: resolved.displayName, size: "md" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-neutral-grey-100 truncate text-xs font-medium", children: resolved.displayName }), _jsx("div", { className: "text-neutral-grey-50 truncate text-xs", children: timeAgo })] })] }));
|
|
116
102
|
}
|
|
117
103
|
function formatTimeAgo(date) {
|
|
118
104
|
const now = new Date();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActiveUsers.js","sourceRoot":"","sources":["../../../src/editor/menubar/ActiveUsers.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAe,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"ActiveUsers.js","sourceRoot":"","sources":["../../../src/editor/menubar/ActiveUsers.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type OpenInNewTabButtonProps = {
|
|
2
|
+
/**
|
|
3
|
+
* When true, pin the button to the top-right inside a scroll container (used on
|
|
4
|
+
* the Home splash, which has no menu bar). When false (default), render the bare
|
|
5
|
+
* button for inline placement in a flex row such as the GlobalMenuBar.
|
|
6
|
+
*/
|
|
7
|
+
floating?: boolean;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Shows an "open in new tab" button when the editor is embedded in an iframe,
|
|
11
|
+
* letting the user break out into a standalone top-level browser tab. Renders
|
|
12
|
+
* nothing when the editor is already the top-level document.
|
|
13
|
+
*/
|
|
14
|
+
export declare function OpenInNewTabButton({ floating }: OpenInNewTabButtonProps): import("react/jsx-runtime").JSX.Element | null;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ExternalLink } from "lucide-react";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Button } from "../../components/ui/button";
|
|
5
|
+
import { Tooltip, TooltipContent, TooltipTrigger, } from "../../components/ui/tooltip";
|
|
6
|
+
/**
|
|
7
|
+
* True when the editor is running inside an iframe (e.g. embedded in Sitecore
|
|
8
|
+
* XM Cloud Pages). A cross-origin parent makes `window.top` throw on access —
|
|
9
|
+
* that itself means we are embedded.
|
|
10
|
+
*/
|
|
11
|
+
function detectEmbedded() {
|
|
12
|
+
if (typeof window === "undefined")
|
|
13
|
+
return false;
|
|
14
|
+
try {
|
|
15
|
+
return window.self !== window.top;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Shows an "open in new tab" button when the editor is embedded in an iframe,
|
|
23
|
+
* letting the user break out into a standalone top-level browser tab. Renders
|
|
24
|
+
* nothing when the editor is already the top-level document.
|
|
25
|
+
*/
|
|
26
|
+
export function OpenInNewTabButton({ floating = false }) {
|
|
27
|
+
// Whether we're embedded doesn't change during a session, so compute it once.
|
|
28
|
+
const [isEmbedded] = useState(detectEmbedded);
|
|
29
|
+
if (!isEmbedded)
|
|
30
|
+
return null;
|
|
31
|
+
const label = "Open in new tab";
|
|
32
|
+
const openInNewTab = () => {
|
|
33
|
+
window.open(window.location.href, "_blank", "noopener,noreferrer");
|
|
34
|
+
};
|
|
35
|
+
const button = (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { size: "iconSm", variant: "ghost", onClick: openInNewTab, "aria-label": label, "data-testid": "open-in-new-tab", children: _jsx(ExternalLink, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: label })] }));
|
|
36
|
+
if (!floating)
|
|
37
|
+
return button;
|
|
38
|
+
// Pinned to the top of the scroll container; the wrapper ignores pointer events
|
|
39
|
+
// so it never blocks the content beneath it, while the button itself stays clickable.
|
|
40
|
+
return (_jsx("div", { className: "pointer-events-none sticky top-0 z-20 flex justify-end px-4 pt-3", children: _jsx("div", { className: "pointer-events-auto", children: button }) }));
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=OpenInNewTabButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenInNewTabButton.js","sourceRoot":"","sources":["../../../src/editor/menubar/OpenInNewTabButton.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,6BAA6B,CAAC;AAErC;;;;GAIG;AACH,SAAS,cAAc;IACrB,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAChD,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,GAAG,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,EAAE,QAAQ,GAAG,KAAK,EAA2B;IAC9E,8EAA8E;IAC9E,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAE7B,MAAM,KAAK,GAAG,iBAAiB,CAAC;IAChC,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IACrE,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,CACb,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,KAAC,MAAM,IACL,IAAI,EAAC,QAAQ,EACb,OAAO,EAAC,OAAO,EACf,OAAO,EAAE,YAAY,gBACT,KAAK,iBACL,iBAAiB,YAE7B,KAAC,YAAY,IAAC,SAAS,EAAC,SAAS,GAAG,GAC7B,GACM,EACjB,KAAC,cAAc,cAAE,KAAK,GAAkB,IAChC,CACX,CAAC;IAEF,IAAI,CAAC,QAAQ;QAAE,OAAO,MAAM,CAAC;IAE7B,gFAAgF;IAChF,sFAAsF;IACtF,OAAO,CACL,cAAK,SAAS,EAAC,kEAAkE,YAC/E,cAAK,SAAS,EAAC,qBAAqB,YAAE,MAAM,GAAO,GAC/C,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEditContext } from "../client/editContext";
|
|
3
|
+
import { Avatar } from "../../components/ui/avatar";
|
|
3
4
|
export function User({ session }) {
|
|
4
5
|
const editContext = useEditContext();
|
|
5
6
|
if (!editContext)
|
|
6
7
|
return;
|
|
7
8
|
const userName = session.user.fullName || session.user.name;
|
|
8
|
-
const idxBackslash = userName.indexOf("\\");
|
|
9
|
-
const letter = idxBackslash >= 0
|
|
10
|
-
? userName[idxBackslash + 1]
|
|
11
|
-
: userName[0]
|
|
12
|
-
? userName[0].toUpperCase()
|
|
13
|
-
: "";
|
|
14
9
|
const userEmail = session.user.email?.trim();
|
|
15
10
|
const userTitle = userEmail ? `${userName} (${userEmail})` : userName;
|
|
16
|
-
return (_jsx(
|
|
11
|
+
return (_jsx(Avatar, { src: session.user.avatarUrl, name: userName, fallbackColor: session.color, title: userTitle, size: "sm" }));
|
|
17
12
|
}
|
|
18
13
|
//# sourceMappingURL=User.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"User.js","sourceRoot":"","sources":["../../../src/editor/menubar/User.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"User.js","sourceRoot":"","sources":["../../../src/editor/menubar/User.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAEpD,MAAM,UAAU,IAAI,CAAC,EAAE,OAAO,EAA4B;IACxD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,IAAI,CAAC,WAAW;QAAE,OAAO;IAEzB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;IAC5D,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;IAC7C,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,QAAQ,KAAK,SAAS,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEtE,OAAO,CACL,KAAC,MAAM,IACL,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAC3B,IAAI,EAAE,QAAQ,EACd,aAAa,EAAE,OAAO,CAAC,KAAK,EAC5B,KAAK,EAAE,SAAS,EAChB,IAAI,EAAC,IAAI,GACT,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -1,13 +1,57 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { CompareIcon } from "../../ui/Icons";
|
|
3
3
|
import { useEditContext } from "../../client/editContext";
|
|
4
4
|
import { SimpleIconButton } from "../../ui/SimpleIconButton";
|
|
5
|
-
import { MessageSquareMore, Map, Layers, PanelRight, FileDiff, } from "lucide-react";
|
|
5
|
+
import { MessageSquareMore, Map, Layers, PanelRight, FileDiff, RotateCcw, ZoomIn, ZoomOut, } from "lucide-react";
|
|
6
6
|
import { Separator } from "../Separator";
|
|
7
7
|
import { useEffect, useState } from "react";
|
|
8
8
|
import { DEVICE_CHANGE_EVENT } from "../../page-viewer/pageViewContext";
|
|
9
9
|
import { cn } from "../../../lib/utils";
|
|
10
10
|
import { DeviceSwitchToolbar } from "./DeviceSwitchToolbar";
|
|
11
|
+
import { Select } from "../../../components/ui/select";
|
|
12
|
+
const ZOOM_MIN = 0.25;
|
|
13
|
+
const ZOOM_MAX = 2;
|
|
14
|
+
const ZOOM_STEP = 0.25;
|
|
15
|
+
const ZOOM_PRESETS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
|
16
|
+
function clampZoom(value) {
|
|
17
|
+
return Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, value));
|
|
18
|
+
}
|
|
19
|
+
function zoomValue(value) {
|
|
20
|
+
return value.toFixed(2);
|
|
21
|
+
}
|
|
22
|
+
function zoomLabel(value) {
|
|
23
|
+
return `${Math.round(value * 100)}%`;
|
|
24
|
+
}
|
|
25
|
+
function ZoomControls() {
|
|
26
|
+
const editContext = useEditContext();
|
|
27
|
+
if (!editContext || editContext.isMobile)
|
|
28
|
+
return null;
|
|
29
|
+
const pageViewContext = editContext.getActiveSlotContext()?.primaryPageViewContext;
|
|
30
|
+
if (!pageViewContext || !pageViewContext.device)
|
|
31
|
+
return null;
|
|
32
|
+
const zoom = pageViewContext.zoom;
|
|
33
|
+
const activeZoomValue = zoomValue(zoom);
|
|
34
|
+
const presetOptions = ZOOM_PRESETS.map((value) => ({
|
|
35
|
+
label: zoomLabel(value),
|
|
36
|
+
value: zoomValue(value),
|
|
37
|
+
}));
|
|
38
|
+
const hasPreset = ZOOM_PRESETS.some((value) => zoomValue(value) === activeZoomValue);
|
|
39
|
+
const options = hasPreset
|
|
40
|
+
? presetOptions
|
|
41
|
+
: [
|
|
42
|
+
...presetOptions,
|
|
43
|
+
{
|
|
44
|
+
label: zoomLabel(zoom),
|
|
45
|
+
value: activeZoomValue,
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
const setActiveSlotZoom = (value) => {
|
|
49
|
+
const currentPageViewContext = editContext.getActiveSlotContext()?.primaryPageViewContext ??
|
|
50
|
+
pageViewContext;
|
|
51
|
+
currentPageViewContext.setZoom(value);
|
|
52
|
+
};
|
|
53
|
+
return (_jsxs("div", { className: "flex shrink-0 items-center gap-0.5", children: [_jsx(SimpleIconButton, { icon: _jsx(ZoomOut, { className: "h-5 w-5 p-0.5", strokeWidth: 1 }), label: "Zoom out", className: "h-7 w-7 p-0.5", "data-testid": "zoom-out-button", disabled: zoom <= ZOOM_MIN, onClick: () => setActiveSlotZoom((value) => clampZoom(value - ZOOM_STEP)) }), _jsx(Select, { className: "h-7 w-[88px] px-2", options: options, value: activeZoomValue, onValueChange: (value) => setActiveSlotZoom(Number(value)), placeholder: zoomLabel(zoom), size: "xs", "data-testid": "zoom-select" }), _jsx(SimpleIconButton, { icon: _jsx(ZoomIn, { className: "h-5 w-5 p-0.5", strokeWidth: 1 }), label: "Zoom in", className: "h-7 w-7 p-0.5", "data-testid": "zoom-in-button", disabled: zoom >= ZOOM_MAX, onClick: () => setActiveSlotZoom((value) => clampZoom(value + ZOOM_STEP)) }), _jsx(SimpleIconButton, { icon: _jsx(RotateCcw, { className: "h-5 w-5 p-0.5", strokeWidth: 1 }), label: "Reset zoom", className: "h-7 w-7 p-0.5", "data-testid": "zoom-reset-button", disabled: zoom === 1, onClick: () => setActiveSlotZoom(1) })] }));
|
|
54
|
+
}
|
|
11
55
|
export function ViewportControls() {
|
|
12
56
|
const editContext = useEditContext();
|
|
13
57
|
// Counter to force re-renders when device changes.
|
|
@@ -37,7 +81,8 @@ export function ViewportControls() {
|
|
|
37
81
|
const canToggleDiffHighlighting = hasLayout && !!device;
|
|
38
82
|
const activeSlotId = editContext.getActiveSlotId();
|
|
39
83
|
const editorFormVisible = !editContext.isEditorFormHiddenForSlot(activeSlotId);
|
|
40
|
-
|
|
84
|
+
const showZoomControls = hasLayout && !!device;
|
|
85
|
+
return (_jsxs(_Fragment, { children: [hasLayout && (_jsxs(_Fragment, { children: [_jsx(DeviceSwitchToolbar, {}), showZoomControls && (_jsxs(_Fragment, { children: [_jsx(Separator, { size: "small" }), _jsx(ZoomControls, {})] })), _jsx(Separator, { size: "large" })] })), !editContext.isMobile && (_jsx(SimpleIconButton, { icon: _jsx(CompareIcon, { className: "h-6 w-6 p-1" }), label: "Compare", size: "large", "data-testid": "compare-mode-button", className: activeSlotContext?.compareMode
|
|
41
86
|
? "text-neutral-grey-50"
|
|
42
87
|
: "hover:text-neutral-grey-50", selected: activeSlotContext?.compareMode, onClick: () => {
|
|
43
88
|
activeSlotContext.setCompareMode(!activeSlotContext.compareMode);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewportControls.js","sourceRoot":"","sources":["../../../../src/editor/menubar/toolbar-sections/ViewportControls.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EACL,iBAAiB,EACjB,GAAG,EACH,MAAM,EACN,UAAU,EACV,QAAQ,
|
|
1
|
+
{"version":3,"file":"ViewportControls.js","sourceRoot":"","sources":["../../../../src/editor/menubar/toolbar-sections/ViewportControls.tsx"],"names":[],"mappings":"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"}
|