@medalsocial/meda 0.2.0 → 1.0.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.
Files changed (150) hide show
  1. package/README.md +26 -0
  2. package/dist/brand/index.d.ts +2 -0
  3. package/dist/brand/index.js +1 -0
  4. package/dist/brand/medal-social-mark.d.ts +7 -0
  5. package/dist/brand/medal-social-mark.js +6 -0
  6. package/dist/brand/public.d.ts +2 -0
  7. package/dist/brand/public.js +1 -0
  8. package/dist/chat/index.d.ts +11 -0
  9. package/dist/chat/index.js +5 -0
  10. package/dist/chat/latency-badge.d.ts +7 -0
  11. package/dist/chat/latency-badge.js +23 -0
  12. package/dist/chat/latency-breakdown.d.ts +8 -0
  13. package/dist/chat/latency-breakdown.js +9 -0
  14. package/dist/chat/public.d.ts +1 -0
  15. package/dist/chat/public.js +1 -0
  16. package/dist/chat/tool-call-block.d.ts +6 -0
  17. package/dist/chat/tool-call-block.js +19 -0
  18. package/dist/chat/transcript-stream.d.ts +10 -0
  19. package/dist/chat/transcript-stream.js +40 -0
  20. package/dist/chat/turn-card.d.ts +10 -0
  21. package/dist/chat/turn-card.js +25 -0
  22. package/dist/chat/types.d.ts +36 -0
  23. package/dist/chat/types.js +1 -0
  24. package/dist/components/ui/command.d.ts +19 -0
  25. package/dist/components/ui/command.js +37 -0
  26. package/dist/components/ui/dialog.d.ts +26 -0
  27. package/dist/components/ui/dialog.js +39 -0
  28. package/dist/components/ui/drawer.d.ts +16 -0
  29. package/dist/components/ui/drawer.js +35 -0
  30. package/dist/components/ui/dropdown-menu.d.ts +32 -0
  31. package/dist/components/ui/dropdown-menu.js +68 -0
  32. package/dist/components/ui/tooltip.d.ts +6 -0
  33. package/dist/components/ui/tooltip.js +17 -0
  34. package/dist/index.d.ts +6 -1
  35. package/dist/index.js +6 -1
  36. package/dist/lib/format-time.d.ts +9 -0
  37. package/dist/lib/format-time.js +34 -0
  38. package/dist/lib/utils.d.ts +2 -0
  39. package/dist/lib/utils.js +5 -0
  40. package/dist/marketing/index.d.ts +5 -0
  41. package/dist/marketing/index.js +4 -0
  42. package/dist/marketing/marketing-callout.d.ts +2 -0
  43. package/dist/marketing/marketing-callout.js +8 -0
  44. package/dist/marketing/marketing-contact.d.ts +2 -0
  45. package/dist/marketing/marketing-contact.js +19 -0
  46. package/dist/marketing/marketing-cta-list.d.ts +2 -0
  47. package/dist/marketing/marketing-cta-list.js +21 -0
  48. package/dist/marketing/marketing-lead-magnet.d.ts +2 -0
  49. package/dist/marketing/marketing-lead-magnet.js +9 -0
  50. package/dist/marketing/public.d.ts +1 -0
  51. package/dist/marketing/public.js +1 -0
  52. package/dist/marketing/types.d.ts +67 -0
  53. package/dist/marketing/types.js +1 -0
  54. package/dist/marketing/utils.d.ts +2 -0
  55. package/dist/marketing/utils.js +6 -0
  56. package/dist/panel/index.d.ts +6 -0
  57. package/dist/panel/index.js +3 -0
  58. package/dist/panel/inspector-field.d.ts +9 -0
  59. package/dist/panel/inspector-field.js +4 -0
  60. package/dist/panel/inspector-json.d.ts +7 -0
  61. package/dist/panel/inspector-json.js +75 -0
  62. package/dist/panel/inspector.d.ts +7 -0
  63. package/dist/panel/inspector.js +12 -0
  64. package/dist/panel/public.d.ts +1 -0
  65. package/dist/panel/public.js +1 -0
  66. package/dist/panel/types.d.ts +6 -0
  67. package/dist/panel/types.js +1 -0
  68. package/dist/shell/app-shell.d.ts +9 -0
  69. package/dist/shell/app-shell.js +11 -0
  70. package/dist/shell/command-palette.d.ts +23 -0
  71. package/dist/shell/command-palette.js +138 -0
  72. package/dist/shell/context-rail.d.ts +31 -0
  73. package/dist/shell/context-rail.js +81 -0
  74. package/dist/shell/extras/index.d.ts +4 -0
  75. package/dist/shell/extras/index.js +4 -0
  76. package/dist/shell/extras/shell-desktop-panel-dock.d.ts +14 -0
  77. package/dist/shell/extras/shell-desktop-panel-dock.js +43 -0
  78. package/dist/shell/extras/shell-scrollable-content.d.ts +9 -0
  79. package/dist/shell/extras/shell-scrollable-content.js +7 -0
  80. package/dist/shell/extras/shell-tab-bar.d.ts +18 -0
  81. package/dist/shell/extras/shell-tab-bar.js +27 -0
  82. package/dist/shell/extras/types.d.ts +64 -0
  83. package/dist/shell/extras/types.js +2 -0
  84. package/dist/shell/extras/workbench-layout.d.ts +10 -0
  85. package/dist/shell/extras/workbench-layout.js +29 -0
  86. package/dist/shell/icon-rail.d.ts +29 -0
  87. package/dist/shell/icon-rail.js +38 -0
  88. package/dist/shell/index.d.ts +24 -15
  89. package/dist/shell/index.js +35 -15
  90. package/dist/shell/layout-state.d.ts +32 -0
  91. package/dist/shell/layout-state.js +98 -0
  92. package/dist/shell/mobile/mobile-bottom-nav.d.ts +15 -0
  93. package/dist/shell/mobile/mobile-bottom-nav.js +76 -0
  94. package/dist/shell/mobile/mobile-drawers.d.ts +20 -0
  95. package/dist/shell/mobile/mobile-drawers.js +62 -0
  96. package/dist/shell/mobile/mobile-header.d.ts +23 -0
  97. package/dist/shell/mobile/mobile-header.js +22 -0
  98. package/dist/shell/motion.d.ts +22 -0
  99. package/dist/shell/motion.js +19 -0
  100. package/dist/shell/public.d.ts +16 -2
  101. package/dist/shell/public.js +20 -1
  102. package/dist/shell/resizable-shell.d.ts +45 -0
  103. package/dist/shell/resizable-shell.js +15 -0
  104. package/dist/shell/right-panel.d.ts +15 -0
  105. package/dist/shell/right-panel.js +126 -0
  106. package/dist/shell/shell-auth-frame.d.ts +22 -0
  107. package/dist/shell/shell-auth-frame.js +60 -0
  108. package/dist/shell/shell-header.d.ts +10 -9
  109. package/dist/shell/shell-header.js +57 -14
  110. package/dist/shell/shell-layout-utils.d.ts +2 -2
  111. package/dist/shell/shell-main.d.ts +8 -0
  112. package/dist/shell/shell-main.js +11 -0
  113. package/dist/shell/shell-provider.d.ts +65 -0
  114. package/dist/shell/shell-provider.js +152 -0
  115. package/dist/shell/shell-route-utils.d.ts +1 -1
  116. package/dist/shell/theme-next-themes.d.ts +4 -0
  117. package/dist/shell/theme-next-themes.js +24 -0
  118. package/dist/shell/theme.d.ts +9 -0
  119. package/dist/shell/theme.js +58 -0
  120. package/dist/shell/types.d.ts +41 -41
  121. package/dist/shell/types.js +1 -0
  122. package/dist/shell/use-shell-viewport.d.ts +2 -0
  123. package/dist/shell/use-shell-viewport.js +40 -0
  124. package/dist/shell/utils.d.ts +1 -1
  125. package/dist/styles/globals.css +26 -0
  126. package/dist/styles/theme.css +147 -0
  127. package/dist/styles/tokens.css +338 -0
  128. package/dist/timeline/date-switcher.d.ts +11 -0
  129. package/dist/timeline/date-switcher.js +64 -0
  130. package/dist/timeline/event-card.d.ts +9 -0
  131. package/dist/timeline/event-card.js +18 -0
  132. package/dist/timeline/index.d.ts +13 -0
  133. package/dist/timeline/index.js +6 -0
  134. package/dist/timeline/live-indicator.d.ts +7 -0
  135. package/dist/timeline/live-indicator.js +7 -0
  136. package/dist/timeline/public.d.ts +1 -0
  137. package/dist/timeline/public.js +1 -0
  138. package/dist/timeline/scrub-bar.d.ts +14 -0
  139. package/dist/timeline/scrub-bar.js +43 -0
  140. package/dist/timeline/timeline-rail.d.ts +19 -0
  141. package/dist/timeline/timeline-rail.js +66 -0
  142. package/dist/timeline/timeline-tape.d.ts +19 -0
  143. package/dist/timeline/timeline-tape.js +65 -0
  144. package/dist/timeline/types.d.ts +40 -0
  145. package/dist/timeline/types.js +1 -0
  146. package/dist/voice/voice-level.js +3 -1
  147. package/dist/voice/voice-orb-scene.js +1 -0
  148. package/dist/voice/voice-orb.js +9 -11
  149. package/dist/voice/voice-status-pill.js +4 -9
  150. package/package.json +67 -7
package/README.md CHANGED
@@ -52,6 +52,7 @@ See the [demo app](./demo) for a live playground.
52
52
 
53
53
  - `@medalsocial/meda` — curated public API (components + helpers)
54
54
  - `@medalsocial/meda/shell` — shell-only subpath
55
+ - `@medalsocial/meda/marketing` — marketing sections and campaign blocks
55
56
  - `@medalsocial/meda/styles.css` — design tokens + base styles
56
57
 
57
58
  ## Alternative: shadcn registry
@@ -73,10 +74,35 @@ The registry index is at `https://meda.medalsocial.com/registry.json`. Source JS
73
74
  pnpm install
74
75
  pnpm build # compile dist/
75
76
  pnpm test # vitest (jsdom)
77
+ pnpm typecheck
78
+ pnpm lint
76
79
  pnpm registry:validate
77
80
  pnpm demo:dev # run the playground locally
81
+ pnpm storybook # http://localhost:6006
82
+ pnpm storybook:build # storybook-static/
83
+ pnpm size-limit # bundle-size gate
78
84
  ```
79
85
 
86
+ ## Storybook + Chromatic
87
+
88
+ Stories are colocated as `Component.stories.tsx` next to each primitive. Build
89
+ the static bundle with:
90
+
91
+ ```bash
92
+ pnpm storybook:build
93
+ ```
94
+
95
+ Visual review runs via **Chromatic**. The `Chromatic` GitHub workflow publishes
96
+ Storybook on pushes and pull requests targeting `dev` or `prod`, using the
97
+ repository secret `CHROMATIC_PROJECT_TOKEN`.
98
+
99
+ ```bash
100
+ pnpm chromatic
101
+ ```
102
+
103
+ Chromatic handles UI diffs and review state, so visual snapshot baselines are
104
+ not committed to this repository.
105
+
80
106
  ## Release
81
107
 
82
108
  Changesets + GitHub Actions (OIDC trusted publishing). Add a changeset with `pnpm changeset`, merge to the release branch, and the `Release` workflow handles npm publish with provenance.
@@ -0,0 +1,2 @@
1
+ export type { MedalSocialMarkProps } from './medal-social-mark.js';
2
+ export { MedalSocialMark } from './medal-social-mark.js';
@@ -0,0 +1 @@
1
+ export { MedalSocialMark } from './medal-social-mark.js';
@@ -0,0 +1,7 @@
1
+ import type { SVGProps } from 'react';
2
+ export interface MedalSocialMarkProps extends SVGProps<SVGSVGElement> {
3
+ title?: string;
4
+ backgroundColor?: string;
5
+ markColor?: string;
6
+ }
7
+ export declare function MedalSocialMark({ title, backgroundColor, markColor, role, focusable, 'aria-hidden': ariaHidden, ...props }: MedalSocialMarkProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export function MedalSocialMark({ title, backgroundColor = 'hsl(0, 0%, 10%)', markColor = 'hsl(0, 0%, 90%)', role, focusable = 'false', 'aria-hidden': ariaHidden, ...props }) {
3
+ const accessibleTitle = title?.trim();
4
+ const hasAccessibleName = Boolean(accessibleTitle || props['aria-label'] || props['aria-labelledby']);
5
+ return (_jsxs("svg", { ...props, viewBox: "0 0 48 48", fill: "none", role: hasAccessibleName ? (role ?? 'img') : role, "aria-hidden": hasAccessibleName ? ariaHidden : (ariaHidden ?? true), focusable: focusable, children: [_jsx("title", { children: accessibleTitle || 'Medal Social' }), _jsx("circle", { cx: "24", cy: "24", r: "23", fill: backgroundColor }), _jsx("path", { d: "M8 24L24 8L40 24L24 40L8 24Z", stroke: markColor, strokeWidth: "1.3", fill: "none" }), _jsx("circle", { cx: "24", cy: "8.5", r: "2.5", fill: markColor }), _jsx("circle", { cx: "39.5", cy: "24", r: "2.5", fill: markColor }), _jsx("circle", { cx: "24", cy: "39.5", r: "2.5", fill: markColor }), _jsx("circle", { cx: "8.5", cy: "24", r: "2.5", fill: markColor }), _jsx("g", { transform: "translate(12, 12) scale(1)", children: _jsx("path", { d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z", fill: "none", stroke: markColor, strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) })] }));
6
+ }
@@ -0,0 +1,2 @@
1
+ export type { MedalSocialMarkProps } from './medal-social-mark.js';
2
+ export { MedalSocialMark } from './medal-social-mark.js';
@@ -0,0 +1 @@
1
+ export { MedalSocialMark } from './medal-social-mark.js';
@@ -0,0 +1,11 @@
1
+ export type { LatencyBadgeProps, LatencyKind } from './latency-badge.js';
2
+ export { LatencyBadge } from './latency-badge.js';
3
+ export type { LatencyBreakdownProps } from './latency-breakdown.js';
4
+ export { LatencyBreakdown } from './latency-breakdown.js';
5
+ export type { ToolCallBlockProps } from './tool-call-block.js';
6
+ export { ToolCallBlock } from './tool-call-block.js';
7
+ export type { TranscriptStreamProps } from './transcript-stream.js';
8
+ export { TranscriptStream } from './transcript-stream.js';
9
+ export type { TurnCardProps } from './turn-card.js';
10
+ export { TurnCard } from './turn-card.js';
11
+ export type { Speaker, ToolCall, Turn, TurnLatency } from './types.js';
@@ -0,0 +1,5 @@
1
+ export { LatencyBadge } from './latency-badge.js';
2
+ export { LatencyBreakdown } from './latency-breakdown.js';
3
+ export { ToolCallBlock } from './tool-call-block.js';
4
+ export { TranscriptStream } from './transcript-stream.js';
5
+ export { TurnCard } from './turn-card.js';
@@ -0,0 +1,7 @@
1
+ export type LatencyKind = 'stt' | 'claude' | 'tts';
2
+ export interface LatencyBadgeProps {
3
+ kind: LatencyKind;
4
+ ms: number;
5
+ className?: string;
6
+ }
7
+ export declare function LatencyBadge({ kind, ms, className }: LatencyBadgeProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Tones use 700-shade variants so 11px badge text clears WCAG AA (4.5:1)
3
+ // against the white/card background. The 400/500 shades chosen for visual
4
+ // consistency with the colored bar segments don't satisfy contrast at this
5
+ // size, so the *bar* keeps the lighter shade and the *label* uses the darker.
6
+ const KIND = {
7
+ stt: { label: 'STT', tone: 'text-sky-700' },
8
+ claude: { label: 'Claude', tone: 'text-primary' },
9
+ tts: { label: 'TTS', tone: 'text-emerald-700' },
10
+ };
11
+ function fmt(ms) {
12
+ if (ms >= 1000)
13
+ return `${(ms / 1000).toFixed(1)}s`;
14
+ return `${Math.round(ms)}ms`;
15
+ }
16
+ export function LatencyBadge({ kind, ms, className }) {
17
+ const meta = KIND[kind];
18
+ return (_jsxs("span", { "data-kind": kind, className: [
19
+ 'inline-flex items-center gap-1.5 text-[11px] tabular-nums',
20
+ meta.tone,
21
+ className ?? '',
22
+ ].join(' '), children: [_jsx("span", { "aria-hidden": "true", className: "size-1 rounded-full bg-current" }), meta.label, " ", fmt(ms)] }));
23
+ }
@@ -0,0 +1,8 @@
1
+ export interface LatencyBreakdownProps {
2
+ sttMs: number;
3
+ claudeMs: number;
4
+ ttsMs: number;
5
+ showLegend?: boolean;
6
+ className?: string;
7
+ }
8
+ export declare function LatencyBreakdown({ sttMs, claudeMs, ttsMs, showLegend, className, }: LatencyBreakdownProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { LatencyBadge } from './latency-badge.js';
3
+ export function LatencyBreakdown({ sttMs, claudeMs, ttsMs, showLegend = true, className, }) {
4
+ const total = Math.max(1, sttMs + claudeMs + ttsMs);
5
+ const sttPct = (sttMs / total) * 100;
6
+ const claudePct = (claudeMs / total) * 100;
7
+ const ttsPct = (ttsMs / total) * 100;
8
+ return (_jsxs("div", { className: className, children: [_jsxs("div", { className: "flex h-1.5 gap-0.5 overflow-hidden rounded-sm bg-muted", children: [_jsx("span", { "data-segment": "stt", className: "block bg-sky-400", style: { width: `${sttPct}%` } }), _jsx("span", { "data-segment": "claude", className: "block bg-primary", style: { width: `${claudePct}%` } }), _jsx("span", { "data-segment": "tts", className: "block bg-emerald-500", style: { width: `${ttsPct}%` } })] }), showLegend && (_jsxs("div", { className: "mt-1.5 flex flex-wrap gap-3 text-[11px] tabular-nums text-muted-foreground", children: [_jsx(LatencyBadge, { kind: "stt", ms: sttMs }), _jsx(LatencyBadge, { kind: "claude", ms: claudeMs }), _jsx(LatencyBadge, { kind: "tts", ms: ttsMs })] }))] }));
9
+ }
@@ -0,0 +1 @@
1
+ export type { Speaker, ToolCall, Turn, TurnLatency } from './types.js';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { ToolCall } from './types.js';
2
+ export interface ToolCallBlockProps {
3
+ call: ToolCall;
4
+ className?: string;
5
+ }
6
+ export declare function ToolCallBlock({ call, className }: ToolCallBlockProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Zap } from 'lucide-react';
3
+ function safeStringify(v) {
4
+ // Tolerate values JSON.stringify can't handle (BigInt, circular refs, etc.)
5
+ // so a malformed tool arg never crashes the transcript view.
6
+ try {
7
+ const out = JSON.stringify(v);
8
+ return out === undefined ? String(v) : out;
9
+ }
10
+ catch {
11
+ return String(v);
12
+ }
13
+ }
14
+ export function ToolCallBlock({ call, className }) {
15
+ return (_jsxs("div", { className: [
16
+ 'mt-3 rounded-md border border-border border-l-2 border-l-amber-500 bg-card p-3 font-mono text-xs',
17
+ className ?? '',
18
+ ].join(' '), children: [_jsxs("div", { className: "mb-1.5 flex items-center gap-2 text-[11px]", children: [_jsx(Zap, { className: "size-3 text-amber-500" }), _jsx("strong", { className: "font-semibold text-foreground", children: call.name }), call.latencyMs != null && (_jsxs("span", { className: "ml-auto tabular-nums text-muted-foreground", children: [call.latencyMs, "ms"] }))] }), _jsxs("div", { className: "text-muted-foreground", children: [Object.entries(call.args && typeof call.args === 'object' ? call.args : {}).map(([k, v], i) => (_jsxs("span", { children: [i > 0 && ', ', _jsx("span", { className: "text-primary", children: k }), ": ", '', _jsx("span", { className: "text-emerald-700", children: safeStringify(v) })] }, k))), call.resultSummary && (_jsxs("span", { className: "text-muted-foreground", children: [" \u2192 ", call.resultSummary] }))] })] }));
19
+ }
@@ -0,0 +1,10 @@
1
+ import type { Turn } from './types.js';
2
+ export interface TranscriptStreamProps {
3
+ turns: Turn[];
4
+ /** When true (default), auto-scroll to bottom on new turn IF user is already near bottom. */
5
+ autoScroll?: boolean;
6
+ tz?: string;
7
+ onTurnPlay?: (turnId: string) => void;
8
+ className?: string;
9
+ }
10
+ export declare function TranscriptStream({ turns, autoScroll, tz, onTurnPlay, className, }: TranscriptStreamProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from 'react';
3
+ import { TurnCard } from './turn-card.js';
4
+ const SCROLL_THRESHOLD = 120;
5
+ export function TranscriptStream({ turns, autoScroll = true, tz, onTurnPlay, className, }) {
6
+ const ref = useRef(null);
7
+ // Snapshot of "was the user near the bottom?" sampled BEFORE the new turn
8
+ // renders, so that a tall appended turn doesn't push the bottom off-screen
9
+ // and falsely look like the user scrolled away.
10
+ const wasAtBottomRef = useRef(true);
11
+ useEffect(() => {
12
+ const el = ref.current;
13
+ if (!el)
14
+ return;
15
+ const onScroll = () => {
16
+ const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
17
+ wasAtBottomRef.current = distanceFromBottom < SCROLL_THRESHOLD;
18
+ };
19
+ el.addEventListener('scroll', onScroll, { passive: true });
20
+ return () => el.removeEventListener('scroll', onScroll);
21
+ }, []);
22
+ // Auto-follow last turn when the user was near the bottom before the new turn appended.
23
+ // biome-ignore lint/correctness/useExhaustiveDependencies: turns changes trigger scroll check
24
+ useEffect(() => {
25
+ const el = ref.current;
26
+ if (!el || !autoScroll)
27
+ return;
28
+ if (wasAtBottomRef.current) {
29
+ el.scrollTop = el.scrollHeight;
30
+ }
31
+ }, [turns, autoScroll]);
32
+ if (turns.length === 0) {
33
+ return (_jsx("div", { ref: ref, className: [
34
+ 'flex flex-1 items-center justify-center text-sm text-muted-foreground',
35
+ className ?? '',
36
+ ].join(' '), children: "No turns yet." }));
37
+ }
38
+ const ref0 = turns[0]?.startedAt ?? 0;
39
+ return (_jsx("div", { ref: ref, className: ['flex-1 overflow-y-auto px-7 pb-6 pt-2', className ?? ''].join(' '), children: turns.map((t) => (_jsx(TurnCard, { turn: t, startedAtRef: ref0, tz: tz, onPlay: onTurnPlay }, t.id))) }));
40
+ }
@@ -0,0 +1,10 @@
1
+ import type { Turn } from './types.js';
2
+ export interface TurnCardProps {
3
+ turn: Turn;
4
+ /** Reference instant for the relative offset column (typically the conversation start). */
5
+ startedAtRef: number;
6
+ tz?: string;
7
+ onPlay?: (turnId: string) => void;
8
+ className?: string;
9
+ }
10
+ export declare function TurnCard({ turn, startedAtRef, tz, onPlay, className }: TurnCardProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Play } from 'lucide-react';
3
+ import { formatClock, formatRelativeOffset } from '../lib/format-time.js';
4
+ import { LatencyBadge } from './latency-badge.js';
5
+ import { ToolCallBlock } from './tool-call-block.js';
6
+ const SPEAKER_LABEL = {
7
+ user: 'You',
8
+ assistant: 'Assistant',
9
+ system: 'System',
10
+ };
11
+ export function TurnCard({ turn, startedAtRef, tz, onPlay, className }) {
12
+ const label = turn.speakerLabel ?? SPEAKER_LABEL[turn.speaker];
13
+ const offset = turn.startedAt - startedAtRef;
14
+ // amber-700 (not -500) for the 11px system speaker label so it clears
15
+ // WCAG AA (4.5:1) against the card background.
16
+ const speakerColor = turn.speaker === 'assistant'
17
+ ? 'text-primary'
18
+ : turn.speaker === 'system'
19
+ ? 'text-amber-700'
20
+ : 'text-foreground';
21
+ return (_jsxs("div", { className: [
22
+ 'grid grid-cols-[64px_1fr] gap-5 border-b border-border py-4 last:border-b-0',
23
+ className ?? '',
24
+ ].join(' '), children: [_jsxs("div", { className: "pt-1 text-[11px] tabular-nums text-muted-foreground", children: [_jsx("strong", { className: "mb-0.5 block text-[12px] font-medium text-muted-foreground", children: formatClock(new Date(turn.startedAt), { tz }) }), formatRelativeOffset(offset)] }), _jsxs("div", { children: [_jsxs("div", { className: "mb-1.5 flex items-center gap-2", children: [_jsx("span", { className: ['text-[11px] font-semibold uppercase tracking-wider', speakerColor].join(' '), children: label }), turn.modelLabel && (_jsx("span", { className: "rounded bg-muted px-1.5 py-px text-[10px] font-medium text-muted-foreground", children: turn.modelLabel })), turn.spokenSeconds != null && turn.speaker === 'user' && (_jsxs("span", { className: "rounded bg-muted px-1.5 py-px text-[10px] font-medium text-muted-foreground", children: ["spoken \u00B7 ", turn.spokenSeconds.toFixed(1), "s"] }))] }), _jsxs("p", { className: "text-[15px] leading-relaxed text-foreground", "data-streaming": String(turn.streaming ?? false), children: [turn.text, turn.streaming && (_jsx("span", { "aria-hidden": "true", className: "ml-0.5 animate-pulse text-primary", children: "\u258D" }))] }), turn.toolCalls?.map((c) => (_jsx(ToolCallBlock, { call: c }, c.id))), (turn.audioUrl || turn.latency) && (_jsxs("div", { className: "mt-2.5 flex flex-wrap items-center gap-4 text-[11px] text-muted-foreground", children: [turn.audioUrl && (_jsx("button", { type: "button", "aria-label": "Play this turn", onClick: () => onPlay?.(turn.id), className: "inline-flex size-6 items-center justify-center rounded-full bg-muted text-muted-foreground hover:text-foreground", children: _jsx(Play, { className: "size-3" }) })), turn.latency?.sttMs != null && _jsx(LatencyBadge, { kind: "stt", ms: turn.latency.sttMs }), turn.latency?.claudeMs != null && (_jsx(LatencyBadge, { kind: "claude", ms: turn.latency.claudeMs })), turn.latency?.ttsMs != null && _jsx(LatencyBadge, { kind: "tts", ms: turn.latency.ttsMs })] }))] })] }));
25
+ }
@@ -0,0 +1,36 @@
1
+ export type Speaker = 'user' | 'assistant' | 'system';
2
+ /** Per-stage latency breakdown for one turn. */
3
+ export interface TurnLatency {
4
+ sttMs?: number;
5
+ claudeMs?: number;
6
+ ttsMs?: number;
7
+ }
8
+ /** A single AI tool / function-call invocation. */
9
+ export interface ToolCall {
10
+ id: string;
11
+ name: string;
12
+ args: Record<string, unknown>;
13
+ /** Short human-readable summary, e.g. "3 events". */
14
+ resultSummary?: string;
15
+ latencyMs?: number;
16
+ }
17
+ /** One conversational exchange. */
18
+ export interface Turn {
19
+ id: string;
20
+ speaker: Speaker;
21
+ /** Display label, e.g. "Morpheus" or "Operator (Ali)". Optional override of speaker. */
22
+ speakerLabel?: string;
23
+ /** Optional model identifier, e.g. "claude-opus-4-7". */
24
+ modelLabel?: string;
25
+ /** URL or blob: URL for per-turn replay. */
26
+ audioUrl?: string;
27
+ /** Spoken duration if known. */
28
+ spokenSeconds?: number;
29
+ text: string;
30
+ /** Unix ms. */
31
+ startedAt: number;
32
+ /** True if the assistant is still streaming this turn. */
33
+ streaming?: boolean;
34
+ latency?: TurnLatency;
35
+ toolCalls?: ToolCall[];
36
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ import { Command as CommandPrimitive } from 'cmdk';
2
+ import type * as React from 'react';
3
+ import { Dialog } from './dialog.js';
4
+ declare function Command({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>): import("react/jsx-runtime").JSX.Element;
5
+ declare function CommandDialog({ title, description, children, className, showCloseButton, ...props }: Omit<React.ComponentProps<typeof Dialog>, 'children'> & {
6
+ title?: string;
7
+ description?: string;
8
+ className?: string;
9
+ showCloseButton?: boolean;
10
+ children: React.ReactNode;
11
+ }): import("react/jsx-runtime").JSX.Element;
12
+ declare function CommandInput({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Input>): import("react/jsx-runtime").JSX.Element;
13
+ declare function CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.List>): import("react/jsx-runtime").JSX.Element;
14
+ declare function CommandEmpty({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Empty>): import("react/jsx-runtime").JSX.Element;
15
+ declare function CommandGroup({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Group>): import("react/jsx-runtime").JSX.Element;
16
+ declare function CommandSeparator({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Separator>): import("react/jsx-runtime").JSX.Element;
17
+ declare function CommandItem({ className, children, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>): import("react/jsx-runtime").JSX.Element;
18
+ declare function CommandShortcut({ className, ...props }: React.ComponentProps<'span'>): import("react/jsx-runtime").JSX.Element;
19
+ export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, };
@@ -0,0 +1,37 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Command as CommandPrimitive } from 'cmdk';
4
+ import { SearchIcon } from 'lucide-react';
5
+ import { cn } from '../../lib/utils.js';
6
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from './dialog.js';
7
+ function Command({ className, ...props }) {
8
+ return (_jsx(CommandPrimitive, { "data-slot": "command", className: cn('flex size-full flex-col overflow-hidden bg-popover text-popover-foreground', className), ...props }));
9
+ }
10
+ function CommandDialog({ title = 'Command Palette', description = 'Search for a command to run...', children, className, showCloseButton = false, ...props }) {
11
+ return (_jsxs(Dialog, { ...props, children: [_jsxs(DialogHeader, { className: "sr-only", children: [_jsx(DialogTitle, { children: title }), _jsx(DialogDescription, { children: description })] }), _jsx(DialogContent, { className: cn('top-[38%] overflow-hidden rounded-xl! p-0 sm:max-w-2xl', className), showCloseButton: showCloseButton, children: children })] }));
12
+ }
13
+ function CommandInput({ className, ...props }) {
14
+ return (_jsxs("div", { "data-slot": "command-input-wrapper", className: "flex items-center gap-3 border-b px-4 py-3", children: [_jsx(SearchIcon, { className: "size-5 shrink-0 text-muted-foreground/60" }), _jsx(CommandPrimitive.Input, { "data-slot": "command-input", className: cn('flex-1 bg-transparent text-base outline-none placeholder:text-muted-foreground/60 disabled:cursor-not-allowed disabled:opacity-50', className), ...props })] }));
15
+ }
16
+ function CommandList({ className, ...props }) {
17
+ return (_jsx(CommandPrimitive.List, { "data-slot": "command-list", className: cn('no-scrollbar max-h-[400px] scroll-py-1 overflow-y-auto overflow-x-hidden p-2 outline-none', className), ...props }));
18
+ }
19
+ function CommandEmpty({ className, ...props }) {
20
+ return (_jsx(CommandPrimitive.Empty, { "data-slot": "command-empty", className: cn('py-6 text-center text-sm', className), ...props }));
21
+ }
22
+ function CommandGroup({ className, ...props }) {
23
+ return (_jsx(CommandPrimitive.Group, { "data-slot": "command-group", className: cn(
24
+ // group heading uses solid muted-foreground (not /70) so 12px
25
+ // labels meet WCAG AA contrast on the popover background.
26
+ 'overflow-hidden text-foreground [&:first-child_[cmdk-group-heading]]:pt-1 [&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:pt-4 [&_[cmdk-group-heading]]:pb-1 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:text-xs', className), ...props }));
27
+ }
28
+ function CommandSeparator({ className, ...props }) {
29
+ return (_jsx(CommandPrimitive.Separator, { "data-slot": "command-separator", className: cn('-mx-1 h-px bg-border', className), ...props }));
30
+ }
31
+ function CommandItem({ className, children, ...props }) {
32
+ return (_jsx(CommandPrimitive.Item, { "data-slot": "command-item", className: cn("group/command-item relative flex cursor-default select-none items-center gap-3 rounded-lg px-3 py-2 text-sm outline-hidden data-[disabled=true]:pointer-events-none data-selected:bg-accent data-selected:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg:not([class*='size-'])]:size-5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:text-muted-foreground data-selected:[&_svg]:text-accent-foreground", className), ...props, children: children }));
33
+ }
34
+ function CommandShortcut({ className, ...props }) {
35
+ return (_jsx("span", { "data-slot": "command-shortcut", className: cn('ml-auto text-muted-foreground text-xs tracking-widest group-data-selected/command-item:text-foreground', className), ...props }));
36
+ }
37
+ export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, };
@@ -0,0 +1,26 @@
1
+ import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
2
+ import type * as React from 'react';
3
+ interface DialogProps extends DialogPrimitive.Root.Props {
4
+ /**
5
+ * When false, prevents closing via backdrop/outside clicks.
6
+ * Escape key and X button still work (WCAG compliance).
7
+ * @default true
8
+ */
9
+ dismissible?: boolean;
10
+ }
11
+ declare function Dialog({ dismissible, ...props }: DialogProps): import("react/jsx-runtime").JSX.Element;
12
+ interface DialogTriggerProps extends Omit<React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>, 'render'> {
13
+ render?: React.ReactElement;
14
+ }
15
+ declare function DialogTrigger({ render, children, ...props }: DialogTriggerProps): import("react/jsx-runtime").JSX.Element;
16
+ declare function DialogPortal({ ...props }: DialogPrimitive.Portal.Props): import("react/jsx-runtime").JSX.Element;
17
+ declare function DialogClose({ ...props }: DialogPrimitive.Close.Props): import("react/jsx-runtime").JSX.Element;
18
+ declare function DialogOverlay({ className, ...props }: DialogPrimitive.Backdrop.Props): import("react/jsx-runtime").JSX.Element;
19
+ declare function DialogContent({ className, children, showCloseButton, ...props }: DialogPrimitive.Popup.Props & {
20
+ showCloseButton?: boolean;
21
+ }): import("react/jsx-runtime").JSX.Element;
22
+ declare function DialogHeader({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
23
+ declare function DialogFooter({ className, children, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
24
+ declare function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props): import("react/jsx-runtime").JSX.Element;
25
+ declare function DialogDescription({ className, ...props }: DialogPrimitive.Description.Props): import("react/jsx-runtime").JSX.Element;
26
+ export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, };
@@ -0,0 +1,39 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
4
+ import { XIcon } from 'lucide-react';
5
+ import { cn } from '../../lib/utils.js';
6
+ function Dialog({ dismissible = true, ...props }) {
7
+ return (_jsx(DialogPrimitive.Root, { "data-slot": "dialog", disablePointerDismissal: !dismissible, ...props }));
8
+ }
9
+ function DialogTrigger({ render, children, ...props }) {
10
+ if (render) {
11
+ return (_jsx(DialogPrimitive.Trigger, { "data-slot": "dialog-trigger", render: render, ...props, children: children }));
12
+ }
13
+ return (_jsx(DialogPrimitive.Trigger, { "data-slot": "dialog-trigger", ...props, children: children }));
14
+ }
15
+ function DialogPortal({ ...props }) {
16
+ return _jsx(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
17
+ }
18
+ function DialogClose({ ...props }) {
19
+ return _jsx(DialogPrimitive.Close, { "data-slot": "dialog-close", ...props });
20
+ }
21
+ function DialogOverlay({ className, ...props }) {
22
+ return (_jsx(DialogPrimitive.Backdrop, { "data-slot": "dialog-overlay", className: cn('data-closed:fade-out-0 data-open:fade-in-0 fixed inset-0 isolate z-50 bg-black/20 duration-100 data-closed:animate-out data-open:animate-in motion-reduce:duration-0 supports-backdrop-filter:backdrop-blur-xs dark:bg-black/40', className), ...props }));
23
+ }
24
+ function DialogContent({ className, children, showCloseButton = true, ...props }) {
25
+ return (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Popup, { "data-slot": "dialog-content", className: cn('data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-lg bg-background p-4 text-sm outline-none ring-1 ring-foreground/10 duration-100 data-closed:animate-out data-open:animate-in motion-reduce:duration-0 sm:max-w-sm overscroll-behavior-y-contain dark:ring-border', className), ...props, children: [children, showCloseButton && (_jsxs(DialogPrimitive.Close, { "data-slot": "dialog-close", className: "absolute top-2 right-2 inline-flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-accent-foreground", children: [_jsx(XIcon, { size: 16 }), _jsx("span", { className: "sr-only", children: "Close" })] }))] })] }));
26
+ }
27
+ function DialogHeader({ className, ...props }) {
28
+ return (_jsx("div", { "data-slot": "dialog-header", className: cn('flex flex-col gap-2', className), ...props }));
29
+ }
30
+ function DialogFooter({ className, children, ...props }) {
31
+ return (_jsx("div", { "data-slot": "dialog-footer", className: cn('-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end dark:bg-muted/70', className), ...props, children: children }));
32
+ }
33
+ function DialogTitle({ className, ...props }) {
34
+ return (_jsx(DialogPrimitive.Title, { "data-slot": "dialog-title", className: cn('font-semibold text-base leading-snug tracking-tight', className), ...props }));
35
+ }
36
+ function DialogDescription({ className, ...props }) {
37
+ return (_jsx(DialogPrimitive.Description, { "data-slot": "dialog-description", className: cn('text-muted-foreground text-sm *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground', className), ...props }));
38
+ }
39
+ export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, };
@@ -0,0 +1,16 @@
1
+ import type * as React from 'react';
2
+ import { Drawer as DrawerPrimitive } from 'vaul';
3
+ declare function Drawer({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
4
+ declare function DrawerTrigger({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Trigger>): import("react/jsx-runtime").JSX.Element;
5
+ declare function DrawerPortal({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Portal>): import("react/jsx-runtime").JSX.Element;
6
+ declare function DrawerClose({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Close>): import("react/jsx-runtime").JSX.Element;
7
+ declare function DrawerOverlay({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Overlay>): import("react/jsx-runtime").JSX.Element;
8
+ declare function DrawerContent({ className, children, showOverlay, overlayClassName, ...props }: React.ComponentProps<typeof DrawerPrimitive.Content> & {
9
+ showOverlay?: boolean;
10
+ overlayClassName?: string;
11
+ }): import("react/jsx-runtime").JSX.Element;
12
+ declare function DrawerHeader({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
13
+ declare function DrawerFooter({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
14
+ declare function DrawerTitle({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Title>): import("react/jsx-runtime").JSX.Element;
15
+ declare function DrawerDescription({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Description>): import("react/jsx-runtime").JSX.Element;
16
+ export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, };
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Drawer as DrawerPrimitive } from 'vaul';
4
+ import { cn } from '../../lib/utils.js';
5
+ function Drawer({ ...props }) {
6
+ return _jsx(DrawerPrimitive.Root, { "data-slot": "drawer", ...props });
7
+ }
8
+ function DrawerTrigger({ ...props }) {
9
+ return _jsx(DrawerPrimitive.Trigger, { "data-slot": "drawer-trigger", ...props });
10
+ }
11
+ function DrawerPortal({ ...props }) {
12
+ return _jsx(DrawerPrimitive.Portal, { "data-slot": "drawer-portal", ...props });
13
+ }
14
+ function DrawerClose({ ...props }) {
15
+ return _jsx(DrawerPrimitive.Close, { "data-slot": "drawer-close", ...props });
16
+ }
17
+ function DrawerOverlay({ className, ...props }) {
18
+ return (_jsx(DrawerPrimitive.Overlay, { "data-slot": "drawer-overlay", className: cn('data-closed:fade-out-0 data-open:fade-in-0 fixed inset-0 z-50 bg-black/10 data-closed:animate-out data-open:animate-in supports-backdrop-filter:backdrop-blur-xs dark:bg-black/40', className), ...props }));
19
+ }
20
+ function DrawerContent({ className, children, showOverlay = true, overlayClassName, ...props }) {
21
+ return (_jsxs(DrawerPortal, { "data-slot": "drawer-portal", children: [showOverlay ? _jsx(DrawerOverlay, { className: overlayClassName }) : null, _jsxs(DrawerPrimitive.Content, { "data-slot": "drawer-content", className: cn('group/drawer-content fixed z-50 flex h-auto flex-col bg-card text-sm data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=bottom]:rounded-t-xl data-[vaul-drawer-direction=left]:rounded-r-xl data-[vaul-drawer-direction=top]:rounded-b-xl data-[vaul-drawer-direction=right]:rounded-l-xl data-[vaul-drawer-direction=bottom]:border-t data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=top]:border-b data-[vaul-drawer-direction=right]:border-l border-border data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm', className), ...props, children: [_jsx("div", { className: "mx-auto mt-4 hidden h-1 w-[100px] shrink-0 rounded-full bg-muted group-data-[vaul-drawer-direction=bottom]/drawer-content:block" }), children] })] }));
22
+ }
23
+ function DrawerHeader({ className, ...props }) {
24
+ return (_jsx("div", { "data-slot": "drawer-header", className: cn('flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-0.5 md:text-left', className), ...props }));
25
+ }
26
+ function DrawerFooter({ className, ...props }) {
27
+ return (_jsx("div", { "data-slot": "drawer-footer", className: cn('mt-auto flex flex-col gap-2 p-4', className), ...props }));
28
+ }
29
+ function DrawerTitle({ className, ...props }) {
30
+ return (_jsx(DrawerPrimitive.Title, { "data-slot": "drawer-title", className: cn('font-semibold text-base text-foreground leading-snug tracking-tight', className), ...props }));
31
+ }
32
+ function DrawerDescription({ className, ...props }) {
33
+ return (_jsx(DrawerPrimitive.Description, { "data-slot": "drawer-description", className: cn('text-muted-foreground text-sm', className), ...props }));
34
+ }
35
+ export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, };
@@ -0,0 +1,32 @@
1
+ import { Menu as MenuPrimitive } from '@base-ui/react/menu';
2
+ import type * as React from 'react';
3
+ declare function DropdownMenu({ ...props }: MenuPrimitive.Root.Props): import("react/jsx-runtime").JSX.Element;
4
+ declare function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props): import("react/jsx-runtime").JSX.Element;
5
+ interface DropdownMenuTriggerProps extends Omit<MenuPrimitive.Trigger.Props, 'render'> {
6
+ render?: React.ReactElement | MenuPrimitive.Trigger.Props['render'];
7
+ }
8
+ declare function DropdownMenuTrigger({ render, children, ...props }: DropdownMenuTriggerProps): import("react/jsx-runtime").JSX.Element;
9
+ declare function DropdownMenuContent({ align, alignOffset, side, sideOffset, className, ...props }: MenuPrimitive.Popup.Props & Pick<MenuPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>): import("react/jsx-runtime").JSX.Element;
10
+ declare function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props): import("react/jsx-runtime").JSX.Element;
11
+ declare function DropdownMenuLabel({ className, inset, ...props }: MenuPrimitive.GroupLabel.Props & {
12
+ inset?: boolean;
13
+ }): import("react/jsx-runtime").JSX.Element;
14
+ interface MenuItemProps extends Omit<MenuPrimitive.Item.Props, 'render' | 'onClick' | 'onSelect'> {
15
+ inset?: boolean;
16
+ variant?: 'default' | 'destructive';
17
+ render?: React.ReactElement;
18
+ onClick?: MenuPrimitive.Item.Props['onClick'];
19
+ onSelect?: MenuPrimitive.Item.Props['onClick'];
20
+ }
21
+ declare function DropdownMenuItem({ className, inset, variant, render, onClick, onSelect, children, ...props }: MenuItemProps): import("react/jsx-runtime").JSX.Element;
22
+ declare function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props): import("react/jsx-runtime").JSX.Element;
23
+ declare function DropdownMenuSubTrigger({ className, inset, children, ...props }: MenuPrimitive.SubmenuTrigger.Props & {
24
+ inset?: boolean;
25
+ }): import("react/jsx-runtime").JSX.Element;
26
+ declare function DropdownMenuSubContent({ align, alignOffset, side, sideOffset, className, ...props }: React.ComponentProps<typeof DropdownMenuContent>): import("react/jsx-runtime").JSX.Element;
27
+ declare function DropdownMenuCheckboxItem({ className, children, checked, ...props }: MenuPrimitive.CheckboxItem.Props): import("react/jsx-runtime").JSX.Element;
28
+ declare function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props): import("react/jsx-runtime").JSX.Element;
29
+ declare function DropdownMenuRadioItem({ className, children, ...props }: MenuPrimitive.RadioItem.Props): import("react/jsx-runtime").JSX.Element;
30
+ declare function DropdownMenuSeparator({ className, ...props }: MenuPrimitive.Separator.Props): import("react/jsx-runtime").JSX.Element;
31
+ declare function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>): import("react/jsx-runtime").JSX.Element;
32
+ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type MenuItemProps, };