langwatch 0.2.0 → 0.3.0-prerelease.2

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 (229) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +268 -1
  3. package/dist/chunk-4BZATFKJ.mjs +181 -0
  4. package/dist/chunk-4BZATFKJ.mjs.map +1 -0
  5. package/dist/chunk-CSC3CMIT.mjs +118 -0
  6. package/dist/chunk-CSC3CMIT.mjs.map +1 -0
  7. package/dist/chunk-F63YKTXA.mjs +47 -0
  8. package/dist/chunk-F63YKTXA.mjs.map +1 -0
  9. package/dist/chunk-G3AUABT7.js +4 -0
  10. package/dist/chunk-G3AUABT7.js.map +1 -0
  11. package/dist/chunk-HPC6Z7J4.js +118 -0
  12. package/dist/chunk-HPC6Z7J4.js.map +1 -0
  13. package/dist/chunk-KGDAENGD.js +50 -0
  14. package/dist/chunk-KGDAENGD.js.map +1 -0
  15. package/dist/chunk-LD74LVRU.js +47 -0
  16. package/dist/chunk-LD74LVRU.js.map +1 -0
  17. package/dist/chunk-OM7VY3XT.mjs +4 -0
  18. package/dist/chunk-PCQVQ7SB.js +45 -0
  19. package/dist/chunk-PCQVQ7SB.js.map +1 -0
  20. package/dist/chunk-PMBEK6YE.mjs +424 -0
  21. package/dist/chunk-PMBEK6YE.mjs.map +1 -0
  22. package/dist/chunk-PR3JDWC3.mjs +50 -0
  23. package/dist/chunk-PR3JDWC3.mjs.map +1 -0
  24. package/dist/chunk-PTJ6AAI7.js +360 -0
  25. package/dist/chunk-PTJ6AAI7.js.map +1 -0
  26. package/dist/chunk-QEWDG5QE.mjs +45 -0
  27. package/dist/chunk-QEWDG5QE.mjs.map +1 -0
  28. package/dist/chunk-REUCVT7A.mjs +39 -0
  29. package/dist/chunk-REUCVT7A.mjs.map +1 -0
  30. package/dist/chunk-SVJ7SCGB.js +424 -0
  31. package/dist/chunk-SVJ7SCGB.js.map +1 -0
  32. package/dist/chunk-VJSOCNPA.js +181 -0
  33. package/dist/chunk-VJSOCNPA.js.map +1 -0
  34. package/dist/chunk-WM2GRSRW.js +39 -0
  35. package/dist/chunk-WM2GRSRW.js.map +1 -0
  36. package/dist/chunk-Z5J5UI5E.mjs +360 -0
  37. package/dist/chunk-Z5J5UI5E.mjs.map +1 -0
  38. package/dist/client-B2HqIKg6.d.ts +51 -0
  39. package/dist/client-XyCqclCi.d.mts +51 -0
  40. package/dist/client-browser.d.mts +8 -0
  41. package/dist/client-browser.d.ts +8 -0
  42. package/dist/client-browser.js +83 -0
  43. package/dist/client-browser.js.map +1 -0
  44. package/dist/client-browser.mjs +83 -0
  45. package/dist/client-browser.mjs.map +1 -0
  46. package/dist/client-node.d.mts +8 -0
  47. package/dist/client-node.d.ts +8 -0
  48. package/dist/client-node.js +90 -0
  49. package/dist/client-node.js.map +1 -0
  50. package/dist/client-node.mjs +90 -0
  51. package/dist/client-node.mjs.map +1 -0
  52. package/dist/evaluation/index.d.mts +897 -0
  53. package/dist/evaluation/index.d.ts +897 -0
  54. package/dist/evaluation/index.js +13 -0
  55. package/dist/evaluation/index.js.map +1 -0
  56. package/dist/evaluation/index.mjs +13 -0
  57. package/dist/evaluation/index.mjs.map +1 -0
  58. package/dist/filterable-batch-span-processor-zO5kcjBY.d.mts +64 -0
  59. package/dist/filterable-batch-span-processor-zO5kcjBY.d.ts +64 -0
  60. package/dist/index.d.mts +45 -1027
  61. package/dist/index.d.ts +45 -1027
  62. package/dist/index.js +11 -27291
  63. package/dist/index.js.map +1 -1
  64. package/dist/index.mjs +23 -956
  65. package/dist/index.mjs.map +1 -1
  66. package/dist/observability/index.d.mts +260 -0
  67. package/dist/observability/index.d.ts +260 -0
  68. package/dist/observability/index.js +20 -0
  69. package/dist/observability/index.js.map +1 -0
  70. package/dist/observability/index.mjs +20 -0
  71. package/dist/observability/index.mjs.map +1 -0
  72. package/dist/observability/instrumentation/langchain/index.d.mts +40 -0
  73. package/dist/observability/instrumentation/langchain/index.d.ts +40 -0
  74. package/dist/observability/instrumentation/langchain/index.js +666 -0
  75. package/dist/observability/instrumentation/langchain/index.js.map +1 -0
  76. package/dist/observability/instrumentation/langchain/index.mjs +666 -0
  77. package/dist/observability/instrumentation/langchain/index.mjs.map +1 -0
  78. package/dist/prompt/index.d.mts +10 -0
  79. package/dist/prompt/index.d.ts +10 -0
  80. package/dist/prompt/index.js +18 -0
  81. package/dist/prompt/index.js.map +1 -0
  82. package/dist/prompt/index.mjs +18 -0
  83. package/dist/prompt/index.mjs.map +1 -0
  84. package/dist/prompt-BXJWdbQp.d.mts +1967 -0
  85. package/dist/prompt-BXJWdbQp.d.ts +1967 -0
  86. package/dist/record-evaluation-CmxMXa-3.d.mts +25 -0
  87. package/dist/record-evaluation-CmxMXa-3.d.ts +25 -0
  88. package/dist/trace-D-bZOuqb.d.mts +622 -0
  89. package/dist/trace-G2312klE.d.ts +622 -0
  90. package/package.json +86 -37
  91. package/.eslintrc.cjs +0 -37
  92. package/copy-types.sh +0 -17
  93. package/dist/chunk-LKD2K67J.mjs +0 -717
  94. package/dist/chunk-LKD2K67J.mjs.map +0 -1
  95. package/dist/utils-Cv-rUjJ1.d.mts +0 -313
  96. package/dist/utils-Cv-rUjJ1.d.ts +0 -313
  97. package/dist/utils.d.mts +0 -2
  98. package/dist/utils.d.ts +0 -2
  99. package/dist/utils.js +0 -709
  100. package/dist/utils.js.map +0 -1
  101. package/dist/utils.mjs +0 -11
  102. package/example/.env.example +0 -12
  103. package/example/.eslintrc.json +0 -26
  104. package/example/LICENSE +0 -13
  105. package/example/README.md +0 -12
  106. package/example/app/(chat)/chat/[id]/page.tsx +0 -60
  107. package/example/app/(chat)/layout.tsx +0 -14
  108. package/example/app/(chat)/page.tsx +0 -27
  109. package/example/app/actions.ts +0 -156
  110. package/example/app/globals.css +0 -76
  111. package/example/app/guardrails/page.tsx +0 -26
  112. package/example/app/langchain/page.tsx +0 -27
  113. package/example/app/langchain-rag/page.tsx +0 -28
  114. package/example/app/late-update/page.tsx +0 -27
  115. package/example/app/layout.tsx +0 -64
  116. package/example/app/login/actions.ts +0 -71
  117. package/example/app/login/page.tsx +0 -18
  118. package/example/app/manual/page.tsx +0 -27
  119. package/example/app/new/page.tsx +0 -5
  120. package/example/app/opengraph-image.png +0 -0
  121. package/example/app/share/[id]/page.tsx +0 -58
  122. package/example/app/signup/actions.ts +0 -111
  123. package/example/app/signup/page.tsx +0 -18
  124. package/example/app/twitter-image.png +0 -0
  125. package/example/auth.config.ts +0 -42
  126. package/example/auth.ts +0 -45
  127. package/example/components/button-scroll-to-bottom.tsx +0 -36
  128. package/example/components/chat-history.tsx +0 -49
  129. package/example/components/chat-list.tsx +0 -52
  130. package/example/components/chat-message-actions.tsx +0 -40
  131. package/example/components/chat-message.tsx +0 -80
  132. package/example/components/chat-panel.tsx +0 -139
  133. package/example/components/chat-share-dialog.tsx +0 -95
  134. package/example/components/chat.tsx +0 -84
  135. package/example/components/clear-history.tsx +0 -75
  136. package/example/components/empty-screen.tsx +0 -38
  137. package/example/components/external-link.tsx +0 -29
  138. package/example/components/footer.tsx +0 -19
  139. package/example/components/header.tsx +0 -114
  140. package/example/components/login-button.tsx +0 -42
  141. package/example/components/login-form.tsx +0 -97
  142. package/example/components/markdown.tsx +0 -9
  143. package/example/components/prompt-form.tsx +0 -115
  144. package/example/components/providers.tsx +0 -17
  145. package/example/components/sidebar-actions.tsx +0 -125
  146. package/example/components/sidebar-desktop.tsx +0 -19
  147. package/example/components/sidebar-footer.tsx +0 -16
  148. package/example/components/sidebar-item.tsx +0 -124
  149. package/example/components/sidebar-items.tsx +0 -42
  150. package/example/components/sidebar-list.tsx +0 -38
  151. package/example/components/sidebar-mobile.tsx +0 -31
  152. package/example/components/sidebar-toggle.tsx +0 -24
  153. package/example/components/sidebar.tsx +0 -21
  154. package/example/components/signup-form.tsx +0 -95
  155. package/example/components/stocks/events-skeleton.tsx +0 -31
  156. package/example/components/stocks/events.tsx +0 -30
  157. package/example/components/stocks/index.tsx +0 -36
  158. package/example/components/stocks/message.tsx +0 -134
  159. package/example/components/stocks/spinner.tsx +0 -16
  160. package/example/components/stocks/stock-purchase.tsx +0 -146
  161. package/example/components/stocks/stock-skeleton.tsx +0 -22
  162. package/example/components/stocks/stock.tsx +0 -210
  163. package/example/components/stocks/stocks-skeleton.tsx +0 -9
  164. package/example/components/stocks/stocks.tsx +0 -67
  165. package/example/components/tailwind-indicator.tsx +0 -14
  166. package/example/components/theme-toggle.tsx +0 -31
  167. package/example/components/ui/alert-dialog.tsx +0 -141
  168. package/example/components/ui/badge.tsx +0 -36
  169. package/example/components/ui/button.tsx +0 -57
  170. package/example/components/ui/codeblock.tsx +0 -148
  171. package/example/components/ui/dialog.tsx +0 -122
  172. package/example/components/ui/dropdown-menu.tsx +0 -205
  173. package/example/components/ui/icons.tsx +0 -507
  174. package/example/components/ui/input.tsx +0 -25
  175. package/example/components/ui/label.tsx +0 -26
  176. package/example/components/ui/select.tsx +0 -164
  177. package/example/components/ui/separator.tsx +0 -31
  178. package/example/components/ui/sheet.tsx +0 -140
  179. package/example/components/ui/sonner.tsx +0 -31
  180. package/example/components/ui/switch.tsx +0 -29
  181. package/example/components/ui/textarea.tsx +0 -24
  182. package/example/components/ui/tooltip.tsx +0 -30
  183. package/example/components/user-menu.tsx +0 -53
  184. package/example/components.json +0 -17
  185. package/example/instrumentation.ts +0 -11
  186. package/example/lib/chat/guardrails.tsx +0 -181
  187. package/example/lib/chat/langchain-rag.tsx +0 -191
  188. package/example/lib/chat/langchain.tsx +0 -112
  189. package/example/lib/chat/late-update.tsx +0 -208
  190. package/example/lib/chat/manual.tsx +0 -605
  191. package/example/lib/chat/vercel-ai.tsx +0 -576
  192. package/example/lib/hooks/use-copy-to-clipboard.tsx +0 -33
  193. package/example/lib/hooks/use-enter-submit.tsx +0 -23
  194. package/example/lib/hooks/use-local-storage.ts +0 -24
  195. package/example/lib/hooks/use-scroll-anchor.tsx +0 -86
  196. package/example/lib/hooks/use-sidebar.tsx +0 -60
  197. package/example/lib/hooks/use-streamable-text.ts +0 -25
  198. package/example/lib/types.ts +0 -41
  199. package/example/lib/utils.ts +0 -89
  200. package/example/middleware.ts +0 -8
  201. package/example/next-env.d.ts +0 -5
  202. package/example/next.config.js +0 -16
  203. package/example/package-lock.json +0 -10917
  204. package/example/package.json +0 -84
  205. package/example/pnpm-lock.yaml +0 -5712
  206. package/example/postcss.config.js +0 -6
  207. package/example/prettier.config.cjs +0 -34
  208. package/example/public/apple-touch-icon.png +0 -0
  209. package/example/public/favicon-16x16.png +0 -0
  210. package/example/public/favicon.ico +0 -0
  211. package/example/public/next.svg +0 -1
  212. package/example/public/thirteen.svg +0 -1
  213. package/example/public/vercel.svg +0 -1
  214. package/example/tailwind.config.ts +0 -81
  215. package/example/tsconfig.json +0 -35
  216. package/src/LangWatchExporter.ts +0 -96
  217. package/src/evaluations.ts +0 -219
  218. package/src/index.test.ts +0 -402
  219. package/src/index.ts +0 -596
  220. package/src/langchain.ts +0 -557
  221. package/src/server/types/.gitkeep +0 -0
  222. package/src/typeUtils.ts +0 -89
  223. package/src/types.ts +0 -82
  224. package/src/utils.ts +0 -205
  225. package/ts-to-zod.config.js +0 -24
  226. package/tsconfig.json +0 -32
  227. package/tsup.config.ts +0 -10
  228. package/vitest.config.ts +0 -8
  229. /package/dist/{utils.mjs.map → chunk-OM7VY3XT.mjs.map} +0 -0
@@ -1,210 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useRef, useEffect, useId } from 'react'
4
- import { scaleLinear } from 'd3-scale'
5
- import { subMonths, format } from 'date-fns'
6
- import { useResizeObserver } from 'usehooks-ts'
7
- import { useAIState } from 'ai/rsc'
8
-
9
- interface Stock {
10
- symbol: string
11
- price: number
12
- delta: number
13
- }
14
-
15
- export function Stock({ props: { symbol, price, delta } }: { props: Stock }) {
16
- const [aiState, setAIState] = useAIState()
17
- const id = useId()
18
-
19
- const [priceAtTime, setPriceAtTime] = useState({
20
- time: '00:00',
21
- value: price.toFixed(2),
22
- x: 0
23
- })
24
-
25
- const [startHighlight, setStartHighlight] = useState(0)
26
- const [endHighlight, setEndHighlight] = useState(0)
27
-
28
- const chartRef = useRef<HTMLDivElement>(null)
29
- const { width = 0 } = useResizeObserver({
30
- ref: chartRef,
31
- box: 'border-box'
32
- })
33
-
34
- const xToDate = scaleLinear(
35
- [0, width],
36
- [subMonths(new Date(), 6), new Date()]
37
- )
38
- const xToValue = scaleLinear(
39
- [0, width],
40
- [price - price / 2, price + price / 2]
41
- )
42
-
43
- useEffect(() => {
44
- if (startHighlight && endHighlight) {
45
- const message = {
46
- id,
47
- role: 'system' as const,
48
- content: `[User has highlighted dates between between ${format(
49
- xToDate(startHighlight),
50
- 'd LLL'
51
- )} and ${format(xToDate(endHighlight), 'd LLL, yyyy')}`
52
- }
53
-
54
- if (aiState.messages[aiState.messages.length - 1]?.id === id) {
55
- setAIState({
56
- ...aiState,
57
- messages: [...aiState.messages.slice(0, -1), message]
58
- })
59
- } else {
60
- setAIState({
61
- ...aiState,
62
- messages: [...aiState.messages, message]
63
- })
64
- }
65
- }
66
- }, [startHighlight, endHighlight])
67
-
68
- return (
69
- <div className="rounded-xl border bg-zinc-950 p-4 text-green-400">
70
- <div className="float-right inline-block rounded-full bg-white/10 px-2 py-1 text-xs">
71
- {`${delta > 0 ? '+' : ''}${((delta / price) * 100).toFixed(2)}% ${
72
- delta > 0 ? '↑' : '↓'
73
- }`}
74
- </div>
75
- <div className="text-lg text-zinc-300">{symbol}</div>
76
- <div className="text-3xl font-bold">${price}</div>
77
- <div className="text mt-1 text-xs text-zinc-500">
78
- Closed: Feb 27, 4:59 PM EST
79
- </div>
80
-
81
- <div
82
- className="relative -mx-4 cursor-col-resize"
83
- onPointerDown={event => {
84
- if (chartRef.current) {
85
- const { clientX } = event
86
- const { left } = chartRef.current.getBoundingClientRect()
87
-
88
- setStartHighlight(clientX - left)
89
- setEndHighlight(0)
90
-
91
- setPriceAtTime({
92
- time: format(xToDate(clientX), 'dd LLL yy'),
93
- value: xToValue(clientX).toFixed(2),
94
- x: clientX - left
95
- })
96
- }
97
- }}
98
- onPointerUp={event => {
99
- if (chartRef.current) {
100
- const { clientX } = event
101
- const { left } = chartRef.current.getBoundingClientRect()
102
-
103
- setEndHighlight(clientX - left)
104
- }
105
- }}
106
- onPointerMove={event => {
107
- if (chartRef.current) {
108
- const { clientX } = event
109
- const { left } = chartRef.current.getBoundingClientRect()
110
-
111
- setPriceAtTime({
112
- time: format(xToDate(clientX), 'dd LLL yy'),
113
- value: xToValue(clientX).toFixed(2),
114
- x: clientX - left
115
- })
116
- }
117
- }}
118
- onPointerLeave={() => {
119
- setPriceAtTime({
120
- time: '00:00',
121
- value: price.toFixed(2),
122
- x: 0
123
- })
124
- }}
125
- ref={chartRef}
126
- >
127
- {priceAtTime.x > 0 ? (
128
- <div
129
- className="pointer-events-none absolute z-10 flex w-fit select-none gap-2 rounded-md bg-zinc-800 p-2"
130
- style={{
131
- left: priceAtTime.x - 124 / 2,
132
- top: 30
133
- }}
134
- >
135
- <div className="text-xs tabular-nums">${priceAtTime.value}</div>
136
- <div className="text-xs tabular-nums text-zinc-400">
137
- {priceAtTime.time}
138
- </div>
139
- </div>
140
- ) : null}
141
-
142
- {startHighlight ? (
143
- <div
144
- className="pointer-events-none absolute h-32 w-5 select-none rounded-md border border-zinc-500 bg-zinc-500/20"
145
- style={{
146
- left: startHighlight,
147
- width: endHighlight
148
- ? endHighlight - startHighlight
149
- : priceAtTime.x - startHighlight,
150
- bottom: 0
151
- }}
152
- ></div>
153
- ) : null}
154
-
155
- <svg
156
- viewBox="0 0 250.0 168.0"
157
- height="150"
158
- width="100%"
159
- preserveAspectRatio="none"
160
- >
161
- <defs>
162
- <linearGradient
163
- id="fill-id-tsuid_31"
164
- x1="0%"
165
- x2="0%"
166
- y1="0%"
167
- y2="100%"
168
- >
169
- <stop offset="0%" stopColor="#34a853" stopOpacity="0.38"></stop>
170
- <stop offset="13%" stopColor="#e6f4ea" stopOpacity="0"></stop>
171
- </linearGradient>
172
- <clipPath id="range-id-tsuid_31">
173
- <rect height="100%" width="0" x="0" y="0"></rect>
174
- </clipPath>
175
- <defs>
176
- <linearGradient
177
- id="chart-grad-_f1bJZYLUHqWpxc8Prs2meA_33"
178
- x1="0%"
179
- x2="0%"
180
- y1="0%"
181
- y2="100%"
182
- >
183
- <stop offset="0%" stopColor="#34a853" stopOpacity="0.38"></stop>
184
- <stop offset="13%" stopColor="#e6f4ea" stopOpacity="0"></stop>
185
- </linearGradient>
186
- </defs>
187
- <clipPath id="mask-_f1bJZYLUHqWpxc8Prs2meA_32">
188
- <rect height="218" width="250" x="0" y="-5"></rect>
189
- </clipPath>
190
- </defs>
191
- <path
192
- d="M 0 42.86 L 0.89 46.26 L 1.78 44.3 L 2.68 44.24 L 3.57 42 L 4.46 43.42 L 5.35 43.62 L 6.25 47 L 7.14 47.65 L 8.03 47.69 L 8.92 45.55 L 9.82 43.19 L 10.71 43.9 L 11.6 42.83 L 12.49 42.81 L 13.39 46.75 L 14.28 43.06 L 15.17 40.8 L 16.06 39.72 L 16.96 39.77 L 17.85 45.77 L 18.74 44.93 L 19.63 44.35 L 20.53 40.29 L 21.42 42.77 L 22.31 42.12 L 23.2 43.4 L 24.1 47.95 L 24.99 50.15 L 25.88 48.59 L 26.77 42.18 L 27.67 44.1 L 28.56 39.91 L 29.45 44.92 L 30.34 47.62 L 31.24 48.06 L 32.13 47.67 L 33.02 56.47 L 33.91 57.74 L 34.8 65.48 L 35.7 64.47 L 36.59 47.25 L 37.48 58.26 L 38.37 52.04 L 39.27 55.8 L 40.16 92.92 L 41.05 105.2 L 41.94 102 L 42.84 106.14 L 43.73 78.71 L 44.62 104.6 L 45.51 96.58 L 46.41 67.56 L 47.3 69.53 L 48.19 69.99 L 49.08 66.75 L 49.98 69.72 L 50.87 70.13 L 51.76 71.3 L 52.65 70.03 L 53.55 67.92 L 54.44 66.41 L 55.33 97.12 L 56.22 95.93 L 57.12 95.03 L 58.01 95.09 L 58.9 65.56 L 59.79 65.12 L 60.69 82.42 L 61.58 74.7 L 62.47 71.13 L 63.36 82.43 L 64.26 96.02 L 65.15 100.36 L 66.04 98.6 L 66.93 103.37 L 67.82 102.12 L 68.72 97.08 L 69.61 89.74 L 70.5 90.7 L 71.39 93.46 L 72.29 94.24 L 73.18 97.8 L 74.07 97.88 L 74.96 96.63 L 75.86 96.27 L 76.75 97.15 L 77.64 100.12 L 78.53 100.51 L 79.43 106.59 L 80.32 104.54 L 81.21 100.31 L 82.1 118.76 L 83 106.24 L 83.89 114.8 L 84.78 174.89 L 85.67 122.28 L 86.57 149.25 L 87.46 151.47 L 88.35 153.38 L 89.24 153.5 L 90.14 149.24 L 91.03 122.44 L 91.92 122.08 L 92.81 147.16 L 93.71 147.46 L 94.6 119.13 L 95.49 117.97 L 96.38 122.22 L 97.28 116.38 L 98.17 119.53 L 99.06 119.65 L 99.95 120.15 L 100.84 120.22 L 101.74 121.28 L 102.63 121.4 L 103.52 122.97 L 104.41 122.15 L 105.31 120.6 L 106.2 116.55 L 107.09 122.23 L 107.98 120.96 L 108.88 119.54 L 109.77 120.19 L 110.66 120.99 L 111.55 119.92 L 112.45 115.69 L 113.34 116.33 L 114.23 116.07 L 115.12 115.34 L 116.02 111.34 L 116.91 107.23 L 117.8 113.21 L 118.69 98.77 L 119.59 97.04 L 120.48 96.56 L 121.37 96.36 L 122.26 99.7 L 123.16 103.33 L 124.05 100.38 L 124.94 99.68 L 125.83 99.02 L 126.73 102.56 L 127.62 103.25 L 128.51 103.38 L 129.4 104.89 L 130.3 118.07 L 131.19 100.82 L 132.08 103.06 L 132.97 103.47 L 133.86 99.8 L 134.76 111.28 L 135.65 107.73 L 136.54 107.46 L 137.43 108.08 L 138.33 109.82 L 139.22 110.94 L 140.11 111.3 L 141 108.14 L 141.9 109.35 L 142.79 108.38 L 143.68 99.08 L 144.57 99.02 L 145.47 98.61 L 146.36 99.07 L 147.25 99.26 L 148.14 95.1 L 149.04 92.08 L 149.93 92.76 L 150.82 92.87 L 151.71 83.31 L 152.61 82.93 L 153.5 84.86 L 154.39 84.12 L 155.28 94.08 L 156.18 93.31 L 157.07 94.23 L 157.96 94.58 L 158.85 99.33 L 159.75 80 L 160.64 90.28 L 161.53 84.07 L 162.42 68.37 L 163.32 76.88 L 164.21 81.78 L 165.1 80.72 L 165.99 73.89 L 166.88 77.14 L 167.78 67.58 L 168.67 59.82 L 169.56 61.91 L 170.45 61.07 L 171.35 73.74 L 172.24 77.02 L 173.13 78.61 L 174.02 71.59 L 174.92 68.24 L 175.81 72.14 L 176.7 65.37 L 177.59 76.73 L 178.49 88.02 L 179.38 88.01 L 180.27 88.27 L 181.16 86.23 L 182.06 86.14 L 182.95 89.54 L 183.84 94.16 L 184.73 97.72 L 185.63 81.52 L 186.52 92.85 L 187.41 94.14 L 188.3 93.06 L 189.2 92.64 L 190.09 92.44 L 190.98 91.75 L 191.87 90.53 L 192.77 88.27 L 193.66 85.44 L 194.55 82.26 L 195.44 85.08 L 196.34 85.65 L 197.23 53.43 L 198.12 72.01 L 199.01 38.37 L 199.9 69.43 L 200.8 74.46 L 201.69 74.22 L 202.58 82.46 L 203.47 77.01 L 204.37 87.8 L 205.26 91.56 L 206.15 76.69 L 207.04 76.46 L 207.94 78.13 L 208.83 80.06 L 209.72 92.79 L 210.61 87.74 L 211.51 88.21 L 212.4 88.47 L 213.29 87.35 L 214.18 89.69 L 215.08 77.37 L 215.97 87.95 L 216.86 75.16 L 217.75 70.47 L 218.65 85.11 L 219.54 88.1 L 220.43 88.06 L 221.32 86.34 L 222.22 76.91 L 223.11 75.33 L 224 73.6 L 224.89 25.31 L 225.79 44.14 L 226.68 43.93 L 227.57 45.13 L 228.46 44.03 L 229.36 35.73 L 230.25 33.65 L 231.14 34.81 L 232.03 17.64 L 232.92 21.13 L 233.82 19.37 L 234.71 24.66 L 235.6 23.87 L 236.49 22.56 L 237.39 28.48 L 238.28 25.33 L 239.17 28.51 L 240.06 30.83 L 240.96 35.79 L 241.85 34.6 L 242.74 31.2 L 243.63 32.97 L 244.53 33.01 L 245.42 31.38 L 246.31 30.21 L 247.2 27.75 L 248.1 25.27 L 248.99 23 L 249.88 23 L 250 23 L 2000 0 L 2000 1000 L -1000 1000"
193
- clipPath="url(#range-id-tsuid_31)"
194
- vectorEffect="non-scaling-stroke"
195
- stroke="none"
196
- strokeWidth={2}
197
- fill='url("#fill-id-tsuid_31")'
198
- ></path>
199
- <path
200
- clipPath="url(#mask-_f1bJZYLUHqWpxc8Prs2meA_32)"
201
- d="M 0 42.86 L 0.89 46.26 L 1.78 44.3 L 2.68 44.24 L 3.57 42 L 4.46 43.42 L 5.35 43.62 L 6.25 47 L 7.14 47.65 L 8.03 47.69 L 8.92 45.55 L 9.82 43.19 L 10.71 43.9 L 11.6 42.83 L 12.49 42.81 L 13.39 46.75 L 14.28 43.06 L 15.17 40.8 L 16.06 39.72 L 16.96 39.77 L 17.85 45.77 L 18.74 44.93 L 19.63 44.35 L 20.53 40.29 L 21.42 42.77 L 22.31 42.12 L 23.2 43.4 L 24.1 47.95 L 24.99 50.15 L 25.88 48.59 L 26.77 42.18 L 27.67 44.1 L 28.56 39.91 L 29.45 44.92 L 30.34 47.62 L 31.24 48.06 L 32.13 47.67 L 33.02 56.47 L 33.91 57.74 L 34.8 65.48 L 35.7 64.47 L 36.59 47.25 L 37.48 58.26 L 38.37 52.04 L 39.27 55.8 L 40.16 92.92 L 41.05 105.2 L 41.94 102 L 42.84 106.14 L 43.73 78.71 L 44.62 104.6 L 45.51 96.58 L 46.41 67.56 L 47.3 69.53 L 48.19 69.99 L 49.08 66.75 L 49.98 69.72 L 50.87 70.13 L 51.76 71.3 L 52.65 70.03 L 53.55 67.92 L 54.44 66.41 L 55.33 97.12 L 56.22 95.93 L 57.12 95.03 L 58.01 95.09 L 58.9 65.56 L 59.79 65.12 L 60.69 82.42 L 61.58 74.7 L 62.47 71.13 L 63.36 82.43 L 64.26 96.02 L 65.15 100.36 L 66.04 98.6 L 66.93 103.37 L 67.82 102.12 L 68.72 97.08 L 69.61 89.74 L 70.5 90.7 L 71.39 93.46 L 72.29 94.24 L 73.18 97.8 L 74.07 97.88 L 74.96 96.63 L 75.86 96.27 L 76.75 97.15 L 77.64 100.12 L 78.53 100.51 L 79.43 106.59 L 80.32 104.54 L 81.21 100.31 L 82.1 118.76 L 83 106.24 L 83.89 114.8 L 84.78 174.89 L 85.67 122.28 L 86.57 149.25 L 87.46 151.47 L 88.35 153.38 L 89.24 153.5 L 90.14 149.24 L 91.03 122.44 L 91.92 122.08 L 92.81 147.16 L 93.71 147.46 L 94.6 119.13 L 95.49 117.97 L 96.38 122.22 L 97.28 116.38 L 98.17 119.53 L 99.06 119.65 L 99.95 120.15 L 100.84 120.22 L 101.74 121.28 L 102.63 121.4 L 103.52 122.97 L 104.41 122.15 L 105.31 120.6 L 106.2 116.55 L 107.09 122.23 L 107.98 120.96 L 108.88 119.54 L 109.77 120.19 L 110.66 120.99 L 111.55 119.92 L 112.45 115.69 L 113.34 116.33 L 114.23 116.07 L 115.12 115.34 L 116.02 111.34 L 116.91 107.23 L 117.8 113.21 L 118.69 98.77 L 119.59 97.04 L 120.48 96.56 L 121.37 96.36 L 122.26 99.7 L 123.16 103.33 L 124.05 100.38 L 124.94 99.68 L 125.83 99.02 L 126.73 102.56 L 127.62 103.25 L 128.51 103.38 L 129.4 104.89 L 130.3 118.07 L 131.19 100.82 L 132.08 103.06 L 132.97 103.47 L 133.86 99.8 L 134.76 111.28 L 135.65 107.73 L 136.54 107.46 L 137.43 108.08 L 138.33 109.82 L 139.22 110.94 L 140.11 111.3 L 141 108.14 L 141.9 109.35 L 142.79 108.38 L 143.68 99.08 L 144.57 99.02 L 145.47 98.61 L 146.36 99.07 L 147.25 99.26 L 148.14 95.1 L 149.04 92.08 L 149.93 92.76 L 150.82 92.87 L 151.71 83.31 L 152.61 82.93 L 153.5 84.86 L 154.39 84.12 L 155.28 94.08 L 156.18 93.31 L 157.07 94.23 L 157.96 94.58 L 158.85 99.33 L 159.75 80 L 160.64 90.28 L 161.53 84.07 L 162.42 68.37 L 163.32 76.88 L 164.21 81.78 L 165.1 80.72 L 165.99 73.89 L 166.88 77.14 L 167.78 67.58 L 168.67 59.82 L 169.56 61.91 L 170.45 61.07 L 171.35 73.74 L 172.24 77.02 L 173.13 78.61 L 174.02 71.59 L 174.92 68.24 L 175.81 72.14 L 176.7 65.37 L 177.59 76.73 L 178.49 88.02 L 179.38 88.01 L 180.27 88.27 L 181.16 86.23 L 182.06 86.14 L 182.95 89.54 L 183.84 94.16 L 184.73 97.72 L 185.63 81.52 L 186.52 92.85 L 187.41 94.14 L 188.3 93.06 L 189.2 92.64 L 190.09 92.44 L 190.98 91.75 L 191.87 90.53 L 192.77 88.27 L 193.66 85.44 L 194.55 82.26 L 195.44 85.08 L 196.34 85.65 L 197.23 53.43 L 198.12 72.01 L 199.01 38.37 L 199.9 69.43 L 200.8 74.46 L 201.69 74.22 L 202.58 82.46 L 203.47 77.01 L 204.37 87.8 L 205.26 91.56 L 206.15 76.69 L 207.04 76.46 L 207.94 78.13 L 208.83 80.06 L 209.72 92.79 L 210.61 87.74 L 211.51 88.21 L 212.4 88.47 L 213.29 87.35 L 214.18 89.69 L 215.08 77.37 L 215.97 87.95 L 216.86 75.16 L 217.75 70.47 L 218.65 85.11 L 219.54 88.1 L 220.43 88.06 L 221.32 86.34 L 222.22 76.91 L 223.11 75.33 L 224 73.6 L 224.89 25.31 L 225.79 44.14 L 226.68 43.93 L 227.57 45.13 L 228.46 44.03 L 229.36 35.73 L 230.25 33.65 L 231.14 34.81 L 232.03 17.64 L 232.92 21.13 L 233.82 19.37 L 234.71 24.66 L 235.6 23.87 L 236.49 22.56 L 237.39 28.48 L 238.28 25.33 L 239.17 28.51 L 240.06 30.83 L 240.96 35.79 L 241.85 34.6 L 242.74 31.2 L 243.63 32.97 L 244.53 33.01 L 245.42 31.38 L 246.31 30.21 L 247.2 27.75 L 248.1 25.27 L 248.99 23 L 249.88 23 L 250 23 L 2000 0 L 2000 1000 L -1000 1000"
202
- vectorEffect="non-scaling-stroke"
203
- stroke="#34a853"
204
- style={{ fill: 'url(#chart-grad-_f1bJZYLUHqWpxc8Prs2meA_33)' }}
205
- ></path>
206
- </svg>
207
- </div>
208
- </div>
209
- )
210
- }
@@ -1,9 +0,0 @@
1
- export const StocksSkeleton = () => {
2
- return (
3
- <div className="mb-4 flex flex-col gap-2 overflow-y-scroll pb-4 text-sm sm:flex-row">
4
- <div className="flex h-[60px] w-full cursor-pointer flex-row gap-2 rounded-lg bg-zinc-800 p-2 text-left hover:bg-zinc-800 sm:w-[208px]"></div>
5
- <div className="flex h-[60px] w-full cursor-pointer flex-row gap-2 rounded-lg bg-zinc-800 p-2 text-left hover:bg-zinc-800 sm:w-[208px]"></div>
6
- <div className="flex h-[60px] w-full cursor-pointer flex-row gap-2 rounded-lg bg-zinc-800 p-2 text-left hover:bg-zinc-800 sm:w-[208px]"></div>
7
- </div>
8
- )
9
- }
@@ -1,67 +0,0 @@
1
- 'use client'
2
-
3
- import { useActions, useUIState } from 'ai/rsc'
4
-
5
- import type { AI } from '@/lib/chat/vercel-ai'
6
-
7
- interface Stock {
8
- symbol: string
9
- price: number
10
- delta: number
11
- }
12
-
13
- export function Stocks({ props: stocks }: { props: Stock[] }) {
14
- const [, setMessages] = useUIState<typeof AI>()
15
- const { submitUserMessage } = useActions()
16
-
17
- return (
18
- <div>
19
- <div className="mb-4 flex flex-col gap-2 overflow-y-scroll pb-4 text-sm sm:flex-row">
20
- {stocks.map(stock => (
21
- <button
22
- key={stock.symbol}
23
- className="flex cursor-pointer flex-row gap-2 rounded-lg bg-zinc-800 p-2 text-left hover:bg-zinc-700 sm:w-52"
24
- onClick={async () => {
25
- const response = await submitUserMessage(`View ${stock.symbol}`)
26
- setMessages(currentMessages => [...currentMessages, response])
27
- }}
28
- >
29
- <div
30
- className={`text-xl ${
31
- stock.delta > 0 ? 'text-green-600' : 'text-red-600'
32
- } flex w-11 flex-row justify-center rounded-md bg-white/10 p-2`}
33
- >
34
- {stock.delta > 0 ? '↑' : '↓'}
35
- </div>
36
- <div className="flex flex-col">
37
- <div className="bold uppercase text-zinc-300">{stock.symbol}</div>
38
- <div className="text-base text-zinc-500">
39
- ${stock.price.toExponential(1)}
40
- </div>
41
- </div>
42
- <div className="ml-auto flex flex-col">
43
- <div
44
- className={`${
45
- stock.delta > 0 ? 'text-green-600' : 'text-red-600'
46
- } bold text-right uppercase`}
47
- >
48
- {` ${((stock.delta / stock.price) * 100).toExponential(1)}%`}
49
- </div>
50
- <div
51
- className={`${
52
- stock.delta > 0 ? 'text-green-700' : 'text-red-700'
53
- } text-right text-base`}
54
- >
55
- {stock.delta.toExponential(1)}
56
- </div>
57
- </div>
58
- </button>
59
- ))}
60
- </div>
61
- <div className="p-4 text-center text-sm text-zinc-500">
62
- Note: Data and latency are simulated for illustrative purposes and
63
- should not be considered as financial advice.
64
- </div>
65
- </div>
66
- )
67
- }
@@ -1,14 +0,0 @@
1
- export function TailwindIndicator() {
2
- if (process.env.NODE_ENV === 'production') return null
3
-
4
- return (
5
- <div className="fixed bottom-1 left-1 z-50 flex size-6 items-center justify-center rounded-full bg-gray-800 p-3 font-mono text-xs text-white">
6
- <div className="block sm:hidden">xs</div>
7
- <div className="hidden sm:block md:hidden">sm</div>
8
- <div className="hidden md:block lg:hidden">md</div>
9
- <div className="hidden lg:block xl:hidden">lg</div>
10
- <div className="hidden xl:block 2xl:hidden">xl</div>
11
- <div className="hidden 2xl:block">2xl</div>
12
- </div>
13
- )
14
- }
@@ -1,31 +0,0 @@
1
- 'use client'
2
-
3
- import * as React from 'react'
4
- import { useTheme } from 'next-themes'
5
-
6
- import { Button } from '@/components/ui/button'
7
- import { IconMoon, IconSun } from '@/components/ui/icons'
8
-
9
- export function ThemeToggle() {
10
- const { setTheme, theme } = useTheme()
11
- const [_, startTransition] = React.useTransition()
12
-
13
- return (
14
- <Button
15
- variant="ghost"
16
- size="icon"
17
- onClick={() => {
18
- startTransition(() => {
19
- setTheme(theme === 'light' ? 'dark' : 'light')
20
- })
21
- }}
22
- >
23
- {!theme ? null : theme === 'dark' ? (
24
- <IconMoon className="transition-all" />
25
- ) : (
26
- <IconSun className="transition-all" />
27
- )}
28
- <span className="sr-only">Toggle theme</span>
29
- </Button>
30
- )
31
- }
@@ -1,141 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
5
-
6
- import { cn } from "@/lib/utils"
7
- import { buttonVariants } from "@/components/ui/button"
8
-
9
- const AlertDialog = AlertDialogPrimitive.Root
10
-
11
- const AlertDialogTrigger = AlertDialogPrimitive.Trigger
12
-
13
- const AlertDialogPortal = AlertDialogPrimitive.Portal
14
-
15
- const AlertDialogOverlay = React.forwardRef<
16
- React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
17
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
18
- >(({ className, ...props }, ref) => (
19
- <AlertDialogPrimitive.Overlay
20
- className={cn(
21
- "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",
22
- className
23
- )}
24
- {...props}
25
- ref={ref}
26
- />
27
- ))
28
- AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
29
-
30
- const AlertDialogContent = React.forwardRef<
31
- React.ElementRef<typeof AlertDialogPrimitive.Content>,
32
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
33
- >(({ className, ...props }, ref) => (
34
- <AlertDialogPortal>
35
- <AlertDialogOverlay />
36
- <AlertDialogPrimitive.Content
37
- ref={ref}
38
- className={cn(
39
- "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",
40
- className
41
- )}
42
- {...props}
43
- />
44
- </AlertDialogPortal>
45
- ))
46
- AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
47
-
48
- const AlertDialogHeader = ({
49
- className,
50
- ...props
51
- }: React.HTMLAttributes<HTMLDivElement>) => (
52
- <div
53
- className={cn(
54
- "flex flex-col space-y-2 text-center sm:text-left",
55
- className
56
- )}
57
- {...props}
58
- />
59
- )
60
- AlertDialogHeader.displayName = "AlertDialogHeader"
61
-
62
- const AlertDialogFooter = ({
63
- className,
64
- ...props
65
- }: React.HTMLAttributes<HTMLDivElement>) => (
66
- <div
67
- className={cn(
68
- "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
69
- className
70
- )}
71
- {...props}
72
- />
73
- )
74
- AlertDialogFooter.displayName = "AlertDialogFooter"
75
-
76
- const AlertDialogTitle = React.forwardRef<
77
- React.ElementRef<typeof AlertDialogPrimitive.Title>,
78
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
79
- >(({ className, ...props }, ref) => (
80
- <AlertDialogPrimitive.Title
81
- ref={ref}
82
- className={cn("text-lg font-semibold", className)}
83
- {...props}
84
- />
85
- ))
86
- AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
87
-
88
- const AlertDialogDescription = React.forwardRef<
89
- React.ElementRef<typeof AlertDialogPrimitive.Description>,
90
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
91
- >(({ className, ...props }, ref) => (
92
- <AlertDialogPrimitive.Description
93
- ref={ref}
94
- className={cn("text-sm text-muted-foreground", className)}
95
- {...props}
96
- />
97
- ))
98
- AlertDialogDescription.displayName =
99
- AlertDialogPrimitive.Description.displayName
100
-
101
- const AlertDialogAction = React.forwardRef<
102
- React.ElementRef<typeof AlertDialogPrimitive.Action>,
103
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
104
- >(({ className, ...props }, ref) => (
105
- <AlertDialogPrimitive.Action
106
- ref={ref}
107
- className={cn(buttonVariants(), className)}
108
- {...props}
109
- />
110
- ))
111
- AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
112
-
113
- const AlertDialogCancel = React.forwardRef<
114
- React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
115
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
116
- >(({ className, ...props }, ref) => (
117
- <AlertDialogPrimitive.Cancel
118
- ref={ref}
119
- className={cn(
120
- buttonVariants({ variant: "outline" }),
121
- "mt-2 sm:mt-0",
122
- className
123
- )}
124
- {...props}
125
- />
126
- ))
127
- AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
128
-
129
- export {
130
- AlertDialog,
131
- AlertDialogPortal,
132
- AlertDialogOverlay,
133
- AlertDialogTrigger,
134
- AlertDialogContent,
135
- AlertDialogHeader,
136
- AlertDialogFooter,
137
- AlertDialogTitle,
138
- AlertDialogDescription,
139
- AlertDialogAction,
140
- AlertDialogCancel,
141
- }
@@ -1,36 +0,0 @@
1
- import * as React from "react"
2
- import { cva, type VariantProps } from "class-variance-authority"
3
-
4
- import { cn } from "@/lib/utils"
5
-
6
- const badgeVariants = cva(
7
- "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8
- {
9
- variants: {
10
- variant: {
11
- default:
12
- "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
13
- secondary:
14
- "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15
- destructive:
16
- "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
17
- outline: "text-foreground",
18
- },
19
- },
20
- defaultVariants: {
21
- variant: "default",
22
- },
23
- }
24
- )
25
-
26
- export interface BadgeProps
27
- extends React.HTMLAttributes<HTMLDivElement>,
28
- VariantProps<typeof badgeVariants> {}
29
-
30
- function Badge({ className, variant, ...props }: BadgeProps) {
31
- return (
32
- <div className={cn(badgeVariants({ variant }), className)} {...props} />
33
- )
34
- }
35
-
36
- export { Badge, badgeVariants }
@@ -1,57 +0,0 @@
1
- import * as React from 'react'
2
- import { Slot } from '@radix-ui/react-slot'
3
- import { cva, type VariantProps } from 'class-variance-authority'
4
-
5
- import { cn } from '@/lib/utils'
6
-
7
- const buttonVariants = cva(
8
- 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
9
- {
10
- variants: {
11
- variant: {
12
- default:
13
- 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
14
- destructive:
15
- 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
16
- outline:
17
- 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
18
- secondary:
19
- 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
20
- ghost: 'hover:bg-accent hover:text-accent-foreground',
21
- link: 'text-primary underline-offset-4 hover:underline'
22
- },
23
- size: {
24
- default: 'h-9 px-4 py-2',
25
- sm: 'h-8 rounded-md px-3 text-xs',
26
- lg: 'h-10 rounded-md px-8',
27
- icon: 'size-9'
28
- }
29
- },
30
- defaultVariants: {
31
- variant: 'default',
32
- size: 'default'
33
- }
34
- }
35
- )
36
-
37
- export interface ButtonProps
38
- extends React.ButtonHTMLAttributes<HTMLButtonElement>,
39
- VariantProps<typeof buttonVariants> {
40
- asChild?: boolean
41
- }
42
-
43
- const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
44
- ({ className, variant, size, asChild = false, ...props }, ref) => {
45
- const Comp = asChild ? Slot : 'button'
46
- return (
47
- <Comp
48
- className={cn(buttonVariants({ variant, size, className }))}
49
- ref={ref}
50
- {...props}
51
- />
52
- )
53
- }
54
- )
55
- Button.displayName = 'Button'
56
-
57
- export { Button, buttonVariants }