UNPKG

11 kBJavaScriptView Raw
1/**!
2* matrix-pointer 0.0.1
3* MIT License
4* Copyright (c) 2023 Yuta Arai
5**/
6'use strict';
7
8class 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}
38function isId(id) {
39 return null !== id;
40}
41function 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}
64function 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}
91function 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}
123function 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}
153function 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}
171function 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}
186function 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}
352class 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}
391module.exports = MatrixPointer;