@cosmicdrift/kumiko-renderer-web 0.168.0 → 0.170.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-renderer-web",
3
- "version": "0.168.0",
3
+ "version": "0.170.0",
4
4
  "description": "Web-platform bindings for @cosmicdrift/kumiko-renderer. HTML default-primitives, browser history-based navigation, EventSource-backed live events, and a one-call createKumikoApp that mounts the whole stack via react-dom.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -16,9 +16,9 @@
16
16
  "./styles.css": "./src/styles.css"
17
17
  },
18
18
  "dependencies": {
19
- "@cosmicdrift/kumiko-dispatcher-live": "0.168.0",
20
- "@cosmicdrift/kumiko-headless": "0.168.0",
21
- "@cosmicdrift/kumiko-renderer": "0.168.0",
19
+ "@cosmicdrift/kumiko-dispatcher-live": "0.170.0",
20
+ "@cosmicdrift/kumiko-headless": "0.170.0",
21
+ "@cosmicdrift/kumiko-renderer": "0.170.0",
22
22
  "@radix-ui/react-dialog": "^1.1.15",
23
23
  "@radix-ui/react-dropdown-menu": "^2.1.16",
24
24
  "@radix-ui/react-label": "^2.1.8",
@@ -421,6 +421,28 @@ describe("WorkspaceShell", () => {
421
421
  expect(screen.queryByText("Orders")).toBeNull();
422
422
  expect(screen.queryByText("Tours")).toBeNull();
423
423
  });
424
+
425
+ test("fill=true applies h-svh on root and min-h-0 on inset/main", () => {
426
+ renderShell(
427
+ <WorkspaceShell
428
+ brand={<div>Brand</div>}
429
+ schema={schema}
430
+ user={{ id: "u1", roles: ["admin"] }}
431
+ fill
432
+ >
433
+ <div>content</div>
434
+ </WorkspaceShell>,
435
+ );
436
+ const root = document.querySelector('[data-slot="sidebar-wrapper"]');
437
+ expect(root?.classList.contains("h-svh")).toBe(true);
438
+ const inset = document.querySelector('[data-slot="sidebar-inset"]');
439
+ expect(inset?.classList.contains("min-h-0")).toBe(true);
440
+ const mains = screen.getAllByRole("main");
441
+ const innerMain = mains.find((m) => m !== inset);
442
+ expect(innerMain?.classList.contains("min-h-0")).toBe(true);
443
+ expect(innerMain?.classList.contains("flex-1")).toBe(true);
444
+ expect(innerMain?.classList.contains("overflow-auto")).toBe(true);
445
+ });
424
446
  });
425
447
 
426
448
  // ---------------------------------------------------------------------------
@@ -77,6 +77,9 @@ export type WorkspaceShellProps = {
77
77
  readonly sidebarFooter?: ReactNode;
78
78
  /** Runtime badge slot per nav leaf (bare nav id), same as DefaultAppShell. */
79
79
  readonly navBadges?: ReadonlyMap<string, ReactNode>;
80
+ /** Viewport-fit shell. true → fixed viewport height (`h-svh`), content
81
+ * scrolls INSIDE instead of the whole page. Default false (page scroll). */
82
+ readonly fill?: boolean;
80
83
  /** Screen content. */
81
84
  readonly children: ReactNode;
82
85
  };
@@ -89,6 +92,7 @@ export function WorkspaceShell({
89
92
  initialWorkspaceId,
90
93
  sidebarFooter,
91
94
  navBadges,
95
+ fill,
92
96
  children,
93
97
  }: WorkspaceShellProps): ReactNode {
94
98
  const app = useMemo(() => toAppSchema(schema), [schema]);
@@ -220,7 +224,7 @@ export function WorkspaceShell({
220
224
  // Content. topbarActions landen rechts in der Header-Zeile statt in einer
221
225
  // separaten Topbar — eine Kopfzeile statt zwei.
222
226
  return (
223
- <SidebarProvider>
227
+ <SidebarProvider {...(fill === true && { className: "h-svh" })}>
224
228
  <Sidebar collapsible="icon">
225
229
  <SidebarHeader data-kumiko-layout="sidebar-header">
226
230
  {brand}
@@ -232,13 +236,13 @@ export function WorkspaceShell({
232
236
  )}
233
237
  <SidebarRail />
234
238
  </Sidebar>
235
- <SidebarInset>
239
+ <SidebarInset className={fill === true ? "min-h-0" : undefined}>
236
240
  <ShellHeader
237
241
  schema={app}
238
242
  {...(user !== undefined && { user })}
239
243
  {...(topbarActions !== undefined && { headerActions: topbarActions })}
240
244
  />
241
- <main className="flex-1 overflow-auto">
245
+ <main className={fill === true ? "min-h-0 flex-1 overflow-auto" : "flex-1 overflow-auto"}>
242
246
  {activeTarget !== undefined ? (
243
247
  <EditorPanel resolvers={resolvers} />
244
248
  ) : (