@superleapai/flow-ui 2.2.9 → 2.2.10

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.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Record Select Component (superleap-flow)
3
3
  * Single-record select with search; same trigger/content styling as Select.
4
- * Uses: Popover (dropdown), InputComponent (search), Spinner (loading), Avatar (vivid for user).
4
+ * Uses Popover for dropdown (required), InputComponent (search), Spinner (loading), Avatar (vivid for user).
5
5
  * Fetches records via superleapClient.getSdk().model(objectSlug).
6
6
  * For objectSlug === 'user' shows Vivid Avatar; otherwise static icon from schema or object map (database fallback).
7
7
  * Does not use icon from backend payload.
@@ -23,7 +23,7 @@
23
23
  role: { iconStr: "IconShield", color: "info" },
24
24
  iframe: { iconStr: "IconLayout", color: "neutral" },
25
25
  lead: { iconStr: "IconUser", color: "primary" },
26
- opportunity: { iconStr: "IconCurrencyDollar", color: "success" },
26
+ opportunity: { iconStr: "IconStar", color: "success" },
27
27
  call_log: { iconStr: "IconPhone", color: "info" },
28
28
  communication: { iconStr: "IconMessage", color: "primary" },
29
29
  history_field: { iconStr: "IconClock", color: "neutral" },
@@ -170,6 +170,12 @@
170
170
  errEl.textContent = "Record select: objectSlug is required.";
171
171
  return errEl;
172
172
  }
173
+ if (!Popover || typeof Popover.create !== "function") {
174
+ var popoverErr = document.createElement("div");
175
+ popoverErr.className = "text-reg-13 text-typography-quaternary-text";
176
+ popoverErr.textContent = "Record select: Popover is required.";
177
+ return popoverErr;
178
+ }
173
179
 
174
180
  var container = document.createElement("div");
175
181
  container.className = "record-select relative w-full group";
@@ -182,16 +188,11 @@
182
188
  var isOpen = false;
183
189
  var searchTerm = "";
184
190
  var searchDebounceTimer = null;
185
- var usePopover = Popover && typeof Popover.create === "function";
186
191
  var popover = null;
187
192
  var hasMoreRecords = true;
188
193
  var currentPage = 1;
189
194
  var isFetchingMore = false;
190
195
  var totalFetched = 0;
191
- var contentBase = "record-select-content min-w-[8rem] ";
192
- if (!usePopover) {
193
- contentBase += "absolute left-0 right-0 z-50 max-h-[30vh] overflow-hidden rounded-4 bg-fill-quarternary-fill-white shadow-default-medium opacity-0 invisible transition-all duration-150 ease-out group-[.open]:opacity-100 group-[.open]:visible ";
194
- }
195
196
 
196
197
  // Trigger wrapper + button (same structure as Select)
197
198
  var triggerWrapper = document.createElement("span");
@@ -257,7 +258,7 @@
257
258
  // Dropdown content: search + list (same content pattern as Select)
258
259
  var content = document.createElement("div");
259
260
  content.setAttribute("role", "listbox");
260
- content.className = contentBase + (usePopover ? "max-h-[30vh] overflow-hidden flex flex-col" : "top-full mt-1 -translate-y-1 group-[.open]:translate-y-0");
261
+ content.className = "record-select-content max-h-[30vh] overflow-hidden flex flex-col";
261
262
 
262
263
  var searchWrap = document.createElement("div");
263
264
  searchWrap.className = "py-8 border-b-1/2 border-border-primary";
@@ -324,57 +325,51 @@
324
325
 
325
326
  content.appendChild(optionsList);
326
327
 
327
- if (!usePopover) {
328
- container.appendChild(content);
329
- }
330
-
331
- if (usePopover) {
332
- popover = Popover.create({
333
- trigger: trigger,
334
- content: content,
335
- placement: "bottom",
336
- align: "start",
337
- closeOnClickOutside: true,
338
- bodyClassName: "p-0 overflow-hidden",
339
- panelClassName: "max-h-[30vh] overflow-hidden",
340
- onOpen: function () {
341
- if (disabled) {
342
- popover.hide();
343
- return;
344
- }
345
- document.querySelectorAll(".custom-select.open, .record-select.open").forEach(function (other) {
346
- if (other !== container) {
347
- other.classList.remove("open");
348
- var t = other.querySelector("button, .custom-select-trigger, .record-select-trigger");
349
- if (t) t.setAttribute("aria-expanded", "false");
350
- }
351
- });
352
- isOpen = true;
353
- container.classList.add("open");
354
- trigger.setAttribute("aria-expanded", "true");
355
- searchTerm = "";
356
- if (searchInputWrapper) searchInputWrapper.setValue("");
357
- else if (searchInputEl) searchInputEl.value = "";
358
- content.style.minWidth = trigger.offsetWidth + "px";
359
- loadInitialAndRender();
360
- setTimeout(function () {
361
- if (searchInputEl) searchInputEl.focus();
362
- }, 0);
363
- },
364
- onClose: function () {
365
- isOpen = false;
366
- container.classList.remove("open");
367
- trigger.setAttribute("aria-expanded", "false");
368
- searchTerm = "";
369
- if (searchInputWrapper) searchInputWrapper.setValue("");
370
- else if (searchInputEl) searchInputEl.value = "";
371
- if (searchDebounceTimer) {
372
- clearTimeout(searchDebounceTimer);
373
- searchDebounceTimer = null;
328
+ popover = Popover.create({
329
+ trigger: trigger,
330
+ content: content,
331
+ placement: "bottom",
332
+ align: "start",
333
+ closeOnClickOutside: true,
334
+ bodyClassName: "p-0 overflow-hidden",
335
+ panelClassName: "max-h-[30vh] overflow-hidden",
336
+ onOpen: function () {
337
+ if (disabled) {
338
+ popover.hide();
339
+ return;
340
+ }
341
+ document.querySelectorAll(".custom-select.open, .record-select.open").forEach(function (other) {
342
+ if (other !== container) {
343
+ other.classList.remove("open");
344
+ var t = other.querySelector("button, .custom-select-trigger, .record-select-trigger");
345
+ if (t) t.setAttribute("aria-expanded", "false");
374
346
  }
375
- },
376
- });
377
- }
347
+ });
348
+ isOpen = true;
349
+ container.classList.add("open");
350
+ trigger.setAttribute("aria-expanded", "true");
351
+ searchTerm = "";
352
+ if (searchInputWrapper) searchInputWrapper.setValue("");
353
+ else if (searchInputEl) searchInputEl.value = "";
354
+ content.style.minWidth = trigger.offsetWidth + "px";
355
+ loadInitialAndRender();
356
+ setTimeout(function () {
357
+ if (searchInputEl) searchInputEl.focus();
358
+ }, 0);
359
+ },
360
+ onClose: function () {
361
+ isOpen = false;
362
+ container.classList.remove("open");
363
+ trigger.setAttribute("aria-expanded", "false");
364
+ searchTerm = "";
365
+ if (searchInputWrapper) searchInputWrapper.setValue("");
366
+ else if (searchInputEl) searchInputEl.value = "";
367
+ if (searchDebounceTimer) {
368
+ clearTimeout(searchDebounceTimer);
369
+ searchDebounceTimer = null;
370
+ }
371
+ },
372
+ });
378
373
 
379
374
  if (clearBtn) clearBtn.style.display = canClear && value && !disabled ? "" : "none";
380
375
 
@@ -791,62 +786,11 @@
791
786
 
792
787
  function openDropdown() {
793
788
  if (disabled) return;
794
- if (usePopover && popover) {
795
- popover.show();
796
- return;
797
- }
798
- document
799
- .querySelectorAll(".custom-select.open, .record-select.open")
800
- .forEach(function (other) {
801
- if (other !== container) {
802
- other.classList.remove("open");
803
- var t = other.querySelector(
804
- "button, .custom-select-trigger, .record-select-trigger"
805
- );
806
- if (t) t.setAttribute("aria-expanded", "false");
807
- }
808
- });
809
- isOpen = true;
810
- container.classList.add("open");
811
- trigger.setAttribute("aria-expanded", "true");
812
- searchTerm = "";
813
- if (searchInputWrapper) searchInputWrapper.setValue("");
814
- else if (searchInputEl) searchInputEl.value = "";
815
- loadInitialAndRender();
816
- setTimeout(function () {
817
- if (searchInputEl) searchInputEl.focus();
818
- }, 0);
819
- updatePosition();
789
+ popover.show();
820
790
  }
821
791
 
822
792
  function closeDropdown() {
823
- if (usePopover && popover) {
824
- popover.hide();
825
- return;
826
- }
827
- isOpen = false;
828
- container.classList.remove("open");
829
- trigger.setAttribute("aria-expanded", "false");
830
- searchTerm = "";
831
- if (searchInputWrapper) searchInputWrapper.setValue("");
832
- else if (searchInputEl) searchInputEl.value = "";
833
- if (searchDebounceTimer) {
834
- clearTimeout(searchDebounceTimer);
835
- searchDebounceTimer = null;
836
- }
837
- }
838
-
839
- function updatePosition() {
840
- if (usePopover) return;
841
- var rect = trigger.getBoundingClientRect();
842
- var vh = window.innerHeight;
843
- var below = vh - rect.bottom;
844
- var above = rect.top;
845
- if (below < 200 && above > below) {
846
- content.className = contentBase + "bottom-full mb-1 translate-y-1 group-[.open]:translate-y-0";
847
- } else {
848
- content.className = contentBase + "top-full mt-1 -translate-y-1 group-[.open]:translate-y-0";
849
- }
793
+ popover.hide();
850
794
  }
851
795
 
852
796
  if (!searchInputWrapper && searchInputEl) {
@@ -865,41 +809,14 @@
865
809
  });
866
810
  }
867
811
 
868
- if (usePopover && popover) {
869
- trigger.addEventListener("keydown", function (e) {
870
- if (disabled) return;
871
- if (e.key === "Enter" || e.key === " ") {
872
- e.preventDefault();
873
- if (isOpen) popover.hide();
874
- else popover.show();
875
- }
876
- });
877
- } else {
878
- trigger.addEventListener("click", function (e) {
812
+ trigger.addEventListener("keydown", function (e) {
813
+ if (disabled) return;
814
+ if (e.key === "Enter" || e.key === " ") {
879
815
  e.preventDefault();
880
- e.stopPropagation();
881
- if (isOpen) closeDropdown();
882
- else openDropdown();
883
- });
884
- trigger.addEventListener("keydown", function (e) {
885
- if (disabled) return;
886
- if (e.key === "Enter" || e.key === " ") {
887
- e.preventDefault();
888
- if (isOpen) closeDropdown();
889
- else openDropdown();
890
- }
891
- if (e.key === "Escape" && isOpen) {
892
- e.preventDefault();
893
- closeDropdown();
894
- }
895
- });
896
- document.addEventListener("click", function (e) {
897
- if (isOpen && !container.contains(e.target)) closeDropdown();
898
- });
899
- document.addEventListener("keydown", function (e) {
900
- if (e.key === "Escape" && isOpen) closeDropdown();
901
- });
902
- }
816
+ if (isOpen) popover.hide();
817
+ else popover.show();
818
+ }
819
+ });
903
820
 
904
821
  container.updateValue = function (newVal) {
905
822
  setValue(newVal);
@@ -52,6 +52,14 @@
52
52
  return Array.prototype.filter.call(arguments, Boolean).join(" ");
53
53
  }
54
54
 
55
+ function getDep(name) {
56
+ if (typeof global.FlowUI !== "undefined" && typeof global.FlowUI._getComponent === "function") {
57
+ var c = global.FlowUI._getComponent(name);
58
+ if (c) return c;
59
+ }
60
+ return global[name];
61
+ }
62
+
55
63
  /**
56
64
  * Create a custom select component
57
65
  * @param {Object} config
@@ -81,6 +89,11 @@
81
89
  var value =
82
90
  config.value !== undefined && config.value !== null ? config.value : "";
83
91
 
92
+ var Popover = getDep("Popover");
93
+ if (!Popover || typeof Popover.create !== "function") {
94
+ throw new Error("Select requires Popover");
95
+ }
96
+
84
97
  var selectedOption = options.find(function (opt) {
85
98
  var optValue =
86
99
  opt.value !== undefined && opt.value !== null
@@ -180,11 +193,7 @@
180
193
 
181
194
  var content = document.createElement("div");
182
195
  content.setAttribute("role", "listbox");
183
- var contentBase =
184
- "custom-select-content absolute left-0 right-0 z-50 max-h-[200px] min-w-[8rem] overflow-hidden rounded-4 bg-fill-quarternary-fill-white shadow-default-medium opacity-0 invisible transition-all duration-150 ease-out " +
185
- "group-[.open]:opacity-100 group-[.open]:visible ";
186
- content.className =
187
- contentBase + "top-full mt-1 -translate-y-1 group-[.open]:translate-y-0";
196
+ content.className = "custom-select-content w-full max-h-[200px] overflow-hidden flex flex-col";
188
197
 
189
198
  var optionsList = document.createElement("div");
190
199
  optionsList.className =
@@ -238,47 +247,66 @@
238
247
  }
239
248
 
240
249
  content.appendChild(optionsList);
241
- container.appendChild(content);
242
250
 
243
- var isOpen = false;
244
251
  var highlightedIndex = -1;
252
+ var popover = Popover.create({
253
+ trigger: trigger,
254
+ content: content,
255
+ placement: "bottom",
256
+ align: "start",
257
+ closeOnClickOutside: true,
258
+ bodyClassName: "p-0 overflow-hidden",
259
+ panelClassName: "min-w-[var(--trigger-width)] max-h-[200px] overflow-hidden",
260
+ onOpen: function () {
261
+ if (disabled) {
262
+ popover.hide();
263
+ return;
264
+ }
265
+ document
266
+ .querySelectorAll(".custom-select, .record-select, .enum-select, .enum-multiselect, .custom-multiselect, .record-multiselect")
267
+ .forEach(function (other) {
268
+ if (other !== container && other.popoverInstance) {
269
+ other.popoverInstance.hide();
270
+ }
271
+ });
272
+ trigger.setAttribute("aria-expanded", "true");
273
+ chevron.style.transform = "rotate(180deg)";
274
+ highlightOptionByValue(value);
275
+ if (popover.panel) {
276
+ var triggerWidthPx = trigger.offsetWidth + "px";
277
+ popover.panel.style.setProperty("--trigger-width", triggerWidthPx);
278
+ popover.panel.style.minWidth = triggerWidthPx;
279
+ popover.panel.style.width = triggerWidthPx;
280
+ }
281
+ },
282
+ onClose: function () {
283
+ trigger.setAttribute("aria-expanded", "false");
284
+ chevron.style.transform = "";
285
+ highlightedIndex = -1;
286
+ },
287
+ });
288
+ container.popoverInstance = popover;
245
289
 
246
290
  function openDropdown() {
247
291
  if (disabled) return;
248
- document
249
- .querySelectorAll(".custom-select.open, .record-select.open")
250
- .forEach(function (other) {
251
- if (other !== container) {
252
- other.classList.remove("open");
253
- var t = other.querySelector(
254
- "button, .custom-select-trigger, .record-select-trigger"
255
- );
256
- if (t) t.setAttribute("aria-expanded", "false");
257
- }
258
- });
259
- isOpen = true;
260
- container.classList.add("open");
261
- trigger.setAttribute("aria-expanded", "true");
262
- highlightOptionByValue(value);
263
- updatePosition();
292
+ popover.show();
264
293
  }
265
294
 
266
295
  function closeDropdown() {
267
- isOpen = false;
268
- container.classList.remove("open");
269
- trigger.setAttribute("aria-expanded", "false");
296
+ popover.hide();
270
297
  highlightedIndex = -1;
271
298
  }
272
299
 
273
300
  function toggleDropdown() {
301
+ var isVisible = popover.element && popover.element.classList.contains("visible");
274
302
  var others = document.querySelectorAll(
275
- ".custom-select.open, .record-select.open"
303
+ ".custom-select, .record-select, .enum-select, .enum-multiselect, .custom-multiselect, .record-multiselect"
276
304
  );
277
305
  var hasOther = Array.from(others).some(function (s) {
278
- return s !== container;
306
+ return s !== container && s.popoverInstance && s.popoverInstance.element && s.popoverInstance.element.classList.contains("visible");
279
307
  });
280
308
  if (hasOther) openDropdown();
281
- else if (isOpen) closeDropdown();
309
+ else if (isVisible) closeDropdown();
282
310
  else openDropdown();
283
311
  }
284
312
 
@@ -357,40 +385,26 @@
357
385
 
358
386
  function scrollToOption(opt) {
359
387
  if (!opt) return;
360
- var cr = content.getBoundingClientRect();
388
+ var cr = optionsList.getBoundingClientRect();
361
389
  var top = opt.offsetTop;
362
390
  var bottom = top + opt.offsetHeight;
363
- var st = content.scrollTop;
391
+ var st = optionsList.scrollTop;
364
392
  var sb = st + cr.height;
365
- if (top < st) content.scrollTop = top - 8;
393
+ if (top < st) optionsList.scrollTop = top - 8;
366
394
  else if (bottom > sb)
367
- content.scrollTop = bottom - cr.height + 8;
368
- }
369
-
370
- function updatePosition() {
371
- var rect = trigger.getBoundingClientRect();
372
- var vh = window.innerHeight;
373
- var below = vh - rect.bottom;
374
- var above = rect.top;
375
- if (below < 200 && above > below) {
376
- content.className =
377
- contentBase +
378
- "bottom-full mb-1 translate-y-1 group-[.open]:translate-y-0";
379
- } else {
380
- content.className =
381
- contentBase +
382
- "top-full mt-1 -translate-y-1 group-[.open]:translate-y-0";
383
- }
395
+ optionsList.scrollTop = bottom - cr.height + 8;
384
396
  }
385
397
 
386
398
  trigger.addEventListener("click", function (e) {
387
- e.preventDefault();
388
- e.stopPropagation();
389
- toggleDropdown();
390
- });
399
+ if (disabled) {
400
+ e.preventDefault();
401
+ e.stopImmediatePropagation();
402
+ }
403
+ }, true);
391
404
 
392
405
  trigger.addEventListener("keydown", function (e) {
393
406
  if (disabled) return;
407
+ var isVisible = popover.element && popover.element.classList.contains("visible");
394
408
  switch (e.key) {
395
409
  case "Enter":
396
410
  case " ":
@@ -399,16 +413,16 @@
399
413
  break;
400
414
  case "ArrowDown":
401
415
  e.preventDefault();
402
- if (!isOpen) openDropdown();
416
+ if (!isVisible) openDropdown();
403
417
  else navigateOptions(1);
404
418
  break;
405
419
  case "ArrowUp":
406
420
  e.preventDefault();
407
- if (!isOpen) openDropdown();
421
+ if (!isVisible) openDropdown();
408
422
  else navigateOptions(-1);
409
423
  break;
410
424
  case "Escape":
411
- if (isOpen) {
425
+ if (isVisible) {
412
426
  e.preventDefault();
413
427
  closeDropdown();
414
428
  }
@@ -429,13 +443,6 @@
429
443
  scrollToOption(opt);
430
444
  }
431
445
 
432
- document.addEventListener("click", function (e) {
433
- if (isOpen && !container.contains(e.target)) closeDropdown();
434
- });
435
- document.addEventListener("keydown", function (e) {
436
- if (e.key === "Escape" && isOpen) closeDropdown();
437
- });
438
-
439
446
  container.updateValue = function (newValue) {
440
447
  value =
441
448
  newValue !== undefined && newValue !== null ? newValue : "";
@@ -532,7 +539,8 @@
532
539
  canClear && !!value && !disabled
533
540
  );
534
541
  updateClearButton();
535
- if (disabled && isOpen) closeDropdown();
542
+ var isVisible = popover.element && popover.element.classList.contains("visible");
543
+ if (disabled && isVisible) closeDropdown();
536
544
  };
537
545
 
538
546
  return container;
@@ -296,12 +296,12 @@
296
296
  if (periodColumn) periodColumn.scrollToSelected();
297
297
  }
298
298
 
299
+ // Trigger must be in DOM before Popover.create() so Popover can wrap it and insert its panel into the document.
300
+ container.appendChild(trigger);
301
+
299
302
  var Popover = getDep("Popover");
300
303
  if (!Popover || typeof Popover.create !== "function") {
301
- container.appendChild(trigger);
302
- container.updateValue = function (newVal) { value = typeof newVal === "string" ? newVal : ""; };
303
- container.setDisabled = function (isDisabled) { trigger.disabled = !!isDisabled; };
304
- return container;
304
+ throw new Error("TimePicker requires Popover");
305
305
  }
306
306
  var popover = Popover.create({
307
307
  trigger: trigger,
@@ -322,8 +322,6 @@
322
322
  });
323
323
  hidePopover = popover.hide;
324
324
 
325
- container.appendChild(trigger);
326
-
327
325
  container.updateValue = function (newVal) {
328
326
  value = typeof newVal === "string" ? newVal : "";
329
327
  var p = parseValue(value);
@@ -96,18 +96,11 @@
96
96
 
97
97
  _config = mergeConfig(DEFAULT_CONFIG, config);
98
98
 
99
- // Create SDK instance immediately during init
100
- // Check for both global function and class constructor
99
+ // Create SDK instance using the SDK factory if available
101
100
  if (typeof global.createSuperLeapSDK === "function") {
102
101
  _sdkInstance = global.createSuperLeapSDK(_config);
103
- console.log("[superleapClient] SDK created via createSuperLeapSDK");
104
- console.log("[superleapClient] SDK has records?", !!_sdkInstance?.records);
105
- console.log("[superleapClient] SDK keys:", _sdkInstance ? Object.keys(_sdkInstance) : "null");
106
102
  } else if (typeof global.SuperLeapSDK === "function") {
107
103
  _sdkInstance = new global.SuperLeapSDK(_config);
108
- console.log("[superleapClient] SDK created via new SuperLeapSDK()");
109
- console.log("[superleapClient] SDK has records?", !!_sdkInstance?.records);
110
- console.log("[superleapClient] SDK keys:", _sdkInstance ? Object.keys(_sdkInstance) : "null");
111
104
  } else {
112
105
  console.warn(
113
106
  "[superleapClient] SuperLeap SDK not found. Install with: npm install superleap-sdk"
@@ -117,8 +110,8 @@
117
110
  }
118
111
 
119
112
  /**
120
- * Get the SDK instance. Returns the instance created during init().
121
- * Returns null if init() was not called or the SDK script is not loaded (components can show empty state).
113
+ * Get the SDK instance.
114
+ * Returns null if init() was not called or the SDK script is not loaded.
122
115
  *
123
116
  * @returns {SuperLeapSDK|null} SDK instance or null
124
117
  */