qbs-react-grid 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.
@@ -1,5 +1,4 @@
1
1
  import React, { useCallback, useEffect, useId, useRef, useState } from 'react';
2
- import ReactDOM from 'react-dom';
3
2
 
4
3
  import { QbsColumnProps } from '../commontypes';
5
4
  import type { QbsTableLabels } from '../labels';
@@ -40,32 +39,7 @@ const ColumnToggle: React.FC<ColumnToggleProps> = ({
40
39
  const toggleId = useId();
41
40
  const [draggedItem, setDraggedItem] = useState<number | null>(null);
42
41
  const popupRef = useRef<HTMLDivElement | null>(null);
43
- const settingsBtnRef = useRef<HTMLButtonElement | null>(null);
44
42
  const [dragOverPosition, setDragOverPosition] = useState<number | null>();
45
- const [position, setPosition] = useState({ top: 0, left: 0 });
46
-
47
- const updatePopupPosition = useCallback(() => {
48
- if (!settingsBtnRef.current) return;
49
- const rect = settingsBtnRef.current.getBoundingClientRect();
50
- const viewportPadding = 8;
51
- const popupWidth = popupRef.current?.offsetWidth || 272;
52
- const popupHeight = popupRef.current?.offsetHeight || 320;
53
-
54
- let left = rtl ? rect.left : rect.right - popupWidth;
55
- if (left + popupWidth > window.innerWidth - viewportPadding) {
56
- left = Math.max(viewportPadding, window.innerWidth - popupWidth - viewportPadding);
57
- }
58
- if (left < viewportPadding) {
59
- left = viewportPadding;
60
- }
61
-
62
- let top = rect.bottom + 4;
63
- if (top + popupHeight > window.innerHeight - viewportPadding) {
64
- top = Math.max(viewportPadding, rect.top - popupHeight - 4);
65
- }
66
-
67
- setPosition({ top, left });
68
- }, [rtl]);
69
43
 
70
44
  useEffect(() => {
71
45
  const handleCloseOthers = (event: Event) => {
@@ -78,13 +52,6 @@ const ColumnToggle: React.FC<ColumnToggleProps> = ({
78
52
  return () => document.removeEventListener(COLUMN_TOGGLE_CLOSE_OTHERS, handleCloseOthers);
79
53
  }, [setIsOpen, toggleId]);
80
54
 
81
- useEffect(() => {
82
- if (!isOpen) return;
83
- updatePopupPosition();
84
- const frame = requestAnimationFrame(() => updatePopupPosition());
85
- return () => cancelAnimationFrame(frame);
86
- }, [isOpen, updatePopupPosition]);
87
-
88
55
  const handleToggle = useCallback(
89
56
  (columnName: string) => {
90
57
  onToggle(columnName);
@@ -122,10 +89,7 @@ const ColumnToggle: React.FC<ColumnToggleProps> = ({
122
89
  const handleClickOutside = useCallback(
123
90
  (event: MouseEvent) => {
124
91
  const target = event.target as Node;
125
- if (
126
- popupRef.current?.contains(target) ||
127
- settingsBtnRef.current?.contains(target)
128
- ) {
92
+ if (popupRef.current?.contains(target)) {
129
93
  return;
130
94
  }
131
95
  setIsOpen(false);
@@ -151,9 +115,9 @@ const ColumnToggle: React.FC<ColumnToggleProps> = ({
151
115
  checked={column.isVisible}
152
116
  onChange={() => handleToggle(column.title)}
153
117
  className="qbs-table-checkbox-input"
154
- id={column.title}
118
+ id={`${toggleId}-${column.title}`}
155
119
  />
156
- <label htmlFor={column.title}>
120
+ <label htmlFor={`${toggleId}-${column.title}`}>
157
121
  <svg
158
122
  width="8"
159
123
  height="6"
@@ -188,9 +152,9 @@ const ColumnToggle: React.FC<ColumnToggleProps> = ({
188
152
  checked={column.isVisible}
189
153
  onChange={() => handleToggle(column.title)}
190
154
  className="qbs-table-checkbox-input"
191
- id={column.title}
155
+ id={`${toggleId}-${column.title}`}
192
156
  />
193
- <label htmlFor={column.title}>
157
+ <label htmlFor={`${toggleId}-${column.title}`}>
194
158
  <svg
195
159
  width="8"
196
160
  height="6"
@@ -235,85 +199,10 @@ const ColumnToggle: React.FC<ColumnToggleProps> = ({
235
199
  handleColumnToggle?.(columns);
236
200
  };
237
201
 
238
- const portalTarget = document.getElementById('portal-root') ?? document.body;
239
-
240
- const popupContent = (
241
- <div
242
- className={`qbs-table-column-popup${rtl ? ' qbs-table-column-popup--rtl' : ''}`}
243
- style={{
244
- position: 'fixed',
245
- top: position.top,
246
- left: position.left,
247
- maxHeight: tableHeight - 40,
248
- zIndex: 10060,
249
- }}
250
- ref={popupRef}
251
- dir={rtl ? 'rtl' : 'ltr'}
252
- >
253
- <div className="qbs-table-popup-container">
254
- <div className="qbs-table-popup-item">
255
- <div className="qbs-table-popup-label">{labels.fixedColumns}</div>
256
- <div className="qbs-table-columns-container">
257
- <div className="qbs-table-column">
258
- {columns.map((column, index) =>
259
- column.fixed ? renderFixedColumn(column, index) : null,
260
- )}
261
- </div>
262
- </div>
263
- </div>
264
- <div className="qbs-table-divider" />
265
- <div className="qbs-table-popup-item">
266
- <div className="qbs-table-popup-label">{labels.visibleColumns}</div>
267
- <div className="qbs-table-columns-container">
268
- <div className="qbs-table-column">
269
- {columns.map((column, index) =>
270
- column.isVisible && !column.fixed ? renderColumn(column, index) : null,
271
- )}
272
- </div>
273
- </div>
274
- </div>
275
- {handleAvailableColumns() && (
276
- <>
277
- <div className="qbs-table-divider" />
278
- <div className="qbs-table-popup-item">
279
- <div className="qbs-table-popup-label">{labels.availableColumns}</div>
280
- <div className="qbs-table-columns-container">
281
- <div className="qbs-table-column">
282
- {columns.map((column, index) =>
283
- !column.isVisible && !column.fixed ? renderFixedColumn(column, index) : null,
284
- )}
285
- </div>
286
- </div>
287
- </div>
288
- </>
289
- )}
290
- </div>
291
- {handleResetColumns && (
292
- <>
293
- <div className="qbs-table-divider" />
294
- <div className="qbs-table-popup-footer">
295
- <button
296
- type="button"
297
- className="qbs-table-reset-link"
298
- onClick={() => handleResetColumns?.()}
299
- >
300
- {labels.resetToDefault}
301
- </button>
302
- <button type="button" className="qbs-table-reset-link" onClick={() => handleColToggle()}>
303
- {labels.save}
304
- </button>
305
- </div>
306
- </>
307
- )}
308
- </div>
309
- );
310
-
311
202
  return (
312
203
  <div className="qbs-table-settings-wrapper">
313
204
  <button
314
205
  type="button"
315
- className="qbs-table-settings-btn"
316
- ref={settingsBtnRef}
317
206
  onClick={event => {
318
207
  event.stopPropagation();
319
208
  if (isOpen) {
@@ -321,13 +210,75 @@ const ColumnToggle: React.FC<ColumnToggleProps> = ({
321
210
  return;
322
211
  }
323
212
  closeOtherColumnToggles(toggleId);
324
- updatePopupPosition();
325
213
  setIsOpen(true);
326
214
  }}
327
215
  >
328
216
  <SettingsIcon />
329
217
  </button>
330
- {isOpen && portalTarget && ReactDOM.createPortal(popupContent, portalTarget)}
218
+ {isOpen && (
219
+ <div
220
+ className={`qbs-table-column-popup${rtl ? ' qbs-table-column-popup--rtl' : ''}`}
221
+ style={{ maxHeight: tableHeight - 40 }}
222
+ ref={popupRef}
223
+ dir={rtl ? 'rtl' : 'ltr'}
224
+ >
225
+ <div className="qbs-table-popup-container">
226
+ <div className="qbs-table-popup-item">
227
+ <div className="qbs-table-popup-label">{labels.fixedColumns}</div>
228
+ <div className="qbs-table-columns-container">
229
+ <div className="qbs-table-column">
230
+ {columns.map((column, index) =>
231
+ column.fixed ? renderFixedColumn(column, index) : null,
232
+ )}
233
+ </div>
234
+ </div>
235
+ </div>
236
+ <div className="qbs-table-divider" />
237
+ <div className="qbs-table-popup-item">
238
+ <div className="qbs-table-popup-label">{labels.visibleColumns}</div>
239
+ <div className="qbs-table-columns-container">
240
+ <div className="qbs-table-column">
241
+ {columns.map((column, index) =>
242
+ column.isVisible && !column.fixed ? renderColumn(column, index) : null,
243
+ )}
244
+ </div>
245
+ </div>
246
+ </div>
247
+ {handleAvailableColumns() && (
248
+ <>
249
+ <div className="qbs-table-divider" />
250
+ <div className="qbs-table-popup-item">
251
+ <div className="qbs-table-popup-label">{labels.availableColumns}</div>
252
+ <div className="qbs-table-columns-container">
253
+ <div className="qbs-table-column">
254
+ {columns.map((column, index) =>
255
+ !column.isVisible && !column.fixed ? renderFixedColumn(column, index) : null,
256
+ )}
257
+ </div>
258
+ </div>
259
+ </div>
260
+ </>
261
+ )}
262
+ </div>
263
+ {handleResetColumns && (
264
+ <>
265
+ <div className="qbs-table-divider" />
266
+ <div className="qbs-table-popup-footer">
267
+ <button
268
+ type="button"
269
+ className="qbs-table-reset-link"
270
+ onClick={() => handleResetColumns?.()}
271
+ >
272
+ {labels.resetToDefault}
273
+ </button>
274
+ <button type="button" className="qbs-table-reset-link" onClick={() => handleColToggle()}>
275
+ {labels.save}
276
+ </button>
277
+ </div>
278
+ </>
279
+ )}
280
+ </div>
281
+ )}
331
282
  </div>
332
283
  );
333
284
  };
@@ -29,7 +29,7 @@ const TooltipComponent: React.FC<any> = ({ title, children, tableBodyRef }) => {
29
29
  >
30
30
  {children}
31
31
  </span>
32
- <span ref={dropRef} className={'tooltiptext'}>
32
+ <span ref={dropRef} className="tooltiptext" dir="auto">
33
33
  {title}
34
34
  </span>
35
35
  </div>
@@ -62,7 +62,15 @@ const VerticalMenuDropdown: React.FC<VerticalMenuDropdownProps> = ({
62
62
  const spaceBelow = window.innerHeight - rect.bottom;
63
63
  const openBelow = spaceBelow >= menuHeight + menuGap;
64
64
 
65
- let left = rect.left;
65
+ const isRtl =
66
+ (document.documentElement.getAttribute('dir') ||
67
+ document.body.getAttribute('dir') ||
68
+ getComputedStyle(document.documentElement).direction) === 'rtl';
69
+
70
+ let left = isRtl ? rect.left : rect.left - menuWidth;
71
+ if (!isRtl && left < viewportPadding) {
72
+ left = rect.left;
73
+ }
66
74
  if (left + menuWidth > window.innerWidth - viewportPadding) {
67
75
  left = Math.max(viewportPadding, rect.right - menuWidth);
68
76
  }
@@ -191,7 +199,7 @@ const VerticalMenuDropdown: React.FC<VerticalMenuDropdownProps> = ({
191
199
  {visibleCount > 0 && (
192
200
  <button
193
201
  type="button"
194
- className="vertical-menu-trigger-button p-2 rounded text-base-gray hover:bg-gray-light-1 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
202
+ className="vertical-menu-trigger-button"
195
203
  onClick={event => {
196
204
  event.stopPropagation();
197
205
  if (openMenu) {