flowstudio 0.0.31 → 0.0.33

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 (50) hide show
  1. package/README.md +6 -6
  2. package/dist/ai_creator.js +1 -9
  3. package/dist/ai_creator.js.map +1 -1
  4. package/dist/api_calls.js +5 -6
  5. package/dist/api_calls.js.map +1 -1
  6. package/dist/app_settings.js +3 -2
  7. package/dist/app_settings.js.map +1 -1
  8. package/dist/channels.d.ts +16 -0
  9. package/dist/channels.js +133 -0
  10. package/dist/channels.js.map +1 -0
  11. package/dist/components/mention_input/index.js +1 -1
  12. package/dist/constants.js +7 -5
  13. package/dist/constants.js.map +1 -1
  14. package/dist/context.js +1 -1
  15. package/dist/context.js.map +1 -1
  16. package/dist/globals.css +19 -8
  17. package/dist/home.d.ts +1 -1
  18. package/dist/home.js +55 -27
  19. package/dist/home.js.map +1 -1
  20. package/dist/index.d.ts +17 -1
  21. package/dist/index.js +29 -11
  22. package/dist/index.js.map +1 -1
  23. package/dist/new_project.js +52 -29
  24. package/dist/new_project.js.map +1 -1
  25. package/dist/node.js +8 -13
  26. package/dist/node.js.map +1 -1
  27. package/dist/providers/index.d.ts +4 -0
  28. package/dist/providers/index.js +97 -0
  29. package/dist/providers/index.js.map +1 -0
  30. package/dist/secrets.js +3 -2
  31. package/dist/secrets.js.map +1 -1
  32. package/dist/simulator.js +182 -62
  33. package/dist/simulator.js.map +1 -1
  34. package/dist/studio_pane.js +118 -80
  35. package/dist/studio_pane.js.map +1 -1
  36. package/dist/styles/globals.css +2 -2
  37. package/dist/styles.css +1 -1
  38. package/dist/top_left_panel.d.ts +1 -1
  39. package/dist/top_left_panel.js +2 -2
  40. package/dist/top_left_panel.js.map +1 -1
  41. package/dist/top_right_panel.js +1 -1
  42. package/dist/top_right_panel.js.map +1 -1
  43. package/dist/triggers.js +129 -87
  44. package/dist/triggers.js.map +1 -1
  45. package/dist/zustand/store.d.ts +92 -0
  46. package/dist/zustand/store.js +4 -0
  47. package/dist/zustand/store.js.map +1 -1
  48. package/package.json +4 -3
  49. package/src/globals.css +19 -8
  50. package/src/styles/globals.css +2 -2
package/dist/simulator.js CHANGED
@@ -1,78 +1,198 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from "react";
2
3
  import { Button } from "@osanim/shared";
3
- import { Card } from "@osanim/shared";
4
- import { Spinner } from "@osanim/shared";
5
4
  import { Popover, PopoverContent, PopoverTrigger } from "@osanim/shared";
6
5
  import { Tooltip, TooltipContent, TooltipTrigger } from "@osanim/shared";
7
6
  import { Tabs, TabsList, TabsTrigger } from "@osanim/shared";
8
- import { useForm } from "react-hook-form";
9
- import { IoReload } from "react-icons/io5";
10
- import { useState } from "react";
11
- import parse from 'html-react-parser';
12
- import { SendHorizonalIcon } from "lucide-react";
7
+ import { Spinner } from "@osanim/shared";
8
+ import { RotateCcw } from "lucide-react";
13
9
  import { MdOutlinePhoneAndroid } from "react-icons/md";
14
10
  import flow_constants from "./constants";
15
- import { Form, FormControl, FormField, FormItem, FormMessage } from "@osanim/shared";
16
- import { zodResolver } from "@hookform/resolvers/zod";
17
- import * as Zod from "zod";
18
- import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "@osanim/shared";
11
+ const THEME = {
12
+ ussd: {
13
+ shellBorder: '#3a3a3a',
14
+ headerBg: '#111111', headerText: 'rgba(255,255,255,0.75)',
15
+ chatBg: '#0a0a0a', chatExtra: {},
16
+ botBubble: '#1c1c1e', botText: 'rgba(255,255,255,0.9)',
17
+ userBubble: '#0a84ff', userText: '#fff',
18
+ inputBg: '#111111', inputField: '#2c2c2e', sendBg: '#0a84ff',
19
+ optionBorder: 'rgba(255,255,255,0.15)', optionText: 'rgba(255,255,255,0.75)',
20
+ },
21
+ whatsapp: {
22
+ shellBorder: '#3a3a3a',
23
+ headerBg: '#1f2c34', headerText: '#e9edef',
24
+ chatBg: '#0b141a',
25
+ chatExtra: {
26
+ backgroundImage: `url("data:image/svg+xml,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40"><path d="M20 2L38 20L20 38L2 20Z" fill="none" stroke="rgba(255,255,255,0.025)" stroke-width="0.8"/></svg>')}")`,
27
+ backgroundRepeat: 'repeat',
28
+ backgroundSize: '40px 40px',
29
+ },
30
+ botBubble: '#1f2c34', botText: '#e9edef',
31
+ userBubble: '#005c4b', userText: '#e9edef',
32
+ inputBg: '#1f2c34', inputField: '#2a3942', sendBg: '#00a884',
33
+ optionBorder: '#00a884', optionText: '#00a884',
34
+ },
35
+ telegram: {
36
+ shellBorder: '#3a3a3a',
37
+ headerBg: '#232e3c', headerText: '#ffffff',
38
+ chatBg: '#17212b',
39
+ chatExtra: {
40
+ backgroundImage: `url("data:image/svg+xml,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60"><circle cx="30" cy="30" r="1.2" fill="rgba(255,255,255,0.03)"/><circle cx="0" cy="0" r="1.2" fill="rgba(255,255,255,0.03)"/><circle cx="60" cy="60" r="1.2" fill="rgba(255,255,255,0.03)"/></svg>')}")`,
41
+ backgroundRepeat: 'repeat',
42
+ backgroundSize: '60px 60px',
43
+ },
44
+ botBubble: '#182533', botText: 'rgba(255,255,255,0.9)',
45
+ userBubble: '#2b5278', userText: '#ffffff',
46
+ inputBg: '#17212b', inputField: '#242f3d', sendBg: '#3390ec',
47
+ optionBorder: '#3390ec', optionText: '#3390ec',
48
+ },
49
+ };
50
+ const CHANNEL_LABELS = {
51
+ ussd: 'USSD Simulator',
52
+ whatsapp: 'WhatsApp',
53
+ telegram: 'Telegram',
54
+ };
55
+ function parseApiResponse(raw) {
56
+ const clean = raw.replace(/<br\s*\/?>/gi, '\n');
57
+ const lines = clean.split('\n');
58
+ const options = [];
59
+ const msgLines = [];
60
+ for (const line of lines) {
61
+ const m = line.match(/^(\d+)\.\s+(.+)$/);
62
+ if (m)
63
+ options.push({ id: parseInt(m[1]), text: m[2].trim() });
64
+ else
65
+ msgLines.push(line);
66
+ }
67
+ return { message: msgLines.join('\n').replace(/^\n+|\n+$/g, ''), options };
68
+ }
19
69
  export default function Simulator({ api_key, projectId }) {
70
+ var _a;
20
71
  const [deploymentType, setDeploymentType] = useState('draft');
21
- const [flowMessage, setFlowMessage] = useState('');
22
- const [refreshing, setRefreshing] = useState(false);
23
- const simulatorEndpoint = `${flow_constants.SIMULATOR_ENDPOINT}`;
24
- const initialFormSubmit = async () => {
25
- setRefreshing(true);
26
- await onSubmit({
27
- production_type: deploymentType || "live",
28
- user_input: "800",
29
- sessionid: '1234567',
30
- msisdn: "024",
31
- mode: "start",
32
- trafficId: "123456789",
33
- trafficSource: "ussd"
34
- });
35
- setRefreshing(false);
36
- };
37
- const formSchema = Zod.object({
38
- user_input: Zod.string().min(1, 'required')
39
- });
40
- const form = useForm({
41
- resolver: zodResolver(formSchema),
42
- defaultValues: {
43
- user_input: ''
72
+ const [channel, setChannel] = useState('ussd');
73
+ const [loading, setLoading] = useState(false);
74
+ // USSD state
75
+ const [ussdText, setUssdText] = useState('');
76
+ const [ussdInput, setUssdInput] = useState('');
77
+ // Chat state (WhatsApp / Telegram)
78
+ const [history, setHistory] = useState([]);
79
+ const [chatInput, setChatInput] = useState('');
80
+ const sessionId = useRef('sim-' + Math.random().toString(36).slice(2, 8));
81
+ const chatContainerRef = useRef(null);
82
+ const interacted = useRef(false);
83
+ const openRef = useRef(false);
84
+ const channelRef = useRef(channel);
85
+ const deployRef = useRef(deploymentType);
86
+ channelRef.current = channel;
87
+ deployRef.current = deploymentType;
88
+ useEffect(() => {
89
+ if (interacted.current) {
90
+ const el = chatContainerRef.current;
91
+ if (el)
92
+ el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });
44
93
  }
45
- });
46
- const onSubmit = async (data) => {
94
+ }, [history, ussdText]);
95
+ const callApi = async (userdata, mode, ch = channelRef.current, dt = deployRef.current) => {
96
+ setLoading(true);
47
97
  try {
48
- // alert(data.user_input)
49
- const post_data = JSON.stringify({
50
- project_id: projectId,
51
- production_type: deploymentType,
52
- userdata: data.user_input,
53
- sessionid: '1234567',
54
- msisdn: "024",
55
- mode: (data === null || data === void 0 ? void 0 : data.mode) || "more",
56
- trafficId: "123456789",
57
- trafficSource: "ussd"
98
+ const res = await fetch(flow_constants.SIMULATOR_ENDPOINT, {
99
+ method: 'POST',
100
+ headers: { 'X-API-KEY': `${api_key}`, 'Content-Type': 'application/json' },
101
+ body: JSON.stringify({
102
+ project_id: projectId,
103
+ production_type: dt,
104
+ userdata,
105
+ sessionid: sessionId.current,
106
+ msisdn: '024',
107
+ mode,
108
+ trafficId: '123456789',
109
+ trafficSource: ch,
110
+ }),
58
111
  });
59
- const response = await fetch(`${simulatorEndpoint}`, { method: 'POST', body: post_data, headers: { "X-API-KEY": `${api_key}`, "Content-Type": "application/json" } });
60
- const response_text = await response.text();
61
- if (response.ok) {
62
- form.reset();
63
- form.setFocus('user_input');
64
- const new_message = response_text.replace(/\n/g, "<br>");
65
- setFlowMessage(new_message);
66
- }
67
- else {
68
- console.log(`simulator POST not successful: ${response_text}`);
69
- }
112
+ if (!res.ok)
113
+ return null;
114
+ return await res.text();
70
115
  }
71
- catch (e) {
72
- console.log(`Form Submit Error: ${e}`);
116
+ catch {
117
+ return null;
118
+ }
119
+ finally {
120
+ setLoading(false);
121
+ }
122
+ };
123
+ const start = async (ch = channelRef.current, dt = deployRef.current) => {
124
+ sessionId.current = 'sim-' + Math.random().toString(36).slice(2, 8);
125
+ interacted.current = false;
126
+ setUssdText('');
127
+ setUssdInput('');
128
+ setHistory([]);
129
+ setChatInput('');
130
+ const raw = await callApi('800', 'start', ch, dt);
131
+ if (!raw)
132
+ return;
133
+ if (ch === 'ussd') {
134
+ setUssdText(raw.replace(/<br\s*\/?>/gi, '\n'));
73
135
  }
136
+ else {
137
+ const p = parseApiResponse(raw);
138
+ setHistory([{ role: 'bot', text: p.message, options: p.options }]);
139
+ }
140
+ };
141
+ const handleOpenChange = (isOpen) => {
142
+ openRef.current = isOpen;
143
+ if (isOpen)
144
+ start();
145
+ };
146
+ const handleChannelChange = (v) => {
147
+ const ch = v;
148
+ setChannel(ch);
149
+ if (openRef.current)
150
+ start(ch);
151
+ };
152
+ const handleDeployChange = (v) => {
153
+ setDeploymentType(v);
154
+ if (openRef.current)
155
+ start(channelRef.current, v);
156
+ };
157
+ const ussdSend = async () => {
158
+ const val = ussdInput.trim();
159
+ if (!val || loading)
160
+ return;
161
+ interacted.current = true;
162
+ setUssdInput('');
163
+ const raw = await callApi(val, 'more');
164
+ if (raw)
165
+ setUssdText(raw.replace(/<br\s*\/?>/gi, '\n'));
166
+ };
167
+ const chatSend = async (displayText, inputValue) => {
168
+ if (loading)
169
+ return;
170
+ interacted.current = true;
171
+ setHistory(h => [...h, { role: 'user', text: displayText }]);
172
+ setChatInput('');
173
+ const raw = await callApi(inputValue, 'more');
174
+ if (!raw)
175
+ return;
176
+ const p = parseApiResponse(raw);
177
+ setHistory(h => [...h, { role: 'bot', text: p.message, options: p.options }]);
74
178
  };
75
- return (_jsxs(Popover, { onOpenChange: (open) => { if (open)
76
- initialFormSubmit(); }, children: [_jsxs(Tooltip, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { className: "text-xs rounded-xs", size: "xs", variant: "secondary", children: _jsx(MdOutlinePhoneAndroid, { style: { width: '12px', height: '12px' } }) }) }) }), _jsx(TooltipContent, { side: "right", align: 'start', children: "Simulator" })] }), _jsx(PopoverContent, { side: "right", align: 'start', sideOffset: 10, children: _jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("div", { className: "flex justify-between", children: [_jsx(Tabs, { value: deploymentType, onValueChange: setDeploymentType, children: _jsxs(TabsList, { className: "h-9", children: [_jsx(TabsTrigger, { value: "draft", className: "text-xs", children: "Draft" }), _jsx(TabsTrigger, { value: "live", className: "text-xs", children: "Live" })] }) }), _jsxs(Button, { size: "sm", variant: "outline", onClick: initialFormSubmit, children: [!refreshing && _jsx(IoReload, { size: 13 }), refreshing && _jsx(Spinner, {})] })] }), _jsx(Card, { className: "h-auto min-h-[150px] w-full p-4", children: _jsx("p", { className: "text-xs text-muted-foreground break-words", children: parse(flowMessage) || 'No message' }) }), _jsx(Form, { ...form, children: _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), noValidate: true, children: [_jsx(FormField, { control: form.control, name: "user_input", render: ({ field }) => (_jsx(FormItem, { children: _jsxs(InputGroup, { children: [_jsx(FormControl, { children: _jsx(InputGroupInput, { autoFocus: true, autoComplete: "off", ...field, placeholder: "User Input", className: "focus-visible:ring-1 focus-visible:ring-offset-0" }) }), _jsx(InputGroupAddon, { align: "inline-end", children: _jsxs(InputGroupButton, { variant: "secondary", type: "submit", children: [_jsx(Spinner, { loading: form.formState.isSubmitting }), !form.formState.isSubmitting && _jsx(SendHorizonalIcon, { size: 15 })] }) })] }) })) }), _jsx(FormMessage, {})] }) })] }) })] }));
179
+ const th = THEME[channel];
180
+ const lastBotMsg = history.filter(l => l.role === 'bot').at(-1);
181
+ const currentOptions = (_a = lastBotMsg === null || lastBotMsg === void 0 ? void 0 : lastBotMsg.options) !== null && _a !== void 0 ? _a : [];
182
+ const isEnded = history.length > 0 && lastBotMsg && currentOptions.length === 0;
183
+ return (_jsxs(Popover, { onOpenChange: handleOpenChange, children: [_jsxs(Tooltip, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { className: "text-xs rounded-xs", size: "xs", variant: "secondary", children: _jsx(MdOutlinePhoneAndroid, { style: { width: '12px', height: '12px' } }) }) }) }), _jsx(TooltipContent, { side: "right", align: "start", children: "Simulator" })] }), _jsxs(PopoverContent, { side: "right", align: "start", sideOffset: 10, style: { width: 306, padding: '12px 12px 16px' }, children: [_jsxs("div", { className: "flex items-center justify-between mb-3", children: [_jsx(Tabs, { value: deploymentType, onValueChange: handleDeployChange, children: _jsxs(TabsList, { className: "h-7", children: [_jsx(TabsTrigger, { value: "draft", className: "text-[10px] px-2.5", children: "Draft" }), _jsx(TabsTrigger, { value: "live", className: "text-[10px] px-2.5", children: "Live" })] }) }), _jsx(Tabs, { value: channel, onValueChange: handleChannelChange, children: _jsxs(TabsList, { className: "h-7", children: [_jsx(TabsTrigger, { value: "ussd", className: "text-[10px] px-2", children: "USSD" }), _jsx(TabsTrigger, { value: "whatsapp", className: "text-[10px] px-2", children: "WA" }), _jsx(TabsTrigger, { value: "telegram", className: "text-[10px] px-2", children: "TG" })] }) })] }), _jsx("div", { className: "relative mx-auto select-none", style: { width: 270 }, children: _jsxs("div", { className: "relative rounded-[44px] shadow-2xl", style: { background: '#1a1a1a', border: `2px solid ${th.shellBorder}`, padding: 6 }, children: [_jsx("div", { className: "absolute rounded-r", style: { right: -4, top: 88, width: 3, height: 56, background: th.shellBorder } }), _jsx("div", { className: "absolute rounded-l", style: { left: -4, top: 72, width: 3, height: 32, background: th.shellBorder } }), _jsx("div", { className: "absolute rounded-l", style: { left: -4, top: 112, width: 3, height: 32, background: th.shellBorder } }), _jsx("div", { className: "absolute rounded-l", style: { left: -4, top: 44, width: 3, height: 20, background: th.shellBorder } }), _jsxs("div", { className: "rounded-[40px] overflow-hidden flex flex-col", style: { background: '#000', height: 490 }, children: [_jsx("div", { className: "flex justify-center pt-3 pb-1 shrink-0", children: _jsx("div", { className: "rounded-full", style: { width: 100, height: 28, background: '#000', border: '1px solid #333' } }) }), _jsxs("div", { className: "flex justify-between items-center px-5 pb-1 shrink-0", style: { fontSize: 11, color: 'rgba(255,255,255,0.85)', fontWeight: 600 }, children: [_jsx("span", { children: "9:41" }), _jsxs("div", { className: "flex items-center gap-1.5", style: { fontSize: 10 }, children: [_jsx("span", { children: "WiFi" }), _jsx("span", { children: "100%" })] })] }), _jsxs("div", { className: "flex items-center justify-between px-4 py-2 shrink-0", style: { background: th.headerBg, borderBottom: '1px solid rgba(255,255,255,0.07)' }, children: [_jsx("span", { style: { fontSize: 12, fontWeight: 600, color: th.headerText }, children: CHANNEL_LABELS[channel] }), _jsx("button", { onClick: () => start(), disabled: loading, style: { color: th.headerText, opacity: loading ? 0.3 : 0.6, background: 'none', border: 'none', cursor: loading ? 'not-allowed' : 'pointer', padding: 0, lineHeight: 1 }, title: "Restart", children: _jsx(RotateCcw, { size: 13 }) })] }), channel === 'ussd' && (_jsxs(_Fragment, { children: [_jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4", style: { background: th.chatBg }, children: loading && !ussdText ? (_jsx("div", { className: "flex justify-center pt-6", children: _jsx(Spinner, {}) })) : (_jsx("p", { className: "whitespace-pre-wrap leading-snug", style: { fontSize: 12.5, color: 'rgba(255,255,255,0.88)' }, children: ussdText || 'No message' })) }), _jsxs("div", { className: "flex items-center gap-2 px-3 py-3 shrink-0", style: { background: th.inputBg, borderTop: '1px solid rgba(255,255,255,0.06)' }, children: [_jsx("input", { value: ussdInput, onChange: (e) => setUssdInput(e.target.value), onKeyDown: (e) => e.key === 'Enter' && ussdSend(), placeholder: "Enter choice...", style: { flex: 1, background: th.inputField, border: 'none', borderRadius: 18, padding: '7px 14px', fontSize: 12, color: '#fff', outline: 'none' } }), _jsx("button", { onClick: ussdSend, disabled: !ussdInput.trim() || loading, style: { background: th.sendBg, border: 'none', borderRadius: 16, padding: '6px 12px', fontSize: 11, fontWeight: 600, color: '#fff', cursor: (ussdInput.trim() && !loading) ? 'pointer' : 'not-allowed', opacity: (ussdInput.trim() && !loading) ? 1 : 0.4, flexShrink: 0, whiteSpace: 'nowrap' }, children: loading ? '...' : 'Send' })] })] })), channel !== 'ussd' && (_jsxs("div", { ref: chatContainerRef, className: "flex-1 overflow-y-auto px-3 py-3 space-y-2", style: { background: th.chatBg, minHeight: 0, ...th.chatExtra }, children: [history.length === 0 && loading && (_jsx("div", { className: "flex justify-center pt-6", children: _jsx(Spinner, {}) })), history.map((line, i) => (_jsx("div", { className: `flex ${line.role === 'user' ? 'justify-end' : 'justify-start'}`, children: _jsx("div", { className: "max-w-[88%] px-3 py-2 whitespace-pre-wrap", style: {
184
+ fontSize: 12, lineHeight: 1.45,
185
+ background: line.role === 'user' ? th.userBubble : th.botBubble,
186
+ color: line.role === 'user' ? th.userText : th.botText,
187
+ borderRadius: line.role === 'user' ? '18px 18px 4px 18px' : '18px 18px 18px 4px',
188
+ }, children: line.text }) }, i))), currentOptions.length > 0 && !loading && (_jsx("div", { className: "flex flex-col gap-1.5 pt-1", children: currentOptions.map((opt) => (_jsx("button", { onMouseDown: (e) => e.preventDefault(), onClick: () => chatSend(opt.text, String(opt.id)), style: {
189
+ background: 'transparent', border: `1px solid ${th.optionBorder}`,
190
+ borderRadius: 8, padding: '6px 12px', color: th.optionText,
191
+ fontSize: 12, cursor: 'pointer', textAlign: 'left', width: '100%',
192
+ }, children: opt.text }, opt.id))) })), loading && history.length > 0 && (_jsx("div", { className: "flex justify-start pl-1 pt-1", children: _jsx(Spinner, {}) })), isEnded && !loading && (_jsx("div", { className: "flex justify-center pt-3", children: _jsx("button", { onMouseDown: (e) => e.preventDefault(), onClick: () => start(), style: {
193
+ background: 'transparent', border: `1px solid ${th.optionBorder}`,
194
+ borderRadius: 8, padding: '6px 20px', color: th.optionText,
195
+ fontSize: 11, cursor: 'pointer',
196
+ }, children: "Start Over" }) }))] })), _jsx("div", { className: "flex justify-center pb-2 pt-1 shrink-0", children: _jsx("div", { className: "rounded-full", style: { width: 100, height: 4, background: 'rgba(255,255,255,0.25)' } }) })] })] }) })] })] }));
77
197
  }
78
198
  //# sourceMappingURL=simulator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"simulator.js","sourceRoot":"","sources":["../src/simulator.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"simulator.js","sourceRoot":"","sources":["../src/simulator.tsx"],"names":[],"mappings":"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"}
@@ -30,8 +30,8 @@ const NODE_TEMPLATES = {
30
30
  // type: 'fNode' as const,
31
31
  // data: { label: '', function: '' }
32
32
  // },
33
- // bnode: {
34
- // type: 'bNode' as const,
33
+ // gotonode: {
34
+ // type: 'gotoNode' as const,
35
35
  // data: { label: '', function: '' }
36
36
  // },
37
37
  default: {
@@ -60,82 +60,119 @@ const NODE_TEMPLATES = {
60
60
  function autoArrangeNodes(nodes, edges, options = {}) {
61
61
  if (!nodes || nodes.length === 0)
62
62
  return nodes;
63
- const { horizontalSpacing = 300, // Horizontal offset between levels
64
- verticalSpacing = 150, // Vertical offset between nodes
65
- startX = 100, // Starting X position
66
- startY = 100, // Starting Y position
67
- nodeWidth: NODE_WIDTH = 250, nodeHeight: NODE_HEIGHT = 180, } = options;
68
- // Build adjacency lists
69
- const incomingEdges = new Map();
70
- const outgoingEdges = new Map();
71
- nodes.forEach((n) => {
72
- incomingEdges.set(n.id, []);
73
- outgoingEdges.set(n.id, []);
74
- });
63
+ const { horizontalSpacing = 80, verticalSpacing = 50, nodeWidth: DEFAULT_WIDTH = 250, nodeHeight: DEFAULT_HEIGHT = 200, } = options;
64
+ // Use the actual rendered size when available (React Flow populates node.measured after paint)
65
+ const nw = (n) => { var _a, _b, _c; return (_c = (_b = (_a = n.measured) === null || _a === void 0 ? void 0 : _a.width) !== null && _b !== void 0 ? _b : n.width) !== null && _c !== void 0 ? _c : DEFAULT_WIDTH; };
66
+ const nh = (n) => { var _a, _b, _c; return (_c = (_b = (_a = n.measured) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : n.height) !== null && _c !== void 0 ? _c : DEFAULT_HEIGHT; };
67
+ const nodeById = new Map(nodes.map((n) => [n.id, n]));
68
+ // ── 1. Build adjacency (deduplicate, skip self-loops) ────────────────────
69
+ const nodeSet = new Set(nodes.map((n) => n.id));
70
+ const childMap = new Map();
71
+ const parentMap = new Map();
72
+ nodes.forEach((n) => { childMap.set(n.id, []); parentMap.set(n.id, []); });
73
+ const seenEdge = new Set();
75
74
  edges.forEach((e) => {
76
- if (incomingEdges.has(e.target)) {
77
- incomingEdges.get(e.target).push(e.source);
78
- }
79
- if (outgoingEdges.has(e.source)) {
80
- outgoingEdges.get(e.source).push(e.target);
75
+ const key = `${e.source}|${e.target}`;
76
+ if (nodeSet.has(e.source) && nodeSet.has(e.target) && e.source !== e.target && !seenEdge.has(key)) {
77
+ seenEdge.add(key);
78
+ childMap.get(e.source).push(e.target);
79
+ parentMap.get(e.target).push(e.source);
81
80
  }
82
81
  });
83
- // Find starting nodes (no incoming edges)
84
- const startNodes = nodes.filter((n) => { var _a, _b; return ((_b = (_a = incomingEdges.get(n.id)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) === 0; });
85
- // BFS level assignment
86
- const levels = [];
82
+ // ── 2. Shortest-path BFS layering ────────────────────────────────────────
83
+ const levelMap = new Map();
87
84
  const visited = new Set();
88
- const queue = startNodes.map((n) => ({
89
- id: n.id,
90
- level: 0,
91
- }));
85
+ const roots = nodes.filter((n) => { var _a, _b; return ((_b = (_a = parentMap.get(n.id)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) === 0; });
86
+ const queue = (roots.length > 0 ? roots : [nodes[0]])
87
+ .map((n) => ({ id: n.id, level: 0 }));
92
88
  while (queue.length > 0) {
93
89
  const { id, level } = queue.shift();
94
- if (!levels[level])
95
- levels[level] = [];
96
- if (!visited.has(id)) {
97
- levels[level].push(id);
98
- visited.add(id);
99
- const children = outgoingEdges.get(id) || [];
100
- children.forEach((childId) => {
101
- if (!visited.has(childId))
102
- queue.push({ id: childId, level: level + 1 });
90
+ if (visited.has(id))
91
+ continue;
92
+ visited.add(id);
93
+ levelMap.set(id, level);
94
+ (childMap.get(id) || []).forEach((c) => {
95
+ if (!visited.has(c))
96
+ queue.push({ id: c, level: level + 1 });
97
+ });
98
+ }
99
+ let extraCol = levelMap.size > 0 ? Math.max(...Array.from(levelMap.values())) + 1 : 0;
100
+ nodes.forEach((n) => { if (!levelMap.has(n.id))
101
+ levelMap.set(n.id, extraCol++); });
102
+ // ── 3. Group into columns ─────────────────────────────────────────────────
103
+ const columns = new Map();
104
+ levelMap.forEach((lv, id) => {
105
+ if (!columns.has(lv))
106
+ columns.set(lv, []);
107
+ columns.get(lv).push(id);
108
+ });
109
+ const sortedLevels = Array.from(columns.keys()).sort((a, b) => a - b);
110
+ // ── 4. Compute column X positions using actual node widths ────────────────
111
+ const colX = [];
112
+ let curX = 0;
113
+ sortedLevels.forEach((lv, colIdx) => {
114
+ colX[colIdx] = curX;
115
+ const maxW = Math.max(...(columns.get(lv).map(id => nw(nodeById.get(id)))));
116
+ curX += maxW + horizontalSpacing;
117
+ });
118
+ // ── 5. Place nodes — sequential Y using actual heights, centred on parents ─
119
+ const pos = new Map();
120
+ sortedLevels.forEach((lv, colIdx) => {
121
+ const group = columns.get(lv);
122
+ const x = colX[colIdx];
123
+ // Sort within column by average parent Y-centre (minimises edge crossings)
124
+ if (colIdx > 0) {
125
+ group.sort((a, b) => {
126
+ const midY = (id) => {
127
+ const ps = parentMap.get(id) || [];
128
+ if (!ps.length)
129
+ return 0;
130
+ return ps.reduce((s, p) => {
131
+ const pp = pos.get(p);
132
+ return s + (pp ? pp.y + nh(nodeById.get(p)) / 2 : 0);
133
+ }, 0) / ps.length;
134
+ };
135
+ return midY(a) - midY(b);
103
136
  });
104
137
  }
105
- }
106
- // Assign positions level by level (left → right)
107
- const updatedNodes = nodes.map((n) => ({ ...n }));
108
- const nodeMap = new Map(updatedNodes.map((n) => [n.id, n]));
109
- const nodePositions = new Map();
110
- levels.forEach((levelNodes, levelIndex) => {
111
- const x = startX + levelIndex * (NODE_WIDTH + horizontalSpacing);
112
- // Sort nodes in this level based on their parent positions (top to bottom)
113
- if (levelIndex > 0) {
114
- levelNodes.sort((a, b) => {
115
- const parentsA = incomingEdges.get(a) || [];
116
- const parentsB = incomingEdges.get(b) || [];
117
- // Calculate average Y position of parents
118
- const avgYA = parentsA.length > 0
119
- ? parentsA.reduce((sum, parentId) => { var _a; return sum + (((_a = nodePositions.get(parentId)) === null || _a === void 0 ? void 0 : _a.y) || 0); }, 0) / parentsA.length
120
- : 0;
121
- const avgYB = parentsB.length > 0
122
- ? parentsB.reduce((sum, parentId) => { var _a; return sum + (((_a = nodePositions.get(parentId)) === null || _a === void 0 ? void 0 : _a.y) || 0); }, 0) / parentsB.length
123
- : 0;
124
- return avgYA - avgYB;
138
+ // Total column height = sum of actual node heights + gaps between them
139
+ const heights = group.map((id) => nh(nodeById.get(id)));
140
+ const totalHeight = heights.reduce((s, h) => s + h, 0)
141
+ + (group.length - 1) * verticalSpacing;
142
+ // Centre point: Y=0 for first column, parent mid-Y centroid for the rest
143
+ let colCenterY = 0;
144
+ if (colIdx > 0) {
145
+ const pys = [];
146
+ group.forEach((id) => {
147
+ ;
148
+ (parentMap.get(id) || []).forEach((p) => {
149
+ const pp = pos.get(p);
150
+ if (pp)
151
+ pys.push(pp.y + nh(nodeById.get(p)) / 2);
152
+ });
125
153
  });
154
+ if (pys.length > 0)
155
+ colCenterY = pys.reduce((s, y) => s + y, 0) / pys.length;
126
156
  }
127
- const totalHeight = levelNodes.length * (NODE_HEIGHT + verticalSpacing);
128
- const baseY = startY - totalHeight / 2;
129
- levelNodes.forEach((nodeId, idx) => {
130
- const y = baseY + idx * (NODE_HEIGHT + verticalSpacing);
131
- const node = nodeMap.get(nodeId);
132
- if (node) {
133
- node.position = { x, y };
134
- nodePositions.set(nodeId, { x, y });
135
- }
157
+ // Place nodes sequentially from the top of the column, never with a fixed step —
158
+ // each node starts immediately after the actual bottom of the previous one.
159
+ let y = colCenterY - totalHeight / 2;
160
+ group.forEach((id, i) => {
161
+ pos.set(id, { x, y });
162
+ y += heights[i] + verticalSpacing;
136
163
  });
137
164
  });
138
- return Array.from(nodeMap.values());
165
+ // ── 6. Shift to match the canvas top-left bounding box ───────────────────
166
+ const originX = Math.min(...nodes.map((n) => { var _a, _b; return (_b = (_a = n.position) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0; }));
167
+ const originY = Math.min(...nodes.map((n) => { var _a, _b; return (_b = (_a = n.position) === null || _a === void 0 ? void 0 : _a.y) !== null && _b !== void 0 ? _b : 0; }));
168
+ const minPX = Math.min(...Array.from(pos.values()).map(p => p.x));
169
+ const minPY = Math.min(...Array.from(pos.values()).map(p => p.y));
170
+ return nodes.map((n) => {
171
+ const p = pos.get(n.id);
172
+ return p
173
+ ? { ...n, position: { x: p.x + (originX - minPX), y: p.y + (originY - minPY) } }
174
+ : n;
175
+ });
139
176
  }
140
177
  // Debounce utility
141
178
  function useDebounce(callback, delay) {
@@ -593,16 +630,17 @@ export default function StudioPane({ api_key, projectsRefetch, identifier, provi
593
630
  }, [cmdAndZPressed, cmdAndYPressed, handleUndo, handleRedo]);
594
631
  ////////////////// Auto Arrange Nodes /////////////////////////////
595
632
  const handleAutoArrange = useCallback(() => {
596
- setNodes((currentNodes) => {
597
- const arrangedNodes = autoArrangeNodes(currentNodes, edges, {
598
- horizontalSpacing: 300, // Horizontal offset between levels
599
- verticalSpacing: 150, // Vertical offset between nodes
600
- startX: 100, // Starting X position
601
- startY: 100 // Starting Y position
602
- });
603
- return arrangedNodes;
604
- });
605
- }, [edges, setNodes]);
633
+ // Use rfInstance.getNodes() so each node carries its actual measured dimensions
634
+ const liveNodes = rfInstance ? rfInstance.getNodes() : nodes;
635
+ const arrangedNodes = autoArrangeNodes(liveNodes, edges);
636
+ setNodes(arrangedNodes);
637
+ addToHistory({ nodes: arrangedNodes, edges, viewport: rfInstance === null || rfInstance === void 0 ? void 0 : rfInstance.getViewport() });
638
+ performSave();
639
+ // Wait for React to repaint the new positions before fitting the view
640
+ setTimeout(() => {
641
+ rfInstance === null || rfInstance === void 0 ? void 0 : rfInstance.fitView({ padding: 0.15, duration: 400 });
642
+ }, 50);
643
+ }, [nodes, edges, setNodes, addToHistory, rfInstance, performSave]);
606
644
  ////////////////// For Context Menu /////////////////////////////
607
645
  const createNode = useCallback((type) => {
608
646
  if ((contextMenuPosition === null || contextMenuPosition === void 0 ? void 0 : contextMenuPosition.x) != null && (contextMenuPosition === null || contextMenuPosition === void 0 ? void 0 : contextMenuPosition.y) != null) {
@@ -615,7 +653,7 @@ export default function StudioPane({ api_key, projectsRefetch, identifier, provi
615
653
  while (existingLabels.has(newLabel)) {
616
654
  newLabel = `${type}_label_${counter++}`;
617
655
  }
618
- // const template = type === 'function' ? NODE_TEMPLATES.function : type === 'bnode' ? NODE_TEMPLATES.bnode : NODE_TEMPLATES.default;
656
+ // const template = type === 'function' ? NODE_TEMPLATES.function : type === 'gotonode' ? NODE_TEMPLATES.gotonode : NODE_TEMPLATES.default;
619
657
  const template = NODE_TEMPLATES.default;
620
658
  return [
621
659
  ...prevNodes,
@@ -633,10 +671,10 @@ export default function StudioPane({ api_key, projectsRefetch, identifier, provi
633
671
  source: 'api_call',
634
672
  inputs: [{ id: 1 }]
635
673
  }
636
- } : type === 'bnode' ? {
674
+ } : type === 'gotonode' ? {
637
675
  node: '',
638
676
  response: {
639
- source: 'bnode',
677
+ source: 'gotonode',
640
678
  inputs: [{ id: 1 }]
641
679
  }
642
680
  } : {
@@ -694,6 +732,6 @@ export default function StudioPane({ api_key, projectsRefetch, identifier, provi
694
732
  window.addEventListener('keydown', handleKeyDown);
695
733
  return () => window.removeEventListener('keydown', handleKeyDown);
696
734
  }, [setNodes, setEdges]);
697
- return (_jsxs("div", { className: 'absolute top-0 right-0 bottom-0 left-0', children: [_jsxs(ReactFlow, { nodes: nodes, edges: edges, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, onConnect: onConnect, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onNodesDelete: onNodesDelete, onEdgesDelete: onEdgesDelete, onSelectionChange: onSelectionChange, onConnectEnd: onConnectEnd, onConnectStart: onConnectStart, onReconnect: onReconnect, onReconnectStart: onReconnectStart, onNodeDragStart: onNodeDragStart, onNodeDragStop: onNodeDragStop, onReconnectEnd: onReconnectEnd, onInit: setRfInstance, snapToGrid: true, fitView: true, minZoom: 0.1, maxZoom: 3, colorMode: theme, onPaneContextMenu: handleContextMenu, deleteKeyCode: null, attributionPosition: "bottom-right", children: [_jsx(Background, { gap: 12, size: 1 }), _jsx(Panel, { position: "top-center", children: _jsx(TopCenterPanel, { projectId: getIdentifier }) }), _jsx(Panel, { position: "top-left", children: _jsx(TopLeftPanel, { api_key: api_key, projectId: getIdentifier, createNode: createNode, onSave: onSave, saving: saving, rfInstance: rfInstance, redo: handleRedo, undo: handleUndo, historyIndex: historyIndex, autoArrange: handleAutoArrange }) }), _jsx(Panel, { position: "bottom-left", children: _jsx(BottomLeftPanel, { api_key: api_key, projectId: getIdentifier, createNode: createNode, onSave: onSave, saving: saving, rfInstance: rfInstance, redo: handleRedo, undo: handleUndo, historyIndex: historyIndex, autoArrange: handleAutoArrange }) }), _jsx(Panel, { position: "top-right", children: _jsx(TopRightPanel, { api_key: api_key, projectId: getIdentifier, createNode: createNode, onSave: onSave, saving: saving, rfInstance: rfInstance }) })] }), _jsx(AppAnalytics, { api_key: api_key, project: project, sessions: sessions, sessionsStatus: sessionsStatus, refetch: sessionsRefetch }), _jsx(AppSettings, { api_key: api_key, project: project, projectRefetch: projectRefetch, projectsRefetch: projectsRefetch, providers: providers, provider: provider, triggers: triggers, triggersRefetch: triggersRefetch, functions: functions, functionsRefetch: functionsRefetch, envs: envs, envsRefetch: envsRefetch }), _jsx(ContextMenu, { api_key: api_key, open: showContextMenu, setOpen: setShowContextMenu, createNode: createNode, menuPosition: contextMenuPosition })] }));
735
+ return (_jsxs("div", { className: 'absolute top-0 right-0 bottom-0 left-0', children: [_jsxs(ReactFlow, { nodes: nodes, edges: edges, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, onConnect: onConnect, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onNodesDelete: onNodesDelete, onEdgesDelete: onEdgesDelete, onSelectionChange: onSelectionChange, onConnectEnd: onConnectEnd, onConnectStart: onConnectStart, onReconnect: onReconnect, onReconnectStart: onReconnectStart, onNodeDragStart: onNodeDragStart, onNodeDragStop: onNodeDragStop, onReconnectEnd: onReconnectEnd, onInit: setRfInstance, snapToGrid: true, fitView: true, minZoom: 0.1, maxZoom: 3, colorMode: theme, onPaneContextMenu: handleContextMenu, deleteKeyCode: null, attributionPosition: "bottom-right", children: [_jsx(Background, { gap: 12, size: 1 }), _jsx(Panel, { position: "top-center", children: _jsx(TopCenterPanel, { projectId: getIdentifier }) }), _jsx(Panel, { position: "top-left", children: _jsx(TopLeftPanel, { api_key: api_key, projectId: getIdentifier, createNode: createNode, onSave: onSave, saving: saving, rfInstance: rfInstance, redo: handleRedo, undo: handleUndo, historyIndex: historyIndex, historySize: historySize, autoArrange: handleAutoArrange }) }), _jsx(Panel, { position: "bottom-left", children: _jsx(BottomLeftPanel, { api_key: api_key, projectId: getIdentifier, createNode: createNode, onSave: onSave, saving: saving, rfInstance: rfInstance, redo: handleRedo, undo: handleUndo, historyIndex: historyIndex, autoArrange: handleAutoArrange }) }), _jsx(Panel, { position: "top-right", children: _jsx(TopRightPanel, { api_key: api_key, projectId: getIdentifier, createNode: createNode, onSave: onSave, saving: saving, rfInstance: rfInstance }) })] }), _jsx(AppAnalytics, { api_key: api_key, project: project, sessions: sessions, sessionsStatus: sessionsStatus, refetch: sessionsRefetch }), _jsx(AppSettings, { api_key: api_key, project: project, projectRefetch: projectRefetch, projectsRefetch: projectsRefetch, providers: providers, provider: provider, triggers: triggers, triggersRefetch: triggersRefetch, functions: functions, functionsRefetch: functionsRefetch, envs: envs, envsRefetch: envsRefetch }), _jsx(ContextMenu, { api_key: api_key, open: showContextMenu, setOpen: setShowContextMenu, createNode: createNode, menuPosition: contextMenuPosition })] }));
698
736
  }
699
737
  //# sourceMappingURL=studio_pane.js.map