@superleapai/flow-ui 2.5.19 → 2.5.21
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.
- package/CHANGELOG.md +2 -2
- package/LICENSE +1 -1
- package/README.md +38 -38
- package/components/enum-multiselect.js +119 -56
- package/components/enum-select.js +90 -48
- package/components/file-input.js +111 -49
- package/core/bridge.js +4 -6
- package/core/crm.js +17 -17
- package/core/flow.js +230 -59
- package/core/superleapClient.js +2 -2
- package/dist/superleap-flow.js +271 -2227
- package/dist/superleap-flow.js.map +1 -1
- package/dist/superleap-flow.min.js +2 -2
- package/index.d.ts +31 -20
- package/index.js +41 -30
- package/package.json +2 -2
package/components/file-input.js
CHANGED
|
@@ -10,16 +10,23 @@
|
|
|
10
10
|
// Tabler-style inline SVGs (no external deps) – match React IconFile, IconCopy, IconEye, IconX
|
|
11
11
|
var ICONS = {
|
|
12
12
|
file: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></svg>',
|
|
13
|
-
fileImage:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
fileImage:
|
|
14
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/></svg>',
|
|
15
|
+
filePdf:
|
|
16
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M9 12h6"/><path d="M9 16h6"/><path d="M9 8h1"/></svg>',
|
|
17
|
+
fileVideo:
|
|
18
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m22 8-6 4 6 4V8Z"/><rect width="14" height="12" x="2" y="6" rx="2" ry="2"/></svg>',
|
|
19
|
+
fileAudio:
|
|
20
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>',
|
|
21
|
+
fileSpreadsheet:
|
|
22
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M8 12h8"/><path d="M8 16h8"/><path d="M8 8h8"/></svg>',
|
|
23
|
+
fileText:
|
|
24
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg>',
|
|
19
25
|
copy: '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>',
|
|
20
26
|
eye: '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>',
|
|
21
27
|
x: '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>',
|
|
22
|
-
loader:
|
|
28
|
+
loader:
|
|
29
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="animate-spin"><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg>',
|
|
23
30
|
};
|
|
24
31
|
|
|
25
32
|
var IMAGE_EXT = /\.(jpe?g|png|gif|webp|bmp|svg|ico|avif)(\?|$)/i;
|
|
@@ -80,10 +87,15 @@
|
|
|
80
87
|
}
|
|
81
88
|
|
|
82
89
|
if (!baseUrl) {
|
|
83
|
-
throw new Error(
|
|
90
|
+
throw new Error(
|
|
91
|
+
"Superleap client not initialized. Call superleapClient.init({ baseUrl, apiKey }) first.",
|
|
92
|
+
);
|
|
84
93
|
}
|
|
85
94
|
|
|
86
|
-
const fullUrl = uploadUrl.startsWith("http")
|
|
95
|
+
const fullUrl = uploadUrl.startsWith("http")
|
|
96
|
+
? uploadUrl
|
|
97
|
+
: baseUrl.replace(/\/$/, "") +
|
|
98
|
+
(uploadUrl.startsWith("/") ? uploadUrl : "/" + uploadUrl);
|
|
87
99
|
|
|
88
100
|
const headers = {};
|
|
89
101
|
if (apiKey) {
|
|
@@ -103,14 +115,14 @@
|
|
|
103
115
|
|
|
104
116
|
const result = await response.json();
|
|
105
117
|
console.log("[S3FileUpload] Upload response:");
|
|
106
|
-
|
|
118
|
+
|
|
107
119
|
const url = result?.data?.url;
|
|
108
|
-
|
|
120
|
+
|
|
109
121
|
if (!url) {
|
|
110
122
|
console.error("[S3FileUpload] No URL found in response:", result);
|
|
111
123
|
throw new Error("Upload response did not contain a file URL");
|
|
112
124
|
}
|
|
113
|
-
|
|
125
|
+
|
|
114
126
|
return {
|
|
115
127
|
url: url,
|
|
116
128
|
};
|
|
@@ -135,8 +147,7 @@
|
|
|
135
147
|
* @returns {HTMLElement} Field element
|
|
136
148
|
*/
|
|
137
149
|
var UPLOAD_WRAPPER_CLASS = {
|
|
138
|
-
base:
|
|
139
|
-
"group relative flex w-full items-center justify-between border-1/2 rounded-4 text-typography-primary-text w-full transition-all ease-in-out focus-within:outline-none group-has-[:disabled]:cursor-not-allowed group-has-[:disabled]:border-border-primary group-has-[:disabled]:bg-fill-tertiary-fill-light-gray group-has-[:disabled]:text-typography-quaternary-text group-has-[:disabled]:hover:border-border-primary",
|
|
150
|
+
base: "group relative flex w-full items-center justify-between border-1/2 rounded-4 text-typography-primary-text w-full transition-all ease-in-out focus-within:outline-none group-has-[:disabled]:cursor-not-allowed group-has-[:disabled]:border-border-primary group-has-[:disabled]:bg-fill-tertiary-fill-light-gray group-has-[:disabled]:text-typography-quaternary-text group-has-[:disabled]:hover:border-border-primary",
|
|
140
151
|
default:
|
|
141
152
|
"border-border-primary bg-fill-quarternary-fill-white hover:border-primary-base focus-within:border-primary-base",
|
|
142
153
|
error:
|
|
@@ -205,23 +216,29 @@
|
|
|
205
216
|
UPLOAD_WRAPPER_CLASS.base,
|
|
206
217
|
UPLOAD_WRAPPER_CLASS[currentVariant] || UPLOAD_WRAPPER_CLASS.default,
|
|
207
218
|
sizeClass,
|
|
208
|
-
className
|
|
219
|
+
className,
|
|
209
220
|
);
|
|
210
221
|
}
|
|
211
222
|
applyWrapperClasses();
|
|
212
223
|
uploadWrapper.setAttribute("data-file-input-variant", currentVariant);
|
|
213
224
|
uploadWrapper.setAttribute("data-file-input-size", currentInputSize);
|
|
214
|
-
uploadWrapper.setAttribute(
|
|
225
|
+
uploadWrapper.setAttribute(
|
|
226
|
+
"data-disabled",
|
|
227
|
+
disabledState ? "true" : "false",
|
|
228
|
+
);
|
|
215
229
|
|
|
216
230
|
// Left content (button + status) – pointer-events-none so overlay input receives clicks
|
|
217
231
|
const leftContent = document.createElement("div");
|
|
218
|
-
leftContent.className =
|
|
232
|
+
leftContent.className =
|
|
233
|
+
"pointer-events-none flex min-w-0 flex-1 items-center gap-8 truncate";
|
|
219
234
|
|
|
220
235
|
var disabledChildClasses =
|
|
221
236
|
"group-has-[:disabled]:text-typography-quaternary-text group-has-[:disabled]:bg-fill-tertiary-fill-light-gray group-has-[:disabled]:hover:bg-fill-tertiary-fill-light-gray";
|
|
222
237
|
var statusTextBaseClass = "text-reg-13 min-w-0 flex-1 truncate";
|
|
223
|
-
var statusTextDisabledClass =
|
|
224
|
-
|
|
238
|
+
var statusTextDisabledClass =
|
|
239
|
+
" group-has-[:disabled]:text-typography-quaternary-text";
|
|
240
|
+
const useButtonComponent =
|
|
241
|
+
global.Button && typeof global.Button.create === "function";
|
|
225
242
|
const initialButtonText = multiple ? "Choose files" : "Choose a file";
|
|
226
243
|
const btn = useButtonComponent
|
|
227
244
|
? global.Button.create({
|
|
@@ -241,7 +258,10 @@
|
|
|
241
258
|
|
|
242
259
|
// Status text: "No files chosen" (quaternary) or "X file(s) selected"
|
|
243
260
|
const statusText = document.createElement("p");
|
|
244
|
-
statusText.className =
|
|
261
|
+
statusText.className =
|
|
262
|
+
statusTextBaseClass +
|
|
263
|
+
" text-typography-quaternary-text" +
|
|
264
|
+
statusTextDisabledClass;
|
|
245
265
|
|
|
246
266
|
// Hidden file input – overlays row, high z-index so it receives clicks
|
|
247
267
|
const input = document.createElement("input");
|
|
@@ -250,7 +270,9 @@
|
|
|
250
270
|
function applyInputClasses() {
|
|
251
271
|
input.className =
|
|
252
272
|
inputBaseClass +
|
|
253
|
-
(disabledState
|
|
273
|
+
(disabledState
|
|
274
|
+
? " !pointer-events-none !cursor-not-allowed"
|
|
275
|
+
: " cursor-pointer");
|
|
254
276
|
}
|
|
255
277
|
applyInputClasses();
|
|
256
278
|
input.multiple = multiple;
|
|
@@ -294,7 +316,8 @@
|
|
|
294
316
|
function makeCopyBtn(fileUrl) {
|
|
295
317
|
const btn = document.createElement("button");
|
|
296
318
|
btn.type = "button";
|
|
297
|
-
btn.className =
|
|
319
|
+
btn.className =
|
|
320
|
+
"shrink-0 rounded-2 p-4 text-typography-quaternary-text transition-colors hover:text-typography-primary-text focus:outline-none";
|
|
298
321
|
btn.innerHTML = ICONS.copy;
|
|
299
322
|
btn.setAttribute("aria-label", "Copy URL");
|
|
300
323
|
btn.addEventListener("click", function (e) {
|
|
@@ -309,7 +332,7 @@
|
|
|
309
332
|
if (global.FlowUI && global.FlowUI.showToast) {
|
|
310
333
|
global.FlowUI.showToast("Copy failed", "error");
|
|
311
334
|
}
|
|
312
|
-
}
|
|
335
|
+
},
|
|
313
336
|
);
|
|
314
337
|
});
|
|
315
338
|
return btn;
|
|
@@ -318,7 +341,8 @@
|
|
|
318
341
|
function makeViewBtn(fileUrl) {
|
|
319
342
|
const btn = document.createElement("button");
|
|
320
343
|
btn.type = "button";
|
|
321
|
-
btn.className =
|
|
344
|
+
btn.className =
|
|
345
|
+
"shrink-0 rounded-2 p-4 text-typography-quaternary-text transition-colors hover:text-typography-primary-text focus:outline-none";
|
|
322
346
|
btn.innerHTML = ICONS.eye;
|
|
323
347
|
btn.setAttribute("aria-label", "View file");
|
|
324
348
|
btn.addEventListener("click", function (e) {
|
|
@@ -331,7 +355,8 @@
|
|
|
331
355
|
function makeRemoveBtn(onRemove) {
|
|
332
356
|
const btn = document.createElement("button");
|
|
333
357
|
btn.type = "button";
|
|
334
|
-
btn.className =
|
|
358
|
+
btn.className =
|
|
359
|
+
"shrink-0 rounded-2 p-4 text-error-text-base transition-colors hover:bg-error-surface focus:outline-none";
|
|
335
360
|
btn.innerHTML = ICONS.x;
|
|
336
361
|
btn.setAttribute("aria-label", "Remove file");
|
|
337
362
|
btn.addEventListener("click", function (e) {
|
|
@@ -348,7 +373,8 @@
|
|
|
348
373
|
|
|
349
374
|
uploadedFiles.forEach(function (file, index) {
|
|
350
375
|
var nameEl = document.createElement("p");
|
|
351
|
-
nameEl.className =
|
|
376
|
+
nameEl.className =
|
|
377
|
+
"max-w-[100px] truncate text-reg-10 text-typography-secondary-text";
|
|
352
378
|
nameEl.textContent = file.name;
|
|
353
379
|
nameEl.title = file.url;
|
|
354
380
|
|
|
@@ -356,12 +382,14 @@
|
|
|
356
382
|
actionsWrap.className = "flex items-center gap-2 shrink-0";
|
|
357
383
|
actionsWrap.appendChild(makeCopyBtn(file.url));
|
|
358
384
|
actionsWrap.appendChild(makeViewBtn(file.url));
|
|
359
|
-
actionsWrap.appendChild(
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
385
|
+
actionsWrap.appendChild(
|
|
386
|
+
makeRemoveBtn(function () {
|
|
387
|
+
uploadedFiles.splice(index, 1);
|
|
388
|
+
saveToState();
|
|
389
|
+
renderFilesList();
|
|
390
|
+
updateStatus();
|
|
391
|
+
}),
|
|
392
|
+
);
|
|
365
393
|
|
|
366
394
|
var badge;
|
|
367
395
|
if (useBadge) {
|
|
@@ -373,12 +401,15 @@
|
|
|
373
401
|
className: "text-typography-primary-text",
|
|
374
402
|
});
|
|
375
403
|
var iconWraps = badge.querySelectorAll(".flex.size-16");
|
|
376
|
-
if (iconWraps.length >= 1)
|
|
404
|
+
if (iconWraps.length >= 1)
|
|
405
|
+
iconWraps[0].classList.add("text-typography-secondary-text");
|
|
377
406
|
} else {
|
|
378
407
|
badge = document.createElement("div");
|
|
379
|
-
badge.className =
|
|
408
|
+
badge.className =
|
|
409
|
+
"inline-flex items-center gap-4 rounded-4 border-1/2 border-border-primary bg-fill-tertiary-fill-light-gray px-8 py-2 text-med-12 text-typography-primary-text";
|
|
380
410
|
var iconWrap = document.createElement("span");
|
|
381
|
-
iconWrap.className =
|
|
411
|
+
iconWrap.className =
|
|
412
|
+
"flex size-16 shrink-0 items-center justify-center text-typography-secondary-text";
|
|
382
413
|
iconWrap.innerHTML = getFileTypeIcon(file.name || file.url);
|
|
383
414
|
badge.appendChild(iconWrap);
|
|
384
415
|
badge.appendChild(nameEl);
|
|
@@ -396,7 +427,8 @@
|
|
|
396
427
|
|
|
397
428
|
uploadingFiles.forEach(function (item) {
|
|
398
429
|
var nameEl = document.createElement("p");
|
|
399
|
-
nameEl.className =
|
|
430
|
+
nameEl.className =
|
|
431
|
+
"max-w-[100px] truncate text-reg-10 text-typography-secondary-text";
|
|
400
432
|
nameEl.textContent = item.name;
|
|
401
433
|
|
|
402
434
|
var badge;
|
|
@@ -408,12 +440,15 @@
|
|
|
408
440
|
className: "text-typography-primary-text",
|
|
409
441
|
});
|
|
410
442
|
var iconWraps = badge.querySelectorAll(".flex.size-16");
|
|
411
|
-
if (iconWraps.length >= 1)
|
|
443
|
+
if (iconWraps.length >= 1)
|
|
444
|
+
iconWraps[0].classList.add("text-typography-secondary-text");
|
|
412
445
|
} else {
|
|
413
446
|
badge = document.createElement("div");
|
|
414
|
-
badge.className =
|
|
447
|
+
badge.className =
|
|
448
|
+
"inline-flex items-center gap-4 rounded-4 border-1/2 border-border-primary bg-fill-tertiary-fill-light-gray px-8 py-2 text-med-12";
|
|
415
449
|
var iconWrap = document.createElement("span");
|
|
416
|
-
iconWrap.className =
|
|
450
|
+
iconWrap.className =
|
|
451
|
+
"flex size-16 shrink-0 items-center justify-center text-typography-secondary-text";
|
|
417
452
|
iconWrap.innerHTML = ICONS.loader;
|
|
418
453
|
badge.appendChild(iconWrap);
|
|
419
454
|
badge.appendChild(nameEl);
|
|
@@ -443,13 +478,22 @@
|
|
|
443
478
|
|
|
444
479
|
if (!filesChosen) {
|
|
445
480
|
statusText.textContent = "No files chosen";
|
|
446
|
-
statusText.className =
|
|
481
|
+
statusText.className =
|
|
482
|
+
statusTextBaseClass +
|
|
483
|
+
" text-typography-quaternary-text" +
|
|
484
|
+
statusTextDisabledClass;
|
|
447
485
|
} else if (uploadingCount > 0) {
|
|
448
486
|
statusText.textContent = "Uploading…";
|
|
449
|
-
statusText.className =
|
|
487
|
+
statusText.className =
|
|
488
|
+
statusTextBaseClass +
|
|
489
|
+
" text-typography-quaternary-text" +
|
|
490
|
+
statusTextDisabledClass;
|
|
450
491
|
} else {
|
|
451
492
|
statusText.textContent = `${uploadedCount} file${uploadedCount !== 1 ? "s" : ""} selected`;
|
|
452
|
-
statusText.className =
|
|
493
|
+
statusText.className =
|
|
494
|
+
statusTextBaseClass +
|
|
495
|
+
" text-typography-primary-text" +
|
|
496
|
+
statusTextDisabledClass;
|
|
453
497
|
}
|
|
454
498
|
|
|
455
499
|
endIconSlot.style.display = uploadingCount > 0 ? "flex" : "none";
|
|
@@ -486,7 +530,9 @@
|
|
|
486
530
|
return fileExtension === type.toLowerCase();
|
|
487
531
|
}
|
|
488
532
|
if (type.includes("/")) {
|
|
489
|
-
return
|
|
533
|
+
return (
|
|
534
|
+
fileType === type || fileType.startsWith(type.split("/")[0] + "/")
|
|
535
|
+
);
|
|
490
536
|
}
|
|
491
537
|
return false;
|
|
492
538
|
});
|
|
@@ -517,9 +563,13 @@
|
|
|
517
563
|
const result = await uploadFileToS3(file, isPrivate);
|
|
518
564
|
const fileUrl = result?.url;
|
|
519
565
|
if (!fileUrl) {
|
|
520
|
-
throw new Error(
|
|
566
|
+
throw new Error(
|
|
567
|
+
`No URL returned from upload for file "${file.name}"`,
|
|
568
|
+
);
|
|
521
569
|
}
|
|
522
|
-
console.log(
|
|
570
|
+
console.log(
|
|
571
|
+
`[S3FileUpload] File uploaded successfully: ${file.name} -> ${fileUrl}`,
|
|
572
|
+
);
|
|
523
573
|
|
|
524
574
|
uploadingFiles = uploadingFiles.filter((f) => f.file !== file);
|
|
525
575
|
uploadedFiles.push({ url: fileUrl, name: file.name });
|
|
@@ -533,7 +583,10 @@
|
|
|
533
583
|
renderUploadingList();
|
|
534
584
|
updateStatus();
|
|
535
585
|
if (global.FlowUI && global.FlowUI.showToast) {
|
|
536
|
-
global.FlowUI.showToast(
|
|
586
|
+
global.FlowUI.showToast(
|
|
587
|
+
`Failed to upload "${file.name}": ${error.message}`,
|
|
588
|
+
"error",
|
|
589
|
+
);
|
|
537
590
|
}
|
|
538
591
|
}
|
|
539
592
|
}
|
|
@@ -541,10 +594,16 @@
|
|
|
541
594
|
// Handle file selection
|
|
542
595
|
input.addEventListener("change", async function (e) {
|
|
543
596
|
const files = Array.from(e.target.files || []);
|
|
544
|
-
if (files.length === 0) {
|
|
597
|
+
if (files.length === 0) {
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
545
600
|
|
|
546
601
|
// Check max files limit
|
|
547
|
-
if (
|
|
602
|
+
if (
|
|
603
|
+
multiple &&
|
|
604
|
+
maxFiles &&
|
|
605
|
+
uploadedFiles.length + files.length > maxFiles
|
|
606
|
+
) {
|
|
548
607
|
const message = `You can only upload ${maxFiles} file${maxFiles !== 1 ? "s" : ""}`;
|
|
549
608
|
if (global.FlowUI && global.FlowUI.showToast) {
|
|
550
609
|
global.FlowUI.showToast(message, "error");
|
|
@@ -591,7 +650,10 @@
|
|
|
591
650
|
input.disabled = disabledState;
|
|
592
651
|
applyInputClasses();
|
|
593
652
|
applyWrapperClasses();
|
|
594
|
-
uploadWrapper.setAttribute(
|
|
653
|
+
uploadWrapper.setAttribute(
|
|
654
|
+
"data-disabled",
|
|
655
|
+
disabledState ? "true" : "false",
|
|
656
|
+
);
|
|
595
657
|
};
|
|
596
658
|
|
|
597
659
|
field.setVariant = function (v) {
|
package/core/bridge.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Native WebView via window.ReactNativeWebView.
|
|
7
7
|
*
|
|
8
8
|
* This module is transport-only — it knows nothing about CRM concepts,
|
|
9
|
-
* the
|
|
9
|
+
* the Superleap SDK, or FlowUI state. The higher-level core/crm.js
|
|
10
10
|
* builds on top of it.
|
|
11
11
|
*
|
|
12
12
|
* Exposed temporarily as window.SuperleapBridge, then captured into
|
|
@@ -327,7 +327,7 @@
|
|
|
327
327
|
if (!_bridgeId) {
|
|
328
328
|
reject(
|
|
329
329
|
new Error(
|
|
330
|
-
"SuperleapBridge: No _bridgeId found in URL. Is this page embedded in the
|
|
330
|
+
"SuperleapBridge: No _bridgeId found in URL. Is this page embedded in the Superleap CRM?",
|
|
331
331
|
),
|
|
332
332
|
);
|
|
333
333
|
return;
|
|
@@ -391,7 +391,7 @@
|
|
|
391
391
|
var err = new Error(
|
|
392
392
|
"SuperleapBridge: Handshake timed out after " +
|
|
393
393
|
timeoutMs +
|
|
394
|
-
"ms. Is this page embedded in the
|
|
394
|
+
"ms. Is this page embedded in the Superleap CRM?",
|
|
395
395
|
);
|
|
396
396
|
if (_pendingReject) _pendingReject(err);
|
|
397
397
|
cleanup();
|
|
@@ -422,9 +422,7 @@
|
|
|
422
422
|
*/
|
|
423
423
|
function send(action, payload) {
|
|
424
424
|
if (!_connected) {
|
|
425
|
-
throw new Error(
|
|
426
|
-
"SuperleapBridge: Not connected. Call connect() first.",
|
|
427
|
-
);
|
|
425
|
+
throw new Error("SuperleapBridge: Not connected. Call connect() first.");
|
|
428
426
|
}
|
|
429
427
|
sendRaw(createEnvelope(action, payload));
|
|
430
428
|
}
|
package/core/crm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Superleap-Flow CRM Bridge Extensions
|
|
3
3
|
*
|
|
4
|
-
* This module extends the existing
|
|
4
|
+
* This module extends the existing Superleap object (from superleapClient.js)
|
|
5
5
|
* with CRM bridge functionality. It wraps the low-level bridge transport
|
|
6
6
|
* (core/bridge.js) and adds:
|
|
7
7
|
*
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* read from the URL). User code should listen for the 'superleap-flow:ready'
|
|
15
15
|
* event — by the time it fires, the SDK is initialized and context is available.
|
|
16
16
|
*
|
|
17
|
-
* This extends the existing
|
|
17
|
+
* This extends the existing Superleap API from superleapClient.js which
|
|
18
18
|
* already has: init(), getSdk(), isAvailable(), getDefaultConfig().
|
|
19
19
|
*/
|
|
20
20
|
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
if (c) return c;
|
|
74
74
|
}
|
|
75
75
|
if (global.superleapClient) return global.superleapClient;
|
|
76
|
-
if (global.
|
|
76
|
+
if (global.Superleap) return global.Superleap;
|
|
77
77
|
return null;
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
/**
|
|
85
85
|
* Connect to the CRM. Performs the postMessage handshake, receives
|
|
86
86
|
* credentials and context, and (by default) auto-initializes the
|
|
87
|
-
*
|
|
87
|
+
* Superleap SDK.
|
|
88
88
|
*
|
|
89
89
|
* If already connected, silently resolves with the existing context/config.
|
|
90
90
|
* If a connection is in flight (e.g. auto-connect), returns the same promise.
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
* @param {Object} [options]
|
|
93
93
|
* @param {string} [options.bridgeId] – explicit bridgeId override (auto-read from URL)
|
|
94
94
|
* @param {string} [options.crmOrigin] – expected CRM origin for validation
|
|
95
|
-
* @param {boolean} [options.autoInit] – auto-call
|
|
95
|
+
* @param {boolean} [options.autoInit] – auto-call Superleap.init() (default true)
|
|
96
96
|
* @param {number} [options.timeout] – handshake timeout in ms (default 5000)
|
|
97
97
|
* @returns {Promise<{ context: Object, config: Object }>}
|
|
98
98
|
*/
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
_context = (payload && payload.context) || {};
|
|
126
126
|
_config = (payload && payload.config) || {};
|
|
127
127
|
|
|
128
|
-
// Auto-initialize the
|
|
128
|
+
// Auto-initialize the Superleap SDK
|
|
129
129
|
var sdkConfig = payload && payload.sdkConfig;
|
|
130
130
|
if (opts.autoInit !== false && sdkConfig) {
|
|
131
131
|
var client = getSuperLeapClient();
|
|
@@ -248,18 +248,17 @@
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
/**
|
|
251
|
-
*
|
|
252
|
-
* The CRM
|
|
251
|
+
* Notify the CRM that the form was submitted successfully.
|
|
252
|
+
* The CRM listens for 'crm:formSubmitSuccess' and can react
|
|
253
|
+
* (e.g. close the form, refresh data, show a toast).
|
|
253
254
|
*
|
|
254
|
-
* @param {
|
|
255
|
-
* @returns {Function} unsubscribe function
|
|
255
|
+
* @param {Object} [payload] – optional data about the submission
|
|
256
256
|
*/
|
|
257
|
-
function
|
|
257
|
+
function formSubmittedSuccessfully(payload) {
|
|
258
258
|
var bridge = getBridge();
|
|
259
|
-
if (
|
|
260
|
-
|
|
259
|
+
if (bridge && bridge.isConnected()) {
|
|
260
|
+
bridge.send("crm:formSubmitSuccess", payload || {});
|
|
261
261
|
}
|
|
262
|
-
return bridge.onMessage("crm:onFormSubmitSuccess", callback);
|
|
263
262
|
}
|
|
264
263
|
|
|
265
264
|
// ---------------------------------------------------------------------------
|
|
@@ -325,7 +324,7 @@
|
|
|
325
324
|
}
|
|
326
325
|
|
|
327
326
|
// ---------------------------------------------------------------------------
|
|
328
|
-
// Extend the existing superleapClient (which becomes
|
|
327
|
+
// Extend the existing superleapClient (which becomes Superleap)
|
|
329
328
|
// ---------------------------------------------------------------------------
|
|
330
329
|
|
|
331
330
|
// Wait for superleapClient to be defined, then extend it
|
|
@@ -336,7 +335,8 @@
|
|
|
336
335
|
global.superleapClient.disconnect = disconnect;
|
|
337
336
|
global.superleapClient.setLoading = setLoading;
|
|
338
337
|
global.superleapClient.closeForm = closeForm;
|
|
339
|
-
global.superleapClient.
|
|
338
|
+
global.superleapClient.formSubmittedSuccessfully =
|
|
339
|
+
formSubmittedSuccessfully;
|
|
340
340
|
global.superleapClient.toast = toast;
|
|
341
341
|
global.superleapClient.navigate = navigate;
|
|
342
342
|
global.superleapClient.getContext = getContext;
|
|
@@ -347,7 +347,7 @@
|
|
|
347
347
|
// superleapClient not loaded yet — this shouldn't happen if scripts
|
|
348
348
|
// load in order, but handle it gracefully
|
|
349
349
|
console.warn(
|
|
350
|
-
"
|
|
350
|
+
"Superleap CRM Bridge: superleapClient not found. Make sure core/superleapClient.js loads before core/crm.js",
|
|
351
351
|
);
|
|
352
352
|
}
|
|
353
353
|
})(typeof window !== "undefined" ? window : this);
|