Showing preview only (4,593K chars total). Download the full file or copy to clipboard to get everything.
Repository: assistant-ui/tool-ui
Branch: main
Commit: e3f90d71c36e
Files: 779
Total size: 4.2 MB
Directory structure:
gitextract_06635t45/
├── .changeset/
│ └── config.json
├── .git-blame-ignore-revs
├── .githooks/
│ ├── pre-commit
│ └── pre-push
├── .github/
│ ├── pull_request_template.md
│ └── workflows/
│ ├── changeset.yaml
│ ├── ci.yml
│ └── npm-publish.yaml
├── .gitignore
├── .prettierignore
├── AGENTS.md
├── AGENT_CHANGELOG.md
├── CLAUDE.md
├── LICENSE.md
├── README.md
├── apps/
│ └── www/
│ ├── .oxfmtrc.jsonc
│ ├── .oxlintrc.json
│ ├── .prettierignore
│ ├── app/
│ │ ├── api/
│ │ │ ├── builder/
│ │ │ │ ├── chat/
│ │ │ │ │ └── route.ts
│ │ │ │ └── create-freestyle/
│ │ │ │ └── route.ts
│ │ │ ├── chat/
│ │ │ │ └── route.ts
│ │ │ ├── mcp-tools/
│ │ │ │ └── route.ts
│ │ │ ├── playground/
│ │ │ │ └── chat/
│ │ │ │ └── route.ts
│ │ │ └── weather-tuning/
│ │ │ ├── _lib/
│ │ │ │ └── tuned-presets-io.ts
│ │ │ ├── apply/
│ │ │ │ └── route.ts
│ │ │ └── recover/
│ │ │ └── route.ts
│ │ ├── builder/
│ │ │ ├── layout.tsx
│ │ │ ├── opengraph-image.tsx
│ │ │ └── page.tsx
│ │ ├── components/
│ │ │ ├── analytics/
│ │ │ │ └── posthog-init.client.tsx
│ │ │ ├── assistant-ui/
│ │ │ │ ├── markdown-text.tsx
│ │ │ │ ├── thread-list.tsx
│ │ │ │ ├── tool-fallback.tsx
│ │ │ │ └── tooltip-icon-button.tsx
│ │ │ ├── builder/
│ │ │ │ ├── mcp-icon.tsx
│ │ │ │ ├── theme-toggle.tsx
│ │ │ │ ├── webview-actions.ts
│ │ │ │ └── webview.tsx
│ │ │ ├── home/
│ │ │ │ ├── chat-showcase.tsx
│ │ │ │ ├── demo-chat.tsx
│ │ │ │ ├── faux-chat-shell-animated.tsx
│ │ │ │ ├── faux-chat-shell-mobile-animated.tsx
│ │ │ │ ├── faux-chat-shell-mobile.tsx
│ │ │ │ ├── faux-chat-shell.tsx
│ │ │ │ ├── home-background.tsx
│ │ │ │ ├── home-hero.tsx
│ │ │ │ ├── home-hexnut-scene.tsx
│ │ │ │ └── noise-texture.ts
│ │ │ ├── layout/
│ │ │ │ ├── app-header.server.tsx
│ │ │ │ ├── app-shell-animated.client.tsx
│ │ │ │ ├── app-shell.tsx
│ │ │ │ ├── header-active-link.client.tsx
│ │ │ │ ├── mobile-nav-sheet-gate.client.tsx
│ │ │ │ ├── mobile-nav-sheet.client.tsx
│ │ │ │ ├── page-shell.tsx
│ │ │ │ └── tracked-external-anchor.client.tsx
│ │ │ ├── mdx/
│ │ │ │ ├── features.tsx
│ │ │ │ └── mermaid.tsx
│ │ │ ├── theme/
│ │ │ │ └── theme-provider.tsx
│ │ │ └── visuals/
│ │ │ └── spinning-hexnut/
│ │ │ └── hexnut-scene.tsx
│ │ ├── docs/
│ │ │ ├── _components/
│ │ │ │ ├── chat-context-preview.tsx
│ │ │ │ ├── collaboration-diagram.tsx
│ │ │ │ ├── component-docs-tabs.tsx
│ │ │ │ ├── component-preview-shell.tsx
│ │ │ │ ├── component-preview.tsx
│ │ │ │ ├── component-previews/
│ │ │ │ │ └── social-post-preview.tsx
│ │ │ │ ├── copy-markdown-button.tsx
│ │ │ │ ├── docs-article.tsx
│ │ │ │ ├── docs-bordered-shell.tsx
│ │ │ │ ├── docs-content.tsx
│ │ │ │ ├── docs-header.tsx
│ │ │ │ ├── docs-nav.tsx
│ │ │ │ ├── docs-pager.tsx
│ │ │ │ ├── docs-pages.ts
│ │ │ │ ├── docs-search-shortcut.ts
│ │ │ │ ├── docs-search.client.tsx
│ │ │ │ ├── docs-toc-context.tsx
│ │ │ │ ├── docs-toc-wrapper.tsx
│ │ │ │ ├── docs-toc.tsx
│ │ │ │ ├── gallery-analytics.client.tsx
│ │ │ │ ├── gallery-card-header.tsx
│ │ │ │ ├── gallery-docs-link.tsx
│ │ │ │ ├── header-preview-tabs.tsx
│ │ │ │ ├── install-command-block.tsx
│ │ │ │ ├── install-command-line.tsx
│ │ │ │ ├── interactive-option-demo.tsx
│ │ │ │ ├── mdx-to-markdown.ts
│ │ │ │ ├── mock-thread.tsx
│ │ │ │ ├── preset-example.tsx
│ │ │ │ ├── preset-selector.tsx
│ │ │ │ └── tracked-dynamic-codeblock.tsx
│ │ │ ├── actions/
│ │ │ │ ├── actions-examples.tsx
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── advanced/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── agent-skills/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── approval-card/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── audio/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── changelog/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── chart/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── citation/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── code-block/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── code-diff/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── data-table/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── formatting-gallery.tsx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ ├── page.tsx
│ │ │ │ └── tasks-demo.tsx
│ │ │ ├── design-guidelines/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── gallery/
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── geo-map/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── image/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── image-gallery/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── instagram-post/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── item-carousel/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── layout.tsx
│ │ │ ├── link-preview/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── linkedin-post/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── message-draft/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── option-list/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── order-summary/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── overview/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── page.tsx
│ │ │ ├── parameter-slider/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── plan/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── preferences-panel/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── progress-tracker/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── question-flow/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── quick-start/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── receipts/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── stats-display/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── terminal/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── video/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── weather-widget/
│ │ │ │ ├── content.mdx
│ │ │ │ ├── opengraph-image.tsx
│ │ │ │ └── page.tsx
│ │ │ └── x-post/
│ │ │ ├── content.mdx
│ │ │ ├── opengraph-image.tsx
│ │ │ └── page.tsx
│ │ ├── global-error.tsx
│ │ ├── layout.tsx
│ │ ├── not-found.tsx
│ │ ├── opengraph-image.tsx
│ │ ├── page.tsx
│ │ ├── playground/
│ │ │ ├── chat-pane.tsx
│ │ │ ├── chat-ui.tsx
│ │ │ ├── opengraph-image.tsx
│ │ │ ├── page.tsx
│ │ │ ├── tool-inspector.tsx
│ │ │ └── waymo-demo/
│ │ │ ├── opengraph-image.tsx
│ │ │ └── page.tsx
│ │ ├── sandbox/
│ │ │ ├── celestial-effect/
│ │ │ │ ├── celestial-canvas.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── cloud-effect/
│ │ │ │ ├── cloud-canvas.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── lightning-effect/
│ │ │ │ ├── lightning-canvas.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── page.tsx
│ │ │ ├── rain-effect/
│ │ │ │ ├── page.tsx
│ │ │ │ └── rain-canvas.tsx
│ │ │ ├── snow-effect/
│ │ │ │ ├── page.tsx
│ │ │ │ └── snow-canvas.tsx
│ │ │ ├── weather-compositor/
│ │ │ │ ├── celestial-canvas.tsx
│ │ │ │ ├── interpolation.ts
│ │ │ │ ├── page.tsx
│ │ │ │ ├── presets.ts
│ │ │ │ └── tuned-presets.json
│ │ │ ├── weather-effects/
│ │ │ │ └── page.tsx
│ │ │ ├── weather-tuning/
│ │ │ │ ├── components/
│ │ │ │ │ ├── checkpoint-dots.tsx
│ │ │ │ │ ├── condition-sidebar.tsx
│ │ │ │ │ ├── detail-editor.tsx
│ │ │ │ │ ├── export-panel.tsx
│ │ │ │ │ ├── glass-controls.tsx
│ │ │ │ │ ├── parameter-definitions.ts
│ │ │ │ │ ├── parameter-matrix-view.tsx
│ │ │ │ │ ├── parameter-panel.tsx
│ │ │ │ │ ├── parameter-row.tsx
│ │ │ │ │ ├── time-dial.tsx
│ │ │ │ │ ├── time-matrix-view.tsx
│ │ │ │ │ ├── view-mode-toggle.tsx
│ │ │ │ │ └── weather-data-overlay.tsx
│ │ │ │ ├── hooks/
│ │ │ │ │ └── use-tuning-state.ts
│ │ │ │ ├── lib/
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── has-any-tuning-delta.ts
│ │ │ │ │ ├── list-updated-params.ts
│ │ │ │ │ ├── map-to-canvas-props.ts
│ │ │ │ │ ├── recover-repo-overrides.ts
│ │ │ │ │ ├── resolve-params.ts
│ │ │ │ │ ├── studio-timestamp.ts
│ │ │ │ │ ├── tool-ui-export.ts
│ │ │ │ │ ├── tool-ui-import.ts
│ │ │ │ │ └── workflow-state.ts
│ │ │ │ ├── page.tsx
│ │ │ │ └── types.ts
│ │ │ ├── weather-widget/
│ │ │ │ └── page.tsx
│ │ │ ├── weather-widget-production/
│ │ │ │ ├── page.tsx
│ │ │ │ └── runtime-input.ts
│ │ │ └── weather-widget-stress/
│ │ │ └── page.tsx
│ │ ├── staging/
│ │ │ ├── _components/
│ │ │ │ ├── rounded-rect-overlay.tsx
│ │ │ │ ├── staging-canvas.tsx
│ │ │ │ ├── staging-showcase.tsx
│ │ │ │ ├── staging-toolbar.tsx
│ │ │ │ ├── use-keyboard-shortcuts.ts
│ │ │ │ └── use-staging-state.ts
│ │ │ ├── layout.tsx
│ │ │ └── page.tsx
│ │ └── styles/
│ │ ├── builder-loader.css
│ │ ├── custom-utilities.css
│ │ ├── fumadocs-overrides.css
│ │ ├── globals.css
│ │ ├── leaflet-overrides.css
│ │ ├── nav-sheet.css
│ │ ├── prose.css
│ │ ├── shadcn-theme.css
│ │ ├── squircle.css
│ │ └── theme-transition.css
│ ├── components/
│ │ ├── assistant-ui/
│ │ │ ├── assistant-modal.tsx
│ │ │ ├── attachment.tsx
│ │ │ ├── markdown-text.tsx
│ │ │ ├── reasoning.tsx
│ │ │ ├── shiki-highlighter.tsx
│ │ │ ├── thread-list.tsx
│ │ │ ├── thread.tsx
│ │ │ ├── threadlist-sidebar.tsx
│ │ │ ├── tool-fallback.tsx
│ │ │ └── tooltip-icon-button.tsx
│ │ ├── tool-ui/
│ │ │ ├── approval-card/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── approval-card.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── audio/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── audio.tsx
│ │ │ │ ├── context.tsx
│ │ │ │ ├── index.ts
│ │ │ │ └── schema.ts
│ │ │ ├── chart/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── chart.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── citation/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── citation-list.tsx
│ │ │ │ ├── citation.tsx
│ │ │ │ ├── index.ts
│ │ │ │ └── schema.ts
│ │ │ ├── code-block/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── code-block.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── code-diff/
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── code-diff.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── data-table/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── data-table.tsx
│ │ │ │ ├── formatters.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── schema.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── utilities.ts
│ │ │ ├── geo-map/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── geo-map-engine.tsx
│ │ │ │ ├── geo-map-icons.ts
│ │ │ │ ├── geo-map-overlays.tsx
│ │ │ │ ├── geo-map-theme.module.css
│ │ │ │ ├── geo-map.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── image/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── image.tsx
│ │ │ │ ├── index.ts
│ │ │ │ └── schema.ts
│ │ │ ├── image-gallery/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── context.tsx
│ │ │ │ ├── gallery-grid.tsx
│ │ │ │ ├── gallery-lightbox.tsx
│ │ │ │ ├── image-gallery.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── schema.ts
│ │ │ │ └── styles.css
│ │ │ ├── index.ts
│ │ │ ├── instagram-post/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── instagram-post.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── item-carousel/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── item-card.tsx
│ │ │ │ ├── item-carousel.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── link-preview/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── link-preview.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── linkedin-post/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── linkedin-post.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── message-draft/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── message-draft.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── option-list/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── option-list.tsx
│ │ │ │ ├── schema.ts
│ │ │ │ └── selection.ts
│ │ │ ├── order-summary/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── order-summary.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── parameter-slider/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── math.ts
│ │ │ │ ├── parameter-slider.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── plan/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── plan.tsx
│ │ │ │ ├── progress.ts
│ │ │ │ └── schema.ts
│ │ │ ├── preferences-panel/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── preferences-panel.tsx
│ │ │ │ ├── schema.ts
│ │ │ │ └── signature.ts
│ │ │ ├── progress-tracker/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── progress-tracker.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── question-flow/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── question-flow.tsx
│ │ │ │ └── schema.ts
│ │ │ ├── shared/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── action-buttons.tsx
│ │ │ │ ├── actions-config.ts
│ │ │ │ ├── contract.ts
│ │ │ │ ├── decision-actions.tsx
│ │ │ │ ├── embedded-actions.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── local-actions.tsx
│ │ │ │ ├── media/
│ │ │ │ │ ├── aspect-ratio.ts
│ │ │ │ │ ├── format-utils.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── overlay-gradient.ts
│ │ │ │ │ ├── safe-navigation.ts
│ │ │ │ │ └── sanitize-href.ts
│ │ │ │ ├── parse.ts
│ │ │ │ ├── pierre-dark-theme.js
│ │ │ │ ├── pierre-light-theme.js
│ │ │ │ ├── schema.ts
│ │ │ │ ├── tool-ui-context.tsx
│ │ │ │ ├── tool-ui.tsx
│ │ │ │ ├── toolkit.tsx
│ │ │ │ ├── use-action-buttons.tsx
│ │ │ │ ├── use-controllable-state.ts
│ │ │ │ ├── use-copy-to-clipboard.ts
│ │ │ │ ├── use-signature-reset.ts
│ │ │ │ └── utils.ts
│ │ │ ├── stats-display/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── schema.ts
│ │ │ │ ├── sparkline.tsx
│ │ │ │ └── stats-display.tsx
│ │ │ ├── terminal/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── schema.ts
│ │ │ │ └── terminal.tsx
│ │ │ ├── video/
│ │ │ │ ├── README.md
│ │ │ │ ├── _adapter.tsx
│ │ │ │ ├── context.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── schema.ts
│ │ │ │ ├── video-helpers.ts
│ │ │ │ └── video.tsx
│ │ │ ├── weather-widget/
│ │ │ │ ├── generated/
│ │ │ │ │ └── weather-runtime-core.generated.ts
│ │ │ │ ├── runtime.ts
│ │ │ │ ├── schema-runtime.ts
│ │ │ │ ├── weather-data-overlay.tsx
│ │ │ │ └── weather-widget-container.tsx
│ │ │ └── x-post/
│ │ │ ├── README.md
│ │ │ ├── _adapter.tsx
│ │ │ ├── index.ts
│ │ │ ├── schema.ts
│ │ │ └── x-post.tsx
│ │ └── ui/
│ │ ├── accordion.tsx
│ │ ├── alert.tsx
│ │ ├── avatar.tsx
│ │ ├── badge.tsx
│ │ ├── button-group.tsx
│ │ ├── button.tsx
│ │ ├── card.tsx
│ │ ├── chart.tsx
│ │ ├── code-block.tsx
│ │ ├── collapsible.tsx
│ │ ├── dialog.tsx
│ │ ├── dropdown-menu.tsx
│ │ ├── input-group.tsx
│ │ ├── input.tsx
│ │ ├── item.tsx
│ │ ├── label.tsx
│ │ ├── logo.tsx
│ │ ├── popover.tsx
│ │ ├── radio-group.tsx
│ │ ├── select.tsx
│ │ ├── separator.tsx
│ │ ├── sheet.tsx
│ │ ├── sidebar.tsx
│ │ ├── skeleton.tsx
│ │ ├── slider.tsx
│ │ ├── switch.tsx
│ │ ├── table.tsx
│ │ ├── tabs.tsx
│ │ ├── textarea.tsx
│ │ ├── toggle-group.tsx
│ │ ├── toggle.tsx
│ │ └── tooltip.tsx
│ ├── components.json
│ ├── css.d.ts
│ ├── docs/
│ │ ├── changelog.md
│ │ └── tests.md
│ ├── eslint.config.ts
│ ├── hooks/
│ │ ├── use-extract-headings.ts
│ │ ├── use-headings-observer.ts
│ │ ├── use-mobile.ts
│ │ ├── use-preset-param.ts
│ │ ├── use-reduced-motion.ts
│ │ ├── use-responsive-preview.ts
│ │ ├── use-tab-search-param.ts
│ │ └── use-toc-keyboard-nav.ts
│ ├── lib/
│ │ ├── analytics.ts
│ │ ├── changelog/
│ │ │ ├── changelog.ts
│ │ │ ├── git.ts
│ │ │ └── inference.ts
│ │ ├── demo-chat/
│ │ │ └── toolkit.tsx
│ │ ├── docs/
│ │ │ ├── auto-link.tsx
│ │ │ ├── component-ids.ts
│ │ │ ├── component-registry.ts
│ │ │ ├── gallery-component-docs.ts
│ │ │ ├── gallery-layout.ts
│ │ │ ├── gallery-usage-code.ts
│ │ │ ├── install-snippet-analytics.ts
│ │ │ └── preview-config.tsx
│ │ ├── eslint/
│ │ │ └── tool-ui-action-model-plugin.ts
│ │ ├── integrations/
│ │ │ ├── freestyle/
│ │ │ │ ├── create-chat.ts
│ │ │ │ └── get-code.ts
│ │ │ └── rate-limit/
│ │ │ └── upstash.ts
│ │ ├── mocks/
│ │ │ ├── chat-showcase-data.ts
│ │ │ ├── stocks.ts
│ │ │ └── tasks.ts
│ │ ├── og/
│ │ │ └── og-image.tsx
│ │ ├── playground/
│ │ │ ├── constants.ts
│ │ │ ├── index.ts
│ │ │ ├── mocks.ts
│ │ │ ├── prototypes/
│ │ │ │ ├── food-ordering/
│ │ │ │ │ ├── get-menu.ts
│ │ │ │ │ ├── get-restaurant-details.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── place-order.ts
│ │ │ │ │ ├── search-restaurants.ts
│ │ │ │ │ └── shared.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── waymo/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── WaymoDemo.tsx
│ │ │ │ │ ├── check-ride-prices.ts
│ │ │ │ │ ├── components/
│ │ │ │ │ │ ├── BookingConfirmation.tsx
│ │ │ │ │ │ ├── RideQuote.tsx
│ │ │ │ │ │ └── index.tsx
│ │ │ │ │ ├── confirm-ride-booking.ts
│ │ │ │ │ ├── confirm-user-payment.ts
│ │ │ │ │ ├── get-profile-context.ts
│ │ │ │ │ ├── get-user-destination.ts
│ │ │ │ │ ├── get-user-location.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── precheck-prices.ts
│ │ │ │ │ ├── request-payment-method.ts
│ │ │ │ │ ├── schedule-ride.ts
│ │ │ │ │ ├── search-places.ts
│ │ │ │ │ ├── select-frequent-location-tool.tsx
│ │ │ │ │ ├── shared.ts
│ │ │ │ │ ├── show-ride-details.ts
│ │ │ │ │ ├── show-ride-options.ts
│ │ │ │ │ ├── system-message-v2.ts
│ │ │ │ │ ├── toggle-gps.ts
│ │ │ │ │ ├── tools.ts
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── wip-tool-uis/
│ │ │ │ │ ├── FrequentLocationSelector.tsx
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── TOOL-UI-PATTERNS.md
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ ├── ux-v3.md
│ │ │ │ │ └── ux.md
│ │ │ │ └── waymo-v2/
│ │ │ │ ├── DESIGN.md
│ │ │ │ ├── components/
│ │ │ │ │ ├── DestinationPicker.tsx
│ │ │ │ │ ├── PickupPicker.tsx
│ │ │ │ │ ├── RideQuote.tsx
│ │ │ │ │ ├── TripStatus.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── system-prompt.ts
│ │ │ │ ├── tools/
│ │ │ │ │ ├── get-ride-quote.tsx
│ │ │ │ │ ├── get-trip-status.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── select-destination.tsx
│ │ │ │ │ └── select-pickup.tsx
│ │ │ │ └── types.ts
│ │ │ ├── registry.ts
│ │ │ ├── runtime.ts
│ │ │ ├── tool-uis.ts
│ │ │ ├── types.ts
│ │ │ └── weather-tuning/
│ │ │ ├── has-any-tuning-delta.test.ts
│ │ │ ├── list-updated-params.test.ts
│ │ │ ├── parameter-definitions-coverage.test.ts
│ │ │ ├── rain-param-ranges.test.ts
│ │ │ ├── recover-repo-overrides.test.ts
│ │ │ ├── resolve-params.test.ts
│ │ │ ├── snow-fall-speed-range.test.ts
│ │ │ ├── studio-timestamp.test.ts
│ │ │ ├── tool-ui-export.test.ts
│ │ │ ├── tool-ui-import.test.ts
│ │ │ └── workflow-state.test.ts
│ │ ├── presets/
│ │ │ ├── approval-card.ts
│ │ │ ├── audio.ts
│ │ │ ├── chart.ts
│ │ │ ├── citation.ts
│ │ │ ├── code-block.ts
│ │ │ ├── code-diff.ts
│ │ │ ├── data-table.ts
│ │ │ ├── geo-map.ts
│ │ │ ├── image-gallery.ts
│ │ │ ├── image.ts
│ │ │ ├── instagram-post.ts
│ │ │ ├── item-carousel.ts
│ │ │ ├── link-preview.ts
│ │ │ ├── linkedin-post.ts
│ │ │ ├── message-draft.ts
│ │ │ ├── option-list.ts
│ │ │ ├── order-summary.ts
│ │ │ ├── parameter-slider.ts
│ │ │ ├── plan.ts
│ │ │ ├── preferences-panel.ts
│ │ │ ├── progress-tracker.ts
│ │ │ ├── question-flow.ts
│ │ │ ├── stats-display.ts
│ │ │ ├── terminal.ts
│ │ │ ├── types.ts
│ │ │ ├── video.ts
│ │ │ ├── weather-widget.ts
│ │ │ └── x-post.ts
│ │ ├── registry/
│ │ │ └── tool-ui-registry.ts
│ │ ├── staging/
│ │ │ ├── configs/
│ │ │ │ ├── parameter-slider.tsx
│ │ │ │ ├── plan.tsx
│ │ │ │ ├── progress-tracker.tsx
│ │ │ │ └── stats-display.tsx
│ │ │ ├── staging-config.ts
│ │ │ └── types.ts
│ │ ├── system/
│ │ │ └── tool-builder-message.ts
│ │ ├── tests/
│ │ │ ├── app/
│ │ │ │ └── leaflet-css-import.test.ts
│ │ │ ├── docs/
│ │ │ │ ├── header-preview-tabs-hydration.test.ts
│ │ │ │ └── tracked-dynamic-codeblock.test.ts
│ │ │ ├── registry/
│ │ │ │ └── tool-ui-registry.test.ts
│ │ │ ├── setup/
│ │ │ │ └── console-guard.ts
│ │ │ └── tool-ui/
│ │ │ ├── docs/
│ │ │ │ ├── changelog-inference-parser.test.ts
│ │ │ │ ├── changelog-inference-prompt.test.ts
│ │ │ │ ├── docs-search-shortcut.test.ts
│ │ │ │ ├── gallery-layout.test.ts
│ │ │ │ └── install-snippet-analytics.test.ts
│ │ │ ├── geo-map/
│ │ │ │ ├── geo-map-render.test.ts
│ │ │ │ ├── schema.test.ts
│ │ │ │ └── spatial.test.ts
│ │ │ ├── scripts/
│ │ │ │ └── install-git-hooks.test.ts
│ │ │ ├── shared/
│ │ │ │ └── safe-navigation.test.ts
│ │ │ ├── social/
│ │ │ │ └── link-sanitization.test.ts
│ │ │ ├── video/
│ │ │ │ └── media-events.test.ts
│ │ │ └── weather-widget/
│ │ │ ├── canvas-resolver-parity.test.ts
│ │ │ ├── glass-style-resolver.test.ts
│ │ │ ├── parameter-mapper.test.ts
│ │ │ ├── production-runtime-harness.test.ts
│ │ │ ├── weather-data-overlay-observer.test.ts
│ │ │ ├── weather-runtime-codegen.test.ts
│ │ │ ├── weather-widget-layout.test.ts
│ │ │ └── webgl-budget-guard.test.ts
│ │ ├── ui/
│ │ │ └── cn.ts
│ │ ├── utils.ts
│ │ ├── weather-authoring/
│ │ │ ├── presets/
│ │ │ │ └── tuned-presets.json
│ │ │ ├── runtime/
│ │ │ │ └── glass-panel-svg.tsx
│ │ │ ├── shaders/
│ │ │ │ ├── celestial.frag.glsl
│ │ │ │ ├── cloud.frag.glsl
│ │ │ │ ├── composite.frag.glsl
│ │ │ │ ├── fullscreen.vert.glsl
│ │ │ │ ├── lightning.frag.glsl
│ │ │ │ ├── rain.frag.glsl
│ │ │ │ └── snow.frag.glsl
│ │ │ ├── shared/
│ │ │ │ └── contract.ts
│ │ │ └── weather-widget/
│ │ │ ├── README.md
│ │ │ ├── _adapter.tsx
│ │ │ ├── effects/
│ │ │ │ ├── canvas-resolver-base.ts
│ │ │ │ ├── canvas-resolver-runtime.ts
│ │ │ │ ├── canvas-resolver.ts
│ │ │ │ ├── checkpoint-overrides.ts
│ │ │ │ ├── custom-effect-props.ts
│ │ │ │ ├── effect-compositor-custom-props.ts
│ │ │ │ ├── effect-compositor-quality.ts
│ │ │ │ ├── effect-compositor-runtime.tsx
│ │ │ │ ├── effect-compositor.tsx
│ │ │ │ ├── generated/
│ │ │ │ │ ├── glass-panel-svg.generated.tsx
│ │ │ │ │ ├── tuned-presets.generated.ts
│ │ │ │ │ └── weather-effect-shaders.generated.ts
│ │ │ │ ├── glass-panel-svg.tsx
│ │ │ │ ├── glass-style-resolver.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── parameter-mapper.generated.js
│ │ │ │ ├── parameter-mapper.ts
│ │ │ │ ├── tuned-presets.ts
│ │ │ │ ├── tuning.ts
│ │ │ │ ├── types.ts
│ │ │ │ ├── use-glass-region.ts
│ │ │ │ ├── use-glass-styles.ts
│ │ │ │ ├── use-weather-effects-renderer.generated.js
│ │ │ │ ├── use-weather-effects-renderer.ts
│ │ │ │ ├── weather-compositor-types.ts
│ │ │ │ ├── weather-effect-gl.ts
│ │ │ │ ├── weather-effect-render-passes.generated.js
│ │ │ │ ├── weather-effect-render-passes.ts
│ │ │ │ ├── weather-effect-shaders.ts
│ │ │ │ ├── weather-effects-canvas.tsx
│ │ │ │ ├── weather-effects-defaults.ts
│ │ │ │ ├── weather-effects-props.ts
│ │ │ │ ├── weather-effects-types.ts
│ │ │ │ └── weather-webgl-budget.ts
│ │ │ ├── index.tsx
│ │ │ ├── schema-runtime.ts
│ │ │ ├── schema.ts
│ │ │ ├── time.ts
│ │ │ ├── weather-data-overlay.generated.ts
│ │ │ ├── weather-data-overlay.tsx
│ │ │ ├── weather-runtime-core.ts
│ │ │ ├── weather-widget-container.tsx
│ │ │ └── weather-widget.tsx
│ │ └── weather-codegen/
│ │ └── compile-weather-runtime.ts
│ ├── mdx-components.tsx
│ ├── next.config.ts
│ ├── package.json
│ ├── postcss.config.mjs
│ ├── proxy.ts
│ ├── public/
│ │ └── r/
│ │ ├── approval-card.json
│ │ ├── audio.json
│ │ ├── chart.json
│ │ ├── citation.json
│ │ ├── code-block.json
│ │ ├── code-diff.json
│ │ ├── data-table.json
│ │ ├── geo-map.json
│ │ ├── image-gallery.json
│ │ ├── image.json
│ │ ├── instagram-post.json
│ │ ├── item-carousel.json
│ │ ├── link-preview.json
│ │ ├── linkedin-post.json
│ │ ├── message-draft.json
│ │ ├── option-list.json
│ │ ├── order-summary.json
│ │ ├── parameter-slider.json
│ │ ├── plan.json
│ │ ├── preferences-panel.json
│ │ ├── progress-tracker.json
│ │ ├── question-flow.json
│ │ ├── registry.json
│ │ ├── stats-display.json
│ │ ├── terminal.json
│ │ ├── video.json
│ │ ├── weather-widget.json
│ │ └── x-post.json
│ ├── scripts/
│ │ ├── build-tool-ui-registry.ts
│ │ ├── check-changelog.ts
│ │ ├── compile-weather-runtime.ts
│ │ ├── generate-changelog.ts
│ │ ├── install-git-hooks.ts
│ │ ├── new-tool-ui-component.ts
│ │ ├── precommit-registry-sync.ts
│ │ └── registry-check.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── package.json
├── packages/
│ └── agent/
│ ├── package.json
│ ├── plugin/
│ │ ├── .claude-plugin/
│ │ │ └── plugin.json
│ │ └── skills/
│ │ └── tool-ui/
│ │ └── SKILL.md
│ ├── src/
│ │ └── cli.ts
│ ├── tsconfig.json
│ └── tsup.config.ts
├── pnpm-workspace.yaml
└── skills-lock.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .changeset/config.json
================================================
{
"$schema": "https://unpkg.com/@changesets/config@3.0.1/schema.json",
"access": "public",
"privatePackages": {
"version": false
}
}
================================================
FILE: .git-blame-ignore-revs
================================================
# oxfmt bulk reformat (Prettier → Oxfmt migration)
e052c5666f770d1521b8e5e574d2fa69152f89dc
================================================
FILE: .githooks/pre-commit
================================================
#!/usr/bin/env sh
set -eu
pnpm hooks:pre-commit
pnpm lint-staged
================================================
FILE: .githooks/pre-push
================================================
#!/usr/bin/env sh
set -eu
pnpm hooks:pre-push
================================================
FILE: .github/pull_request_template.md
================================================
## Summary
## Verification
- [ ] Ran `pnpm verify:ci`
- [ ] Committed updated `public/r` artifacts when Tool UI or registry sources changed
================================================
FILE: .github/workflows/changeset.yaml
================================================
name: Changesets
on:
push:
branches:
- main
permissions:
contents: write
pull-requests: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CI: true
jobs:
version:
name: Create Version PR
runs-on: ubuntu-latest
steps:
- name: Checkout code repository
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Create version PR
id: changesets
uses: changesets/action@v1
with:
commit: "chore: update versions"
title: "chore: update versions"
version: pnpm ci:version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check if any packages need publishing
id: check-publish
if: steps.changesets.outputs.hasChangesets == 'false'
run: |
needs_publish="false"
for pkg in packages/*/package.json; do
[ -f "$pkg" ] || continue
name=$(jq -r '.name' "$pkg")
version=$(jq -r '.version' "$pkg")
private=$(jq -r '.private // false' "$pkg")
if [ "$private" = "true" ]; then
echo "Skipping private package: $name"
continue
fi
if npm view "${name}@${version}" version 2>/dev/null | grep -q "${version}"; then
echo "✓ ${name}@${version} already published"
else
echo "✗ ${name}@${version} needs publishing"
needs_publish="true"
fi
done
echo "needsPublish=${needs_publish}" >> $GITHUB_OUTPUT
- name: Trigger npm publish
if: steps.changesets.outputs.hasChangesets == 'false' && steps.check-publish.outputs.needsPublish == 'true'
uses: actions/github-script@v7
with:
script: |
await github.rest.repos.createDispatchEvent({
owner: context.repo.owner,
repo: context.repo.repo,
event_type: 'npm-publish'
});
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Format check
run: pnpm lint:format
- name: Lint - Oxlint
run: pnpm lint:oxlint
- name: Lint - ESLint custom rules
run: pnpm lint:eslint
- name: Typecheck
run: pnpm typecheck
- name: Test
run: pnpm test
- name: Check changelog structure
run: pnpm changelog:check
- name: Verify registry artifacts are up to date
run: pnpm registry:check
================================================
FILE: .github/workflows/npm-publish.yaml
================================================
name: npm Publish
on:
repository_dispatch:
types: [npm-publish]
permissions:
id-token: write
contents: write
env:
CI: true
jobs:
publish:
name: Publish to npm
if: github.ref == 'refs/heads/main'
environment: npm Publish
runs-on: ubuntu-latest
steps:
- name: Checkout code repository
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup node.js
uses: actions/setup-node@v6
with:
node-version: 24
registry-url: "https://registry.npmjs.org"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Publish to npm
run: pnpm ci:publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Create GitHub Releases
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git fetch --tags
for pkg in packages/*/package.json; do
name=$(jq -r '.name' "$pkg")
version=$(jq -r '.version' "$pkg")
private=$(jq -r '.private // false' "$pkg")
[[ "$private" == "true" ]] && continue
tag="${name}@${version}"
git rev-parse "$tag" >/dev/null 2>&1 || continue
gh release view "$tag" >/dev/null 2>&1 && continue
changelog_dir=$(dirname "$pkg")
changelog="$changelog_dir/CHANGELOG.md"
notes=""
if [[ -f "$changelog" ]]; then
notes=$(awk "/^## ${version//./\\.}\$/,/^## [0-9]/" "$changelog" | head -n -1 | tail -n +2)
fi
[[ -z "$notes" ]] && notes="Release ${tag}"
echo "Creating release: $tag"
gh release create "$tag" \
--title "$tag" \
--notes "$notes" \
--verify-tag || echo "Warning: Failed to create release for $tag"
done
================================================
FILE: .gitignore
================================================
# Dependencies
node_modules
/.pnp
.pnp.*
# Testing
coverage
# Next.js
.next/
out/
# Production
build
dist
# Misc
.DS_Store
*.pem
private
# Debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# Local env files
.env*.local
.env
# Vercel
.vercel
# TypeScript
*.tsbuildinfo
next-env.d.ts
# Turbo
.turbo
# Cursor
.cursor
# Claude
.claude/
# VSCode
.vscode/
.vscode.playwright-mcp/
.vscode/terminals.json
.playwright-mcp
================================================
FILE: .prettierignore
================================================
# Generated artifacts (managed by build scripts)
apps/www/public/r/
apps/www/components/tool-ui/weather-widget/generated/
apps/www/lib/weather-authoring/weather-widget/effects/generated/
apps/www/lib/weather-authoring/weather-widget/weather-data-overlay.generated.ts
================================================
FILE: AGENTS.md
================================================
# AGENTS.md
## Cursor Cloud specific instructions
### Project overview
Tool UI is a Next.js 16 documentation/demo site and copy-paste component library for AI assistant interfaces. The app lives in `apps/www/` within a pnpm monorepo. There is no database, no Docker, and no required background services beyond the Node.js dev server.
### Running services
- **Dev server**: `pnpm dev` (Turbopack, port 3000). The static docs, gallery, and component previews work without any API keys.
- **Chat/Playground features** require `OPENAI_API_KEY` in `.env` (see `.env.example`). Without it the chat API routes return errors, but the rest of the site functions normally.
### Commands reference
All standard commands are documented in `CLAUDE.md`. Key ones:
| Task | Command |
| ------------------------- | ---------------- |
| Dev server | `pnpm dev` |
| Lint + typecheck + format | `pnpm check` |
| Tests (Vitest) | `pnpm test` |
| Fix lint issues | `pnpm lint:fix` |
| Typecheck only | `pnpm typecheck` |
### Non-obvious caveats
- **Typecheck uses `tsgo`** (`@typescript/native-preview`), not standard `tsc`. The `pnpm typecheck` command runs `tsgo --noEmit`.
- **Formatter is `oxfmt`**, not Prettier. Run `pnpm format` to format or `pnpm format:check` to verify. It handles Tailwind class sorting and import sorting.
- **Linting is split**: `oxlint` handles standard rules; `eslint` is retained only for `no-restricted-syntax`, `no-restricted-imports`, custom `tool-ui/*` rules, and React Compiler hooks. `pnpm check` runs both in parallel.
- **`pnpm install` triggers `prepare`** which sets up git hooks via `tsx apps/www/scripts/install-git-hooks.ts`. The hooks directory is `.githooks/`.
- **Pre-existing lint warnings** (60 warnings, 0 errors): these are known oxlint a11y warnings in the codebase and are not regressions.
- **Build uses `--experimental-build-mode=compile`**: `pnpm build` runs `next build --experimental-build-mode=compile`.
================================================
FILE: AGENT_CHANGELOG.md
================================================
# Agent Changelog
> This file helps coding agents understand project evolution, key decisions, and deprecated patterns.
> Updated: 2026-02-11
## Current State Summary
Tool UI is a maintainer-owned copy/paste component library (shadcn/ui model) for AI assistant interfaces with a registry-first install path (`https://tool-ui.com/r/<component>.json`). Component APIs are flat, receipt semantics are unified on `choice`, and component directories remain the product surface (`schema`, `component`, `README`, exports). Registry adapters now use `@/lib/utils` for `cn` (no registry-shipped `lib/ui/cn.ts`), Tool UI component motion is constrained to Tailwind/tw-animate-compatible classes, and docs place Source/Install + GitHub source links ahead of feature marketing sections.
## Stale Information Detected
| Location | States | Reality | Since |
| -------------------------------------------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------- |
| `README.md` (Shadcn Registry section) | Registry artifacts include `lib/ui/cn.ts` | Registry adapters use `@/lib/utils`; `lib/ui/cn.ts` is no longer part of generated install artifacts | 2026-02 |
| `.claude/plans/plan-sequential-munching-canyon.md` | References `hooks/use-code-gen.ts` TypeScript generation | Tuning flow is apply/recover via repo routes; `use-code-gen.ts` removed | 2026-02 |
| `.claude/plans/plan-sequential-munching-canyon.md` | Targets deletion of `app/sandbox/weather-compositor/` | `weather-tuning` still imports compositor presets/interpolation modules; compositor remains active | 2026-02 |
| `.claude/docs/component-workflow.md` | New component contract requires `error-boundary.tsx` | Error-boundary layer was removed from component contracts; index exports no longer include local error boundaries | 2026-02 |
| `.claude/agents/tool-ui-implementer.md` | Instructs creating `error-boundary.tsx` and using `createToolUiErrorBoundary` | Error-boundary wrappers were removed; component contract now centers on `_adapter`, schema, component, index, README | 2026-02 |
| `.claude/agents/tool-ui-reviewer.md` | Blocks review if `error-boundary.tsx` is missing | `error-boundary.tsx` is no longer required in component directories | 2026-02 |
| `.claude/compiled/component-creation.md` | Uses `../shared` barrel and error-boundary scaffolding in canonical template | Current standards forbid `../shared` barrel imports for core logic and remove per-component error boundary scaffolds | 2026-02 |
| `docs/plans/2026-01-22-feat-wizard-step-component-plan.md` | Active implementation target is `WizardStep` at `components/tool-ui/wizard-step/*` | Implemented component is `QuestionFlow` at `components/tool-ui/question-flow/*` | 2026-01 |
| `docs/plans/2026-01-23-feat-wizard-step-visual-polish-plan.md` | Polish targets `WizardStep` paths and naming | Final shipped component naming/path is `QuestionFlow` | 2026-01 |
## Timeline
### 2026-02-11 — Component Docs Prioritize Install + Source Visibility
**What changed:** All component docs were normalized so `## Source and Install` appears above `## Key Features`, with a GitHub source link for each component (`components/tool-ui/<id>`).
Highlights:
- Reordered sections across all component docs to surface install instructions first
- Normalized mixed `## Features`/`## Key Features` headings to `## Key Features`
- Added docs contract enforcement to prevent regressions in section order and source-link presence
**Why:** Make integration steps and source discovery immediately visible for maintainers/copy-paste users.
**Agent impact:** In component docs, place install/source sections before feature callouts. Include both:
- `npx shadcn@latest add https://tool-ui.com/r/<component>.json`
- GitHub source link to `components/tool-ui/<component>`
**Files:** `app/docs/*/content.mdx`, `lib/tests/tool-ui/docs/registry-installation-contract.test.ts`
---
### 2026-02-11 — Tool UI Animation Portability Standardized for Registry Consumers
**What changed:** Tool UI components were migrated off repo-private animation keyframes and now rely on Tailwind/tw-animate-compatible classes only.
Highlights:
- Replaced private animation names (e.g. `spring-bounce`, `check-draw`, `fade-blur-in`, `progress-pulse`) in shipped component code
- Removed inline `@keyframes` from `stats-display/sparkline`
- Added portability contract tests that fail on private keyframe tokens or inline keyframes in source and generated registry artifacts
- Added registry dependency assertions for motion primitives (`accordion`/`collapsible`)
**Why:** Prevent no-op/broken transitions in downstream shadcn apps that do not include this repo’s private CSS.
**Agent impact:** For `components/tool-ui/**`, use Tailwind/tw-animate classes (`animate-in/out`, fade/zoom/slide, `animate-spin`, `animate-pulse`) and avoid custom keyframe names unless they are provided by stock shadcn/tw-animate setup.
**Files:** `components/tool-ui/plan/plan.tsx`, `components/tool-ui/progress-tracker/progress-tracker.tsx`, `components/tool-ui/question-flow/question-flow.tsx`, `components/tool-ui/approval-card/approval-card.tsx`, `components/tool-ui/option-list/option-list.tsx`, `components/tool-ui/stats-display/sparkline.tsx`, `lib/tests/tool-ui/docs/animation-portability-contract.test.ts`, `lib/tests/registry/tool-ui-registry.test.ts`
---
### 2026-02-11 — Registry Adapter `cn` Dependency Migrated to shadcn `@/lib/utils`
**What changed:** Registry component adapters were updated to import `cn` from `@/lib/utils`; generated artifacts no longer rely on/emit `lib/ui/cn.ts`.
Highlights:
- Adapter imports switched from `@/lib/ui/cn` to `@/lib/utils`
- Registry artifact checks updated accordingly
- Fresh install path validated against root-level shadcn command and hosted component JSON URLs
**Why:** Align Tool UI install output with stock shadcn app structure and eliminate repo-specific `cn` scaffolding.
**Agent impact:** For registry-consumed component adapters, expect:
- `import { cn } from "@/lib/utils"`
- no generated `lib/ui/cn.ts` dependency
**Files:** `components/tool-ui/*/_adapter.tsx`, `lib/tests/registry/tool-ui-registry.test.ts`, `app/docs/quick-start/content.mdx`, `public/r/*.json`
---
### 2026-02-11 — Registry-First Install Path Finalized; ZIP/Manual Guidance Removed
**What changed:** Docs were converted to a single registry-first install flow using full component URLs, and legacy ZIP/manual copy instructions were removed.
**Why:** Reduce install ambiguity and support a single canonical setup path for consumers.
**Agent impact:** Use only:
- `npx shadcn@latest add https://tool-ui.com/r/<component>.json`
Do not propose ZIP/manual copy workflows.
**Files:** `app/docs/*/content.mdx`, `app/docs/quick-start/content.mdx`, `lib/tests/tool-ui/docs/registry-installation-contract.test.ts`
---
### 2026-02-11 — Import Boundary Enforcement + Error Boundary Layer Removal
**What changed:** Tool UI component contracts were tightened around portability boundaries and local adapter ownership.
Highlights:
- Removed per-component `error-boundary.tsx` files and related exports across component directories
- Normalized component `_adapter.tsx` files to alias-based UI imports
- Enforced adapter-only UI primitive imports via ESLint (`@/components/ui/*` and `@/lib/ui/cn` are restricted outside `_adapter.tsx`)
- Hardened registry/ID contracts and tests (`data-table` row keys, `question-flow` ids, registry generation edge cases like OS metadata files)
**Why:** Reduce copy/paste friction, prevent component-internal import drift, and keep portability constraints enforceable by lint/tests instead of convention.
**Agent impact:** Do not add local `error-boundary.tsx` files for new components. In non-adapter component modules, import UI primitives and `cn` only from `./_adapter`; keep shared imports as direct leaf modules (`../shared/*`), not barrels.
**Files:** `eslint.config.ts`, `components/tool-ui/*/_adapter.tsx`, `components/tool-ui/*/index.ts*`, `lib/registry/tool-ui-registry.ts`, `lib/tests/tool-ui/data-table/row-keys-contract.test.ts`, `lib/tests/tool-ui/question-flow/ids-contract.test.ts`, `lib/tests/registry/tool-ui-registry.test.ts`
---
### 2026-02-11 — Maintainer Workflow + State Contract Hardening
**What changed:** Shifted docs and tooling to a maintainer-first workflow and added targeted regression contracts for high-risk UI state paths.
Highlights:
- Reframed onboarding/docs around maintainers (`README.md`, `CONTRIBUTING.md`, `app/docs/contributing/content.mdx`, `docs/playground.md`, `docs/tests.md`)
- Added component-local README coverage and scaffold automation via `pnpm component:new` (`scripts/new-tool-ui-component.ts`)
- Added `components/tool-ui/index.ts` aggregate export surface
- Added contract tests for deterministic row keys, outcome sync transitions, step ids, and tab search param resolution
- Closed component contract gaps and improved scaffold consistency
**Why:** Reduce time-to-first-working-component, make component directory contracts explicit, and keep state/ID behavior stable as internals evolve.
**Agent impact:** Use scaffold + maintainer docs as the default path for new components. When changing stateful behavior, expose deterministic helpers and add contract tests under `lib/tests/**`.
**Files:** `README.md`, `CONTRIBUTING.md`, `app/docs/contributing/content.mdx`, `scripts/new-tool-ui-component.ts`, `components/tool-ui/index.ts`, `lib/tests/tool-ui/**/*`
---
### 2026-02-10 — Registry Pipeline Hardened for Per-Component Install
**What changed:** Registry generation moved to component-directory discovery with per-item artifacts and minimal dependency closure (instead of relying on prefixed/manual lists and shared monolith assumptions).
Highlights:
- Component discovery from `components/tool-ui/*` (excluding `shared`)
- Registry items unprefixed (`tool-ui-foo` → `foo`)
- Shared artifact dependencies inlined per item where needed
- Registry tests assert discovered items match component directories
**Why:** Keep shadcn registry output aligned with the actual product surface and reduce drift from manually curated registry definitions.
**Agent impact:** Treat `components/tool-ui` directories as source of truth for registry coverage. After adding/refactoring components, run `pnpm registry:build` and `pnpm registry:check`.
**Files:** `lib/registry/tool-ui-registry.ts`, `lib/tests/registry/tool-ui-registry.test.ts`, `scripts/build-tool-ui-registry.ts`, `public/r/*.json`
---
### 2026-02-10 — CI 1.0 Quality Gates
**What changed:** CI now enforces lint/typecheck/test/registry artifact consistency on push/PR to `main`.
**Why:** Prevent state contract regressions and stale registry artifacts from landing.
**Agent impact:** A local "done" state for maintainer work is: `pnpm lint:ci`, `pnpm typecheck`, `pnpm test`, `pnpm registry:check`.
**Files:** `.github/workflows/ci.yml`, `package.json`
---
### 2026-02-10 — Weather Widget V3.1 Clean Break
**What changed:** Weather widget migrated to a strict V3.1 payload contract and removed legacy compatibility layers.
Key contract shifts:
- Canonical parser: `safeParseWeatherWidgetPayload`
- Payload shape is widget prop contract (+ UI-only props)
- Deterministic time input is now `time` (`timeBucket` or `localTimeOfDay`)
- Field names normalized (`current.conditionCode`, `units.temperature`, `forecast[].label`, etc.)
**Why:** Keep provider normalization in the tool layer, simplify widget rendering inputs, and make day/night/effects deterministic.
**Agent impact:** Emit only V3.1 payloads when rendering WeatherWidget. Do not use legacy serializable weather parser/types or provider-specific fields in widget render payloads.
**Files:** `components/tool-ui/weather-widget/schema.ts`, `components/tool-ui/weather-widget/time.ts`, `components/tool-ui/weather-widget/weather-widget.tsx`, `lib/presets/weather-widget.ts`
---
### 2026-02-10 — Weather Tuning Workflow Simplified (Apply-Only)
**What changed:** Removed client-side weather tuning codegen hook (`app/sandbox/weather-tuning/hooks/use-code-gen.ts`) and standardized on repo-backed apply/recover endpoints.
**Why:** Reduce duplicate export logic and keep one source of truth (`components/tool-ui/weather-widget/effects/tuned-presets.ts`).
**Agent impact:** In tuning flows, treat `Apply to repo` as the path to production. Use:
- `POST /api/weather-tuning/apply`
- `GET /api/weather-tuning/recover`
Do not add/restore parallel clipboard/download codegen paths for production tuning updates.
---
### 2026-02-10 — Test Location Policy Enforced
**What changed:** Weather + shared tests were moved under `lib/tests/**` to ensure they run under current Vitest include globs and are not copied with component folders.
**Why:** Components are copy-paste product surface; test fixtures/infra should stay internal to this repo.
**Agent impact:** Place new executable tests in:
- `lib/tests/**` (preferred)
- `lib/playground/**` (playground-specific)
Tests under `components/tool-ui/**` are out-of-policy and may not run by default.
**Files:** `vitest.config.ts`, `lib/tests/tool-ui/shared/*`, `lib/tests/tool-ui/weather-widget/*`
---
### 2026-01-30 — PostHog Analytics Added
**What changed:** Added PostHog instrumentation with Vercel Analytics dual-tracking.
**Why:** Track component usage, preset selection, and code copying to understand what components and presets are most valuable.
**Files added:**
- `instrumentation-client.ts` — Client-side PostHog initialization
- `lib/posthog-server.ts` — Server-side PostHog SDK
- `lib/analytics.ts` — Typed event tracking SDK
**Files modified:**
- `next.config.ts` — Added `/ph/*` proxy rewrites for PostHog
- `preset-selector.tsx` — Tracks `component_preset_selected`
- `component-preview-shell.tsx` — Tracks `component_code_copied`, now requires `componentId` prop
**Agent impact:** When adding new trackable interactions, use `analytics.*` methods from `lib/analytics.ts`. The `ComponentPreviewShell` now requires a `componentId` prop.
**Events tracked:**
- `component_preset_selected` — User selects a preset
- `component_code_copied` — User copies component code
- `component_viewed` — User views a component (ready to instrument)
- `search_no_results` — Search with no matches (ready to instrument)
---
### 2026-01-29 — Sandbox Middleware Added
**What changed:** Added middleware to gate `/sandbox/*` routes behind a `?sandbox=true` query param in production. Development mode always allows access.
**Why:** Keep experimental sandboxes (weather effects testing, etc.) accessible for development without exposing them in production.
**Agent impact:** Sandbox pages work normally in dev. In production, add `?sandbox=true` to URL to access.
---
### 2026-01-29 — SVG Glass Panel Effect Added
**What changed:** Added `GlassPanel` component and `useGlassStyles` hook for frosted glass refraction effects using SVG displacement maps via CSS `backdrop-filter`.
**Why:** Provide realistic glass distortion effects for weather widget overlays without WebGL complexity. SVG approach composes naturally with DOM, handles transparency correctly, and doesn't require canvas management.
**Technical approach:**
- SVG `feDisplacementMap` filter encodes X/Y displacement via R/G color channels
- Chromatic aberration displaces RGB channels by different amounts (R most, G middle, B least)
- Filter embedded as data URI in `backdrop-filter` CSS property
- Graceful degradation on unsupported browsers (no effect, content still visible)
**Agent impact:** Use `useGlassStyles` hook or `GlassPanel` component for glass effects. Don't implement WebGL-based glass effects—the SVG approach is simpler and sufficient.
```tsx
// Hook for applying to existing elements
const glassStyles = useGlassStyles({
width: 300,
height: 200,
depth: 12,
strength: 40,
chromaticAberration: 8,
});
// Component wrapper
<GlassPanel depth={10} strength={40}>
content
</GlassPanel>;
```
**Files:** `components/tool-ui/weather-widget/effects/glass-panel-svg.tsx`
---
### 2026-01-26 — AI SDK v5 → v6 Upgrade
**What changed:** Upgraded AI SDK from v5 to v6, assistant-ui to v0.12 with new hook APIs.
**Why:** Keep dependencies current with latest AI SDK patterns.
**Agent impact:** When referencing AI SDK or assistant-ui patterns, use v6/v0.12 APIs. Don't reference deprecated v5 patterns.
---
### 2026-01-23 — Question Flow Component Added
**What changed:** Added Question Flow component (renamed from "Wizard Step" during development). Includes variants: `inline` (default) and `upfront`.
**Why:** Provide structured multi-step question UI for AI assistants.
**Agent impact:** Use `QuestionFlow` for multi-step user input. Component was briefly in showcase, then removed—current best practice is to use `defaultValue` prop for pre-selected state.
**Files:** `components/tool-ui/question-flow/`
---
### 2026-01-22 — Copy Humanization Pass
**What changed:** Systematic rewrite of component docs and non-component docs to remove promotional language and improve voice.
**Why:** Copy should feel like real, believable interactions (see `.claude/docs/copy-guide.md`).
**Agent impact:** Follow copy-guide.md when writing example content. Avoid promotional language, generic placeholders, and tech demo patterns.
---
### 2026-01-19 — Unified Receipt Prop (`choice`)
**What changed:** All receipt state props unified to `choice` across components.
**Before:** `confirmed`, `decision` (inconsistent per component)
**After:** `choice` (universal)
**Why:** Consistent API for LLM serialization and code readability.
**Agent impact:** Always use `choice` prop for receipt state. Never use `confirmed` or `decision`.
```tsx
// Correct
<ApprovalCard choice="approved" />
<OptionList choice="option-a" />
// Deprecated (don't use)
<ApprovalCard decision="approved" />
<OptionList confirmed="option-a" />
```
**Files:** Plan at `.claude/plans/2025-01-19-unified-receipt-prop.md`
---
### 2026-01-16 — MessageDraft Component Added
**What changed:** Added MessageDraft component for email and Slack message previews.
**Agent impact:** Use `MessageDraft` for email/Slack preview UIs, not custom implementations.
**Files:** `components/tool-ui/message-draft/`
---
### 2026-01-14 — Gallery Removals (X Post, ParameterSlider)
**What changed:** X Post and ParameterSlider removed from gallery (components still exist in codebase).
**Why:** X Post scenario didn't pass believability test. ParameterSlider was experimental.
**Agent impact:** Components exist but aren't prominently featured. ParameterSlider is still usable; X Post exists but has copy issues.
---
### 2026-01-06 — ImageGallery Migration to View Transitions API
**What changed:** ImageGallery migrated from Framer Motion to native View Transitions API.
**Why:** Reduce bundle size, use platform features.
**Agent impact:** Don't add Framer Motion for ImageGallery animations. Use View Transitions API patterns.
---
## Deprecated Patterns
| Don't | Do Instead | Since |
| --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ----------------- |
| Use `confirmed` prop | Use `choice` prop | 2026-01-19 |
| Use `decision` prop | Use `choice` prop | 2026-01-19 |
| Add `maxWidth`/`padding` props | Let users customize via `className` | Project inception |
| Use nested config objects | Use flat props | Project inception |
| Add Framer Motion to ImageGallery | Use View Transitions API | 2026-01-06 |
| Use AI SDK v5 patterns | Use AI SDK v6 patterns | 2026-01-26 |
| Implement WebGL glass effects | Use `useGlassStyles` or `GlassPanel` from glass-panel-svg | 2026-01-29 |
| Use `ComponentPreviewShell` without `componentId` | Always pass `componentId` prop for analytics | 2026-01-30 |
| Use weather payload prop `visual` | Use weather payload prop `time` | 2026-02-10 |
| Use legacy serializable weather parser/types | Use `WeatherWidgetPayloadSchema` + `safeParseWeatherWidgetPayload` | 2026-02-10 |
| Put executable tests in `components/tool-ui/**` | Put tests in `lib/tests/**` (or `lib/playground/**`) | 2026-02-10 |
| Use `app/sandbox/weather-tuning/hooks/use-code-gen.ts` export flow | Use apply/recover API routes and `tuned-presets.ts` | 2026-02-10 |
| Curate registry component lists by hand | Discover from `components/tool-ui/*` and validate with registry tests | 2026-02-10 |
| Import from `../shared` barrel in core interactive components | Import direct leaf modules from `../shared/*` | 2026-02-10 |
| Import shadcn primitives (`@/components/ui/*`, `@/lib/ui/cn`) directly in non-adapter component files | Import those primitives from local `./_adapter` files | 2026-02-11 |
| Require/export per-component `error-boundary.tsx` wrappers | Export component + schema contracts directly; rely on caller/app-level boundaries | 2026-02-11 |
| Add new components without local READMEs and contract scaffold files | Use `pnpm component:new` and keep the full component directory contract | 2026-02-11 |
| Depend on registry-shipped `lib/ui/cn.ts` in generated component installs | Use shadcn `@/lib/utils` (`cn`) in adapter output | 2026-02-11 |
| Use private animation keyframes in `components/tool-ui/**` (e.g. `spring-bounce`, `check-draw`, `fade-blur-in`) | Use Tailwind/tw-animate-compatible classes only | 2026-02-11 |
| Put `## Source and Install` below features in component docs | Put `## Source and Install` above `## Key Features` and include GitHub source link | 2026-02-11 |
## Trajectory
Based on recent changes, the project is:
- **Standardizing APIs** — Receipt props unified, flat prop patterns enforced
- **Maintainer-first DX** — onboarding and docs tuned for direct maintenance in this repo
- **Polishing copy** — Moving from capability demos to believable scenarios
- **Keeping dependencies current** — AI SDK v6, assistant-ui v0.12
- **Reducing bundle** — View Transitions over Framer Motion where possible
- **Adding specialized components** — MessageDraft, QuestionFlow, StatsDisplay for specific use cases
- **Adding visual effects** — SVG-based glass refraction for weather widget, preferring CSS/SVG over WebGL
- **Adding analytics** — PostHog + Vercel Analytics for usage tracking
- **Hardening weather contracts** — V3.1 clean-break payloads with deterministic `time` input and apply-only tuning workflow
- **Hardening delivery rails** — registry auto-discovery + CI gates to catch drift early
- **Tightening portability boundaries** — adapter-only UI imports and removal of per-component error-boundary wrappers
- **Registry-first distribution UX** — docs and tests now prioritize install/source visibility and hosted registry URLs
- **Runtime portability over private styling** — shipped Tool UI components avoid repo-private keyframes and rely on tw-animate-compatible motion
================================================
FILE: CLAUDE.md
================================================
# Tool UI
Copy/paste component library (shadcn/ui model) for AI assistant interfaces. Users copy component directories into projects and modify them. Source code is the product—readability over cleverness.
## Commands
```bash
pnpm dev # Dev server (Turbopack)
pnpm build # Production build
pnpm check # Parallel: typecheck + oxlint + eslint + format check
pnpm lint:fix # Fix lint errors (run before committing)
pnpm typecheck # TypeScript checking (tsgo)
pnpm test # Run tests (Vitest)
```
## Tooling
- **Formatter**: Oxfmt (config: `apps/www/.oxfmtrc.jsonc`) — Tailwind class sorting + import sorting
- **Linter**: Oxlint (`apps/www/.oxlintrc.json`) handles standard rules; ESLint (`apps/www/eslint.config.ts`) retained only for `no-restricted-syntax`, `no-restricted-imports`, custom `tool-ui/*` rules, and React Compiler hooks
- **Typecheck**: tsgo (`@typescript/native-preview`) — native TypeScript compiler
- **Parallel checks**: `pnpm check` runs typecheck + all linters + format in parallel via `npm-run-all2`
## Stack
- **Package manager**: pnpm (required)
- **Dependencies**: Only shadcn/ui prerequisites (Tailwind, Radix, Lucide)—users shouldn't need new deps
## Architecture
### Component Structure
Each component lives in `apps/www/components/tool-ui/{name}/`. Reference: `apps/www/components/tool-ui/approval-card/`
Key files:
- `index.tsx` — Barrel exports
- `{name}.tsx` — Main component
- `schema.ts` — Zod schema + SerializableX types
- `_adapter.tsx` — shadcn re-exports
The `shared/` directory contains utilities all components need.
### Documentation Site
Interconnected registries:
- Component metadata: `apps/www/lib/docs/component-registry.ts`
- Presets (example data): `apps/www/lib/presets/{component}.ts`
- Preview rendering: `apps/www/lib/docs/preview-config.tsx`
- Doc pages: `apps/www/app/docs/{component}/content.mdx`
- Gallery: `apps/www/app/docs/gallery/page.tsx`
## Key Patterns
### Component API
- **Tailwind for layout**: No `maxWidth`/`padding` props—users customize via `className`
- **Standard widths**: Cards use `min-w-80 max-w-md`, compact components use `max-w-sm`
- **Flat props**: Avoid nested config objects
- **Semantic action IDs**: Use `id: "confirm"` / `id: "cancel"` for local and decision actions
- **Receipt state**: Use `choice` prop to render confirmed state (e.g., `<OptionList choice="option-a" />`)
### Main Component Structure
Reference: `apps/www/components/tool-ui/approval-card/approval-card.tsx:183`
- Outer `<article>` with `data-slot`, `data-tool-ui-id`, `lang="en"`, `aria-busy`
- Loading skeleton via `isLoading` prop
- Optional sibling `ToolUI.LocalActions` / `ToolUI.DecisionActions` surfaces
## Discovery
| What | Where |
| ----------------------- | ------------------------------------------------ |
| Tool UI components | `apps/www/components/tool-ui/` (scan barrels) |
| Component docs metadata | `apps/www/lib/docs/component-registry.ts` |
| Preset configurations | `apps/www/lib/presets/*.ts` |
| Types & validation | Colocated `schema.ts` files |
| assistant-ui reference | `private/reference-docs/assistant-ui/` |
| Design system specs | `private/design-system/` |
## Task Guides
- Adding/modifying components: `.claude/docs/component-workflow.md`
- Writing doc pages: `.claude/docs/mdx-authoring.md`
- Copy style for examples: `.claude/docs/copy-guide.md`
- Writing changelog entries: `apps/www/docs/changelog.md`
================================================
FILE: LICENSE.md
================================================
MIT License
Copyright (c) 2025 AgentbaseAI Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<a href="https://tool-ui.com">
<img src=".github/assets/header.png" alt="Tool UI" width="100%">
</a>
Copy/paste React components for rendering tool calls in AI chat interfaces. Built by [assistant-ui](https://github.com/assistant-ui).
**[Docs](https://tool-ui.com/docs/overview)** · **[Gallery](https://tool-ui.com/docs/gallery)** · **[Quick Start](https://tool-ui.com/docs/quick-start)**
When a model calls a tool, most apps dump raw JSON into the conversation. These components turn tool payloads into interactive UI like approvals, forms, tables, charts, and media cards so users can understand and act without leaving the chat.
## Featured Components
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="top" width="50%">
<strong><a href="https://www.tool-ui.com/docs/option-list">Option List</a></strong><br>
Let users select from multiple choices<br><br>
<a href="https://tool-ui.com/docs/option-list">
<img src=".github/assets/option-list.png" alt="Option List component" width="100%">
</a>
</td>
<td valign="top" width="50%">
<strong><a href="https://www.tool-ui.com/docs/question-flow">Question Flow</a></strong><br>
Multi-step guided questions with branching<br><br>
<a href="https://tool-ui.com/docs/question-flow">
<img src=".github/assets/question-flow.png" alt="Question Flow component" width="100%">
</a>
</td>
</tr>
</table>
## Why Tool UI?
- **Copy/paste, not install** — shadcn/ui model. Components live in your codebase. No dependency lock-in.
- **Schema-validated** — Every component has a Zod schema. Parse tool output, render when valid, fail safely when not.
- **Interactive with receipts** — Components aren't just displays. Users make choices that flow back to the assistant. Choices persist as receipts.
- **Built on shadcn/ui** — Radix primitives, Tailwind styling, your theme. No new design system to learn.
## Components
- **Progress**: Plan, Progress Tracker
- **Input**: Option List, Parameter Slider, Preferences Panel, Question Flow
- **Display**: Citation, Geo Map, Item Carousel, Link Preview, Stats Display, Terminal, Weather Widget
- **Artifacts**: Chart, Code Block, Code Diff, Data Table, Instagram Post, LinkedIn Post, Message Draft, X Post
- **Confirmation**: Approval Card, Order Summary
- **Media**: Audio, Image, Image Gallery, Video
Each component includes a Zod schema for payload validation and presets for realistic example data. Browse them all in the [Gallery](https://tool-ui.com/docs/gallery).
<a href="https://tool-ui.com/docs/gallery">
<img src=".github/assets/gallery.png" alt="Tool UI component gallery" width="100%">
</a>
## License
MIT License. See [LICENSE](LICENSE.md) for details.
================================================
FILE: apps/www/.oxfmtrc.jsonc
================================================
{
"$schema": "https://raw.githubusercontent.com/nicolo-ribaudo/oxfmt/main/npm/oxfmt/schema.json",
// Match existing Prettier settings
"semi": true,
"singleQuote": false,
"trailingComma": "all",
"tabWidth": 2,
"printWidth": 80,
// Tailwind class sorting (v4 entry point)
"tailwindcss": {
"stylesheet": "./app/styles/globals.css",
"functions": ["clsx", "cn"],
},
// Import sorting (bonus — Prettier didn't do this)
"importSort": {},
}
================================================
FILE: apps/www/.oxlintrc.json
================================================
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": [
"typescript",
"react",
"unicorn",
"oxc",
"import",
"jsx-a11y",
"nextjs",
"vitest"
],
"categories": {
"correctness": "error"
},
"rules": {
"@typescript-eslint/no-explicit-any": "error",
"no-unused-vars": [
"error",
{
"ignoreRestSiblings": true,
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
],
// jsx-a11y: match Next.js defaults (warn, not error) for rules
// that fire on component library patterns
"jsx-a11y/heading-has-content": "warn",
"jsx-a11y/anchor-has-content": "warn",
"jsx-a11y/media-has-caption": "warn",
"jsx-a11y/no-autofocus": "warn",
"jsx-a11y/no-static-element-interactions": "warn",
"jsx-a11y/click-events-have-key-events": "warn",
"jsx-a11y/prefer-tag-over-role": "warn",
"jsx-a11y/iframe-has-title": "warn",
"jsx-a11y/aria-role": "warn",
// tool-ui components use <img> for portability (not Next.js specific)
"nextjs/no-img-element": "off",
// jest rules leak through vitest plugin — disable
"jest/valid-expect": "off",
// false positives: \$ before { in template literals, control chars in sanitizer
"no-useless-escape": "warn",
"no-control-regex": "warn"
},
"env": {
"browser": true,
"builtin": true,
"es2024": true,
"node": true
},
"ignorePatterns": [
"**/dist/**",
"**/node_modules/**",
"**/.next/**",
"**/out/**",
"**/next-env.d.ts",
"components/tool-ui/weather-widget/generated/**"
],
"settings": {
"next": {
"rootDir": ["."]
},
"react": {
"version": "19"
}
}
}
================================================
FILE: apps/www/.prettierignore
================================================
# Generated artifacts (managed by build scripts)
.next/
public/r/
components/tool-ui/weather-widget/generated/
lib/weather-authoring/weather-widget/effects/generated/
lib/weather-authoring/weather-widget/weather-data-overlay.generated.ts
================================================
FILE: apps/www/app/api/builder/chat/route.ts
================================================
import { openai } from "@ai-sdk/openai";
import { anthropic } from "@ai-sdk/anthropic";
import { streamText, convertToModelMessages, stepCountIs } from "ai";
import { experimental_createMCPClient as createMCPClient } from "@ai-sdk/mcp";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { checkRateLimit } from "@/lib/integrations/rate-limit/upstash";
import { requestDevServer } from "@/lib/integrations/freestyle/create-chat";
import { SYSTEM_MESSAGE } from "@/lib/system/tool-builder-message";
export const maxDuration = 300;
export async function POST(req: Request) {
try {
if (!process.env.OPENAI_API_KEY && !process.env.ANTHROPIC_API_KEY) {
return new Response(
JSON.stringify({
error:
"API key is not configured. Please set OPENAI_API_KEY or ANTHROPIC_API_KEY in your environment variables.",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
},
);
}
const ip =
req.headers.get("x-forwarded-for")?.split(",")[0] ||
req.headers.get("x-real-ip") ||
"anonymous";
const rateLimitResult = await checkRateLimit(ip);
if (!rateLimitResult.success) {
return new Response(
JSON.stringify({
error: "Rate limit exceeded. Please try again later.",
reset: rateLimitResult.reset,
}),
{
status: 429,
headers: {
"Content-Type": "application/json",
"X-RateLimit-Limit": rateLimitResult.limit.toString(),
"X-RateLimit-Remaining": rateLimitResult.remaining.toString(),
"X-RateLimit-Reset": rateLimitResult.reset.toString(),
},
},
);
}
const { messages } = await req.json();
const repoId = req.headers.get("Repo-Id");
if (!messages || !Array.isArray(messages)) {
return new Response(
JSON.stringify({ error: "Invalid request: messages array required" }),
{
status: 400,
headers: { "Content-Type": "application/json" },
},
);
}
const modelMessages = await convertToModelMessages(messages);
// Choose model based on what's available
const model = process.env.ANTHROPIC_API_KEY
? anthropic("claude-sonnet-4-5-20250929")
: openai("gpt-5-nano");
// If we have a repoId and Freestyle is configured, use Freestyle tools
let tools = {};
if (repoId && process.env.FREESTYLE_API_KEY) {
try {
const { mcpEphemeralUrl } = await requestDevServer({ repoId });
if (mcpEphemeralUrl) {
const devServerMcp = await createMCPClient({
transport: new StreamableHTTPClientTransport(
new URL(mcpEphemeralUrl),
),
});
tools = await devServerMcp.tools();
}
} catch (error) {
console.error("Error setting up Freestyle MCP:", error);
// Continue without Freestyle tools if there's an error
}
}
const result = streamText({
model,
messages: modelMessages,
system: SYSTEM_MESSAGE,
tools,
stopWhen: stepCountIs(100),
temperature: 0.7,
});
result.consumeStream();
return result.toUIMessageStreamResponse();
} catch (error) {
console.error("Error in builder chat API route:", error);
return new Response(
JSON.stringify({
error: "An error occurred while processing your request.",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
},
);
}
}
================================================
FILE: apps/www/app/api/builder/create-freestyle/route.ts
================================================
import { createChat } from "@/lib/integrations/freestyle/create-chat";
export async function POST() {
try {
if (!process.env.FREESTYLE_API_KEY) {
return new Response(
JSON.stringify({
error:
"Freestyle API key is not configured. Please set FREESTYLE_API_KEY in your environment variables.",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
},
);
}
const { repoId, ephemeralUrl, mcpEphemeralUrl } = await createChat();
return new Response(
JSON.stringify({
repoId,
ephemeralUrl,
mcpEphemeralUrl,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
} catch (error) {
console.error("Error creating Freestyle project:", error);
return new Response(
JSON.stringify({
error: "Failed to create Freestyle project.",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
},
);
}
}
================================================
FILE: apps/www/app/api/chat/route.ts
================================================
import { openai } from "@ai-sdk/openai";
import { streamText, convertToModelMessages, tool } from "ai";
import { z } from "zod";
import { checkRateLimit } from "@/lib/integrations/rate-limit/upstash";
import { getMockTasks } from "@/lib/mocks/tasks";
import { STATS_DISPLAY_DATA } from "@/lib/mocks/chat-showcase-data";
export const runtime = "edge";
const DEMO_SYSTEM_PROMPT = `You are a helpful assistant that showcases the power of Tool UI—a copy-paste component library for AI assistant interfaces.
Your role is to demonstrate how AI assistants can render rich, interactive UIs in chat. Use the available tools proactively and enthusiastically when they fit the user's request.
## Tools and when to use them
- **show_plan**: Present a step-by-step plan for multi-step tasks. Use when the user asks for a plan, workflow, checklist, deployment steps, research approach, or "how do I" questions that break down into phases.
- **get_tasks**: Retrieve and display support tickets or task lists. Use when the user asks about tickets, tasks, support queue, what's open, or wants to see a table of work items.
- **show_stats**: Display key metrics and KPIs. Use when the user asks about performance, revenue, dashboards, quarterly numbers, or business metrics.
- **show_terminal**: Show command-line output (test results, logs, build output). Use when the user asks to run tests, show terminal output, execute a command, or see build/log output.
## Guidelines
- Be concise and friendly. Add a short preamble before or after tool output—don't repeat what the UI already shows.
- NEVER describe or assume data without calling the tool. Always invoke the tool first—the tool returns real data.
- When the user asks to see support tickets, tasks, or a queue → ALWAYS call get_tasks.
- When the user asks for a plan, deployment steps, or a checklist → ALWAYS call show_plan.
- When the user asks about Q4, metrics, revenue, or dashboards → ALWAYS call show_stats.
- When the user asks to run tests, execute a command, or show terminal output → ALWAYS call show_terminal.
- When using show_plan, create relevant plans (e.g. "Deploy to production", "Research competitors").
- When using get_tasks, the tool returns a support ticket queue. Present it with a brief intro.
- When get_tasks returns an empty list (no tickets), you MUST add a friendly message such as: "It looks like there are currently no support tickets in the system. If you need assistance with anything else, feel free to ask!"
- When using show_stats, the tool returns Q4 metrics. Present it with a brief intro.
- When using show_terminal, create realistic output for commands like "pnpm test auth", "npm run build".
- Keep responses brief—let the Tool UI components do the visual heavy lifting.`;
export async function POST(req: Request) {
try {
if (!process.env.OPENAI_API_KEY) {
return new Response(
JSON.stringify({
error:
"OpenAI API key is not configured. Please set OPENAI_API_KEY in your environment variables.",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
},
);
}
const ip =
req.headers.get("x-forwarded-for")?.split(",")[0] ||
req.headers.get("x-real-ip") ||
"anonymous";
const rateLimitResult = await checkRateLimit(ip);
if (!rateLimitResult.success) {
return new Response(
JSON.stringify({
error: "Rate limit exceeded. Please try again later.",
reset: rateLimitResult.reset,
}),
{
status: 429,
headers: {
"Content-Type": "application/json",
"X-RateLimit-Limit": rateLimitResult.limit.toString(),
"X-RateLimit-Remaining": rateLimitResult.remaining.toString(),
"X-RateLimit-Reset": rateLimitResult.reset.toString(),
},
},
);
}
const { messages } = await req.json();
if (!messages || !Array.isArray(messages)) {
return new Response(
JSON.stringify({ error: "Invalid request: messages array required" }),
{
status: 400,
headers: { "Content-Type": "application/json" },
},
);
}
const modelMessages = await convertToModelMessages(messages);
const result = streamText({
model: openai("gpt-4o-mini"),
messages: modelMessages,
system: DEMO_SYSTEM_PROMPT,
tools: {
show_plan: tool({
description:
"Present a step-by-step plan for the user to follow. Use for workflows, checklists, deployment steps, research plans, or any multi-phase task.",
inputSchema: z.object({
title: z.string().describe("Short title for the plan"),
description: z.string().optional().describe("Context or goal"),
todos: z
.array(
z.object({
id: z.string(),
label: z.string(),
status: z
.enum(["pending", "in_progress", "completed", "cancelled"])
.default("pending"),
description: z.string().optional(),
}),
)
.min(1)
.describe("Steps in order"),
}),
execute: async ({ title, description, todos }) => {
return {
id: `plan-${Date.now()}`,
title,
description: description ?? title,
todos: todos.map((t) => ({
...t,
status: t.status ?? "pending",
})),
};
},
}),
get_tasks: tool({
description:
"Retrieve the support ticket queue and display it in a sortable table. Use when the user asks about tickets, tasks, support queue, or open work.",
inputSchema: z.object({
assignee: z
.string()
.optional()
.describe('Filter by assignee name (e.g. "Chen", "Patel")'),
}),
execute: async ({ assignee }) => {
const tasks = await getMockTasks({ assignee });
const rank = { high: 1, medium: 2, low: 3 } as const;
const sorted = [...tasks].sort((a, b) => {
const byUrgency = rank[a.priority] - rank[b.priority];
if (byUrgency !== 0) return byUrgency;
return (
new Date(b.created).getTime() - new Date(a.created).getTime()
);
});
const columns = [
{
key: "priority",
label: "Urgency",
format: {
kind: "status" as const,
statusMap: {
high: { tone: "danger" as const, label: "High" },
medium: { tone: "warning" as const, label: "Medium" },
low: { tone: "neutral" as const, label: "Low" },
},
},
},
{
key: "issue",
label: "Issue",
truncate: true,
priority: "primary" as const,
},
{
key: "customer",
label: "Customer",
priority: "primary" as const,
},
{
key: "status",
label: "Status",
format: {
kind: "badge" as const,
colorMap: {
open: "info",
"in-progress": "warning",
waiting: "neutral",
done: "success",
},
},
},
{ key: "assignee", label: "Owner" },
{
key: "created",
label: "Created",
format: {
kind: "date" as const,
dateFormat: "relative" as const,
},
hideOnMobile: true,
},
];
const data = sorted.map((t) => ({
id: t.id,
issue: t.issue,
customer: t.customer,
priority: t.priority,
status: t.status,
assignee: t.assignee,
created: t.created,
urgencyOrder:
t.priority === "high" ? 1 : t.priority === "medium" ? 2 : 3,
}));
return {
id: `tasks-${Date.now()}`,
columns,
data,
rowIdKey: "id",
defaultSort: { by: "urgencyOrder", direction: "asc" as const },
};
},
}),
show_stats: tool({
description:
"Display key metrics and KPIs in a visual stats grid. Use when the user asks about performance, revenue, dashboards, quarterly numbers, or business metrics.",
inputSchema: z.object({}),
execute: async () => {
return {
id: `stats-${Date.now()}`,
...STATS_DISPLAY_DATA,
};
},
}),
show_terminal: tool({
description:
"Show command-line output (test results, logs, build output). Use when the user asks to run tests, execute a command, show terminal output, or see build/log results.",
inputSchema: z.object({
command: z.string().describe("The command that was run"),
stdout: z.string().describe("The terminal output"),
exitCode: z.number().describe("Exit code (0 = success)"),
durationMs: z.number().optional().describe("Execution time in ms"),
}),
execute: async ({ command, stdout, exitCode, durationMs }) => {
return {
id: `terminal-${Date.now()}`,
command,
stdout,
exitCode,
durationMs,
};
},
}),
},
temperature: 0.7,
});
return result.toUIMessageStreamResponse();
} catch (error) {
console.error("Error in chat API route:", error);
return new Response(
JSON.stringify({
error: "An error occurred while processing your request.",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
},
);
}
}
================================================
FILE: apps/www/app/api/mcp-tools/route.ts
================================================
import { experimental_createMCPClient as createMCPClient } from "@ai-sdk/mcp";
export const runtime = "edge";
interface MCPTool {
name: string;
description?: string;
inputSchema: {
type: string;
properties?: Record<string, unknown>;
required?: string[];
};
}
export async function POST(req: Request) {
try {
const { serverUrl, transportType = "http" } = await req.json();
if (!serverUrl || typeof serverUrl !== "string") {
return new Response(
JSON.stringify({ error: "Invalid request: serverUrl is required" }),
{
status: 400,
headers: { "Content-Type": "application/json" },
},
);
}
// Validate URL format
try {
new URL(serverUrl);
} catch {
return new Response(
JSON.stringify({
error: "Invalid URL format",
}),
{
status: 400,
headers: { "Content-Type": "application/json" },
},
);
}
// Use Vercel AI SDK's MCP client
console.log(
`[MCP] Creating MCP client for ${serverUrl} with transport: ${transportType}`,
);
try {
const mcpClient = await createMCPClient({
transport: {
type: transportType as "http" | "sse",
url: serverUrl,
},
});
console.log(`[MCP] Client created, fetching tools...`);
const tools = await mcpClient.tools();
console.log(`[MCP] Received ${Object.keys(tools).length} tools`);
// Convert AI SDK tool format to our format
const mcpTools: MCPTool[] = Object.entries(tools).map(([name, tool]) => ({
name,
description: tool.description,
inputSchema: tool.inputSchema as unknown as {
type: string;
properties?: Record<string, unknown>;
required?: string[];
},
}));
// Close the client
await mcpClient.close();
return new Response(
JSON.stringify({
tools: mcpTools,
serverUrl,
count: mcpTools.length,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
} catch (error) {
console.error(`[MCP] Error with AI SDK client:`, error);
return new Response(
JSON.stringify({
error: `Could not connect to MCP server: ${error instanceof Error ? error.message : "Unknown error"}`,
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
},
);
}
} catch (error) {
console.error("Error fetching MCP tools:", error);
return new Response(
JSON.stringify({
error: "An error occurred while fetching MCP tools",
details: error instanceof Error ? error.message : "Unknown error",
}),
{
status: 500,
headers: { "Content-Type": "application/json" },
},
);
}
}
================================================
FILE: apps/www/app/api/playground/chat/route.ts
================================================
import type { NextRequest } from "next/server";
import type { UIMessage } from "ai";
import { findPrototype, streamPrototypeResponse } from "@/lib/playground";
import { PROTOTYPE_SLUG_HEADER } from "@/lib/playground/constants";
const isUiMessageArray = (value: unknown): value is UIMessage[] =>
Array.isArray(value);
const extractSlug = (request: NextRequest): string | null => {
const headerSlug = request.headers.get(PROTOTYPE_SLUG_HEADER)?.trim();
if (headerSlug) {
return headerSlug;
}
const url = new URL(request.url);
const querySlug = url.searchParams.get("slug")?.trim();
if (querySlug) {
return querySlug;
}
return null;
};
export async function POST(request: NextRequest) {
const slug = extractSlug(request);
if (!slug) {
return new Response(JSON.stringify({ error: "Missing prototype slug." }), {
status: 400,
headers: { "Content-Type": "application/json" },
});
}
const prototype = findPrototype(slug);
if (!prototype) {
return new Response(
JSON.stringify({ error: `Prototype "${slug}" not found.` }),
{
status: 404,
headers: { "Content-Type": "application/json" },
},
);
}
let body: unknown;
try {
body = await request.json();
} catch {
return new Response(JSON.stringify({ error: "Invalid JSON body." }), {
status: 400,
headers: { "Content-Type": "application/json" },
});
}
const messages =
typeof body === "object" && body !== null && "messages" in body
? (body as Record<string, unknown>).messages
: undefined;
if (!isUiMessageArray(messages)) {
return new Response(
JSON.stringify({ error: "Request body must include a messages array." }),
{
status: 400,
headers: { "Content-Type": "application/json" },
},
);
}
if (process.env.NODE_ENV !== "production") {
try {
const lastAssistantWithTools = [...messages]
.reverse()
.find(
(message) =>
message.role === "assistant" &&
Array.isArray(message.parts) &&
message.parts.some(
(part) =>
typeof part?.type === "string" && part.type.startsWith("tool-"),
),
);
if (lastAssistantWithTools) {
const toolParts = lastAssistantWithTools.parts?.filter(
(part) =>
typeof part?.type === "string" && part.type.startsWith("tool-"),
);
console.debug(
"[playground] forwarding tool parts:",
JSON.stringify(toolParts, null, 2),
);
}
} catch (error) {
console.warn("[playground] failed to log tool parts", error);
}
}
// Extract frontend tools from request body
const clientTools: unknown =
typeof body === "object" && body !== null && "tools" in body
? (body as Record<string, unknown>).tools
: undefined;
const result = await streamPrototypeResponse(
prototype,
messages,
clientTools,
);
return result.toUIMessageStreamResponse();
}
================================================
FILE: apps/www/app/api/weather-tuning/_lib/tuned-presets-io.ts
================================================
import { readFile } from "fs/promises";
import path from "path";
import type { WeatherEffectsTunedPresets } from "../../../../lib/weather-authoring/weather-widget/effects/tuning";
export const TOOL_UI_TUNED_PRESETS_PATH = path.join(
process.cwd(),
"lib/weather-authoring/presets/tuned-presets.json",
);
export async function readToolUiTunedPresetsFromDisk(): Promise<WeatherEffectsTunedPresets> {
const source = await readFile(TOOL_UI_TUNED_PRESETS_PATH, "utf8");
return JSON.parse(source) as WeatherEffectsTunedPresets;
}
================================================
FILE: apps/www/app/api/weather-tuning/apply/route.ts
================================================
import { writeFile } from "fs/promises";
import type { WeatherConditionCode } from "../../../../lib/weather-authoring/weather-widget/schema";
import type { CheckpointOverrides } from "../../../sandbox/weather-compositor/presets";
import {
buildCanonicalToolUiPresetsForEditedConditions,
replaceEditedConditions,
} from "../../../sandbox/weather-tuning/lib/tool-ui-export";
import type { WeatherEffectsTunedPresets } from "../../../../lib/weather-authoring/weather-widget/effects/tuning";
import {
canonicalizeWeatherPresetData,
writeWeatherRuntimeArtifacts,
} from "../../../../lib/weather-codegen/compile-weather-runtime";
import {
readToolUiTunedPresetsFromDisk,
TOOL_UI_TUNED_PRESETS_PATH,
} from "../_lib/tuned-presets-io";
import { mapToolUiPresetsToCompositor } from "../../../sandbox/weather-tuning/lib/tool-ui-import";
export const runtime = "nodejs";
export async function POST(request: Request) {
if (process.env.NODE_ENV === "production") {
return new Response("Disabled in production.", { status: 403 });
}
type ApplyPayload = {
checkpointOverrides?: Partial<
Record<WeatherConditionCode, CheckpointOverrides>
>;
signedOff?: WeatherConditionCode[];
};
let payload: ApplyPayload | null = null;
try {
payload = (await request.json()) as ApplyPayload;
} catch {
return new Response("Invalid JSON payload.", { status: 400 });
}
if (
!payload?.checkpointOverrides ||
typeof payload.checkpointOverrides !== "object"
) {
return new Response("Missing 'checkpointOverrides' field.", {
status: 400,
});
}
if (Object.keys(payload.checkpointOverrides).length === 0) {
return new Response("No tuning changes to apply.", { status: 400 });
}
let base: WeatherEffectsTunedPresets;
try {
base = await readToolUiTunedPresetsFromDisk();
} catch (error) {
console.warn(
"Failed to read current tuned presets; falling back to empty.",
error,
);
base = {};
}
const repoCheckpointOverrides = mapToolUiPresetsToCompositor(base);
const canonicalEditedConditions =
buildCanonicalToolUiPresetsForEditedConditions(
payload.checkpointOverrides,
repoCheckpointOverrides,
);
if (Object.keys(canonicalEditedConditions).length === 0) {
return new Response("No tuning changes to apply.", { status: 400 });
}
const merged = replaceEditedConditions(base, canonicalEditedConditions);
const canonicalMerged = canonicalizeWeatherPresetData(
merged,
) as WeatherEffectsTunedPresets;
const content = `${JSON.stringify(canonicalMerged, null, 2)}\n`;
await writeFile(TOOL_UI_TUNED_PRESETS_PATH, content, "utf8");
const generated = await writeWeatherRuntimeArtifacts(process.cwd());
const updatedArtifacts = [
"lib/weather-authoring/presets/tuned-presets.json",
...generated.written,
];
return Response.json({
ok: true,
path: "lib/weather-authoring/presets/tuned-presets.json",
updatedArtifacts,
checkpointOverrides: mapToolUiPresetsToCompositor(canonicalMerged),
});
}
================================================
FILE: apps/www/app/api/weather-tuning/recover/route.ts
================================================
import { mapToolUiPresetsToCompositor } from "../../../sandbox/weather-tuning/lib/tool-ui-import";
import { readToolUiTunedPresetsFromDisk } from "../_lib/tuned-presets-io";
export const runtime = "nodejs";
export async function GET() {
if (process.env.NODE_ENV === "production") {
return new Response("Disabled in production.", { status: 403 });
}
try {
const presets = await readToolUiTunedPresetsFromDisk();
const checkpointOverrides = mapToolUiPresetsToCompositor(presets);
return Response.json({ ok: true, checkpointOverrides });
} catch (error) {
console.error("Failed to recover tuning from repo presets.", error);
return new Response("Failed to recover tuning from repo presets.", {
status: 500,
});
}
}
================================================
FILE: apps/www/app/builder/layout.tsx
================================================
import type { ReactNode } from "react";
import ContentLayout from "@/app/components/layout/page-shell";
import { HeaderFrame } from "@/app/components/layout/app-shell";
import { ThemeToggle } from "@/app/components/builder/theme-toggle";
export default function BuilderLayout({ children }: { children: ReactNode }) {
return (
<HeaderFrame rightContent={<ThemeToggle />}>
<ContentLayout>{children}</ContentLayout>
</HeaderFrame>
);
}
================================================
FILE: apps/www/app/builder/opengraph-image.tsx
================================================
import {
generateOgImage,
size as ogSize,
contentType as ogContentType,
} from "@/lib/og/og-image";
export const runtime = "nodejs";
export const alt = "Tool UI - Builder";
export const size = ogSize;
export const contentType = ogContentType;
export default async function Image() {
return generateOgImage("Builder", "Construct components visually");
}
================================================
FILE: apps/www/app/builder/page.tsx
================================================
"use client";
import {
AssistantRuntimeProvider,
ThreadPrimitive,
ComposerPrimitive,
MessagePrimitive,
useAui,
useAuiState,
makeAssistantToolUI,
ActionBarPrimitive,
BranchPickerPrimitive,
ErrorPrimitive,
makeAssistantTool,
} from "@assistant-ui/react";
import {
useChatRuntime,
AssistantChatTransport,
} from "@assistant-ui/react-ai-sdk";
import { ThreadList } from "@/app/components/assistant-ui/thread-list";
import { MarkdownText } from "@/app/components/assistant-ui/markdown-text";
import WebView from "@/app/components/builder/webview";
import {
ArrowUpIcon,
Square,
Loader2,
Eye,
Code,
Copy,
Check,
PencilIcon,
RefreshCw,
FileEdit,
FileText,
CopyIcon,
CheckIcon,
RefreshCwIcon,
ChevronLeftIcon,
ChevronRightIcon,
ConstructionIcon,
} from "lucide-react";
import { MCPIcon } from "@/app/components/builder/mcp-icon";
import { Button } from "@/components/ui/button";
import { CodeBlock, CodeBlockCode } from "@/components/ui/code-block";
import { getComponentCode } from "@/lib/integrations/freestyle/get-code";
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
} from "@/components/ui/card";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import {
InputGroup,
InputGroupInput,
InputGroupAddon,
} from "@/components/ui/input-group";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useState, useEffect, type FC, createContext, useContext } from "react";
import { ToolFallback } from "@/app/components/assistant-ui/tool-fallback";
import { TooltipIconButton } from "@/app/components/assistant-ui/tooltip-icon-button";
import React from "react";
import { cn } from "@/lib/ui/cn";
// Context for refreshing the preview pane
const PreviewRefreshContext = createContext<(() => void) | null>(null);
const usePreviewRefresh = () => {
const refresh = useContext(PreviewRefreshContext);
return refresh;
};
// Module-level holder for the refresh function (accessible from streamCall)
let globalRefreshPreview: (() => void) | null = null;
const PreviewRefreshSetter: FC = () => {
const refresh = usePreviewRefresh();
useEffect(() => {
globalRefreshPreview = refresh;
return () => {
globalRefreshPreview = null;
};
}, [refresh]);
return null;
};
const UserMessage: FC = () => {
return (
<MessagePrimitive.Root className="mx-auto grid w-full max-w-2xl auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 px-2 py-4 [&:where(>*)]:col-start-2">
<div className="relative col-start-2 min-w-0">
<div className="bg-muted text-foreground rounded-3xl px-5 py-2.5 break-words">
<MessagePrimitive.Content components={{ Text: MarkdownText }} />
</div>
<div className="absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2">
<UserActionBar />
</div>
</div>
<BranchPicker className="col-span-full col-start-1 row-start-3 -mr-1 justify-end" />
</MessagePrimitive.Root>
);
};
const AssistantMessage: FC = () => {
return (
<MessagePrimitive.Root className="relative mx-auto w-full max-w-2xl py-4">
<div className="text-foreground mx-2 leading-7 break-words">
<MessagePrimitive.Content
components={{ Text: MarkdownText, tools: { Fallback: ToolFallback } }}
/>
<MessageError />
</div>
<div className="mt-2 ml-2 flex">
<BranchPicker />
<AssistantActionBar />
</div>
</MessagePrimitive.Root>
);
};
const MessageError: FC = () => {
return (
<MessagePrimitive.Error>
<ErrorPrimitive.Root className="border-destructive bg-destructive/10 text-destructive dark:bg-destructive/5 mt-2 rounded-md border p-3 text-sm dark:text-red-200">
<ErrorPrimitive.Message className="line-clamp-2" />
</ErrorPrimitive.Root>
</MessagePrimitive.Error>
);
};
const UserActionBar: FC = () => {
return (
<ActionBarPrimitive.Root
hideWhenRunning
autohide="not-last"
className="flex flex-col items-end"
>
<ActionBarPrimitive.Edit asChild>
<TooltipIconButton tooltip="Edit" className="p-4">
<PencilIcon />
</TooltipIconButton>
</ActionBarPrimitive.Edit>
</ActionBarPrimitive.Root>
);
};
const AssistantActionBar: FC = () => {
return (
<ActionBarPrimitive.Root
hideWhenRunning
autohide="not-last"
autohideFloat="single-branch"
className="text-muted-foreground data-floating:bg-background col-start-3 row-start-2 -ml-1 flex gap-1 data-floating:absolute data-floating:rounded-md data-floating:border data-floating:p-1 data-floating:shadow-sm"
>
<ActionBarPrimitive.Copy asChild>
<TooltipIconButton tooltip="Copy">
<MessagePrimitive.If copied>
<CheckIcon />
</MessagePrimitive.If>
<MessagePrimitive.If copied={false}>
<CopyIcon />
</MessagePrimitive.If>
</TooltipIconButton>
</ActionBarPrimitive.Copy>
<ActionBarPrimitive.Reload asChild>
<TooltipIconButton tooltip="Refresh">
<RefreshCwIcon />
</TooltipIconButton>
</ActionBarPrimitive.Reload>
</ActionBarPrimitive.Root>
);
};
const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
className,
...rest
}) => {
return (
<BranchPickerPrimitive.Root
hideWhenSingleBranch
className={cn(
"text-muted-foreground mr-2 -ml-2 inline-flex items-center text-xs",
className,
)}
{...rest}
>
<BranchPickerPrimitive.Previous asChild>
<TooltipIconButton tooltip="Previous">
<ChevronLeftIcon />
</TooltipIconButton>
</BranchPickerPrimitive.Previous>
<span className="font-medium">
<BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
</span>
<BranchPickerPrimitive.Next asChild>
<TooltipIconButton tooltip="Next">
<ChevronRightIcon />
</TooltipIconButton>
</BranchPickerPrimitive.Next>
</BranchPickerPrimitive.Root>
);
};
const EditComposer: FC = () => {
return (
<div className="mx-auto flex w-full max-w-2xl flex-col gap-4 px-2 first:mt-4">
<ComposerPrimitive.Root className="bg-muted ml-auto flex w-full max-w-7/8 flex-col rounded-xl">
<ComposerPrimitive.Input
className="text-foreground flex min-h-[60px] w-full resize-none bg-transparent p-4 outline-none"
autoFocus
/>
<div className="mx-3 mb-3 flex items-center justify-center gap-2 self-end">
<ComposerPrimitive.Cancel asChild>
<Button variant="ghost" size="sm" aria-label="Cancel edit">
Cancel
</Button>
</ComposerPrimitive.Cancel>
<ComposerPrimitive.Send asChild>
<Button size="sm" aria-label="Update message">
Update
</Button>
</ComposerPrimitive.Send>
</div>
</ComposerPrimitive.Root>
</div>
);
};
interface MCPTool {
name: string;
description?: string;
inputSchema: {
type: string;
properties?: Record<string, unknown>;
required?: string[];
};
}
const MCPModal: FC<{
open: boolean;
onOpenChange: (open: boolean) => void;
}> = ({ open, onOpenChange }) => {
const aui = useAui();
const [mcpUrl, setMcpUrl] = useState("");
const [transportType, setTransportType] = useState<"http" | "sse">("http");
const [tools, setTools] = useState<MCPTool[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
// Auto-detect transport type based on URL
useEffect(() => {
if (mcpUrl.toLowerCase().endsWith("/sse")) {
setTransportType("sse");
} else {
setTransportType("http");
}
}, [mcpUrl]);
const loadTools = async () => {
if (!mcpUrl.trim()) return;
setLoading(true);
setError(null);
try {
const response = await fetch("/api/mcp-tools", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
serverUrl: mcpUrl,
transportType,
}),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || "Failed to fetch tools");
}
setTools(data.tools || []);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to fetch tools");
setTools([]);
} finally {
setLoading(false);
}
};
const handleGenerateUI = (tool: MCPTool) => {
// Create a formatted prompt with tool information
const prompt = `Please create a Tool UI component for the following MCP tool:
**Tool Name:** ${tool.name}
**Description:** ${tool.description || "No description provided"}
**Full Schema:**
\`\`\`json
${JSON.stringify(tool.inputSchema, null, 2)}
\`\`\``;
// Send the message to the current thread
aui.thread().append({
role: "user",
content: [{ type: "text", text: prompt }],
});
// Close the modal
onOpenChange(false);
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="flex max-h-[80vh] max-w-2xl flex-col">
<DialogHeader>
<DialogTitle>Import MCP Tool</DialogTitle>
</DialogHeader>
<div className="mb-4 flex gap-2">
<InputGroup className="flex-1">
<InputGroupInput
placeholder="Enter MCP server URL..."
value={mcpUrl}
onChange={(e) => setMcpUrl(e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter") {
loadTools();
}
}}
/>
<InputGroupAddon align="inline-end" className="pr-1">
<Select
value={transportType}
onValueChange={(value: "http" | "sse") =>
setTransportType(value)
}
>
<SelectTrigger className="h-6 w-auto gap-1 border-0 bg-transparent px-2 text-xs shadow-none hover:bg-transparent focus:ring-0 data-[state=open]:bg-transparent dark:bg-transparent dark:hover:bg-transparent">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="http">HTTP</SelectItem>
<SelectItem value="sse">SSE</SelectItem>
</SelectContent>
</Select>
</InputGroupAddon>
</InputGroup>
<Button onClick={loadTools} disabled={loading || !mcpUrl.trim()}>
{loading ? (
<>
<Loader2 className="mr-2 size-4 animate-spin" />
Loading
</>
) : (
"Load"
)}
</Button>
</div>
{error && (
<div className="text-destructive bg-destructive/10 mb-4 rounded-md p-3 text-sm">
{error}
</div>
)}
<div className="flex-1 overflow-y-auto rounded-md border">
{tools.length === 0 ? (
<div className="text-muted-foreground flex h-32 items-center justify-center text-sm">
{loading ? "Loading tools..." : "No tools loaded"}
</div>
) : (
<div className="divide-y">
{tools.map((tool) => (
<div
key={tool.name}
className="hover:bg-muted/50 flex items-center justify-between p-4 transition-colors"
>
<div className="mr-4 min-w-0 flex-1">
<div className="text-sm font-medium">{tool.name}</div>
{tool.description && (
<div className="text-muted-foreground mt-1 truncate text-xs">
{tool.description}
</div>
)}
</div>
<Button
size="sm"
onClick={() => handleGenerateUI(tool)}
className="shrink-0"
>
Generate UI
</Button>
</div>
))}
</div>
)}
</div>
</DialogContent>
</Dialog>
);
};
const Composer: FC = () => {
const [mcpModalOpen, setMcpModalOpen] = useState(false);
const isNewThread = useAuiState(
({ threadListItem }) => threadListItem.status === "new",
);
return (
<>
<MCPModal open={mcpModalOpen} onOpenChange={setMcpModalOpen} />
<div className="bg-background sticky bottom-0 mx-auto flex w-full max-w-2xl flex-col gap-4 overflow-visible rounded-t-3xl pb-4 md:pb-6">
<ComposerPrimitive.Root className="group/input-group border-input bg-background has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:ring-ring/50 relative flex w-full flex-col rounded-3xl border px-1 pt-2 shadow-xs transition-[color,box-shadow] outline-none has-[textarea:focus-visible]:ring-[3px]">
<ComposerPrimitive.Input
placeholder="Describe the tool UI you want to build..."
className="placeholder:text-muted-foreground mb-1 max-h-32 min-h-16 w-full resize-none bg-transparent px-3.5 pt-1.5 pb-3 text-base outline-none focus-visible:ring-0"
rows={1}
autoFocus
/>
<div className="relative mx-1 mt-2 mb-2 flex items-center justify-between">
<div>
{isNewThread && (
<Button
type="button"
variant="ghost"
size="sm"
className="text-muted-foreground hover:text-foreground h-[34px] gap-1.5 rounded-full text-xs"
onClick={() => setMcpModalOpen(true)}
>
<MCPIcon className="size-3.5" />
<span>MCP</span>
</Button>
)}
</div>
<div className="flex items-center justify-end">
<ThreadPrimitive.If running={false}>
<ComposerPrimitive.Send asChild>
<Button
type="submit"
variant="default"
size="icon"
className="size-[34px] rounded-full p-1"
>
<ArrowUpIcon className="size-5" />
</Button>
</ComposerPrimitive.Send>
</ThreadPrimitive.If>
<ThreadPrimitive.If running>
<ComposerPrimitive.Cancel asChild>
<Button
type="button"
variant="default"
size="icon"
className="border-muted-foreground/60 hover:bg-primary/75 dark:border-muted-foreground/90 size-[34px] rounded-full border"
>
<Square className="size-3.5 fill-white dark:fill-black" />
</Button>
</ComposerPrimitive.Cancel>
</ThreadPrimitive.If>
</div>
</div>
</ComposerPrimitive.Root>
<div className="flex items-center justify-center gap-2 text-center text-xs text-amber-700 dark:text-amber-400">
<ConstructionIcon className="size-3.5 shrink-0" />
<span>
This builder is under heavy construction and may not always work as
expected.
</span>
</div>
</div>
</>
);
};
const Thread: FC = () => {
return (
<ThreadPrimitive.Root className="bg-background flex h-full w-full flex-col">
<ThreadPrimitive.Viewport className="relative flex flex-1 flex-col overflow-y-auto px-4">
<ThreadPrimitive.If empty>
<div className="flex flex-1 items-center justify-center">
<Composer />
</div>
</ThreadPrimitive.If>
<ThreadPrimitive.If empty={false}>
<ThreadPrimitive.Messages
components={{
UserMessage,
EditComposer,
AssistantMessage,
}}
/>
<div className="min-h-8 grow" />
<Composer />
</ThreadPrimitive.If>
</ThreadPrimitive.Viewport>
</ThreadPrimitive.Root>
);
};
type ViewMode = "rendered" | "code";
export default function BuilderPage() {
const [repoId, setRepoId] = useState<string | null>(null);
const repoIdRef = useState({ current: repoId })[0];
const [_appId, setAppId] = useState<string | null>(null);
const [webviewWidth, setWebviewWidth] = useState(50); // percentage
const [viewMode, setViewMode] = useState<ViewMode>("rendered");
const [codeContent, setCodeContent] = useState<string | null>(null);
const [isCodeLoading, setIsCodeLoading] = useState(false);
const [copied, setCopied] = useState(false);
const [refreshKey, setRefreshKey] = useState(0);
const timestampRef = useState(() => Date.now())[0];
// Keep ref in sync with state
repoIdRef.current = repoId;
// Load code when switching to code view
useEffect(() => {
if (viewMode === "code" && repoId && !codeContent) {
setIsCodeLoading(true);
getComponentCode(repoId, "components/demo-tool-ui.tsx")
.then((content) => {
setCodeContent(content);
setIsCodeLoading(false);
})
.catch((err) => {
console.error("Failed to load code:", err);
setIsCodeLoading(false);
});
}
}, [viewMode, repoId, codeContent]);
const runtime = useChatRuntime({
transport: new AssistantChatTransport({
api: "/api/builder/chat",
headers: async () => {
// Auto-create Freestyle project on first message if not already created
if (
!repoIdRef.current &&
process.env.NEXT_PUBLIC_FREESTYLE_ENABLED !== "false"
) {
try {
const response = await fetch("/api/builder/create-freestyle", {
method: "POST",
});
if (response.ok) {
const data = await response.json();
setRepoId(data.repoId);
repoIdRef.current = data.repoId;
// Use a unique ID for this app instance
setAppId(data.repoId + "-" + timestampRef);
}
} catch (error) {
console.error("Failed to create Freestyle project:", error);
}
}
return {
"Repo-Id": repoIdRef.current || "",
};
},
}),
});
const handleCopy = async () => {
if (!codeContent) return;
try {
await navigator.clipboard.writeText(codeContent);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch (err) {
console.error("Failed to copy:", err);
}
};
const handleMouseDown = (e: React.MouseEvent) => {
e.preventDefault();
const startX = e.clientX;
const startWidth = webviewWidth;
const containerWidth = window.innerWidth - 240; // Subtract sidebar width
const handleMouseMove = (e: MouseEvent) => {
const diff = startX - e.clientX;
const percentageChange = (diff / containerWidth) * 100;
const newWidth = Math.min(
Math.max(startWidth + percentageChange, 20),
80,
);
setWebviewWidth(newWidth);
};
const handleMouseUp = () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
};
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
};
const handleRefreshPreview = () => {
setRefreshKey((prev) => prev + 1);
};
return (
<PreviewRefreshContext.Provider value={handleRefreshPreview}>
<AssistantRuntimeProvider runtime={runtime}>
<PreviewRefreshSetter />
<div className="flex h-full flex-1 flex-col md:flex-row">
{/* Thread List Sidebar - hidden on mobile */}
<div className="bg-background hidden w-[220px] shrink-0 overflow-y-auto p-4 md:block">
<ThreadList />
</div>
{/* Main Thread Area */}
<div
className="overflow-hidden border md:rounded-t-lg"
style={{ width: repoId ? `${100 - webviewWidth}%` : "100%" }}
>
<Thread />
</div>
{/* Preview/Code Panel */}
{repoId && (
<>
{/* Resize Handle - hidden on mobile */}
<div
role="separator"
className="bg-border hover:bg-primary hidden w-1 cursor-col-resize transition-colors md:block"
onMouseDown={handleMouseDown}
/>
{/* Preview Panel */}
<div
className="flex flex-col"
style={{ width: `${webviewWidth}%` }}
>
{/* Header with view toggle and copy/refresh button */}
<div className="bg-background flex h-12 shrink-0 items-center justify-between border-t border-b px-4">
<div className="flex items-center gap-2">
<Button
variant={viewMode === "rendered" ? "secondary" : "ghost"}
size="sm"
onClick={() => setViewMode("rendered")}
className="gap-2"
>
<Eye className="h-4 w-4" />
<span className="hidden sm:inline">Preview</span>
</Button>
<Button
variant={viewMode === "code" ? "secondary" : "ghost"}
size="sm"
onClick={() => setViewMode("code")}
className="gap-2"
>
<Code className="h-4 w-4" />
<span className="hidden sm:inline">Code</span>
</Button>
</div>
{viewMode === "rendered" ? (
<Button
variant="ghost"
size="icon"
onClick={() => setRefreshKey((prev) => prev + 1)}
title="Refresh preview"
>
<RefreshCw className="h-4 w-4" />
</Button>
) : (
<Button
variant="ghost"
size="icon"
onClick={handleCopy}
disabled={!codeContent || isCodeLoading}
>
{copied ? (
<Check className="h-4 w-4" />
) : (
<Copy className="h-4 w-4" />
)}
</Button>
)}
</div>
<div className="flex-1 overflow-hidden">
{viewMode === "rendered" ? (
<WebView key={refreshKey} repo={repoId} />
) : (
<div className="h-full overflow-auto p-4">
{isCodeLoading ? (
<div className="flex h-full items-center justify-center">
<div className="text-center">
<Loader2 className="mx-auto h-8 w-8 animate-spin" />
<p className="text-muted-foreground mt-4 text-sm">
Loading code...
</p>
</div>
</div>
) : codeContent ? (
<CodeBlock>
<CodeBlockCode code={codeContent} language="tsx" />
</CodeBlock>
) : (
<div className="flex h-full items-center justify-center">
<p className="text-muted-foreground text-sm">
Failed to load code
</p>
</div>
)}
</div>
)}
</div>
</div>
</>
)}
</div>
<EditFileToolUI />
<WriteFileToolUI />
<ReadFileToolUI />
</AssistantRuntimeProvider>
</PreviewRefreshContext.Provider>
);
}
const EditFileToolUI = makeAssistantTool<
{
path?: string;
edits?: Array<{
oldText?: string;
newText?: string;
}>;
},
{}
>({
type: "backend",
toolName: "edit_file",
streamCall: async (reader) => {
await reader.response.get();
// Refresh the preview pane after edit completes
if (globalRefreshPreview) {
globalRefreshPreview();
}
},
render: ({ args }) => {
console.log("EditFileToolUI", args);
const path = args?.path;
const edits = args?.edits;
if (!path && (!edits || edits.length === 0)) {
return null;
}
return (
<Card className="mb-4 w-full">
<CardHeader>
<div className="flex items-center gap-2">
<PencilIcon className="text-primary h-4 w-4" />
<CardTitle className="text-base">Editing File</CardTitle>
</div>
{path && (
<CardDescription className="mt-1 font-mono text-xs">
{path}
</CardDescription>
)}
</CardHeader>
{edits && edits.length > 0 && (
<CardContent>
<div className="grid gap-2">
{edits.map(
(edit, index) =>
(edit.oldText || edit.newText) && (
<CodeBlock
key={index}
className="grid overflow-scroll py-2"
>
{edit.oldText && (
<>
<CodeBlockCode
code={edit.oldText
.split("\n")
.slice(0, 5)
.join("\n")}
language="tsx"
className="col-start-1 col-end-1 row-start-1 row-end-1 overflow-visible bg-red-200 [&_code]:bg-red-200 [&>pre]:py-0"
/>
{edit.oldText.split("\n").length > 5 && (
<div className="px-4 font-mono text-xs text-red-700">
+{edit.oldText.split("\n").length - 5} more
</div>
)}
</>
)}
{edit.newText && (
<>
<CodeBlockCode
code={edit.newText
.trimEnd()
.split("\n")
.slice(0, 5)
.join("\n")}
language="tsx"
className="col-start-1 col-end-1 row-start-1 row-end-1 overflow-visible bg-green-200 [&_code]:bg-green-200 [&>pre]:py-0"
/>
{edit.newText.split("\n").length > 5 && (
<div className="px-4 font-mono text-xs text-green-700">
+{edit.newText.split("\n").length - 5} more
</div>
)}
</>
)}
</CodeBlock>
),
)}
</div>
</CardContent>
)}
</Card>
);
},
});
const WriteFileToolUI = makeAssistantTool<
{
path?: string;
content?: string;
},
{}
>({
type: "backend",
toolName: "write_file",
streamCall: async (reader) => {
await reader.response.get();
// Refresh the preview pane after write completes
if (globalRefreshPreview) {
globalRefreshPreview();
}
},
render: ({ args }) => {
const path = args?.path;
if (!path) {
return null;
}
return (
<Card className="mb-4 w-full">
<CardHeader>
<div className="flex items-center gap-2">
<FileEdit className="text-primary h-4 w-4" />
<CardTitle className="text-base">Writing File</CardTitle>
</div>
<CardDescription className="mt-1 font-mono text-xs">
{path}
</CardDescription>
</CardHeader>
</Card>
);
},
});
const ReadFileToolUI = makeAssistantToolUI<
{
path?: string;
},
{}
>({
toolName: "read_file",
render: ({ args }) => {
const path = args?.path;
if (!path) {
return null;
}
return (
<Card className="mb-4 w-full">
<CardHeader>
<div className="flex items-center gap-2">
<FileText className="text-primary h-4 w-4" />
<CardTitle className="text-base">Reading File</CardTitle>
</div>
<CardDescription className="mt-1 font-mono text-xs">
{path}
</CardDescription>
</CardHeader>
</Card>
);
},
});
================================================
FILE: apps/www/app/components/analytics/posthog-init.client.tsx
================================================
"use client";
import { useEffect } from "react";
const apiKey = process.env["NEXT_PUBLIC_POSTHOG_API_KEY"];
const isDev = process.env.NODE_ENV === "development";
let didInit = false;
let initPromise: Promise<void> | null = null;
export function PostHogInit() {
useEffect(() => {
if (didInit || initPromise || !apiKey) {
return;
}
initPromise = (async () => {
const { default: posthog } = await import("posthog-js");
if (didInit) {
return;
}
posthog.init(apiKey, {
api_host: "/ph",
ui_host: "https://us.posthog.com",
defaults: "2025-11-30",
capture_exceptions: true,
advanced_disable_flags: true, // Skip feature flags API call
loaded: (instance) => {
// Tag all events with environment for filtering.
instance.register({
environment: isDev ? "development" : "production",
app: "tool-ui",
});
},
});
didInit = true;
})()
.catch((error) => {
if (isDev) {
console.error("[PostHog] failed to initialize", error);
}
})
.finally(() => {
initPromise = null;
});
}, []);
return null;
}
================================================
FILE: apps/www/app/components/assistant-ui/markdown-text.tsx
================================================
"use client";
import "@assistant-ui/react-markdown/styles/dot.css";
import {
type CodeHeaderProps,
MarkdownTextPrimitive,
unstable_memoizeMarkdownComponents as memoizeMarkdownComponents,
useIsMarkdownCodeBlock,
} from "@assistant-ui/react-markdown";
import remarkGfm from "remark-gfm";
import { type FC, memo, useState } from "react";
import { CheckIcon, CopyIcon } from "lucide-react";
import { TooltipIconButton } from "@/app/components/assistant-ui/tooltip-icon-button";
import { cn } from "@/lib/ui/cn";
const MarkdownTextImpl = () => {
return (
<MarkdownTextPrimitive
remarkPlugins={[remarkGfm]}
className="aui-md"
components={defaultComponents}
/>
);
};
export const MarkdownText = memo(MarkdownTextImpl);
const CodeHeader: FC<CodeHeaderProps> = ({ language, code }) => {
const { isCopied, copyToClipboard } = useCopyToClipboard();
const onCopy = () => {
if (!code || isCopied) return;
copyToClipboard(code);
};
return (
<div className="aui-code-header-root bg-muted-foreground/15 text-foreground dark:bg-muted-foreground/20 mt-4 flex items-center justify-between gap-4 rounded-t-lg px-4 py-2 text-sm font-semibold">
<span className="aui-code-header-language lowercase [&>span]:text-xs">
{language}
</span>
<TooltipIconButton tooltip="Copy" onClick={onCopy}>
{!isCopied && <CopyIcon />}
{isCopied && <CheckIcon />}
</TooltipIconButton>
</div>
);
};
const useCopyToClipboard = ({
copiedDuration = 3000,
}: {
copiedDuration?: number;
} = {}) => {
const [isCopied, setIsCopied] = useState<boolean>(false);
const copyToClipboard = (value: string) => {
if (!value) return;
navigator.clipboard.writeText(value).then(() => {
setIsCopied(true);
setTimeout(() => setIsCopied(false), copiedDuration);
});
};
return { isCopied, copyToClipboard };
};
const defaultComponents = memoizeMarkdownComponents({
h1: ({ className, ...props }) => (
<h1
className={cn(
"aui-md-h1 mb-8 scroll-m-20 text-4xl font-extrabold last:mb-0",
className,
)}
{...props}
/>
),
h2: ({ className, ...props }) => (
<h2
className={cn(
"aui-md-h2 mt-8 mb-4 scroll-m-20 text-3xl font-semibold first:mt-0 last:mb-0",
className,
)}
{...props}
/>
),
h3: ({ className, ...props }) => (
<h3
className={cn(
"aui-md-h3 mt-6 mb-4 scroll-m-20 text-2xl font-semibold first:mt-0 last:mb-0",
className,
)}
{...props}
/>
),
h4: ({ className, ...props }) => (
<h4
className={cn(
"aui-md-h4 mt-6 mb-4 scroll-m-20 text-xl font-semibold first:mt-0 last:mb-0",
className,
)}
{...props}
/>
),
h5: ({ className, ...props }) => (
<h5
className={cn(
"aui-md-h5 my-4 text-lg font-semibold first:mt-0 last:mb-0",
className,
)}
{...props}
/>
),
h6: ({ className, ...props }) => (
<h6
className={cn(
"aui-md-h6 my-4 font-semibold first:mt-0 last:mb-0",
className,
)}
{...props}
/>
),
p: ({ className, ...props }) => (
<p
className={cn("aui-md-p mt-5 mb-5 first:mt-0 last:mb-0", className)}
{...props}
/>
),
a: ({ className, ...props }) => (
<a
className={cn(
"aui-md-a text-primary font-medium underline underline-offset-4",
className,
)}
{...props}
/>
),
blockquote: ({ className, ...props }) => (
<blockquote
className={cn("aui-md-blockquote border-l-2 pl-6 italic", className)}
{...props}
/>
),
ul: ({ className, ...props }) => (
<ul
className={cn(
"aui-md-ul my-5 ml-6 list-disc border border-red-500 [&>li]:mt-2",
className,
)}
{...props}
/>
),
ol: ({ className, ...props }) => (
<ol
className={cn("aui-md-ol my-5 ml-6 list-decimal [&>li]:mt-2", className)}
{...props}
/>
),
hr: ({ className, ...props }) => (
<hr className={cn("aui-md-hr my-5 border-b", className)} {...props} />
),
table: ({ className, ...props }) => (
<table
className={cn(
"aui-md-table my-5 w-full border-separate border-spacing-0 overflow-y-auto",
className,
)}
{...props}
/>
),
th: ({ className, ...props }) => (
<th
className={cn(
"aui-md-th bg-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [&[align=center]]:text-center [&[align=right]]:text-right",
className,
)}
{...props}
/>
),
td: ({ className, ...props }) => (
<td
className={cn(
"aui-md-td border-b border-l px-4 py-2 text-left last:border-r [&[align=center]]:text-center [&[align=right]]:text-right",
className,
)}
{...props}
/>
),
tr: ({ className, ...props }) => (
<tr
className={cn(
"aui-md-tr m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg",
className,
)}
{...props}
/>
),
sup: ({ className, ...props }) => (
<sup
className={cn("aui-md-sup [&>a]:text-xs [&>a]:no-underline", className)}
{...props}
/>
),
pre: ({ className, ...props }) => (
<pre
className={cn(
"aui-md-pre overflow-x-auto !rounded-t-none rounded-b-lg bg-black p-4 text-white",
className,
)}
{...props}
/>
),
code: function Code({ className, ...props }) {
const isCodeBlock = useIsMarkdownCodeBlock();
return (
<code
className={cn(
!isCodeBlock &&
"aui-md-inline-code bg-muted rounded border font-semibold",
className,
)}
{...props}
/>
);
},
CodeHeader,
});
================================================
FILE: apps/www/app/components/assistant-ui/thread-list.tsx
================================================
import { useCallback, type FC } from "react";
import {
ThreadListItemPrimitive,
ThreadListPrimitive,
useAuiState,
} from "@assistant-ui/react";
import { ArchiveIcon, HistoryIcon, PlusIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { TooltipIconButton } from "@/app/components/assistant-ui/tooltip-icon-button";
import { Skeleton } from "@/components/ui/skeleton";
export type ThreadListProps = {
allowedThreadIds?: Set<string>;
newLabel?: string;
emptyState?: React.ReactNode;
onReplay?: (threadId: string) => void;
};
export const ThreadList: FC<ThreadListProps> = ({
allowedThreadIds,
newLabel = "New Tool UI",
emptyState,
onReplay,
}) => {
return (
<ThreadListPrimitive.Root className="aui-root aui-thread-list-root flex flex-col items-stretch gap-1.5">
<ThreadListNew label={newLabel} />
<ThreadListItems
allowedThreadIds={allowedThreadIds}
emptyState={emptyState}
onReplay={onReplay}
/>
</ThreadListPrimitive.Root>
);
};
const ThreadListNew: FC<{ label: string }> = ({ label }) => {
return (
<ThreadListPrimitive.New asChild>
<Button
className="aui-thread-list-new hover:bg-muted data-active:bg-muted flex items-center justify-start gap-1 rounded-lg px-2.5 py-2 text-start"
variant="ghost"
>
<PlusIcon />
{label}
</Button>
</ThreadListPrimitive.New>
);
};
type ThreadListItemsProps = {
allowedThreadIds?: Set<string>;
emptyState?: React.ReactNode;
onReplay?: (threadId: string) => void;
};
const ThreadListItems: FC<ThreadListItemsProps> = ({
allowedThreadIds,
emptyState,
onReplay,
}) => {
const threadsState = useAuiState(useCallback((state) => state.threads, []));
const isLoading = threadsState.isLoading;
const threadIds = threadsState.threadIds;
if (isLoading) {
return <ThreadListSkeleton />;
}
const indexMap = threadIds
.map((id, index) => ({ id, index }))
.filter(({ id }) => !allowedThreadIds || allowedThreadIds.has(id));
if (indexMap.length === 0) {
return emptyState ? <>{emptyState}</> : null;
}
return indexMap.map(({ id, index }) => (
<ThreadListPrimitive.ItemByIndex
key={id}
index={index}
components={{
ThreadListItem: () => <ThreadListItem onReplay={onReplay} />,
}}
/>
));
};
const ThreadListSkeleton: FC = () => {
return (
<>
{Array.from({ length: 5 }, (_, i) => (
<div
key={i}
role="status"
aria-label="Loading threads"
aria-live="polite"
className="aui-thread-list-skeleton-wrapper flex items-center gap-2 rounded-md px-3 py-2"
>
<Skeleton className="aui-thread-list-skeleton h-[22px] grow" />
</div>
))}
</>
);
};
const ThreadListItem: FC<{ onReplay?: (threadId: string) => void }> = ({
onReplay,
}) => {
return (
<ThreadListItemPrimitive.Root className="aui-thread-list-item hover:bg-muted focus-visible:bg-muted focus-visible:ring-ring data-active:bg-muted flex items-center gap-2 rounded-lg transition-all focus-visible:ring-2 focus-visible:outline-none">
<ThreadListItemPrimitive.Trigger className="aui-thread-list-item-trigger grow px-3 py-2 text-start">
<ThreadListItemTitle />
</ThreadListItemPrimitive.Trigger>
<ThreadListItemActions onReplay={onReplay} />
</ThreadListItemPrimitive.Root>
);
};
const ThreadListItemTitle: FC = () => {
return (
<span className="aui-thread-list-item-title text-sm">
<ThreadListItemPrimitive.Title fallback="New Chat" />
</span>
);
};
const ThreadListItemActions: FC<{ onReplay?: (threadId: string) => void }> = ({
onReplay,
}) => {
const threadId = useAuiState(({ threadListItem }) => threadListItem.id);
return (
<div className="flex items-center gap-1 pr-2">
{onReplay && (
<TooltipIconButton
className="aui-thread-list-item-replay text-foreground hover:text-primary size-4 p-0"
variant="ghost"
tooltip="Replay with another instance"
onClick={(event) => {
event.stopPropagation();
onReplay(threadId);
}}
>
<HistoryIcon />
</TooltipIconButton>
)}
<ThreadListItemPrimitive.Archive asChild>
<TooltipIconButton
className="aui-thread-list-item-archive text-foreground hover:text-primary size-4 p-0"
variant="ghost"
tooltip="Archive thread"
>
<ArchiveIcon />
</TooltipIconButton>
</ThreadListItemPrimitive.Archive>
</div>
);
};
================================================
FILE: apps/www/app/components/assistant-ui/tool-fallback.tsx
================================================
"use client";
import type { ToolCallMessagePartComponent } from "@assistant-ui/react";
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
import { useState } from "react";
import { Button } from "@/components/ui/button";
export const ToolFallback: ToolCallMessagePartComponent = ({
toolName,
argsText,
result,
}) => {
const [isCollapsed, setIsCollapsed] = useState(true);
return (
<div className="aui-tool-fallback-root mb-4 flex w-full flex-col gap-3 rounded-lg border py-3">
<div className="aui-tool-fallback-header flex items-center gap-2 px-4">
<CheckIcon className="aui-tool-fallback-icon size-4" />
<p className="aui-tool-fallback-title flex-grow">
Used tool: <b>{toolName}</b>
</p>
<Button onClick={() => setIsCollapsed(!isCollapsed)}>
{isCollapsed ? <ChevronUpIcon /> : <ChevronDownIcon />}
</Button>
</div>
{!isCollapsed && (
<div className="aui-tool-fallback-content flex flex-col gap-2 border-t pt-2">
<div className="aui-tool-fallback-args-root px-4">
<pre className="aui-tool-fallback-args-value whitespace-pre-wrap">
{argsText}
</pre>
</div>
{result !== undefined && (
<div className="aui-tool-fallback-result-root border-t border-dashed px-4 pt-2">
<p className="aui-tool-fallback-result-header font-semibold">
Result:
</p>
<pre className="aui-tool-fallback-result-content whitespace-pre-wrap">
{typeof result === "string"
? result
: JSON.stringify(result, null, 2)}
</pre>
</div>
)}
</div>
)}
</div>
);
};
================================================
FILE: apps/www/app/components/assistant-ui/tooltip-icon-button.tsx
================================================
"use client";
import { ComponentPropsWithRef, forwardRef } from "react";
import { Slottable } from "@radix-ui/react-slot";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/ui/cn";
export type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
tooltip: string;
side?: "top" | "bottom" | "left" | "right";
};
export const TooltipIconButton = forwardRef<
HTMLButtonElement,
TooltipIconButtonProps
>(({ children, tooltip, side = "bottom", className, ...rest }, ref) => {
return (
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
{...rest}
className={cn("aui-button-icon size-6 p-1", className)}
ref={ref}
>
<Slottable>{children}</Slottable>
<span className="aui-sr-only sr-only">{tooltip}</span>
</Button>
</TooltipTrigger>
<TooltipContent side={side}>{tooltip}</TooltipContent>
</Tooltip>
);
});
TooltipIconButton.displayName = "TooltipIconButton";
================================================
FILE: apps/www/app/components/builder/mcp-icon.tsx
================================================
import * as React from "react";
export function MCPIcon({
className,
...props
}: React.SVGProps<SVGSVGElement>) {
return (
<svg
viewBox="0 0 195 195"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
{...props}
>
<path
d="M25 97.8528L92.8823 29.9706C102.255 20.598 117.451 20.598 126.823 29.9706V29.9706C136.196 39.3431 136.196 54.5391 126.823 63.9117L75.5581 115.177"
stroke="currentColor"
strokeWidth="12"
strokeLinecap="round"
/>
<path
d="M76.2653 114.47L126.823 63.9117C136.196 54.5391 151.392 54.5391 160.765 63.9117L161.118 64.2652C170.491 73.6378 170.491 88.8338 161.118 98.2063L99.7248 159.6C96.6006 162.724 96.6006 167.789 99.7248 170.913L112.331 183.52"
stroke="currentColor"
strokeWidth="12"
strokeLinecap="round"
/>
<path
d="M109.853 46.9411L59.6482 97.1457C50.2757 106.518 50.2757 121.714 59.6482 131.087V131.087C69.0208 140.459 84.2168 140.459 93.5894 131.087L143.794 80.8822"
stroke="currentColor"
strokeWidth="12"
strokeLinecap="round"
/>
</svg>
);
}
================================================
FILE: apps/www/app/components/builder/theme-toggle.tsx
================================================
"use client";
import * as React from "react";
import { Moon, Sun } from "lucide-react";
import { useTheme } from "next-themes";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/ui/cn";
export function ThemeToggle() {
const { setTheme, resolvedTheme } = useTheme();
const [mounted, setMounted] = React.useState(false);
function changeTheme(newTheme: string) {
if (!document.startViewTransition) {
setTheme(newTheme);
return;
}
document.documentElement.dataset.themeTransition = "";
const transition = document.startViewTransition(() => {
setTheme(newTheme);
});
transition.finished.then(() => {
delete document.documentElement.dataset.themeTransition;
});
}
React.useEffect(() => {
setMounted(true);
}, []);
const isDark = mounted && resolvedTheme === "dark";
const toggleTheme = () => {
changeTheme(isDark ? "light" : "dark");
};
return (
<Button
variant="ghost"
size="icon"
type="button"
aria-label="Toggle theme"
aria-pressed={isDark}
className="relative"
onClick={toggleTheme}
>
<Sun
className={cn(
"size-4 transition-all",
isDark ? "scale-0 rotate-90" : "scale-100 rotate-0",
)}
/>
<Moon
className={cn(
"absolute size-4 transition-all",
isDark ? "scale-100 rotate-0" : "scale-0 -rotate-90",
)}
/>
<span className="sr-only">Toggle theme</span>
</Button>
);
}
================================================
FILE: apps/www/app/components/builder/webview-actions.ts
================================================
"use server";
import { requestDevServer as requestDevServerInner } from "@/lib/integrations/freestyle/create-chat";
export async function requestDevServer({ repoId }: { repoId: string }) {
return await requestDevServerInner({ repoId });
}
================================================
FILE: apps/www/app/components/builder/webview.tsx
================================================
"use client";
import { requestDevServer as requestDevServerInner } from "./webview-actions";
import "@/app/styles/builder-loader.css";
import {
forwardRef,
useCallback,
useEffect,
useImperativeHandle,
useMemo,
useState,
} from "react";
export interface WebViewHandle {
refresh: () => void;
}
type DevServerResponse = Awaited<ReturnType<typeof requestDevServerInner>>;
export default forwardRef<
WebViewHandle,
{
repo: string;
}
>(function WebView(props, ref) {
const [devServer, setDevServer] = useState<DevServerResponse | null>(null);
const [requesting, setRequesting] = useState(false);
const [iframeLoading, setIframeLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const devServerUrl = useMemo(
() => devServer?.ephemeralUrl ?? null,
[devServer],
);
const requestDevServer = useCallback(async () => {
setRequesting(true);
setIframeLoading(true);
setError(null);
try {
const response = await requestDevServerInner({ repoId: props.repo });
setDevServer(response);
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
setError(message);
setDevServer(null);
setIframeLoading(false);
} finally {
setRequesting(false);
}
}, [props.repo]);
useImperativeHandle(ref, () => ({
refresh: () => {
void requestDevServer();
},
}));
useEffect(() => {
if (!props.repo) {
setDevServer(null);
setError("Repo ID is missing.");
return;
}
void requestDevServer();
}, [props.repo, requestDevServer]);
return (
<div className="flex h-full flex-col overflow-hidden border-l transition-opacity duration-700">
{(requesting || iframeLoading) && !devServer?.devCommandRunning && (
<div className="flex h-full items-center justify-center">
<div>
<div className="text-center">
{iframeLoading ? "JavaScript Loading" : "Starting VM"}
</div>
<div>
<div className="loader"></div>
</div>
</div>
</div>
)}
{error ? (
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">
{error}
</div>
) : devServerUrl ? (
<iframe
key={devServerUrl}
className="h-full w-full border-0"
src={devServerUrl}
onLoad={() => setIframeLoading(false)}
/>
) : null}
</div>
);
});
================================================
FILE: apps/www/app/components/home/chat-showcase.tsx
================================================
"use client";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { AnimatePresence, motion, type Transition } from "motion/react";
import { cn } from "@/lib/ui/cn";
import { CitationList } from "@/components/tool-ui/citation";
import { DataTable } from "@/components/tool-ui/data-table";
import { LinkPreview } from "@/components/tool-ui/link-preview";
import { Plan } from "@/components/tool-ui/plan";
import { Terminal } from "@/components/tool-ui/terminal";
import { CodeBlock } from "@/components/tool-ui/code-block";
import { ItemCarousel } from "@/components/tool-ui/item-carousel";
import { ParameterSlider } from "@/components/tool-ui/parameter-slider";
import { StatsDisplay } from "@/components/tool-ui/stats-display";
import { ProgressTracker } from "@/components/tool-ui/progress-tracker";
import { MessageDraft } from "@/components/tool-ui/message-draft";
import { WeatherWidget } from "@/components/tool-ui/weather-widget/runtime";
import {
type Flight,
TABLE_COLUMNS,
TABLE_DATA,
LINK_PREVIEW,
PLAN_TODO_LABELS,
ITEM_CAROUSEL_DATA,
LLM_CITATIONS,
PARAMETER_SLIDER_DATA,
STATS_DISPLAY_DATA,
PROGRESS_TRACKER_DATA,
} from "@/lib/mocks/chat-showcase-data";
const TIMING = {
durations: {
userIn: 500,
preambleIn: 280,
toolIn: 600,
},
beats: {
afterUser: 700,
beforeContent: 500,
afterPreamble: 200,
},
sceneHold: 4500,
exitStagger: {
user: 0,
preamble: 80,
tool: 160,
},
reducedMotion: {
duration: 250,
sceneHold: 1500,
},
} as const;
const SPRINGS = {
gentle: {
type: "spring",
damping: 28,
stiffness: 180,
mass: 0.8,
},
smooth: {
type: "spring",
damping: 24,
stiffness: 260,
mass: 0.8,
},
standard: {
type: "spring",
damping: 26,
stiffness: 220,
mass: 0.7,
},
} as const satisfies Record<string, Transition>;
type SceneConfig = {
userMessage?: string;
preamble?: string;
toolUI: React.ReactNode;
toolFallbackHeight?: number;
holdDuration?: number;
};
type SceneTimelineState = {
preambleReady: boolean;
showTool: boolean;
setShowTool: (value: boolean) => void;
};
function useReducedMotion(): boolean {
const [reducedMotion, setReducedMotion] = useState(false);
useEffect(() => {
if (typeof window === "undefined") return;
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
setReducedMotion(mediaQuery.matches);
const handleChange = () => setReducedMotion(mediaQuery.matches);
mediaQuery.addEventListener?.("change", handleChange);
return () => mediaQuery.removeEventListener?.("change", handleChange);
}, []);
return reducedMotion;
}
function useSceneTimeline({
reducedMotion,
onComplete,
hasUserMessage = true,
initialDelay = 0,
holdDuration,
}: {
reducedMotion: boolean;
onComplete: () => void;
hasUserMessage?: boolean;
initialDelay?: number;
holdDuration?: number;
}): SceneTimelineState {
const [preambleReady, setPreambleReady] = useState(reducedMotion);
const [showTool, setShowTool] = useState(reducedMotion);
const hasScheduledCompletion = useRef(false);
useEffect(() => {
if (!reducedMotion) return;
const timeoutId = window.setTimeout(
onComplete,
TIMING.reducedMotion.sceneHold,
);
return () => window.clearTimeout(timeoutId);
}, [reducedMotion, onComplete]);
useEffect(() => {
if (reducedMotion || preambleReady) return;
const delay =
initialDelay +
(hasUserMessage ? TIMING.durations.userIn + TIMING.beats.afterUser : 0);
const timeoutId = window.setTimeout(() => setPreambleReady(true), delay);
return () => window.clearTimeout(timeoutId);
}, [preambleReady, reducedMotion, hasUserMessage, initialDelay]);
useEffect(() => {
const shouldScheduleCompletion =
!hasScheduledCompletion.current &&
preambleReady &&
showTool &&
!reducedMotion;
if (!shouldScheduleCompletion) return;
hasScheduledCompletion.current = true;
const timeoutId = window.setTimeout(
onComplete,
holdDuration ?? TIMING.sceneHold,
);
return () => window.clearTimeout(timeoutId);
}, [preambleReady, showTool, onComplete, reducedMotion, holdDuration]);
return useMemo(
() => ({ preambleReady, showTool, setShowTool }),
[preambleReady, showTool],
);
}
function ToolReveal({ children }: { children: React.ReactNode }) {
return (
<motion.div
initial={{ opacity: 0, y: 30, filter: "blur(10px)" }}
animate={{ opacity: 1, y: 0, filter: "blur(0px)" }}
transition={SPRINGS.gentle}
>
{children}
</motion.div>
);
}
function TypingIndicator() {
return (
<motion.span
className="bg-foreground/50 block size-4 rounded-full"
animate={{ opacity: [0.4, 1, 0.4] }}
transition={{
duration: 1.4,
repeat: Infinity,
ease: "easeInOut",
}}
aria-label="Assistant is typing"
/>
);
}
const TEST_LINES = [
"\x1b[32m✓\x1b[0m login flow handles invalid credentials \x1b[90m(3 tests)\x1b[0m \x1b[33m42ms\x1b[0m",
"\x1b[32m✓\x1b[0m session tokens refresh correctly \x1b[90m(5 tests)\x1b[0m \x1b[33m128ms\x1b[0m",
"\x1b[32m✓\x1b[0m logout clears all cookies \x1b[90m(2 tests)\x1b[0m \x1b[33m18ms\x1b[0m",
"",
"\x1b[32mTests:\x1b[0m 10 passed, 10 total",
];
function AnimatedTerminal({ className }: { className?: string }) {
const [lineCount, setLineCount] = useState(0);
useEffect(() => {
if (lineCount >= TEST_LINES.length) return;
const delay = lineCount === 0 ? 300 : 700;
const timeoutId = window.setTimeout(() => {
setLineCount((c) => c + 1);
}, delay);
return () => window.clearTimeout(timeoutId);
}, [lineCount]);
const visibleOutput = TEST_LINES.slice(0, lineCount).join("\n") || " ";
const isComplete = lineCount >= TEST_LINES.length;
return (
<Terminal
id="chat-showcase-terminal"
command="pnpm test auth"
stdout={visibleOutput}
exitCode={0}
durationMs={isComplete ? 1243 : undefined}
className={className}
/>
);
}
function AnimatedPlan({ className }: { className?: string }) {
const [completedCount, setCompletedCount] = useState(0);
useEffect(() => {
if (completedCount >= PLAN_TODO_LABELS.length) return;
const delay = completedCount === 0 ? 400 : 1100;
const timeoutId = window.setTimeout(() => {
setCompletedCount((c) => c + 1);
}, delay);
return () => window.clearTimeout(timeoutId);
}, [completedCount]);
const todoDescriptions = [
"Analyzing social media activity and recent conversations",
"Browsing gift guides and personalized recommendations",
"Evaluating quality, reviews, and price ranges",
"Selecting the top 3 options with purchase links",
];
const todos = PLAN_TODO_LABELS.map((label: string, index: number) => ({
id: String(index + 1),
label,
description: todoDescriptions[index],
status:
index < completedCount
? ("completed" as const)
: index === completedCount
? ("in_progress" as const)
: ("pending" as const),
}));
return (
<Plan
id="chat-showcase-plan"
title="Gift Research"
description="Finding the perfect birthday gift for Sarah"
todos={todos}
className={className}
/>
);
}
function AnimatedProgressTracker({ className }: { className?: string }) {
const [currentStep, setCurrentStep] = useState(1);
useEffect(() => {
if (currentStep >= 3) return;
const delay = currentStep === 1 ? 1300 : 1500;
const timeoutId = window.setTimeout(() => {
setCurrentStep((s) => s + 1);
}, delay);
return () => window.clearTimeout(timeoutId);
}, [currentStep]);
const steps = PROGRESS_TRACKER_DATA.steps.map((step, index) => ({
...step,
status:
index < currentStep
? ("completed" as const)
: index === currentStep
? ("in-progress" as const)
: ("pending" as const),
}));
const elapsedTime = PROGRESS_TRACKER_DATA.elapsedTime! + currentStep * 12000;
return (
<ProgressTracker
id="chat-showcase-progress-tracker"
steps={steps}
elapsedTime={elapsedTime}
className={className}
/>
);
}
type ChatBubbleProps = {
role: "user" | "assistant";
children: React.ReactNode;
className?: string;
};
function ChatBubble({ role, children, className }: ChatBubbleProps) {
const isUser = role === "user";
return (
<div
className={cn(
"flex w-full",
isUser ? "justify-end pb-3" : "justify-start",
)}
aria-label={isUser ? "User message" : "Assistant message"}
>
<div
className={cn(
"relative max-w-[min(720px,100%)] text-xl",
isUser && "rounded-full bg-[#007AFF] text-white dark:bg-[#002b90]",
!isUser && "text-foreground",
className,
)}
>
{children}
</div>
</div>
);
}
type PreambleBubbleProps = {
text: string;
msPerChar?: number;
reducedMotion?: boolean;
onComplete?: () => void;
};
function StreamingChar({ char, delay }: { char: string; delay: number }) {
return (
<motion.span
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{
duration: 0.4,
delay,
ease: [0.25, 0.1, 0.25, 1],
}}
>
{char}
</motion.span>
);
}
function PreambleBubble({
text,
msPerChar = 18,
reducedMotion,
onComplete,
}: PreambleBubbleProps) {
const [isVisible, setIsVisible] = useState(reducedMotion);
const hasCalledComplete = useRef(false);
useEffect(() => {
if (reducedMotion) return;
const timeoutId = window.setTimeout(() => setIsVisible(true), 100);
return () => window.clearTimeout(timeoutId);
}, [reducedMotion]);
useEffect(() => {
if (hasCalledComplete.current) return;
if (reducedMotion) {
hasCalledComplete.current = true;
onComplete?.();
return;
}
if (!isVisible) return;
const totalDuration = text.length * msPerChar + 400;
const timeoutId = window.setTimeout(() => {
if (!hasCalledComplete.current) {
hasCalledComplete.current = true;
onComplete?.();
}
}, totalDuration);
return () => window.clearTimeout(timeoutId);
}, [reducedMotion, msPerChar, text.length, onComplete, isVisible]);
const characters = useMemo(() => {
return text.split("").map((char, index) => ({
char,
delay: index * (msPerChar / 1000),
}));
}, [text, msPerChar]);
if (reducedMotion) {
return (
<ChatBubble role="assistant">
<span>{text}</span>
</ChatBubble>
);
}
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: isVisible ? 1 : 0 }}
transition={SPRINGS.smooth}
>
<ChatBubble role="assistant">
<span>
{isVisible &&
characters.map(({ char, delay }, index) => (
<StreamingChar key={index} char={char} delay={delay} />
))}
</span>
</ChatBubble>
</motion.div>
);
}
function createSceneConfigs(reducedMotion: boolean): SceneConfig[] {
const { title: _title, ...statsDataWithoutTitle } = STATS_DISPLAY_DATA;
return [
{
userMessage: "How's the business doing this quarter?",
preamble: "Q4 numbers are in. Looking solid.",
toolUI: (
<StatsDisplay
id="chat-showcase-stats-display"
{...statsDataWithoutTitle}
className="w-full max-w-[560px]"
/>
),
toolFallbackHeight: 280,
},
{
userMessage: "What's the weather like this week?",
preamble: "Stormy night ahead. Clears up by Thursday.",
toolUI: (
<WeatherWidget
version="3.1"
id="chat-showcase-weather"
location={{ name: "San Francisco, CA" }}
units={{ temperature: "fahrenheit" }}
current={{
temperature: 54,
tempMin: 51,
tempMax: 58,
conditionCode: "thunderstorm",
}}
forecast={[
{
label: "Tue",
tempMin: 50,
tempMax: 56,
conditionCode: "heavy-rain",
},
{ label: "Wed", tempMin: 49, tempMax: 55, conditionCode: "rain" },
{ label: "Thu", tempMin: 51, tempMax: 60, conditionCode: "cloudy" },
{
label: "Fri",
tempMin: 53,
tempMax: 64,
conditionCode: "partly-cloudy",
},
{ label: "Sat", tempMin: 55, tempMax: 68, conditionCode: "clear" },
]}
time={{ localTimeOfDay: 23 / 24 }}
updatedAt="2024-01-15T23:00:00Z"
className="w-full max-w-[400px]"
effects={{
enabled: !reducedMotion,
reducedMotion,
quality: "auto",
}}
/>
),
toolFallbackHeight: 280,
holdDuration: 6000,
},
{
userMessage: "Boost the bass a bit on this track",
preamble: "Bass is up. Here's the full EQ.",
toolUI: (
<ParameterSlider
id="chat-showcase-parameter-slider"
sliders={[
{
id: "bass",
label: "Bass",
min: -12,
max: 12,
step: 1,
value: 4,
unit: "dB",
fillClassName: "bg-fuchsia-500/30 dark:bg-fuchsia-400/35",
handleClassName: "bg-fuchsia-500 dark:bg-fuchsia-400",
},
{
id: "mid",
label: "Mid",
min: -12,
max: 12,
step: 1,
value: -1,
unit: "dB",
fillClassName: "bg-cyan-500/30 dark:bg-cyan-400/35",
handleClassName: "bg-cyan-500 dark:bg-cyan-400",
},
{
id: "treble",
label: "Treble",
min: -12,
max: 12,
step: 1,
value: 3,
unit: "dB",
fillClassName: "bg-violet-500/30 dark:bg-violet-400/35",
handleClassName: "bg-violet-500 dark:bg-violet-400",
},
]}
actions={PARAMETER_SLIDER_DATA.actions}
className="w-full max-w-[480px]"
/>
),
toolFallbackHeight: 240,
},
{
userMessage: "Find me a birthday gift for Sarah",
preamble: "On it. Checking her interests now.",
toolUI: <AnimatedPlan className="w-full max-w-[480px]" />,
toolFallbackHeight: 280,
},
{
userMessage: "What should I listen to right now?",
preamble: "Found a few albums for you.",
toolUI: (
<ItemCarousel
id="chat-showcase-item-carousel"
{...ITEM_CAROUSEL_DATA}
className="w-full max-w-[640px]"
/>
),
toolFallbackHeight: 320,
},
{
userMessage: "Run the tests for the auth module",
preamble: "Running auth tests now.",
toolUI: <AnimatedTerminal className="w-full max-w-[560px]" />,
toolFallbackHeight: 200,
},
{
userMessage: "Deploy the updates to production",
preamble: "Deployment started. Tracking progress.",
toolUI: <AnimatedProgressTracker className="w-full max-w-[480px]" />,
toolFallbackHeight: 260,
},
{
userMessage: "Find me flights to Tokyo in March",
preamble: "Found 4 nonstop flights. Sorted by price.",
toolUI: (
<DataTable.Table<Flight>
id="chat-showcase-data-table"
rowIdKey="id"
columns={TABLE_COLUMNS}
data={TABLE_DATA}
defaultSort={{ by: "price", direction: "asc" }}
/>
),
toolFallbackHeight: 320,
},
{
userMessage: "Create a skill that learns from mistakes",
preamble: "Here's a self-improving metaskill.",
toolUI: (
<CodeBlock
id="chat-showcase-code-block"
language="markdown"
lineNumbers="visible"
filename="learn-from-errors.md"
code={`name: learn-from-errors
triggers: [error, failed, mistake, wrong]
## Behavior
When an error occurs:
1. Capture the context and attempted solution
2. Analyze what went wrong
3. Update \`~/.claude/learnings.md\` with the pattern
4. Apply the learning to retry
## Self-Improvement Loop
\`\`\`
error → analyze → document → retry → verify
↑ ↓
└──────── if failed ─────────┘
\`\`\``}
className="w-full"
/>
),
toolFallbackHeight: 260,
},
{
userMessage: "Find that physics article from Quanta",
preamble: "Was it this one?",
toolUI: <LinkPreview {...LINK_PREVIEW} />,
toolFallbackHeight: 260,
},
{
userMessage: "Send Marcus the updated proposal",
preamble: "Drafted this for you. Review before sending.",
toolUI: (
<MessageDraft
id="chat-showcase-message-draft"
channel="email"
subject="Updated proposal attached"
to={["marcus.chen@acme.co"]}
body={`Hi Marcus,
I've attached the revised proposal with the changes we discussed. The new timeline reflects the Q2 launch date, and I've adjusted the budget breakdown in section 3.
Let me know if you have any questions.
Best,
Sarah`}
className="w-full max-w-[480px]"
/>
),
toolFallbackHeight: 340,
},
{
userMessage: "What was the first LLM?",
preamble: "GPT-1 from OpenAI in 2018. Here are the key sources.",
toolUI: (
<CitationList
id="showcase-citations"
citations={LLM_CITATIONS}
variant="stacked"
className="w-full max-w-[480px]"
/>
),
toolFallbackHeight: 56,
},
];
}
const SCENE_COUNT = 11;
type AnimatedSceneProps = {
config: SceneConfig;
reducedMotion: boolean;
onComplete: () => void;
sceneId: string;
isExiting?: boolean;
composerPadding?: boolean;
initialDelay?: number;
};
function AnimatedScene({
config,
reducedMotion,
onComplete,
sceneId,
isExiting = false,
initialDelay = 0,
}: AnimatedSceneProps) {
const timeline = useSceneTimeline({
reducedMotion,
onComplete,
hasUserMessage: !!config.userMessage,
initialDelay,
holdDuration: config.holdDuration,
});
const handlePreambleComplete = useCallback(() => {
timeline.setShowTool(true);
}, [timeline]);
useEffect(() => {
const shouldShowTool = timeline.preambleReady && !timeline.showTool;
if (shouldShowTool) {
timeline.setShowTool(true);
}
}, [timeline]);
const shouldRenderItems = !isExiting;
const shouldShowToolContent = config.preamble ? timeline.showTool : true;
const createEntryTransition = (delayMs: number) => ({
...SPRINGS.standard,
delay: delayMs / 1000,
});
const createExitTransition = (delayMs: number) => ({
...SPRINGS.standard,
delay: delayMs / 1000,
});
return (
<div className="flex flex-col pb-20">
<AnimatePresence>
{shouldRenderItems && config.userMessage && (
<motion.div
key={`${sceneId}-user`}
initial={{ opacity: 0, y: 16 }}
animate={{
opacity: 1,
y: 0,
transition: createEntryTransition(initialDelay + 80),
}}
exit={{
opacity: 0,
y: -8,
transition: createExitTransition(TIMING.exitStagger.user),
}}
className="mb-11"
>
<ChatBubble role="user" className="px-6 py-3">
{config.userMessage}
</ChatBubble>
</motion.div>
)}
{shouldRenderItems && config.preamble && (
<motion.div
key={`${sceneId}-preamble-area`}
className="relative mb-3"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{
opacity: 0,
y: -8,
transition: createExitTransition(TIMING.exitStagger.preamble),
}}
>
<AnimatePresence>
{config.userMessage &&
!timeline.preambleReady &&
!reducedMotion && (
<motion.div
key={`${sceneId}-indicator`}
className="absolute top-1.5 left-0"
initial={{ opacity: 0, scale: 0.5, filter: "blur(4px)" }}
animate={{
opacity: 1,
scale: 1,
filter: "blur(0px)",
transition: {
...SPRINGS.smooth,
delay: TIMING.durations.userIn / 1000,
},
}}
exit={{
opacity: 0,
x: 20,
filter: "blur(4px)",
transition: { duration: 0.2, ease: "easeOut" },
}}
>
<TypingIndicator />
</motion.div>
)}
</AnimatePresence>
{timeline.preambleReady && (
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
<PreambleBubble
text={config.preamble}
reducedMotion={reducedMotion}
onComplete={handlePreambleComplete}
/>
</motion.div>
)}
</motion.div>
)}
{shouldRenderItems &&
timeline.preambleReady &&
shouldShowToolContent && (
<motion.div
key={`${sceneId}-tool`}
initial={{ opacity: 0, y: 16 }}
animate={{
opacity: 1,
y: 0,
transition: createEntryTransition(
(config.preamble
? TIMING.beats.afterPreamble
: TIMING.beats.beforeContent) + 300,
),
}}
exit={{
opacity: 0,
y: -8,
transition: createExitTransition(TIMING.exitStagger.tool),
}}
className={config.userMessage ? "" : "mb-11"}
>
<div className="flex w-full justify-start">
<div className="w-full max-w-[720px] *:**:data-[slot=table]:min-w-0">
<ToolReveal>{config.toolUI}</ToolReveal>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
);
}
export function ChatShowcase() {
const reducedMotion = useReducedMotion();
const sceneConfigs = useMemo(
() => createSceneConfigs(reducedMotion),
[reducedMotion],
);
const [sceneIndex, setSceneIndex] = useState(0);
const [sceneRunId, setSceneRunId] = useState(0);
const [isExiting, setIsExiting] = useState(false);
const exitDuration = reducedMotion
? TIMING.reducedMotion.duration
: TIMING.exitStagger.tool + 500;
const transitionToScene = useCallback(
(getNextIndex: (current: number) => number) => {
setIsExiting(true);
setTimeout(() => {
setIsExiting(false);
setSceneIndex(getNextIndex);
setSceneRunId((id) => id + 1);
}, exitDuration);
},
[exitDuration],
);
const advanceToNextScene = useCallback(() => {
transitionToScene((current) => (current + 1) % SCENE_COUNT);
}, [transitionToScene]);
const goToPreviousScene = useCallback(() => {
transitionToScene((current) => (current - 1 + SCENE_COUNT) % SCENE_COUNT);
}, [transitionToScene]);
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === "ArrowRight") {
advanceToNextScene();
} else if (e.key === "ArrowLeft") {
goToPreviousScene();
}
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [advanceToNextScene, goToPreviousScene]);
return (
<div className="relative flex h-full w-full flex-col">
<div
className="pointer-events-none absolute inset-0 opacity-60 dark:opacity-40"
aria-hidden="true"
/>
<div className="relative z-10 h-full min-h-0 w-full">
<motion.div
key={`scene-${sceneIndex}-${sceneRunId}`}
className="absolute inset-0"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={SPRINGS.smooth}
>
<AnimatedScene
config={sceneConfigs[sceneIndex]}
reducedMotion={reducedMotion}
onComplete={advanceToNextScene}
sceneId={`scene-${sceneIndex}`}
isExiting={isExiting}
initialDelay={sceneRunId === 0 ? 2500 : 0}
/>
</motion.div>
</div>
</div>
);
}
================================================
FILE: apps/www/app/components/home/demo-chat.tsx
================================================
"use client";
import { useMemo } from "react";
import {
AssistantRuntimeProvider,
ThreadPrimitive,
Tools,
useAui,
} from "@assistant-ui/react";
import {
AssistantChatTransport,
useChatRuntime,
} from "@assistant-ui/react-ai-sdk";
import { lastAssistantMessageIsCompleteWithToolCalls } from "ai";
import { DEMO_CHAT_TOOLKIT } from "@/lib/demo-chat/toolkit";
import {
AssistantMessage,
Composer,
UserMessage,
} from "@/app/playground/chat-ui";
// Prompts designed to trigger specific tools: get_tasks, show_plan, show_stats, show_terminal
const SUGGESTIONS = [
{ text: "Show me the support tickets", tool: "get_tasks" },
{ text: "Create a deployment plan", tool: "show_plan" },
{ text: "How's Q4 looking?", tool: "show_stats" },
{ text: "Run the auth tests", tool: "show_terminal" },
] as const;
const PASTEL_COLORS = [
"bg-pink-100 text-pink-800 border-pink-200 hover:bg-pink-200/80 dark:bg-pink-950/40 dark:text-pink-200 dark:border-pink-800/50 dark:hover:bg-pink-900/30",
"bg-violet-100 text-violet-800 border-violet-200 hover:bg-violet-200/80 dark:bg-violet-950/40 dark:text-violet-200 dark:border-violet-800/50 dark:hover:bg-violet-900/30",
"bg-sky-100 text-sky-800 border-sky-200 hover:bg-sky-200/80 dark:bg-sky-950/40 dark:text-sky-200 dark:border-sky-800/50 dark:hover:bg-sky-900/30",
"bg-emerald-100 text-emerald-800 border-emerald-200 hover:bg-emerald-200/80 dark:bg-emerald-950/40 dark:text-emerald-200 dark:border-emerald-800/50 dark:hover:bg-emerald-900/30",
] as const;
function SuggestionChip({
children,
onClick,
colorClass,
}: {
children: string;
onClick: () => void;
colorClass: string;
}) {
return (
<button
type="button"
onClick={onClick}
className={`cursor-pointer rounded-2xl border px-6 py-4 text-left text-base font-medium transition-colors ${colorClass}`}
>
{children}
</button>
);
}
function SuggestionChips() {
const aui = useAui();
return (
<div className="flex flex-wrap justify-center gap-3">
{SUGGESTIONS.map(({ text, tool }, i) => (
<SuggestionChip
key={tool}
colorClass={PASTEL_COLORS[i]}
onClick={() => {
const composer = aui.composer();
composer.setText(text);
composer.send();
}}
>
{text}
</SuggestionChip>
))}
</div>
);
}
export function DemoChat() {
const transport = useMemo(
() =>
new AssistantChatTransport({
api: "/api/chat",
}),
[],
);
const runtime = useChatRuntime({
transport,
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls,
});
const aui = useAui({
tools: Tools({ toolkit: DEMO_CHAT_TOOLKIT }),
});
return (
<AssistantRuntimeProvider runtime={runtime} aui={aui}>
<ThreadPrimitive.Root className="flex h-full flex-col overflow-hidden">
<ThreadPrimitive.Viewport className="scrollbar-subtle bg-muted/30 flex flex-1 flex-col overflow-y-auto px-6 pt-20 pb-6">
<ThreadPrimitive.If empty>
<div className="text-muted-foreground mx-auto flex max-w-md flex-1 flex-col items-center justify-center gap-6 text-center">
<p className="text-2xl font-semibold">Try Tool UI</p>
<p className="text-sm">
Ask to see a plan, support tickets, metrics, or run a command.
Each response uses a different Tool UI component.
</p>
<SuggestionChips />
</div>
</ThreadPrimitive.If>
<ThreadPrimitive.Messages
components={{
UserMessage,
AssistantMessage,
}}
/>
</ThreadPrimitive.Viewport>
<div className="border-t px-4 pb-4 pt-3">
<Composer />
</div>
</ThreadPrimitive.Root>
</AssistantRuntimeProvider>
);
}
================================================
FILE: apps/www/app/components/home/faux-chat-shell-animated.tsx
================================================
"use client";
import { motion } from "motion/react";
import { FauxChatShellNoLightOverlay } from "./faux-chat-shell";
import { generateNoiseDataUri } from "./noise-texture";
function generateSineEasedGradient(
angle: number,
centerPosition: number,
peakOpacity: number,
spreadWidth: number,
steps: number = 128,
): string {
const stops: string[] = [];
for (let i = 0; i <= steps; i++) {
const t = i / steps;
const position = centerPosition - spreadWidth / 2 + spreadWidth * t;
const sineValue = Math.sin(t * Math.PI);
const eased = sineValue * sineValue;
const opacity = peakOpacity * eased;
stops.push(
`rgba(255, 255, 255, ${opacity.toFixed(4)}) ${position.toFixed(1)}%`,
);
}
return `linear-gradient(${angle}deg, ${stops.join(", ")})`;
}
export function FauxChatShellAnimated() {
// Hardcoded animation values
const initial = {
opacity: 0,
rotateX: 20,
rotateY: 37,
rotateZ: -13,
x: 429,
y: -298,
scale: 2,
};
const resting = {
opacity: 1,
rotateX: 37,
rotateY: 26,
rotateZ: -18,
x: -35,
y: -60,
scale: 1.05,
};
// Perspective and transform origin
const perspective = 3700;
const perspectiveOriginX = 100;
const perspectiveOriginY = 29;
const originX = 70;
const originY = 64;
const translateZInitial = 96;
const translateZResting = 96;
// Lighting parameters
const lightAngle = 140;
const lightPosition = 82;
const lightSpread = 29;
const lightOpacity = 0.07;
// Calculate light position based on surface normal (simulates static directional light)
function calculateLightPosition(rotateX: number, rotateY: number) {
const baseY = lightPosition;
const highlightY = baseY - rotateX * 0.8 - rotateY * 0.3;
return highlightY;
}
// Calculate highlight position for resting state
const restingLightPos = calculateLightPosition(
resting.rotateX,
resting.rotateY,
);
// Generate gradient centered at calculated position
const restingLightGradient = generateSineEasedGradient(
lightAngle,
restingLightPos,
lightOpacity,
lightSpread,
32,
);
// Animation config
const transition = {
type: "spring" as const,
duration: 5,
bounce: 0.2,
};
return (
<div
className="relative h-full w-full"
style={{
perspective: `${perspective}px`,
perspectiveOrigin: `${perspectiveOriginX}% ${perspectiveOriginY}%`,
}}
>
<motion.div
className="relative h-full w-full overflow-hidden rounded-2xl"
initial={{ ...initial, translateZ: translateZInitial }}
animate={{ ...resting, translateZ: translateZResting }}
transition={transition}
style={{
transformStyle: "preserve-3d",
transformOrigin: `${originX}% ${originY}%`,
}}
>
<FauxChatShellNoLightOverlay />
{/* Lighting overlay - fades in from 0 to full opacity */}
<motion.div
className="pointer-events-none absolute inset-0 z-30"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={transition}
style={{
backgroundImage: `url("${generateNoiseDataUri(64, 0.015)}"), ${restingLightGradient}`,
backgroundBlendMode: "overlay, normal",
}}
aria-hidden="true"
/>
</motion.div>
</div>
);
}
================================================
FILE: apps/www/app/components/home/faux-chat-shell-mobile-animated.tsx
================================================
"use client";
import { motion } from "motion/react";
import { FauxChatShellMobile } from "./faux-chat-shell-mobile";
import { generateNoiseDataUri } from "./noise-texture";
function generateSineEasedGradient(
angle: number,
centerPosition: number,
peakOpacity: number,
spreadWidth: number,
steps: number = 128,
): string {
const stops: string[] = [];
for (let i = 0; i <= steps; i++) {
const t = i / steps;
const position = centerPosition - spreadWidth / 2 + spreadWidth * t;
const sineValue = Math.sin(t * Math.PI);
const eased = sineValue * sineValue;
const opacity = peakOpacity * eased;
stops.push(
`rgba(255, 255, 255, ${opacity.toFixed(4)}) ${position.toFixed(1)}%`,
);
}
return `linear-gradient(${angle}deg, ${stops.join(", ")})`;
}
export function FauxChatShellMobileAnimated() {
// Hardcoded animation values - adjusted for portrait phone
const initial = {
opacity: 0,
rotateX: 20,
rotateY: 37,
rotateZ: -13,
x: 429,
y: -298,
scale: 2,
};
const resting = {
opacity: 1,
rotateX: 37,
rotateY: 26,
rotateZ: -18,
x: -35,
y: -60,
scale: 1.05,
};
// Perspective and transform origin
const perspective = 3700;
const perspectiveOriginX = 100;
const perspectiveOriginY = 29;
const originX = 70;
const originY = 64;
const translateZInitial = 96;
const translateZResting = 96;
// Lighting parameters
const lightAngle = 140;
const lightPosition = 82;
const lightSpread = 29;
const lightOpacity = 0.07;
// Calculate light position based on surface normal (simulates static directional light)
function calculateLightPosition(rotateX: number, rotateY: number) {
const baseY = lightPosition;
const highlightY = baseY - rotateX * 0.8 - rotateY * 0.3;
return highlightY;
}
// Calculate highlight position for resting state
const restingLightPos = calculateLightPosition(
resting.rotateX,
resting.rotateY,
);
// Generate gradient centered at calculated position
const restingLightGradient = generateSineEasedGradient(
lightAngle,
restingLightPos,
lightOpacity,
lightSpread,
32,
);
// Animation config
const transition = {
type: "spring" as const,
duration: 5,
bounce: 0.2,
};
return (
<div
className="relative h-full w-full flex items-center justify-center"
style={{
perspective: `${perspective}px`,
perspectiveOrigin: `${perspectiveOriginX}% ${perspectiveOriginY}%`,
}}
>
<motion.div
className="relative h-full w-full overflow-hidden rounded-[2.5rem]"
initial={{ ...initial, translateZ: translateZInitial }}
animate={{ ...resting, translateZ: translateZResting }}
transition={transition}
style={{
transformStyle: "preserve-3d",
transformOrigin: `${originX}% ${originY}%`,
}}
>
<FauxChatShellMobile />
{/* Lighting overlay - fades in from 0 to full opacity */}
<motion.div
className="pointer-events-none absolute inset-0 z-30"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={transition}
style={{
backgroundImage: `url("${generateNoiseDataUri(64, 0.015)}"), ${restingLightGradient}`,
backgroundBlendMode: "overlay, normal",
}}
aria-hidden="true"
/>
</motion.div>
</div>
);
}
================================================
FILE: apps/www/app/components/home/faux-chat-shell-mobile.tsx
================================================
"use client";
import { useEffect, useState } from "react";
import { cn } from "@/lib/ui/cn";
import { ChatShowcase } from "./chat-showcase";
type FauxChatShellMobileProps = {
className?: string;
};
function DynamicIsland() {
return (
<div
className="absolute left-1/2 top-3 z-30 -translate-x-1/2"
aria-hidden="true"
>
<div className="border-gradient-glow-notch h-9 w-32 rounded-full" />
</div>
);
}
function StatusBar() {
const [time, setTime] = useState<string>("");
useEffect(() => {
const updateTime = () => {
const now = new Date();
let hours = now.getHours();
const minutes = now.getMinutes().toString().padStart(2, "0");
hours = hours % 12 || 12;
setTime(`${hours}:${minutes}`);
};
updateTime();
const scheduleNextUpdate = () => {
const now = new Date();
const msUntilNextMinute =
(60 - now.getSeconds()) * 1000 - now.getMilliseconds();
return setTimeout(() => {
updateTime();
intervalRef = setInterval(updateTime, 60000);
}, msUntilNextMinute);
};
let intervalRef: ReturnType<typeof setInterval> | null = null;
const timeoutRef = scheduleNextUpdate();
return () => {
clearTimeout(timeoutRef);
if (intervalRef) clearInterval(intervalRef);
};
}, []);
return (
<div className="absolute inset-x-0 top-0 z-20 flex items-center justify-between px-6 pt-6 text-sm">
<div className="font-medium">{time}</div>
<div className="flex items-center gap-1">
{/* Signal/WiFi/Battery icons would go here - keeping minimal */}
</div>
</div>
);
}
export function FauxChatShellMobile({ className }: FauxChatShellMobileProps) {
return (
<div
className={cn(
"border-gradient-glow relative flex h-full w-full max-w-[430px] flex-col overflow-hidden rounded-[2.5rem] backdrop-blur-lg",
className,
)}
style={{
aspectRatio: "9 / 19.5",
boxShadow: [
"0 1px 3px rgba(0, 0, 0, 0.05)",
"0 2px 4px rgba(0, 0, 0, 0.008)",
"0 4px 8px rgba(0, 0, 0, 0.02)",
"0 8px 16px rgba(0, 0, 0, 0.02)",
"0 16px 32px rgba(0, 0, 0, 0.02)",
"0 32px 48px rgba(0, 0, 0, 0.03)",
].join(", "),
backfaceVisibility: "hidden",
willChange: "transform",
WebkitFontSmoothing: "subpixel-antialiased",
}}
>
<DynamicIsland />
<StatusBar />
<div className="scrollbar-subtle relative z-0 grow overflow-y-auto px-4 pt-20">
<ChatShowcase />
</div>
<div
className="pointer-events-none absolute inset-x-0 bottom-0 z-10 h-24"
style={{
background:
"linear-gradient(to top, var(--glow-surface-to) 0%, transparent 100%)",
}}
aria-hidden="true"
/>
</div>
);
}
================================================
FILE: apps/www/app/components/home/faux-chat-shell.tsx
================================================
"use client";
import { useEffect, useRef, useState } from "react";
import { cn } from "@/lib/ui/cn";
import { ChatShowcase } from "./chat-showcase";
import { DemoChat } from "./demo-chat";
type FauxChatShellProps = {
className?: string;
/** When true, renders live DemoChat instead of static ChatShowcase */
live?: boolean;
};
export function generateSineEasedGradient(
angle: number,
centerPosition: number,
peakOpacity: number,
spreadWidth: number,
steps: number = 128,
): string {
const stops: string[] = [];
for (let i = 0; i <= steps; i++) {
const t = i / steps;
const position = centerPosition - spreadWidth / 2 + spreadWidth * t;
// Sine curve: peaks at center (t=0.5), zero at edges (t=0, t=1)
// Square the sine for even smoother falloff at edges
const sineValue = Math.sin(t * Math.PI);
const eased = sineValue * sineValue;
const opacity = peakOpacity * eased;
stops.push(
`rgba(255, 255, 255, ${opacity.toFixed(4)}) ${position.toFixed(1)}%`,
);
}
// No hard transparent stops — sine² already smoothly reaches zero at edges
return `linear-gradient(${angle}deg, ${stops.join(", ")})`;
}
function useDirectionalLight(
containerRef: React.RefObject<HTMLDivElement | null>,
) {
const [gradientStyle, setGradientStyle] = useState<React.CSSProperties>({});
useEffect(() => {
const container = containerRef.current;
if (!container) return;
const updateGradient = () => {
const parent = container.parentElement;
if (!parent) return;
const style = getComputedStyle(parent);
const rotateX =
parseFloat(style.getPropertyValue("--shell-rotate-x")) || 0;
const rotateY =
parseFloat(style.getPropertyValue("--shell-rotate-y")) || 0;
// Light params from CSS custom properties (with defaults)
const baseAngle =
parseFloat(style.getPropertyValue("--light-angle")) || 135;
const basePosition =
parseFloat(style.getPropertyValue("--light-position")) || 35;
const spread = parseFloat(style.getPropertyValue("--light-spread")) || 40;
const opacity =
parseFloat(style.getPropertyValue("--light-opacity")) || 0.12;
const rotateXFactor =
parseFloat(style.getPropertyValue("--light-rotate-x-factor")) || 1.2;
const rotateYFactor =
parseFloat(style.getPropertyValue("--light-rotate-y-factor")) || 0.8;
// Highlight position shifts based on rotation (light "slides" across surface)
const centerPosition =
basePosition - rotateX * rotateXFactor - rotateY * rotateYFactor;
const gradient = generateSineEasedGradient(
baseAngle,
centerPosition,
opacity,
spread,
32,
);
setGradientStyle({ background: gradient });
};
updateGradient();
// Watch for changes via MutationObserver on parent's style attribute
const parent = container.parentElement;
if (!parent) return;
const observer = new MutationObserver(updateGradient);
observer.observe(parent, { attributes: true, attributeFilter: ["style"] });
return () => observer.disconnect();
}, [containerRef]);
return gradientStyle;
}
function WindowDots() {
return (
<div className="flex items-center gap-1.5" aria-hidden="true">
<span className="border-gradient-glow border-gradient-glow-dot size-3.5 rounded-full" />
<span className="border-gradient-glow border-gradient-glow-dot size-3.5 rounded-full" />
<span className="border-gradient-glow border-gradient-glow-dot size-3.5 rounded-full" />
</div>
);
}
function ComposerBar() {
return (
<div className="absolute inset-x-0 bottom-0 z-20 px-4 pb-4">
<div className="border-gradient-glow border-gradient-glow-composer h-10 w-full rounded-full" />
</div>
);
}
function FauxChatShellBase({
className,
showLightOverlay,
live = false,
}: FauxChatShellProps & { showLightOverlay: boolean }) {
const containerRef = useRef<HTMLDivElement>(null);
const gradientStyle = useDirectionalLight(containerRef);
return (
<div
ref={containerRef}
className={cn(
"border-gradient-glow relative flex h-full w-full flex-col overflow-hidden rounded-2xl backdrop-blur-lg",
className,
)}
style={{
boxShadow: [
"0 1px 3px rgba(0, 0, 0, 0.05)",
"0 2px 4px rgba(0, 0, 0, 0.008)",
"0 4px 8px rgba(0, 0, 0, 0.02)",
"0 8px 16px rgba(0, 0, 0, 0.02)",
"0 16px 32px rgba(0, 0, 0, 0.02)",
"0 32px 48px rgba(0, 0, 0, 0.03)",
].join(", "),
// 3D rendering quality improvements
backfaceVisibility: "hidden",
willChange: "transform",
WebkitFontSmoothing: "subpixel-antialiased",
}}
>
{/* Directional light reflection overlay */}
{showLightOverlay && (
<div
className="pointer-events-none absolute inset-0 z-30 rounded-2xl"
style={gradientStyle}
aria-hidden="true"
/>
)}
<div className="bg-background/80 absolute z-20 w-full rounded-t-2xl backdrop-blur-lg">
<div className="flex h-10 shrink-0 items-center px-4 pt-0.5">
<WindowDots />
</div>
<div className="gradient-line-header h-px" />
</div>
<div
className={
live
? "relative z-0 flex min-h-0 flex-1 flex-col overflow-hidden"
: "scrollbar-subtle relative z-0 grow overflow-y-auto px-6 pt-24"
}
>
{live ? <DemoChat /> : <ChatShowcase />}
</div>
{!live && (
<>
<div
className="pointer-events-none absolute inset-x-0 right-3 bottom-0 z-10 h-24"
style={{
background:
"linear-gradient(to top, var(--glow-surface-to) 0%, transparent 100%)",
}}
aria-hidden="true"
/>
<ComposerBar />
</>
)}
</div>
);
}
export function FauxChatShell(props: FauxChatShellProps) {
return <FauxChatShellBase {...props} showLightOverlay={true} />;
}
export function FauxChatShellNoLightOverlay(props: FauxChatShellProps) {
return <FauxChatShellBase {...props} showLightOverlay={false} />;
}
================================================
FILE: apps/www/app/components/home/home-background.tsx
================================================
"use client";
export function HomeBackground() {
return (
<>
<div
className="bg-background pointer-events-none fixed inset-0 opacity-60 dark:opacity-40"
style={{ animation: "home-bg-fade-in 0.6s ease-out forwards" }}
aria-hidden="true"
/>
<style jsx>{`
@keyframes home-bg-fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
`}</style>
</>
);
}
================================================
FILE: apps/www/app/components/home/home-hero.tsx
================================================
"use client";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { ArrowRight } from "lucide-react";
import { motion } from "motion/react";
import { HomeHexnutScene } from "./home-hexnut-scene";
import { Button } from "@/components/ui/button";
import { analytics } from "@/lib/analytics";
const smoothSpring = {
type: "spring" as const,
stiffness: 200,
damping: 40,
duration: 0.8,
restDelta: 0.0001,
};
export function HomeHero() {
const router = useRouter();
const preloadGallery = () => {
void router.prefetch("/docs/gallery");
};
return (
<div className="flex flex-col gap-7">
<motion.div
className="-mb-4 -ml-4 flex items-end justify-start"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ ...smoothSpring, delay: 0.1 }}
>
<HomeHexnutScene />
</motion.div>
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-3">
<motion.h1
className="text-6xl font-bold tracking-wide"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ ...smoothSpring, delay: 0.1 }}
>
Tool UI
</motion.h1>
</div>
<motion.h2
className="text-2xl text-pretty"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ ...smoothSpring, delay: 0.3 }}
>
UI components for AI interfaces
</motion.h2>
</div>
<motion.p
className="text-muted-foreground mb-2 text-lg text-pretty"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ ...smoothSpring, delay: 0.4 }}
>
JSON-native, typed, accessible, copy-pasteable.{" "}
<br className="hidden md:block" />
Built on Tailwind, Radix, and shadcn/ui. Open Source.
</motion.p>
<motion.div
initial={{ opacity: 0, y: 20, scale: 0.98 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
transition={{ ...smoothSpring, delay: 0.5 }}
>
<Button
asChild
className="group font-medium tracking-wide"
size="homeCTA"
>
<Link
href="/docs/gallery"
onMouseEnter={preloadGallery}
onFocus={preloadGallery}
onClick={() => analytics.cta.clicked("see_components", "home_hero")}
>
See the Components
<ArrowRight className="size-5 shrink-0 transition-transform group-hover:translate-x-1" />
</Link>
</Button>
</motion.div>
</div>
);
}
================================================
FILE: apps/www/app/components/home/home-hexnut-scene.tsx
================================================
"use client";
import dynamic from "next/dynamic";
// Dynamic import with SSR disabled for Three.js components
const HexnutSceneCanvas = dynamic(
() =>
import("@/app/components/visuals/spinning-hexnut/hexnut-scene").then(
(mod) => mod.HexnutScene,
),
{
ssr: false,
loading: () => <div className="size-36 sm:size-48 bg-transparent" />,
},
);
export function HomeHexnutScene() {
return (
<div className="size-36 sm:size-48">
<HexnutSceneCanvas width="100%" height="100%" />
</div>
);
}
================================================
FILE: apps/www/app/components/home/noise-texture.ts
================================================
/**
* Generates a data URI for a subtle noise texture to reduce gradient banding
* @param size - Size of the noise tile (default: 64px)
* @param opacity - Opacity of the noise (0-1, default: 0.02)
*/
export function generateNoiseDataUri(
size: number = 64,
opacity: number = 0.02,
): string {
// Create a minimal noise pattern using SVG
// This is more efficient than canvas and works in SSR
const svg = `
<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}">
<filter id="noise">
<feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="4" />
<feComponentTransfer>
<feFuncA type="discrete" tableValues="0 ${opacity}" />
</feComponentTransfer>
</filter>
<rect width="${size}" height="${size}" filter="url(#noise)" />
</svg>
`.trim();
// Use URL encoding consistently for both SSR and client to avoid hydration mismatch
return `data:image/svg+xml,${encodeURIComponent(svg)}`;
}
/**
* CSS style object for applying noise texture over gradients
*/
export function getNoiseOverlayStyle(opacity: number = 0.02) {
return {
backgroundImage: `url("${generateNoiseDataUri(64, opacity)}")`,
backgroundBlendMode: "overlay" as const,
};
}
================================================
FILE: apps/www/app/components/layout/app-header.server.tsx
================================================
import { ReactNode } from "react";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { FaGithub } from "react-icons/fa";
import { FaXTwitter } from "react-icons/fa6";
import { ArrowUpRight } from "lucide-react";
import { LogoMark } from "@/components/ui/logo";
import { ActiveNavLink } from "./header-active-link.client";
import { TrackedExternalAnchor } from "./tracked-external-anchor.client";
interface ResponsiveHeaderProps {
rightContent?: ReactNode;
}
export function ResponsiveHeader({ rightContent }: ResponsiveHeaderProps) {
const navLinks = [
{ href: "/docs/overview", label: "Docs" },
{ href: "/docs/gallery", label: "Gallery" },
];
return (
<div className="pt-calc(env(safe-area-inset-top)+0.5rem) flex gap-4 pt-4 pb-2 sm:pt-8 sm:pb-3 md:gap-8">
<div className="flex w-fit shrink-0 items-center justify-start gap-3 md:items-center">
<Link href="/" className="flex items-center gap-1.5">
<LogoMark className="-mb-0.5 size-6" />
<h1 className="text-2xl font-semibold">Tool UI</h1>
</Link>
</div>
{/* Desktop Navigation */}
<div className="hidden flex-1 items-center justify-between md:flex md:pl-18">
<nav className="flex items-center gap-1">
{navLinks.map(({ href, label }) => (
<ActiveNavLink key={href} href={href}>
{label}
</ActiveNavLink>
))}
<TrackedExternalAnchor
href="https://www.assistant-ui.com"
destination="docs"
target="_blank"
rel="noopener noreferrer"
className="hover:text-foreground hover:bg-muted/50 hidden items-center gap-0.5 rounded-lg px-4 py-2 text-sm font-medium transition-colors lg:flex"
>
assistant-ui
<ArrowUpRight className="size-4" />
</TrackedExternalAnchor>
</nav>
<div className="flex items-center gap-4">
{rightContent}
<div className="flex items-center">
<Button variant="ghost" size="icon" asChild>
<TrackedExternalAnchor
href="https://github.com/assistant-ui/tool-ui"
destination="github"
target="_blank"
rel="noopener noreferrer"
>
<FaGithub className="size-5" />
<span className="sr-only">GitHub Repository</span>
</TrackedExternalAnchor>
</Button>
<Button variant="ghost" size="icon" asChild>
<TrackedExternalAnchor
href="https://x.com/assistantui"
destination="other"
target="_blank"
rel="noopener noreferrer"
>
<FaXTwitter className="size-5" />
<span className="sr-only">X (Twitter)</span>
</TrackedExternalAnchor>
</Button>
</div>
</div>
</div>
{/* Mobile Right Content */}
<div className="flex flex-1 items-center justify-end gap-2 md:hidden">
{rightContent}
</div>
</div>
);
}
================================================
FILE: apps/www/app/components/layout/app-shell-animated.client.tsx
================================================
"use client";
import type { ReactNode } from "react";
import { useEffect, useState } from "react";
import { ResponsiveHeader } from "@/app/components/layout/app-header.server";
import { cn } from "@/lib/ui/cn";
type HeaderFrameProps = {
children: ReactNode;
rightContent?: ReactNode;
background?: ReactNode;
};
// Persists for the life of the client bundle so the intro animation runs once.
let hasPlayedIntroAnimation = false;
function HeaderFrameBase({
children,
rightContent,
background,
shouldAnimate,
}: HeaderFrameProps & { shouldAnimate: boolean }) {
return (
<div className="relative flex h-full flex-col items-center overflow-hidden">
{background ? (
<div className="pointer-events-none absolute inset-0 z-0">
{background}
</div>
) : null}
<div
className={cn(
"relative z-10 w-full max-w-[1440px] shrink-0 px-4 md:px-8",
shouldAnimate && "animate-navbar-fade-in",
)}
>
<ResponsiveHeader rightContent={rightContent} />
</div>
<div className="relative z-10 flex min-h-0 w-full flex-1 justify-center">
{children}
</div>
</div>
);
}
export function AnimatedHeaderFrame(props: HeaderFrameProps) {
const [shouldAnimate] = useState(() => !hasPlayedIntroAnimation);
useEffect(() => {
if (shouldAnimate) {
hasPlayedIntroAnimation = true;
}
}, [shouldAnimate]);
return <HeaderFrameBase {...props} shouldAnimate={shouldAnimate} />;
}
================================================
FILE: apps/www/app/components/layout/app-shell.tsx
================================================
import type { ReactNode } from "react";
import { ResponsiveHeader } from "@/app/components/layout/app-header.server";
import { cn } from "@/lib/ui/cn";
export type HeaderFrameProps = {
children: ReactNode;
rightContent?: ReactNode;
background?: ReactNode;
};
function HeaderFrameBase({
children,
rightContent,
background,
shouldAnimate,
}: HeaderFrameProps & { shouldAnimate: boolean }) {
return (
<div className="relative flex h-full flex-col items-center overflow-hidden">
{background ? (
<div className="pointer-events-none absolute inset-0 z-0">
{background}
</div>
) : null}
<div
className={cn(
"relative z-10 w-full max-w-[1440px] shrink-0 px-4 md:px-8",
shouldAnimate && "animate-navbar-fade-in",
)}
>
<ResponsiveHeader rightContent={rightContent} />
</div>
<div className="relative z-10 flex min-h-0 w-full flex-1 justify-center">
{children}
</div>
</div>
);
}
export function HeaderFrame(props: HeaderFrameProps) {
return <HeaderFrameBase {...props} shouldAnimate={false} />;
}
================================================
FILE: apps/www/app/components/layout/header-active-link.client.tsx
================================================
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { cn } from "@/lib/ui/cn";
interface ActiveNavLinkProps {
href: string;
children: React.ReactNode;
}
export function ActiveNavLink({ href, children }: ActiveNavLinkProps) {
const pathname = usePathname();
const isActive = href === "/" ? pathname === "/" : pathname.startsWith(href);
return (
<Link
href={href}
className={cn(
"active:bg-primary/10 rounded-lg px-4 py-2 text-sm transition-[colors,background] duration-75",
isActive ? "bg-primary/5" : "hover:bg-primary/5",
)}
aria-current={isActive ? "page" : undefined}
>
{children}
</Link>
);
}
================================================
FILE: apps/www/app/components/layout/mobile-nav-sheet-gate.client.tsx
================================================
"use client";
import dynamic from "next/dynamic";
import { usePathname } from "next/navigation";
import { useEffect, useState } from "react";
const MobileNavSheet = dynamic(
() =>
import("@/app/components/layout/mobile-nav-sheet.client").then(
(mod) => mod.MobileNavSheet,
),
{
ssr: false,
},
);
const MOBILE_QUERY = "(max-width: 767px)";
function shouldRenderForPath(pathname: string) {
return (
pathname === "/" ||
pathname.startsWith("/docs") ||
pathname.startsWith("/builder")
);
}
export function MobileNavSheetGate() {
const pathname = usePathname();
const [isMobileViewport, setIsMobileViewport] = useState(false);
useEffect(() => {
const mediaQuery = window.matchMedia(MOBILE_QUERY);
const updateViewportMatch = () => setIsMobileViewport(mediaQuery.matches);
updateViewportMatch();
mediaQuery.addEventListener("change", updateViewportMatch);
return () => {
mediaQuery.removeEventListener("change", updateViewportMatch);
};
}, []);
if (!isMobileViewport || !shouldRenderForPath(pathname)) {
return null;
}
return <MobileNavSheet />;
}
================================================
FILE: apps/www/app/components/layout/mobile-nav-sheet.client.tsx
================================================
"use client";
import React from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { Sheet, Scroll } from "@silk-hq/components";
import { FaGithub } from "react-icons/fa";
import { FaXTwitter } from "react-icons/fa6";
import { componentsRegistry } from "@/lib/docs/component-registry";
import { BASE_DOCS_PAGES } from "@/app/docs/_components/docs-pages";
import { cn } from "@/lib/ui/cn";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
import { TrackedExternalAnchor } from "./tracked-external-anchor.client";
import "@/app/styles/nav-sheet.css";
export function MobileNavSheet() {
const pathname = usePathname();
const [presented, setPresented] = React.useState(false);
const [showScrollIndicator, setShowScrollIndicator] = React.useState(true);
const [isMobileViewport, setIsMobileViewport] = React.useState(false);
React.useEffect(() => {
const mediaQuery = window.matchMedia("(max-width: 767px)");
const updateViewportMatch = () => setIsMobileViewport(mediaQuery.matches);
updateViewportMatch();
mediaQuery.addEventListener("change", updateViewportMatch);
return () => {
mediaQuery.removeEventListener("change", updateViewportMatch);
};
}, []);
const isDocs = pathname.startsWith("/docs") && pathname !== "/docs/gallery";
const isGallery = pathname === "/docs/gallery";
const mainNavLinks = [
{ href: "/docs/overview", label: "Docs", isActive: isDocs },
{ href: "/docs/gallery", label: "Gallery", isActive: isGallery },
];
if (!isMobileViewport) {
return null;
}
return (
<Sheet.Root
license="non-commercial"
presented={presented}
onPresentedChange={setPresented}
defaultActiveDetent={1}
>
{/* Floating Action Button */}
<Sheet.Trigger asChild>
<Button
variant="default"
size="icon"
className="MobileNavSheet-trigger z-50 size-14 rounded-full shadow-lg md:hidden"
aria-label="Open navigation"
>
<svg
className="size-6"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
>
<line x1="4" y1="8" x2="20" y2="8" />
<line x1="4" y1="16" x2="20" y2="16" />
</svg>
</Button>
</Sheet.Trigger>
{/* Bottom Sheet Portal */}
<Sheet.Portal>
<Sheet.View
className="MobileNavSheet-view"
nativeEdgeSwipePrevention={true}
>
<Sheet.Backdrop
className="MobileNavSheet-backdrop"
travelAnimation={{
opacity: [0, 0.8],
}}
themeColorDimming="auto"
/>
<Sheet.Content className="MobileNavSheet-content">
<Sheet.BleedingBackground className="MobileNavSheet-bleedingBackground" />
{/* handle */}
<div className="elative absolute top-0 right-0 left-0 z-20 flex items-center justify-center bg-transparent py-4">
<div className="bg-muted-foreground h-1 w-12 rounded-full" />
</div>
{/* Top Scroll Indicator Gradient */}
<div className="from-background pointer-events-none absolute top-0 right-0 left-0 z-10 h-24 rounded-tl-xl rounded-tr-xl bg-linear-to-b to-transparent" />
<Scroll.Root className="scrollbar-subtle relative flex-1 overflow-hidden">
<Scroll.View
className="h-full"
safeArea="visual-viewport"
nativeFocusScrollPrevention={true}
onScroll={({ progress }) => {
// Hide bottom indicator when scrolled near the bottom (within 5%)
setShowScrollIndicator(progress < 0.95);
}}
>
<Scroll.Content>
<nav className="flex flex-col gap-2 p-4 pt-12">
{mainNavLinks.map(({ href, label, isActive }) => (
<Link
key={href}
href={href}
onClick={() => setPresented(false)}
className={cn(
"rounded-lg px-4 py-4 text-3xl font-medium transition-colors",
isActive
? "bg-muted text-foreground"
: "text-primary hover:bg-muted/50 hover:text-foreground",
)}
>
{label}
</Link>
))}
</nav>
<div className="my-3 px-8">
<Separator />
</div>
{/* Docs Section */}
<div className="flex flex-col gap-1 px-4 py-8">
<div className="text-muted-foreground mb-3 px-4 text-xs tracking-widest uppercase">
Get Started
</div>
{BASE_DOCS_PAGES.map((page) => {
const isActive = pathname === page.path;
return (
<Link
key={page.path}
href={page.path}
onClick={() => setPresented(false)}
className={cn(
"text-primary rounded-lg px-4 py-3.5",
isActive
? "bg-muted text-foreground font-medium"
: "text-primary hover:bg-muted/50 hover:text-foreground",
)}
>
{page.label}
</Link>
);
})}
</div>
{/* Components Section */}
<div className="flex flex-col gap-1 px-4 pb-8">
<div className="text-muted-foreground mb-3 px-4 text-xs tracking-widest uppercase">
Components
</div>
{componentsRegistry.map((component) => {
const isActive = pathname === component.path;
return (
<Link
key={component.id}
href={component.path}
onClick={() => setPresented(false)}
className={cn(
"text-primary rounded-lg px-4 py-3.5",
isActive
? "bg-muted text-foreground font-medium"
: "text-primary hover:bg-muted/50 hover:text-foreground",
)}
>
{component.label}
</Link>
);
})}
</div>
</Scroll.Content>
</Scroll.View>
{/* Bottom Scroll Indicator Gradient */}
{showScrollIndicator && (
<div className="MobileNavSheet-bottomGradient" />
)}
</Scroll.Root>
{/* Social Links Footer */}
<footer className="MobileNavSheet-footer">
<div className="MobileNavSheet-footerInner">
<Button variant="outline" size="lg" className="flex-1" asChild>
<TrackedExternalAnchor
href="https://github.com/assistant-ui/tool-ui"
destination="github"
target="_blank"
rel="noopener noreferrer"
>
<FaGithub className="size-6" />
</TrackedExternalAnchor>
</Button>
<Button variant="outline" size="lg" className="flex-1" asChild>
<TrackedExternalAnchor
href="https://x.com/assistantui"
destination="other"
target="_blank"
rel="noopener noreferrer"
>
<FaXTwitter className="size-6" />
</TrackedExternalAnchor>
</Button>
</div>
</footer>
</Sheet.Content>
</Sheet.View>
</Sheet.Portal>
</Sheet.Root>
);
}
================================================
FILE: apps/www/app/components/layout/page-shell.tsx
================================================
import type { ReactNode } from "react";
type ContentLayoutProps = {
children: ReactNode;
sidebar?: ReactNode;
};
export default function ContentLayout({
children,
sidebar,
}: ContentLayoutProps) {
return (
<div className="flex min-h-0 w-full max-w-[1440px] flex-1">
{sidebar ? (
<div className="relative hidden w-[220px] shrink-0 md:block">
<div
className="from-background pointer-events-none absolute top-0 right-2 left-0 z-10 h-12 bg-linear-to-b to-transparent"
aria-hidden="true"
/>
<div className="scrollbar-subtle h-full overflow-y-auto pt-4">
{sidebar}
</div>
<div
className="from-background pointer-events-none absolute right-2 bottom-0 left-0 z-10 h-12 bg-linear-to-t to-transparent"
aria-hidden="true"
/>
</div>
) : null}
<div className="flex min-h-0 min-w-0 w-full flex-1">{children}</div>
</div>
);
}
================================================
FILE: apps/www/app/components/layout/tracked-external-anchor.client.tsx
================================================
"use client";
import * as React from "react";
import { analytics } from "@/lib/analytics";
type ExternalDestination = "github" | "npm" | "docs" | "other";
type TrackedExternalAnchorProps = React.ComponentPropsWithoutRef<"a"> & {
destination: ExternalDestination;
};
export const TrackedExternalAnchor = React.forwardRef<
HTMLAnchorElement,
TrackedExternalAnchorProps
>(function TrackedExternalAnchor(
{ destination, href, onClick, ...props },
ref,
) {
const hrefValue = typeof href === "string" ? href : "";
const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
analytics.external.linkClicked(destination, hrefValue);
onClick?.(event);
};
return <a ref={ref} href={href} onClick={handleClick} {...props} />;
});
================================================
FILE: apps/www/app/components/mdx/features.tsx
================================================
import { cn } from "@/lib/ui/cn";
import type { LucideIcon } from "lucide-react";
import {
Palette,
Copy,
Hash,
Highlighter,
FoldVertical,
FileCode,
FileText,
Moon,
BarChart3,
LineChart,
MousePointerClick,
CircleCheck,
CheckCircle2,
ListChecks,
Settings2,
SquareCheck,
Paintbrush,
Terminal,
Timer,
AlertCircle,
AlertTriangle,
Code,
FileOutput,
Smartphone,
ArrowUpDown,
Table2,
Accessibility,
Link,
Image,
Video,
Headphones,
Download,
Expand,
PartyPopper,
HelpCircle,
Layers,
Play,
Eye,
Maximize2,
ListTodo,
List,
GalleryHorizontalEnd,
Keyboard,
Globe,
ExternalLink,
Ratio,
Quote,
ShieldCheck,
Target,
MessageSquare,
BadgeCheck,
Images,
Network,
Route,
ScanSearch,
Rocket,
DollarSign,
Package,
Grid2x2,
Move,
PlusCircle,
SlidersHorizontal,
CloudSun,
MapPin,
Thermometer,
Calendar,
} from "lucide-react";
const ICON_MAP: Record<string, LucideIcon> = {
Palette,
Copy,
Hash,
Highlighter,
FoldVertical,
FileCode,
FileText,
Moon,
BarChart3,
LineChart,
MousePointerClick,
CircleCheck,
CheckCircle2,
ListChecks,
Settings2,
SquareCheck,
Paintbrush,
Terminal,
Timer,
AlertCircle,
AlertTriangle,
Code,
FileOutput,
Smartphone,
ArrowUpDown,
Table2,
Accessibility,
Link,
Image,
Video,
Headphones,
Download,
Expand,
PartyPopper,
HelpCircle,
Layers,
Play,
Eye,
Maximize2,
ListTodo,
List,
GalleryHorizontalEnd,
Keyboard,
Globe,
ExternalLink,
AspectRatio: Ratio,
Quote,
ShieldCheck,
Target,
MessageSquare,
BadgeCheck,
Images,
Network,
Route,
ScanSearch,
Rocket,
DollarSign,
Package,
Grid2x2,
Move,
PlusCircle,
SlidersHorizontal,
CloudSun,
MapPin,
Thermometer,
Calendar,
};
interface FeatureGridProps {
children: React.ReactNode;
className?: string;
}
export function FeatureGrid({ children, className }: FeatureGridProps) {
return (
<div
className={cn(
"not-prose my-6 grid grid-cols-1 gap-4 sm:grid-cols-2",
className,
)}
>
{children}
</div>
);
}
interface FeatureProps {
icon: string;
title: string;
children: React.ReactNode;
className?: string;
}
export function Feature({ icon, title, children, className }: FeatureProps) {
const IconComponent = ICON_MAP[icon] ?? HelpCircle;
return (
<div
className={cn(
"border-border/50 bg-muted/50 flex min-h-26 flex-col justify-between gap-3 rounded-xl border p-4",
className,
)}
>
<IconComponent className="text-muted-foreground h-5 w-5" />
<div>
<div className="leading-none font-semibold text-pretty">{title}</div>
<div className="text-muted-foreground mt-1.5 text-sm text-pretty">
{children}
</div>
</div>
</div>
);
}
================================================
FILE: apps/www/app/components/mdx/mermaid.tsx
================================================
"use client";
import { useEffect, useId, useRef, useState } from "react";
import { useTheme } from "next-themes";
interface MermaidProps {
chart: string;
}
let mermaidPromise: Promise<typeof import("mermaid")> | null = null;
function getMermaid() {
if (!mermaidPromise) {
mermaidPromise = import("mermaid");
}
return mermaidPromise;
}
export function Mermaid({ chart }: MermaidProps) {
const id = useId();
const { resolvedTheme } = useTheme();
const [svg, setSvg] = useState<string>("");
gitextract_06635t45/ ├── .changeset/ │ └── config.json ├── .git-blame-ignore-revs ├── .githooks/ │ ├── pre-commit │ └── pre-push ├── .github/ │ ├── pull_request_template.md │ └── workflows/ │ ├── changeset.yaml │ ├── ci.yml │ └── npm-publish.yaml ├── .gitignore ├── .prettierignore ├── AGENTS.md ├── AGENT_CHANGELOG.md ├── CLAUDE.md ├── LICENSE.md ├── README.md ├── apps/ │ └── www/ │ ├── .oxfmtrc.jsonc │ ├── .oxlintrc.json │ ├── .prettierignore │ ├── app/ │ │ ├── api/ │ │ │ ├── builder/ │ │ │ │ ├── chat/ │ │ │ │ │ └── route.ts │ │ │ │ └── create-freestyle/ │ │ │ │ └── route.ts │ │ │ ├── chat/ │ │ │ │ └── route.ts │ │ │ ├── mcp-tools/ │ │ │ │ └── route.ts │ │ │ ├── playground/ │ │ │ │ └── chat/ │ │ │ │ └── route.ts │ │ │ └── weather-tuning/ │ │ │ ├── _lib/ │ │ │ │ └── tuned-presets-io.ts │ │ │ ├── apply/ │ │ │ │ └── route.ts │ │ │ └── recover/ │ │ │ └── route.ts │ │ ├── builder/ │ │ │ ├── layout.tsx │ │ │ ├── opengraph-image.tsx │ │ │ └── page.tsx │ │ ├── components/ │ │ │ ├── analytics/ │ │ │ │ └── posthog-init.client.tsx │ │ │ ├── assistant-ui/ │ │ │ │ ├── markdown-text.tsx │ │ │ │ ├── thread-list.tsx │ │ │ │ ├── tool-fallback.tsx │ │ │ │ └── tooltip-icon-button.tsx │ │ │ ├── builder/ │ │ │ │ ├── mcp-icon.tsx │ │ │ │ ├── theme-toggle.tsx │ │ │ │ ├── webview-actions.ts │ │ │ │ └── webview.tsx │ │ │ ├── home/ │ │ │ │ ├── chat-showcase.tsx │ │ │ │ ├── demo-chat.tsx │ │ │ │ ├── faux-chat-shell-animated.tsx │ │ │ │ ├── faux-chat-shell-mobile-animated.tsx │ │ │ │ ├── faux-chat-shell-mobile.tsx │ │ │ │ ├── faux-chat-shell.tsx │ │ │ │ ├── home-background.tsx │ │ │ │ ├── home-hero.tsx │ │ │ │ ├── home-hexnut-scene.tsx │ │ │ │ └── noise-texture.ts │ │ │ ├── layout/ │ │ │ │ ├── app-header.server.tsx │ │ │ │ ├── app-shell-animated.client.tsx │ │ │ │ ├── app-shell.tsx │ │ │ │ ├── header-active-link.client.tsx │ │ │ │ ├── mobile-nav-sheet-gate.client.tsx │ │ │ │ ├── mobile-nav-sheet.client.tsx │ │ │ │ ├── page-shell.tsx │ │ │ │ └── tracked-external-anchor.client.tsx │ │ │ ├── mdx/ │ │ │ │ ├── features.tsx │ │ │ │ └── mermaid.tsx │ │ │ ├── theme/ │ │ │ │ └── theme-provider.tsx │ │ │ └── visuals/ │ │ │ └── spinning-hexnut/ │ │ │ └── hexnut-scene.tsx │ │ ├── docs/ │ │ │ ├── _components/ │ │ │ │ ├── chat-context-preview.tsx │ │ │ │ ├── collaboration-diagram.tsx │ │ │ │ ├── component-docs-tabs.tsx │ │ │ │ ├── component-preview-shell.tsx │ │ │ │ ├── component-preview.tsx │ │ │ │ ├── component-previews/ │ │ │ │ │ └── social-post-preview.tsx │ │ │ │ ├── copy-markdown-button.tsx │ │ │ │ ├── docs-article.tsx │ │ │ │ ├── docs-bordered-shell.tsx │ │ │ │ ├── docs-content.tsx │ │ │ │ ├── docs-header.tsx │ │ │ │ ├── docs-nav.tsx │ │ │ │ ├── docs-pager.tsx │ │ │ │ ├── docs-pages.ts │ │ │ │ ├── docs-search-shortcut.ts │ │ │ │ ├── docs-search.client.tsx │ │ │ │ ├── docs-toc-context.tsx │ │ │ │ ├── docs-toc-wrapper.tsx │ │ │ │ ├── docs-toc.tsx │ │ │ │ ├── gallery-analytics.client.tsx │ │ │ │ ├── gallery-card-header.tsx │ │ │ │ ├── gallery-docs-link.tsx │ │ │ │ ├── header-preview-tabs.tsx │ │ │ │ ├── install-command-block.tsx │ │ │ │ ├── install-command-line.tsx │ │ │ │ ├── interactive-option-demo.tsx │ │ │ │ ├── mdx-to-markdown.ts │ │ │ │ ├── mock-thread.tsx │ │ │ │ ├── preset-example.tsx │ │ │ │ ├── preset-selector.tsx │ │ │ │ └── tracked-dynamic-codeblock.tsx │ │ │ ├── actions/ │ │ │ │ ├── actions-examples.tsx │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── advanced/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── agent-skills/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── approval-card/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── audio/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── changelog/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── chart/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── citation/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── code-block/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── code-diff/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── data-table/ │ │ │ │ ├── content.mdx │ │ │ │ ├── formatting-gallery.tsx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── tasks-demo.tsx │ │ │ ├── design-guidelines/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── gallery/ │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── geo-map/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── image/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── image-gallery/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── instagram-post/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── item-carousel/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ ├── link-preview/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── linkedin-post/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── message-draft/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── option-list/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── order-summary/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── overview/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── page.tsx │ │ │ ├── parameter-slider/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── plan/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── preferences-panel/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── progress-tracker/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── question-flow/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── quick-start/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── receipts/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── stats-display/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── terminal/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── video/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ ├── weather-widget/ │ │ │ │ ├── content.mdx │ │ │ │ ├── opengraph-image.tsx │ │ │ │ └── page.tsx │ │ │ └── x-post/ │ │ │ ├── content.mdx │ │ │ ├── opengraph-image.tsx │ │ │ └── page.tsx │ │ ├── global-error.tsx │ │ ├── layout.tsx │ │ ├── not-found.tsx │ │ ├── opengraph-image.tsx │ │ ├── page.tsx │ │ ├── playground/ │ │ │ ├── chat-pane.tsx │ │ │ ├── chat-ui.tsx │ │ │ ├── opengraph-image.tsx │ │ │ ├── page.tsx │ │ │ ├── tool-inspector.tsx │ │ │ └── waymo-demo/ │ │ │ ├── opengraph-image.tsx │ │ │ └── page.tsx │ │ ├── sandbox/ │ │ │ ├── celestial-effect/ │ │ │ │ ├── celestial-canvas.tsx │ │ │ │ └── page.tsx │ │ │ ├── cloud-effect/ │ │ │ │ ├── cloud-canvas.tsx │ │ │ │ └── page.tsx │ │ │ ├── lightning-effect/ │ │ │ │ ├── lightning-canvas.tsx │ │ │ │ └── page.tsx │ │ │ ├── page.tsx │ │ │ ├── rain-effect/ │ │ │ │ ├── page.tsx │ │ │ │ └── rain-canvas.tsx │ │ │ ├── snow-effect/ │ │ │ │ ├── page.tsx │ │ │ │ └── snow-canvas.tsx │ │ │ ├── weather-compositor/ │ │ │ │ ├── celestial-canvas.tsx │ │ │ │ ├── interpolation.ts │ │ │ │ ├── page.tsx │ │ │ │ ├── presets.ts │ │ │ │ └── tuned-presets.json │ │ │ ├── weather-effects/ │ │ │ │ └── page.tsx │ │ │ ├── weather-tuning/ │ │ │ │ ├── components/ │ │ │ │ │ ├── checkpoint-dots.tsx │ │ │ │ │ ├── condition-sidebar.tsx │ │ │ │ │ ├── detail-editor.tsx │ │ │ │ │ ├── export-panel.tsx │ │ │ │ │ ├── glass-controls.tsx │ │ │ │ │ ├── parameter-definitions.ts │ │ │ │ │ ├── parameter-matrix-view.tsx │ │ │ │ │ ├── parameter-panel.tsx │ │ │ │ │ ├── parameter-row.tsx │ │ │ │ │ ├── time-dial.tsx │ │ │ │ │ ├── time-matrix-view.tsx │ │ │ │ │ ├── view-mode-toggle.tsx │ │ │ │ │ └── weather-data-overlay.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-tuning-state.ts │ │ │ │ ├── lib/ │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── has-any-tuning-delta.ts │ │ │ │ │ ├── list-updated-params.ts │ │ │ │ │ ├── map-to-canvas-props.ts │ │ │ │ │ ├── recover-repo-overrides.ts │ │ │ │ │ ├── resolve-params.ts │ │ │ │ │ ├── studio-timestamp.ts │ │ │ │ │ ├── tool-ui-export.ts │ │ │ │ │ ├── tool-ui-import.ts │ │ │ │ │ └── workflow-state.ts │ │ │ │ ├── page.tsx │ │ │ │ └── types.ts │ │ │ ├── weather-widget/ │ │ │ │ └── page.tsx │ │ │ ├── weather-widget-production/ │ │ │ │ ├── page.tsx │ │ │ │ └── runtime-input.ts │ │ │ └── weather-widget-stress/ │ │ │ └── page.tsx │ │ ├── staging/ │ │ │ ├── _components/ │ │ │ │ ├── rounded-rect-overlay.tsx │ │ │ │ ├── staging-canvas.tsx │ │ │ │ ├── staging-showcase.tsx │ │ │ │ ├── staging-toolbar.tsx │ │ │ │ ├── use-keyboard-shortcuts.ts │ │ │ │ └── use-staging-state.ts │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ │ └── styles/ │ │ ├── builder-loader.css │ │ ├── custom-utilities.css │ │ ├── fumadocs-overrides.css │ │ ├── globals.css │ │ ├── leaflet-overrides.css │ │ ├── nav-sheet.css │ │ ├── prose.css │ │ ├── shadcn-theme.css │ │ ├── squircle.css │ │ └── theme-transition.css │ ├── components/ │ │ ├── assistant-ui/ │ │ │ ├── assistant-modal.tsx │ │ │ ├── attachment.tsx │ │ │ ├── markdown-text.tsx │ │ │ ├── reasoning.tsx │ │ │ ├── shiki-highlighter.tsx │ │ │ ├── thread-list.tsx │ │ │ ├── thread.tsx │ │ │ ├── threadlist-sidebar.tsx │ │ │ ├── tool-fallback.tsx │ │ │ └── tooltip-icon-button.tsx │ │ ├── tool-ui/ │ │ │ ├── approval-card/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── approval-card.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── schema.ts │ │ │ ├── audio/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── audio.tsx │ │ │ │ ├── context.tsx │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── chart/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── chart.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── schema.ts │ │ │ ├── citation/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── citation-list.tsx │ │ │ │ ├── citation.tsx │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── code-block/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── code-block.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── schema.ts │ │ │ ├── code-diff/ │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── code-diff.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── schema.ts │ │ │ ├── data-table/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── data-table.tsx │ │ │ │ ├── formatters.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── schema.ts │ │ │ │ ├── types.ts │ │ │ │ └── utilities.ts │ │ │ ├── geo-map/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── geo-map-engine.tsx │ │ │ │ ├── geo-map-icons.ts │ │ │ │ ├── geo-map-overlays.tsx │ │ │ │ ├── geo-map-theme.module.css │ │ │ │ ├── geo-map.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── schema.ts │ │ │ ├── image/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── image.tsx │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── image-gallery/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── context.tsx │ │ │ │ ├── gallery-grid.tsx │ │ │ │ ├── gallery-lightbox.tsx │ │ │ │ ├── image-gallery.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── schema.ts │ │ │ │ └── styles.css │ │ │ ├── index.ts │ │ │ ├── instagram-post/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── instagram-post.tsx │ │ │ │ └── schema.ts │ │ │ ├── item-carousel/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── item-card.tsx │ │ │ │ ├── item-carousel.tsx │ │ │ │ └── schema.ts │ │ │ ├── link-preview/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── link-preview.tsx │ │ │ │ └── schema.ts │ │ │ ├── linkedin-post/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── linkedin-post.tsx │ │ │ │ └── schema.ts │ │ │ ├── message-draft/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── message-draft.tsx │ │ │ │ └── schema.ts │ │ │ ├── option-list/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── option-list.tsx │ │ │ │ ├── schema.ts │ │ │ │ └── selection.ts │ │ │ ├── order-summary/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── order-summary.tsx │ │ │ │ └── schema.ts │ │ │ ├── parameter-slider/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── math.ts │ │ │ │ ├── parameter-slider.tsx │ │ │ │ └── schema.ts │ │ │ ├── plan/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── plan.tsx │ │ │ │ ├── progress.ts │ │ │ │ └── schema.ts │ │ │ ├── preferences-panel/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── preferences-panel.tsx │ │ │ │ ├── schema.ts │ │ │ │ └── signature.ts │ │ │ ├── progress-tracker/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── progress-tracker.tsx │ │ │ │ └── schema.ts │ │ │ ├── question-flow/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── question-flow.tsx │ │ │ │ └── schema.ts │ │ │ ├── shared/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── action-buttons.tsx │ │ │ │ ├── actions-config.ts │ │ │ │ ├── contract.ts │ │ │ │ ├── decision-actions.tsx │ │ │ │ ├── embedded-actions.ts │ │ │ │ ├── index.ts │ │ │ │ ├── local-actions.tsx │ │ │ │ ├── media/ │ │ │ │ │ ├── aspect-ratio.ts │ │ │ │ │ ├── format-utils.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── overlay-gradient.ts │ │ │ │ │ ├── safe-navigation.ts │ │ │ │ │ └── sanitize-href.ts │ │ │ │ ├── parse.ts │ │ │ │ ├── pierre-dark-theme.js │ │ │ │ ├── pierre-light-theme.js │ │ │ │ ├── schema.ts │ │ │ │ ├── tool-ui-context.tsx │ │ │ │ ├── tool-ui.tsx │ │ │ │ ├── toolkit.tsx │ │ │ │ ├── use-action-buttons.tsx │ │ │ │ ├── use-controllable-state.ts │ │ │ │ ├── use-copy-to-clipboard.ts │ │ │ │ ├── use-signature-reset.ts │ │ │ │ └── utils.ts │ │ │ ├── stats-display/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── schema.ts │ │ │ │ ├── sparkline.tsx │ │ │ │ └── stats-display.tsx │ │ │ ├── terminal/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── schema.ts │ │ │ │ └── terminal.tsx │ │ │ ├── video/ │ │ │ │ ├── README.md │ │ │ │ ├── _adapter.tsx │ │ │ │ ├── context.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── schema.ts │ │ │ │ ├── video-helpers.ts │ │ │ │ └── video.tsx │ │ │ ├── weather-widget/ │ │ │ │ ├── generated/ │ │ │ │ │ └── weather-runtime-core.generated.ts │ │ │ │ ├── runtime.ts │ │ │ │ ├── schema-runtime.ts │ │ │ │ ├── weather-data-overlay.tsx │ │ │ │ └── weather-widget-container.tsx │ │ │ └── x-post/ │ │ │ ├── README.md │ │ │ ├── _adapter.tsx │ │ │ ├── index.ts │ │ │ ├── schema.ts │ │ │ └── x-post.tsx │ │ └── ui/ │ │ ├── accordion.tsx │ │ ├── alert.tsx │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── button-group.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── chart.tsx │ │ ├── code-block.tsx │ │ ├── collapsible.tsx │ │ ├── dialog.tsx │ │ ├── dropdown-menu.tsx │ │ ├── input-group.tsx │ │ ├── input.tsx │ │ ├── item.tsx │ │ ├── label.tsx │ │ ├── logo.tsx │ │ ├── popover.tsx │ │ ├── radio-group.tsx │ │ ├── select.tsx │ │ ├── separator.tsx │ │ ├── sheet.tsx │ │ ├── sidebar.tsx │ │ ├── skeleton.tsx │ │ ├── slider.tsx │ │ ├── switch.tsx │ │ ├── table.tsx │ │ ├── tabs.tsx │ │ ├── textarea.tsx │ │ ├── toggle-group.tsx │ │ ├── toggle.tsx │ │ └── tooltip.tsx │ ├── components.json │ ├── css.d.ts │ ├── docs/ │ │ ├── changelog.md │ │ └── tests.md │ ├── eslint.config.ts │ ├── hooks/ │ │ ├── use-extract-headings.ts │ │ ├── use-headings-observer.ts │ │ ├── use-mobile.ts │ │ ├── use-preset-param.ts │ │ ├── use-reduced-motion.ts │ │ ├── use-responsive-preview.ts │ │ ├── use-tab-search-param.ts │ │ └── use-toc-keyboard-nav.ts │ ├── lib/ │ │ ├── analytics.ts │ │ ├── changelog/ │ │ │ ├── changelog.ts │ │ │ ├── git.ts │ │ │ └── inference.ts │ │ ├── demo-chat/ │ │ │ └── toolkit.tsx │ │ ├── docs/ │ │ │ ├── auto-link.tsx │ │ │ ├── component-ids.ts │ │ │ ├── component-registry.ts │ │ │ ├── gallery-component-docs.ts │ │ │ ├── gallery-layout.ts │ │ │ ├── gallery-usage-code.ts │ │ │ ├── install-snippet-analytics.ts │ │ │ └── preview-config.tsx │ │ ├── eslint/ │ │ │ └── tool-ui-action-model-plugin.ts │ │ ├── integrations/ │ │ │ ├── freestyle/ │ │ │ │ ├── create-chat.ts │ │ │ │ └── get-code.ts │ │ │ └── rate-limit/ │ │ │ └── upstash.ts │ │ ├── mocks/ │ │ │ ├── chat-showcase-data.ts │ │ │ ├── stocks.ts │ │ │ └── tasks.ts │ │ ├── og/ │ │ │ └── og-image.tsx │ │ ├── playground/ │ │ │ ├── constants.ts │ │ │ ├── index.ts │ │ │ ├── mocks.ts │ │ │ ├── prototypes/ │ │ │ │ ├── food-ordering/ │ │ │ │ │ ├── get-menu.ts │ │ │ │ │ ├── get-restaurant-details.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── place-order.ts │ │ │ │ │ ├── search-restaurants.ts │ │ │ │ │ └── shared.ts │ │ │ │ ├── index.ts │ │ │ │ ├── waymo/ │ │ │ │ │ ├── README.md │ │ │ │ │ ├── WaymoDemo.tsx │ │ │ │ │ ├── check-ride-prices.ts │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── BookingConfirmation.tsx │ │ │ │ │ │ ├── RideQuote.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── confirm-ride-booking.ts │ │ │ │ │ ├── confirm-user-payment.ts │ │ │ │ │ ├── get-profile-context.ts │ │ │ │ │ ├── get-user-destination.ts │ │ │ │ │ ├── get-user-location.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── precheck-prices.ts │ │ │ │ │ ├── request-payment-method.ts │ │ │ │ │ ├── schedule-ride.ts │ │ │ │ │ ├── search-places.ts │ │ │ │ │ ├── select-frequent-location-tool.tsx │ │ │ │ │ ├── shared.ts │ │ │ │ │ ├── show-ride-details.ts │ │ │ │ │ ├── show-ride-options.ts │ │ │ │ │ ├── system-message-v2.ts │ │ │ │ │ ├── toggle-gps.ts │ │ │ │ │ ├── tools.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── wip-tool-uis/ │ │ │ │ │ ├── FrequentLocationSelector.tsx │ │ │ │ │ ├── README.md │ │ │ │ │ ├── TOOL-UI-PATTERNS.md │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── ux-v3.md │ │ │ │ │ └── ux.md │ │ │ │ └── waymo-v2/ │ │ │ │ ├── DESIGN.md │ │ │ │ ├── components/ │ │ │ │ │ ├── DestinationPicker.tsx │ │ │ │ │ ├── PickupPicker.tsx │ │ │ │ │ ├── RideQuote.tsx │ │ │ │ │ ├── TripStatus.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── system-prompt.ts │ │ │ │ ├── tools/ │ │ │ │ │ ├── get-ride-quote.tsx │ │ │ │ │ ├── get-trip-status.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── select-destination.tsx │ │ │ │ │ └── select-pickup.tsx │ │ │ │ └── types.ts │ │ │ ├── registry.ts │ │ │ ├── runtime.ts │ │ │ ├── tool-uis.ts │ │ │ ├── types.ts │ │ │ └── weather-tuning/ │ │ │ ├── has-any-tuning-delta.test.ts │ │ │ ├── list-updated-params.test.ts │ │ │ ├── parameter-definitions-coverage.test.ts │ │ │ ├── rain-param-ranges.test.ts │ │ │ ├── recover-repo-overrides.test.ts │ │ │ ├── resolve-params.test.ts │ │ │ ├── snow-fall-speed-range.test.ts │ │ │ ├── studio-timestamp.test.ts │ │ │ ├── tool-ui-export.test.ts │ │ │ ├── tool-ui-import.test.ts │ │ │ └── workflow-state.test.ts │ │ ├── presets/ │ │ │ ├── approval-card.ts │ │ │ ├── audio.ts │ │ │ ├── chart.ts │ │ │ ├── citation.ts │ │ │ ├── code-block.ts │ │ │ ├── code-diff.ts │ │ │ ├── data-table.ts │ │ │ ├── geo-map.ts │ │ │ ├── image-gallery.ts │ │ │ ├── image.ts │ │ │ ├── instagram-post.ts │ │ │ ├── item-carousel.ts │ │ │ ├── link-preview.ts │ │ │ ├── linkedin-post.ts │ │ │ ├── message-draft.ts │ │ │ ├── option-list.ts │ │ │ ├── order-summary.ts │ │ │ ├── parameter-slider.ts │ │ │ ├── plan.ts │ │ │ ├── preferences-panel.ts │ │ │ ├── progress-tracker.ts │ │ │ ├── question-flow.ts │ │ │ ├── stats-display.ts │ │ │ ├── terminal.ts │ │ │ ├── types.ts │ │ │ ├── video.ts │ │ │ ├── weather-widget.ts │ │ │ └── x-post.ts │ │ ├── registry/ │ │ │ └── tool-ui-registry.ts │ │ ├── staging/ │ │ │ ├── configs/ │ │ │ │ ├── parameter-slider.tsx │ │ │ │ ├── plan.tsx │ │ │ │ ├── progress-tracker.tsx │ │ │ │ └── stats-display.tsx │ │ │ ├── staging-config.ts │ │ │ └── types.ts │ │ ├── system/ │ │ │ └── tool-builder-message.ts │ │ ├── tests/ │ │ │ ├── app/ │ │ │ │ └── leaflet-css-import.test.ts │ │ │ ├── docs/ │ │ │ │ ├── header-preview-tabs-hydration.test.ts │ │ │ │ └── tracked-dynamic-codeblock.test.ts │ │ │ ├── registry/ │ │ │ │ └── tool-ui-registry.test.ts │ │ │ ├── setup/ │ │ │ │ └── console-guard.ts │ │ │ └── tool-ui/ │ │ │ ├── docs/ │ │ │ │ ├── changelog-inference-parser.test.ts │ │ │ │ ├── changelog-inference-prompt.test.ts │ │ │ │ ├── docs-search-shortcut.test.ts │ │ │ │ ├── gallery-layout.test.ts │ │ │ │ └── install-snippet-analytics.test.ts │ │ │ ├── geo-map/ │ │ │ │ ├── geo-map-render.test.ts │ │ │ │ ├── schema.test.ts │ │ │ │ └── spatial.test.ts │ │ │ ├── scripts/ │ │ │ │ └── install-git-hooks.test.ts │ │ │ ├── shared/ │ │ │ │ └── safe-navigation.test.ts │ │ │ ├── social/ │ │ │ │ └── link-sanitization.test.ts │ │ │ ├── video/ │ │ │ │ └── media-events.test.ts │ │ │ └── weather-widget/ │ │ │ ├── canvas-resolver-parity.test.ts │ │ │ ├── glass-style-resolver.test.ts │ │ │ ├── parameter-mapper.test.ts │ │ │ ├── production-runtime-harness.test.ts │ │ │ ├── weather-data-overlay-observer.test.ts │ │ │ ├── weather-runtime-codegen.test.ts │ │ │ ├── weather-widget-layout.test.ts │ │ │ └── webgl-budget-guard.test.ts │ │ ├── ui/ │ │ │ └── cn.ts │ │ ├── utils.ts │ │ ├── weather-authoring/ │ │ │ ├── presets/ │ │ │ │ └── tuned-presets.json │ │ │ ├── runtime/ │ │ │ │ └── glass-panel-svg.tsx │ │ │ ├── shaders/ │ │ │ │ ├── celestial.frag.glsl │ │ │ │ ├── cloud.frag.glsl │ │ │ │ ├── composite.frag.glsl │ │ │ │ ├── fullscreen.vert.glsl │ │ │ │ ├── lightning.frag.glsl │ │ │ │ ├── rain.frag.glsl │ │ │ │ └── snow.frag.glsl │ │ │ ├── shared/ │ │ │ │ └── contract.ts │ │ │ └── weather-widget/ │ │ │ ├── README.md │ │ │ ├── _adapter.tsx │ │ │ ├── effects/ │ │ │ │ ├── canvas-resolver-base.ts │ │ │ │ ├── canvas-resolver-runtime.ts │ │ │ │ ├── canvas-resolver.ts │ │ │ │ ├── checkpoint-overrides.ts │ │ │ │ ├── custom-effect-props.ts │ │ │ │ ├── effect-compositor-custom-props.ts │ │ │ │ ├── effect-compositor-quality.ts │ │ │ │ ├── effect-compositor-runtime.tsx │ │ │ │ ├── effect-compositor.tsx │ │ │ │ ├── generated/ │ │ │ │ │ ├── glass-panel-svg.generated.tsx │ │ │ │ │ ├── tuned-presets.generated.ts │ │ │ │ │ └── weather-effect-shaders.generated.ts │ │ │ │ ├── glass-panel-svg.tsx │ │ │ │ ├── glass-style-resolver.ts │ │ │ │ ├── index.ts │ │ │ │ ├── parameter-mapper.generated.js │ │ │ │ ├── parameter-mapper.ts │ │ │ │ ├── tuned-presets.ts │ │ │ │ ├── tuning.ts │ │ │ │ ├── types.ts │ │ │ │ ├── use-glass-region.ts │ │ │ │ ├── use-glass-styles.ts │ │ │ │ ├── use-weather-effects-renderer.generated.js │ │ │ │ ├── use-weather-effects-renderer.ts │ │ │ │ ├── weather-compositor-types.ts │ │ │ │ ├── weather-effect-gl.ts │ │ │ │ ├── weather-effect-render-passes.generated.js │ │ │ │ ├── weather-effect-render-passes.ts │ │ │ │ ├── weather-effect-shaders.ts │ │ │ │ ├── weather-effects-canvas.tsx │ │ │ │ ├── weather-effects-defaults.ts │ │ │ │ ├── weather-effects-props.ts │ │ │ │ ├── weather-effects-types.ts │ │ │ │ └── weather-webgl-budget.ts │ │ │ ├── index.tsx │ │ │ ├── schema-runtime.ts │ │ │ ├── schema.ts │ │ │ ├── time.ts │ │ │ ├── weather-data-overlay.generated.ts │ │ │ ├── weather-data-overlay.tsx │ │ │ ├── weather-runtime-core.ts │ │ │ ├── weather-widget-container.tsx │ │ │ └── weather-widget.tsx │ │ └── weather-codegen/ │ │ └── compile-weather-runtime.ts │ ├── mdx-components.tsx │ ├── next.config.ts │ ├── package.json │ ├── postcss.config.mjs │ ├── proxy.ts │ ├── public/ │ │ └── r/ │ │ ├── approval-card.json │ │ ├── audio.json │ │ ├── chart.json │ │ ├── citation.json │ │ ├── code-block.json │ │ ├── code-diff.json │ │ ├── data-table.json │ │ ├── geo-map.json │ │ ├── image-gallery.json │ │ ├── image.json │ │ ├── instagram-post.json │ │ ├── item-carousel.json │ │ ├── link-preview.json │ │ ├── linkedin-post.json │ │ ├── message-draft.json │ │ ├── option-list.json │ │ ├── order-summary.json │ │ ├── parameter-slider.json │ │ ├── plan.json │ │ ├── preferences-panel.json │ │ ├── progress-tracker.json │ │ ├── question-flow.json │ │ ├── registry.json │ │ ├── stats-display.json │ │ ├── terminal.json │ │ ├── video.json │ │ ├── weather-widget.json │ │ └── x-post.json │ ├── scripts/ │ │ ├── build-tool-ui-registry.ts │ │ ├── check-changelog.ts │ │ ├── compile-weather-runtime.ts │ │ ├── generate-changelog.ts │ │ ├── install-git-hooks.ts │ │ ├── new-tool-ui-component.ts │ │ ├── precommit-registry-sync.ts │ │ └── registry-check.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── package.json ├── packages/ │ └── agent/ │ ├── package.json │ ├── plugin/ │ │ ├── .claude-plugin/ │ │ │ └── plugin.json │ │ └── skills/ │ │ └── tool-ui/ │ │ └── SKILL.md │ ├── src/ │ │ └── cli.ts │ ├── tsconfig.json │ └── tsup.config.ts ├── pnpm-workspace.yaml └── skills-lock.json
Showing preview only (223K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2369 symbols across 512 files)
FILE: apps/www/app/api/builder/chat/route.ts
function POST (line 12) | async function POST(req: Request) {
FILE: apps/www/app/api/builder/create-freestyle/route.ts
function POST (line 3) | async function POST() {
FILE: apps/www/app/api/chat/route.ts
constant DEMO_SYSTEM_PROMPT (line 10) | const DEMO_SYSTEM_PROMPT = `You are a helpful assistant that showcases t...
function POST (line 36) | async function POST(req: Request) {
FILE: apps/www/app/api/mcp-tools/route.ts
type MCPTool (line 5) | interface MCPTool {
function POST (line 15) | async function POST(req: Request) {
FILE: apps/www/app/api/playground/chat/route.ts
function POST (line 24) | async function POST(request: NextRequest) {
FILE: apps/www/app/api/weather-tuning/_lib/tuned-presets-io.ts
constant TOOL_UI_TUNED_PRESETS_PATH (line 6) | const TOOL_UI_TUNED_PRESETS_PATH = path.join(
function readToolUiTunedPresetsFromDisk (line 11) | async function readToolUiTunedPresetsFromDisk(): Promise<WeatherEffectsT...
FILE: apps/www/app/api/weather-tuning/apply/route.ts
function POST (line 22) | async function POST(request: Request) {
FILE: apps/www/app/api/weather-tuning/recover/route.ts
function GET (line 6) | async function GET() {
FILE: apps/www/app/builder/layout.tsx
function BuilderLayout (line 6) | function BuilderLayout({ children }: { children: ReactNode }) {
FILE: apps/www/app/builder/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/builder/page.tsx
type MCPTool (line 241) | interface MCPTool {
type ViewMode (line 514) | type ViewMode = "rendered" | "code";
function BuilderPage (line 516) | function BuilderPage() {
FILE: apps/www/app/components/analytics/posthog-init.client.tsx
function PostHogInit (line 10) | function PostHogInit() {
FILE: apps/www/app/components/assistant-ui/thread-list.tsx
type ThreadListProps (line 13) | type ThreadListProps = {
type ThreadListItemsProps (line 52) | type ThreadListItemsProps = {
FILE: apps/www/app/components/assistant-ui/tooltip-icon-button.tsx
type TooltipIconButtonProps (line 14) | type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
FILE: apps/www/app/components/builder/mcp-icon.tsx
function MCPIcon (line 3) | function MCPIcon({
FILE: apps/www/app/components/builder/theme-toggle.tsx
function ThemeToggle (line 9) | function ThemeToggle() {
FILE: apps/www/app/components/builder/webview-actions.ts
function requestDevServer (line 5) | async function requestDevServer({ repoId }: { repoId: string }) {
FILE: apps/www/app/components/builder/webview.tsx
type WebViewHandle (line 14) | interface WebViewHandle {
type DevServerResponse (line 18) | type DevServerResponse = Awaited<ReturnType<typeof requestDevServerInner>>;
FILE: apps/www/app/components/home/chat-showcase.tsx
constant TIMING (line 31) | const TIMING = {
constant SPRINGS (line 54) | const SPRINGS = {
type SceneConfig (line 75) | type SceneConfig = {
type SceneTimelineState (line 83) | type SceneTimelineState = {
function useReducedMotion (line 89) | function useReducedMotion(): boolean {
function useSceneTimeline (line 106) | function useSceneTimeline({
function ToolReveal (line 167) | function ToolReveal({ children }: { children: React.ReactNode }) {
function TypingIndicator (line 179) | function TypingIndicator() {
constant TEST_LINES (line 194) | const TEST_LINES = [
function AnimatedTerminal (line 202) | function AnimatedTerminal({ className }: { className?: string }) {
function AnimatedPlan (line 231) | function AnimatedPlan({ className }: { className?: string }) {
function AnimatedProgressTracker (line 275) | function AnimatedProgressTracker({ className }: { className?: string }) {
type ChatBubbleProps (line 311) | type ChatBubbleProps = {
function ChatBubble (line 317) | function ChatBubble({ role, children, className }: ChatBubbleProps) {
type PreambleBubbleProps (line 342) | type PreambleBubbleProps = {
function StreamingChar (line 349) | function StreamingChar({ char, delay }: { char: string; delay: number }) {
function PreambleBubble (line 365) | function PreambleBubble({
function createSceneConfigs (line 436) | function createSceneConfigs(reducedMotion: boolean): SceneConfig[] {
constant SCENE_COUNT (line 664) | const SCENE_COUNT = 11;
type AnimatedSceneProps (line 666) | type AnimatedSceneProps = {
function AnimatedScene (line 676) | function AnimatedScene({
function ChatShowcase (line 829) | function ChatShowcase() {
FILE: apps/www/app/components/home/demo-chat.tsx
constant SUGGESTIONS (line 23) | const SUGGESTIONS = [
constant PASTEL_COLORS (line 30) | const PASTEL_COLORS = [
function SuggestionChip (line 37) | function SuggestionChip({
function SuggestionChips (line 57) | function SuggestionChips() {
function DemoChat (line 78) | function DemoChat() {
FILE: apps/www/app/components/home/faux-chat-shell-animated.tsx
function generateSineEasedGradient (line 7) | function generateSineEasedGradient(
function FauxChatShellAnimated (line 32) | function FauxChatShellAnimated() {
FILE: apps/www/app/components/home/faux-chat-shell-mobile-animated.tsx
function generateSineEasedGradient (line 7) | function generateSineEasedGradient(
function FauxChatShellMobileAnimated (line 32) | function FauxChatShellMobileAnimated() {
FILE: apps/www/app/components/home/faux-chat-shell-mobile.tsx
type FauxChatShellMobileProps (line 7) | type FauxChatShellMobileProps = {
function DynamicIsland (line 11) | function DynamicIsland() {
function StatusBar (line 22) | function StatusBar() {
function FauxChatShellMobile (line 65) | function FauxChatShellMobile({ className }: FauxChatShellMobileProps) {
FILE: apps/www/app/components/home/faux-chat-shell.tsx
type FauxChatShellProps (line 8) | type FauxChatShellProps = {
function generateSineEasedGradient (line 14) | function generateSineEasedGradient(
function useDirectionalLight (line 42) | function useDirectionalLight(
function WindowDots (line 104) | function WindowDots() {
function ComposerBar (line 114) | function ComposerBar() {
function FauxChatShellBase (line 122) | function FauxChatShellBase({
function FauxChatShell (line 193) | function FauxChatShell(props: FauxChatShellProps) {
function FauxChatShellNoLightOverlay (line 197) | function FauxChatShellNoLightOverlay(props: FauxChatShellProps) {
FILE: apps/www/app/components/home/home-background.tsx
function HomeBackground (line 3) | function HomeBackground() {
FILE: apps/www/app/components/home/home-hero.tsx
function HomeHero (line 19) | function HomeHero() {
FILE: apps/www/app/components/home/home-hexnut-scene.tsx
function HomeHexnutScene (line 17) | function HomeHexnutScene() {
FILE: apps/www/app/components/home/noise-texture.ts
function generateNoiseDataUri (line 6) | function generateNoiseDataUri(
function getNoiseOverlayStyle (line 31) | function getNoiseOverlayStyle(opacity: number = 0.02) {
FILE: apps/www/app/components/layout/app-header.server.tsx
type ResponsiveHeaderProps (line 12) | interface ResponsiveHeaderProps {
function ResponsiveHeader (line 16) | function ResponsiveHeader({ rightContent }: ResponsiveHeaderProps) {
FILE: apps/www/app/components/layout/app-shell-animated.client.tsx
type HeaderFrameProps (line 8) | type HeaderFrameProps = {
function HeaderFrameBase (line 17) | function HeaderFrameBase({
function AnimatedHeaderFrame (line 45) | function AnimatedHeaderFrame(props: HeaderFrameProps) {
FILE: apps/www/app/components/layout/app-shell.tsx
type HeaderFrameProps (line 5) | type HeaderFrameProps = {
function HeaderFrameBase (line 11) | function HeaderFrameBase({
function HeaderFrame (line 39) | function HeaderFrame(props: HeaderFrameProps) {
FILE: apps/www/app/components/layout/header-active-link.client.tsx
type ActiveNavLinkProps (line 7) | interface ActiveNavLinkProps {
function ActiveNavLink (line 12) | function ActiveNavLink({ href, children }: ActiveNavLinkProps) {
FILE: apps/www/app/components/layout/mobile-nav-sheet-gate.client.tsx
constant MOBILE_QUERY (line 17) | const MOBILE_QUERY = "(max-width: 767px)";
function shouldRenderForPath (line 19) | function shouldRenderForPath(pathname: string) {
function MobileNavSheetGate (line 27) | function MobileNavSheetGate() {
FILE: apps/www/app/components/layout/mobile-nav-sheet.client.tsx
function MobileNavSheet (line 18) | function MobileNavSheet() {
FILE: apps/www/app/components/layout/page-shell.tsx
type ContentLayoutProps (line 3) | type ContentLayoutProps = {
function ContentLayout (line 8) | function ContentLayout({
FILE: apps/www/app/components/layout/tracked-external-anchor.client.tsx
type ExternalDestination (line 6) | type ExternalDestination = "github" | "npm" | "docs" | "other";
type TrackedExternalAnchorProps (line 8) | type TrackedExternalAnchorProps = React.ComponentPropsWithoutRef<"a"> & {
FILE: apps/www/app/components/mdx/features.tsx
constant ICON_MAP (line 72) | const ICON_MAP: Record<string, LucideIcon> = {
type FeatureGridProps (line 141) | interface FeatureGridProps {
function FeatureGrid (line 146) | function FeatureGrid({ children, className }: FeatureGridProps) {
type FeatureProps (line 159) | interface FeatureProps {
function Feature (line 166) | function Feature({ icon, title, children, className }: FeatureProps) {
FILE: apps/www/app/components/mdx/mermaid.tsx
type MermaidProps (line 6) | interface MermaidProps {
function getMermaid (line 12) | function getMermaid() {
function Mermaid (line 19) | function Mermaid({ chart }: MermaidProps) {
FILE: apps/www/app/components/theme/theme-provider.tsx
type ThemeProviderProps (line 6) | type ThemeProviderProps = React.ComponentProps<typeof NextThemesProvider>;
function ThemeProvider (line 8) | function ThemeProvider({ children, ...props }: ThemeProviderProps) {
FILE: apps/www/app/components/visuals/spinning-hexnut/hexnut-scene.tsx
function createHexnutGeometry (line 11) | function createHexnutGeometry(
type HexnutProps (line 58) | interface HexnutProps {
constant DRAG_SENSITIVITY (line 70) | const DRAG_SENSITIVITY = 0.01;
constant MOMENTUM_FRICTION (line 71) | const MOMENTUM_FRICTION = 0.96;
constant MAX_VELOCITY (line 72) | const MAX_VELOCITY = 10;
type ThemeConfig (line 74) | type ThemeConfig = {
constant THEME_CONFIGS (line 86) | const THEME_CONFIGS: Record<"dark" | "light", ThemeConfig> = {
function RotatingHexnut (line 111) | function RotatingHexnut({
type PostFXOptions (line 168) | interface PostFXOptions {
type HexnutSceneProps (line 177) | interface HexnutSceneProps {
function HexnutScene (line 185) | function HexnutScene({
FILE: apps/www/app/docs/_components/chat-context-preview.tsx
type ChatBubbleProps (line 4) | interface ChatBubbleProps {
function ChatBubble (line 9) | function ChatBubble({ role, children }: ChatBubbleProps) {
type ChatContextPreviewProps (line 30) | interface ChatContextPreviewProps {
function ChatContextPreview (line 36) | function ChatContextPreview({
FILE: apps/www/app/docs/_components/collaboration-diagram.tsx
function CollaborationDiagram (line 3) | function CollaborationDiagram() {
FILE: apps/www/app/docs/_components/component-docs-tabs.tsx
type DocsTab (line 15) | type DocsTab = "docs" | "examples";
constant VALID_TABS (line 17) | const VALID_TABS = ["docs", "examples"] as const;
type ComponentDocsTabsProps (line 19) | interface ComponentDocsTabsProps {
FILE: apps/www/app/docs/_components/component-preview-shell.tsx
constant PREVIEW_MIN_WIDTH (line 16) | const PREVIEW_MIN_WIDTH = 40;
constant PREVIEW_MAX_WIDTH (line 17) | const PREVIEW_MAX_WIDTH = 100;
constant VALID_VIEW_MODES (line 19) | const VALID_VIEW_MODES = ["canvas", "chat", "code"] as const;
type ViewMode (line 20) | type ViewMode = (typeof VALID_VIEW_MODES)[number];
function toStablePanelIdSegment (line 22) | function toStablePanelIdSegment(value: string): string {
function ViewModeToggle (line 30) | function ViewModeToggle({
constant RESIZE_HANDLE_STYLES (line 70) | const RESIZE_HANDLE_STYLES = cn(
type ComponentPreviewShellProps (line 132) | interface ComponentPreviewShellProps {
constant COPY_ID (line 141) | const COPY_ID = "code-panel";
function ComponentPreviewShell (line 143) | function ComponentPreviewShell({
FILE: apps/www/app/docs/_components/component-preview.tsx
type ComponentPreviewProps (line 16) | interface ComponentPreviewProps {
constant EMPTY_STATE (line 20) | const EMPTY_STATE: PreviewState = {};
function ComponentPreview (line 22) | function ComponentPreview({ componentId }: ComponentPreviewProps) {
FILE: apps/www/app/docs/_components/component-previews/social-post-preview.tsx
type Platform (line 30) | type Platform = "x" | "instagram" | "linkedin";
type PresetName (line 31) | type PresetName =
constant VALID_PLATFORMS (line 36) | const VALID_PLATFORMS: readonly Platform[] = ["x", "instagram", "linkedi...
function resolveActions (line 38) | function resolveActions(actions: unknown): Action[] | null {
function getPresetNames (line 67) | function getPresetNames(platform: Platform): PresetName[] {
function getValidPreset (line 71) | function getValidPreset(platform: Platform, preset: string | null): Pres...
function PlatformSelector (line 79) | function PlatformSelector({
function PresetSelector (line 111) | function PresetSelector({
function SocialPostPreview (line 168) | function SocialPostPreview({
FILE: apps/www/app/docs/_components/copy-markdown-button.tsx
type CopyMarkdownButtonProps (line 9) | type CopyMarkdownButtonProps = {
function CopyMarkdownButton (line 13) | function CopyMarkdownButton({ markdown }: CopyMarkdownButtonProps) {
FILE: apps/www/app/docs/_components/docs-article.tsx
function DocsArticle (line 9) | function DocsArticle({
FILE: apps/www/app/docs/_components/docs-bordered-shell.tsx
function DocsBorderedShell (line 4) | function DocsBorderedShell({
FILE: apps/www/app/docs/_components/docs-content.tsx
type DocsContentProps (line 5) | interface DocsContentProps {
function DocsContent (line 11) | function DocsContent({
FILE: apps/www/app/docs/_components/docs-header.tsx
type DocsHeaderProps (line 7) | type DocsHeaderProps = {
function DocsHeader (line 13) | function DocsHeader({ title, description, mdxPath }: DocsHeaderProps) {
FILE: apps/www/app/docs/_components/docs-nav.tsx
constant STORAGE_KEY (line 18) | const STORAGE_KEY = "tool-ui-components-nav-collapsed:v1";
function DocsNav (line 20) | function DocsNav() {
FILE: apps/www/app/docs/_components/docs-pager.tsx
function useDocsPagination (line 12) | function useDocsPagination() {
type PagerLinkProps (line 26) | type PagerLinkProps = {
function PagerLink (line 32) | function PagerLink({ href, label, direction }: PagerLinkProps) {
function DocsPager (line 70) | function DocsPager() {
FILE: apps/www/app/docs/_components/docs-pages.ts
type DocsPageLink (line 3) | type DocsPageLink = {
constant GET_STARTED_DOCS_PAGES (line 8) | const GET_STARTED_DOCS_PAGES: DocsPageLink[] = [
constant CONCEPTS_DOCS_PAGES (line 17) | const CONCEPTS_DOCS_PAGES: DocsPageLink[] = [
constant BASE_DOCS_PAGES (line 22) | const BASE_DOCS_PAGES: DocsPageLink[] = [
function getAllDocsPageLinks (line 27) | function getAllDocsPageLinks(): DocsPageLink[] {
FILE: apps/www/app/docs/_components/docs-search-shortcut.ts
type SearchShortcutEvent (line 1) | type SearchShortcutEvent = Pick<
FILE: apps/www/app/docs/_components/docs-search.client.tsx
type SearchResult (line 15) | type SearchResult = {
constant SEARCH_RESULTS (line 21) | const SEARCH_RESULTS: SearchResult[] = [
constant MAX_RESULTS (line 35) | const MAX_RESULTS = 10;
function DocsSearch (line 37) | function DocsSearch() {
FILE: apps/www/app/docs/_components/docs-toc-context.tsx
type DocsTocContextValue (line 13) | type DocsTocContextValue = {
function useDocsToc (line 22) | function useDocsToc() {
function DocsTocProvider (line 30) | function DocsTocProvider({ children }: { children: ReactNode }) {
FILE: apps/www/app/docs/_components/docs-toc-wrapper.tsx
function DocsTocWrapper (line 3) | function DocsTocWrapper() {
FILE: apps/www/app/docs/_components/docs-toc.tsx
function DocsToc (line 10) | function DocsToc() {
FILE: apps/www/app/docs/_components/gallery-analytics.client.tsx
function GalleryPageAnalytics (line 6) | function GalleryPageAnalytics() {
type GalleryPreviewImpressionProps (line 14) | interface GalleryPreviewImpressionProps {
function GalleryPreviewImpression (line 18) | function GalleryPreviewImpression({
FILE: apps/www/app/docs/_components/gallery-card-header.tsx
type GalleryCardHeaderProps (line 23) | interface GalleryCardHeaderProps {
function GalleryCardHeader (line 29) | function GalleryCardHeader({
FILE: apps/www/app/docs/_components/gallery-docs-link.tsx
type GalleryDocsLinkProps (line 9) | interface GalleryDocsLinkProps {
function GalleryDocsLink (line 16) | function GalleryDocsLink({
FILE: apps/www/app/docs/_components/header-preview-tabs.tsx
type HeaderPreviewTabsProps (line 14) | interface HeaderPreviewTabsProps {
constant EMPTY_STATE (line 18) | const EMPTY_STATE: PreviewState = {};
function HeaderPreviewTabs (line 20) | function HeaderPreviewTabs({ componentId }: HeaderPreviewTabsProps) {
FILE: apps/www/app/docs/_components/install-command-block.tsx
type InstallCommandBlockProps (line 18) | interface InstallCommandBlockProps {
function CopyableCommand (line 27) | function CopyableCommand({
function InstallCommandBlock (line 91) | function InstallCommandBlock({
FILE: apps/www/app/docs/_components/install-command-line.tsx
type InstallCommandLineProps (line 5) | interface InstallCommandLineProps {
function InstallCommandLine (line 10) | function InstallCommandLine({
FILE: apps/www/app/docs/_components/interactive-option-demo.tsx
constant OPTIONS (line 9) | const OPTIONS = [
constant FOLLOW_UP (line 27) | const FOLLOW_UP: Record<string, string> = {
function InteractiveOptionDemo (line 36) | function InteractiveOptionDemo() {
FILE: apps/www/app/docs/_components/mdx-to-markdown.ts
function getMdxAsMarkdown (line 8) | function getMdxAsMarkdown(mdxPath: string): string {
FILE: apps/www/app/docs/_components/mock-thread.tsx
type MockMessageProps (line 6) | interface MockMessageProps {
function MockMessage (line 11) | function MockMessage({ role, children }: MockMessageProps) {
type MockThreadProps (line 29) | interface MockThreadProps {
function MockThread (line 35) | function MockThread({ children, className, caption }: MockThreadProps) {
FILE: apps/www/app/docs/_components/preset-example.tsx
function generateOptionListCode (line 37) | function generateOptionListCode(preset: OptionListPresetName): string {
function generateCodeBlockCode (line 86) | function generateCodeBlockCode(preset: CodeBlockPresetName): string {
function generateTerminalCode (line 110) | function generateTerminalCode(preset: TerminalPresetName): string {
type OptionListPresetExampleProps (line 145) | interface OptionListPresetExampleProps {
function OptionListPresetExample (line 149) | function OptionListPresetExample({
function generateChartCode (line 173) | function generateChartCode(preset: ChartPresetName): string {
type ChartPresetExampleProps (line 207) | interface ChartPresetExampleProps {
function ChartPresetExample (line 211) | function ChartPresetExample({ preset }: ChartPresetExampleProps) {
type CodeBlockPresetExampleProps (line 233) | interface CodeBlockPresetExampleProps {
function CodeBlockPresetExample (line 237) | function CodeBlockPresetExample({
type TerminalPresetExampleProps (line 261) | interface TerminalPresetExampleProps {
function TerminalPresetExample (line 265) | function TerminalPresetExample({ preset }: TerminalPresetExampleProps) {
function generatePlanCode (line 287) | function generatePlanCode(preset: PlanPresetName): string {
type PlanPresetExampleProps (line 309) | interface PlanPresetExampleProps {
function PlanPresetExample (line 313) | function PlanPresetExample({ preset }: PlanPresetExampleProps) {
function generateItemCarouselCode (line 335) | function generateItemCarouselCode(preset: ItemCarouselPresetName): string {
type ItemCarouselPresetExampleProps (line 351) | interface ItemCarouselPresetExampleProps {
function ItemCarouselPresetExample (line 355) | function ItemCarouselPresetExample({
function generateApprovalCardCode (line 379) | function generateApprovalCardCode(preset: ApprovalCardPresetName): string {
type ApprovalCardPresetExampleProps (line 419) | interface ApprovalCardPresetExampleProps {
function ApprovalCardPresetExample (line 423) | function ApprovalCardPresetExample({
type QuestionFlowPresetExampleProps (line 447) | interface QuestionFlowPresetExampleProps {
function QuestionFlowPresetExample (line 451) | function QuestionFlowPresetExample({
FILE: apps/www/app/docs/_components/preset-selector.tsx
type PresetMap (line 38) | type PresetMap = Record<string, Preset<unknown>>;
constant PRESET_REGISTRY (line 40) | const PRESET_REGISTRY: Record<string, PresetMap> = {
constant DEFAULT_COMPONENT (line 67) | const DEFAULT_COMPONENT = "chart";
function getPresets (line 69) | function getPresets(componentId: string): PresetMap {
function formatPresetName (line 73) | function formatPresetName(preset: string): string {
type PresetSelectorProps (line 77) | interface PresetSelectorProps {
function PresetSelector (line 83) | function PresetSelector({
type PresetItemProps (line 111) | interface PresetItemProps {
function PresetItem (line 118) | function PresetItem({
type SelectionIndicatorProps (line 156) | interface SelectionIndicatorProps {
function SelectionIndicator (line 160) | function SelectionIndicator({ isSelected }: SelectionIndicatorProps) {
FILE: apps/www/app/docs/_components/tracked-dynamic-codeblock.tsx
type InstallSnippetType (line 21) | type InstallSnippetType = ReturnType<typeof detectInstallSnippetType>;
type TrackedDynamicCodeBlockProps (line 23) | type TrackedDynamicCodeBlockProps = DynamicCodeblockProps & {
type CopyButtonElementProps (line 27) | type CopyButtonElementProps = {
function resolveSnippetPreview (line 35) | function resolveSnippetPreview(code: string): string {
function resolveInstallCopyLabel (line 48) | function resolveInstallCopyLabel(type: InstallSnippetType): string | null {
function resolveCopyContextLabel (line 64) | function resolveCopyContextLabel({
function relabelCopyButtons (line 88) | function relabelCopyButtons(
function TrackedDynamicCodeBlock (line 141) | function TrackedDynamicCodeBlock({
FILE: apps/www/app/docs/actions/actions-examples.tsx
function ActionFlowToolCallVisual (line 71) | function ActionFlowToolCallVisual() {
function ActionFlowRenderVisual (line 92) | function ActionFlowRenderVisual() {
function ActionFlowUserActionVisual (line 108) | function ActionFlowUserActionVisual() {
function ActionFlowRuntimeHandleVisual (line 146) | function ActionFlowRuntimeHandleVisual() {
function ActionFlowCommitVisual (line 178) | function ActionFlowCommitVisual() {
function DisplaySurfaceLocalActionsExample (line 270) | function DisplaySurfaceLocalActionsExample() {
function DecisionSurfaceExample (line 308) | function DecisionSurfaceExample() {
function ActionCentricExceptionsExample (line 400) | function ActionCentricExceptionsExample() {
FILE: apps/www/app/docs/actions/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/actions/page.tsx
function ActionsPage (line 12) | function ActionsPage() {
FILE: apps/www/app/docs/advanced/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/advanced/page.tsx
function AdvancedDocsPage (line 12) | function AdvancedDocsPage() {
FILE: apps/www/app/docs/agent-skills/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/agent-skills/page.tsx
function AgentSkillsPage (line 12) | function AgentSkillsPage() {
FILE: apps/www/app/docs/approval-card/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/approval-card/page.tsx
function ApprovalCardDocsPage (line 12) | function ApprovalCardDocsPage() {
FILE: apps/www/app/docs/audio/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/audio/page.tsx
function AudioDocsPage (line 12) | function AudioDocsPage() {
FILE: apps/www/app/docs/changelog/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/changelog/page.tsx
function ChangelogDocsPage (line 12) | function ChangelogDocsPage() {
FILE: apps/www/app/docs/chart/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/chart/page.tsx
function ChartDocsPage (line 12) | function ChartDocsPage() {
FILE: apps/www/app/docs/citation/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/citation/page.tsx
function CitationDocsPage (line 12) | function CitationDocsPage() {
FILE: apps/www/app/docs/code-block/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/code-block/page.tsx
function CodeBlockDocsPage (line 12) | function CodeBlockDocsPage() {
FILE: apps/www/app/docs/code-diff/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/code-diff/page.tsx
function CodeDiffDocsPage (line 12) | function CodeDiffDocsPage() {
FILE: apps/www/app/docs/data-table/formatting-gallery.tsx
type Row (line 9) | type Row = Record<
type FormatSampleProps (line 14) | interface FormatSampleProps {
function FormatSample (line 29) | function FormatSample({
function FormattingGallery (line 75) | function FormattingGallery() {
function FormatInlineExample (line 215) | function FormatInlineExample({
FILE: apps/www/app/docs/data-table/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/data-table/page.tsx
function DataTableDocsPage (line 12) | function DataTableDocsPage() {
FILE: apps/www/app/docs/data-table/tasks-demo.tsx
function TasksDemo (line 11) | function TasksDemo() {
FILE: apps/www/app/docs/design-guidelines/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/design-guidelines/page.tsx
function DesignGuidelinesPage (line 12) | function DesignGuidelinesPage() {
FILE: apps/www/app/docs/gallery/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/gallery/page.tsx
type GalleryPreviewCardProps (line 129) | interface GalleryPreviewCardProps {
type GalleryCardConfig (line 135) | interface GalleryCardConfig {
function GalleryPreviewCard (line 141) | function GalleryPreviewCard({
function ComponentsGalleryPage (line 160) | function ComponentsGalleryPage() {
FILE: apps/www/app/docs/geo-map/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/geo-map/page.tsx
function GeoMapDocsPage (line 12) | function GeoMapDocsPage() {
FILE: apps/www/app/docs/image-gallery/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/image-gallery/page.tsx
function ImageGalleryDocsPage (line 12) | function ImageGalleryDocsPage() {
FILE: apps/www/app/docs/image/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/image/page.tsx
function ImageDocsPage (line 12) | function ImageDocsPage() {
FILE: apps/www/app/docs/instagram-post/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/instagram-post/page.tsx
function InstagramPostDocsPage (line 12) | function InstagramPostDocsPage() {
FILE: apps/www/app/docs/item-carousel/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/item-carousel/page.tsx
function ItemCarouselDocsPage (line 12) | function ItemCarouselDocsPage() {
FILE: apps/www/app/docs/layout.tsx
function DocsLayout (line 19) | function DocsLayout({ children }: { children: ReactNode }) {
FILE: apps/www/app/docs/link-preview/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/link-preview/page.tsx
function LinkPreviewDocsPage (line 12) | function LinkPreviewDocsPage() {
FILE: apps/www/app/docs/linkedin-post/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/linkedin-post/page.tsx
function LinkedInPostDocsPage (line 12) | function LinkedInPostDocsPage() {
FILE: apps/www/app/docs/message-draft/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/message-draft/page.tsx
function MessageDraftDocsPage (line 12) | function MessageDraftDocsPage() {
FILE: apps/www/app/docs/option-list/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/option-list/page.tsx
function OptionListDocsPage (line 12) | function OptionListDocsPage() {
FILE: apps/www/app/docs/order-summary/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/order-summary/page.tsx
function OrderSummaryDocsPage (line 13) | function OrderSummaryDocsPage() {
FILE: apps/www/app/docs/overview/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/overview/page.tsx
function OverviewPage (line 12) | function OverviewPage() {
FILE: apps/www/app/docs/page.tsx
function DocsIndexPage (line 3) | function DocsIndexPage() {
FILE: apps/www/app/docs/parameter-slider/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/parameter-slider/page.tsx
function ParameterSliderDocsPage (line 12) | function ParameterSliderDocsPage() {
FILE: apps/www/app/docs/plan/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/plan/page.tsx
function PlanDocsPage (line 12) | function PlanDocsPage() {
FILE: apps/www/app/docs/preferences-panel/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/preferences-panel/page.tsx
function PreferencesPanelDocsPage (line 12) | function PreferencesPanelDocsPage() {
FILE: apps/www/app/docs/progress-tracker/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/progress-tracker/page.tsx
function ProgressTrackerDocsPage (line 12) | function ProgressTrackerDocsPage() {
FILE: apps/www/app/docs/question-flow/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/question-flow/page.tsx
function QuestionFlowDocsPage (line 12) | function QuestionFlowDocsPage() {
FILE: apps/www/app/docs/quick-start/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/quick-start/page.tsx
function QuickStartPage (line 12) | function QuickStartPage() {
FILE: apps/www/app/docs/receipts/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/receipts/page.tsx
function ReceiptsPage (line 12) | function ReceiptsPage() {
FILE: apps/www/app/docs/stats-display/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/stats-display/page.tsx
function StatsDisplayDocsPage (line 12) | function StatsDisplayDocsPage() {
FILE: apps/www/app/docs/terminal/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/terminal/page.tsx
function TerminalDocsPage (line 12) | function TerminalDocsPage() {
FILE: apps/www/app/docs/video/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/video/page.tsx
function VideoDocsPage (line 12) | function VideoDocsPage() {
FILE: apps/www/app/docs/weather-widget/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/weather-widget/page.tsx
function WeatherWidgetDocsPage (line 12) | function WeatherWidgetDocsPage() {
FILE: apps/www/app/docs/x-post/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/docs/x-post/page.tsx
function XPostDocsPage (line 12) | function XPostDocsPage() {
FILE: apps/www/app/global-error.tsx
function GlobalError (line 3) | function GlobalError({
FILE: apps/www/app/layout.tsx
function RootLayout (line 25) | function RootLayout({ children }: { children: ReactNode }) {
FILE: apps/www/app/not-found.tsx
function NotFound (line 3) | function NotFound() {
FILE: apps/www/app/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/page.tsx
function HomePage (line 9) | function HomePage() {
FILE: apps/www/app/playground/chat-pane.tsx
constant THREAD_STORAGE_KEY_PREFIX (line 45) | const THREAD_STORAGE_KEY_PREFIX = "playground:thread:";
constant WAYMO_BOOKING_TOOLKIT (line 47) | const WAYMO_BOOKING_TOOLKIT: Toolkit = {
constant WAYMO_V2_TOOLKIT (line 51) | const WAYMO_V2_TOOLKIT: Toolkit = {
method load (line 130) | async load() {
method append (line 134) | async append(item) {
method withFormat (line 145) | withFormat<TMessage, TStorageFormat>(
type ChatPaneProps (line 188) | type ChatPaneProps = {
type ChatPaneRef (line 192) | type ChatPaneRef = {
FILE: apps/www/app/playground/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/playground/page.tsx
constant PROTOTYPES (line 28) | const PROTOTYPES = listPrototypes();
FILE: apps/www/app/playground/waymo-demo/opengraph-image.tsx
function Image (line 12) | async function Image() {
FILE: apps/www/app/playground/waymo-demo/page.tsx
function WaymoDemoPage (line 3) | function WaymoDemoPage() {
FILE: apps/www/app/sandbox/celestial-effect/celestial-canvas.tsx
type CelestialCanvasProps (line 9) | interface CelestialCanvasProps {
type UniformLocations (line 38) | interface UniformLocations {
constant VERTEX_SHADER (line 67) | const VERTEX_SHADER = /* glsl */ `#version 300 es
constant GLSL_CONSTANTS (line 81) | const GLSL_CONSTANTS = /* glsl */ `
constant GLSL_UNIFORMS (line 86) | const GLSL_UNIFORMS = /* glsl */ `
constant GLSL_NOISE (line 111) | const GLSL_NOISE = /* glsl */ `
constant GLSL_CELESTIAL_POSITIONS (line 154) | const GLSL_CELESTIAL_POSITIONS = /* glsl */ `
constant GLSL_SKY (line 183) | const GLSL_SKY = /* glsl */ `
constant GLSL_STARS (line 210) | const GLSL_STARS = /* glsl */ `
constant GLSL_SUN (line 242) | const GLSL_SUN = /* glsl */ `
constant GLSL_MOON (line 284) | const GLSL_MOON = /* glsl */ `
constant GLSL_DEBUG (line 374) | const GLSL_DEBUG = /* glsl */ `
constant GLSL_MAIN (line 394) | const GLSL_MAIN = /* glsl */ `
constant FRAGMENT_SHADER (line 437) | const FRAGMENT_SHADER = /* glsl */ `#version 300 es
function createShader (line 459) | function createShader(
function createProgram (line 479) | function createProgram(
function getUniformLocations (line 500) | function getUniformLocations(
function setupQuadGeometry (line 536) | function setupQuadGeometry(
function loadMoonTexture (line 553) | function loadMoonTexture(
function updateCanvasSize (line 595) | function updateCanvasSize(
function CelestialCanvas (line 613) | function CelestialCanvas({
FILE: apps/www/app/sandbox/celestial-effect/page.tsx
function CelestialEffectSandbox (line 6) | function CelestialEffectSandbox() {
FILE: apps/www/app/sandbox/cloud-effect/cloud-canvas.tsx
type CloudCanvasProps (line 5) | interface CloudCanvasProps {
constant VERTEX_SHADER (line 37) | const VERTEX_SHADER = `#version 300 es
constant FRAGMENT_SHADER (line 47) | const FRAGMENT_SHADER = `#version 300 es
function createShader (line 695) | function createShader(
function createProgram (line 715) | function createProgram(
function CloudCanvas (line 736) | function CloudCanvas({
FILE: apps/www/app/sandbox/cloud-effect/page.tsx
function CloudEffectSandbox (line 6) | function CloudEffectSandbox() {
FILE: apps/www/app/sandbox/lightning-effect/lightning-canvas.tsx
type LightningCanvasProps (line 5) | interface LightningCanvasProps {
constant VERTEX_SHADER (line 19) | const VERTEX_SHADER = `#version 300 es
constant FRAGMENT_SHADER (line 29) | const FRAGMENT_SHADER = `#version 300 es
function createShader (line 469) | function createShader(
function createProgram (line 489) | function createProgram(
function LightningCanvas (line 510) | function LightningCanvas({
FILE: apps/www/app/sandbox/lightning-effect/page.tsx
function LightningEffectSandbox (line 7) | function LightningEffectSandbox() {
FILE: apps/www/app/sandbox/page.tsx
function SandboxIndex (line 82) | function SandboxIndex() {
FILE: apps/www/app/sandbox/rain-effect/page.tsx
function RainEffectSandbox (line 6) | function RainEffectSandbox() {
FILE: apps/www/app/sandbox/rain-effect/rain-canvas.tsx
type RainCanvasProps (line 5) | interface RainCanvasProps {
constant VERTEX_SHADER (line 23) | const VERTEX_SHADER = `#version 300 es
constant FRAGMENT_SHADER (line 35) | const FRAGMENT_SHADER = `#version 300 es
function createShader (line 497) | function createShader(
function createProgram (line 517) | function createProgram(
function RainCanvas (line 538) | function RainCanvas({
FILE: apps/www/app/sandbox/snow-effect/page.tsx
function SnowEffectSandbox (line 6) | function SnowEffectSandbox() {
FILE: apps/www/app/sandbox/snow-effect/snow-canvas.tsx
type SnowCanvasProps (line 5) | interface SnowCanvasProps {
constant VERTEX_SHADER (line 30) | const VERTEX_SHADER = `#version 300 es
constant FRAGMENT_SHADER (line 40) | const FRAGMENT_SHADER = `#version 300 es
function createShader (line 396) | function createShader(
function createProgram (line 416) | function createProgram(
function SnowCanvas (line 437) | function SnowCanvas({
FILE: apps/www/app/sandbox/weather-compositor/celestial-canvas.tsx
type CelestialCanvasProps (line 5) | interface CelestialCanvasProps {
type UniformLocations (line 33) | interface UniformLocations {
constant VERTEX_SHADER (line 55) | const VERTEX_SHADER = /* glsl */ `#version 300 es
constant FRAGMENT_SHADER (line 65) | const FRAGMENT_SHADER = /* glsl */ `#version 300 es
function createShader (line 450) | function createShader(
function createProgram (line 470) | function createProgram(
function getUniformLocations (line 491) | function getUniformLocations(
function loadMoonTexture (line 521) | function loadMoonTexture(
function CelestialCanvas (line 562) | function CelestialCanvas({
FILE: apps/www/app/sandbox/weather-compositor/interpolation.ts
type CheckpointOverrides (line 9) | interface CheckpointOverrides {
type BaseParamsGetter (line 16) | type BaseParamsGetter = (checkpoint: TimeCheckpoint) => FullCompositorPa...
type SurroundingCheckpoints (line 18) | interface SurroundingCheckpoints {
function getSurroundingCheckpoints (line 24) | function getSurroundingCheckpoints(
function lerpNumber (line 69) | function lerpNumber(a: number, b: number, t: number): number {
function interpolatePartialObject (line 73) | function interpolatePartialObject<T extends object>(
function interpolateOverrides (line 120) | function interpolateOverrides(
function getInterpolatedOverrides (line 206) | function getInterpolatedOverrides(
function createEmptyCheckpointOverrides (line 224) | function createEmptyCheckpointOverrides(): CheckpointOverrides {
function isCheckpointOverridesEmpty (line 233) | function isCheckpointOverridesEmpty(
function getCheckpointForTime (line 244) | function getCheckpointForTime(timeOfDay: number): TimeCheckpoint {
function isNearCheckpoint (line 249) | function isNearCheckpoint(
FILE: apps/www/app/sandbox/weather-compositor/page.tsx
function formatTimeLabel (line 43) | function formatTimeLabel(timeOfDay: number): string {
type ConditionPillProps (line 52) | interface ConditionPillProps {
function ConditionPill (line 59) | function ConditionPill({
function useDebounce (line 82) | function useDebounce<T>(value: T, delay: number): T {
constant DEFAULT_GLOBAL_SETTINGS (line 93) | const DEFAULT_GLOBAL_SETTINGS: GlobalSettings = {
function createEmptyCheckpointOverrides (line 97) | function createEmptyCheckpointOverrides(): CheckpointOverrides {
function WeatherCompositorSandbox (line 101) | function WeatherCompositorSandbox() {
FILE: apps/www/app/sandbox/weather-compositor/presets.ts
type ConditionGroup (line 9) | interface ConditionGroup {
constant CONDITION_GROUPS (line 14) | const CONDITION_GROUPS: ConditionGroup[] = [
constant WEATHER_CONDITIONS (line 34) | const WEATHER_CONDITIONS: WeatherConditionCode[] =
constant CONDITION_LABELS (line 37) | const CONDITION_LABELS: Record<WeatherConditionCode, string> = {
type LayerToggles (line 53) | interface LayerToggles {
type CelestialParams (line 61) | interface CelestialParams {
type CloudParams (line 91) | interface CloudParams {
type RainParams (line 111) | interface RainParams {
type LightningParams (line 124) | interface LightningParams {
type SnowParams (line 135) | interface SnowParams {
type PostParams (line 153) | interface PostParams {
type GlassParams (line 174) | interface GlassParams {
type ConditionOverrides (line 184) | interface ConditionOverrides {
type GlobalSettings (line 195) | interface GlobalSettings {
type CheckpointOverrides (line 199) | interface CheckpointOverrides {
type CompositorStateV4 (line 206) | interface CompositorStateV4 {
type CompositorState (line 215) | type CompositorState = CompositorStateV4;
type FullCompositorParams (line 217) | interface FullCompositorParams {
function buildBaseParamsForCondition (line 228) | function buildBaseParamsForCondition(
function getRawBaseParamsForCondition (line 370) | function getRawBaseParamsForCondition(
function getBaseParamsForCondition (line 377) | function getBaseParamsForCondition(
function mergeWithOverrides (line 395) | function mergeWithOverrides(
function extractOverrides (line 413) | function extractOverrides(
function diffObjects (line 451) | function diffObjects<T extends object>(
constant STORAGE_KEY (line 466) | const STORAGE_KEY = "weather-compositor-state";
constant DEFAULT_CHECKPOINT_OVERRIDES (line 469) | const DEFAULT_CHECKPOINT_OVERRIDES: Partial<
function createEmptyCheckpointOverrides (line 914) | function createEmptyCheckpointOverrides(): CheckpointOverrides {
function isV4State (line 923) | function isV4State(state: unknown): state is CompositorStateV4 {
function loadFromStorage (line 929) | function loadFromStorage(): CompositorState | null {
function saveToStorage (line 947) | function saveToStorage(state: CompositorState): void {
function getCheckpointOverridesForCondition (line 956) | function getCheckpointOverridesForCondition(
function exportToFile (line 966) | function exportToFile(state: CompositorState): void {
function importFromFile (line 977) | function importFromFile(file: File): Promise<CompositorState> {
FILE: apps/www/app/sandbox/weather-effects/page.tsx
function WeatherEffectsSandbox (line 15) | function WeatherEffectsSandbox() {
FILE: apps/www/app/sandbox/weather-tuning/components/checkpoint-dots.tsx
type CheckpointDotsProps (line 7) | interface CheckpointDotsProps {
constant DEFAULT_CHECKPOINTS (line 13) | const DEFAULT_CHECKPOINTS: ConditionCheckpoints = {
function CheckpointDots (line 20) | function CheckpointDots({
FILE: apps/www/app/sandbox/weather-tuning/components/condition-sidebar.tsx
type ConditionSidebarProps (line 26) | interface ConditionSidebarProps {
constant CONDITION_ICONS (line 34) | const CONDITION_ICONS: Record<WeatherConditionCode, typeof Sun> = {
constant CONDITION_COLORS (line 50) | const CONDITION_COLORS: Record<WeatherConditionCode, string> = {
function ConditionSidebar (line 66) | function ConditionSidebar({
FILE: apps/www/app/sandbox/weather-tuning/components/detail-editor.tsx
type LayerKey (line 32) | type LayerKey =
type DetailEditorProps (line 42) | interface DetailEditorProps {
function DetailEditor (line 68) | function DetailEditor({
FILE: apps/www/app/sandbox/weather-tuning/components/export-panel.tsx
type ExportPanelProps (line 11) | interface ExportPanelProps {
type ToastState (line 28) | type ToastState = {
function ExportPanel (line 34) | function ExportPanel({
FILE: apps/www/app/sandbox/weather-tuning/components/glass-controls.tsx
type GlassControlsProps (line 8) | interface GlassControlsProps {
type SliderRowProps (line 13) | interface SliderRowProps {
function SliderRow (line 23) | function SliderRow({
function GlassControls (line 64) | function GlassControls({ params, onChange }: GlassControlsProps) {
FILE: apps/www/app/sandbox/weather-tuning/components/parameter-definitions.ts
type TunableLayerKey (line 4) | type TunableLayerKey = Exclude<LayerKey, "layers">;
type ParameterDef (line 6) | interface ParameterDef {
type ParameterGroup (line 14) | interface ParameterGroup {
constant PARAMETER_GROUPS (line 20) | const PARAMETER_GROUPS: ParameterGroup[] = [
FILE: apps/www/app/sandbox/weather-tuning/components/parameter-matrix-view.tsx
type ParameterMatrixViewProps (line 49) | interface ParameterMatrixViewProps {
function useParameterAccessor (line 61) | function useParameterAccessor(
function ConditionPreview (line 159) | function ConditionPreview({
function BulkApplyMenu (line 202) | function BulkApplyMenu({
function ConditionSlider (line 259) | function ConditionSlider({
function ParameterRow (line 309) | function ParameterRow({
function ParameterListHeader (line 353) | function ParameterListHeader({
function GroupHeader (line 388) | function GroupHeader({ name }: { name: string }) {
function ParameterMatrixView (line 402) | function ParameterMatrixView({ tuningState }: ParameterMatrixViewProps) {
FILE: apps/www/app/sandbox/weather-tuning/components/parameter-panel.tsx
type LayerKey (line 42) | type LayerKey =
type ParameterPanelProps (line 52) | interface ParameterPanelProps {
function countChanges (line 68) | function countChanges<T extends object>(current: T, base: T): number {
function DeltaBadge (line 82) | function DeltaBadge({ count }: { count: number }) {
constant LAYER_CONFIG (line 91) | const LAYER_CONFIG = {
function CopyToDropdown (line 111) | function CopyToDropdown({
function ParameterPanel (line 174) | function ParameterPanel({
FILE: apps/www/app/sandbox/weather-tuning/components/parameter-row.tsx
type ParameterRowProps (line 8) | interface ParameterRowProps {
function ParameterRow (line 19) | function ParameterRow({
type ParameterToggleRowProps (line 168) | interface ParameterToggleRowProps {
function ParameterToggleRow (line 176) | function ParameterToggleRow({
FILE: apps/www/app/sandbox/weather-tuning/components/time-dial.tsx
type TimeDialProps (line 8) | interface TimeDialProps {
function TimeDial (line 17) | function TimeDial({
FILE: apps/www/app/sandbox/weather-tuning/components/time-matrix-view.tsx
constant PARAMETER_GROUP_ICONS (line 33) | const PARAMETER_GROUP_ICONS: Record<string, LucideIcon> = {
constant PARAMETER_GROUP_COLORS (line 44) | const PARAMETER_GROUP_COLORS: Record<string, { dot: string; text: string...
type TimeMatrixViewProps (line 55) | interface TimeMatrixViewProps {
function getNumericValue (line 60) | function getNumericValue(
function CheckpointSlider (line 68) | function CheckpointSlider({
function ParameterTimeRow (line 130) | function ParameterTimeRow({
function CheckpointPreview (line 223) | function CheckpointPreview({
function TimeMatrixView (line 265) | function TimeMatrixView({
FILE: apps/www/app/sandbox/weather-tuning/components/view-mode-toggle.tsx
type ViewMode (line 6) | type ViewMode = "condition" | "parameter" | "time";
type ViewModeToggleProps (line 8) | interface ViewModeToggleProps {
function ViewModeToggle (line 13) | function ViewModeToggle({ value, onChange }: ViewModeToggleProps) {
FILE: apps/www/app/sandbox/weather-tuning/components/weather-data-overlay.tsx
type WeatherOverlayStubData (line 18) | interface WeatherOverlayStubData {
function createWeatherOverlayStubData (line 28) | function createWeatherOverlayStubData(
FILE: apps/www/app/sandbox/weather-tuning/hooks/use-tuning-state.ts
type LayerKey (line 46) | type LayerKey =
constant STUDIO_PREVIEW_CHECKPOINT_MODE (line 56) | const STUDIO_PREVIEW_CHECKPOINT_MODE: WeatherEffectsCheckpointMode = "ne...
function createEmptyCheckpointOverrides (line 58) | function createEmptyCheckpointOverrides(): CheckpointOverrides {
function useTuningState (line 67) | function useTuningState() {
type TuningStateReturn (line 780) | type TuningStateReturn = ReturnType<typeof useTuningState>;
FILE: apps/www/app/sandbox/weather-tuning/lib/constants.ts
constant TIME_CHECKPOINTS (line 7) | const TIME_CHECKPOINTS: Record<
constant TIME_CHECKPOINT_ORDER (line 17) | const TIME_CHECKPOINT_ORDER: TimeCheckpoint[] =
constant STORAGE_KEY (line 20) | const STORAGE_KEY = "weather-tuning-state";
constant SESSION_KEY (line 21) | const SESSION_KEY = "weather-tuning-workflow";
constant DEFAULT_TIME_OF_DAY (line 23) | const DEFAULT_TIME_OF_DAY = 0.5;
constant SNOW_FALL_SPEED_MAX (line 24) | const SNOW_FALL_SPEED_MAX = 8;
constant RAIN_PARAM_LIMITS (line 26) | const RAIN_PARAM_LIMITS = {
FILE: apps/www/app/sandbox/weather-tuning/lib/has-any-tuning-delta.ts
function hasAnyTuningDelta (line 4) | function hasAnyTuningDelta(
FILE: apps/www/app/sandbox/weather-tuning/lib/list-updated-params.ts
type CheckpointKey (line 4) | type CheckpointKey = keyof CheckpointOverrides;
constant CHECKPOINTS (line 6) | const CHECKPOINTS: CheckpointKey[] = ["dawn", "noon", "dusk", "midnight"];
function listUpdatedParams (line 8) | function listUpdatedParams(
FILE: apps/www/app/sandbox/weather-tuning/lib/map-to-canvas-props.ts
function mapCompositorParamsToCanvasProps (line 16) | function mapCompositorParamsToCanvasProps(
FILE: apps/www/app/sandbox/weather-tuning/lib/recover-repo-overrides.ts
type RecoverPayload (line 4) | type RecoverPayload = {
function recoverRepoCheckpointOverrides (line 10) | async function recoverRepoCheckpointOverrides(
FILE: apps/www/app/sandbox/weather-tuning/lib/resolve-params.ts
type BaseGetter (line 7) | type BaseGetter = (checkpoint: TimeCheckpoint) => FullCompositorParams;
function resolveCompositorParamsAtTime (line 15) | function resolveCompositorParamsAtTime(opts: {
FILE: apps/www/app/sandbox/weather-tuning/lib/studio-timestamp.ts
function createStudioTimestamp (line 1) | function createStudioTimestamp(
FILE: apps/www/app/sandbox/weather-tuning/lib/tool-ui-export.ts
constant CHECKPOINTS (line 20) | const CHECKPOINTS: TimeCheckpoint[] = ["dawn", "noon", "dusk", "midnight"];
constant WEATHER_CONDITION_ORDER (line 22) | const WEATHER_CONDITION_ORDER: WeatherConditionCode[] = [
function isObjectEmpty (line 38) | function isObjectEmpty(value: unknown): boolean {
function mapConditionOverridesToToolUi (line 46) | function mapConditionOverridesToToolUi(
function mergeGroup (line 233) | function mergeGroup<T extends object>(
function mergeWeatherEffectsOverrides (line 241) | function mergeWeatherEffectsOverrides(
function mergeTunedPresets (line 258) | function mergeTunedPresets(
function hasAnyOverrideGroups (line 298) | function hasAnyOverrideGroups(
function buildCanonicalToolUiPresetsForEditedConditions (line 310) | function buildCanonicalToolUiPresetsForEditedConditions(
function replaceEditedConditions (line 354) | function replaceEditedConditions(
function toToolUiDelta (line 374) | function toToolUiDelta(
function generateToolUiTypeScript (line 410) | function generateToolUiTypeScript(
FILE: apps/www/app/sandbox/weather-tuning/lib/tool-ui-import.ts
function isEmptyObject (line 12) | function isEmptyObject(value: unknown): boolean {
function mapToolUiOverridesToCompositor (line 20) | function mapToolUiOverridesToCompositor(
function mapToolUiCheckpointsToCompositor (line 100) | function mapToolUiCheckpointsToCompositor(
function mapToolUiPresetsToCompositor (line 111) | function mapToolUiPresetsToCompositor(
FILE: apps/www/app/sandbox/weather-tuning/lib/workflow-state.ts
constant WORKFLOW_STATE_STORAGE_KEY (line 6) | const WORKFLOW_STATE_STORAGE_KEY = "weather-tuning-studio-session";
constant STORAGE_KEY (line 7) | const STORAGE_KEY = WORKFLOW_STATE_STORAGE_KEY;
type WorkflowState (line 9) | interface WorkflowState {
function isRecord (line 17) | function isRecord(value: unknown): value is Record<string, unknown> {
function parseWorkflowState (line 21) | function parseWorkflowState(parsed: unknown): WorkflowState | null {
function loadWorkflowState (line 57) | function loadWorkflowState(): WorkflowState | null {
function saveWorkflowState (line 71) | function saveWorkflowState(state: WorkflowState): void {
FILE: apps/www/app/sandbox/weather-tuning/page.tsx
function WeatherTuningPage (line 18) | function WeatherTuningPage() {
FILE: apps/www/app/sandbox/weather-tuning/types.ts
type CheckpointStatus (line 4) | type CheckpointStatus = "pending" | "reviewed";
type ConditionCheckpoints (line 6) | interface ConditionCheckpoints {
type CompareMode (line 13) | type CompareMode = "off" | "ab" | "side-by-side";
type TuningState (line 15) | interface TuningState {
FILE: apps/www/app/sandbox/weather-widget-production/page.tsx
constant CONDITION_OPTIONS (line 32) | const CONDITION_OPTIONS: WeatherConditionCode[] = [
constant PRECIPITATION_OPTIONS (line 48) | const PRECIPITATION_OPTIONS: PrecipitationLevel[] = [
constant TEMPERATURE_UNIT_OPTIONS (line 55) | const TEMPERATURE_UNIT_OPTIONS: TemperatureUnit[] = ["celsius", "fahrenh...
constant QUALITY_OPTIONS (line 56) | const QUALITY_OPTIONS: EffectQuality[] = ["low", "medium", "high", "auto"];
function timeToISOString (line 58) | function timeToISOString(timeOfDay: number): string {
function formatValue (line 67) | function formatValue(value: number): string {
function formatDelta (line 71) | function formatDelta(next: number, prev: number): string {
type UntunedPreviewProps (line 77) | interface UntunedPreviewProps {
function UntunedPreview (line 85) | function UntunedPreview({
function WeatherWidgetProductionHarnessPage (line 143) | function WeatherWidgetProductionHarnessPage() {
FILE: apps/www/app/sandbox/weather-widget-production/runtime-input.ts
type ProductionHarnessRuntimeInput (line 7) | interface ProductionHarnessRuntimeInput {
function createProductionHarnessRuntimeInput (line 16) | function createProductionHarnessRuntimeInput(
FILE: apps/www/app/sandbox/weather-widget-stress/page.tsx
constant CONDITIONS (line 14) | const CONDITIONS: WeatherConditionCode[] = [
constant WEBGL_SAFE_WIDGET_COUNT (line 30) | const WEBGL_SAFE_WIDGET_COUNT = 8;
constant CONDITION_SPECTRUM (line 34) | const CONDITION_SPECTRUM: WeatherConditionCode[] = [
constant CITIES (line 45) | const CITIES = [
constant WEEKDAYS (line 58) | const WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] as co...
function clamp (line 60) | function clamp(value: number, min: number, max: number): number {
function mulberry32 (line 64) | function mulberry32(seed: number): () => number {
function pick (line 75) | function pick<T>(rand: () => number, items: readonly T[]): T {
function timeToISOString (line 79) | function timeToISOString(timeOfDay: number): string {
function baseTempForCondition (line 89) | function baseTempForCondition(
function precipitationForCondition (line 113) | function precipitationForCondition(
function buildForecast (line 133) | function buildForecast(
function WeatherWidgetStressPage (line 157) | function WeatherWidgetStressPage() {
FILE: apps/www/app/sandbox/weather-widget/page.tsx
type LocationPreset (line 12) | interface LocationPreset {
constant LOCATION_PRESETS (line 21) | const LOCATION_PRESETS: LocationPreset[] = [
function formatTimeLabel (line 321) | function formatTimeLabel(timeOfDay: number): string {
function timeToISOString (line 330) | function timeToISOString(timeOfDay: number): string {
type LocationPillProps (line 340) | interface LocationPillProps {
function LocationPill (line 346) | function LocationPill({ preset, isActive, onClick }: LocationPillProps) {
function WeatherWidgetSandbox (line 362) | function WeatherWidgetSandbox() {
FILE: apps/www/app/staging/_components/rounded-rect-overlay.tsx
type RoundedRectOverlayProps (line 5) | interface RoundedRectOverlayProps {
constant COLOR_STYLES (line 19) | const COLOR_STYLES = {
function RoundedRectOverlay (line 43) | function RoundedRectOverlay({
type ThumbIndicatorProps (line 141) | interface ThumbIndicatorProps {
function ThumbIndicator (line 146) | function ThumbIndicator({ rect, containerRect }: ThumbIndicatorProps) {
FILE: apps/www/app/staging/_components/staging-canvas.tsx
type StagingCanvasProps (line 9) | interface StagingCanvasProps {
function StagingCanvas (line 15) | function StagingCanvas({
FILE: apps/www/app/staging/_components/staging-showcase.tsx
constant TIMING (line 17) | const TIMING = {
constant SPRINGS (line 30) | const SPRINGS = {
type ChatBubbleProps (line 51) | interface ChatBubbleProps {
function ChatBubble (line 57) | function ChatBubble({ role, children, className }: ChatBubbleProps) {
function TypingIndicator (line 82) | function TypingIndicator() {
function StreamingChar (line 97) | function StreamingChar({ char, delay }: { char: string; delay: number }) {
type PreambleBubbleProps (line 113) | interface PreambleBubbleProps {
function PreambleBubble (line 119) | function PreambleBubble({
function ToolReveal (line 171) | function ToolReveal({ children }: { children: ReactNode }) {
type ShowcasePhase (line 183) | type ShowcasePhase = "user" | "typing" | "preamble" | "tool" | "complete";
type StagingShowcaseProps (line 185) | interface StagingShowcaseProps {
function StagingShowcase (line 191) | function StagingShowcase({
FILE: apps/www/app/staging/_components/staging-toolbar.tsx
constant COMPONENT_IDS (line 26) | const COMPONENT_IDS = Object.keys(previewConfigs) as ComponentId[];
constant DEBUG_LEVEL_LABELS (line 28) | const DEBUG_LEVEL_LABELS: Record<DebugLevel, string> = {
function ComponentSelector (line 35) | function ComponentSelector() {
function formatComponentName (line 57) | function formatComponentName(id: string): string {
function PresetPills (line 64) | function PresetPills() {
function formatPresetName (line 91) | function formatPresetName(name: string): string {
function SettingsPopover (line 98) | function SettingsPopover() {
function ViewModeToggle (line 197) | function ViewModeToggle() {
function DebugLevelIndicator (line 232) | function DebugLevelIndicator() {
function StagingToolbar (line 256) | function StagingToolbar() {
FILE: apps/www/app/staging/_components/use-keyboard-shortcuts.ts
function useKeyboardShortcuts (line 6) | function useKeyboardShortcuts() {
FILE: apps/www/app/staging/_components/use-staging-state.ts
type ViewMode (line 9) | type ViewMode = "static" | "showcase";
type StagingState (line 11) | interface StagingState {
constant DEBUG_LEVELS (line 23) | const DEBUG_LEVELS: DebugLevel[] = ["off", "boundaries", "margins", "ful...
function useStagingState (line 55) | function useStagingState() {
function usePresetNames (line 116) | function usePresetNames(): string[] {
FILE: apps/www/app/staging/layout.tsx
function StagingLayout (line 4) | function StagingLayout({ children }: { children: ReactNode }) {
FILE: apps/www/app/staging/page.tsx
function StagingContent (line 10) | function StagingContent() {
function StagingPage (line 36) | function StagingPage() {
FILE: apps/www/components/assistant-ui/assistant-modal.tsx
type AssistantModalButtonProps (line 29) | type AssistantModalButtonProps = { "data-state"?: "open" | "closed" };
FILE: apps/www/components/assistant-ui/attachment.tsx
type AttachmentPreviewProps (line 64) | type AttachmentPreviewProps = {
FILE: apps/www/components/assistant-ui/reasoning.tsx
constant ANIMATION_DURATION (line 28) | const ANIMATION_DURATION = 200;
constant SHIMMER_DURATION (line 29) | const SHIMMER_DURATION = 1000;
FILE: apps/www/components/assistant-ui/shiki-highlighter.tsx
type HighlighterProps (line 11) | type HighlighterProps = Omit<
FILE: apps/www/components/assistant-ui/thread.tsx
constant SUGGESTIONS (line 99) | const SUGGESTIONS = [
FILE: apps/www/components/assistant-ui/threadlist-sidebar.tsx
function ThreadListSidebar (line 16) | function ThreadListSidebar({
FILE: apps/www/components/assistant-ui/tooltip-icon-button.tsx
type TooltipIconButtonProps (line 14) | type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
FILE: apps/www/components/tool-ui/approval-card/approval-card.tsx
type LucideIcon (line 11) | type LucideIcon = React.ComponentType<{ className?: string }>;
function getLucideIcon (line 13) | function getLucideIcon(name: string): LucideIcon | null {
type ApprovalCardReceiptProps (line 23) | interface ApprovalCardReceiptProps {
function ApprovalCardReceipt (line 31) | function ApprovalCardReceipt({
function ApprovalCard (line 77) | function ApprovalCard({
FILE: apps/www/components/tool-ui/approval-card/schema.ts
type MetadataItem (line 10) | type MetadataItem = z.infer<typeof MetadataItemSchema>;
type ApprovalDecision (line 14) | type ApprovalDecision = z.infer<typeof ApprovalDecisionSchema>;
type SerializableApprovalCard (line 33) | type SerializableApprovalCard = z.infer<
type ApprovalCardProps (line 50) | interface ApprovalCardProps extends SerializableApprovalCard {
FILE: apps/www/components/tool-ui/audio/audio.tsx
constant FALLBACK_LOCALE (line 10) | const FALLBACK_LOCALE = "en-US";
function formatTime (line 12) | function formatTime(seconds: number): string {
type AudioProps (line 19) | interface AudioProps extends SerializableAudio {
function Audio (line 25) | function Audio(props: AudioProps) {
type PlayerControls (line 33) | interface PlayerControls {
type FullPlayerProps (line 43) | interface FullPlayerProps {
function FullPlayer (line 50) | function FullPlayer({
type CompactPlayerProps (line 121) | interface CompactPlayerProps {
function CompactPlayer (line 128) | function CompactPlayer({
function AudioInner (line 206) | function AudioInner(props: AudioProps) {
FILE: apps/www/components/tool-ui/audio/context.tsx
type AudioPlaybackState (line 5) | interface AudioPlaybackState {
type AudioContextValue (line 10) | interface AudioContextValue {
function useAudio (line 19) | function useAudio() {
type AudioProviderProps (line 27) | interface AudioProviderProps {
function AudioProvider (line 32) | function AudioProvider({ children, defaultState }: AudioProviderProps) {
FILE: apps/www/components/tool-ui/audio/schema.ts
type Source (line 15) | type Source = z.infer<typeof SourceSchema>;
type SerializableAudio (line 33) | type SerializableAudio = z.infer<typeof SerializableAudioSchema>;
type AudioVariant (line 46) | type AudioVariant = "full" | "compact";
FILE: apps/www/components/tool-ui/chart/chart.tsx
constant DEFAULT_COLORS (line 30) | const DEFAULT_COLORS = [
FILE: apps/www/components/tool-ui/chart/schema.ts
type ChartSeries (line 15) | type ChartSeries = z.infer<typeof ChartSeriesSchema>;
type ChartDataPoint (line 91) | type ChartDataPoint = {
type ChartClientProps (line 100) | type ChartClientProps = {
type ChartProps (line 105) | type ChartProps = z.infer<typeof ChartPropsSchema> & ChartClientProps;
type SerializableChart (line 109) | type SerializableChart = z.infer<typeof SerializableChartSchema>;
FILE: apps/www/components/tool-ui/citation/citation-list.tsx
constant TYPE_ICONS (line 26) | const TYPE_ICONS: Record<CitationType, LucideIcon> = {
function useHoverPopover (line 35) | function useHoverPopover(delay = 100) {
type CitationListProps (line 87) | interface CitationListProps {
function CitationList (line 96) | function CitationList(props: CitationListProps) {
type OverflowIndicatorProps (line 184) | interface OverflowIndicatorProps {
function OverflowIndicator (line 191) | function OverflowIndicator({
type OverflowItemProps (line 289) | interface OverflowItemProps {
function OverflowItem (line 294) | function OverflowItem({ citation, onClick }: OverflowItemProps) {
type StackedCitationsProps (line 331) | interface StackedCitationsProps {
function StackedCitations (line 338) | function StackedCitations({
FILE: apps/www/components/tool-ui/citation/citation.tsx
constant FALLBACK_LOCALE (line 23) | const FALLBACK_LOCALE = "en-US";
constant TYPE_ICONS (line 25) | const TYPE_ICONS: Record<CitationType, LucideIcon> = {
function extractDomain (line 34) | function extractDomain(url: string): string | undefined {
function formatDate (line 43) | function formatDate(isoString: string, locale: string): string {
function useHoverPopover (line 55) | function useHoverPopover(delay = 100) {
type CitationProps (line 78) | interface CitationProps extends SerializableCitation {
function Citation (line 84) | function Citation(props: CitationProps) {
FILE: apps/www/components/tool-ui/citation/schema.ts
type CitationType (line 18) | type CitationType = z.infer<typeof CitationTypeSchema>;
type CitationVariant (line 22) | type CitationVariant = z.infer<typeof CitationVariantSchema>;
type SerializableCitation (line 39) | type SerializableCitation = z.infer<typeof SerializableCitationSchema>;
FILE: apps/www/components/tool-ui/code-block/code-block.tsx
constant COPY_ID (line 24) | const COPY_ID = "codeblock-code";
constant MAX_HTML_CACHE_ENTRIES (line 25) | const MAX_HTML_CACHE_ENTRIES = 64;
function getHighlighter (line 29) | function getHighlighter(): Promise<Highlighter> {
function getCacheKey (line 42) | function getCacheKey(
function setCachedHtml (line 58) | function setCachedHtml(cacheKey: string, html: string): void {
constant LANGUAGE_DISPLAY_NAMES (line 74) | const LANGUAGE_DISPLAY_NAMES: Record<string, string> = {
function getLanguageDisplayName (line 93) | function getLanguageDisplayName(lang: string): string {
function getSystemTheme (line 97) | function getSystemTheme(): "light" | "dark" {
function getDocumentTheme (line 104) | function getDocumentTheme(): "light" | "dark" | null {
function useResolvedTheme (line 115) | function useResolvedTheme(): "light" | "dark" {
type CodeBlockRootProps (line 145) | type CodeBlockRootProps = CodeBlockProps & {
type CodeBlockSharedState (line 152) | type CodeBlockSharedState = {
function useCodeBlock (line 168) | function useCodeBlock(): CodeBlockSharedState {
function CodeBlockRoot (line 178) | function CodeBlockRoot({
type CodeBlockSectionProps (line 351) | type CodeBlockSectionProps = {
function CodeBlockHeader (line 355) | function CodeBlockHeader({ className }: CodeBlockSectionProps) {
function CodeBlockContent (line 394) | function CodeBlockContent({ className }: CodeBlockSectionProps) {
function CodeBlockCollapseToggle (line 411) | function CodeBlockCollapseToggle({ className }: CodeBlockSectionProps) {
type CodeBlockComposedProps (line 443) | type CodeBlockComposedProps = Omit<CodeBlockRootProps, "children">;
function CodeBlockComposed (line 445) | function CodeBlockComposed(props: CodeBlockComposedProps) {
type CodeBlockComponent (line 455) | type CodeBlockComponent = typeof CodeBlockComposed & {
FILE: apps/www/components/tool-ui/code-block/schema.ts
type CodeBlockProps (line 22) | type CodeBlockProps = z.infer<typeof CodeBlockPropsSchema>;
type CodeBlockLineNumbersMode (line 23) | type CodeBlockLineNumbersMode = CodeBlockProps["lineNumbers"];
type SerializableCodeBlock (line 29) | type SerializableCodeBlock = z.infer<typeof SerializableCodeBlockSchema>;
FILE: apps/www/components/tool-ui/code-diff/code-diff.tsx
constant COPY_ID (line 37) | const COPY_ID = "codediff-code";
function getSystemTheme (line 41) | function getSystemTheme(): "light" | "dark" {
function getDocumentTheme (line 48) | function getDocumentTheme(): "light" | "dark" | null {
function useResolvedTheme (line 59) | function useResolvedTheme(): "light" | "dark" {
constant LANGUAGE_DISPLAY_NAMES (line 91) | const LANGUAGE_DISPLAY_NAMES: Record<string, string> = {
function getLanguageDisplayName (line 110) | function getLanguageDisplayName(lang: string): string {
type CodeDiffSharedState (line 116) | type CodeDiffSharedState = {
function useCodeDiff (line 139) | function useCodeDiff(): CodeDiffSharedState {
type CodeDiffRootProps (line 151) | type CodeDiffRootProps = CodeDiffProps & {
function CodeDiffRoot (line 158) | function CodeDiffRoot({
type CodeDiffSectionProps (line 298) | type CodeDiffSectionProps = {
function CodeDiffHeader (line 302) | function CodeDiffHeader({ className }: CodeDiffSectionProps) {
function CodeDiffContent (line 354) | function CodeDiffContent({ className }: CodeDiffSectionProps) {
function CodeDiffCollapseToggle (line 404) | function CodeDiffCollapseToggle({ className }: CodeDiffSectionProps) {
type CodeDiffComposedProps (line 437) | type CodeDiffComposedProps = Omit<CodeDiffRootProps, "children">;
function CodeDiffComposed (line 439) | function CodeDiffComposed(props: CodeDiffComposedProps) {
type CodeDiffComponent (line 451) | type CodeDiffComponent = typeof CodeDiffComposed & {
FILE: apps/www/components/tool-ui/code-diff/schema.ts
function validateCodeDiffInputMode (line 24) | function validateCodeDiffInputMode(
type CodeDiffProps (line 52) | type CodeDiffProps = z.infer<typeof CodeDiffPropsSchema>;
type SerializableCodeDiff (line 58) | type SerializableCodeDiff = z.infer<typeof SerializableCodeDiffSchema>;
FILE: apps/www/components/tool-ui/data-table/data-table.tsx
constant DEFAULT_LOCALE (line 38) | const DEFAULT_LOCALE = "en-US" as const;
function isNumericFormat (line 40) | function isNumericFormat(format?: FormatConfig): boolean {
function getAlignmentClass (line 50) | function getAlignmentClass(
function useDataTable (line 63) | function useDataTable<T extends object = RowData>() {
type DataTableLayout (line 73) | type DataTableLayout = "auto" | "table" | "cards";
type DataTableBaseProps (line 75) | type DataTableBaseProps<T extends object = RowData> = DataTableProps<T> & {
type DataTableProviderProps (line 79) | type DataTableProviderProps<T extends object = RowData> = Pick<
function DataTableProvider (line 93) | function DataTableProvider<T extends object = RowData>({
type DataTableLayoutProps (line 171) | interface DataTableLayoutProps {
function DataTableLayout (line 178) | function DataTableLayout({
function DataTableBase (line 305) | function DataTableBase<T extends object = RowData>(
function DataTableRoot (line 344) | function DataTableRoot<T extends object = RowData>(props: DataTableProps...
function DataTableTable (line 348) | function DataTableTable<T extends object = RowData>(props: DataTableProp...
function DataTableCards (line 352) | function DataTableCards<T extends object = RowData>(props: DataTableProp...
type DataTableComponent (line 356) | type DataTableComponent = {
function DataTableContent (line 369) | function DataTableContent() {
function DataTableEmpty (line 378) | function DataTableEmpty({ message }: { message: string }) {
function SortIcon (line 392) | function SortIcon({ state }: { state?: "asc" | "desc" }) {
function DataTableHeader (line 413) | function DataTableHeader() {
type DataTableHeadProps (line 434) | interface DataTableHeadProps {
function DataTableHead (line 440) | function DataTableHead({
function DataTableBody (line 559) | function DataTableBody() {
type DataTableRowProps (line 593) | interface DataTableRowProps {
function DataTableRow (line 598) | function DataTableRow({ row, className }: DataTableRowProps) {
type DataTableCellProps (line 616) | interface DataTableCellProps {
function DataTableCell (line 629) | function DataTableCell({
function categorizeColumns (line 656) | function categorizeColumns(columns: Column[]) {
type DataTableAccordionCardProps (line 683) | interface DataTableAccordionCardProps {
function getDataTableRowDomId (line 690) | function getDataTableRowDomId(rowKey: string): string {
function DataTableAccordionCard (line 694) | function DataTableAccordionCard({
function SimpleCard (line 859) | function SimpleCard({
FILE: apps/www/components/tool-ui/data-table/formatters.tsx
type Tone (line 7) | type Tone = "success" | "warning" | "danger" | "info" | "neutral";
type FormatConfig (line 9) | type FormatConfig =
type DeltaValueProps (line 41) | interface DeltaValueProps {
function DeltaValue (line 47) | function DeltaValue({ value, options, locale }: DeltaValueProps) {
type StatusBadgeProps (line 88) | interface StatusBadgeProps {
function StatusBadge (line 93) | function StatusBadge({ value, options }: StatusBadgeProps) {
type CurrencyValueProps (line 127) | interface CurrencyValueProps {
function CurrencyValue (line 133) | function CurrencyValue({ value, options, locale }: CurrencyValueProps) {
type PercentValueProps (line 147) | interface PercentValueProps {
function PercentValue (line 153) | function PercentValue({ value, options, locale }: PercentValueProps) {
type DateValueProps (line 170) | interface DateValueProps {
function DateValue (line 176) | function DateValue({ value, options, locale }: DateValueProps) {
function getRelativeTime (line 217) | function getRelativeTime(date: Date, locale?: string): string {
type BooleanValueProps (line 246) | interface BooleanValueProps {
function BooleanValue (line 251) | function BooleanValue({ value, options }: BooleanValueProps) {
type LinkValueProps (line 259) | interface LinkValueProps {
function LinkValue (line 268) | function LinkValue({ value, options, row }: LinkValueProps) {
type NumberValueProps (line 297) | interface NumberValueProps {
function NumberValue (line 303) | function NumberValue({ value, options, locale }: NumberValueProps) {
type BadgeValueProps (line 325) | interface BadgeValueProps {
function BadgeValue (line 330) | function BadgeValue({ value, options }: BadgeValueProps) {
type ArrayValueProps (line 360) | interface ArrayValueProps {
function ArrayValue (line 365) | function ArrayValue({ value, options }: ArrayValueProps) {
type RenderFormattedValueParams (line 410) | interface RenderFormattedValueParams {
function renderFormattedValue (line 425) | function renderFormattedValue({
FILE: apps/www/components/tool-ui/data-table/schema.ts
type SerializableDataTable (line 207) | type SerializableDataTable = z.infer<typeof SerializableDataTableSchema>;
function parseSerializableDataTable (line 237) | function parseSerializableDataTable(
function safeParseSerializableDataTable (line 291) | function safeParseSerializableDataTable(
FILE: apps/www/components/tool-ui/data-table/types.ts
type JsonPrimitive (line 7) | type JsonPrimitive = string | number | boolean | null;
type RowPrimitive (line 35) | type RowPrimitive = JsonPrimitive | JsonPrimitive[];
type DataTableRowData (line 36) | type DataTableRowData = Record<string, RowPrimitive>;
type RowData (line 37) | type RowData = Record<string, unknown>;
type ColumnKey (line 38) | type ColumnKey<T extends object> = Extract<keyof T, string>;
type FormatFor (line 40) | type FormatFor<V> = V extends number
type Column (line 60) | interface Column<
type DataTableSerializableProps (line 102) | interface DataTableSerializableProps<T extends object = RowData> {
type DataTableClientProps (line 195) | interface DataTableClientProps<T extends object = RowData> {
type DataTableProps (line 250) | interface DataTableProps<T extends object = RowData>
type DataTableContextValue (line 253) | interface DataTableContextValue<T extends object = RowData> {
FILE: apps/www/components/tool-ui/data-table/utilities.ts
function sortData (line 4) | function sortData<T, K extends Extract<keyof T, string>>(
function getRowIdentifier (line 75) | function getRowIdentifier(
function stableStringify (line 100) | function stableStringify(value: unknown): string {
function hashString (line 124) | function hashString(value: string): string {
function createDataTableRowKeys (line 139) | function createDataTableRowKeys(
function sanitizeDomIdToken (line 187) | function sanitizeDomIdToken(value: string): string {
function getDataTableMobileDescriptionId (line 191) | function getDataTableMobileDescriptionId(surfaceId: string): string {
function parseNumericLike (line 216) | function parseNumericLike(input: string): number | null {
FILE: apps/www/components/tool-ui/geo-map/geo-map-engine.tsx
constant TILE_ATTRIBUTION (line 26) | const TILE_ATTRIBUTION =
constant ROUTE_DEFAULT_COLOR (line 28) | const ROUTE_DEFAULT_COLOR = "var(--primary)";
constant ROUTE_DEFAULT_WEIGHT (line 29) | const ROUTE_DEFAULT_WEIGHT = 3;
constant ROUTE_DEFAULT_OPACITY (line 30) | const ROUTE_DEFAULT_OPACITY = 0.85;
constant EMPTY_ROUTES (line 31) | const EMPTY_ROUTES: GeoMapRoute[] = [];
constant CLUSTER_RADIUS_DEFAULT (line 33) | const CLUSTER_RADIUS_DEFAULT = 60;
constant CLUSTER_MAX_ZOOM_DEFAULT (line 34) | const CLUSTER_MAX_ZOOM_DEFAULT = 16;
constant CLUSTER_MIN_POINTS_DEFAULT (line 35) | const CLUSTER_MIN_POINTS_DEFAULT = 2;
constant DEFAULT_CENTER (line 37) | const DEFAULT_CENTER: [number, number] = [20, 0];
constant DEFAULT_VIEW_ZOOM (line 38) | const DEFAULT_VIEW_ZOOM = 2;
constant SINGLE_LOCATION_ZOOM (line 39) | const SINGLE_LOCATION_ZOOM = 13;
constant DEFAULT_VIEWPORT_PADDING (line 40) | const DEFAULT_VIEWPORT_PADDING = 32;
type LeafletRuntime (line 42) | type LeafletRuntime = Pick<
type GeoMapBbox (line 47) | type GeoMapBbox = [
type GeoMapLatLng (line 53) | type GeoMapLatLng = [lat: number, lng: number];
type GeoMapClusterProperties (line 55) | type GeoMapClusterProperties = {
type GeoMapClusterFeature (line 62) | type GeoMapClusterFeature = GeoJSON.Feature<
type MarkerClusterPointProperties (line 67) | type MarkerClusterPointProperties = GeoMapClusterProperties & {
type MapViewportState (line 72) | type MapViewportState = {
function roundCoordinate (line 77) | function roundCoordinate(value: number): number {
function normalizeViewportState (line 81) | function normalizeViewportState(state: MapViewportState): MapViewportSta...
function areViewportStatesEqual (line 93) | function areViewportStatesEqual(
function serializeFitPoints (line 110) | function serializeFitPoints(points: [number, number][]): string {
function readViewportState (line 116) | function readViewportState(map: LeafletMap): MapViewportState {
function collectFitPoints (line 129) | function collectFitPoints(
function resolveFitPointsWithFallback (line 149) | function resolveFitPointsWithFallback(
function splitDatelineBbox (line 166) | function splitDatelineBbox(bbox: GeoMapBbox): GeoMapBbox[] {
function getClusterFeatureKey (line 179) | function getClusterFeatureKey(feature: GeoMapClusterFeature): string {
function dedupeClusterFeatures (line 201) | function dedupeClusterFeatures(
function getClustersForDatelineAwareBbox (line 220) | function getClustersForDatelineAwareBbox(
function toSafeExpansionZoom (line 235) | function toSafeExpansionZoom(
function resolveInitialView (line 250) | function resolveInitialView(
function ViewportController (line 277) | function ViewportController({
function MapObserver (line 346) | function MapObserver({
function resolveMarkerAriaLabel (line 370) | function resolveMarkerAriaLabel(marker: GeoMapMarker): string {
FILE: apps/www/components/tool-ui/geo-map/geo-map-icons.ts
type LeafletIconRuntime (line 4) | type LeafletIconRuntime = Pick<typeof import("leaflet"), "divIcon">;
function isSafeHttpUrl (line 6) | function isSafeHttpUrl(value: string | undefined): boolean {
function escapeHtml (line 19) | function escapeHtml(value: string): string {
function createEmojiIcon (line 28) | function createEmojiIcon(
function createImageIcon (line 58) | function createImageIcon(
function createClusterIcon (line 86) | function createClusterIcon(
function resolveMarkerIcon (line 118) | function resolveMarkerIcon(
FILE: apps/www/components/tool-ui/geo-map/geo-map-overlays.tsx
function GeoMapPopupContent (line 7) | function GeoMapPopupContent({
function GeoMapTooltipContent (line 30) | function GeoMapTooltipContent({ text }: { text: string }) {
function GeoMapOverlays (line 34) | function GeoMapOverlays({
FILE: apps/www/components/tool-ui/geo-map/geo-map.tsx
constant LIGHT_TILE_URL (line 9) | const LIGHT_TILE_URL =
constant DARK_TILE_URL (line 11) | const DARK_TILE_URL =
function getSystemTheme (line 14) | function getSystemTheme(): "light" | "dark" {
function getDocumentTheme (line 21) | function getDocumentTheme(): "light" | "dark" | null {
function useInheritedTheme (line 34) | function useInheritedTheme(): "light" | "dark" {
function resolveMapAriaLabel (line 64) | function resolveMapAriaLabel(title?: string, description?: string): stri...
FILE: apps/www/components/tool-ui/geo-map/schema.ts
type GeoMapMarkerIcon (line 49) | type GeoMapMarkerIcon = z.infer<typeof GeoMapMarkerIconSchema>;
type GeoMapMarker (line 61) | type GeoMapMarker = z.infer<typeof GeoMapMarkerSchema>;
type GeoMapRoute (line 80) | type GeoMapRoute = z.infer<typeof GeoMapRouteSchema>;
type GeoMapClustering (line 89) | type GeoMapClustering = z.infer<typeof GeoMapClusteringSchema>;
type GeoMapFitTarget (line 92) | type GeoMapFitTarget = z.infer<typeof GeoMapFitTargetSchema>;
type GeoMapViewport (line 115) | type GeoMapViewport = z.infer<typeof GeoMapViewportSchema>;
type GeoMapStyle (line 170) | type GeoMapStyle = CSSProperties &
type GeoMapClientProps (line 173) | type GeoMapClientProps = {
type GeoMapProps (line 182) | type GeoMapProps = z.infer<typeof GeoMapPropsSchema> & GeoMapClientProps;
type SerializableGeoMap (line 186) | type SerializableGeoMap = z.infer<typeof SerializableGeoMapSchema>;
FILE: apps/www/components/tool-ui/image-gallery/context.tsx
constant VIEW_TRANSITION_NAME (line 14) | const VIEW_TRANSITION_NAME = "active-gallery-image";
type ImageGalleryContextValue (line 16) | interface ImageGalleryContextValue {
function useImageGallery (line 30) | function useImageGallery(): ImageGalleryContextValue {
function supportsViewTransitions (line 38) | function supportsViewTransitions(): boolean {
function withViewTransition (line 47) | function withViewTransition(
type ImageGalleryProviderProps (line 68) | interface ImageGalleryProviderProps {
function ImageGalleryProvider (line 73) | function ImageGalleryProvider({
FILE: apps/www/components/tool-ui/image-gallery/gallery-grid.tsx
type GridImage (line 8) | type GridImage = Pick<
type GalleryGridProps (line 13) | interface GalleryGridProps {
function GalleryGrid (line 17) | function GalleryGrid({ onImageClick }: GalleryGridProps) {
type GridImageCardProps (line 48) | interface GridImageCardProps {
function GridImageCard (line 54) | function GridImageCard({ image, index, onClick }: GridImageCardProps) {
function isPortraitImage (line 117) | function isPortraitImage(image: GridImage): boolean {
function ImageErrorState (line 124) | function ImageErrorState({ alt }: { alt: string }) {
FILE: apps/www/components/tool-ui/image-gallery/gallery-lightbox.tsx
type LightboxImage (line 9) | type LightboxImage = Pick<ImageGalleryItem, "title" | "caption" | "sourc...
function GalleryLightbox (line 11) | function GalleryLightbox() {
function CloseButton (line 81) | function CloseButton({ onClose }: { onClose: () => void }) {
function Metadata (line 98) | function Metadata({ image }: { image: LightboxImage }) {
function SourceLink (line 126) | function SourceLink({
FILE: apps/www/components/tool-ui/image-gallery/image-gallery.tsx
function ImageGallery (line 10) | function ImageGallery({
type HeaderProps (line 51) | interface HeaderProps {
function Header (line 56) | function Header({ title, description }: HeaderProps) {
FILE: apps/www/components/tool-ui/image-gallery/schema.ts
type ImageGallerySource (line 14) | type ImageGallerySource = z.infer<typeof ImageGallerySourceSchema>;
type ImageGalleryItem (line 27) | type ImageGalleryItem = z.infer<typeof ImageGalleryItemSchema>;
type SerializableImageGallery (line 38) | type SerializableImageGallery = z.infer<
type ImageGalleryProps (line 42) | interface ImageGalleryProps extends SerializableImageGallery {
FILE: apps/www/components/tool-ui/image/image.tsx
constant FALLBACK_LOCALE (line 15) | const FALLBACK_LOCALE = "en-US";
type ImageProps (line 17) | interface ImageProps extends SerializableImage {
function Image (line 22) | function Image(props: ImageProps) {
type SourceAttributionProps (line 141) | interface SourceAttributionProps {
function SourceAttribution (line 150) | function SourceAttribution({
FILE: apps/www/components/tool-ui/image/schema.ts
type Source (line 17) | type Source = z.infer<typeof SourceSchema>;
type SerializableImage (line 38) | type SerializableImage = z.infer<typeof SerializableImageSchema>;
FILE: apps/www/components/tool-ui/instagram-post/instagram-post.tsx
type InstagramPostProps (line 17) | interface InstagramPostProps {
function InstagramLogo (line 23) | function InstagramLogo({ className }: { className?: string }) {
function Header (line 80) | function Header({
function MediaGrid (line 118) | function MediaGrid({
function PostBody (line 196) | function PostBody({ text }: { text?: string }) {
function ActionButton (line 205) | function ActionButton({
function PostActions (line 241) | function PostActions({
function InstagramPost (line 270) | function InstagramPost({
FILE: apps/www/components/tool-ui/instagram-post/schema.ts
type InstagramPostData (line 22) | interface InstagramPostData {
type InstagramPostAuthor (line 41) | type InstagramPostAuthor = z.infer<typeof InstagramPostAuthorSchema>;
type InstagramPostMedia (line 42) | type InstagramPostMedia = z.infer<typeof InstagramPostMediaSchema>;
type InstagramPostStats (line 43) | type InstagramPostStats = z.infer<typeof InstagramPostStatsSchema>;
FILE: apps/www/components/tool-ui/item-carousel/item-card.tsx
type ItemCardProps (line 6) | interface ItemCardProps {
function ItemCard (line 12) | function ItemCard({ item, onItemClick, onItemAction }: ItemCardProps) {
FILE: apps/www/components/tool-ui/item-carousel/item-carousel.tsx
constant SCROLL_PADDING_STYLE (line 9) | const SCROLL_PADDING_STYLE = { scrollPaddingInline: "1rem" };
constant SCROLL_EDGE_THRESHOLD_PX (line 11) | const SCROLL_EDGE_THRESHOLD_PX = 8;
constant SNAP_EPSILON_PX (line 12) | const SNAP_EPSILON_PX = 5;
constant SCROLL_ANIMATION_DURATION_MS (line 13) | const SCROLL_ANIMATION_DURATION_MS = 300;
constant PAGE_SCROLL_RATIO (line 14) | const PAGE_SCROLL_RATIO = 0.8;
constant PAGE_SCROLL_BREAKPOINT_PX (line 15) | const PAGE_SCROLL_BREAKPOINT_PX = 640;
type ScrollDirection (line 17) | type ScrollDirection = "left" | "right";
type ScrollAnimationState (line 19) | interface ScrollAnimationState {
function useSmoothScroll (line 27) | function useSmoothScroll() {
function useScrollEdgeState (line 104) | function useScrollEdgeState(
function CarouselNavButton (line 155) | function CarouselNavButton({
type ItemCarouselHeaderProps (line 191) | interface ItemCarouselHeaderProps {
function ItemCarouselHeader (line 196) | function ItemCarouselHeader({ title, description }: ItemCarouselHeaderPr...
type EmptyStateProps (line 215) | interface EmptyStateProps {
function EmptyState (line 220) | function EmptyState({ id, className }: EmptyStateProps) {
function ItemCarouselRoot (line 232) | function ItemCarouselRoot({
type ItemCarouselComponent (line 390) | type ItemCarouselComponent = typeof ItemCarouselRoot & {
FILE: apps/www/components/tool-ui/item-carousel/schema.ts
type Item (line 26) | type Item = z.infer<typeof ItemSchema>;
type ItemCarouselProps (line 28) | type ItemCarouselProps = z.infer<typeof ItemCarouselPropsSchema> & {
type SerializableItem (line 60) | type SerializableItem = z.infer<typeof SerializableItemSchema>;
type SerializableItemCarousel (line 61) | type SerializableItemCarousel = z.infer<
FILE: apps/www/components/tool-ui/link-preview/link-preview.tsx
constant FALLBACK_LOCALE (line 14) | const FALLBACK_LOCALE = "en-US";
constant CONTENT_SPACING (line 15) | const CONTENT_SPACING = "px-5 py-4 gap-2";
type LinkPreviewProps (line 17) | interface LinkPreviewProps extends SerializableLinkPreview {
function LinkPreview (line 22) | function LinkPreview(props: LinkPreviewProps) {
FILE: apps/www/components/tool-ui/link-preview/schema.ts
type SerializableLinkPreview (line 27) | type SerializableLinkPreview = z.infer<
FILE: apps/www/components/tool-ui/linkedin-post/linkedin-post.tsx
constant TEXT_PREVIEW_LENGTH (line 22) | const TEXT_PREVIEW_LENGTH = 280;
type LinkedInPostProps (line 24) | interface LinkedInPostProps {
function LinkedInLogo (line 30) | function LinkedInLogo({ className }: { className?: string }) {
function Header (line 52) | function Header({
function PostBody (line 88) | function PostBody({ text }: { text?: string }) {
function PostMedia (line 114) | function PostMedia({ media }: { media: LinkedInPostMedia }) {
function PostLinkPreview (line 138) | function PostLinkPreview({ preview }: { preview: LinkedInPostLinkPreview...
function ActionButton (line 182) | function ActionButton({
function PostActions (line 230) | function PostActions({
function LinkedInPost (line 259) | function LinkedInPost({ post, className, onAction }: LinkedInPostProps) {
FILE: apps/www/components/tool-ui/linkedin-post/schema.ts
type LinkedInPostData (line 39) | type LinkedInPostData = z.infer<typeof SerializableLinkedInPostSchema>;
type LinkedInPostAuthor (line 41) | type LinkedInPostAuthor = z.infer<typeof LinkedInPostAuthorSchema>;
type LinkedInPostMedia (line 42) | type LinkedInPostMedia = z.infer<typeof LinkedInPostMediaSchema>;
type LinkedInPostLinkPreview (line 43) | type LinkedInPostLinkPreview = z.infer<
type LinkedInPostStats (line 46) | type LinkedInPostStats = z.infer<typeof LinkedInPostStatsSchema>;
FILE: apps/www/components/tool-ui/message-draft/message-draft.tsx
type DraftState (line 14) | type DraftState = "review" | "sending" | "sent" | "cancelled";
type DraftOutcome (line 15) | type DraftOutcome = MessageDraftProps["outcome"];
constant DEFAULT_GRACE_PERIOD (line 17) | const DEFAULT_GRACE_PERIOD = 5000;
constant COLLAPSED_BODY_HEIGHT (line 18) | const COLLAPSED_BODY_HEIGHT = 280;
type RecipientRowProps (line 20) | interface RecipientRowProps {
function RecipientRow (line 27) | function RecipientRow({
type SingleFieldRowProps (line 51) | interface SingleFieldRowProps {
function SingleFieldRow (line 56) | function SingleFieldRow({ label, value }: SingleFieldRowProps) {
type ExpandableBodyProps (line 67) | interface ExpandableBodyProps {
function ExpandableBody (line 73) | function ExpandableBody({
type EmailDraftContentProps (line 123) | interface EmailDraftContentProps {
function EmailDraftContent (line 130) | function EmailDraftContent({
type SlackDraftContentProps (line 166) | interface SlackDraftContentProps {
function SlackLogo (line 173) | function SlackLogo({ className }: { className?: string }) {
function SlackDraftContent (line 196) | function SlackDraftContent({
function formatSentTime (line 235) | function formatSentTime(date: Date): string {
function resolveStateFromOutcome (line 242) | function resolveStateFromOutcome(outcome: DraftOutcome): DraftState {
function resolveOutcomeTransition (line 248) | function resolveOutcomeTransition(
type SentConfirmationProps (line 259) | interface SentConfirmationProps {
function SentConfirmation (line 263) | function SentConfirmation({ sentAt }: SentConfirmationProps) {
function MessageDraft (line 280) | function MessageDraft(props: MessageDraftProps) {
FILE: apps/www/components/tool-ui/message-draft/schema.ts
type MessageDraftChannel (line 7) | type MessageDraftChannel = z.infer<typeof MessageDraftChannelSchema>;
type MessageDraftOutcome (line 11) | type MessageDraftOutcome = z.infer<typeof MessageDraftOutcomeSchema>;
type SlackTarget (line 22) | type SlackTarget = z.infer<typeof SlackTargetSchema>;
type SerializableMessageDraft (line 51) | type SerializableMessageDraft = z.infer<
type SerializableEmailDraft (line 55) | type SerializableEmailDraft = z.infer<
type SerializableSlackDraft (line 59) | type SerializableSlackDraft = z.infer<
type MessageDraftProps (line 77) | type MessageDraftProps = SerializableMessageDraft & {
FILE: apps/www/components/tool-ui/option-list/option-list.tsx
function convertIdSetToSelection (line 27) | function convertIdSetToSelection(
function areSetsEqual (line 38) | function areSetsEqual(a: Set<string>, b: Set<string>) {
type SelectionIndicatorProps (line 46) | interface SelectionIndicatorProps {
function SelectionIndicator (line 52) | function SelectionIndicator({
type OptionItemProps (line 77) | interface OptionItemProps {
function OptionItem (line 90) | function OptionItem({
type OptionListConfirmationProps (line 152) | interface OptionListConfirmationProps {
function OptionListConfirmation (line 159) | function OptionListConfirmation({
function OptionList (line 216) | function OptionList({
FILE: apps/www/components/tool-ui/option-list/schema.ts
type OptionListSelection (line 23) | type OptionListSelection = string[] | string | null;
type OptionListSchemaInvariantInput (line 29) | type OptionListSchemaInvariantInput = {
function selectionToIds (line 38) | function selectionToIds(selection: OptionListSelection | undefined): str...
function validateOptionListInvariants (line 44) | function validateOptionListInvariants(
type OptionListOption (line 159) | type OptionListOption = z.infer<typeof OptionListOptionSchema>;
type OptionListProps (line 161) | type OptionListProps = Omit<
type SerializableOptionList (line 194) | type SerializableOptionList = z.infer<
FILE: apps/www/components/tool-ui/option-list/selection.ts
function parseSelectionToIdSet (line 3) | function parseSelectionToIdSet(
function normalizeSelectionForOptions (line 24) | function normalizeSelectionForOptions(
FILE: apps/www/components/tool-ui/order-summary/order-summary.tsx
function formatCurrency (line 12) | function formatCurrency(amount: number, currency: string): string {
function formatQuantity (line 23) | function formatQuantity(quantity: number): string {
function ItemImage (line 27) | function ItemImage({ src, alt }: { src?: string; alt: string }) {
function OrderItemRow (line 51) | function OrderItemRow({
function PricingBreakdown (line 85) | function PricingBreakdown({
function formatDate (line 142) | function formatDate(isoString: string): string | undefined {
function ReceiptBadge (line 156) | function ReceiptBadge({
function OrderSummaryRoot (line 173) | function OrderSummaryRoot({
type OrderSummaryDisplayProps (line 267) | type OrderSummaryDisplayProps = OrderSummaryProps;
function OrderSummaryDisplay (line 269) | function OrderSummaryDisplay(props: OrderSummaryDisplayProps) {
type OrderSummaryReceiptProps (line 273) | interface OrderSummaryReceiptProps extends Omit<
function OrderSummaryReceipt (line 280) | function OrderSummaryReceipt(props: OrderSummaryReceiptProps) {
type OrderSummaryCompoundComponent (line 284) | interface OrderSummaryCompoundComponent {
FILE: apps/www/components/tool-ui/order-summary/schema.ts
type OrderItem (line 14) | type OrderItem = z.infer<typeof OrderItemSchema>;
type Pricing (line 46) | type Pricing = z.infer<typeof PricingSchema>;
type OrderSummaryVariant (line 49) | type OrderSummaryVariant = z.infer<typeof OrderSummaryVariantSchema>;
type OrderDecision (line 57) | type OrderDecision = z.infer<typeof OrderDecisionSchema>;
type SerializableOrderSummary (line 88) | type SerializableOrderSummary = z.infer<
type OrderSummaryProps (line 106) | interface OrderSummaryProps extends SerializableOrderSummary {
FILE: apps/www/components/tool-ui/parameter-slider/math.ts
type SliderPercentInput (line 3) | type SliderPercentInput = {
function clampPercent (line 9) | function clampPercent(value: number): number {
function sliderRangeToPercent (line 14) | function sliderRangeToPercent({
function createSliderValueSnapshot (line 24) | function createSliderValueSnapshot(
function createSliderSignature (line 30) | function createSliderSignature(sliders: SliderConfig[]): string {
FILE: apps/www/components/tool-ui/parameter-slider/parameter-slider.tsx
function formatSignedValue (line 25) | function formatSignedValue(
function getAriaValueText (line 39) | function getAriaValueText(
constant TICK_COUNT (line 58) | const TICK_COUNT = 16;
constant TEXT_PADDING_X (line 59) | const TEXT_PADDING_X = 4;
constant TEXT_PADDING_X_OUTER (line 60) | const TEXT_PADDING_X_OUTER = 0;
constant TEXT_PADDING_Y (line 61) | const TEXT_PADDING_Y = 2;
constant DETECTION_MARGIN_X (line 62) | const DETECTION_MARGIN_X = 12;
constant DETECTION_MARGIN_X_OUTER (line 63) | const DETECTION_MARGIN_X_OUTER = 4;
constant DETECTION_MARGIN_Y (line 64) | const DETECTION_MARGIN_Y = 12;
constant TRACK_HEIGHT (line 65) | const TRACK_HEIGHT = 48;
constant TEXT_RELEASE_INSET (line 66) | const TEXT_RELEASE_INSET = 8;
constant TRACK_EDGE_INSET (line 67) | const TRACK_EDGE_INSET = 4;
constant THUMB_WIDTH (line 68) | const THUMB_WIDTH = 12;
constant TEXT_VERTICAL_OFFSET (line 71) | const TEXT_VERTICAL_OFFSET = 0.5;
function clampPercent (line 73) | function clampPercent(value: number): number {
function toInsetPosition (line 80) | function toInsetPosition(percent: number): string {
function getRadixThumbInBoundsOffsetPx (line 87) | function getRadixThumbInBoundsOffsetPx(percent: number): number {
function toRadixThumbPosition (line 93) | function toRadixThumbPosition(percent: number): string {
function signedDistanceToRoundedRect (line 99) | function signedDistanceToRoundedRect(
constant OUTER_EDGE_RADIUS_FACTOR (line 136) | const OUTER_EDGE_RADIUS_FACTOR = 0.3;
function calculateGap (line 138) | function calculateGap(
type SliderRowProps (line 223) | interface SliderRowProps {
function SliderRow (line 232) | function SliderRow({
function ParameterSlider (line 694) | function ParameterSlider({
FILE: apps/www/components/tool-ui/parameter-slider/schema.ts
type SliderConfig (line 45) | type SliderConfig = z.infer<typeof SliderConfigSchema>;
type SerializableParameterSlider (line 77) | type SerializableParameterSlider = z.infer<
type SliderValue (line 96) | interface SliderValue {
type ParameterSliderProps (line 101) | interface ParameterSliderProps extends Omit<
FILE: apps/www/components/tool-ui/plan/plan.tsx
constant INITIAL_VISIBLE_TODO_COUNT (line 24) | const INITIAL_VISIBLE_TODO_COUNT = 4;
type PlanTodoItemProps (line 82) | interface PlanTodoItemProps {
function areTodoPropsEqual (line 89) | function areTodoPropsEqual(
type TodoListProps (line 205) | interface TodoListProps {
function TodoList (line 210) | function TodoList({ todos, newTodoIds }: TodoListProps) {
type ProgressBarProps (line 241) | interface ProgressBarProps {
function PlanRoot (line 283) | function PlanRoot({
function PlanComponent (line 414) | function PlanComponent(props: PlanProps) {
function PlanCompact (line 418) | function PlanCompact(props: PlanProps) {
type PlanComponentType (line 422) | type PlanComponentType = typeof PlanComponent & {
FILE: apps/www/components/tool-ui/plan/progress.ts
type ProgressInput (line 1) | type ProgressInput = {
type CelebrateProgressInput (line 6) | type CelebrateProgressInput = {
function clampProgress (line 11) | function clampProgress(value: number): number {
function calculatePlanProgress (line 16) | function calculatePlanProgress({
function shouldCelebrateProgress (line 24) | function shouldCelebrateProgress({
FILE: apps/www/components/tool-ui/plan/schema.ts
type PlanTodoStatus (line 23) | type PlanTodoStatus = z.infer<typeof PlanTodoStatusSchema>;
type PlanTodo (line 24) | type PlanTodo = z.infer<typeof PlanTodoSchema>;
type PlanProps (line 51) | type PlanProps = z.infer<typeof PlanPropsSchema> & {
type SerializablePlan (line 57) | type SerializablePlan = z.infer<typeof SerializablePlanSchema>;
FILE: apps/www/components/tool-ui/preferences-panel/preferences-panel.tsx
function getInitialValue (line 33) | function getInitialValue(item: PreferenceItem): string | boolean {
function formatDisplayValue (line 44) | function formatDisplayValue(
function computeInitialValues (line 59) | function computeInitialValues(sections: PreferenceSection[]): Preference...
type PreferenceControlProps (line 68) | interface PreferenceControlProps {
function SwitchControl (line 75) | function SwitchControl({
function ToggleControl (line 99) | function ToggleControl({
function SelectControl (line 135) | function SelectControl({
function PreferenceControl (line 166) | function PreferenceControl({
type PreferenceItemRowProps (line 216) | interface PreferenceItemRowProps {
function ItemLabel (line 227) | function ItemLabel({
function ItemValue (line 271) | function ItemValue({
function PreferenceItemRow (line 298) | function PreferenceItemRow({
type ItemListProps (line 344) | interface ItemListProps {
function ItemList (line 356) | function ItemList({
type PreferencesSectionProps (line 400) | interface PreferencesSectionProps {
function PreferencesSection (line 410) | function PreferencesSection({
type ReceiptHeaderProps (line 449) | interface ReceiptHeaderProps {
function ReceiptHeader (line 454) | function ReceiptHeader({ title, hasErrors }: ReceiptHeaderProps) {
function PreferencesPanelReceipt (line 476) | function PreferencesPanelReceipt({
function PreferencesPanelRoot (line 522) | function PreferencesPanelRoot({
type PreferencesPanelComponent (line 675) | type PreferencesPanelComponent = typeof PreferencesPanelRoot & {
FILE: apps/www/components/tool-ui/preferences-panel/schema.ts
type SerializablePreferencesPanel (line 85) | type SerializablePreferencesPanel = z.infer<
type SerializablePreferencesPanelReceipt (line 89) | type SerializablePreferencesPanelReceipt = z.infer<
type PreferencesValue (line 123) | interface PreferencesValue {
type PreferencesPanelProps (line 127) | interface PreferencesPanelProps extends Omit<
type PreferencesPanelReceiptProps (line 139) | interface PreferencesPanelReceiptProps extends SerializablePreferencesPa...
type PreferenceItem (line 143) | type PreferenceItem = z.infer<typeof PreferenceItemSchema>;
type PreferenceSection (line 144) | type PreferenceSection = z.infer<typeof PreferenceSectionSchema>;
FILE: apps/www/components/tool-ui/preferences-panel/signature.ts
function createPreferencesSectionSignature (line 3) | function createPreferencesSectionSignature(
FILE: apps/www/components/tool-ui/progress-tracker/progress-tracker.tsx
function formatElapsedTime (line 10) | function formatElapsedTime(milliseconds: number): string {
function formatElapsedTimeDateTime (line 23) | function formatElapsedTimeDateTime(milliseconds: number): string {
function getCurrentStepId (line 46) | function getCurrentStepId(steps: ProgressStep[]): string | null {
function getReceiptState (line 59) | function getReceiptState(outcome: ProgressTrackerChoice["outcome"]): {
type StepIndicatorProps (line 87) | interface StepIndicatorProps {
function StepIndicator (line 91) | function StepIndicator({ status }: StepIndicatorProps) {
function ElapsedTimeBadge (line 143) | function ElapsedTimeBadge({ elapsedTime }: { elapsedTime?: number }) {
type ProgressTrackerBaseProps (line 158) | interface ProgressTrackerBaseProps {
function ProgressTrackerReceipt (line 165) | function ProgressTrackerReceipt({
function ProgressTrackerLive (line 239) | function ProgressTrackerLive({
function ProgressTrackerRoot (line 342) | function ProgressTrackerRoot({
type ProgressTrackerComponent (line 373) | type ProgressTrackerComponent = typeof ProgressTrackerRoot & {
FILE: apps/www/components/tool-ui/progress-tracker/schema.ts
type ProgressTrackerChoice (line 12) | type ProgressTrackerChoice = ToolUIReceipt;
type ProgressStep (line 21) | type ProgressStep = z.infer<typeof ProgressStepSchema>;
type SerializableProgressTracker (line 55) | type SerializableProgressTracker = z.infer<
type ProgressTrackerProps (line 74) | interface ProgressTrackerProps extends SerializableProgressTracker {
FILE: apps/www/components/tool-ui/question-flow/question-flow.tsx
type SelectionIndicatorProps (line 22) | interface SelectionIndicatorProps {
type ProgressBarProps (line 28) | interface ProgressBarProps {
function ProgressBar (line 33) | function ProgressBar({ current, total }: ProgressBarProps) {
function SelectionIndicator (line 60) | function SelectionIndicator({
type OptionItemProps (line 94) | interface OptionItemProps {
function OptionItem (line 107) | function OptionItem({
function QuestionFlowReceipt (line 169) | function QuestionFlowReceipt({
type StepBodyData (line 219) | interface StepBodyData {
function getQuestionFlowStepIds (line 228) | function getQuestionFlowStepIds(id: string, stepKey: string) {
type StepContentProps (line 237) | interface StepContentProps {
function StepBodyContent (line 257) | function StepBodyContent({
function StepContent (line 449) | function StepContent({
function QuestionFlowProgressive (line 573) | function QuestionFlowProgressive({
function QuestionFlowUpfront (line 638) | function QuestionFlowUpfront({
function QuestionFlow (line 781) | function QuestionFlow(props: QuestionFlowProps) {
FILE: apps/www/components/tool-ui/question-flow/schema.ts
type QuestionFlowOption (line 14) | type QuestionFlowOption = z.infer<typeof QuestionFlowOptionSchema>;
type QuestionFlowStepDefinition (line 24) | type QuestionFlowStepDefinition = z.infer<
type QuestionFlowSummaryItem (line 33) | type QuestionFlowSummaryItem = z.infer<
type QuestionFlowChoice (line 42) | type QuestionFlowChoice = z.infer<typeof QuestionFlowChoiceSchema>;
type SerializableProgressiveMode (line 57) | type SerializableProgressiveMode = z.infer<
type SerializableUpfrontMode (line 65) | type SerializableUpfrontMode = z.infer<
type SerializableReceiptMode (line 73) | type SerializableReceiptMode = z.infer<
type SerializableQuestionFlow (line 83) | type SerializableQuestionFlow = z.infer<
type BaseRuntimeProps (line 100) | interface BaseRuntimeProps {
type QuestionFlowProgressiveProps (line 104) | interface QuestionFlowProgressiveProps
type QuestionFlowUpfrontProps (line 114) | interface QuestionFlowUpfrontProps
type QuestionFlowReceiptProps (line 122) | interface QuestionFlowReceiptProps
type QuestionFlowProps (line 128) | type QuestionFlowProps =
FILE: apps/www/components/tool-ui/shared/action-buttons.tsx
type ActionButtonsProps (line 7) | interface ActionButtonsProps {
function ActionButtons (line 16) | function ActionButtons({
FILE: apps/www/components/tool-ui/shared/actions-config.ts
type ActionsProp (line 3) | type ActionsProp = ActionsConfig | Action[];
constant NEGATORY_ACTION_IDS (line 5) | const NEGATORY_ACTION_IDS = new Set([
function inferVariant (line 20) | function inferVariant(action: Action): Action {
function normalizeActionsConfig (line 28) | function normalizeActionsConfig(
FILE: apps/www/components/tool-ui/shared/contract.ts
type ToolUiContract (line 4) | interface ToolUiContract<T> {
function defineToolUiContract (line 10) | function defineToolUiContract<T>(
FILE: apps/www/components/tool-ui/shared/decision-actions.tsx
type DecisionActionsProps (line 13) | interface DecisionActionsProps<
function DecisionActions (line 30) | function DecisionActions<
FILE: apps/www/components/tool-ui/shared/embedded-actions.ts
type EmbeddedActionHandler (line 3) | type EmbeddedActionHandler<TState> = (
type EmbeddedBeforeActionHandler (line 8) | type EmbeddedBeforeActionHandler<TState> = (
type EmbeddedActionsProps (line 13) | interface EmbeddedActionsProps<TState> {
FILE: apps/www/components/tool-ui/shared/local-actions.tsx
type LocalActionsProps (line 8) | interface LocalActionsProps {
function LocalActions (line 19) | function LocalActions({
FILE: apps/www/components/tool-ui/shared/media/aspect-ratio.ts
type AspectRatio (line 7) | type AspectRatio = z.infer<typeof AspectRatioSchema>;
type MediaFit (line 11) | type MediaFit = z.infer<typeof MediaFitSchema>;
constant RATIO_CLASS_MAP (line 13) | const RATIO_CLASS_MAP: Record<AspectRatio, string> = {
function getRatioClass (line 21) | function getRatioClass(ratio: AspectRatio): string {
function getFitClass (line 25) | function getFitClass(fit: MediaFit): string {
FILE: apps/www/components/tool-ui/shared/media/format-utils.ts
function formatDuration (line 6) | function formatDuration(durationMs: number): string {
function formatFileSize (line 25) | function formatFileSize(bytes: number): string {
FILE: apps/www/components/tool-ui/shared/media/overlay-gradient.ts
constant OVERLAY_GRADIENT (line 7) | const OVERLAY_GRADIENT = `linear-gradient(
FILE: apps/www/components/tool-ui/shared/media/safe-navigation.ts
function resolveSafeNavigationHref (line 3) | function resolveSafeNavigationHref(
function openSafeNavigationHref (line 16) | function openSafeNavigationHref(href: string | undefined): boolean {
FILE: apps/www/components/tool-ui/shared/media/sanitize-href.ts
function sanitizeHref (line 9) | function sanitizeHref(href?: string): string | undefined {
FILE: apps/www/components/tool-ui/shared/parse.ts
function formatZodPath (line 3) | function formatZodPath(path: Array<string | number | symbol>): string {
function formatZodError (line 15) | function formatZodError(error: z.ZodError): string {
function parseWithSchema (line 27) | function parseWithSchema<T>(
function safeParseWithSchema (line 45) | function safeParseWithSchema<T>(
FILE: apps/www/components/tool-ui/shared/schema.ts
type ToolUIId (line 27) | type ToolUIId = z.infer<typeof ToolUIIdSchema>;
type ToolUIRole (line 40) | type ToolUIRole = z.infer<typeof ToolUIRoleSchema>;
type ToolUIReceiptOutcome (line 49) | type ToolUIReceiptOutcome = z.infer<typeof ToolUIReceiptOutcomeSchema>;
type ToolUIReceipt (line 61) | type ToolUIReceipt = z.infer<typeof ToolUIReceiptSchema>;
type ToolUISurface (line 72) | type ToolUISurface = z.infer<typeof ToolUISurfaceSchema>;
type Action (line 93) | type Action = z.infer<typeof ActionSchema>;
type LocalAction (line 94) | type LocalAction = Action;
type DecisionAction (line 95) | type DecisionAction = Action;
type DecisionResult (line 107) | type DecisionResult<
function createDecisionResult (line 113) | function createDecisionResult<
type ActionsConfig (line 143) | interface ActionsConfig {
type SerializableActionsConfig (line 155) | type SerializableActionsConfig = z.infer<
type SerializableAction (line 159) | type SerializableAction = z.infer<typeof SerializableActionSchema>;
FILE: apps/www/components/tool-ui/shared/tool-ui-context.tsx
type ToolUIContextValue (line 5) | interface ToolUIContextValue {
function useOptionalToolUI (line 13) | function useOptionalToolUI(): ToolUIContextValue | null {
function useToolUI (line 17) | function useToolUI(): ToolUIContextValue {
FILE: apps/www/components/tool-ui/shared/tool-ui.tsx
type ToolUIProps (line 9) | interface ToolUIProps {
function ToolUIRoot (line 15) | function ToolUIRoot({ id, children, className }: ToolUIProps) {
type ToolUISurfaceProps (line 36) | interface ToolUISurfaceProps {
function ToolUISurface (line 40) | function ToolUISurface({ children }: ToolUISurfaceProps) {
type ToolUIActionsProps (line 51) | interface ToolUIActionsProps {
function ToolUIActions (line 57) | function ToolUIActions({ children, className, ariaLabel }: ToolUIActions...
type ToolUIComponent (line 77) | type ToolUIComponent = typeof ToolUIRoot & {
FILE: apps/www/components/tool-ui/shared/toolkit.tsx
type ToolUiToolkitRenderContext (line 3) | type ToolUiToolkitRenderContext = {
function createResultToolRenderer (line 11) | function createResultToolRenderer<T>(options: {
FILE: apps/www/components/tool-ui/shared/use-action-buttons.tsx
type UseActionButtonsOptions (line 6) | type UseActionButtonsOptions = {
type UseActionButtonsResult (line 13) | type UseActionButtonsResult = {
type ActionExecutionLock (line 28) | type ActionExecutionLock = {
function createActionExecutionLock (line 33) | function createActionExecutionLock(): ActionExecutionLock {
function useActionButtons (line 48) | function useActionButtons(
FILE: apps/www/components/tool-ui/shared/use-controllable-state.ts
type UseControllableStateOptions (line 5) | type UseControllableStateOptions<T> = {
function useControllableState (line 11) | function useControllableState<T>({
FILE: apps/www/components/tool-ui/shared/use-copy-to-clipboard.ts
function fallbackCopyToClipboard (line 5) | function fallbackCopyToClipboard(text: string): boolean {
function useCopyToClipboard (line 25) | function useCopyToClipboard(options?: { resetAfterMs?: number }): {
FILE: apps/www/components/tool-ui/shared/use-signature-reset.ts
function useSignatureReset (line 5) | function useSignatureReset(
FILE: apps/www/components/tool-ui/shared/utils.ts
function formatRelativeTime (line 1) | function formatRelativeTime(iso: string): string {
function formatCount (line 10) | function formatCount(count: number): string {
function getDomain (line 16) | function getDomain(url: string): string {
function prefersReducedMotion (line 24) | function prefersReducedMotion(): boolean {
FILE: apps/www/components/tool-ui/stats-display/schema.ts
type StatFormat (line 34) | type StatFormat = z.infer<typeof StatFormatSchema>;
type StatDiff (line 43) | type StatDiff = z.infer<typeof StatDiffSchema>;
type StatSparkline (line 50) | type StatSparkline = z.infer<typeof StatSparklineSchema>;
type StatItem (line 61) | type StatItem = z.infer<typeof StatItemSchema>;
type SerializableStatsDisplay (line 71) | type SerializableStatsDisplay = z.infer<
type StatsDisplayProps (line 88) | interface StatsDisplayProps extends SerializableStatsDisplay {
FILE: apps/www/components/tool-ui/stats-display/sparkline.tsx
type SparklineProps (line 7) | interface SparklineProps {
function Sparkline (line 18) | function Sparkline({
FILE: apps/www/components/tool-ui/stats-display/stats-display.tsx
type FormattedValueProps (line 18) | interface FormattedValueProps {
function FormattedValue (line 24) | function FormattedValue({ value, format, locale }: FormattedValueProps) {
type DeltaValueProps (line 108) | interface DeltaValueProps {
function DeltaValue (line 112) | function DeltaValue({ diff }: DeltaValueProps) {
type StatCardProps (line 156) | interface StatCardProps {
function StatCard (line 163) | function StatCard({
function StatsDisplay (line 218) | function StatsDisplay({
FILE: apps/www/components/tool-ui/terminal/schema.ts
type TerminalProps (line 24) | type TerminalProps = z.infer<typeof TerminalPropsSchema>;
type SerializableTerminal (line 30) | type SerializableTerminal = z.infer<typeof SerializableTerminalSchema>;
FILE: apps/www/components/tool-ui/terminal/terminal.tsx
constant COPY_ID (line 18) | const COPY_ID = "terminal-output";
type TerminalControlledProps (line 20) | type TerminalControlledProps = {
type TerminalRootProps (line 26) | type TerminalRootProps = TerminalProps & TerminalControlledProps;
type TerminalHeaderProps (line 28) | type TerminalHeaderProps = Pick<
type TerminalOutputProps (line 38) | type TerminalOutputProps = Pick<
function formatDuration (line 48) | function formatDuration(durationMs?: number): string | null {
function countOutputLines (line 54) | function countOutputLines(output: string): number {
function TerminalHeader (line 60) | function TerminalHeader({
function TerminalOutput (line 119) | function TerminalOutput({
function TerminalEmpty (line 184) | function TerminalEmpty() {
function TerminalRoot (line 192) | function TerminalRoot({
type TerminalComponent (line 273) | type TerminalComponent = typeof TerminalRoot & {
FILE: apps/www/components/tool-ui/video/context.tsx
type VideoPlaybackState (line 5) | interface VideoPlaybackState {
type VideoContextValue (line 10) | interface VideoContextValue {
function useVideo (line 19) | function useVideo() {
type VideoProviderProps (line 27) | interface VideoProviderProps {
function VideoProvider (line 32) | function VideoProvider({ children, defaultState }: VideoProviderProps) {
FILE: apps/www/components/tool-ui/video/schema.ts
type Source (line 17) | type Source = z.infer<typeof SourceSchema>;
type SerializableVideo (line 38) | type SerializableVideo = z.infer<typeof SerializableVideoSchema>;
FILE: apps/www/components/tool-ui/video/video-helpers.ts
type VideoMediaEvent (line 4) | type VideoMediaEvent = "mute" | "unmute";
type ResolvedVideoNavigation (line 6) | interface ResolvedVideoNavigation {
function getMuteMediaEvent (line 12) | function getMuteMediaEvent(
function resolveVideoNavigation (line 23) | function resolveVideoNavigation(
function normalizeVideoDataForCallback (line 37) | function normalizeVideoDataForCallback(
FILE: apps/www/components/tool-ui/video/video.tsx
constant FALLBACK_LOCALE (line 22) | const FALLBACK_LOCALE = "en-US";
type VideoProps (line 24) | interface VideoProps extends SerializableVideo {
function VideoRoot (line 33) | function VideoRoot(props: VideoProps) {
function VideoInner (line 43) | function VideoInner(props: Omit<VideoProps, "defaultMuted">) {
function formatCreatedAt (line 268) | function formatCreatedAt(createdAt: string, locale: string): string {
type VideoComponent (line 277) | type VideoComponent = typeof VideoRoot & {
FILE: apps/www/components/tool-ui/weather-widget/generated/weather-runtime-core.generated.ts
function he (line 6) | function he(e){return j.has(e)?!0:j.size>=Ze?!1:(j.add(e),!0)}
function ae (line 6) | function ae(e){j.delete(e)}
function ge (line 6) | function ge(e,t){return t&&(ae(e),null)}
function pe (line 31) | function pe(e,t,a){if(e.isContextLost())return null;let n=e.createShader...
function B (line 31) | function B(e,t,a){if(e.isContextLost())return null;let n=pe(e,e.VERTEX_S...
function ce (line 31) | function ce(e,t,a){let n=e.createTexture();if(!n)return null;e.bindTextu...
function fe (line 31) | function fe(e,t,a,n){t.width===a&&t.height===n||(e.bindTexture(e.TEXTURE...
function J (line 31) | function J(e,t,a){let n=Math.max(0,Math.min(1,(a-e)/(t-e)));return n*n*(...
function Se (line 31) | function Se(e){let t=e.timeOfDay,a=e.celestialY,n=-.25,s=J(.18,.32,t),c=...
function Z (line 31) | function Z(e,t,a,n,s){e.bindFramebuffer(e.FRAMEBUFFER,a.fbo),e.viewport(...
function K (line 31) | function K(e,t,a,n){e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_...
function ve (line 31) | function ve(e,t,a,n){e.bindFramebuffer(e.FRAMEBUFFER,t.fbo),e.viewport(0...
function be (line 31) | function be({gl:e,program:t,target:a,displayWidth:n,displayHeight:s,time...
function we (line 31) | function we({gl:e,program:t,target:a,sceneTexture:n,displayWidth:s,displ...
function xe (line 31) | function xe({gl:e,program:t,target:a,sceneTexture:n,displayWidth:s,displ...
function Ie (line 31) | function Ie(e,t,a,n,s){if(!e.lightning||!a||!t.enabled)return!1;let l=.8...
function Re (line 31) | function Re({gl:e,program:t,target:a,sceneTexture:n,displayWidth:s,displ...
function ke (line 31) | function ke({gl:e,program:t,target:a,sceneTexture:n,displayWidth:s,displ...
function _e (line 31) | function _e({gl:e,program:t,sceneTexture:a,displayWidth:n,displayHeight:...
function Ce (line 31) | function Ce(e){let t=v(null),a=v(null),n=v(0),s=v(0),c=v(-100),l=v(0),o=...
function M (line 31) | function M(e,t){if(!t)return{...e};let a={...e};for(let n of Object.keys...
function We (line 31) | function We(e){return{layers:M(De,e.layers),celestial:M(Te,e.celestial),...
function Fe (line 31) | function Fe({className:e,dpr:t,layers:a,celestial:n,cloud:s,rain:c,light...
function H (line 31) | function H(e){if(!e)return .5;let t=new Date(e),a=t.getUTCHours(),n=t.ge...
function Qe (line 31) | function Qe(e){if(!e)return .5;let t=new Date(e);t.setUTCHours(0,0,0,0);...
function je (line 31) | function je(e){return e<0}
function et (line 31) | function et(e,t){return e<.35?"dark":e>.45?"light":t??"dark"}
function Oe (line 31) | function Oe(e){let t=e*24;return t<6?-1+t/6:t<12?(t-6)/6:t<18?1-(t-12)/6...
function tt (line 31) | function tt(e,t="clear"){let a=Oe(e),n;a<0?n=.05+(1+a)*.1:n=.15+a*.85;le...
function nt (line 31) | function nt(e=0){return e<=10?e/10*.3:e<=25?.3+(e-10)/15*.4:.7+Math.min(...
function at (line 31) | function at(e){switch(e){case"light":return .3;case"moderate":return .6;...
function st (line 31) | function st(e=10){return e>=10?0:e>=5?(10-e)/5*.3:.3+(5-e)/5*.7}
function te (line 31) | function te(e){return Math.max(0,Math.min(1,e))}
function ee (line 31) | function ee(e,t,a){let n=te((a-e)/(t-e));return n*n*(3-2*n)}
function Me (line 31) | function Me(e){let{conditionCode:t,windSpeed:a,precipitationLevel:n,visi...
function rt (line 31) | function rt(e){let t=Me(e),a=e.timeOfDay??t.celestial?.timeOfDay??H(e.ti...
function lt (line 31) | function lt(e){return{layers:e.layers,celestial:{timeOfDay:e.celestial.t...
function Be (line 31) | function Be(e){return lt(rt(e))}
function q (line 31) | function q(e){let t=(e%1+1)%1,a="noon",n=1/0;for(let s of ut){let c=me[s...
function W (line 31) | function W(e,t){if(!(!e&&!t))return{...e,...t}}
function Ne (line 31) | function Ne(e,t){return{...e,layers:W(e.layers,t.layers),celestial:W(e.c...
function Ye (line 31) | function Ye(e){let t=Be(e),a=e.timeOfDay;typeof a=="number"&&t.celestial...
function ct (line 31) | function ct(){if(typeof window>"u")return"high";let e=window.devicePixel...
function Ve (line 31) | function Ve(e){return e==="low"||e==="medium"||e==="high"?e:ct()}
function Xe (line 31) | function Xe(e){if(typeof window>"u")return;let t=window.devicePixelRatio...
function yt (line 31) | function yt({conditionCode:e,windSpeed:t,precipitationLevel:a,visibility...
function ht (line 31) | function ht({glassStyles:e,blurAmount:t}){if(!!e.backdropFilter)return e...
function vt (line 31) | function vt({width:e,height:t,radius:a,depth:n}){let s=Math.ceil(a/t*15)...
function bt (line 50) | function bt({width:e,height:t,radius:a,depth:n,strength:s,chromaticAberr...
function wt (line 67) | function wt({filterUrl:e,blur:t,brightness:a,saturation:n}){return`blur(...
function xt (line 67) | function xt(){let[e,t]=St(!0);return gt(()=>{let a=CSS.supports("backdro...
function It (line 67) | function It({width:e,height:t,depth:a=Y.depth,radius:n=Y.radius,strength...
function Ue (line 67) | function Ue(e){return(e%1+1)%1}
function Rt (line 67) | function Rt(e){let t=Ue(e),a=q(t);return me[a]}
function kt (line 67) | function kt(e){return((Math.floor(e)%12+12)%12+.5)/12}
function _t (line 67) | function _t(e){let{time:t,updatedAt:a}=e;return typeof t?.timeBucket=="n...
FILE: apps/www/components/tool-ui/weather-widget/schema-runtime.ts
type WeatherConditionCode (line 1) | type WeatherConditionCode =
type TemperatureUnit (line 16) | type TemperatureUnit = "celsius" | "fahrenheit";
type PrecipitationLevel (line 18) | type PrecipitationLevel = "none" | "light" | "moderate" | "heavy";
type TimeBucket (line 20) | type TimeBucket = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11;
type ForecastDay (line 22) | interface ForecastDay {
type WeatherWidgetCurrent (line 29) | interface WeatherWidgetCurrent {
type WeatherWidgetTime (line 39) | interface WeatherWidgetTime {
type WeatherWidgetLocation (line 44) | interface WeatherWidgetLocation {
type WeatherWidgetPayload (line 48) | interface WeatherWidgetPayload {
type EffectQuality (line 61) | type EffectQuality = "low" | "medium" | "high" | "auto";
type EffectSettings (line 63) | interface EffectSettings {
type WeatherWidgetRuntimeProps (line 69) | interface WeatherWidgetRuntimeProps extends WeatherWidgetPayload {
FILE: apps/www/components/tool-ui/weather-widget/weather-data-overlay.tsx
type WeatherTheme (line 33) | type WeatherTheme = "light" | "dark";
function getPeakIntensity (line 35) | function getPeakIntensity(timeOfDay: number): number {
function sineEasedGradient (line 42) | function sineEasedGradient(
type GlassEffectParams (line 78) | interface GlassEffectParams {
type WeatherDataOverlayProps (line 88) | interface WeatherDataOverlayProps {
type GlowState (line 112) | interface GlowState {
function observeCardDimensions (line 118) | function observeCardDimensions(
function WeatherDataOverlay (line 131) | function WeatherDataOverlay({
FILE: apps/www/components/tool-ui/weather-widget/weather-widget-container.tsx
type TimeCheckpoint (line 18) | type TimeCheckpoint = "dawn" | "noon" | "dusk" | "midnight";
function WeatherWidget (line 20) | function WeatherWidget({
FILE: apps/www/components/tool-ui/x-post/schema.ts
type XPostData (line 33) | interface XPostData {
type XPostAuthor (line 54) | type XPostAuthor = z.infer<typeof XPostAuthorSchema>;
type XPostMedia (line 55) | type XPostMedia = z.infer<typeof XPostMediaSchema>;
type XPostLinkPreview (line 56) | type XPostLinkPreview = z.infer<typeof XPostLinkPreviewSchema>;
type XPostStats (line 57) | type XPostStats = z.infer<typeof XPostStatsSchema>;
FILE: apps/www/components/tool-ui/x-post/x-post.tsx
type XPostProps (line 18) | interface XPostProps {
function Avatar (line 24) | function Avatar({ src, alt }: { src: string; alt: string }) {
function XLogo (line 36) | function XLogo({ className }: { className?: string }) {
function VerifiedBadge (line 52) | function VerifiedBadge({ className }: { className?: string }) {
function AuthorInfo (line 68) | function AuthorInfo({
function PostBody (line 98) | function PostBody({ text }: { text?: string }) {
function PostMedia (line 107) | function PostMedia({
function PostLinkPreview (line 147) | function PostLinkPreview({ preview }: { preview: XPostLinkPreview }) {
function QuotedPostCard (line 196) | function QuotedPostCard({ post }: { post: XPostData }) {
function ActionButton (line 235) | function ActionButton({
function PostActions (line 280) | function PostActions({
function XPost (line 310) | function XPost({ post, className, onAction }: XPostProps) {
FILE: apps/www/components/ui/accordion.tsx
function Accordion (line 9) | function Accordion({
function AccordionItem (line 15) | function AccordionItem({
function AccordionTrigger (line 28) | function AccordionTrigger({
function AccordionContent (line 50) | function AccordionContent({
FILE: apps/www/components/ui/alert.tsx
function Alert (line 24) | function Alert({
function AlertTitle (line 39) | function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
function AlertDescription (line 52) | function AlertDescription({
FILE: apps/www/components/ui/avatar.tsx
function Avatar (line 8) | function Avatar({
function AvatarImage (line 24) | function AvatarImage({
function AvatarFallback (line 37) | function AvatarFallback({
FILE: apps/www/components/ui/badge.tsx
function Badge (line 30) | function Badge({
FILE: apps/www/components/ui/button-group.tsx
function ButtonGroup (line 24) | function ButtonGroup({
function ButtonGroupText (line 40) | function ButtonGroupText({
function ButtonGroupSeparator (line 60) | function ButtonGroupSeparator({
FILE: apps/www/components/ui/button.tsx
function Button (line 40) | function Button({
FILE: apps/www/components/ui/card.tsx
function Card (line 5) | function Card({ className, ...props }: React.ComponentProps<"div">) {
function CardHeader (line 18) | function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
function CardTitle (line 31) | function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
function CardDescription (line 41) | function CardDescription({ className, ...props }: React.ComponentProps<"...
function CardAction (line 51) | function CardAction({ className, ...props }: React.ComponentProps<"div">) {
function CardContent (line 64) | function CardContent({ className, ...props }: React.ComponentProps<"div"...
function CardFooter (line 74) | function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
FILE: apps/www/components/ui/chart.tsx
constant THEMES (line 9) | const THEMES = { light: "", dark: ".dark" } as const;
type ChartConfig (line 11) | type ChartConfig = {
type ChartContextProps (line 21) | type ChartContextProps = {
function useChart (line 27) | function useChart() {
function ChartContainer (line 37) | function ChartContainer({
function ChartTooltipContent (line 107) | function ChartTooltipContent({
function ChartLegendContent (line 255) | function ChartLegendContent({
function getPayloadConfigFromPayload (line 312) | function getPayloadConfigFromPayload(
FILE: apps/www/components/ui/code-block.tsx
type CodeBlockProps (line 8) | type CodeBlockProps = {
function CodeBlock (line 13) | function CodeBlock({ children, className, ...props }: CodeBlockProps) {
type CodeBlockCodeProps (line 28) | type CodeBlockCodeProps = {
function CodeBlockCode (line 35) | function CodeBlockCode({
type CodeBlockGroupProps (line 81) | type CodeBlockGroupProps = React.HTMLAttributes<HTMLDivElement>;
function CodeBlockGroup (line 83) | function CodeBlockGroup({
FILE: apps/www/components/ui/collapsible.tsx
function Collapsible (line 6) | function Collapsible({
function CollapsibleTrigger (line 12) | function CollapsibleTrigger({
function CollapsibleContent (line 23) | function CollapsibleContent({
FILE: apps/www/components/ui/dialog.tsx
function Dialog (line 9) | function Dialog({
function DialogTrigger (line 15) | function DialogTrigger({
function DialogPortal (line 21) | function DialogPortal({
function DialogClose (line 27) | function DialogClose({
function DialogOverlay (line 33) | function DialogOverlay({
function DialogContent (line 49) | function DialogContent({
function DialogHeader (line 83) | function DialogHeader({ className, ...props }: React.ComponentProps<"div...
function DialogFooter (line 93) | function DialogFooter({ className, ...props }: React.ComponentProps<"div...
function DialogTitle (line 106) | function DialogTitle({
function DialogDescription (line 119) | function DialogDescription({
FILE: apps/www/components/ui/dropdown-menu.tsx
function DropdownMenu (line 9) | function DropdownMenu({
function DropdownMenuPortal (line 15) | function DropdownMenuPortal({
function DropdownMenuTrigger (line 23) | function DropdownMenuTrigger({
function DropdownMenuContent (line 34) | function DropdownMenuContent({
function DropdownMenuGroup (line 54) | function DropdownMenuGroup({
function DropdownMenuItem (line 62) | function DropdownMenuItem({
function DropdownMenuCheckboxItem (line 85) | function DropdownMenuCheckboxItem({
function DropdownMenuRadioGroup (line 111) | function DropdownMenuRadioGroup({
function DropdownMenuRadioItem (line 122) | function DropdownMenuRadioItem({
function DropdownMenuLabel (line 146) | function DropdownMenuLabel({
function DropdownMenuSeparator (line 166) | function DropdownMenuSeparator({
function DropdownMenuShortcut (line 179) | function DropdownMenuShortcut({
function DropdownMenuSub (line 195) | function DropdownMenuSub({
function DropdownMenuSubTrigger (line 201) | function DropdownMenuSubTrigger({
function DropdownMenuSubContent (line 225) | function DropdownMenuSubContent({
FILE: apps/www/components/ui/input-group.tsx
function InputGroup (line 11) | function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
function InputGroupAddon (line 60) | function InputGroupAddon({
function InputGroupButton (line 100) | function InputGroupButton({
function InputGroupText (line 119) | function InputGroupText({ className, ...props }: React.ComponentProps<"s...
function InputGroupInput (line 131) | function InputGroupInput({
function InputGroupTextarea (line 147) | function InputGroupTextarea({
FILE: apps/www/components/ui/input.tsx
function Input (line 5) | function Input({ className, type, ...props }: React.ComponentProps<"inpu...
FILE: apps/www/components/ui/item.tsx
function ItemGroup (line 8) | function ItemGroup({ className, ...props }: React.ComponentProps<"div">) {
function ItemSeparator (line 19) | function ItemSeparator({
function Item (line 54) | function Item({
function ItemMedia (line 91) | function ItemMedia({
function ItemContent (line 106) | function ItemContent({ className, ...props }: React.ComponentProps<"div"...
function ItemTitle (line 119) | function ItemTitle({ className, ...props }: React.ComponentProps<"div">) {
function ItemDescription (line 132) | function ItemDescription({ className, ...props }: React.ComponentProps<"...
function ItemActions (line 146) | function ItemActions({ className, ...props }: React.ComponentProps<"div"...
function ItemHeader (line 156) | function ItemHeader({ className, ...props }: React.ComponentProps<"div">) {
function ItemFooter (line 169) | function ItemFooter({ className, ...props }: React.ComponentProps<"div">) {
FILE: apps/www/components/ui/label.tsx
function Label (line 8) | function Label({
FILE: apps/www/components/ui/logo.tsx
function LogoMark (line 3) | function LogoMark({
FILE: apps/www/components/ui/popover.tsx
function Popover (line 8) | function Popover({
function PopoverTrigger (line 14) | function PopoverTrigger({
function PopoverAnchor (line 20) | function PopoverAnchor({
function PopoverContent (line 26) | function PopoverContent({
FILE: apps/www/components/ui/radio-group.tsx
function RadioGroup (line 9) | function RadioGroup({
function RadioGroupItem (line 22) | function RadioGroupItem({
FILE: apps/www/components/ui/select.tsx
function Select (line 9) | function Select({
function SelectGroup (line 15) | function SelectGroup({
function SelectValue (line 21) | function SelectValue({
function SelectTrigger (line 27) | function SelectTrigger({
function SelectContent (line 53) | function SelectContent({
function SelectLabel (line 90) | function SelectLabel({
function SelectItem (line 103) | function SelectItem({
function SelectSeparator (line 127) | function SelectSeparator({
function SelectScrollUpButton (line 140) | function SelectScrollUpButton({
function SelectScrollDownButton (line 158) | function SelectScrollDownButton({
FILE: apps/www/components/ui/separator.tsx
function Separator (line 8) | function Separator({
FILE: apps/www/components/ui/sheet.tsx
function Sheet (line 9) | function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive....
function SheetTrigger (line 13) | function SheetTrigger({
function SheetClose (line 19) | function SheetClose({
function SheetPortal (line 25) | function SheetPortal({
function SheetOverlay (line 31) | function SheetOverlay({
function SheetContent (line 47) | function SheetContent({
function SheetHeader (line 84) | function SheetHeader({ className, ...props }: React.ComponentProps<"div"...
function SheetFooter (line 94) | function SheetFooter({ className, ...props }: React.ComponentProps<"div"...
function SheetTitle (line 104) | function SheetTitle({
function SheetDescription (line 117) | function SheetDescription({
FILE: apps/www/components/ui/sidebar.tsx
constant SIDEBAR_COOKIE_NAME (line 28) | const SIDEBAR_COOKIE_NAME = "sidebar_state";
constant SIDEBAR_COOKIE_MAX_AGE (line 29) | const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
constant SIDEBAR_WIDTH (line 30) | const SIDEBAR_WIDTH = "16rem";
constant SIDEBAR_WIDTH_MOBILE (line 31) | const SIDEBAR_WIDTH_MOBILE = "18rem";
constant SIDEBAR_WIDTH_ICON (line 32) | const SIDEBAR_WIDTH_ICON = "3rem";
constant SIDEBAR_KEYBOARD_SHORTCUT (line 33) | const SIDEBAR_KEYBOARD_SHORTCUT = "b";
type SidebarContextProps (line 35) | type SidebarContextProps = {
function useSidebar (line 47) | function useSidebar() {
function SidebarProvider (line 56) | function SidebarProvider({
function Sidebar (line 154) | function Sidebar({
function SidebarTrigger (line 256) | function SidebarTrigger({
function SidebarRail (line 282) | function SidebarRail({ className, ...props }: React.ComponentProps<"butt...
function SidebarInset (line 307) | function SidebarInset({ className, ...props }: React.ComponentProps<"mai...
function SidebarInput (line 321) | function SidebarInput({
function SidebarHeader (line 335) | function SidebarHeader({ className, ...props }: React.ComponentProps<"di...
function SidebarFooter (line 346) | function SidebarFooter({ className, ...props }: React.ComponentProps<"di...
function SidebarSeparator (line 357) | function SidebarSeparator({
function SidebarContent (line 371) | function SidebarContent({ className, ...props }: React.ComponentProps<"d...
function SidebarGroup (line 385) | function SidebarGroup({ className, ...props }: React.ComponentProps<"div...
function SidebarGroupLabel (line 396) | function SidebarGroupLabel({
function SidebarGroupAction (line 417) | function SidebarGroupAction({
function SidebarGroupContent (line 440) | function SidebarGroupContent({
function SidebarMenu (line 454) | function SidebarMenu({ className, ...props }: React.ComponentProps<"ul">) {
function SidebarMenuItem (line 465) | function SidebarMenuItem({ className, ...props }: React.ComponentProps<"...
function SidebarMenuButton (line 498) | function SidebarMenuButton({
function SidebarMenuAction (line 548) | function SidebarMenuAction({
function SidebarMenuBadge (line 580) | function SidebarMenuBadge({
function SidebarMenuSkeleton (line 602) | function SidebarMenuSkeleton({
function SidebarMenuSub (line 638) | function SidebarMenuSub({ className, ...props }: React.ComponentProps<"u...
function SidebarMenuSubItem (line 653) | function SidebarMenuSubItem({
function SidebarMenuSubButton (line 667) | function SidebarMenuSubButton({
FILE: apps/www/components/ui/skeleton.tsx
function Skeleton (line 3) | function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
FILE: apps/www/components/ui/slider.tsx
function Slider (line 8) | function Slider({
FILE: apps/www/components/ui/switch.tsx
function Switch (line 8) | function Switch({
FILE: apps/www/components/ui/table.tsx
function Table (line 7) | function Table({ className, ...props }: React.ComponentProps<"table">) {
function TableHeader (line 22) | function TableHeader({ className, ...props }: React.ComponentProps<"thea...
function TableBody (line 32) | function TableBody({ className, ...props }: React.ComponentProps<"tbody"...
function TableRow (line 42) | function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
function TableHead (line 55) | function TableHead({ className, ...props }: React.ComponentProps<"th">) {
function TableCell (line 68) | function TableCell({ className, ...props }: React.ComponentProps<"td">) {
FILE: apps/www/components/ui/tabs.tsx
function Tabs (line 8) | function Tabs({
function TabsList (line 21) | function TabsList({
function TabsTrigger (line 37) | function TabsTrigger({
function TabsContent (line 53) | function TabsContent({
FILE: apps/www/components/ui/textarea.tsx
function Textarea (line 5) | function Textarea({ className, ...props }: React.ComponentProps<"textare...
FILE: apps/www/components/ui/toggle-group.tsx
function ToggleGroup (line 20) | function ToggleGroup({
function ToggleGroupItem (line 51) | function ToggleGroupItem({
FILE: apps/www/components/ui/toggle.tsx
function Toggle (line 31) | function Toggle({
FILE: apps/www/components/ui/tooltip.tsx
function TooltipProvider (line 8) | function TooltipProvider({
function Tooltip (line 21) | function Tooltip({
function TooltipTrigger (line 31) | function TooltipTrigger({
function TooltipContent (line 37) | function TooltipContent({
FILE: apps/www/hooks/use-extract-headings.ts
type Heading (line 6) | type Heading = {
function useExtractHeadings (line 11) | function useExtractHeadings(container: HTMLElement | null): Heading[] {
FILE: apps/www/hooks/use-headings-observer.ts
function useHeadingsObserver (line 6) | function useHeadingsObserver(
FILE: apps/www/hooks/use-mobile.ts
constant MOBILE_BREAKPOINT (line 3) | const MOBILE_BREAKPOINT = 768;
function useIsMobile (line 5) | function useIsMobile() {
FILE: apps/www/hooks/use-preset-param.ts
type UsePresetParamOptions (line 6) | interface UsePresetParamOptions<T extends string> {
type UsePresetParamReturn (line 12) | interface UsePresetParamReturn<T extends string> {
function usePresetParam (line 17) | function usePresetParam<T extends string>({
FILE: apps/www/hooks/use-reduced-motion.ts
function useReducedMotion (line 5) | function useReducedMotion(): boolean {
FILE: apps/www/hooks/use-responsive-preview.ts
type UseResponsivePreviewOptions (line 6) | interface UseResponsivePreviewOptions {
type UseResponsivePreviewReturn (line 12) | interface UseResponsivePreviewReturn {
type PreviewLayoutSizes (line 17) | type PreviewLayoutSizes = [
function useResponsivePreview (line 32) | function useResponsivePreview({
FILE: apps/www/hooks/use-tab-search-param.ts
type UseTabSearchParamOptions (line 6) | interface UseTabSearchParamOptions<T extends string> {
type UseTabSearchParamReturn (line 14) | interface UseTabSearchParamReturn<T extends string> {
function resolveTabFromSearchParam (line 19) | function resolveTabFromSearchParam<T extends string>(
function useTabSearchParam (line 29) | function useTabSearchParam<T extends string>({
FILE: apps/www/hooks/use-toc-keyboard-nav.ts
function useTocKeyboardNav (line 6) | function useTocKeyboardNav(
FILE: apps/www/lib/analytics.ts
type AnalyticsProperties (line 1) | type AnalyticsProperties = Record<string, string | number | boolean>;
function loadPostHog (line 24) | function loadPostHog() {
function loadVercelTrack (line 31) | function loadVercelTrack() {
FILE: apps/www/lib/changelog/changelog.ts
type InferredReleaseNotes (line 4) | type InferredReleaseNotes = {
type RenderReleaseSectionInput (line 10) | type RenderReleaseSectionInput = {
type UpsertReleaseSectionInput (line 16) | type UpsertReleaseSectionInput = {
type ChangelogValidationResult (line 22) | type ChangelogValidationResult = {
type SectionBounds (line 27) | type SectionBounds = {
type SubsectionBounds (line 33) | type SubsectionBounds = {
function normalizeItemList (line 40) | function normalizeItemList(items: string[]): string[] {
function listToBullets (line 47) | function listToBullets(items: string[]): string {
function parseReleaseSectionBounds (line 51) | function parseReleaseSectionBounds(content: string): SectionBounds[] {
function parseSubsectionBounds (line 70) | function parseSubsectionBounds(sectionContent: string): SubsectionBounds...
function hasMarkdownCodeFence (line 89) | function hasMarkdownCodeFence(input: string): boolean {
function toMarkdownCodeFence (line 96) | function toMarkdownCodeFence(input: string, language: string): string {
function extractGeneratedToRef (line 108) | function extractGeneratedToRef(content: string): string | null {
function extractReleaseDateFromHeading (line 116) | function extractReleaseDateFromHeading(heading: string): string | null {
function introAreaContainsOnlyAllowedComments (line 125) | function introAreaContainsOnlyAllowedComments(introArea: string): boolean {
function createInitialChangelogContent (line 133) | function createInitialChangelogContent(): string {
function ensureChangelogFileExists (line 142) | function ensureChangelogFileExists(filePath: string): void {
function renderReleaseSection (line 151) | function renderReleaseSection({
function upsertReleaseSection (line 190) | function upsertReleaseSection({
function validateChangelogStructure (line 217) | function validateChangelogStructure(
function readLatestReleaseGeneratedToRef (line 325) | function readLatestReleaseGeneratedToRef(
function readLatestReleaseDate (line 345) | function readLatestReleaseDate(content: string): string | null {
FILE: apps/www/lib/changelog/git.ts
type ReleaseGitContext (line 3) | type ReleaseGitContext = {
type ReleaseGitContextOptions (line 15) | type ReleaseGitContextOptions = {
function isToolUiComponentPath (line 22) | function isToolUiComponentPath(filePath: string): boolean {
function filterToolUiComponentFiles (line 26) | function filterToolUiComponentFiles(files: string[]): string[] {
function runGit (line 30) | function runGit(projectRoot: string, args: string[]): string {
function tryRunGit (line 37) | function tryRunGit(projectRoot: string, args: string[]): string | null {
function collectCommitFiles (line 45) | function collectCommitFiles(projectRoot: string, hash: string): string[] {
function resolveReleaseRange (line 59) | function resolveReleaseRange(
function collectReleaseGitContext (line 156) | function collectReleaseGitContext(
function formatCommitSummary (line 207) | function formatCommitSummary(
FILE: apps/www/lib/changelog/inference.ts
type InferReleaseNotesInput (line 13) | type InferReleaseNotesInput = {
type CriticalMigrationEvidence (line 20) | type CriticalMigrationEvidence = Pick<
constant RELEASE_NOTES_SYSTEM_PROMPT (line 25) | const RELEASE_NOTES_SYSTEM_PROMPT =
type CriticalTheme (line 28) | type CriticalTheme = {
constant ACTION_MODEL_THEME (line 40) | const ACTION_MODEL_THEME: CriticalTheme = {
constant CRITICAL_THEMES (line 86) | const CRITICAL_THEMES: CriticalTheme[] = [ACTION_MODEL_THEME];
function extractJsonPayload (line 88) | function extractJsonPayload(text: string): string {
function normalizeInferredNotes (line 103) | function normalizeInferredNotes(
function textHasAnySignal (line 177) | function textHasAnySignal(text: string, signals: RegExp[]): boolean {
function filesHaveAnySignal (line 181) | function filesHaveAnySignal(filePaths: string[], signals: RegExp[]): boo...
function appendThemeMigrationSteps (line 187) | function appendThemeMigrationSteps(
function ensureCriticalMigrationCoverage (line 212) | function ensureCriticalMigrationCoverage(
function parseInferredReleaseNotes (line 265) | function parseInferredReleaseNotes(text: string): InferredReleaseNotes {
function selectModel (line 284) | function selectModel() {
function buildInferencePrompt (line 298) | function buildInferencePrompt(input: InferReleaseNotesInput): string {
function inferReleaseNotes (line 343) | async function inferReleaseNotes(
FILE: apps/www/lib/demo-chat/toolkit.tsx
constant DEMO_CHAT_TOOLKIT (line 15) | const DEMO_CHAT_TOOLKIT: Toolkit = {
constant DEMO_CHAT_TOOL_FALLBACK (line 75) | const DEMO_CHAT_TOOL_FALLBACK = ToolFallback;
FILE: apps/www/lib/docs/auto-link.tsx
type ReactNode (line 4) | type ReactNode = React.ReactNode;
type Pattern (line 6) | type Pattern = { match: string; href: string };
function isWordChar (line 40) | function isWordChar(ch?: string) {
function isBoundary (line 44) | function isBoundary(prev: string | undefined, next: string | undefined) {
function processText (line 51) | function processText(value: string): ReactNode[] {
constant SKIP_TYPES (line 98) | const SKIP_TYPES = new Set(["a", "code", "pre", "kbd", "samp"]);
function transform (line 100) | function transform(node: ReactNode): ReactNode {
function cloneWithChildren (line 115) | function cloneWithChildren(
function AutoLinkChildren (line 143) | function AutoLinkChildren({ children }: { children: ReactNode }) {
function withAutoLink (line 147) | function withAutoLink<E extends React.ElementType>(Base: E) {
FILE: apps/www/lib/docs/component-ids.ts
type ComponentId (line 31) | type ComponentId = (typeof componentIds)[number];
function isComponentId (line 33) | function isComponentId(
FILE: apps/www/lib/docs/component-registry.ts
type ComponentCategory (line 1) | type ComponentCategory =
type CategoryMeta (line 9) | interface CategoryMeta {
constant CATEGORY_META (line 14) | const CATEGORY_META: Record<ComponentCategory, CategoryMeta> = {
type ComponentMeta (line 23) | interface ComponentMeta {
FILE: apps/www/lib/docs/gallery-component-docs.ts
type GalleryComponentDocId (line 115) | type GalleryComponentDocId = keyof typeof galleryComponentDocs;
FILE: apps/www/lib/docs/gallery-layout.ts
constant GALLERY_LAYOUT_CLASS (line 1) | const GALLERY_LAYOUT_CLASS =
constant GALLERY_MOBILE_STACK_CLASS (line 4) | const GALLERY_MOBILE_STACK_CLASS = "flex flex-col gap-0 lg:hidden";
constant GALLERY_DESKTOP_GRID_CLASS (line 6) | const GALLERY_DESKTOP_GRID_CLASS =
constant GALLERY_COLUMN_STACK_CLASS (line 9) | const GALLERY_COLUMN_STACK_CLASS = "flex flex-col gap-0";
constant GALLERY_STANDARD_PREVIEW_WRAPPER_CLASS (line 11) | const GALLERY_STANDARD_PREVIEW_WRAPPER_CLASS =
FILE: apps/www/lib/docs/gallery-usage-code.ts
function toPascalCase (line 5) | function toPascalCase(kebab: string): string {
constant IMPORT_OVERRIDES (line 12) | const IMPORT_OVERRIDES: Partial<Record<GalleryComponentDocId, string>> = {
function getImportLine (line 22) | function getImportLine(
function getGalleryUsageCode (line 34) | function getGalleryUsageCode(
FILE: apps/www/lib/docs/install-snippet-analytics.ts
type InstallSnippetType (line 1) | type InstallSnippetType =
constant SKILLS_INSTALL_PATTERN (line 7) | const SKILLS_INSTALL_PATTERN = /(?:^|\n)\s*npx\s+skills\s+add\b/i;
constant TOOL_AGENT_PATTERN (line 8) | const TOOL_AGENT_PATTERN = /(?:^|\n)\s*npx\s+tool-agent\b/i;
constant REGISTRY_INSTALL_PATTERN (line 9) | const REGISTRY_INSTALL_PATTERN = /(?:^|\n)\s*npx\s+shadcn@latest\s+add\b/i;
constant PACKAGE_INSTALL_PATTERN (line 10) | const PACKAGE_INSTALL_PATTERN =
function detectInstallSnippetType (line 13) | function detectInstallSnippetType(
function getDocsCodeCopySource (line 35) | function getDocsCodeCopySource(
FILE: apps/www/lib/docs/preview-config.tsx
function QuestionFlowUpfrontWithReceipt (line 238) | function QuestionFlowUpfrontWithReceipt({
type ChatContext (line 286) | interface ChatContext {
type PreviewConfig (line 291) | interface PreviewConfig<TData, TPresetName extends string> {
type PreviewState (line 304) | interface PreviewState {
function toRecord (line 309) | function toRecord(value: unknown): Record<string, unknown> | null {
function resolveActionItems (line 315) | function resolveActionItems(actions: unknown): Action[] | null {
function resolveLocalActionItems (line 325) | function resolveLocalActionItems(data: unknown): Action[] | null {
function renderWithLocalActions (line 331) | function renderWithLocalActions(
function MaxWidthWrapper (line 353) | function MaxWidthWrapper({ children }: { children: ReactNode }) {
function MaxWidthSmWrapper (line 357) | function MaxWidthSmWrapper({ children }: { children: ReactNode }) {
function MaxWidthSmStartWrapper (line 361) | function MaxWidthSmStartWrapper({ children }: { children: ReactNode }) {
function MaxWidthStartWrapper (line 365) | function MaxWidthStartWrapper({ children }: { children: ReactNode }) {
function getPreviewConfig (line 1001) | function getPreviewConfig(componentId: ComponentId) {
FILE: apps/www/lib/eslint/tool-ui-action-model-plugin.ts
constant RESPONSE_ACTION_IDENTIFIERS (line 3) | const RESPONSE_ACTION_IDENTIFIERS = new Set([
constant LOCAL_ACTION_ELEMENTS (line 9) | const LOCAL_ACTION_ELEMENTS = new Set(["LocalActions", "ToolUI.LocalActi...
constant DECISION_ACTION_ELEMENTS (line 10) | const DECISION_ACTION_ELEMENTS = new Set([
function jsxNameToString (line 15) | function jsxNameToString(
method create (line 68) | create(context) {
method create (line 98) | create(context) {
method create (line 147) | create(context) {
FILE: apps/www/lib/integrations/freestyle/create-chat.ts
function requestDevServerInternal (line 15) | async function requestDevServerInternal(
function createChat (line 36) | async function createChat() {
function requestDevServer (line 58) | async function requestDevServer({ repoId }: { repoId: string }) {
FILE: apps/www/lib/integrations/freestyle/get-code.ts
function getFileFromRepo (line 15) | async function getFileFromRepo(
function getComponentCode (line 36) | async function getComponentCode(
FILE: apps/www/lib/integrations/rate-limit/upstash.ts
function checkRateLimit (line 27) | async function checkRateLimit(identifier: string) {
FILE: apps/www/lib/mocks/chat-showcase-data.ts
type Flight (line 14) | type Flight = {
type BadgeColor (line 24) | type BadgeColor = "danger" | "warning" | "info" | "success" | "neutral";
constant TABLE_COLUMNS (line 26) | const TABLE_COLUMNS: Column<Flight>[] = [
constant TABLE_DATA (line 48) | const TABLE_DATA: Flight[] = [
constant LINK_PREVIEW (line 87) | const LINK_PREVIEW: SerializableLinkPreview = {
constant X_POST (line 100) | const X_POST: XPostData = {
constant X_POST_ACTIONS (line 112) | const X_POST_ACTIONS = [
constant SPENDING_DATA (line 118) | const SPENDING_DATA = [
constant SPENDING_CHART (line 126) | const SPENDING_CHART: Omit<SerializableChart, "id"> = {
constant PLAN_TODO_LABELS (line 135) | const PLAN_TODO_LABELS = [
constant TERMINAL_DATA (line 142) | const TERMINAL_DATA: Omit<SerializableTerminal, "id"> = {
constant CODE_BLOCK_DATA (line 154) | const CODE_BLOCK_DATA: Omit<SerializableCodeBlock, "id"> = {
constant OPTION_LIST_OPTIONS (line 184) | const OPTION_LIST_OPTIONS: OptionListOption[] = [
constant OPTION_LIST_CONFIRMED (line 203) | const OPTION_LIST_CONFIRMED = ["comedy", "comfort"];
constant ITEM_CAROUSEL_DATA (line 205) | const ITEM_CAROUSEL_DATA: Omit<SerializableItemCarousel, "id"> = {
constant PARAMETER_SLIDER_DATA (line 250) | const PARAMETER_SLIDER_DATA: Omit<SerializableParameterSlider, "id"> = {
function favicon (line 286) | function favicon(domain: string, size = 32): string {
constant LLM_CITATIONS (line 290) | const LLM_CITATIONS: SerializableCitation[] = [
constant STATS_DISPLAY_DATA (line 333) | const STATS_DISPLAY_DATA: Omit<SerializableStatsDisplay, "id"> = {
constant PROGRESS_TRACKER_DATA (line 389) | const PROGRESS_TRACKER_DATA: Omit<SerializableProgressTracker, "id"> = {
FILE: apps/www/lib/mocks/stocks.ts
type Stock (line 6) | interface Stock {
type GetStocksParams (line 109) | interface GetStocksParams {
function getStocks (line 127) | async function getStocks(
FILE: apps/www/lib/mocks/tasks.ts
type Task (line 1) | type Task = {
constant ALL_TASKS (line 11) | const ALL_TASKS: Task[] = [
function getMockTasks (line 50) | async function getMockTasks({
FILE: apps/www/lib/og/og-image.tsx
constant ZINC_950 (line 12) | const ZINC_950 = "#09090b";
constant ZINC_400 (line 13) | const ZINC_400 = "#a1a1aa";
function loadGeistFont (line 15) | async function loadGeistFont(weight: "Regular" | "Bold") {
function generateOgImage (line 20) | async function generateOgImage(title: string, description?: string) {
function createOgImageHandler (line 103) | function createOgImageHandler(title: string, description?: string) {
FILE: apps/www/lib/playground/constants.ts
constant PROTOTYPE_SLUG_HEADER (line 1) | const PROTOTYPE_SLUG_HEADER = "x-prototype-slug";
FILE: apps/www/lib/playground/mocks.ts
function mockTool (line 6) | function mockTool<TResult>(
FILE: apps/www/lib/playground/prototypes/food-ordering/get-menu.ts
type GetMenuArgs (line 3) | type GetMenuArgs = {
type GetMenuResult (line 7) | type GetMenuResult = typeof MENU;
FILE: apps/www/lib/playground/prototypes/food-ordering/get-restaurant-details.ts
type GetRestaurantDetailsArgs (line 3) | type GetRestaurantDetailsArgs = {
type GetRestaurantDetailsResult (line 7) | type GetRestaurantDetailsResult = typeof RESTAURANT_DETAILS;
FILE: apps/www/lib/playground/prototypes/food-ordering/place-order.ts
type OrderItem (line 1) | type OrderItem = {
type PlaceOrderArgs (line 8) | type PlaceOrderArgs = {
type PlaceOrderResult (line 17) | type PlaceOrderResult = {
constant DELIVERY_FEE (line 39) | const DELIVERY_FEE = 2.99;
constant TAX_RATE (line 40) | const TAX_RATE = 0.0875;
FILE: apps/www/lib/playground/prototypes/food-ordering/search-restaurants.ts
type SearchRestaurantsArgs (line 3) | type SearchRestaurantsArgs = {
type SearchRestaurantsResult (line 8) | type SearchRestaurantsResult = typeof RESTAURANT_SEARCH_RESULTS;
FILE: apps/www/lib/playground/prototypes/food-ordering/shared.ts
constant RESTAURANT_SEARCH_RESULTS (line 1) | const RESTAURANT_SEARCH_RESULTS = {
constant RESTAURANT_DETAILS (line 37) | const RESTAURANT_DETAILS = {
constant MENU (line 61) | const MENU = {
FILE: apps/www/lib/playground/prototypes/waymo-v2/components/DestinationPicker.tsx
function DestinationPicker (line 37) | function DestinationPicker({
FILE: apps/www/lib/playground/prototypes/waymo-v2/components/PickupPicker.tsx
type PickupOption (line 23) | interface PickupOption {
function PickupPicker (line 67) | function PickupPicker({
FILE: apps/www/lib/playground/prototypes/waymo-v2/components/RideQuote.tsx
type PickupOption (line 32) | interface PickupOption {
function RideQuote (line 133) | function RideQuote({
FILE: apps/www/lib/playground/prototypes/waymo-v2/components/TripStatus.tsx
function TripStatus (line 82) | function TripStatus({
FILE: apps/www/lib/playground/prototypes/waymo-v2/system-prompt.ts
constant WAYMO_V2_SYSTEM_PROMPT (line 7) | const WAYMO_V2_SYSTEM_PROMPT =
FILE: apps/www/lib/playground/prototypes/waymo-v2/types.ts
type Location (line 14) | interface Location {
type Price (line 21) | interface Price {
type Vehicle (line 26) | interface Vehicle {
type SelectDestinationArgs (line 39) | interface SelectDestinationArgs {
type SelectDestinationResult (line 43) | interface SelectDestinationResult {
type PickupOption (line 53) | interface PickupOption {
type SelectPickupResult (line 60) | interface SelectPickupResult {
type GetRideQuoteArgs (line 69) | interface GetRideQuoteArgs {
type RideQuote (line 73) | interface RideQuote {
type GetRideQuoteResult (line 94) | interface GetRideQuoteResult {
type TripPhase (line 104) | type TripPhase =
type TripStep (line 114) | interface TripStep {
type GetTripStatusArgs (line 121) | interface GetTripStatusArgs {
type TripStatus (line 125) | interface TripStatus {
type GetTripStatusResult (line 134) | interface GetTripStatusResult {
constant MOCK_LOCATIONS (line 143) | const MOCK_LOCATIONS: Location[] = [
constant MOCK_PICKUP (line 164) | const MOCK_PICKUP = {
constant MOCK_VEHICLE (line 169) | const MOCK_VEHICLE: Vehicle = {
FILE: apps/www/lib/playground/prototypes/waymo/WaymoDemo.tsx
type Message (line 31) | interface Message {
function WaymoDemo (line 36) | function WaymoDemo() {
FILE: apps/www/lib/playground/prototypes/waymo/check-ride-prices.ts
type CheckRidePricesArgs (line 3) | type CheckRidePricesArgs = {
type RideOption (line 10) | type RideOption = (typeof RIDE_OPTIONS)[number];
type CheckRidePricesResult (line 12) | type CheckRidePricesResult = {
FILE: apps/www/lib/playground/prototypes/waymo/components/BookingConfirmation.tsx
function BookingConfirmation (line 25) | function BookingConfirmation({ trip }: BookingConfirmationProps) {
FILE: apps/www/lib/playground/prototypes/waymo/components/RideQuote.tsx
function RideQuote (line 18) | function RideQuote({
FILE: apps/www/lib/playground/prototypes/waymo/confirm-ride-booking.ts
type ConfirmRideBookingArgs (line 4) | type ConfirmRideBookingArgs = RideSummary;
type ConfirmRideBookingResult (line 6) | type ConfirmRideBookingResult = {
FILE: apps/www/lib/playground/prototypes/waymo/confirm-user-payment.ts
type ConfirmUserPaymentArgs (line 3) | type ConfirmUserPaymentArgs = {
type ConfirmUserPaymentResult (line 8) | type ConfirmUserPaymentResult = {
FILE: apps/www/lib/playground/prototypes/waymo/get-profile-context.ts
type GetProfileContextResult (line 8) | type GetProfileContextResult = {
FILE: apps/www/lib/playground/prototypes/waymo/get-user-destination.ts
type GetUserDestinationArgs (line 3) | type GetUserDestinationArgs = {
type Destination (line 7) | type Destination = typeof DESTINATIONS.home | typeof DESTINATIONS.ferry;
type GetUserDestinationResult (line 9) | type GetUserDestinationResult = {
FILE: apps/www/lib/playground/prototypes/waymo/get-user-location.ts
type GetUserLocationArgs (line 3) | type GetUserLocationArgs = {
type GetUserLocationResult (line 7) | type GetUserLocationResult = {
FILE: apps/www/lib/playground/prototypes/waymo/precheck-prices.ts
type Suggestion (line 4) | type Suggestion = {
type PrecheckPricesArgs (line 17) | type PrecheckPricesArgs = {
type PrecheckPricesResult (line 22) | type PrecheckPricesResult = {
FILE: apps/www/lib/playground/prototypes/waymo/request-payment-method.ts
type RequestPaymentMethodArgs (line 3) | type RequestPaymentMethodArgs = {
type PaymentInstrument (line 7) | type PaymentInstrument =
type RequestPaymentMethodResult (line 11) | type RequestPaymentMethodResult = {
FILE: apps/www/lib/playground/prototypes/waymo/schedule-ride.ts
type ScheduleRideArgs (line 3) | type ScheduleRideArgs = RideSummary;
type ScheduleRideResult (line 5) | type ScheduleRideResult = {
FILE: apps/www/lib/playground/prototypes/waymo/search-places.ts
type SearchPlacesArgs (line 3) | type SearchPlacesArgs = {
type PlaceChoice (line 8) | type PlaceChoice = (typeof PLACE_CHOICES)[number];
type SearchPlacesResult (line 10) | type SearchPlacesResult = {
FILE: apps/www/lib/playground/prototypes/waymo/shared.ts
constant MOCK_NOW (line 3) | const MOCK_NOW = "2024-06-01T12:00:00.000Z";
constant DEFAULT_PICKUP (line 5) | const DEFAULT_PICKUP = {
constant DEFAULT_FAVORITES (line 13) | const DEFAULT_FAVORITES = [
constant DEFAULT_RECENTS (line 26) | const DEFAULT_RECENTS = [
constant RIDE_OPTIONS (line 34) | const RIDE_OPTIONS = [
constant DESTINATIONS (line 58) | const DESTINATIONS = {
constant PLACE_CHOICES (line 75) | const PLACE_CHOICES = [
constant SUGGESTION_SERVICES (line 93) | const SUGGESTION_SERVICES = ["Standard", "XL", "Premium"] as const;
constant SUGGESTION_REASONS (line 95) | const SUGGESTION_REASONS = ["frequent", "workday", "recent"] as const;
constant PAYMENT_METHODS (line 97) | const PAYMENT_METHODS = ["apple_pay", "google_pay", "card"] as const;
type PaymentMethod (line 99) | type PaymentMethod = (typeof PAYMENT_METHODS)[number];
type Candidate (line 111) | type Candidate = z.infer<typeof candidateSchema>;
type RideSummary (line 123) | type RideSummary = z.infer<typeof rideSummarySchema>;
FILE: apps/www/lib/playground/prototypes/waymo/show-ride-details.ts
type ShowRideDetailsArgs (line 3) | type ShowRideDetailsArgs = RideSummary;
type ShowRideDetailsResult (line 5) | type ShowRideDetailsResult = {
FILE: apps/www/lib/playground/prototypes/waymo/show-ride-options.ts
type ShowRideOptionsArgs (line 9) | type ShowRideOptionsArgs = {
type RideSuggestionsResult (line 14) | type RideSuggestionsResult = {
FILE: apps/www/lib/playground/prototypes/waymo/system-message-v2.ts
constant WAYMO_SYSTEM_MESSAGE_V2 (line 1) | const WAYMO_SYSTEM_MESSAGE_V2 =
FILE: apps/www/lib/playground/prototypes/waymo/toggle-gps.ts
type ToggleGpsArgs (line 1) | type ToggleGpsArgs = {
type ToggleGpsResult (line 5) | type ToggleGpsResult = {
FILE: apps/www/lib/playground/prototypes/waymo/tools.ts
constant MOCK_HOME (line 25) | const MOCK_HOME: Location = {
constant MOCK_WORK (line 32) | const MOCK_WORK: Location = {
constant MOCK_COFFEE_SHOP (line 39) | const MOCK_COFFEE_SHOP: Location = {
constant MOCK_DEFAULT_PAYMENT (line 46) | const MOCK_DEFAULT_PAYMENT: PaymentMethod = {
constant MOCK_PAYMENT_METHODS (line 52) | const MOCK_PAYMENT_METHODS: PaymentMethod[] = [
function getRiderContext (line 64) | async function getRiderContext(options?: {
function resolveAddress (line 107) | async function resolveAddress(query: string): Promise<Location> {
function getPickupLocation (line 121) | async function getPickupLocation(
function getQuote (line 137) | async function getQuote(input: GetQuoteInput): Promise<RideQuote> {
function bookTrip (line 164) | async function bookTrip(input: BookTripInput): Promise<BookedTrip> {
FILE: apps/www/lib/playground/prototypes/waymo/types.ts
type Location (line 14) | interface Location {
type PaymentMethod (line 21) | interface PaymentMethod {
type RiderContext (line 29) | interface RiderContext {
type RideQuote (line 38) | interface RideQuote {
type BookedTrip (line 55) | interface BookedTrip {
type GetPickupLocationInput (line 76) | interface GetPickupLocationInput {
type GetPickupLocationOutput (line 80) | interface GetPickupLocationOutput {
type GetQuoteInput (line 85) | interface GetQuoteInput {
type BookTripInput (line 90) | interface BookTripInput {
type ToolUIMessage (line 97) | interface ToolUIMessage {
type RideQuoteProps (line 105) | interface RideQuoteProps {
type BookingConfirmationProps (line 112) | interface BookingConfirmationProps {
FILE: apps/www/lib/playground/prototypes/waymo/wip-tool-uis/FrequentLocationSelector.tsx
type FrequentLocation (line 9) | type FrequentLocation = {
type SelectFrequentLocationResult (line 16) | type SelectFrequentLocationResult = {
FILE: apps/www/lib/playground/registry.ts
constant PROTOTYPES (line 9) | const PROTOTYPES: Prototype[] = [
FILE: apps/www/lib/playground/runtime.ts
constant DEFAULT_MODEL (line 18) | const DEFAULT_MODEL = "openai/gpt-4.1-mini";
constant PROVIDERS (line 20) | const PROVIDERS: Record<string, (modelId: string) => LanguageModel> = {
method execute (line 90) | async execute(args: unknown) {
FILE: apps/www/lib/playground/tool-uis.ts
constant TOOL_UI_REGISTRY (line 17) | const TOOL_UI_REGISTRY = registry;
FILE: apps/www/lib/playground/types.ts
type ToolUiId (line 3) | type ToolUiId = "fallback" | "waymo-location-selector";
type ToolExecute (line 5) | type ToolExecute = (args: unknown) => Promise<unknown>;
type Tool (line 7) | type Tool = {
type Prototype (line 16) | type Prototype = {
FILE: apps/www/lib/playground/weather-tuning/parameter-definitions-coverage.test.ts
function getNumericKeys (line 6) | function getNumericKeys(value: unknown): string[] {
FILE: apps/www/lib/playground/weather-tuning/resolve-params.test.ts
function makeBase (line 10) | function makeBase(timeOfDay: number): FullCompositorParams {
function makeEmptyCheckpointOverrides (line 58) | function makeEmptyCheckpointOverrides(): CheckpointOverrides {
FILE: apps/www/lib/playground/weather-tuning/workflow-state.test.ts
constant STORAGE_KEY (line 9) | const STORAGE_KEY = "weather-tuning-studio-session";
class MemoryStorage (line 11) | class MemoryStorage {
method getItem (line 14) | getItem(key: string): string | null {
method setItem (line 18) | setItem(key: string, value: string): void {
method removeItem (line 22) | removeItem(key: string): void {
method clear (line 26) | clear(): void {
FILE: apps/www/lib/presets/approval-card.ts
type ApprovalCardPresetName (line 4) | type ApprovalCardPresetName =
function generateApprovalCardCode (line 11) | function generateApprovalCardCode(data: SerializableApprovalCard): string {
FILE: apps/www/lib/presets/audio.ts
type AudioData (line 8) | interface AudioData {
function escape (line 14) | function escape(value: string): string {
function formatObject (line 18) | function formatObject(value: Record<string, unknown>): string {
function generateAudioCode (line 22) | function generateAudioCode(data: AudioData): string {
type AudioPresetName (line 77) | type AudioPresetName = "full" | "compact" | "with-actions";
FILE: apps/www/lib/presets/chart.ts
type ChartData (line 4) | type ChartData = Omit<SerializableChart, "id">;
type ChartPresetName (line 6) | type ChartPresetName = "revenue" | "performance" | "minimal";
function generateChartCode (line 8) | function generateChartCode(data: ChartData): string {
FILE: apps/www/lib/presets/citation.ts
function favicon (line 8) | function favicon(domain: string, size = 32): string {
type CitationData (line 12) | interface CitationData {
function escape (line 19) | function escape(value: string): string {
function generateCitationCode (line 23) | function generateCitationCode(data: CitationData): string {
type CitationPresetName (line 93) | type CitationPresetName =
FILE: apps/www/lib/presets/code-block.ts
type CodeBlockPresetName (line 5) | type CodeBlockPresetName =
function escape (line 14) | function escape(value: string): string {
type CodeBlockPresetData (line 18) | interface CodeBlockPresetData extends SerializableCodeBlock {
function generateCodeBlockCode (line 22) | function generateCodeBlockCode(data: CodeBlockPresetData): string {
FILE: apps/www/lib/presets/code-diff.ts
type CodeDiffPresetName (line 4) | type CodeDiffPresetName =
function escape (line 12) | function escape(value: string): string {
function generateCodeDiffCode (line 20) | function generateCodeDiffCode(data: SerializableCodeDiff): string {
FILE: apps/www/lib/presets/data-table.ts
type GenericRow (line 5) | type GenericRow = Record<string, RowPrimitive>;
type SortState (line 7) | type SortState = { by?: string; direction?: "asc" | "desc" };
type DataTableData (line 9) | interface DataTableData {
function generateDataTableCode (line 21) | function generateDataTableCode(data: DataTableData): string {
type DataTablePresetName (line 371) | type DataTablePresetName = "stocks" | "tasks" | "links-tags" | "actions";
FILE: apps/www/lib/presets/geo-map.ts
type GeoMapData (line 4) | type GeoMapData = Omit<SerializableGeoMap, "id">;
type GeoMapPresetName (line 6) | type GeoMapPresetName = "facility" | "fleet" | "focused";
function generateGeoMapCode (line 8) | function generateGeoMapCode(data: GeoMapData): string {
FILE: apps/www/lib/presets/image-gallery.ts
type ImageGalleryPresetName (line 4) | type ImageGalleryPresetName =
function generateImageGalleryCode (line 9) | function generateImageGalleryCode(data: SerializableImageGallery): string {
FILE: apps/www/lib/presets/image.ts
type ImageData (line 5) | interface ImageData {
function escape (line 10) | function escape(value: string): string {
function formatObject (line 14) | function formatObject(value: Record<string, unknown>): string {
function generateImageCode (line 18) | function generateImageCode(data: ImageData): string {
type ImagePresetName (line 78) | type ImagePresetName = "basic" | "with-source" | "with-actions";
FILE: apps/www/lib/presets/instagram-post.ts
type InstagramPostPresetData (line 5) | interface InstagramPostPresetData {
type InstagramPostPresetName (line 10) | type InstagramPostPresetName = "basic" | "carousel" | "footer-actions";
function generateInstagramPostCode (line 12) | function generateInstagramPostCode(data: InstagramPostPresetData): string {
FILE: apps/www/lib/presets/item-carousel.ts
type ItemCarouselPresetName (line 4) | type ItemCarouselPresetName =
function generateItemCarouselCode (line 12) | function generateItemCarouselCode(data: SerializableItemCarousel): string {
FILE: apps/www/lib/presets/link-preview.ts
type LinkPreviewData (line 5) | interface LinkPreviewData {
function escape (line 10) | function escape(value: string): string {
function generateLinkPreviewCode (line 14) | function generateLinkPreviewCode(data: LinkPreviewData): string {
type LinkPreviewPresetName (line 62) | type LinkPreviewPresetName = "basic" | "with-image" | "with-actions";
FILE: apps/www/lib/presets/linkedin-post.ts
type LinkedInPostPresetData (line 5) | interface LinkedInPostPresetData {
type LinkedInPostPresetName (line 10) | type LinkedInPostPresetName =
function generateLinkedInPostCode (line 16) | function generateLinkedInPostCode(data: LinkedInPostPresetData): string {
FILE: apps/www/lib/presets/message-draft.ts
type MessageDraftPresetName (line 4) | type MessageDraftPresetName =
function generateMessageDraftCode (line 11) | function generateMessageDraftCode(data: SerializableMessageDraft): string {
FILE: apps/www/lib/presets/option-list.ts
type OptionListPresetName (line 4) | type OptionListPresetName =
function generateOptionListCode (line 12) | function generateOptionListCode(data: SerializableOptionList): string {
FILE: apps/www/lib/presets/order-summary.ts
type OrderSummaryPresetName (line 4) | type OrderSummaryPresetName =
function generateOrderSummaryCode (line 11) | function generateOrderSummaryCode(data: SerializableOrderSummary): string {
FILE: apps/www/lib/presets/parameter-slider.ts
type ParameterSliderPresetName (line 4) | type ParameterSliderPresetName =
function formatSliderConfig (line 11) | function formatSliderConfig(
function generateParameterSliderCode (line 38) | function generateParameterSliderCode(
FILE: apps/www/lib/presets/plan.ts
type PlanPresetName (line 4) | type PlanPresetName =
function escape (line 11) | function escape(value: string): string {
function generatePlanCode (line 15) | function generatePlanCode(data: SerializablePlan): string {
function generatePlanCompactCode (line 36) | function generatePlanCompactCode(data: SerializablePlan): string {
FILE: apps/www/lib/presets/preferences-panel.ts
type PreferencesPanelPresetName (line 7) | type PreferencesPanelPresetName =
function generatePreferencesPanelCode (line 15) | function generatePreferencesPanelCode(
FILE: apps/www/lib/presets/progress-tracker.ts
type ProgressTrackerPresetName (line 4) | type ProgressTrackerPresetName =
type ProgressTrackerPreset (line 12) | type ProgressTrackerPreset = PresetWithCodeGen<SerializableProgressTrack...
function generateProgressTrackerCode (line 14) | function generateProgressTrackerCode(
FILE: apps/www/lib/presets/question-flow.ts
type QuestionFlowPresetName (line 9) | type QuestionFlowPresetName =
function generateProgressiveCode (line 15) | function generateProgressiveCode(data: SerializableProgressiveMode): str...
function generateUpfrontCode (line 40) | function generateUpfrontCode(data: SerializableUpfrontMode): string {
function generateReceiptCode (line 52) | function generateReceiptCode(data: SerializableReceiptMode): string {
function generateQuestionFlowCode (line 63) | function generateQuestionFlowCode(data: SerializableQuestionFlow): string {
FILE: apps/www/lib/presets/stats-display.ts
type StatsDisplayPresetName (line 4) | type StatsDisplayPresetName =
type StatsDisplayPreset (line 11) | type StatsDisplayPreset = PresetWithCodeGen<SerializableStatsDisplay>;
function generateStatsDisplayCode (line 13) | function generateStatsDisplayCode(data: SerializableStatsDisplay): string {
FILE: apps/www/lib/presets/terminal.ts
type TerminalPresetName (line 5) | type TerminalPresetName =
function escape (line 14) | function escape(value: string): string {
type TerminalPresetData (line 18) | interface TerminalPresetData extends SerializableTerminal {
function generateTerminalCode (line 22) | function generateTerminalCode(data: TerminalPresetData): string {
FILE: apps/www/lib/presets/types.ts
type Preset (line 1) | interface Preset<T> {
type PresetRecord (line 6) | type PresetRecord<TName extends string, TData> = Record<
type PresetWithCodeGen (line 11) | interface PresetWithCodeGen<T> extends Preset<T> {
type PresetRecordWithCodeGen (line 15) | type PresetRecordWithCodeGen<TName extends string, TData> = Record<
FILE: apps/www/lib/presets/video.ts
type VideoData (line 5) | interface VideoData {
function escape (line 10) | function escape(value: string): string {
function formatObject (line 14) | function formatObject(value: Record<string, unknown>): string {
function generateVideoCode (line 18) | function generateVideoCode(data: VideoData): string {
type VideoPresetName (line 73) | type VideoPresetName = "basic" | "with-poster" | "with-actions";
FILE: apps/www/lib/presets/weather-widget.ts
type WeatherWidgetPresetName (line 4) | type WeatherWidgetPresetName =
function generateWeatherWidgetCode (line 11) | function generateWeatherWidgetCode(data: WeatherWidgetPayload): string {
FILE: apps/www/lib/presets/x-post.ts
type XPostPresetData (line 5) | interface XPostPresetData {
type XPostPresetName (line 10) | type XPostPresetName =
function generateXPostCode (line 17) | function generateXPostCode(data: XPostPresetData): string {
FILE: apps/www/lib/registry/tool-ui-registry.ts
type RegistryItemType (line 5) | type RegistryItemType =
type RegistryFile (line 17) | interface RegistryFile {
type RegistryItem (line 24) | interface RegistryItem {
type RegistryIndex (line 35) | interface RegistryIndex {
type ToolUiRegistryDefinition (line 42) | interface ToolUiRegistryDefinition {
type ToolUiRegistryArtifacts (line 50) | interface ToolUiRegistryArtifacts {
constant REGISTRY_SCHEMA (line 55) | const REGISTRY_SCHEMA = "https://ui.shadcn.com/schema/registry.json";
constant REGISTRY_ITEM_SCHEMA (line 56) | const REGISTRY_ITEM_SCHEMA = "https://ui.shadcn.com/schema/registry-item...
constant IMPORT_META_URL_RE (line 58) | const IMPORT_META_URL_RE =
constant TOOL_UI_COMPONENTS_DIR (line 60) | const TOOL_UI_COMPONENTS_DIR = "components/tool-ui";
constant IGNORED_REGISTRY_FILE_NAMES (line 61) | const IGNORED_REGISTRY_FILE_NAMES = new Set([".DS_Store", "Thumbs.db"]);
constant IMPORT_GRAPH_SOURCE_EXTENSIONS (line 62) | const IMPORT_GRAPH_SOURCE_EXTENSIONS = new Set([
constant DEPENDENCY_VERSION_OVERRIDES (line 72) | const DEPENDENCY_VERSION_OVERRIDES: Record<string, string> = {
constant COMPONENT_DESCRIPTION_OVERRIDES (line 76) | const COMPONENT_DESCRIPTION_OVERRIDES: Partial<Record<string, string>> = {
constant COMPONENT_ENTRYPOINT_OVERRIDES (line 105) | const COMPONENT_ENTRYPOINT_OVERRIDES: Partial<Record<string, string[]>> = {
function inferRegistryFileType (line 109) | function inferRegistryFileType(filePath: string): RegistryItemType {
function listFilesRecursively (line 116) | async function listFilesRecursively(dirPath: string): Promise<string[]> {
function toPosixPath (line 138) | function toPosixPath(filePath: string): string {
function shouldTraverseImportGraph (line 142) | function shouldTraverseImportGraph(filePath: string): boolean {
function resolveLocalImport (line 146) | function resolveLocalImport(
function extractImportSpecifiers (line 184) | function extractImportSpecifiers(
function extractImportMetaUrlSpecifiers (line 243) | function extractImportMetaUrlSpecifiers(content: string): string[] {
function extractLocalImportSpecifiers (line 256) | function extractLocalImportSpecifiers(content: string): string[] {
function toTitleCase (line 276) | function toTitleCase(name: string): string {
function toPackageName (line 284) | function toPackageName(specifier: string): string | null {
function toRegistryDependency (line 303) | function toRegistryDependency(specifier: string): string | null {
function toRegistryDependencyFromResolvedPath (line 309) | function toRegistryDependencyFromResolvedPath(
function withPinnedVersion (line 320) | function withPinnedVersion(pkg: string): string {
function discoverToolUiRegistryDefinitions (line 325) | async function discoverToolUiRegistryDefinitions(
function shouldIncludeResolvedPath (line 353) | function shouldIncludeResolvedPath(
function collectItemFilePaths (line 361) | async function collectItemFilePaths(
function buildRegistryItem (line 414) | async function buildRegistryItem(
function toIndexItem (line 484) | function toIndexItem(item: RegistryItem): RegistryIndex["items"][number] {
function buildToolUiRegistryArtifacts (line 500) | async function buildToolUiRegistryArtifacts(
function writeToolUiRegistryArtifacts (line 521) | async function writeToolUiRegistryArtifacts(
FILE: apps/www/lib/staging/configs/parameter-slider.tsx
type SliderElementRects (line 10) | interface SliderElementRects {
function getSliderElements (line 17) | function getSliderElements(
function ParameterSliderDebugOverlay (line 69) | function ParameterSliderDebugOverlay({
FILE: apps/www/lib/staging/configs/plan.tsx
constant SAMPLE_TODOS (line 9) | const SAMPLE_TODOS: PlanTodo[] = [
function PlanTuningPanel (line 36) | function PlanTuningPanel() {
FILE: apps/www/lib/staging/configs/progress-tracker.tsx
constant SAMPLE_STEPS (line 9) | const SAMPLE_STEPS: ProgressStep[] = [
function ProgressTrackerTuningPanel (line 30) | function ProgressTrackerTuningPanel() {
FILE: apps/www/lib/staging/configs/stats-display.tsx
type SparklineAnimationParams (line 27) | interface SparklineAnimationParams {
type StatCardAnimationParams (line 47) | interface StatCardAnimationParams {
type TunableSparklineProps (line 57) | interface TunableSparklineProps {
function TunableSparkline (line 69) | function TunableSparkline({
type FormattedValueProps (line 209) | interface FormattedValueProps {
function FormattedValue (line 215) | function FormattedValue({ value, format, locale }: FormattedValueProps) {
type DeltaValueProps (line 299) | interface DeltaValueProps {
function DeltaValue (line 303) | function DeltaValue({ diff }: DeltaValueProps) {
type TunableStatCardProps (line 347) | interface TunableStatCardProps {
function TunableStatCard (line 356) | function TunableStatCard({
type TunableStatsDisplayProps (line 440) | interface TunableStatsDisplayProps extends StatsDisplayProps {
function TunableStatsDisplay (line 445) | function TunableStatsDisplay({
type TuningPanelProps (line 523) | interface TuningPanelProps {
function TuningPanel (line 527) | function TuningPanel({ data }: TuningPanelProps) {
FILE: apps/www/lib/staging/staging-config.ts
function getStagingConfig (line 14) | function getStagingConfig(
FILE: apps/www/lib/staging/types.ts
type DebugLevel (line 4) | type DebugLevel = "off" | "boundaries" | "margins" | "full";
type StagingConfig (line 6) | interface StagingConfig {
FILE: apps/www/lib/system/tool-builder-message.ts
constant SYSTEM_MESSAGE (line 1) | const SYSTEM_MESSAGE = `You are an AI assistant that creates tool UI wid...
FILE: apps/www/lib/tests/registry/tool-ui-registry.test.ts
function getProjectRoot (line 7) | function getProjectRoot(): string {
function listExpectedComponents (line 13) | async function listExpectedComponents(): Promise<string[]> {
FILE: apps/www/lib/tests/setup/console-guard.ts
constant ALLOWED_PATTERNS (line 3) | const ALLOWED_PATTERNS: RegExp[] = [];
function toMessage (line 8) | function toMessage(args: unknown[]): string {
function isAllowedMessage (line 26) | function isAllowedMessage(message: string): boolean {
FILE: apps/www/lib/tests/tool-ui/geo-map/geo-map-render.test.ts
type MockMapEvents (line 9) | type MockMapEvents = {
function DivWrapper (line 50) | function DivWrapper({
function LeafletWrapper (line 57) | function LeafletWrapper({
function PopupWrapper (line 63) | function PopupWrapper({
function TooltipWrapper (line 71) | function TooltipWrapper({
method observe (line 165) | observe() {}
method disconnect (line 166) | disconnect() {}
FILE: apps/www/lib/tests/tool-ui/weather-widget/canvas-resolver-parity.test.ts
constant REFERENCE_DATE (line 19) | const REFERENCE_DATE = new Date("2026-01-01T00:00:00Z");
constant REPO_CHECKPOINT_OVERRIDES (line 20) | const REPO_CHECKPOINT_OVERRIDES = mapToolUiPresetsToCompositor(
function resolveStudioCanvasProps (line 24) | function resolveStudioCanvasProps(
FILE: apps/www/lib/tests/tool-ui/weather-widget/weather-data-overlay-observer.test.ts
function installCssSupportsStub (line 10) | function installCssSupportsStub() {
class MockResizeObserver (line 38) | class MockResizeObserver {
method constructor (line 39) | constructor(_callback: ResizeObserverCallback) {}
method observe (line 40) | observe(target: Element) {
method disconnect (line 43) | disconnect() {
method constructor (line 66) | constructor(_callback: ResizeObserverCallback) {}
method observe (line 67) | observe(target: Element) {
method disconnect (line 70) | disconnect() {
class MockResizeObserver (line 65) | class MockResizeObserver {
method constructor (line 39) | constructor(_callback: ResizeObserverCallback) {}
method observe (line 40) | observe(target: Element) {
method disconnect (line 43) | disconnect() {
method constructor (line 66) | constructor(_callback: ResizeObserverCallback) {}
method observe (line 67) | observe(target: Element) {
method disconnect (line 70) | disconnect() {
FILE: apps/www/lib/tests/tool-ui/weather-widget/weather-runtime-codegen.test.ts
constant PROJECT_ROOT (line 18) | const PROJECT_ROOT = process.cwd();
constant WEATHER_RUNTIME_BUNDLE_PATH (line 19) | const WEATHER_RUNTIME_BUNDLE_PATH =
constant WEATHER_RUNTIME_MAX_BYTES (line 21) | const WEATHER_RUNTIME_MAX_BYTES = 120_000;
constant WEATHER_RUNTIME_MAX_LINES (line 22) | const WEATHER_RUNTIME_MAX_LINES = 120;
constant WEATHER_REGISTRY_ENTRY_PATH (line 23) | const WEATHER_REGISTRY_ENTRY_PATH = "public/r/weather-widget.json";
constant WEATHER_REGISTRY_MAX_BYTES (line 24) | const WEATHER_REGISTRY_MAX_BYTES = 170_000;
constant WEATHER_REGISTRY_RUNTIME_FILES (line 25) | const WEATHER_REGISTRY_RUNTIME_FILES = [
constant SHADER_EXPORT_NAMES (line 32) | const SHADER_EXPORT_NAMES = [
FILE: apps/www/lib/tests/tool-ui/weather-widget/weather-widget-layout.test.ts
function getClassForDataSlot (line 7) | function getClassForDataSlot(html: string, dataSlot: string): string {
FILE: apps/www/lib/utils.ts
function cn (line 4) | function cn(...inputs: ClassValue[]) {
FILE: apps/www/lib/weather-authoring/runtime/glass-panel-svg.tsx
type Dimensions (line 42) | interface Dimensions {
type GlassEffectOptions (line 47) | interface GlassEffectOptions {
constant DEFAULT_GLASS_OPTIONS (line 68) | const DEFAULT_GLASS_OPTIONS: GlassEffectOptions = {
type DisplacementMapParams (line 82) | interface DisplacementMapParams {
function buildDisplacementMapSvg (line 102) | function buildDisplacementMapSvg({
type DisplacementFilterParams (line 138) | interface DisplacementFilterParams extends DisplacementMapParams {
function buildDisplacementFilterUrl (line 150) | function buildDisplacementFilterUrl({
type BackdropFilterParams (line 202) | interface BackdropFilterParams {
function buildBackdropFilterValue (line 218) | function buildBackdropFilterValue({
function useElementDimensions (line 237) | function useElementDimensions(
function useSupportsBackdropFilter (line 274) | function useSupportsBackdropFilter(): boolean {
type GlassPanelProps (line 291) | interface GlassPanelProps {
function GlassPanel (line 306) | function GlassPanel({
function GlassPanelCSS (line 373) | function GlassPanelCSS() {
type GlassPanelUnderlayProps (line 394) | interface GlassPanelUnderlayProps {
function GlassPanelUnderlay (line 409) | function GlassPanelUnderlay({
type UseGlassStylesOptions (line 476) | interface UseGlassStylesOptions {
function useGlassStyles (line 494) | function useGlassStyles({
FILE: apps/www/lib/weather-authoring/weather-widget/effects/canvas-resolver-base.ts
function createStudioTimestamp (line 11) | function createStudioTimestamp(
function buildCompositorBaseFromWeather (line 28) | function buildCompositorBaseFromWeather(
function mapWeatherCompositorParamsToCanvasProps (line 147) | function mapWeatherCompositorParamsToCanvasProps(
function buildCanvasBaseFromWeather (line 226) | function buildCanvasBaseFromWeather(
FILE: apps/www/lib/weather-authoring/weather-widget/effects/canvas-resolver-runtime.ts
type ResolveRuntimeWeatherEffectsCanvasPropsInput (line 10) | interface ResolveRuntimeWeatherEffectsCanvasPropsInput extends WeatherEf...
function resolveWeatherEffectsCanvasRuntimeProps (line 19) | function resolveWeatherEffectsCanvasRuntimeProps(
FILE: apps/www/lib/weather-authoring/weather-widget/effects/canvas-resolver.ts
type WeatherEffectsCheckpointMode (line 27) | type WeatherEffectsCheckpointMode = "nearest" | "interpolated";
type ResolveWeatherEffectsCanvasPropsInput (line 29) | interface ResolveWeatherEffectsCanvasPropsInput extends WeatherEffectPar...
function resolveBaseForCheckpoint (line 39) | function resolveBaseForCheckpoint(
function resolveWeatherEffectsCanvasProps (line 51) | function resolveWeatherEffectsCanvasProps(
FILE: apps/www/lib/weather-authoring/weather-widget/effects/checkpoint-overrides.ts
type SurroundingCheckpoints (line 13) | interface SurroundingCheckpoints {
function getSurroundingCheckpoints (line 19) | function getSurroundingCheckpoints(timeOfDay: number): SurroundingCheckp...
function lerp (line 61) | function lerp(a: number, b: number, t: number): number {
function interpolatePartialObject (line 65) | function interpolatePartialObject<T extends object>(
function interpolateWeatherEffectsOverrides (line 119) | function interpolateWeatherEffectsOverrides(
function resolveInterpolatedOverridesForTime (line 205) | function resolveInterpolatedOverridesForTime(opts: {
function resolveConditionCheckpointOverridesForTime (line 223) | function resolveConditionCheckpointOverridesForTime(opts: {
FILE: apps/www/lib/weather-authoring/weather-widget/effects/custom-effect-props.ts
type WeatherEffectLayer (line 1) | type WeatherEffectLayer =
type CustomEffectProps (line 12) | interface CustomEffectProps {
FILE: apps/www/lib/weather-authoring/weather-widget/effects/effect-compositor-custom-props.ts
function sunAltitudeToLightIntensity (line 10) | function sunAltitudeToLightIntensity(sunAltitude: number): number {
function isLayerEnabled (line 18) | function isLayerEnabled(
function mapCustomEffectPropsToCanvasProps (line 28) | function mapCustomEffectPropsToCanvasProps(
FILE: apps/www/lib/weather-authoring/weather-widget/effects/effect-compositor-quality.ts
type ResolvedEffectQuality (line 3) | type ResolvedEffectQuality = "low" | "medium" | "high";
function resolveAutoQuality (line 5) | function resolveAutoQuality(): ResolvedEffectQuality {
function resolveEffectQuality (line 34) | function resolveEffectQuality(
function resolveEffectCanvasDpr (line 43) | function resolveEffectCanvasDpr(
FILE: apps/www/lib/weather-authoring/weather-widget/effects/effect-compositor-runtime.tsx
constant DEFAULT_TUNED_PRESETS (line 16) | const DEFAULT_TUNED_PRESETS: WeatherEffectsTunedPresets =
type EffectCompositorRuntimeProps (line 19) | interface EffectCompositorRuntimeProps {
function EffectCompositorRuntime (line 30) | function EffectCompositorRuntime({
FILE: apps/www/lib/weather-authoring/weather-widget/effects/effect-compositor.tsx
constant DEFAULT_CHECKPOINT_MODE (line 21) | const DEFAULT_CHECKPOINT_MODE: WeatherEffectsCheckpointMode = "nearest";
constant DEFAULT_TUNED_PRESETS (line 22) | const DEFAULT_TUNED_PRESETS: WeatherEffectsTunedPresets =
type EffectCompositorProps (line 25) | interface EffectCompositorProps {
function EffectCompositor (line 41) | function EffectCompositor({
FILE: apps/www/lib/weather-authoring/weather-widget/effects/generated/glass-panel-svg.generated.tsx
type Dimensions (line 7) | interface Dimensions {
type GlassEffectOptions (line 11) | interface GlassEffectOptions {
constant DEFAULT_GLASS_OPTIONS (line 20) | const DEFAULT_GLASS_OPTIONS: GlassEffectOptions = {
type DisplacementMapParams (line 29) | interface DisplacementMapParams {
function buildDisplacementMapSvg (line 35) | function buildDisplacementMapSvg({ width, height, radius, depth, }: Disp...
type DisplacementFilterParams (line 62) | interface DisplacementFilterParams extends DisplacementMapParams {
function buildDisplacementFilterUrl (line 66) | function buildDisplacementFilterUrl({ width, height, radius, depth, stre...
type BackdropFilterParams (line 99) | interface BackdropFilterParams {
function buildBackdropFilterValue (line 105) | function buildBackdropFilterValue({ filterUrl, blur, brightness, saturat...
function useElementDimensions (line 108) | function useElementDimensions(ref: RefObject<HTMLElement | null>): Dimen...
function useSupportsBackdropFilter (line 130) | function useSupportsBackdropFilter(): boolean {
type GlassPanelProps (line 139) | interface GlassPanelProps {
function GlassPanel (line 149) | function GlassPanel({ children, className, depth = DEFAULT_GLASS_OPTIONS...
function GlassPanelCSS (line 194) | function GlassPanelCSS() {
type GlassPanelUnderlayProps (line 212) | interface GlassPanelUnderlayProps {
function GlassPanelUnderlay (line 222) | function GlassPanelUnderlay({ children, className, depth = DEFAULT_GLASS...
type UseGlassStylesOptions (line 269) | interface UseGlassStylesOptions {
function useGlassStyles (line 281) | function useGlassStyles({ width, height, depth = DEFAULT_GLASS_OPTIONS.d...
FILE: apps/www/lib/weather-authoring/weather-widget/effects/generated/tuned-presets.generated.ts
constant TUNED_WEATHER_EFFECTS_CHECKPOINT_OVERRIDES (line 8) | const TUNED_WEATHER_EFFECTS_CHECKPOINT_OVERRIDES: Partial<
FILE: apps/www/lib/weather-authoring/weather-widget/effects/generated/weather-effect-shaders.generated.ts
constant FULLSCREEN_VERTEX (line 5) | const FULLSCREEN_VERTEX = "#version 300 es\nin vec4 a_position;out vec2 ...
constant CELESTIAL_FRAGMENT (line 7) | const CELESTIAL_FRAGMENT = "#version 300 es\nprecision highp float;in ve...
constant CLOUD_FRAGMENT (line 9) | const CLOUD_FRAGMENT = "#version 300 es\nprecision highp float;in vec2 v...
constant RAIN_FRAGMENT (line 11) | const RAIN_FRAGMENT = "#version 300 es\nprecision highp float;in vec2 v_...
constant LIGHTNING_FRAGMENT (line 13) | const LIGHTNING_FRAGMENT = "#version 300 es\nprecision highp float;in ve...
constant SNOW_FRAGMENT (line 15) | const SNOW_FRAGMENT = "#version 300 es\nprecision highp float;in vec2 v_...
constant COMPOSITE_FRAGMENT (line 17) | const COMPOSITE_FRAGMENT = "#version 300 es\nprecision highp float;in ve...
FILE: apps/www/lib/weather-authoring/weather-widget/effects/glass-style-resolver.ts
function resolveGlassBackdropFilterStyles (line 8) | function resolveGlassBackdropFilterStyles({
FILE: apps/www/lib/weather-authoring/weather-widget/effects/parameter-mapper.generated.js
function getTimeOfDay (line 5) | function getTimeOfDay(timestamp) {
function getMoonPhase (line 14) | function getMoonPhase(timestamp) {
function getSunAltitude (line 28) | function getSunAltitude(timestamp) {
function isNightTime (line 44) | function isNightTime(sunAltitude) {
constant CONDITION_BRIGHTNESS (line 47) | const CONDITION_BRIGHTNESS = {
function getSceneBrightness (line 62) | function getSceneBrightness(timestamp, conditionCode = "clear") {
function getWeatherTheme (line 74) | function getWeatherTheme(brightness, currentTheme) {
function timeOfDayToSunAltitude (line 85) | function timeOfDayToSunAltitude(timeOfDay) {
function getSceneBrightnessFromTimeOfDay (line 97) | function getSceneBrightnessFromTimeOfDay(
function mapWindSpeed (line 112) | function mapWindSpeed(mph = 0) {
function mapPrecipitation (line 117) | function mapPrecipitation(level) {
function mapVisibility (line 129) | function mapVisibility(miles = 10) {
function clamp01 (line 134) | function clamp01(value) {
function smoothstep (line 137) | function smoothstep(edge0, edge1, x) {
constant UNIFIED_CELESTIAL (line 141) | const UNIFIED_CELESTIAL = {
constant CELESTIAL_PRESETS (line 155) | const CELESTIAL_PRESETS = {
constant CONDITION_PRESETS (line 170) | const CONDITION_PRESETS = {
function mapWeatherToEffects (line 226) | function mapWeatherToEffects(params) {
function configToCloudProps (line 340) | function configToCloudProps(config) {
function configToRainProps (line 351) | function configToRainProps(config) {
function configToLightningProps (line 359) | function configToLightningProps(config) {
function configToSnowProps (line 367) | function configToSnowProps(config) {
function configToCelestialProps (line 375) | function configToCelestialProps(config) {
function configToPostProps (line 394) | function configToPostProps(config) {
FILE: apps/www/lib/weather-authoring/weather-widget/effects/parameter-mapper.ts
function getTimeOfDay (line 13) | function getTimeOfDay(timestamp?: string): number {
function getMoonPhase (line 30) | function getMoonPhase(timestamp?: string): number {
function getSunAltitude (line 53) | function getSunAltitude(timestamp?: string): number {
function isNightTime (line 80) | function isNightTime(sunAltitude: number): boolean {
constant CONDITION_BRIGHTNESS (line 89) | const CONDITION_BRIGHTNESS: Record<WeatherConditionCode, number> = {
function getSceneBrightness (line 112) | function getSceneBrightness(
type WeatherTheme (line 144) | type WeatherTheme = "light" | "dark";
function getWeatherTheme (line 146) | function getWeatherTheme(
function timeOfDayToSunAltitude (line 169) | function timeOfDayToSunAltitude(timeOfDay: number): number {
function getSceneBrightnessFromTimeOfDay (line 192) | function getSceneBrightnessFromTimeOfDay(
function mapWindSpeed (line 215) | function mapWindSpeed(mph: number = 0): number {
function mapPrecipitation (line 224) | function mapPrecipitation(
function mapVisibility (line 243) | function mapVisibility(miles: number = 10): number {
function clamp01 (line 249) | function clamp01(value: number): number {
function smoothstep (line 253) | function smoothstep(edge0: number, edge1: number, x: number): number {
type CelestialPreset (line 281) | interface CelestialPreset {
constant UNIFIED_CELESTIAL (line 297) | const UNIFIED_CELESTIAL: CelestialPreset = {
constant CELESTIAL_PRESETS (line 312) | const CELESTIAL_PRESETS: Record<WeatherConditionCode, CelestialPreset> = {
constant CONDITION_PRESETS (line 332) | const CONDITION_PRESETS: Record<
function mapWeatherToEffects (line 408) | function mapWeatherToEffects(
function configToCloudProps (line 564) | function configToCloudProps(config: EffectLayerConfig) {
function confi
Condensed preview — 779 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,728K chars).
[
{
"path": ".changeset/config.json",
"chars": 145,
"preview": "{\n \"$schema\": \"https://unpkg.com/@changesets/config@3.0.1/schema.json\",\n \"access\": \"public\",\n \"privatePackages\": {\n "
},
{
"path": ".git-blame-ignore-revs",
"chars": 92,
"preview": "# oxfmt bulk reformat (Prettier → Oxfmt migration)\ne052c5666f770d1521b8e5e574d2fa69152f89dc\n"
},
{
"path": ".githooks/pre-commit",
"chars": 67,
"preview": "#!/usr/bin/env sh\nset -eu\n\npnpm hooks:pre-commit\n\npnpm lint-staged\n"
},
{
"path": ".githooks/pre-push",
"chars": 47,
"preview": "#!/usr/bin/env sh\nset -eu\n\npnpm hooks:pre-push\n"
},
{
"path": ".github/pull_request_template.md",
"chars": 142,
"preview": "## Summary\n\n## Verification\n\n- [ ] Ran `pnpm verify:ci`\n- [ ] Committed updated `public/r` artifacts when Tool UI or reg"
},
{
"path": ".github/workflows/changeset.yaml",
"chars": 2316,
"preview": "name: Changesets\n\non:\n push:\n branches:\n - main\n\npermissions:\n contents: write\n pull-requests: write\n\nconcurr"
},
{
"path": ".github/workflows/ci.yml",
"chars": 911,
"preview": "name: CI\n\non:\n pull_request:\n branches: [main]\n push:\n branches: [main]\n\njobs:\n verify:\n runs-on: ubuntu-lat"
},
{
"path": ".github/workflows/npm-publish.yaml",
"chars": 1956,
"preview": "name: npm Publish\n\non:\n repository_dispatch:\n types: [npm-publish]\n\npermissions:\n id-token: write\n contents: write"
},
{
"path": ".gitignore",
"chars": 445,
"preview": "# Dependencies\nnode_modules\n/.pnp\n.pnp.*\n\n# Testing\ncoverage\n\n# Next.js\n.next/\nout/\n\n# Production\nbuild\ndist\n\n# Misc\n.DS"
},
{
"path": ".prettierignore",
"chars": 267,
"preview": "# Generated artifacts (managed by build scripts)\napps/www/public/r/\napps/www/components/tool-ui/weather-widget/generated"
},
{
"path": "AGENTS.md",
"chars": 2045,
"preview": "# AGENTS.md\n\n## Cursor Cloud specific instructions\n\n### Project overview\n\nTool UI is a Next.js 16 documentation/demo sit"
},
{
"path": "AGENT_CHANGELOG.md",
"chars": 26231,
"preview": "# Agent Changelog\n\n> This file helps coding agents understand project evolution, key decisions, and deprecated patterns."
},
{
"path": "CLAUDE.md",
"chars": 3621,
"preview": "# Tool UI\n\nCopy/paste component library (shadcn/ui model) for AI assistant interfaces. Users copy component directories "
},
{
"path": "LICENSE.md",
"chars": 1073,
"preview": "MIT License\n\nCopyright (c) 2025 AgentbaseAI Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "README.md",
"chars": 2759,
"preview": "<a href=\"https://tool-ui.com\">\n <img src=\".github/assets/header.png\" alt=\"Tool UI\" width=\"100%\">\n</a>\n\nCopy/paste React"
},
{
"path": "apps/www/.oxfmtrc.jsonc",
"chars": 468,
"preview": "{\n \"$schema\": \"https://raw.githubusercontent.com/nicolo-ribaudo/oxfmt/main/npm/oxfmt/schema.json\",\n\n // Match existing"
},
{
"path": "apps/www/.oxlintrc.json",
"chars": 1734,
"preview": "{\n \"$schema\": \"./node_modules/oxlint/configuration_schema.json\",\n \"plugins\": [\n \"typescript\",\n \"react\",\n \"uni"
},
{
"path": "apps/www/.prettierignore",
"chars": 238,
"preview": "# Generated artifacts (managed by build scripts)\n.next/\npublic/r/\ncomponents/tool-ui/weather-widget/generated/\nlib/weath"
},
{
"path": "apps/www/app/api/builder/chat/route.ts",
"chars": 3627,
"preview": "import { openai } from \"@ai-sdk/openai\";\nimport { anthropic } from \"@ai-sdk/anthropic\";\nimport { streamText, convertToMo"
},
{
"path": "apps/www/app/api/builder/create-freestyle/route.ts",
"chars": 1066,
"preview": "import { createChat } from \"@/lib/integrations/freestyle/create-chat\";\n\nexport async function POST() {\n try {\n if (!"
},
{
"path": "apps/www/app/api/chat/route.ts",
"chars": 10378,
"preview": "import { openai } from \"@ai-sdk/openai\";\nimport { streamText, convertToModelMessages, tool } from \"ai\";\nimport { z } fro"
},
{
"path": "apps/www/app/api/mcp-tools/route.ts",
"chars": 2921,
"preview": "import { experimental_createMCPClient as createMCPClient } from \"@ai-sdk/mcp\";\n\nexport const runtime = \"edge\";\n\ninterfac"
},
{
"path": "apps/www/app/api/playground/chat/route.ts",
"chars": 3055,
"preview": "import type { NextRequest } from \"next/server\";\n\nimport type { UIMessage } from \"ai\";\n\nimport { findPrototype, streamPro"
},
{
"path": "apps/www/app/api/weather-tuning/_lib/tuned-presets-io.ts",
"chars": 534,
"preview": "import { readFile } from \"fs/promises\";\nimport path from \"path\";\n\nimport type { WeatherEffectsTunedPresets } from \"../.."
},
{
"path": "apps/www/app/api/weather-tuning/apply/route.ts",
"chars": 3061,
"preview": "import { writeFile } from \"fs/promises\";\n\nimport type { WeatherConditionCode } from \"../../../../lib/weather-authoring/w"
},
{
"path": "apps/www/app/api/weather-tuning/recover/route.ts",
"chars": 759,
"preview": "import { mapToolUiPresetsToCompositor } from \"../../../sandbox/weather-tuning/lib/tool-ui-import\";\nimport { readToolUiTu"
},
{
"path": "apps/www/app/builder/layout.tsx",
"chars": 452,
"preview": "import type { ReactNode } from \"react\";\nimport ContentLayout from \"@/app/components/layout/page-shell\";\nimport { HeaderF"
},
{
"path": "apps/www/app/builder/opengraph-image.tsx",
"chars": 363,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/builder/page.tsx",
"chars": 29365,
"preview": "\"use client\";\n\nimport {\n AssistantRuntimeProvider,\n ThreadPrimitive,\n ComposerPrimitive,\n MessagePrimitive,\n useAui"
},
{
"path": "apps/www/app/components/analytics/posthog-init.client.tsx",
"chars": 1225,
"preview": "\"use client\";\n\nimport { useEffect } from \"react\";\n\nconst apiKey = process.env[\"NEXT_PUBLIC_POSTHOG_API_KEY\"];\nconst isDe"
},
{
"path": "apps/www/app/components/assistant-ui/markdown-text.tsx",
"chars": 5853,
"preview": "\"use client\";\n\nimport \"@assistant-ui/react-markdown/styles/dot.css\";\n\nimport {\n type CodeHeaderProps,\n MarkdownTextPri"
},
{
"path": "apps/www/app/components/assistant-ui/thread-list.tsx",
"chars": 4649,
"preview": "import { useCallback, type FC } from \"react\";\nimport {\n ThreadListItemPrimitive,\n ThreadListPrimitive,\n useAuiState,\n"
},
{
"path": "apps/www/app/components/assistant-ui/tool-fallback.tsx",
"chars": 1793,
"preview": "\"use client\";\n\nimport type { ToolCallMessagePartComponent } from \"@assistant-ui/react\";\nimport { CheckIcon, ChevronDownI"
},
{
"path": "apps/www/app/components/assistant-ui/tooltip-icon-button.tsx",
"chars": 1136,
"preview": "\"use client\";\n\nimport { ComponentPropsWithRef, forwardRef } from \"react\";\nimport { Slottable } from \"@radix-ui/react-slo"
},
{
"path": "apps/www/app/components/builder/mcp-icon.tsx",
"chars": 1169,
"preview": "import * as React from \"react\";\n\nexport function MCPIcon({\n className,\n ...props\n}: React.SVGProps<SVGSVGElement>) {\n "
},
{
"path": "apps/www/app/components/builder/theme-toggle.tsx",
"chars": 1534,
"preview": "\"use client\";\n\nimport * as React from \"react\";\nimport { Moon, Sun } from \"lucide-react\";\nimport { useTheme } from \"next-"
},
{
"path": "apps/www/app/components/builder/webview-actions.ts",
"chars": 243,
"preview": "\"use server\";\n\nimport { requestDevServer as requestDevServerInner } from \"@/lib/integrations/freestyle/create-chat\";\n\nex"
},
{
"path": "apps/www/app/components/builder/webview.tsx",
"chars": 2535,
"preview": "\"use client\";\n\nimport { requestDevServer as requestDevServerInner } from \"./webview-actions\";\nimport \"@/app/styles/build"
},
{
"path": "apps/www/app/components/home/chat-showcase.tsx",
"chars": 25073,
"preview": "\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { AnimatePresence, moti"
},
{
"path": "apps/www/app/components/home/demo-chat.tsx",
"chars": 3894,
"preview": "\"use client\";\n\nimport { useMemo } from \"react\";\nimport {\n AssistantRuntimeProvider,\n ThreadPrimitive,\n Tools,\n useAu"
},
{
"path": "apps/www/app/components/home/faux-chat-shell-animated.tsx",
"chars": 3411,
"preview": "\"use client\";\n\nimport { motion } from \"motion/react\";\nimport { FauxChatShellNoLightOverlay } from \"./faux-chat-shell\";\ni"
},
{
"path": "apps/www/app/components/home/faux-chat-shell-mobile-animated.tsx",
"chars": 3476,
"preview": "\"use client\";\n\nimport { motion } from \"motion/react\";\nimport { FauxChatShellMobile } from \"./faux-chat-shell-mobile\";\nim"
},
{
"path": "apps/www/app/components/home/faux-chat-shell-mobile.tsx",
"chars": 2873,
"preview": "\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { cn } from \"@/lib/ui/cn\";\nimport { ChatShowcase } fr"
},
{
"path": "apps/www/app/components/home/faux-chat-shell.tsx",
"chars": 6261,
"preview": "\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { cn } from \"@/lib/ui/cn\";\nimport { ChatShowc"
},
{
"path": "apps/www/app/components/home/home-background.tsx",
"chars": 485,
"preview": "\"use client\";\n\nexport function HomeBackground() {\n return (\n <>\n <div\n className=\"bg-background pointer-"
},
{
"path": "apps/www/app/components/home/home-hero.tsx",
"chars": 2702,
"preview": "\"use client\";\n\nimport Link from \"next/link\";\nimport { useRouter } from \"next/navigation\";\nimport { ArrowRight } from \"lu"
},
{
"path": "apps/www/app/components/home/home-hexnut-scene.tsx",
"chars": 532,
"preview": "\"use client\";\n\nimport dynamic from \"next/dynamic\";\n\n// Dynamic import with SSR disabled for Three.js components\nconst He"
},
{
"path": "apps/www/app/components/home/noise-texture.ts",
"chars": 1251,
"preview": "/**\n * Generates a data URI for a subtle noise texture to reduce gradient banding\n * @param size - Size of the noise til"
},
{
"path": "apps/www/app/components/layout/app-header.server.tsx",
"chars": 3151,
"preview": "import { ReactNode } from \"react\";\nimport Link from \"next/link\";\nimport { Button } from \"@/components/ui/button\";\n\nimpor"
},
{
"path": "apps/www/app/components/layout/app-shell-animated.client.tsx",
"chars": 1507,
"preview": "\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { ResponsiveH"
},
{
"path": "apps/www/app/components/layout/app-shell.tsx",
"chars": 1138,
"preview": "import type { ReactNode } from \"react\";\nimport { ResponsiveHeader } from \"@/app/components/layout/app-header.server\";\nim"
},
{
"path": "apps/www/app/components/layout/header-active-link.client.tsx",
"chars": 717,
"preview": "\"use client\";\n\nimport Link from \"next/link\";\nimport { usePathname } from \"next/navigation\";\nimport { cn } from \"@/lib/ui"
},
{
"path": "apps/www/app/components/layout/mobile-nav-sheet-gate.client.tsx",
"chars": 1140,
"preview": "\"use client\";\n\nimport dynamic from \"next/dynamic\";\nimport { usePathname } from \"next/navigation\";\nimport { useEffect, us"
},
{
"path": "apps/www/app/components/layout/mobile-nav-sheet.client.tsx",
"chars": 8492,
"preview": "\"use client\";\n\nimport React from \"react\";\nimport Link from \"next/link\";\nimport { usePathname } from \"next/navigation\";\ni"
},
{
"path": "apps/www/app/components/layout/page-shell.tsx",
"chars": 988,
"preview": "import type { ReactNode } from \"react\";\n\ntype ContentLayoutProps = {\n children: ReactNode;\n sidebar?: ReactNode;\n};\n\ne"
},
{
"path": "apps/www/app/components/layout/tracked-external-anchor.client.tsx",
"chars": 760,
"preview": "\"use client\";\n\nimport * as React from \"react\";\nimport { analytics } from \"@/lib/analytics\";\n\ntype ExternalDestination = "
},
{
"path": "apps/www/app/components/mdx/features.tsx",
"chars": 2877,
"preview": "import { cn } from \"@/lib/ui/cn\";\nimport type { LucideIcon } from \"lucide-react\";\nimport {\n Palette,\n Copy,\n Hash,\n "
},
{
"path": "apps/www/app/components/mdx/mermaid.tsx",
"chars": 3647,
"preview": "\"use client\";\n\nimport { useEffect, useId, useRef, useState } from \"react\";\nimport { useTheme } from \"next-themes\";\n\ninte"
},
{
"path": "apps/www/app/components/theme/theme-provider.tsx",
"chars": 342,
"preview": "\"use client\";\n\nimport * as React from \"react\";\nimport { ThemeProvider as NextThemesProvider } from \"next-themes\";\n\ntype "
},
{
"path": "apps/www/app/components/visuals/spinning-hexnut/hexnut-scene.tsx",
"chars": 16211,
"preview": "\"use client\";\n\nimport { useEffect, useRef, useMemo, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\ni"
},
{
"path": "apps/www/app/docs/_components/chat-context-preview.tsx",
"chars": 1250,
"preview": "import type { ReactNode } from \"react\";\nimport { cn } from \"@/lib/ui/cn\";\n\ninterface ChatBubbleProps {\n role: \"user\" | "
},
{
"path": "apps/www/app/docs/_components/collaboration-diagram.tsx",
"chars": 3628,
"preview": "\"use client\";\n\nexport function CollaborationDiagram() {\n return (\n <svg\n viewBox=\"0 0 600 200\"\n className="
},
{
"path": "apps/www/app/docs/_components/component-docs-tabs.tsx",
"chars": 4481,
"preview": "\"use client\";\n\nimport dynamic from \"next/dynamic\";\nimport { memo, useCallback, useMemo, useRef, type ReactNode } from \"r"
},
{
"path": "apps/www/app/docs/_components/component-preview-shell.tsx",
"chars": 9940,
"preview": "\"use client\";\n\nimport { memo, useCallback, type ReactNode } from \"react\";\nimport { Panel, PanelGroup, PanelResizeHandle "
},
{
"path": "apps/www/app/docs/_components/component-preview.tsx",
"chars": 2851,
"preview": "\"use client\";\n\nimport { useCallback, useState } from \"react\";\nimport { ComponentPreviewShell } from \"./component-preview"
},
{
"path": "apps/www/app/docs/_components/component-previews/social-post-preview.tsx",
"chars": 12013,
"preview": "\"use client\";\n\nimport { useCallback, useMemo, useState, type ReactNode } from \"react\";\nimport { useSearchParams, usePath"
},
{
"path": "apps/www/app/docs/_components/copy-markdown-button.tsx",
"chars": 1002,
"preview": "\"use client\";\n\nimport type { MouseEventHandler } from \"react\";\nimport { useCopyButton } from \"fumadocs-ui/utils/use-copy"
},
{
"path": "apps/www/app/docs/_components/docs-article.tsx",
"chars": 889,
"preview": "\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { DocsBorderedShell } from \"./docs-bordered-shell\";\nimport"
},
{
"path": "apps/www/app/docs/_components/docs-bordered-shell.tsx",
"chars": 529,
"preview": "import type { ReactNode } from \"react\";\nimport { cn } from \"@/lib/ui/cn\";\n\nexport function DocsBorderedShell({\n childre"
},
{
"path": "apps/www/app/docs/_components/docs-content.tsx",
"chars": 530,
"preview": "import type { ReactNode } from \"react\";\nimport { cn } from \"@/lib/ui/cn\";\nimport { DocsPager } from \"./docs-pager\";\n\nint"
},
{
"path": "apps/www/app/docs/_components/docs-header.tsx",
"chars": 1359,
"preview": "import { CopyMarkdownButton } from \"./copy-markdown-button\";\nimport { HeaderPreviewTabs } from \"./header-preview-tabs\";\n"
},
{
"path": "apps/www/app/docs/_components/docs-nav.tsx",
"chars": 7792,
"preview": "\"use client\";\n\nimport React, { useState } from \"react\";\nimport Link from \"next/link\";\nimport { usePathname } from \"next/"
},
{
"path": "apps/www/app/docs/_components/docs-pager.tsx",
"chars": 2556,
"preview": "\"use client\";\n\nimport * as React from \"react\";\nimport Link from \"next/link\";\nimport { usePathname } from \"next/navigatio"
},
{
"path": "apps/www/app/docs/_components/docs-pages.ts",
"chars": 993,
"preview": "import { componentsRegistry } from \"@/lib/docs/component-registry\";\n\nexport type DocsPageLink = {\n path: string;\n labe"
},
{
"path": "apps/www/app/docs/_components/docs-search-shortcut.ts",
"chars": 652,
"preview": "export type SearchShortcutEvent = Pick<\n KeyboardEvent,\n \"metaKey\" | \"ctrlKey\" | \"key\" | \"preventDefault\" | \"defaultPr"
},
{
"path": "apps/www/app/docs/_components/docs-search.client.tsx",
"chars": 5433,
"preview": "\"use client\";\n\nimport * as React from \"react\";\nimport Link from \"next/link\";\nimport { SearchIcon } from \"lucide-react\";\n"
},
{
"path": "apps/www/app/docs/_components/docs-toc-context.tsx",
"chars": 1354,
"preview": "\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useState,\n type ReactNode,\n} from \"react\";\nimpo"
},
{
"path": "apps/www/app/docs/_components/docs-toc-wrapper.tsx",
"chars": 238,
"preview": "import { DocsToc } from \"./docs-toc\";\n\nexport function DocsTocWrapper() {\n return (\n <div className=\"hidden min-w-0 "
},
{
"path": "apps/www/app/docs/_components/docs-toc.tsx",
"chars": 4663,
"preview": "\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { cn } from \"@/lib/ui/cn\";\nimpor"
},
{
"path": "apps/www/app/docs/_components/gallery-analytics.client.tsx",
"chars": 1341,
"preview": "\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { analytics } from \"@/lib/analytics\";\n\nexport function "
},
{
"path": "apps/www/app/docs/_components/gallery-card-header.tsx",
"chars": 4253,
"preview": "\"use client\";\n\nimport Link from \"next/link\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Sheet,\n SheetC"
},
{
"path": "apps/www/app/docs/_components/gallery-docs-link.tsx",
"chars": 1598,
"preview": "\"use client\";\n\nimport Link from \"next/link\";\nimport { ArrowRight } from \"lucide-react\";\nimport { analytics } from \"@/lib"
},
{
"path": "apps/www/app/docs/_components/header-preview-tabs.tsx",
"chars": 2511,
"preview": "\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { Tab, Tabs } from \"fumadocs-ui/componen"
},
{
"path": "apps/www/app/docs/_components/install-command-block.tsx",
"chars": 3708,
"preview": "\"use client\";\n\nimport type { MouseEventHandler } from \"react\";\nimport { Check, Copy as CopyIcon } from \"lucide-react\";\ni"
},
{
"path": "apps/www/app/docs/_components/install-command-line.tsx",
"chars": 392,
"preview": "\"use client\";\n\nimport { InstallCommandBlock } from \"./install-command-block\";\n\ninterface InstallCommandLineProps {\n com"
},
{
"path": "apps/www/app/docs/_components/interactive-option-demo.tsx",
"chars": 3058,
"preview": "\"use client\";\n\nimport { useCallback, useState } from \"react\";\nimport { RotateCcw } from \"lucide-react\";\nimport { MockThr"
},
{
"path": "apps/www/app/docs/_components/mdx-to-markdown.ts",
"chars": 725,
"preview": "import { readFileSync } from \"fs\";\nimport { join } from \"path\";\n\n/**\n * Reads an MDX file and returns it with minimal cl"
},
{
"path": "apps/www/app/docs/_components/mock-thread.tsx",
"chars": 1653,
"preview": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/ui/cn\";\n\ninterface MockMessageProps {\n role: \""
},
{
"path": "apps/www/app/docs/_components/preset-example.tsx",
"chars": 12024,
"preview": "\"use client\";\n\nimport { TrackedDynamicCodeBlock } from \"./tracked-dynamic-codeblock\";\nimport { Tabs, Tab } from \"fumadoc"
},
{
"path": "apps/www/app/docs/_components/preset-selector.tsx",
"chars": 5784,
"preview": "\"use client\";\n\nimport {\n Item,\n ItemContent,\n ItemDescription,\n ItemGroup,\n ItemTitle,\n} from \"@/components/ui/item"
},
{
"path": "apps/www/app/docs/_components/tracked-dynamic-codeblock.tsx",
"chars": 4767,
"preview": "\"use client\";\n\nimport {\n Children,\n cloneElement,\n isValidElement,\n useCallback,\n type ReactElement,\n type ReactNo"
},
{
"path": "apps/www/app/docs/actions/actions-examples.tsx",
"chars": 18777,
"preview": "\"use client\";\n\nimport { useState } from \"react\";\nimport { DataTable } from \"@/components/tool-ui/data-table\";\nimport {\n "
},
{
"path": "apps/www/app/docs/actions/content.mdx",
"chars": 5086,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport {\n ActionFlowCommitVisual,\n ActionFlowRenderVisual,\n "
},
{
"path": "apps/www/app/docs/actions/opengraph-image.tsx",
"chars": 402,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/actions/page.tsx",
"chars": 380,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { DocsArticle } from \"../_components/d"
},
{
"path": "apps/www/app/docs/advanced/content.mdx",
"chars": 7924,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader\n title=\"Advanced\"\n description=\"Typing, frontend"
},
{
"path": "apps/www/app/docs/advanced/opengraph-image.tsx",
"chars": 364,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/advanced/page.tsx",
"chars": 407,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { DocsArticle } from \"../_components/d"
},
{
"path": "apps/www/app/docs/agent-skills/content.mdx",
"chars": 3123,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader\n title=\"Agent Skills\"\n description=\"AI-assisted "
},
{
"path": "apps/www/app/docs/agent-skills/opengraph-image.tsx",
"chars": 400,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/agent-skills/page.tsx",
"chars": 412,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { DocsArticle } from \"../_components/d"
},
{
"path": "apps/www/app/docs/approval-card/content.mdx",
"chars": 6066,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { ApprovalCard } from \"@/components/tool-ui/approval-car"
},
{
"path": "apps/www/app/docs/approval-card/opengraph-image.tsx",
"chars": 396,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/approval-card/page.tsx",
"chars": 433,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/audio/content.mdx",
"chars": 4233,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { Audio } from \"@/components/tool-ui/audio\";\n\n<DocsHeade"
},
{
"path": "apps/www/app/docs/audio/opengraph-image.tsx",
"chars": 370,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/audio/page.tsx",
"chars": 413,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/changelog/content.mdx",
"chars": 6049,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader title=\"Changelog\" mdxPath=\"app/docs/changelog/cont"
},
{
"path": "apps/www/app/docs/changelog/opengraph-image.tsx",
"chars": 374,
"preview": "import {\n contentType as ogContentType,\n generateOgImage,\n size as ogSize,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/changelog/page.tsx",
"chars": 404,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { DocsArticle } from \"../_components/d"
},
{
"path": "apps/www/app/docs/chart/content.mdx",
"chars": 5399,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader\n title=\"Chart\"\n description=\"Display interactive"
},
{
"path": "apps/www/app/docs/chart/opengraph-image.tsx",
"chars": 368,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/chart/page.tsx",
"chars": 411,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/citation/content.mdx",
"chars": 4861,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { Citation } from \"@/components/tool-ui/citation\";\n\n<Doc"
},
{
"path": "apps/www/app/docs/citation/opengraph-image.tsx",
"chars": 391,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/citation/page.tsx",
"chars": 424,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/code-block/content.mdx",
"chars": 5094,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader\n title=\"Code Block\"\n description=\"Display syntax"
},
{
"path": "apps/www/app/docs/code-block/opengraph-image.tsx",
"chars": 393,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/code-block/page.tsx",
"chars": 427,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/code-diff/content.mdx",
"chars": 4612,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader\n title=\"Code Diff\"\n description=\"Display syntax-"
},
{
"path": "apps/www/app/docs/code-diff/opengraph-image.tsx",
"chars": 401,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/code-diff/page.tsx",
"chars": 434,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/data-table/content.mdx",
"chars": 14007,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { DataTable } from \"@/components/tool-ui/data-table\";\nim"
},
{
"path": "apps/www/app/docs/data-table/formatting-gallery.tsx",
"chars": 6607,
"preview": "\"use client\";\n\nimport * as React from \"react\";\nimport {\n renderFormattedValue,\n type FormatConfig,\n} from \"@/component"
},
{
"path": "apps/www/app/docs/data-table/opengraph-image.tsx",
"chars": 395,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/data-table/page.tsx",
"chars": 429,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/data-table/tasks-demo.tsx",
"chars": 2092,
"preview": "\"use client\";\n\nimport {\n Column,\n DataTable,\n DataTableRowData,\n} from \"@/components/tool-ui/data-table\";\nimport { ge"
},
{
"path": "apps/www/app/docs/design-guidelines/content.mdx",
"chars": 7283,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { MockThread, MockMessage } from \"../_components/mock-th"
},
{
"path": "apps/www/app/docs/design-guidelines/opengraph-image.tsx",
"chars": 400,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/design-guidelines/page.tsx",
"chars": 432,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { DocsArticle } from \"../_components/d"
},
{
"path": "apps/www/app/docs/gallery/opengraph-image.tsx",
"chars": 363,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/gallery/page.tsx",
"chars": 15517,
"preview": "import type { Metadata } from \"next\";\nimport dynamic from \"next/dynamic\";\nimport type { ReactNode } from \"react\";\n\nimpor"
},
{
"path": "apps/www/app/docs/geo-map/content.mdx",
"chars": 9395,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader\n title=\"Geo Map\"\n description=\"Display geolocate"
},
{
"path": "apps/www/app/docs/geo-map/opengraph-image.tsx",
"chars": 397,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/geo-map/page.tsx",
"chars": 428,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/image/content.mdx",
"chars": 4530,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { Image } from \"@/components/tool-ui/image\";\n\n<DocsHeade"
},
{
"path": "apps/www/app/docs/image/opengraph-image.tsx",
"chars": 387,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/image/page.tsx",
"chars": 417,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/image-gallery/content.mdx",
"chars": 5033,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { ImageGallery } from \"@/components/tool-ui/image-galler"
},
{
"path": "apps/www/app/docs/image-gallery/opengraph-image.tsx",
"chars": 403,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/image-gallery/page.tsx",
"chars": 440,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/instagram-post/content.mdx",
"chars": 3727,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { InstagramPost } from \"@/components/tool-ui/instagram-p"
},
{
"path": "apps/www/app/docs/instagram-post/opengraph-image.tsx",
"chars": 378,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/instagram-post/page.tsx",
"chars": 429,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/item-carousel/content.mdx",
"chars": 5743,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader\n title=\"Item Carousel\"\n description=\"Horizontal "
},
{
"path": "apps/www/app/docs/item-carousel/opengraph-image.tsx",
"chars": 399,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/item-carousel/page.tsx",
"chars": 445,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/layout.tsx",
"chars": 1145,
"preview": "import type { ReactNode } from \"react\";\nimport type { Metadata } from \"next\";\nimport { NuqsAdapter } from \"nuqs/adapters"
},
{
"path": "apps/www/app/docs/link-preview/content.mdx",
"chars": 4118,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { LinkPreview } from \"@/components/tool-ui/link-preview\""
},
{
"path": "apps/www/app/docs/link-preview/opengraph-image.tsx",
"chars": 375,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/link-preview/page.tsx",
"chars": 424,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/linkedin-post/content.mdx",
"chars": 3560,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { LinkedInPost } from \"@/components/tool-ui/linkedin-pos"
},
{
"path": "apps/www/app/docs/linkedin-post/opengraph-image.tsx",
"chars": 375,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/linkedin-post/page.tsx",
"chars": 425,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/message-draft/content.mdx",
"chars": 6399,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { MessageDraft } from \"@/components/tool-ui/message-draf"
},
{
"path": "apps/www/app/docs/message-draft/opengraph-image.tsx",
"chars": 401,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/message-draft/page.tsx",
"chars": 453,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/option-list/content.mdx",
"chars": 6348,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader\n title=\"Option List\"\n description=\"Let users sel"
},
{
"path": "apps/www/app/docs/option-list/opengraph-image.tsx",
"chars": 393,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/option-list/page.tsx",
"chars": 428,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/order-summary/content.mdx",
"chars": 8704,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { OrderSummary } from \"@/components/tool-ui/order-summar"
},
{
"path": "apps/www/app/docs/order-summary/opengraph-image.tsx",
"chars": 406,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/order-summary/page.tsx",
"chars": 477,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/overview/content.mdx",
"chars": 8163,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { MockThread, MockMessage } from \"../_components/mock-th"
},
{
"path": "apps/www/app/docs/overview/opengraph-image.tsx",
"chars": 370,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/overview/page.tsx",
"chars": 403,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { DocsArticle } from \"../_components/d"
},
{
"path": "apps/www/app/docs/page.tsx",
"chars": 118,
"preview": "import { redirect } from \"next/navigation\";\n\nexport default function DocsIndexPage() {\n redirect(\"/docs/gallery\");\n}\n"
},
{
"path": "apps/www/app/docs/parameter-slider/content.mdx",
"chars": 6486,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { ParameterSlider } from \"@/components/tool-ui/parameter"
},
{
"path": "apps/www/app/docs/parameter-slider/opengraph-image.tsx",
"chars": 402,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/parameter-slider/page.tsx",
"chars": 452,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/plan/content.mdx",
"chars": 5783,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader\n title=\"Plan\"\n description=\"Display step-by-step"
},
{
"path": "apps/www/app/docs/plan/opengraph-image.tsx",
"chars": 363,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/plan/page.tsx",
"chars": 405,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/preferences-panel/content.mdx",
"chars": 9632,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { PreferencesPanel } from \"@/components/tool-ui/preferen"
},
{
"path": "apps/www/app/docs/preferences-panel/opengraph-image.tsx",
"chars": 376,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/preferences-panel/page.tsx",
"chars": 461,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/progress-tracker/content.mdx",
"chars": 7009,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { ProgressTracker } from \"@/components/tool-ui/progress-"
},
{
"path": "apps/www/app/docs/progress-tracker/opengraph-image.tsx",
"chars": 416,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/progress-tracker/page.tsx",
"chars": 466,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/question-flow/content.mdx",
"chars": 7375,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader\n title=\"Question Flow\"\n description=\"Multi-step "
},
{
"path": "apps/www/app/docs/question-flow/opengraph-image.tsx",
"chars": 401,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/question-flow/page.tsx",
"chars": 438,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/quick-start/content.mdx",
"chars": 7138,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { Alert, AlertDescription, AlertTitle } from \"@/componen"
},
{
"path": "apps/www/app/docs/quick-start/opengraph-image.tsx",
"chars": 371,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/quick-start/page.tsx",
"chars": 402,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { DocsArticle } from \"../_components/d"
},
{
"path": "apps/www/app/docs/receipts/content.mdx",
"chars": 5072,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { MockThread, MockMessage } from \"../_components/mock-th"
},
{
"path": "apps/www/app/docs/receipts/opengraph-image.tsx",
"chars": 392,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/receipts/page.tsx",
"chars": 405,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { DocsArticle } from \"../_components/d"
},
{
"path": "apps/www/app/docs/stats-display/content.mdx",
"chars": 7709,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { StatsDisplay } from \"@/components/tool-ui/stats-displa"
},
{
"path": "apps/www/app/docs/stats-display/opengraph-image.tsx",
"chars": 375,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/stats-display/page.tsx",
"chars": 425,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/terminal/content.mdx",
"chars": 5222,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\n\n<DocsHeader\n title=\"Terminal\"\n description=\"Show command-lin"
},
{
"path": "apps/www/app/docs/terminal/opengraph-image.tsx",
"chars": 369,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/terminal/page.tsx",
"chars": 415,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/video/content.mdx",
"chars": 4848,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { Video } from \"@/components/tool-ui/video\";\n\n<DocsHeade"
},
{
"path": "apps/www/app/docs/video/opengraph-image.tsx",
"chars": 369,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/video/page.tsx",
"chars": 412,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
},
{
"path": "apps/www/app/docs/weather-widget/content.mdx",
"chars": 9553,
"preview": "import { DocsHeader } from \"../_components/docs-header\";\nimport { WeatherWidget } from \"@/components/tool-ui/weather-wid"
},
{
"path": "apps/www/app/docs/weather-widget/opengraph-image.tsx",
"chars": 401,
"preview": "import {\n generateOgImage,\n size as ogSize,\n contentType as ogContentType,\n} from \"@/lib/og/og-image\";\n\nexport const "
},
{
"path": "apps/www/app/docs/weather-widget/page.tsx",
"chars": 439,
"preview": "import type { Metadata } from \"next\";\nimport Content from \"./content.mdx\";\nimport { ComponentDocsTabs } from \"../_compon"
}
]
// ... and 579 more files (download for full content)
About this extraction
This page contains the full source code of the assistant-ui/tool-ui GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 779 files (4.2 MB), approximately 1.1M tokens, and a symbol index with 2369 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.