@usetheo/ui 0.6.2-next.0 → 0.7.0-next.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/dist/index.d.ts CHANGED
@@ -194,6 +194,14 @@ interface ThemeScriptProps {
194
194
  defaultTheme?: string;
195
195
  /** Mode to apply when no persisted value exists. Default `"dark"`. */
196
196
  defaultMode?: ThemeMode;
197
+ /**
198
+ * Density to apply when no persisted value exists. Default `"comfortable"`.
199
+ * Mirrors `ThemeProvider`'s `defaultDensity` so the inline-script and
200
+ * the React provider agree on the SSR-default density (and the
201
+ * `data-density` attribute set by this script matches what
202
+ * `ThemeProvider` promotes via its post-mount hydration effect).
203
+ */
204
+ defaultDensity?: "compact" | "comfortable" | "spacious";
197
205
  /**
198
206
  * localStorage namespace. Must match the `storageKey` passed to
199
207
  * `<ThemeProvider>`. Default `"theo-ui:theme"`. Pass `null` to disable
@@ -201,7 +209,7 @@ interface ThemeScriptProps {
201
209
  */
202
210
  storageKey?: string | null;
203
211
  }
204
- declare function ThemeScript({ defaultTheme, defaultMode, storageKey, }: ThemeScriptProps): JSX$1.Element;
212
+ declare function ThemeScript({ defaultTheme, defaultMode, defaultDensity, storageKey, }: ThemeScriptProps): JSX$1.Element;
205
213
 
206
214
  interface ThemeSwitcherProps {
207
215
  className?: string;
@@ -2596,6 +2604,179 @@ interface ToolResultProps extends HTMLAttributes<HTMLDivElement> {
2596
2604
  */
2597
2605
  declare const ToolResult: react.ForwardRefExoticComponent<ToolResultProps & react.RefAttributes<HTMLDivElement>>;
2598
2606
 
2607
+ /**
2608
+ * Progress — accessible progress bar primitive.
2609
+ *
2610
+ * Built on `<div role="progressbar">` (NOT native `<progress>`) so Tailwind
2611
+ * classes can style the track + fill cross-browser (Chrome/Safari/Firefox
2612
+ * shadow-DOM hooks for `<progress>` diverge). Matches Radix / shadcn /
2613
+ * Mantine convention.
2614
+ *
2615
+ * Variants:
2616
+ * - intent: `default` | `success` | `warning` | `destructive` — controls fill color
2617
+ * - height: `h-1` (4px, default) | `h-1.5` | `h-2` | `h-3`
2618
+ * - indeterminate: animated bar, no value (e.g. "uploading…", "building…")
2619
+ *
2620
+ * Composition:
2621
+ * <Progress value={42} max={100} intent="success" aria-label="Upload" />
2622
+ * <Progress indeterminate aria-label="Building" />
2623
+ *
2624
+ * A11y:
2625
+ * - role="progressbar"
2626
+ * - aria-valuenow / aria-valuemin / aria-valuemax (determinate)
2627
+ * - aria-busy="true" when indeterminate
2628
+ * - Respects `prefers-reduced-motion` (no animation when set)
2629
+ *
2630
+ * Used by `<UsageMeter>` to render each metric's fill bar, but ships as a
2631
+ * standalone primitive for direct consumer use (deploy phase, file upload,
2632
+ * build progress, quota fill).
2633
+ */
2634
+ interface ProgressProps extends Omit<HTMLAttributes<HTMLDivElement>, "role"> {
2635
+ /** Current value (0..max). Values outside the range are clamped. */
2636
+ value?: number;
2637
+ /** Maximum value. Defaults to 100. */
2638
+ max?: number;
2639
+ /** Visual intent — controls fill color. */
2640
+ intent?: "default" | "success" | "warning" | "destructive";
2641
+ /** Bar height in tailwind units. Defaults to `"h-1"` (4px). */
2642
+ height?: "h-1" | "h-1.5" | "h-2" | "h-3";
2643
+ /** When true, animated bar with no value. Omits `aria-valuenow`, adds `aria-busy`. */
2644
+ indeterminate?: boolean;
2645
+ /** Accessible label. Required if not preceded by an `aria-labelledby` element. */
2646
+ "aria-label"?: string;
2647
+ }
2648
+ declare const Progress: react.ForwardRefExoticComponent<ProgressProps & react.RefAttributes<HTMLDivElement>>;
2649
+
2650
+ /**
2651
+ * PlanBadge — semantic pricing-tier badge.
2652
+ *
2653
+ * Five canonical tiers (`free` / `hobby` / `pro` / `team` / `enterprise`) with
2654
+ * distinct color tokens. Consumers self-document intent with `plan="hobby"`
2655
+ * instead of mapping a generic `<Badge variant="outline">` to colors per app.
2656
+ * Future rebrand / dark-mode tweaks propagate automatically — no consumer
2657
+ * code change.
2658
+ *
2659
+ * Visual spec (per `theo/docs/handoff/2026-05-23-theo-ui-cloud-dashboard-gaps-brief.md`):
2660
+ *
2661
+ * | tier | bg | border | text |
2662
+ * |--------------|---------------------|--------------------------|-----------------------|
2663
+ * | free | bg-muted/40 | border-muted-foreground/20 | text-muted-foreground |
2664
+ * | hobby | bg-warning/10 | border-warning/30 | text-warning |
2665
+ * | pro | bg-primary/10 | border-primary/30 | text-primary |
2666
+ * | team | bg-success/10 | border-success/30 | text-success |
2667
+ * | enterprise | bg-foreground/5 | border-foreground/20 | text-foreground |
2668
+ *
2669
+ * Default label capitalizes the tier (`hobby → "Hobby"`, `enterprise → "Enterprise"`).
2670
+ *
2671
+ * Used by `<AccountMenu>` inline with the user name; usable standalone.
2672
+ */
2673
+ type PlanTier = "free" | "hobby" | "pro" | "team" | "enterprise";
2674
+ interface PlanBadgeProps extends HTMLAttributes<HTMLSpanElement> {
2675
+ /** Plan tier identifier. */
2676
+ plan: PlanTier;
2677
+ /** Override the display label. Defaults to the capitalized tier name. */
2678
+ label?: string;
2679
+ /** Size variant. */
2680
+ size?: "sm" | "md";
2681
+ }
2682
+ declare const PlanBadge: react.ForwardRefExoticComponent<PlanBadgeProps & react.RefAttributes<HTMLSpanElement>>;
2683
+
2684
+ /**
2685
+ * UsageMeter — multi-metric stacked usage card.
2686
+ *
2687
+ * PaaS-shape sibling of `<CostMeter>` (which is mono-USD). Displays N
2688
+ * metrics with arbitrary units (GB, requests, build-minutes, seats) per
2689
+ * the reference TheoCloud dashboard mockup. Each row = label + value/max
2690
+ * + `<Progress>` fill bar.
2691
+ *
2692
+ * Composition:
2693
+ *
2694
+ * <UsageMeter
2695
+ * title="Last 30 days"
2696
+ * action={<Badge variant="outline">Upgrade</Badge>}
2697
+ * metrics={[
2698
+ * { label: "Fast Data Transfer", value: 0, max: 100, unit: "GB" },
2699
+ * { label: "Edge Requests", value: 0, max: 1_000_000, unit: "req",
2700
+ * formatter: (v, m) => `${v} / ${m >= 1e6 ? `${m / 1e6}M` : m}` },
2701
+ * ]}
2702
+ * />
2703
+ *
2704
+ * Over-quota detection: when `value > max`, the value text gets the
2705
+ * `text-warning` class and the underlying `<Progress>` uses
2706
+ * `intent="warning"` (bar fills 100% via Progress's own clamping).
2707
+ *
2708
+ * `compact` mode renders only the bars (no label/value text) — useful in
2709
+ * narrow nav-bar slots.
2710
+ *
2711
+ * Imports the sibling `<Progress>` primitive via relative path (per RFC
2712
+ * dashboard-paas-primitives D3) — primitives must not depend on the
2713
+ * `@usetheo/ui` barrel.
2714
+ */
2715
+ interface UsageMetric {
2716
+ /** Display label (e.g. "Fast Data Transfer"). */
2717
+ label: ReactNode;
2718
+ /** Current consumption. */
2719
+ value: number;
2720
+ /** Maximum allowed in the current period. */
2721
+ max: number;
2722
+ /** Unit string (e.g. "GB", "req", "min"). Rendered after value/max. */
2723
+ unit?: string;
2724
+ /** Optional custom formatter — overrides default `${value} / ${max} ${unit}`. */
2725
+ formatter?: (value: number, max: number, unit?: string) => string;
2726
+ }
2727
+ interface UsageMeterProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
2728
+ /** Card title (e.g. "Last 30 days", "This billing period"). */
2729
+ title?: ReactNode;
2730
+ /** Optional right-aligned action slot (e.g. an Upgrade Badge or Button). */
2731
+ action?: ReactNode;
2732
+ /** Array of metrics to display. Order preserved. */
2733
+ metrics: UsageMetric[];
2734
+ /** When true, show only the bars without label/value text (sparkline mode). */
2735
+ compact?: boolean;
2736
+ }
2737
+ declare const UsageMeter: react.ForwardRefExoticComponent<UsageMeterProps & react.RefAttributes<HTMLDivElement>>;
2738
+
2739
+ /**
2740
+ * AccountMenu — sidebar header for PaaS surfaces.
2741
+ *
2742
+ * Renders avatar + name + (optional) plan badge + (optional) secondary line.
2743
+ * Dual mode: with `onClick`, renders as a `<button>` with a `ChevronsUpDown`
2744
+ * trailing icon (account picker affordance); without, renders as a static
2745
+ * `<div>` (read-only display, not focusable).
2746
+ *
2747
+ * Composition:
2748
+ *
2749
+ * <Sidebar.Header className="p-0">
2750
+ * <AccountMenu
2751
+ * name="paulohenriquevn"
2752
+ * avatar="https://avatars.githubusercontent.com/u/12345"
2753
+ * plan="hobby"
2754
+ * onClick={openAccountSwitcher}
2755
+ * />
2756
+ * </Sidebar.Header>
2757
+ *
2758
+ * Avatar handling:
2759
+ * - URL (`http(s)://` or `/`) → `<Avatar.Image>` with `<Avatar.Fallback>` initials
2760
+ * - Short string (≤2 chars) → treated as initials directly
2761
+ * - Undefined → initials derived from the first character of `name`
2762
+ *
2763
+ * PaaS-shape sibling of `<ProjectSwitcher>` (workspace + branch + agent-status).
2764
+ * Same dual-mode (interactive vs static) pattern; different semantics.
2765
+ */
2766
+ interface AccountMenuProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type" | "children" | "name"> {
2767
+ /** Display name (username, email, org name). */
2768
+ name: ReactNode;
2769
+ /** Avatar URL or 1-2-char initials. If undefined, derives initials from `name`. */
2770
+ avatar?: string;
2771
+ /** Plan tier — renders inline `<PlanBadge size="sm">`. Omit for none. */
2772
+ plan?: PlanTier;
2773
+ /** Optional secondary line below name (e.g. email). */
2774
+ secondary?: ReactNode;
2775
+ /** Make the row interactive (button) with a trailing chevron. */
2776
+ onClick?: () => void;
2777
+ }
2778
+ declare const AccountMenu: react.ForwardRefExoticComponent<AccountMenuProps & react.RefAttributes<HTMLElement>>;
2779
+
2599
2780
  interface ProgressChecklistProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
2600
2781
  title?: ReactNode;
2601
2782
  steps: TaskStep[];
@@ -3662,4 +3843,4 @@ interface CommandPaletteProps {
3662
3843
  */
3663
3844
  declare function CommandPalette({ open, onOpenChange, items, onSelect, placeholder, emptyMessage, filter, }: CommandPaletteProps): react_jsx_runtime.JSX.Element;
3664
3845
 
3665
- export { ALL_MODES, AgentComposer, type AgentDraft, AgentEditor, AgentErrorCard, type AgentErrorKind, AgentEvent, type AgentEvent$1 as AgentEventModel, type AgentEventStatus, type AgentEventType, AgentHandoff, AgentProfile, type AgentProfileDescriptor, AgentStartingState, AgentStream, type AgentStreamItem, AgentStreaming, AgentTimeline, ApprovalCard, type ApprovalSeverity, ArtifactPreview, type Attachment, AttachmentChip, type AuditActorKind, type AuditEntry, AuditLogEntry, type AuditSeverity, AutoCompactNotice, Avatar, BadgeWithDot as Badge, type BadgeProps, BrowserControls, BuildLogStream, Button, type ButtonProps, type Capability, CapabilityIndicator, type CapabilityState, Card, ChatComposer, ChatMessage, ChatMessageAction, type ChatMessageActionProps, ChatMessageActions, type ChatMessageActionsProps, ChatMessageBranch, ChatMessageBranchContent, type ChatMessageBranchContentProps, ChatMessageBranchNext, type ChatMessageBranchNextProps, ChatMessageBranchPage, type ChatMessageBranchPageProps, ChatMessageBranchPrevious, type ChatMessageBranchPreviousProps, type ChatMessageBranchProps, ChatMessageBranchSelector, type ChatMessageBranchSelectorProps, ChatMessageContent, type ChatMessageContentProps, type ChatMessageContentVariant, type ChatMessageProps, ChatMessageResponse, type ChatMessageResponseProps, ChatMessageRoot, type ChatMessageRootProps, ChatMessageToolbar, type ChatMessageToolbarProps, ChatThread, Checkbox, type ColorScale, type CommandItem, CommandPalette, type ComposerMode, ContextCard, ContextWindowBar, CostMeter, type CreatedFile, CreatedFilesCard, type CronJob, CronJobCard, type CronJobStatus, CronJobsList, type CustomContentUIPart, DataPart, type DataPartProps, type DataRenderer, type DataRendererMap, type DataUIPart, type DefineThemeInput, type Density, type DensityContextValue, type Deployment, DeploymentRow, type DeploymentStatus, Dialog, type DiffHunk, type DiffLine, type DiffLineKind, DiffViewer, type Domain, DomainConfig, type DomainStatus, EmptyState, type EnvScope, type EnvVar, EnvVarEditor, FilePart, type FilePartProps, type FileUIPart, FolderContextCard, type FolderEntry, FolderSelector, FormField, HOOK_EVENTS, type HandoffParty, HookConfig, type HookEntry, type HookEvent, type HookEventEntry, HookEventLog, type HookEventResult, Input, type InputProps, type IntentOption, IntentSelector, Label, type Lane, LaneBoard, type LaneCard, type LaneState, type LogLevel, type LogLine, LoginSplit, type MCPServer, MCPServerCard, MCPServerList, type MCPServerStatus, MODE_LABEL, MemoryEditor, type MemoryLayer, type MemoryScope, type MentionItem, MentionMenu, type MentionTrigger, type MessageRole, type Metric, MetricsPanel, type Mode, type ModelCapabilityFlag, ModelCard, type ModelInfo, type ModelOption, ModelSelector, type PartRendererMap, type PermissionDecision, type PermissionDecisionKind, PermissionMatrix, PermissionModal, type PermissionOperation, type PermissionRequest, type PermissionRule, type PlanNode, type PlanNodeStatus, type PreviewEnv, PreviewEnvCard, PreviewPanel, type PreviewService, ProgressChecklist, type Project, ProjectCard, type ProjectStatus, ProjectSwitcher, type ProviderMetadata, type QuickAction, QuickActionChips, RadioGroup, type RailStep, type ReasoningFileUIPart, ReasoningPart, type ReasoningPartProps, type ReasoningUIPart, type RecentFolder, RecentFoldersList, type RenderPartOptions, type RollbackTarget, RollbackUI, type Rule, RuleCard, RuleEditor, type RuleScope, type RuleState, RunStats, type RunningTaskItem, type RunningTaskStatus, RunningTasksPanel, ScrollArea, Select, SessionListItem, type SessionMode, type SessionRunStatus, type SessionStatus, type SessionSummary, SessionTimeline, Sheet, Sidebar, Skeleton, type Skill, SkillCard, SkillEditor, type SkillSource, type SkillState, SkillsList, SocialAuthRow, type SocialProvider, SourceDocumentPart, type SourceDocumentPartProps, type SourceDocumentUIPart, SourceUrlPart, type SourceUrlPartProps, type SourceUrlUIPart, type StepStartUIPart, StepsRail, SubAgentDispatch, type SubAgentRun, type SubAgentState, Switch, SystemPromptEditor, Tabs, TaskHeader, TaskNode, TaskPlan, type TaskSource, type TaskStatus, type TaskStep, type TaskStepStatus, type TerminalLine, TerminalPanel, TextPart, type TextPartProps, type TextUIPart, Textarea, type TextareaProps, type Theme, type ThemeFonts, type ThemeMode, ThemeProvider, ThemeScript, ThemeSwitcher, TheoUIProvider, type TheoUIProviderProps, Toast, type ToastVariant, Toaster, TokenUsageChart, type TokenUsagePoint, ToolCall, ToolCallCard, ToolCallPart, type ToolCallPartProps, type ToolCallStatus, type ToolEnablement, type ToolEntry, type ToolInvocationState, ToolResult, type ToolUIPart, ToolsList, TooltipWithStatics as Tooltip, TopNav, type UIMessage, type UIMessagePart, anthropicStyle, auroraTerminal, avatarVariants, badgeVariants, builtinThemes, buttonVariants, capabilityPresets, classicPaper, cn, defineTheme, dracula, githubDark, hex, isCustomContentUIPart, isDataUIPart, isFileUIPart, isReasoningFileUIPart, isReasoningUIPart, isSourceDocumentUIPart, isSourceUrlUIPart, isStepStartUIPart, isTextUIPart, isToolUIPart, linearGlass, modelCapabilityPresets, oneDark, openaiStyle, renderPart, rgb, sheetVariants, useDensity, useTheme, useToast, vercelMono, violetForge };
3846
+ export { ALL_MODES, AccountMenu, type AccountMenuProps, AgentComposer, type AgentDraft, AgentEditor, AgentErrorCard, type AgentErrorKind, AgentEvent, type AgentEvent$1 as AgentEventModel, type AgentEventStatus, type AgentEventType, AgentHandoff, AgentProfile, type AgentProfileDescriptor, AgentStartingState, AgentStream, type AgentStreamItem, AgentStreaming, AgentTimeline, ApprovalCard, type ApprovalSeverity, ArtifactPreview, type Attachment, AttachmentChip, type AuditActorKind, type AuditEntry, AuditLogEntry, type AuditSeverity, AutoCompactNotice, Avatar, BadgeWithDot as Badge, type BadgeProps, BrowserControls, BuildLogStream, Button, type ButtonProps, type Capability, CapabilityIndicator, type CapabilityState, Card, ChatComposer, ChatMessage, ChatMessageAction, type ChatMessageActionProps, ChatMessageActions, type ChatMessageActionsProps, ChatMessageBranch, ChatMessageBranchContent, type ChatMessageBranchContentProps, ChatMessageBranchNext, type ChatMessageBranchNextProps, ChatMessageBranchPage, type ChatMessageBranchPageProps, ChatMessageBranchPrevious, type ChatMessageBranchPreviousProps, type ChatMessageBranchProps, ChatMessageBranchSelector, type ChatMessageBranchSelectorProps, ChatMessageContent, type ChatMessageContentProps, type ChatMessageContentVariant, type ChatMessageProps, ChatMessageResponse, type ChatMessageResponseProps, ChatMessageRoot, type ChatMessageRootProps, ChatMessageToolbar, type ChatMessageToolbarProps, ChatThread, Checkbox, type ColorScale, type CommandItem, CommandPalette, type ComposerMode, ContextCard, ContextWindowBar, CostMeter, type CreatedFile, CreatedFilesCard, type CronJob, CronJobCard, type CronJobStatus, CronJobsList, type CustomContentUIPart, DataPart, type DataPartProps, type DataRenderer, type DataRendererMap, type DataUIPart, type DefineThemeInput, type Density, type DensityContextValue, type Deployment, DeploymentRow, type DeploymentStatus, Dialog, type DiffHunk, type DiffLine, type DiffLineKind, DiffViewer, type Domain, DomainConfig, type DomainStatus, EmptyState, type EnvScope, type EnvVar, EnvVarEditor, FilePart, type FilePartProps, type FileUIPart, FolderContextCard, type FolderEntry, FolderSelector, FormField, HOOK_EVENTS, type HandoffParty, HookConfig, type HookEntry, type HookEvent, type HookEventEntry, HookEventLog, type HookEventResult, Input, type InputProps, type IntentOption, IntentSelector, Label, type Lane, LaneBoard, type LaneCard, type LaneState, type LogLevel, type LogLine, LoginSplit, type MCPServer, MCPServerCard, MCPServerList, type MCPServerStatus, MODE_LABEL, MemoryEditor, type MemoryLayer, type MemoryScope, type MentionItem, MentionMenu, type MentionTrigger, type MessageRole, type Metric, MetricsPanel, type Mode, type ModelCapabilityFlag, ModelCard, type ModelInfo, type ModelOption, ModelSelector, type PartRendererMap, type PermissionDecision, type PermissionDecisionKind, PermissionMatrix, PermissionModal, type PermissionOperation, type PermissionRequest, type PermissionRule, PlanBadge, type PlanBadgeProps, type PlanNode, type PlanNodeStatus, type PlanTier, type PreviewEnv, PreviewEnvCard, PreviewPanel, type PreviewService, Progress, ProgressChecklist, type ProgressProps, type Project, ProjectCard, type ProjectStatus, ProjectSwitcher, type ProviderMetadata, type QuickAction, QuickActionChips, RadioGroup, type RailStep, type ReasoningFileUIPart, ReasoningPart, type ReasoningPartProps, type ReasoningUIPart, type RecentFolder, RecentFoldersList, type RenderPartOptions, type RollbackTarget, RollbackUI, type Rule, RuleCard, RuleEditor, type RuleScope, type RuleState, RunStats, type RunningTaskItem, type RunningTaskStatus, RunningTasksPanel, ScrollArea, Select, SessionListItem, type SessionMode, type SessionRunStatus, type SessionStatus, type SessionSummary, SessionTimeline, Sheet, Sidebar, Skeleton, type Skill, SkillCard, SkillEditor, type SkillSource, type SkillState, SkillsList, SocialAuthRow, type SocialProvider, SourceDocumentPart, type SourceDocumentPartProps, type SourceDocumentUIPart, SourceUrlPart, type SourceUrlPartProps, type SourceUrlUIPart, type StepStartUIPart, StepsRail, SubAgentDispatch, type SubAgentRun, type SubAgentState, Switch, SystemPromptEditor, Tabs, TaskHeader, TaskNode, TaskPlan, type TaskSource, type TaskStatus, type TaskStep, type TaskStepStatus, type TerminalLine, TerminalPanel, TextPart, type TextPartProps, type TextUIPart, Textarea, type TextareaProps, type Theme, type ThemeFonts, type ThemeMode, ThemeProvider, ThemeScript, ThemeSwitcher, TheoUIProvider, type TheoUIProviderProps, Toast, type ToastVariant, Toaster, TokenUsageChart, type TokenUsagePoint, ToolCall, ToolCallCard, ToolCallPart, type ToolCallPartProps, type ToolCallStatus, type ToolEnablement, type ToolEntry, type ToolInvocationState, ToolResult, type ToolUIPart, ToolsList, TooltipWithStatics as Tooltip, TopNav, type UIMessage, type UIMessagePart, UsageMeter, type UsageMeterProps, type UsageMetric, anthropicStyle, auroraTerminal, avatarVariants, badgeVariants, builtinThemes, buttonVariants, capabilityPresets, classicPaper, cn, defineTheme, dracula, githubDark, hex, isCustomContentUIPart, isDataUIPart, isFileUIPart, isReasoningFileUIPart, isReasoningUIPart, isSourceDocumentUIPart, isSourceUrlUIPart, isStepStartUIPart, isTextUIPart, isToolUIPart, linearGlass, modelCapabilityPresets, oneDark, openaiStyle, renderPart, rgb, sheetVariants, useDensity, useTheme, useToast, vercelMono, violetForge };
package/dist/index.js CHANGED
@@ -188,35 +188,25 @@ function ThemeProvider({
188
188
  useEffect(() => {
189
189
  setThemes(mergedThemes);
190
190
  }, [mergedThemes]);
191
- const [themeName, setThemeName] = useState(() => {
192
- if (typeof window === "undefined" || !storageKey) return defaultTheme;
193
- try {
194
- return window.localStorage.getItem(`${storageKey}:name`) ?? defaultTheme;
195
- } catch (err) {
196
- warnStorageFailure("read theme name", err);
197
- return defaultTheme;
198
- }
199
- });
200
- const [mode, setModeState] = useState(() => {
201
- if (typeof window === "undefined" || !storageKey) return defaultMode;
202
- try {
203
- const stored = window.localStorage.getItem(`${storageKey}:mode`);
204
- return stored === "dark" || stored === "light" ? stored : defaultMode;
205
- } catch (err) {
206
- warnStorageFailure("read theme mode", err);
207
- return defaultMode;
208
- }
209
- });
210
- const [density, setDensityState] = useState(() => {
211
- if (typeof window === "undefined" || !storageKey) return defaultDensity;
191
+ const [themeName, setThemeName] = useState(defaultTheme);
192
+ const [mode, setModeState] = useState(defaultMode);
193
+ const [density, setDensityState] = useState(defaultDensity);
194
+ const skipFirstPersistRef = useRef(true);
195
+ useEffect(() => {
196
+ if (typeof window === "undefined" || !storageKey) return;
212
197
  try {
213
- const stored = window.localStorage.getItem(`${storageKey}:density`);
214
- return stored === "compact" || stored === "comfortable" || stored === "spacious" ? stored : defaultDensity;
198
+ const storedName = window.localStorage.getItem(`${storageKey}:name`);
199
+ const storedMode = window.localStorage.getItem(`${storageKey}:mode`);
200
+ const storedDensity = window.localStorage.getItem(`${storageKey}:density`);
201
+ if (storedName) setThemeName(storedName);
202
+ if (storedMode === "dark" || storedMode === "light") setModeState(storedMode);
203
+ if (storedDensity === "compact" || storedDensity === "comfortable" || storedDensity === "spacious") {
204
+ setDensityState(storedDensity);
205
+ }
215
206
  } catch (err) {
216
- warnStorageFailure("read density", err);
217
- return defaultDensity;
207
+ warnStorageFailure("read theme + mode + density", err);
218
208
  }
219
- });
209
+ }, [storageKey]);
220
210
  useEffect(() => {
221
211
  injectThemeCss(themes);
222
212
  }, [themes]);
@@ -232,6 +222,10 @@ function ThemeProvider({
232
222
  injectDensityCss();
233
223
  }, [themeName, mode, density, themes]);
234
224
  useEffect(() => {
225
+ if (skipFirstPersistRef.current) {
226
+ skipFirstPersistRef.current = false;
227
+ return;
228
+ }
235
229
  if (typeof window === "undefined" || !storageKey) return;
236
230
  try {
237
231
  window.localStorage.setItem(`${storageKey}:name`, themeName);
@@ -285,18 +279,20 @@ function useTheme() {
285
279
  function safe(value) {
286
280
  return JSON.stringify(value).replace(/</g, "\\u003c");
287
281
  }
288
- function buildScript(defaultTheme, defaultMode, storageKey) {
282
+ function buildScript(defaultTheme, defaultMode, defaultDensity, storageKey) {
289
283
  const k = safe(storageKey);
290
284
  const t = safe(defaultTheme);
291
285
  const m = safe(defaultMode);
292
- return `(function(){try{var k=${k};var d=document.documentElement;var t=null;var m=null;if(k){t=localStorage.getItem(k+":name");m=localStorage.getItem(k+":mode");}d.setAttribute("data-theme",t||${t});d.setAttribute("data-mode",m||${m});if((m||${m})==="dark"){d.classList.add("dark");}}catch(e){}})();`;
286
+ const dn = safe(defaultDensity);
287
+ return `(function(){try{var k=${k};var d=document.documentElement;var t=null;var m=null;var dn=null;if(k){t=localStorage.getItem(k+":name");m=localStorage.getItem(k+":mode");dn=localStorage.getItem(k+":density");}d.setAttribute("data-theme",t||${t});d.setAttribute("data-mode",m||${m});d.setAttribute("data-density",dn||${dn});if((m||${m})==="dark"){d.classList.add("dark");}}catch(e){}})();`;
293
288
  }
294
289
  function ThemeScript({
295
290
  defaultTheme = "violet-forge",
296
291
  defaultMode = "dark",
292
+ defaultDensity = "comfortable",
297
293
  storageKey = "theo-ui:theme"
298
294
  }) {
299
- const code = buildScript(defaultTheme, defaultMode, storageKey);
295
+ const code = buildScript(defaultTheme, defaultMode, defaultDensity, storageKey);
300
296
  return /* @__PURE__ */ jsx("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: code } });
301
297
  }
302
298
  function ThemeSwitcher({ className, showModeToggle = true }) {
@@ -5550,12 +5546,12 @@ async function sanitizeHast(tree) {
5550
5546
  return safe2.type === "root" ? safe2 : { type: "root", children: [safe2] };
5551
5547
  }
5552
5548
  async function hastToReact(tree, components) {
5553
- const { Fragment: Fragment17, jsx: jsx117, jsxs: jsxs95 } = await import('react/jsx-runtime');
5549
+ const { Fragment: Fragment18, jsx: jsx121, jsxs: jsxs97 } = await import('react/jsx-runtime');
5554
5550
  const { toJsxRuntime } = await import('hast-util-to-jsx-runtime');
5555
5551
  return toJsxRuntime(tree, {
5556
- Fragment: Fragment17,
5557
- jsx: jsx117,
5558
- jsxs: jsxs95,
5552
+ Fragment: Fragment18,
5553
+ jsx: jsx121,
5554
+ jsxs: jsxs97,
5559
5555
  components
5560
5556
  });
5561
5557
  }
@@ -6756,6 +6752,251 @@ var ToolResult = forwardRef(
6756
6752
  }
6757
6753
  );
6758
6754
  ToolResult.displayName = "ToolResult";
6755
+ var INTENT_FILL = {
6756
+ default: "bg-primary",
6757
+ success: "bg-success",
6758
+ warning: "bg-warning",
6759
+ destructive: "bg-destructive"
6760
+ };
6761
+ var Progress = forwardRef(
6762
+ ({
6763
+ className,
6764
+ value = 0,
6765
+ max = 100,
6766
+ intent = "default",
6767
+ height = "h-1",
6768
+ indeterminate = false,
6769
+ ...props
6770
+ }, ref) => {
6771
+ const clampedMax = Math.max(0, max);
6772
+ const clampedValue = Math.min(clampedMax, Math.max(0, value));
6773
+ const percent = clampedMax > 0 ? clampedValue / clampedMax * 100 : 0;
6774
+ const fillClass = INTENT_FILL[intent];
6775
+ return (
6776
+ // biome-ignore lint/a11y/useFocusableInteractive: WAI-ARIA `progressbar` is a status role (https://www.w3.org/TR/wai-aria-1.2/#progressbar) — NOT supposed to be focusable; screen readers announce updates without keyboard navigation.
6777
+ /* @__PURE__ */ jsx(
6778
+ "div",
6779
+ {
6780
+ ref,
6781
+ role: "progressbar",
6782
+ "aria-valuemin": 0,
6783
+ "aria-valuemax": clampedMax,
6784
+ "aria-valuenow": indeterminate ? void 0 : clampedValue,
6785
+ "aria-busy": indeterminate ? true : void 0,
6786
+ className: cn("relative w-full overflow-hidden rounded-full bg-muted", height, className),
6787
+ ...props,
6788
+ children: indeterminate ? /* @__PURE__ */ jsx(
6789
+ "div",
6790
+ {
6791
+ className: cn(
6792
+ "absolute inset-y-0 left-0 w-1/3 rounded-full",
6793
+ "animate-[progress-indeterminate_1.4s_ease-in-out_infinite] motion-reduce:animate-none",
6794
+ "motion-reduce:w-full motion-reduce:opacity-50",
6795
+ fillClass
6796
+ )
6797
+ }
6798
+ ) : /* @__PURE__ */ jsx(
6799
+ "div",
6800
+ {
6801
+ className: cn(
6802
+ "h-full rounded-full transition-[width] duration-base ease-out-soft",
6803
+ "motion-reduce:transition-none",
6804
+ fillClass
6805
+ ),
6806
+ style: { width: `${percent}%` }
6807
+ }
6808
+ )
6809
+ }
6810
+ )
6811
+ );
6812
+ }
6813
+ );
6814
+ Progress.displayName = "Progress";
6815
+ var TIER_CLASS = {
6816
+ free: "bg-muted/40 border-muted-foreground/20 text-muted-foreground",
6817
+ hobby: "bg-warning/10 border-warning/30 text-warning",
6818
+ pro: "bg-primary/10 border-primary/30 text-primary",
6819
+ team: "bg-success/10 border-success/30 text-success",
6820
+ enterprise: "bg-foreground/5 border-foreground/20 text-foreground"
6821
+ };
6822
+ var SIZE_CLASS = {
6823
+ sm: "px-1.5 py-0 text-label-caps",
6824
+ md: "px-2 py-0.5 text-label"
6825
+ };
6826
+ function defaultLabel2(plan) {
6827
+ return plan.charAt(0).toUpperCase() + plan.slice(1);
6828
+ }
6829
+ var PlanBadge = forwardRef(
6830
+ ({ className, plan, label, size = "md", ...props }, ref) => {
6831
+ const tierClass = TIER_CLASS[plan] ?? TIER_CLASS.free;
6832
+ const displayLabel = label ?? defaultLabel2(plan);
6833
+ return /* @__PURE__ */ jsx(
6834
+ "span",
6835
+ {
6836
+ ref,
6837
+ className: cn(
6838
+ "inline-flex items-center rounded-md border",
6839
+ "font-mono uppercase tabular-nums tracking-wider",
6840
+ tierClass,
6841
+ SIZE_CLASS[size],
6842
+ className
6843
+ ),
6844
+ "data-plan": plan,
6845
+ ...props,
6846
+ children: displayLabel
6847
+ }
6848
+ );
6849
+ }
6850
+ );
6851
+ PlanBadge.displayName = "PlanBadge";
6852
+ function defaultFormat(value, max, unit) {
6853
+ return `${value} / ${max}${unit ? ` ${unit}` : ""}`;
6854
+ }
6855
+ function metricAriaLabel(metric, formatted) {
6856
+ const label = typeof metric.label === "string" ? metric.label : "metric";
6857
+ return `${label}: ${formatted}`;
6858
+ }
6859
+ var UsageMeter = forwardRef(
6860
+ ({ className, title, action, metrics, compact = false, ...props }, ref) => {
6861
+ const hasHeader = Boolean(title) || Boolean(action);
6862
+ return /* @__PURE__ */ jsxs(
6863
+ "div",
6864
+ {
6865
+ ref,
6866
+ className: cn(
6867
+ "grid gap-3 rounded-xl border border-border bg-card p-4",
6868
+ compact && "gap-2",
6869
+ className
6870
+ ),
6871
+ "data-theo-usage-meter": "",
6872
+ ...props,
6873
+ children: [
6874
+ hasHeader ? /* @__PURE__ */ jsxs("header", { className: "flex items-baseline justify-between gap-3", children: [
6875
+ title ? /* @__PURE__ */ jsx(
6876
+ "span",
6877
+ {
6878
+ className: cn(
6879
+ "font-mono text-label-caps text-muted-foreground uppercase tracking-wider"
6880
+ ),
6881
+ children: title
6882
+ }
6883
+ ) : /* @__PURE__ */ jsx("span", {}),
6884
+ action ? /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action }) : null
6885
+ ] }) : null,
6886
+ metrics.map((metric, idx) => {
6887
+ const overQuota = metric.value > metric.max;
6888
+ const fmt = metric.formatter ?? defaultFormat;
6889
+ const formatted = fmt(metric.value, metric.max, metric.unit);
6890
+ const intent = overQuota ? "warning" : "default";
6891
+ const key = `${typeof metric.label === "string" ? metric.label : "metric"}-${idx}`;
6892
+ if (compact) {
6893
+ return /* @__PURE__ */ jsx(
6894
+ Progress,
6895
+ {
6896
+ value: metric.value,
6897
+ max: metric.max,
6898
+ intent,
6899
+ "aria-label": metricAriaLabel(metric, formatted)
6900
+ },
6901
+ key
6902
+ );
6903
+ }
6904
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-1.5", children: [
6905
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-3 text-body-sm", children: [
6906
+ /* @__PURE__ */ jsx("span", { className: "truncate text-muted-foreground", children: metric.label }),
6907
+ /* @__PURE__ */ jsx(
6908
+ "span",
6909
+ {
6910
+ className: cn(
6911
+ "shrink-0 font-mono tabular-nums",
6912
+ overQuota ? "text-warning" : "text-foreground"
6913
+ ),
6914
+ children: formatted
6915
+ }
6916
+ )
6917
+ ] }),
6918
+ /* @__PURE__ */ jsx(
6919
+ Progress,
6920
+ {
6921
+ value: metric.value,
6922
+ max: metric.max,
6923
+ intent,
6924
+ "aria-label": metricAriaLabel(metric, formatted)
6925
+ }
6926
+ )
6927
+ ] }, key);
6928
+ })
6929
+ ]
6930
+ }
6931
+ );
6932
+ }
6933
+ );
6934
+ UsageMeter.displayName = "UsageMeter";
6935
+ var URL_RE = /^(?:https?:\/\/|\/)/;
6936
+ function deriveInitials(name, avatar) {
6937
+ if (avatar && !URL_RE.test(avatar) && avatar.length <= 2) {
6938
+ return avatar.toUpperCase();
6939
+ }
6940
+ if (typeof name === "string" && name.length > 0) {
6941
+ return name.charAt(0).toUpperCase();
6942
+ }
6943
+ return "?";
6944
+ }
6945
+ var AccountMenu = forwardRef(
6946
+ ({ className, name, avatar, plan, secondary, onClick, ...props }, ref) => {
6947
+ const interactive = typeof onClick === "function";
6948
+ const initials = deriveInitials(name, avatar);
6949
+ const isUrlAvatar = avatar !== void 0 && URL_RE.test(avatar);
6950
+ const altText = typeof name === "string" ? name : "account";
6951
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
6952
+ /* @__PURE__ */ jsxs(Avatar, { size: "sm", children: [
6953
+ isUrlAvatar ? /* @__PURE__ */ jsx(Avatar.Image, { src: avatar, alt: altText }) : null,
6954
+ /* @__PURE__ */ jsx(Avatar.Fallback, { delayMs: 0, children: initials })
6955
+ ] }),
6956
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
6957
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
6958
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium text-body-sm text-foreground", children: name }),
6959
+ plan ? /* @__PURE__ */ jsx(PlanBadge, { plan, size: "sm" }) : null
6960
+ ] }),
6961
+ secondary ? /* @__PURE__ */ jsx("span", { className: "truncate text-label text-muted-foreground", children: secondary }) : null
6962
+ ] }),
6963
+ interactive ? /* @__PURE__ */ jsx(ChevronsUpDown, { className: "size-3 shrink-0 text-muted-foreground", "aria-hidden": "true" }) : null
6964
+ ] });
6965
+ const baseClass = cn(
6966
+ "flex w-full items-center gap-3 px-3 py-2",
6967
+ interactive && cn(
6968
+ "rounded-md text-left transition-colors",
6969
+ "hover:bg-muted/40",
6970
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-card"
6971
+ ),
6972
+ className
6973
+ );
6974
+ if (interactive) {
6975
+ const { ...buttonProps } = props;
6976
+ return /* @__PURE__ */ jsx(
6977
+ "button",
6978
+ {
6979
+ ref,
6980
+ type: "button",
6981
+ className: baseClass,
6982
+ onClick,
6983
+ ...buttonProps,
6984
+ children: content
6985
+ }
6986
+ );
6987
+ }
6988
+ return /* @__PURE__ */ jsx(
6989
+ "div",
6990
+ {
6991
+ ref,
6992
+ className: baseClass,
6993
+ ...props,
6994
+ children: content
6995
+ }
6996
+ );
6997
+ }
6998
+ );
6999
+ AccountMenu.displayName = "AccountMenu";
6759
7000
  var statusIcon2 = {
6760
7001
  pending: CircleDashed,
6761
7002
  running: Loader2,
@@ -9526,6 +9767,6 @@ function CommandPalette({
9526
9767
  ] }) });
9527
9768
  }
9528
9769
 
9529
- export { ALL_MODES, AgentComposer, AgentEditor, AgentErrorCard, AgentEvent, AgentHandoff, AgentProfile, AgentStartingState, AgentStream, AgentStreaming, AgentTimeline, ApprovalCard, ArtifactPreview, AttachmentChip, AuditLogEntry, AutoCompactNotice, Avatar, BadgeWithDot as Badge, BrowserControls, BuildLogStream, Button, CapabilityIndicator, Card, ChatComposer, ChatMessage, ChatMessageAction, ChatMessageActions, ChatMessageBranch, ChatMessageBranchContent, ChatMessageBranchNext, ChatMessageBranchPage, ChatMessageBranchPrevious, ChatMessageBranchSelector, ChatMessageContent, ChatMessageResponse, ChatMessageRoot, ChatMessageToolbar, ChatThread, Checkbox, CommandPalette, ContextCard, ContextWindowBar, CostMeter, CreatedFilesCard, CronJobCard, CronJobsList, DataPart, DeploymentRow, Dialog, DiffViewer, DomainConfig, EmptyState, EnvVarEditor, FilePart, FolderContextCard, FolderSelector, FormField, HOOK_EVENTS, HookConfig, HookEventLog, Input, IntentSelector, Label, LaneBoard, LoginSplit, MCPServerCard, MCPServerList, MODE_LABEL, MemoryEditor, MentionMenu, MetricsPanel, ModelCard, ModelSelector, PermissionMatrix, PermissionModal, PreviewEnvCard, PreviewPanel, ProgressChecklist, ProjectCard, ProjectSwitcher, QuickActionChips, RadioGroup, ReasoningPart, RecentFoldersList, RollbackUI, RuleCard, RuleEditor, RunStats, RunningTasksPanel, ScrollArea, Select, SessionListItem, SessionTimeline, Sheet, Sidebar, Skeleton, SkillCard, SkillEditor, SkillsList, SocialAuthRow, SourceDocumentPart, SourceUrlPart, StepsRail, SubAgentDispatch, Switch, SystemPromptEditor, Tabs, TaskHeader, TaskNode, TaskPlan, TerminalPanel, TextPart, Textarea, ThemeProvider, ThemeScript, ThemeSwitcher, TheoUIProvider, Toast, Toaster, TokenUsageChart, ToolCall, ToolCallCard, ToolCallPart, ToolResult, ToolsList, TooltipWithStatics as Tooltip, TopNav, anthropicStyle, auroraTerminal, avatarVariants, badgeVariants, builtinThemes, buttonVariants, capabilityPresets, classicPaper, cn, defineTheme, dracula, githubDark, hex, isCustomContentUIPart, isDataUIPart, isFileUIPart, isReasoningFileUIPart, isReasoningUIPart, isSourceDocumentUIPart, isSourceUrlUIPart, isStepStartUIPart, isTextUIPart, isToolUIPart, linearGlass, modelCapabilityPresets, oneDark, openaiStyle, renderPart, rgb, sheetVariants, useDensity, useTheme, useToast, vercelMono, violetForge };
9770
+ export { ALL_MODES, AccountMenu, AgentComposer, AgentEditor, AgentErrorCard, AgentEvent, AgentHandoff, AgentProfile, AgentStartingState, AgentStream, AgentStreaming, AgentTimeline, ApprovalCard, ArtifactPreview, AttachmentChip, AuditLogEntry, AutoCompactNotice, Avatar, BadgeWithDot as Badge, BrowserControls, BuildLogStream, Button, CapabilityIndicator, Card, ChatComposer, ChatMessage, ChatMessageAction, ChatMessageActions, ChatMessageBranch, ChatMessageBranchContent, ChatMessageBranchNext, ChatMessageBranchPage, ChatMessageBranchPrevious, ChatMessageBranchSelector, ChatMessageContent, ChatMessageResponse, ChatMessageRoot, ChatMessageToolbar, ChatThread, Checkbox, CommandPalette, ContextCard, ContextWindowBar, CostMeter, CreatedFilesCard, CronJobCard, CronJobsList, DataPart, DeploymentRow, Dialog, DiffViewer, DomainConfig, EmptyState, EnvVarEditor, FilePart, FolderContextCard, FolderSelector, FormField, HOOK_EVENTS, HookConfig, HookEventLog, Input, IntentSelector, Label, LaneBoard, LoginSplit, MCPServerCard, MCPServerList, MODE_LABEL, MemoryEditor, MentionMenu, MetricsPanel, ModelCard, ModelSelector, PermissionMatrix, PermissionModal, PlanBadge, PreviewEnvCard, PreviewPanel, Progress, ProgressChecklist, ProjectCard, ProjectSwitcher, QuickActionChips, RadioGroup, ReasoningPart, RecentFoldersList, RollbackUI, RuleCard, RuleEditor, RunStats, RunningTasksPanel, ScrollArea, Select, SessionListItem, SessionTimeline, Sheet, Sidebar, Skeleton, SkillCard, SkillEditor, SkillsList, SocialAuthRow, SourceDocumentPart, SourceUrlPart, StepsRail, SubAgentDispatch, Switch, SystemPromptEditor, Tabs, TaskHeader, TaskNode, TaskPlan, TerminalPanel, TextPart, Textarea, ThemeProvider, ThemeScript, ThemeSwitcher, TheoUIProvider, Toast, Toaster, TokenUsageChart, ToolCall, ToolCallCard, ToolCallPart, ToolResult, ToolsList, TooltipWithStatics as Tooltip, TopNav, UsageMeter, anthropicStyle, auroraTerminal, avatarVariants, badgeVariants, builtinThemes, buttonVariants, capabilityPresets, classicPaper, cn, defineTheme, dracula, githubDark, hex, isCustomContentUIPart, isDataUIPart, isFileUIPart, isReasoningFileUIPart, isReasoningUIPart, isSourceDocumentUIPart, isSourceUrlUIPart, isStepStartUIPart, isTextUIPart, isToolUIPart, linearGlass, modelCapabilityPresets, oneDark, openaiStyle, renderPart, rgb, sheetVariants, useDensity, useTheme, useToast, vercelMono, violetForge };
9530
9771
  //# sourceMappingURL=index.js.map
9531
9772
  //# sourceMappingURL=index.js.map