@guiexpert/demo-table-models 1.1.107 → 1.1.108

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,17 @@
1
+ import { AreaIdent, AreaModelIf, CellRendererIf, DomServiceIf, RendererCleanupFnType, TableModelAndOptionsIf } from '@guiexpert/table';
2
+ import { LogLineIf } from '../../model/log-line.if.js';
3
+
4
+ /** The level of a log line as a small badge: class `ge-log-level ge-log-level-error` … (text, never HTML). */
5
+ export declare class LogLevelCellRenderer implements CellRendererIf {
6
+ render(cellDiv: HTMLDivElement, _rowIndex: number, _columnIndex: number, _areaIdent: AreaIdent, _areaModel: AreaModelIf, cellValue: unknown, domService: DomServiceIf): RendererCleanupFnType | undefined;
7
+ }
8
+ /**
9
+ * A log viewer table (live data, since 1.1.108): #, time, level (badge), source, message; 24 px rows, range
10
+ * selection, cell focus. Feed it with `tableApi.appendRows(lines, { follow: "auto", maxRows })` or the
11
+ * {@link LogTailController}.
12
+ *
13
+ * CSS for the level badges (not part of the table CSS): `.ge-log-level-error { color: … }` – see the showcase.
14
+ *
15
+ * @param lines - the first lines (default none) – the table appends to this array
16
+ */
17
+ export declare function createLogTailModelAndOptions(lines?: LogLineIf[]): TableModelAndOptionsIf;
@@ -0,0 +1,24 @@
1
+ import { LogLineIf } from '../../model/log-line.if.js';
2
+
3
+ /**
4
+ * Generates log lines with a fixed seed – the same seed gives the same lines (live data demos, since 1.1.108).
5
+ * Levels: ~70 % INFO, 15 % DEBUG, 10 % WARN, 5 % ERROR; the time advances by `msPerLine`.
6
+ *
7
+ * @example
8
+ * const generator = new LogGenerator(42);
9
+ * const lines = generator.next(500);
10
+ */
11
+ export declare class LogGenerator {
12
+ private readonly msPerLine;
13
+ private seed;
14
+ private nextId;
15
+ private timeMs;
16
+ constructor(seed?: number, startTimeMs?: number, msPerLine?: number);
17
+ /** The next `count` lines. */
18
+ next(count: number): LogLineIf[];
19
+ /** Number of lines generated so far. */
20
+ getCount(): number;
21
+ private line;
22
+ /** mulberry32 */
23
+ private random;
24
+ }
@@ -0,0 +1,100 @@
1
+ import { AppendRowsResultIf, TableApi } from '@guiexpert/table';
2
+ import { LogLineIf } from '../../model/log-line.if.js';
3
+
4
+ /** Numbers of a running {@link LogTailController} – reported about four times per second. */
5
+ export interface LogTailStatsIf {
6
+ /** lines generated so far */
7
+ totalLines: number;
8
+ /** lines in the table now (ring buffer) */
9
+ rowCount: number;
10
+ /** lines per second (measured) */
11
+ linesPerSecond: number;
12
+ /** animation frames per second */
13
+ fps: number;
14
+ /** median time of `appendRows` incl. its render pass over the last second, ms */
15
+ msPerUpdate: number;
16
+ /** lines that came in below the view while it did not follow ("+N new lines") */
17
+ newBelow: number;
18
+ /** lines waiting while the intake is paused */
19
+ pending: number;
20
+ frozen: boolean;
21
+ intakePaused: boolean;
22
+ following: boolean;
23
+ }
24
+ export interface LogTailControllerOptionsIf {
25
+ /** lines per second, default 500 */
26
+ rate?: number;
27
+ /** ring buffer size, default 1,000,000 */
28
+ maxRows?: number;
29
+ /** seed of the {@link LogGenerator}, default 42 */
30
+ seed?: number;
31
+ /** called about four times per second */
32
+ onStats?: (stats: LogTailStatsIf) => void;
33
+ /** where the lines come from (default: a {@link LogGenerator}) */
34
+ source?: (count: number) => LogLineIf[];
35
+ }
36
+ /**
37
+ * Drives a live log table (since 1.1.108) – the shared logic of the showcase `logtail`, `apps/table-demo/log-tail.html`
38
+ * and the specs. Per animation frame: the lines that are due at `rate` go to a buffer, then **one**
39
+ * `tableApi.appendRows(buffer, { follow, maxRows })`.
40
+ *
41
+ * - **Freeze scroll** (`setFreezeScroll(true)`): `follow: false` – the view stays where it is, even at the end; lines keep
42
+ * coming ("+N new lines").
43
+ * - **Scroll to end** (`scrollToEnd()`): unfreezes and jumps to the end; from then on `follow: "auto"` follows again –
44
+ * also when the user scrolls to the end by hand.
45
+ * - **Pause intake** (`setIntakePaused(true)`): the app pattern "freeze" – lines are collected, nothing is appended;
46
+ * unpausing appends the whole block at once.
47
+ *
48
+ * @example
49
+ * const live = new LogTailController(tableApi, { rate: 5_000, maxRows: 1_000_000, onStats: s => show(s) });
50
+ * live.start();
51
+ * freezeButton.onclick = () => live.setFreezeScroll(!live.isFrozen());
52
+ * endButton.onclick = () => live.scrollToEnd();
53
+ */
54
+ export declare class LogTailController {
55
+ private readonly tableApi;
56
+ private readonly options;
57
+ private readonly generator;
58
+ private readonly source;
59
+ private rate;
60
+ private readonly maxRows;
61
+ private readonly pending;
62
+ private frozen;
63
+ private intakePaused;
64
+ private following;
65
+ private newBelow;
66
+ private running;
67
+ private frameId;
68
+ private lastTime;
69
+ private due;
70
+ private statsStart;
71
+ private statsFrames;
72
+ private statsLines;
73
+ private statsTimes;
74
+ private lastStats?;
75
+ constructor(tableApi: TableApi, options?: LogTailControllerOptionsIf);
76
+ /** Starts the frame loop. */
77
+ start(): void;
78
+ /** Stops the frame loop (lines in the buffer stay). */
79
+ stop(): void;
80
+ isRunning(): boolean;
81
+ /** Lines per second. */
82
+ setRate(linesPerSecond: number): void;
83
+ getRate(): number;
84
+ /** Freeze scroll: the view stays where it is, lines keep coming. */
85
+ setFreezeScroll(frozen: boolean): void;
86
+ isFrozen(): boolean;
87
+ /** Pause intake (app pattern "freeze"): lines are buffered and appended as one block when unpaused. */
88
+ setIntakePaused(paused: boolean): void;
89
+ isIntakePaused(): boolean;
90
+ /** Unfreezes and jumps to the end – the view follows again. */
91
+ scrollToEnd(): void;
92
+ /** Appends the buffered lines now (one `appendRows`) – also used by the frame loop. */
93
+ flush(): AppendRowsResultIf | false | undefined;
94
+ /** Adds lines from outside (e.g. a WebSocket) – appended with the next frame. */
95
+ push(lines: LogLineIf[]): void;
96
+ /** The latest numbers (also passed to `onStats`). */
97
+ getStats(): LogTailStatsIf;
98
+ private frame;
99
+ private createStats;
100
+ }
@@ -0,0 +1,11 @@
1
+ /** One line of a log file (live data demos, since 1.1.108). */
2
+ export interface LogLineIf {
3
+ /** running number, unique */
4
+ id: number;
5
+ /** "HH:MM:SS.mmm" */
6
+ time: string;
7
+ level: "DEBUG" | "INFO" | "WARN" | "ERROR";
8
+ /** the service that wrote the line */
9
+ source: string;
10
+ text: string;
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guiexpert/demo-table-models",
3
- "version": "1.1.107",
3
+ "version": "1.1.108",
4
4
  "license": "MIT",
5
5
  "author": "Dr. Marc Kronberg <info@gui.expert> (https://gui.expert)",
6
6
  "repository": {
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "tslib": "^2.3.0",
34
- "@guiexpert/table": "^1.1.107"
34
+ "@guiexpert/table": "^1.1.108"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "^20.11.17",