@backmatter/studio 0.0.16 → 0.0.18
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/{UiKitApp-_EDqWID3.js → UiKitApp-DkuQBiQZ.js} +2 -2
- package/dist/chunks/{WorkspaceRoutes-B2PrFgpz.js → WorkspaceRoutes-DVvb3N-V.js} +27489 -26622
- package/dist/chunks/{dashboard-BnlnMnnr.js → dashboard-B4FITg6c.js} +2 -2
- package/dist/chunks/{define-studio-BYtYDGLX.js → define-studio-DlYjgrwr.js} +12 -16
- package/dist/chunks/{index-D_BHF_8q.js → index-CegtXnEI.js} +1 -1
- package/dist/dashboard.js +2 -2
- package/dist/define.js +1 -1
- package/dist/index.js +4 -4
- package/dist/site-widget.css +45 -1
- package/dist/site-widget.js +2799 -2791
- package/dist/studio.css +113 -15
- package/package.json +2 -2
- package/src/api.ts +22 -0
- package/src/chat/ChatProvider.tsx +6 -0
- package/src/chat/Composer.tsx +3 -1
- package/src/chrome/Toast.tsx +115 -0
- package/src/chrome/WorkspaceStatusBar.tsx +12 -3
- package/src/chrome/commit-error.ts +13 -0
- package/src/chrome/pull-failure.ts +61 -0
- package/src/{pages/code-session-routes.ts → content-routes.ts} +6 -6
- package/src/fields/FieldControl.tsx +771 -0
- package/src/fields/LinkFieldInput.tsx +315 -0
- package/src/fields/choose-field-input.ts +69 -0
- package/src/fields/link-targets.ts +60 -0
- package/src/fields/load-relation-documents.ts +35 -0
- package/src/fields/omit-field.ts +12 -0
- package/src/fields/relation-targets.ts +44 -0
- package/src/fields/resolve-object-fields.ts +21 -0
- package/src/host-path.ts +13 -0
- package/src/pages/BlockSettingsDialog.tsx +19 -115
- package/src/pages/BlocksList.tsx +43 -35
- package/src/pages/BodyProse.tsx +16 -1
- package/src/pages/CodeSessionPage.tsx +186 -248
- package/src/pages/DocEditorPage.tsx +168 -213
- package/src/pages/MediaFieldInput.tsx +609 -26
- package/src/pages/MediaGalleryPage.tsx +14 -3
- package/src/pages/PreviewAddress.tsx +263 -0
- package/src/pages/RenderedBody.tsx +17 -2
- package/src/pages/branch-notice.ts +16 -0
- package/src/pages/code-session-boot.ts +0 -12
- package/src/pages/code-session-context.tsx +2 -0
- package/src/pages/media-selection.ts +79 -0
- package/src/shell-resets.css +15 -0
- package/src/ui/Input.tsx +178 -20
- package/src/ui/popup.ts +11 -2
|
@@ -3,8 +3,10 @@ import { Snake } from "loading-dev";
|
|
|
3
3
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { useOutletContext, useParams, useSearchParams, Link, useNavigate } from "react-router";
|
|
5
5
|
import * as stylex from "@stylexjs/stylex";
|
|
6
|
+
import { matchRoute, repoPathFromModel } from "@backmatter/core";
|
|
6
7
|
import {
|
|
7
8
|
fetchDoc,
|
|
9
|
+
fetchDocs,
|
|
8
10
|
notifyTreeChanged,
|
|
9
11
|
type TreeChangeDetail,
|
|
10
12
|
createPreviewTicket,
|
|
@@ -17,8 +19,12 @@ import {
|
|
|
17
19
|
type SchemaPayload,
|
|
18
20
|
type SchemaField,
|
|
19
21
|
} from "../api";
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
+
import { FieldControl } from "../fields/FieldControl";
|
|
23
|
+
import { loadRelationDocuments } from "../fields/load-relation-documents";
|
|
24
|
+
import { omitField } from "../fields/omit-field";
|
|
25
|
+
import { linkDocumentTypes } from "../fields/link-targets";
|
|
26
|
+
import { relationTargets } from "../fields/relation-targets";
|
|
27
|
+
import { useReplicaState } from "../replica/useReplica";
|
|
22
28
|
import { useSetEditorActions } from "../chrome/EditorActionsContext";
|
|
23
29
|
import {
|
|
24
30
|
DOC_CHANGED_EVENT,
|
|
@@ -30,7 +36,6 @@ import {
|
|
|
30
36
|
} from "../chrome/EditorFocusContext";
|
|
31
37
|
import { useSetEditorStatus } from "../chrome/EditorStatusContext";
|
|
32
38
|
import { modifierSymbol } from "../chrome/hotkeys";
|
|
33
|
-
import { ReloadIcon } from "../chrome/icons";
|
|
34
39
|
import { colors, radius, space, type } from "../styles/tokens.stylex";
|
|
35
40
|
import { Button, ButtonLink } from "../ui/Button";
|
|
36
41
|
import { ConfirmDialog } from "../ui/ConfirmDialog";
|
|
@@ -46,6 +51,8 @@ import {
|
|
|
46
51
|
persistPreviewPct,
|
|
47
52
|
readPreviewPct,
|
|
48
53
|
} from "./preview-split";
|
|
54
|
+
import { routesForContentFiles } from "../content-routes";
|
|
55
|
+
import { PreviewAddress } from "./PreviewAddress";
|
|
49
56
|
import { PreviewSizeSwitch, PreviewViewport } from "./PreviewSize";
|
|
50
57
|
import { persistPreviewSize, readPreviewSize, type PreviewSize } from "./preview-size";
|
|
51
58
|
import {
|
|
@@ -78,10 +85,6 @@ import {
|
|
|
78
85
|
const AUTOSAVE_MS = 400;
|
|
79
86
|
const hover = "@media (hover: hover)";
|
|
80
87
|
|
|
81
|
-
const spin = stylex.keyframes({
|
|
82
|
-
to: { transform: "rotate(360deg)" },
|
|
83
|
-
});
|
|
84
|
-
|
|
85
88
|
const pulse = stylex.keyframes({
|
|
86
89
|
"0%": { opacity: 0.4 },
|
|
87
90
|
"50%": { opacity: 1 },
|
|
@@ -130,48 +133,6 @@ function emptyFrontmatter(model: SchemaPayload["models"][number] | undefined) {
|
|
|
130
133
|
return out;
|
|
131
134
|
}
|
|
132
135
|
|
|
133
|
-
function JsonField({
|
|
134
|
-
value,
|
|
135
|
-
kind,
|
|
136
|
-
readOnly,
|
|
137
|
-
onValidChange,
|
|
138
|
-
}: {
|
|
139
|
-
value: unknown;
|
|
140
|
-
kind: "object" | "array";
|
|
141
|
-
readOnly?: boolean;
|
|
142
|
-
onValidChange: (next: unknown) => void;
|
|
143
|
-
}) {
|
|
144
|
-
const serialized = JSON.stringify(value ?? (kind === "array" ? [] : {}), null, 2);
|
|
145
|
-
const [draft, setDraft] = useState(serialized);
|
|
146
|
-
const [focused, setFocused] = useState(false);
|
|
147
|
-
const [invalid, setInvalid] = useState(false);
|
|
148
|
-
useEffect(() => {
|
|
149
|
-
if (!focused) {
|
|
150
|
-
setDraft(serialized);
|
|
151
|
-
setInvalid(false);
|
|
152
|
-
}
|
|
153
|
-
}, [serialized, focused]);
|
|
154
|
-
return (
|
|
155
|
-
<Textarea
|
|
156
|
-
value={draft}
|
|
157
|
-
readOnly={readOnly}
|
|
158
|
-
aria-invalid={invalid || undefined}
|
|
159
|
-
onFocus={() => setFocused(true)}
|
|
160
|
-
onBlur={() => setFocused(false)}
|
|
161
|
-
onChange={(e) => {
|
|
162
|
-
const next = e.target.value;
|
|
163
|
-
setDraft(next);
|
|
164
|
-
try {
|
|
165
|
-
onValidChange(JSON.parse(next || (kind === "array" ? "[]" : "{}")));
|
|
166
|
-
setInvalid(false);
|
|
167
|
-
} catch {
|
|
168
|
-
setInvalid(true);
|
|
169
|
-
}
|
|
170
|
-
}}
|
|
171
|
-
/>
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
136
|
/** Status-bar label for the doc's state against the branch HEAD. */
|
|
176
137
|
export function docStatusLabel(status: DocStatus | null): string | null {
|
|
177
138
|
if (status === null) return null;
|
|
@@ -202,7 +163,34 @@ export function DocEditorPage() {
|
|
|
202
163
|
const [docFormat, setDocFormat] = useState<"mdx" | "page">("mdx");
|
|
203
164
|
const [fieldKinds, setFieldKinds] = useState<Record<string, string>>({});
|
|
204
165
|
const [fieldDefs, setFieldDefs] = useState<Record<string, SchemaField>>({});
|
|
205
|
-
const
|
|
166
|
+
const replica = useReplicaState();
|
|
167
|
+
const objects = useMemo(
|
|
168
|
+
() => replica.checkout(workspace.id)?.schema?.payload.objects ?? [],
|
|
169
|
+
[replica, workspace.id],
|
|
170
|
+
);
|
|
171
|
+
const relationTargetTypes = useMemo(() => {
|
|
172
|
+
const targets = new Set<string>();
|
|
173
|
+
const groups: Record<string, SchemaField>[] = [];
|
|
174
|
+
if (model?.fields) groups.push(model.fields);
|
|
175
|
+
for (const block of blocks) {
|
|
176
|
+
if (block.fields) groups.push(block.fields);
|
|
177
|
+
}
|
|
178
|
+
for (const block of richtext) {
|
|
179
|
+
if (block.fields) groups.push(block.fields);
|
|
180
|
+
}
|
|
181
|
+
for (const fields of groups) {
|
|
182
|
+
for (const type of relationTargets(fields, models, objects)) {
|
|
183
|
+
targets.add(type);
|
|
184
|
+
}
|
|
185
|
+
for (const type of linkDocumentTypes(fields, models, objects)) {
|
|
186
|
+
targets.add(type);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return [...targets].sort();
|
|
190
|
+
}, [model, blocks, richtext, models, objects]);
|
|
191
|
+
const [documentLists, setDocumentLists] = useState<
|
|
192
|
+
Record<string, Array<{ slug: string; frontmatter: Record<string, unknown> }>> | undefined
|
|
193
|
+
>(undefined);
|
|
206
194
|
const [parseFailed, setParseFailed] = useState(false);
|
|
207
195
|
const [error, setError] = useState<string | null>(null);
|
|
208
196
|
const [status, setStatus] = useState<string | null>(null);
|
|
@@ -260,6 +248,9 @@ export function DocEditorPage() {
|
|
|
260
248
|
editEpochRef.current = editEpoch;
|
|
261
249
|
|
|
262
250
|
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
|
|
251
|
+
const docIdentity = `${type}\0${slug}`;
|
|
252
|
+
const [browse, setBrowse] = useState<{ doc: string; path: string } | null>(null);
|
|
253
|
+
const browsedPath = browse?.doc === docIdentity ? browse.path : null;
|
|
263
254
|
const isPage = docFormat === "page";
|
|
264
255
|
const detailNames = fieldNames.filter((name) => fieldKinds[name] !== "blocks");
|
|
265
256
|
const blocksField =
|
|
@@ -282,18 +273,28 @@ export function DocEditorPage() {
|
|
|
282
273
|
branch,
|
|
283
274
|
tree,
|
|
284
275
|
});
|
|
276
|
+
const framePath = browsedPath ?? previewPath;
|
|
277
|
+
// Each document is the content file its model path names. A deleted document is gone.
|
|
278
|
+
const previewRoutes = routesForContentFiles(
|
|
279
|
+
models,
|
|
280
|
+
replica.docs(workspaceId).flatMap((doc) => {
|
|
281
|
+
if (doc.status === "deleted") return [];
|
|
282
|
+
const model = models.find((item) => item.type === doc.type);
|
|
283
|
+
return model ? [repoPathFromModel(model, doc.slug)] : [];
|
|
284
|
+
}),
|
|
285
|
+
);
|
|
285
286
|
|
|
286
287
|
useEffect(() => {
|
|
287
|
-
if (!frameIdentity || !
|
|
288
|
+
if (!frameIdentity || !framePath || !workspaceId || !siteUrl) {
|
|
288
289
|
setPreviewUrl(null);
|
|
289
290
|
return;
|
|
290
291
|
}
|
|
291
292
|
if (studioIsOnSite(siteUrl, window.location.origin)) {
|
|
292
|
-
setPreviewUrl(onSitePreviewUrl(siteUrl,
|
|
293
|
+
setPreviewUrl(onSitePreviewUrl(siteUrl, framePath));
|
|
293
294
|
return;
|
|
294
295
|
}
|
|
295
296
|
let cancelled = false;
|
|
296
|
-
void createPreviewTicket(workspaceId, { redirect:
|
|
297
|
+
void createPreviewTicket(workspaceId, { redirect: framePath, branch, tree })
|
|
297
298
|
.then((res) => {
|
|
298
299
|
if (!cancelled) setPreviewUrl(previewEnableUrl(siteUrl, res.ticket));
|
|
299
300
|
})
|
|
@@ -303,7 +304,32 @@ export function DocEditorPage() {
|
|
|
303
304
|
return () => {
|
|
304
305
|
cancelled = true;
|
|
305
306
|
};
|
|
306
|
-
}, [frameIdentity,
|
|
307
|
+
}, [frameIdentity, framePath, workspaceId, siteUrl, branch, tree]);
|
|
308
|
+
|
|
309
|
+
useEffect(() => {
|
|
310
|
+
if (relationTargetTypes.length === 0) {
|
|
311
|
+
setDocumentLists({});
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
let cancelled = false;
|
|
315
|
+
setDocumentLists(undefined);
|
|
316
|
+
void loadRelationDocuments(
|
|
317
|
+
relationTargetTypes,
|
|
318
|
+
async () => (await fetchDocs(workspaceId)).docs,
|
|
319
|
+
async (relationType, relationSlug) => ({
|
|
320
|
+
frontmatter: (await fetchDoc(workspaceId, relationType, relationSlug)).doc.frontmatter,
|
|
321
|
+
}),
|
|
322
|
+
)
|
|
323
|
+
.then((loaded) => {
|
|
324
|
+
if (!cancelled) setDocumentLists(loaded);
|
|
325
|
+
})
|
|
326
|
+
.catch(() => {
|
|
327
|
+
if (!cancelled) setDocumentLists({});
|
|
328
|
+
});
|
|
329
|
+
return () => {
|
|
330
|
+
cancelled = true;
|
|
331
|
+
};
|
|
332
|
+
}, [workspaceId, type, slug, relationTargetTypes.join("\0")]);
|
|
307
333
|
|
|
308
334
|
useEffect(() => {
|
|
309
335
|
setPreviewLoading(true);
|
|
@@ -477,6 +503,17 @@ export function DocEditorPage() {
|
|
|
477
503
|
setPreviewKey((k) => k + 1);
|
|
478
504
|
}
|
|
479
505
|
|
|
506
|
+
function onPreviewPath(next: string) {
|
|
507
|
+
const pathname = next.split(/[?#]/, 1)[0] || "/";
|
|
508
|
+
const doc = matchRoute(models, pathname);
|
|
509
|
+
if (doc && (doc.type !== type || doc.slug !== slug)) {
|
|
510
|
+
navigate(contentDocPath(workspace.slug, doc.type, doc.slug));
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
if (next === framePath) remountPreview();
|
|
514
|
+
setBrowse({ doc: docIdentity, path: next });
|
|
515
|
+
}
|
|
516
|
+
|
|
480
517
|
function choosePreviewSize(size: PreviewSize) {
|
|
481
518
|
setPreviewSize(size);
|
|
482
519
|
persistPreviewSize(size);
|
|
@@ -870,32 +907,7 @@ export function DocEditorPage() {
|
|
|
870
907
|
style={{ ...previewSx.style, flexBasis: `${previewPct}%` }}
|
|
871
908
|
>
|
|
872
909
|
<div {...stylex.props(styles.previewBar)}>
|
|
873
|
-
<div {...stylex.props(styles.
|
|
874
|
-
<Tooltip label={previewLoading ? "Loading preview…" : "Reload preview"}>
|
|
875
|
-
<button
|
|
876
|
-
type="button"
|
|
877
|
-
aria-label={previewLoading ? "Preview loading" : "Reload preview"}
|
|
878
|
-
aria-busy={previewLoading || undefined}
|
|
879
|
-
onClick={remountPreview}
|
|
880
|
-
{...stylex.props(styles.reloadBtn)}
|
|
881
|
-
>
|
|
882
|
-
<span
|
|
883
|
-
{...stylex.props(
|
|
884
|
-
styles.reloadIcon,
|
|
885
|
-
previewLoading && styles.reloadSpinning,
|
|
886
|
-
)}
|
|
887
|
-
>
|
|
888
|
-
<ReloadIcon />
|
|
889
|
-
</span>
|
|
890
|
-
</button>
|
|
891
|
-
</Tooltip>
|
|
892
|
-
<span {...stylex.props(styles.url)} title={previewUrl ?? undefined}>
|
|
893
|
-
{previewUrl
|
|
894
|
-
? previewUrl.replace(/^https?:\/\//, "")
|
|
895
|
-
: !siteUrl
|
|
896
|
-
? "No site URL"
|
|
897
|
-
: "Loading checkout…"}
|
|
898
|
-
</span>
|
|
910
|
+
<div {...stylex.props(styles.previewLead)}>
|
|
899
911
|
{previewLive === "rendered" ? (
|
|
900
912
|
<span {...stylex.props(styles.previewLive)}>Updated</span>
|
|
901
913
|
) : null}
|
|
@@ -916,15 +928,20 @@ export function DocEditorPage() {
|
|
|
916
928
|
</button>
|
|
917
929
|
) : null}
|
|
918
930
|
</div>
|
|
919
|
-
<
|
|
920
|
-
|
|
921
|
-
{
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
{
|
|
927
|
-
|
|
931
|
+
<PreviewAddress
|
|
932
|
+
path={framePath ?? (!siteUrl ? "No site URL" : "Loading checkout…")}
|
|
933
|
+
enabled={previewUrl !== null}
|
|
934
|
+
routes={previewRoutes}
|
|
935
|
+
routesPending={!replica.ready}
|
|
936
|
+
onPath={onPreviewPath}
|
|
937
|
+
onReload={remountPreview}
|
|
938
|
+
onOpen={() => {
|
|
939
|
+
if (previewUrl) window.open(previewUrl, "_blank", "noopener,noreferrer");
|
|
940
|
+
}}
|
|
941
|
+
/>
|
|
942
|
+
<div {...stylex.props(styles.sizeSwitch)}>
|
|
943
|
+
<PreviewSizeSwitch size={previewSize} onSize={choosePreviewSize} />
|
|
944
|
+
</div>
|
|
928
945
|
</div>
|
|
929
946
|
{previewUrl ? (
|
|
930
947
|
<PreviewViewport size={previewSize} dragging={dragging}>
|
|
@@ -989,7 +1006,7 @@ export function DocEditorPage() {
|
|
|
989
1006
|
<div {...stylex.props(styles.editorColumn, !showPreview && styles.editorColumnSolo)}>
|
|
990
1007
|
<div {...stylex.props(styles.toolbar)}>
|
|
991
1008
|
<div {...stylex.props(styles.meta)}>
|
|
992
|
-
<Text as="h1" size="
|
|
1009
|
+
<Text as="h1" size="sm" weight="medium" truncate>
|
|
993
1010
|
{type}/{slug}
|
|
994
1011
|
</Text>
|
|
995
1012
|
</div>
|
|
@@ -1103,55 +1120,33 @@ export function DocEditorPage() {
|
|
|
1103
1120
|
</Text>
|
|
1104
1121
|
) : (
|
|
1105
1122
|
detailNames.map((name) => {
|
|
1106
|
-
const
|
|
1107
|
-
const composite = kind === "object" || kind === "array";
|
|
1108
|
-
const CustomInput = resolveFieldInput(studio, fieldDefs[name]);
|
|
1123
|
+
const field = fieldDefs[name]!;
|
|
1109
1124
|
return (
|
|
1110
1125
|
<Field key={name} label={fieldLabel(name)}>
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
value={frontmatter[name]}
|
|
1136
|
-
readOnly={aiEditing || parseFailed}
|
|
1137
|
-
onValidChange={(next) => {
|
|
1138
|
-
markEdited();
|
|
1139
|
-
setFrontmatter((prev) => ({ ...prev, [name]: next }));
|
|
1140
|
-
}}
|
|
1141
|
-
/>
|
|
1142
|
-
) : (
|
|
1143
|
-
<Input
|
|
1144
|
-
value={String(frontmatter[name] ?? "")}
|
|
1145
|
-
readOnly={aiEditing || parseFailed}
|
|
1146
|
-
onChange={(e) => {
|
|
1147
|
-
markEdited();
|
|
1148
|
-
setFrontmatter((prev) => ({
|
|
1149
|
-
...prev,
|
|
1150
|
-
[name]: e.target.value,
|
|
1151
|
-
}));
|
|
1152
|
-
}}
|
|
1153
|
-
/>
|
|
1154
|
-
)}
|
|
1126
|
+
<FieldControl
|
|
1127
|
+
name={name}
|
|
1128
|
+
field={field}
|
|
1129
|
+
value={frontmatter[name]}
|
|
1130
|
+
models={models}
|
|
1131
|
+
objects={objects}
|
|
1132
|
+
documentLists={documentLists}
|
|
1133
|
+
readOnly={aiEditing || parseFailed}
|
|
1134
|
+
blocksEditor={({ value, readOnly: blocksReadOnly, onChange: onBlocksChange }) => (
|
|
1135
|
+
<BlocksList
|
|
1136
|
+
blocks={blocksFromFrontmatter(value)}
|
|
1137
|
+
catalog={blocks}
|
|
1138
|
+
models={models}
|
|
1139
|
+
objects={objects}
|
|
1140
|
+
documentLists={documentLists}
|
|
1141
|
+
readOnly={blocksReadOnly}
|
|
1142
|
+
onChange={onBlocksChange}
|
|
1143
|
+
/>
|
|
1144
|
+
)}
|
|
1145
|
+
onChange={(next) => {
|
|
1146
|
+
markEdited();
|
|
1147
|
+
setFrontmatter((prev) => omitField(prev, name, next));
|
|
1148
|
+
}}
|
|
1149
|
+
/>
|
|
1155
1150
|
</Field>
|
|
1156
1151
|
);
|
|
1157
1152
|
})
|
|
@@ -1160,6 +1155,9 @@ export function DocEditorPage() {
|
|
|
1160
1155
|
<BlocksList
|
|
1161
1156
|
blocks={blocksFromFrontmatter(frontmatter[blocksField])}
|
|
1162
1157
|
catalog={blocks}
|
|
1158
|
+
models={models}
|
|
1159
|
+
objects={objects}
|
|
1160
|
+
documentLists={documentLists}
|
|
1163
1161
|
readOnly={aiEditing || parseFailed}
|
|
1164
1162
|
focusBlock={blockFocus}
|
|
1165
1163
|
onChange={(next) => {
|
|
@@ -1171,6 +1169,9 @@ export function DocEditorPage() {
|
|
|
1171
1169
|
<BodyField
|
|
1172
1170
|
value={body}
|
|
1173
1171
|
catalog={richtext}
|
|
1172
|
+
models={models}
|
|
1173
|
+
objects={objects}
|
|
1174
|
+
documentLists={documentLists}
|
|
1174
1175
|
readOnly={aiEditing || parseFailed}
|
|
1175
1176
|
onChange={(value) => {
|
|
1176
1177
|
markEdited();
|
|
@@ -1235,74 +1236,34 @@ const styles = stylex.create({
|
|
|
1235
1236
|
flexShrink: 0,
|
|
1236
1237
|
flexDirection: "column",
|
|
1237
1238
|
overflow: "hidden",
|
|
1238
|
-
backgroundColor: colors.
|
|
1239
|
+
backgroundColor: colors.bgApp,
|
|
1239
1240
|
},
|
|
1240
1241
|
previewBar: {
|
|
1241
|
-
display: "
|
|
1242
|
-
|
|
1242
|
+
display: "grid",
|
|
1243
|
+
gridTemplateColumns: "1fr minmax(0, 520px) 1fr",
|
|
1243
1244
|
alignItems: "center",
|
|
1244
|
-
|
|
1245
|
+
flexShrink: 0,
|
|
1245
1246
|
gap: space.md,
|
|
1247
|
+
height: "44px",
|
|
1248
|
+
boxSizing: "border-box",
|
|
1246
1249
|
paddingInline: space.md,
|
|
1247
|
-
paddingBlock: space.sm,
|
|
1248
1250
|
borderBottomWidth: 1,
|
|
1249
1251
|
borderBottomStyle: "solid",
|
|
1250
1252
|
borderBottomColor: colors.border,
|
|
1253
|
+
backgroundColor: colors.bgSurface,
|
|
1251
1254
|
fontSize: type.xs,
|
|
1252
1255
|
color: colors.textMuted,
|
|
1253
1256
|
},
|
|
1254
|
-
|
|
1257
|
+
previewLead: {
|
|
1255
1258
|
display: "flex",
|
|
1256
|
-
minWidth: 0,
|
|
1257
|
-
flex: 1,
|
|
1258
1259
|
alignItems: "center",
|
|
1259
1260
|
gap: space.sm,
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
display: "inline-flex",
|
|
1263
|
-
flexShrink: 0,
|
|
1264
|
-
alignItems: "center",
|
|
1265
|
-
justifyContent: "center",
|
|
1266
|
-
width: 22,
|
|
1267
|
-
height: 22,
|
|
1268
|
-
padding: 0,
|
|
1269
|
-
borderWidth: 0,
|
|
1270
|
-
borderRadius: radius.sm,
|
|
1271
|
-
backgroundColor: "transparent",
|
|
1272
|
-
color: colors.textMuted,
|
|
1273
|
-
cursor: "pointer",
|
|
1274
|
-
touchAction: "manipulation",
|
|
1275
|
-
[hover]: {
|
|
1276
|
-
":hover": {
|
|
1277
|
-
backgroundColor: colors.bgHover,
|
|
1278
|
-
color: colors.text,
|
|
1279
|
-
},
|
|
1280
|
-
},
|
|
1281
|
-
":focus-visible": {
|
|
1282
|
-
outlineWidth: 2,
|
|
1283
|
-
outlineStyle: "solid",
|
|
1284
|
-
outlineColor: colors.focus,
|
|
1285
|
-
outlineOffset: 1,
|
|
1286
|
-
},
|
|
1287
|
-
},
|
|
1288
|
-
reloadIcon: {
|
|
1289
|
-
display: "inline-flex",
|
|
1290
|
-
},
|
|
1291
|
-
reloadSpinning: {
|
|
1292
|
-
animationName: spin,
|
|
1293
|
-
animationDuration: "700ms",
|
|
1294
|
-
animationTimingFunction: "linear",
|
|
1295
|
-
animationIterationCount: "infinite",
|
|
1296
|
-
"@media (prefers-reduced-motion: reduce)": {
|
|
1297
|
-
animationName: "none",
|
|
1298
|
-
animationDuration: "0s",
|
|
1299
|
-
},
|
|
1300
|
-
},
|
|
1301
|
-
url: {
|
|
1261
|
+
minWidth: 0,
|
|
1262
|
+
justifySelf: "start",
|
|
1302
1263
|
overflow: "hidden",
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1264
|
+
},
|
|
1265
|
+
sizeSwitch: {
|
|
1266
|
+
justifySelf: "end",
|
|
1306
1267
|
},
|
|
1307
1268
|
previewLive: {
|
|
1308
1269
|
flexShrink: 0,
|
|
@@ -1315,28 +1276,21 @@ const styles = stylex.create({
|
|
|
1315
1276
|
editPage: {
|
|
1316
1277
|
flexShrink: 0,
|
|
1317
1278
|
borderWidth: 0,
|
|
1318
|
-
borderRadius:
|
|
1279
|
+
borderRadius: radius.sm,
|
|
1319
1280
|
backgroundColor: colors.bgHover,
|
|
1320
1281
|
color: colors.text,
|
|
1321
1282
|
cursor: "pointer",
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
},
|
|
1326
|
-
badge: {
|
|
1327
|
-
flexShrink: 0,
|
|
1328
|
-
borderWidth: 1,
|
|
1329
|
-
borderStyle: "solid",
|
|
1330
|
-
borderColor: colors.border,
|
|
1331
|
-
borderRadius: 4,
|
|
1283
|
+
font: "inherit",
|
|
1284
|
+
fontSize: type.xs,
|
|
1285
|
+
fontWeight: 500,
|
|
1332
1286
|
paddingInline: space.sm,
|
|
1333
|
-
paddingBlock:
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1287
|
+
paddingBlock: "2px",
|
|
1288
|
+
":focus-visible": {
|
|
1289
|
+
outlineWidth: 2,
|
|
1290
|
+
outlineStyle: "solid",
|
|
1291
|
+
outlineColor: colors.focus,
|
|
1292
|
+
outlineOffset: 1,
|
|
1293
|
+
},
|
|
1340
1294
|
},
|
|
1341
1295
|
conflictBanner: {
|
|
1342
1296
|
display: "flex",
|
|
@@ -1459,22 +1413,23 @@ const styles = stylex.create({
|
|
|
1459
1413
|
toolbar: {
|
|
1460
1414
|
display: "flex",
|
|
1461
1415
|
flexShrink: 0,
|
|
1462
|
-
flexWrap: "wrap",
|
|
1463
1416
|
alignItems: "center",
|
|
1464
1417
|
justifyContent: "space-between",
|
|
1465
|
-
gap: space.
|
|
1466
|
-
|
|
1467
|
-
|
|
1418
|
+
gap: space.md,
|
|
1419
|
+
height: "44px",
|
|
1420
|
+
boxSizing: "border-box",
|
|
1421
|
+
paddingInline: space.md,
|
|
1468
1422
|
borderBottomWidth: 1,
|
|
1469
1423
|
borderBottomStyle: "solid",
|
|
1470
1424
|
borderBottomColor: colors.border,
|
|
1425
|
+
backgroundColor: colors.bgSurface,
|
|
1471
1426
|
},
|
|
1472
1427
|
meta: {
|
|
1473
1428
|
minWidth: 0,
|
|
1474
1429
|
},
|
|
1475
1430
|
actions: {
|
|
1476
1431
|
display: "flex",
|
|
1477
|
-
|
|
1432
|
+
flexShrink: 0,
|
|
1478
1433
|
gap: space.sm,
|
|
1479
1434
|
},
|
|
1480
1435
|
formWrap: {
|