@squawk/adsbtop 0.2.0 → 0.3.0

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 (74) hide show
  1. package/README.md +14 -2
  2. package/package.json +6 -6
  3. package/dist/aircraft-state.d.ts +0 -77
  4. package/dist/aircraft-state.d.ts.map +0 -1
  5. package/dist/aircraft-state.js +0 -87
  6. package/dist/app.d.ts +0 -41
  7. package/dist/app.d.ts.map +0 -1
  8. package/dist/app.js +0 -166
  9. package/dist/cli-args.d.ts +0 -43
  10. package/dist/cli-args.d.ts.map +0 -1
  11. package/dist/cli-args.js +0 -150
  12. package/dist/cli.d.ts +0 -3
  13. package/dist/cli.d.ts.map +0 -1
  14. package/dist/cli.js +0 -17
  15. package/dist/columns.d.ts +0 -84
  16. package/dist/columns.d.ts.map +0 -1
  17. package/dist/columns.js +0 -203
  18. package/dist/components/aircraft-table.d.ts +0 -27
  19. package/dist/components/aircraft-table.d.ts.map +0 -1
  20. package/dist/components/aircraft-table.js +0 -83
  21. package/dist/components/detail-view.d.ts +0 -20
  22. package/dist/components/detail-view.d.ts.map +0 -1
  23. package/dist/components/detail-view.js +0 -14
  24. package/dist/components/help-overlay.d.ts +0 -4
  25. package/dist/components/help-overlay.d.ts.map +0 -1
  26. package/dist/components/help-overlay.js +0 -22
  27. package/dist/components/hotkey-bar.d.ts +0 -21
  28. package/dist/components/hotkey-bar.d.ts.map +0 -1
  29. package/dist/components/hotkey-bar.js +0 -28
  30. package/dist/components/messages-panel.d.ts +0 -27
  31. package/dist/components/messages-panel.d.ts.map +0 -1
  32. package/dist/components/messages-panel.js +0 -17
  33. package/dist/components/search-bar.d.ts +0 -19
  34. package/dist/components/search-bar.d.ts.map +0 -1
  35. package/dist/components/search-bar.js +0 -13
  36. package/dist/components/status-header.d.ts +0 -17
  37. package/dist/components/status-header.d.ts.map +0 -1
  38. package/dist/components/status-header.js +0 -14
  39. package/dist/create-feed.d.ts +0 -33
  40. package/dist/create-feed.d.ts.map +0 -1
  41. package/dist/create-feed.js +0 -40
  42. package/dist/detail-fields.d.ts +0 -23
  43. package/dist/detail-fields.d.ts.map +0 -1
  44. package/dist/detail-fields.js +0 -68
  45. package/dist/format.d.ts +0 -91
  46. package/dist/format.d.ts.map +0 -1
  47. package/dist/format.js +0 -138
  48. package/dist/location.d.ts +0 -20
  49. package/dist/location.d.ts.map +0 -1
  50. package/dist/location.js +0 -29
  51. package/dist/registration-cache.d.ts +0 -23
  52. package/dist/registration-cache.d.ts.map +0 -1
  53. package/dist/registration-cache.js +0 -24
  54. package/dist/search.d.ts +0 -27
  55. package/dist/search.d.ts.map +0 -1
  56. package/dist/search.js +0 -54
  57. package/dist/selection.d.ts +0 -25
  58. package/dist/selection.d.ts.map +0 -1
  59. package/dist/selection.js +0 -38
  60. package/dist/sparkline.d.ts +0 -26
  61. package/dist/sparkline.d.ts.map +0 -1
  62. package/dist/sparkline.js +0 -62
  63. package/dist/status-line.d.ts +0 -28
  64. package/dist/status-line.d.ts.map +0 -1
  65. package/dist/status-line.js +0 -18
  66. package/dist/test-utils.d.ts +0 -23
  67. package/dist/test-utils.d.ts.map +0 -1
  68. package/dist/test-utils.js +0 -35
  69. package/dist/use-aircraft-feed.d.ts +0 -28
  70. package/dist/use-aircraft-feed.d.ts.map +0 -1
  71. package/dist/use-aircraft-feed.js +0 -68
  72. package/dist/use-icao-registry.d.ts +0 -27
  73. package/dist/use-icao-registry.d.ts.map +0 -1
  74. package/dist/use-icao-registry.js +0 -37
package/dist/columns.d.ts DELETED
@@ -1,84 +0,0 @@
1
- import type { Aircraft, Coordinates } from '@squawk/types';
2
- /** One column in the aircraft table. */
3
- export interface ColumnDef {
4
- /** Stable identifier for the column, also used as its React list key. */
5
- key: string;
6
- /** Column header text. */
7
- header: string;
8
- /** Fixed display width, in terminal columns. Headers and cells are padded/truncated to this. */
9
- width: number;
10
- /** Whether this column stays visible in compact mode (narrow terminals), toggled by the `[C]olumns` hotkey. */
11
- compact: boolean;
12
- /**
13
- * Renders one aircraft's value for this column.
14
- *
15
- * @param aircraft - The aircraft to render a cell for.
16
- * @param nowMs - The current time, for age-relative columns.
17
- */
18
- render: (aircraft: Aircraft, nowMs: number) => string;
19
- }
20
- /**
21
- * The aircraft table's columns, in display order. `compact: true` columns
22
- * are the reduced set shown on a narrow terminal; the rest are additionally
23
- * shown in the full-width layout. See {@link visibleColumns}.
24
- */
25
- export declare const COLUMNS: readonly ColumnDef[];
26
- /**
27
- * Builds the Dist column shown when a receiver location (`--lat`/`--lon`) is
28
- * configured. Not part of {@link COLUMNS} since its render function needs to
29
- * close over `location`.
30
- *
31
- * @param location - The configured receiver location.
32
- * @returns The Dist column definition.
33
- */
34
- export declare function buildDistanceColumn(location: Coordinates): ColumnDef;
35
- /**
36
- * Builds the Brg column shown when a receiver location (`--lat`/`--lon`) is
37
- * configured. Not part of {@link COLUMNS} since its render function needs to
38
- * close over `location`.
39
- *
40
- * @param location - The configured receiver location.
41
- * @returns The Brg column definition.
42
- */
43
- export declare function buildBearingColumn(location: Coordinates): ColumnDef;
44
- /**
45
- * Selects the columns to render for the current width mode, appending the
46
- * Dist/Brg columns when `location` is configured. Dist/Brg are omitted
47
- * entirely (not shown blank) without a configured location, and never shown
48
- * in compact mode regardless.
49
- *
50
- * @param compact - True to show only the columns marked `compact: true` (narrow terminal).
51
- * @param location - The configured receiver location, if any.
52
- * @returns The columns to render, in display order.
53
- */
54
- export declare function visibleColumns(compact: boolean, location?: Coordinates): readonly ColumnDef[];
55
- /** Table sort keys, in the order `[O]` cycles through them. */
56
- export type SortKey = 'icaoHex' | 'callsign' | 'altitude' | 'groundSpeed' | 'age';
57
- /**
58
- * Advances to the next sort key in the fixed cycle bound to the `[O]` hotkey.
59
- *
60
- * @param current - The active sort key.
61
- * @returns The next sort key in the cycle.
62
- */
63
- export declare function nextSortKey(current: SortKey): SortKey;
64
- /**
65
- * Compares two aircraft for ordering by `sortKey`. Aircraft missing the
66
- * sorted-on field always sort after aircraft that have it, regardless of
67
- * which key is active, so unknown values consistently sink to the bottom
68
- * instead of interleaving with real data.
69
- *
70
- * @param a - First aircraft to compare.
71
- * @param b - Second aircraft to compare.
72
- * @param sortKey - The field to compare on.
73
- * @returns A negative number if `a` sorts first, positive if `b` sorts first, zero if equivalent.
74
- */
75
- export declare function compareAircraft(a: Aircraft, b: Aircraft, sortKey: SortKey): number;
76
- /**
77
- * Returns a new array of `aircraft` sorted by `sortKey`. Does not mutate the input.
78
- *
79
- * @param aircraft - The aircraft to sort.
80
- * @param sortKey - The field to sort on.
81
- * @returns A new, sorted array.
82
- */
83
- export declare function sortAircraft(aircraft: readonly Aircraft[], sortKey: SortKey): Aircraft[];
84
- //# sourceMappingURL=columns.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"columns.d.ts","sourceRoot":"","sources":["../src/columns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAc3D,wCAAwC;AACxC,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAC;IACZ,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,gGAAgG;IAChG,KAAK,EAAE,MAAM,CAAC;IACd,+GAA+G;IAC/G,OAAO,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,MAAM,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACvD;AAED;;;;GAIG;AACH,eAAO,MAAM,OAAO,EAAE,SAAS,SAAS,EAuE9B,CAAC;AAEX;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,GAAG,SAAS,CAQpE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,WAAW,GAAG,SAAS,CAQnE;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,SAAS,SAAS,EAAE,CAM7F;AAED,+DAA+D;AAC/D,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,aAAa,GAAG,KAAK,CAAC;AAWlF;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAErD;AAOD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CA8BlF;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,QAAQ,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,QAAQ,EAAE,CAExF"}
package/dist/columns.js DELETED
@@ -1,203 +0,0 @@
1
- import { formatAltitude, formatAge, formatBearing, formatDistance, formatGroundSpeed, formatHeading, formatOnGround, formatVerticalRate, } from './format.js';
2
- import { bearingToAircraftDeg, distanceToAircraftNm } from './location.js';
3
- /**
4
- * The aircraft table's columns, in display order. `compact: true` columns
5
- * are the reduced set shown on a narrow terminal; the rest are additionally
6
- * shown in the full-width layout. See {@link visibleColumns}.
7
- */
8
- export const COLUMNS = [
9
- {
10
- key: 'icaoHex',
11
- header: 'ICAO',
12
- width: 6,
13
- compact: true,
14
- render: (aircraft) => aircraft.icaoHex,
15
- },
16
- {
17
- key: 'callsign',
18
- header: 'Callsign',
19
- width: 8,
20
- compact: true,
21
- render: (aircraft) => aircraft.callsign ?? '-',
22
- },
23
- {
24
- key: 'registration',
25
- header: 'Reg',
26
- width: 7,
27
- compact: false,
28
- render: (aircraft) => aircraft.registration?.registration ?? '-',
29
- },
30
- {
31
- key: 'squawk',
32
- header: 'Squawk',
33
- width: 6,
34
- compact: true,
35
- render: (aircraft) => aircraft.squawk ?? '-',
36
- },
37
- {
38
- key: 'altitude',
39
- header: 'Alt',
40
- width: 7,
41
- compact: true,
42
- render: (aircraft) => formatAltitude(aircraft),
43
- },
44
- {
45
- key: 'groundSpeed',
46
- header: 'GS',
47
- width: 6,
48
- compact: false,
49
- render: (aircraft) => formatGroundSpeed(aircraft),
50
- },
51
- {
52
- key: 'heading',
53
- header: 'Hdg',
54
- width: 5,
55
- compact: false,
56
- render: (aircraft) => formatHeading(aircraft),
57
- },
58
- {
59
- key: 'verticalRate',
60
- header: 'VS',
61
- width: 8,
62
- compact: false,
63
- render: (aircraft) => formatVerticalRate(aircraft),
64
- },
65
- {
66
- key: 'onGround',
67
- header: 'Grnd',
68
- width: 4,
69
- compact: false,
70
- render: (aircraft) => formatOnGround(aircraft),
71
- },
72
- {
73
- key: 'age',
74
- header: 'Age',
75
- width: 6,
76
- compact: true,
77
- render: (aircraft, nowMs) => formatAge(aircraft.lastSeenAt, nowMs),
78
- },
79
- ];
80
- /**
81
- * Builds the Dist column shown when a receiver location (`--lat`/`--lon`) is
82
- * configured. Not part of {@link COLUMNS} since its render function needs to
83
- * close over `location`.
84
- *
85
- * @param location - The configured receiver location.
86
- * @returns The Dist column definition.
87
- */
88
- export function buildDistanceColumn(location) {
89
- return {
90
- key: 'distance',
91
- header: 'Dist',
92
- width: 6,
93
- compact: false,
94
- render: (aircraft) => formatDistance(distanceToAircraftNm(location, aircraft)),
95
- };
96
- }
97
- /**
98
- * Builds the Brg column shown when a receiver location (`--lat`/`--lon`) is
99
- * configured. Not part of {@link COLUMNS} since its render function needs to
100
- * close over `location`.
101
- *
102
- * @param location - The configured receiver location.
103
- * @returns The Brg column definition.
104
- */
105
- export function buildBearingColumn(location) {
106
- return {
107
- key: 'bearing',
108
- header: 'Brg',
109
- width: 5,
110
- compact: false,
111
- render: (aircraft) => formatBearing(bearingToAircraftDeg(location, aircraft)),
112
- };
113
- }
114
- /**
115
- * Selects the columns to render for the current width mode, appending the
116
- * Dist/Brg columns when `location` is configured. Dist/Brg are omitted
117
- * entirely (not shown blank) without a configured location, and never shown
118
- * in compact mode regardless.
119
- *
120
- * @param compact - True to show only the columns marked `compact: true` (narrow terminal).
121
- * @param location - The configured receiver location, if any.
122
- * @returns The columns to render, in display order.
123
- */
124
- export function visibleColumns(compact, location) {
125
- const baseColumns = compact ? COLUMNS.filter((column) => column.compact) : COLUMNS;
126
- if (compact || location === undefined) {
127
- return baseColumns;
128
- }
129
- return [...baseColumns, buildDistanceColumn(location), buildBearingColumn(location)];
130
- }
131
- /** The sort key `[O]` switches to next, from the current one. */
132
- const NEXT_SORT_KEY = {
133
- icaoHex: 'callsign',
134
- callsign: 'altitude',
135
- altitude: 'groundSpeed',
136
- groundSpeed: 'age',
137
- age: 'icaoHex',
138
- };
139
- /**
140
- * Advances to the next sort key in the fixed cycle bound to the `[O]` hotkey.
141
- *
142
- * @param current - The active sort key.
143
- * @returns The next sort key in the cycle.
144
- */
145
- export function nextSortKey(current) {
146
- return NEXT_SORT_KEY[current];
147
- }
148
- /** Altitude used for sorting: barometric preferred, geometric fallback - mirrors {@link formatAltitude}'s precedence. */
149
- function sortAltitudeFt(aircraft) {
150
- return aircraft.position?.baroAltitudeFt ?? aircraft.position?.geoAltitudeFt;
151
- }
152
- /**
153
- * Compares two aircraft for ordering by `sortKey`. Aircraft missing the
154
- * sorted-on field always sort after aircraft that have it, regardless of
155
- * which key is active, so unknown values consistently sink to the bottom
156
- * instead of interleaving with real data.
157
- *
158
- * @param a - First aircraft to compare.
159
- * @param b - Second aircraft to compare.
160
- * @param sortKey - The field to compare on.
161
- * @returns A negative number if `a` sorts first, positive if `b` sorts first, zero if equivalent.
162
- */
163
- export function compareAircraft(a, b, sortKey) {
164
- switch (sortKey) {
165
- case 'icaoHex':
166
- return a.icaoHex.localeCompare(b.icaoHex);
167
- case 'callsign': {
168
- if (a.callsign === undefined || b.callsign === undefined) {
169
- return (a.callsign === undefined ? 1 : 0) - (b.callsign === undefined ? 1 : 0);
170
- }
171
- return a.callsign.localeCompare(b.callsign);
172
- }
173
- case 'altitude': {
174
- const altitudeA = sortAltitudeFt(a);
175
- const altitudeB = sortAltitudeFt(b);
176
- if (altitudeA === undefined || altitudeB === undefined) {
177
- return (altitudeA === undefined ? 1 : 0) - (altitudeB === undefined ? 1 : 0);
178
- }
179
- return altitudeA - altitudeB;
180
- }
181
- case 'groundSpeed': {
182
- if (a.groundSpeedKt === undefined || b.groundSpeedKt === undefined) {
183
- return (a.groundSpeedKt === undefined ? 1 : 0) - (b.groundSpeedKt === undefined ? 1 : 0);
184
- }
185
- return a.groundSpeedKt - b.groundSpeedKt;
186
- }
187
- case 'age':
188
- // Most-recently-seen (smallest age) first - equivalent to descending lastSeenAt.
189
- return b.lastSeenAt - a.lastSeenAt;
190
- default:
191
- return 0;
192
- }
193
- }
194
- /**
195
- * Returns a new array of `aircraft` sorted by `sortKey`. Does not mutate the input.
196
- *
197
- * @param aircraft - The aircraft to sort.
198
- * @param sortKey - The field to sort on.
199
- * @returns A new, sorted array.
200
- */
201
- export function sortAircraft(aircraft, sortKey) {
202
- return [...aircraft].sort((a, b) => compareAircraft(a, b, sortKey));
203
- }
@@ -1,27 +0,0 @@
1
- import type { ReactElement } from 'react';
2
- import type { Aircraft } from '@squawk/types';
3
- import type { ColumnDef, SortKey } from '../columns.js';
4
- /** Props for {@link AircraftTable}. */
5
- export interface AircraftTableProps {
6
- /** Aircraft to render, already sorted in display order. */
7
- aircraft: readonly Aircraft[];
8
- /** Columns to render, in display order. */
9
- columns: readonly ColumnDef[];
10
- /** Current time, passed through to age-relative column renderers. */
11
- nowMs: number;
12
- /** The column `aircraft` is currently sorted by - highlighted in the header row so the active sort is visible while cycling with `[O]`. */
13
- sortKey: SortKey;
14
- /** ICAO hex of the cursor row, moved with the arrow keys - highlighted with its own background. Undefined selects nothing. */
15
- selectedIcaoHex: string | undefined;
16
- }
17
- /**
18
- * The live-updating aircraft table: a header row followed by one row per
19
- * tracked aircraft. Rows squawking a declared emergency code render in bold
20
- * red - see {@link isEmergencySquawk}. The active sort column's header is
21
- * highlighted - see {@link AircraftTableProps.sortKey}. The cursor row is
22
- * highlighted separately - see {@link AircraftTableProps.selectedIcaoHex}.
23
- *
24
- * @param props - The aircraft, columns, active sort key, selected row, and current time to render.
25
- */
26
- export declare function AircraftTable(props: AircraftTableProps): ReactElement;
27
- //# sourceMappingURL=aircraft-table.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"aircraft-table.d.ts","sourceRoot":"","sources":["../../src/components/aircraft-table.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAcxD,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,QAAQ,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC9B,2CAA2C;IAC3C,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,2IAA2I;IAC3I,OAAO,EAAE,OAAO,CAAC;IACjB,8HAA8H;IAC9H,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AA4HD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,YAAY,CAmCrE"}
@@ -1,83 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- import { Fragment } from 'react';
4
- import { isEmergencySquawk } from '../format.js';
5
- /**
6
- * Width of the header row's `|` column separator (a space, the pipe, and
7
- * another space - see {@link HeaderSeparator}). `AircraftCell`'s
8
- * `marginRight` is derived from this so a data row's column gap always
9
- * matches the header's separator width - the two are visually the same
10
- * column boundary and would drift out of alignment if their widths could
11
- * diverge. Keep this in sync with `HeaderSeparator`'s own rendered width if
12
- * that ever changes.
13
- */
14
- const HEADER_SEPARATOR_WIDTH = ' | '.length;
15
- /**
16
- * Renders one column header cell. The header row shares one continuous blue
17
- * background (set on the row `Box` in {@link AircraftTable}) which this
18
- * inherits by default; the active sort column's `Box` overrides it with its
19
- * own yellow background instead of just coloring the `Text` inside it, so
20
- * the whole cell width - including the padding around the header label -
21
- * reads as a distinct chip within the bar, not just the label's own glyphs.
22
- * Its text uses an explicit hex black (`#000000`) rather than the named
23
- * ANSI `black`, which routes through the terminal's own customizable
24
- * 16-color palette - many terminal themes remap that slot to a soft gray,
25
- * which is indistinguishable from true black at a glance but reads as gray
26
- * against a bright background like this cell's yellow. It is also
27
- * deliberately not `bold`, since bold text in a base ANSI color commonly
28
- * renders as that color's bright variant on top of any palette remapping.
29
- */
30
- function HeaderCell({ column, active }) {
31
- return active ? (_jsx(Box, { width: column.width, backgroundColor: "yellow", children: _jsx(Text, { color: "#000000", children: column.header }) })) : (_jsx(Box, { width: column.width, children: _jsx(Text, { bold: true, color: "white", children: column.header }) }));
32
- }
33
- /**
34
- * Renders the header row's `|` column separator between two adjacent
35
- * cells. The padding space on each side of the pipe independently picks up
36
- * a yellow background when the column it sits against is the active sort
37
- * column, so the highlight reaches all the way to the pipe on that side
38
- * instead of leaving a blue gap between the highlighted cell and its
39
- * boundary - the pipe glyph itself always stays neutral.
40
- */
41
- function HeaderSeparator({ beforeActive, afterActive, }) {
42
- return (_jsxs(Text, { color: "white", children: [beforeActive ? _jsx(Text, { backgroundColor: "yellow", children: " " }) : ' ', "|", afterActive ? _jsx(Text, { backgroundColor: "yellow", children: " " }) : ' '] }));
43
- }
44
- /**
45
- * Renders one aircraft's cell for `column`. A declared emergency squawk
46
- * (7500/7600/7700) renders in bold red - this is a full separate `<Text>`
47
- * branch rather than a conditionally-`undefined` `color` prop, since Ink's
48
- * `color`/`bold` props are only ever fully present or fully omitted here.
49
- */
50
- function AircraftCell({ column, aircraft, nowMs, emergency, }) {
51
- const value = column.render(aircraft, nowMs);
52
- return (_jsx(Box, { width: column.width, marginRight: HEADER_SEPARATOR_WIDTH, children: emergency ? (_jsx(Text, { color: "red", bold: true, wrap: "truncate-end", children: value })) : (_jsx(Text, { wrap: "truncate-end", children: value })) }));
53
- }
54
- /**
55
- * Renders one aircraft's full row. The cursor row gets its own cyan
56
- * background (full width, like the header bars) - a separate branch rather
57
- * than a conditional `backgroundColor` prop, matching {@link AircraftCell}'s
58
- * established convention of never passing Ink style props as `undefined`.
59
- * Cyan stays legible against emergency rows' bold red text, so the two
60
- * indicators don't fight each other when a selected row is also squawking
61
- * an emergency code.
62
- */
63
- function AircraftRow({ aircraft, columns, nowMs, selected, }) {
64
- const emergency = isEmergencySquawk(aircraft.squawk);
65
- const cells = columns.map((column) => (_jsx(AircraftCell, { column: column, aircraft: aircraft, nowMs: nowMs, emergency: emergency }, column.key)));
66
- return selected ? (_jsx(Box, { width: "100%", backgroundColor: "cyan", children: cells })) : (_jsx(Box, { width: "100%", children: cells }));
67
- }
68
- /**
69
- * The live-updating aircraft table: a header row followed by one row per
70
- * tracked aircraft. Rows squawking a declared emergency code render in bold
71
- * red - see {@link isEmergencySquawk}. The active sort column's header is
72
- * highlighted - see {@link AircraftTableProps.sortKey}. The cursor row is
73
- * highlighted separately - see {@link AircraftTableProps.selectedIcaoHex}.
74
- *
75
- * @param props - The aircraft, columns, active sort key, selected row, and current time to render.
76
- */
77
- export function AircraftTable(props) {
78
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { width: "100%", backgroundColor: "blue", children: props.columns.map((column, index) => {
79
- const active = column.key === props.sortKey;
80
- const previousColumn = props.columns[index - 1];
81
- return (_jsxs(Fragment, { children: [index > 0 ? (_jsx(HeaderSeparator, { beforeActive: previousColumn?.key === props.sortKey, afterActive: active })) : undefined, _jsx(HeaderCell, { column: column, active: active })] }, column.key));
82
- }) }), props.aircraft.length === 0 ? (_jsx(Text, { dimColor: true, children: "No aircraft tracked yet." })) : (props.aircraft.map((aircraft) => (_jsx(AircraftRow, { aircraft: aircraft, columns: props.columns, nowMs: props.nowMs, selected: aircraft.icaoHex === props.selectedIcaoHex }, aircraft.icaoHex))))] }));
83
- }
@@ -1,20 +0,0 @@
1
- import type { ReactElement } from 'react';
2
- import type { Aircraft, Coordinates } from '@squawk/types';
3
- /** Props for {@link DetailView}. */
4
- export interface DetailViewProps {
5
- /** The aircraft to show full detail for. */
6
- aircraft: Aircraft;
7
- /** Current time, for the "last seen" age. */
8
- nowMs: number;
9
- /** Configured receiver location (`--lat`/`--lon`), if any. Adds Distance/Bearing rows when set. */
10
- location: Coordinates | undefined;
11
- }
12
- /**
13
- * Full field dump for one aircraft, replacing the table area while open.
14
- * Opened with `[Enter]`/`[D]` on the selected row, closed the same way or
15
- * with `Escape`.
16
- *
17
- * @param props - The aircraft, the current time, and the configured receiver location.
18
- */
19
- export declare function DetailView({ aircraft, nowMs, location }: DetailViewProps): ReactElement;
20
- //# sourceMappingURL=detail-view.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"detail-view.d.ts","sourceRoot":"","sources":["../../src/components/detail-view.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAI3D,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B,4CAA4C;IAC5C,QAAQ,EAAE,QAAQ,CAAC;IACnB,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,QAAQ,EAAE,WAAW,GAAG,SAAS,CAAC;CACnC;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,eAAe,GAAG,YAAY,CAevF"}
@@ -1,14 +0,0 @@
1
- import { jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- import { buildDetailFields } from '../detail-fields.js';
4
- /**
5
- * Full field dump for one aircraft, replacing the table area while open.
6
- * Opened with `[Enter]`/`[D]` on the selected row, closed the same way or
7
- * with `Escape`.
8
- *
9
- * @param props - The aircraft, the current time, and the configured receiver location.
10
- */
11
- export function DetailView({ aircraft, nowMs, location }) {
12
- const fields = buildDetailFields(aircraft, nowMs, location);
13
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [_jsxs(Text, { bold: true, color: "cyan", children: [aircraft.icaoHex, " detail"] }), fields.map((field) => (_jsxs(Text, { children: [_jsxs(Text, { bold: true, children: [field.label, ":"] }), " ", field.value] }, field.label)))] }));
14
- }
@@ -1,4 +0,0 @@
1
- import type { ReactElement } from 'react';
2
- /** Bordered keybinding legend, toggled by the `[H]` hotkey. */
3
- export declare function HelpOverlay(): ReactElement;
4
- //# sourceMappingURL=help-overlay.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"help-overlay.d.ts","sourceRoot":"","sources":["../../src/components/help-overlay.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AA2B1C,+DAA+D;AAC/D,wBAAgB,WAAW,IAAI,YAAY,CAa1C"}
@@ -1,22 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- const HELP_ENTRIES = [
4
- { key: 'Up/Down', description: 'Move the row cursor' },
5
- { key: 'O', description: 'Cycle sort column (ICAO, callsign, altitude, ground speed, age)' },
6
- { key: 'C', description: 'Toggle compact columns for narrow terminals' },
7
- { key: 'P', description: 'Pause/resume the table - the feed keeps running underneath' },
8
- {
9
- key: 'S',
10
- description: 'Search by ICAO hex, callsign, squawk, or N-number - jumps to the first match',
11
- },
12
- { key: 'N / Shift+N', description: 'Jump to the next/previous search match' },
13
- { key: 'M', description: 'Toggle the messages panel (recent new/update/lost events)' },
14
- { key: 'V', description: 'Toggle messages panel verbosity (new/lost only vs. every update)' },
15
- { key: 'Enter / D', description: "Show the cursor row's full detail view" },
16
- { key: 'H', description: 'Toggle this help overlay' },
17
- { key: 'Q', description: 'Quit adsbtop' },
18
- ];
19
- /** Bordered keybinding legend, toggled by the `[H]` hotkey. */
20
- export function HelpOverlay() {
21
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "adsbtop help" }), HELP_ENTRIES.map((entry) => (_jsxs(Text, { children: [_jsxs(Text, { bold: true, children: ["[", entry.key, "]"] }), " ", entry.description] }, entry.key)))] }));
22
- }
@@ -1,21 +0,0 @@
1
- import type { ReactElement } from 'react';
2
- /** Props for {@link HotkeyBar}. */
3
- export interface HotkeyBarProps {
4
- /** Whether the table is currently paused - swaps the pause hotkey's label to "Resume". */
5
- paused: boolean;
6
- /** Whether the messages panel is currently shown - swaps its label and reveals `[V]erbosity`. */
7
- showMessages: boolean;
8
- /** Whether a search has been submitted - reveals `[N]ext match` for cycling. */
9
- hasActiveSearch: boolean;
10
- }
11
- /**
12
- * htop-style hotkey bar shown below the aircraft table, listing every
13
- * currently-active single-key action. `[N]ext match` and `[V]erbosity` only
14
- * appear while they would actually do something, keeping the bar accurate
15
- * to what a keypress does right now rather than listing every hotkey that
16
- * exists anywhere in the app.
17
- *
18
- * @param props - Pause/messages/search state, for the conditional labels and entries.
19
- */
20
- export declare function HotkeyBar({ paused, showMessages, hasActiveSearch }: HotkeyBarProps): ReactElement;
21
- //# sourceMappingURL=hotkey-bar.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hotkey-bar.d.ts","sourceRoot":"","sources":["../../src/components/hotkey-bar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAU1C,mCAAmC;AACnC,MAAM,WAAW,cAAc;IAC7B,0FAA0F;IAC1F,MAAM,EAAE,OAAO,CAAC;IAChB,iGAAiG;IACjG,YAAY,EAAE,OAAO,CAAC;IACtB,gFAAgF;IAChF,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,EAAE,cAAc,GAAG,YAAY,CAiCjG"}
@@ -1,28 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- /**
4
- * htop-style hotkey bar shown below the aircraft table, listing every
5
- * currently-active single-key action. `[N]ext match` and `[V]erbosity` only
6
- * appear while they would actually do something, keeping the bar accurate
7
- * to what a keypress does right now rather than listing every hotkey that
8
- * exists anywhere in the app.
9
- *
10
- * @param props - Pause/messages/search state, for the conditional labels and entries.
11
- */
12
- export function HotkeyBar({ paused, showMessages, hasActiveSearch }) {
13
- const hotkeys = [
14
- { key: 'O', label: 'Sort' },
15
- { key: 'C', label: 'Columns' },
16
- { key: 'P', label: paused ? 'Resume' : 'Pause' },
17
- { key: 'S', label: 'Search' },
18
- ];
19
- if (hasActiveSearch) {
20
- hotkeys.push({ key: 'N', label: 'Next match' });
21
- }
22
- hotkeys.push({ key: 'M', label: showMessages ? 'Hide msgs' : 'Messages' });
23
- if (showMessages) {
24
- hotkeys.push({ key: 'V', label: 'Verbosity' });
25
- }
26
- hotkeys.push({ key: 'D', label: 'Detail' }, { key: 'H', label: 'Help' }, { key: 'Q', label: 'Quit' });
27
- return (_jsx(Box, { children: hotkeys.map((hotkey, index) => (_jsxs(Text, { children: [_jsxs(Text, { bold: true, color: "cyan", children: ["[", hotkey.key, "]"] }), hotkey.label, index < hotkeys.length - 1 ? ' ' : ''] }, hotkey.key))) }));
28
- }
@@ -1,27 +0,0 @@
1
- import type { ReactElement } from 'react';
2
- import type { MessageLogEntry } from '../aircraft-state.js';
3
- /** Verbosity levels for {@link MessagesPanel}, toggled by `[V]`. */
4
- export type MessageVerbosity = 'newAndLost' | 'all';
5
- /** Props for {@link MessagesPanel}. */
6
- export interface MessagesPanelProps {
7
- /**
8
- * The log to render, oldest first - already scoped to the active
9
- * verbosity by the caller (`view.newAndLostLog` or `view.messageLog`),
10
- * not filtered here. The two are separately-maintained logs, not one log
11
- * filtered two ways - see {@link MessageVerbosity} and
12
- * `AircraftTableState.newAndLostLog`'s doc comment for why.
13
- */
14
- entries: readonly MessageLogEntry[];
15
- /** Which verbosity `entries` was scoped to - used only for the header label here. */
16
- verbosity: MessageVerbosity;
17
- }
18
- /**
19
- * Split-view panel below the aircraft table, toggled by `[M]`, showing the
20
- * most recent decoded feed events. Always shows the last {@link VISIBLE_ROWS}
21
- * entries - there is no scroll-back, matching a live `tail -f`-style log
22
- * rather than a browsable history.
23
- *
24
- * @param props - The already-verbosity-scoped log to render, and which verbosity it is.
25
- */
26
- export declare function MessagesPanel({ entries, verbosity }: MessagesPanelProps): ReactElement;
27
- //# sourceMappingURL=messages-panel.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"messages-panel.d.ts","sourceRoot":"","sources":["../../src/components/messages-panel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAM5D,oEAAoE;AACpE,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,KAAK,CAAC;AAEpD,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,qFAAqF;IACrF,SAAS,EAAE,gBAAgB,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,kBAAkB,GAAG,YAAY,CAetF"}
@@ -1,17 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- import { formatMessageLogLine } from '../format.js';
4
- /** Number of log lines shown at once - older entries scroll off the top as new ones arrive. */
5
- const VISIBLE_ROWS = 8;
6
- /**
7
- * Split-view panel below the aircraft table, toggled by `[M]`, showing the
8
- * most recent decoded feed events. Always shows the last {@link VISIBLE_ROWS}
9
- * entries - there is no scroll-back, matching a live `tail -f`-style log
10
- * rather than a browsable history.
11
- *
12
- * @param props - The already-verbosity-scoped log to render, and which verbosity it is.
13
- */
14
- export function MessagesPanel({ entries, verbosity }) {
15
- const visible = entries.slice(-VISIBLE_ROWS);
16
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", paddingX: 1, children: [_jsxs(Text, { bold: true, color: "cyan", children: ["Messages ", verbosity === 'newAndLost' ? '(new/lost)' : '(all)'] }), visible.length === 0 ? (_jsx(Text, { dimColor: true, children: "No messages yet." })) : (visible.map((entry) => _jsx(Text, { children: formatMessageLogLine(entry) }, entry.id)))] }));
17
- }
@@ -1,19 +0,0 @@
1
- import type { ReactElement } from 'react';
2
- /** Props for {@link SearchBar}. */
3
- export interface SearchBarProps {
4
- /** The in-progress query text. */
5
- query: string;
6
- /** Called with the updated query on every keystroke. */
7
- onChange: (query: string) => void;
8
- /** Called with the submitted query when `Enter` is pressed. */
9
- onSubmit: (query: string) => void;
10
- }
11
- /**
12
- * `[S]earch` prompt line shown in place of the hotkey bar while composing a
13
- * query. `Escape` cancels - handled by the app's own `useInput`, not here,
14
- * since `ink-text-input` has no built-in cancel key.
15
- *
16
- * @param props - The in-progress query and change/submit callbacks.
17
- */
18
- export declare function SearchBar({ query, onChange, onSubmit }: SearchBarProps): ReactElement;
19
- //# sourceMappingURL=search-bar.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"search-bar.d.ts","sourceRoot":"","sources":["../../src/components/search-bar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,mCAAmC;AACnC,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,+DAA+D;IAC/D,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,cAAc,GAAG,YAAY,CASrF"}
@@ -1,13 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- import TextInput from 'ink-text-input';
4
- /**
5
- * `[S]earch` prompt line shown in place of the hotkey bar while composing a
6
- * query. `Escape` cancels - handled by the app's own `useInput`, not here,
7
- * since `ink-text-input` has no built-in cancel key.
8
- *
9
- * @param props - The in-progress query and change/submit callbacks.
10
- */
11
- export function SearchBar({ query, onChange, onSubmit }) {
12
- return (_jsxs(Box, { children: [_jsxs(Text, { bold: true, color: "cyan", children: ["Search:", ' '] }), _jsx(TextInput, { value: query, onChange: onChange, onSubmit: onSubmit, focus: true })] }));
13
- }
@@ -1,17 +0,0 @@
1
- import type { ReactElement } from 'react';
2
- import type { StatusLineInfo } from '../status-line.js';
3
- /** Props for {@link StatusHeader}. */
4
- export interface StatusHeaderProps extends StatusLineInfo {
5
- /** Whether the table is currently paused. */
6
- paused: boolean;
7
- }
8
- /**
9
- * Connection and activity summary shown above the aircraft table:
10
- * source/host/port, tracked aircraft count, message rate, and time since the
11
- * last update, followed by a blank line (same background) to give the table
12
- * header row below it some breathing room.
13
- *
14
- * @param props - The connection/activity state to display.
15
- */
16
- export declare function StatusHeader(props: StatusHeaderProps): ReactElement;
17
- //# sourceMappingURL=status-header.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"status-header.d.ts","sourceRoot":"","sources":["../../src/components/status-header.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,sCAAsC;AACtC,MAAM,WAAW,iBAAkB,SAAQ,cAAc;IACvD,6CAA6C;IAC7C,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,CAiBnE"}