@superleapai/flow-ui 2.5.19 → 2.5.20

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.
@@ -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: '<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>',
14
- filePdf: '<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>',
15
- fileVideo: '<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>',
16
- fileAudio: '<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>',
17
- fileSpreadsheet: '<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>',
18
- fileText: '<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>',
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: '<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>',
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("SuperLeap client not initialized. Call superleapClient.init({ baseUrl, apiKey }) first.");
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") ? uploadUrl : baseUrl.replace(/\/$/, "") + (uploadUrl.startsWith("/") ? uploadUrl : "/" + uploadUrl);
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("data-disabled", disabledState ? "true" : "false");
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 = "pointer-events-none flex min-w-0 flex-1 items-center gap-8 truncate";
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 = " group-has-[:disabled]:text-typography-quaternary-text";
224
- const useButtonComponent = global.Button && typeof global.Button.create === "function";
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 = statusTextBaseClass + " text-typography-quaternary-text" + statusTextDisabledClass;
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 ? " !pointer-events-none !cursor-not-allowed" : " cursor-pointer");
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 = "shrink-0 rounded-2 p-4 text-typography-quaternary-text transition-colors hover:text-typography-primary-text focus:outline-none";
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 = "shrink-0 rounded-2 p-4 text-typography-quaternary-text transition-colors hover:text-typography-primary-text focus:outline-none";
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 = "shrink-0 rounded-2 p-4 text-error-text-base transition-colors hover:bg-error-surface focus:outline-none";
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 = "max-w-[100px] truncate text-reg-10 text-typography-secondary-text";
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(makeRemoveBtn(function () {
360
- uploadedFiles.splice(index, 1);
361
- saveToState();
362
- renderFilesList();
363
- updateStatus();
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) iconWraps[0].classList.add("text-typography-secondary-text");
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 = "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";
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 = "flex size-16 shrink-0 items-center justify-center text-typography-secondary-text";
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 = "max-w-[100px] truncate text-reg-10 text-typography-secondary-text";
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) iconWraps[0].classList.add("text-typography-secondary-text");
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 = "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";
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 = "flex size-16 shrink-0 items-center justify-center text-typography-secondary-text";
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 = statusTextBaseClass + " text-typography-quaternary-text" + statusTextDisabledClass;
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 = statusTextBaseClass + " text-typography-quaternary-text" + statusTextDisabledClass;
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 = statusTextBaseClass + " text-typography-primary-text" + statusTextDisabledClass;
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 fileType === type || fileType.startsWith(type.split("/")[0] + "/");
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(`No URL returned from upload for file "${file.name}"`);
566
+ throw new Error(
567
+ `No URL returned from upload for file "${file.name}"`,
568
+ );
521
569
  }
522
- console.log(`[S3FileUpload] File uploaded successfully: ${file.name} -> ${fileUrl}`);
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(`Failed to upload "${file.name}": ${error.message}`, "error");
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) {return;}
597
+ if (files.length === 0) {
598
+ return;
599
+ }
545
600
 
546
601
  // Check max files limit
547
- if (multiple && maxFiles && uploadedFiles.length + files.length > maxFiles) {
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("data-disabled", disabledState ? "true" : "false");
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 SuperLeap SDK, or FlowUI state. The higher-level core/crm.js
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 SuperLeap CRM?",
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 SuperLeap CRM?",
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 SuperLeap object (from superleapClient.js)
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 SuperLeap API from superleapClient.js which
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.SuperLeap) return global.SuperLeap;
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
- * SuperLeap SDK.
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 SuperLeap.init() (default true)
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 SuperLeap SDK
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
- * Register a callback for when the CRM form is submitted successfully.
252
- * The CRM sends a 'crm:formSubmitSuccess' message after the form saves.
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 {Function} callbackreceives (payload)
255
- * @returns {Function} unsubscribe function
255
+ * @param {Object} [payload]optional data about the submission
256
256
  */
257
- function onFormSubmitSuccess(callback) {
257
+ function formSubmittedSuccessfully(payload) {
258
258
  var bridge = getBridge();
259
- if (!bridge) {
260
- return function () {};
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 SuperLeap)
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.onFormSubmitSuccess = onFormSubmitSuccess;
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
- "SuperLeap CRM Bridge: superleapClient not found. Make sure core/superleapClient.js loads before core/crm.js",
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);