astar-visualizer 1.0.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.
- package/README.md +54 -0
- package/dist/astar-visualizer.js +791 -0
- package/dist/astar-visualizer.umd.cjs +33 -0
- package/dist/style.css +1 -0
- package/dist/vite.svg +1 -0
- package/package.json +73 -0
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# A* Pathfinding Visualizer
|
|
2
|
+
|
|
3
|
+
A React component for visualizing the A* pathfinding algorithm with an interactive grid interface.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install astar-visualizer
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { AStarVisualizer } from 'astar-visualizer';
|
|
15
|
+
import 'astar-visualizer/style.css';
|
|
16
|
+
|
|
17
|
+
function App() {
|
|
18
|
+
return (
|
|
19
|
+
<div>
|
|
20
|
+
<AStarVisualizer />
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default App;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Features
|
|
29
|
+
|
|
30
|
+
- Interactive grid for setting start/end points and obstacles
|
|
31
|
+
- Real-time visualization of the A* algorithm
|
|
32
|
+
- Customizable grid size
|
|
33
|
+
- Control panel for algorithm execution
|
|
34
|
+
- Smooth animations with Framer Motion
|
|
35
|
+
|
|
36
|
+
## Development
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Install dependencies
|
|
40
|
+
npm install
|
|
41
|
+
|
|
42
|
+
# Run development server
|
|
43
|
+
npm run dev
|
|
44
|
+
|
|
45
|
+
# Build library for publishing
|
|
46
|
+
npm run build:lib
|
|
47
|
+
|
|
48
|
+
# Run tests
|
|
49
|
+
npm test
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
MIT
|
|
@@ -0,0 +1,791 @@
|
|
|
1
|
+
import { jsx as S, jsxs as y } from "react/jsx-runtime";
|
|
2
|
+
import D, { useState as H, useEffect as $ } from "react";
|
|
3
|
+
const P = (e) => {
|
|
4
|
+
let t;
|
|
5
|
+
const r = /* @__PURE__ */ new Set(), l = (c, f) => {
|
|
6
|
+
const u = typeof c == "function" ? c(t) : c;
|
|
7
|
+
if (!Object.is(u, t)) {
|
|
8
|
+
const s = t;
|
|
9
|
+
t = f ?? (typeof u != "object" || u === null) ? u : Object.assign({}, t, u), r.forEach((a) => a(t, s));
|
|
10
|
+
}
|
|
11
|
+
}, o = () => t, g = { setState: l, getState: o, getInitialState: () => d, subscribe: (c) => (r.add(c), () => r.delete(c)), destroy: () => {
|
|
12
|
+
r.clear();
|
|
13
|
+
} }, d = t = e(l, o, g);
|
|
14
|
+
return g;
|
|
15
|
+
}, U = (e) => e ? P(e) : P;
|
|
16
|
+
function q(e) {
|
|
17
|
+
return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
|
|
18
|
+
}
|
|
19
|
+
var V = { exports: {} }, R = {}, L = { exports: {} }, A = {};
|
|
20
|
+
/**
|
|
21
|
+
* @license React
|
|
22
|
+
* use-sync-external-store-shim.production.js
|
|
23
|
+
*
|
|
24
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
25
|
+
*
|
|
26
|
+
* This source code is licensed under the MIT license found in the
|
|
27
|
+
* LICENSE file in the root directory of this source tree.
|
|
28
|
+
*/
|
|
29
|
+
var x;
|
|
30
|
+
function J() {
|
|
31
|
+
if (x)
|
|
32
|
+
return A;
|
|
33
|
+
x = 1;
|
|
34
|
+
var e = D;
|
|
35
|
+
function t(f, u) {
|
|
36
|
+
return f === u && (f !== 0 || 1 / f === 1 / u) || f !== f && u !== u;
|
|
37
|
+
}
|
|
38
|
+
var r = typeof Object.is == "function" ? Object.is : t, l = e.useState, o = e.useEffect, i = e.useLayoutEffect, m = e.useDebugValue;
|
|
39
|
+
function p(f, u) {
|
|
40
|
+
var s = u(), a = l({ inst: { value: s, getSnapshot: u } }), n = a[0].inst, v = a[1];
|
|
41
|
+
return i(
|
|
42
|
+
function() {
|
|
43
|
+
n.value = s, n.getSnapshot = u, g(n) && v({ inst: n });
|
|
44
|
+
},
|
|
45
|
+
[f, s, u]
|
|
46
|
+
), o(
|
|
47
|
+
function() {
|
|
48
|
+
return g(n) && v({ inst: n }), f(function() {
|
|
49
|
+
g(n) && v({ inst: n });
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
[f]
|
|
53
|
+
), m(s), s;
|
|
54
|
+
}
|
|
55
|
+
function g(f) {
|
|
56
|
+
var u = f.getSnapshot;
|
|
57
|
+
f = f.value;
|
|
58
|
+
try {
|
|
59
|
+
var s = u();
|
|
60
|
+
return !r(f, s);
|
|
61
|
+
} catch {
|
|
62
|
+
return !0;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function d(f, u) {
|
|
66
|
+
return u();
|
|
67
|
+
}
|
|
68
|
+
var c = typeof window > "u" || typeof window.document > "u" || typeof window.document.createElement > "u" ? d : p;
|
|
69
|
+
return A.useSyncExternalStore = e.useSyncExternalStore !== void 0 ? e.useSyncExternalStore : c, A;
|
|
70
|
+
}
|
|
71
|
+
var M = {};
|
|
72
|
+
/**
|
|
73
|
+
* @license React
|
|
74
|
+
* use-sync-external-store-shim.development.js
|
|
75
|
+
*
|
|
76
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
77
|
+
*
|
|
78
|
+
* This source code is licensed under the MIT license found in the
|
|
79
|
+
* LICENSE file in the root directory of this source tree.
|
|
80
|
+
*/
|
|
81
|
+
var B;
|
|
82
|
+
function Y() {
|
|
83
|
+
return B || (B = 1, process.env.NODE_ENV !== "production" && function() {
|
|
84
|
+
function e(s, a) {
|
|
85
|
+
return s === a && (s !== 0 || 1 / s === 1 / a) || s !== s && a !== a;
|
|
86
|
+
}
|
|
87
|
+
function t(s, a) {
|
|
88
|
+
c || o.startTransition === void 0 || (c = !0, console.error(
|
|
89
|
+
"You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release."
|
|
90
|
+
));
|
|
91
|
+
var n = a();
|
|
92
|
+
if (!f) {
|
|
93
|
+
var v = a();
|
|
94
|
+
i(n, v) || (console.error(
|
|
95
|
+
"The result of getSnapshot should be cached to avoid an infinite loop"
|
|
96
|
+
), f = !0);
|
|
97
|
+
}
|
|
98
|
+
v = m({
|
|
99
|
+
inst: { value: n, getSnapshot: a }
|
|
100
|
+
});
|
|
101
|
+
var w = v[0].inst, _ = v[1];
|
|
102
|
+
return g(
|
|
103
|
+
function() {
|
|
104
|
+
w.value = n, w.getSnapshot = a, r(w) && _({ inst: w });
|
|
105
|
+
},
|
|
106
|
+
[s, n, a]
|
|
107
|
+
), p(
|
|
108
|
+
function() {
|
|
109
|
+
return r(w) && _({ inst: w }), s(function() {
|
|
110
|
+
r(w) && _({ inst: w });
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
[s]
|
|
114
|
+
), d(n), n;
|
|
115
|
+
}
|
|
116
|
+
function r(s) {
|
|
117
|
+
var a = s.getSnapshot;
|
|
118
|
+
s = s.value;
|
|
119
|
+
try {
|
|
120
|
+
var n = a();
|
|
121
|
+
return !i(s, n);
|
|
122
|
+
} catch {
|
|
123
|
+
return !0;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function l(s, a) {
|
|
127
|
+
return a();
|
|
128
|
+
}
|
|
129
|
+
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
130
|
+
var o = D, i = typeof Object.is == "function" ? Object.is : e, m = o.useState, p = o.useEffect, g = o.useLayoutEffect, d = o.useDebugValue, c = !1, f = !1, u = typeof window > "u" || typeof window.document > "u" || typeof window.document.createElement > "u" ? l : t;
|
|
131
|
+
M.useSyncExternalStore = o.useSyncExternalStore !== void 0 ? o.useSyncExternalStore : u, typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
|
|
132
|
+
}()), M;
|
|
133
|
+
}
|
|
134
|
+
var I;
|
|
135
|
+
function F() {
|
|
136
|
+
return I || (I = 1, process.env.NODE_ENV === "production" ? L.exports = J() : L.exports = Y()), L.exports;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* @license React
|
|
140
|
+
* use-sync-external-store-shim/with-selector.production.js
|
|
141
|
+
*
|
|
142
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
143
|
+
*
|
|
144
|
+
* This source code is licensed under the MIT license found in the
|
|
145
|
+
* LICENSE file in the root directory of this source tree.
|
|
146
|
+
*/
|
|
147
|
+
var j;
|
|
148
|
+
function Q() {
|
|
149
|
+
if (j)
|
|
150
|
+
return R;
|
|
151
|
+
j = 1;
|
|
152
|
+
var e = D, t = F();
|
|
153
|
+
function r(d, c) {
|
|
154
|
+
return d === c && (d !== 0 || 1 / d === 1 / c) || d !== d && c !== c;
|
|
155
|
+
}
|
|
156
|
+
var l = typeof Object.is == "function" ? Object.is : r, o = t.useSyncExternalStore, i = e.useRef, m = e.useEffect, p = e.useMemo, g = e.useDebugValue;
|
|
157
|
+
return R.useSyncExternalStoreWithSelector = function(d, c, f, u, s) {
|
|
158
|
+
var a = i(null);
|
|
159
|
+
if (a.current === null) {
|
|
160
|
+
var n = { hasValue: !1, value: null };
|
|
161
|
+
a.current = n;
|
|
162
|
+
} else
|
|
163
|
+
n = a.current;
|
|
164
|
+
a = p(
|
|
165
|
+
function() {
|
|
166
|
+
function w(b) {
|
|
167
|
+
if (!_) {
|
|
168
|
+
if (_ = !0, O = b, b = u(b), s !== void 0 && n.hasValue) {
|
|
169
|
+
var E = n.value;
|
|
170
|
+
if (s(E, b))
|
|
171
|
+
return N = E;
|
|
172
|
+
}
|
|
173
|
+
return N = b;
|
|
174
|
+
}
|
|
175
|
+
if (E = N, l(O, b))
|
|
176
|
+
return E;
|
|
177
|
+
var T = u(b);
|
|
178
|
+
return s !== void 0 && s(E, T) ? (O = b, E) : (O = b, N = T);
|
|
179
|
+
}
|
|
180
|
+
var _ = !1, O, N, C = f === void 0 ? null : f;
|
|
181
|
+
return [
|
|
182
|
+
function() {
|
|
183
|
+
return w(c());
|
|
184
|
+
},
|
|
185
|
+
C === null ? void 0 : function() {
|
|
186
|
+
return w(C());
|
|
187
|
+
}
|
|
188
|
+
];
|
|
189
|
+
},
|
|
190
|
+
[c, f, u, s]
|
|
191
|
+
);
|
|
192
|
+
var v = o(d, a[0], a[1]);
|
|
193
|
+
return m(
|
|
194
|
+
function() {
|
|
195
|
+
n.hasValue = !0, n.value = v;
|
|
196
|
+
},
|
|
197
|
+
[v]
|
|
198
|
+
), g(v), v;
|
|
199
|
+
}, R;
|
|
200
|
+
}
|
|
201
|
+
var z = {};
|
|
202
|
+
/**
|
|
203
|
+
* @license React
|
|
204
|
+
* use-sync-external-store-shim/with-selector.development.js
|
|
205
|
+
*
|
|
206
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
207
|
+
*
|
|
208
|
+
* This source code is licensed under the MIT license found in the
|
|
209
|
+
* LICENSE file in the root directory of this source tree.
|
|
210
|
+
*/
|
|
211
|
+
var W;
|
|
212
|
+
function X() {
|
|
213
|
+
return W || (W = 1, process.env.NODE_ENV !== "production" && function() {
|
|
214
|
+
function e(d, c) {
|
|
215
|
+
return d === c && (d !== 0 || 1 / d === 1 / c) || d !== d && c !== c;
|
|
216
|
+
}
|
|
217
|
+
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
218
|
+
var t = D, r = F(), l = typeof Object.is == "function" ? Object.is : e, o = r.useSyncExternalStore, i = t.useRef, m = t.useEffect, p = t.useMemo, g = t.useDebugValue;
|
|
219
|
+
z.useSyncExternalStoreWithSelector = function(d, c, f, u, s) {
|
|
220
|
+
var a = i(null);
|
|
221
|
+
if (a.current === null) {
|
|
222
|
+
var n = { hasValue: !1, value: null };
|
|
223
|
+
a.current = n;
|
|
224
|
+
} else
|
|
225
|
+
n = a.current;
|
|
226
|
+
a = p(
|
|
227
|
+
function() {
|
|
228
|
+
function w(b) {
|
|
229
|
+
if (!_) {
|
|
230
|
+
if (_ = !0, O = b, b = u(b), s !== void 0 && n.hasValue) {
|
|
231
|
+
var E = n.value;
|
|
232
|
+
if (s(E, b))
|
|
233
|
+
return N = E;
|
|
234
|
+
}
|
|
235
|
+
return N = b;
|
|
236
|
+
}
|
|
237
|
+
if (E = N, l(O, b))
|
|
238
|
+
return E;
|
|
239
|
+
var T = u(b);
|
|
240
|
+
return s !== void 0 && s(E, T) ? (O = b, E) : (O = b, N = T);
|
|
241
|
+
}
|
|
242
|
+
var _ = !1, O, N, C = f === void 0 ? null : f;
|
|
243
|
+
return [
|
|
244
|
+
function() {
|
|
245
|
+
return w(c());
|
|
246
|
+
},
|
|
247
|
+
C === null ? void 0 : function() {
|
|
248
|
+
return w(C());
|
|
249
|
+
}
|
|
250
|
+
];
|
|
251
|
+
},
|
|
252
|
+
[c, f, u, s]
|
|
253
|
+
);
|
|
254
|
+
var v = o(d, a[0], a[1]);
|
|
255
|
+
return m(
|
|
256
|
+
function() {
|
|
257
|
+
n.hasValue = !0, n.value = v;
|
|
258
|
+
},
|
|
259
|
+
[v]
|
|
260
|
+
), g(v), v;
|
|
261
|
+
}, typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
|
|
262
|
+
}()), z;
|
|
263
|
+
}
|
|
264
|
+
process.env.NODE_ENV === "production" ? V.exports = Q() : V.exports = X();
|
|
265
|
+
var Z = V.exports;
|
|
266
|
+
const ee = /* @__PURE__ */ q(Z), { useDebugValue: te } = D, { useSyncExternalStoreWithSelector: re } = ee;
|
|
267
|
+
const oe = (e) => e;
|
|
268
|
+
function ne(e, t = oe, r) {
|
|
269
|
+
const l = re(
|
|
270
|
+
e.subscribe,
|
|
271
|
+
e.getState,
|
|
272
|
+
e.getServerState || e.getInitialState,
|
|
273
|
+
t,
|
|
274
|
+
r
|
|
275
|
+
);
|
|
276
|
+
return te(l), l;
|
|
277
|
+
}
|
|
278
|
+
const G = (e) => {
|
|
279
|
+
const t = typeof e == "function" ? U(e) : e, r = (l, o) => ne(t, l, o);
|
|
280
|
+
return Object.assign(r, t), r;
|
|
281
|
+
}, se = (e) => e ? G(e) : G;
|
|
282
|
+
var h = /* @__PURE__ */ ((e) => (e[e.Empty = 0] = "Empty", e[e.Start = 1] = "Start", e[e.End = 2] = "End", e[e.Obstacle = 3] = "Obstacle", e[e.Visited = 4] = "Visited", e[e.Path = 5] = "Path", e))(h || {});
|
|
283
|
+
const k = (e, t) => {
|
|
284
|
+
const r = Math.abs(e.row - t.row), l = Math.abs(e.col - t.col);
|
|
285
|
+
return Math.floor(10 * Math.sqrt(r * r + l * l));
|
|
286
|
+
}, ae = (e, t) => ({
|
|
287
|
+
row: e.row,
|
|
288
|
+
col: e.col,
|
|
289
|
+
g: 0,
|
|
290
|
+
h: k(e, t),
|
|
291
|
+
f: k(e, t),
|
|
292
|
+
parent: null
|
|
293
|
+
}), le = (e, t, r) => {
|
|
294
|
+
const l = [
|
|
295
|
+
{ row: e.row - 1, col: e.col },
|
|
296
|
+
{ row: e.row + 1, col: e.col },
|
|
297
|
+
{ row: e.row, col: e.col - 1 },
|
|
298
|
+
{ row: e.row, col: e.col + 1 }
|
|
299
|
+
];
|
|
300
|
+
return r && l.push(
|
|
301
|
+
{ row: e.row - 1, col: e.col - 1 },
|
|
302
|
+
{ row: e.row - 1, col: e.col + 1 },
|
|
303
|
+
{ row: e.row + 1, col: e.col - 1 },
|
|
304
|
+
{ row: e.row + 1, col: e.col + 1 }
|
|
305
|
+
), l.filter((o) => o.row >= 0 && o.row < t.length && o.col >= 0 && o.col < t[0].length && t[o.row][o.col].state !== h.Obstacle).map((o) => ({
|
|
306
|
+
row: o.row,
|
|
307
|
+
col: o.col,
|
|
308
|
+
state: t[o.row][o.col].state
|
|
309
|
+
}));
|
|
310
|
+
}, ie = (e, t, r) => {
|
|
311
|
+
const l = Math.abs(e.row - t.row), o = Math.abs(e.col - t.col), i = e.g + (l === 0 || o === 0 ? 10 : 14), m = k(t, r), p = i + m;
|
|
312
|
+
return { g: i, h: m, f: p };
|
|
313
|
+
}, ce = (e) => {
|
|
314
|
+
const t = [];
|
|
315
|
+
let r = e;
|
|
316
|
+
for (; r; )
|
|
317
|
+
t.push(r), r = r.parent;
|
|
318
|
+
return t.reverse();
|
|
319
|
+
}, ue = (e, t, r, l) => {
|
|
320
|
+
const o = [], i = [], m = ae(t, r);
|
|
321
|
+
for (o.push(m); o.length > 0; ) {
|
|
322
|
+
o.sort((d, c) => d.f - c.f);
|
|
323
|
+
const p = o.shift();
|
|
324
|
+
if (p.row === r.row && p.col === r.col)
|
|
325
|
+
return i.push(p), { path: ce(p), visitedNodes: i };
|
|
326
|
+
i.push(p);
|
|
327
|
+
const g = le(p, e, l);
|
|
328
|
+
for (const d of g) {
|
|
329
|
+
if (i.some((a) => a.row === d.row && a.col === d.col))
|
|
330
|
+
continue;
|
|
331
|
+
const { g: c, h: f, f: u } = ie(p, d, r), s = o.find(
|
|
332
|
+
(a) => a.row === d.row && a.col === d.col
|
|
333
|
+
);
|
|
334
|
+
if (!s || c < s.g) {
|
|
335
|
+
const a = {
|
|
336
|
+
row: d.row,
|
|
337
|
+
col: d.col,
|
|
338
|
+
g: c,
|
|
339
|
+
h: f,
|
|
340
|
+
f: u,
|
|
341
|
+
parent: p
|
|
342
|
+
};
|
|
343
|
+
s ? (s.g = c, s.f = u, s.parent = p) : o.push(a);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return { path: [], visitedNodes: i };
|
|
348
|
+
}, de = (e) => ({
|
|
349
|
+
cells: Array.from(
|
|
350
|
+
{ length: 8 },
|
|
351
|
+
(t, r) => Array.from({ length: 12 }, (l, o) => ({
|
|
352
|
+
row: r,
|
|
353
|
+
col: o,
|
|
354
|
+
state: h.Empty
|
|
355
|
+
}))
|
|
356
|
+
),
|
|
357
|
+
rows: 8,
|
|
358
|
+
columns: 12,
|
|
359
|
+
startTile: null,
|
|
360
|
+
endTile: null,
|
|
361
|
+
obstacleTiles: [],
|
|
362
|
+
path: [],
|
|
363
|
+
visitedNodes: [],
|
|
364
|
+
setNumberOfColumns: (t) => {
|
|
365
|
+
e((r) => {
|
|
366
|
+
const l = r.cells.map((o) => t > r.columns ? [
|
|
367
|
+
...o,
|
|
368
|
+
...Array.from(
|
|
369
|
+
{ length: t - r.columns },
|
|
370
|
+
(i, m) => ({
|
|
371
|
+
row: o[0].row,
|
|
372
|
+
col: r.columns + m,
|
|
373
|
+
state: h.Empty
|
|
374
|
+
})
|
|
375
|
+
)
|
|
376
|
+
] : o.slice(0, t));
|
|
377
|
+
return {
|
|
378
|
+
...r,
|
|
379
|
+
columns: t,
|
|
380
|
+
cells: l
|
|
381
|
+
};
|
|
382
|
+
});
|
|
383
|
+
},
|
|
384
|
+
setNumberOfRows: (t) => {
|
|
385
|
+
e((r) => {
|
|
386
|
+
let l = [...r.cells];
|
|
387
|
+
return t > r.rows ? l = [
|
|
388
|
+
...l,
|
|
389
|
+
...Array.from(
|
|
390
|
+
{ length: t - r.rows },
|
|
391
|
+
(o, i) => Array.from({ length: r.columns }, (m, p) => ({
|
|
392
|
+
row: r.rows + i,
|
|
393
|
+
col: p,
|
|
394
|
+
state: h.Empty
|
|
395
|
+
}))
|
|
396
|
+
)
|
|
397
|
+
] : l = l.slice(0, t), {
|
|
398
|
+
...r,
|
|
399
|
+
rows: t,
|
|
400
|
+
cells: l
|
|
401
|
+
};
|
|
402
|
+
});
|
|
403
|
+
},
|
|
404
|
+
setCellState: (t, r, l) => {
|
|
405
|
+
e((o) => {
|
|
406
|
+
const i = o.cells.map(
|
|
407
|
+
(d) => d.map((c) => ({ ...c }))
|
|
408
|
+
);
|
|
409
|
+
let m = o.startTile, p = o.endTile, g = [...o.obstacleTiles];
|
|
410
|
+
switch (l === h.Start && o.startTile && (i[o.startTile.row][o.startTile.col].state = h.Empty, m = null), l === h.End && o.endTile && (i[o.endTile.row][o.endTile.col].state = h.Empty, p = null), i[t][r].state = l, l) {
|
|
411
|
+
case h.Start:
|
|
412
|
+
m = { row: t, col: r };
|
|
413
|
+
break;
|
|
414
|
+
case h.End:
|
|
415
|
+
p = { row: t, col: r };
|
|
416
|
+
break;
|
|
417
|
+
case h.Obstacle:
|
|
418
|
+
g.some((d) => d.row === t && d.col === r) || g.push({ row: t, col: r });
|
|
419
|
+
break;
|
|
420
|
+
case h.Empty:
|
|
421
|
+
g = g.filter(
|
|
422
|
+
(d) => !(d.row === t && d.col === r)
|
|
423
|
+
);
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
...o,
|
|
428
|
+
cells: i,
|
|
429
|
+
startTile: m,
|
|
430
|
+
endTile: p,
|
|
431
|
+
obstacleTiles: g
|
|
432
|
+
};
|
|
433
|
+
});
|
|
434
|
+
},
|
|
435
|
+
resetCells: () => {
|
|
436
|
+
e((t) => ({
|
|
437
|
+
...t,
|
|
438
|
+
cells: t.cells.map(
|
|
439
|
+
(r) => r.map((l) => ({
|
|
440
|
+
...l,
|
|
441
|
+
state: h.Empty
|
|
442
|
+
}))
|
|
443
|
+
),
|
|
444
|
+
startTile: null,
|
|
445
|
+
endTile: null,
|
|
446
|
+
obstacleTiles: [],
|
|
447
|
+
path: [],
|
|
448
|
+
visitedNodes: []
|
|
449
|
+
}));
|
|
450
|
+
},
|
|
451
|
+
handleFindPath: (t) => {
|
|
452
|
+
e((r) => {
|
|
453
|
+
const l = r.cells.flat().find((i) => i.state === h.Start), o = r.cells.flat().find((i) => i.state === h.End);
|
|
454
|
+
if (l && o) {
|
|
455
|
+
const i = r.cells.map(
|
|
456
|
+
(d) => d.map((c) => ({
|
|
457
|
+
row: c.row,
|
|
458
|
+
col: c.col,
|
|
459
|
+
state: c.state
|
|
460
|
+
}))
|
|
461
|
+
), { path: m, visitedNodes: p } = ue(i, l, o, t);
|
|
462
|
+
return (async (d, c) => {
|
|
463
|
+
for (let f of c)
|
|
464
|
+
await new Promise((u) => setTimeout(u, 100)), e((u) => {
|
|
465
|
+
const s = u.cells.map(
|
|
466
|
+
(a) => a.map((n) => ({
|
|
467
|
+
...n,
|
|
468
|
+
state: f.row === n.row && f.col === n.col && n.state === h.Empty ? h.Visited : n.state
|
|
469
|
+
}))
|
|
470
|
+
);
|
|
471
|
+
return {
|
|
472
|
+
...u,
|
|
473
|
+
cells: s,
|
|
474
|
+
visitedNodes: [...u.visitedNodes, f]
|
|
475
|
+
};
|
|
476
|
+
});
|
|
477
|
+
for (let f of d)
|
|
478
|
+
await new Promise((u) => setTimeout(u, 250)), e((u) => {
|
|
479
|
+
const s = u.cells.map(
|
|
480
|
+
(a) => a.map((n) => ({
|
|
481
|
+
...n,
|
|
482
|
+
state: f.row === n.row && f.col === n.col ? h.Path : n.state
|
|
483
|
+
}))
|
|
484
|
+
);
|
|
485
|
+
return {
|
|
486
|
+
...u,
|
|
487
|
+
cells: s,
|
|
488
|
+
path: [...u.path, f]
|
|
489
|
+
};
|
|
490
|
+
});
|
|
491
|
+
})(m, p), { ...r, path: [], visitedNodes: [] };
|
|
492
|
+
}
|
|
493
|
+
return r;
|
|
494
|
+
});
|
|
495
|
+
},
|
|
496
|
+
setPath: (t) => {
|
|
497
|
+
e((r) => {
|
|
498
|
+
const l = r.cells.map(
|
|
499
|
+
(o) => o.map((i) => ({
|
|
500
|
+
...i,
|
|
501
|
+
state: t.some((m) => m.row === i.row && m.col === i.col) ? h.Path : i.state
|
|
502
|
+
}))
|
|
503
|
+
);
|
|
504
|
+
return {
|
|
505
|
+
...r,
|
|
506
|
+
cells: l
|
|
507
|
+
};
|
|
508
|
+
});
|
|
509
|
+
},
|
|
510
|
+
setVisitedNodes: (t) => {
|
|
511
|
+
e((r) => {
|
|
512
|
+
const l = r.cells.map(
|
|
513
|
+
(o) => o.map((i) => ({
|
|
514
|
+
...i,
|
|
515
|
+
state: t.some((m) => m.row === i.row && m.col === i.col) && i.state === h.Empty ? h.Visited : i.state
|
|
516
|
+
}))
|
|
517
|
+
);
|
|
518
|
+
return {
|
|
519
|
+
...r,
|
|
520
|
+
cells: l
|
|
521
|
+
};
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}), fe = (e) => ({
|
|
525
|
+
activeButton: h.Start,
|
|
526
|
+
setSelectedButtonState: (t) => e({ activeButton: t }),
|
|
527
|
+
canTravelDiagonally: !0,
|
|
528
|
+
setCanTravelDiagonally: (t) => e({ canTravelDiagonally: t })
|
|
529
|
+
}), K = se((e, t, r) => ({
|
|
530
|
+
...de(e),
|
|
531
|
+
...fe(e)
|
|
532
|
+
}));
|
|
533
|
+
const he = () => {
|
|
534
|
+
var u;
|
|
535
|
+
const { cells: e, activeButton: t, setCellState: r, setSelectedButtonState: l, visitedNodes: o, path: i } = K(), [m, p] = H({ width: window.innerWidth, height: window.innerHeight });
|
|
536
|
+
$(() => {
|
|
537
|
+
const s = () => {
|
|
538
|
+
p({ width: window.innerWidth, height: window.innerHeight });
|
|
539
|
+
};
|
|
540
|
+
return window.addEventListener("resize", s), () => window.removeEventListener("resize", s);
|
|
541
|
+
}, []);
|
|
542
|
+
const g = (s, a) => {
|
|
543
|
+
switch (r(s, a, t), t) {
|
|
544
|
+
case h.Start:
|
|
545
|
+
l(h.End);
|
|
546
|
+
break;
|
|
547
|
+
case h.End:
|
|
548
|
+
l(h.Obstacle);
|
|
549
|
+
break;
|
|
550
|
+
}
|
|
551
|
+
}, d = (s, a) => {
|
|
552
|
+
const n = o.find((v) => v.row === s && v.col === a);
|
|
553
|
+
return n ? { g: n.g, h: n.h, f: n.f } : { g: null, h: null, f: null };
|
|
554
|
+
}, f = (() => {
|
|
555
|
+
var T;
|
|
556
|
+
const s = m.width < 768, a = m.width < 1024, n = s ? Math.min(m.width * 0.98, 500) : a ? Math.min(m.width * 0.95, 800) : Math.min(m.width * 0.9, 1e3), v = s ? Math.min(m.height * 0.75, 500) : a ? Math.min(m.height * 0.8, 700) : Math.min(m.height * 0.85, 800), w = ((T = e[0]) == null ? void 0 : T.length) || 1, _ = e.length || 1, O = s ? 16 : 24, N = (n - O) / w, C = (v - O) / _;
|
|
557
|
+
return Math.max(s ? 30 : 40, Math.min(N, C, s ? 50 : a ? 70 : 90));
|
|
558
|
+
})();
|
|
559
|
+
return /* @__PURE__ */ S("div", { className: "grid-wrapper", children: /* @__PURE__ */ S(
|
|
560
|
+
"div",
|
|
561
|
+
{
|
|
562
|
+
className: "grid-container",
|
|
563
|
+
style: {
|
|
564
|
+
display: "grid",
|
|
565
|
+
gridTemplateColumns: `repeat(${((u = e[0]) == null ? void 0 : u.length) || 1}, ${f}px)`,
|
|
566
|
+
gridTemplateRows: `repeat(${e.length || 1}, ${f}px)`,
|
|
567
|
+
gap: "1px",
|
|
568
|
+
padding: "8px",
|
|
569
|
+
background: "var(--bg-secondary)",
|
|
570
|
+
borderRadius: "8px",
|
|
571
|
+
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.1)",
|
|
572
|
+
border: "1px solid var(--border-color)"
|
|
573
|
+
},
|
|
574
|
+
children: e.map(
|
|
575
|
+
(s, a) => s.map((n, v) => {
|
|
576
|
+
const w = i.some((E) => E.row === n.row && E.col === n.col), _ = o.some((E) => E.row === n.row && E.col === n.col), { g: O, h: N, f: C } = d(n.row, n.col);
|
|
577
|
+
let b = me(n, _);
|
|
578
|
+
if (w) {
|
|
579
|
+
const E = i.findIndex((T) => T.row === n.row && T.col === n.col);
|
|
580
|
+
E === 0 ? b = "var(--cell-start)" : E === i.length - 1 ? b = "var(--cell-end)" : b = "var(--cell-path)";
|
|
581
|
+
}
|
|
582
|
+
return /* @__PURE__ */ y(
|
|
583
|
+
"div",
|
|
584
|
+
{
|
|
585
|
+
className: "grid-cell",
|
|
586
|
+
onClick: () => g(a, v),
|
|
587
|
+
style: {
|
|
588
|
+
width: f,
|
|
589
|
+
height: f,
|
|
590
|
+
backgroundColor: b,
|
|
591
|
+
border: "1px solid var(--cell-border)",
|
|
592
|
+
cursor: "pointer",
|
|
593
|
+
transition: "all 0.15s ease",
|
|
594
|
+
position: "relative",
|
|
595
|
+
display: "flex",
|
|
596
|
+
justifyContent: "center",
|
|
597
|
+
alignItems: "center",
|
|
598
|
+
borderRadius: "2px"
|
|
599
|
+
},
|
|
600
|
+
onMouseEnter: (E) => {
|
|
601
|
+
n.state === h.Empty && (E.currentTarget.style.backgroundColor = "var(--bg-tertiary)", E.currentTarget.style.transform = "scale(1.02)");
|
|
602
|
+
},
|
|
603
|
+
onMouseLeave: (E) => {
|
|
604
|
+
n.state === h.Empty && (E.currentTarget.style.backgroundColor = b, E.currentTarget.style.transform = "scale(1)");
|
|
605
|
+
},
|
|
606
|
+
children: [
|
|
607
|
+
_ && /* @__PURE__ */ y("div", { className: "cell-values", children: [
|
|
608
|
+
/* @__PURE__ */ y("div", { className: "value-h", children: [
|
|
609
|
+
"h",
|
|
610
|
+
N
|
|
611
|
+
] }),
|
|
612
|
+
/* @__PURE__ */ y("div", { className: "value-f", children: [
|
|
613
|
+
"f",
|
|
614
|
+
C
|
|
615
|
+
] }),
|
|
616
|
+
/* @__PURE__ */ y("div", { className: "value-g", children: [
|
|
617
|
+
"g",
|
|
618
|
+
O
|
|
619
|
+
] })
|
|
620
|
+
] }),
|
|
621
|
+
n.state === h.Start && /* @__PURE__ */ S("div", { className: "cell-indicator start", children: "●" }),
|
|
622
|
+
n.state === h.End && /* @__PURE__ */ S("div", { className: "cell-indicator end", children: "●" }),
|
|
623
|
+
n.state === h.Obstacle && /* @__PURE__ */ S("div", { className: "cell-indicator obstacle", children: "■" })
|
|
624
|
+
]
|
|
625
|
+
},
|
|
626
|
+
`${a}-${v}`
|
|
627
|
+
);
|
|
628
|
+
})
|
|
629
|
+
)
|
|
630
|
+
}
|
|
631
|
+
) });
|
|
632
|
+
}, me = (e, t) => {
|
|
633
|
+
if (t)
|
|
634
|
+
return e.state === h.Start ? "var(--cell-start)" : e.state === h.End ? "var(--cell-end)" : "var(--cell-visited)";
|
|
635
|
+
switch (e.state) {
|
|
636
|
+
case h.Start:
|
|
637
|
+
return "var(--cell-start)";
|
|
638
|
+
case h.End:
|
|
639
|
+
return "var(--cell-end)";
|
|
640
|
+
case h.Obstacle:
|
|
641
|
+
return "var(--cell-obstacle)";
|
|
642
|
+
case h.Empty:
|
|
643
|
+
return "var(--cell-empty)";
|
|
644
|
+
default:
|
|
645
|
+
return "var(--cell-empty)";
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
const pe = () => {
|
|
649
|
+
const {
|
|
650
|
+
activeButton: e,
|
|
651
|
+
setSelectedButtonState: t,
|
|
652
|
+
resetCells: r,
|
|
653
|
+
rows: l,
|
|
654
|
+
columns: o,
|
|
655
|
+
setNumberOfRows: i,
|
|
656
|
+
setNumberOfColumns: m,
|
|
657
|
+
handleFindPath: p,
|
|
658
|
+
canTravelDiagonally: g,
|
|
659
|
+
setCanTravelDiagonally: d
|
|
660
|
+
} = K(), [c, f] = H(() => {
|
|
661
|
+
const w = localStorage.getItem("darkMode");
|
|
662
|
+
return w ? JSON.parse(w) : !1;
|
|
663
|
+
});
|
|
664
|
+
$(() => {
|
|
665
|
+
localStorage.setItem("darkMode", JSON.stringify(c)), document.documentElement.setAttribute("data-theme", c ? "dark" : "light");
|
|
666
|
+
}, [c]);
|
|
667
|
+
const u = () => {
|
|
668
|
+
f(!c);
|
|
669
|
+
}, s = [
|
|
670
|
+
{ label: "Start", state: h.Start },
|
|
671
|
+
{ label: "End", state: h.End },
|
|
672
|
+
{ label: "Obstacle", state: h.Obstacle },
|
|
673
|
+
{ label: "Clear", state: h.Empty },
|
|
674
|
+
{ label: "Reset", state: null }
|
|
675
|
+
], a = (w) => {
|
|
676
|
+
w === null ? n() : t(w);
|
|
677
|
+
}, n = () => {
|
|
678
|
+
r(), t(h.Start);
|
|
679
|
+
}, v = () => {
|
|
680
|
+
p(g);
|
|
681
|
+
};
|
|
682
|
+
return /* @__PURE__ */ S("div", { className: "control-panel", children: /* @__PURE__ */ y("div", { className: "control-grid", children: [
|
|
683
|
+
/* @__PURE__ */ y("div", { className: "control-group tools", children: [
|
|
684
|
+
/* @__PURE__ */ S("h3", { className: "group-title", children: "Tools" }),
|
|
685
|
+
/* @__PURE__ */ S("div", { className: "button-group", children: s.map((w, _) => /* @__PURE__ */ S(
|
|
686
|
+
"button",
|
|
687
|
+
{
|
|
688
|
+
className: `control-button ${w.label.toLowerCase()} ${e === w.state ? "active" : ""}`,
|
|
689
|
+
onClick: () => a(w.state),
|
|
690
|
+
children: w.label
|
|
691
|
+
},
|
|
692
|
+
_
|
|
693
|
+
)) })
|
|
694
|
+
] }),
|
|
695
|
+
/* @__PURE__ */ y("div", { className: "control-group actions", children: [
|
|
696
|
+
/* @__PURE__ */ S("h3", { className: "group-title", children: "Actions" }),
|
|
697
|
+
/* @__PURE__ */ y("div", { className: "button-group", children: [
|
|
698
|
+
/* @__PURE__ */ S(
|
|
699
|
+
"button",
|
|
700
|
+
{
|
|
701
|
+
className: "control-button find-path",
|
|
702
|
+
onClick: v,
|
|
703
|
+
children: "Find Path"
|
|
704
|
+
}
|
|
705
|
+
),
|
|
706
|
+
/* @__PURE__ */ S(
|
|
707
|
+
"button",
|
|
708
|
+
{
|
|
709
|
+
className: `control-button diagonal ${g ? "active" : ""}`,
|
|
710
|
+
onClick: () => d(!g),
|
|
711
|
+
children: g ? "Diagonal On" : "Diagonal Off"
|
|
712
|
+
}
|
|
713
|
+
),
|
|
714
|
+
/* @__PURE__ */ S(
|
|
715
|
+
"button",
|
|
716
|
+
{
|
|
717
|
+
className: `control-button theme-toggle ${c ? "active" : ""}`,
|
|
718
|
+
onClick: u,
|
|
719
|
+
title: c ? "Switch to light mode" : "Switch to dark mode",
|
|
720
|
+
children: c ? "☀️ Light" : "🌙 Dark"
|
|
721
|
+
}
|
|
722
|
+
)
|
|
723
|
+
] })
|
|
724
|
+
] }),
|
|
725
|
+
/* @__PURE__ */ y("div", { className: "control-group size", children: [
|
|
726
|
+
/* @__PURE__ */ S("h3", { className: "group-title", children: "Grid Size" }),
|
|
727
|
+
/* @__PURE__ */ y("div", { className: "size-controls", children: [
|
|
728
|
+
/* @__PURE__ */ y("div", { className: "size-control", children: [
|
|
729
|
+
/* @__PURE__ */ S("label", { className: "size-label", children: "Rows" }),
|
|
730
|
+
/* @__PURE__ */ y("div", { className: "size-buttons", children: [
|
|
731
|
+
/* @__PURE__ */ S(
|
|
732
|
+
"button",
|
|
733
|
+
{
|
|
734
|
+
className: "size-button",
|
|
735
|
+
onClick: () => i(Math.max(5, l - 1)),
|
|
736
|
+
disabled: l <= 5,
|
|
737
|
+
children: "−"
|
|
738
|
+
}
|
|
739
|
+
),
|
|
740
|
+
/* @__PURE__ */ S("span", { className: "size-value", children: l }),
|
|
741
|
+
/* @__PURE__ */ S(
|
|
742
|
+
"button",
|
|
743
|
+
{
|
|
744
|
+
className: "size-button",
|
|
745
|
+
onClick: () => i(Math.min(50, l + 1)),
|
|
746
|
+
disabled: l >= 50,
|
|
747
|
+
children: "+"
|
|
748
|
+
}
|
|
749
|
+
)
|
|
750
|
+
] })
|
|
751
|
+
] }),
|
|
752
|
+
/* @__PURE__ */ y("div", { className: "size-control", children: [
|
|
753
|
+
/* @__PURE__ */ S("label", { className: "size-label", children: "Columns" }),
|
|
754
|
+
/* @__PURE__ */ y("div", { className: "size-buttons", children: [
|
|
755
|
+
/* @__PURE__ */ S(
|
|
756
|
+
"button",
|
|
757
|
+
{
|
|
758
|
+
className: "size-button",
|
|
759
|
+
onClick: () => m(Math.max(5, o - 1)),
|
|
760
|
+
disabled: o <= 5,
|
|
761
|
+
children: "−"
|
|
762
|
+
}
|
|
763
|
+
),
|
|
764
|
+
/* @__PURE__ */ S("span", { className: "size-value", children: o }),
|
|
765
|
+
/* @__PURE__ */ S(
|
|
766
|
+
"button",
|
|
767
|
+
{
|
|
768
|
+
className: "size-button",
|
|
769
|
+
onClick: () => m(Math.min(50, o + 1)),
|
|
770
|
+
disabled: o >= 50,
|
|
771
|
+
children: "+"
|
|
772
|
+
}
|
|
773
|
+
)
|
|
774
|
+
] })
|
|
775
|
+
] })
|
|
776
|
+
] })
|
|
777
|
+
] })
|
|
778
|
+
] }) });
|
|
779
|
+
}, ve = () => /* @__PURE__ */ y("div", { className: "app-container", children: [
|
|
780
|
+
/* @__PURE__ */ S("header", { className: "app-header", children: /* @__PURE__ */ S("h1", { className: "app-title", children: "A* Pathfinding" }) }),
|
|
781
|
+
/* @__PURE__ */ S("main", { className: "app-main", children: /* @__PURE__ */ S(he, {}) }),
|
|
782
|
+
/* @__PURE__ */ S("footer", { className: "app-footer", children: /* @__PURE__ */ S(pe, {}) })
|
|
783
|
+
] });
|
|
784
|
+
function Se() {
|
|
785
|
+
return /* @__PURE__ */ S(ve, {});
|
|
786
|
+
}
|
|
787
|
+
export {
|
|
788
|
+
Se as AStarVisualizer,
|
|
789
|
+
h as CellState,
|
|
790
|
+
ve as Layout
|
|
791
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
(function(T,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],u):(T=typeof globalThis<"u"?globalThis:T||self,u(T.AStarVisualizer={},T["react/jsx-runtime"],T.React))})(this,function(T,u,C){"use strict";const x=e=>{let t;const r=new Set,l=(i,h)=>{const d=typeof i=="function"?i(t):i;if(!Object.is(d,t)){const s=t;t=h??(typeof d!="object"||d===null)?d:Object.assign({},t,d),r.forEach(a=>a(t,s))}},o=()=>t,g={setState:l,getState:o,getInitialState:()=>f,subscribe:i=>(r.add(i),()=>r.delete(i)),destroy:()=>{r.clear()}},f=t=e(l,o,g);return g},R=e=>e?x(e):x;function q(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var A={exports:{}},M={},L={exports:{}},z={};/**
|
|
2
|
+
* @license React
|
|
3
|
+
* use-sync-external-store-shim.production.js
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
6
|
+
*
|
|
7
|
+
* This source code is licensed under the MIT license found in the
|
|
8
|
+
* LICENSE file in the root directory of this source tree.
|
|
9
|
+
*/var B;function J(){if(B)return z;B=1;var e=C;function t(h,d){return h===d&&(h!==0||1/h===1/d)||h!==h&&d!==d}var r=typeof Object.is=="function"?Object.is:t,l=e.useState,o=e.useEffect,c=e.useLayoutEffect,m=e.useDebugValue;function v(h,d){var s=d(),a=l({inst:{value:s,getSnapshot:d}}),n=a[0].inst,w=a[1];return c(function(){n.value=s,n.getSnapshot=d,g(n)&&w({inst:n})},[h,s,d]),o(function(){return g(n)&&w({inst:n}),h(function(){g(n)&&w({inst:n})})},[h]),m(s),s}function g(h){var d=h.getSnapshot;h=h.value;try{var s=d();return!r(h,s)}catch{return!0}}function f(h,d){return d()}var i=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?f:v;return z.useSyncExternalStore=e.useSyncExternalStore!==void 0?e.useSyncExternalStore:i,z}var V={};/**
|
|
10
|
+
* @license React
|
|
11
|
+
* use-sync-external-store-shim.development.js
|
|
12
|
+
*
|
|
13
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14
|
+
*
|
|
15
|
+
* This source code is licensed under the MIT license found in the
|
|
16
|
+
* LICENSE file in the root directory of this source tree.
|
|
17
|
+
*/var j;function Y(){return j||(j=1,process.env.NODE_ENV!=="production"&&function(){function e(s,a){return s===a&&(s!==0||1/s===1/a)||s!==s&&a!==a}function t(s,a){i||o.startTransition===void 0||(i=!0,console.error("You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release."));var n=a();if(!h){var w=a();c(n,w)||(console.error("The result of getSnapshot should be cached to avoid an infinite loop"),h=!0)}w=m({inst:{value:n,getSnapshot:a}});var S=w[0].inst,_=w[1];return g(function(){S.value=n,S.getSnapshot=a,r(S)&&_({inst:S})},[s,n,a]),v(function(){return r(S)&&_({inst:S}),s(function(){r(S)&&_({inst:S})})},[s]),f(n),n}function r(s){var a=s.getSnapshot;s=s.value;try{var n=a();return!c(s,n)}catch{return!0}}function l(s,a){return a()}typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart=="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());var o=C,c=typeof Object.is=="function"?Object.is:e,m=o.useState,v=o.useEffect,g=o.useLayoutEffect,f=o.useDebugValue,i=!1,h=!1,d=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?l:t;V.useSyncExternalStore=o.useSyncExternalStore!==void 0?o.useSyncExternalStore:d,typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop=="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error())}()),V}var I;function W(){return I||(I=1,process.env.NODE_ENV==="production"?L.exports=J():L.exports=Y()),L.exports}/**
|
|
18
|
+
* @license React
|
|
19
|
+
* use-sync-external-store-shim/with-selector.production.js
|
|
20
|
+
*
|
|
21
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
22
|
+
*
|
|
23
|
+
* This source code is licensed under the MIT license found in the
|
|
24
|
+
* LICENSE file in the root directory of this source tree.
|
|
25
|
+
*/var G;function Q(){if(G)return M;G=1;var e=C,t=W();function r(f,i){return f===i&&(f!==0||1/f===1/i)||f!==f&&i!==i}var l=typeof Object.is=="function"?Object.is:r,o=t.useSyncExternalStore,c=e.useRef,m=e.useEffect,v=e.useMemo,g=e.useDebugValue;return M.useSyncExternalStoreWithSelector=function(f,i,h,d,s){var a=c(null);if(a.current===null){var n={hasValue:!1,value:null};a.current=n}else n=a.current;a=v(function(){function S(b){if(!_){if(_=!0,y=b,b=d(b),s!==void 0&&n.hasValue){var E=n.value;if(s(E,b))return O=E}return O=b}if(E=O,l(y,b))return E;var N=d(b);return s!==void 0&&s(E,N)?(y=b,E):(y=b,O=N)}var _=!1,y,O,D=h===void 0?null:h;return[function(){return S(i())},D===null?void 0:function(){return S(D())}]},[i,h,d,s]);var w=o(f,a[0],a[1]);return m(function(){n.hasValue=!0,n.value=w},[w]),g(w),w},M}var k={};/**
|
|
26
|
+
* @license React
|
|
27
|
+
* use-sync-external-store-shim/with-selector.development.js
|
|
28
|
+
*
|
|
29
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
30
|
+
*
|
|
31
|
+
* This source code is licensed under the MIT license found in the
|
|
32
|
+
* LICENSE file in the root directory of this source tree.
|
|
33
|
+
*/var H;function X(){return H||(H=1,process.env.NODE_ENV!=="production"&&function(){function e(f,i){return f===i&&(f!==0||1/f===1/i)||f!==f&&i!==i}typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart=="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());var t=C,r=W(),l=typeof Object.is=="function"?Object.is:e,o=r.useSyncExternalStore,c=t.useRef,m=t.useEffect,v=t.useMemo,g=t.useDebugValue;k.useSyncExternalStoreWithSelector=function(f,i,h,d,s){var a=c(null);if(a.current===null){var n={hasValue:!1,value:null};a.current=n}else n=a.current;a=v(function(){function S(b){if(!_){if(_=!0,y=b,b=d(b),s!==void 0&&n.hasValue){var E=n.value;if(s(E,b))return O=E}return O=b}if(E=O,l(y,b))return E;var N=d(b);return s!==void 0&&s(E,N)?(y=b,E):(y=b,O=N)}var _=!1,y,O,D=h===void 0?null:h;return[function(){return S(i())},D===null?void 0:function(){return S(D())}]},[i,h,d,s]);var w=o(f,a[0],a[1]);return m(function(){n.hasValue=!0,n.value=w},[w]),g(w),w},typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop=="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error())}()),k}process.env.NODE_ENV==="production"?A.exports=Q():A.exports=X();var Z=A.exports;const $=q(Z),{useDebugValue:ee}=C,{useSyncExternalStoreWithSelector:te}=$;let ve=!1;const re=e=>e;function oe(e,t=re,r){const l=te(e.subscribe,e.getState,e.getServerState||e.getInitialState,t,r);return ee(l),l}const F=e=>{const t=typeof e=="function"?R(e):e,r=(l,o)=>oe(t,l,o);return Object.assign(r,t),r},ne=e=>e?F(e):F;var p=(e=>(e[e.Empty=0]="Empty",e[e.Start=1]="Start",e[e.End=2]="End",e[e.Obstacle=3]="Obstacle",e[e.Visited=4]="Visited",e[e.Path=5]="Path",e))(p||{});const P=(e,t)=>{const r=Math.abs(e.row-t.row),l=Math.abs(e.col-t.col);return Math.floor(10*Math.sqrt(r*r+l*l))},se=(e,t)=>({row:e.row,col:e.col,g:0,h:P(e,t),f:P(e,t),parent:null}),ae=(e,t,r)=>{const l=[{row:e.row-1,col:e.col},{row:e.row+1,col:e.col},{row:e.row,col:e.col-1},{row:e.row,col:e.col+1}];return r&&l.push({row:e.row-1,col:e.col-1},{row:e.row-1,col:e.col+1},{row:e.row+1,col:e.col-1},{row:e.row+1,col:e.col+1}),l.filter(o=>o.row>=0&&o.row<t.length&&o.col>=0&&o.col<t[0].length&&t[o.row][o.col].state!==p.Obstacle).map(o=>({row:o.row,col:o.col,state:t[o.row][o.col].state}))},le=(e,t,r)=>{const l=Math.abs(e.row-t.row),o=Math.abs(e.col-t.col),c=e.g+(l===0||o===0?10:14),m=P(t,r),v=c+m;return{g:c,h:m,f:v}},ce=e=>{const t=[];let r=e;for(;r;)t.push(r),r=r.parent;return t.reverse()},ie=(e,t,r,l)=>{const o=[],c=[],m=se(t,r);for(o.push(m);o.length>0;){o.sort((f,i)=>f.f-i.f);const v=o.shift();if(v.row===r.row&&v.col===r.col)return c.push(v),{path:ce(v),visitedNodes:c};c.push(v);const g=ae(v,e,l);for(const f of g){if(c.some(a=>a.row===f.row&&a.col===f.col))continue;const{g:i,h,f:d}=le(v,f,r),s=o.find(a=>a.row===f.row&&a.col===f.col);if(!s||i<s.g){const a={row:f.row,col:f.col,g:i,h,f:d,parent:v};s?(s.g=i,s.f=d,s.parent=v):o.push(a)}}}return{path:[],visitedNodes:c}},ue=e=>({cells:Array.from({length:8},(t,r)=>Array.from({length:12},(l,o)=>({row:r,col:o,state:p.Empty}))),rows:8,columns:12,startTile:null,endTile:null,obstacleTiles:[],path:[],visitedNodes:[],setNumberOfColumns:t=>{e(r=>{const l=r.cells.map(o=>t>r.columns?[...o,...Array.from({length:t-r.columns},(c,m)=>({row:o[0].row,col:r.columns+m,state:p.Empty}))]:o.slice(0,t));return{...r,columns:t,cells:l}})},setNumberOfRows:t=>{e(r=>{let l=[...r.cells];return t>r.rows?l=[...l,...Array.from({length:t-r.rows},(o,c)=>Array.from({length:r.columns},(m,v)=>({row:r.rows+c,col:v,state:p.Empty})))]:l=l.slice(0,t),{...r,rows:t,cells:l}})},setCellState:(t,r,l)=>{e(o=>{const c=o.cells.map(f=>f.map(i=>({...i})));let m=o.startTile,v=o.endTile,g=[...o.obstacleTiles];switch(l===p.Start&&o.startTile&&(c[o.startTile.row][o.startTile.col].state=p.Empty,m=null),l===p.End&&o.endTile&&(c[o.endTile.row][o.endTile.col].state=p.Empty,v=null),c[t][r].state=l,l){case p.Start:m={row:t,col:r};break;case p.End:v={row:t,col:r};break;case p.Obstacle:g.some(f=>f.row===t&&f.col===r)||g.push({row:t,col:r});break;case p.Empty:g=g.filter(f=>!(f.row===t&&f.col===r));break}return{...o,cells:c,startTile:m,endTile:v,obstacleTiles:g}})},resetCells:()=>{e(t=>({...t,cells:t.cells.map(r=>r.map(l=>({...l,state:p.Empty}))),startTile:null,endTile:null,obstacleTiles:[],path:[],visitedNodes:[]}))},handleFindPath:t=>{e(r=>{const l=r.cells.flat().find(c=>c.state===p.Start),o=r.cells.flat().find(c=>c.state===p.End);if(l&&o){const c=r.cells.map(f=>f.map(i=>({row:i.row,col:i.col,state:i.state}))),{path:m,visitedNodes:v}=ie(c,l,o,t);return(async(f,i)=>{for(let h of i)await new Promise(d=>setTimeout(d,100)),e(d=>{const s=d.cells.map(a=>a.map(n=>({...n,state:h.row===n.row&&h.col===n.col&&n.state===p.Empty?p.Visited:n.state})));return{...d,cells:s,visitedNodes:[...d.visitedNodes,h]}});for(let h of f)await new Promise(d=>setTimeout(d,250)),e(d=>{const s=d.cells.map(a=>a.map(n=>({...n,state:h.row===n.row&&h.col===n.col?p.Path:n.state})));return{...d,cells:s,path:[...d.path,h]}})})(m,v),{...r,path:[],visitedNodes:[]}}return r})},setPath:t=>{e(r=>{const l=r.cells.map(o=>o.map(c=>({...c,state:t.some(m=>m.row===c.row&&m.col===c.col)?p.Path:c.state})));return{...r,cells:l}})},setVisitedNodes:t=>{e(r=>{const l=r.cells.map(o=>o.map(c=>({...c,state:t.some(m=>m.row===c.row&&m.col===c.col)&&c.state===p.Empty?p.Visited:c.state})));return{...r,cells:l}})}}),de=e=>({activeButton:p.Start,setSelectedButtonState:t=>e({activeButton:t}),canTravelDiagonally:!0,setCanTravelDiagonally:t=>e({canTravelDiagonally:t})}),K=ne((e,t,r)=>({...ue(e),...de(e)})),we="",fe=()=>{var d;const{cells:e,activeButton:t,setCellState:r,setSelectedButtonState:l,visitedNodes:o,path:c}=K(),[m,v]=C.useState({width:window.innerWidth,height:window.innerHeight});C.useEffect(()=>{const s=()=>{v({width:window.innerWidth,height:window.innerHeight})};return window.addEventListener("resize",s),()=>window.removeEventListener("resize",s)},[]);const g=(s,a)=>{switch(r(s,a,t),t){case p.Start:l(p.End);break;case p.End:l(p.Obstacle);break}},f=(s,a)=>{const n=o.find(w=>w.row===s&&w.col===a);return n?{g:n.g,h:n.h,f:n.f}:{g:null,h:null,f:null}},h=(()=>{var N;const s=m.width<768,a=m.width<1024,n=s?Math.min(m.width*.98,500):a?Math.min(m.width*.95,800):Math.min(m.width*.9,1e3),w=s?Math.min(m.height*.75,500):a?Math.min(m.height*.8,700):Math.min(m.height*.85,800),S=((N=e[0])==null?void 0:N.length)||1,_=e.length||1,y=s?16:24,O=(n-y)/S,D=(w-y)/_;return Math.max(s?30:40,Math.min(O,D,s?50:a?70:90))})();return u.jsx("div",{className:"grid-wrapper",children:u.jsx("div",{className:"grid-container",style:{display:"grid",gridTemplateColumns:`repeat(${((d=e[0])==null?void 0:d.length)||1}, ${h}px)`,gridTemplateRows:`repeat(${e.length||1}, ${h}px)`,gap:"1px",padding:"8px",background:"var(--bg-secondary)",borderRadius:"8px",boxShadow:"0 2px 8px rgba(0, 0, 0, 0.1)",border:"1px solid var(--border-color)"},children:e.map((s,a)=>s.map((n,w)=>{const S=c.some(E=>E.row===n.row&&E.col===n.col),_=o.some(E=>E.row===n.row&&E.col===n.col),{g:y,h:O,f:D}=f(n.row,n.col);let b=he(n,_);if(S){const E=c.findIndex(N=>N.row===n.row&&N.col===n.col);E===0?b="var(--cell-start)":E===c.length-1?b="var(--cell-end)":b="var(--cell-path)"}return u.jsxs("div",{className:"grid-cell",onClick:()=>g(a,w),style:{width:h,height:h,backgroundColor:b,border:"1px solid var(--cell-border)",cursor:"pointer",transition:"all 0.15s ease",position:"relative",display:"flex",justifyContent:"center",alignItems:"center",borderRadius:"2px"},onMouseEnter:E=>{n.state===p.Empty&&(E.currentTarget.style.backgroundColor="var(--bg-tertiary)",E.currentTarget.style.transform="scale(1.02)")},onMouseLeave:E=>{n.state===p.Empty&&(E.currentTarget.style.backgroundColor=b,E.currentTarget.style.transform="scale(1)")},children:[_&&u.jsxs("div",{className:"cell-values",children:[u.jsxs("div",{className:"value-h",children:["h",O]}),u.jsxs("div",{className:"value-f",children:["f",D]}),u.jsxs("div",{className:"value-g",children:["g",y]})]}),n.state===p.Start&&u.jsx("div",{className:"cell-indicator start",children:"●"}),n.state===p.End&&u.jsx("div",{className:"cell-indicator end",children:"●"}),n.state===p.Obstacle&&u.jsx("div",{className:"cell-indicator obstacle",children:"■"})]},`${a}-${w}`)}))})})},he=(e,t)=>{if(t)return e.state===p.Start?"var(--cell-start)":e.state===p.End?"var(--cell-end)":"var(--cell-visited)";switch(e.state){case p.Start:return"var(--cell-start)";case p.End:return"var(--cell-end)";case p.Obstacle:return"var(--cell-obstacle)";case p.Empty:return"var(--cell-empty)";default:return"var(--cell-empty)"}},Se="",pe=()=>{const{activeButton:e,setSelectedButtonState:t,resetCells:r,rows:l,columns:o,setNumberOfRows:c,setNumberOfColumns:m,handleFindPath:v,canTravelDiagonally:g,setCanTravelDiagonally:f}=K(),[i,h]=C.useState(()=>{const S=localStorage.getItem("darkMode");return S?JSON.parse(S):!1});C.useEffect(()=>{localStorage.setItem("darkMode",JSON.stringify(i)),document.documentElement.setAttribute("data-theme",i?"dark":"light")},[i]);const d=()=>{h(!i)},s=[{label:"Start",state:p.Start},{label:"End",state:p.End},{label:"Obstacle",state:p.Obstacle},{label:"Clear",state:p.Empty},{label:"Reset",state:null}],a=S=>{S===null?n():t(S)},n=()=>{r(),t(p.Start)},w=()=>{v(g)};return u.jsx("div",{className:"control-panel",children:u.jsxs("div",{className:"control-grid",children:[u.jsxs("div",{className:"control-group tools",children:[u.jsx("h3",{className:"group-title",children:"Tools"}),u.jsx("div",{className:"button-group",children:s.map((S,_)=>u.jsx("button",{className:`control-button ${S.label.toLowerCase()} ${e===S.state?"active":""}`,onClick:()=>a(S.state),children:S.label},_))})]}),u.jsxs("div",{className:"control-group actions",children:[u.jsx("h3",{className:"group-title",children:"Actions"}),u.jsxs("div",{className:"button-group",children:[u.jsx("button",{className:"control-button find-path",onClick:w,children:"Find Path"}),u.jsx("button",{className:`control-button diagonal ${g?"active":""}`,onClick:()=>f(!g),children:g?"Diagonal On":"Diagonal Off"}),u.jsx("button",{className:`control-button theme-toggle ${i?"active":""}`,onClick:d,title:i?"Switch to light mode":"Switch to dark mode",children:i?"☀️ Light":"🌙 Dark"})]})]}),u.jsxs("div",{className:"control-group size",children:[u.jsx("h3",{className:"group-title",children:"Grid Size"}),u.jsxs("div",{className:"size-controls",children:[u.jsxs("div",{className:"size-control",children:[u.jsx("label",{className:"size-label",children:"Rows"}),u.jsxs("div",{className:"size-buttons",children:[u.jsx("button",{className:"size-button",onClick:()=>c(Math.max(5,l-1)),disabled:l<=5,children:"−"}),u.jsx("span",{className:"size-value",children:l}),u.jsx("button",{className:"size-button",onClick:()=>c(Math.min(50,l+1)),disabled:l>=50,children:"+"})]})]}),u.jsxs("div",{className:"size-control",children:[u.jsx("label",{className:"size-label",children:"Columns"}),u.jsxs("div",{className:"size-buttons",children:[u.jsx("button",{className:"size-button",onClick:()=>m(Math.max(5,o-1)),disabled:o<=5,children:"−"}),u.jsx("span",{className:"size-value",children:o}),u.jsx("button",{className:"size-button",onClick:()=>m(Math.min(50,o+1)),disabled:o>=50,children:"+"})]})]})]})]})]})})},U=()=>u.jsxs("div",{className:"app-container",children:[u.jsx("header",{className:"app-header",children:u.jsx("h1",{className:"app-title",children:"A* Pathfinding"})}),u.jsx("main",{className:"app-main",children:u.jsx(fe,{})}),u.jsx("footer",{className:"app-footer",children:u.jsx(pe,{})})]});function me(){return u.jsx(U,{})}T.AStarVisualizer=me,T.CellState=p,T.Layout=U,Object.defineProperty(T,Symbol.toStringTag,{value:"Module"})});
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.grid-wrapper{display:flex;justify-content:center;align-items:center;width:100%;height:100%}.grid-container{display:grid;gap:1px;padding:8px;background:var(--bg-secondary);border-radius:8px;box-shadow:0 2px 8px #0000001a;border:1px solid var(--border-color)}.grid-cell{position:relative;display:flex;justify-content:center;align-items:center;border:1px solid var(--cell-border);cursor:pointer;transition:all .15s ease;border-radius:2px;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.grid-cell:hover{transform:scale(1.02)}.grid-cell:active{transform:scale(.98)}.cell-values{position:absolute;top:0;left:0;right:0;bottom:0;display:grid;grid-template-columns:1fr 1fr 1fr;grid-template-rows:1fr 1fr;font-size:.75rem;font-weight:700;color:#fff;text-shadow:0 2px 4px rgba(0,0,0,.9);pointer-events:none}.value-h{grid-column:1;grid-row:1;display:flex;align-items:center;justify-content:center;font-size:.65rem}.value-f{grid-column:3;grid-row:1;display:flex;align-items:center;justify-content:center;font-size:.65rem}.value-g{grid-column:2;grid-row:2;display:flex;align-items:center;justify-content:center;font-size:.65rem}.cell-indicator{font-size:1.2rem;font-weight:700;color:#fff;text-shadow:0 2px 4px rgba(0,0,0,.9)}.cell-indicator.start,.cell-indicator.end,.cell-indicator.obstacle{color:#fff}@media (max-width: 768px){.cell-values{font-size:.6rem}.value-h,.value-f,.value-g{font-size:.5rem}.cell-indicator{font-size:1rem}}@media (max-width: 480px){.cell-values{font-size:.5rem}.value-h,.value-f,.value-g{font-size:.4rem}.cell-indicator{font-size:.9rem}}.control-panel{padding:1rem;background:var(--bg-secondary);border-radius:8px;border:1px solid var(--border-color);box-shadow:0 2px 8px #0000001a}.control-grid{display:grid;grid-template-columns:1fr;gap:1.5rem;align-items:start}.control-group{display:flex;flex-direction:column;gap:.75rem}.group-title{font-size:.875rem;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.05em;margin:0;padding-bottom:.5rem;border-bottom:1px solid var(--border-color)}.button-group{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center;justify-content:center}.control-button{padding:.5rem 1rem;font-size:.875rem;font-weight:500;color:var(--text-primary);background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:6px;cursor:pointer;transition:all .2s ease;outline:none;min-width:fit-content}.control-button:hover{border-color:var(--border-hover);background:var(--bg-tertiary)}.control-button:active{transform:translateY(1px)}.control-button:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.control-button.start.active{background:var(--success);border-color:var(--success);color:#fff}.control-button.end.active{background:var(--danger);border-color:var(--danger);color:#fff}.control-button.obstacle.active{background:var(--text-primary);border-color:var(--text-primary);color:#fff}.control-button.clear.active{background:var(--text-muted);border-color:var(--text-muted);color:#fff}.control-button.reset{background:var(--danger);border-color:var(--danger);color:#fff}.control-button.reset:hover{background:var(--danger-hover);border-color:var(--danger-hover)}.control-button.find-path{background:var(--primary);border-color:var(--primary);color:#fff}.control-button.find-path:hover{background:var(--primary-hover);border-color:var(--primary-hover)}.control-button.diagonal.active{background:var(--warning);border-color:var(--warning);color:#fff}.control-button.diagonal:hover{background:var(--warning-hover);border-color:var(--warning-hover)}.control-button.theme-toggle{background:var(--text-muted);border-color:var(--text-muted);color:#fff}.control-button.theme-toggle:hover{background:var(--text-secondary);border-color:var(--text-secondary)}.control-button.theme-toggle.active{background:var(--warning);border-color:var(--warning);color:#fff}.control-button.theme-toggle.active:hover{background:var(--warning-hover);border-color:var(--warning-hover)}.size-controls{display:flex;flex-direction:column;gap:.75rem;align-items:center}.size-control{display:flex;flex-direction:column;gap:.25rem;align-items:center}.size-label{font-size:.75rem;font-weight:500;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.05em}.size-buttons{display:flex;align-items:center;gap:.5rem}.size-button{display:flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;font-size:1rem;font-weight:600;color:var(--text-primary);background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:4px;cursor:pointer;transition:all .2s ease;outline:none}.size-button:hover:not(:disabled){background:var(--primary);border-color:var(--primary);color:#fff}.size-button:active:not(:disabled){transform:scale(.95)}.size-button:disabled{opacity:.4;cursor:not-allowed}.size-button:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.size-value{display:flex;align-items:center;justify-content:center;min-width:2.5rem;height:1.75rem;font-size:.875rem;font-weight:600;color:var(--text-primary);background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px}@media (min-width: 1024px){.control-grid{grid-template-columns:2fr 1fr 1fr;gap:2rem}.control-group.tools{grid-column:1}.control-group.actions{grid-column:2}.control-group.size{grid-column:3}}@media (min-width: 768px) and (max-width: 1023px){.control-grid{grid-template-columns:1fr 1fr;gap:1.5rem}.control-group.tools{grid-column:1 / -1}.control-group.actions{grid-column:1}.control-group.size{grid-column:2}}@media (max-width: 768px){.control-panel{padding:.75rem}.control-grid{gap:1rem}.button-group{gap:.375rem}.control-button{padding:.375rem .75rem;font-size:.8125rem}.size-controls{gap:.5rem}.size-buttons{gap:.375rem}.size-button{width:1.5rem;height:1.5rem;font-size:.875rem}.size-value{min-width:2rem;height:1.5rem;font-size:.8125rem}}@media (max-width: 480px){.control-panel{padding:.5rem}.control-grid{gap:.75rem}.button-group{flex-direction:column;gap:.25rem}.control-button{width:100%;padding:.5rem;font-size:.75rem}.size-controls{gap:.375rem}.size-buttons{gap:.25rem}.size-button{width:1.25rem;height:1.25rem;font-size:.75rem}.size-value{min-width:1.75rem;height:1.25rem;font-size:.75rem}}
|
package/dist/vite.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "astar-visualizer",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "A React component for visualizing A* pathfinding algorithm",
|
|
7
|
+
"main": "./dist/astar-visualizer.umd.cjs",
|
|
8
|
+
"module": "./dist/astar-visualizer.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/astar-visualizer.js",
|
|
13
|
+
"require": "./dist/astar-visualizer.umd.cjs",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
},
|
|
16
|
+
"./style.css": "./dist/style.css"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"astar",
|
|
23
|
+
"pathfinding",
|
|
24
|
+
"visualizer",
|
|
25
|
+
"react",
|
|
26
|
+
"algorithm",
|
|
27
|
+
"visualization"
|
|
28
|
+
],
|
|
29
|
+
"author": "",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": ""
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"dev": "vite",
|
|
37
|
+
"build": "tsc && vite build",
|
|
38
|
+
"build:lib": "tsc --project tsconfig.lib.json && vite build --config vite.config.lib.ts",
|
|
39
|
+
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
40
|
+
"preview": "vite preview",
|
|
41
|
+
"storybook": "storybook dev -p 6006",
|
|
42
|
+
"build-storybook": "storybook build",
|
|
43
|
+
"format": "prettier --write .",
|
|
44
|
+
"test": "vitest",
|
|
45
|
+
"prepublishOnly": "npm run build:lib"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"react": "^18.2.0",
|
|
49
|
+
"react-dom": "^18.2.0"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"framer-motion": "^10.16.4",
|
|
53
|
+
"zustand": "^4.4.1"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/react": "^18.2.15",
|
|
57
|
+
"@types/react-dom": "^18.2.7",
|
|
58
|
+
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
59
|
+
"@typescript-eslint/parser": "^6.21.0",
|
|
60
|
+
"@vitejs/plugin-react": "^4.0.3",
|
|
61
|
+
"eslint": "^8.57.1",
|
|
62
|
+
"eslint-config-prettier": "^9.0.0",
|
|
63
|
+
"eslint-plugin-prettier": "^5.0.0",
|
|
64
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
65
|
+
"eslint-plugin-react-refresh": "^0.4.3",
|
|
66
|
+
"husky": "^8.0.3",
|
|
67
|
+
"lint-staged": "^14.0.1",
|
|
68
|
+
"storybook": "^7.4.2",
|
|
69
|
+
"typescript": "^5.0.2",
|
|
70
|
+
"vite": "^4.4.5",
|
|
71
|
+
"vitest": "^3.0.4"
|
|
72
|
+
}
|
|
73
|
+
}
|