gbs-add-block 1.0.7 → 1.0.9

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # GBS Building Blocks 2.0 (v1.0.7)
1
+ # GBS Building Blocks 2.0 (v1.0.9)
2
2
 
3
3
  Latest and upgraded version of GBS building blocks with headless UI and removed dependencies.
4
4
 
@@ -6,7 +6,7 @@ Latest and upgraded version of GBS building blocks with headless UI and removed
6
6
 
7
7
  For detailed documentation on usage and props, Please visit: [Building Block Documentation v2.0](https://blackmax-designs.gitbook.io/building-block-v2.0)
8
8
 
9
- ## What's New 🎉 (Ver 1.0.7)
9
+ ## What's New 🎉 (Ver 1.0.9)
10
10
 
11
11
  - Uploader Enhancement
12
12
  - Select Bug Fix
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gbs-add-block",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "React Component Library",
5
5
  "type": "module",
6
6
  "files": [
@@ -12,6 +12,7 @@ import React, {
12
12
  useEffect,
13
13
  useImperativeHandle,
14
14
  useRef,
15
+ useState,
15
16
  } from "react";
16
17
  import { createPortal } from "react-dom";
17
18
  import Icon from "../icon/Icon";
@@ -24,11 +25,49 @@ import {
24
25
  useSelectData,
25
26
  applyScrollbarStyles,
26
27
  useKeyboardNavigation,
27
- usePortalPopup,
28
- getPortalStyles,
29
- getAnimationClasses,
28
+ useClickOutside,
30
29
  } from "@grampro/headless-helpers";
31
30
 
31
+ // Portal Dropdown Component
32
+ const PortalDropdown = ({ targetRef, children, isVisible }: any) => {
33
+ const [position, setPosition] = useState({ top: 0, left: 0, width: 0 });
34
+
35
+ useEffect(() => {
36
+ if (isVisible && targetRef.current) {
37
+ const rect = targetRef.current.getBoundingClientRect();
38
+ const scrollTop =
39
+ window.pageYOffset || document.documentElement.scrollTop;
40
+ const scrollLeft =
41
+ window.pageXOffset || document.documentElement.scrollLeft;
42
+
43
+ setPosition({
44
+ top: rect.bottom + scrollTop + 4,
45
+ left: rect.left + scrollLeft,
46
+ width: rect.width,
47
+ });
48
+ }
49
+ }, [isVisible, targetRef]);
50
+
51
+ if (!isVisible) return null;
52
+
53
+ return createPortal(
54
+ <div
55
+ style={{
56
+ position: "absolute",
57
+ top: position.top,
58
+ left: position.left,
59
+ width: position.width,
60
+ zIndex: 1000,
61
+ }}
62
+ className={popUp["pop-up-style"]}
63
+ data-select-portal="true"
64
+ >
65
+ {children}
66
+ </div>,
67
+ document.body
68
+ );
69
+ };
70
+
32
71
  const Select = forwardRef<SelectHandle, SelectProps>((props, ref) => {
33
72
  const {
34
73
  id = "",
@@ -70,16 +109,14 @@ const Select = forwardRef<SelectHandle, SelectProps>((props, ref) => {
70
109
 
71
110
  const inputRef = useRef<HTMLInputElement>(null);
72
111
  const selectRef = useRef<HTMLDivElement>(null);
112
+ const buttonRef = useRef<HTMLButtonElement>(null);
73
113
 
74
- // Use the custom portal hooks
75
- const position = usePortalPopup({
76
- isOpen: showPopover,
77
- onClose: () => setShowPopover(false),
78
- triggerRef: selectRef,
79
- popupHeight: 250,
80
- offset: 4,
81
- minSpaceRequired: 50,
82
- portalSelector: '[data-select-portal="true"]',
114
+ useClickOutside(selectRef as React.RefObject<HTMLElement>, (event) => {
115
+ const portalElement = document.querySelector('[data-select-portal="true"]');
116
+ if (portalElement && portalElement.contains(event.target as Node)) {
117
+ return;
118
+ }
119
+ setShowPopover(false);
83
120
  });
84
121
 
85
122
  // Update the handleSelect to accept a SelectItem
@@ -130,15 +167,9 @@ const Select = forwardRef<SelectHandle, SelectProps>((props, ref) => {
130
167
  selected: selectedItem,
131
168
  }));
132
169
 
133
- // Portal popup content with smart positioning
134
- const popupContent = showPopover && !disabled && (
135
- <div
136
- className={`${popUp["pop-up-style"]} ${getAnimationClasses(
137
- position.placement
138
- )}`}
139
- style={getPortalStyles(position, 250)}
140
- data-select-portal="true"
141
- >
170
+ // Portal dropdown content
171
+ const dropdownContent = (
172
+ <>
142
173
  {showSearch && (
143
174
  <div className={selectStyle["input-parent"]}>
144
175
  <Icon elements={search} svgClass={iconClass["grey-common"]} />
@@ -182,61 +213,61 @@ const Select = forwardRef<SelectHandle, SelectProps>((props, ref) => {
182
213
  ) : (
183
214
  <div className="text-sm text-center p-2">No Data Found</div>
184
215
  )}
185
- </div>
216
+ </>
186
217
  );
187
218
 
188
219
  return (
189
- <>
190
- <div
191
- className="relative w-full mt-2"
192
- ref={selectRef}
193
- id={id}
194
- onKeyDown={handleKeyDown}
195
- >
196
- <div className="w-full relative">
220
+ <div
221
+ className="relative w-full mt-2"
222
+ ref={selectRef}
223
+ id={id}
224
+ onKeyDown={handleKeyDown}
225
+ >
226
+ <div className="w-full relative">
227
+ <button
228
+ ref={buttonRef} // Add ref for portal positioning
229
+ className={`${error ? primary["error-border"] : "border"} ${
230
+ selectStyle["select-button"]
231
+ } ${disabled ? "opacity-50 cursor-not-allowed" : ""}`}
232
+ onClick={togglePopover}
233
+ type="button"
234
+ disabled={disabled}
235
+ >
236
+ {selectedDisplay || placeholder}
237
+ <Icon
238
+ elements={upDown}
239
+ svgClass={`${iconClass["grey-common"]} ${
240
+ disabled ? "opacity-50" : ""
241
+ }`}
242
+ />
243
+ </button>
244
+ {selectedDisplay && !disabled && (
197
245
  <button
198
- className={`${error ? primary["error-border"] : "border"} ${
199
- selectStyle["select-button"]
200
- } ${disabled ? "opacity-50 cursor-not-allowed" : ""}`}
201
- onClick={togglePopover}
202
- type="button"
203
- disabled={disabled}
246
+ className={selectStyle["selectedDisplay-Button"]}
247
+ onClick={handleClear}
204
248
  >
205
- {selectedDisplay || placeholder}
206
- <Icon
207
- elements={upDown}
208
- svgClass={`${iconClass["grey-common"]} ${
209
- disabled ? "opacity-50" : ""
210
- } ${
211
- showPopover && position.placement === "top" ? "rotate-180" : ""
212
- }`}
213
- />
249
+ <Icon elements={x} svgClass={iconClass["grey-common"]} />
214
250
  </button>
215
- {selectedDisplay && !disabled && (
216
- <button
217
- className={selectStyle["selectedDisplay-Button"]}
218
- onClick={handleClear}
219
- >
220
- <Icon elements={x} svgClass={iconClass["grey-common"]} />
221
- </button>
222
- )}
223
- {error && <p className={primary["error-primary"]}>{error}</p>}
224
- </div>
225
-
226
- <input
227
- type="hidden"
228
- name={name}
229
- value={selectedItem || ""}
230
- readOnly
231
- disabled={disabled}
232
- />
251
+ )}
252
+ {error && <p className={primary["error-primary"]}>{error}</p>}
233
253
  </div>
234
254
 
235
- {/* Render popup in portal to document.body */}
236
- {typeof document !== "undefined" &&
237
- popupContent &&
238
- createPortal(popupContent, document.body)}
239
- </>
255
+ <input
256
+ type="hidden"
257
+ name={name}
258
+ value={selectedItem || ""}
259
+ readOnly
260
+ disabled={disabled}
261
+ />
262
+
263
+ {/* Portal Dropdown - renders to document.body */}
264
+ <PortalDropdown
265
+ targetRef={buttonRef}
266
+ isVisible={showPopover && !disabled}
267
+ >
268
+ {dropdownContent}
269
+ </PortalDropdown>
270
+ </div>
240
271
  );
241
272
  });
242
273
 
@@ -5,7 +5,7 @@ export const primary = {
5
5
 
6
6
  export const popUp = {
7
7
  "pop-up-style":
8
- "overflow-y-auto px-2 border border-slate-200 rounded-lg scrollbar bg-white scrollbar h-auto dark:bg-black dark:text-white animate-fade-down animate-once animate-duration-200",
8
+ "w-full absolute overflow-y-auto border px-2 rounded-lg mt-[1px] scrollbar bg-white z-50 scrollbar h-auto dark:bg-black dark:text-white animate-fade-down animate-once animate-duration-200",
9
9
  };
10
10
 
11
11
  export const iconClass = {