@tulipfarm/sprout 0.3.1 → 0.5.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 (355) hide show
  1. package/README.md +75 -68
  2. package/dist/components/accordion.d.ts +2 -2
  3. package/dist/components/accordion.js +9 -9
  4. package/dist/components/agent-avatar.d.ts +27 -0
  5. package/dist/components/agent-avatar.js +67 -0
  6. package/dist/components/agent-fanout.d.ts +2 -2
  7. package/dist/components/agent-fanout.js +65 -87
  8. package/dist/components/alert-dialog.d.ts +8 -8
  9. package/dist/components/alert-dialog.js +21 -21
  10. package/dist/components/alert.d.ts +6 -6
  11. package/dist/components/alert.js +13 -13
  12. package/dist/components/aspect-ratio.d.ts +2 -2
  13. package/dist/components/aspect-ratio.js +2 -2
  14. package/dist/components/attachment.d.ts +18 -18
  15. package/dist/components/attachment.js +82 -115
  16. package/dist/components/avatar.d.ts +9 -17
  17. package/dist/components/avatar.js +14 -51
  18. package/dist/components/badge.d.ts +4 -4
  19. package/dist/components/badge.js +18 -18
  20. package/dist/components/board.d.ts +107 -0
  21. package/dist/components/board.js +640 -0
  22. package/dist/components/brand-icon.d.ts +6 -6
  23. package/dist/components/brand-icon.js +55 -63
  24. package/dist/components/breadcrumb.d.ts +11 -11
  25. package/dist/components/breadcrumb.js +16 -18
  26. package/dist/components/button-group.d.ts +6 -6
  27. package/dist/components/button-group.js +14 -14
  28. package/dist/components/button.d.ts +13 -13
  29. package/dist/components/button.js +31 -57
  30. package/dist/components/calendar.d.ts +5 -5
  31. package/dist/components/calendar.js +44 -53
  32. package/dist/components/canvas.d.ts +4 -4
  33. package/dist/components/canvas.js +39 -46
  34. package/dist/components/card.d.ts +7 -7
  35. package/dist/components/card.js +17 -17
  36. package/dist/components/carousel.d.ts +7 -7
  37. package/dist/components/carousel.js +57 -75
  38. package/dist/components/chart.d.ts +5 -112
  39. package/dist/components/chart.js +5 -172
  40. package/dist/components/chat-confirmation.d.ts +10 -10
  41. package/dist/components/chat-confirmation.js +32 -38
  42. package/dist/components/chat-input.d.ts +4 -4
  43. package/dist/components/chat-input.js +74 -81
  44. package/dist/components/chat-plan.d.ts +2 -2
  45. package/dist/components/chat-plan.js +15 -20
  46. package/dist/components/chat-sources.d.ts +8 -8
  47. package/dist/components/chat-sources.js +18 -27
  48. package/dist/components/checkbox.d.ts +1 -1
  49. package/dist/components/checkbox.js +9 -9
  50. package/dist/components/choice-list.d.ts +2 -2
  51. package/dist/components/choice-list.js +16 -18
  52. package/dist/components/code-block.d.ts +5 -5
  53. package/dist/components/code-block.js +26 -26
  54. package/dist/components/collapsible.d.ts +1 -1
  55. package/dist/components/collapsible.js +7 -11
  56. package/dist/components/combobox.d.ts +12 -6
  57. package/dist/components/combobox.js +27 -26
  58. package/dist/components/command.d.ts +13 -13
  59. package/dist/components/command.js +61 -73
  60. package/dist/components/context-menu.d.ts +5 -5
  61. package/dist/components/context-menu.js +22 -22
  62. package/dist/components/dialog.d.ts +6 -6
  63. package/dist/components/dialog.js +23 -28
  64. package/dist/components/direction.d.ts +1 -1
  65. package/dist/components/direction.js +1 -1
  66. package/dist/components/dropdown-menu.d.ts +5 -5
  67. package/dist/components/dropdown-menu.js +20 -20
  68. package/dist/components/field.d.ts +11 -11
  69. package/dist/components/field.js +41 -61
  70. package/dist/components/file-explorer.d.ts +2 -2
  71. package/dist/components/file-explorer.js +89 -105
  72. package/dist/components/file-viewer.d.ts +10 -10
  73. package/dist/components/file-viewer.js +112 -140
  74. package/dist/components/form.d.ts +7 -7
  75. package/dist/components/form.js +24 -28
  76. package/dist/components/glass-banner.d.ts +3 -3
  77. package/dist/components/glass-banner.js +21 -24
  78. package/dist/components/gradient-banner.d.ts +7 -7
  79. package/dist/components/gradient-banner.js +13 -22
  80. package/dist/components/hover-card.d.ts +4 -4
  81. package/dist/components/hover-card.js +6 -6
  82. package/dist/components/input-group.d.ts +18 -18
  83. package/dist/components/input-group.js +25 -39
  84. package/dist/components/input-otp.d.ts +14 -10
  85. package/dist/components/input-otp.js +15 -15
  86. package/dist/components/input.d.ts +3 -3
  87. package/dist/components/input.js +7 -7
  88. package/dist/components/kbd.d.ts +3 -3
  89. package/dist/components/kbd.js +5 -5
  90. package/dist/components/label.d.ts +2 -2
  91. package/dist/components/label.js +2 -2
  92. package/dist/components/mention-list.d.ts +3 -3
  93. package/dist/components/mention-list.js +10 -10
  94. package/dist/components/menubar.d.ts +6 -6
  95. package/dist/components/menubar.js +22 -22
  96. package/dist/components/message-actions.d.ts +2 -2
  97. package/dist/components/message-actions.js +29 -31
  98. package/dist/components/message-response.d.ts +3 -3
  99. package/dist/components/message-response.js +18 -18
  100. package/dist/components/message-scroller.d.ts +12 -12
  101. package/dist/components/message-scroller.js +44 -56
  102. package/dist/components/message.d.ts +11 -11
  103. package/dist/components/message.js +25 -25
  104. package/dist/components/navigation-menu.d.ts +2 -2
  105. package/dist/components/navigation-menu.js +15 -15
  106. package/dist/components/notice-banner.d.ts +2 -2
  107. package/dist/components/notice-banner.js +2 -2
  108. package/dist/components/page-content.d.ts +2 -2
  109. package/dist/components/page-content.js +2 -2
  110. package/dist/components/page-header.d.ts +1 -1
  111. package/dist/components/page-header.js +17 -17
  112. package/dist/components/pagination.d.ts +9 -9
  113. package/dist/components/pagination.js +17 -17
  114. package/dist/components/plan-outline.d.ts +2 -2
  115. package/dist/components/plan-outline.js +43 -60
  116. package/dist/components/popover.d.ts +6 -6
  117. package/dist/components/popover.js +15 -15
  118. package/dist/components/presence-cursor.d.ts +2 -2
  119. package/dist/components/presence-cursor.js +3 -3
  120. package/dist/components/progress.d.ts +1 -1
  121. package/dist/components/progress.js +8 -8
  122. package/dist/components/prompt-list.d.ts +3 -3
  123. package/dist/components/prompt-list.js +6 -6
  124. package/dist/components/questionnaire.d.ts +19 -19
  125. package/dist/components/questionnaire.js +183 -242
  126. package/dist/components/radio-group.d.ts +2 -2
  127. package/dist/components/radio-group.js +6 -6
  128. package/dist/components/reasoning-effort.d.ts +3 -3
  129. package/dist/components/reasoning-effort.js +9 -12
  130. package/dist/components/record-list.d.ts +66 -0
  131. package/dist/components/record-list.js +151 -0
  132. package/dist/components/resizable.d.ts +5 -5
  133. package/dist/components/resizable.js +76 -102
  134. package/dist/components/result-card.d.ts +4 -4
  135. package/dist/components/result-card.js +42 -53
  136. package/dist/components/result-notice.d.ts +18 -0
  137. package/dist/components/result-notice.js +29 -0
  138. package/dist/components/review-card.d.ts +6 -6
  139. package/dist/components/review-card.js +18 -18
  140. package/dist/components/rich-text-editor.d.ts +5 -5
  141. package/dist/components/rich-text-editor.js +56 -72
  142. package/dist/components/schema-diagram.d.ts +3 -3
  143. package/dist/components/schema-diagram.js +39 -53
  144. package/dist/components/scroll-area.d.ts +3 -3
  145. package/dist/components/scroll-area.js +10 -14
  146. package/dist/components/search-dialog.d.ts +6 -6
  147. package/dist/components/search-dialog.js +16 -16
  148. package/dist/components/search-field.d.ts +1 -1
  149. package/dist/components/search-field.js +11 -11
  150. package/dist/components/select.d.ts +5 -9
  151. package/dist/components/select.js +20 -20
  152. package/dist/components/selection-slot.d.ts +2 -2
  153. package/dist/components/selection-slot.js +6 -9
  154. package/dist/components/separator.d.ts +15 -15
  155. package/dist/components/separator.js +22 -27
  156. package/dist/components/settings-list.d.ts +3 -3
  157. package/dist/components/settings-list.js +5 -5
  158. package/dist/components/sheet.d.ts +6 -6
  159. package/dist/components/sheet.js +27 -27
  160. package/dist/components/sidebar.d.ts +22 -22
  161. package/dist/components/sidebar.js +57 -58
  162. package/dist/components/skeleton.d.ts +5 -5
  163. package/dist/components/skeleton.js +14 -21
  164. package/dist/components/slider.d.ts +2 -2
  165. package/dist/components/slider.js +6 -6
  166. package/dist/components/spinner.d.ts +7 -7
  167. package/dist/components/spinner.js +22 -26
  168. package/dist/components/sql-viewer.d.ts +14 -14
  169. package/dist/components/sql-viewer.js +99 -128
  170. package/dist/components/state-panel-samples.d.ts +2 -2
  171. package/dist/components/state-panel-samples.js +209 -245
  172. package/dist/components/state-panel.d.ts +2 -35
  173. package/dist/components/state-panel.js +2 -29
  174. package/dist/components/state-sample.d.ts +8 -8
  175. package/dist/components/state-sample.js +18 -31
  176. package/dist/components/switch.d.ts +3 -3
  177. package/dist/components/switch.js +7 -7
  178. package/dist/components/table-nuqs.d.ts +2 -2
  179. package/dist/components/table-nuqs.js +11 -12
  180. package/dist/components/table.d.ts +4 -4
  181. package/dist/components/table.js +166 -235
  182. package/dist/components/tabs.d.ts +2 -2
  183. package/dist/components/tabs.js +12 -12
  184. package/dist/components/textarea.d.ts +2 -2
  185. package/dist/components/textarea.js +6 -8
  186. package/dist/components/timeline.d.ts +3 -0
  187. package/dist/components/timeline.js +3 -0
  188. package/dist/components/toast.d.ts +2 -2
  189. package/dist/components/toast.js +19 -25
  190. package/dist/components/toggle-group.d.ts +4 -4
  191. package/dist/components/toggle-group.js +18 -20
  192. package/dist/components/toggle.d.ts +4 -4
  193. package/dist/components/toggle.js +8 -8
  194. package/dist/components/tool-activity.d.ts +1 -1
  195. package/dist/components/tool-activity.js +83 -110
  196. package/dist/components/toolbar-status.d.ts +2 -2
  197. package/dist/components/toolbar-status.js +7 -7
  198. package/dist/components/tooltip.d.ts +5 -5
  199. package/dist/components/tooltip.js +12 -11
  200. package/dist/components/typed-text.d.ts +2 -2
  201. package/dist/components/typed-text.js +10 -12
  202. package/dist/components/view-switcher.d.ts +51 -0
  203. package/dist/components/view-switcher.js +114 -0
  204. package/dist/index.d.ts +99 -93
  205. package/dist/index.js +99 -93
  206. package/dist/internal/agent-avatar-artwork.d.ts +4 -0
  207. package/dist/internal/agent-avatar-artwork.js +219 -0
  208. package/dist/internal/chart-kit.d.ts +142 -0
  209. package/dist/internal/chart-kit.js +200 -0
  210. package/dist/internal/charts/bars.d.ts +61 -0
  211. package/dist/internal/charts/bars.js +86 -0
  212. package/dist/internal/charts/lines.d.ts +67 -0
  213. package/dist/internal/charts/lines.js +70 -0
  214. package/dist/internal/charts/more.d.ts +77 -0
  215. package/dist/internal/charts/more.js +68 -0
  216. package/dist/internal/charts/parts.d.ts +54 -0
  217. package/dist/internal/charts/parts.js +82 -0
  218. package/dist/internal/charts/timeline-dates.d.ts +38 -0
  219. package/dist/internal/charts/timeline-dates.js +113 -0
  220. package/dist/internal/charts/timeline-window.d.ts +31 -0
  221. package/dist/internal/charts/timeline-window.js +26 -0
  222. package/dist/internal/charts/timeline.d.ts +72 -0
  223. package/dist/internal/charts/timeline.js +287 -0
  224. package/dist/internal/classes.d.ts +1 -1
  225. package/dist/internal/classes.js +7 -9
  226. package/dist/internal/code-tokens.d.ts +2 -2
  227. package/dist/internal/code-tokens.js +12 -12
  228. package/dist/internal/fieldset.d.ts +1 -1
  229. package/dist/internal/fieldset.js +6 -6
  230. package/dist/internal/file-kind.d.ts +1 -1
  231. package/dist/internal/file-kind.js +43 -51
  232. package/dist/internal/flow.d.ts +4 -4
  233. package/dist/internal/flow.js +20 -23
  234. package/dist/internal/hash.d.ts +1 -0
  235. package/dist/internal/hash.js +9 -0
  236. package/dist/internal/languages.js +999 -999
  237. package/dist/internal/message-scroller.d.ts +3 -3
  238. package/dist/internal/message-scroller.js +64 -112
  239. package/dist/internal/pressable.d.ts +1 -1
  240. package/dist/internal/pressable.js +7 -7
  241. package/dist/internal/state-panel.d.ts +35 -0
  242. package/dist/internal/state-panel.js +22 -0
  243. package/dist/internal/syntax.d.ts +2 -2
  244. package/dist/internal/syntax.js +36 -47
  245. package/dist/styles/accordion.css +3 -5
  246. package/dist/styles/agent-fanout.css +64 -60
  247. package/dist/styles/alert-dialog.css +12 -26
  248. package/dist/styles/alert.css +10 -15
  249. package/dist/styles/attachment.css +56 -98
  250. package/dist/styles/avatar.css +14 -33
  251. package/dist/styles/badge.css +11 -36
  252. package/dist/styles/board.css +571 -0
  253. package/dist/styles/brand-icon.css +7 -8
  254. package/dist/styles/breadcrumb.css +4 -7
  255. package/dist/styles/button-group.css +9 -15
  256. package/dist/styles/button.css +45 -175
  257. package/dist/styles/calendar.css +24 -36
  258. package/dist/styles/canvas.css +2 -3
  259. package/dist/styles/card.css +7 -23
  260. package/dist/styles/carousel.css +11 -12
  261. package/dist/styles/chart.css +215 -31
  262. package/dist/styles/chat-input.css +15 -39
  263. package/dist/styles/chat-plan.css +3 -4
  264. package/dist/styles/chat-sources.css +4 -6
  265. package/dist/styles/checkbox.css +11 -25
  266. package/dist/styles/choice-list.css +17 -31
  267. package/dist/styles/code-block.css +11 -25
  268. package/dist/styles/collapsible.css +10 -15
  269. package/dist/styles/combobox.css +24 -17
  270. package/dist/styles/command.css +8 -9
  271. package/dist/styles/context-menu.css +4 -2
  272. package/dist/styles/dialog.css +5 -16
  273. package/dist/styles/dropdown-menu.css +4 -2
  274. package/dist/styles/field.css +15 -21
  275. package/dist/styles/file-explorer.css +19 -33
  276. package/dist/styles/file-viewer.css +13 -17
  277. package/dist/styles/form.css +3 -3
  278. package/dist/styles/glass-banner.css +12 -47
  279. package/dist/styles/gradient-banner.css +16 -39
  280. package/dist/styles/hover-card.css +9 -15
  281. package/dist/styles/index.css +121 -112
  282. package/dist/styles/input-group.css +61 -69
  283. package/dist/styles/input-otp.css +18 -9
  284. package/dist/styles/input.css +19 -11
  285. package/dist/styles/kbd.css +1 -1
  286. package/dist/styles/label.css +9 -30
  287. package/dist/styles/mention-list.css +6 -8
  288. package/dist/styles/menubar.css +9 -8
  289. package/dist/styles/message-actions.css +1 -1
  290. package/dist/styles/message-response.css +3 -5
  291. package/dist/styles/message-scroller.css +14 -21
  292. package/dist/styles/message.css +23 -60
  293. package/dist/styles/navigation-menu.css +15 -30
  294. package/dist/styles/notice-banner.css +1 -2
  295. package/dist/styles/page-header.css +11 -10
  296. package/dist/styles/pagination.css +12 -6
  297. package/dist/styles/plan-outline.css +20 -37
  298. package/dist/styles/popover.css +10 -19
  299. package/dist/styles/presence-cursor.css +1 -2
  300. package/dist/styles/progress.css +2 -4
  301. package/dist/styles/prompt-list.css +6 -17
  302. package/dist/styles/questionnaire.css +16 -40
  303. package/dist/styles/radio-group.css +12 -23
  304. package/dist/styles/reasoning-effort.css +8 -15
  305. package/dist/styles/record-list.css +243 -0
  306. package/dist/styles/resizable.css +10 -11
  307. package/dist/styles/result-card.css +4 -4
  308. package/dist/styles/result-notice.css +80 -0
  309. package/dist/styles/review-card.css +2 -3
  310. package/dist/styles/rich-text-editor.css +4 -5
  311. package/dist/styles/schema-diagram.css +12 -17
  312. package/dist/styles/scroll-area.css +8 -10
  313. package/dist/styles/search-dialog.css +1 -5
  314. package/dist/styles/search-field.css +1 -2
  315. package/dist/styles/select.css +15 -19
  316. package/dist/styles/selection-slot.css +1 -2
  317. package/dist/styles/separator.css +7 -8
  318. package/dist/styles/settings-list.css +1 -2
  319. package/dist/styles/sheet.css +40 -73
  320. package/dist/styles/sidebar.css +32 -34
  321. package/dist/styles/skeleton.css +9 -11
  322. package/dist/styles/slider.css +11 -21
  323. package/dist/styles/spinner.css +2 -2
  324. package/dist/styles/sql-viewer.css +29 -29
  325. package/dist/styles/state-panel.css +8 -9
  326. package/dist/styles/state-sample.css +20 -33
  327. package/dist/styles/switch.css +11 -18
  328. package/dist/styles/table.css +62 -81
  329. package/dist/styles/tabs.css +13 -19
  330. package/dist/styles/textarea.css +3 -3
  331. package/dist/styles/themes/chatgpt.css +11 -23
  332. package/dist/styles/themes/claude.css +12 -24
  333. package/dist/styles/themes/cloudflare.css +11 -23
  334. package/dist/styles/themes/discord.css +11 -23
  335. package/dist/styles/themes/github.css +11 -23
  336. package/dist/styles/themes/grok.css +11 -23
  337. package/dist/styles/themes/linear.css +12 -25
  338. package/dist/styles/themes/neutral.css +11 -23
  339. package/dist/styles/themes/notion.css +11 -23
  340. package/dist/styles/themes/perplexity.css +11 -23
  341. package/dist/styles/themes/raycast.css +11 -23
  342. package/dist/styles/themes/spotify.css +11 -23
  343. package/dist/styles/themes/stripe.css +11 -23
  344. package/dist/styles/themes/supabase.css +11 -23
  345. package/dist/styles/themes/tulipfarm.css +9 -10
  346. package/dist/styles/themes/vercel.css +12 -25
  347. package/dist/styles/timeline.css +276 -0
  348. package/dist/styles/toast.css +13 -20
  349. package/dist/styles/toggle-group.css +23 -29
  350. package/dist/styles/toggle.css +14 -14
  351. package/dist/styles/tool-activity.css +7 -13
  352. package/dist/styles/toolbar-status.css +2 -7
  353. package/dist/styles/tooltip.css +15 -21
  354. package/dist/styles/view-switcher.css +297 -0
  355. package/package.json +25 -1
@@ -1,16 +1,16 @@
1
- "use client";
1
+ 'use client';
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Background, getSmoothStepPath, Handle, Panel, Position, ReactFlow, ReactFlowProvider, useInternalNode, useNodesState, } from "@xyflow/react";
4
- import { createContext, useCallback, useContext, useEffect, useId, useMemo, useState, } from "react";
5
- import { Fingerprint } from "reicon-react/icons/Fingerprint";
6
- import { Key } from "reicon-react/icons/Key";
7
- import { Layers } from "reicon-react/icons/Layers";
8
- import { Link } from "reicon-react/icons/Link";
9
- import { cn } from "../internal/classes.js";
10
- import { FitOnResize, flowMaxZoom, flowMinZoom, useKeyboardView, useViewportMobile, ZoomControls, } from "../internal/flow.js";
11
- import { Button } from "./button.js";
12
- export const sqlViewerLayoutNames = ["auto", "horizontal", "vertical"];
13
- const moreId = "~more";
3
+ import { Background, getSmoothStepPath, Handle, Panel, Position, ReactFlow, ReactFlowProvider, useInternalNode, useNodesState, } from '@xyflow/react';
4
+ import { createContext, useCallback, useContext, useEffect, useId, useMemo, useState, } from 'react';
5
+ import { Fingerprint } from 'reicon-react/icons/Fingerprint';
6
+ import { Key } from 'reicon-react/icons/Key';
7
+ import { Layers } from 'reicon-react/icons/Layers';
8
+ import { Link } from 'reicon-react/icons/Link';
9
+ import { cn } from '../internal/classes.js';
10
+ import { FitOnResize, flowMaxZoom, flowMinZoom, useKeyboardView, useViewportMobile, ZoomControls, } from '../internal/flow.js';
11
+ import { Button } from './button.js';
12
+ export const sqlViewerLayoutNames = ['auto', 'horizontal', 'vertical'];
13
+ const moreId = '~more';
14
14
  const groupId = (key) => `~group:${key}`;
15
15
  // Card geometry. The CSS uses the same numbers so layout never waits for a measure.
16
16
  const cardWidth = 272;
@@ -19,7 +19,6 @@ const headerHeight = 40;
19
19
  const rowHeight = 28;
20
20
  const keysChrome = 36;
21
21
  const keyHeight = 26;
22
- const moreHeight = 132;
23
22
  const colGap = 104;
24
23
  const rowGap = 32;
25
24
  const groupPad = 20;
@@ -28,38 +27,33 @@ const groupGap = 56;
28
27
  const wrapWidth = 1400;
29
28
  const tones = 5;
30
29
  const fitAll = { padding: 0.12, maxZoom: 1 };
31
- const compositeKeys = (table) => (table.uniqueKeys ?? []).filter((key) => key.fieldIds.length > 1);
30
+ const compositeKeys = (table) => (table.uniqueKeys ?? []).filter(key => key.fieldIds.length > 1);
32
31
  const cardHeight = (table) => {
33
32
  const keys = compositeKeys(table).length;
34
- return (cardChrome +
35
- headerHeight +
36
- (table.fields.length + 1) * rowHeight +
37
- (keys ? keysChrome + keys * keyHeight : 0));
33
+ return cardChrome + headerHeight + (table.fields.length + 1) * rowHeight + (keys ? keysChrome + keys * keyHeight : 0);
38
34
  };
39
35
  function columnType(field) {
40
36
  switch (field.kind) {
41
- case "text":
37
+ case 'text':
42
38
  return `varchar(${field.maxLength})`;
43
- case "numeric":
39
+ case 'numeric':
44
40
  return `numeric(${field.precision},${field.scale})`;
45
- case "timestamp":
46
- return "timestamptz";
47
- case "single-select":
48
- return "enum";
49
- case "multi-select":
50
- return "enum[]";
51
- case "relationship":
52
- return field.cardinality === "one" ? "uuid" : "uuid[]";
53
- case "file":
54
- return field.cardinality === "one" ? "file" : "file[]";
41
+ case 'timestamp':
42
+ return 'timestamptz';
43
+ case 'single-select':
44
+ return 'enum';
45
+ case 'multi-select':
46
+ return 'enum[]';
47
+ case 'relationship':
48
+ return field.cardinality === 'one' ? 'uuid' : 'uuid[]';
49
+ case 'file':
50
+ return field.cardinality === 'one' ? 'file' : 'file[]';
55
51
  default:
56
52
  return field.kind;
57
53
  }
58
54
  }
59
55
  function joinText(from, field, to, many) {
60
- return many
61
- ? `${to}.id = ANY(${from}.${field})`
62
- : `${from}.${field} = ${to}.id`;
56
+ return many ? `${to}.id = ANY(${from}.${field})` : `${from}.${field} = ${to}.id`;
63
57
  }
64
58
  /** Places tables in team groups. Linked tables sit one column right of the tables that link to them. */
65
59
  function arrange(visible, hidden, groups, direction) {
@@ -67,9 +61,9 @@ function arrange(visible, hidden, groups, direction) {
67
61
  for (const table of visible) {
68
62
  const team = table.owningTeamId;
69
63
  const key = team !== undefined && groups?.[team] ? team : null;
70
- let block = blocks.find((candidate) => candidate.key === key);
64
+ let block = blocks.find(candidate => candidate.key === key);
71
65
  if (!block) {
72
- block = { key, label: key ? groups[key] : "", tables: [] };
66
+ block = { key, label: key ? groups[key] : '', tables: [] };
73
67
  blocks.push(block);
74
68
  }
75
69
  block.tables.push(table);
@@ -82,21 +76,18 @@ function arrange(visible, hidden, groups, direction) {
82
76
  let bottom = 0;
83
77
  let tone = 0;
84
78
  for (const block of blocks) {
85
- const ids = new Set(block.tables.map((table) => table.id));
86
- const depth = new Map(block.tables.map((table) => [table.id, 0]));
87
- if (direction === "horizontal") {
79
+ const ids = new Set(block.tables.map(table => table.id));
80
+ const depth = new Map(block.tables.map(table => [table.id, 0]));
81
+ if (direction === 'horizontal') {
88
82
  for (let pass = 0; pass < block.tables.length; pass++) {
89
83
  let moved = false;
90
84
  for (const table of block.tables)
91
85
  for (const field of table.fields) {
92
- if (field.kind !== "relationship")
86
+ if (field.kind !== 'relationship')
93
87
  continue;
94
88
  const target = field.targetTableId;
95
89
  const next = depth.get(table.id) + 1;
96
- if (target !== table.id &&
97
- ids.has(target) &&
98
- next > depth.get(target) &&
99
- next < block.tables.length) {
90
+ if (target !== table.id && ids.has(target) && next > depth.get(target) && next < block.tables.length) {
100
91
  depth.set(target, next);
101
92
  moved = true;
102
93
  }
@@ -106,20 +97,18 @@ function arrange(visible, hidden, groups, direction) {
106
97
  }
107
98
  }
108
99
  const columnBottoms = new Map();
109
- const placed = block.tables.map((table) => {
100
+ const placed = block.tables.map(table => {
110
101
  const column = depth.get(table.id);
111
102
  const y = columnBottoms.get(column) ?? 0;
112
103
  columnBottoms.set(column, y + cardHeight(table) + rowGap);
113
104
  return { table, x: column * (cardWidth + colGap), y };
114
105
  });
115
- const innerWidth = Math.max(...placed.map((item) => item.x)) + cardWidth;
106
+ const innerWidth = Math.max(...placed.map(item => item.x)) + cardWidth;
116
107
  const innerHeight = Math.max(...columnBottoms.values()) - rowGap;
117
108
  const framed = block.key !== null;
118
109
  const width = framed ? innerWidth + groupPad * 2 : innerWidth;
119
110
  const height = framed ? innerHeight + groupHeader + groupPad : innerHeight;
120
- if (direction === "horizontal" &&
121
- cursorX > 0 &&
122
- cursorX + width > wrapWidth) {
111
+ if (direction === 'horizontal' && cursorX > 0 && cursorX + width > wrapWidth) {
123
112
  cursorX = 0;
124
113
  cursorY += lineHeight + groupGap;
125
114
  lineHeight = 0;
@@ -129,7 +118,7 @@ function arrange(visible, hidden, groups, direction) {
129
118
  if (framed)
130
119
  nodes.push({
131
120
  id: parent,
132
- type: "group",
121
+ type: 'group',
133
122
  position: { x: cursorX, y: cursorY },
134
123
  width,
135
124
  height,
@@ -138,26 +127,26 @@ function arrange(visible, hidden, groups, direction) {
138
127
  tone: blockTone,
139
128
  count: block.tables.length,
140
129
  },
141
- dragHandle: ".sprout-sql-group-label",
130
+ dragHandle: '.sprout-sql-group-label',
142
131
  focusable: false,
143
132
  selectable: false,
144
133
  });
145
134
  for (const item of placed)
146
135
  nodes.push({
147
136
  id: item.table.id,
148
- type: "table",
137
+ type: 'table',
149
138
  position: framed
150
139
  ? { x: groupPad + item.x, y: groupHeader + item.y }
151
140
  : { x: cursorX + item.x, y: cursorY + item.y },
152
141
  ...(parent ? { parentId: parent, expandParent: true } : {}),
153
142
  data: { table: item.table, tone: blockTone },
154
- ariaRole: "group",
143
+ ariaRole: 'group',
155
144
  ariaLabel: `${item.table.label} table, ${item.table.fields.length + 1} columns`,
156
- domAttributes: { "aria-roledescription": "table card" },
145
+ domAttributes: { 'aria-roledescription': 'table card' },
157
146
  });
158
147
  right = Math.max(right, cursorX + width);
159
148
  bottom = Math.max(bottom, cursorY + height);
160
- if (direction === "horizontal") {
149
+ if (direction === 'horizontal') {
161
150
  cursorX += width + groupGap;
162
151
  lineHeight = Math.max(lineHeight, height);
163
152
  }
@@ -168,42 +157,40 @@ function arrange(visible, hidden, groups, direction) {
168
157
  if (hidden.length)
169
158
  nodes.push({
170
159
  id: moreId,
171
- type: "more",
172
- position: direction === "horizontal"
173
- ? { x: right + colGap, y: 0 }
174
- : { x: 0, y: bottom + groupGap },
160
+ type: 'more',
161
+ position: direction === 'horizontal' ? { x: right + colGap, y: 0 } : { x: 0, y: bottom + groupGap },
175
162
  data: { tables: [...hidden] },
176
163
  focusable: false,
177
164
  });
178
165
  return nodes;
179
166
  }
180
167
  function joins(visible, hidden) {
181
- const shown = new Set(visible.map((table) => table.id));
182
- const collapsed = new Set(hidden.map((table) => table.id));
183
- const labels = new Map([...visible, ...hidden].map((table) => [table.id, table.label]));
184
- const node = (id) => shown.has(id) ? id : collapsed.has(id) ? moreId : null;
168
+ const shown = new Set(visible.map(table => table.id));
169
+ const collapsed = new Set(hidden.map(table => table.id));
170
+ const labels = new Map([...visible, ...hidden].map(table => [table.id, table.label]));
171
+ const node = (id) => (shown.has(id) ? id : collapsed.has(id) ? moreId : null);
185
172
  const edges = [];
186
173
  for (const table of [...visible, ...hidden])
187
174
  for (const field of table.fields) {
188
- if (field.kind !== "relationship")
175
+ if (field.kind !== 'relationship')
189
176
  continue;
190
177
  const source = node(table.id);
191
178
  const target = node(field.targetTableId);
192
179
  if (!source || !target || (source === moreId && target === moreId))
193
180
  continue;
194
181
  const to = labels.get(field.targetTableId);
195
- const sourceMany = field.inverseCardinality === "many";
196
- const targetMany = field.cardinality === "many";
182
+ const sourceMany = field.inverseCardinality === 'many';
183
+ const targetMany = field.cardinality === 'many';
197
184
  edges.push({
198
185
  id: `${table.id}/${field.id}`,
199
- type: "join",
186
+ type: 'join',
200
187
  source,
201
- sourceHandle: source === moreId ? "out:right" : `${field.id}:right`,
188
+ sourceHandle: source === moreId ? 'out:right' : `${field.id}:right`,
202
189
  target,
203
- targetHandle: target === moreId ? "in:left" : "id:left",
190
+ targetHandle: target === moreId ? 'in:left' : 'id:left',
204
191
  data: {
205
192
  join: joinText(table.label, field.label, to, targetMany),
206
- description: `${table.label}.${field.label} joins ${to}.id, ${sourceMany ? "many" : "one"} to ${targetMany ? "many" : "one"}`,
193
+ description: `${table.label}.${field.label} joins ${to}.id, ${sourceMany ? 'many' : 'one'} to ${targetMany ? 'many' : 'one'}`,
207
194
  sourceMany,
208
195
  targetMany,
209
196
  },
@@ -219,42 +206,36 @@ function sideHandles(type, id) {
219
206
  function TableCard({ id, data: { table, tone } }) {
220
207
  const viewer = useViewer();
221
208
  const composite = compositeKeys(table);
222
- const unique = new Set((table.uniqueKeys ?? [])
223
- .filter((key) => key.fieldIds.length === 1)
224
- .map((key) => key.fieldIds[0]));
225
- const labels = new Map(table.fields.map((field) => [field.id, field.label]));
209
+ const unique = new Set((table.uniqueKeys ?? []).filter(key => key.fieldIds.length === 1).map(key => key.fieldIds[0]));
210
+ const labels = new Map(table.fields.map(field => [field.id, field.label]));
226
211
  const focused = viewer.focus?.table === id;
227
- return (_jsxs("section", { "data-slot": "sql-table", "data-tone": tone, "data-dimmed": viewer.focus && !viewer.related.has(id) ? "" : undefined, "data-active": focused ? "" : undefined, className: "sprout-sql-table", onMouseLeave: () => viewer.hover(null), children: [_jsx("header", { className: "sprout-sql-table-header", children: _jsx("h3", { className: "sprout-sql-table-title", title: table.label, children: table.label }) }), _jsxs("ul", { className: "sprout-sql-columns", children: [_jsxs("li", { className: "sprout-sql-column", "data-key": "primary", children: [sideHandles("target", "id"), _jsx("span", { className: "sprout-sql-column-icon", children: _jsx(Key, { size: 12, role: "img", "aria-label": "Primary key" }) }), _jsx("span", { className: "sprout-sql-column-name", children: "id" }), _jsx("span", { className: "sprout-sql-column-type", children: "uuid" })] }), table.fields.map((field) => {
228
- const join = field.kind === "relationship";
212
+ return (_jsxs("section", { "data-slot": "sql-table", "data-tone": tone, "data-dimmed": viewer.focus && !viewer.related.has(id) ? '' : undefined, "data-active": focused ? '' : undefined, className: "sprout-sql-table", onMouseLeave: () => viewer.hover(null), children: [_jsx("header", { className: "sprout-sql-table-header", children: _jsx("h3", { className: "sprout-sql-table-title", title: table.label, children: table.label }) }), _jsxs("ul", { className: "sprout-sql-columns", children: [_jsxs("li", { className: "sprout-sql-column", "data-key": "primary", children: [sideHandles('target', 'id'), _jsx("span", { className: "sprout-sql-column-icon", children: _jsx(Key, { size: 12, role: "img", "aria-label": "Primary key" }) }), _jsx("span", { className: "sprout-sql-column-name", children: "id" }), _jsx("span", { className: "sprout-sql-column-type", children: "uuid" })] }), table.fields.map(field => {
213
+ const join = field.kind === 'relationship';
229
214
  const type = columnType(field);
230
- return (_jsxs("li", { className: "sprout-sql-column", "data-join": join ? "" : undefined, "data-active": focused && viewer.focus?.field === field.id ? "" : undefined, title: field.kind === "single-select" || field.kind === "multi-select"
215
+ return (_jsxs("li", { className: "sprout-sql-column", "data-join": join ? '' : undefined, "data-active": focused && viewer.focus?.field === field.id ? '' : undefined, title: field.kind === 'single-select' || field.kind === 'multi-select'
231
216
  ? field.options
232
- .filter((option) => !option.retired)
233
- .map((option) => option.label)
234
- .join(" · ")
235
- : undefined, onMouseEnter: join
236
- ? () => viewer.hover({ table: id, field: field.id })
237
- : undefined, onMouseLeave: join ? () => viewer.hover({ table: id }) : undefined, onClick: join
238
- ? (event) => {
217
+ .filter(option => !option.retired)
218
+ .map(option => option.label)
219
+ .join(' · ')
220
+ : undefined, onMouseEnter: join ? () => viewer.hover({ table: id, field: field.id }) : undefined, onMouseLeave: join ? () => viewer.hover({ table: id }) : undefined, onClick: join
221
+ ? event => {
239
222
  event.stopPropagation();
240
223
  viewer.pin({ table: id, field: field.id });
241
224
  }
242
- : undefined, children: [join && sideHandles("source", field.id), _jsx("span", { className: "sprout-sql-column-icon", children: join ? (_jsx(Link, { size: 12, role: "img", "aria-label": "Foreign key" })) : unique.has(field.id) ? (_jsx(Fingerprint, { size: 12, role: "img", "aria-label": "Unique" })) : null }), _jsx("span", { className: "sprout-sql-column-name", title: field.label, children: field.label }), _jsxs("span", { className: "sprout-sql-column-type", children: [type, !field.required && (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": "true", children: "?" }), _jsx("span", { className: "sprout-sql-sr-only", children: ", nullable" })] }))] })] }, field.id));
243
- })] }), composite.length > 0 && (_jsxs("div", { className: "sprout-sql-keys", children: [_jsx("p", { className: "sprout-sql-keys-title", children: "Unique keys" }), _jsx("ul", { className: "sprout-sql-keys-list", children: composite.map((key) => (_jsxs("li", { className: "sprout-sql-key", children: [_jsx(Fingerprint, { size: 12, "aria-hidden": "true" }), _jsx("span", { children: key.fieldIds
244
- .map((field) => labels.get(field) ?? field)
245
- .join(", ") })] }, key.id))) })] }))] }));
225
+ : undefined, children: [join && sideHandles('source', field.id), _jsx("span", { className: "sprout-sql-column-icon", children: join ? (_jsx(Link, { size: 12, role: "img", "aria-label": "Foreign key" })) : unique.has(field.id) ? (_jsx(Fingerprint, { size: 12, role: "img", "aria-label": "Unique" })) : null }), _jsx("span", { className: "sprout-sql-column-name", title: field.label, children: field.label }), _jsxs("span", { className: "sprout-sql-column-type", children: [type, !field.required && (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": "true", children: "?" }), _jsx("span", { className: "sprout-sql-sr-only", children: ", nullable" })] }))] })] }, field.id));
226
+ })] }), composite.length > 0 && (_jsxs("div", { className: "sprout-sql-keys", children: [_jsx("p", { className: "sprout-sql-keys-title", children: "Unique keys" }), _jsx("ul", { className: "sprout-sql-keys-list", children: composite.map(key => (_jsxs("li", { className: "sprout-sql-key", children: [_jsx(Fingerprint, { size: 12, "aria-hidden": "true" }), _jsx("span", { children: key.fieldIds.map(field => labels.get(field) ?? field).join(', ') })] }, key.id))) })] }))] }));
246
227
  }
247
228
  function GroupFrame({ data: { label, tone, count } }) {
248
- return (_jsx("section", { "data-slot": "sql-group", "data-tone": tone, "aria-label": `${label}, ${count} ${count === 1 ? "table" : "tables"}`, className: "sprout-sql-group", children: _jsxs("header", { className: "sprout-sql-group-label", children: [_jsx(Layers, { size: 14, "aria-hidden": "true" }), _jsx("span", { className: "sprout-sql-group-name", children: label }), _jsx("span", { className: "sprout-sql-group-count", children: count })] }) }));
229
+ return (_jsx("section", { "data-slot": "sql-group", "data-tone": tone, "aria-label": `${label}, ${count} ${count === 1 ? 'table' : 'tables'}`, className: "sprout-sql-group", children: _jsxs("header", { className: "sprout-sql-group-label", children: [_jsx(Layers, { size: 14, "aria-hidden": "true" }), _jsx("span", { className: "sprout-sql-group-name", children: label }), _jsx("span", { className: "sprout-sql-group-count", children: count })] }) }));
249
230
  }
250
231
  function MoreCard({ data: { tables } }) {
251
232
  const { expand } = useViewer();
252
- const names = tables.slice(0, 3).map((table) => table.label);
233
+ const names = tables.slice(0, 3).map(table => table.label);
253
234
  const rest = tables.length - names.length;
254
- return (_jsxs("div", { "data-slot": "sql-more", className: "sprout-sql-more", children: [sideHandles("target", "in"), sideHandles("source", "out"), _jsx("span", { "aria-hidden": "true", className: "sprout-sql-more-sheet" }), _jsx("span", { "aria-hidden": "true", className: "sprout-sql-more-sheet" }), _jsxs("button", { type: "button", className: "nodrag sprout-sql-more-button", onClick: expand, "aria-label": `Show ${tables.length} more ${tables.length === 1 ? "table" : "tables"}: ${tables.map((table) => table.label).join(", ")}`, children: [_jsxs("span", { className: "sprout-sql-more-count", children: ["+", tables.length, " ", tables.length === 1 ? "table" : "tables"] }), _jsxs("span", { className: "sprout-sql-more-names", children: [names.join(", "), rest > 0 && ` and ${rest} more`] }), _jsx("span", { className: "sprout-sql-more-action", children: "Show all" })] })] }));
235
+ return (_jsxs("div", { "data-slot": "sql-more", className: "sprout-sql-more", children: [sideHandles('target', 'in'), sideHandles('source', 'out'), _jsx("span", { "aria-hidden": "true", className: "sprout-sql-more-sheet" }), _jsx("span", { "aria-hidden": "true", className: "sprout-sql-more-sheet" }), _jsxs("button", { type: "button", className: "nodrag sprout-sql-more-button", onClick: expand, "aria-label": `Show ${tables.length} more ${tables.length === 1 ? 'table' : 'tables'}: ${tables.map(table => table.label).join(', ')}`, children: [_jsxs("span", { className: "sprout-sql-more-count", children: ["+", tables.length, " ", tables.length === 1 ? 'table' : 'tables'] }), _jsxs("span", { className: "sprout-sql-more-names", children: [names.join(', '), rest > 0 && ` and ${rest} more`] }), _jsx("span", { className: "sprout-sql-more-action", children: "Show all" })] })] }));
255
236
  }
256
237
  function handlePoint(node, type, id) {
257
- const handle = node.internals.handleBounds?.[type]?.find((candidate) => candidate.id === id);
238
+ const handle = node.internals.handleBounds?.[type]?.find(candidate => candidate.id === id);
258
239
  if (!handle)
259
240
  return null;
260
241
  return {
@@ -264,13 +245,13 @@ function handlePoint(node, type, id) {
264
245
  }
265
246
  /** A crow's foot for many, a bar for one, drawn outward from the card edge. */
266
247
  function endMark(x, y, side, many) {
267
- const out = side === "right" ? 1 : -1;
248
+ const out = side === 'right' ? 1 : -1;
268
249
  return many
269
250
  ? `M ${x + out * 12} ${y} L ${x} ${y - 6} M ${x + out * 12} ${y} L ${x} ${y + 6}`
270
251
  : `M ${x + out * 9} ${y - 5} L ${x + out * 9} ${y + 5}`;
271
252
  }
272
253
  // Picks the facing sides of the two cards on every render, so links stay tidy while tables are dragged.
273
- function JoinLine({ id, source, target, sourceHandleId, targetHandleId, data, }) {
254
+ function JoinLine({ id, source, target, sourceHandleId, targetHandleId, data }) {
274
255
  const from = useInternalNode(source);
275
256
  const to = useInternalNode(target);
276
257
  const viewer = useViewer();
@@ -280,17 +261,13 @@ function JoinLine({ id, source, target, sourceHandleId, targetHandleId, data, })
280
261
  const toLeft = to.internals.positionAbsolute.x;
281
262
  const fromRight = fromLeft + (from.measured.width ?? 0);
282
263
  const toRight = toLeft + (to.measured.width ?? 0);
283
- const [sourceSide, targetSide] = fromRight + 24 <= toLeft
284
- ? ["right", "left"]
285
- : toRight + 24 <= fromLeft
286
- ? ["left", "right"]
287
- : ["right", "right"];
288
- const base = (handle) => handle.slice(0, handle.lastIndexOf(":"));
289
- const start = handlePoint(from, "source", `${base(sourceHandleId)}:${sourceSide}`);
290
- const end = handlePoint(to, "target", `${base(targetHandleId)}:${targetSide}`);
264
+ const [sourceSide, targetSide] = fromRight + 24 <= toLeft ? ['right', 'left'] : toRight + 24 <= fromLeft ? ['left', 'right'] : ['right', 'right'];
265
+ const base = (handle) => handle.slice(0, handle.lastIndexOf(':'));
266
+ const start = handlePoint(from, 'source', `${base(sourceHandleId)}:${sourceSide}`);
267
+ const end = handlePoint(to, 'target', `${base(targetHandleId)}:${targetSide}`);
291
268
  if (!start || !end)
292
269
  return null;
293
- const position = (side) => side === "right" ? Position.Right : Position.Left;
270
+ const position = (side) => (side === 'right' ? Position.Right : Position.Left);
294
271
  const [path] = getSmoothStepPath({
295
272
  sourceX: start.x,
296
273
  sourceY: start.y,
@@ -302,7 +279,7 @@ function JoinLine({ id, source, target, sourceHandleId, targetHandleId, data, })
302
279
  offset: 28,
303
280
  });
304
281
  const active = viewer.activeEdges.has(id);
305
- return (_jsx("path", { d: `${path} ${endMark(start.x, start.y, sourceSide, data.sourceMany)} ${endMark(end.x, end.y, targetSide, data.targetMany)}`, className: "react-flow__edge-path sprout-sql-join", "data-active": active ? "" : undefined, "data-dimmed": viewer.focus && !active ? "" : undefined }));
282
+ return (_jsx("path", { d: `${path} ${endMark(start.x, start.y, sourceSide, data.sourceMany)} ${endMark(end.x, end.y, targetSide, data.targetMany)}`, className: "react-flow__edge-path sprout-sql-join", "data-active": active ? '' : undefined, "data-dimmed": viewer.focus && !active ? '' : undefined }));
306
283
  }
307
284
  const nodeTypes = { table: TableCard, group: GroupFrame, more: MoreCard };
308
285
  const edgeTypes = { join: JoinLine };
@@ -313,9 +290,7 @@ function ViewerFlow({ layoutNodes, edges, direction, label, hintId, expanded, se
313
290
  const [hovered, setHovered] = useState(null);
314
291
  const [pinned, setPinned] = useState(null);
315
292
  const focus = hovered ?? pinned;
316
- const pin = useCallback((next) => setPinned((current) => current?.table === next.table && current.field === next.field
317
- ? null
318
- : next), []);
293
+ const pin = useCallback((next) => setPinned(current => (current?.table === next.table && current.field === next.field ? null : next)), []);
319
294
  const state = useMemo(() => {
320
295
  const activeEdges = new Set();
321
296
  const related = new Set();
@@ -341,69 +316,65 @@ function ViewerFlow({ layoutNodes, edges, direction, label, hintId, expanded, se
341
316
  };
342
317
  }, [focus, edges, pin, setExpanded]);
343
318
  const shownEdges = useMemo(() => state.activeEdges.size
344
- ? edges.map((edge) => state.activeEdges.has(edge.id) ? { ...edge, zIndex: 1000 } : edge)
319
+ ? edges.map(edge => (state.activeEdges.has(edge.id) ? { ...edge, zIndex: 1000 } : edge))
345
320
  : edges, [edges, state.activeEdges]);
346
321
  // Phones fit the first block to the width and let people pan down; wider panes fit everything.
347
- const fitFirst = useMemo(() => direction === "vertical" && layoutNodes[0]
322
+ const fitFirst = useMemo(() => direction === 'vertical' && layoutNodes[0]
348
323
  ? { padding: 0.06, maxZoom: 1, nodes: [{ id: layoutNodes[0].id }] }
349
324
  : fitAll, [direction, layoutNodes]);
350
325
  const keyboardView = useKeyboardView(fitAll);
351
326
  const onKeyDown = (event) => {
352
327
  const target = event.target;
353
- const id = target.dataset["id"];
354
- if ((event.key === "Enter" || event.key === " ") &&
355
- target.classList.contains("react-flow__node-table") &&
356
- id) {
328
+ const id = target.dataset['id'];
329
+ if ((event.key === 'Enter' || event.key === ' ') && target.classList.contains('react-flow__node-table') && id) {
357
330
  event.preventDefault();
358
331
  pin({ table: id });
359
332
  return;
360
333
  }
361
- if (event.key === "Escape" && pinned) {
334
+ if (event.key === 'Escape' && pinned) {
362
335
  setPinned(null);
363
336
  return;
364
337
  }
365
338
  keyboardView(event);
366
339
  };
367
340
  const onFocus = (event) => {
368
- const id = event.target.dataset["id"];
369
- if (event.target.classList.contains("react-flow__node-table") && id)
341
+ const id = event.target.dataset['id'];
342
+ if (event.target.classList.contains('react-flow__node-table') && id)
370
343
  setHovered({ table: id });
371
344
  };
372
345
  const onNodeMouseEnter = (_, node) => {
373
- if (node.type === "table")
346
+ if (node.type === 'table')
374
347
  setHovered({ table: node.id });
375
348
  };
376
349
  const onNodeClick = (_, node) => {
377
- if (node.type === "table")
350
+ if (node.type === 'table')
378
351
  pin({ table: node.id });
379
352
  };
380
- return (_jsx(ViewerContext.Provider, { value: state, children: _jsxs(ReactFlow, { className: "sprout-schema-flow sprout-sql-flow", "data-slot": "sql-viewer-viewport", "data-focus": focus ? "" : undefined, "aria-label": label, "aria-describedby": hintId, tabIndex: 0, onKeyDown: onKeyDown, onFocus: onFocus, onBlur: () => setHovered(null), nodes: nodes, edges: shownEdges, onNodesChange: onNodesChange, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onNodeMouseEnter: onNodeMouseEnter, onNodeClick: onNodeClick, onPaneClick: () => setPinned(null), fitView: true, fitViewOptions: fitFirst, minZoom: flowMinZoom, maxZoom: flowMaxZoom, nodesConnectable: false, elementsSelectable: false, edgesFocusable: false, ariaLabelConfig: {
381
- "node.a11yDescription.default": keyboardHint,
382
- "node.a11yDescription.keyboardDisabled": keyboardHint,
353
+ return (_jsx(ViewerContext.Provider, { value: state, children: _jsxs(ReactFlow, { className: "sprout-schema-flow sprout-sql-flow", "data-slot": "sql-viewer-viewport", "data-focus": focus ? '' : undefined, "aria-label": label, "aria-describedby": hintId, tabIndex: 0, onKeyDown: onKeyDown, onFocus: onFocus, onBlur: () => setHovered(null), nodes: nodes, edges: shownEdges, onNodesChange: onNodesChange, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onNodeMouseEnter: onNodeMouseEnter, onNodeClick: onNodeClick, onPaneClick: () => setPinned(null), fitView: true, fitViewOptions: fitFirst, minZoom: flowMinZoom, maxZoom: flowMaxZoom, nodesConnectable: false, elementsSelectable: false, edgesFocusable: false, ariaLabelConfig: {
354
+ 'node.a11yDescription.default': keyboardHint,
355
+ 'node.a11yDescription.keyboardDisabled': keyboardHint,
383
356
  }, proOptions: { hideAttribution: true }, children: [_jsx(Background, { gap: 16, size: 1 }), _jsx(FitOnResize, { nodes: layoutNodes, fit: fitFirst }), collapsible && expanded && (_jsx(Panel, { position: "top-left", "data-slot": "sql-viewer-collapse", children: _jsxs(Button, { variant: "secondary", size: "sm", onClick: () => {
384
357
  setPinned(null);
385
358
  setExpanded(false);
386
359
  }, children: ["Show ", maxVisible, " tables"] }) })), state.activeEdges.size > 0 && (_jsxs(Panel, { position: "bottom-left", "data-slot": "sql-viewer-joins", "aria-hidden": "true", className: "sprout-sql-joins", children: [edges
387
- .filter((edge) => state.activeEdges.has(edge.id))
360
+ .filter(edge => state.activeEdges.has(edge.id))
388
361
  .slice(0, 3)
389
- .map((edge) => (_jsx("code", { className: "sprout-sql-join-text", children: edge.data.join }, edge.id))), state.activeEdges.size > 3 && (_jsxs("span", { className: "sprout-sql-joins-more", children: ["and ", state.activeEdges.size - 3, " more"] }))] })), _jsx(ZoomControls, { position: direction === "vertical" ? "top-right" : "bottom-right", fit: fitAll, className: "sprout-schema-controls", slot: "sql-viewer-controls" })] }) }));
362
+ .map(edge => (_jsx("code", { className: "sprout-sql-join-text", children: edge.data.join }, edge.id))), state.activeEdges.size > 3 && (_jsxs("span", { className: "sprout-sql-joins-more", children: ["and ", state.activeEdges.size - 3, " more"] }))] })), _jsx(ZoomControls, { position: direction === 'vertical' ? 'top-right' : 'bottom-right', fit: fitAll, className: "sprout-schema-controls", slot: "sql-viewer-controls" })] }) }));
390
363
  }
391
364
  /**
392
365
  * A pan-and-zoom map of SQL tables, their columns and keys, and the joins
393
366
  * between them. Hover or pin a table or a foreign key to trace its joins.
394
367
  */
395
- export function SqlViewer({ tables, label, groups, maxVisible = 4, layout = "auto", className, ...props }) {
368
+ export function SqlViewer({ tables, label, groups, maxVisible = 4, layout = 'auto', className, ...props }) {
396
369
  const mobile = useViewportMobile();
397
- const direction = layout === "auto" ? (mobile ? "vertical" : "horizontal") : layout;
370
+ const direction = layout === 'auto' ? (mobile ? 'vertical' : 'horizontal') : layout;
398
371
  const hintId = useId();
399
372
  const [expanded, setExpanded] = useState(false);
400
373
  const limit = Math.max(1, Math.floor(maxVisible));
401
374
  const collapsible = tables.length > limit;
402
- const [visible, hidden] = useMemo(() => collapsible && !expanded
403
- ? [tables.slice(0, limit), tables.slice(limit)]
404
- : [tables, []], [tables, limit, collapsible, expanded]);
375
+ const [visible, hidden] = useMemo(() => (collapsible && !expanded ? [tables.slice(0, limit), tables.slice(limit)] : [tables, []]), [tables, limit, collapsible, expanded]);
405
376
  const layoutNodes = useMemo(() => arrange(visible, hidden, groups, direction), [visible, hidden, groups, direction]);
406
377
  const edges = useMemo(() => joins(visible, hidden), [visible, hidden]);
407
378
  const descriptions = joins(tables, []);
408
- return (_jsxs("div", { ...props, role: "figure", "aria-label": label, "data-slot": "sql-viewer", "data-layout": direction, className: cn("sprout-sql-viewer", className), children: [_jsx("p", { id: hintId, className: "sprout-sql-sr-only", children: keyboardHint }), descriptions.length > 0 && (_jsx("ul", { "aria-label": "Joins", className: "sprout-sql-sr-only", children: descriptions.map((edge) => (_jsx("li", { children: edge.data.description }, edge.id))) })), tables.length === 0 ? (_jsx("p", { className: "sprout-sql-empty", children: "No tables to show" })) : (_jsx(ReactFlowProvider, { children: _jsx(ViewerFlow, { layoutNodes: layoutNodes, edges: edges, direction: direction, label: label, hintId: hintId, expanded: expanded, setExpanded: setExpanded, collapsible: collapsible, maxVisible: limit }) }, direction))] }));
379
+ return (_jsxs("div", { ...props, role: "figure", "aria-label": label, "data-slot": "sql-viewer", "data-layout": direction, className: cn('sprout-sql-viewer', className), children: [_jsx("p", { id: hintId, className: "sprout-sql-sr-only", children: keyboardHint }), descriptions.length > 0 && (_jsx("ul", { "aria-label": "Joins", className: "sprout-sql-sr-only", children: descriptions.map(edge => (_jsx("li", { children: edge.data.description }, edge.id))) })), tables.length === 0 ? (_jsx("p", { className: "sprout-sql-empty", children: "No tables to show" })) : (_jsx(ReactFlowProvider, { children: _jsx(ViewerFlow, { layoutNodes: layoutNodes, edges: edges, direction: direction, label: label, hintId: hintId, expanded: expanded, setExpanded: setExpanded, collapsible: collapsible, maxVisible: limit }) }, direction))] }));
409
380
  }
@@ -1,6 +1,6 @@
1
- import { type SampleWindowProps } from "./state-sample.js";
1
+ import { type SampleWindowProps } from './state-sample.js';
2
2
  /** Pass-through props for the outer sample window. */
3
- export type StatePanelSampleProps = Omit<SampleWindowProps, "icon" | "trail" | "tabs" | "children">;
3
+ export type StatePanelSampleProps = Omit<SampleWindowProps, 'icon' | 'trail' | 'tabs' | 'children'>;
4
4
  export declare function ChatsSample(props: StatePanelSampleProps): import("react").JSX.Element;
5
5
  export declare function FilesSample(props: StatePanelSampleProps): import("react").JSX.Element;
6
6
  export declare function AgentsSample(props: StatePanelSampleProps): import("react").JSX.Element;