@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/dashboard.js CHANGED
@@ -1,5 +1,5 @@
1
- import { A as a, i as s } from "./chunks/dashboard-DCHRI0WD.js";
2
- import { w as t, Q as f } from "./chunks/status-bar-action-wj1KZ51m.js";
1
+ import { A as a, i as s } from "./chunks/dashboard-bNp6AbKE.js";
2
+ import { w as t, Q as f } from "./chunks/status-bar-action-C0fsAWvD.js";
3
3
  export {
4
4
  a as DashboardApp,
5
5
  t as configureStudio,
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { jsx as r, jsxs as l } from "react/jsx-runtime";
2
2
  import { useLayoutEffect as I, useEffect as u, useRef as C, useState as S } from "react";
3
- import { i as L, T, E as N, C as M, z, A as D, D as O, F as g, H as x, I as v, L as _, M as A, N as B, O as F, w as P, Q as w, R as V, U as j, f as q, V as G, W as m, X as b } from "./chunks/status-bar-action-wj1KZ51m.js";
4
- import { Y as Se } from "./chunks/status-bar-action-wj1KZ51m.js";
5
- import { f as H, s as W, g as $, R as K, h as X, i as Y, L as Q, w as J, T as E, r as Z } from "./chunks/WorkspaceRoutes-DXzdWqN3.js";
3
+ import { i as L, T, E as N, C as M, z, A as D, D as O, F as g, H as x, I as v, L as _, M as A, N as B, O as F, w as P, Q as w, R as V, U as j, f as q, V as G, W as m, X as b } from "./chunks/status-bar-action-C0fsAWvD.js";
4
+ import { Y as Se } from "./chunks/status-bar-action-C0fsAWvD.js";
5
+ import { f as H, s as W, g as $, R as K, h as X, i as Y, L as Q, w as J, T as E, r as Z } from "./chunks/WorkspaceRoutes-DVpUOaMV.js";
6
6
  import { u as ee, S as te } from "./chunks/define-studio-BYtYDGLX.js";
7
7
  import { d as Pe } from "./chunks/define-studio-BYtYDGLX.js";
8
- import { E as ne } from "./chunks/EmbedPublishPage-88VsmOhi.js";
8
+ import { E as ne } from "./chunks/EmbedPublishPage-CtIlaeGO.js";
9
9
  const p = {
10
10
  accent: "var(--x11n7hvk)",
11
11
  accentHover: "var(--x1vnpaut)",
@@ -1,7 +1,7 @@
1
1
  import { jsxs as p, Fragment as B, jsx as n } from "react/jsx-runtime";
2
2
  import { useRef as P, useState as k, useEffect as N, useId as V, useLayoutEffect as j } from "react";
3
- import { S as H, m as J, P as K, k as T, l as Q, o as O, b as Y, G as _, q as Z, t as X, u as ee, v as te, w as ne, x as re, p as ae, y as oe, T as ie, E as se, C as le, z as ce, A as ue, D as de, F as D, H as M, I as z, J as F, K as pe, L as fe } from "./chunks/status-bar-action-wj1KZ51m.js";
4
- import { E as he } from "./chunks/EmbedPublishPage-88VsmOhi.js";
3
+ import { S as H, m as J, P as K, k as T, l as Q, o as O, b as Y, G as _, q as Z, t as X, u as ee, v as te, w as ne, x as re, p as ae, y as oe, T as ie, E as se, C as le, z as ce, A as ue, D as de, F as D, H as M, I as z, J as F, K as pe, L as fe } from "./chunks/status-bar-action-C0fsAWvD.js";
4
+ import { E as he } from "./chunks/EmbedPublishPage-CtIlaeGO.js";
5
5
  const I = "backmatter-preview-frame", A = "#d97706";
6
6
  function me() {
7
7
  return /* @__PURE__ */ p("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", "aria-hidden": !0, children: [
package/dist/studio.css CHANGED
@@ -11,6 +11,10 @@
11
11
  inset: 0;
12
12
  }
13
13
 
14
+ .x184nht {
15
+ inset: var(--x1o7ezzp);
16
+ }
17
+
14
18
  .xkdpibf {
15
19
  margin: -1px;
16
20
  }
@@ -23,10 +27,6 @@
23
27
  padding: 0;
24
28
  }
25
29
 
26
- .x1ruevkc {
27
- padding: 6px;
28
- }
29
-
30
30
  .xk7greg {
31
31
  padding: var(--x1ft7ks7);
32
32
  }
@@ -35,10 +35,6 @@
35
35
  padding: var(--x1lzhbes);
36
36
  }
37
37
 
38
- .x12u58kn {
39
- padding: var(--x1o7ezzp);
40
- }
41
-
42
38
  .xue2yr4 {
43
39
  padding: var(--x1uiwg42);
44
40
  }
@@ -65,10 +61,6 @@
65
61
  border-color: #ffffff1a;
66
62
  }
67
63
 
68
- .x1gb98jh {
69
- border-color: #ffffff29;
70
- }
71
-
72
64
  .xe0g8ez {
73
65
  border-color: #ffffffb8;
74
66
  }
@@ -165,6 +157,10 @@
165
157
  border-width: 3px;
166
158
  }
167
159
 
160
+ .x1oeqjk2 {
161
+ flex: 16rem;
162
+ }
163
+
168
164
  .x98rzlu {
169
165
  flex: 1;
170
166
  }
@@ -465,6 +461,10 @@
465
461
  align-items: flex-start;
466
462
  }
467
463
 
464
+ .x7a106z {
465
+ align-items: start;
466
+ }
467
+
468
468
  .x1qjc9v5 {
469
469
  align-items: stretch;
470
470
  }
@@ -537,6 +537,10 @@
537
537
  animation-timing-function: linear;
538
538
  }
539
539
 
540
+ .x1plog1 {
541
+ aspect-ratio: 1;
542
+ }
543
+
540
544
  .x1fx9mx7 {
541
545
  backdrop-filter: blur(28px) saturate(1.15);
542
546
  }
@@ -1022,6 +1026,10 @@
1022
1026
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
1023
1027
  }
1024
1028
 
1029
+ .x10vl0y4 {
1030
+ grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
1031
+ }
1032
+
1025
1033
  .xl56j7k {
1026
1034
  justify-content: center;
1027
1035
  }
@@ -1551,15 +1559,7 @@
1551
1559
  .x1aquc0h.x1aquc0h {
1552
1560
  animation-name: none;
1553
1561
  }
1554
- }
1555
-
1556
- @media (hover: hover) {
1557
- .x1m2avzc.x1m2avzc {
1558
- background-color: #ffffff29;
1559
- }
1560
- }
1561
1562
 
1562
- @media (prefers-reduced-motion: reduce) {
1563
1563
  .xphioz4.xphioz4 {
1564
1564
  background-image: none;
1565
1565
  }
@@ -1701,10 +1701,6 @@
1701
1701
  border-right-style: solid;
1702
1702
  }
1703
1703
 
1704
- .xgfja2r {
1705
- border-right-width: 0;
1706
- }
1707
-
1708
1704
  .xs1s249 {
1709
1705
  border-right-width: 1px;
1710
1706
  }
@@ -2093,6 +2089,10 @@
2093
2089
  min-height: 32px;
2094
2090
  }
2095
2091
 
2092
+ .xu0aao5 {
2093
+ min-height: 36px;
2094
+ }
2095
+
2096
2096
  .x1gg8mnh {
2097
2097
  min-height: 44px;
2098
2098
  }
@@ -2133,6 +2133,10 @@
2133
2133
  min-width: 200px;
2134
2134
  }
2135
2135
 
2136
+ .x1f4i7yj {
2137
+ min-width: 252px;
2138
+ }
2139
+
2136
2140
  .x18n5i07 {
2137
2141
  min-width: 300px;
2138
2142
  }
@@ -2289,10 +2293,6 @@
2289
2293
  right: var(--x1lzhbes);
2290
2294
  }
2291
2295
 
2292
- .x1swmuje {
2293
- right: var(--xvc7yhn);
2294
- }
2295
-
2296
2296
  .x13vifvy {
2297
2297
  top: 0;
2298
2298
  }
@@ -2325,10 +2325,6 @@
2325
2325
  top: var(--x1y1rrep);
2326
2326
  }
2327
2327
 
2328
- .x1s7yh1o {
2329
- top: var(--xvc7yhn);
2330
- }
2331
-
2332
2328
  .xh8yej3 {
2333
2329
  width: 100%;
2334
2330
  }
@@ -2369,6 +2365,10 @@
2369
2365
  width: 22px;
2370
2366
  }
2371
2367
 
2368
+ .xafpxmx {
2369
+ width: 240px;
2370
+ }
2371
+
2372
2372
  .xvy4d1p {
2373
2373
  width: 24px;
2374
2374
  }
@@ -2445,6 +2445,10 @@
2445
2445
  width: auto;
2446
2446
  }
2447
2447
 
2448
+ .x12pdk5b {
2449
+ width: calc(min(360px, 38vw) - 48px);
2450
+ }
2451
+
2448
2452
  .x3bfboh {
2449
2453
  width: min(360px, 38vw);
2450
2454
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backmatter/studio",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "The Backmatter editing surface: document editor, AI chat, publish. Mounted on your site or hosted on the dashboard.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -52,7 +52,7 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "@ai-sdk/react": "^4.0.100",
55
- "@backmatter/core": "^0.0.24",
55
+ "@backmatter/core": "^0.0.25",
56
56
  "@base-ui/react": "^1.6.0",
57
57
  "@central-icons-react/round-outlined-radius-2-stroke-1.5": "1.2.15",
58
58
  "@dnd-kit/abstract": "^0.5.0",
@@ -1,5 +1,5 @@
1
1
  // packages/studio/src/chrome/AppShell.tsx
2
- import { useEffect } from "react";
2
+ import { useEffect, useState } from "react";
3
3
  import { useLocation, useSearchParams } from "react-router";
4
4
  import * as stylex from "@stylexjs/stylex";
5
5
  import { ChatBar } from "../chat/ChatBar";
@@ -9,12 +9,13 @@ import { colors } from "../styles/tokens.stylex";
9
9
  import { TooltipProvider } from "../ui/Tooltip";
10
10
  import { cmsWorkspaceSlug, isOrgPickerPath } from "../workspace-path";
11
11
  import { AppSidebar } from "./AppSidebar";
12
+ import { WorkspaceRail } from "./ContentExplorerSidebar";
12
13
  import { CommandPalette } from "./CommandPalette";
13
14
  import { FloatingUserMenu } from "./UserMenu";
14
15
  import { EditorActionsProvider } from "./EditorActionsContext";
15
16
  import { EditorFocusProvider } from "./EditorFocusContext";
16
17
  import { EditorStatusProvider } from "./EditorStatusContext";
17
- import { WorkspaceNavProvider } from "./WorkspaceNavContext";
18
+ import { WorkspaceNavProvider, useWorkspaceNav } from "./WorkspaceNavContext";
18
19
  import { installParentChatHotkey } from "./hotkeys";
19
20
  import { WorkspaceStatusBar } from "./WorkspaceStatusBar";
20
21
 
@@ -40,28 +41,43 @@ function AppShellInner({ children }: { children: React.ReactNode }) {
40
41
  // Mount from the URL, not from nav. Waiting on nav remounts this tree when
41
42
  // WorkspaceLayout publishes (and later clears) nav, which loops loading.
42
43
  const workspaceKey = cmsWorkspaceSlug(location.pathname);
44
+ const workspaceNav = useWorkspaceNav();
43
45
  const orgPicker = isOrgPickerPath(location.pathname);
44
46
  const embed = searchParams.get("embed") === "1";
47
+ const [treeHost, setTreeHost] = useState<HTMLDivElement | null>(null);
48
+ const inWorkspace = Boolean(workspaceKey && !embed && !orgPicker);
45
49
 
46
50
  useEffect(() => {
47
51
  if (!embed) return;
48
52
  return installParentChatHotkey();
49
53
  }, [embed]);
50
54
 
55
+ const chat =
56
+ workspaceKey && !embed ? (
57
+ <ChatSessionScope>
58
+ <ChatBar />
59
+ <ChatPanel />
60
+ </ChatSessionScope>
61
+ ) : null;
62
+
51
63
  const shell = (
52
64
  <div {...stylex.props(styles.shell)}>
53
65
  {workspaceKey && !embed ? <WorkspaceStatusBar workspaceId={workspaceKey} /> : null}
54
66
  <div {...stylex.props(styles.body)}>
55
- {orgPicker || embed ? null : <AppSidebar />}
56
- <main {...stylex.props(styles.main)}>{children}</main>
67
+ {orgPicker || embed ? null : inWorkspace ? (
68
+ <WorkspaceRail workspace={workspaceNav} treeHost={treeHost} />
69
+ ) : (
70
+ <AppSidebar />
71
+ )}
72
+ <div {...stylex.props(styles.stage)}>
73
+ <div {...stylex.props(styles.stageBody)}>
74
+ <div ref={setTreeHost} {...stylex.props(styles.treeHost)} />
75
+ <main {...stylex.props(styles.main)}>{children}</main>
76
+ </div>
77
+ {chat}
78
+ </div>
57
79
  </div>
58
80
  {orgPicker ? <FloatingUserMenu /> : null}
59
- {workspaceKey && !embed ? (
60
- <ChatSessionScope>
61
- <ChatBar />
62
- <ChatPanel />
63
- </ChatSessionScope>
64
- ) : null}
65
81
  {embed ? null : <CommandPalette />}
66
82
  </div>
67
83
  );
@@ -89,6 +105,27 @@ const styles = stylex.create({
89
105
  flex: 1,
90
106
  overflow: "hidden",
91
107
  },
108
+ stage: {
109
+ display: "flex",
110
+ minWidth: 0,
111
+ minHeight: 0,
112
+ flex: 1,
113
+ flexDirection: "column",
114
+ overflow: "hidden",
115
+ },
116
+ stageBody: {
117
+ display: "flex",
118
+ minWidth: 0,
119
+ minHeight: 0,
120
+ flex: 1,
121
+ overflow: "hidden",
122
+ },
123
+ treeHost: {
124
+ display: "flex",
125
+ minWidth: 0,
126
+ minHeight: 0,
127
+ flexShrink: 0,
128
+ },
92
129
  main: {
93
130
  display: "flex",
94
131
  minWidth: 0,
@@ -1,30 +1,18 @@
1
1
  // packages/studio/src/chrome/AppSidebar.tsx
2
- import { useLocation } from "react-router";
3
2
  import * as stylex from "@stylexjs/stylex";
4
3
  import { useReplicaState } from "../replica/useReplica";
5
4
  import { colors, space, type } from "../styles/tokens.stylex";
6
- import { useWorkspaceNav } from "./WorkspaceNavContext";
7
5
  import { NavItem } from "./NavItem";
8
6
  import { UserMenu } from "./UserMenu";
9
- import { cmsWorkspaceSlug, isWorkspaceMediaPath, workspaceHomePath } from "../workspace-path";
7
+ import { workspaceHomePath } from "../workspace-path";
10
8
  import { DocIcon } from "./icons";
11
- import { ContentExplorerSidebar } from "./ContentExplorerSidebar";
12
- export function AppSidebar() {
13
- const location = useLocation();
14
- const workspaceNav = useWorkspaceNav();
15
- const inWorkspace = Boolean(cmsWorkspaceSlug(location.pathname));
16
- const railOnly = inWorkspace && isWorkspaceMediaPath(location.pathname);
17
9
 
10
+ /** Workspace list. Inside a workspace the explorer frame owns the rail. */
11
+ export function AppSidebar() {
18
12
  return (
19
- <aside {...stylex.props(styles.aside, railOnly && styles.asideRail)}>
20
- {inWorkspace && workspaceNav ? (
21
- <div {...stylex.props(styles.workspaceNav)}>
22
- <ContentExplorerSidebar workspace={workspaceNav} />
23
- </div>
24
- ) : (
25
- <WorkspaceListNav />
26
- )}
27
- <SidebarFooter compact={railOnly} />
13
+ <aside {...stylex.props(styles.aside)}>
14
+ <WorkspaceListNav />
15
+ <SidebarFooter />
28
16
  </aside>
29
17
  );
30
18
  }
@@ -68,21 +56,15 @@ function SectionLabel({ children }: { children: React.ReactNode }) {
68
56
  return <p {...stylex.props(styles.section)}>{children}</p>;
69
57
  }
70
58
 
71
- function SidebarFooter({ compact = false }: { compact?: boolean }) {
59
+ function SidebarFooter() {
72
60
  return (
73
- <div {...stylex.props(styles.footer, compact && styles.footerCompact)}>
74
- <UserMenu compact={compact} />
61
+ <div {...stylex.props(styles.footer)}>
62
+ <UserMenu />
75
63
  </div>
76
64
  );
77
65
  }
78
66
 
79
67
  const styles = stylex.create({
80
- workspaceNav: {
81
- display: "flex",
82
- minHeight: 0,
83
- flex: 1,
84
- flexDirection: "column",
85
- },
86
68
  aside: {
87
69
  display: "flex",
88
70
  height: "100%",
@@ -95,10 +77,6 @@ const styles = stylex.create({
95
77
  borderRightColor: colors.border,
96
78
  backgroundColor: colors.bgSurface,
97
79
  },
98
- asideRail: {
99
- width: "48px",
100
- minWidth: "48px",
101
- },
102
80
  brand: {
103
81
  flexShrink: 0,
104
82
  borderBottomWidth: 1,
@@ -174,7 +152,4 @@ const styles = stylex.create({
174
152
  borderTopColor: colors.border,
175
153
  padding: space.md,
176
154
  },
177
- footerCompact: {
178
- padding: space.sm,
179
- },
180
155
  });