@timbal-ai/timbal-react 1.3.0 → 1.4.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/CHANGELOG.md CHANGED
@@ -4,6 +4,24 @@ All notable changes to `@timbal-ai/timbal-react` are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.4.0] — 2026-06-05
8
+
9
+ ### Added
10
+
11
+ - **`AppShell contentFill`** — makes the content region a bounded, non-scrolling flex column instead of the default padded scroll area. For full-bleed pages that own their own scroll (a full-page chat, a canvas, an editor, a split master–detail view): a `h-full` / `flex-1 min-h-0` child now fills exactly and a pinned footer (the chat composer) stays put instead of riding down on scroll. No `mainClassName` surgery and no `h-[calc(100dvh-…)]` guesses required.
12
+ - **`Page fill`** — makes a `Page` a `min-h-0 flex-1` flex column (pair with `AppShell contentFill` for full-height content). Give the fill child `min-h-0 flex-1`.
13
+ - **Headerless `Page`** — `Page.title` (and `PageHeader.title`) is now optional. Omit it to render a page with no `<h1>` header row (and no header padding), instead of dropping `Page` entirely to lose a heading.
14
+ - **New layout recipes** (`examples/app-kit/src/recipes/`): **full-page chat** (`contentFill` + headerless `fill` + `TimbalChat`), **split view** (master–detail two-pane), and **bento dashboard** (asymmetric `SurfaceCard`/`ChartPanel`/`StatTile` grid) — surfaced in the Blocks gallery and `APP_KIT_AGENT_INSTRUCTIONS` as distinct layout archetypes so generated UIs vary beyond the single sidebar+topbar+MetricRow+table shape.
15
+
16
+ ### Changed
17
+
18
+ - **`AppShell` `main` is now a bounded flex column by default** (`flex min-h-0 flex-col`, keeping `pb-8 md:pb-10`). Previously the content `main` was content-sized, so every full-height child had to pass `mainClassName="flex min-h-0 flex-col"` to undo a layout deficiency; `h-full` / `flex-1` children now resolve a height out of the box. Scrolling `Page` content is unaffected (the outer scroll region still scrolls).
19
+ - **`APP_KIT_AGENT_INSTRUCTIONS`** documents a **Layout archetypes** menu (sidebar dashboard, focused, bento overview, split master–detail, full-page chat/canvas, copilot overlay, section-switcher) and the full-height contract (`contentFill` / `fill` / headerless `Page`), steering codegen away from shipping the same layout every time and away from `h-[calc(100dvh-…)]` / `min-h-[…]` sizing hacks.
20
+
21
+ ### Fixed
22
+
23
+ - **`FieldSwitch` / `FieldSelect` id collision** — these derived their input id from `id ?? name ?? "switch"`, so multiple unlabeled instances all rendered `id="switch"` and toggling one flipped the others (and labels mis-associated). They now fall back to a `useId()`-generated id, so every instance is unique by default. `FieldInput` / `FieldTextarea` get the same `useId()` fallback (fixes silent label/control mis-association when no `name` is set).
24
+
7
25
  ## [1.3.0] — 2026-06-04
8
26
 
9
27
  ### Added
package/README.md CHANGED
@@ -356,6 +356,16 @@ function MyShell() {
356
356
 
357
357
  For a fully custom shell, drive your own offset from `StudioSidebar`'s `onInsetChange` callback, which fires with the live inset width (px) whenever the collapse state changes.
358
358
 
359
+ The `AppShell` content region is a padded scroll area by default. For a **full-bleed page that fills the viewport** (a full-page chat, a canvas, an editor, a split master–detail view), pass `contentFill` to `AppShell` and `fill` to `Page` (omit `Page.title` for a headerless page), then give the filling child `min-h-0 flex-1` — the composer / footer stays pinned and you avoid `h-[calc(100dvh-…)]` guesses:
360
+
361
+ ```tsx
362
+ <AppShell contentFill>
363
+ <Page fill>
364
+ <TimbalChat workforceId="…" className="min-h-0 flex-1" />
365
+ </Page>
366
+ </AppShell>
367
+ ```
368
+
359
369
  ### Drop-in shell (header + agent picker)
360
370
 
361
371
  `TimbalChatShell` wraps the common blueprint layout: brand area, workforce selector, optional header actions, and a full-height chat. When `workforceId` is omitted, it fetches `{baseUrl}/workforce` and selects the first agent automatically:
package/dist/app.cjs CHANGED
@@ -336,6 +336,40 @@ You are **not** required to copy any example layout, page title, section order,
336
336
 
337
337
  When in doubt: compose from the **component menu** + **guidelines**, then adapt creatively to the request.
338
338
 
339
+ ### Layout archetypes \u2014 pick the shape that fits (don't default to one)
340
+
341
+ The most common failure is shipping the **same** layout every time: sidebar + topbar + \`Page\` + one \`MetricRow\` + one full-width \`DataTable\`. That is *one* archetype, not *the* layout. Choose deliberately \u2014 different domains want different shapes, and varying the shell/page composition is encouraged.
342
+
343
+ | Archetype | When | Compose |
344
+ |-----------|------|---------|
345
+ | **Sidebar dashboard** | Multi-section product (CRM, billing, ops) with nav | \`StudioSidebar\` in \`AppShell.sidebar\` + \`Page\` \u2192 \`Section\` |
346
+ | **Focused / no-chrome** | A single tool or one-screen utility | \`AppShell\` (no sidebar) + \`Page\` (optionally just \`AppShellTopbar\`); or a centered narrow column |
347
+ | **Bento overview** | Home / at-a-glance dashboards | \`Page\` + an **asymmetric grid** of \`SurfaceCard\` / \`ChartPanel\` / \`StatTile\` spanning different widths (not a uniform row + table) |
348
+ | **Split master\u2013detail** | Inbox, triage queue, record browser, log explorer | \`AppShell contentFill\` + \`Page fill\` + a two-column flex row, each pane \`min-h-0 overflow-y-auto\` |
349
+ | **Full-page chat / canvas** | Chat-first app, editor, map, single full-bleed surface | \`AppShell contentFill\` + headerless \`Page fill\` + a \`min-h-0 flex-1\` child (e.g. \`TimbalChat\`) |
350
+ | **Copilot overlay** | A data app that also wants an assistant | any of the above + \`AppShell chat={<AppChatPanel />}\` (floating, never a second column) |
351
+ | **Section-switcher** | One page, several views | \`SubNav\` / \`PillSegmentedTabs\` (\`trackVariant="flush"\`) switching panels with state/router |
352
+
353
+ Mix them: vary the grid columns, density, header placement (\`Page\` actions vs. a global \`AppShellTopbar\`), and whether there's a sidebar at all. Two dashboards for two domains should not look identical.
354
+
355
+ ### Full-height pages (chat, canvas, split views)
356
+
357
+ The content region is a **padded scroll area** by default \u2014 great for stacked \`Page\` \u2192 \`Section\` content, wrong for a surface that must fill the viewport. For full-bleed pages:
358
+
359
+ - Pass **\`contentFill\`** to \`AppShell\` \u2192 the content region becomes a bounded, non-scrolling flex column (clipped, no bottom padding).
360
+ - Pass **\`fill\`** to \`Page\` \u2192 the page becomes a \`min-h-0 flex-1\` flex column.
361
+ - Give the filling child **\`min-h-0 flex-1\`** (or \`h-full\`) so its own scroll/footer resolves \u2014 e.g. \`<TimbalChat className="min-h-0 flex-1" />\`, or a two-pane row where each pane is \`min-h-0 overflow-y-auto\`.
362
+
363
+ \`\`\`tsx
364
+ <AppShell contentFill topbar={<AppShellTopbar actions={<ModeToggle />} />}>
365
+ <Page fill> {/* headerless: omit title */}
366
+ <TimbalChat workforceId="\u2026" className="min-h-0 flex-1" />
367
+ </Page>
368
+ </AppShell>
369
+ \`\`\`
370
+
371
+ **Don't** size full-height content with \`h-[calc(100dvh-\u2026)]\` (guesses chrome height \u2192 spurious scrollbar) or \`min-h-[\u2026]\` (free-growing floor \u2192 a pinned footer like the chat composer rides down on scroll). Let \`contentFill\` + \`fill\` provide the bounded height. \`Page\` with no \`title\` renders **no header** \u2014 you don't need to abandon \`Page\` to drop a heading.
372
+
339
373
  ### Module layout (source folders)
340
374
 
341
375
  Presentational groups \u2014 import from the package root, not from these paths:
@@ -394,12 +428,12 @@ The cause of slop is dropping **below** the curated block layer into raw primiti
394
428
 
395
429
  | Component | Use for |
396
430
  |-----------|---------|
397
- | \`AppShell\` | Shell: optional \`sidebar\`, \`topbar\`, main \`children\`, optional floating \`chat\`. Props: \`chatTriggerLabel\`, \`chatCollapsible\`, \`chatWidth\`, \`chatHeight\`, controlled \`chatOpen\`. |
431
+ | \`AppShell\` | Shell: optional \`sidebar\`, \`topbar\`, main \`children\`, optional floating \`chat\`. Props: \`chatTriggerLabel\`, \`chatCollapsible\`, \`chatWidth\`, \`chatHeight\`, controlled \`chatOpen\`, **\`contentFill\`** (bounded non-scrolling content region for full-bleed pages \u2014 chat/canvas/split view). |
398
432
  | \`AppShellTopbar\` | Full-width top bar: \`start\`, \`actions\` slots. |
399
433
  | \`AppCopilotProvider\` | React context for copilot-aware tools (page, filters, selection, etc.). |
400
434
  | \`AppChatPanel\` | Floating thread: \`workforceId\`, \`welcome\`, \`debug\`. |
401
435
  | \`useAppShellChat\` | Custom open/close trigger when \`hideChatTrigger\` on shell. |
402
- | \`Page\` | Page title, description, \`breadcrumbs\`, \`actions\`, \`density\` (\`"default"\` | \`"compact"\`), children. |
436
+ | \`Page\` | Page title, description, \`breadcrumbs\`, \`actions\`, \`density\` (\`"default"\` | \`"compact"\`), children. **\`title\` is optional** \u2014 omit it for a headerless page (no \`<h1>\`). **\`fill\`** makes it a \`min-h-0 flex-1\` column for full-height content (pair with \`AppShell contentFill\`). |
403
437
  | \`Section\` | Titled block inside a page. Optional \`density\` overrides inherited page density. |
404
438
  | \`SubNav\` | **Section switcher** (Overview / Reports pill bar): \`items\`, \`activeId\`, \`onChange\`. Never use Radix/shadcn \`Tabs\` \u2014 it is not in this package. Switch panels with state or the router. |
405
439
  | **Menus** | **Select** = short list, no search. **Combobox** = searchable (same trigger as Select). **Command** only inside \`PopoverContent variant="list"\` or Combobox \u2014 never padded default Popover. See \`examples/app-kit/src/recipes/primitives-catalog.ts\`. |
@@ -492,8 +526,11 @@ Ready-made **section patterns** assembled from the components above. Each is a c
492
526
  - **Empty states** \u2014 no-data / no-results / first-run. Compose \`EmptyState\` + \`Card\` + \`Button\`.
493
527
  - **Sign-in card** \u2014 centered auth entry. Compose \`Card\` + \`Input\` + \`Label\` + \`Button\`.
494
528
 
495
- **Shells & theming**
529
+ **Shells & layouts**
496
530
  - **Minimal shell** \u2014 \`AppShell\` + \`Page\` (no sidebar/chat).
531
+ - **Bento dashboard** \u2014 \`Page\` + an asymmetric grid of \`SurfaceCard\` / \`ChartPanel\` / \`StatTile\` (varied spans) for overview/home screens.
532
+ - **Split view** \u2014 master\u2013detail: \`AppShell contentFill\` + \`Page fill\` + a two-pane flex row (list + detail), each pane \`min-h-0 overflow-y-auto\`.
533
+ - **Full-page chat** \u2014 \`AppShell contentFill\` + headerless \`Page fill\` + \`TimbalChat className="min-h-0 flex-1"\` (composer pinned; no \`h-[calc(...)]\`).
497
534
  - **Copilot overlay** \u2014 \`AppShell\` + floating \`AppChatPanel\`.
498
535
  - **Theme presets** \u2014 apply a brand preset programmatically (\`applyThemePreset\` / \`applyTimbalTheme\`); never hand-author OKLCH and don't expose a theme picker to end users.
499
536
 
@@ -2253,6 +2290,7 @@ var AppShellBody = ({
2253
2290
  sidebar,
2254
2291
  topbarContent,
2255
2292
  mainClassName,
2293
+ contentFill = false,
2256
2294
  insetPaddingPx,
2257
2295
  insetExpanded,
2258
2296
  children
@@ -2275,7 +2313,10 @@ var AppShellBody = ({
2275
2313
  "div",
2276
2314
  {
2277
2315
  className: cn(
2278
- "aui-app-shell-scroll flex min-h-0 flex-1 flex-col overflow-y-auto",
2316
+ "aui-app-shell-scroll flex min-h-0 flex-1 flex-col",
2317
+ // Padded scroll region by default; a full-bleed page (chat / canvas) owns
2318
+ // its own scroll, so clip here and let the bounded `main` fill exactly.
2319
+ contentFill ? "overflow-hidden" : "overflow-y-auto",
2279
2320
  !topbarContent && appShellInsetTopClass
2280
2321
  ),
2281
2322
  children: [
@@ -2284,8 +2325,11 @@ var AppShellBody = ({
2284
2325
  "main",
2285
2326
  {
2286
2327
  className: cn(
2287
- "aui-app-shell-main min-w-0 flex-1",
2288
- appShellInsetBottomClass,
2328
+ // Bounded flex column by default so `h-full` / `flex-1 min-h-0` children
2329
+ // (full-page chat, canvas) resolve a height without `mainClassName` surgery.
2330
+ "aui-app-shell-main flex min-h-0 min-w-0 flex-1 flex-col",
2331
+ // Bottom breathing room for scrolling content; full-bleed pages skip it.
2332
+ !contentFill && appShellInsetBottomClass,
2289
2333
  mainClassName
2290
2334
  ),
2291
2335
  children
@@ -2315,7 +2359,8 @@ var AppShell = ({
2315
2359
  defaultNavOpen = false,
2316
2360
  onNavOpenChange,
2317
2361
  className,
2318
- mainClassName
2362
+ mainClassName,
2363
+ contentFill = false
2319
2364
  }) => {
2320
2365
  const topbarContent = topbar ?? header;
2321
2366
  const hasChat = Boolean(chat);
@@ -2362,6 +2407,7 @@ var AppShell = ({
2362
2407
  sidebar,
2363
2408
  topbarContent,
2364
2409
  mainClassName,
2410
+ contentFill,
2365
2411
  insetPaddingPx,
2366
2412
  insetExpanded,
2367
2413
  children
@@ -2511,11 +2557,14 @@ var PageHeader = ({
2511
2557
  className
2512
2558
  }) => {
2513
2559
  const pageHeaderClass = useAppDensityClass("pageHeader");
2560
+ if (title == null && description == null && actions == null) {
2561
+ return null;
2562
+ }
2514
2563
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("header", { className: cn("aui-app-page-header", pageHeaderClass, className), children: [
2515
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
2516
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: title }),
2564
+ title != null || description != null ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
2565
+ title != null ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: title }) : null,
2517
2566
  description ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
2518
- ] }),
2567
+ ] }) : null,
2519
2568
  actions ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "aui-app-page-header-actions flex shrink-0 flex-wrap items-center gap-2", children: actions }) : null
2520
2569
  ] });
2521
2570
  };
@@ -2525,6 +2574,7 @@ var import_jsx_runtime13 = require("react/jsx-runtime");
2525
2574
  var PageFrame = ({
2526
2575
  children,
2527
2576
  breadcrumbs,
2577
+ fill = false,
2528
2578
  className,
2529
2579
  ...headerProps
2530
2580
  }) => {
@@ -2533,7 +2583,11 @@ var PageFrame = ({
2533
2583
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2534
2584
  "div",
2535
2585
  {
2536
- className: cn("aui-app-page", pageColumnClass, className),
2586
+ className: cn(
2587
+ "aui-app-page",
2588
+ fill ? "flex min-h-0 min-w-0 flex-1 flex-col" : pageColumnClass,
2589
+ className
2590
+ ),
2537
2591
  "data-density": density,
2538
2592
  children: [
2539
2593
  breadcrumbs,
@@ -2547,10 +2601,20 @@ var Page = ({
2547
2601
  density = "default",
2548
2602
  children,
2549
2603
  breadcrumbs,
2604
+ fill = false,
2550
2605
  className,
2551
2606
  ...headerProps
2552
2607
  }) => {
2553
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AppDensityProvider, { density, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PageFrame, { breadcrumbs, className, ...headerProps, children }) });
2608
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AppDensityProvider, { density, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2609
+ PageFrame,
2610
+ {
2611
+ breadcrumbs,
2612
+ fill,
2613
+ className,
2614
+ ...headerProps,
2615
+ children
2616
+ }
2617
+ ) });
2554
2618
  };
2555
2619
 
2556
2620
  // src/app/layout/Section.tsx
@@ -8154,6 +8218,7 @@ var Breadcrumbs = ({ items, className }) => {
8154
8218
  };
8155
8219
 
8156
8220
  // src/app/forms/Field.tsx
8221
+ var import_react48 = require("react");
8157
8222
  var import_jsx_runtime73 = require("react/jsx-runtime");
8158
8223
  var Field = ({
8159
8224
  label,
@@ -8179,7 +8244,8 @@ var FieldInput = ({
8179
8244
  id,
8180
8245
  ...inputProps
8181
8246
  }) => {
8182
- const inputId = id ?? inputProps.name;
8247
+ const autoId = (0, import_react48.useId)();
8248
+ const inputId = id ?? inputProps.name ?? autoId;
8183
8249
  return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
8184
8250
  Field,
8185
8251
  {
@@ -8202,6 +8268,7 @@ var FieldInput = ({
8202
8268
  };
8203
8269
 
8204
8270
  // src/app/forms/FieldTextarea.tsx
8271
+ var import_react49 = require("react");
8205
8272
  var import_jsx_runtime74 = require("react/jsx-runtime");
8206
8273
  var textareaClass = cn(
8207
8274
  appInputClass,
@@ -8216,7 +8283,8 @@ var FieldTextarea = ({
8216
8283
  id,
8217
8284
  ...props
8218
8285
  }) => {
8219
- const textareaId = id ?? props.name;
8286
+ const autoId = (0, import_react49.useId)();
8287
+ const textareaId = id ?? props.name ?? autoId;
8220
8288
  return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
8221
8289
  Field,
8222
8290
  {
@@ -8239,6 +8307,7 @@ var FieldTextarea = ({
8239
8307
  };
8240
8308
 
8241
8309
  // src/app/forms/FieldSelect.tsx
8310
+ var import_react50 = require("react");
8242
8311
  var import_lucide_react11 = require("lucide-react");
8243
8312
  var import_jsx_runtime75 = require("react/jsx-runtime");
8244
8313
  var selectWrapClass = "relative";
@@ -8256,7 +8325,8 @@ var FieldSelect = ({
8256
8325
  id,
8257
8326
  ...props
8258
8327
  }) => {
8259
- const selectId = id ?? props.name;
8328
+ const autoId = (0, import_react50.useId)();
8329
+ const selectId = id ?? props.name ?? autoId;
8260
8330
  return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8261
8331
  Field,
8262
8332
  {
@@ -8289,6 +8359,7 @@ var FieldSelect = ({
8289
8359
  };
8290
8360
 
8291
8361
  // src/app/forms/FieldSwitch.tsx
8362
+ var import_react51 = require("react");
8292
8363
  var import_jsx_runtime76 = require("react/jsx-runtime");
8293
8364
  var trackClass = cn(
8294
8365
  "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-[background,box-shadow,border-color] duration-200",
@@ -8309,7 +8380,8 @@ var FieldSwitch = ({
8309
8380
  id,
8310
8381
  ...props
8311
8382
  }) => {
8312
- const inputId = id ?? props.name ?? "switch";
8383
+ const autoId = (0, import_react51.useId)();
8384
+ const inputId = id ?? props.name ?? autoId;
8313
8385
  return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
8314
8386
  "label",
8315
8387
  {
@@ -8418,7 +8490,7 @@ var FilterField = ({
8418
8490
  };
8419
8491
 
8420
8492
  // src/app/data/DataTable.tsx
8421
- var import_react48 = require("react");
8493
+ var import_react52 = require("react");
8422
8494
  var import_lucide_react14 = require("lucide-react");
8423
8495
 
8424
8496
  // src/ui/checkbox.tsx
@@ -8546,7 +8618,7 @@ function DataTable({
8546
8618
  defaultPageIndex = 0,
8547
8619
  onPageChange
8548
8620
  }) {
8549
- const [uncontrolledSort, setUncontrolledSort] = (0, import_react48.useState)(
8621
+ const [uncontrolledSort, setUncontrolledSort] = (0, import_react52.useState)(
8550
8622
  defaultSort
8551
8623
  );
8552
8624
  const isSortControlled = sortProp !== void 0;
@@ -8557,19 +8629,19 @@ function DataTable({
8557
8629
  }
8558
8630
  onSortChange?.(next);
8559
8631
  };
8560
- const [uncontrolledSelected, setUncontrolledSelected] = (0, import_react48.useState)(
8632
+ const [uncontrolledSelected, setUncontrolledSelected] = (0, import_react52.useState)(
8561
8633
  defaultSelectedKeys ?? []
8562
8634
  );
8563
8635
  const isSelectionControlled = selectedKeysProp !== void 0;
8564
8636
  const selectedKeys = isSelectionControlled ? selectedKeysProp : uncontrolledSelected;
8565
- const selectedSet = (0, import_react48.useMemo)(() => new Set(selectedKeys), [selectedKeys]);
8637
+ const selectedSet = (0, import_react52.useMemo)(() => new Set(selectedKeys), [selectedKeys]);
8566
8638
  const setSelected = (next) => {
8567
8639
  if (!isSelectionControlled) {
8568
8640
  setUncontrolledSelected(next);
8569
8641
  }
8570
8642
  onSelectionChange?.(next);
8571
8643
  };
8572
- const [uncontrolledPage, setUncontrolledPage] = (0, import_react48.useState)(defaultPageIndex);
8644
+ const [uncontrolledPage, setUncontrolledPage] = (0, import_react52.useState)(defaultPageIndex);
8573
8645
  const isPageControlled = pageIndexProp !== void 0;
8574
8646
  const rawPageIndex = isPageControlled ? pageIndexProp : uncontrolledPage;
8575
8647
  const setPage = (next) => {
@@ -8578,7 +8650,7 @@ function DataTable({
8578
8650
  }
8579
8651
  onPageChange?.(next);
8580
8652
  };
8581
- const sortedRows = (0, import_react48.useMemo)(() => {
8653
+ const sortedRows = (0, import_react52.useMemo)(() => {
8582
8654
  if (!sort) return rows;
8583
8655
  const column = columns.find((col) => col.id === sort.columnId);
8584
8656
  if (!column?.sortable) return rows;
@@ -8597,13 +8669,13 @@ function DataTable({
8597
8669
  const paginated = typeof pageSize === "number" && pageSize > 0;
8598
8670
  const pageCount = paginated ? Math.max(1, Math.ceil(sortedRows.length / pageSize)) : 1;
8599
8671
  const pageIndex = Math.min(Math.max(0, rawPageIndex), pageCount - 1);
8600
- (0, import_react48.useEffect)(() => {
8672
+ (0, import_react52.useEffect)(() => {
8601
8673
  if (!paginated || isPageControlled) return;
8602
8674
  if (uncontrolledPage > pageCount - 1) {
8603
8675
  setUncontrolledPage(pageCount - 1);
8604
8676
  }
8605
8677
  }, [paginated, isPageControlled, uncontrolledPage, pageCount]);
8606
- const visibleRows = (0, import_react48.useMemo)(() => {
8678
+ const visibleRows = (0, import_react52.useMemo)(() => {
8607
8679
  if (!paginated) return sortedRows;
8608
8680
  const start = pageIndex * pageSize;
8609
8681
  return sortedRows.slice(start, start + pageSize);
@@ -8814,7 +8886,7 @@ function DataTable({
8814
8886
  }
8815
8887
 
8816
8888
  // src/app/data/ChartPanel.tsx
8817
- var import_react49 = require("react");
8889
+ var import_react53 = require("react");
8818
8890
  var import_jsx_runtime84 = require("react/jsx-runtime");
8819
8891
  var ChartPanel = ({
8820
8892
  title,
@@ -8830,7 +8902,7 @@ var ChartPanel = ({
8830
8902
  const height = heightProp ?? APP_DENSITY_CHART_HEIGHT[density];
8831
8903
  const metricChartPlotRegionClass = useAppDensityClass("metricChartPlotRegion");
8832
8904
  const chartPanelBodyClass = useAppDensityClass("chartPanelBody");
8833
- const titleId = (0, import_react49.useId)();
8905
+ const titleId = (0, import_react53.useId)();
8834
8906
  const resolvedTitle = title ?? artifact?.title;
8835
8907
  const hasHeader = Boolean(resolvedTitle || description || actions);
8836
8908
  const body = loading ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Skeleton, { className: "w-full rounded-lg", style: { height }, "aria-hidden": true }) : children ?? (artifact ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(ChartArtifactView, { artifact, embedded: true, height }) : null);
@@ -8873,7 +8945,7 @@ var ChartPanel = ({
8873
8945
  };
8874
8946
 
8875
8947
  // src/app/data/MetricRow.tsx
8876
- var import_react50 = require("react");
8948
+ var import_react54 = require("react");
8877
8949
  var import_jsx_runtime85 = require("react/jsx-runtime");
8878
8950
  var MetricRow = ({
8879
8951
  title,
@@ -8888,9 +8960,9 @@ var MetricRow = ({
8888
8960
  className
8889
8961
  }) => {
8890
8962
  const metricTileClass = useAppDensityClass("metricTile");
8891
- const titleId = (0, import_react50.useId)();
8963
+ const titleId = (0, import_react54.useId)();
8892
8964
  const selectable = onMetricChange != null || activeMetricId != null;
8893
- const [internalId, setInternalId] = (0, import_react50.useState)(
8965
+ const [internalId, setInternalId] = (0, import_react54.useState)(
8894
8966
  defaultActiveMetricId ?? metrics[0]?.id
8895
8967
  );
8896
8968
  const activeId = activeMetricId ?? internalId;
@@ -8957,7 +9029,7 @@ var MetricRow = ({
8957
9029
  };
8958
9030
 
8959
9031
  // src/app/data/MetricChartCard.tsx
8960
- var import_react51 = require("react");
9032
+ var import_react55 = require("react");
8961
9033
  var import_jsx_runtime86 = require("react/jsx-runtime");
8962
9034
  var MetricChartCard = ({
8963
9035
  title,
@@ -8981,8 +9053,8 @@ var MetricChartCard = ({
8981
9053
  const height = heightProp ?? APP_DENSITY_CHART_HEIGHT[density];
8982
9054
  const metricChartRegionClass = useAppDensityClass("metricChartRegion");
8983
9055
  const metricTileClass = useAppDensityClass("metricTile");
8984
- const titleId = (0, import_react51.useId)();
8985
- const [internalId, setInternalId] = (0, import_react51.useState)(
9056
+ const titleId = (0, import_react55.useId)();
9057
+ const [internalId, setInternalId] = (0, import_react55.useState)(
8986
9058
  defaultActiveMetricId ?? metrics[0]?.id
8987
9059
  );
8988
9060
  const activeId = activeMetricId ?? internalId;
@@ -9088,13 +9160,13 @@ var MetricChartCard = ({
9088
9160
  };
9089
9161
 
9090
9162
  // src/hooks/use-live-query.ts
9091
- var import_react52 = require("react");
9163
+ var import_react56 = require("react");
9092
9164
  function useInterval(callback, delayMs) {
9093
- const saved = (0, import_react52.useRef)(callback);
9094
- (0, import_react52.useEffect)(() => {
9165
+ const saved = (0, import_react56.useRef)(callback);
9166
+ (0, import_react56.useEffect)(() => {
9095
9167
  saved.current = callback;
9096
9168
  }, [callback]);
9097
- (0, import_react52.useEffect)(() => {
9169
+ (0, import_react56.useEffect)(() => {
9098
9170
  if (delayMs === null) return;
9099
9171
  const id = setInterval(() => saved.current(), delayMs);
9100
9172
  return () => clearInterval(id);
@@ -9107,25 +9179,25 @@ function useLiveQuery(fetcher, options = {}) {
9107
9179
  immediate = true,
9108
9180
  refetchOnFocus = true
9109
9181
  } = options;
9110
- const [data, setData] = (0, import_react52.useState)(void 0);
9111
- const [error, setError] = (0, import_react52.useState)(void 0);
9112
- const [loading, setLoading] = (0, import_react52.useState)(enabled);
9113
- const [refreshing, setRefreshing] = (0, import_react52.useState)(false);
9114
- const [lastUpdated, setLastUpdated] = (0, import_react52.useState)(null);
9115
- const fetcherRef = (0, import_react52.useRef)(fetcher);
9116
- (0, import_react52.useEffect)(() => {
9182
+ const [data, setData] = (0, import_react56.useState)(void 0);
9183
+ const [error, setError] = (0, import_react56.useState)(void 0);
9184
+ const [loading, setLoading] = (0, import_react56.useState)(enabled);
9185
+ const [refreshing, setRefreshing] = (0, import_react56.useState)(false);
9186
+ const [lastUpdated, setLastUpdated] = (0, import_react56.useState)(null);
9187
+ const fetcherRef = (0, import_react56.useRef)(fetcher);
9188
+ (0, import_react56.useEffect)(() => {
9117
9189
  fetcherRef.current = fetcher;
9118
9190
  }, [fetcher]);
9119
- const mounted = (0, import_react52.useRef)(true);
9120
- const requestId = (0, import_react52.useRef)(0);
9121
- const hasData = (0, import_react52.useRef)(false);
9122
- (0, import_react52.useEffect)(() => {
9191
+ const mounted = (0, import_react56.useRef)(true);
9192
+ const requestId = (0, import_react56.useRef)(0);
9193
+ const hasData = (0, import_react56.useRef)(false);
9194
+ (0, import_react56.useEffect)(() => {
9123
9195
  mounted.current = true;
9124
9196
  return () => {
9125
9197
  mounted.current = false;
9126
9198
  };
9127
9199
  }, []);
9128
- const run = (0, import_react52.useCallback)(() => {
9200
+ const run = (0, import_react56.useCallback)(() => {
9129
9201
  const id = ++requestId.current;
9130
9202
  if (hasData.current) {
9131
9203
  setRefreshing(true);
@@ -9147,15 +9219,15 @@ function useLiveQuery(fetcher, options = {}) {
9147
9219
  setRefreshing(false);
9148
9220
  });
9149
9221
  }, []);
9150
- const refetch = (0, import_react52.useCallback)(() => {
9222
+ const refetch = (0, import_react56.useCallback)(() => {
9151
9223
  if (!enabled) return;
9152
9224
  run();
9153
9225
  }, [enabled, run]);
9154
- (0, import_react52.useEffect)(() => {
9226
+ (0, import_react56.useEffect)(() => {
9155
9227
  if (!enabled) return;
9156
9228
  if (immediate) run();
9157
9229
  }, [enabled, immediate, run]);
9158
- (0, import_react52.useEffect)(() => {
9230
+ (0, import_react56.useEffect)(() => {
9159
9231
  if (!enabled || intervalMs === null) return;
9160
9232
  const tick = () => {
9161
9233
  if (refetchOnFocus && typeof document !== "undefined" && document.visibilityState === "hidden") {
@@ -9166,7 +9238,7 @@ function useLiveQuery(fetcher, options = {}) {
9166
9238
  const handle = setInterval(tick, intervalMs);
9167
9239
  return () => clearInterval(handle);
9168
9240
  }, [enabled, intervalMs, refetchOnFocus, run]);
9169
- (0, import_react52.useEffect)(() => {
9241
+ (0, import_react56.useEffect)(() => {
9170
9242
  if (!enabled || !refetchOnFocus || typeof document === "undefined") return;
9171
9243
  const onVisible = () => {
9172
9244
  if (document.visibilityState === "visible") run();
@@ -9178,7 +9250,7 @@ function useLiveQuery(fetcher, options = {}) {
9178
9250
  }
9179
9251
 
9180
9252
  // src/charts/sparkline.tsx
9181
- var import_react53 = require("react");
9253
+ var import_react57 = require("react");
9182
9254
  var import_jsx_runtime87 = require("react/jsx-runtime");
9183
9255
  var Sparkline = ({
9184
9256
  data,
@@ -9191,7 +9263,7 @@ var Sparkline = ({
9191
9263
  className,
9192
9264
  ariaLabel = "Trend"
9193
9265
  }) => {
9194
- const uid = (0, import_react53.useId)();
9266
+ const uid = (0, import_react57.useId)();
9195
9267
  const values = data.map((d) => typeof d === "number" ? d : toNum(d[dataKey]));
9196
9268
  if (values.length === 0) {
9197
9269
  return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: cn("inline-block", className), style: { width, height } });
package/dist/app.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AppDensity, a as AppDensityClassKey } from './chart-artifact-WDEW9dHT.cjs';
2
- export { b as APP_DENSITY_CHART_HEIGHT, c as APP_DENSITY_CLASSES, d as APP_KIT_AGENT_INSTRUCTIONS, e as AppChatPanel, f as AppChatPanelProps, g as AppConfirmDialog, h as AppConfirmDialogProps, i as AppCopilotContextValue, j as AppCopilotProvider, k as AppCopilotProviderProps, l as AppShell, m as AppShellChatControls, n as AppShellChatTrigger, o as AppShellChatTriggerProps, p as AppShellNavControls, q as AppShellProps, r as AppShellSidebarTrigger, s as AppShellSidebarTriggerProps, t as AppShellTopbar, u as AppShellTopbarProps, B as BreadcrumbEntry, v as BreadcrumbItem, w as Breadcrumbs, x as BreadcrumbsProps, C as CHART_PALETTE, y as COLOR_UTILITY_PREFIXES, z as ChartArtifactView, D as ChartLayout, E as ChartMargin, F as ChartPanel, G as ChartPanelProps, H as ChartSeries, I as ChartTooltipIndicator, J as ChartVariant, K as ConnectionRow, L as ConnectionRowList, M as ConnectionRowListProps, N as ConnectionRowProps, O as DangerZone, P as DangerZoneAction, Q as DangerZoneActionProps, R as DangerZoneProps, S as DataTable, T as DataTableColumn, U as DataTableProps, V as DataTableSort, W as DataTableSortDirection, X as DescriptionItem, Y as DescriptionList, Z as DescriptionListProps, _ as EmptyState, $ as EmptyStateProps, a0 as ExpandableSection, a1 as ExpandableSectionProps, a2 as Field, a3 as FieldInput, a4 as FieldInputProps, a5 as FieldProps, a6 as FieldRow, a7 as FieldRowProps, a8 as FieldSelect, a9 as FieldSelectProps, aa as FieldSwitch, ab as FieldSwitchProps, ac as FieldTextarea, ad as FieldTextareaProps, ae as FilterBar, af as FilterBarProps, ag as FilterField, ah as FilterFieldProps, ai as FloatingUnsavedChangesBar, aj as FloatingUnsavedChangesBarProps, ak as FormSection, al as FormSectionProps, am as HOUSE_RULES, an as HouseRule, ao as INTEGRATION_CATALOG_CARD_HEIGHT_CLASS, ap as InfoCard, aq as InfoCardProps, ar as InfoCardTone, as as IntegrationCard, at as IntegrationCardProps, au as IntegrationCardStatus, av as IntegrationsEmptyState, aw as IntegrationsEmptyStateProps, ax as LineAreaChart, ay as LineAreaChartProps, az as LintFinding, aA as LintOptions, aB as LintResult, aC as LintSeverity, aD as MetricChartCard, aE as MetricChartCardProps, aF as MetricChartMetric, aG as MetricRow, aH as MetricRowItem, aI as MetricRowProps, aJ as MetricTile, aK as MetricTileProps, aL as Page, aM as PageHeader, aN as PageHeaderProps, aO as PageProps, aP as PieChart, aQ as PieChartProps, aR as PlanBadge, aS as PlanBadgeProps, aT as PlanBadgeTone, aU as RESERVED_GRADIENT_TOKENS, aV as RadarChart, aW as RadarChartProps, aX as RadialChart, aY as RadialChartProps, aZ as ResourceCard, a_ as ResourceCardProps, a$ as ReviewResult, b0 as SEMANTIC_COLOR_TOKENS, b1 as SLOP_BUDGETS, b2 as SearchInput, b3 as SearchInputProps, b4 as Section, b5 as SectionProps, b6 as SemanticColorToken, b7 as SettingsSection, b8 as SettingsSectionHeader, b9 as SettingsSectionHeaderProps, ba as SettingsSectionProps, bb as Sparkline, bc as SparklineProps, bd as StatTile, be as StatTileProps, bf as StatusBadge, bg as StatusBadgeProps, bh as StatusBadgeTone, bi as StatusDot, bj as StatusDotProps, bk as StatusDotTone, bl as SubNav, bm as SubNavItem, bn as SubNavProps, bo as SurfaceCard, bp as SurfaceCardProps, bq as TAILWIND_PALETTE_COLORS, br as THEME_AGENT_INSTRUCTIONS, bs as TIMBAL_THEME_PRESETS, bt as ThemeShadow, bu as ThemeToCssOptions, bv as ThemeTokenMap, bw as TimbalThemeIntent, bx as TimbalThemePreset, by as TimbalThemePresetId, bz as TimbalThemeStyle, bA as TimbalThemeStyleProps, bB as TimbalThemeTokens, bC as TimbalThemeTypography, bD as UI_REVIEW_AGENT_INSTRUCTIONS, bE as UseLiveQueryOptions, bF as UseLiveQueryResult, bG as appDensityClass, bH as applyThemePreset, bI as applyTimbalTheme, bJ as clearTimbalTheme, bK as connectionRowListClass, bL as createTimbalTheme, bM as ensureThemeFontLink, bN as flushBarCategoryGap, bO as flushLineAreaEdgeToEdge, bP as formatLintReport, bQ as getStoredThemePreset, bR as getThemePreset, bS as lintGeneratedUi, bT as resolveChartMargin, bU as resolveTooltipCategory, bV as reviewGeneratedUi, bW as themeToCss, bX as useAppCopilotContext, bY as useAppShellChat, bZ as useAppShellNav, b_ as useInterval, b$ as useLiveQuery } from './chart-artifact-WDEW9dHT.cjs';
1
+ import { A as AppDensity, a as AppDensityClassKey } from './chart-artifact-C8-Py6lc.cjs';
2
+ export { b as APP_DENSITY_CHART_HEIGHT, c as APP_DENSITY_CLASSES, d as APP_KIT_AGENT_INSTRUCTIONS, e as AppChatPanel, f as AppChatPanelProps, g as AppConfirmDialog, h as AppConfirmDialogProps, i as AppCopilotContextValue, j as AppCopilotProvider, k as AppCopilotProviderProps, l as AppShell, m as AppShellChatControls, n as AppShellChatTrigger, o as AppShellChatTriggerProps, p as AppShellNavControls, q as AppShellProps, r as AppShellSidebarTrigger, s as AppShellSidebarTriggerProps, t as AppShellTopbar, u as AppShellTopbarProps, B as BreadcrumbEntry, v as BreadcrumbItem, w as Breadcrumbs, x as BreadcrumbsProps, C as CHART_PALETTE, y as COLOR_UTILITY_PREFIXES, z as ChartArtifactView, D as ChartLayout, E as ChartMargin, F as ChartPanel, G as ChartPanelProps, H as ChartSeries, I as ChartTooltipIndicator, J as ChartVariant, K as ConnectionRow, L as ConnectionRowList, M as ConnectionRowListProps, N as ConnectionRowProps, O as DangerZone, P as DangerZoneAction, Q as DangerZoneActionProps, R as DangerZoneProps, S as DataTable, T as DataTableColumn, U as DataTableProps, V as DataTableSort, W as DataTableSortDirection, X as DescriptionItem, Y as DescriptionList, Z as DescriptionListProps, _ as EmptyState, $ as EmptyStateProps, a0 as ExpandableSection, a1 as ExpandableSectionProps, a2 as Field, a3 as FieldInput, a4 as FieldInputProps, a5 as FieldProps, a6 as FieldRow, a7 as FieldRowProps, a8 as FieldSelect, a9 as FieldSelectProps, aa as FieldSwitch, ab as FieldSwitchProps, ac as FieldTextarea, ad as FieldTextareaProps, ae as FilterBar, af as FilterBarProps, ag as FilterField, ah as FilterFieldProps, ai as FloatingUnsavedChangesBar, aj as FloatingUnsavedChangesBarProps, ak as FormSection, al as FormSectionProps, am as HOUSE_RULES, an as HouseRule, ao as INTEGRATION_CATALOG_CARD_HEIGHT_CLASS, ap as InfoCard, aq as InfoCardProps, ar as InfoCardTone, as as IntegrationCard, at as IntegrationCardProps, au as IntegrationCardStatus, av as IntegrationsEmptyState, aw as IntegrationsEmptyStateProps, ax as LineAreaChart, ay as LineAreaChartProps, az as LintFinding, aA as LintOptions, aB as LintResult, aC as LintSeverity, aD as MetricChartCard, aE as MetricChartCardProps, aF as MetricChartMetric, aG as MetricRow, aH as MetricRowItem, aI as MetricRowProps, aJ as MetricTile, aK as MetricTileProps, aL as Page, aM as PageHeader, aN as PageHeaderProps, aO as PageProps, aP as PieChart, aQ as PieChartProps, aR as PlanBadge, aS as PlanBadgeProps, aT as PlanBadgeTone, aU as RESERVED_GRADIENT_TOKENS, aV as RadarChart, aW as RadarChartProps, aX as RadialChart, aY as RadialChartProps, aZ as ResourceCard, a_ as ResourceCardProps, a$ as ReviewResult, b0 as SEMANTIC_COLOR_TOKENS, b1 as SLOP_BUDGETS, b2 as SearchInput, b3 as SearchInputProps, b4 as Section, b5 as SectionProps, b6 as SemanticColorToken, b7 as SettingsSection, b8 as SettingsSectionHeader, b9 as SettingsSectionHeaderProps, ba as SettingsSectionProps, bb as Sparkline, bc as SparklineProps, bd as StatTile, be as StatTileProps, bf as StatusBadge, bg as StatusBadgeProps, bh as StatusBadgeTone, bi as StatusDot, bj as StatusDotProps, bk as StatusDotTone, bl as SubNav, bm as SubNavItem, bn as SubNavProps, bo as SurfaceCard, bp as SurfaceCardProps, bq as TAILWIND_PALETTE_COLORS, br as THEME_AGENT_INSTRUCTIONS, bs as TIMBAL_THEME_PRESETS, bt as ThemeShadow, bu as ThemeToCssOptions, bv as ThemeTokenMap, bw as TimbalThemeIntent, bx as TimbalThemePreset, by as TimbalThemePresetId, bz as TimbalThemeStyle, bA as TimbalThemeStyleProps, bB as TimbalThemeTokens, bC as TimbalThemeTypography, bD as UI_REVIEW_AGENT_INSTRUCTIONS, bE as UseLiveQueryOptions, bF as UseLiveQueryResult, bG as appDensityClass, bH as applyThemePreset, bI as applyTimbalTheme, bJ as clearTimbalTheme, bK as connectionRowListClass, bL as createTimbalTheme, bM as ensureThemeFontLink, bN as flushBarCategoryGap, bO as flushLineAreaEdgeToEdge, bP as formatLintReport, bQ as getStoredThemePreset, bR as getThemePreset, bS as lintGeneratedUi, bT as resolveChartMargin, bU as resolveTooltipCategory, bV as reviewGeneratedUi, bW as themeToCss, bX as useAppCopilotContext, bY as useAppShellChat, bZ as useAppShellNav, b_ as useInterval, b$ as useLiveQuery } from './chart-artifact-C8-Py6lc.cjs';
3
3
  import { FC, ReactNode } from 'react';
4
4
  export { B as Button } from './button-BoyX5pM_.cjs';
5
5
  export { C as ChartArtifact, a as ChartSeriesConfig, T as ThreadVariant, b as TimbalChat, c as TimbalChatProps } from './chat-ClmzWzCX.cjs';
package/dist/app.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AppDensity, a as AppDensityClassKey } from './chart-artifact-Q5QgMtbj.js';
2
- export { b as APP_DENSITY_CHART_HEIGHT, c as APP_DENSITY_CLASSES, d as APP_KIT_AGENT_INSTRUCTIONS, e as AppChatPanel, f as AppChatPanelProps, g as AppConfirmDialog, h as AppConfirmDialogProps, i as AppCopilotContextValue, j as AppCopilotProvider, k as AppCopilotProviderProps, l as AppShell, m as AppShellChatControls, n as AppShellChatTrigger, o as AppShellChatTriggerProps, p as AppShellNavControls, q as AppShellProps, r as AppShellSidebarTrigger, s as AppShellSidebarTriggerProps, t as AppShellTopbar, u as AppShellTopbarProps, B as BreadcrumbEntry, v as BreadcrumbItem, w as Breadcrumbs, x as BreadcrumbsProps, C as CHART_PALETTE, y as COLOR_UTILITY_PREFIXES, z as ChartArtifactView, D as ChartLayout, E as ChartMargin, F as ChartPanel, G as ChartPanelProps, H as ChartSeries, I as ChartTooltipIndicator, J as ChartVariant, K as ConnectionRow, L as ConnectionRowList, M as ConnectionRowListProps, N as ConnectionRowProps, O as DangerZone, P as DangerZoneAction, Q as DangerZoneActionProps, R as DangerZoneProps, S as DataTable, T as DataTableColumn, U as DataTableProps, V as DataTableSort, W as DataTableSortDirection, X as DescriptionItem, Y as DescriptionList, Z as DescriptionListProps, _ as EmptyState, $ as EmptyStateProps, a0 as ExpandableSection, a1 as ExpandableSectionProps, a2 as Field, a3 as FieldInput, a4 as FieldInputProps, a5 as FieldProps, a6 as FieldRow, a7 as FieldRowProps, a8 as FieldSelect, a9 as FieldSelectProps, aa as FieldSwitch, ab as FieldSwitchProps, ac as FieldTextarea, ad as FieldTextareaProps, ae as FilterBar, af as FilterBarProps, ag as FilterField, ah as FilterFieldProps, ai as FloatingUnsavedChangesBar, aj as FloatingUnsavedChangesBarProps, ak as FormSection, al as FormSectionProps, am as HOUSE_RULES, an as HouseRule, ao as INTEGRATION_CATALOG_CARD_HEIGHT_CLASS, ap as InfoCard, aq as InfoCardProps, ar as InfoCardTone, as as IntegrationCard, at as IntegrationCardProps, au as IntegrationCardStatus, av as IntegrationsEmptyState, aw as IntegrationsEmptyStateProps, ax as LineAreaChart, ay as LineAreaChartProps, az as LintFinding, aA as LintOptions, aB as LintResult, aC as LintSeverity, aD as MetricChartCard, aE as MetricChartCardProps, aF as MetricChartMetric, aG as MetricRow, aH as MetricRowItem, aI as MetricRowProps, aJ as MetricTile, aK as MetricTileProps, aL as Page, aM as PageHeader, aN as PageHeaderProps, aO as PageProps, aP as PieChart, aQ as PieChartProps, aR as PlanBadge, aS as PlanBadgeProps, aT as PlanBadgeTone, aU as RESERVED_GRADIENT_TOKENS, aV as RadarChart, aW as RadarChartProps, aX as RadialChart, aY as RadialChartProps, aZ as ResourceCard, a_ as ResourceCardProps, a$ as ReviewResult, b0 as SEMANTIC_COLOR_TOKENS, b1 as SLOP_BUDGETS, b2 as SearchInput, b3 as SearchInputProps, b4 as Section, b5 as SectionProps, b6 as SemanticColorToken, b7 as SettingsSection, b8 as SettingsSectionHeader, b9 as SettingsSectionHeaderProps, ba as SettingsSectionProps, bb as Sparkline, bc as SparklineProps, bd as StatTile, be as StatTileProps, bf as StatusBadge, bg as StatusBadgeProps, bh as StatusBadgeTone, bi as StatusDot, bj as StatusDotProps, bk as StatusDotTone, bl as SubNav, bm as SubNavItem, bn as SubNavProps, bo as SurfaceCard, bp as SurfaceCardProps, bq as TAILWIND_PALETTE_COLORS, br as THEME_AGENT_INSTRUCTIONS, bs as TIMBAL_THEME_PRESETS, bt as ThemeShadow, bu as ThemeToCssOptions, bv as ThemeTokenMap, bw as TimbalThemeIntent, bx as TimbalThemePreset, by as TimbalThemePresetId, bz as TimbalThemeStyle, bA as TimbalThemeStyleProps, bB as TimbalThemeTokens, bC as TimbalThemeTypography, bD as UI_REVIEW_AGENT_INSTRUCTIONS, bE as UseLiveQueryOptions, bF as UseLiveQueryResult, bG as appDensityClass, bH as applyThemePreset, bI as applyTimbalTheme, bJ as clearTimbalTheme, bK as connectionRowListClass, bL as createTimbalTheme, bM as ensureThemeFontLink, bN as flushBarCategoryGap, bO as flushLineAreaEdgeToEdge, bP as formatLintReport, bQ as getStoredThemePreset, bR as getThemePreset, bS as lintGeneratedUi, bT as resolveChartMargin, bU as resolveTooltipCategory, bV as reviewGeneratedUi, bW as themeToCss, bX as useAppCopilotContext, bY as useAppShellChat, bZ as useAppShellNav, b_ as useInterval, b$ as useLiveQuery } from './chart-artifact-Q5QgMtbj.js';
1
+ import { A as AppDensity, a as AppDensityClassKey } from './chart-artifact-CMnDys2t.js';
2
+ export { b as APP_DENSITY_CHART_HEIGHT, c as APP_DENSITY_CLASSES, d as APP_KIT_AGENT_INSTRUCTIONS, e as AppChatPanel, f as AppChatPanelProps, g as AppConfirmDialog, h as AppConfirmDialogProps, i as AppCopilotContextValue, j as AppCopilotProvider, k as AppCopilotProviderProps, l as AppShell, m as AppShellChatControls, n as AppShellChatTrigger, o as AppShellChatTriggerProps, p as AppShellNavControls, q as AppShellProps, r as AppShellSidebarTrigger, s as AppShellSidebarTriggerProps, t as AppShellTopbar, u as AppShellTopbarProps, B as BreadcrumbEntry, v as BreadcrumbItem, w as Breadcrumbs, x as BreadcrumbsProps, C as CHART_PALETTE, y as COLOR_UTILITY_PREFIXES, z as ChartArtifactView, D as ChartLayout, E as ChartMargin, F as ChartPanel, G as ChartPanelProps, H as ChartSeries, I as ChartTooltipIndicator, J as ChartVariant, K as ConnectionRow, L as ConnectionRowList, M as ConnectionRowListProps, N as ConnectionRowProps, O as DangerZone, P as DangerZoneAction, Q as DangerZoneActionProps, R as DangerZoneProps, S as DataTable, T as DataTableColumn, U as DataTableProps, V as DataTableSort, W as DataTableSortDirection, X as DescriptionItem, Y as DescriptionList, Z as DescriptionListProps, _ as EmptyState, $ as EmptyStateProps, a0 as ExpandableSection, a1 as ExpandableSectionProps, a2 as Field, a3 as FieldInput, a4 as FieldInputProps, a5 as FieldProps, a6 as FieldRow, a7 as FieldRowProps, a8 as FieldSelect, a9 as FieldSelectProps, aa as FieldSwitch, ab as FieldSwitchProps, ac as FieldTextarea, ad as FieldTextareaProps, ae as FilterBar, af as FilterBarProps, ag as FilterField, ah as FilterFieldProps, ai as FloatingUnsavedChangesBar, aj as FloatingUnsavedChangesBarProps, ak as FormSection, al as FormSectionProps, am as HOUSE_RULES, an as HouseRule, ao as INTEGRATION_CATALOG_CARD_HEIGHT_CLASS, ap as InfoCard, aq as InfoCardProps, ar as InfoCardTone, as as IntegrationCard, at as IntegrationCardProps, au as IntegrationCardStatus, av as IntegrationsEmptyState, aw as IntegrationsEmptyStateProps, ax as LineAreaChart, ay as LineAreaChartProps, az as LintFinding, aA as LintOptions, aB as LintResult, aC as LintSeverity, aD as MetricChartCard, aE as MetricChartCardProps, aF as MetricChartMetric, aG as MetricRow, aH as MetricRowItem, aI as MetricRowProps, aJ as MetricTile, aK as MetricTileProps, aL as Page, aM as PageHeader, aN as PageHeaderProps, aO as PageProps, aP as PieChart, aQ as PieChartProps, aR as PlanBadge, aS as PlanBadgeProps, aT as PlanBadgeTone, aU as RESERVED_GRADIENT_TOKENS, aV as RadarChart, aW as RadarChartProps, aX as RadialChart, aY as RadialChartProps, aZ as ResourceCard, a_ as ResourceCardProps, a$ as ReviewResult, b0 as SEMANTIC_COLOR_TOKENS, b1 as SLOP_BUDGETS, b2 as SearchInput, b3 as SearchInputProps, b4 as Section, b5 as SectionProps, b6 as SemanticColorToken, b7 as SettingsSection, b8 as SettingsSectionHeader, b9 as SettingsSectionHeaderProps, ba as SettingsSectionProps, bb as Sparkline, bc as SparklineProps, bd as StatTile, be as StatTileProps, bf as StatusBadge, bg as StatusBadgeProps, bh as StatusBadgeTone, bi as StatusDot, bj as StatusDotProps, bk as StatusDotTone, bl as SubNav, bm as SubNavItem, bn as SubNavProps, bo as SurfaceCard, bp as SurfaceCardProps, bq as TAILWIND_PALETTE_COLORS, br as THEME_AGENT_INSTRUCTIONS, bs as TIMBAL_THEME_PRESETS, bt as ThemeShadow, bu as ThemeToCssOptions, bv as ThemeTokenMap, bw as TimbalThemeIntent, bx as TimbalThemePreset, by as TimbalThemePresetId, bz as TimbalThemeStyle, bA as TimbalThemeStyleProps, bB as TimbalThemeTokens, bC as TimbalThemeTypography, bD as UI_REVIEW_AGENT_INSTRUCTIONS, bE as UseLiveQueryOptions, bF as UseLiveQueryResult, bG as appDensityClass, bH as applyThemePreset, bI as applyTimbalTheme, bJ as clearTimbalTheme, bK as connectionRowListClass, bL as createTimbalTheme, bM as ensureThemeFontLink, bN as flushBarCategoryGap, bO as flushLineAreaEdgeToEdge, bP as formatLintReport, bQ as getStoredThemePreset, bR as getThemePreset, bS as lintGeneratedUi, bT as resolveChartMargin, bU as resolveTooltipCategory, bV as reviewGeneratedUi, bW as themeToCss, bX as useAppCopilotContext, bY as useAppShellChat, bZ as useAppShellNav, b_ as useInterval, b$ as useLiveQuery } from './chart-artifact-CMnDys2t.js';
3
3
  import { FC, ReactNode } from 'react';
4
4
  export { B as Button } from './button-BoyX5pM_.js';
5
5
  export { C as ChartArtifact, a as ChartSeriesConfig, T as ThreadVariant, b as TimbalChat, c as TimbalChatProps } from './chat-ClmzWzCX.js';
package/dist/app.esm.js CHANGED
@@ -88,7 +88,7 @@ import {
88
88
  useAppShellNav,
89
89
  useInterval,
90
90
  useLiveQuery
91
- } from "./chunk-YCXN67SD.esm.js";
91
+ } from "./chunk-VOWNCS3F.esm.js";
92
92
  import "./chunk-QIABF4KB.esm.js";
93
93
  import {
94
94
  CHART_PALETTE,
@@ -426,6 +426,15 @@ interface AppShellProps {
426
426
  onNavOpenChange?: (open: boolean) => void;
427
427
  className?: string;
428
428
  mainClassName?: string;
429
+ /**
430
+ * Make the content region a bounded, non-scrolling flex column instead of the
431
+ * default padded scroll area. Use for full-bleed pages that own their own
432
+ * scroll — a full-page chat (`TimbalChat` / `Thread`), a canvas, a map, an
433
+ * editor — so a `h-full` / `flex-1 min-h-0` child fills exactly and a pinned
434
+ * footer (e.g. the chat composer) stays put instead of riding down on scroll.
435
+ * Do **not** combine with `h-[calc(100dvh-…)]` guesses on the child.
436
+ */
437
+ contentFill?: boolean;
429
438
  }
430
439
  /**
431
440
  * App-first layout: sidebar + topbar + main, with optional **floating** copilot.
@@ -557,7 +566,8 @@ type AppDensityClassKey = keyof typeof APP_DENSITY_CLASSES;
557
566
  declare function appDensityClass(key: AppDensityClassKey, density?: AppDensity): string;
558
567
 
559
568
  interface PageHeaderProps {
560
- title: ReactNode;
569
+ /** Page title. Omit for a headerless page (no `<h1>` rendered). */
570
+ title?: ReactNode;
561
571
  description?: ReactNode;
562
572
  actions?: ReactNode;
563
573
  className?: string;
@@ -573,6 +583,13 @@ interface PageProps extends PageHeaderProps {
573
583
  * `compact` tightens page insets, section gaps, and card padding.
574
584
  */
575
585
  density?: AppDensity;
586
+ /**
587
+ * Make the page a bounded, full-height flex column instead of a centered,
588
+ * content-sized column. Pair with `AppShell contentFill` for full-bleed pages
589
+ * (a full-page chat, a canvas, an editor) whose body should fill the viewport
590
+ * and own its own scroll. Give the fill child `min-h-0 flex-1`.
591
+ */
592
+ fill?: boolean;
576
593
  className?: string;
577
594
  }
578
595
  declare const Page: FC<PageProps>;