langwatch 0.1.7 → 0.3.0-prerelease.1

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 (235) hide show
  1. package/.editorconfig +16 -0
  2. package/LICENSE +7 -0
  3. package/README.md +268 -1
  4. package/copy-types.sh +19 -8
  5. package/examples/langchain/.env.example +2 -0
  6. package/examples/langchain/README.md +42 -0
  7. package/examples/langchain/package-lock.json +2930 -0
  8. package/examples/langchain/package.json +27 -0
  9. package/examples/langchain/src/cli-markdown.d.ts +137 -0
  10. package/examples/langchain/src/index.ts +109 -0
  11. package/examples/langchain/tsconfig.json +25 -0
  12. package/examples/langgraph/.env.example +2 -0
  13. package/examples/langgraph/README.md +42 -0
  14. package/examples/langgraph/package-lock.json +3031 -0
  15. package/examples/langgraph/package.json +28 -0
  16. package/examples/langgraph/src/cli-markdown.d.ts +137 -0
  17. package/examples/langgraph/src/index.ts +196 -0
  18. package/examples/langgraph/tsconfig.json +25 -0
  19. package/examples/mastra/.env.example +2 -0
  20. package/examples/mastra/README.md +57 -0
  21. package/examples/mastra/package-lock.json +5296 -0
  22. package/examples/mastra/package.json +32 -0
  23. package/examples/mastra/src/cli-markdown.d.ts +137 -0
  24. package/examples/mastra/src/index.ts +120 -0
  25. package/examples/mastra/src/mastra/agents/weather-agent.ts +30 -0
  26. package/examples/mastra/src/mastra/index.ts +21 -0
  27. package/examples/mastra/src/mastra/tools/weather-tool.ts +102 -0
  28. package/examples/mastra/tsconfig.json +25 -0
  29. package/examples/vercel-ai/.env.example +2 -0
  30. package/examples/vercel-ai/README.md +38 -0
  31. package/examples/vercel-ai/package-lock.json +2571 -0
  32. package/examples/vercel-ai/package.json +27 -0
  33. package/examples/vercel-ai/src/cli-markdown.d.ts +137 -0
  34. package/examples/vercel-ai/src/index.ts +110 -0
  35. package/examples/vercel-ai/src/instrumentation.ts +9 -0
  36. package/examples/vercel-ai/tsconfig.json +25 -0
  37. package/package.json +80 -33
  38. package/src/__tests__/client-browser.test.ts +92 -0
  39. package/src/__tests__/client-node.test.ts +76 -0
  40. package/src/__tests__/client.test.ts +71 -0
  41. package/src/__tests__/integration/client-browser.test.ts +46 -0
  42. package/src/__tests__/integration/client-node.test.ts +46 -0
  43. package/src/client-browser.ts +70 -0
  44. package/src/client-node.ts +82 -0
  45. package/src/client-shared.ts +72 -0
  46. package/src/client.ts +119 -0
  47. package/src/evaluation/__tests__/record-evaluation.test.ts +112 -0
  48. package/src/evaluation/__tests__/run-evaluation.test.ts +171 -0
  49. package/src/evaluation/index.ts +2 -0
  50. package/src/evaluation/record-evaluation.ts +101 -0
  51. package/src/evaluation/run-evaluation.ts +133 -0
  52. package/src/evaluation/tracer.ts +3 -0
  53. package/src/evaluation/types.ts +23 -0
  54. package/src/index.ts +10 -591
  55. package/src/internal/api/__tests__/errors.test.ts +98 -0
  56. package/src/internal/api/client.ts +30 -0
  57. package/src/internal/api/errors.ts +32 -0
  58. package/src/internal/generated/types/.gitkeep +0 -0
  59. package/src/observability/__tests__/integration/base.test.ts +74 -0
  60. package/src/observability/__tests__/integration/browser-setup-ordering.test.ts +60 -0
  61. package/src/observability/__tests__/integration/complex-nested-spans.test.ts +29 -0
  62. package/src/observability/__tests__/integration/error-handling.test.ts +24 -0
  63. package/src/observability/__tests__/integration/langwatch-disabled-otel.test.ts +24 -0
  64. package/src/observability/__tests__/integration/langwatch-first-then-vercel.test.ts +24 -0
  65. package/src/observability/__tests__/integration/multiple-setup-attempts.test.ts +27 -0
  66. package/src/observability/__tests__/integration/otel-ordering.test.ts +27 -0
  67. package/src/observability/__tests__/integration/vercel-configurations.test.ts +20 -0
  68. package/src/observability/__tests__/integration/vercel-first-then-langwatch.test.ts +27 -0
  69. package/src/observability/__tests__/span.test.ts +214 -0
  70. package/src/observability/__tests__/trace.test.ts +180 -0
  71. package/src/observability/exporters/index.ts +1 -0
  72. package/src/observability/exporters/langwatch-exporter.ts +53 -0
  73. package/src/observability/index.ts +4 -0
  74. package/src/observability/instrumentation/langchain/__tests__/integration/langchain-chatbot.test.ts +112 -0
  75. package/src/observability/instrumentation/langchain/__tests__/langchain.test.ts +284 -0
  76. package/src/observability/instrumentation/langchain/index.ts +624 -0
  77. package/src/observability/processors/__tests__/filterable-batch-span-exporter.test.ts +98 -0
  78. package/src/observability/processors/filterable-batch-span-processor.ts +99 -0
  79. package/src/observability/processors/index.ts +1 -0
  80. package/src/observability/semconv/attributes.ts +185 -0
  81. package/src/observability/semconv/events.ts +42 -0
  82. package/src/observability/semconv/index.ts +16 -0
  83. package/src/observability/semconv/values.ts +159 -0
  84. package/src/observability/span.ts +728 -0
  85. package/src/observability/trace.ts +301 -0
  86. package/src/prompt/__tests__/prompt.test.ts +139 -0
  87. package/src/prompt/get-prompt-version.ts +49 -0
  88. package/src/prompt/get-prompt.ts +44 -0
  89. package/src/prompt/index.ts +3 -0
  90. package/src/prompt/prompt.ts +133 -0
  91. package/src/prompt/service.ts +221 -0
  92. package/src/prompt/tracer.ts +3 -0
  93. package/src/prompt/types.ts +0 -0
  94. package/ts-to-zod.config.js +11 -0
  95. package/tsconfig.json +3 -9
  96. package/tsup.config.ts +11 -1
  97. package/vitest.config.ts +1 -0
  98. package/dist/chunk-FWBCQQYZ.mjs +0 -711
  99. package/dist/chunk-FWBCQQYZ.mjs.map +0 -1
  100. package/dist/index.d.mts +0 -1010
  101. package/dist/index.d.ts +0 -1010
  102. package/dist/index.js +0 -27294
  103. package/dist/index.js.map +0 -1
  104. package/dist/index.mjs +0 -959
  105. package/dist/index.mjs.map +0 -1
  106. package/dist/utils-B0pgWcps.d.mts +0 -303
  107. package/dist/utils-B0pgWcps.d.ts +0 -303
  108. package/dist/utils.d.mts +0 -2
  109. package/dist/utils.d.ts +0 -2
  110. package/dist/utils.js +0 -703
  111. package/dist/utils.js.map +0 -1
  112. package/dist/utils.mjs +0 -11
  113. package/dist/utils.mjs.map +0 -1
  114. package/example/.env.example +0 -12
  115. package/example/.eslintrc.json +0 -26
  116. package/example/LICENSE +0 -13
  117. package/example/README.md +0 -12
  118. package/example/app/(chat)/chat/[id]/page.tsx +0 -60
  119. package/example/app/(chat)/layout.tsx +0 -14
  120. package/example/app/(chat)/page.tsx +0 -27
  121. package/example/app/actions.ts +0 -156
  122. package/example/app/globals.css +0 -76
  123. package/example/app/guardrails/page.tsx +0 -26
  124. package/example/app/langchain/page.tsx +0 -27
  125. package/example/app/langchain-rag/page.tsx +0 -28
  126. package/example/app/late-update/page.tsx +0 -27
  127. package/example/app/layout.tsx +0 -64
  128. package/example/app/login/actions.ts +0 -71
  129. package/example/app/login/page.tsx +0 -18
  130. package/example/app/manual/page.tsx +0 -27
  131. package/example/app/new/page.tsx +0 -5
  132. package/example/app/opengraph-image.png +0 -0
  133. package/example/app/share/[id]/page.tsx +0 -58
  134. package/example/app/signup/actions.ts +0 -111
  135. package/example/app/signup/page.tsx +0 -18
  136. package/example/app/twitter-image.png +0 -0
  137. package/example/auth.config.ts +0 -42
  138. package/example/auth.ts +0 -45
  139. package/example/components/button-scroll-to-bottom.tsx +0 -36
  140. package/example/components/chat-history.tsx +0 -49
  141. package/example/components/chat-list.tsx +0 -52
  142. package/example/components/chat-message-actions.tsx +0 -40
  143. package/example/components/chat-message.tsx +0 -80
  144. package/example/components/chat-panel.tsx +0 -139
  145. package/example/components/chat-share-dialog.tsx +0 -95
  146. package/example/components/chat.tsx +0 -84
  147. package/example/components/clear-history.tsx +0 -75
  148. package/example/components/empty-screen.tsx +0 -38
  149. package/example/components/external-link.tsx +0 -29
  150. package/example/components/footer.tsx +0 -19
  151. package/example/components/header.tsx +0 -114
  152. package/example/components/login-button.tsx +0 -42
  153. package/example/components/login-form.tsx +0 -97
  154. package/example/components/markdown.tsx +0 -9
  155. package/example/components/prompt-form.tsx +0 -115
  156. package/example/components/providers.tsx +0 -17
  157. package/example/components/sidebar-actions.tsx +0 -125
  158. package/example/components/sidebar-desktop.tsx +0 -19
  159. package/example/components/sidebar-footer.tsx +0 -16
  160. package/example/components/sidebar-item.tsx +0 -124
  161. package/example/components/sidebar-items.tsx +0 -42
  162. package/example/components/sidebar-list.tsx +0 -38
  163. package/example/components/sidebar-mobile.tsx +0 -31
  164. package/example/components/sidebar-toggle.tsx +0 -24
  165. package/example/components/sidebar.tsx +0 -21
  166. package/example/components/signup-form.tsx +0 -95
  167. package/example/components/stocks/events-skeleton.tsx +0 -31
  168. package/example/components/stocks/events.tsx +0 -30
  169. package/example/components/stocks/index.tsx +0 -36
  170. package/example/components/stocks/message.tsx +0 -134
  171. package/example/components/stocks/spinner.tsx +0 -16
  172. package/example/components/stocks/stock-purchase.tsx +0 -146
  173. package/example/components/stocks/stock-skeleton.tsx +0 -22
  174. package/example/components/stocks/stock.tsx +0 -210
  175. package/example/components/stocks/stocks-skeleton.tsx +0 -9
  176. package/example/components/stocks/stocks.tsx +0 -67
  177. package/example/components/tailwind-indicator.tsx +0 -14
  178. package/example/components/theme-toggle.tsx +0 -31
  179. package/example/components/ui/alert-dialog.tsx +0 -141
  180. package/example/components/ui/badge.tsx +0 -36
  181. package/example/components/ui/button.tsx +0 -57
  182. package/example/components/ui/codeblock.tsx +0 -148
  183. package/example/components/ui/dialog.tsx +0 -122
  184. package/example/components/ui/dropdown-menu.tsx +0 -205
  185. package/example/components/ui/icons.tsx +0 -507
  186. package/example/components/ui/input.tsx +0 -25
  187. package/example/components/ui/label.tsx +0 -26
  188. package/example/components/ui/select.tsx +0 -164
  189. package/example/components/ui/separator.tsx +0 -31
  190. package/example/components/ui/sheet.tsx +0 -140
  191. package/example/components/ui/sonner.tsx +0 -31
  192. package/example/components/ui/switch.tsx +0 -29
  193. package/example/components/ui/textarea.tsx +0 -24
  194. package/example/components/ui/tooltip.tsx +0 -30
  195. package/example/components/user-menu.tsx +0 -53
  196. package/example/components.json +0 -17
  197. package/example/instrumentation.ts +0 -11
  198. package/example/lib/chat/guardrails.tsx +0 -181
  199. package/example/lib/chat/langchain-rag.tsx +0 -191
  200. package/example/lib/chat/langchain.tsx +0 -112
  201. package/example/lib/chat/late-update.tsx +0 -208
  202. package/example/lib/chat/manual.tsx +0 -605
  203. package/example/lib/chat/vercel-ai.tsx +0 -576
  204. package/example/lib/hooks/use-copy-to-clipboard.tsx +0 -33
  205. package/example/lib/hooks/use-enter-submit.tsx +0 -23
  206. package/example/lib/hooks/use-local-storage.ts +0 -24
  207. package/example/lib/hooks/use-scroll-anchor.tsx +0 -86
  208. package/example/lib/hooks/use-sidebar.tsx +0 -60
  209. package/example/lib/hooks/use-streamable-text.ts +0 -25
  210. package/example/lib/types.ts +0 -41
  211. package/example/lib/utils.ts +0 -89
  212. package/example/middleware.ts +0 -8
  213. package/example/next-env.d.ts +0 -5
  214. package/example/next.config.js +0 -16
  215. package/example/package-lock.json +0 -9990
  216. package/example/package.json +0 -84
  217. package/example/pnpm-lock.yaml +0 -5712
  218. package/example/postcss.config.js +0 -6
  219. package/example/prettier.config.cjs +0 -34
  220. package/example/public/apple-touch-icon.png +0 -0
  221. package/example/public/favicon-16x16.png +0 -0
  222. package/example/public/favicon.ico +0 -0
  223. package/example/public/next.svg +0 -1
  224. package/example/public/thirteen.svg +0 -1
  225. package/example/public/vercel.svg +0 -1
  226. package/example/tailwind.config.ts +0 -81
  227. package/example/tsconfig.json +0 -35
  228. package/src/LangWatchExporter.ts +0 -91
  229. package/src/evaluations.ts +0 -219
  230. package/src/index.test.ts +0 -402
  231. package/src/langchain.ts +0 -557
  232. package/src/typeUtils.ts +0 -89
  233. package/src/types.ts +0 -79
  234. package/src/utils.ts +0 -205
  235. /package/src/{server/types → internal/generated/openapi}/.gitkeep +0 -0
@@ -1,148 +0,0 @@
1
- // Inspired by Chatbot-UI and modified to fit the needs of this project
2
- // @see https://github.com/mckaywrigley/chatbot-ui/blob/main/components/Markdown/CodeBlock.tsx
3
-
4
- 'use client'
5
-
6
- import { FC, memo } from 'react'
7
- import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
8
- import { coldarkDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'
9
-
10
- import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-clipboard'
11
- import { IconCheck, IconCopy, IconDownload } from '@/components/ui/icons'
12
- import { Button } from '@/components/ui/button'
13
-
14
- interface Props {
15
- language: string
16
- value: string
17
- }
18
-
19
- interface languageMap {
20
- [key: string]: string | undefined
21
- }
22
-
23
- export const programmingLanguages: languageMap = {
24
- javascript: '.js',
25
- python: '.py',
26
- java: '.java',
27
- c: '.c',
28
- cpp: '.cpp',
29
- 'c++': '.cpp',
30
- 'c#': '.cs',
31
- ruby: '.rb',
32
- php: '.php',
33
- swift: '.swift',
34
- 'objective-c': '.m',
35
- kotlin: '.kt',
36
- typescript: '.ts',
37
- go: '.go',
38
- perl: '.pl',
39
- rust: '.rs',
40
- scala: '.scala',
41
- haskell: '.hs',
42
- lua: '.lua',
43
- shell: '.sh',
44
- sql: '.sql',
45
- html: '.html',
46
- css: '.css'
47
- // add more file extensions here, make sure the key is same as language prop in CodeBlock.tsx component
48
- }
49
-
50
- export const generateRandomString = (length: number, lowercase = false) => {
51
- const chars = 'ABCDEFGHJKLMNPQRSTUVWXY3456789' // excluding similar looking characters like Z, 2, I, 1, O, 0
52
- let result = ''
53
- for (let i = 0; i < length; i++) {
54
- result += chars.charAt(Math.floor(Math.random() * chars.length))
55
- }
56
- return lowercase ? result.toLowerCase() : result
57
- }
58
-
59
- const CodeBlock: FC<Props> = memo(({ language, value }) => {
60
- const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 })
61
-
62
- const downloadAsFile = () => {
63
- if (typeof window === 'undefined') {
64
- return
65
- }
66
- const fileExtension = programmingLanguages[language] || '.file'
67
- const suggestedFileName = `file-${generateRandomString(
68
- 3,
69
- true
70
- )}${fileExtension}`
71
- const fileName = window.prompt('Enter file name' || '', suggestedFileName)
72
-
73
- if (!fileName) {
74
- // User pressed cancel on prompt.
75
- return
76
- }
77
-
78
- const blob = new Blob([value], { type: 'text/plain' })
79
- const url = URL.createObjectURL(blob)
80
- const link = document.createElement('a')
81
- link.download = fileName
82
- link.href = url
83
- link.style.display = 'none'
84
- document.body.appendChild(link)
85
- link.click()
86
- document.body.removeChild(link)
87
- URL.revokeObjectURL(url)
88
- }
89
-
90
- const onCopy = () => {
91
- if (isCopied) return
92
- copyToClipboard(value)
93
- }
94
-
95
- return (
96
- <div className="relative w-full font-sans codeblock bg-zinc-950">
97
- <div className="flex items-center justify-between w-full px-6 py-2 pr-4 bg-zinc-800 text-zinc-100">
98
- <span className="text-xs lowercase">{language}</span>
99
- <div className="flex items-center space-x-1">
100
- <Button
101
- variant="ghost"
102
- className="hover:bg-zinc-800 focus-visible:ring-1 focus-visible:ring-slate-700 focus-visible:ring-offset-0"
103
- onClick={downloadAsFile}
104
- size="icon"
105
- >
106
- <IconDownload />
107
- <span className="sr-only">Download</span>
108
- </Button>
109
- <Button
110
- variant="ghost"
111
- size="icon"
112
- className="text-xs hover:bg-zinc-800 focus-visible:ring-1 focus-visible:ring-slate-700 focus-visible:ring-offset-0"
113
- onClick={onCopy}
114
- >
115
- {isCopied ? <IconCheck /> : <IconCopy />}
116
- <span className="sr-only">Copy code</span>
117
- </Button>
118
- </div>
119
- </div>
120
- <SyntaxHighlighter
121
- language={language}
122
- style={coldarkDark}
123
- PreTag="div"
124
- showLineNumbers
125
- customStyle={{
126
- margin: 0,
127
- width: '100%',
128
- background: 'transparent',
129
- padding: '1.5rem 1rem'
130
- }}
131
- lineNumberStyle={{
132
- userSelect: 'none'
133
- }}
134
- codeTagProps={{
135
- style: {
136
- fontSize: '0.9rem',
137
- fontFamily: 'var(--font-mono)'
138
- }
139
- }}
140
- >
141
- {value}
142
- </SyntaxHighlighter>
143
- </div>
144
- )
145
- })
146
- CodeBlock.displayName = 'CodeBlock'
147
-
148
- export { CodeBlock }
@@ -1,122 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as DialogPrimitive from "@radix-ui/react-dialog"
5
- import { Cross2Icon } from "@radix-ui/react-icons"
6
-
7
- import { cn } from "@/lib/utils"
8
-
9
- const Dialog = DialogPrimitive.Root
10
-
11
- const DialogTrigger = DialogPrimitive.Trigger
12
-
13
- const DialogPortal = DialogPrimitive.Portal
14
-
15
- const DialogClose = DialogPrimitive.Close
16
-
17
- const DialogOverlay = React.forwardRef<
18
- React.ElementRef<typeof DialogPrimitive.Overlay>,
19
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
20
- >(({ className, ...props }, ref) => (
21
- <DialogPrimitive.Overlay
22
- ref={ref}
23
- className={cn(
24
- "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
25
- className
26
- )}
27
- {...props}
28
- />
29
- ))
30
- DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
31
-
32
- const DialogContent = React.forwardRef<
33
- React.ElementRef<typeof DialogPrimitive.Content>,
34
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
35
- >(({ className, children, ...props }, ref) => (
36
- <DialogPortal>
37
- <DialogOverlay />
38
- <DialogPrimitive.Content
39
- ref={ref}
40
- className={cn(
41
- "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
42
- className
43
- )}
44
- {...props}
45
- >
46
- {children}
47
- <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
48
- <Cross2Icon className="size-4" />
49
- <span className="sr-only">Close</span>
50
- </DialogPrimitive.Close>
51
- </DialogPrimitive.Content>
52
- </DialogPortal>
53
- ))
54
- DialogContent.displayName = DialogPrimitive.Content.displayName
55
-
56
- const DialogHeader = ({
57
- className,
58
- ...props
59
- }: React.HTMLAttributes<HTMLDivElement>) => (
60
- <div
61
- className={cn(
62
- "flex flex-col space-y-1.5 text-center sm:text-left",
63
- className
64
- )}
65
- {...props}
66
- />
67
- )
68
- DialogHeader.displayName = "DialogHeader"
69
-
70
- const DialogFooter = ({
71
- className,
72
- ...props
73
- }: React.HTMLAttributes<HTMLDivElement>) => (
74
- <div
75
- className={cn(
76
- "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
77
- className
78
- )}
79
- {...props}
80
- />
81
- )
82
- DialogFooter.displayName = "DialogFooter"
83
-
84
- const DialogTitle = React.forwardRef<
85
- React.ElementRef<typeof DialogPrimitive.Title>,
86
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
87
- >(({ className, ...props }, ref) => (
88
- <DialogPrimitive.Title
89
- ref={ref}
90
- className={cn(
91
- "text-lg font-semibold leading-none tracking-tight",
92
- className
93
- )}
94
- {...props}
95
- />
96
- ))
97
- DialogTitle.displayName = DialogPrimitive.Title.displayName
98
-
99
- const DialogDescription = React.forwardRef<
100
- React.ElementRef<typeof DialogPrimitive.Description>,
101
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
102
- >(({ className, ...props }, ref) => (
103
- <DialogPrimitive.Description
104
- ref={ref}
105
- className={cn("text-sm text-muted-foreground", className)}
106
- {...props}
107
- />
108
- ))
109
- DialogDescription.displayName = DialogPrimitive.Description.displayName
110
-
111
- export {
112
- Dialog,
113
- DialogPortal,
114
- DialogOverlay,
115
- DialogTrigger,
116
- DialogClose,
117
- DialogContent,
118
- DialogHeader,
119
- DialogFooter,
120
- DialogTitle,
121
- DialogDescription,
122
- }
@@ -1,205 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
5
- import {
6
- CheckIcon,
7
- ChevronRightIcon,
8
- DotFilledIcon,
9
- } from "@radix-ui/react-icons"
10
-
11
- import { cn } from "@/lib/utils"
12
-
13
- const DropdownMenu = DropdownMenuPrimitive.Root
14
-
15
- const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
16
-
17
- const DropdownMenuGroup = DropdownMenuPrimitive.Group
18
-
19
- const DropdownMenuPortal = DropdownMenuPrimitive.Portal
20
-
21
- const DropdownMenuSub = DropdownMenuPrimitive.Sub
22
-
23
- const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
24
-
25
- const DropdownMenuSubTrigger = React.forwardRef<
26
- React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
27
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
28
- inset?: boolean
29
- }
30
- >(({ className, inset, children, ...props }, ref) => (
31
- <DropdownMenuPrimitive.SubTrigger
32
- ref={ref}
33
- className={cn(
34
- "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
35
- inset && "pl-8",
36
- className
37
- )}
38
- {...props}
39
- >
40
- {children}
41
- <ChevronRightIcon className="ml-auto size-4" />
42
- </DropdownMenuPrimitive.SubTrigger>
43
- ))
44
- DropdownMenuSubTrigger.displayName =
45
- DropdownMenuPrimitive.SubTrigger.displayName
46
-
47
- const DropdownMenuSubContent = React.forwardRef<
48
- React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
49
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
50
- >(({ className, ...props }, ref) => (
51
- <DropdownMenuPrimitive.SubContent
52
- ref={ref}
53
- className={cn(
54
- "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
55
- className
56
- )}
57
- {...props}
58
- />
59
- ))
60
- DropdownMenuSubContent.displayName =
61
- DropdownMenuPrimitive.SubContent.displayName
62
-
63
- const DropdownMenuContent = React.forwardRef<
64
- React.ElementRef<typeof DropdownMenuPrimitive.Content>,
65
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
66
- >(({ className, sideOffset = 4, ...props }, ref) => (
67
- <DropdownMenuPrimitive.Portal>
68
- <DropdownMenuPrimitive.Content
69
- ref={ref}
70
- sideOffset={sideOffset}
71
- className={cn(
72
- "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
73
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
74
- className
75
- )}
76
- {...props}
77
- />
78
- </DropdownMenuPrimitive.Portal>
79
- ))
80
- DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
81
-
82
- const DropdownMenuItem = React.forwardRef<
83
- React.ElementRef<typeof DropdownMenuPrimitive.Item>,
84
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
85
- inset?: boolean
86
- }
87
- >(({ className, inset, ...props }, ref) => (
88
- <DropdownMenuPrimitive.Item
89
- ref={ref}
90
- className={cn(
91
- "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
92
- inset && "pl-8",
93
- className
94
- )}
95
- {...props}
96
- />
97
- ))
98
- DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
99
-
100
- const DropdownMenuCheckboxItem = React.forwardRef<
101
- React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
102
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
103
- >(({ className, children, checked, ...props }, ref) => (
104
- <DropdownMenuPrimitive.CheckboxItem
105
- ref={ref}
106
- className={cn(
107
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
108
- className
109
- )}
110
- checked={checked}
111
- {...props}
112
- >
113
- <span className="absolute left-2 flex size-3.5 items-center justify-center">
114
- <DropdownMenuPrimitive.ItemIndicator>
115
- <CheckIcon className="size-4" />
116
- </DropdownMenuPrimitive.ItemIndicator>
117
- </span>
118
- {children}
119
- </DropdownMenuPrimitive.CheckboxItem>
120
- ))
121
- DropdownMenuCheckboxItem.displayName =
122
- DropdownMenuPrimitive.CheckboxItem.displayName
123
-
124
- const DropdownMenuRadioItem = React.forwardRef<
125
- React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
126
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
127
- >(({ className, children, ...props }, ref) => (
128
- <DropdownMenuPrimitive.RadioItem
129
- ref={ref}
130
- className={cn(
131
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
132
- className
133
- )}
134
- {...props}
135
- >
136
- <span className="absolute left-2 flex size-3.5 items-center justify-center">
137
- <DropdownMenuPrimitive.ItemIndicator>
138
- <DotFilledIcon className="size-4 fill-current" />
139
- </DropdownMenuPrimitive.ItemIndicator>
140
- </span>
141
- {children}
142
- </DropdownMenuPrimitive.RadioItem>
143
- ))
144
- DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
145
-
146
- const DropdownMenuLabel = React.forwardRef<
147
- React.ElementRef<typeof DropdownMenuPrimitive.Label>,
148
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
149
- inset?: boolean
150
- }
151
- >(({ className, inset, ...props }, ref) => (
152
- <DropdownMenuPrimitive.Label
153
- ref={ref}
154
- className={cn(
155
- "px-2 py-1.5 text-sm font-semibold",
156
- inset && "pl-8",
157
- className
158
- )}
159
- {...props}
160
- />
161
- ))
162
- DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
163
-
164
- const DropdownMenuSeparator = React.forwardRef<
165
- React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
166
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
167
- >(({ className, ...props }, ref) => (
168
- <DropdownMenuPrimitive.Separator
169
- ref={ref}
170
- className={cn("-mx-1 my-1 h-px bg-muted", className)}
171
- {...props}
172
- />
173
- ))
174
- DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
175
-
176
- const DropdownMenuShortcut = ({
177
- className,
178
- ...props
179
- }: React.HTMLAttributes<HTMLSpanElement>) => {
180
- return (
181
- <span
182
- className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
183
- {...props}
184
- />
185
- )
186
- }
187
- DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
188
-
189
- export {
190
- DropdownMenu,
191
- DropdownMenuTrigger,
192
- DropdownMenuContent,
193
- DropdownMenuItem,
194
- DropdownMenuCheckboxItem,
195
- DropdownMenuRadioItem,
196
- DropdownMenuLabel,
197
- DropdownMenuSeparator,
198
- DropdownMenuShortcut,
199
- DropdownMenuGroup,
200
- DropdownMenuPortal,
201
- DropdownMenuSub,
202
- DropdownMenuSubContent,
203
- DropdownMenuSubTrigger,
204
- DropdownMenuRadioGroup,
205
- }