@backmatter/studio 0.0.7 → 0.0.8
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-88VsmOhi.js → EmbedPublishPage-CtIlaeGO.js} +1 -1
- package/dist/chunks/{UiKitPage-X4hkFL2d.js → UiKitPage-DcnSQ-Hf.js} +3 -3
- package/dist/chunks/{WorkspaceRoutes-DXzdWqN3.js → WorkspaceRoutes-DVpUOaMV.js} +13416 -13389
- package/dist/chunks/{dashboard-DCHRI0WD.js → dashboard-bNp6AbKE.js} +3 -3
- package/dist/chunks/{index-BS0-Bvbk.js → index-DoDE-hwB.js} +2 -2
- package/dist/chunks/{status-bar-action-wj1KZ51m.js → status-bar-action-C0fsAWvD.js} +3205 -3199
- package/dist/dashboard.js +2 -2
- package/dist/index.js +4 -4
- package/dist/site-widget.js +2 -2
- package/dist/studio.css +36 -32
- package/package.json +2 -2
- package/src/chrome/AppShell.tsx +47 -10
- package/src/chrome/AppSidebar.tsx +9 -34
- package/src/chrome/ContentExplorerSidebar.tsx +129 -91
- package/src/chrome/UserMenu.tsx +3 -1
- package/src/chrome/explorer-icons.tsx +2 -4
- package/src/pages/MediaGalleryPage.tsx +70 -74
- package/src/pages/MediaLightbox.tsx +103 -96
- package/src/pages/SelectRepositoriesLink.tsx +28 -4
- package/src/pages/SettingsGeneralPage.tsx +25 -28
- package/src/pages/SettingsGithubPage.tsx +413 -124
- package/src/pages/media-grid.ts +1 -1
- package/src/workspace-path.ts +14 -1
|
@@ -66,9 +66,38 @@ export function MediaLightbox({
|
|
|
66
66
|
aria-label={item.filename}
|
|
67
67
|
>
|
|
68
68
|
<div {...stylex.props(styles.stage)} onClick={onClose}>
|
|
69
|
-
<
|
|
69
|
+
<button
|
|
70
|
+
type="button"
|
|
71
|
+
aria-label="Previous image"
|
|
72
|
+
disabled={index <= 0}
|
|
73
|
+
{...stylex.props(styles.nav, styles.navPrev)}
|
|
74
|
+
onClick={(event) => {
|
|
75
|
+
event.stopPropagation();
|
|
76
|
+
onPrev();
|
|
77
|
+
}}
|
|
78
|
+
>
|
|
79
|
+
‹
|
|
80
|
+
</button>
|
|
81
|
+
<div {...stylex.props(styles.frame)} onClick={(event) => event.stopPropagation()}>
|
|
82
|
+
<StageImage key={item.id} thumb={item.thumbUrl} full={full} alt={item.filename} />
|
|
83
|
+
</div>
|
|
84
|
+
<button
|
|
85
|
+
type="button"
|
|
86
|
+
aria-label="Next image"
|
|
87
|
+
disabled={index >= count - 1}
|
|
88
|
+
{...stylex.props(styles.nav, styles.navNext)}
|
|
89
|
+
onClick={(event) => {
|
|
90
|
+
event.stopPropagation();
|
|
91
|
+
onNext();
|
|
92
|
+
}}
|
|
93
|
+
>
|
|
94
|
+
›
|
|
95
|
+
</button>
|
|
96
|
+
</div>
|
|
97
|
+
<aside {...stylex.props(styles.sidebar)}>
|
|
98
|
+
<div {...stylex.props(styles.sidebarTools)}>
|
|
70
99
|
<Menu.Root>
|
|
71
|
-
<Menu.Trigger aria-label="Image actions" className={cx(styles.
|
|
100
|
+
<Menu.Trigger aria-label="Image actions" className={cx(styles.sidebarTool)}>
|
|
72
101
|
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true">
|
|
73
102
|
<circle cx="3" cy="7" r="1.15" fill="currentColor" />
|
|
74
103
|
<circle cx="7" cy="7" r="1.15" fill="currentColor" />
|
|
@@ -109,12 +138,7 @@ export function MediaLightbox({
|
|
|
109
138
|
</Menu.Positioner>
|
|
110
139
|
</Menu.Portal>
|
|
111
140
|
</Menu.Root>
|
|
112
|
-
<button
|
|
113
|
-
type="button"
|
|
114
|
-
aria-label="Close"
|
|
115
|
-
{...stylex.props(styles.stageTool)}
|
|
116
|
-
onClick={onClose}
|
|
117
|
-
>
|
|
141
|
+
<button type="button" aria-label="Close" {...stylex.props(styles.sidebarTool)} onClick={onClose}>
|
|
118
142
|
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true">
|
|
119
143
|
<path
|
|
120
144
|
d="M3.5 3.5l7 7M10.5 3.5l-7 7"
|
|
@@ -126,81 +150,54 @@ export function MediaLightbox({
|
|
|
126
150
|
</svg>
|
|
127
151
|
</button>
|
|
128
152
|
</div>
|
|
129
|
-
<
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
{...stylex.props(styles.nav, styles.navPrev)}
|
|
134
|
-
onClick={(event) => {
|
|
135
|
-
event.stopPropagation();
|
|
136
|
-
onPrev();
|
|
137
|
-
}}
|
|
138
|
-
>
|
|
139
|
-
‹
|
|
140
|
-
</button>
|
|
141
|
-
<div {...stylex.props(styles.frame)} onClick={(event) => event.stopPropagation()}>
|
|
142
|
-
<StageImage key={item.id} thumb={item.thumbUrl} full={full} alt={item.filename} />
|
|
143
|
-
</div>
|
|
144
|
-
<button
|
|
145
|
-
type="button"
|
|
146
|
-
aria-label="Next image"
|
|
147
|
-
disabled={index >= count - 1}
|
|
148
|
-
{...stylex.props(styles.nav, styles.navNext)}
|
|
149
|
-
onClick={(event) => {
|
|
150
|
-
event.stopPropagation();
|
|
151
|
-
onNext();
|
|
152
|
-
}}
|
|
153
|
-
>
|
|
154
|
-
›
|
|
155
|
-
</button>
|
|
156
|
-
</div>
|
|
157
|
-
<aside {...stylex.props(styles.sidebar)}>
|
|
158
|
-
<div {...stylex.props(styles.filename)}>
|
|
159
|
-
<Text as="h2" size="lg" weight="medium">
|
|
160
|
-
{item.filename}
|
|
161
|
-
</Text>
|
|
162
|
-
</div>
|
|
163
|
-
<dl {...stylex.props(styles.facts)}>
|
|
164
|
-
<Fact label="Dimensions" value={dimensions(item)} />
|
|
165
|
-
<Fact label="Size" value={item.byteSize === undefined ? "—" : formatBytes(item.byteSize)} />
|
|
166
|
-
<Fact label="Type" value={kindLabel(item.contentType)} />
|
|
167
|
-
<Fact label="Added" value={addedLabel(item.createdAt)} />
|
|
168
|
-
</dl>
|
|
169
|
-
<div {...stylex.props(styles.urlBlock)}>
|
|
170
|
-
<div {...stylex.props(styles.urlHead)}>
|
|
171
|
-
<Text size="xs" tone="muted">
|
|
172
|
-
Original URL
|
|
153
|
+
<div {...stylex.props(styles.sidebarBody)}>
|
|
154
|
+
<div {...stylex.props(styles.filename)}>
|
|
155
|
+
<Text as="h2" size="lg" weight="medium">
|
|
156
|
+
{item.filename}
|
|
173
157
|
</Text>
|
|
174
|
-
<button
|
|
175
|
-
type="button"
|
|
176
|
-
aria-label={copied ? "Copied" : "Copy URL"}
|
|
177
|
-
{...stylex.props(styles.copy)}
|
|
178
|
-
onClick={() => {
|
|
179
|
-
void navigator.clipboard.writeText(item.url).then(() => setCopied(true));
|
|
180
|
-
}}
|
|
181
|
-
>
|
|
182
|
-
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true">
|
|
183
|
-
<rect
|
|
184
|
-
x="4.75"
|
|
185
|
-
y="4.75"
|
|
186
|
-
width="7"
|
|
187
|
-
height="7"
|
|
188
|
-
rx="1.25"
|
|
189
|
-
fill="none"
|
|
190
|
-
stroke="currentColor"
|
|
191
|
-
strokeWidth="1.5"
|
|
192
|
-
/>
|
|
193
|
-
<path
|
|
194
|
-
d="M9.25 4.75V3.25A1.25 1.25 0 0 0 8 2H3.25A1.25 1.25 0 0 0 2 3.25V8A1.25 1.25 0 0 0 3.25 9.25H4.75"
|
|
195
|
-
fill="none"
|
|
196
|
-
stroke="currentColor"
|
|
197
|
-
strokeWidth="1.5"
|
|
198
|
-
/>
|
|
199
|
-
</svg>
|
|
200
|
-
{copied ? "Copied" : "Copy"}
|
|
201
|
-
</button>
|
|
202
158
|
</div>
|
|
203
|
-
<
|
|
159
|
+
<dl {...stylex.props(styles.facts)}>
|
|
160
|
+
<Fact label="Dimensions" value={dimensions(item)} />
|
|
161
|
+
<Fact label="Size" value={item.byteSize === undefined ? "—" : formatBytes(item.byteSize)} />
|
|
162
|
+
<Fact label="Type" value={kindLabel(item.contentType)} />
|
|
163
|
+
<Fact label="Added" value={addedLabel(item.createdAt)} />
|
|
164
|
+
</dl>
|
|
165
|
+
<div {...stylex.props(styles.urlBlock)}>
|
|
166
|
+
<div {...stylex.props(styles.urlHead)}>
|
|
167
|
+
<Text size="xs" tone="muted">
|
|
168
|
+
Original URL
|
|
169
|
+
</Text>
|
|
170
|
+
<button
|
|
171
|
+
type="button"
|
|
172
|
+
aria-label={copied ? "Copied" : "Copy URL"}
|
|
173
|
+
{...stylex.props(styles.copy)}
|
|
174
|
+
onClick={() => {
|
|
175
|
+
void navigator.clipboard.writeText(item.url).then(() => setCopied(true));
|
|
176
|
+
}}
|
|
177
|
+
>
|
|
178
|
+
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true">
|
|
179
|
+
<rect
|
|
180
|
+
x="4.75"
|
|
181
|
+
y="4.75"
|
|
182
|
+
width="7"
|
|
183
|
+
height="7"
|
|
184
|
+
rx="1.25"
|
|
185
|
+
fill="none"
|
|
186
|
+
stroke="currentColor"
|
|
187
|
+
strokeWidth="1.5"
|
|
188
|
+
/>
|
|
189
|
+
<path
|
|
190
|
+
d="M9.25 4.75V3.25A1.25 1.25 0 0 0 8 2H3.25A1.25 1.25 0 0 0 2 3.25V8A1.25 1.25 0 0 0 3.25 9.25H4.75"
|
|
191
|
+
fill="none"
|
|
192
|
+
stroke="currentColor"
|
|
193
|
+
strokeWidth="1.5"
|
|
194
|
+
/>
|
|
195
|
+
</svg>
|
|
196
|
+
{copied ? "Copied" : "Copy"}
|
|
197
|
+
</button>
|
|
198
|
+
</div>
|
|
199
|
+
<p {...stylex.props(styles.url)}>{item.url}</p>
|
|
200
|
+
</div>
|
|
204
201
|
</div>
|
|
205
202
|
</aside>
|
|
206
203
|
</div>
|
|
@@ -324,31 +321,35 @@ const styles = stylex.create({
|
|
|
324
321
|
cursor: "default",
|
|
325
322
|
},
|
|
326
323
|
},
|
|
327
|
-
|
|
328
|
-
position: "absolute",
|
|
329
|
-
top: space.xl,
|
|
330
|
-
right: space.xl,
|
|
331
|
-
zIndex: 2,
|
|
324
|
+
sidebarTools: {
|
|
332
325
|
display: "flex",
|
|
333
326
|
alignItems: "center",
|
|
334
|
-
|
|
327
|
+
justifyContent: "flex-end",
|
|
328
|
+
gap: space.xs,
|
|
335
329
|
},
|
|
336
|
-
|
|
330
|
+
sidebarTool: {
|
|
337
331
|
width: "32px",
|
|
338
332
|
height: "32px",
|
|
339
333
|
display: "flex",
|
|
340
334
|
alignItems: "center",
|
|
341
335
|
justifyContent: "center",
|
|
342
336
|
padding: 0,
|
|
343
|
-
borderWidth:
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
backgroundColor: "rgba(0, 0, 0, 0.45)",
|
|
348
|
-
color: "#fafafa",
|
|
337
|
+
borderWidth: 0,
|
|
338
|
+
borderRadius: radius.md,
|
|
339
|
+
backgroundColor: "transparent",
|
|
340
|
+
color: colors.textMuted,
|
|
349
341
|
cursor: "pointer",
|
|
350
342
|
[hover]: {
|
|
351
|
-
|
|
343
|
+
":hover": {
|
|
344
|
+
backgroundColor: colors.bgHover,
|
|
345
|
+
color: colors.text,
|
|
346
|
+
},
|
|
347
|
+
},
|
|
348
|
+
":focus-visible": {
|
|
349
|
+
outlineWidth: 2,
|
|
350
|
+
outlineStyle: "solid",
|
|
351
|
+
outlineColor: colors.focus,
|
|
352
|
+
outlineOffset: 1,
|
|
352
353
|
},
|
|
353
354
|
},
|
|
354
355
|
menu: {
|
|
@@ -371,7 +372,7 @@ const styles = stylex.create({
|
|
|
371
372
|
flexShrink: 0,
|
|
372
373
|
display: "flex",
|
|
373
374
|
flexDirection: "column",
|
|
374
|
-
justifyContent: "
|
|
375
|
+
justifyContent: "space-between",
|
|
375
376
|
gap: space.xl,
|
|
376
377
|
padding: space.xl,
|
|
377
378
|
backgroundColor: colors.bgSurface,
|
|
@@ -388,6 +389,12 @@ const styles = stylex.create({
|
|
|
388
389
|
borderTopColor: colors.border,
|
|
389
390
|
},
|
|
390
391
|
},
|
|
392
|
+
sidebarBody: {
|
|
393
|
+
display: "flex",
|
|
394
|
+
flexDirection: "column",
|
|
395
|
+
gap: space.xl,
|
|
396
|
+
minWidth: 0,
|
|
397
|
+
},
|
|
391
398
|
filename: {
|
|
392
399
|
minWidth: 0,
|
|
393
400
|
overflowWrap: "anywhere",
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// packages/studio/src/pages/SelectRepositoriesLink.tsx
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
2
|
+
import { useEffect, useState, type ReactNode } from "react";
|
|
3
3
|
import { fetchGithubRepositoryAccess } from "../api";
|
|
4
4
|
import { ButtonLink } from "../ui/Button";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
export function SelectRepositoriesLink({ workspaceId }: { workspaceId: string }) {
|
|
6
|
+
function useRepositoryAccessUrl(workspaceId: string) {
|
|
8
7
|
const [url, setUrl] = useState<string | null>(null);
|
|
9
8
|
|
|
10
9
|
useEffect(() => {
|
|
@@ -21,10 +20,35 @@ export function SelectRepositoriesLink({ workspaceId }: { workspaceId: string })
|
|
|
21
20
|
};
|
|
22
21
|
}, [workspaceId]);
|
|
23
22
|
|
|
23
|
+
return url;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Opens the GitHub page where this installation's repository access is chosen. */
|
|
27
|
+
export function SelectRepositoriesLink({
|
|
28
|
+
workspaceId,
|
|
29
|
+
label = "Select repositories on GitHub",
|
|
30
|
+
}: {
|
|
31
|
+
workspaceId: string;
|
|
32
|
+
label?: string;
|
|
33
|
+
}) {
|
|
34
|
+
const url = useRepositoryAccessUrl(workspaceId);
|
|
24
35
|
if (!url) return null;
|
|
25
36
|
return (
|
|
26
37
|
<ButtonLink href={url} variant="secondary">
|
|
27
|
-
|
|
38
|
+
{label}
|
|
28
39
|
</ButtonLink>
|
|
29
40
|
);
|
|
30
41
|
}
|
|
42
|
+
|
|
43
|
+
/** Renders nothing until the GitHub App's repository-access URL is known. */
|
|
44
|
+
export function GithubRepositoryAccess({
|
|
45
|
+
workspaceId,
|
|
46
|
+
children,
|
|
47
|
+
}: {
|
|
48
|
+
workspaceId: string;
|
|
49
|
+
children: (url: string) => ReactNode;
|
|
50
|
+
}) {
|
|
51
|
+
const url = useRepositoryAccessUrl(workspaceId);
|
|
52
|
+
if (!url) return null;
|
|
53
|
+
return children(url);
|
|
54
|
+
}
|
|
@@ -11,7 +11,6 @@ import { hostEnvSnippet } from "./host-env";
|
|
|
11
11
|
import { isStudioDev, publicApiUrl } from "../studio-config";
|
|
12
12
|
import { revalidateWebhookUrl } from "./preview-url";
|
|
13
13
|
import { Button } from "../ui/Button";
|
|
14
|
-
import { Field } from "../ui/Field";
|
|
15
14
|
import { Input } from "../ui/Input";
|
|
16
15
|
import { PageHeader, Panel, Stack } from "../ui/Page";
|
|
17
16
|
import { Text } from "../ui/Text";
|
|
@@ -147,40 +146,33 @@ export function SettingsGeneralPage() {
|
|
|
147
146
|
</Text>
|
|
148
147
|
<form onSubmit={(e) => void onSaveSiteUrl(e)}>
|
|
149
148
|
<div {...stylex.props(styles.block)}>
|
|
150
|
-
<
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
placeholder="https://www.example.com"
|
|
163
|
-
autoComplete="off"
|
|
164
|
-
spellCheck={false}
|
|
165
|
-
data-lpignore="true"
|
|
166
|
-
data-1p-ignore
|
|
167
|
-
onChange={(e) => setSiteUrl(e.target.value)}
|
|
168
|
-
/>
|
|
169
|
-
</Field>
|
|
149
|
+
<Input
|
|
150
|
+
type="url"
|
|
151
|
+
aria-label="Site URL"
|
|
152
|
+
value={siteUrl}
|
|
153
|
+
readOnly={!canEdit}
|
|
154
|
+
placeholder="https://www.example.com"
|
|
155
|
+
autoComplete="off"
|
|
156
|
+
spellCheck={false}
|
|
157
|
+
data-lpignore="true"
|
|
158
|
+
data-1p-ignore
|
|
159
|
+
onChange={(e) => setSiteUrl(e.target.value)}
|
|
160
|
+
/>
|
|
170
161
|
</div>
|
|
162
|
+
<p {...stylex.props(styles.caption)}>
|
|
163
|
+
{webhookUrl
|
|
164
|
+
? `Preview origin. Pushes POST ${webhookUrl}`
|
|
165
|
+
: "Preview origin. A content push POSTs the revalidate route on this origin."}
|
|
166
|
+
</p>
|
|
167
|
+
<StudioVersions versions={workspace.studioVersions} />
|
|
171
168
|
{canEdit ? (
|
|
172
|
-
<div {...stylex.props(styles.
|
|
173
|
-
<Button
|
|
174
|
-
type="submit"
|
|
175
|
-
variant="secondary"
|
|
176
|
-
disabled={busy !== null}
|
|
177
|
-
>
|
|
169
|
+
<div {...stylex.props(styles.actions)}>
|
|
170
|
+
<Button type="submit" variant="secondary" disabled={busy !== null}>
|
|
178
171
|
{busy === "site-url" ? "Saving…" : "Save"}
|
|
179
172
|
</Button>
|
|
180
173
|
</div>
|
|
181
174
|
) : null}
|
|
182
175
|
</form>
|
|
183
|
-
<StudioVersions versions={workspace.studioVersions} />
|
|
184
176
|
</Panel>
|
|
185
177
|
<Panel>
|
|
186
178
|
<Text as="h2" size="lg" weight="medium">
|
|
@@ -370,6 +362,11 @@ const styles = stylex.create({
|
|
|
370
362
|
block: {
|
|
371
363
|
marginTop: space.md,
|
|
372
364
|
},
|
|
365
|
+
actions: {
|
|
366
|
+
display: "flex",
|
|
367
|
+
justifyContent: "flex-end",
|
|
368
|
+
marginTop: space.lg,
|
|
369
|
+
},
|
|
373
370
|
idRow: {
|
|
374
371
|
display: "flex",
|
|
375
372
|
alignItems: "center",
|