@vllnt/ui 0.1.4 → 0.1.7-canary.2c4792f

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 (225) hide show
  1. package/dist/components/accordion/accordion.js +172 -0
  2. package/dist/components/accordion/index.js +12 -0
  3. package/dist/components/alert/alert.js +53 -0
  4. package/dist/components/alert/index.js +7 -0
  5. package/dist/components/alert-dialog/alert-dialog.js +117 -0
  6. package/dist/components/alert-dialog/index.js +26 -0
  7. package/dist/components/aspect-ratio/aspect-ratio.js +6 -0
  8. package/dist/components/aspect-ratio/index.js +4 -0
  9. package/dist/components/avatar/avatar.js +43 -0
  10. package/dist/components/avatar/index.js +6 -0
  11. package/dist/components/badge/badge.js +26 -0
  12. package/dist/components/badge/index.js +5 -0
  13. package/dist/components/blog-card/blog-card.js +50 -0
  14. package/dist/components/blog-card/index.js +5 -0
  15. package/dist/components/breadcrumb/breadcrumb.js +61 -0
  16. package/dist/components/breadcrumb/index.js +4 -0
  17. package/dist/components/button/button.js +48 -0
  18. package/dist/components/button/index.js +5 -0
  19. package/dist/components/calendar/calendar.js +71 -0
  20. package/dist/components/calendar/index.js +4 -0
  21. package/dist/components/callout/callout.js +59 -0
  22. package/dist/components/callout/index.js +4 -0
  23. package/dist/components/card/card.js +64 -0
  24. package/dist/components/card/index.js +16 -0
  25. package/dist/components/carousel/carousel.js +239 -0
  26. package/dist/components/carousel/index.js +14 -0
  27. package/dist/components/category-filter/category-filter.js +34 -0
  28. package/dist/components/category-filter/index.js +4 -0
  29. package/dist/components/chart/area-chart.js +99 -0
  30. package/dist/components/chart/bar-chart.js +80 -0
  31. package/dist/components/chart/index.js +3 -0
  32. package/dist/components/chart/line-chart.js +97 -0
  33. package/dist/components/checkbox/checkbox.js +28 -0
  34. package/dist/components/checkbox/index.js +4 -0
  35. package/dist/components/checklist/checklist.js +181 -0
  36. package/dist/components/checklist/index.js +6 -0
  37. package/dist/components/code-block/code-block.js +126 -0
  38. package/dist/components/code-block/index.js +4 -0
  39. package/dist/components/code-playground/code-playground.js +86 -0
  40. package/dist/components/code-playground/index.js +8 -0
  41. package/dist/components/collapsible/collapsible.js +10 -0
  42. package/dist/components/collapsible/index.js +10 -0
  43. package/dist/components/command/command.js +123 -0
  44. package/dist/components/command/index.js +22 -0
  45. package/dist/components/comparison/comparison.js +121 -0
  46. package/dist/components/comparison/index.js +8 -0
  47. package/dist/components/completion-dialog/completion-dialog.js +173 -0
  48. package/dist/components/completion-dialog/index.js +6 -0
  49. package/dist/components/content-intro/content-intro.js +144 -0
  50. package/dist/components/content-intro/index.js +6 -0
  51. package/dist/components/context-menu/context-menu.js +154 -0
  52. package/dist/components/context-menu/index.js +34 -0
  53. package/dist/components/cookie-consent/cookie-consent.js +175 -0
  54. package/dist/components/cookie-consent/index.js +8 -0
  55. package/dist/components/dialog/dialog.js +105 -0
  56. package/dist/components/dialog/index.js +24 -0
  57. package/dist/components/drawer/drawer.js +102 -0
  58. package/dist/components/drawer/index.js +24 -0
  59. package/dist/components/dropdown-menu/dropdown-menu.js +151 -0
  60. package/dist/components/dropdown-menu/index.js +34 -0
  61. package/dist/components/exercise/exercise.js +112 -0
  62. package/dist/components/exercise/index.js +4 -0
  63. package/dist/components/faq/faq.js +56 -0
  64. package/dist/components/faq/index.js +5 -0
  65. package/dist/components/filter-bar/filter-bar.js +244 -0
  66. package/dist/components/filter-bar/index.js +6 -0
  67. package/dist/components/floating-action-button/floating-action-button.js +35 -0
  68. package/dist/components/floating-action-button/index.js +6 -0
  69. package/dist/components/flow-diagram/flow-canvas.js +109 -0
  70. package/dist/components/flow-diagram/flow-controls.js +140 -0
  71. package/dist/components/flow-diagram/flow-diagram.js +114 -0
  72. package/dist/components/flow-diagram/flow-error-boundary.js +63 -0
  73. package/dist/components/flow-diagram/flow-fullscreen.js +58 -0
  74. package/dist/components/flow-diagram/index.js +12 -0
  75. package/dist/components/flow-diagram/types.js +0 -0
  76. package/dist/components/flow-diagram/use-flow-diagram.js +146 -0
  77. package/dist/components/horizontal-scroll-row/horizontal-scroll-row.js +66 -0
  78. package/dist/components/horizontal-scroll-row/index.js +6 -0
  79. package/dist/components/hover-card/hover-card.js +26 -0
  80. package/dist/components/hover-card/index.js +6 -0
  81. package/dist/components/index.js +641 -0
  82. package/dist/components/inline-input/index.js +4 -0
  83. package/dist/components/inline-input/inline-input.js +42 -0
  84. package/dist/components/input/index.js +4 -0
  85. package/dist/components/input/input.js +23 -0
  86. package/dist/components/input-otp/index.js +12 -0
  87. package/dist/components/input-otp/input-otp.js +54 -0
  88. package/dist/components/key-concept/index.js +8 -0
  89. package/dist/components/key-concept/key-concept.js +79 -0
  90. package/dist/components/keyboard-shortcuts-help/index.js +6 -0
  91. package/dist/components/keyboard-shortcuts-help/keyboard-shortcuts-help.js +121 -0
  92. package/dist/components/label/index.js +4 -0
  93. package/dist/components/label/label.js +21 -0
  94. package/dist/components/lang-provider/index.js +4 -0
  95. package/dist/components/lang-provider/lang-provider.js +18 -0
  96. package/dist/components/learning-objectives/index.js +10 -0
  97. package/dist/components/learning-objectives/learning-objectives.js +76 -0
  98. package/dist/components/mdx-content/index.js +4 -0
  99. package/dist/components/mdx-content/mdx-content.js +151 -0
  100. package/dist/components/menubar/index.js +36 -0
  101. package/dist/components/menubar/menubar.js +183 -0
  102. package/dist/components/model-selector/index.js +6 -0
  103. package/dist/components/model-selector/model-selector.js +374 -0
  104. package/dist/components/navbar-saas/index.js +6 -0
  105. package/dist/components/navbar-saas/navbar-saas.js +68 -0
  106. package/dist/components/navbar-saas/use-mobile.js +19 -0
  107. package/dist/components/navigation-menu/index.js +22 -0
  108. package/dist/components/navigation-menu/navigation-menu.js +108 -0
  109. package/dist/components/pagination/index.js +4 -0
  110. package/dist/components/pagination/pagination.js +44 -0
  111. package/dist/components/popover/index.js +12 -0
  112. package/dist/components/popover/popover.js +28 -0
  113. package/dist/components/pro-tip/index.js +8 -0
  114. package/dist/components/pro-tip/pro-tip.js +139 -0
  115. package/dist/components/profile-section/index.js +4 -0
  116. package/dist/components/profile-section/profile-section.js +45 -0
  117. package/dist/components/progress-bar/index.js +4 -0
  118. package/dist/components/progress-bar/progress-bar.js +56 -0
  119. package/dist/components/progress-card/index.js +6 -0
  120. package/dist/components/progress-card/progress-card.js +71 -0
  121. package/dist/components/quiz/index.js +4 -0
  122. package/dist/components/quiz/quiz.js +210 -0
  123. package/dist/components/radio-group/index.js +5 -0
  124. package/dist/components/radio-group/radio-group.js +36 -0
  125. package/dist/components/resizable/index.js +10 -0
  126. package/dist/components/resizable/resizable.js +39 -0
  127. package/dist/components/scroll-area/index.js +5 -0
  128. package/dist/components/scroll-area/scroll-area.js +39 -0
  129. package/dist/components/search-bar/index.js +4 -0
  130. package/dist/components/search-bar/search-bar.js +122 -0
  131. package/dist/components/search-dialog/index.js +4 -0
  132. package/dist/components/search-dialog/search-dialog.js +102 -0
  133. package/dist/components/select/index.js +24 -0
  134. package/dist/components/select/select.js +125 -0
  135. package/dist/components/separator/index.js +4 -0
  136. package/dist/components/separator/separator.js +25 -0
  137. package/dist/components/share-dialog/index.js +6 -0
  138. package/dist/components/share-dialog/share-dialog.js +121 -0
  139. package/dist/components/share-section/index.js +6 -0
  140. package/dist/components/share-section/share-section.js +57 -0
  141. package/dist/components/sheet/index.js +24 -0
  142. package/dist/components/sheet/sheet.js +116 -0
  143. package/dist/components/sidebar/index.js +4 -0
  144. package/dist/components/sidebar/sidebar.js +188 -0
  145. package/dist/components/sidebar-provider/index.js +5 -0
  146. package/dist/components/sidebar-provider/sidebar-provider.js +25 -0
  147. package/dist/components/sidebar-toggle/index.js +4 -0
  148. package/dist/components/sidebar-toggle/sidebar-toggle.js +36 -0
  149. package/dist/components/skeleton/index.js +4 -0
  150. package/dist/components/skeleton/skeleton.js +17 -0
  151. package/dist/components/slider/index.js +4 -0
  152. package/dist/components/slider/slider.js +24 -0
  153. package/dist/components/slideshow/index.js +6 -0
  154. package/dist/components/slideshow/slideshow.js +440 -0
  155. package/dist/components/social-fab/index.js +6 -0
  156. package/dist/components/social-fab/social-fab.js +211 -0
  157. package/dist/components/social-fab/use-social-fab.js +111 -0
  158. package/dist/components/spinner/index.js +4 -0
  159. package/dist/components/spinner/spinner.js +23 -0
  160. package/dist/components/step-by-step/index.js +8 -0
  161. package/dist/components/step-by-step/step-by-step.js +194 -0
  162. package/dist/components/step-navigation/index.js +4 -0
  163. package/dist/components/step-navigation/step-navigation.js +119 -0
  164. package/dist/components/switch/index.js +4 -0
  165. package/dist/components/switch/switch.js +28 -0
  166. package/dist/components/table/index.js +20 -0
  167. package/dist/components/table/table.js +87 -0
  168. package/dist/components/table-of-contents/index.js +4 -0
  169. package/dist/components/table-of-contents/table-of-contents.js +71 -0
  170. package/dist/components/table-of-contents-panel/index.js +6 -0
  171. package/dist/components/table-of-contents-panel/table-of-contents-panel.js +202 -0
  172. package/dist/components/tabs/index.js +12 -0
  173. package/dist/components/tabs/tabs.js +84 -0
  174. package/dist/components/terminal/index.js +8 -0
  175. package/dist/components/terminal/terminal.js +119 -0
  176. package/dist/components/textarea/index.js +4 -0
  177. package/dist/components/textarea/textarea.js +22 -0
  178. package/dist/components/theme-provider/index.js +4 -0
  179. package/dist/components/theme-provider/theme-provider.js +11 -0
  180. package/dist/components/theme-toggle/index.js +4 -0
  181. package/dist/components/theme-toggle/theme-toggle.js +170 -0
  182. package/dist/components/thinking-block/index.js +4 -0
  183. package/dist/components/thinking-block/thinking-block.js +56 -0
  184. package/dist/components/tldr-section/index.js +4 -0
  185. package/dist/components/tldr-section/tldr-section.js +101 -0
  186. package/dist/components/toast/index.js +18 -0
  187. package/dist/components/toast/toast.js +84 -0
  188. package/dist/components/toast/toaster.js +38 -0
  189. package/dist/components/toggle/index.js +5 -0
  190. package/dist/components/toggle/toggle.js +39 -0
  191. package/dist/components/toggle-group/index.js +5 -0
  192. package/dist/components/toggle-group/toggle-group.js +46 -0
  193. package/dist/components/tooltip/index.js +12 -0
  194. package/dist/components/tooltip/tooltip.js +27 -0
  195. package/dist/components/truncated-text/index.js +4 -0
  196. package/dist/components/truncated-text/truncated-text.js +25 -0
  197. package/dist/components/tutorial-card/index.js +6 -0
  198. package/dist/components/tutorial-card/tutorial-card.js +78 -0
  199. package/dist/components/tutorial-complete/index.js +6 -0
  200. package/dist/components/tutorial-complete/tutorial-complete.js +134 -0
  201. package/dist/components/tutorial-filters/index.js +6 -0
  202. package/dist/components/tutorial-filters/tutorial-filters.js +205 -0
  203. package/dist/components/tutorial-intro-content/index.js +6 -0
  204. package/dist/components/tutorial-intro-content/tutorial-intro-content.js +141 -0
  205. package/dist/components/tutorial-mdx/index.js +8 -0
  206. package/dist/components/tutorial-mdx/tutorial-mdx.js +219 -0
  207. package/dist/components/video-embed/index.js +4 -0
  208. package/dist/components/video-embed/video-embed.js +77 -0
  209. package/dist/components/view-switcher/index.js +6 -0
  210. package/dist/components/view-switcher/view-switcher.js +92 -0
  211. package/dist/index.d.ts +44 -2
  212. package/dist/index.js +14 -8556
  213. package/dist/lib/types.js +11 -0
  214. package/dist/lib/use-debounce.js +17 -0
  215. package/dist/lib/use-horizontal-scroll.js +60 -0
  216. package/dist/lib/use-mounted.js +17 -0
  217. package/dist/lib/utils.js +8 -0
  218. package/dist/tailwind-preset.d.ts +5 -0
  219. package/dist/tailwind-preset.js +9 -10
  220. package/dist/types/content.js +0 -0
  221. package/dist/types/index.js +0 -0
  222. package/package.json +42 -23
  223. package/LICENSE +0 -21
  224. package/dist/chunk-XRV5RSYH.js +0 -569
  225. package/dist/flow-diagram-N3EHM6VB.js +0 -2
@@ -1,569 +0,0 @@
1
- "use client";
2
- import '@xyflow/react/dist/style.css';
3
- import { memo, useEffect, useCallback, Component, useState } from 'react';
4
- import { ReactFlow, Background, BackgroundVariant, ReactFlowProvider, useReactFlow, getNodesBounds, getViewportForBounds } from '@xyflow/react';
5
- import { clsx } from 'clsx';
6
- import { twMerge } from 'tailwind-merge';
7
- import { useTheme } from 'next-themes';
8
- import { Plus, Minus, Move, Maximize2, X, Copy, Check, Loader2, AlertTriangle, RefreshCw } from 'lucide-react';
9
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
10
- import { createPortal } from 'react-dom';
11
- import { toPng } from 'html-to-image';
12
-
13
- // src/components/flow-diagram/flow-diagram.tsx
14
- function cn(...inputs) {
15
- return twMerge(clsx(inputs));
16
- }
17
- var BUTTON_CLASS = "flex h-8 w-8 items-center justify-center rounded hover:bg-muted transition-colors disabled:opacity-50 disabled:cursor-not-allowed";
18
- function ControlButton({
19
- disabled,
20
- icon,
21
- label,
22
- onClick,
23
- title
24
- }) {
25
- return /* @__PURE__ */ jsx(
26
- "button",
27
- {
28
- "aria-label": label,
29
- className: BUTTON_CLASS,
30
- disabled,
31
- onClick,
32
- title,
33
- type: "button",
34
- children: icon
35
- }
36
- );
37
- }
38
- function getCopyIcon(status) {
39
- switch (status) {
40
- case "copying":
41
- return /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" });
42
- case "success":
43
- return /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-green-500" });
44
- case "error":
45
- return /* @__PURE__ */ jsx(X, { className: "h-4 w-4 text-destructive" });
46
- case "idle":
47
- case void 0:
48
- return /* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" });
49
- }
50
- }
51
- function getCopyTitle(status) {
52
- switch (status) {
53
- case "copying":
54
- return "Copying...";
55
- case "success":
56
- return "Copied!";
57
- case "error":
58
- return "Copy failed";
59
- case "idle":
60
- case void 0:
61
- return "Copy as image";
62
- }
63
- }
64
- var FlowControls = memo(function FlowControls2({
65
- className,
66
- copyStatus,
67
- onCopy,
68
- onFitView,
69
- onFullscreen,
70
- onZoomIn,
71
- onZoomOut,
72
- showCopy = false,
73
- showFullscreen = false
74
- }) {
75
- return /* @__PURE__ */ jsxs(
76
- "div",
77
- {
78
- className: cn(
79
- "absolute bottom-4 left-4 z-10 flex flex-col gap-1 rounded-md border border-border bg-background/90 p-1 backdrop-blur-sm",
80
- className
81
- ),
82
- children: [
83
- /* @__PURE__ */ jsx(
84
- ControlButton,
85
- {
86
- icon: /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
87
- label: "Zoom in",
88
- onClick: onZoomIn,
89
- title: "Zoom in"
90
- }
91
- ),
92
- /* @__PURE__ */ jsx(
93
- ControlButton,
94
- {
95
- icon: /* @__PURE__ */ jsx(Minus, { className: "h-4 w-4" }),
96
- label: "Zoom out",
97
- onClick: onZoomOut,
98
- title: "Zoom out"
99
- }
100
- ),
101
- /* @__PURE__ */ jsx("div", { className: "h-px bg-border" }),
102
- /* @__PURE__ */ jsx(
103
- ControlButton,
104
- {
105
- icon: /* @__PURE__ */ jsx(Move, { className: "h-4 w-4" }),
106
- label: "Fit view",
107
- onClick: onFitView,
108
- title: "Fit view"
109
- }
110
- ),
111
- showCopy && onCopy ? /* @__PURE__ */ jsxs(Fragment, { children: [
112
- /* @__PURE__ */ jsx("div", { className: "h-px bg-border" }),
113
- /* @__PURE__ */ jsx(
114
- ControlButton,
115
- {
116
- disabled: copyStatus === "copying",
117
- icon: getCopyIcon(copyStatus),
118
- label: getCopyTitle(copyStatus),
119
- onClick: onCopy,
120
- title: getCopyTitle(copyStatus)
121
- }
122
- )
123
- ] }) : null,
124
- showFullscreen && onFullscreen ? /* @__PURE__ */ jsxs(Fragment, { children: [
125
- /* @__PURE__ */ jsx("div", { className: "h-px bg-border" }),
126
- /* @__PURE__ */ jsx(
127
- ControlButton,
128
- {
129
- icon: /* @__PURE__ */ jsx(Maximize2, { className: "h-4 w-4" }),
130
- label: "Fullscreen",
131
- onClick: onFullscreen,
132
- title: "Toggle fullscreen"
133
- }
134
- )
135
- ] }) : null
136
- ]
137
- }
138
- );
139
- });
140
- var REACT_FLOW_CLASS = [
141
- // Node container styling — no !important on bg/color so inline styles take precedence
142
- "[&_.react-flow__node]:rounded-md",
143
- "[&_.react-flow__node]:border",
144
- "[&_.react-flow__node]:border-border",
145
- "[&_.react-flow__node]:bg-card",
146
- "[&_.react-flow__node]:px-4",
147
- "[&_.react-flow__node]:py-2",
148
- "[&_.react-flow__node]:shadow-sm",
149
- // Node text styling — defaults, overridable by inline style.color
150
- "[&_.react-flow__node]:text-sm",
151
- "[&_.react-flow__node]:text-card-foreground",
152
- "[&_.react-flow__node]:font-medium",
153
- // Edge styling
154
- "[&_.react-flow__edge-path]:!stroke-muted-foreground",
155
- "[&_.react-flow__edge-path]:!stroke-2",
156
- // Arrow marker styling
157
- "[&_.react-flow__arrowhead_polyline]:!fill-muted-foreground",
158
- "[&_.react-flow__arrowhead_polyline]:!stroke-muted-foreground"
159
- ].join(" ");
160
- var FlowCanvas = memo(function FlowCanvas2({
161
- allowCopy,
162
- allowFullscreen,
163
- className,
164
- copyStatus,
165
- edges,
166
- fitView,
167
- fitViewOptions,
168
- height,
169
- isFullscreen,
170
- nodes,
171
- onCopy,
172
- onFitView,
173
- onFullscreen,
174
- onNodeClick,
175
- onZoomIn,
176
- onZoomOut,
177
- showControls,
178
- title
179
- }) {
180
- const { resolvedTheme } = useTheme();
181
- const colorMode = resolvedTheme === "dark" ? "dark" : "light";
182
- return /* @__PURE__ */ jsxs("div", { className: cn("relative w-full", className), children: [
183
- title ? /* @__PURE__ */ jsx("div", { className: "mb-2 text-sm font-medium text-foreground", children: title }) : null,
184
- /* @__PURE__ */ jsx(
185
- "div",
186
- {
187
- className: "relative w-full rounded-lg border border-border bg-background overflow-hidden",
188
- style: { height: isFullscreen ? "100%" : height },
189
- children: /* @__PURE__ */ jsxs(
190
- ReactFlow,
191
- {
192
- className: REACT_FLOW_CLASS,
193
- colorMode,
194
- edges,
195
- elementsSelectable: false,
196
- fitView,
197
- fitViewOptions: fitViewOptions ?? { padding: 0.2 },
198
- nodes,
199
- nodesConnectable: false,
200
- nodesDraggable: false,
201
- onNodeClick,
202
- panOnScroll: true,
203
- proOptions: { hideAttribution: true },
204
- zoomOnScroll: true,
205
- children: [
206
- /* @__PURE__ */ jsx(
207
- Background,
208
- {
209
- className: "!bg-background [&>pattern>circle]:fill-muted-foreground/20",
210
- gap: 16,
211
- size: 1,
212
- variant: BackgroundVariant.Dots
213
- }
214
- ),
215
- showControls ? /* @__PURE__ */ jsx(
216
- FlowControls,
217
- {
218
- copyStatus,
219
- onCopy,
220
- onFitView,
221
- onFullscreen,
222
- onZoomIn,
223
- onZoomOut,
224
- showCopy: allowCopy,
225
- showFullscreen: allowFullscreen
226
- }
227
- ) : null
228
- ]
229
- }
230
- )
231
- }
232
- )
233
- ] });
234
- });
235
- var FlowErrorBoundary = class extends Component {
236
- constructor(props) {
237
- super(props);
238
- this.handleRetry = () => {
239
- this.setState({ error: null, hasError: false });
240
- };
241
- this.state = { error: null, hasError: false };
242
- }
243
- static getDerivedStateFromError(error) {
244
- return { error, hasError: true };
245
- }
246
- componentDidCatch(error, errorInfo) {
247
- console.error("[FlowDiagram] Error caught by boundary:", error, errorInfo);
248
- this.props.onError?.(error, errorInfo);
249
- }
250
- render() {
251
- const { children, className, fallback, height = 400 } = this.props;
252
- const { error, hasError } = this.state;
253
- if (hasError) {
254
- if (fallback) {
255
- return fallback;
256
- }
257
- return /* @__PURE__ */ jsxs(
258
- "div",
259
- {
260
- className: cn(
261
- "flex flex-col items-center justify-center gap-4 rounded-lg border border-border bg-muted/50 p-8 text-center",
262
- className
263
- ),
264
- style: { height },
265
- children: [
266
- /* @__PURE__ */ jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-destructive/10", children: /* @__PURE__ */ jsx(AlertTriangle, { className: "h-6 w-6 text-destructive" }) }),
267
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
268
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-foreground", children: "Failed to render diagram" }),
269
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: error?.message ?? "An unexpected error occurred while rendering the flow diagram." })
270
- ] }),
271
- /* @__PURE__ */ jsxs(
272
- "button",
273
- {
274
- className: "inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90",
275
- onClick: this.handleRetry,
276
- type: "button",
277
- children: [
278
- /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }),
279
- "Try again"
280
- ]
281
- }
282
- )
283
- ]
284
- }
285
- );
286
- }
287
- return children;
288
- }
289
- };
290
- var FlowFullscreen = memo(function FlowFullscreen2({
291
- children,
292
- isOpen,
293
- onClose
294
- }) {
295
- useEffect(() => {
296
- if (!isOpen) return;
297
- const handleKeyDown = (e) => {
298
- if (e.key === "Escape") {
299
- onClose();
300
- }
301
- };
302
- document.addEventListener("keydown", handleKeyDown);
303
- return () => {
304
- document.removeEventListener("keydown", handleKeyDown);
305
- };
306
- }, [isOpen, onClose]);
307
- if (!isOpen) return null;
308
- if (typeof document === "undefined") return null;
309
- return createPortal(
310
- /* @__PURE__ */ jsxs(
311
- "div",
312
- {
313
- "aria-label": "Flow diagram fullscreen view",
314
- "aria-modal": "true",
315
- className: cn(
316
- "fixed inset-0 z-[9999] flex flex-col bg-background",
317
- "animate-in fade-in duration-200"
318
- ),
319
- role: "dialog",
320
- children: [
321
- /* @__PURE__ */ jsx("div", { className: "flex h-12 items-center justify-end border-b border-border px-4", children: /* @__PURE__ */ jsx(
322
- "button",
323
- {
324
- "aria-label": "Close fullscreen",
325
- className: "flex h-8 w-8 items-center justify-center rounded hover:bg-muted transition-colors",
326
- onClick: onClose,
327
- title: "Close fullscreen (Esc)",
328
- type: "button",
329
- children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" })
330
- }
331
- ) }),
332
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden", children })
333
- ]
334
- }
335
- ),
336
- document.body
337
- );
338
- });
339
- var MIN_ZOOM = 0.1;
340
- var MAX_ZOOM = 2;
341
- var ZOOM_STEP = 0.2;
342
- function useZoomControls(reactFlow) {
343
- const [zoom, setZoom] = useState(1);
344
- const zoomIn = useCallback(() => {
345
- const newZoom = Math.min(zoom + ZOOM_STEP, MAX_ZOOM);
346
- setZoom(newZoom);
347
- void reactFlow.zoomTo(newZoom, { duration: 200 });
348
- }, [zoom, reactFlow]);
349
- const zoomOut = useCallback(() => {
350
- const newZoom = Math.max(zoom - ZOOM_STEP, MIN_ZOOM);
351
- setZoom(newZoom);
352
- void reactFlow.zoomTo(newZoom, { duration: 200 });
353
- }, [zoom, reactFlow]);
354
- const fitView = useCallback(() => {
355
- void reactFlow.fitView({ duration: 200, padding: 0.2 });
356
- }, [reactFlow]);
357
- useEffect(() => {
358
- const viewport = reactFlow.getViewport();
359
- setZoom(viewport.zoom);
360
- }, [reactFlow]);
361
- return { fitView, zoom, zoomIn, zoomOut };
362
- }
363
- function useFullscreenState(allowFullscreen) {
364
- const [isFullscreen, setIsFullscreen] = useState(false);
365
- const toggleFullscreen = useCallback(() => {
366
- if (!allowFullscreen) return;
367
- setIsFullscreen((previous) => !previous);
368
- }, [allowFullscreen]);
369
- const closeFullscreen = useCallback(() => {
370
- setIsFullscreen(false);
371
- }, []);
372
- useEffect(() => {
373
- if (!isFullscreen) return;
374
- const handleKeyDown = (e) => {
375
- if (e.key === "Escape") {
376
- closeFullscreen();
377
- }
378
- };
379
- document.addEventListener("keydown", handleKeyDown);
380
- return () => {
381
- document.removeEventListener("keydown", handleKeyDown);
382
- };
383
- }, [isFullscreen, closeFullscreen]);
384
- useEffect(() => {
385
- document.body.style.overflow = isFullscreen ? "hidden" : "";
386
- return () => {
387
- document.body.style.overflow = "";
388
- };
389
- }, [isFullscreen]);
390
- return { closeFullscreen, isFullscreen, toggleFullscreen };
391
- }
392
- var IMAGE_WIDTH = 1024;
393
- var IMAGE_HEIGHT = 768;
394
- var COPY_SUCCESS_DURATION = 2e3;
395
- async function captureFlowImage(reactFlow) {
396
- const nodes = reactFlow.getNodes();
397
- if (nodes.length === 0) {
398
- throw new Error("Cannot copy: no nodes in diagram");
399
- }
400
- const nodesBounds = getNodesBounds(nodes);
401
- const viewport = getViewportForBounds(
402
- nodesBounds,
403
- IMAGE_WIDTH,
404
- IMAGE_HEIGHT,
405
- 0.5,
406
- 2,
407
- 0.2
408
- );
409
- const flowElement = document.querySelector(".react-flow__viewport");
410
- if (!flowElement || !(flowElement instanceof HTMLElement)) {
411
- throw new Error("Cannot copy: flow viewport element not found");
412
- }
413
- const dataUrl = await toPng(flowElement, {
414
- backgroundColor: "white",
415
- height: IMAGE_HEIGHT,
416
- style: {
417
- height: String(IMAGE_HEIGHT),
418
- transform: `translate(${viewport.x}px, ${viewport.y}px) scale(${viewport.zoom})`,
419
- width: String(IMAGE_WIDTH)
420
- },
421
- width: IMAGE_WIDTH
422
- });
423
- const response = await fetch(dataUrl);
424
- if (!response.ok) {
425
- throw new Error("Failed to fetch image data");
426
- }
427
- return response.blob();
428
- }
429
- function useCopyToClipboard(reactFlow) {
430
- const [copyStatus, setCopyStatus] = useState("idle");
431
- const copyToClipboard = useCallback(async () => {
432
- setCopyStatus("copying");
433
- try {
434
- const blob = await captureFlowImage(reactFlow);
435
- const clipboardItem = new ClipboardItem({ ["image/png"]: blob });
436
- await navigator.clipboard.write([clipboardItem]);
437
- setCopyStatus("success");
438
- setTimeout(() => {
439
- setCopyStatus("idle");
440
- }, COPY_SUCCESS_DURATION);
441
- } catch (error) {
442
- console.error("[FlowDiagram] Copy failed:", error);
443
- setCopyStatus("error");
444
- setTimeout(() => {
445
- setCopyStatus("idle");
446
- }, COPY_SUCCESS_DURATION);
447
- }
448
- }, [reactFlow]);
449
- return { copyStatus, copyToClipboard };
450
- }
451
- function useFlowDiagram(options = {}) {
452
- const { allowFullscreen = true } = options;
453
- const reactFlow = useReactFlow();
454
- const { fitView, zoom, zoomIn, zoomOut } = useZoomControls(reactFlow);
455
- const { closeFullscreen, isFullscreen, toggleFullscreen } = useFullscreenState(allowFullscreen);
456
- const { copyStatus, copyToClipboard } = useCopyToClipboard(reactFlow);
457
- return {
458
- closeFullscreen,
459
- copyStatus,
460
- copyToClipboard,
461
- fitView,
462
- isFullscreen,
463
- toggleFullscreen,
464
- zoom,
465
- zoomIn,
466
- zoomOut
467
- };
468
- }
469
- function validateFlowData(nodes, edges) {
470
- if (nodes.length === 0 && edges.length > 0) {
471
- console.warn(
472
- "[FlowDiagram] Edges provided without nodes - edges will not render"
473
- );
474
- }
475
- const nodeIds = new Set(nodes.map((n) => n.id));
476
- const invalidEdges = edges.filter(
477
- (e) => !nodeIds.has(e.source) || !nodeIds.has(e.target)
478
- );
479
- if (invalidEdges.length > 0) {
480
- console.warn(
481
- `[FlowDiagram] ${invalidEdges.length} edge(s) reference non-existent nodes:`,
482
- invalidEdges.map((e) => `${e.id}: ${e.source} -> ${e.target}`)
483
- );
484
- }
485
- const nodesWithoutPosition = nodes.filter((n) => n.position === void 0);
486
- if (nodesWithoutPosition.length > 0) {
487
- console.warn(
488
- `[FlowDiagram] ${nodesWithoutPosition.length} node(s) missing position:`,
489
- nodesWithoutPosition.map((n) => n.id)
490
- );
491
- }
492
- }
493
- var FlowDiagramInner = memo(function FlowDiagramInner2({
494
- allowCopy = false,
495
- allowFullscreen = true,
496
- className,
497
- edges,
498
- fitView = true,
499
- fitViewOptions,
500
- height = 400,
501
- nodes,
502
- onNodeClick,
503
- showControls = true,
504
- title
505
- }) {
506
- useEffect(() => {
507
- validateFlowData(nodes, edges);
508
- }, [nodes, edges]);
509
- const {
510
- closeFullscreen,
511
- copyStatus,
512
- copyToClipboard,
513
- fitView: handleFitView,
514
- isFullscreen,
515
- toggleFullscreen,
516
- zoomIn,
517
- zoomOut
518
- } = useFlowDiagram({ allowFullscreen });
519
- const handleNodeClick = useCallback(
520
- (_event, node) => {
521
- onNodeClick?.(node);
522
- },
523
- [onNodeClick]
524
- );
525
- const handleCopy = useCallback(() => {
526
- void copyToClipboard();
527
- }, [copyToClipboard]);
528
- const canvasProps = {
529
- allowCopy,
530
- allowFullscreen,
531
- className,
532
- copyStatus,
533
- edges,
534
- fitView,
535
- fitViewOptions,
536
- height,
537
- isFullscreen,
538
- nodes,
539
- onCopy: allowCopy ? handleCopy : void 0,
540
- onFitView: handleFitView,
541
- onFullscreen: allowFullscreen ? toggleFullscreen : void 0,
542
- onNodeClick: onNodeClick ? handleNodeClick : void 0,
543
- onZoomIn: zoomIn,
544
- onZoomOut: zoomOut,
545
- showControls,
546
- title
547
- };
548
- if (isFullscreen) {
549
- return /* @__PURE__ */ jsxs(Fragment, { children: [
550
- /* @__PURE__ */ jsx(
551
- "div",
552
- {
553
- className: cn(
554
- "rounded-lg border border-border bg-muted/50",
555
- className
556
- ),
557
- style: { height }
558
- }
559
- ),
560
- /* @__PURE__ */ jsx(FlowFullscreen, { isOpen: isFullscreen, onClose: closeFullscreen, children: /* @__PURE__ */ jsx(FlowCanvas, { ...canvasProps }) })
561
- ] });
562
- }
563
- return /* @__PURE__ */ jsx(FlowCanvas, { ...canvasProps });
564
- });
565
- var FlowDiagram = memo(function FlowDiagram2(props) {
566
- return /* @__PURE__ */ jsx(FlowErrorBoundary, { height: props.height, children: /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(FlowDiagramInner, { ...props }) }) });
567
- });
568
-
569
- export { FlowControls, FlowDiagram, FlowErrorBoundary, FlowFullscreen, cn, useFlowDiagram };
@@ -1,2 +0,0 @@
1
- "use client";
2
- export { FlowControls, FlowDiagram, FlowErrorBoundary, FlowFullscreen, useFlowDiagram } from './chunk-XRV5RSYH.js';