@azrico/reactgrid 1.2.4 → 1.2.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.
@@ -5,40 +5,20 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.AzGrid = AzGrid;
7
7
  exports.default = void 0;
8
- exports.get_col_header = get_col_header;
9
- exports.get_col_name = get_col_name;
10
8
  require("@inovua/reactdatagrid-enterprise/index.css");
11
9
  require("@inovua/reactdatagrid-enterprise/theme/default-dark.css");
12
10
  require("@inovua/reactdatagrid-enterprise/theme/amber-dark.css");
13
11
  require("../themes/base_styles.css");
14
12
  require("../themes/grid.css");
13
+ var _func_grid = require("../func/func_grid");
15
14
  var _controls = require("@azrico/controls");
16
15
  var _react = _interopRequireDefault(require("react"));
17
- var _helpers = require("../func/helpers");
18
- var _BoolEditor = _interopRequireDefault(require("@inovua/reactdatagrid-community/BoolEditor"));
19
- var _NumericEditor = _interopRequireDefault(require("@inovua/reactdatagrid-community/NumericEditor"));
16
+ var _func_child = require("../func/func_child");
20
17
  var _reactdatagridEnterprise = _interopRequireDefault(require("@inovua/reactdatagrid-enterprise"));
21
- var _SelectEditor = _interopRequireDefault(require("@inovua/reactdatagrid-community/SelectEditor"));
22
18
  var _clsx = _interopRequireDefault(require("clsx"));
23
- var _object = require("@azrico/object");
24
19
  var _reactUseSize = require("react-use-size");
25
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
26
21
  /* -------------------------------------------------------------------------- */
27
- // const defaultfilterTypes: FilterTypes = {
28
- // string: {
29
- // type: 'string',
30
- // emptyValue: '',
31
- // operators: [
32
- // {
33
- // name: 'contains',
34
- // fn: ({ value, filterValue, data }) => {
35
- // console.log('fn');
36
- // return !filterValue ? true : value.indexOf(filterValue) != -1;
37
- // },
38
- // },
39
- // ],
40
- // },
41
- // };
42
22
  const defaultOptions = {
43
23
  //filterTypes: defaultfilterTypes,
44
24
  remoteFilter: false,
@@ -56,19 +36,16 @@ const forcedOptions = {
56
36
  idProperty: '__table_id',
57
37
  nodesProperty: '__children'
58
38
  };
59
- const defaultColumnOptions = {
60
- draggable: false,
61
- lockable: false,
62
- editable: false
63
- };
64
39
  const dynamic_option_names = ['selected', 'loading', 'limit', 'skip'];
65
40
  /* -------------------------------------------------------------------------- */
66
41
  function AzGrid(props) {
42
+ const gridRefBackup = _react.default.useRef(null);
43
+ const gridRef = props.gridRef || gridRefBackup;
67
44
  /* -------------------------------------------------------------------------- */
68
45
  /* Columns */
69
46
  /* -------------------------------------------------------------------------- */
70
47
  const cached_columns = _react.default.useMemo(() => {
71
- return ApplyColumnData(props);
48
+ return (0, _func_grid.ApplyColumnData)(props);
72
49
  }, [props.columns, props.leftColumns, props.rightColumns, props.editableColumns, props.columnExtensions, props.customColumns]);
73
50
  /* -------------------------------------------------------------------------- */
74
51
  /* Row changes */
@@ -76,46 +53,16 @@ function AzGrid(props) {
76
53
  const cached_data = _react.default.useRef();
77
54
  const last_cache_info = _react.default.useRef();
78
55
  const dataSource = _react.default.useCallback(async dt => {
79
- let result_data = undefined;
80
- let isUsingCache = false;
81
- const cacheInfo = {
82
- ds: props.dataSource,
56
+ return await (0, _func_grid.ApplyDataSource)(props.dataSource, {
83
57
  skip: dt.skip,
84
- limit: dt.limit
85
- };
86
- //check if we can used cached data
87
- //if the datasource is changed since last render, we should invalidate cache
88
- if (!validateCache(last_cache_info.current, cacheInfo, props.looseCacheCheck)) {
89
- cached_data.current = undefined;
90
- last_cache_info.current = cacheInfo;
91
- }
92
- if (cached_data.current) {
93
- //cache is valid, use the cache
94
- isUsingCache = true;
95
- result_data = cached_data.current;
96
- } else {
97
- //cache is invalid, use the datasource again
98
- isUsingCache = false;
99
- if (typeof props.dataSource === 'function') {
100
- result_data = await props.dataSource(dt);
101
- } else result_data = props.dataSource;
102
- }
103
- //making sure the datasource is a valid object :
104
- if (!result_data) result_data = [];
105
- if (Array.isArray(result_data) || typeof result_data !== 'object') result_data = {
106
- data: result_data
107
- };
108
- if (!Array.isArray(result_data.data)) result_data.data = [result_data.data];
109
- //no need to fix parent/child when using cache (it should be already fixed)
110
- if (!isUsingCache && props.allowChildRows) result_data.data = (0, _helpers.fix_parent_child_relations)(result_data.data);
111
- if (!result_data.count) result_data.count = result_data.data.length;
112
- //update cache
113
- cached_data.current = result_data;
114
- return result_data;
58
+ limit: dt.limit,
59
+ cached_data: cached_data,
60
+ last_cache_info: last_cache_info
61
+ });
115
62
  }, [props.dataSource]);
116
63
  const base_gridOptions = _react.default.useMemo(() => {
117
64
  const firstcolumn = cached_columns[0];
118
- const licenseKey = props.licenseKey || get_default_key();
65
+ const licenseKey = props.licenseKey || (0, _func_grid.get_default_key)();
119
66
  const events = {
120
67
  onSkipChange: props.onSkipChange,
121
68
  onLimitChange: props.onLimitChange,
@@ -151,6 +98,7 @@ function AzGrid(props) {
151
98
  }, dynamic_option_names.map(r => props[r]));
152
99
  return _react.default.createElement(DataGridEventsWrapper, {
153
100
  ...props,
101
+ gridRef: gridRef,
154
102
  static_gridOptions: static_gridOptions,
155
103
  dynamic_gridOptions: dynamic_gridOptions,
156
104
  columns: cached_columns,
@@ -171,22 +119,22 @@ function DataGridEventsWrapper(props) {
171
119
  const [menuRow, set_menuRow] = _react.default.useState(null);
172
120
  /* --------------------------------- events --------------------------------- */
173
121
  const onRowContextMenu = _react.default.useCallback((rowProps, event) => {
174
- if (_helpers.func_selection.has_selection()) return;
122
+ if (_func_child.func_selection.has_selection()) return;
175
123
  update_menuRow(rowProps.data);
176
- update_menuAnchorEl(_helpers.func_selection.getVirtualElement(event.clientX, event.clientY));
124
+ update_menuAnchorEl(_func_child.func_selection.getVirtualElement(event.clientX, event.clientY));
177
125
  event.preventDefault();
178
126
  }, []);
179
127
  const onRowClick = _react.default.useCallback((rowProps, event) => {
180
128
  const nowDate = Date.now();
181
- const lastclick = click_data.current[get_row_id(rowProps)];
129
+ const lastclick = click_data.current[(0, _func_grid.get_row_id)(rowProps)];
182
130
  if (lastclick) {
183
131
  const diffTime = Math.abs(nowDate - lastclick);
184
132
  if (diffTime < 400) {
185
- click_data.current[get_row_id(rowProps)] = null;
133
+ click_data.current[(0, _func_grid.get_row_id)(rowProps)] = null;
186
134
  return props.onRowDoubleClick && props.onRowDoubleClick(rowProps.rowIndex, rowProps.data);
187
135
  }
188
136
  }
189
- click_data.current[get_row_id(rowProps)] = nowDate;
137
+ click_data.current[(0, _func_grid.get_row_id)(rowProps)] = nowDate;
190
138
  return props.onRowClick && props.onRowClick(rowProps.rowIndex, rowProps.data);
191
139
  }, [props.onRowClick, props.onRowDoubleClick]);
192
140
  _react.default.useEffect(() => {
@@ -216,18 +164,63 @@ function DataGridEventsWrapper(props) {
216
164
  ...events
217
165
  };
218
166
  }, [props.static_gridOptions, onRowClick]);
219
- return _react.default.createElement(DataGridSizeWrapper, {
220
- ...props,
221
- static_gridOptions: static_gridOptions
222
- }, _react.default.createElement(_controls.ContextMenu, {
167
+ const contextMenu = _react.default.createElement(_controls.ContextMenu, {
223
168
  menuAnchorEl: menuAnchorEl,
224
169
  set_menuAnchorEl: update_menuAnchorEl,
225
170
  menuRow: menuRow,
226
171
  menu_items: props.contextMenuItems
227
- }), props.children);
172
+ });
173
+ if (props.details_dataSource) {
174
+ return _react.default.createElement(DataGridDetailsWrapper, {
175
+ ...props,
176
+ static_gridOptions: static_gridOptions
177
+ }, contextMenu, props.children);
178
+ } else {
179
+ return _react.default.createElement(DataGridSizeWrapper, {
180
+ ...props,
181
+ static_gridOptions: static_gridOptions
182
+ }, contextMenu, props.children);
183
+ }
184
+ }
185
+ function DataGridDetailsWrapper(props) {
186
+ const cached_details_columns = _react.default.useMemo(() => {
187
+ return (0, _func_grid.ApplyColumnData)(props.details_columns);
188
+ }, [props.details_columns]);
189
+ const cached_data = _react.default.useRef();
190
+ const last_cache_info = _react.default.useRef();
191
+ const dataSource = _react.default.useCallback(async dt => {
192
+ const res = await (0, _func_grid.ApplyDataSource)(props.details_dataSource, {
193
+ skip: dt.skip,
194
+ limit: dt.limit,
195
+ cached_data: cached_data,
196
+ last_cache_info: last_cache_info
197
+ });
198
+ console.log('ds', res);
199
+ return res;
200
+ }, [props.dataSource]);
201
+ const renderDetailsGrid = ({
202
+ data
203
+ }) => {
204
+ return _react.default.createElement(_reactdatagridEnterprise.default, {
205
+ defaultFilterValue: props.details_filter,
206
+ dataSource: dataSource,
207
+ columns: cached_details_columns
208
+ });
209
+ };
210
+ /**
211
+ * Merge details into grid
212
+ */
213
+ const static_gridOptions = _react.default.useMemo(() => {
214
+ const finalresult = props.static_gridOptions || {};
215
+ finalresult['renderDetailsGrid'] = renderDetailsGrid;
216
+ return finalresult;
217
+ }, [props.static_gridOptions]);
218
+ return _react.default.createElement(DataGridSizeWrapper, {
219
+ ...props,
220
+ static_gridOptions: static_gridOptions
221
+ }, props.children);
228
222
  }
229
223
  function DataGridSizeWrapper(props) {
230
- // console.log(props);
231
224
  if (props.delayedSize) {
232
225
  return _react.default.createElement(DataGridDelayedSize, {
233
226
  ...props
@@ -238,8 +231,8 @@ function DataGridSizeWrapper(props) {
238
231
  });
239
232
  }
240
233
  }
234
+ /* -------------------------------------------------------------------------- */
241
235
  function DataGridDelayedSize(props) {
242
- const gridRef = _react.default.useRef(null);
243
236
  const {
244
237
  ref,
245
238
  height,
@@ -251,7 +244,7 @@ function DataGridDelayedSize(props) {
251
244
  }, _react.default.createElement(_reactdatagridEnterprise.default, {
252
245
  ...props.static_gridOptions,
253
246
  ...props.dynamic_gridOptions,
254
- handle: ref => gridRef.current = ref ? ref.current : null,
247
+ handle: ref => props.gridRef.current = ref ? ref.current : null,
255
248
  className: 'azgrid-delayedresize',
256
249
  style: {
257
250
  height: height,
@@ -262,13 +255,12 @@ function DataGridDelayedSize(props) {
262
255
  }), props.children);
263
256
  }
264
257
  function DataGridFlexSize(props) {
265
- const gridRef = _react.default.useRef(null);
266
258
  return _react.default.createElement("div", {
267
259
  className: (0, _clsx.default)(props.className, 'azgrid-nooverflow', 'azgrid-filler')
268
260
  }, _react.default.createElement(_reactdatagridEnterprise.default, {
269
261
  ...props.static_gridOptions,
270
262
  ...props.dynamic_gridOptions,
271
- handle: ref => gridRef.current = ref ? ref.current : null,
263
+ handle: ref => props.gridRef.current = ref ? ref.current : null,
272
264
  className: 'azgrid-filler',
273
265
  columns: props.columns,
274
266
  dataSource: props.dataSource
@@ -278,216 +270,6 @@ function DataGridFlexSize(props) {
278
270
  /* -------------------------------------------------------------------------- */
279
271
  /* -------------------------------------------------------------------------- */
280
272
  /* -------------------------------------------------------------------------- */
281
- /**
282
- * merges together all different props for columns
283
- * to build a single final column data array
284
- * @param props
285
- * @returns
286
- */
287
- function ApplyColumnData(props) {
288
- const final_columns = [];
289
- let mcols = props.columns || [];
290
- let mcolExts = props.columnExtensions || [];
291
- let rightColumns = props.rightColumns || [];
292
- let leftColumns = props.leftColumns || [];
293
- let editableColumns = props.editableColumns || [];
294
- let customColumns = props.customColumns || [];
295
- if (!Array.isArray(mcols)) return [];
296
- /* ------------------------------- fix columns ------------------------------ */
297
- mcols.map(r => {
298
- if (r == null) return null;
299
- if (typeof r === 'string') return {
300
- field: r,
301
- header: r
302
- };
303
- if (typeof r === 'object') {
304
- let final_cl = {
305
- name: get_col_name(r),
306
- header: get_col_header(r),
307
- width: r.width || undefined
308
- };
309
- final_cl = {
310
- ...defaultColumnOptions,
311
- ...r,
312
- ...final_cl
313
- };
314
- return final_cl;
315
- }
316
- return null;
317
- }).forEach(r => {
318
- if (r != null) final_columns.push(r);
319
- });
320
- /* ---------------------------- apply extensions ---------------------------- */
321
- if (mcolExts && Array.isArray(mcolExts)) for (let index = 0; index < mcolExts.length; index++) {
322
- const ext = mcolExts[index];
323
- const ext_cl = get_col_name(ext);
324
- if (!ext_cl) {
325
- console.warn('ColumnExtension must have a name');
326
- continue;
327
- }
328
- const mcol = final_columns.find(s => get_col_name(s) === ext_cl);
329
- if (mcol) {
330
- for (const key in ext) {
331
- if (!mcol[key] && key != 'name') mcol[key] = ext[key];
332
- }
333
- }
334
- // if (ext.widthGrow) mcol.widthGrow = ext.widthGrow;
335
- }
336
- /* ------------------------------- frozen cols ------------------------------ */
337
- if (Array.isArray(leftColumns)) {
338
- for (let index = 0; index < leftColumns.length; index++) {
339
- const r = get_col_name(leftColumns[index]);
340
- const mcol = final_columns.find(s => get_col_name(s) === r);
341
- if (mcol) {
342
- mcol.locked = 'start';
343
- }
344
- }
345
- }
346
- if (Array.isArray(rightColumns)) {
347
- for (let index = 0; index < rightColumns.length; index++) {
348
- const r = get_col_name(rightColumns[index]);
349
- const mcol = final_columns.find(s => get_col_name(s) === r);
350
- if (mcol) {
351
- mcol.locked = 'end';
352
- }
353
- }
354
- }
355
- /* -------------------------------- ediatable ------------------------------- */
356
- if (Array.isArray(editableColumns)) {
357
- for (let index = 0; index < editableColumns.length; index++) {
358
- const r = get_col_name(editableColumns[index]);
359
- const mcol = final_columns.find(s => get_col_name(s) === r);
360
- if (mcol) {
361
- mcol.editable = true;
362
- }
363
- }
364
- }
365
- for (let index = 0; index < final_columns.length; index++) {
366
- const col = final_columns[index];
367
- if (col.type) {
368
- switch (col.type) {
369
- case 'combo':
370
- case 'select':
371
- //@ts-ignore
372
- col.editor = _SelectEditor.default;
373
- break;
374
- case 'number':
375
- case 'numberic':
376
- //@ts-ignore
377
- col.editor = _NumericEditor.default;
378
- break;
379
- case 'truefalse':
380
- case 'bool':
381
- //@ts-ignore
382
- col.editor = _BoolEditor.default;
383
- break;
384
- }
385
- if (col.editable != false) col.editable = true;
386
- delete col.type;
387
- }
388
- //@ts-ignore
389
- if (!col.editorProps) col.editorProps = {};
390
- if (col.items) {
391
- //@ts-ignore
392
- if (!col.editorProps.idProperty) col.editorProps.idProperty = 'id';
393
- //@ts-ignore
394
- if (!col.editorProps.collapseOnSelect) col.editorProps.collapseOnSelect = true;
395
- //@ts-ignore
396
- col.editorProps.dataSource = to_datasource(col.items, col.editorProps.idProperty);
397
- delete col.items;
398
- }
399
- }
400
- /* -------------------------------------------------------------------------- */
401
- if (Array.isArray(customColumns)) {
402
- for (let index = 0; index < customColumns.length; index++) {
403
- const r = customColumns[index];
404
- const rn = get_col_name(r);
405
- const mcol = final_columns.find(s => get_col_name(s) === rn);
406
- if (mcol) {
407
- //@ts-ignore
408
- mcol.render = r.render;
409
- }
410
- }
411
- }
412
- /* ------------------------------ apply renames ----------------------------- */
413
- for (let index = 0; index < final_columns.length; index++) {
414
- const col = final_columns[index];
415
- if (!col.name) {
416
- col.name = get_col_name(col);
417
- delete col.field;
418
- delete col.key;
419
- delete col.columnName;
420
- if (col.flex && !col.defaultFlex) col.defaultFlex = col.flex;
421
- }
422
- }
423
- /* -------------------------------------------------------------------------- */
424
- //console.log(final_columns);
425
- return final_columns;
426
- }
427
- function to_datasource(arr, idProperty, valueAsID = true) {
428
- const res = [];
429
- let index = 0;
430
- if (Array.isArray(arr)) {
431
- arr.map(s => {
432
- let elem = {};
433
- if (valueAsID) elem[idProperty] = String(s).toLowerCase();else elem[idProperty] = '_cid_' + index;
434
- if (typeof s === 'object') elem = {
435
- ...elem,
436
- ...s
437
- };else elem['label'] = s;
438
- res.push(elem);
439
- index++;
440
- });
441
- }
442
- return res;
443
- }
444
- /**
445
- * Gets name of a column from its column object
446
- * @param obj
447
- * @returns
448
- */
449
- function get_col_name(obj) {
450
- if (!obj) return '';
451
- if (typeof obj == 'string') return obj;
452
- if (typeof obj != 'object') return '';
453
- return obj.name || obj.field || obj.key || obj.columnName || '';
454
- }
455
- /**
456
- * Gets header of a column
457
- * @param obj
458
- * @returns
459
- */
460
- function get_col_header(obj) {
461
- if (!obj) return '';
462
- if (typeof obj == 'string') return obj;
463
- if (typeof obj != 'object') return '';
464
- return obj.header || obj.title || get_col_name(obj);
465
- }
466
- /**
467
- * Gets name of a column from its column object
468
- * @param obj
469
- * @returns
470
- */
471
- function get_row_id(obj) {
472
- if (!obj) return '-1';
473
- if (typeof obj == 'string') return obj;
474
- if (typeof obj != 'object') return '-1';
475
- return obj.__table_id || obj.id || '-1';
476
- }
477
- /**
478
- * Gets default activation key for grid plugin
479
- * @returns
480
- */
481
- function get_default_key() {
482
- return 'ExpiryDate=2999-01-01,Z=1040577552';
483
- }
484
- //check if two cache objects are the same
485
- function validateCache(current, old, looseCheck = false) {
486
- if (!old || !(0, _object.object_equals)(current, old)) return false;
487
- if (looseCheck) return true;
488
- if (current.ds != old.ds) return false;
489
- return true;
490
- }
491
273
  /* -------------------------------------------------------------------------- */
492
274
  var _default = AzGrid;
493
275
  exports.default = _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azrico/reactgrid",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "main": "dist/index.js",
5
5
  "description": "React Datagrid",
6
6
  "author": "Azrideus <MehrdadTavangar@gmail.com>",
package/src/example.tsx CHANGED
@@ -9,7 +9,7 @@ import { getFormControlUtilityClasses } from '@mui/material';
9
9
  const columns = [
10
10
  {
11
11
  name: 'name',
12
- title: 'Category',
12
+ title: 'Name',
13
13
  defaultFlex: 1,
14
14
  },
15
15
  {
@@ -29,10 +29,10 @@ const columns = [
29
29
  const editableColumns = ['job', 'age'];
30
30
  const contextMenuItems = ['test'];
31
31
 
32
- function getData(delta: any) {
32
+ function getData(delta: any, max = 200) {
33
33
  const fd: any[] = [];
34
34
  console.log('Delta:', delta);
35
- for (let index = 0; index < 200; index++) {
35
+ for (let index = 0; index < max; index++) {
36
36
  const currentObject = {
37
37
  __table_id: String(index),
38
38
  name: 'user-' + index,
@@ -71,6 +71,7 @@ function getData(delta: any) {
71
71
  export function ExampleGrid() {
72
72
  const [ds_reset, set_ds_reset] = React.useState(0);
73
73
  const [delta, set_delta] = React.useState({});
74
+ const [delayed_reload, set_delayed_reload] = React.useState(false);
74
75
 
75
76
  const dataSource = React.useCallback(
76
77
  async (dt) => {
@@ -83,6 +84,17 @@ export function ExampleGrid() {
83
84
  },
84
85
  [ds_reset, delta]
85
86
  );
87
+ const details_dataSource = React.useCallback(
88
+ async (dt) => {
89
+ //console.log('Start loading');
90
+ return await new Promise((resolve) => {
91
+ setTimeout(() => {
92
+ resolve(getData(delta, 5));
93
+ }, 1000);
94
+ });
95
+ },
96
+ [ds_reset, delta]
97
+ );
86
98
 
87
99
  function onEditComplete(params) {
88
100
  const { value, columnId, rowId, ...rest } = params;
@@ -101,22 +113,29 @@ export function ExampleGrid() {
101
113
  //console.log(rowdata?.data || rowdata);
102
114
  }, []);
103
115
 
104
- function rst_ds() {
105
- //console.log('rst_ds');
106
- set_ds_reset((s) => s + 1);
107
- }
116
+ React.useEffect(() => {
117
+ setTimeout(() => {
118
+ set_delayed_reload(true);
119
+ }, 2000);
120
+ }, []);
121
+ const customColumns = React.useMemo(() => {
122
+ if (!delayed_reload) return [];
123
+ return [{ name: 'name', render: (r) => r.value + '^' }];
124
+ }, [delayed_reload]);
108
125
 
109
126
  return (
110
127
  <AzGrid
111
128
  dark
112
129
  delayedSize
130
+ details_dataSource={details_dataSource}
131
+ details_columns={columns}
113
132
  onRowClick={onRowClick}
114
133
  onRowDoubleClick={onRowDoubleClick}
115
134
  // allowChildRows
116
135
  // onSelectionChange={onSelectionChange}
117
136
  // selected={selected}
118
137
  contextMenuItems={contextMenuItems}
119
- // customColumns={customColumns}
138
+ customColumns={customColumns}
120
139
  columns={columns}
121
140
  editableColumns={editableColumns}
122
141
  editable={true}
@@ -10,22 +10,26 @@ function get_selfId(obj) {
10
10
  //given an array of rows, fixes parent,child relations
11
11
  export function fix_parent_child_relations<T extends mrow>(rows: T[]): T[] {
12
12
  if (!Array.isArray(rows)) rows = [];
13
+ const anyparentid = rows.find((r) => get_parentId(r));
14
+ const anyselfid = rows.find((r) => get_selfId(r));
15
+ if (!anyparentid || !anyselfid) return rows;
13
16
 
14
17
  const converted_rows: converted_row[] = rows
15
18
  .filter((r) => r != null)
16
19
  .map((r) => {
17
20
  return { parent: get_parentId(r), self: get_selfId(r), data: r };
18
21
  });
19
- const top_level_rows: converted_row[] = converted_rows.filter((r) => !r.parent);
20
22
 
21
- //find children of top-level parents:
22
- for (let index = 0; index < top_level_rows.length; index++) {
23
- const mrow = top_level_rows[index];
24
- assign_children(mrow, converted_rows);
23
+ const top_level_rows: converted_row[] = converted_rows.filter((r) => !r.parent);
24
+ const any_child = converted_rows.find((r) => Boolean(r.parent));
25
+ if (any_child) {
26
+ //find children of top-level parents:
27
+ for (let index = 0; index < top_level_rows.length; index++) {
28
+ const mrow = top_level_rows[index];
29
+ assign_children(mrow, converted_rows);
30
+ }
25
31
  }
26
- const result = top_level_rows.map((r) => r.data) as T[];
27
- //console.log(result);
28
- return result;
32
+ return top_level_rows.map((r) => r.data) as T[];
29
33
  }
30
34
 
31
35
  function assign_children(row: converted_row, all_rows: converted_row[]) {
@@ -37,7 +41,8 @@ function assign_children(row: converted_row, all_rows: converted_row[]) {
37
41
  assign_children(child, all_rows);
38
42
  }
39
43
  row.data.__children = my_children.map((r) => r.data);
40
- } else if (!Array.isArray(row.data.__children) || row.data.__children.length == 0) row.data.__children = undefined;
44
+ } else if (!Array.isArray(row.data.__children) || row.data.__children.length == 0)
45
+ row.data.__children = undefined;
41
46
  }
42
47
  export class func_selection {
43
48
  static getVirtualElement(x = 0, y = 0) {
@@ -59,7 +64,10 @@ export class func_selection {
59
64
  var text: any = '';
60
65
  if (window.getSelection) {
61
66
  text = window.getSelection()?.toString();
62
- } else if ((document as any).selection && (document as any).selection.type != 'Control') {
67
+ } else if (
68
+ (document as any).selection &&
69
+ (document as any).selection.type != 'Control'
70
+ ) {
63
71
  text = (document as any).selection.createRange()?.text;
64
72
  }
65
73
  return text || '';