@azrico/reactgrid 1.3.49 → 1.3.52

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.
@@ -0,0 +1,122 @@
1
+ import { ModifyFields } from '../func/func_grid';
2
+ import { ConvertableToMenuItem } from '@azrico/controls';
3
+ import React from 'react';
4
+ import {
5
+ TypeCellSelection,
6
+ TypeColumn,
7
+ TypeDataGridProps,
8
+ TypeDataSource,
9
+ TypeEditInfo,
10
+ TypeFilterTypes,
11
+ TypeFilterValue,
12
+ TypeRowDetailsInfo,
13
+ TypeRowProps,
14
+ TypeRowSelection,
15
+ TypeComputedProps,
16
+ } from '@inovua/reactdatagrid-community/types';
17
+
18
+ import { TypeOnSelectionChangeArg } from '@inovua/reactdatagrid-community/types/TypeDataGridProps';
19
+
20
+ /* -------------------------------------------------------------------------- */
21
+ export type ColumnDefinition = TypeColumn;
22
+ export type CellDefinition = any;
23
+ export type RowDefinition = any;
24
+ export type RowProps = TypeRowProps;
25
+ export type RowSelectionValue = TypeRowSelection;
26
+ export type CellSelectionValue = TypeCellSelection;
27
+ export type DataRowDefinition = any;
28
+ export type FilterTypes = TypeFilterTypes;
29
+ export type FilterValues = TypeFilterValue;
30
+ export type DataSourceDefinition = TypeDataSource;
31
+ export type OnSelectionChangeFunc = (config: TypeOnSelectionChangeArg) => void;
32
+ export type OnCellSelectionChangeFunc = (s: { [key: string]: boolean }) => void;
33
+ export type RowDetailsFunc = (rowDetailsInfo: TypeRowDetailsInfo) => React.ReactNode;
34
+
35
+ export type loose_column_names = {
36
+ key: string;
37
+ field: string;
38
+ columnName: string;
39
+ name: string;
40
+ };
41
+ export type loose_column_fields = loose_column_names & {
42
+ title: string;
43
+ type: string;
44
+ items: any[];
45
+ };
46
+ export type LooseColumnDefinition = Partial<loose_column_fields & ColumnDefinition>;
47
+ //
48
+
49
+ export type CustomColumnDefinition = {
50
+ name: string;
51
+ render: (cell: any, formatterParams, onRendered) => React.ReactNode | undefined | null;
52
+ };
53
+ export type AzGridOptions = Partial<TypeDataGridProps>;
54
+ /* -------------------------------------------------------------------------- */
55
+ export type AzGridProps = {
56
+ dataSource?: any[] | ((args: any) => any[] | Promise<any[] | any>);
57
+ details_dataSource?: any[] | ((args: any) => any[] | Promise<any[] | any>); //details is rendered under each row
58
+ details_columns?: LooseColumnDefinition[];
59
+ details_filter?: FilterValues;
60
+
61
+ licenseKey?: string;
62
+
63
+ gridRef?: React.MutableRefObject<TypeComputedProps>;
64
+ gridOptions?: AzGridOptions;
65
+
66
+ columns?: LooseColumnDefinition[];
67
+ columnExtensions?: Partial<LooseColumnDefinition>;
68
+
69
+ editableColumns?: string[];
70
+ leftColumns?: string[];
71
+ rightColumns?: string[];
72
+ customColumns?: CustomColumnDefinition[];
73
+
74
+ contextMenuItems?: ConvertableToMenuItem;
75
+
76
+ highlightedRow?: any;
77
+ RowDetail?: RowDetailsFunc;
78
+
79
+ selected?: RowSelectionValue;
80
+ cellSelection?: CellSelectionValue;
81
+ /* -------------------------------------------------------------------------- */
82
+ onEditComplete?: (editInfo: TypeEditInfo) => void;
83
+ onSelectionChange?: OnSelectionChangeFunc;
84
+ onCellSelectionChange?: OnCellSelectionChangeFunc;
85
+
86
+ onRowClick?: (rowIndex: number, row: any) => void;
87
+ onRowDoubleClick?: (rowIndex: number, row: any) => void;
88
+ onLimitChange?: (v: number) => void;
89
+ onSkipChange?: (v: number) => void;
90
+ /* -------------------------------------------------------------------------- */
91
+ skip?: number;
92
+ limit?: number;
93
+ //
94
+ editable?: boolean | ((editValue: any, cellProps: any) => boolean);
95
+ advancedFilterFields?: string[];
96
+ //
97
+
98
+ loading?: boolean;
99
+ dark?: boolean;
100
+ delayedSize?: boolean;
101
+ allowChildRows?: boolean;
102
+ looseCacheCheck?: boolean;
103
+ className?: string;
104
+ };
105
+
106
+ export type DataGridProps = ModifyFields<
107
+ AzGridProps,
108
+ {
109
+ columns: ColumnDefinition[];
110
+ dataSource: any;
111
+ }
112
+ >;
113
+ export type GridType = TypeComputedProps;
114
+ export type DataGridWrapperProps = ModifyFields<
115
+ DataGridProps,
116
+ {
117
+ gridRef: React.MutableRefObject<TypeComputedProps>;
118
+ static_gridOptions: AzGridOptions;
119
+ dynamic_gridOptions: AzGridOptions;
120
+ children?: React.ReactNode;
121
+ }
122
+ >;
@@ -3,144 +3,24 @@ import '@inovua/reactdatagrid-enterprise/theme/default-dark.css';
3
3
  import '@inovua/reactdatagrid-enterprise/theme/amber-dark.css';
4
4
  import '../themes/base_styles.css';
5
5
  import '../themes/grid.css';
6
+ import { applyColumnData, ApplyDataSource, get_default_key } from '../func/func_grid';
7
+ import { ContextMenu } from '@azrico/controls';
8
+ import React from 'react';
6
9
 
7
- import {
8
- ApplyColumnData,
9
- ApplyDataSource,
10
- ModifyFields,
11
- find_realData,
12
- get_default_key,
13
- get_row_id,
14
- validateCache,
15
- } from '../func/func_grid';
16
- import { ContextMenu, ConvertableToMenuItem } from '@azrico/controls';
17
- import React, { useCallback, useState } from 'react';
18
- import {
19
- TypeCellSelection,
20
- TypeColumn,
21
- TypeDataGridProps,
22
- TypeDataSource,
23
- TypeEditInfo,
24
- TypeFilterTypes,
25
- TypeFilterValue,
26
- TypeRowDetailsInfo,
27
- TypeRowProps,
28
- TypeRowSelection,
29
- TypeComputedProps,
30
- } from '@inovua/reactdatagrid-community/types';
31
- import { fix_parent_child_relations, func_selection } from '../func/func_child';
32
10
  import { array_intersection, fn_eval } from '@azrico/object';
33
11
 
34
12
  import ReactDataGrid from '@inovua/reactdatagrid-enterprise';
35
- import { TypeOnSelectionChangeArg } from '@inovua/reactdatagrid-community/types/TypeDataGridProps';
36
13
  import clsx from 'clsx';
37
14
  import { useComponentSize } from 'react-use-size';
38
15
 
39
16
  import debounce from 'lodash.debounce';
17
+ import { AzGridOptions, AzGridProps, DataGridWrapperProps } from '../types/types';
18
+ import { useGridEvents } from '../hooks/useGridEvents';
19
+ import { useColumnData } from '../hooks/useColumnData';
20
+ import { useDataSource } from '../hooks/useDatasource';
21
+ import { useGridSearch } from '../hooks/useGridSearch';
40
22
  /* -------------------------------------------------------------------------- */
41
23
 
42
- /* -------------------------------------------------------------------------- */
43
- export type ColumnDefinition = TypeColumn;
44
- export type CellDefinition = any;
45
- export type RowDefinition = any;
46
- export type RowProps = TypeRowProps;
47
- export type RowSelectionValue = TypeRowSelection;
48
- export type CellSelectionValue = TypeCellSelection;
49
- export type DataRowDefinition = any;
50
- export type FilterTypes = TypeFilterTypes;
51
- export type FilterValues = TypeFilterValue;
52
- export type DataSourceDefinition = TypeDataSource;
53
- export type OnSelectionChangeFunc = (config: TypeOnSelectionChangeArg) => void;
54
- export type OnCellSelectionChangeFunc = (s: { [key: string]: boolean }) => void;
55
- export type RowDetailsFunc = (rowDetailsInfo: TypeRowDetailsInfo) => React.ReactNode;
56
- /* -------------------------------------------------------------------------- */
57
- type loose_column_names = {
58
- key: string;
59
- field: string;
60
- columnName: string;
61
- name: string;
62
- };
63
- type loose_column_fields = loose_column_names & {
64
- title: string;
65
- type: string;
66
- items: any[];
67
- };
68
- export type LooseColumnDefinition = Partial<loose_column_fields & ColumnDefinition>;
69
- //
70
-
71
- export type CustomColumnDefinition = {
72
- name: string;
73
- render: (cell: any, formatterParams, onRendered) => React.ReactNode | undefined | null;
74
- };
75
- export type AzGridOptions = Partial<TypeDataGridProps>;
76
- /* -------------------------------------------------------------------------- */
77
- export type AzGridProps = {
78
- dataSource?: any[] | ((args: any) => any[] | Promise<any[] | any>);
79
- details_dataSource?: any[] | ((args: any) => any[] | Promise<any[] | any>); //details is rendered under each row
80
- details_columns?: LooseColumnDefinition[];
81
- details_filter?: FilterValues;
82
-
83
- licenseKey?: string;
84
-
85
- gridRef?: React.MutableRefObject<TypeComputedProps>;
86
- gridOptions?: AzGridOptions;
87
-
88
- columns?: LooseColumnDefinition[];
89
- columnExtensions?: Partial<LooseColumnDefinition>;
90
-
91
- editableColumns?: string[];
92
- leftColumns?: string[];
93
- rightColumns?: string[];
94
- customColumns?: CustomColumnDefinition[];
95
-
96
- contextMenuItems?: ConvertableToMenuItem;
97
-
98
- highlightedRow?: any;
99
- RowDetail?: RowDetailsFunc;
100
-
101
- selected?: RowSelectionValue;
102
- cellSelection?: CellSelectionValue;
103
- /* -------------------------------------------------------------------------- */
104
- onEditComplete?: (editInfo: TypeEditInfo) => void;
105
- onSelectionChange?: OnSelectionChangeFunc;
106
- onCellSelectionChange?: OnCellSelectionChangeFunc;
107
-
108
- onRowClick?: (rowIndex: number, row: any) => void;
109
- onRowDoubleClick?: (rowIndex: number, row: any) => void;
110
- onLimitChange?: (v: number) => void;
111
- onSkipChange?: (v: number) => void;
112
- /* -------------------------------------------------------------------------- */
113
- skip?: number;
114
- limit?: number;
115
- //
116
- editable?: boolean | ((editValue: any, cellProps: any) => boolean);
117
- advancedFilterFields?: string[];
118
- //
119
-
120
- loading?: boolean;
121
- dark?: boolean;
122
- delayedSize?: boolean;
123
- allowChildRows?: boolean;
124
- looseCacheCheck?: boolean;
125
- className?: string;
126
- };
127
-
128
- type DataGridProps = ModifyFields<
129
- AzGridProps,
130
- {
131
- columns: ColumnDefinition[];
132
- dataSource: any;
133
- }
134
- >;
135
- type DataGridWrapperProps = ModifyFields<
136
- DataGridProps,
137
- {
138
- gridRef: React.MutableRefObject<TypeComputedProps>;
139
- static_gridOptions: AzGridOptions;
140
- dynamic_gridOptions: AzGridOptions;
141
- children?: React.ReactNode;
142
- }
143
- >;
144
24
  /* -------------------------------------------------------------------------- */
145
25
 
146
26
  const defaultOptions: AzGridOptions = {
@@ -168,35 +48,12 @@ export function AzGrid(props: AzGridProps) {
168
48
  /* -------------------------------------------------------------------------- */
169
49
  /* Columns */
170
50
  /* -------------------------------------------------------------------------- */
171
- const cached_columns = React.useMemo(() => {
172
- return ApplyColumnData(props);
173
- }, [
174
- props.columns,
175
- props.leftColumns,
176
- props.rightColumns,
177
- props.editableColumns,
178
- props.columnExtensions,
179
- props.customColumns,
180
- ]);
51
+ const cached_columns = useColumnData(props);
52
+ const dataSource = useDataSource(props.dataSource, props);
181
53
  /* -------------------------------------------------------------------------- */
182
54
  /* Row changes */
183
55
  /* -------------------------------------------------------------------------- */
184
56
 
185
- const cached_data = React.useRef<any>();
186
- const last_cache_info = React.useRef<any>();
187
-
188
- const dataSource = React.useCallback(
189
- async (dt) => {
190
- return await ApplyDataSource(props.dataSource, {
191
- skip: dt?.skip,
192
- limit: dt?.limit,
193
- cached_data: cached_data,
194
- last_cache_info: last_cache_info,
195
- });
196
- },
197
- [props.dataSource]
198
- );
199
-
200
57
  const base_gridOptions = React.useMemo<AzGridOptions>(() => {
201
58
  const firstcolumn = cached_columns[0];
202
59
  const licenseKey = props.licenseKey || get_default_key();
@@ -270,87 +127,14 @@ export function AzGrid(props: AzGridProps) {
270
127
  */
271
128
  function DataGridEventsWrapper(props: DataGridWrapperProps) {
272
129
  /* -------------------------------------------------------------------------- */
273
-
274
- const click_data = React.useRef<any>(null);
275
-
276
- const [menuAnchorEl, set_menuAnchorEl] = React.useState<any>(null);
277
- const [menuRow, set_menuRow] = React.useState<any>(null);
278
-
279
- /* -------------------------------------------------------------------------- */
280
- /* refresh functions */
281
- /* -------------------------------------------------------------------------- */
282
- const refreshColumn = React.useCallback(
283
- (col: string) => {
284
- const dt = props.gridRef.current.ungroupedData;
285
- for (let index = 0; index < dt.length; index++) {
286
- (props.gridRef.current as any).setItemPropertyAt(index, col, dt[index][col]);
287
- }
288
- },
289
- [props.gridRef.current]
290
- );
291
- const refresh = React.useCallback(() => {
292
- const dt = props.gridRef.current.ungroupedData;
293
- for (let index = 0; index < dt.length; index++) {
294
- (props.gridRef.current as any).setItemAt(index, {}, { replace: false });
295
- }
296
- }, [props.gridRef.current]);
297
- React.useEffect(() => {
298
- if (!props.gridRef.current) return;
299
- props.gridRef.current['refresh'] = refresh;
300
- props.gridRef.current['refreshColumn'] = refreshColumn;
301
- }, [props.gridRef.current, props.dataSource, refresh, refreshColumn]);
302
- /* -------------------------------------------------------------------------- */
303
- /* events */
304
- /* -------------------------------------------------------------------------- */
305
- const onRowClick = React.useCallback(
306
- (rowProps, event) => {
307
- const nowDate = Date.now();
308
- const lastclick: number = click_data.current[get_row_id(rowProps)];
309
- if (lastclick) {
310
- const diffTime = Math.abs(nowDate - lastclick);
311
- if (diffTime < 400) {
312
- click_data.current[get_row_id(rowProps)] = null;
313
- return (
314
- props.onRowDoubleClick &&
315
- props.onRowDoubleClick(rowProps.rowIndex, rowProps.data)
316
- );
317
- }
318
- }
319
-
320
- click_data.current[get_row_id(rowProps)] = nowDate;
321
- return props.onRowClick && props.onRowClick(rowProps.rowIndex, rowProps.data);
322
- },
323
- [props.onRowClick, props.onRowDoubleClick]
324
- );
325
-
326
- React.useEffect(() => {
327
- click_data.current = {};
328
- }, [props.dataSource]);
329
-
330
- /* ------------------------------- ContextMenu ------------------------------ */
331
- const onRowContextMenu = React.useCallback((rowProps, event) => {
332
- if (!rowProps || !rowProps.data || func_selection.has_selection()) {
333
- update_menuRow(null, null);
334
- return true;
335
- }
336
- event.preventDefault();
337
-
338
- const realRow = find_realData(rowProps.dataSourceArray, event.target, rowProps.data);
339
- const anEl = func_selection.getVirtualElement(event.clientX, event.clientY);
340
- update_menuRow(realRow, anEl);
341
- return false;
342
- }, []);
343
-
344
- const update_menuRow = React.useCallback((r: any = null, el: any = null) => {
345
- set_menuRow(r || null);
346
- set_menuAnchorEl(el || null);
347
- }, []);
348
-
349
- /* -------------------------------------------------------------------------- */
350
- const onRenderRow = useCallback((rowProps) => {
351
- // save the original handlers to be called later
352
- rowProps['data-row-id'] = get_row_id(rowProps.data);
353
- }, []);
130
+ const {
131
+ onRowClick,
132
+ onRowContextMenu,
133
+ onRenderRow,
134
+ update_menuRow,
135
+ menuAnchorEl,
136
+ menuRow,
137
+ } = useGridEvents(props.gridRef.current, props);
354
138
  /* -------------------------------------------------------------------------- */
355
139
  /**
356
140
  * Merge click events into grid options
@@ -392,25 +176,8 @@ function DataGridEventsWrapper(props: DataGridWrapperProps) {
392
176
  }
393
177
 
394
178
  function DataGridDetailsWrapper(props: DataGridWrapperProps) {
395
- const cached_details_columns = React.useMemo(() => {
396
- return ApplyColumnData(props.details_columns);
397
- }, [props.details_columns]);
398
-
399
- const cached_data = React.useRef<any>();
400
- const last_cache_info = React.useRef<any>();
401
-
402
- const details_dataSource = React.useCallback(
403
- async (dt) => {
404
- const res = await ApplyDataSource(props.details_dataSource, {
405
- skip: dt.skip,
406
- limit: dt.limit,
407
- cached_data: cached_data,
408
- last_cache_info: last_cache_info,
409
- });
410
- return res;
411
- },
412
- [props.details_dataSource]
413
- );
179
+ const cached_details_columns = useColumnData(props.details_columns);
180
+ const details_dataSource = useDataSource(props.details_dataSource, props);
414
181
  const renderDetailsGrid = ({ data }) => {
415
182
  return (
416
183
  <ReactDataGrid
@@ -467,75 +234,11 @@ function DataGridDelayedSizeWrapper(props: DataGridWrapperProps) {
467
234
  );
468
235
  }
469
236
  function DataGridSearchWrapper(props: DataGridWrapperProps) {
470
- const [search, set_search] = React.useState('');
471
- const [filteredData, set_filteredData] = React.useState<any>([]);
472
- const currentSearch = React.useRef('');
473
- const currentDS = React.useRef<any[]>([]);
474
-
475
- const try_search = React.useCallback(
476
- debounce(() => {
477
- if (!Array.isArray(currentDS.current)) {
478
- return;
479
- }
480
- let newData: any[] = [];
481
- if (currentSearch.current) {
482
- const visibleColumns = props.gridRef.current.visibleColumns;
483
- const columns_to_search: string[] = array_intersection(
484
- props.advancedFilterFields || [],
485
- visibleColumns.map((r) => r.id)
486
- );
487
- const lowerSearchText = currentSearch.current.toLowerCase().trim();
488
- if (!lowerSearchText || columns_to_search.length === 0)
489
- newData = currentDS.current;
490
- else {
491
- newData = currentDS.current.filter((p) => {
492
- for (let index = 0; index < columns_to_search.length; index++) {
493
- const col = columns_to_search[index];
494
- const v = (p[col] + '').toLowerCase(); //value of column
495
- if (v && v.indexOf(lowerSearchText) != -1) {
496
- //if one column is matching then the row is a match
497
- return true;
498
- }
499
- }
500
- return false;
501
- });
502
- }
503
- } else newData = currentDS.current;
504
- set_filteredData(newData);
505
- }, 1000),
506
- []
507
- );
508
- React.useEffect(() => {
509
- fn_eval(props.dataSource).then((r) => {
510
- currentDS.current = typeof r === 'object' ? r.data || r : r;
511
- searchIfNeeded();
512
- });
513
- }, [props.dataSource]);
514
-
515
- React.useEffect(() => {
516
- currentSearch.current = search;
517
- searchIfNeeded();
518
- }, [search]);
519
-
520
- function searchIfNeeded() {
521
- if (!search) {
522
- set_filteredData(props.dataSource);
523
- } else try_search();
524
- }
237
+ const { element, filteredData } = useGridSearch(props.gridRef.current, props);
525
238
 
526
239
  return (
527
240
  <div className={'azgrid-flexed azgrid-flexlayout azgrid-nooverflow'}>
528
- <form className={'azgrid-searcharea'}>
529
- <label>
530
- Search
531
- <input
532
- type="text"
533
- name="name"
534
- value={search}
535
- onChange={(e) => set_search(e.target.value)}
536
- />
537
- </label>
538
- </form>
241
+ {element}
539
242
  <DataGridCore {...props} dataSource={filteredData} />
540
243
  </div>
541
244
  );