@superleapai/flow-ui 2.2.9 → 2.2.11

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.
@@ -42,9 +42,18 @@
42
42
  return { show: noop, hide: noop, destroy: noop, element: null };
43
43
  }
44
44
 
45
+ // Wrap trigger in a relative container so popover can be absolute relative to it (full width so parent controls it)
46
+ const container = document.createElement("div");
47
+ container.className = "relative w-full";
48
+ const triggerParent = triggerEl.parentNode;
49
+ if (triggerParent) {
50
+ triggerParent.insertBefore(container, triggerEl);
51
+ container.appendChild(triggerEl);
52
+ }
53
+
45
54
  const wrapper = document.createElement("div");
46
55
  wrapper.className =
47
- "fixed z-50 pointer-events-none opacity-0 invisible transition-opacity duration-150 ease-out";
56
+ "absolute z-50 pointer-events-none opacity-0 invisible transition-opacity duration-150 ease-out";
48
57
  wrapper.setAttribute("aria-hidden", "true");
49
58
 
50
59
  const panel = document.createElement("div");
@@ -80,57 +89,46 @@
80
89
  panel.appendChild(body);
81
90
 
82
91
  wrapper.appendChild(panel);
92
+ container.appendChild(wrapper);
83
93
 
84
94
  function noop() {}
85
95
 
86
96
  function position() {
87
- const rect = triggerEl.getBoundingClientRect();
97
+ const triggerRect = triggerEl.getBoundingClientRect();
88
98
  const panelRect = panel.getBoundingClientRect();
89
99
  const gap = 8;
90
100
  let top = 0;
91
101
  let left = 0;
92
102
 
93
103
  // Alignment offset: start = 0, center = half diff, end = full diff
94
- const alignLeft = (align === "center" ? (rect.width - panelRect.width) / 2 : align === "end" ? rect.width - panelRect.width : 0);
95
- const alignTop = (align === "center" ? (rect.height - panelRect.height) / 2 : align === "end" ? rect.height - panelRect.height : 0);
104
+ const alignLeft = (align === "center" ? (triggerRect.width - panelRect.width) / 2 : align === "end" ? triggerRect.width - panelRect.width : 0);
105
+ const alignTop = (align === "center" ? (triggerRect.height - panelRect.height) / 2 : align === "end" ? triggerRect.height - panelRect.height : 0);
96
106
 
97
107
  switch (placement) {
98
108
  case "bottom":
99
- top = rect.bottom + gap;
100
- left = rect.left + alignLeft;
109
+ top = triggerRect.height + gap;
110
+ left = alignLeft;
101
111
  break;
102
112
  case "top":
103
- top = rect.top - panelRect.height - gap;
104
- left = rect.left + alignLeft;
113
+ top = -panelRect.height - gap;
114
+ left = alignLeft;
105
115
  break;
106
116
  case "right":
107
- top = rect.top + alignTop;
108
- left = rect.right + gap;
117
+ top = alignTop;
118
+ left = triggerRect.width + gap;
109
119
  break;
110
120
  case "left":
111
- top = rect.top + alignTop;
112
- left = rect.left - panelRect.width - gap;
121
+ top = alignTop;
122
+ left = -panelRect.width - gap;
113
123
  break;
114
124
  default:
115
- top = rect.bottom + gap;
116
- left = rect.left + alignLeft;
125
+ top = triggerRect.height + gap;
126
+ left = alignLeft;
117
127
  }
118
128
 
119
- // Keep within viewport
120
- const padding = 8;
121
- if (left < padding) left = padding;
122
- if (left + panelRect.width > window.innerWidth - padding) {
123
- left = window.innerWidth - panelRect.width - padding;
124
- }
125
- if (top < padding) top = padding;
126
- if (top + panelRect.height > window.innerHeight - padding) {
127
- top = window.innerHeight - panelRect.height - padding;
128
- }
129
-
130
- wrapper.style.left = "0";
131
- wrapper.style.top = "0";
132
- wrapper.style.transform = "translate(" + left + "px, " + top + "px)";
133
- // Force reflow so transform is applied before we show (avoids flash from left/top-left)
129
+ wrapper.style.transform = "";
130
+ wrapper.style.top = top + "px";
131
+ wrapper.style.left = left + "px";
134
132
  wrapper.offsetHeight;
135
133
  }
136
134
 
@@ -144,24 +142,7 @@
144
142
 
145
143
  function show() {
146
144
  if (onOpen) onOpen();
147
- var justAppended = !wrapper.parentNode;
148
- if (justAppended) {
149
- document.body.appendChild(wrapper);
150
- }
151
- // On first open, wait for layout so getBoundingClientRect() is correct (avoids wrong position / "from left" look)
152
- if (justAppended) {
153
- requestAnimationFrame(function () {
154
- position();
155
- wrapper.classList.remove("invisible", "opacity-0", "pointer-events-none");
156
- wrapper.classList.add("visible", "opacity-100", "pointer-events-auto");
157
- wrapper.setAttribute("aria-hidden", "false");
158
- requestAnimationFrame(function () {
159
- requestAnimationFrame(function () {
160
- panel.setAttribute("data-state", "open");
161
- });
162
- });
163
- });
164
- } else {
145
+ requestAnimationFrame(function () {
165
146
  position();
166
147
  wrapper.classList.remove("invisible", "opacity-0", "pointer-events-none");
167
148
  wrapper.classList.add("visible", "opacity-100", "pointer-events-auto");
@@ -171,7 +152,7 @@
171
152
  panel.setAttribute("data-state", "open");
172
153
  });
173
154
  });
174
- }
155
+ });
175
156
  }
176
157
 
177
158
  function destroy() {
@@ -179,6 +160,10 @@
179
160
  if (wrapper.parentNode) {
180
161
  wrapper.parentNode.removeChild(wrapper);
181
162
  }
163
+ if (container.parentNode && triggerEl.parentNode === container) {
164
+ container.parentNode.insertBefore(triggerEl, container);
165
+ container.parentNode.removeChild(container);
166
+ }
182
167
  if (closeOnClickOutside) {
183
168
  document.removeEventListener("click", outsideClick);
184
169
  }
@@ -10,7 +10,14 @@
10
10
  (function (global) {
11
11
  "use strict";
12
12
 
13
- var Popover = global.Popover;
13
+ function getDep(name) {
14
+ if (global.FlowUI && typeof global.FlowUI._getComponent === "function") {
15
+ var c = global.FlowUI._getComponent(name);
16
+ if (c) return c;
17
+ }
18
+ return global[name];
19
+ }
20
+
14
21
  var InputComponent = global.InputComponent;
15
22
  var Spinner = global.Spinner;
16
23
 
@@ -23,7 +30,7 @@
23
30
  role: { iconStr: "IconShield", color: "info" },
24
31
  iframe: { iconStr: "IconLayout", color: "neutral" },
25
32
  lead: { iconStr: "IconUser", color: "primary" },
26
- opportunity: { iconStr: "IconCurrencyDollar", color: "success" },
33
+ opportunity: { iconStr: "IconStar", color: "success" },
27
34
  call_log: { iconStr: "IconPhone", color: "info" },
28
35
  communication: { iconStr: "IconMessage", color: "primary" },
29
36
  history_field: { iconStr: "IconClock", color: "neutral" },
@@ -183,19 +190,13 @@
183
190
  var selectedRecords = [];
184
191
  var allRecords = [];
185
192
  var filteredRecords = [];
186
- var isOpen = false;
187
193
  var searchTerm = "";
188
194
  var searchDebounceTimer = null;
189
- var usePopover = Popover && typeof Popover.create === "function";
190
195
  var popover = null;
191
196
  var hasMoreRecords = true;
192
197
  var currentPage = 1;
193
198
  var isFetchingMore = false;
194
199
  var totalFetched = 0;
195
- var contentBase = "record-multiselect-content min-w-[8rem] ";
196
- if (!usePopover) {
197
- 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 ";
198
- }
199
200
 
200
201
  // Trigger wrapper + button
201
202
  var triggerWrapper = document.createElement("span");
@@ -290,7 +291,7 @@
290
291
  var content = document.createElement("div");
291
292
  content.setAttribute("role", "listbox");
292
293
  content.setAttribute("aria-multiselectable", "true");
293
- content.className = contentBase + (usePopover ? "max-h-[30vh] overflow-hidden flex flex-col" : "top-full mt-1 -translate-y-1 group-[.open]:translate-y-0");
294
+ content.className = "record-multiselect-content max-h-[30vh] overflow-hidden flex flex-col";
294
295
 
295
296
  var searchWrap = document.createElement("div");
296
297
  searchWrap.className = "p-8 pb-4 border-b-1/2 border-border-primary ";
@@ -357,57 +358,58 @@
357
358
 
358
359
  content.appendChild(optionsList);
359
360
 
360
- if (!usePopover) {
361
- container.appendChild(content);
362
- }
363
-
364
- if (usePopover) {
365
- popover = Popover.create({
366
- trigger: trigger,
367
- content: content,
368
- placement: "bottom",
369
- align: "start",
370
- closeOnClickOutside: true,
371
- bodyClassName: "p-0 overflow-hidden",
372
- panelClassName: "max-h-[30vh] overflow-hidden",
373
- onOpen: function () {
374
- if (disabled) {
375
- popover.hide();
376
- return;
377
- }
378
- document.querySelectorAll(".custom-select.open, .record-select.open, .custom-multiselect.open, .record-multiselect.open").forEach(function (other) {
379
- if (other !== container) {
380
- other.classList.remove("open");
381
- var t = other.querySelector("button, .custom-select-trigger, .record-select-trigger, .multiselect-trigger-wrapper button, .record-multiselect-trigger");
382
- if (t) t.setAttribute("aria-expanded", "false");
383
- }
384
- });
385
- isOpen = true;
386
- container.classList.add("open");
387
- trigger.setAttribute("aria-expanded", "true");
388
- searchTerm = "";
389
- if (searchInputWrapper) searchInputWrapper.setValue("");
390
- else if (searchInputEl) searchInputEl.value = "";
391
- content.style.minWidth = trigger.offsetWidth + "px";
392
- loadInitialAndRender();
393
- setTimeout(function () {
394
- if (searchInputEl) searchInputEl.focus();
395
- }, 0);
396
- },
397
- onClose: function () {
398
- isOpen = false;
399
- container.classList.remove("open");
400
- trigger.setAttribute("aria-expanded", "false");
401
- searchTerm = "";
402
- if (searchInputWrapper) searchInputWrapper.setValue("");
403
- else if (searchInputEl) searchInputEl.value = "";
404
- if (searchDebounceTimer) {
405
- clearTimeout(searchDebounceTimer);
406
- searchDebounceTimer = null;
361
+ var Popover = getDep("Popover");
362
+ if (!Popover || typeof Popover.create !== "function") {
363
+ throw new Error("RecordMultiSelect requires Popover");
364
+ }
365
+ popover = Popover.create({
366
+ trigger: trigger,
367
+ content: content,
368
+ placement: "bottom",
369
+ align: "start",
370
+ closeOnClickOutside: true,
371
+ bodyClassName: "p-0 overflow-hidden",
372
+ panelClassName: "max-h-[30vh] overflow-hidden",
373
+ onOpen: function () {
374
+ if (disabled) {
375
+ popover.hide();
376
+ return;
377
+ }
378
+ document.querySelectorAll(".custom-select.open, .record-select.open, .custom-multiselect.open, .record-multiselect.open, .enum-select, .enum-multiselect").forEach(function (other) {
379
+ if (other !== container && other.popoverInstance) {
380
+ other.popoverInstance.hide();
407
381
  }
408
- },
409
- });
410
- }
382
+ });
383
+ container.classList.add("open");
384
+ trigger.setAttribute("aria-expanded", "true");
385
+ searchTerm = "";
386
+ if (searchInputWrapper) searchInputWrapper.setValue("");
387
+ else if (searchInputEl) searchInputEl.value = "";
388
+ var triggerWidthPx = trigger.offsetWidth + "px";
389
+ content.style.minWidth = triggerWidthPx;
390
+ content.style.width = triggerWidthPx;
391
+ if (popover.panel) {
392
+ popover.panel.style.width = triggerWidthPx;
393
+ popover.panel.style.minWidth = triggerWidthPx;
394
+ }
395
+ loadInitialAndRender();
396
+ setTimeout(function () {
397
+ if (searchInputEl) searchInputEl.focus();
398
+ }, 0);
399
+ },
400
+ onClose: function () {
401
+ container.classList.remove("open");
402
+ trigger.setAttribute("aria-expanded", "false");
403
+ searchTerm = "";
404
+ if (searchInputWrapper) searchInputWrapper.setValue("");
405
+ else if (searchInputEl) searchInputEl.value = "";
406
+ if (searchDebounceTimer) {
407
+ clearTimeout(searchDebounceTimer);
408
+ searchDebounceTimer = null;
409
+ }
410
+ },
411
+ });
412
+ container.popoverInstance = popover;
411
413
 
412
414
  function isSelected(recordId) {
413
415
  return values.some(function (v) {
@@ -814,42 +816,11 @@
814
816
 
815
817
  function openDropdown() {
816
818
  if (disabled) return;
817
- if (usePopover && popover) {
818
- popover.show();
819
- return;
820
- }
821
- document
822
- .querySelectorAll(".custom-select.open, .record-select.open, .custom-multiselect.open, .record-multiselect.open")
823
- .forEach(function (other) {
824
- if (other !== container) {
825
- other.classList.remove("open");
826
- var t = other.querySelector(
827
- "button, .custom-select-trigger, .record-select-trigger, .multiselect-trigger-wrapper button, .record-multiselect-trigger"
828
- );
829
- if (t) t.setAttribute("aria-expanded", "false");
830
- }
831
- });
832
- isOpen = true;
833
- container.classList.add("open");
834
- trigger.setAttribute("aria-expanded", "true");
835
- searchTerm = "";
836
- if (searchInputWrapper) searchInputWrapper.setValue("");
837
- else if (searchInputEl) searchInputEl.value = "";
838
- loadInitialAndRender();
839
- setTimeout(function () {
840
- if (searchInputEl) searchInputEl.focus();
841
- }, 0);
842
- updatePosition();
819
+ popover.show();
843
820
  }
844
821
 
845
822
  function closeDropdown() {
846
- if (usePopover && popover) {
847
- popover.hide();
848
- return;
849
- }
850
- isOpen = false;
851
- container.classList.remove("open");
852
- trigger.setAttribute("aria-expanded", "false");
823
+ popover.hide();
853
824
  searchTerm = "";
854
825
  if (searchInputWrapper) searchInputWrapper.setValue("");
855
826
  else if (searchInputEl) searchInputEl.value = "";
@@ -859,19 +830,6 @@
859
830
  }
860
831
  }
861
832
 
862
- function updatePosition() {
863
- if (usePopover) return;
864
- var rect = trigger.getBoundingClientRect();
865
- var vh = window.innerHeight;
866
- var below = vh - rect.bottom;
867
- var above = rect.top;
868
- if (below < 200 && above > below) {
869
- content.className = contentBase + "bottom-full mb-1 translate-y-1 group-[.open]:translate-y-0";
870
- } else {
871
- content.className = contentBase + "top-full mt-1 -translate-y-1 group-[.open]:translate-y-0";
872
- }
873
- }
874
-
875
833
  if (!searchInputWrapper && searchInputEl) {
876
834
  searchInputEl.addEventListener("input", function () {
877
835
  searchTerm = this.value.trim();
@@ -888,41 +846,19 @@
888
846
  });
889
847
  }
890
848
 
891
- if (usePopover && popover) {
892
- trigger.addEventListener("keydown", function (e) {
893
- if (disabled) return;
894
- if (e.key === "Enter" || e.key === " ") {
895
- e.preventDefault();
896
- if (isOpen) popover.hide();
897
- else popover.show();
898
- }
899
- });
900
- } else {
901
- trigger.addEventListener("click", function (e) {
849
+ trigger.addEventListener("keydown", function (e) {
850
+ if (disabled) return;
851
+ var isVisible = popover.element && popover.element.classList.contains("visible");
852
+ if (e.key === "Enter" || e.key === " ") {
902
853
  e.preventDefault();
903
- e.stopPropagation();
904
- if (isOpen) closeDropdown();
905
- else openDropdown();
906
- });
907
- trigger.addEventListener("keydown", function (e) {
908
- if (disabled) return;
909
- if (e.key === "Enter" || e.key === " ") {
910
- e.preventDefault();
911
- if (isOpen) closeDropdown();
912
- else openDropdown();
913
- }
914
- if (e.key === "Escape" && isOpen) {
915
- e.preventDefault();
916
- closeDropdown();
917
- }
918
- });
919
- document.addEventListener("click", function (e) {
920
- if (isOpen && !container.contains(e.target)) closeDropdown();
921
- });
922
- document.addEventListener("keydown", function (e) {
923
- if (e.key === "Escape" && isOpen) closeDropdown();
924
- });
925
- }
854
+ if (isVisible) popover.hide();
855
+ else popover.show();
856
+ }
857
+ if (e.key === "Escape" && isVisible) {
858
+ e.preventDefault();
859
+ popover.hide();
860
+ }
861
+ });
926
862
 
927
863
  container.updateValues = function (newValues) {
928
864
  values = Array.isArray(newValues) ? newValues.slice() : [];
@@ -933,7 +869,8 @@
933
869
  disabled = !!isDisabled;
934
870
  trigger.disabled = disabled;
935
871
  trigger.className = triggerClasses(variant, size, disabled, values.length === 0);
936
- if (disabled && isOpen) closeDropdown();
872
+ var isVisible = popover.element && popover.element.classList.contains("visible");
873
+ if (disabled && isVisible) popover.hide();
937
874
  };
938
875
 
939
876
  container.getValues = function () {