@guiexpert/demo-table-models 1.1.78 → 1.1.80

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.
Files changed (2) hide show
  1. package/index.js +911 -2
  2. package/package.json +5 -3
package/index.js CHANGED
@@ -152,28 +152,128 @@ class fe {
152
152
  }
153
153
  }
154
154
  class De extends ee {
155
+ /**
156
+ * Creates an instance of AreaModelObjectArray.
157
+ *
158
+ * @param {AreaIdent} areaIdent - Identifies which area of the table this model represents ('header', 'body', or 'footer')
159
+ * @param {T[]} rows - The array of objects that represent the rows in this area
160
+ * @param {number} defaultRowHeight - The default height for rows in this area (in pixels)
161
+ * @param {ColumnDefIf[]} [columnDefs=[]] - Definitions for the columns in this area
162
+ * @param {string} [selectedRowClass='ge-selected-row'] - CSS class to apply to selected rows
163
+ * @param {string} [focusedRowClass='ge-focused-row'] - CSS class to apply to the focused row
164
+ *
165
+ * @example
166
+ * const rows = [
167
+ * { id: 1, name: 'John', age: 30 },
168
+ * { id: 2, name: 'Jane', age: 25 }
169
+ * ];
170
+ *
171
+ * const columnDefs = [
172
+ * { property: 'id', headerLabel: 'ID', width: 50 },
173
+ * { property: 'name', headerLabel: 'Name', width: 150 },
174
+ * { property: 'age', headerLabel: 'Age', width: 100 }
175
+ * ];
176
+ *
177
+ * const bodyAreaModel = new AreaModelObjectArray(
178
+ * 'body',
179
+ * rows,
180
+ * 30,
181
+ * columnDefs
182
+ * );
183
+ */
155
184
  constructor(e, r, a, t = [], n = "ge-selected-row", m = "ge-focused-row") {
156
185
  super(e, t, a), this.areaIdent = e, this.rows = r, this.defaultRowHeight = a, this.columnDefs = t, this.selectedRowClass = n, this.focusedRowClass = m, this.sorterService = new fe(), this._focusedRowIndex = 0, this.filteredRows = [...r], this.properties = t.map((d) => d.property);
157
186
  }
187
+ /**
188
+ * Gets the index of the currently focused row.
189
+ *
190
+ * @returns {number} The index of the focused row
191
+ *
192
+ * @example
193
+ * const focusedRowIndex = bodyAreaModel.getFocusedRowIndex();
194
+ * console.log(`The focused row is at index ${focusedRowIndex}`);
195
+ */
158
196
  getFocusedRowIndex() {
159
197
  return this._focusedRowIndex;
160
198
  }
199
+ /**
200
+ * Sets the index of the focused row.
201
+ * This will apply the focused row styling to the specified row.
202
+ *
203
+ * @param {number} value - The index of the row to focus
204
+ *
205
+ * @example
206
+ * // Focus the second row (index 1)
207
+ * bodyAreaModel.setFocusedRowIndex(1);
208
+ */
161
209
  setFocusedRowIndex(e) {
162
210
  this._focusedRowIndex = e;
163
211
  }
212
+ /**
213
+ * Replaces the current rows array with a new one.
214
+ * This also resets the filtered rows to match the new rows array.
215
+ *
216
+ * @param {T[]} rows - The new array of row objects
217
+ *
218
+ * @example
219
+ * // Replace the current rows with new data
220
+ * const newRows = [
221
+ * { id: 4, name: 'Alice', age: 35 },
222
+ * { id: 5, name: 'Charlie', age: 45 }
223
+ * ];
224
+ * bodyAreaModel.setRows(newRows);
225
+ */
164
226
  setRows(e) {
165
227
  this.rows = e, this.filteredRows = [...e];
166
228
  }
229
+ /**
230
+ * Filters both the original rows and filtered rows arrays using the provided predicate function.
231
+ * Unlike `externalFilterChanged`, this method permanently modifies the original rows array.
232
+ *
233
+ * @param {(row: T) => boolean} predict - A function that returns true for rows to keep and false for rows to filter out
234
+ *
235
+ * @example
236
+ * // Remove all rows where age is less than 30
237
+ * bodyAreaModel.filterRowsByPredict(row => row.age >= 30);
238
+ */
167
239
  filterRowsByPredict(e) {
168
240
  this.rows = this.rows.filter(e), this.filteredRows = this.filteredRows.filter(e);
169
241
  }
170
242
  /**
171
- * return row count of filtered rows
243
+ * Returns the number of rows in the filtered rows array.
244
+ * This is used to determine how many rows should be rendered in the table.
245
+ *
246
+ * @returns {number} The number of rows in the filtered rows array
247
+ *
248
+ * @example
249
+ * const rowCount = bodyAreaModel.getRowCount();
250
+ * console.log(`The table has ${rowCount} rows`);
172
251
  */
173
252
  getRowCount() {
174
253
  var e;
175
254
  return ((e = this.filteredRows) == null ? void 0 : e.length) ?? 0;
176
255
  }
256
+ /**
257
+ * Gets the value at the specified row and column indices.
258
+ * This method handles tree rows and nested properties.
259
+ *
260
+ * @param {number} rowIndex - The index of the row
261
+ * @param {number} columnIndex - The index of the column
262
+ * @returns {any} The value at the specified cell, or an empty string if not found
263
+ *
264
+ * @example
265
+ * // Get the value in the first row, second column
266
+ * const value = bodyAreaModel.getValueAt(0, 1);
267
+ * console.log(`The value is: ${value}`);
268
+ *
269
+ * @example
270
+ * // Iterate through all cells in a row
271
+ * const rowIndex = 0;
272
+ * for (let colIndex = 0; colIndex < columnDefs.length; colIndex++) {
273
+ * const value = bodyAreaModel.getValueAt(rowIndex, colIndex);
274
+ * console.log(`Cell (${rowIndex}, ${colIndex}): ${value}`);
275
+ * }
276
+ */
177
277
  getValueAt(e, r) {
178
278
  const a = this.properties[r];
179
279
  let t = this.filteredRows[e];
@@ -182,46 +282,176 @@ class De extends ee {
182
282
  /**
183
283
  * Retrieves the filtered and sorted rows from the dataset.
184
284
  * These rows are used for rendering the table.
285
+ * Unlike `getAllRows()`, this method returns only the rows that match any applied filters.
185
286
  *
186
- * @return {T[]} An array containing the filtered (and sorted) rows.
287
+ * @returns {T[]} An array containing the filtered (and sorted) rows
288
+ *
289
+ * @example
290
+ * // Get all filtered rows
291
+ * const filteredRows = bodyAreaModel.getFilteredRows();
292
+ *
293
+ * // Count rows that match a certain condition
294
+ * const adultsCount = filteredRows.filter(row => row.age >= 18).length;
187
295
  */
188
296
  getFilteredRows() {
189
297
  return this.filteredRows;
190
298
  }
299
+ /**
300
+ * Returns the original, unfiltered array of rows.
301
+ * This can be useful when you need to access all data regardless of any applied filters.
302
+ *
303
+ * @returns {T[]} The original array of row objects
304
+ *
305
+ * @example
306
+ * // Get all rows, including those filtered out
307
+ * const allRows = bodyAreaModel.getAllRows();
308
+ *
309
+ * // Calculate average age across all rows
310
+ * const totalAge = allRows.reduce((sum, row) => sum + row.age, 0);
311
+ * const averageAge = totalAge / allRows.length;
312
+ */
191
313
  getAllRows() {
192
314
  return this.rows;
193
315
  }
194
316
  /**
195
317
  * Returns the first row from the filtered rows that matches the given criteria based on the provided predicate function.
318
+ * This method only searches within the filtered rows, not the original rows array.
196
319
  *
197
320
  * @param {Partial<T>} criteria - A partial object containing the search criteria
198
321
  * @param {(criteria: Partial<T>, row: T) => boolean} predicate - A function that takes the search criteria and a row,
199
322
  * and returns true if the row matches the criteria
200
323
  * @returns {T | undefined} The first matching row, or undefined if no match is found
324
+ *
325
+ * @example
326
+ * // Find a user by name in the filtered rows
327
+ * const criteria = { name: 'John' };
328
+ * const user = bodyAreaModel.findRowFromFilteredRowsByAllCriteria(
329
+ * criteria,
330
+ * (criteria, row) => row.name === criteria.name
331
+ * );
332
+ *
333
+ * @example
334
+ * // Find a user by age range in the filtered rows
335
+ * const criteria = { minAge: 25, maxAge: 35 };
336
+ * const user = bodyAreaModel.findRowFromFilteredRowsByAllCriteria(
337
+ * criteria,
338
+ * (criteria, row) => row.age >= criteria.minAge && row.age <= criteria.maxAge
339
+ * );
201
340
  */
202
341
  findRowFromFilteredRowsByAllCriteria(e, r) {
203
342
  return this.getFilteredRows().find((a) => r(e, a));
204
343
  }
205
344
  /**
206
345
  * Searches through all rows to find a row that matches the given criteria based on the predicate function.
346
+ * This method searches within the original rows array, including rows that may have been filtered out.
207
347
  *
208
348
  * @param {Partial<T>} criteria - A partial object containing the search criteria
209
349
  * @param {(criteria: Partial<T>, row: T) => boolean} predicate - A function that takes the search criteria and a row,
210
350
  * and returns true if the row matches the criteria
211
351
  * @returns {T | undefined} The first matching row from all rows, or undefined if no match is found
352
+ *
353
+ * @example
354
+ * // Find a user by ID in all rows
355
+ * const criteria = { id: 42 };
356
+ * const user = bodyAreaModel.findRowFromAllRowsByAllCriteria(
357
+ * criteria,
358
+ * (criteria, row) => row.id === criteria.id
359
+ * );
360
+ *
361
+ * @example
362
+ * // Find a user with a specific property value in all rows
363
+ * const criteria = { department: 'Engineering', role: 'Manager' };
364
+ * const user = bodyAreaModel.findRowFromAllRowsByAllCriteria(
365
+ * criteria,
366
+ * (criteria, row) => row.department === criteria.department && row.role === criteria.role
367
+ * );
212
368
  */
213
369
  findRowFromAllRowsByAllCriteria(e, r) {
214
370
  return this.getAllRows().find((a) => r(e, a));
215
371
  }
372
+ /**
373
+ * Returns the height of the row at the specified index.
374
+ * This implementation always returns the default row height.
375
+ * Override this method in subclasses to support variable row heights.
376
+ *
377
+ * @param {number} _rowIndex - The index of the row (unused in this implementation)
378
+ * @returns {number} The height of the row in pixels
379
+ *
380
+ * @example
381
+ * const rowHeight = bodyAreaModel.getRowHeight(0);
382
+ * console.log(`The first row has a height of ${rowHeight}px`);
383
+ */
216
384
  getRowHeight(e) {
217
385
  return this.defaultRowHeight;
218
386
  }
387
+ /**
388
+ * Returns the row object at the specified index from the filtered rows array.
389
+ * This method overrides the parent class implementation.
390
+ *
391
+ * @param {number} rowIndex - The index of the row to retrieve
392
+ * @returns {any} The row object at the specified index, or undefined if the index is out of bounds
393
+ *
394
+ * @example
395
+ * // Get the first row object
396
+ * const row = bodyAreaModel.getRowByIndex(0);
397
+ * console.log('First row:', row);
398
+ *
399
+ * @example
400
+ * // Iterate through all rows
401
+ * for (let i = 0; i < bodyAreaModel.getRowCount(); i++) {
402
+ * const row = bodyAreaModel.getRowByIndex(i);
403
+ * console.log(`Row ${i}:`, row);
404
+ * }
405
+ */
219
406
  getRowByIndex(e) {
220
407
  return this.filteredRows[e];
221
408
  }
409
+ /**
410
+ * Applies an external filter function to the rows array.
411
+ * This method updates the filtered rows array without modifying the original rows array.
412
+ *
413
+ * @param {FilterFunction<any>} predictFn - A function that returns true for rows to keep and false for rows to filter out
414
+ *
415
+ * @example
416
+ * // Filter rows where age is greater than 30
417
+ * bodyAreaModel.externalFilterChanged(row => row.age > 30);
418
+ *
419
+ * @example
420
+ * // Filter rows based on a search term
421
+ * const searchTerm = 'john';
422
+ * bodyAreaModel.externalFilterChanged(row =>
423
+ * row.name.toLowerCase().includes(searchTerm.toLowerCase())
424
+ * );
425
+ *
426
+ * @example
427
+ * // Clear all filters
428
+ * bodyAreaModel.externalFilterChanged(() => true);
429
+ */
222
430
  externalFilterChanged(e) {
223
431
  this.filteredRows = this.rows ? this.rows.filter(e) : [];
224
432
  }
433
+ /**
434
+ * Sorts the filtered rows based on the provided sort items.
435
+ * This method supports sorting by multiple columns with different sort directions.
436
+ *
437
+ * @param {SortItem[]} sortItems - An array of sort items, each containing a column index and sort state
438
+ * @returns {boolean} Always returns true to indicate sorting was performed
439
+ *
440
+ * @example
441
+ * // Sort by age in ascending order
442
+ * bodyAreaModel.doSort([{ columnIndex: 2, sortState: 'asc' }]);
443
+ *
444
+ * @example
445
+ * // Sort by name in descending order, then by age in ascending order
446
+ * bodyAreaModel.doSort([
447
+ * { columnIndex: 1, sortState: 'desc' },
448
+ * { columnIndex: 2, sortState: 'asc' }
449
+ * ]);
450
+ *
451
+ * @example
452
+ * // Clear sorting
453
+ * bodyAreaModel.doSort([{ columnIndex: 0, sortState: 'none' }]);
454
+ */
225
455
  doSort(e) {
226
456
  for (const r of e) {
227
457
  const { columnIndex: a, sortState: t } = r, n = t === "asc" ? 1 : t === "desc" ? -1 : 0, m = this.properties[a];
@@ -229,20 +459,110 @@ class De extends ee {
229
459
  }
230
460
  return !0;
231
461
  }
462
+ /**
463
+ * Sorts the filtered rows using a custom comparator function.
464
+ * This method provides more flexibility than `doSort()` for complex sorting logic.
465
+ *
466
+ * @param {(a: T, b: T) => number} compareFn - A function that compares two rows and returns a number:
467
+ * - Negative if a should come before b
468
+ * - Positive if a should come after b
469
+ * - Zero if they are equivalent for sorting purposes
470
+ *
471
+ * @example
472
+ * // Sort by name length
473
+ * bodyAreaModel.sort((a, b) => a.name.length - b.name.length);
474
+ *
475
+ * @example
476
+ * // Sort by a computed value
477
+ * bodyAreaModel.sort((a, b) => {
478
+ * const scoreA = a.wins * 3 + a.draws;
479
+ * const scoreB = b.wins * 3 + b.draws;
480
+ * return scoreB - scoreA; // Descending order
481
+ * });
482
+ */
232
483
  sort(e) {
233
484
  this.filteredRows = this.filteredRows.sort(e);
234
485
  }
486
+ /**
487
+ * Gets a value from an object using a property path.
488
+ * This method supports accessing nested properties using dot notation (e.g., 'person.name').
489
+ *
490
+ * @param {T} t - The object to get the value from
491
+ * @param {string} property - The property path to access (e.g., 'name' or 'person.contact.email')
492
+ * @returns {any} The value at the specified property path, or undefined if not found
493
+ *
494
+ * @example
495
+ * const user = { id: 1, name: 'John', contact: { email: 'john@example.com' } };
496
+ *
497
+ * // Access simple property
498
+ * const name = bodyAreaModel.getValueByT(user, 'name');
499
+ * console.log(name); // 'John'
500
+ *
501
+ * // Access nested property
502
+ * const email = bodyAreaModel.getValueByT(user, 'contact.email');
503
+ * console.log(email); // 'john@example.com'
504
+ */
235
505
  getValueByT(e, r) {
236
506
  if (e && r)
237
507
  return r.includes(".") ? this.getPropertyValue(e, r.split(".")) : e[r];
238
508
  }
509
+ /**
510
+ * Changes the order of columns by moving a column from one position to another.
511
+ * This method updates both the properties array and calls the parent class implementation.
512
+ *
513
+ * @param {number} sourceColumnIndex - The index of the column to move
514
+ * @param {number} targetColumnIndex - The index where the column should be moved to
515
+ *
516
+ * @example
517
+ * // Move the second column (index 1) to the fourth position (index 3)
518
+ * bodyAreaModel.changeColumnOrder(1, 3);
519
+ *
520
+ * @example
521
+ * // Move the last column to the first position
522
+ * const lastIndex = bodyAreaModel.columnDefs.length - 1;
523
+ * bodyAreaModel.changeColumnOrder(lastIndex, 0);
524
+ */
239
525
  changeColumnOrder(e, r) {
240
526
  this.arrayMove(this.properties, e, r), super.changeColumnOrder(e, r);
241
527
  }
528
+ /**
529
+ * Gets the custom CSS classes that should be applied to a cell.
530
+ * This method extends the parent class implementation to add selection and focus classes.
531
+ *
532
+ * @param {number} rowIndex - The index of the row
533
+ * @param {number} _columnIndex - The index of the column (unused in this implementation)
534
+ * @returns {string[]} An array of CSS class names to apply to the cell
535
+ *
536
+ * @example
537
+ * // Get the CSS classes for a cell
538
+ * const classes = bodyAreaModel.getCustomClassesAt(1, 2);
539
+ * console.log('CSS classes:', classes);
540
+ *
541
+ * @example
542
+ * // Apply the classes to a cell element
543
+ * const cellElement = document.createElement('div');
544
+ * const classes = bodyAreaModel.getCustomClassesAt(rowIndex, columnIndex);
545
+ * cellElement.classList.add(...classes);
546
+ */
242
547
  getCustomClassesAt(e, r) {
243
548
  const a = super.getCustomClassesAt(e, r);
244
549
  return this.getRowByIndex(e).selected && a.push(this.selectedRowClass), this._focusedRowIndex === e && a.push(this.focusedRowClass), a;
245
550
  }
551
+ /**
552
+ * Creates a comparator function for sorting rows based on a property and sort direction.
553
+ * This method supports custom sort comparators defined in column definitions.
554
+ *
555
+ * @param {string} property - The property to sort by
556
+ * @param {number} f - The sort direction factor: 1 for ascending, -1 for descending, 0 for no sorting
557
+ * @returns {(a: T, b: T) => number} A comparator function that compares two rows
558
+ *
559
+ * @example
560
+ * // Create a comparator for sorting by name in ascending order
561
+ * const comparator = bodyAreaModel.genericFlatTableSortComparator('name', 1);
562
+ *
563
+ * // Sort the rows using the comparator
564
+ * const sortedRows = [...bodyAreaModel.getFilteredRows()].sort(comparator);
565
+ */
246
566
  genericFlatTableSortComparator(e, r) {
247
567
  const a = this.columnDefs.find((t) => t.property === e);
248
568
  return (t, n) => {
@@ -250,6 +570,16 @@ class De extends ee {
250
570
  return a != null && a.sortComparator ? r * a.sortComparator(m, d, t, n, r) : this.sorterService.genericSortComparator(m, d, r);
251
571
  };
252
572
  }
573
+ /**
574
+ * Recursively gets a value from an object using an array of property names.
575
+ * This is a helper method used by `getValueByT` to access nested properties.
576
+ *
577
+ * @param {any} o - The object to get the value from
578
+ * @param {string[]} props - An array of property names representing the path to the value
579
+ * @returns {any} The value at the specified property path, or undefined if not found
580
+ *
581
+ * @private
582
+ */
253
583
  getPropertyValue(e, r) {
254
584
  const a = r.shift(), t = e[a];
255
585
  return t && r.length ? this.getPropertyValue(t, r) : t;
@@ -1574,6 +1904,35 @@ class W {
1574
1904
  }
1575
1905
  }
1576
1906
  class B extends De {
1907
+ /**
1908
+ * Creates an instance of AreaModelObjectArrayWithColumndefs.
1909
+ *
1910
+ * @param {AreaIdent} areaIdent - Identifies which area of the table this model represents ('header', 'body', or 'footer')
1911
+ * @param {T[]} rows - The array of objects that represent the rows in this area
1912
+ * @param {ColumnDefIf[]} columnDefs - Definitions for the columns in this area (required parameter)
1913
+ * @param {number} defaultRowHeight - The default height for rows in this area (in pixels)
1914
+ * @param {string} [selectedRowClass='ge-selected-row'] - CSS class to apply to selected rows
1915
+ * @param {string} [focusedRowClass='ge-focused-row'] - CSS class to apply to the focused row
1916
+ *
1917
+ * @example
1918
+ * const rows = [
1919
+ * { id: 1, name: 'John', age: 30 },
1920
+ * { id: 2, name: 'Jane', age: 25 }
1921
+ * ];
1922
+ *
1923
+ * const columnDefs = [
1924
+ * { property: 'id', headerLabel: 'ID', width: new Size(50, 'px') },
1925
+ * { property: 'name', headerLabel: 'Name', width: new Size(150, 'px') },
1926
+ * { property: 'age', headerLabel: 'Age', width: new Size(100, 'px') }
1927
+ * ];
1928
+ *
1929
+ * const bodyAreaModel = new AreaModelObjectArrayWithColumndefs(
1930
+ * 'body',
1931
+ * rows,
1932
+ * columnDefs,
1933
+ * 30
1934
+ * );
1935
+ */
1577
1936
  constructor(e, r, a, t, n = "ge-selected-row", m = "ge-focused-row") {
1578
1937
  super(
1579
1938
  e,
@@ -2228,70 +2587,620 @@ class te {
2228
2587
  constructor() {
2229
2588
  this.areaIdent = "body", this.rowSelectionModel = void 0;
2230
2589
  }
2590
+ /**
2591
+ * Changes the order of columns by moving a column from one position to another.
2592
+ * This method is called when the user drags a column to a new position.
2593
+ * The base implementation does nothing and should be overridden by subclasses
2594
+ * that support column reordering.
2595
+ *
2596
+ * @param {number} _sourceColumnIndex - The index of the column to move
2597
+ * @param {number} _targetColumnIndex - The index where the column should be moved to
2598
+ * @returns {void}
2599
+ *
2600
+ * @example
2601
+ * // Override in a subclass to implement column reordering
2602
+ * changeColumnOrder(sourceColumnIndex: number, targetColumnIndex: number): void {
2603
+ * // Move the column in the internal data structure
2604
+ * this.arrayMove(this.columns, sourceColumnIndex, targetColumnIndex);
2605
+ * }
2606
+ */
2231
2607
  changeColumnOrder(e, r) {
2232
2608
  }
2609
+ /**
2610
+ * Sorts the rows in this area based on the provided sort items.
2611
+ * This method is called when the user clicks on a sortable column header.
2612
+ * The base implementation returns false (no sorting performed) and should be
2613
+ * overridden by subclasses that support sorting.
2614
+ *
2615
+ * @param {SortItem[]} _sortItems - An array of sort items, each containing a column index and sort direction
2616
+ * @returns {boolean} True if sorting was performed, false otherwise
2617
+ *
2618
+ * @example
2619
+ * // Override in a subclass to implement sorting
2620
+ * doSort(sortItems: SortItem[]): boolean {
2621
+ * if (!sortItems.length) return false;
2622
+ *
2623
+ * // Apply sorting to the rows
2624
+ * this.rows.sort((a, b) => {
2625
+ * const { columnIndex, sortState } = sortItems[0];
2626
+ * const valueA = this.getValueAt(this.rows.indexOf(a), columnIndex);
2627
+ * const valueB = this.getValueAt(this.rows.indexOf(b), columnIndex);
2628
+ *
2629
+ * const direction = sortState === 'asc' ? 1 : -1;
2630
+ * if (valueA < valueB) return -1 * direction;
2631
+ * if (valueA > valueB) return 1 * direction;
2632
+ * return 0;
2633
+ * });
2634
+ *
2635
+ * return true;
2636
+ * }
2637
+ */
2233
2638
  doSort(e) {
2234
2639
  return !1;
2235
2640
  }
2641
+ /**
2642
+ * Sorts the rows in this area using a custom comparator function.
2643
+ * This method provides more flexibility than doSort for complex sorting logic.
2644
+ * The base implementation does nothing and should be overridden by subclasses
2645
+ * that support custom sorting.
2646
+ *
2647
+ * @param {(a: any, b: any) => number} [_compareFn] - A function that compares two rows and returns a number:
2648
+ * - Negative if a should come before b
2649
+ * - Positive if a should come after b
2650
+ * - Zero if they are equivalent for sorting purposes
2651
+ * @returns {void}
2652
+ *
2653
+ * @example
2654
+ * // Override in a subclass to implement custom sorting
2655
+ * sort(compareFn?: (a: any, b: any) => number): void {
2656
+ * if (!compareFn) return;
2657
+ *
2658
+ * // Apply the custom sort function
2659
+ * this.rows.sort(compareFn);
2660
+ * }
2661
+ */
2236
2662
  sort(e) {
2237
2663
  }
2664
+ /**
2665
+ * Applies a filter function to the rows in this area.
2666
+ * This method is called when a filter is applied to the table.
2667
+ * The base implementation does nothing and should be overridden by subclasses
2668
+ * that support filtering.
2669
+ *
2670
+ * @param {FilterFunction<T>} _predictFn - A function that takes a row and returns true if the row should be visible
2671
+ * @returns {void}
2672
+ *
2673
+ * @example
2674
+ * // Override in a subclass to implement filtering
2675
+ * externalFilterChanged<T>(predictFn: FilterFunction<T>): void {
2676
+ * // Apply the filter to the rows
2677
+ * this.filteredRows = this.rows.filter(predictFn);
2678
+ * }
2679
+ */
2238
2680
  externalFilterChanged(e) {
2239
2681
  }
2682
+ /**
2683
+ * Returns a cell renderer for the cell at the specified row and column indices.
2684
+ * A cell renderer is responsible for rendering the cell content in a custom way.
2685
+ * The base implementation returns undefined (default rendering) and should be
2686
+ * overridden by subclasses that support custom cell rendering.
2687
+ *
2688
+ * @param {number} _rowIndex - The index of the row
2689
+ * @param {number} _columnIndex - The index of the column
2690
+ * @returns {CellRendererIf | undefined} A cell renderer instance, or undefined for default rendering
2691
+ *
2692
+ * @example
2693
+ * // Override in a subclass to provide custom cell renderers
2694
+ * getCellRenderer(rowIndex: number, columnIndex: number): CellRendererIf | undefined {
2695
+ * // Get renderer from column definition
2696
+ * const columnDef = this.columnDefs[columnIndex];
2697
+ * return columnDef?.rendererMap?.[this.areaIdent];
2698
+ * }
2699
+ */
2240
2700
  getCellRenderer(e, r) {
2241
2701
  }
2702
+ /**
2703
+ * Returns the column span value for the cell at the specified row and column indices.
2704
+ * A colspan value of N means the cell spans N columns horizontally.
2705
+ * The base implementation returns 0 (no spanning) and should be overridden by
2706
+ * subclasses that support column spanning.
2707
+ *
2708
+ * @param {number} _rowIndex - The index of the row
2709
+ * @param {number} _columnIndex - The index of the column
2710
+ * @returns {number} The colspan value (number of columns the cell spans)
2711
+ *
2712
+ * @example
2713
+ * // Override in a subclass to implement column spanning
2714
+ * getColspanAt(rowIndex: number, columnIndex: number): number {
2715
+ * // Special case: first row, first column spans 3 columns
2716
+ * if (rowIndex === 0 && columnIndex === 0) return 3;
2717
+ *
2718
+ * // No spanning for other cells
2719
+ * return 1;
2720
+ * }
2721
+ */
2242
2722
  getColspanAt(e, r) {
2243
2723
  return 0;
2244
2724
  }
2725
+ /**
2726
+ * Returns an array of CSS class names to apply to the cell at the specified row and column indices.
2727
+ * This method allows for custom styling of individual cells.
2728
+ * The base implementation returns an empty array (no custom classes) and should be
2729
+ * overridden by subclasses that support custom cell styling.
2730
+ *
2731
+ * @param {number} _rowIndex - The index of the row
2732
+ * @param {number} _columnIndex - The index of the column
2733
+ * @returns {string[]} An array of CSS class names
2734
+ *
2735
+ * @example
2736
+ * // Override in a subclass to implement custom cell classes
2737
+ * getCustomClassesAt(rowIndex: number, columnIndex: number): string[] {
2738
+ * const classes: string[] = [];
2739
+ *
2740
+ * // Add classes based on row index
2741
+ * if (rowIndex % 2 === 0) {
2742
+ * classes.push('even-row');
2743
+ * } else {
2744
+ * classes.push('odd-row');
2745
+ * }
2746
+ *
2747
+ * // Add classes based on cell value
2748
+ * const value = this.getValueAt(rowIndex, columnIndex);
2749
+ * if (typeof value === 'number' && value < 0) {
2750
+ * classes.push('negative-value');
2751
+ * }
2752
+ *
2753
+ * return classes;
2754
+ * }
2755
+ */
2245
2756
  getCustomClassesAt(e, r) {
2246
2757
  return [];
2247
2758
  }
2759
+ /**
2760
+ * Returns an object containing CSS style properties to apply to the cell at the specified row and column indices.
2761
+ * This method allows for inline styling of individual cells.
2762
+ * The base implementation returns undefined (no custom styles) and should be
2763
+ * overridden by subclasses that support custom cell styling.
2764
+ *
2765
+ * @param {number} _rowIndex - The index of the row
2766
+ * @param {number} _columnIndex - The index of the column
2767
+ * @returns {{ [key: string]: string } | undefined} An object with CSS style properties, or undefined if no custom styles
2768
+ *
2769
+ * @example
2770
+ * // Override in a subclass to implement custom cell styles
2771
+ * getCustomStyleAt(rowIndex: number, columnIndex: number): { [key: string]: string } | undefined {
2772
+ * // Apply background color based on value
2773
+ * const value = this.getValueAt(rowIndex, columnIndex);
2774
+ *
2775
+ * if (typeof value === 'number') {
2776
+ * // Color gradient based on value
2777
+ * if (value < 0) {
2778
+ * return { 'background-color': `rgba(255, 0, 0, ${Math.min(Math.abs(value) / 100, 0.5)})` };
2779
+ * } else if (value > 0) {
2780
+ * return { 'background-color': `rgba(0, 255, 0, ${Math.min(value / 100, 0.5)})` };
2781
+ * }
2782
+ * }
2783
+ *
2784
+ * return undefined; // No custom styles
2785
+ * }
2786
+ */
2248
2787
  getCustomStyleAt(e, r) {
2249
2788
  }
2789
+ /**
2790
+ * Returns the maximum colspan value that can occur in this area model.
2791
+ * This value is used to optimize rendering performance.
2792
+ * The base implementation returns 0 (no colspans) and should be overridden by
2793
+ * subclasses that support column spanning.
2794
+ *
2795
+ * @returns {number} The maximum possible colspan value in this area
2796
+ *
2797
+ * @example
2798
+ * // Override in a subclass to specify maximum colspan
2799
+ * getMaxColspan(): number {
2800
+ * // If the model has colspans, return the maximum possible value
2801
+ * return 3; // If some cells span up to 3 columns
2802
+ * }
2803
+ */
2250
2804
  getMaxColspan() {
2251
2805
  return 0;
2252
2806
  }
2807
+ /**
2808
+ * Returns the maximum rowspan value that can occur in this area model.
2809
+ * This value is used to optimize rendering performance.
2810
+ * The base implementation returns 0 (no rowspans) and should be overridden by
2811
+ * subclasses that support row spanning.
2812
+ *
2813
+ * @returns {number} The maximum possible rowspan value in this area
2814
+ *
2815
+ * @example
2816
+ * // Override in a subclass to specify maximum rowspan
2817
+ * getMaxRowspan(): number {
2818
+ * // If the model has rowspans, return the maximum possible value
2819
+ * return 2; // If some cells span up to 2 rows
2820
+ * }
2821
+ */
2253
2822
  getMaxRowspan() {
2254
2823
  return 0;
2255
2824
  }
2825
+ /**
2826
+ * Returns the row object at the specified index.
2827
+ * This method provides access to the underlying data structure.
2828
+ * The base implementation returns undefined and should be overridden by
2829
+ * subclasses that have a row-based data structure.
2830
+ *
2831
+ * @param {number} _rowIndex - The index of the row
2832
+ * @returns {any} The row object, or undefined if the row doesn't exist
2833
+ *
2834
+ * @example
2835
+ * // Override in a subclass to provide access to row data
2836
+ * getRowByIndex(rowIndex: number): any {
2837
+ * if (rowIndex < 0 || rowIndex >= this.data.length) return undefined;
2838
+ * return this.data[rowIndex];
2839
+ * }
2840
+ */
2256
2841
  getRowByIndex(e) {
2257
2842
  }
2843
+ /**
2844
+ * Returns the number of rows in this area.
2845
+ * This is a fundamental method that determines the vertical size of the area.
2846
+ * The base implementation returns 0 (no rows) and should be overridden by
2847
+ * all subclasses.
2848
+ *
2849
+ * @returns {number} The number of rows in the area
2850
+ *
2851
+ * @example
2852
+ * // Override in a subclass to provide the row count
2853
+ * getRowCount(): number {
2854
+ * return this.data.length;
2855
+ * }
2856
+ */
2258
2857
  getRowCount() {
2259
2858
  return 0;
2260
2859
  }
2860
+ /**
2861
+ * Returns the height of the row at the specified index, in pixels.
2862
+ * This method allows for variable row heights in the table.
2863
+ * The base implementation returns 0 and should be overridden by
2864
+ * all subclasses.
2865
+ *
2866
+ * @param {number} _rowIndex - The index of the row
2867
+ * @returns {number} The height of the row in pixels
2868
+ *
2869
+ * @example
2870
+ * // Override in a subclass to provide fixed row heights
2871
+ * getRowHeight(rowIndex: number): number {
2872
+ * return 30; // 30px for all rows
2873
+ * }
2874
+ *
2875
+ * @example
2876
+ * // Override in a subclass to provide variable row heights
2877
+ * getRowHeight(rowIndex: number): number {
2878
+ * // First row is taller
2879
+ * if (rowIndex === 0) return 50;
2880
+ *
2881
+ * // Default height for other rows
2882
+ * return 30;
2883
+ * }
2884
+ */
2261
2885
  getRowHeight(e) {
2262
2886
  return 0;
2263
2887
  }
2888
+ /**
2889
+ * Returns the row span value for the cell at the specified row and column indices.
2890
+ * A rowspan value of N means the cell spans N rows vertically.
2891
+ * The base implementation returns 0 (no spanning) and should be overridden by
2892
+ * subclasses that support row spanning.
2893
+ *
2894
+ * @param {number} _rowIndex - The index of the row
2895
+ * @param {number} _columnIndex - The index of the column
2896
+ * @returns {number} The rowspan value (number of rows the cell spans)
2897
+ *
2898
+ * @example
2899
+ * // Override in a subclass to implement row spanning
2900
+ * getRowspanAt(rowIndex: number, columnIndex: number): number {
2901
+ * // Special case: first column spans 2 rows at the beginning
2902
+ * if (columnIndex === 0 && rowIndex % 2 === 0) return 2;
2903
+ *
2904
+ * // No spanning for other cells
2905
+ * return 1;
2906
+ * }
2907
+ */
2264
2908
  getRowspanAt(e, r) {
2265
2909
  return 0;
2266
2910
  }
2911
+ /**
2912
+ * Returns the tooltip text for the cell at the specified row and column indices.
2913
+ * This tooltip will be displayed when the user hovers over the cell.
2914
+ * The base implementation returns undefined (no tooltip) and should be overridden by
2915
+ * subclasses that support tooltips.
2916
+ *
2917
+ * @param {number} _rowIndex - The index of the row
2918
+ * @param {number} _columnIndex - The index of the column
2919
+ * @returns {any} The tooltip content (usually a string)
2920
+ *
2921
+ * @example
2922
+ * // Override in a subclass to provide tooltips
2923
+ * getTooltipAt(rowIndex: number, columnIndex: number): any {
2924
+ * // Use the cell value as the tooltip
2925
+ * return this.getValueAt(rowIndex, columnIndex);
2926
+ *
2927
+ * // Or provide a more detailed tooltip
2928
+ * // const value = this.getValueAt(rowIndex, columnIndex);
2929
+ * // return `Value: ${value}\nRow: ${rowIndex}\nColumn: ${columnIndex}`;
2930
+ * }
2931
+ */
2267
2932
  getTooltipAt(e, r) {
2268
2933
  }
2934
+ /**
2935
+ * Returns the value of the cell at the specified row and column indices.
2936
+ * This is one of the most important methods in the area model, as it provides
2937
+ * the actual data to be displayed in each cell.
2938
+ * The base implementation returns undefined and should be overridden by
2939
+ * all subclasses.
2940
+ *
2941
+ * @param {number} _rowIndex - The index of the row
2942
+ * @param {number} _columnIndex - The index of the column
2943
+ * @returns {any} The value at the specified cell
2944
+ *
2945
+ * @example
2946
+ * // Override in a subclass for a 2D array model
2947
+ * getValueAt(rowIndex: number, columnIndex: number): any {
2948
+ * if (rowIndex < 0 || rowIndex >= this.data.length) return undefined;
2949
+ * const row = this.data[rowIndex];
2950
+ * if (columnIndex < 0 || columnIndex >= row.length) return undefined;
2951
+ * return row[columnIndex];
2952
+ * }
2953
+ *
2954
+ * @example
2955
+ * // Override in a subclass for an object array model
2956
+ * getValueAt(rowIndex: number, columnIndex: number): any {
2957
+ * const row = this.getRowByIndex(rowIndex);
2958
+ * if (!row) return undefined;
2959
+ *
2960
+ * const property = this.columnDefs[columnIndex].property;
2961
+ * return row[property];
2962
+ * }
2963
+ */
2269
2964
  getValueAt(e, r) {
2270
2965
  }
2966
+ /**
2967
+ * Returns a string representation of the cell value at the specified row and column indices.
2968
+ * This method is used when exporting the table data or copying to clipboard.
2969
+ * The base implementation returns an empty string and should be overridden by
2970
+ * subclasses that need custom text conversion.
2971
+ *
2972
+ * @param {number} _rowIndex - The index of the row
2973
+ * @param {number} _columnIndex - The index of the column
2974
+ * @returns {string} The text value of the specified cell
2975
+ *
2976
+ * @example
2977
+ * // Override in a subclass to provide text representation
2978
+ * getTextValueAt(rowIndex: number, columnIndex: number): string {
2979
+ * const value = this.getValueAt(rowIndex, columnIndex);
2980
+ *
2981
+ * // Handle different data types appropriately
2982
+ * if (value === null || value === undefined) return '';
2983
+ * if (value instanceof Date) return value.toISOString();
2984
+ * return String(value);
2985
+ * }
2986
+ */
2271
2987
  getTextValueAt(e, r) {
2272
2988
  return "";
2273
2989
  }
2990
+ /**
2991
+ * Returns the Y-coordinate (in pixels) of the top of the row at the specified index.
2992
+ * This method is used for scrolling and positioning rows in the viewport.
2993
+ * The base implementation returns 0 and should be overridden by
2994
+ * subclasses that support scrolling.
2995
+ *
2996
+ * @param {number} _rowIndex - The index of the row
2997
+ * @returns {number} The Y-coordinate of the top of the row, in pixels
2998
+ *
2999
+ * @example
3000
+ * // Override in a subclass with fixed row heights
3001
+ * getYPosByRowIndex(rowIndex: number): number {
3002
+ * return rowIndex * this.defaultRowHeight;
3003
+ * }
3004
+ *
3005
+ * @example
3006
+ * // Override in a subclass with variable row heights
3007
+ * getYPosByRowIndex(rowIndex: number): number {
3008
+ * // Use a pre-calculated array of Y-positions
3009
+ * return this.yPositions[rowIndex];
3010
+ *
3011
+ * // Or calculate on-the-fly
3012
+ * // let yPos = 0;
3013
+ * // for (let i = 0; i < rowIndex; i++) {
3014
+ * // yPos += this.getRowHeight(i);
3015
+ * // }
3016
+ * // return yPos;
3017
+ * }
3018
+ */
2274
3019
  getYPosByRowIndex(e) {
2275
3020
  return 0;
2276
3021
  }
3022
+ /**
3023
+ * Initializes the area model.
3024
+ * This method is called internally by the TableModel during initialization.
3025
+ * It can be used to perform any necessary setup, such as calculating row positions.
3026
+ * The base implementation does nothing and can be overridden by
3027
+ * subclasses that need initialization.
3028
+ *
3029
+ * @returns {void}
3030
+ *
3031
+ * @example
3032
+ * // Override in a subclass to perform initialization
3033
+ * init(): void {
3034
+ * // Calculate y-positions for all rows
3035
+ * this.yPositions = [];
3036
+ * let currentY = 0;
3037
+ *
3038
+ * for (let i = 0; i < this.getRowCount(); i++) {
3039
+ * this.yPositions[i] = currentY;
3040
+ * currentY += this.getRowHeight(i);
3041
+ * }
3042
+ * }
3043
+ */
2277
3044
  init() {
2278
3045
  }
3046
+ /**
3047
+ * Determines whether the cell at the specified row and column indices is editable.
3048
+ * If true, the user can edit the cell content.
3049
+ * The base implementation returns false (not editable) and should be overridden by
3050
+ * subclasses that support cell editing.
3051
+ *
3052
+ * @param {number} _rowIndex - The index of the row
3053
+ * @param {number} _columnIndex - The index of the column
3054
+ * @returns {boolean} True if the cell is editable, false otherwise
3055
+ *
3056
+ * @example
3057
+ * // Override in a subclass to implement cell editability
3058
+ * isEditable(rowIndex: number, columnIndex: number): boolean {
3059
+ * // Header cells are not editable
3060
+ * if (this.areaIdent === 'header') return false;
3061
+ *
3062
+ * // First column is not editable (e.g., ID column)
3063
+ * if (columnIndex === 0) return false;
3064
+ *
3065
+ * // Other cells in the body are editable
3066
+ * return this.areaIdent === 'body';
3067
+ * }
3068
+ */
2279
3069
  isEditable(e, r) {
2280
3070
  return !1;
2281
3071
  }
3072
+ /**
3073
+ * Determines whether this area supports filtering.
3074
+ * If true, the area can be filtered using the externalFilterChanged method.
3075
+ * The base implementation returns false (not filterable) and should be overridden by
3076
+ * subclasses that support filtering.
3077
+ *
3078
+ * @returns {boolean} True if the area is filterable, false otherwise
3079
+ *
3080
+ * @example
3081
+ * // Override in a subclass to enable filtering
3082
+ * isFilterable(): boolean {
3083
+ * // Only the body area is filterable
3084
+ * return this.areaIdent === 'body';
3085
+ * }
3086
+ */
2282
3087
  isFilterable() {
2283
3088
  return !1;
2284
3089
  }
3090
+ /**
3091
+ * Determines whether the row at the specified index is checkable.
3092
+ * If true, a checkbox will be rendered at the beginning of the row.
3093
+ * The base implementation returns false (not checkable) and should be overridden by
3094
+ * subclasses that support row selection.
3095
+ *
3096
+ * @param {number} _rowIndex - The index of the row
3097
+ * @returns {boolean} True if the row is checkable, false otherwise
3098
+ *
3099
+ * @example
3100
+ * // Override in a subclass to implement row checkability
3101
+ * isRowCheckable(rowIndex: number): boolean {
3102
+ * // All rows in the body are checkable
3103
+ * if (this.areaIdent !== 'body') return false;
3104
+ *
3105
+ * // Except for special rows
3106
+ * const row = this.getRowByIndex(rowIndex);
3107
+ * return row && !row.locked;
3108
+ * }
3109
+ */
2285
3110
  isRowCheckable(e) {
2286
3111
  return !1;
2287
3112
  }
3113
+ /**
3114
+ * Returns the checked state of the row at the specified index.
3115
+ * The base implementation returns undefined (not checked) and should be overridden by
3116
+ * subclasses that support row selection.
3117
+ *
3118
+ * @param {number} _rowIndex - The index of the row
3119
+ * @returns {CheckedType | undefined} The checked state of the row (true, false, or 'indeterminate'),
3120
+ * or undefined if the row is not checkable
3121
+ *
3122
+ * @example
3123
+ * // Override in a subclass to implement row checked state
3124
+ * isRowChecked(rowIndex: number): CheckedType | undefined {
3125
+ * if (!this.rowSelectionModel) return undefined;
3126
+ *
3127
+ * const row = this.getRowByIndex(rowIndex);
3128
+ * return this.rowSelectionModel.isRowChecked(row);
3129
+ * }
3130
+ */
2288
3131
  isRowChecked(e) {
2289
3132
  }
3133
+ /**
3134
+ * Determines whether the cell at the specified row and column indices is selectable.
3135
+ * If true, the user can select the cell.
3136
+ * The base implementation returns false (not selectable) and should be overridden by
3137
+ * subclasses that support cell selection.
3138
+ *
3139
+ * @param {number} _rowIndex - The index of the row
3140
+ * @param {number} _columnIndex - The index of the column
3141
+ * @returns {boolean} True if the cell is selectable, false otherwise
3142
+ *
3143
+ * @example
3144
+ * // Override in a subclass to implement cell selectability
3145
+ * isSelectable(rowIndex: number, columnIndex: number): boolean {
3146
+ * // All cells in the body are selectable
3147
+ * return this.areaIdent === 'body';
3148
+ * }
3149
+ */
2290
3150
  isSelectable(e, r) {
2291
3151
  return !1;
2292
3152
  }
3153
+ /**
3154
+ * Sets the checked state of the row at the specified index.
3155
+ * The base implementation does nothing and should be overridden by
3156
+ * subclasses that support row selection.
3157
+ *
3158
+ * @param {number} _rowIndex - The index of the row
3159
+ * @param {boolean} _checked - The new checked state
3160
+ * @returns {void}
3161
+ *
3162
+ * @example
3163
+ * // Override in a subclass to implement row checking
3164
+ * setRowChecked(rowIndex: number, checked: boolean): void {
3165
+ * if (!this.rowSelectionModel) return;
3166
+ *
3167
+ * const row = this.getRowByIndex(rowIndex);
3168
+ * if (row) {
3169
+ * this.rowSelectionModel.checkRow(row, checked);
3170
+ * }
3171
+ * }
3172
+ */
2293
3173
  setRowChecked(e, r) {
2294
3174
  }
3175
+ /**
3176
+ * Sets the value of a cell at the specified row and column indices.
3177
+ * This method is called when a cell is edited by the user or programmatically.
3178
+ * The base implementation returns false (value not set) and should be overridden by
3179
+ * subclasses that support cell editing.
3180
+ *
3181
+ * @param {number} _rowIndex - The index of the row containing the cell
3182
+ * @param {number} _columnIndex - The index of the column containing the cell
3183
+ * @param {any} _value - The new value to set
3184
+ * @returns {boolean} - True if the value was successfully set, false otherwise
3185
+ *
3186
+ * @example
3187
+ * // Override in a subclass to implement cell value setting
3188
+ * setValue(rowIndex: number, columnIndex: number, value: any): boolean {
3189
+ * // Check if the cell is editable
3190
+ * if (!this.isEditable(rowIndex, columnIndex)) return false;
3191
+ *
3192
+ * // For a 2D array model
3193
+ * if (rowIndex >= 0 && rowIndex < this.data.length) {
3194
+ * const row = this.data[rowIndex];
3195
+ * if (columnIndex >= 0 && columnIndex < row.length) {
3196
+ * row[columnIndex] = value;
3197
+ * return true;
3198
+ * }
3199
+ * }
3200
+ *
3201
+ * return false;
3202
+ * }
3203
+ */
2295
3204
  setValue(e, r, a) {
2296
3205
  return !1;
2297
3206
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guiexpert/demo-table-models",
3
- "version": "1.1.78",
3
+ "version": "1.1.80",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -8,7 +8,9 @@
8
8
  "entryFile": "src/index.ts"
9
9
  },
10
10
  "publishConfig": {
11
- "directory": "dist"
11
+ "directory": "dist",
12
+ "registry": "https://registry.npmjs.org/",
13
+ "access": "public"
12
14
  },
13
15
  "exports": {
14
16
  ".": {
@@ -18,7 +20,7 @@
18
20
  },
19
21
  "dependencies": {
20
22
  "tslib": "^2.3.0",
21
- "@guiexpert/table": "^1.1.78"
23
+ "@guiexpert/table": "^1.1.80"
22
24
  },
23
25
  "devDependencies": {
24
26
  "@types/node": "^20.11.17",