@addev-be/ui 0.11.4 → 0.11.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@addev-be/ui",
3
- "version": "0.11.4",
3
+ "version": "0.11.6",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "watch": "tsc -b --watch",
@@ -3,10 +3,9 @@
3
3
 
4
4
  import * as styles from './styles';
5
5
 
6
- import { MouseEvent, useCallback, useMemo, useRef, useState } from 'react';
6
+ import { useCallback, useMemo, useRef, useState } from 'react';
7
7
 
8
8
  import { ChevronDownIcon } from '../../../Icons';
9
- import { DEFAULT_COLUMN_WIDTH } from './constants';
10
9
  import { DataGridFilterMenu } from './DataGridFilterMenu';
11
10
  import { DataGridHeaderCellProps } from './types';
12
11
  import { Dropdown } from '../../layout';
@@ -24,41 +23,14 @@ export const DataGridHeaderCell = <R,>({
24
23
  const contextValue = useDataGridContext(context);
25
24
  const {
26
25
  filters = {},
27
- setColumnWidth,
28
- saveSettings,
29
26
  headerColor,
27
+ resizingColumnKey,
28
+ startResizing,
30
29
  } = contextValue;
31
30
  const filterButtonRef = useRef<HTMLButtonElement | null>(null);
32
31
 
33
32
  /** RESIZING */
34
33
 
35
- const [isResizing, setIsResizing] = useState(false);
36
- const resizingOffset = useRef(0);
37
-
38
- const onResizeStart = useCallback(
39
- (e: MouseEvent) => {
40
- resizingOffset.current =
41
- e.screenX - (column.width || DEFAULT_COLUMN_WIDTH);
42
- setIsResizing(true);
43
- },
44
- [column.width]
45
- );
46
-
47
- const onResizeMove = useCallback(
48
- (e: MouseEvent) => {
49
- if (isResizing) {
50
- const newWidth = Math.max(86, e.screenX - resizingOffset.current);
51
- setColumnWidth(columnKey, newWidth);
52
- }
53
- },
54
- [columnKey, isResizing, setColumnWidth]
55
- );
56
-
57
- const onResizeEnd = useCallback(() => {
58
- setIsResizing(false);
59
- saveSettings();
60
- }, [saveSettings]);
61
-
62
34
  const [isFilterDropdownVisible, setIsFilterDropdownVisible] = useState(false);
63
35
  const filterDropdown = useMemo(() => {
64
36
  if (!isFilterDropdownVisible || !filterButtonRef.current || !columnKey) {
@@ -95,6 +67,7 @@ export const DataGridHeaderCell = <R,>({
95
67
  setIsFilterDropdownVisible(true);
96
68
  }, []);
97
69
 
70
+ const isResizing = resizingColumnKey === columnKey;
98
71
  const hasFilters = filters[columnKey]?.values.length > 0;
99
72
 
100
73
  return (
@@ -119,14 +92,8 @@ export const DataGridHeaderCell = <R,>({
119
92
  <styles.DataGridResizeGrip
120
93
  className={isResizing ? 'active' : ''}
121
94
  $headerColor={headerColor}
122
- onMouseDown={onResizeStart}
95
+ onMouseDown={(e) => startResizing(e, columnKey)}
123
96
  />
124
- {isResizing && (
125
- <styles.ResizeBackdrop
126
- onMouseMove={onResizeMove}
127
- onMouseUp={onResizeEnd}
128
- />
129
- )}
130
97
  </>
131
98
  )}
132
99
  </styles.DataGridHeaderCellContainer>
@@ -12,6 +12,7 @@ import {
12
12
  DataGridSort,
13
13
  } from '../types';
14
14
  import {
15
+ MouseEvent,
15
16
  createContext,
16
17
  useCallback,
17
18
  useEffect,
@@ -19,10 +20,10 @@ import {
19
20
  useRef,
20
21
  useState,
21
22
  } from 'react';
23
+ import { merge, pickBy } from 'lodash';
22
24
  import { useDataGridCopy, useSortedColumns } from '.';
23
25
 
24
26
  import { applyFilter } from '../helpers';
25
- import { merge } from 'lodash';
26
27
  import { useDataGridSettings } from './useDataGridSettings';
27
28
 
28
29
  export const useDataGrid = <R,>(
@@ -69,7 +70,13 @@ export const useDataGrid = <R,>(
69
70
 
70
71
  // Update columns when settings change
71
72
  useEffect(() => {
72
- setColumns((prev) => merge({}, prev, settings));
73
+ setColumns((prev) =>
74
+ merge(
75
+ {},
76
+ prev,
77
+ pickBy(settings, (_, key) => key in prev)
78
+ )
79
+ );
73
80
  }, [settings]);
74
81
 
75
82
  /** ROWS SELECTION **/
@@ -166,6 +173,36 @@ export const useDataGrid = <R,>(
166
173
  /** VIRTUAL SCROLLING */
167
174
  const scrollableRef = useRef<HTMLDivElement>(null);
168
175
 
176
+ /** RESIZING */
177
+ const [resizingColumnKey, setResizingColumnKey] = useState<string | null>(
178
+ null
179
+ );
180
+ const resizingOffset = useRef(0);
181
+
182
+ const startResizing = useCallback(
183
+ (e: MouseEvent, columnKey: string) => {
184
+ resizingOffset.current =
185
+ e.screenX - (columns[columnKey]?.width || DEFAULT_COLUMN_WIDTH);
186
+ setResizingColumnKey(columnKey);
187
+ },
188
+ [columns]
189
+ );
190
+
191
+ const moveResizing = useCallback(
192
+ (e: MouseEvent) => {
193
+ if (resizingColumnKey) {
194
+ const newWidth = Math.max(86, e.screenX - resizingOffset.current);
195
+ setColumnWidth(resizingColumnKey, newWidth);
196
+ }
197
+ },
198
+ [resizingColumnKey, setColumnWidth]
199
+ );
200
+
201
+ const endResizing = useCallback(() => {
202
+ setResizingColumnKey(null);
203
+ saveSettings();
204
+ }, [saveSettings]);
205
+
169
206
  /** FOOTERS */
170
207
  const [footers, setFooters] = useState<Record<string, string>>(
171
208
  props.initialFooters ?? {}
@@ -229,6 +266,10 @@ export const useDataGrid = <R,>(
229
266
  setFooters,
230
267
  footerFunctions,
231
268
  toggleSelection,
269
+ resizingColumnKey,
270
+ startResizing,
271
+ moveResizing,
272
+ endResizing,
232
273
  ...override,
233
274
  }),
234
275
  [
@@ -246,12 +287,15 @@ export const useDataGrid = <R,>(
246
287
  settings,
247
288
  setSettings,
248
289
  saveSettings,
249
- scrollableRef,
250
290
  rowKeyGetter,
251
291
  gridTemplateColumns,
252
292
  footers,
253
293
  footerFunctions,
254
294
  toggleSelection,
295
+ resizingColumnKey,
296
+ startResizing,
297
+ moveResizing,
298
+ endResizing,
255
299
  override,
256
300
  ]
257
301
  );
@@ -282,6 +326,10 @@ export const useDataGrid = <R,>(
282
326
  footers: {},
283
327
  setFooters: () => {},
284
328
  toggleSelection: () => {},
329
+ resizingColumnKey: null,
330
+ startResizing: () => {},
331
+ moveResizing: () => {},
332
+ endResizing: () => {},
285
333
  }),
286
334
  []
287
335
  );
@@ -47,6 +47,9 @@ export const DataGridInner = <R,>(
47
47
  refresh,
48
48
  setSelectedKeys,
49
49
  fixedColumnsCount,
50
+ resizingColumnKey,
51
+ moveResizing,
52
+ endResizing,
50
53
  } = contextProps;
51
54
 
52
55
  useImperativeHandle(
@@ -82,6 +85,12 @@ export const DataGridInner = <R,>(
82
85
  className={className}
83
86
  $fixedColumnWidths={fixedColumnWidths}
84
87
  >
88
+ {resizingColumnKey && (
89
+ <styles.ResizeBackdrop
90
+ onMouseMove={moveResizing}
91
+ onMouseUp={endResizing}
92
+ />
93
+ )}
85
94
  <DataGridHeader context={DataGridContext} />
86
95
  <VirtualScroller<R, { context: Context<DataGridContextProps<R>> }>
87
96
  integrated
@@ -1,4 +1,3 @@
1
- import styled, { css } from 'styled-components';
2
1
  import {
3
2
  DEFAULT_FOOTER_ROW_HEIGHT,
4
3
  DEFAULT_HEADER_ROW_HEIGHT,
@@ -6,6 +5,7 @@ import {
6
5
  SELECTION_CELL_WIDTH,
7
6
  TOOLBAR_HEIGHT,
8
7
  } from './constants';
8
+ import styled, { css } from 'styled-components';
9
9
 
10
10
  import { ThemeColor } from '../../../providers/ThemeProvider/types';
11
11
  import { VirtualScrollerFiller } from '../VirtualScroller/styles';
@@ -331,5 +331,6 @@ export const ResizeBackdrop = styled.div.attrs({
331
331
  bottom: 0;
332
332
  background-color: rgba(0, 0, 0, 0);
333
333
  cursor: col-resize;
334
+ z-index: 100;
334
335
  `;
335
336
  ResizeBackdrop.displayName = 'ResizeBackdrop';
@@ -130,6 +130,10 @@ export type DataGridContextProps<R> = DataGridProps<R> & {
130
130
  length: number;
131
131
  rowKeyGetter: (row: R) => string;
132
132
  gridTemplateColumns: string;
133
+ resizingColumnKey: string | null;
134
+ startResizing: (e: MouseEvent, columnKey: string) => void;
135
+ moveResizing: (e: MouseEvent) => void;
136
+ endResizing: () => void;
133
137
  toggleSelection: (key: string) => void;
134
138
  };
135
139
 
@@ -44,7 +44,7 @@ export type SqlRequestGridProps<R, P extends object = {}> = {
44
44
  orderBy?: OrderByDTO[];
45
45
  conditions?: ConditionDTO[];
46
46
  parser?: (row: SqlRequestRow<R>) => R;
47
- itemProps: P;
47
+ itemProps: P | ((item: R) => P);
48
48
  initialSorts?: Record<string, DataGridSort>;
49
49
  };
50
50
 
@@ -15,7 +15,7 @@ type VirtualScrollerProps<R, P extends object> = {
15
15
  gap?: string;
16
16
  itemsPerRow?: number;
17
17
  tolerance?: number;
18
- itemProps: P;
18
+ itemProps: P | ((item: R) => P);
19
19
  onRangeChanged?: (index: number, length: number) => void;
20
20
  integrated?: boolean;
21
21
  };
@@ -70,14 +70,18 @@ export const VirtualScroller = <R, P extends object>({
70
70
  $itemHeight={rowHeightInPx}
71
71
  $gap={gap}
72
72
  >
73
- {visibleItems.map((item, currentIndex) => (
74
- <ItemTemplate
75
- key={indexWithTolerance + currentIndex}
76
- item={item}
77
- index={currentIndex}
78
- {...itemProps}
79
- />
80
- ))}
73
+ {visibleItems.map((item, currentIndex) => {
74
+ const currentItemProps =
75
+ typeof itemProps === 'function' ? itemProps(item) : itemProps;
76
+ return (
77
+ <ItemTemplate
78
+ key={indexWithTolerance + currentIndex}
79
+ item={item}
80
+ index={currentIndex}
81
+ {...currentItemProps}
82
+ />
83
+ );
84
+ })}
81
85
  </styles.VirtualScrollerItemsContainer>
82
86
  </styles.VirtualScrollerFiller>
83
87
  </styles.VirtualScrollerContainer>
@@ -79,24 +79,27 @@ export const AuthenticationProvider: FC<AuthenticationProviderProps> = ({
79
79
  const sendCheckRecoveryKeyRequest = useCheckRecoveryKeyRequestHandler();
80
80
  const sendResetPasswordRequest = useResetPasswordRequestHandler();
81
81
 
82
- const authenticate = useCallback(() => {
83
- if (token && !user) {
84
- sendAuthenticateRequest({ token }).then(
85
- (response) => {
86
- if (response.status === 0 && response.user) {
87
- setUser(response.user);
88
- } else if (response.status > 0) {
82
+ const authenticate = useCallback(
83
+ (force = false) => {
84
+ if (token && (!user || force)) {
85
+ sendAuthenticateRequest({ token }).then(
86
+ (response) => {
87
+ if (response.status === 0 && response.user) {
88
+ setUser(response.user);
89
+ } else if (response.status > 0) {
90
+ setToken(undefined);
91
+ setUser(undefined);
92
+ }
93
+ },
94
+ () => {
89
95
  setToken(undefined);
90
96
  setUser(undefined);
91
97
  }
92
- },
93
- () => {
94
- setToken(undefined);
95
- setUser(undefined);
96
- }
97
- );
98
- }
99
- }, [sendAuthenticateRequest, token, user]);
98
+ );
99
+ }
100
+ },
101
+ [sendAuthenticateRequest, token, user]
102
+ );
100
103
 
101
104
  useEffect(() => {
102
105
  if (token) {
@@ -215,7 +218,7 @@ export const AuthenticationProvider: FC<AuthenticationProviderProps> = ({
215
218
  (newStatus) => {
216
219
  setWebSocketStatus((previousStatus) => {
217
220
  if (!previousStatus && newStatus) {
218
- authenticate();
221
+ authenticate(true);
219
222
  }
220
223
  return newStatus;
221
224
  });