@guiexpert/table 1.1.105 → 1.1.106

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,10 @@
1
+ /**
2
+ * macOS or not – the one place where the table asks for the platform (⌘ shortcuts, ⌥+letter types text,
3
+ * `aria-keyshortcuts`). Reads `navigator.platform` ("MacIntel", also iPadOS Safari with a keyboard); without a
4
+ * `navigator` (SSR, Node) `false`. Tests switch the platform here with `vi.spyOn(navigator, "platform", "get")`.
5
+ *
6
+ * `navigator.userAgentData.platform` is not used on purpose: only Chromium has it, and the result would be the same.
7
+ *
8
+ * @internal
9
+ */
10
+ export declare function isMacPlatform(): boolean;
@@ -7,7 +7,22 @@ import { SortItem } from '../../common/sort-item.js';
7
7
  import { AreaIdent } from '../area-ident.type.js';
8
8
  import { SorterService } from '../../../service/sorter.service.js';
9
9
 
10
- /** @category Area models */
10
+ /**
11
+ * Body of a cover grid: `filteredItems[row * columns + column]` is the item of a tile (`getValueAt`), `columns` =
12
+ * `floor(width / coverWidth)`. `items` = all items, `filteredItems` = shown items (filter and `sort()` work on it).
13
+ * Change `coverWidth`/`coverHeight` or the items and call `tableApi.repaintHard()`.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * declare const grid: CoverGridTableModel<string>;
18
+ * const tiles = grid.bodyModel;
19
+ * tiles.items = ["new-1.jpg", "new-2.jpg"];
20
+ * tiles.filteredItems = tiles.items; // or tableApi.externalFilterChanged() with a filter
21
+ * tableApi.repaintHard();
22
+ * ```
23
+ *
24
+ * @category Area models
25
+ */
11
26
  export declare class CoverGridBodyModel<T> implements AreaModelIf {
12
27
  items: T[];
13
28
  cellRenderer: CellRendererIf;
@@ -9,7 +9,20 @@ import { ColumnDefIf } from './column/column-def.if.js';
9
9
  import { Padding } from './padding.js';
10
10
  import { SelectionModelIf } from '../../selection/selection-model.if.js';
11
11
 
12
- /** @category Table model */
12
+ /**
13
+ * Table model of a cover grid (created by {@link CoverGridFactory.createCoverGridModel}): items as tiles, the number of
14
+ * columns follows the width (`floor(width / coverWidth)`), header and footer are hidden. The data and the tile size
15
+ * live in {@link CoverGridBodyModel} (`tableModel.bodyModel`).
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * declare const grid: CoverGridTableModel<{ title: string }>;
20
+ * const columns = grid.getColumnCount();
21
+ * tableApi.scrollToIndex(0, Math.floor(500 / columns)); // the row of item 500
22
+ * ```
23
+ *
24
+ * @category Table model
25
+ */
13
26
  export declare class CoverGridTableModel<T> implements TableModelIf {
14
27
  bodyModel: CoverGridBodyModel<T>;
15
28
  paddingTop: number;
@@ -39,6 +52,7 @@ export declare class CoverGridTableModel<T> implements TableModelIf {
39
52
  setColumnWidth(_columnIndex: number, width: number): void;
40
53
  recalcSize(_clientWidth: number): void;
41
54
  recalcPadding(): void;
55
+ /** No-op: the height follows from the item count, the column count and `coverHeight` – `repaintHard()` is enough. */
42
56
  recalcHeightAndPadding(): void;
43
57
  getPadding(): Padding;
44
58
  getContentHeightInPixel(): number;
@@ -2,8 +2,73 @@ import { CoverGridTableModel } from '../data/tablemodel/cover-grid-table-model.j
2
2
  import { CellRendererIf } from '../renderer/cell-render.if.js';
3
3
  import { TableOptionsIf } from '../data/options/table-options.if.js';
4
4
 
5
- /** @category Table model */
5
+ /**
6
+ * Creates cover grids: a flat array of items shown as tiles (book covers, photos, products) – as many per row as fit
7
+ * into the width of the table (`floor(width / coverWidth)`), without header and footer. Only the visible rows are
8
+ * rendered, like in every GuiExpert Table; filter (`externalFilterFunction`), `sort()` and the scroll position work as
9
+ * usual. Guide: instructions.md 5.10, showcase https://gui.expert/showcase/covergrid/run.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * interface Book { title: string; }
14
+ * declare const books: Book[];
15
+ *
16
+ * const renderer: CellRendererIf = {
17
+ * render(cellDiv: HTMLDivElement, _r: number, _c: number, _a: AreaIdent, _m: AreaModelIf, book: any) {
18
+ * if (book) cellDiv.textContent = (book as Book).title; // the item of this tile (undefined after the last one)
19
+ * return undefined;
20
+ * }
21
+ * };
22
+ * const gridModel = CoverGridFactory.createCoverGridModel(books, renderer, 160, 240);
23
+ * const gridOptions = CoverGridFactory.createCoverGrisDefaultOptions(240, () => "books");
24
+ * const gridApi = new TableScope(host, gridModel, new SimpleDomService(), gridOptions, new EventAdapter())
25
+ * .firstInit()
26
+ * .getApi();
27
+ * ```
28
+ *
29
+ * @category Table model
30
+ */
6
31
  export declare class CoverGridFactory {
32
+ /**
33
+ * Creates the model of a cover grid.
34
+ *
35
+ * @param items - the items, one per tile (the renderer gets the item as `cellValue`)
36
+ * @param cellRenderer - draws one tile into the cell `<div>`
37
+ * @param coverWidth - width of a tile in px (default 200) – change it later via `bodyModel.coverWidth` + `repaintHard()`
38
+ * @param coverHeight - height of a tile in px (default 300)
39
+ * @param width - initial width of the grid; the table sets the width of its host on start and after a resize
40
+ * @param firstRowPaddingTop - extra height of the first row in px (room above the first tiles, e.g. for a toolbar)
41
+ * @returns the table model; `tableModel.bodyModel` holds `items`, `filteredItems`, `coverWidth`, `coverHeight`
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * declare const renderer: CellRendererIf;
46
+ * const gridModel = CoverGridFactory.createCoverGridModel(["a.jpg", "b.jpg", "c.jpg"], renderer, 120, 180);
47
+ * // bigger tiles – no new model:
48
+ * gridModel.bodyModel.coverWidth = 200;
49
+ * gridModel.bodyModel.coverHeight = 300;
50
+ * tableApi.repaintHard();
51
+ * ```
52
+ */
7
53
  static createCoverGridModel<T>(items: T[], cellRenderer: CellRendererIf, coverWidth?: number, coverHeight?: number, width?: number, firstRowPaddingTop?: number): CoverGridTableModel<T>;
54
+ /**
55
+ * Options for a cover grid: no borders and separators, no row or column hover, header and footer height 0, and the
56
+ * scroll position restored under the key of `getStorageKeyFn` (`localStorage`). (The name has a typo – kept for
57
+ * compatibility.)
58
+ *
59
+ * @param defaultRowHeight - the height of a tile (`coverHeight`)
60
+ * @param getStorageKeyFn - storage key of the scroll position (default `"CoverGrid"`)
61
+ * @returns new options – add your own fields with a spread
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * let photoFilter = "";
66
+ * const gridOptions: TableOptionsIf = {
67
+ * ...CoverGridFactory.createCoverGrisDefaultOptions(240, () => "photos"),
68
+ * externalFilterFunction: (photo: { name: string }) => photo.name.includes(photoFilter),
69
+ * shortcutActionsDisabled: true
70
+ * };
71
+ * ```
72
+ */
8
73
  static createCoverGrisDefaultOptions(defaultRowHeight: number, getStorageKeyFn?: () => string): TableOptionsIf;
9
74
  }
@@ -27,6 +27,10 @@ export declare class MouseHandler {
27
27
  private mouseDown;
28
28
  private repaintAfterMouseUp;
29
29
  private dragging;
30
+ /** Counts the drags: a frame callback of a drag that is over (a new one started) does nothing. */
31
+ private dragGeneration;
32
+ /** The end of the last drag, until its frame ran – a new mousedown handles it at once (see {@link flushDraggingEnd}). */
33
+ private pendingDraggingEnd?;
30
34
  constructor(tableScope: TableScope);
31
35
  /**
32
36
  * Handles the "contextmenu" event.
@@ -76,7 +80,8 @@ export declare class MouseHandler {
76
80
  private onMouseMove;
77
81
  private onMouseUp;
78
82
  private mouseDraggingOnFrame;
79
- private mouseDraggingEndOnFrame;
83
+ /** Handles the end of the last drag now (in its frame, or earlier when the next mousedown comes first). */
84
+ private flushDraggingEnd;
80
85
  private mouseMoveOnFrame;
81
86
  /** A mouse event on a blocking loading overlay ({@link TableOverlay.isEventBlocked}): the table ignores it. */
82
87
  private isBlocked;
@@ -17,6 +17,8 @@ import { ValueLabelIf } from '../../data/common/value-label.if.js';
17
17
  export declare class SelectCellEditor implements CellEditorIf {
18
18
  protected readonly options: ValueLabelIf[];
19
19
  private select?;
20
+ /** The text of the cell when the editor opened: "nothing chosen" counts as unchanged (since 1.1.106). */
21
+ private startText;
20
22
  private readonly abort;
21
23
  constructor(options: ValueLabelIf[]);
22
24
  /**
@@ -28,6 +30,12 @@ export declare class SelectCellEditor implements CellEditorIf {
28
30
  static create(values: string[]): SelectCellEditor;
29
31
  open(container: HTMLDivElement, ctx: CellEditorContextIf): void;
30
32
  getValue(): unknown;
33
+ /**
34
+ * The chosen value as text; with nothing chosen (the cell's value is not in the list) the start text, so that
35
+ * Enter without a choice writes nothing (before 1.1.106 it emptied the cell).
36
+ *
37
+ * @returns {string} the text
38
+ */
31
39
  getText(): string;
32
40
  focus(): void;
33
41
  getFocusElement(): HTMLElement | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guiexpert/table",
3
- "version": "1.1.105",
3
+ "version": "1.1.106",
4
4
  "license": "MIT",
5
5
  "author": "Dr. Marc Kronberg <info@gui.expert> (https://gui.expert)",
6
6
  "repository": {