@flowdrop/flowdrop 2.0.0-beta.3 → 2.0.0-beta.4

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 (49) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +5 -5
  3. package/dist/components/App.svelte +15 -146
  4. package/dist/components/Button.stories.svelte +65 -0
  5. package/dist/components/Button.stories.svelte.d.ts +19 -0
  6. package/dist/components/Button.svelte +62 -0
  7. package/dist/components/Button.svelte.d.ts +24 -0
  8. package/dist/components/ConfigForm.svelte +4 -4
  9. package/dist/components/EditorStatusBar.stories.svelte +44 -0
  10. package/dist/components/EditorStatusBar.stories.svelte.d.ts +27 -0
  11. package/dist/components/EditorStatusBar.svelte +99 -0
  12. package/dist/components/EditorStatusBar.svelte.d.ts +15 -0
  13. package/dist/components/IconButton.svelte +80 -0
  14. package/dist/components/IconButton.svelte.d.ts +30 -0
  15. package/dist/components/Input.svelte +74 -0
  16. package/dist/components/Input.svelte.d.ts +17 -0
  17. package/dist/components/Navbar.svelte +9 -4
  18. package/dist/components/Navbar.svelte.d.ts +3 -0
  19. package/dist/components/NodeSidebar.svelte +13 -111
  20. package/dist/components/NodeSwapPicker.svelte +10 -26
  21. package/dist/components/Select.svelte +53 -0
  22. package/dist/components/Select.svelte.d.ts +15 -0
  23. package/dist/components/Textarea.svelte +39 -0
  24. package/dist/components/Textarea.svelte.d.ts +12 -0
  25. package/dist/components/ThemeToggle.svelte +15 -89
  26. package/dist/components/form/FormArray.svelte +37 -157
  27. package/dist/components/form/FormCheckboxGroup.svelte +1 -1
  28. package/dist/components/form/FormField.svelte +5 -44
  29. package/dist/components/form/FormFieldLight.svelte +5 -44
  30. package/dist/components/form/FormFieldset.svelte +1 -1
  31. package/dist/components/form/FormNumberField.svelte +4 -32
  32. package/dist/components/form/FormRangeField.svelte +17 -7
  33. package/dist/components/form/FormSelect.svelte +13 -79
  34. package/dist/components/form/FormTextField.svelte +3 -39
  35. package/dist/components/form/FormTextarea.svelte +4 -43
  36. package/dist/components/form/resolveFieldType.d.ts +24 -0
  37. package/dist/components/form/resolveFieldType.js +55 -0
  38. package/dist/components/icons/CloseIcon.svelte +6 -0
  39. package/dist/components/icons/CloseIcon.svelte.d.ts +26 -0
  40. package/dist/components/playground/InputCollector.svelte +11 -46
  41. package/dist/messages/index.d.ts +1 -1
  42. package/dist/messages/index.js +1 -1
  43. package/dist/openapi/v1/openapi.yaml +2 -2
  44. package/dist/skins/drafter.js +41 -28
  45. package/dist/styles/base.css +247 -5
  46. package/dist/styles/tokens.css +6 -0
  47. package/dist/svelte-app.js +68 -107
  48. package/dist/utils/connections.js +14 -50
  49. package/package.json +1 -1
@@ -253,8 +253,17 @@ export function getConnectionSuggestions(checker, nodeId, nodes, nodeTypes) {
253
253
  * @returns True if any cycle exists in the workflow
254
254
  */
255
255
  export function hasCycles(nodes, edges) {
256
- // Build adjacency map once (O(E)) so the DFS inner loop is O(1) per lookup
257
- // instead of scanning all edges on every recursive call (which was O(V*E)).
256
+ return detectCycles(nodes, edges);
257
+ }
258
+ /**
259
+ * Detect whether a directed graph contains a cycle, using DFS over a pre-built
260
+ * adjacency map (O(E) build, O(1) per neighbour lookup — avoids the O(V*E) of
261
+ * re-scanning every edge on each recursive call).
262
+ *
263
+ * Shared by `hasCycles` (all edges) and `hasInvalidCycles` (loopback edges
264
+ * pre-filtered out by the caller).
265
+ */
266
+ function detectCycles(nodes, edges) {
258
267
  const adjacencyMap = new Map();
259
268
  for (const node of nodes) {
260
269
  adjacencyMap.set(node.id, []);
@@ -274,7 +283,6 @@ export function hasCycles(nodes, edges) {
274
283
  return false;
275
284
  visited.add(nodeId);
276
285
  recursionStack.add(nodeId);
277
- // Use pre-built adjacency map instead of filtering all edges each call
278
286
  const neighbors = adjacencyMap.get(nodeId) || [];
279
287
  for (const target of neighbors) {
280
288
  if (hasCycleUtil(target))
@@ -283,7 +291,6 @@ export function hasCycles(nodes, edges) {
283
291
  recursionStack.delete(nodeId);
284
292
  return false;
285
293
  }
286
- // Check each node
287
294
  for (const node of nodes) {
288
295
  if (!visited.has(node.id)) {
289
296
  if (hasCycleUtil(node.id))
@@ -309,53 +316,10 @@ export function hasCycles(nodes, edges) {
309
316
  * ```
310
317
  */
311
318
  export function hasInvalidCycles(nodes, edges) {
312
- // Filter out loopback edges - these create valid cycles for loop iteration
319
+ // Filter out loopback edges - these create valid cycles for loop iteration,
320
+ // then reuse the shared detector over the remaining edges.
313
321
  const nonLoopbackEdges = edges.filter((edge) => !isLoopbackEdge(edge));
314
- // Build adjacency map from non-loopback edges once (O(E)) so the DFS inner
315
- // loop is O(1) per lookup instead of scanning all edges on every recursive
316
- // call (which was O(V*E)).
317
- const adjacencyMap = new Map();
318
- for (const node of nodes) {
319
- adjacencyMap.set(node.id, []);
320
- }
321
- for (const edge of nonLoopbackEdges) {
322
- const neighbors = adjacencyMap.get(edge.source);
323
- if (neighbors) {
324
- neighbors.push(edge.target);
325
- }
326
- }
327
- // Check for cycles using only non-loopback edges
328
- const visited = new Set();
329
- const recursionStack = new Set();
330
- /**
331
- * DFS utility to detect cycles in the graph
332
- * @param nodeId - Current node being visited
333
- * @returns True if a cycle is found from this node
334
- */
335
- function hasCycleUtil(nodeId) {
336
- if (recursionStack.has(nodeId))
337
- return true;
338
- if (visited.has(nodeId))
339
- return false;
340
- visited.add(nodeId);
341
- recursionStack.add(nodeId);
342
- // Use pre-built adjacency map instead of filtering all edges each call
343
- const neighbors = adjacencyMap.get(nodeId) || [];
344
- for (const target of neighbors) {
345
- if (hasCycleUtil(target))
346
- return true;
347
- }
348
- recursionStack.delete(nodeId);
349
- return false;
350
- }
351
- // Check each node for cycles
352
- for (const node of nodes) {
353
- if (!visited.has(node.id)) {
354
- if (hasCycleUtil(node.id))
355
- return true;
356
- }
357
- }
358
- return false;
322
+ return detectCycles(nodes, nonLoopbackEdges);
359
323
  }
360
324
  /**
361
325
  * Get the execution order for a workflow (topological sort)
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "A drop-in visual workflow editor for any web application. You own the backend. You own the data. You own the orchestration.",
4
4
  "license": "MIT",
5
5
  "private": false,
6
- "version": "2.0.0-beta.3",
6
+ "version": "2.0.0-beta.4",
7
7
  "author": "Shibin Das (D34dMan)",
8
8
  "bugs": {
9
9
  "url": "https://github.com/flowdrop-io/flowdrop/issues"