basalt-ui 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +21 -21
- package/CHANGELOG.md +32 -0
- package/README.md +63 -51
- package/agent/rules/basalt-agent.md +14 -0
- package/agent/rules/basalt-content.md +16 -3
- package/configs/oxlint-plugin.js +7 -3
- package/configs/oxlint-plugin.test.ts +34 -5
- package/configs/oxlint.json +4 -4
- package/dist/agent/adapter.d.ts +150 -0
- package/dist/agent/adapter.d.ts.map +1 -0
- package/dist/agent/adapter.js +482 -0
- package/dist/agent/adapter.test.d.ts +2 -0
- package/dist/agent/adapter.test.d.ts.map +1 -0
- package/dist/agent/ai-sdk-transport.d.ts.map +1 -1
- package/dist/agent/ai-sdk-transport.js +6 -2
- package/dist/agent/ai-sdk-transport.test.d.ts +2 -0
- package/dist/agent/ai-sdk-transport.test.d.ts.map +1 -0
- package/dist/agent/coalesce.d.ts +20 -4
- package/dist/agent/coalesce.d.ts.map +1 -1
- package/dist/agent/coalesce.js +76 -8
- package/dist/agent/coalesce.test.d.ts +2 -0
- package/dist/agent/coalesce.test.d.ts.map +1 -0
- package/dist/agent/foreign.test.d.ts +2 -0
- package/dist/agent/foreign.test.d.ts.map +1 -0
- package/dist/agent/id.d.ts +78 -0
- package/dist/agent/id.d.ts.map +1 -1
- package/dist/agent/id.js +30 -0
- package/dist/agent/id.test.d.ts +2 -0
- package/dist/agent/id.test.d.ts.map +1 -0
- package/dist/agent/index.d.ts +2 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +3 -0
- package/dist/agent/merge.d.ts.map +1 -1
- package/dist/agent/merge.js +19 -7
- package/dist/agent/merge.test.d.ts +2 -0
- package/dist/agent/merge.test.d.ts.map +1 -0
- package/dist/agent/part-list.d.ts +49 -34
- package/dist/agent/part-list.d.ts.map +1 -1
- package/dist/agent/part-list.js +42 -6
- package/dist/agent/part-list.test.d.ts +2 -0
- package/dist/agent/part-list.test.d.ts.map +1 -0
- package/dist/agent/parts.d.ts +46 -10
- package/dist/agent/parts.d.ts.map +1 -1
- package/dist/agent/parts.js +16 -6
- package/dist/agent/parts.test.d.ts +2 -0
- package/dist/agent/parts.test.d.ts.map +1 -0
- package/dist/agent/thread.d.ts +18 -0
- package/dist/agent/thread.d.ts.map +1 -1
- package/dist/agent/thread.js +8 -2
- package/dist/agent/thread.test.d.ts +2 -0
- package/dist/agent/thread.test.d.ts.map +1 -0
- package/dist/agent/transport.test.d.ts +2 -0
- package/dist/agent/transport.test.d.ts.map +1 -0
- package/dist/agent/use-agent-stream.d.ts.map +1 -1
- package/dist/agent/use-agent-stream.js +2 -2
- package/dist/agent/use-agent-stream.test.d.ts +2 -0
- package/dist/agent/use-agent-stream.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.d.ts +24 -3
- package/dist/agent/use-agent-thread-runs.d.ts.map +1 -1
- package/dist/agent/use-agent-thread-runs.foreign.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.foreign.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.js +55 -15
- package/dist/agent/use-agent-thread-runs.resume.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.resume.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.wedge.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.wedge.test.d.ts.map +1 -0
- package/dist/agent-chat/composer.d.ts +130 -8
- package/dist/agent-chat/composer.d.ts.map +1 -1
- package/dist/agent-chat/composer.js +189 -23
- package/dist/agent-chat/composer.test.d.ts +2 -0
- package/dist/agent-chat/composer.test.d.ts.map +1 -0
- package/dist/agent-chat/index.d.ts +5 -1
- package/dist/agent-chat/index.d.ts.map +1 -1
- package/dist/agent-chat/index.js +2 -0
- package/dist/agent-chat/message-affordances.d.ts +59 -0
- package/dist/agent-chat/message-affordances.d.ts.map +1 -0
- package/dist/agent-chat/message-affordances.js +7 -0
- package/dist/agent-chat/relative-time.d.ts +27 -0
- package/dist/agent-chat/relative-time.d.ts.map +1 -0
- package/dist/agent-chat/relative-time.js +27 -0
- package/dist/agent-chat/relative-time.test.d.ts +2 -0
- package/dist/agent-chat/relative-time.test.d.ts.map +1 -0
- package/dist/agent-chat/thread-detail-panel.d.ts.map +1 -1
- package/dist/agent-chat/thread-detail-panel.js +1 -1
- package/dist/agent-chat/thread-feed-row.d.ts +65 -0
- package/dist/agent-chat/thread-feed-row.d.ts.map +1 -0
- package/dist/agent-chat/thread-feed-row.js +156 -0
- package/dist/agent-chat/thread-feed-row.test.d.ts +2 -0
- package/dist/agent-chat/thread-feed-row.test.d.ts.map +1 -0
- package/dist/agent-chat/thread-feed.d.ts +34 -5
- package/dist/agent-chat/thread-feed.d.ts.map +1 -1
- package/dist/agent-chat/thread-feed.js +52 -19
- package/dist/agent-chat/thread-feed.test.d.ts +2 -0
- package/dist/agent-chat/thread-feed.test.d.ts.map +1 -0
- package/dist/agent-chat/thread-message.d.ts +183 -2
- package/dist/agent-chat/thread-message.d.ts.map +1 -1
- package/dist/agent-chat/thread-message.js +329 -37
- package/dist/agent-chat/thread-message.test.d.ts +2 -0
- package/dist/agent-chat/thread-message.test.d.ts.map +1 -0
- package/dist/agent-chat/thread-outcome-card.d.ts.map +1 -1
- package/dist/agent-chat/thread-outcome-card.js +1 -16
- package/dist/agent-chat/thread-workspace.d.ts +14 -2
- package/dist/agent-chat/thread-workspace.d.ts.map +1 -1
- package/dist/agent-chat/thread-workspace.js +30 -4
- package/dist/agent-chat/thread-workspace.test.d.ts +2 -0
- package/dist/agent-chat/thread-workspace.test.d.ts.map +1 -0
- package/dist/agent-chat/tool-chip.test.d.ts +2 -0
- package/dist/agent-chat/tool-chip.test.d.ts.map +1 -0
- package/dist/agent-chat/virtualize.d.ts +123 -0
- package/dist/agent-chat/virtualize.d.ts.map +1 -0
- package/dist/agent-chat/virtualize.js +9 -0
- package/dist/agent-chat/virtualize.type-guard.test.d.ts +2 -0
- package/dist/agent-chat/virtualize.type-guard.test.d.ts.map +1 -0
- package/dist/charts/primitives/ChartFrame.test.d.ts +2 -0
- package/dist/charts/primitives/ChartFrame.test.d.ts.map +1 -0
- package/dist/charts/utils/domain.test.d.ts +2 -0
- package/dist/charts/utils/domain.test.d.ts.map +1 -0
- package/dist/cli/check-theme.test.d.ts +2 -0
- package/dist/cli/check-theme.test.d.ts.map +1 -0
- package/dist/cli/help.test.d.ts +2 -0
- package/dist/cli/help.test.d.ts.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/init-sync.test.d.ts +2 -0
- package/dist/cli/init-sync.test.d.ts.map +1 -0
- package/dist/cli/placement-engine.test.d.ts +2 -0
- package/dist/cli/placement-engine.test.d.ts.map +1 -0
- package/dist/cli/tarball-parity.test.d.ts +2 -0
- package/dist/cli/tarball-parity.test.d.ts.map +1 -0
- package/dist/cli/template-format.test.d.ts +2 -0
- package/dist/cli/template-format.test.d.ts.map +1 -0
- package/dist/cli/template-ledger.test.d.ts +2 -0
- package/dist/cli/template-ledger.test.d.ts.map +1 -0
- package/dist/cli/tokens-css.test.d.ts +2 -0
- package/dist/cli/tokens-css.test.d.ts.map +1 -0
- package/dist/content/article-actions.test.d.ts +2 -0
- package/dist/content/article-actions.test.d.ts.map +1 -0
- package/dist/content/article-model.test.d.ts +2 -0
- package/dist/content/article-model.test.d.ts.map +1 -0
- package/dist/content/block-split.test.d.ts +2 -0
- package/dist/content/block-split.test.d.ts.map +1 -0
- package/dist/content/fence-block.d.ts +37 -10
- package/dist/content/fence-block.d.ts.map +1 -1
- package/dist/content/fence-block.js +80 -14
- package/dist/content/heading-components.d.ts.map +1 -1
- package/dist/content/heading-components.js +7 -4
- package/dist/content/heading-components.test.d.ts +2 -0
- package/dist/content/heading-components.test.d.ts.map +1 -0
- package/dist/content/index.d.ts +6 -3
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +5 -1
- package/dist/content/markdown.d.ts +101 -14
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +141 -28
- package/dist/content/markdown.test.d.ts +2 -0
- package/dist/content/markdown.test.d.ts.map +1 -0
- package/dist/content/prose.module.css.test.d.ts +2 -0
- package/dist/content/prose.module.css.test.d.ts.map +1 -0
- package/dist/content/sanitize.d.ts +170 -0
- package/dist/content/sanitize.d.ts.map +1 -0
- package/dist/content/sanitize.js +178 -0
- package/dist/content/sanitize.test.d.ts +2 -0
- package/dist/content/sanitize.test.d.ts.map +1 -0
- package/dist/content/slug.test.d.ts +2 -0
- package/dist/content/slug.test.d.ts.map +1 -0
- package/dist/dashboard/stat-card.test.d.ts +2 -0
- package/dist/dashboard/stat-card.test.d.ts.map +1 -0
- package/dist/data/index.d.ts +5 -1
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/virtual-list.d.ts.map +1 -1
- package/dist/data/virtual.d.ts +2 -1
- package/dist/data/virtual.d.ts.map +1 -1
- package/dist/guard/check-source.test.d.ts +2 -0
- package/dist/guard/check-source.test.d.ts.map +1 -0
- package/dist/guard/guard-hook.test.d.ts +2 -0
- package/dist/guard/guard-hook.test.d.ts.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/provider/index.test.d.ts +2 -0
- package/dist/provider/index.test.d.ts.map +1 -0
- package/dist/provider/lab-theme.test.d.ts +2 -0
- package/dist/provider/lab-theme.test.d.ts.map +1 -0
- package/dist/router-tanstack/multi-search-param-store.test.d.ts +2 -0
- package/dist/router-tanstack/multi-search-param-store.test.d.ts.map +1 -0
- package/dist/styles.floor.test.d.ts +2 -0
- package/dist/styles.floor.test.d.ts.map +1 -0
- package/dist/surfaces.d.ts +5 -5
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +14 -4
- package/dist/theme/border-coverage.test.d.ts +18 -0
- package/dist/theme/border-coverage.test.d.ts.map +1 -0
- package/dist/theme/contrast.test.d.ts +2 -0
- package/dist/theme/contrast.test.d.ts.map +1 -0
- package/dist/theme/density-option.test.d.ts +2 -0
- package/dist/theme/density-option.test.d.ts.map +1 -0
- package/dist/theme/density-relations.test.d.ts +2 -0
- package/dist/theme/density-relations.test.d.ts.map +1 -0
- package/dist/theme/derive-theme.test.d.ts +2 -0
- package/dist/theme/derive-theme.test.d.ts.map +1 -0
- package/dist/theme/fonts-option.test.d.ts +2 -0
- package/dist/theme/fonts-option.test.d.ts.map +1 -0
- package/dist/theme/radius-option.test.d.ts +2 -0
- package/dist/theme/radius-option.test.d.ts.map +1 -0
- package/dist/theme/radius.test.d.ts +2 -0
- package/dist/theme/radius.test.d.ts.map +1 -0
- package/dist/theme/shadow-surfaces.test.d.ts +26 -0
- package/dist/theme/shadow-surfaces.test.d.ts.map +1 -0
- package/dist/theme/spacing.test.d.ts +2 -0
- package/dist/theme/spacing.test.d.ts.map +1 -0
- package/dist/theme/use-basalt-spacing.test.d.ts +2 -0
- package/dist/theme/use-basalt-spacing.test.d.ts.map +1 -0
- package/dist/theme-lab/derive-controls.test.d.ts +2 -0
- package/dist/theme-lab/derive-controls.test.d.ts.map +1 -0
- package/dist/theme-lab/derive-state.test.d.ts +2 -0
- package/dist/theme-lab/derive-state.test.d.ts.map +1 -0
- package/dist/theme-lab/theme-lab.test.d.ts +2 -0
- package/dist/theme-lab/theme-lab.test.d.ts.map +1 -0
- package/dist/tokens/build-fonts-css.test.d.ts +2 -0
- package/dist/tokens/build-fonts-css.test.d.ts.map +1 -0
- package/dist/tokens/build-radius-css.test.d.ts +2 -0
- package/dist/tokens/build-radius-css.test.d.ts.map +1 -0
- package/dist/tokens/density.test.d.ts +2 -0
- package/dist/tokens/density.test.d.ts.map +1 -0
- package/dist/tokens/derive-radius.test.d.ts +2 -0
- package/dist/tokens/derive-radius.test.d.ts.map +1 -0
- package/dist/tokens/derive.test.d.ts +2 -0
- package/dist/tokens/derive.test.d.ts.map +1 -0
- package/dist/tokens/palette.test.d.ts +2 -0
- package/dist/tokens/palette.test.d.ts.map +1 -0
- package/dist/vite-color-mix.test.d.ts +2 -0
- package/dist/vite-color-mix.test.d.ts.map +1 -0
- package/dist/vite.test.d.ts +2 -0
- package/dist/vite.test.d.ts.map +1 -0
- package/llms.txt +9 -9
- package/package.json +7 -2
- package/src/agent/adapter.test.ts +1640 -0
- package/src/agent/adapter.ts +945 -0
- package/src/agent/ai-sdk-transport.test.ts +117 -26
- package/src/agent/ai-sdk-transport.ts +8 -2
- package/src/agent/coalesce.test.ts +202 -9
- package/src/agent/coalesce.ts +126 -15
- package/src/agent/foreign.test.ts +5 -1
- package/src/agent/id.test.ts +101 -3
- package/src/agent/id.ts +118 -0
- package/src/agent/index.ts +8 -0
- package/src/agent/merge.test.ts +87 -0
- package/src/agent/merge.ts +57 -10
- package/src/agent/part-list.test.tsx +31 -1
- package/src/agent/part-list.tsx +77 -29
- package/src/agent/parts.test.ts +121 -4
- package/src/agent/parts.ts +78 -17
- package/src/agent/thread.test.ts +75 -2
- package/src/agent/thread.ts +25 -1
- package/src/agent/use-agent-stream.test.tsx +31 -5
- package/src/agent/use-agent-stream.ts +6 -3
- package/src/agent/use-agent-thread-runs.foreign.test.tsx +5 -0
- package/src/agent/use-agent-thread-runs.resume.test.tsx +16 -11
- package/src/agent/use-agent-thread-runs.test.tsx +356 -17
- package/src/agent/use-agent-thread-runs.ts +159 -23
- package/src/agent/use-agent-thread-runs.wedge.test.tsx +93 -7
- package/src/agent-chat/composer.test.tsx +924 -0
- package/src/agent-chat/composer.tsx +521 -52
- package/src/agent-chat/index.ts +13 -1
- package/src/agent-chat/message-affordances.ts +61 -0
- package/src/agent-chat/relative-time.test.ts +95 -0
- package/src/agent-chat/relative-time.ts +55 -0
- package/src/agent-chat/thread-detail-panel.tsx +3 -1
- package/src/agent-chat/thread-feed-row.test.tsx +510 -0
- package/src/agent-chat/thread-feed-row.tsx +274 -0
- package/src/agent-chat/thread-feed.test.tsx +241 -0
- package/src/agent-chat/thread-feed.tsx +119 -18
- package/src/agent-chat/thread-message.test.tsx +1078 -4
- package/src/agent-chat/thread-message.tsx +795 -42
- package/src/agent-chat/thread-outcome-card.tsx +1 -25
- package/src/agent-chat/thread-workspace.test.tsx +169 -0
- package/src/agent-chat/thread-workspace.tsx +70 -6
- package/src/agent-chat/virtualize.ts +132 -0
- package/src/agent-chat/virtualize.type-guard.test.ts +49 -0
- package/src/cli/index.ts +0 -1
- package/src/cli/template-format.test.ts +2 -2
- package/src/content/fence-block.tsx +242 -15
- package/src/content/heading-components.test.tsx +65 -0
- package/src/content/heading-components.tsx +26 -5
- package/src/content/index.ts +19 -3
- package/src/content/markdown.test.tsx +603 -0
- package/src/content/markdown.tsx +355 -35
- package/src/content/sanitize.test.ts +659 -0
- package/src/content/sanitize.ts +510 -0
- package/src/dashboard/stat-card.test.tsx +6 -1
- package/src/data/index.ts +5 -1
- package/src/data/virtual-list.tsx +2 -1
- package/src/data/virtual.ts +2 -1
- package/src/index.ts +18 -1
- package/src/surfaces.ts +13 -3
- package/src/theme/contrast.test.ts +1 -4
- package/src/theme/density-relations.test.ts +4 -2
- package/src/theme/fonts-option.test.ts +7 -1
- package/src/theme/shadow-surfaces.test.ts +21 -6
- package/src/theme/use-basalt-spacing.test.tsx +2 -1
package/AGENTS.md
CHANGED
|
@@ -6,27 +6,27 @@ Toolchain: Bun runtime, oxlint + oxfmt, conventional commits (empty scope), `mas
|
|
|
6
6
|
|
|
7
7
|
## Subpath ownership
|
|
8
8
|
|
|
9
|
-
| Subpath | Layer | Purpose
|
|
10
|
-
| --------------------------- | --------------- |
|
|
11
|
-
| `basalt-ui` | mantine-coupled | BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, SettingsSection/SettingsRow/DangerZone)
|
|
12
|
-
| `basalt-ui/charts` | headless | visx chart primitives, sparklines, hooks, and token re-exports (Mantine-free)
|
|
13
|
-
| `basalt-ui/tokens` | headless | VX token refs, buildPaletteCss, defineSeries, seriesTokens, groupTokens, alpha (Mantine-free)
|
|
14
|
-
| `basalt-ui/theme-lab` | mantine-coupled | ThemeLabControls, applyOverrides, COLOR_GROUPS — a low-level inspector for the non-derived structural tokens; identity/color tuning lives in DeriveControls
|
|
15
|
-
| `basalt-ui/vite` | mantine-coupled | basaltViteConfig(opts) — Vite preset for basalt-ui consumer apps; basaltAppPlugin(opts) — PWA head, manifest, and icon metadata derived from the token palette
|
|
16
|
-
| `basalt-ui/guard` | headless | checkSource, GUARD_RULES, Finding types — the headless theme-guard core
|
|
17
|
-
| `basalt-ui/query` | headless | createBasaltQueryClient, transport-agnostic unwrap, lazy BasaltQueryDevtools
|
|
18
|
-
| `basalt-ui/router-tanstack` | headless | TanStack Router bridge: useBasaltNav (active route) + useRouterBreadcrumbs + createSearchParamStore (single-select URL-state store) + createMultiSearchParamStore (multi-select URL-state store)
|
|
19
|
-
| `basalt-ui/forms` | mantine-coupled | Mantine form adapter: useBasaltForm, field, FormErrorSummary, useFormDraft (Standard Schema)
|
|
20
|
-
| `basalt-ui/notifications` | mantine-coupled | Mantine notifications: notify helpers, typed registry, persisted history, NotificationBell, NotificationCenter
|
|
21
|
-
| `basalt-ui/commands` | mantine-coupled | typed command bus + overlay controller, toSpotlightActions, ShortcutsHelp, BasaltOverlays
|
|
22
|
-
| `basalt-ui/data` | mantine-coupled | Convenience barrel pulling both TanStack Table + Virtual peer groups: BasaltDataTable, BasaltVirtualList (Mantine-rendered) — prefer ./data/table or ./data/virtual for per-feature opt-in
|
|
23
|
-
| `basalt-ui/data/table` | mantine-coupled | BasaltDataTable: a sortable data table over TanStack Table, rendered with Mantine (Mantine-rendered)
|
|
24
|
-
| `basalt-ui/data/virtual` | mantine-coupled | BasaltVirtualList: a windowed virtual list over TanStack Virtual, rendered with Mantine (Mantine-rendered)
|
|
25
|
-
| `basalt-ui/agent` | headless | Headless streaming-chat layer: useAgentStream, aiSdkTransport (recommended default) + edenTransport, isResumable/ResumableAgentTransport (stream-resumption seam), PartList, coalesceParts, the ForeignPart/definePartRenderers/narrowAgentPart open part-registry seam, plus the multi-thread createThreadsStore + useAgentThreadRuns + outcome-resolver seam (Mantine-free)
|
|
26
|
-
| `basalt-ui/agent-chat` | mantine-coupled | Mantine-styled thread-chat components over basalt-ui/agent: ThreadWorkspace, ThreadFeed, ThreadOutcomeCard, ThreadDetailPanel, Composer, ThreadTranscript (open part-renderer registry via its renderers/fallbackRenderer props), threadPartRenderers, ToolChip (Mantine-coupled).
|
|
27
|
-
| `basalt-ui/content` | mantine-coupled | Prose (article/chat typography), CodeBlock (shiki, optional peer), Callout, TableOfContents, ReadingProgress, Markdown (react-markdown + remark-gfm, optional peers, streaming-
|
|
28
|
-
| `basalt-ui/state` | headless | createPersistedState (versioned localStorage) + useOnlineStatus — Mantine-free state primitives
|
|
29
|
-
| `basalt-ui/connectivity` | mantine-coupled | ConnectivityProvider (aggregates browser online/offline, React Query onlineManager, SSE, and health-check pings into one status), useConnectivity, and ConnectivityIndicator — auto-mounted by BasaltProvider
|
|
9
|
+
| Subpath | Layer | Purpose |
|
|
10
|
+
| --------------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
+
| `basalt-ui` | mantine-coupled | BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, SettingsSection/SettingsRow/DangerZone) |
|
|
12
|
+
| `basalt-ui/charts` | headless | visx chart primitives, sparklines, hooks, and token re-exports (Mantine-free) |
|
|
13
|
+
| `basalt-ui/tokens` | headless | VX token refs, buildPaletteCss, defineSeries, seriesTokens, groupTokens, alpha (Mantine-free) |
|
|
14
|
+
| `basalt-ui/theme-lab` | mantine-coupled | ThemeLabControls, applyOverrides, COLOR_GROUPS — a low-level inspector for the non-derived structural tokens; identity/color tuning lives in DeriveControls |
|
|
15
|
+
| `basalt-ui/vite` | mantine-coupled | basaltViteConfig(opts) — Vite preset for basalt-ui consumer apps; basaltAppPlugin(opts) — PWA head, manifest, and icon metadata derived from the token palette |
|
|
16
|
+
| `basalt-ui/guard` | headless | checkSource, GUARD_RULES, Finding types — the headless theme-guard core |
|
|
17
|
+
| `basalt-ui/query` | headless | createBasaltQueryClient, transport-agnostic unwrap, lazy BasaltQueryDevtools |
|
|
18
|
+
| `basalt-ui/router-tanstack` | headless | TanStack Router bridge: useBasaltNav (active route) + useRouterBreadcrumbs + createSearchParamStore (single-select URL-state store) + createMultiSearchParamStore (multi-select URL-state store) |
|
|
19
|
+
| `basalt-ui/forms` | mantine-coupled | Mantine form adapter: useBasaltForm, field, FormErrorSummary, useFormDraft (Standard Schema) |
|
|
20
|
+
| `basalt-ui/notifications` | mantine-coupled | Mantine notifications: notify helpers, typed registry, persisted history, NotificationBell, NotificationCenter |
|
|
21
|
+
| `basalt-ui/commands` | mantine-coupled | typed command bus + overlay controller, toSpotlightActions, ShortcutsHelp, BasaltOverlays |
|
|
22
|
+
| `basalt-ui/data` | mantine-coupled | Convenience barrel pulling both TanStack Table + Virtual peer groups: BasaltDataTable, BasaltVirtualList (Mantine-rendered) — prefer ./data/table or ./data/virtual for per-feature opt-in |
|
|
23
|
+
| `basalt-ui/data/table` | mantine-coupled | BasaltDataTable: a sortable data table over TanStack Table, rendered with Mantine (Mantine-rendered) |
|
|
24
|
+
| `basalt-ui/data/virtual` | mantine-coupled | BasaltVirtualList: a windowed virtual list over TanStack Virtual, rendered with Mantine (Mantine-rendered) |
|
|
25
|
+
| `basalt-ui/agent` | headless | Headless streaming-chat layer: useAgentStream, aiSdkTransport (recommended default) + edenTransport, isResumable/ResumableAgentTransport (stream-resumption seam), PartList, coalesceParts, the ForeignPart/definePartRenderers/narrowAgentPart open part-registry seam, plus the multi-thread createThreadsStore + useAgentThreadRuns + outcome-resolver seam (Mantine-free) |
|
|
26
|
+
| `basalt-ui/agent-chat` | mantine-coupled | Mantine-styled thread-chat components over basalt-ui/agent: ThreadWorkspace, ThreadFeed (variant/renderRow), ThreadFeedRow (inline-expanding Slack row, lazily mounted + kept mounted), ThreadOutcomeCard, ThreadDetailPanel, Composer, ThreadTranscript (open part-renderer registry via its renderers/fallbackRenderer props, per-message MessageAffordances, groupConsecutive, and an optional virtualize/height windowing mode whose VirtualizeOptions carry overscan/estimateSize/initialScroll — a virtualized transcript opens scrolled to the newest message unless initialScroll is "start"), threadPartRenderers, ToolChip (Mantine-coupled). motion is required, not optional — ThreadFeed/ThreadDetailPanel import motion/react eagerly, so this subpath fails to resolve without it installed even though peerDependenciesMeta marks it optional (npm has no per-subpath optionality). remend is genuinely optional here — ThreadTranscript reaches it only through the lazy dynamic import() inside content/markdown.tsx, and @tanstack/react-virtual the same way through the lazy import() behind ThreadTranscript virtualize (absent peer degrades to an unwindowed, height-bound pane). |
|
|
27
|
+
| `basalt-ui/content` | mantine-coupled | Prose (article/chat typography), CodeBlock (shiki, optional peer), Callout, TableOfContents, ReadingProgress, Markdown (react-markdown + remark-gfm, optional peers; `streaming` is a rendering mode ONLY — `contentTrust` is the independent security input, and any surface rendering agent/model output must pin `contentTrust="untrusted"`, the sole input to the image-origin allowlist; a `fenceRenderers` registry — settledOnly/FenceRenderer/FenceRenderers/FenceRenderContext; `sanitizeSchema`, an additions-only SanitizeSchemaExtension merged over BASALT_SANITIZE_SCHEMA via mergeSanitizeSchema; the remend streaming-repair pass is now a lazy optional peer), MermaidDiagram (beautiful-mermaid, optional peer), mdxComponents/createMdxComponents, ArticleLayout (docs-page frame), ArticleCard/ArticleGrid (overview cards), Article model (sortArticles/filterArticles/formatArticleDate), ArticleFilterBar (category/tags filter UI), toArticleActions (Spotlight projector, @mantine/spotlight type-only), GuideLink/GuideDrawer (contextual-help drawer) — the content/prose surface |
|
|
28
|
+
| `basalt-ui/state` | headless | createPersistedState (versioned localStorage) + useOnlineStatus — Mantine-free state primitives |
|
|
29
|
+
| `basalt-ui/connectivity` | mantine-coupled | ConnectivityProvider (aggregates browser online/offline, React Query onlineManager, SSE, and health-check pings into one status), useConnectivity, and ConnectivityIndicator — auto-mounted by BasaltProvider |
|
|
30
30
|
|
|
31
31
|
## Hard rules
|
|
32
32
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
# [1.13.0](https://github.com/jkrumm/basalt-ui/compare/v1.12.0...v1.13.0) (2026-08-04)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* hold the pack-test consumer inside the peer ranges it declares ([1fb3abe](https://github.com/jkrumm/basalt-ui/commit/1fb3abe09206cdd46a0a6f05cbbb9e3344c899f6))
|
|
7
|
+
* hold the virtual peer floor at the APIs the transcript calls ([324b474](https://github.com/jkrumm/basalt-ui/commit/324b47459b5717210464ffb5eb8b363bb152f87a))
|
|
8
|
+
* mint ids safely off a secure context and never wedge a stopped turn ([2d72074](https://github.com/jkrumm/basalt-ui/commit/2d7207403baa5a1aa5400355ac92417c9f767ffc))
|
|
9
|
+
* stop a hydrating store flashing empty and a cascade burying its cause ([93fe8c2](https://github.com/jkrumm/basalt-ui/commit/93fe8c261f5d027c003f1ce71108cd1bab1163e9))
|
|
10
|
+
* surface a failed thread load instead of an endless skeleton ([ea15873](https://github.com/jkrumm/basalt-ui/commit/ea15873fc797f237dd5d65ad1ffa5a781ff6e86c))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* give the transcript a Slack shape, affordances and virtualization ([33ca057](https://github.com/jkrumm/basalt-ui/commit/33ca057eb9fd78a59b369c1410b6e34ef0a04602))
|
|
16
|
+
* promote the agent guards and raw-scroll-container to error ([9ee8c44](https://github.com/jkrumm/basalt-ui/commit/9ee8c44acc2cc54973372dca5a8712dcf9def644))
|
|
17
|
+
|
|
18
|
+
# [1.12.0](https://github.com/jkrumm/basalt-ui/compare/v1.11.0...v1.12.0) (2026-08-03)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
* stop the tool-part fold carrying stale state and dropping parts ([d47a35f](https://github.com/jkrumm/basalt-ui/commit/d47a35f7d58d985037814b8771b0e426c5396403))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Features
|
|
27
|
+
|
|
28
|
+
* give the composer its slots and a way to write into them ([e115b7e](https://github.com/jkrumm/basalt-ui/commit/e115b7efd428a09701307f9fe7448f72e69606bb))
|
|
29
|
+
* let a server-backed store stand behind the threads API ([dfdf9c5](https://github.com/jkrumm/basalt-ui/commit/dfdf9c543554167ff9d780dda2cb662238eff419))
|
|
30
|
+
* open the markdown seams and split trust from streaming ([90d406e](https://github.com/jkrumm/basalt-ui/commit/90d406e13311a107a6a160d8f66ff42e41085a75))
|
|
31
|
+
* prove the 1.12.0 seams from outside the package ([0231345](https://github.com/jkrumm/basalt-ui/commit/0231345f88f9d8f7191db6c733ac124d5fae85fd))
|
|
32
|
+
|
|
1
33
|
# [1.11.0](https://github.com/jkrumm/basalt-ui/compare/v1.10.0...v1.11.0) (2026-08-03)
|
|
2
34
|
|
|
3
35
|
|
package/README.md
CHANGED
|
@@ -219,31 +219,31 @@ deleted rather than silently surviving into the next real skew.
|
|
|
219
219
|
|
|
220
220
|
## Subpath exports
|
|
221
221
|
|
|
222
|
-
| Subpath | Mantine? | Purpose
|
|
223
|
-
| ------------------- | -------- |
|
|
224
|
-
| `.` | coupled | `BasaltProvider`, `createBasaltTheme` / `baseTheme` / `cssVariablesResolver`, `BasaltShell` + sidebar / mobile-nav / breadcrumbs / page-header, `NavCountBadge`, `SidebarAccount` + the provider-agnostic account contract (`BasaltAccountProps`/`State`/`Actions`), `ThreadWorkspace` + thread-chat components, shell types — the root entry still re-exports the thread-chat components; `./agent-chat` takes the same components standalone, without `BasaltProvider`, the shell, the dashboard composites, or `./connectivity`
|
|
225
|
-
| `./charts` | **free** | visx chart primitives, sparklines, hooks, and token re-exports
|
|
226
|
-
| `./tokens` | **free** | `VX` token refs, `buildPaletteCss`, `defineSeries`, `seriesTokens`, `groupTokens`, `alpha`, `ColorPair` / `SeriesMap` types
|
|
227
|
-
| `./theme-lab` | coupled | `ThemeLabControls`, `applyOverrides`, `loadOverrides`, `COLOR_GROUPS` for live theme inspection
|
|
228
|
-
| `./vite` | — | `basaltViteConfig(opts)` — Vite preset for basalt-ui consumer apps; `basaltAppPlugin(opts)` — PWA head, manifest, and icon metadata derived from the token palette
|
|
229
|
-
| `./guard` | **free** | `checkSource`, `GUARD_RULES`, `Finding` types — the headless theme-guard core
|
|
230
|
-
| `./query` | **free** | `createBasaltQueryClient`, transport-agnostic `unwrap`, lazy `BasaltQueryDevtools`
|
|
231
|
-
| `./router-tanstack` | **free** | TanStack Router bridge: `useBasaltNav` (active route) + `useRouterBreadcrumbs`
|
|
232
|
-
| `./forms` | coupled | Mantine form adapter: `useBasaltForm`, `field`, `FormErrorSummary`, `useFormDraft` (Standard Schema)
|
|
233
|
-
| `./notifications` | coupled | Mantine notifications: `notify` helpers, typed registry, persisted history, `NotificationBell`
|
|
234
|
-
| `./commands` | coupled | Typed command bus + overlay controller, `toSpotlightActions`, `ShortcutsHelp`, `BasaltOverlays`
|
|
235
|
-
| `./data` | coupled | Convenience barrel pulling both peer groups: `BasaltDataTable`, `BasaltVirtualList` (Mantine-rendered) — prefer `./data/table` / `./data/virtual` for per-feature opt-in
|
|
236
|
-
| `./data/table` | coupled | `BasaltDataTable` — sortable data table over TanStack Table, rendered with Mantine
|
|
237
|
-
| `./data/virtual` | coupled | `BasaltVirtualList` — windowed virtual list over TanStack Virtual, rendered with Mantine
|
|
238
|
-
| `./agent` | **free** | Headless streaming layer (`useAgentStream`, `PartList`) + multi-thread `createThreadsStore` / `useAgentThreadRuns` / outcome seam
|
|
239
|
-
| `./agent-chat` | coupled | Mantine-styled thread-chat components over `./agent`: `ThreadWorkspace`, `ThreadFeed
|
|
240
|
-
| `./state` | **free** | `createPersistedState` (versioned localStorage) + `useOnlineStatus` — Mantine-free state primitives
|
|
241
|
-
| `./connectivity` | coupled | `ConnectivityProvider` (aggregates browser/React-Query/SSE/health-check status), `useConnectivity`, `ConnectivityIndicator` — auto-mounted by `BasaltProvider`
|
|
242
|
-
| `./content` | coupled | `Prose`, `CodeBlock`, `Callout`, `TableOfContents`, `ReadingProgress`, `Markdown`, `MermaidDiagram`, `ArticleLayout`, `ArticleCard` / `ArticleGrid`, `GuideLink` / `GuideDrawer`, `mdxComponents`
|
|
243
|
-
| `./styles.css` | — | `@layer basalt` base styles, iOS input safety net, font stack
|
|
244
|
-
| `./tokens.css` | **free** | Prebuilt `--vx-*` stylesheet — the default `buildPaletteCss()` output as a plain file, for a consumer with no bundler, React or Mantine; `basalt-ui tokens:css` re-emits it with a custom scheme selector
|
|
245
|
-
| `./configs/*` | — | Raw toolchain presets — oxlint, oxfmt, tsconfig (base/react-app/node), lefthook
|
|
246
|
-
| `./llms.txt` | — | Machine-readable surface map — one entry per published subpath with import specifier, description, layer, and optional peers
|
|
222
|
+
| Subpath | Mantine? | Purpose |
|
|
223
|
+
| ------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
224
|
+
| `.` | coupled | `BasaltProvider`, `createBasaltTheme` / `baseTheme` / `cssVariablesResolver`, `BasaltShell` + sidebar / mobile-nav / breadcrumbs / page-header, `NavCountBadge`, `SidebarAccount` + the provider-agnostic account contract (`BasaltAccountProps`/`State`/`Actions`), `ThreadWorkspace` + thread-chat components, shell types — the root entry still re-exports the thread-chat components; `./agent-chat` takes the same components standalone, without `BasaltProvider`, the shell, the dashboard composites, or `./connectivity` |
|
|
225
|
+
| `./charts` | **free** | visx chart primitives, sparklines, hooks, and token re-exports |
|
|
226
|
+
| `./tokens` | **free** | `VX` token refs, `buildPaletteCss`, `defineSeries`, `seriesTokens`, `groupTokens`, `alpha`, `ColorPair` / `SeriesMap` types |
|
|
227
|
+
| `./theme-lab` | coupled | `ThemeLabControls`, `applyOverrides`, `loadOverrides`, `COLOR_GROUPS` for live theme inspection |
|
|
228
|
+
| `./vite` | — | `basaltViteConfig(opts)` — Vite preset for basalt-ui consumer apps; `basaltAppPlugin(opts)` — PWA head, manifest, and icon metadata derived from the token palette |
|
|
229
|
+
| `./guard` | **free** | `checkSource`, `GUARD_RULES`, `Finding` types — the headless theme-guard core |
|
|
230
|
+
| `./query` | **free** | `createBasaltQueryClient`, transport-agnostic `unwrap`, lazy `BasaltQueryDevtools` |
|
|
231
|
+
| `./router-tanstack` | **free** | TanStack Router bridge: `useBasaltNav` (active route) + `useRouterBreadcrumbs` |
|
|
232
|
+
| `./forms` | coupled | Mantine form adapter: `useBasaltForm`, `field`, `FormErrorSummary`, `useFormDraft` (Standard Schema) |
|
|
233
|
+
| `./notifications` | coupled | Mantine notifications: `notify` helpers, typed registry, persisted history, `NotificationBell` |
|
|
234
|
+
| `./commands` | coupled | Typed command bus + overlay controller, `toSpotlightActions`, `ShortcutsHelp`, `BasaltOverlays` |
|
|
235
|
+
| `./data` | coupled | Convenience barrel pulling both peer groups: `BasaltDataTable`, `BasaltVirtualList` (Mantine-rendered) — prefer `./data/table` / `./data/virtual` for per-feature opt-in |
|
|
236
|
+
| `./data/table` | coupled | `BasaltDataTable` — sortable data table over TanStack Table, rendered with Mantine |
|
|
237
|
+
| `./data/virtual` | coupled | `BasaltVirtualList` — windowed virtual list over TanStack Virtual, rendered with Mantine |
|
|
238
|
+
| `./agent` | **free** | Headless streaming layer (`useAgentStream`, `PartList`) + multi-thread `createThreadsStore` / `useAgentThreadRuns` / outcome seam |
|
|
239
|
+
| `./agent-chat` | coupled | Mantine-styled thread-chat components over `./agent`: `ThreadWorkspace`, `ThreadFeed` (`variant`/`renderRow`), `ThreadFeedRow` (inline-expanding Slack row, lazily mounted + kept mounted), `ThreadOutcomeCard`, `ThreadDetailPanel`, `Composer`, `ThreadTranscript` (`groupConsecutive`/`affordances`/`virtualize` — windowed transcripts open at the newest message unless `initialScroll: 'start'`; `virtualize` is enabled by the optional `@tanstack/react-virtual` peer, absent it degrades to an unwindowed, height-bound pane), `threadPartRenderers` — **requires `motion`**, not merely an optional peer; see [Requirements](#requirements) |
|
|
240
|
+
| `./state` | **free** | `createPersistedState` (versioned localStorage) + `useOnlineStatus` — Mantine-free state primitives |
|
|
241
|
+
| `./connectivity` | coupled | `ConnectivityProvider` (aggregates browser/React-Query/SSE/health-check status), `useConnectivity`, `ConnectivityIndicator` — auto-mounted by `BasaltProvider` |
|
|
242
|
+
| `./content` | coupled | `Prose`, `CodeBlock`, `Callout`, `TableOfContents`, `ReadingProgress`, `Markdown`, `MermaidDiagram`, `ArticleLayout`, `ArticleCard` / `ArticleGrid`, `GuideLink` / `GuideDrawer`, `mdxComponents` |
|
|
243
|
+
| `./styles.css` | — | `@layer basalt` base styles, iOS input safety net, font stack |
|
|
244
|
+
| `./tokens.css` | **free** | Prebuilt `--vx-*` stylesheet — the default `buildPaletteCss()` output as a plain file, for a consumer with no bundler, React or Mantine; `basalt-ui tokens:css` re-emits it with a custom scheme selector |
|
|
245
|
+
| `./configs/*` | — | Raw toolchain presets — oxlint, oxfmt, tsconfig (base/react-app/node), lefthook |
|
|
246
|
+
| `./llms.txt` | — | Machine-readable surface map — one entry per published subpath with import specifier, description, layer, and optional peers |
|
|
247
247
|
|
|
248
248
|
Named exports only — no default exports.
|
|
249
249
|
|
|
@@ -443,20 +443,19 @@ import { BasaltVirtualList } from 'basalt-ui/data/virtual'
|
|
|
443
443
|
### `./content` — prose + markdown
|
|
444
444
|
|
|
445
445
|
````bash
|
|
446
|
-
bun add
|
|
447
|
-
bun add
|
|
448
|
-
bun add
|
|
449
|
-
bun add
|
|
446
|
+
bun add react-markdown remark-gfm # Markdown
|
|
447
|
+
bun add remend # `Markdown`'s streaming-tail repair — optional, lazy dynamic import
|
|
448
|
+
bun add rehype-sanitize # `Markdown`'s sanitize pass — optional, lazy dynamic import
|
|
449
|
+
bun add shiki # CodeBlock / fenced-code highlighting (brings @shikijs/langs, @shikijs/themes as optional peers)
|
|
450
|
+
bun add beautiful-mermaid # MermaidDiagram / ```mermaid fences
|
|
450
451
|
````
|
|
451
452
|
|
|
452
|
-
|
|
453
|
-
`basalt-ui/content`
|
|
454
|
-
|
|
455
|
-
`
|
|
456
|
-
|
|
457
|
-
only
|
|
458
|
-
Everything else degrades gracefully when absent (markdown falls back to plain text, fences to
|
|
459
|
-
plain mono, mermaid renders nothing). `Markdown` is the package's **only** markdown
|
|
453
|
+
Every peer here is lazy: `Markdown` reaches all of them through a dynamic `import()`, so
|
|
454
|
+
`basalt-ui/content` resolves and renders with none of them installed. Absence degrades gracefully
|
|
455
|
+
— never a crash: without `react-markdown`/`remark-gfm`, markdown falls back to plain text; without
|
|
456
|
+
`remend`, the streaming tail renders unrepaired; without `rehype-sanitize`, the sanitize pass is
|
|
457
|
+
skipped (dev-warned once); without `shiki`, fences fall back to plain mono; without
|
|
458
|
+
`beautiful-mermaid`, mermaid fences render nothing. `Markdown` is the package's **only** markdown
|
|
460
459
|
renderer — it backs long-form content and AI chat alike:
|
|
461
460
|
|
|
462
461
|
```tsx
|
|
@@ -465,12 +464,16 @@ import { Markdown, Prose, CodeBlock, TableOfContents } from 'basalt-ui/content'
|
|
|
465
464
|
// Long-form: 72ch measure, article typography, heading anchors + slug dedup.
|
|
466
465
|
<Markdown>{article.body}</Markdown>
|
|
467
466
|
|
|
468
|
-
// AI output: chat density, block-split + memoized, `remend`-repaired in-flight tail.
|
|
469
|
-
|
|
467
|
+
// AI output: chat density, block-split + memoized, `remend`-repaired in-flight tail. Model-generated
|
|
468
|
+
// text is untrusted regardless of whether it has finished streaming — pin `contentTrust` explicitly.
|
|
469
|
+
<Markdown streaming density="chat" contentTrust="untrusted">{part.text}</Markdown>
|
|
470
470
|
```
|
|
471
471
|
|
|
472
|
-
`streaming`
|
|
473
|
-
|
|
472
|
+
`streaming` is a rendering mode only — it says the text is still arriving, not who wrote it. The
|
|
473
|
+
security input is the separate `contentTrust` prop (`'trusted' | 'untrusted'`), the sole driver of
|
|
474
|
+
the `allowedImagePrefixes` default: same-origin-only when untrusted, since LLM-authored markdown can
|
|
475
|
+
otherwise exfiltrate via a remote image URL. Any surface rendering agent/model output must pin
|
|
476
|
+
`contentTrust="untrusted"` explicitly. Full doctrine: `agent/rules/basalt-content.md`.
|
|
474
477
|
|
|
475
478
|
### `./agent` — streaming-chat layer
|
|
476
479
|
|
|
@@ -606,16 +609,25 @@ Wire the drift gate to catch doctrine falling behind after a basalt-ui upgrade:
|
|
|
606
609
|
|
|
607
610
|
## Requirements
|
|
608
611
|
|
|
609
|
-
| Peer
|
|
610
|
-
|
|
|
611
|
-
| `react` / `react-dom`
|
|
612
|
-
| `@mantine/core`
|
|
613
|
-
| `@mantine/hooks`
|
|
614
|
-
| `@tanstack/react-query`
|
|
615
|
-
| `
|
|
616
|
-
| `
|
|
617
|
-
|
|
618
|
-
|
|
612
|
+
| Peer | Version | Notes |
|
|
613
|
+
| ------------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
614
|
+
| `react` / `react-dom` | `^19` | required |
|
|
615
|
+
| `@mantine/core` | `^9.3` | required |
|
|
616
|
+
| `@mantine/hooks` | `^9.3` | required |
|
|
617
|
+
| `@tanstack/react-query` | — | required for the root `.` entry — `BasaltProvider` hard-requires it at build time; NOT required by `./agent-chat`, which doesn't touch it |
|
|
618
|
+
| `motion` | `12.42.0` | required for both the root `.` entry and `./agent-chat` — both export `ThreadFeed`/`ThreadDetailPanel` (`agent-chat/thread-feed.tsx` / `thread-detail-panel.tsx`), which import `motion/react` eagerly; the root's `ThemeToggle` also uses it |
|
|
619
|
+
| `@tanstack/react-virtual` | `>=3.13.26 <4` | optional for `./agent-chat` — enables `ThreadTranscript`'s `virtualize` windowing mode via a lazy `import()`; absent it degrades to an unwindowed, height-bound pane |
|
|
620
|
+
|
|
621
|
+
`remend` was required through 1.10.x — `content/markdown.tsx` imported it at the top of the module,
|
|
622
|
+
so both the root `.` entry and `./agent-chat`'s `ThreadWorkspace`/`ThreadTranscript` hard-required it
|
|
623
|
+
transitively. It is now a genuinely optional, lazy peer (dynamic `import()`); see
|
|
624
|
+
[`./content`](#content--prose--markdown) below.
|
|
625
|
+
|
|
626
|
+
`./agent-chat`'s `optionalPeers` in `llms.txt`/`surfaces.ts` lists `remend`, `motion`, and
|
|
627
|
+
`@tanstack/react-virtual` (npm has no per-subpath optionality in `peerDependenciesMeta`) — only
|
|
628
|
+
`motion` needs to be treated as required when installing just this subpath; `remend` and
|
|
629
|
+
`@tanstack/react-virtual` are accurately optional there too, both reached only through a lazy
|
|
630
|
+
`import()` (the latter behind `ThreadTranscript`'s `virtualize` option).
|
|
619
631
|
|
|
620
632
|
Optional peer batteries and their packages are listed per battery above.
|
|
621
633
|
|
|
@@ -257,6 +257,20 @@ composer) on the right, collapsing to a single pane below 768px. The lower-level
|
|
|
257
257
|
`threadPartRenderers`) are exported too for bespoke layouts. Motion (feed insert, panel slide) runs
|
|
258
258
|
on the shared `MOTION_*` tokens and honours `useReducedMotion`.
|
|
259
259
|
|
|
260
|
+
`ThreadFeed` also takes a `variant` (`'outcome'`, the default above, or `'inline'` for
|
|
261
|
+
`ThreadFeedRow`, the Slack-style row that expands in place instead of opening a separate detail
|
|
262
|
+
panel — lazily mounted on first expand, then kept mounted and hidden via CSS on every collapse
|
|
263
|
+
after that) and a `renderRow` override that takes priority over `variant` entirely, for full control
|
|
264
|
+
over live-run wiring (`onSend`/`onStop`/`liveParts`/`liveStatus`) the built-in `'inline'` row
|
|
265
|
+
doesn't expose on its own; wire a real `onSend` on `ThreadFeed` itself to make the built-in row's
|
|
266
|
+
composer usable, or omit it and the row's composer renders disabled rather than a live control that
|
|
267
|
+
silently discards input. `ThreadTranscript` also takes `groupConsecutive` (suppresses role
|
|
268
|
+
label/chrome on same-speaker runs), a per-message `affordances` contract (timestamp/copy/regenerate/
|
|
269
|
+
custom actions), and an optional `virtualize`/`height` windowing mode for very long threads. A
|
|
270
|
+
windowed transcript owns its own scroll node (never nest it in `BasaltStickToBottom`) and scrolls
|
|
271
|
+
itself to the newest message once on mount — `virtualize={{ initialScroll: 'start' }}` opts out, and
|
|
272
|
+
is what a consumer restoring its own saved scroll position wants so the two don't fight.
|
|
273
|
+
|
|
260
274
|
**Boundary:** the headless layer (`createThreadsStore`, `useAgentThreadRuns`, the outcome types)
|
|
261
275
|
stays Mantine-free in `./agent`; the components are Mantine-coupled and ship from `./agent-chat`
|
|
262
276
|
(also re-exported from the root entry). Never add `@mantine/*` under `src/agent/**` — it is
|
|
@@ -76,10 +76,23 @@ token, no debouncing needed.
|
|
|
76
76
|
- The LAST (in-flight) block is repaired via `remend` before rendering — unclosed `**`/`` ` ``/
|
|
77
77
|
`~~`/`$$`, an incomplete `[text](url` link (remend rewrites it to
|
|
78
78
|
`streamdown:incomplete-link` — any `streamdown:` href is dropped by the link hardening below).
|
|
79
|
+
`remend` is a lazy optional peer (dynamic `import()`); the root `.` entry no longer hard-requires
|
|
80
|
+
it.
|
|
81
|
+
- **`streaming` is a RENDERING mode only** — it says the text is still arriving, not who wrote it.
|
|
82
|
+
Trust is a separate prop, `contentTrust: 'trusted' | 'untrusted'`, and it is the sole input to the
|
|
83
|
+
image allowlist below. Any surface rendering agent/model output must pin
|
|
84
|
+
`contentTrust="untrusted"` explicitly — a finished agent message is still model-generated, so
|
|
85
|
+
don't lean on `streaming` as a stand-in for trust.
|
|
79
86
|
- **Hardening is ALWAYS ON**, streaming or not: `allowedLinkPrefixes` (default `['https://',
|
|
80
|
-
'mailto:', '#', '/']`) / `
|
|
81
|
-
|
|
82
|
-
|
|
87
|
+
'mailto:', '#', '/']`) / `defaultOrigin` (resolves a relative URL before the allowlist check's
|
|
88
|
+
result is used) / a `rehype-sanitize` pass (optional peer; `sanitizeSchema` only ADDS to the
|
|
89
|
+
default schema, never removes from it). `allowedImagePrefixes` defaults off `contentTrust`, NOT
|
|
90
|
+
`streaming`: `['https://', '/']` when trusted, same-origin-only `['/']` when untrusted — an
|
|
91
|
+
auto-fetched image is the classic prompt-injection exfiltration channel. `contentTrust` itself
|
|
92
|
+
defaults to `'untrusted'` when `streaming` is set, `'trusted'` otherwise — a backward-compat
|
|
93
|
+
floor, not the policy (see the bullet above). An explicit `allowedImagePrefixes` always overrides
|
|
94
|
+
the `contentTrust` default. A disallowed `href`/`src` renders as an unlinked `<span>` / a dropped
|
|
95
|
+
image — never a raw unsafe URL.
|
|
83
96
|
- Fenced code highlights/upgrades per BLOCK on settle, not per token — the in-flight fence renders
|
|
84
97
|
plain mono (`CodeBlock showCopy={false}`) until its block settles.
|
|
85
98
|
- Heading ids: a document-wide `SlugTracker` in non-streaming mode gives correct cross-heading
|
package/configs/oxlint-plugin.js
CHANGED
|
@@ -372,9 +372,13 @@ const OVERFLOW_KEYS = new Set(['overflow', 'overflowY'])
|
|
|
372
372
|
const SCROLLING_VALUES = new Set(['auto', 'scroll'])
|
|
373
373
|
|
|
374
374
|
/**
|
|
375
|
-
* Reports a `style` object property that turns a node into its own scroll container.
|
|
376
|
-
*
|
|
377
|
-
*
|
|
375
|
+
* Reports a `style` object property that turns a node into its own scroll container. Whether a raw
|
|
376
|
+
* scroll box is wrong depends on who owns the scroll node, which no AST check can see — so the
|
|
377
|
+
* `theme-allow` comment is a first-class part of the rule, not an escape valve for exceptional
|
|
378
|
+
* cases: a component that legitimately owns its scroll node (`BasaltStickToBottom`,
|
|
379
|
+
* `BasaltVirtualList`, `ThreadTranscript`'s virtualized pane) declares that ownership with the
|
|
380
|
+
* comment and moves on. Severity went `off` → `warn` (1.12.0) → `error` (1.13.0) once every live
|
|
381
|
+
* site in the repo carried that declaration; the opt-out mechanism is identical at either level.
|
|
378
382
|
*/
|
|
379
383
|
const rawScrollContainer = {
|
|
380
384
|
meta: {
|
|
@@ -417,21 +417,21 @@ describe('basalt/ai-sdk-major', () => {
|
|
|
417
417
|
})
|
|
418
418
|
})
|
|
419
419
|
|
|
420
|
-
// ── raw-scroll-container — promotion (off → warn shipped)
|
|
420
|
+
// ── raw-scroll-container — promotion (off → warn → error shipped) ───────────
|
|
421
421
|
|
|
422
422
|
describe('basalt/raw-scroll-container promotion', () => {
|
|
423
|
-
it('ships "
|
|
423
|
+
it('ships "error" (not "warn"/"off") in the consumer preset', () => {
|
|
424
424
|
const shipped = JSON.parse(
|
|
425
425
|
readFileSync(resolve(import.meta.dirname, 'oxlint.json'), 'utf8'),
|
|
426
426
|
) as { rules: Record<string, unknown> }
|
|
427
|
-
expect(shipped.rules['basalt/raw-scroll-container']).toBe('
|
|
427
|
+
expect(shipped.rules['basalt/raw-scroll-container']).toBe('error')
|
|
428
428
|
})
|
|
429
429
|
|
|
430
|
-
it('stays "
|
|
430
|
+
it('stays at the shipped level ("error") repo-local', () => {
|
|
431
431
|
const repoLocal = JSON.parse(
|
|
432
432
|
readFileSync(resolve(import.meta.dirname, '..', '..', '..', '.oxlintrc.json'), 'utf8'),
|
|
433
433
|
) as { rules: Record<string, unknown> }
|
|
434
|
-
expect(repoLocal.rules['basalt/raw-scroll-container']).toBe('
|
|
434
|
+
expect(repoLocal.rules['basalt/raw-scroll-container']).toBe('error')
|
|
435
435
|
})
|
|
436
436
|
|
|
437
437
|
it('still flags a raw overflow:auto style property at the shipped level', () => {
|
|
@@ -447,3 +447,32 @@ describe('basalt/raw-scroll-container promotion', () => {
|
|
|
447
447
|
expect(rules).toContain('raw-scroll-container')
|
|
448
448
|
})
|
|
449
449
|
})
|
|
450
|
+
|
|
451
|
+
// ── agent rules — promotion (warn → error shipped) ──────────────────────────
|
|
452
|
+
// The three agent-chat rules were promoted warn → error in the SHIPPED preset alongside
|
|
453
|
+
// raw-scroll-container above, but had no equivalent lock — `scripts/gen-oxlint.ts` only regenerates
|
|
454
|
+
// the `overrides` array; this top-level `rules` block is hand-maintained and
|
|
455
|
+
// `tests/oxlint-preset-sync.test.ts` only checks `overrides` against `projectBanList('shipped')`, so
|
|
456
|
+
// a later accidental revert of one of these three back to "warn" would pass the suite silently.
|
|
457
|
+
|
|
458
|
+
describe('basalt agent rules promotion', () => {
|
|
459
|
+
it.each(['basalt/agent-resume-guard', 'basalt/agent-no-raw-usechat', 'basalt/ai-sdk-major'])(
|
|
460
|
+
'%s ships "error" (not "warn"/"off") in the consumer preset',
|
|
461
|
+
(rule) => {
|
|
462
|
+
const shipped = JSON.parse(
|
|
463
|
+
readFileSync(resolve(import.meta.dirname, 'oxlint.json'), 'utf8'),
|
|
464
|
+
) as { rules: Record<string, unknown> }
|
|
465
|
+
expect(shipped.rules[rule]).toBe('error')
|
|
466
|
+
},
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
it.each(['basalt/agent-resume-guard', 'basalt/agent-no-raw-usechat', 'basalt/ai-sdk-major'])(
|
|
470
|
+
'%s stays at the shipped level ("error") repo-local',
|
|
471
|
+
(rule) => {
|
|
472
|
+
const repoLocal = JSON.parse(
|
|
473
|
+
readFileSync(resolve(import.meta.dirname, '..', '..', '..', '.oxlintrc.json'), 'utf8'),
|
|
474
|
+
) as { rules: Record<string, unknown> }
|
|
475
|
+
expect(repoLocal.rules[rule]).toBe('error')
|
|
476
|
+
},
|
|
477
|
+
)
|
|
478
|
+
})
|
package/configs/oxlint.json
CHANGED
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
"basalt/raw-size-literal": "warn",
|
|
21
21
|
"basalt/card-inset": "error",
|
|
22
22
|
"basalt/chart-in-raw-surface": "error",
|
|
23
|
-
"basalt/raw-scroll-container": "
|
|
23
|
+
"basalt/raw-scroll-container": "error",
|
|
24
24
|
"basalt/visx-boundary": "error",
|
|
25
25
|
"basalt/visx-tooltip": "error",
|
|
26
|
-
"basalt/agent-resume-guard": "
|
|
27
|
-
"basalt/agent-no-raw-usechat": "
|
|
28
|
-
"basalt/ai-sdk-major": "
|
|
26
|
+
"basalt/agent-resume-guard": "error",
|
|
27
|
+
"basalt/agent-no-raw-usechat": "error",
|
|
28
|
+
"basalt/ai-sdk-major": "error"
|
|
29
29
|
},
|
|
30
30
|
"overrides": [
|
|
31
31
|
{
|