@burdenoff/fluidgrids-fe-sdk 2026.922.1 → 2026.922.3

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 (27) hide show
  1. package/dist/{WorkflowBuilder-RG4QXBZN.js → WorkflowBuilder-FB5JSGDC.js} +5 -5
  2. package/dist/{WorkflowBuilder-RG4QXBZN.js.map → WorkflowBuilder-FB5JSGDC.js.map} +1 -1
  3. package/dist/{WorkflowsList-ZBMSG2WP.js → WorkflowsList-J6IDS3SR.js} +4 -4
  4. package/dist/{WorkflowsList-ZBMSG2WP.js.map → WorkflowsList-J6IDS3SR.js.map} +1 -1
  5. package/dist/{chunk-XASNLRFQ.js → chunk-2RVL6DT3.js} +564 -41
  6. package/dist/chunk-2RVL6DT3.js.map +1 -0
  7. package/dist/chunk-I3WUYESA.js +668 -0
  8. package/dist/chunk-I3WUYESA.js.map +1 -0
  9. package/dist/{chunk-YAADZDGX.js → chunk-K4U4WX4R.js} +3 -3
  10. package/dist/{chunk-YAADZDGX.js.map → chunk-K4U4WX4R.js.map} +1 -1
  11. package/dist/{chunk-EFLYJTQI.js → chunk-NVQOHU5Y.js} +4 -4
  12. package/dist/{chunk-EFLYJTQI.js.map → chunk-NVQOHU5Y.js.map} +1 -1
  13. package/dist/{chunk-GCUAXFMW.js → chunk-T6EWXQBI.js} +4 -4
  14. package/dist/{chunk-GCUAXFMW.js.map → chunk-T6EWXQBI.js.map} +1 -1
  15. package/dist/{chunk-ND4ACNAW.js → chunk-TCMY3ZN3.js} +4 -4
  16. package/dist/{chunk-ND4ACNAW.js.map → chunk-TCMY3ZN3.js.map} +1 -1
  17. package/dist/index.d.ts +2 -2
  18. package/dist/index.js +10 -10
  19. package/dist/templates.js +3 -3
  20. package/dist/{workflow-builder-JKkdIJoP.d.ts → workflow-builder-BNWKK8C7.d.ts} +53 -2
  21. package/dist/workflow-builder.d.ts +1 -1
  22. package/dist/workflow-builder.js +4 -4
  23. package/dist/workflows-list.js +2 -2
  24. package/package.json +1 -1
  25. package/dist/chunk-KT72XMAB.js +0 -379
  26. package/dist/chunk-KT72XMAB.js.map +0 -1
  27. package/dist/chunk-XASNLRFQ.js.map +0 -1
@@ -9,6 +9,10 @@ interface FlowNodeData {
9
9
  deletable?: boolean;
10
10
  nodeType?: string;
11
11
  config?: Record<string, unknown>;
12
+ /** When true, the node is dimmed on the canvas and the worker executor
13
+ * skips it entirely at runtime — its input passes through unchanged as
14
+ * its output, and its edges stay intact (BOFF-7510). */
15
+ disabled?: boolean;
12
16
  [key: string]: unknown;
13
17
  }
14
18
  interface FlowNode extends Node {
@@ -322,6 +326,16 @@ interface CustomEdgeProps extends Edge {
322
326
  condition?: EdgeCondition;
323
327
  mapping?: EdgeMapping;
324
328
  }
329
+ /** A point-in-time snapshot of canvas structure for undo/redo. */
330
+ interface HistorySnapshot {
331
+ nodes: Node[];
332
+ edges: CustomEdgeProps[];
333
+ }
334
+ /** Undo/redo stacks for the currently open workflow. */
335
+ interface HistoryState {
336
+ past: HistorySnapshot[];
337
+ future: HistorySnapshot[];
338
+ }
325
339
  interface State {
326
340
  nodes: Node[];
327
341
  edges: CustomEdgeProps[];
@@ -330,6 +344,9 @@ interface State {
330
344
  nodeId: string;
331
345
  type: ExtendedNodeType;
332
346
  } | null;
347
+ /** Node currently in inline-rename edit mode (F2 or double-click on its
348
+ * title). Only one node can be renamed at a time. */
349
+ renamingNodeId?: string | null;
333
350
  /**
334
351
  * Node currently open in the single-click floating quick-config panel
335
352
  * (Make-style, attached beside the node). The panel derives its own screen
@@ -374,15 +391,46 @@ interface Actions {
374
391
  };
375
392
  setWorkflow: (workflow: Partial<IFlowState["workflow"]>) => void;
376
393
  resetWorkflow: () => void;
394
+ history: {
395
+ undo: () => void;
396
+ redo: () => void;
397
+ /** Wipe both stacks — called when a (different) workflow is loaded so
398
+ * undo can never reach back into a previously open workflow. */
399
+ clear: () => void;
400
+ };
377
401
  nodes: {
378
402
  onNodesChange: (changes: NodeChange[]) => void;
379
- setNodes: (nodes: Node[]) => void;
403
+ /** `historyKind` groups rapid same-kind writes (e.g. keystrokes in one
404
+ * field) into a single undo step; `skipHistory` opts a caller out of
405
+ * history entirely (e.g. transient UI-only patches). */
406
+ setNodes: (nodes: Node[], opts?: {
407
+ historyKind?: string;
408
+ skipHistory?: boolean;
409
+ }) => void;
380
410
  deleteNode: (node: Node) => void;
411
+ /** Bulk delete (multi-select) — one undo step for the whole selection. */
412
+ deleteNodes: (nodes: Node[]) => void;
413
+ /** Clone the given nodes (+ edges strictly between them) with fresh ids,
414
+ * offset on the canvas, and select only the clones. */
415
+ duplicateNodes: (nodeIds: string[]) => void;
416
+ /** Insert a clipboard payload (possibly from another workflow/tab):
417
+ * fresh ids, offset, selects the pasted nodes. */
418
+ pasteNodes: (payload: {
419
+ nodes: Node[];
420
+ edges: Edge[];
421
+ }) => void;
422
+ toggleDisabled: (nodeId: string) => void;
423
+ renameNode: (nodeId: string, label: string) => void;
424
+ startRename: (nodeId: string) => void;
425
+ endRename: () => void;
381
426
  };
382
427
  edges: {
383
428
  onEdgesChange: (changes: EdgeChange[]) => void;
384
429
  onConnect: (connection: Connection) => void;
385
- setEdges: (edges: Edge[]) => void;
430
+ setEdges: (edges: Edge[], opts?: {
431
+ historyKind?: string;
432
+ skipHistory?: boolean;
433
+ }) => void;
386
434
  deleteEdge: (edge: Edge) => void;
387
435
  };
388
436
  ndv: {
@@ -433,6 +481,9 @@ interface Actions {
433
481
  }
434
482
  interface IFlowState {
435
483
  tags: Tag[];
484
+ /** Undo/redo stacks — canvas structure (nodes/edges) AND parameter edits,
485
+ * since both flow through the same `setNodes`/`setEdges` writes. */
486
+ history: HistoryState;
436
487
  workflow: {
437
488
  id: string;
438
489
  workflowKey: string;
@@ -1,4 +1,4 @@
1
- export { I as IFlowState, W as WorkflowBuilder, o as WorkflowBuilderCore, p as WorkflowBuilderCoreProps, n as WorkflowBuilderPage, q as WorkflowBuilderProps, w as WorkflowSearchRedirect, x as refetchStoreNodes, y as useFlowStore } from './workflow-builder-JKkdIJoP.js';
1
+ export { I as IFlowState, W as WorkflowBuilder, o as WorkflowBuilderCore, p as WorkflowBuilderCoreProps, n as WorkflowBuilderPage, q as WorkflowBuilderProps, w as WorkflowSearchRedirect, x as refetchStoreNodes, y as useFlowStore } from './workflow-builder-BNWKK8C7.js';
2
2
  import 'react/jsx-runtime';
3
3
  import '@apollo/client/core';
4
4
  import '@xyflow/react';
@@ -1,13 +1,13 @@
1
- export { WorkflowBuilder, WorkflowBuilderCore, WorkflowSearchRedirect } from './chunk-ND4ACNAW.js';
2
- export { WorkflowBuilder as WorkflowBuilderPage } from './chunk-GCUAXFMW.js';
3
- export { refetchStoreNodes } from './chunk-XASNLRFQ.js';
1
+ export { WorkflowBuilder, WorkflowBuilderCore, WorkflowSearchRedirect } from './chunk-TCMY3ZN3.js';
2
+ export { WorkflowBuilder as WorkflowBuilderPage } from './chunk-T6EWXQBI.js';
3
+ export { refetchStoreNodes } from './chunk-2RVL6DT3.js';
4
4
  import './chunk-P5PKRQAO.js';
5
5
  import './chunk-NH5YCY37.js';
6
6
  import './chunk-DBOMRIP5.js';
7
7
  import './chunk-BQXHJIER.js';
8
8
  import './chunk-6LXMUIR3.js';
9
9
  import './chunk-XQP33UJR.js';
10
- export { useFlowStore } from './chunk-KT72XMAB.js';
10
+ export { useFlowStore } from './chunk-I3WUYESA.js';
11
11
  import './chunk-UIY2HBWA.js';
12
12
  import './chunk-3ZYUGTIT.js';
13
13
  import './chunk-ELB3LXRJ.js';
@@ -1,5 +1,5 @@
1
- export { WorkflowsList } from './chunk-YAADZDGX.js';
2
- import './chunk-KT72XMAB.js';
1
+ export { WorkflowsList } from './chunk-K4U4WX4R.js';
2
+ import './chunk-I3WUYESA.js';
3
3
  import './chunk-UIY2HBWA.js';
4
4
  import './chunk-3ZYUGTIT.js';
5
5
  import './chunk-ELB3LXRJ.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/fluidgrids-fe-sdk",
3
- "version": "2026.922.1",
3
+ "version": "2026.922.3",
4
4
  "description": "FluidGrids Workflow Builder SDK - Embeddable visual workflow automation",
5
5
  "type": "module",
6
6
  "imports": {
@@ -1,379 +0,0 @@
1
- import { useTr } from './chunk-7YWBH2A5.js';
2
- import { nanoid } from 'nanoid/non-secure';
3
- import { addEdge, applyEdgeChanges, applyNodeChanges } from '@xyflow/react';
4
- import { create } from 'zustand';
5
- import { produce } from 'immer';
6
- import { AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction } from '@burdenoff/fe-libs/ui';
7
- import { jsx, jsxs } from 'react/jsx-runtime';
8
-
9
- var TAGS = [
10
- { value: "marketing", label: "Marketing", color: "#ef4444" },
11
- { value: "support", label: "Support", color: "#ef4444" },
12
- { value: "lead", label: "Lead", color: "#eab308" },
13
- { value: "new", label: "New", color: "#22c55e" }
14
- ];
15
- var INITIAL_EXECUTION = {
16
- isExecuting: false,
17
- executingNodeId: null,
18
- currentRunId: null,
19
- logs: [],
20
- selectedLogId: null,
21
- panelExpanded: false,
22
- nodeStatuses: {},
23
- nodeItemCounts: {}
24
- };
25
- var useFlowStore = create()((set, get) => ({
26
- tags: TAGS,
27
- workflow: {
28
- id: nanoid(),
29
- workflowKey: "",
30
- name: "",
31
- version: "",
32
- alias: "",
33
- edges: [],
34
- nodes: [],
35
- ndv: null,
36
- quickConfig: null,
37
- pendingConnection: null,
38
- sidebar: {
39
- active: "none",
40
- panels: {
41
- nodeProperties: {
42
- selectedNode: null
43
- }
44
- }
45
- }
46
- },
47
- execution: { ...INITIAL_EXECUTION },
48
- actions: {
49
- saveWorkflow: () => {
50
- const { workflow } = get();
51
- const { id, name, version, alias, dbId, status, nodes, edges } = workflow;
52
- set({ workflow });
53
- return { id, name, version, alias, dbId, status, nodes, edges };
54
- },
55
- setWorkflow: (workflow) => {
56
- set((state) => ({
57
- workflow: {
58
- ...state.workflow,
59
- ...workflow
60
- }
61
- }));
62
- },
63
- resetWorkflow: () => {
64
- set(() => ({
65
- workflow: {
66
- id: nanoid(),
67
- workflowKey: "",
68
- name: "",
69
- version: "",
70
- alias: "",
71
- dbId: void 0,
72
- status: void 0,
73
- edges: [],
74
- nodes: [],
75
- ndv: null,
76
- quickConfig: null,
77
- pendingConnection: null,
78
- sidebar: {
79
- active: "none",
80
- panels: {
81
- nodeProperties: {
82
- selectedNode: null
83
- }
84
- }
85
- }
86
- },
87
- // Wipe run state too — resetWorkflow fires when the builder loads a
88
- // (different) workflow, so the previous workflow's logs must not carry
89
- // over into this one's Logs panel.
90
- execution: { ...INITIAL_EXECUTION }
91
- }));
92
- },
93
- ndv: {
94
- // Opening the full NDV supersedes the floating quick-config panel — the
95
- // two edit the same node data, so only one should be visible at a time.
96
- open: (node) => set((state) => ({
97
- workflow: { ...state.workflow, ndv: node, quickConfig: null }
98
- })),
99
- close: () => set((state) => ({
100
- workflow: { ...state.workflow, ndv: null }
101
- }))
102
- },
103
- quickConfig: {
104
- open: (node) => set((state) => ({
105
- workflow: { ...state.workflow, quickConfig: node }
106
- })),
107
- close: () => set((state) => ({
108
- workflow: { ...state.workflow, quickConfig: null }
109
- }))
110
- },
111
- pendingConnection: {
112
- start: (connection) => set((state) => ({
113
- workflow: {
114
- ...state.workflow,
115
- pendingConnection: connection,
116
- sidebar: { ...state.workflow.sidebar, active: "store-browse" }
117
- }
118
- })),
119
- clear: () => set((state) => ({
120
- workflow: { ...state.workflow, pendingConnection: null }
121
- }))
122
- },
123
- sidebar: {
124
- // Leaving the store panel abandons any armed "+" attach mode — the
125
- // pending handle would otherwise silently capture a later insert.
126
- setActivePanel: (panel) => set((state) => ({
127
- workflow: {
128
- ...state.workflow,
129
- sidebar: { ...state.workflow.sidebar, active: panel },
130
- ...panel !== "store-browse" ? { pendingConnection: null } : {}
131
- }
132
- })),
133
- showNodePropertiesOf: (node) => {
134
- set((state) => ({
135
- workflow: {
136
- ...state.workflow,
137
- pendingConnection: null,
138
- sidebar: {
139
- ...state.workflow.sidebar,
140
- active: "node-properties",
141
- panels: {
142
- ...state.workflow.sidebar.panels,
143
- nodeProperties: {
144
- ...state.workflow.sidebar.panels.nodeProperties,
145
- selectedNode: node
146
- }
147
- }
148
- }
149
- }
150
- }));
151
- },
152
- panels: {
153
- nodeProperties: {
154
- setSelectedNode: (node) => set((state) => ({
155
- workflow: {
156
- ...state.workflow,
157
- sidebar: {
158
- ...state.workflow.sidebar,
159
- panels: {
160
- ...state.workflow.sidebar.panels,
161
- nodeProperties: {
162
- ...state.workflow.sidebar.panels.nodeProperties,
163
- selectedNode: node
164
- }
165
- }
166
- }
167
- }
168
- }))
169
- },
170
- tags: {
171
- setTags: (tags) => set({ tags }),
172
- createTag: (tag) => set((state) => ({
173
- tags: [...state.tags, tag]
174
- })),
175
- updateTag: (tag, newTag) => set((state) => ({
176
- tags: state.tags.map((f) => f.value === tag.value ? newTag : f)
177
- })),
178
- deleteTag: (tag) => set((state) => ({
179
- tags: state.tags.filter((f) => f.value !== tag.value)
180
- }))
181
- }
182
- }
183
- },
184
- nodes: {
185
- onNodesChange: (changes) => {
186
- set(
187
- (state) => produce(state, (draft) => {
188
- const updatedNodes = applyNodeChanges(
189
- changes,
190
- draft.workflow.nodes
191
- );
192
- draft.workflow.nodes = updatedNodes;
193
- })
194
- );
195
- },
196
- setNodes: (nodes) => {
197
- set({ workflow: { ...get().workflow, nodes } });
198
- },
199
- deleteNode: (node) => {
200
- set((state) => ({
201
- workflow: {
202
- ...state.workflow,
203
- nodes: state.workflow.nodes.filter((n) => n.id !== node.id),
204
- // Drop any UI state pointing at the removed node.
205
- ...state.workflow.quickConfig?.nodeId === node.id ? { quickConfig: null } : {},
206
- ...state.workflow.pendingConnection?.nodeId === node.id ? { pendingConnection: null } : {}
207
- }
208
- }));
209
- }
210
- },
211
- edges: {
212
- onEdgesChange: (changes) => {
213
- set(
214
- (state) => produce(state, (draft) => {
215
- const updatedEdges = applyEdgeChanges(
216
- changes,
217
- draft.workflow.edges
218
- );
219
- draft.workflow.edges = updatedEdges;
220
- })
221
- );
222
- },
223
- onConnect: (connection) => {
224
- const edge = { ...connection, id: nanoid(), type: "deletable" };
225
- set({
226
- workflow: {
227
- ...get().workflow,
228
- edges: addEdge(edge, get().workflow.edges)
229
- }
230
- });
231
- },
232
- setEdges: (edges) => {
233
- set({ workflow: { ...get().workflow, edges } });
234
- },
235
- deleteEdge: (edge) => {
236
- set((state) => ({
237
- workflow: {
238
- ...state.workflow,
239
- edges: state.workflow.edges.filter((e) => e.id !== edge.id)
240
- }
241
- }));
242
- }
243
- },
244
- execution: {
245
- startExecution: (nodeId, runId) => {
246
- set((state) => ({
247
- execution: {
248
- ...state.execution,
249
- isExecuting: true,
250
- executingNodeId: nodeId,
251
- currentRunId: runId,
252
- panelExpanded: true,
253
- nodeStatuses: {
254
- ...state.execution.nodeStatuses,
255
- [nodeId]: "running"
256
- }
257
- }
258
- }));
259
- },
260
- addLog: (log) => {
261
- set((state) => ({
262
- execution: {
263
- ...state.execution,
264
- logs: [...state.execution.logs, log],
265
- selectedLogId: log.id
266
- }
267
- }));
268
- },
269
- updateLog: (logId, updates) => {
270
- set((state) => ({
271
- execution: {
272
- ...state.execution,
273
- logs: state.execution.logs.map(
274
- (log) => log.id === logId ? { ...log, ...updates } : log
275
- )
276
- }
277
- }));
278
- },
279
- setNodeStatus: (nodeId, status) => {
280
- set((state) => ({
281
- execution: {
282
- ...state.execution,
283
- nodeStatuses: {
284
- ...state.execution.nodeStatuses,
285
- [nodeId]: status
286
- }
287
- }
288
- }));
289
- },
290
- setNodeItemCount: (nodeId, count) => {
291
- set((state) => ({
292
- execution: {
293
- ...state.execution,
294
- nodeItemCounts: {
295
- ...state.execution.nodeItemCounts,
296
- [nodeId]: count
297
- }
298
- }
299
- }));
300
- },
301
- selectLog: (logId) => {
302
- set((state) => ({
303
- execution: {
304
- ...state.execution,
305
- selectedLogId: logId
306
- }
307
- }));
308
- },
309
- togglePanel: () => {
310
- set((state) => ({
311
- execution: {
312
- ...state.execution,
313
- panelExpanded: !state.execution.panelExpanded
314
- }
315
- }));
316
- },
317
- clearLogs: () => {
318
- set((state) => ({
319
- execution: {
320
- ...state.execution,
321
- logs: [],
322
- selectedLogId: null,
323
- nodeStatuses: {},
324
- nodeItemCounts: {}
325
- }
326
- }));
327
- },
328
- completeExecution: () => {
329
- set((state) => ({
330
- execution: {
331
- ...state.execution,
332
- isExecuting: false,
333
- executingNodeId: null
334
- }
335
- }));
336
- }
337
- }
338
- }
339
- }));
340
- if (typeof window !== "undefined" && import.meta.env?.DEV) {
341
- window.__fgFlowStore = useFlowStore;
342
- }
343
- function QuotaExhaustedDialog({
344
- open,
345
- onOpenChange,
346
- onUpgrade,
347
- title,
348
- description
349
- }) {
350
- const tr = useTr();
351
- const resolvedTitle = title ?? tr(
352
- "fluidgrids.components.quotaExhaustedDialog.title",
353
- "Workflow Limit Reached"
354
- );
355
- const resolvedDescription = description ?? tr(
356
- "fluidgrids.components.quotaExhaustedDialog.description",
357
- "You've reached the workflow limit for your plan. Upgrade your plan to create more workflows."
358
- );
359
- return /* @__PURE__ */ jsx(AlertDialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(AlertDialogContent, { children: [
360
- /* @__PURE__ */ jsxs(AlertDialogHeader, { children: [
361
- /* @__PURE__ */ jsx(AlertDialogTitle, { children: resolvedTitle }),
362
- /* @__PURE__ */ jsx(AlertDialogDescription, { children: resolvedDescription })
363
- ] }),
364
- /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [
365
- /* @__PURE__ */ jsx(AlertDialogCancel, { children: tr(
366
- "fluidgrids.components.quotaExhaustedDialog.dismiss",
367
- "Dismiss"
368
- ) }),
369
- /* @__PURE__ */ jsx(AlertDialogAction, { onClick: onUpgrade, children: tr(
370
- "fluidgrids.components.quotaExhaustedDialog.viewBilling",
371
- "View Billing"
372
- ) })
373
- ] })
374
- ] }) });
375
- }
376
-
377
- export { QuotaExhaustedDialog, useFlowStore };
378
- //# sourceMappingURL=chunk-KT72XMAB.js.map
379
- //# sourceMappingURL=chunk-KT72XMAB.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/builder/stores/flow-store.ts","../src/components/shared/QuotaExhaustedDialog.tsx"],"names":[],"mappings":"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","file":"chunk-KT72XMAB.js","sourcesContent":["import { nanoid } from \"nanoid/non-secure\";\nimport {\n addEdge,\n applyEdgeChanges,\n applyNodeChanges,\n type Connection,\n type Edge,\n type EdgeChange,\n type Node,\n type NodeChange,\n} from \"@xyflow/react\";\nimport { create } from \"zustand\";\nimport { produce } from \"immer\";\nimport type {\n ExtendedNodeType,\n EdgeCondition,\n EdgeMapping,\n} from \"../../types/node\";\nimport type { Tag } from \"../../types/workflow\";\nimport type { ExecutionLog } from \"../../types/execution\";\n\n// Node execution state for visual display\nexport interface NodeExecutionState {\n status: \"idle\" | \"running\" | \"success\" | \"error\";\n itemCount?: number;\n error?: string;\n}\n\n// Execution state for step execution feature\ninterface ExecutionState {\n isExecuting: boolean;\n executingNodeId: string | null;\n currentRunId: string | null;\n logs: ExecutionLog[];\n selectedLogId: string | null;\n panelExpanded: boolean;\n nodeStatuses: Record<string, \"idle\" | \"running\" | \"success\" | \"error\">;\n nodeItemCounts: Record<string, number>;\n}\n\ninterface CustomEdgeProps extends Edge {\n condition?: EdgeCondition;\n mapping?: EdgeMapping;\n}\n\ninterface State {\n nodes: Node[];\n edges: CustomEdgeProps[];\n /** Node currently open in the n8n-style 3-pane Node Detail View modal. */\n ndv?: { nodeId: string; type: ExtendedNodeType } | null;\n /**\n * Node currently open in the single-click floating quick-config panel\n * (Make-style, attached beside the node). The panel derives its own screen\n * position from the node's live rect, so no anchor is stored here.\n */\n quickConfig?: {\n nodeId: string;\n type: ExtendedNodeType;\n } | null;\n /**\n * Source handle awaiting attachment via the Node Store (the n8n-style \"+\"\n * button on an output handle). While set, clicking an operation in the\n * store panel creates the node and wires it to this handle.\n */\n pendingConnection?: { nodeId: string; handleId: string } | null;\n sidebar: {\n active: \"node-properties\" | \"store-browse\" | \"none\";\n panels: {\n nodeProperties: {\n selectedNode: { id: string; type: ExtendedNodeType } | null | undefined;\n };\n };\n };\n}\n\ninterface Actions {\n actions: {\n saveWorkflow: () => {\n id: string;\n name: string;\n version: string;\n alias?: string;\n dbId?: string;\n status?: string;\n nodes: Node[];\n edges: Edge[];\n };\n setWorkflow: (workflow: Partial<IFlowState[\"workflow\"]>) => void;\n resetWorkflow: () => void;\n nodes: {\n onNodesChange: (changes: NodeChange[]) => void;\n setNodes: (nodes: Node[]) => void;\n deleteNode: (node: Node) => void;\n };\n edges: {\n onEdgesChange: (changes: EdgeChange[]) => void;\n onConnect: (connection: Connection) => void;\n setEdges: (edges: Edge[]) => void;\n deleteEdge: (edge: Edge) => void;\n };\n ndv: {\n open: (node: { nodeId: string; type: ExtendedNodeType }) => void;\n close: () => void;\n };\n quickConfig: {\n open: (node: { nodeId: string; type: ExtendedNodeType }) => void;\n close: () => void;\n };\n pendingConnection: {\n /** Arm attach mode for a source handle and open the Node Store panel. */\n start: (connection: { nodeId: string; handleId: string }) => void;\n clear: () => void;\n };\n sidebar: {\n setActivePanel: (\n panel: \"node-properties\" | \"store-browse\" | \"none\",\n ) => void;\n showNodePropertiesOf: (node: {\n id: string;\n type: ExtendedNodeType;\n block?: string;\n }) => void;\n panels: {\n nodeProperties: {\n setSelectedNode: (\n node: { id: string; type: ExtendedNodeType } | undefined | null,\n ) => void;\n };\n tags: {\n setTags: (tags: Tag[]) => void;\n createTag: (tag: Tag) => void;\n deleteTag: (tag: Tag) => void;\n updateTag: (tag: Tag, newTag: Tag) => void;\n };\n };\n };\n };\n}\n\nexport interface IFlowState {\n tags: Tag[];\n workflow: {\n id: string;\n workflowKey: string;\n name: string;\n version: string;\n alias?: string;\n /** Database row ID (used for updateWorkflowDefinition) */\n dbId?: string;\n /** Current workflow status: DRAFT | ACTIVE | ARCHIVED | DEPRECATED */\n status?: string;\n } & State;\n execution: ExecutionState;\n actions: Actions[\"actions\"] & {\n execution: {\n startExecution: (nodeId: string, runId: string) => void;\n addLog: (log: ExecutionLog) => void;\n updateLog: (logId: string, updates: Partial<ExecutionLog>) => void;\n setNodeStatus: (\n nodeId: string,\n status: \"idle\" | \"running\" | \"success\" | \"error\",\n ) => void;\n setNodeItemCount: (nodeId: string, count: number) => void;\n selectLog: (logId: string | null) => void;\n togglePanel: () => void;\n clearLogs: () => void;\n completeExecution: () => void;\n };\n };\n}\n\nconst TAGS: Tag[] = [\n { value: \"marketing\", label: \"Marketing\", color: \"#ef4444\" },\n { value: \"support\", label: \"Support\", color: \"#ef4444\" },\n { value: \"lead\", label: \"Lead\", color: \"#eab308\" },\n { value: \"new\", label: \"New\", color: \"#22c55e\" },\n];\n\n/**\n * Pristine execution state. The `execution` slice is global (one run at a\n * time), so it MUST be reset whenever a different workflow is loaded —\n * otherwise the previous workflow's run logs leak into the next workflow's\n * Logs panel. Shared by the store initializer and `resetWorkflow`.\n */\nconst INITIAL_EXECUTION: ExecutionState = {\n isExecuting: false,\n executingNodeId: null,\n currentRunId: null,\n logs: [],\n selectedLogId: null,\n panelExpanded: false,\n nodeStatuses: {},\n nodeItemCounts: {},\n};\n\nexport const useFlowStore = create<IFlowState>()((set, get) => ({\n tags: TAGS,\n workflow: {\n id: nanoid(),\n workflowKey: \"\",\n name: \"\",\n version: \"\",\n alias: \"\",\n edges: [],\n nodes: [],\n ndv: null,\n quickConfig: null,\n pendingConnection: null,\n sidebar: {\n active: \"none\",\n panels: {\n nodeProperties: {\n selectedNode: null,\n },\n },\n },\n },\n execution: { ...INITIAL_EXECUTION },\n actions: {\n saveWorkflow: () => {\n const { workflow } = get();\n const { id, name, version, alias, dbId, status, nodes, edges } = workflow;\n set({ workflow });\n return { id, name, version, alias, dbId, status, nodes, edges };\n },\n setWorkflow: (workflow: Partial<IFlowState[\"workflow\"]>) => {\n set((state) => ({\n workflow: {\n ...state.workflow,\n ...workflow,\n },\n }));\n },\n resetWorkflow: () => {\n set(() => ({\n workflow: {\n id: nanoid(),\n workflowKey: \"\",\n name: \"\",\n version: \"\",\n alias: \"\",\n dbId: undefined,\n status: undefined,\n edges: [],\n nodes: [],\n ndv: null,\n quickConfig: null,\n pendingConnection: null,\n sidebar: {\n active: \"none\",\n panels: {\n nodeProperties: {\n selectedNode: null,\n },\n },\n },\n },\n // Wipe run state too — resetWorkflow fires when the builder loads a\n // (different) workflow, so the previous workflow's logs must not carry\n // over into this one's Logs panel.\n execution: { ...INITIAL_EXECUTION },\n }));\n },\n ndv: {\n // Opening the full NDV supersedes the floating quick-config panel — the\n // two edit the same node data, so only one should be visible at a time.\n open: (node: { nodeId: string; type: ExtendedNodeType }) =>\n set((state) => ({\n workflow: { ...state.workflow, ndv: node, quickConfig: null },\n })),\n close: () =>\n set((state) => ({\n workflow: { ...state.workflow, ndv: null },\n })),\n },\n quickConfig: {\n open: (node: { nodeId: string; type: ExtendedNodeType }) =>\n set((state) => ({\n workflow: { ...state.workflow, quickConfig: node },\n })),\n close: () =>\n set((state) => ({\n workflow: { ...state.workflow, quickConfig: null },\n })),\n },\n pendingConnection: {\n start: (connection: { nodeId: string; handleId: string }) =>\n set((state) => ({\n workflow: {\n ...state.workflow,\n pendingConnection: connection,\n sidebar: { ...state.workflow.sidebar, active: \"store-browse\" },\n },\n })),\n clear: () =>\n set((state) => ({\n workflow: { ...state.workflow, pendingConnection: null },\n })),\n },\n sidebar: {\n // Leaving the store panel abandons any armed \"+\" attach mode — the\n // pending handle would otherwise silently capture a later insert.\n setActivePanel: (panel: \"node-properties\" | \"store-browse\" | \"none\") =>\n set((state) => ({\n workflow: {\n ...state.workflow,\n sidebar: { ...state.workflow.sidebar, active: panel },\n ...(panel !== \"store-browse\" ? { pendingConnection: null } : {}),\n },\n })),\n showNodePropertiesOf: (node: { id: string; type: ExtendedNodeType }) => {\n set((state) => ({\n workflow: {\n ...state.workflow,\n pendingConnection: null,\n sidebar: {\n ...state.workflow.sidebar,\n active: \"node-properties\",\n panels: {\n ...state.workflow.sidebar.panels,\n nodeProperties: {\n ...state.workflow.sidebar.panels.nodeProperties,\n selectedNode: node,\n },\n },\n },\n },\n }));\n },\n panels: {\n nodeProperties: {\n setSelectedNode: (\n node: { id: string; type: ExtendedNodeType } | undefined | null,\n ) =>\n set((state) => ({\n workflow: {\n ...state.workflow,\n sidebar: {\n ...state.workflow.sidebar,\n panels: {\n ...state.workflow.sidebar.panels,\n nodeProperties: {\n ...state.workflow.sidebar.panels.nodeProperties,\n selectedNode: node,\n },\n },\n },\n },\n })),\n },\n tags: {\n setTags: (tags: Tag[]) => set({ tags }),\n createTag: (tag: Tag) =>\n set((state) => ({\n tags: [...state.tags, tag],\n })),\n updateTag: (tag: Tag, newTag: Tag) =>\n set((state) => ({\n tags: state.tags.map((f) => (f.value === tag.value ? newTag : f)),\n })),\n deleteTag: (tag: Tag) =>\n set((state) => ({\n tags: state.tags.filter((f) => f.value !== tag.value),\n })),\n },\n },\n },\n nodes: {\n onNodesChange: (changes) => {\n set((state) =>\n produce(state, (draft) => {\n const updatedNodes = applyNodeChanges(\n changes,\n draft.workflow.nodes,\n );\n draft.workflow.nodes = updatedNodes;\n }),\n );\n },\n setNodes: (nodes) => {\n set({ workflow: { ...get().workflow, nodes } });\n },\n deleteNode: (node: Node) => {\n set((state) => ({\n workflow: {\n ...state.workflow,\n nodes: state.workflow.nodes.filter((n) => n.id !== node.id),\n // Drop any UI state pointing at the removed node.\n ...(state.workflow.quickConfig?.nodeId === node.id\n ? { quickConfig: null }\n : {}),\n ...(state.workflow.pendingConnection?.nodeId === node.id\n ? { pendingConnection: null }\n : {}),\n },\n }));\n },\n },\n edges: {\n onEdgesChange: (changes) => {\n set((state) =>\n produce(state, (draft) => {\n const updatedEdges = applyEdgeChanges(\n changes,\n draft.workflow.edges,\n );\n draft.workflow.edges = updatedEdges;\n }),\n );\n },\n onConnect: (connection) => {\n const edge = { ...connection, id: nanoid(), type: \"deletable\" } as Edge;\n set({\n workflow: {\n ...get().workflow,\n edges: addEdge(edge, get().workflow.edges),\n },\n });\n },\n setEdges: (edges) => {\n set({ workflow: { ...get().workflow, edges } });\n },\n deleteEdge: (edge: Edge) => {\n set((state) => ({\n workflow: {\n ...state.workflow,\n edges: state.workflow.edges.filter((e) => e.id !== edge.id),\n },\n }));\n },\n },\n execution: {\n startExecution: (nodeId: string, runId: string) => {\n set((state) => ({\n execution: {\n ...state.execution,\n isExecuting: true,\n executingNodeId: nodeId,\n currentRunId: runId,\n panelExpanded: true,\n nodeStatuses: {\n ...state.execution.nodeStatuses,\n [nodeId]: \"running\",\n },\n },\n }));\n },\n addLog: (log: ExecutionLog) => {\n set((state) => ({\n execution: {\n ...state.execution,\n logs: [...state.execution.logs, log],\n selectedLogId: log.id,\n },\n }));\n },\n updateLog: (logId: string, updates: Partial<ExecutionLog>) => {\n set((state) => ({\n execution: {\n ...state.execution,\n logs: state.execution.logs.map((log) =>\n log.id === logId ? { ...log, ...updates } : log,\n ),\n },\n }));\n },\n setNodeStatus: (\n nodeId: string,\n status: \"idle\" | \"running\" | \"success\" | \"error\",\n ) => {\n set((state) => ({\n execution: {\n ...state.execution,\n nodeStatuses: {\n ...state.execution.nodeStatuses,\n [nodeId]: status,\n },\n },\n }));\n },\n setNodeItemCount: (nodeId: string, count: number) => {\n set((state) => ({\n execution: {\n ...state.execution,\n nodeItemCounts: {\n ...state.execution.nodeItemCounts,\n [nodeId]: count,\n },\n },\n }));\n },\n selectLog: (logId: string | null) => {\n set((state) => ({\n execution: {\n ...state.execution,\n selectedLogId: logId,\n },\n }));\n },\n togglePanel: () => {\n set((state) => ({\n execution: {\n ...state.execution,\n panelExpanded: !state.execution.panelExpanded,\n },\n }));\n },\n clearLogs: () => {\n set((state) => ({\n execution: {\n ...state.execution,\n logs: [],\n selectedLogId: null,\n nodeStatuses: {},\n nodeItemCounts: {},\n },\n }));\n },\n completeExecution: () => {\n set((state) => ({\n execution: {\n ...state.execution,\n isExecuting: false,\n executingNodeId: null,\n },\n }));\n },\n },\n },\n}));\n\n// Dev-only debug handle so the store can be inspected/driven from the browser\n// console or automated tests. No-op in production builds.\nif (typeof window !== \"undefined\" && import.meta.env?.DEV) {\n (window as unknown as Record<string, unknown>).__fgFlowStore = useFlowStore;\n}\n","import {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from \"@burdenoff/fe-libs/ui\";\nimport { useTr } from \"../../hooks/useTr\";\n\ninterface QuotaExhaustedDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Called when the user clicks \"View Billing\". */\n onUpgrade: () => void;\n title?: string;\n description?: string;\n}\n\n/**\n * Alert shown when a workflow-creating action (save/duplicate/import) is\n * rejected with `QUOTA_EXHAUSTED` for `fluidgrids.workflows.count`. Mirrors\n * the \"Folder Limit Reached\" dialog in microfe-files' BrowserPage.tsx, built\n * on the same `AlertDialog` primitives already used elsewhere in this SDK\n * (see card-workflow.tsx's delete-confirmation dialog).\n */\nexport function QuotaExhaustedDialog({\n open,\n onOpenChange,\n onUpgrade,\n title,\n description,\n}: QuotaExhaustedDialogProps) {\n const tr = useTr();\n // Defaults are resolved here rather than as default parameter values so the\n // copy can go through `tr()` — a hook cannot be called in a parameter list.\n const resolvedTitle =\n title ??\n tr(\n \"fluidgrids.components.quotaExhaustedDialog.title\",\n \"Workflow Limit Reached\",\n );\n const resolvedDescription =\n description ??\n tr(\n \"fluidgrids.components.quotaExhaustedDialog.description\",\n \"You've reached the workflow limit for your plan. Upgrade your plan to create more workflows.\",\n );\n\n return (\n <AlertDialog open={open} onOpenChange={onOpenChange}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>{resolvedTitle}</AlertDialogTitle>\n <AlertDialogDescription>{resolvedDescription}</AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>\n {tr(\n \"fluidgrids.components.quotaExhaustedDialog.dismiss\",\n \"Dismiss\",\n )}\n </AlertDialogCancel>\n <AlertDialogAction onClick={onUpgrade}>\n {tr(\n \"fluidgrids.components.quotaExhaustedDialog.viewBilling\",\n \"View Billing\",\n )}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n"]}