1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | 'use strict';
|
7 |
|
8 | class Emitter {
|
9 | constructor() {
|
10 | this.Emitter$items = [];
|
11 | }
|
12 | on(name, handler, options) {
|
13 | this.off(name, handler);
|
14 | this.Emitter$items.push([name, handler, {
|
15 | once: !!(options === null || options === void 0 ? void 0 : options.once)
|
16 | }]);
|
17 | }
|
18 | off(name, handler) {
|
19 | for (let a = this.Emitter$items, i = 0; a.length > i; i++) {
|
20 | if ("*" === name || a[i][0] === name && a[i][1] === handler) {
|
21 | a.splice(i--, 1);
|
22 | }
|
23 | }
|
24 | }
|
25 | emit(name, event) {
|
26 | this.Emitter$items.forEach(entry => {
|
27 | var _a;
|
28 | if (name === entry[0]) {
|
29 | entry[1](Object.assign(Object.assign({}, event), {
|
30 | target: this,
|
31 | type: name
|
32 | }));
|
33 | if ((_a = entry[2]) === null || _a === void 0 ? void 0 : _a.once) this.off(name, entry[1]);
|
34 | }
|
35 | });
|
36 | }
|
37 | }
|
38 | function isId(id) {
|
39 | return null !== id;
|
40 | }
|
41 | function findArroundX(row, sx, ny) {
|
42 | if (Array.isArray(row)) {
|
43 | const ex = row.length - 1;
|
44 | sx = Math.min(Math.max(0, sx), ex);
|
45 | let id = row[sx];
|
46 | let diff = 0;
|
47 | let nx = sx;
|
48 | while (!isId(id) && (sx - diff > 0 || ex > sx + diff)) {
|
49 | id = row[nx = sx - ++diff];
|
50 | if (!isId(id)) {
|
51 | id = row[nx = sx + diff];
|
52 | }
|
53 | }
|
54 | if (isId(id)) {
|
55 | return {
|
56 | id,
|
57 | x: nx,
|
58 | y: ny
|
59 | };
|
60 | }
|
61 | }
|
62 | return null;
|
63 | }
|
64 | function findArroundY(matrix, nx, sy) {
|
65 | if (Array.isArray(matrix)) {
|
66 | const ey = matrix.length - 1;
|
67 | sy = Math.min(Math.max(0, sy), ey);
|
68 | let id;
|
69 | const row = matrix[sy];
|
70 | if (row) id = row[nx];
|
71 | let diff = 0;
|
72 | let ny = sy;
|
73 | while (!isId(id) && (sy - diff > 0 || ey > sy + diff)) {
|
74 | const row2 = matrix[ny = sy - ++diff];
|
75 | if (row2) id = row2[nx];
|
76 | if (!isId(id)) {
|
77 | const row3 = matrix[ny = sy + diff];
|
78 | if (row3) id = row3[nx];
|
79 | }
|
80 | }
|
81 | if (isId(id)) {
|
82 | return {
|
83 | id,
|
84 | x: nx,
|
85 | y: ny
|
86 | };
|
87 | }
|
88 | }
|
89 | return null;
|
90 | }
|
91 | function moveTo(matrix, sx, sy) {
|
92 | if (Array.isArray(matrix)) {
|
93 | const ey = matrix.length - 1;
|
94 | sx = Math.max(0, sx);
|
95 | sy = Math.min(Math.max(0, sy), ey);
|
96 | let diff = 0;
|
97 | const row = matrix[sy];
|
98 | if (row) {
|
99 | const position = findArroundX(row, sx, sy);
|
100 | if (position) return position;
|
101 | }
|
102 | while (sy - diff > 0 || ey > sy + diff) {
|
103 | {
|
104 | const ny = sy - ++diff;
|
105 | const row2 = matrix[ny];
|
106 | if (row2) {
|
107 | const position = findArroundX(row2, sx, ny);
|
108 | if (position) return position;
|
109 | }
|
110 | }
|
111 | {
|
112 | const ny = sy + diff;
|
113 | const row2 = matrix[ny];
|
114 | if (row2) {
|
115 | const position = findArroundX(row2, sx, ny);
|
116 | if (position) return position;
|
117 | }
|
118 | }
|
119 | }
|
120 | }
|
121 | return null;
|
122 | }
|
123 | function getPosition(matrix, id, fallback) {
|
124 | let defaultPosition = null;
|
125 | const hasId = isId(id);
|
126 | for (let ny = 0; matrix.length > ny; ny++) {
|
127 | const row = matrix[ny];
|
128 | if (Array.isArray(row)) {
|
129 | for (let nx = 0; row.length > nx; nx++) {
|
130 | const column = row[nx];
|
131 | if (isId(column)) {
|
132 | if (!defaultPosition) {
|
133 | defaultPosition = {
|
134 | id: column,
|
135 | x: nx,
|
136 | y: ny
|
137 | };
|
138 | if (!hasId && fallback) return defaultPosition;
|
139 | }
|
140 | if (column === id) {
|
141 | return {
|
142 | id: column,
|
143 | x: nx,
|
144 | y: ny
|
145 | };
|
146 | }
|
147 | }
|
148 | }
|
149 | }
|
150 | }
|
151 | return fallback ? defaultPosition : null;
|
152 | }
|
153 | function findOneDirectionY(matrix, nx, sy, next) {
|
154 | if (Array.isArray(matrix)) {
|
155 | for (let ey = matrix.length - 1, ny = null === sy ? next ? 0 : ey : sy; next ? ey >= ny : ny >= 0; next ? ny++ : ny--) {
|
156 | const row = matrix[ny];
|
157 | if (Array.isArray(row)) {
|
158 | const column = row[nx];
|
159 | if (isId(column)) {
|
160 | return {
|
161 | id: column,
|
162 | x: nx,
|
163 | y: ny
|
164 | };
|
165 | }
|
166 | }
|
167 | }
|
168 | }
|
169 | return null;
|
170 | }
|
171 | function findOneDirectionX(row, sx, ny, next) {
|
172 | if (Array.isArray(row)) {
|
173 | for (let ex = row.length - 1, nx = null === sx ? next ? 0 : ex : sx; next ? ex >= nx : nx >= 0; next ? nx++ : nx--) {
|
174 | const column = row[nx];
|
175 | if (isId(column)) {
|
176 | return {
|
177 | id: column,
|
178 | x: nx,
|
179 | y: ny
|
180 | };
|
181 | }
|
182 | }
|
183 | }
|
184 | return null;
|
185 | }
|
186 | function moveBy(matrix, startPosition, direction, next, loop, loose, jump) {
|
187 | if (startPosition) {
|
188 | const canLoopX = true === loop || loop && loop.x;
|
189 | const canLoopY = true === loop || loop && loop.y;
|
190 | const canLooseX = true === loose || loose && loose.x;
|
191 | const canLooseY = true === loose || loose && loose.y;
|
192 | const canJumpX = true === jump || jump && jump.x;
|
193 | const canJumpY = true === jump || jump && jump.y;
|
194 | let nx = startPosition.x;
|
195 | let ny = startPosition.y;
|
196 | let lx = nx;
|
197 | let ly = ny;
|
198 | const ey = matrix.length - 1;
|
199 | if ("x" === direction) {
|
200 | if (canLooseY) {
|
201 | while (true) {
|
202 | nx += next ? 1 : -1;
|
203 | const ex = matrix[ny].length - 1;
|
204 | const overEnd = nx > ex;
|
205 | const overStart = 0 > nx;
|
206 | if (overStart || overEnd) {
|
207 | if (canLoopX) {
|
208 | if (canJumpY) {
|
209 | ny += next ? 1 : -1;
|
210 | const overEnd2 = ny > ey;
|
211 | const overStart2 = 0 > ny;
|
212 | if (overStart2 || overEnd2) {
|
213 | if (canLoopY) {
|
214 | if (overEnd2) {
|
215 | ny = 0;
|
216 | } else {
|
217 | ny = ey;
|
218 | }
|
219 | } else {
|
220 | ny = ly;
|
221 | }
|
222 | }
|
223 | ly = ny;
|
224 | }
|
225 | if (overEnd) {
|
226 | nx = 0;
|
227 | } else {
|
228 | nx = matrix[ny].length - 1;
|
229 | }
|
230 | } else {
|
231 | nx = lx;
|
232 | }
|
233 | }
|
234 | if (nx === lx) return startPosition;
|
235 | lx = nx;
|
236 | const position = findArroundY(matrix, nx, ny);
|
237 | if (position) return position;
|
238 | }
|
239 | } else {
|
240 | {
|
241 | const row = matrix[ny];
|
242 | const position = findOneDirectionX(row, startPosition.x + (next ? 1 : -1), ny, next);
|
243 | if (position) return position;
|
244 | }
|
245 | if (!canLoopX) {
|
246 | return startPosition;
|
247 | }
|
248 | if (!canJumpY) {
|
249 | const position = findOneDirectionX(matrix[ny], null, ny, next);
|
250 | return position || startPosition;
|
251 | }
|
252 | while (true) {
|
253 | ny += next ? 1 : -1;
|
254 | const overEnd = ny > ey;
|
255 | const overStart = 0 > ny;
|
256 | if (overStart || overEnd) {
|
257 | if (canLoopY) {
|
258 | if (overEnd) {
|
259 | ny = 0;
|
260 | } else {
|
261 | ny = ey;
|
262 | }
|
263 | } else {
|
264 | ny = ly;
|
265 | }
|
266 | }
|
267 | if (ny === ly) return startPosition;
|
268 | ly = ny;
|
269 | const position = findOneDirectionX(matrix[ny], null, ny, next);
|
270 | if (position) return position;
|
271 | }
|
272 | }
|
273 | } else {
|
274 | if (canLooseX) {
|
275 | while (true) {
|
276 | ny += next ? 1 : -1;
|
277 | const overEnd = ny > ey;
|
278 | const overStart = 0 > ny;
|
279 | if (overStart || overEnd) {
|
280 | if (canLoopY) {
|
281 | if (overEnd) {
|
282 | ny = 0;
|
283 | } else {
|
284 | ny = ey;
|
285 | }
|
286 | if (canJumpX) {
|
287 | nx += next ? 1 : -1;
|
288 | const ex = matrix[ny].length - 1;
|
289 | const overEnd2 = nx > ex;
|
290 | const overStart2 = 0 > nx;
|
291 | if (overStart2 || overEnd2) {
|
292 | if (canLoopX) {
|
293 | if (overEnd2) {
|
294 | nx = 0;
|
295 | } else {
|
296 | nx = ex;
|
297 | }
|
298 | } else {
|
299 | nx = lx;
|
300 | }
|
301 | }
|
302 | lx = nx;
|
303 | }
|
304 | } else {
|
305 | ny = ly;
|
306 | }
|
307 | }
|
308 | if (ny === ly) return startPosition;
|
309 | ly = ny;
|
310 | const position = findArroundX(matrix[ny], nx, ny);
|
311 | if (position) return position;
|
312 | }
|
313 | } else {
|
314 | {
|
315 | const position = findOneDirectionY(matrix, nx, startPosition.y + (next ? 1 : -1), next);
|
316 | if (position) return position;
|
317 | }
|
318 | if (!canLoopY) {
|
319 | return startPosition;
|
320 | }
|
321 | if (!canJumpX) {
|
322 | const position = findOneDirectionY(matrix, nx, null, next);
|
323 | return position || startPosition;
|
324 | }
|
325 | while (true) {
|
326 | nx += next ? 1 : -1;
|
327 | const row = matrix[ny];
|
328 | const ex = row.length - 1;
|
329 | const overEnd = nx > ex;
|
330 | const overStart = 0 > nx;
|
331 | if (overStart || overEnd) {
|
332 | if (canLoopX) {
|
333 | if (overEnd) {
|
334 | nx = 0;
|
335 | } else {
|
336 | nx = ex;
|
337 | }
|
338 | } else {
|
339 | nx = lx;
|
340 | }
|
341 | }
|
342 | if (nx === lx) return startPosition;
|
343 | lx = nx;
|
344 | const position = findOneDirectionY(matrix, nx, null, next);
|
345 | if (position) return position;
|
346 | }
|
347 | }
|
348 | }
|
349 | }
|
350 | return null;
|
351 | }
|
352 | class MatrixPointer extends Emitter {
|
353 | constructor(options) {
|
354 | super();
|
355 | this.position = null;
|
356 | this.caches = {
|
357 | matrix: []
|
358 | };
|
359 | this.jump = void 0 !== options.jump ? options.jump : true;
|
360 | this.loop = void 0 !== options.loop ? options.loop : true;
|
361 | this.loose = void 0 !== options.loose ? options.loose : true;
|
362 | this.matrix = options.matrix;
|
363 | }
|
364 | update() {
|
365 | const matrix = "function" === typeof this.matrix ? this.matrix() : this.matrix;
|
366 | return this.caches.matrix = Array.isArray(matrix) ? matrix.filter(row => Array.isArray(row)).map(row => row.map(column => isId(column) ? column : null)) : [];
|
367 | }
|
368 | focus(newPosition) {
|
369 | const oldPosition = this.position;
|
370 | this.position = newPosition;
|
371 | if (!(!oldPosition && !newPosition || (oldPosition === null || oldPosition === void 0 ? void 0 : oldPosition.id) === (newPosition === null || newPosition === void 0 ? void 0 : newPosition.id))) {
|
372 | if (oldPosition) this.emit("blur", oldPosition);
|
373 | if (newPosition) this.emit("focus", newPosition);
|
374 | }
|
375 | return newPosition;
|
376 | }
|
377 | moveTo(x, y) {
|
378 | const matrix = this.update();
|
379 | return this.focus("number" === typeof x && "number" === typeof y ? moveTo(matrix, x, y) : getPosition(matrix, x, false));
|
380 | }
|
381 | moveBy(direction, next) {
|
382 | var _a;
|
383 | const matrix = this.update();
|
384 | return this.focus(moveBy(matrix, getPosition(matrix, (_a = this.position) === null || _a === void 0 ? void 0 : _a.id, true), direction, next, this.loop, this.loose, this.jump));
|
385 | }
|
386 | destroy() {
|
387 | this.caches.matrix = [];
|
388 | this.off("*");
|
389 | }
|
390 | }
|
391 | module.exports = MatrixPointer;
|