@backmatter/studio 0.0.5 → 0.0.6
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/chunks/{EmbedPublishPage-hx1xoAhI.js → EmbedPublishPage-DazYJLaD.js} +13 -13
- package/dist/chunks/{UiKitPage-BOunq6mr.js → UiKitPage-DyVyBp0I.js} +9 -9
- package/dist/chunks/{WorkspaceRoutes-CTFTWu3L.js → WorkspaceRoutes-CPvkgvxe.js} +10869 -10957
- package/dist/chunks/{dashboard-upmiawx5.js → dashboard-6aSS8oyj.js} +194 -194
- package/dist/chunks/{index-CBvevwfT.js → index-DgTNL4t3.js} +2 -2
- package/dist/chunks/{status-bar-action-DiXhfcj3.js → status-bar-action-RNBujSgk.js} +5655 -5427
- package/dist/dashboard.js +2 -2
- package/dist/index.js +18 -18
- package/dist/site-widget.js +788 -234
- package/dist/studio.css +4 -4
- package/package.json +2 -2
- package/src/WorkspaceRoutes.tsx +2 -0
- package/src/api.ts +24 -0
- package/src/chat/ChatPanel.tsx +1 -1
- package/src/chrome/icons.tsx +13 -0
- package/src/pages/SettingsLayout.tsx +7 -1
- package/src/pages/SettingsUsagePage.tsx +168 -0
- package/src/preview-frame.tsx +78 -0
- package/src/site-bar.tsx +769 -0
- package/src/site-widget.tsx +33 -162
package/src/site-widget.tsx
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
// packages/studio/src/site-widget.tsx
|
|
2
|
-
// The on-site bar:
|
|
2
|
+
// The on-site bar: Live/Preview, the current page, the branch, then Agent and Publish. The host page mounts this
|
|
3
3
|
// after the site session verifies. Calls go through the host's same-origin
|
|
4
4
|
// CMS proxy.
|
|
5
|
-
import { useEffect, useLayoutEffect, useRef, useState, type CSSProperties
|
|
5
|
+
import { useEffect, useLayoutEffect, useRef, useState, type CSSProperties } from "react";
|
|
6
6
|
import * as stylex from "@stylexjs/stylex";
|
|
7
7
|
import { ChatPanel } from "./chat/ChatPanel";
|
|
8
|
-
import { PublishIcon, SparkIcon } from "./chat/icons";
|
|
9
8
|
import { chatPointerFromGrab } from "./chat/chat-context";
|
|
10
9
|
import { POINTER_ARM_EVENT } from "./chat/Composer";
|
|
11
10
|
import { ChatProvider, ChatSessionScope, useChatUI } from "./chat/ChatProvider";
|
|
12
11
|
import { isPanelVisible } from "./chat/chat-state";
|
|
13
12
|
import { DOC_CHANGED_EVENT, EditorFocusProvider, useEditorFocus } from "./chrome/EditorFocusContext";
|
|
14
|
-
import { matchAppHotkey
|
|
13
|
+
import { matchAppHotkey } from "./chrome/hotkeys";
|
|
15
14
|
import { EmbedPublishPage } from "./pages/EmbedPublishPage";
|
|
15
|
+
import { PreviewFrame } from "./preview-frame";
|
|
16
|
+
import { DEVBAR_CLASS, SiteBar } from "./site-bar";
|
|
16
17
|
import { installSitePointer } from "./site-pointer";
|
|
17
18
|
import { lightTheme } from "./styles/themes";
|
|
18
19
|
import { configureStudio } from "./studio-config";
|
|
@@ -30,28 +31,36 @@ export type SiteWidgetProps = {
|
|
|
30
31
|
doc: SiteWidgetDoc | null;
|
|
31
32
|
branch?: string;
|
|
32
33
|
tree?: string;
|
|
34
|
+
siteMode?: "preview" | "live";
|
|
33
35
|
exiting?: boolean;
|
|
34
36
|
onExit: () => void;
|
|
37
|
+
onEnterPreview?: () => void;
|
|
35
38
|
/** The host re-renders the page after a write. */
|
|
36
39
|
onDocChanged?: () => void;
|
|
37
40
|
/** The site session was rejected. The host drops the widget. */
|
|
38
41
|
onSessionExpired?: () => void;
|
|
39
42
|
/** Same-origin CMS proxy. Default `/api/backmatter/cms`. */
|
|
40
43
|
proxyPath?: string;
|
|
44
|
+
/** Host route that turns a preview ticket into the site session. */
|
|
45
|
+
previewEntryPath?: string;
|
|
46
|
+
/** Full-viewport preview ring and top pill (see `devBar.previewFrame` in host config). */
|
|
47
|
+
previewFrame?: boolean;
|
|
41
48
|
version?: string;
|
|
42
49
|
};
|
|
43
50
|
|
|
44
|
-
const DEVBAR_CLASS = "backmatter-devbar";
|
|
45
|
-
|
|
46
51
|
export function SiteWidget({
|
|
47
52
|
doc,
|
|
48
53
|
branch,
|
|
49
54
|
tree,
|
|
55
|
+
siteMode = "preview",
|
|
50
56
|
exiting,
|
|
51
57
|
onExit,
|
|
58
|
+
onEnterPreview,
|
|
52
59
|
onDocChanged,
|
|
53
60
|
onSessionExpired,
|
|
54
61
|
proxyPath = "/api/backmatter/cms",
|
|
62
|
+
previewEntryPath,
|
|
63
|
+
previewFrame,
|
|
55
64
|
version,
|
|
56
65
|
}: SiteWidgetProps) {
|
|
57
66
|
const expiredRef = useRef(onSessionExpired);
|
|
@@ -94,50 +103,27 @@ export function SiteWidget({
|
|
|
94
103
|
}, []);
|
|
95
104
|
|
|
96
105
|
const bar = (
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
{
|
|
101
|
-
{
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
<span>Publish{changeCount ? ` ${changeCount}` : ""}</span>
|
|
114
|
-
</button>
|
|
115
|
-
<button
|
|
116
|
-
type="button"
|
|
117
|
-
className={`${DEVBAR_CLASS}-btn ${DEVBAR_CLASS}-agent${chatOpen ? ` ${DEVBAR_CLASS}-on` : ""}`}
|
|
118
|
-
aria-pressed={chatOpen}
|
|
119
|
-
aria-keyshortcuts="Meta+J Control+J"
|
|
120
|
-
disabled={!doc}
|
|
121
|
-
onClick={() => {
|
|
122
|
-
setPublishOpen(false);
|
|
123
|
-
setChatOpen((open) => !open);
|
|
124
|
-
}}
|
|
125
|
-
>
|
|
126
|
-
<SparkIcon />
|
|
127
|
-
<span>Agent</span>
|
|
128
|
-
<kbd>
|
|
129
|
-
{modifierSymbol()}J
|
|
130
|
-
</kbd>
|
|
131
|
-
</button>
|
|
132
|
-
<button type="button" aria-label="Exit preview" disabled={exiting} onClick={onExit} style={barButton}>
|
|
133
|
-
Exit
|
|
134
|
-
</button>
|
|
135
|
-
</footer>
|
|
106
|
+
<SiteBar
|
|
107
|
+
label={label}
|
|
108
|
+
branch={branch}
|
|
109
|
+
tree={tree}
|
|
110
|
+
doc={doc}
|
|
111
|
+
siteMode={siteMode}
|
|
112
|
+
exiting={exiting}
|
|
113
|
+
chatOpen={chatOpen}
|
|
114
|
+
publishOpen={publishOpen}
|
|
115
|
+
changeCount={changeCount}
|
|
116
|
+
previewEntryPath={previewEntryPath}
|
|
117
|
+
onExit={onExit}
|
|
118
|
+
onEnterPreview={onEnterPreview}
|
|
119
|
+
onToggleChat={() => setChatOpen((open) => !open)}
|
|
120
|
+
onTogglePublish={() => setPublishOpen((open) => !open)}
|
|
121
|
+
/>
|
|
136
122
|
);
|
|
137
123
|
|
|
138
124
|
return (
|
|
139
125
|
<>
|
|
140
|
-
<
|
|
126
|
+
{previewFrame ? <PreviewFrame /> : null}
|
|
141
127
|
{doc ? (
|
|
142
128
|
<TooltipProvider>
|
|
143
129
|
<EditorFocusProvider>
|
|
@@ -265,69 +251,10 @@ function SitePointer({ doc }: { doc: SiteWidgetDoc }) {
|
|
|
265
251
|
return null;
|
|
266
252
|
}
|
|
267
253
|
|
|
268
|
-
function BarText({ children }: { children: ReactNode }) {
|
|
269
|
-
return <span style={mutedStyle}>{children}</span>;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const barStyle: CSSProperties = {
|
|
273
|
-
position: "fixed",
|
|
274
|
-
right: "max(16px, env(safe-area-inset-right, 0px))",
|
|
275
|
-
bottom: 0,
|
|
276
|
-
zIndex: 2147483000,
|
|
277
|
-
isolation: "isolate",
|
|
278
|
-
display: "flex",
|
|
279
|
-
alignItems: "center",
|
|
280
|
-
gap: 2,
|
|
281
|
-
width: "max-content",
|
|
282
|
-
maxWidth: "calc(100vw - 32px)",
|
|
283
|
-
minHeight: 36,
|
|
284
|
-
padding: "0 6px 0 10px",
|
|
285
|
-
boxSizing: "border-box",
|
|
286
|
-
border: "1px solid #e4e4e7",
|
|
287
|
-
borderRadius: "12px 12px 0 0",
|
|
288
|
-
background: "#ffffff",
|
|
289
|
-
color: "#71717a",
|
|
290
|
-
boxShadow: "0 10px 28px rgba(24, 24, 27, 0.12), 0 1px 2px rgba(24, 24, 27, 0.06)",
|
|
291
|
-
font: '12px/1 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif',
|
|
292
|
-
WebkitFontSmoothing: "antialiased",
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
const barButton: CSSProperties = {
|
|
296
|
-
border: 0,
|
|
297
|
-
borderRadius: 8,
|
|
298
|
-
background: "transparent",
|
|
299
|
-
color: "#18181b",
|
|
300
|
-
font: "inherit",
|
|
301
|
-
cursor: "pointer",
|
|
302
|
-
padding: "0 8px",
|
|
303
|
-
minHeight: 28,
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const docLabel: CSSProperties = {
|
|
307
|
-
fontWeight: 600,
|
|
308
|
-
color: "#18181b",
|
|
309
|
-
maxWidth: 200,
|
|
310
|
-
overflow: "hidden",
|
|
311
|
-
textOverflow: "ellipsis",
|
|
312
|
-
whiteSpace: "nowrap",
|
|
313
|
-
padding: "0 6px",
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
const mutedStyle: CSSProperties = {
|
|
317
|
-
color: "#71717a",
|
|
318
|
-
fontSize: 12,
|
|
319
|
-
margin: 0,
|
|
320
|
-
padding: "0 6px",
|
|
321
|
-
maxWidth: 140,
|
|
322
|
-
overflow: "hidden",
|
|
323
|
-
textOverflow: "ellipsis",
|
|
324
|
-
whiteSpace: "nowrap",
|
|
325
|
-
};
|
|
326
|
-
|
|
327
254
|
const publishStyle: CSSProperties = {
|
|
328
255
|
position: "fixed",
|
|
329
256
|
right: "max(16px, env(safe-area-inset-right, 0px))",
|
|
330
|
-
bottom: "calc(env(safe-area-inset-bottom, 0px)
|
|
257
|
+
bottom: "calc(48px + env(safe-area-inset-bottom, 0px))",
|
|
331
258
|
zIndex: 2147483001,
|
|
332
259
|
width: "min(320px, calc(100vw - 32px))",
|
|
333
260
|
maxHeight: "min(420px, calc(100vh - 80px))",
|
|
@@ -337,59 +264,3 @@ const publishStyle: CSSProperties = {
|
|
|
337
264
|
background: "#ffffff",
|
|
338
265
|
boxShadow: "0 16px 40px rgba(24, 24, 27, 0.14), 0 2px 8px rgba(24, 24, 27, 0.06)",
|
|
339
266
|
};
|
|
340
|
-
|
|
341
|
-
const BAR_CSS = `
|
|
342
|
-
@keyframes backmatter-devbar-in {
|
|
343
|
-
from { opacity: 0; transform: translateY(10px) scale(0.98); }
|
|
344
|
-
to { opacity: 1; transform: none; }
|
|
345
|
-
}
|
|
346
|
-
.${DEVBAR_CLASS} { animation: backmatter-devbar-in 240ms cubic-bezier(0.23, 1, 0.32, 1) both; }
|
|
347
|
-
@media (prefers-reduced-motion: reduce) {
|
|
348
|
-
.${DEVBAR_CLASS} { animation: none; }
|
|
349
|
-
}
|
|
350
|
-
.${DEVBAR_CLASS}-btn {
|
|
351
|
-
display: inline-flex;
|
|
352
|
-
align-items: center;
|
|
353
|
-
gap: 6px;
|
|
354
|
-
height: 26px;
|
|
355
|
-
margin-inline: 4px;
|
|
356
|
-
padding: 0 8px;
|
|
357
|
-
border: 1px solid #e4e4e7;
|
|
358
|
-
border-radius: 6px;
|
|
359
|
-
background: #ffffff;
|
|
360
|
-
color: #18181b;
|
|
361
|
-
font-size: 11px;
|
|
362
|
-
font-weight: 500;
|
|
363
|
-
line-height: 1;
|
|
364
|
-
cursor: pointer;
|
|
365
|
-
}
|
|
366
|
-
.${DEVBAR_CLASS}-agent kbd {
|
|
367
|
-
font-family: Geist Mono, ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
368
|
-
font-size: 11px;
|
|
369
|
-
font-weight: 400;
|
|
370
|
-
opacity: 0.7;
|
|
371
|
-
}
|
|
372
|
-
.${DEVBAR_CLASS} button.${DEVBAR_CLASS}-on,
|
|
373
|
-
.${DEVBAR_CLASS} button.${DEVBAR_CLASS}-on:hover:not(:disabled) {
|
|
374
|
-
background: #18181b;
|
|
375
|
-
border-color: #18181b;
|
|
376
|
-
color: #fafafa;
|
|
377
|
-
}
|
|
378
|
-
@media (hover: hover) {
|
|
379
|
-
.${DEVBAR_CLASS} button:hover:not(:disabled) { background: #f4f4f5; }
|
|
380
|
-
.${DEVBAR_CLASS} button.${DEVBAR_CLASS}-btn:hover:not(:disabled) {
|
|
381
|
-
background: rgba(24, 24, 27, 0.05);
|
|
382
|
-
}
|
|
383
|
-
.${DEVBAR_CLASS} button.${DEVBAR_CLASS}-on:hover:not(:disabled) {
|
|
384
|
-
background: #18181b;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
.${DEVBAR_CLASS} button:focus-visible { outline: 2px solid #18181b; outline-offset: 2px; }
|
|
388
|
-
.${DEVBAR_CLASS} button:disabled { cursor: default; opacity: 0.5; }
|
|
389
|
-
html.backmatter-pointing, html.backmatter-pointing * { cursor: crosshair !important; }
|
|
390
|
-
html.backmatter-pointing .${DEVBAR_CLASS},
|
|
391
|
-
html.backmatter-pointing .${DEVBAR_CLASS} *,
|
|
392
|
-
html.backmatter-pointing [data-backmatter-panel],
|
|
393
|
-
html.backmatter-pointing [data-backmatter-panel] * { cursor: pointer !important; }
|
|
394
|
-
html.backmatter-pointing .${DEVBAR_CLASS} button:disabled { cursor: default !important; }
|
|
395
|
-
`;
|