• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

iddan / react-spreadsheet / 5662612095

pending completion
5662612095

push

github

iddan
Move out direction and optimize selection methods

408 of 544 branches covered (75.0%)

Branch coverage included in aggregate %.

19 of 19 new or added lines in 2 files covered. (100.0%)

961 of 1149 relevant lines covered (83.64%)

28.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.53
/src/selection.ts
1
import { PointRange } from "./point-range";
11✔
2
import * as Point from "./point";
11✔
3
import * as Matrix from "./matrix";
11✔
4

5
/** Selection from a spreadsheet */
6
export abstract class Selection {
11✔
7
  /** Get concrete range of the selection in the given data */
8
  abstract toRange(data: Matrix.Matrix<unknown>): PointRange | null;
9

10
  /** Normalize the selection according to the given data */
11
  abstract normalizeTo(data: Matrix.Matrix<unknown>): this;
12

13
  /** Determines whether the given row is entirely selected in given selection */
14
  abstract hasEntireRow(row: number): boolean;
15

16
  /** Determines whether the given column is entirely selected in given selection */
17
  abstract hasEntireColumn(column: number): boolean;
18

19
  /** Get the number of selected points according to given data */
20
  abstract size(data: Matrix.Matrix<unknown>): number;
21

22
  /** Determines whether the given point is within the selection */
23
  abstract has(data: Matrix.Matrix<unknown>, point: Point.Point): boolean;
24
}
25

26
/** Selection of no cells */
27
export class EmptySelection extends Selection {
11✔
28
  toRange(data: Matrix.Matrix<unknown>): PointRange | null {
29
    return null;
22✔
30
  }
31
  normalizeTo(data: Matrix.Matrix<unknown>): this {
32
    return this;
3✔
33
  }
34
  hasEntireRow(row: number): boolean {
35
    return false;
53✔
36
  }
37
  hasEntireColumn(column: number): boolean {
38
    return false;
53✔
39
  }
40
  size(): number {
41
    return 0;
21✔
42
  }
43
  has(): boolean {
44
    return false;
224✔
45
  }
46
}
47

48
/** Selection of a range of cells */
49
export class RangeSelection extends Selection {
11✔
50
  constructor(public range: PointRange) {
73✔
51
    super();
73✔
52
  }
53

54
  toRange(data: Matrix.Matrix<unknown>): PointRange | null {
55
    return this.range;
176✔
56
  }
57

58
  normalizeTo(data: Matrix.Matrix<unknown>): this {
59
    const dataRange = getMatrixRange(data);
15✔
60
    const nextSelection = new RangeSelection(this.range.mask(dataRange));
15✔
61
    // @ts-expect-error
62
    return nextSelection;
15✔
63
  }
64

65
  hasEntireRow(row: number): boolean {
66
    return false;
32✔
67
  }
68

69
  hasEntireColumn(column: number): boolean {
70
    return false;
32✔
71
  }
72

73
  size(data: Matrix.Matrix<unknown>): number {
74
    const range = this.toRange(data);
17✔
75
    return range ? range.size() : 0;
17!
76
  }
77

78
  has(data: Matrix.Matrix<unknown>, point: Point.Point): boolean {
79
    const range = this.toRange(data);
133✔
80
    return range !== null && range.has(point);
133✔
81
  }
82
}
83

84
/** Selection of an entire part of the spreadsheet */
85
abstract class EntireSelection extends Selection {}
86

87
/** Selection of the entire table */
88
export class EntireTableSelection extends EntireSelection {
11✔
89
  toRange(data: Matrix.Matrix<unknown>): PointRange {
90
    return getMatrixRange(data);
1✔
91
  }
92

93
  normalizeTo(data: Matrix.Matrix<unknown>): this {
94
    return this;
×
95
  }
96

97
  hasEntireColumn(column: number): boolean {
98
    return true;
×
99
  }
100

101
  hasEntireRow(row: number): boolean {
102
    return true;
×
103
  }
104

105
  size(data: Matrix.Matrix<unknown>): number {
106
    return Matrix.getColumnsCount(data) * Matrix.getRowsCount(data);
×
107
  }
108

109
  has(data: Matrix.Matrix<unknown>, point: Point.Point): boolean {
110
    return true;
×
111
  }
112
}
113

114
/** Selection of an entire axis in the spreadsheet */
115
export abstract class EntireAxisSelection extends EntireSelection {
11✔
116
  /** Selection start index, integer */
117
  readonly start: number;
118
  /** Selection end index, integer */
119
  readonly end: number;
120

121
  /**
122
   * @param start - row index where the selection starts, integer
123
   * @param end - row index where the selection ends, integer
124
   * @throws {@link InvalidIndexError}
125
   */
126
  constructor(start: number, end: number) {
127
    if (!isIndex(start)) {
95✔
128
      throw new InvalidIndexError("start");
2✔
129
    }
130
    if (!isIndex(end)) {
93✔
131
      throw new InvalidIndexError("end");
2✔
132
    }
133
    super();
91✔
134
    this.start = Math.min(start, end);
91✔
135
    this.end = Math.max(start, end);
91✔
136
  }
137

138
  /** Immutably set given property with given value */
139
  set(property: "start" | "end", value: number): this {
140
    if (!isIndex(value)) {
×
141
      throw new InvalidIndexError(property);
×
142
    }
143
    const { start, end } = this;
×
144
    const data = { start, end };
×
145
    data[property] = value;
×
146
    // @ts-expect-error
147
    return new this.constructor(data.start, data.end);
×
148
  }
149
}
150

151
/** Selection of entire rows in the spreadsheet */
152
export class EntireRowsSelection extends EntireAxisSelection {
11✔
153
  toRange(data: Matrix.Matrix<unknown>): PointRange {
154
    const max = Matrix.maxPoint(data);
1✔
155
    return new PointRange(
1✔
156
      { row: this.start, column: 0 },
157
      { row: this.end, column: max.column }
158
    );
159
  }
160

161
  normalizeTo(data: Matrix.Matrix<unknown>): this {
162
    const count = Matrix.getRowsCount(data);
8✔
163
    const nextSelection = new EntireRowsSelection(
8✔
164
      Math.max(this.start, 0),
165
      Math.min(this.end, count - 1)
166
    );
167
    // @ts-expect-error
168
    return nextSelection;
8✔
169
  }
170

171
  hasEntireRow(row: number): boolean {
172
    return row >= this.start && row <= this.end;
2✔
173
  }
174

175
  hasEntireColumn(column: number): boolean {
176
    return false;
×
177
  }
178

179
  size(data: Matrix.Matrix<unknown>): number {
180
    const rows = this.end - this.start + 1;
×
181
    return rows * Matrix.getColumnsCount(data);
×
182
  }
183

184
  has(data: Matrix.Matrix<unknown>, point: Point.Point): boolean {
185
    return point.row >= this.start && point.row <= this.end;
×
186
  }
187
}
188

189
/** Selection of entire columns in the spreadsheet */
190
export class EntireColumnsSelection extends EntireAxisSelection {
11✔
191
  toRange(data: Matrix.Matrix<unknown>): PointRange {
192
    const max = Matrix.maxPoint(data);
1✔
193
    return new PointRange(
1✔
194
      { row: 0, column: this.start },
195
      { row: max.row, column: this.end }
196
    );
197
  }
198

199
  normalizeTo(data: Matrix.Matrix<unknown>): this {
200
    const count = Matrix.getColumnsCount(data);
8✔
201
    const nextSelection = new EntireColumnsSelection(
8✔
202
      Math.max(this.start, 0),
203
      Math.min(this.end, count - 1)
204
    );
205
    // @ts-expect-error
206
    return nextSelection;
8✔
207
  }
208

209
  hasEntireRow(row: number): boolean {
210
    return false;
×
211
  }
212

213
  hasEntireColumn(column: number): boolean {
214
    return column >= this.start && column <= this.end;
2✔
215
  }
216

217
  size(data: Matrix.Matrix<unknown>): number {
218
    const columns = this.end - this.start + 1;
×
219
    return columns * Matrix.getRowsCount(data);
×
220
  }
221

222
  has(data: Matrix.Matrix<unknown>, point: Point.Point): boolean {
223
    return point.column >= this.start && point.column <= this.end;
×
224
  }
225
}
226

227
/** Get the point range of given matrix */
228
export function getMatrixRange(data: Matrix.Matrix<unknown>): PointRange {
11✔
229
  const maxPoint = Matrix.maxPoint(data);
18✔
230
  return new PointRange(Point.ORIGIN, maxPoint);
18✔
231
}
232

233
/** Determines whether the given value is a valid index */
234
export function isIndex(value: number): boolean {
11✔
235
  return Number.isInteger(value) && value >= 0;
191✔
236
}
237

238
/** Error thrown when passing a non-index value where an index value is expected */
239
export class InvalidIndexError extends Error {
11✔
240
  constructor(name: string) {
241
    super(`${name} is not a valid index. It must be 0 or a positive integer`);
8✔
242
  }
243
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc