@burdenoff/fluidgrids-fe-sdk 2026.922.13 → 2026.923.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/ExecutionDetailPage-BD7CS4KL.js +12 -0
  2. package/dist/{ExecutionDetailPage-OSDL7NDT.js.map → ExecutionDetailPage-BD7CS4KL.js.map} +1 -1
  3. package/dist/ExecutionsListPage-VOGSLA7T.js +11 -0
  4. package/dist/{ExecutionsListPage-AATDFFIH.js.map → ExecutionsListPage-VOGSLA7T.js.map} +1 -1
  5. package/dist/{WorkflowBuilder-D7RKU4UK.js → WorkflowBuilder-WLJBVVHS.js} +8 -8
  6. package/dist/{WorkflowBuilder-D7RKU4UK.js.map → WorkflowBuilder-WLJBVVHS.js.map} +1 -1
  7. package/dist/{WorkflowsList-JHM7Q5HE.js → WorkflowsList-QREUMT55.js} +6 -6
  8. package/dist/{WorkflowsList-JHM7Q5HE.js.map → WorkflowsList-QREUMT55.js.map} +1 -1
  9. package/dist/{chunk-5IAMVAGX.js → chunk-4C6UYNC5.js} +43 -5
  10. package/dist/chunk-4C6UYNC5.js.map +1 -0
  11. package/dist/chunk-5A7GP6O7.js +729 -0
  12. package/dist/chunk-5A7GP6O7.js.map +1 -0
  13. package/dist/{chunk-MTWEYC2W.js → chunk-5PZDLMC4.js} +4 -4
  14. package/dist/{chunk-MTWEYC2W.js.map → chunk-5PZDLMC4.js.map} +1 -1
  15. package/dist/chunk-FKOUPL6Z.js +753 -0
  16. package/dist/chunk-FKOUPL6Z.js.map +1 -0
  17. package/dist/{chunk-EUZZLC3N.js → chunk-HNVWIVJH.js} +202 -6
  18. package/dist/chunk-HNVWIVJH.js.map +1 -0
  19. package/dist/{chunk-PTGKDQ5K.js → chunk-LH2YML5F.js} +8 -2
  20. package/dist/chunk-LH2YML5F.js.map +1 -0
  21. package/dist/chunk-NK32XOQN.js +248 -0
  22. package/dist/chunk-NK32XOQN.js.map +1 -0
  23. package/dist/{chunk-CVVNQCFM.js → chunk-Q4RPP67K.js} +4 -4
  24. package/dist/{chunk-CVVNQCFM.js.map → chunk-Q4RPP67K.js.map} +1 -1
  25. package/dist/{chunk-UNW4I442.js → chunk-Q7RJYGQK.js} +3 -3
  26. package/dist/{chunk-UNW4I442.js.map → chunk-Q7RJYGQK.js.map} +1 -1
  27. package/dist/{chunk-RJQJAN6J.js → chunk-TEZV7I6A.js} +4 -4
  28. package/dist/{chunk-RJQJAN6J.js.map → chunk-TEZV7I6A.js.map} +1 -1
  29. package/dist/{chunk-XQYAM47Y.js → chunk-TOHTP3BT.js} +4 -4
  30. package/dist/{chunk-XQYAM47Y.js.map → chunk-TOHTP3BT.js.map} +1 -1
  31. package/dist/{chunk-IPVHC2DM.js → chunk-TVLE7GNH.js} +374 -7
  32. package/dist/chunk-TVLE7GNH.js.map +1 -0
  33. package/dist/{chunk-ISS73LG3.js → chunk-VPWQN7KV.js} +3 -3
  34. package/dist/{chunk-ISS73LG3.js.map → chunk-VPWQN7KV.js.map} +1 -1
  35. package/dist/{chunk-R6JFXZXN.js → chunk-VTPBYPDV.js} +47 -5
  36. package/dist/chunk-VTPBYPDV.js.map +1 -0
  37. package/dist/{chunk-GWRX2T3K.js → chunk-XF7QA3QT.js} +417 -155
  38. package/dist/chunk-XF7QA3QT.js.map +1 -0
  39. package/dist/executions.js +7 -6
  40. package/dist/history.js +4 -4
  41. package/dist/index.d.ts +71 -1
  42. package/dist/index.js +26 -23
  43. package/dist/index.js.map +1 -1
  44. package/dist/nodes.js +2 -2
  45. package/dist/observability-5ShR4Phm.d.ts +134 -0
  46. package/dist/observability.d.ts +2 -0
  47. package/dist/observability.js +8 -0
  48. package/dist/observability.js.map +1 -0
  49. package/dist/settings.js +5 -1
  50. package/dist/templates.js +6 -6
  51. package/dist/workflow-builder.js +7 -7
  52. package/dist/workflows-list.js +4 -4
  53. package/package.json +5 -1
  54. package/dist/ExecutionDetailPage-OSDL7NDT.js +0 -11
  55. package/dist/ExecutionsListPage-AATDFFIH.js +0 -10
  56. package/dist/chunk-5IAMVAGX.js.map +0 -1
  57. package/dist/chunk-EUZZLC3N.js.map +0 -1
  58. package/dist/chunk-GWRX2T3K.js.map +0 -1
  59. package/dist/chunk-IPVHC2DM.js.map +0 -1
  60. package/dist/chunk-PTGKDQ5K.js.map +0 -1
  61. package/dist/chunk-R6JFXZXN.js.map +0 -1
@@ -1,19 +1,19 @@
1
+ import { deepClone, applyTemplateInputs } from './chunk-XQP33UJR.js';
1
2
  import { Input as Input$1 } from './chunk-P5PKRQAO.js';
2
3
  import { Dialog as Dialog$1, DialogContent as DialogContent$1, DialogHeader as DialogHeader$1, DialogTitle as DialogTitle$1, DialogDescription as DialogDescription$1, DialogFooter } from './chunk-NH5YCY37.js';
3
4
  import { Badge as Badge$1, Button as Button$1 } from './chunk-DBOMRIP5.js';
4
5
  import { getGlobalStoreClient, createGlobalStoreClient, setGlobalStoreClient, resetGlobalStoreClient } from './chunk-BQXHJIER.js';
5
6
  import { GetMyNodeInstallationsDocument, BrowseWorkflowTemplatesDocument, InstallWorkflowNodeDocument, InstallPurchasedNodeDocument, BrowseWorkflowNodesDocument, UninstallWorkflowNodeDocument, CreateStoreOrderDocument, GetNodeInstallableVersionsDocument } from './chunk-6LXMUIR3.js';
6
- import { deepClone, applyTemplateInputs } from './chunk-XQP33UJR.js';
7
7
  import { QuotaExhaustedDialog } from './chunk-AANIWER2.js';
8
8
  import { SdkPermissionGate, FLUIDGRIDS_PERMISSIONS, SdkPermissionButton } from './chunk-W23ZXNKU.js';
9
9
  import { cn as cn$1 } from './chunk-3ZYUGTIT.js';
10
- import { useWorkflowVersions, useRestoreWorkflowVersion, useActivateWorkflow, useDeleteWorkflow, useDeactivateWorkflow } from './chunk-CVVNQCFM.js';
11
- import { throwIfResultError, describeOperationError } from './chunk-LMO5ASOE.js';
10
+ import { useWorkflowVersions, useRestoreWorkflowVersion, useActivateWorkflow, useDeleteWorkflow, useLazyWorkflowDefinition, useDeactivateWorkflow } from './chunk-Q4RPP67K.js';
12
11
  import { config, getFluidGridsConfig, validateTrustedOrigin, setFluidGridsConfig, resetFluidGridsConfig } from './chunk-WWU2O2SR.js';
13
- import { waitForFluidGridsClient, getFluidGridsClient, createFluidGridsClient, setFluidGridsClient, resetFluidGridsClient, getFluidGridsClientSafe } from './chunk-5BDQNSP3.js';
14
12
  import { useFlowStore } from './chunk-YMD3T6J2.js';
15
13
  import { NodeEndpointConfigsDocument, NodeManifestDocument, UpdateWorkflowDefinitionDocument, CreateWorkflowDefinitionDocument, CreateWorkflowVersionDocument, TriggerWorkflowDocument, RunFromNodeDocument, ExecutionDetailDocument, WorkflowRunDocument, FluidgridsEntityTagsDocument, AvailableFluidgridsTagsDocument, SearchFluidgridsTagsDocument, TagFluidgridsEntityDocument, UntagFluidgridsEntityDocument, ReplaceFluidgridsEntityTagsDocument, CreateFluidgridsTagDocument, NodeSchemaIntrospectionDocument, useWorkflowPinnedDataQuery, usePinNodeDataMutation, useUnpinNodeDataMutation, EventRegistrationsDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument } from './chunk-BHITFSOK.js';
14
+ import { throwIfResultError, describeOperationError } from './chunk-LMO5ASOE.js';
16
15
  import { useTr, FluidGridsTranslationProvider, ENGLISH_FALLBACK_TRANSLATOR } from './chunk-7YWBH2A5.js';
16
+ import { waitForFluidGridsClient, getFluidGridsClient, createFluidGridsClient, setFluidGridsClient, resetFluidGridsClient, getFluidGridsClientSafe } from './chunk-5BDQNSP3.js';
17
17
  import * as React2 from 'react';
18
18
  import React2__default, { forwardRef, useState, useImperativeHandle, useRef, useEffect, useMemo, memo, createContext, lazy, useCallback, useContext, useLayoutEffect, Suspense, useDeferredValue } from 'react';
19
19
  import { Textarea, Input, Button, Card, Badge, CardContent as CardContent$1, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator, Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, TooltipProvider, AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, Popover, PopoverTrigger, PopoverContent, Tooltip, TooltipTrigger, TooltipContent, Toaster, Tabs, TabsList, TabsTrigger, TabsContent, CardHeader as CardHeader$1, CardTitle as CardTitle$1, CardDescription as CardDescription$1, ScrollArea, Label, Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@burdenoff/fe-libs/ui';
@@ -38,7 +38,7 @@ import { ApolloProvider, useQuery, useMutation } from '@apollo/client/react';
38
38
  import { TagBadge, TagsWidget } from '@burdenoff/fe-libs/tag';
39
39
  import { gql as gql$1 } from '@apollo/client/core';
40
40
  import 'jszip';
41
- import { Sparkles, Star, Download, Eye, History, Loader2, Play, RotateCcw, Trash2, Maximize2, Undo2, Redo2, LayoutGrid, Keyboard, Plus, GitBranch, AlertCircle, Search, RefreshCw, CheckCircle2, Package, Info, Copy, BadgeCheck, DollarSign, Type, Code, Hash, List, Braces, Workflow, PlusCircle, ChevronDown, ChevronRight, Layers, X, AlertTriangle } from 'lucide-react';
41
+ import { Sparkles, Star, Download, Eye, History, GitCompareArrows, Loader2, Play, RotateCcw, Trash2, Maximize2, Undo2, Redo2, LayoutGrid, Keyboard, Plus, GitBranch, AlertCircle, Search, RefreshCw, CheckCircle2, Package, Info, Copy, BadgeCheck, DollarSign, Type, Code, Hash, List, Braces, Workflow, PlusCircle, ChevronDown, ChevronRight, Layers, X, AlertTriangle } from 'lucide-react';
42
42
  import { produce } from 'immer';
43
43
  import { isEmpty } from 'radash';
44
44
  import { animate, easeOut } from 'popmotion';
@@ -24534,6 +24534,81 @@ function QuickConfigPanelInner({
24534
24534
  )
24535
24535
  ] });
24536
24536
  }
24537
+
24538
+ // src/utils/workflow-definition-diff.ts
24539
+ function isRecord3(value) {
24540
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24541
+ }
24542
+ function equalJson(left, right) {
24543
+ if (Object.is(left, right)) return true;
24544
+ if (Array.isArray(left) && Array.isArray(right)) {
24545
+ return left.length === right.length && left.every((value, index) => equalJson(value, right[index]));
24546
+ }
24547
+ if (isRecord3(left) && isRecord3(right)) {
24548
+ const leftKeys = Object.keys(left).sort((a, b) => a.localeCompare(b));
24549
+ const rightKeys = Object.keys(right).sort((a, b) => a.localeCompare(b));
24550
+ return leftKeys.length === rightKeys.length && leftKeys.every(
24551
+ (key, index) => key === rightKeys[index] && equalJson(left[key], right[key])
24552
+ );
24553
+ }
24554
+ return false;
24555
+ }
24556
+ function diffWorkflowDefinitionJson(before, after, maxEntries = 2e3) {
24557
+ const entries = [];
24558
+ const visit = (left, right, path) => {
24559
+ if (entries.length >= maxEntries || equalJson(left, right)) return;
24560
+ if (isRecord3(left) && isRecord3(right)) {
24561
+ const keys = [
24562
+ .../* @__PURE__ */ new Set([...Object.keys(left), ...Object.keys(right)])
24563
+ ].sort((a, b) => a.localeCompare(b));
24564
+ for (const key of keys) {
24565
+ const childPath = `${path}.${key}`;
24566
+ if (!(key in left))
24567
+ entries.push({
24568
+ path: childPath,
24569
+ kind: "ADDED",
24570
+ before: void 0,
24571
+ after: right[key]
24572
+ });
24573
+ else if (!(key in right))
24574
+ entries.push({
24575
+ path: childPath,
24576
+ kind: "REMOVED",
24577
+ before: left[key],
24578
+ after: void 0
24579
+ });
24580
+ else visit(left[key], right[key], childPath);
24581
+ if (entries.length >= maxEntries) return;
24582
+ }
24583
+ return;
24584
+ }
24585
+ if (Array.isArray(left) && Array.isArray(right)) {
24586
+ for (let index = 0; index < Math.max(left.length, right.length); index += 1) {
24587
+ const childPath = `${path}[${index}]`;
24588
+ if (index >= left.length)
24589
+ entries.push({
24590
+ path: childPath,
24591
+ kind: "ADDED",
24592
+ before: void 0,
24593
+ after: right[index]
24594
+ });
24595
+ else if (index >= right.length)
24596
+ entries.push({
24597
+ path: childPath,
24598
+ kind: "REMOVED",
24599
+ before: left[index],
24600
+ after: void 0
24601
+ });
24602
+ else visit(left[index], right[index], childPath);
24603
+ if (entries.length >= maxEntries) return;
24604
+ }
24605
+ return;
24606
+ }
24607
+ entries.push({ path, kind: "CHANGED", before: left, after: right });
24608
+ };
24609
+ visit(before, after, "$");
24610
+ return entries;
24611
+ }
24537
24612
  function relativeTime(dateStr) {
24538
24613
  if (!dateStr) return "";
24539
24614
  const then = new Date(dateStr).getTime();
@@ -24566,6 +24641,14 @@ function absoluteTime(dateStr) {
24566
24641
  return dateStr;
24567
24642
  }
24568
24643
  }
24644
+ function formatDiffValue(value) {
24645
+ if (value === void 0) return "\u2014";
24646
+ try {
24647
+ return JSON.stringify(value);
24648
+ } catch {
24649
+ return String(value);
24650
+ }
24651
+ }
24569
24652
  function ActionButton({
24570
24653
  label,
24571
24654
  onClick,
@@ -24624,9 +24707,26 @@ function VersionHistoryPanel({ className }) {
24624
24707
  const { restoreVersion } = useRestoreWorkflowVersion();
24625
24708
  const { activateWorkflow } = useActivateWorkflow();
24626
24709
  const { deleteWorkflow } = useDeleteWorkflow();
24710
+ const { getWorkflow } = useLazyWorkflowDefinition();
24627
24711
  const setWorkflow = useFlowStore((s) => s.actions.setWorkflow);
24712
+ const [compareFrom, setCompareFrom] = useState("");
24713
+ const [compareTo, setCompareTo] = useState("");
24714
+ const [comparison, setComparison] = useState(null);
24715
+ const [compareLoading, setCompareLoading] = useState(false);
24628
24716
  const [busy, setBusy] = useState(null);
24629
24717
  const [deleteTarget, setDeleteTarget] = useState(null);
24718
+ useEffect(() => {
24719
+ if (versions.length < 2) {
24720
+ setCompareFrom("");
24721
+ setCompareTo("");
24722
+ setComparison(null);
24723
+ return;
24724
+ }
24725
+ setCompareFrom((current) => current || versions[1]?.version || "");
24726
+ setCompareTo(
24727
+ (current) => current || currentVersion || versions[0]?.version || ""
24728
+ );
24729
+ }, [versions, currentVersion]);
24630
24730
  const config2 = getFluidGridsConfig();
24631
24731
  const actorInputs = useMemo(() => {
24632
24732
  const ids = /* @__PURE__ */ new Set();
@@ -24644,6 +24744,39 @@ function VersionHistoryPanel({ className }) {
24644
24744
  if (!createdById) return null;
24645
24745
  return actorProfiles[createdById]?.displayName ?? buildActorFallback({ actorId: createdById, actorType: "user" }).displayName;
24646
24746
  };
24747
+ const handleCompare = async () => {
24748
+ if (!compareFrom || !compareTo || compareFrom === compareTo) return;
24749
+ setCompareLoading(true);
24750
+ try {
24751
+ const [fromWorkflow, toWorkflow] = await Promise.all([
24752
+ getWorkflow(workflowKey, void 0, compareFrom),
24753
+ getWorkflow(workflowKey, void 0, compareTo)
24754
+ ]);
24755
+ if (!fromWorkflow || !toWorkflow)
24756
+ throw new Error("Unable to load both workflow versions");
24757
+ setComparison({
24758
+ fromVersion: compareFrom,
24759
+ toVersion: compareTo,
24760
+ entries: diffWorkflowDefinitionJson(
24761
+ fromWorkflow.definitionJson,
24762
+ toWorkflow.definitionJson
24763
+ )
24764
+ });
24765
+ } catch (error) {
24766
+ toast.error(
24767
+ tr(
24768
+ "fluidgrids.builder.versionHistory.compareError",
24769
+ "Failed to compare versions"
24770
+ ),
24771
+ {
24772
+ description: error instanceof Error ? error.message : "Unknown error"
24773
+ }
24774
+ );
24775
+ setComparison(null);
24776
+ } finally {
24777
+ setCompareLoading(false);
24778
+ }
24779
+ };
24647
24780
  const handleRestore = async (version) => {
24648
24781
  setBusy(`restore:${version}`);
24649
24782
  try {
@@ -24782,163 +24915,292 @@ function VersionHistoryPanel({ className }) {
24782
24915
  )
24783
24916
  ] })
24784
24917
  ] }),
24785
- /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsx("div", { className: "mt-4 overflow-y-auto max-h-[calc(100vh-140px)] pr-1", children: loading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center py-8", children: [
24786
- /* @__PURE__ */ jsx(Loader2, { className: "size-5 animate-spin text-muted-foreground" }),
24787
- /* @__PURE__ */ jsx("span", { className: "ml-2 text-muted-foreground text-sm", children: tr(
24788
- "fluidgrids.builder.versionHistory.loading",
24789
- "Loading versions..."
24790
- ) })
24791
- ] }) : versions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm text-center py-8", children: tr(
24792
- "fluidgrids.builder.versionHistory.emptyState",
24793
- "No versions found."
24794
- ) }) : /* @__PURE__ */ jsx("ul", { children: versions.map((v, index) => {
24795
- const isCurrent = v.version === currentVersion;
24796
- const isActive = v.status === "ACTIVE";
24797
- const isLast = index === versions.length - 1;
24798
- const statusInfo = STATUS_STYLES[v.status ?? "DRAFT"] ?? STATUS_STYLES.DRAFT;
24799
- const author = authorName(v.createdById);
24800
- return /* @__PURE__ */ jsxs("li", { className: "flex gap-3", children: [
24801
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center pt-4", children: [
24802
- /* @__PURE__ */ jsx(
24803
- "span",
24804
- {
24805
- className: cn(
24806
- "size-2.5 shrink-0 rounded-full border-2",
24807
- isActive ? "border-[var(--color-status-success-bg)] bg-[var(--color-status-success-bg)]" : isCurrent ? "border-primary bg-primary" : "border-border bg-background"
24918
+ /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxs("div", { className: "mt-4 overflow-y-auto max-h-[calc(100vh-140px)] pr-1", children: [
24919
+ !loading && versions.length > 1 && /* @__PURE__ */ jsxs(
24920
+ "section",
24921
+ {
24922
+ className: "mb-4 rounded-lg border border-border bg-card p-3",
24923
+ "aria-label": "Compare workflow versions",
24924
+ children: [
24925
+ /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2 text-sm font-semibold", children: [
24926
+ /* @__PURE__ */ jsx(GitCompareArrows, { className: "size-4" }),
24927
+ tr(
24928
+ "fluidgrids.builder.versionHistory.compareTitle",
24929
+ "Compare versions"
24808
24930
  )
24809
- }
24810
- ),
24811
- !isLast && /* @__PURE__ */ jsx("span", { className: "w-px flex-1 bg-border" })
24812
- ] }),
24813
- /* @__PURE__ */ jsxs(
24814
- "div",
24815
- {
24816
- className: cn(
24817
- "mb-2 flex-1 rounded-lg border p-3 transition-colors",
24818
- isCurrent ? "border-primary/50 bg-primary/5" : "border-border hover:bg-accent/50"
24819
- ),
24820
- children: [
24821
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
24822
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
24823
- /* @__PURE__ */ jsx(
24824
- "button",
24825
- {
24826
- type: "button",
24827
- className: cn(
24828
- "font-mono text-sm font-semibold text-foreground",
24829
- !isCurrent && "cursor-pointer hover:text-primary"
24830
- ),
24831
- onClick: () => !isCurrent && handleSwitchVersion(v.version),
24832
- title: isCurrent ? void 0 : `Open ${v.version} in the builder`,
24833
- children: v.version
24834
- }
24835
- ),
24836
- /* @__PURE__ */ jsx(
24837
- Badge,
24838
- {
24839
- variant: statusInfo.variant,
24840
- className: "text-[10px] px-1.5 py-0 h-5",
24841
- children: statusInfo.label
24842
- }
24843
- ),
24844
- isCurrent && /* @__PURE__ */ jsx(
24845
- Badge,
24846
- {
24847
- variant: "outline",
24848
- className: "text-[10px] px-1.5 py-0 h-5 border-primary text-primary",
24849
- children: tr(
24850
- "fluidgrids.builder.versionHistory.currentBadge",
24851
- "Current"
24852
- )
24853
- }
24854
- ),
24855
- v.alias && /* @__PURE__ */ jsxs(
24856
- Badge,
24857
- {
24858
- variant: "outline",
24859
- className: "text-[10px] px-1.5 py-0 h-5 font-mono",
24860
- title: tr(
24861
- "fluidgrids.builder.versionHistory.aliasTooltip",
24862
- "Version alias"
24863
- ),
24864
- children: [
24865
- "@",
24866
- v.alias
24867
- ]
24868
- }
24869
- )
24870
- ] }),
24871
- /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center", children: [
24872
- !isCurrent && /* @__PURE__ */ jsx(
24873
- ActionButton,
24874
- {
24875
- label: tr(
24876
- "fluidgrids.builder.versionHistory.actionView",
24877
- "View in builder"
24878
- ),
24879
- icon: /* @__PURE__ */ jsx(Eye, { className: "size-3.5" }),
24880
- disabled: busy !== null,
24881
- onClick: () => handleSwitchVersion(v.version)
24882
- }
24883
- ),
24884
- !isActive && /* @__PURE__ */ jsx(
24885
- ActionButton,
24886
- {
24887
- label: tr(
24888
- "fluidgrids.builder.versionHistory.actionActivate",
24889
- "Activate this version"
24890
- ),
24891
- icon: /* @__PURE__ */ jsx(Play, { className: "size-3.5" }),
24892
- disabled: busy !== null,
24893
- busy: busy === `activate:${v.version}`,
24894
- onClick: () => handleActivate(v.id, v.version)
24895
- }
24931
+ ] }),
24932
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_auto_1fr] items-center gap-2", children: [
24933
+ /* @__PURE__ */ jsx(
24934
+ "select",
24935
+ {
24936
+ value: compareFrom,
24937
+ onChange: (event) => setCompareFrom(event.target.value),
24938
+ className: "h-8 min-w-0 rounded-md border border-border bg-background px-2 text-xs",
24939
+ "aria-label": tr(
24940
+ "fluidgrids.builder.versionHistory.compareFrom",
24941
+ "From version"
24896
24942
  ),
24897
- !isCurrent && /* @__PURE__ */ jsx(
24898
- ActionButton,
24943
+ children: versions.map((version) => /* @__PURE__ */ jsx(
24944
+ "option",
24899
24945
  {
24900
- label: tr(
24901
- "fluidgrids.builder.versionHistory.actionRestore",
24902
- "Restore as new draft"
24903
- ),
24904
- icon: /* @__PURE__ */ jsx(RotateCcw, { className: "size-3.5" }),
24905
- disabled: busy !== null,
24906
- busy: busy === `restore:${v.version}`,
24907
- onClick: () => handleRestore(v.version)
24908
- }
24946
+ value: version.version,
24947
+ children: version.version
24948
+ },
24949
+ `from-${version.id}`
24950
+ ))
24951
+ }
24952
+ ),
24953
+ /* @__PURE__ */ jsx(
24954
+ "span",
24955
+ {
24956
+ className: "text-xs text-muted-foreground",
24957
+ "aria-hidden": "true",
24958
+ children: "\u2192"
24959
+ }
24960
+ ),
24961
+ /* @__PURE__ */ jsx(
24962
+ "select",
24963
+ {
24964
+ value: compareTo,
24965
+ onChange: (event) => setCompareTo(event.target.value),
24966
+ className: "h-8 min-w-0 rounded-md border border-border bg-background px-2 text-xs",
24967
+ "aria-label": tr(
24968
+ "fluidgrids.builder.versionHistory.compareTo",
24969
+ "To version"
24909
24970
  ),
24910
- !isCurrent && !isActive && /* @__PURE__ */ jsx(
24911
- ActionButton,
24912
- {
24913
- label: tr(
24914
- "fluidgrids.builder.versionHistory.actionDelete",
24915
- "Delete version"
24916
- ),
24917
- destructive: true,
24918
- icon: /* @__PURE__ */ jsx(Trash2, { className: "size-3.5" }),
24919
- disabled: busy !== null,
24920
- busy: busy === `delete:${v.version}`,
24921
- onClick: () => setDeleteTarget(v.version)
24922
- }
24971
+ children: versions.map((version) => /* @__PURE__ */ jsx("option", { value: version.version, children: version.version }, `to-${version.id}`))
24972
+ }
24973
+ )
24974
+ ] }),
24975
+ /* @__PURE__ */ jsxs(
24976
+ Button,
24977
+ {
24978
+ className: "mt-2 w-full",
24979
+ size: "sm",
24980
+ variant: "secondary",
24981
+ disabled: compareLoading || !compareFrom || !compareTo || compareFrom === compareTo,
24982
+ onClick: () => void handleCompare(),
24983
+ children: [
24984
+ compareLoading ? /* @__PURE__ */ jsx(Loader2, { className: "mr-2 size-3.5 animate-spin" }) : /* @__PURE__ */ jsx(GitCompareArrows, { className: "mr-2 size-3.5" }),
24985
+ compareLoading ? tr(
24986
+ "fluidgrids.builder.versionHistory.comparing",
24987
+ "Comparing\u2026"
24988
+ ) : tr(
24989
+ "fluidgrids.builder.versionHistory.compareButton",
24990
+ "Compare"
24923
24991
  )
24924
- ] })
24992
+ ]
24993
+ }
24994
+ ),
24995
+ comparison && /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2 border-t border-border pt-3", children: [
24996
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
24997
+ comparison.fromVersion,
24998
+ " \u2192 ",
24999
+ comparison.toVersion,
25000
+ ":",
25001
+ " ",
25002
+ comparison.entries.length,
25003
+ " ",
25004
+ tr(
25005
+ "fluidgrids.builder.versionHistory.changes",
25006
+ "changes"
25007
+ )
24925
25008
  ] }),
24926
- /* @__PURE__ */ jsxs(
24927
- "p",
25009
+ comparison.entries.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: tr(
25010
+ "fluidgrids.builder.versionHistory.noChanges",
25011
+ "Definitions are identical"
25012
+ ) }) : /* @__PURE__ */ jsx("ul", { className: "max-h-64 space-y-1 overflow-y-auto", children: comparison.entries.map((entry) => /* @__PURE__ */ jsxs(
25013
+ "li",
24928
25014
  {
24929
- className: "mt-1.5 text-xs text-muted-foreground",
24930
- title: absoluteTime(v.updatedAt),
25015
+ className: "rounded border border-border p-2 text-xs",
24931
25016
  children: [
24932
- author ? `${author} \xB7 ` : "",
24933
- relativeTime(v.updatedAt)
25017
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
25018
+ /* @__PURE__ */ jsx(
25019
+ Badge,
25020
+ {
25021
+ variant: entry.kind === "CHANGED" ? "secondary" : entry.kind === "ADDED" ? "default" : "destructive",
25022
+ className: "text-[10px]",
25023
+ children: entry.kind
25024
+ }
25025
+ ),
25026
+ /* @__PURE__ */ jsx("code", { className: "min-w-0 truncate font-mono", children: entry.path })
25027
+ ] }),
25028
+ entry.kind === "CHANGED" && /* @__PURE__ */ jsxs("div", { className: "mt-1 grid gap-1 text-[11px] text-muted-foreground", children: [
25029
+ /* @__PURE__ */ jsxs("span", { className: "truncate", children: [
25030
+ "\u2212 ",
25031
+ formatDiffValue(entry.before)
25032
+ ] }),
25033
+ /* @__PURE__ */ jsxs("span", { className: "truncate", children: [
25034
+ "+ ",
25035
+ formatDiffValue(entry.after)
25036
+ ] })
25037
+ ] })
24934
25038
  ]
24935
- }
24936
- )
24937
- ]
24938
- }
24939
- )
24940
- ] }, v.id);
24941
- }) }) }) })
25039
+ },
25040
+ `${entry.kind}-${entry.path}`
25041
+ )) })
25042
+ ] })
25043
+ ]
25044
+ }
25045
+ ),
25046
+ loading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center py-8", children: [
25047
+ /* @__PURE__ */ jsx(Loader2, { className: "size-5 animate-spin text-muted-foreground" }),
25048
+ /* @__PURE__ */ jsx("span", { className: "ml-2 text-muted-foreground text-sm", children: tr(
25049
+ "fluidgrids.builder.versionHistory.loading",
25050
+ "Loading versions..."
25051
+ ) })
25052
+ ] }) : versions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm text-center py-8", children: tr(
25053
+ "fluidgrids.builder.versionHistory.emptyState",
25054
+ "No versions found."
25055
+ ) }) : /* @__PURE__ */ jsx("ul", { children: versions.map((v, index) => {
25056
+ const isCurrent = v.version === currentVersion;
25057
+ const isActive = v.status === "ACTIVE";
25058
+ const isLast = index === versions.length - 1;
25059
+ const statusInfo = STATUS_STYLES[v.status ?? "DRAFT"] ?? STATUS_STYLES.DRAFT;
25060
+ const author = authorName(v.createdById);
25061
+ return /* @__PURE__ */ jsxs("li", { className: "flex gap-3", children: [
25062
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center pt-4", children: [
25063
+ /* @__PURE__ */ jsx(
25064
+ "span",
25065
+ {
25066
+ className: cn(
25067
+ "size-2.5 shrink-0 rounded-full border-2",
25068
+ isActive ? "border-[var(--color-status-success-bg)] bg-[var(--color-status-success-bg)]" : isCurrent ? "border-primary bg-primary" : "border-border bg-background"
25069
+ )
25070
+ }
25071
+ ),
25072
+ !isLast && /* @__PURE__ */ jsx("span", { className: "w-px flex-1 bg-border" })
25073
+ ] }),
25074
+ /* @__PURE__ */ jsxs(
25075
+ "div",
25076
+ {
25077
+ className: cn(
25078
+ "mb-2 flex-1 rounded-lg border p-3 transition-colors",
25079
+ isCurrent ? "border-primary/50 bg-primary/5" : "border-border hover:bg-accent/50"
25080
+ ),
25081
+ children: [
25082
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
25083
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
25084
+ /* @__PURE__ */ jsx(
25085
+ "button",
25086
+ {
25087
+ type: "button",
25088
+ className: cn(
25089
+ "font-mono text-sm font-semibold text-foreground",
25090
+ !isCurrent && "cursor-pointer hover:text-primary"
25091
+ ),
25092
+ onClick: () => !isCurrent && handleSwitchVersion(v.version),
25093
+ title: isCurrent ? void 0 : `Open ${v.version} in the builder`,
25094
+ children: v.version
25095
+ }
25096
+ ),
25097
+ /* @__PURE__ */ jsx(
25098
+ Badge,
25099
+ {
25100
+ variant: statusInfo.variant,
25101
+ className: "text-[10px] px-1.5 py-0 h-5",
25102
+ children: statusInfo.label
25103
+ }
25104
+ ),
25105
+ isCurrent && /* @__PURE__ */ jsx(
25106
+ Badge,
25107
+ {
25108
+ variant: "outline",
25109
+ className: "text-[10px] px-1.5 py-0 h-5 border-primary text-primary",
25110
+ children: tr(
25111
+ "fluidgrids.builder.versionHistory.currentBadge",
25112
+ "Current"
25113
+ )
25114
+ }
25115
+ ),
25116
+ v.alias && /* @__PURE__ */ jsxs(
25117
+ Badge,
25118
+ {
25119
+ variant: "outline",
25120
+ className: "text-[10px] px-1.5 py-0 h-5 font-mono",
25121
+ title: tr(
25122
+ "fluidgrids.builder.versionHistory.aliasTooltip",
25123
+ "Version alias"
25124
+ ),
25125
+ children: [
25126
+ "@",
25127
+ v.alias
25128
+ ]
25129
+ }
25130
+ )
25131
+ ] }),
25132
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center", children: [
25133
+ !isCurrent && /* @__PURE__ */ jsx(
25134
+ ActionButton,
25135
+ {
25136
+ label: tr(
25137
+ "fluidgrids.builder.versionHistory.actionView",
25138
+ "View in builder"
25139
+ ),
25140
+ icon: /* @__PURE__ */ jsx(Eye, { className: "size-3.5" }),
25141
+ disabled: busy !== null,
25142
+ onClick: () => handleSwitchVersion(v.version)
25143
+ }
25144
+ ),
25145
+ !isActive && /* @__PURE__ */ jsx(
25146
+ ActionButton,
25147
+ {
25148
+ label: tr(
25149
+ "fluidgrids.builder.versionHistory.actionActivate",
25150
+ "Activate this version"
25151
+ ),
25152
+ icon: /* @__PURE__ */ jsx(Play, { className: "size-3.5" }),
25153
+ disabled: busy !== null,
25154
+ busy: busy === `activate:${v.version}`,
25155
+ onClick: () => handleActivate(v.id, v.version)
25156
+ }
25157
+ ),
25158
+ !isCurrent && /* @__PURE__ */ jsx(
25159
+ ActionButton,
25160
+ {
25161
+ label: tr(
25162
+ "fluidgrids.builder.versionHistory.actionRestore",
25163
+ "Restore as new draft"
25164
+ ),
25165
+ icon: /* @__PURE__ */ jsx(RotateCcw, { className: "size-3.5" }),
25166
+ disabled: busy !== null,
25167
+ busy: busy === `restore:${v.version}`,
25168
+ onClick: () => handleRestore(v.version)
25169
+ }
25170
+ ),
25171
+ !isCurrent && !isActive && /* @__PURE__ */ jsx(
25172
+ ActionButton,
25173
+ {
25174
+ label: tr(
25175
+ "fluidgrids.builder.versionHistory.actionDelete",
25176
+ "Delete version"
25177
+ ),
25178
+ destructive: true,
25179
+ icon: /* @__PURE__ */ jsx(Trash2, { className: "size-3.5" }),
25180
+ disabled: busy !== null,
25181
+ busy: busy === `delete:${v.version}`,
25182
+ onClick: () => setDeleteTarget(v.version)
25183
+ }
25184
+ )
25185
+ ] })
25186
+ ] }),
25187
+ /* @__PURE__ */ jsxs(
25188
+ "p",
25189
+ {
25190
+ className: "mt-1.5 text-xs text-muted-foreground",
25191
+ title: absoluteTime(v.updatedAt),
25192
+ children: [
25193
+ author ? `${author} \xB7 ` : "",
25194
+ relativeTime(v.updatedAt)
25195
+ ]
25196
+ }
25197
+ )
25198
+ ]
25199
+ }
25200
+ )
25201
+ ] }, v.id);
25202
+ }) })
25203
+ ] }) })
24942
25204
  ] }),
24943
25205
  /* @__PURE__ */ jsx(
24944
25206
  AlertDialog,
@@ -25550,5 +25812,5 @@ var FlowBuilderPage = ({
25550
25812
  };
25551
25813
 
25552
25814
  export { Card2 as Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ConnectionFormDialog, ConnectionSelector, EntityTagPicker, FLUIDGRIDS_ENTITY_TYPES, FlowBuilderPage, FluidGridsProvider, ProviderPicker, SchemaConnectionForm, ScopePicker, TemplateCard, buildNodeCheck, buildRequiredNodeTypes, listCustomBlocks, mergeStickyNotes, refetchStoreNodes, registerCustomBlock, resolveUiSpec, stripSubmitActions, tagLabel, useAvailableTags, useConnection, useConnectionDialog, useConnections, useConnectionsByProvider, useCreateConnection, useCreateTag, useDraftEntityTags, useEntityTags, useFluidGridsContext, useImportWorkflowTemplate, useInitiateOAuth, useInstalledNodes, useNodeExecution, useProviderByKey, useProviderCatalog, useProviders, useReplaceEntityTags, useSearchTags, useTagEntity, useUntagEntity, useWorkflowTemplates };
25553
- //# sourceMappingURL=chunk-GWRX2T3K.js.map
25554
- //# sourceMappingURL=chunk-GWRX2T3K.js.map
25815
+ //# sourceMappingURL=chunk-XF7QA3QT.js.map
25816
+ //# sourceMappingURL=chunk-XF7QA3QT.js.map