fantasy-map-router 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 ADDED
@@ -0,0 +1 @@
1
+ React component for fantasy map with router
@@ -0,0 +1,2 @@
1
+ .map-wrapper{background-color:#111;font-family:Cormorant Garamond,serif;position:relative;overflow:hidden}.map-container{background-color:#dcb88c;width:100%;height:100%}.parchment-overlay{pointer-events:none;z-index:400;mix-blend-mode:multiply;opacity:.9;background-color:#dcb88c;background-image:url(https://www.transparenttextures.com/patterns/aged-paper.png);position:absolute;inset:0}.burnt-edges{pointer-events:none;z-index:401;position:absolute;inset:0;box-shadow:inset 0 0 200px #2a1a0ef2}.l2-window{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);z-index:1000;background-color:#0a0a0ad9;border:2px solid #5c4a33;width:20rem;padding:.25rem;transition:background-color .3s,-webkit-backdrop-filter .3s,backdrop-filter .3s;position:absolute;top:1.5rem;left:1.5rem;box-shadow:0 0 15px #000000e6}.l2-window-collapsed{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background-color:#0a0a0a66}.l2-window-inner{border:1px solid #3a2e20;height:100%;padding:1.25rem}.l2-header{cursor:pointer;border-bottom:2px solid #5c4a33;justify-content:space-between;align-items:center;margin-bottom:1.25rem;padding-bottom:.75rem;transition:border-color .2s;display:flex}.l2-header:hover{border-bottom-color:#8c7853}.l2-header-collapsed{border-bottom:none;margin-bottom:0;padding-bottom:0}.l2-header-left{align-items:center;gap:.75rem;display:flex}.l2-toggle-btn{color:#8c7853;cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;padding:0;transition:color .2s;display:flex}.l2-header:hover .l2-toggle-btn{color:#fc0}.l2-collapsed-summary{cursor:pointer;border-top:1px dashed #5c4a33;margin-top:.5rem;padding-top:.5rem;transition:opacity .2s}.l2-collapsed-summary:hover{opacity:.8}.l2-summary-route{color:#d4c4a1;align-items:center;gap:.5rem;margin-bottom:.25rem;font-size:.95rem;display:flex}.l2-summary-point{color:#fc0;white-space:nowrap;text-overflow:ellipsis;max-width:110px;font-weight:600;overflow:hidden}.l2-summary-arrow{color:#8c7853;flex-shrink:0}.l2-summary-stats{color:#a89f91;font-size:.85rem;font-style:italic}.l2-header-icon{color:#fc0;width:1.5rem;height:1.5rem}.l2-title{color:#fc0;letter-spacing:.025em;text-transform:uppercase;filter:drop-shadow(0 1px 2px #000);margin:0;font-size:1.25rem;font-weight:700}.l2-form{flex-direction:column;gap:1.25rem;display:flex}.l2-form-group{flex-direction:column;display:flex}.l2-label{color:#8c7853;letter-spacing:.05em;margin-bottom:.25rem;font-size:.875rem;font-weight:700;display:block}.l2-input-wrapper{position:relative}.l2-input-icon{width:1rem;height:1rem;position:absolute;top:50%;left:.5rem;transform:translateY(-50%)}.l2-icon-blue{color:#06c}.l2-icon-red{color:#c00}.l2-input{color:#d4c4a1;box-sizing:border-box;background-color:#111;border:1px solid #5c4a33;width:100%;padding:.375rem .75rem .375rem 2rem;font-family:Cormorant Garamond,serif;font-size:1rem;transition:border-color .2s;box-shadow:inset 0 2px 4px #00000080}.l2-input:focus{border-color:#fc0;outline:none}.l2-input::placeholder{color:#4a3b29}.l2-error{color:#f66;text-align:center;background-color:#300c;border:1px solid #c00;padding:.5rem;font-size:.875rem;font-weight:700}.l2-button-group{gap:.5rem;padding-top:.5rem;display:flex}.l2-button{letter-spacing:.05em;cursor:pointer;border:1px solid #5c4a33;justify-content:center;align-items:center;gap:.5rem;padding:.375rem 1rem;font-size:.875rem;font-weight:700;transition:all .2s;display:flex;box-shadow:0 2px 5px #00000080}.l2-button:disabled{opacity:.5;cursor:not-allowed}.l2-button-primary{color:#fc0;background:linear-gradient(#3a2e20,#1a1510);flex:1}.l2-button-primary:hover:not(:disabled){background:linear-gradient(#4a3b29,#2a221a)}.l2-button-secondary{color:#8c7853;background:linear-gradient(#222,#000)}.l2-button-secondary:hover:not(:disabled){background:linear-gradient(#333,#111)}.l2-btn-icon{width:1rem;height:1rem}.l2-route-info{background-color:#11111180;border:1px solid #3a2e20;flex-direction:column;gap:.25rem;margin-top:1.25rem;padding:.75rem;display:flex}.l2-route-stat-row{justify-content:space-between;align-items:center;font-size:1rem;display:flex}.l2-stat-label{color:#8c7853;font-weight:700}.l2-stat-value{color:#d4c4a1;font-weight:700}.l2-marker-container{flex-direction:column;align-items:center;display:flex;position:relative}.l2-marker-dest-icon-wrapper{justify-content:center;align-items:center;width:2rem;height:2rem;display:flex}.l2-marker-dest-icon{background-color:#c00;border:3px solid #fc0;width:1rem;height:1rem;transform:rotate(45deg);box-shadow:0 0 15px #c00}.l2-marker-origin-icon-wrapper{justify-content:center;align-items:center;width:1.5rem;height:1.5rem;display:flex}.l2-marker-origin-icon{background-color:#06c;border:2px solid #fff;width:.75rem;height:.75rem;transform:rotate(45deg);box-shadow:0 0 10px #06c}.l2-marker-label{white-space:nowrap;filter:drop-shadow(0 2px 2px #000);font-weight:700;position:absolute}.l2-marker-label-dest{color:#fc0;font-size:1.125rem;top:2rem}.l2-marker-label-origin{color:#fff;font-size:.875rem;top:1.5rem}.l2-route-line{filter:drop-shadow(0 0 5px #fa0c)}
2
+ /*$vite$:1*/
@@ -0,0 +1,434 @@
1
+ import { useEffect as e, useState as t } from "react";
2
+ import { MapContainer as n, Marker as r, Polyline as i, TileLayer as a, useMap as o } from "react-leaflet";
3
+ import s from "leaflet";
4
+ import { ChevronDown as c, ChevronUp as l, Crosshair as u, Map as d, MapPin as f, Navigation as p } from "lucide-react";
5
+ //#region \0rolldown/runtime.js
6
+ var m = (e, t) => () => (t || e((t = { exports: {} }).exports, t), t.exports), h = /* @__PURE__ */ ((e) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(e, { get: (e, t) => (typeof require < "u" ? require : e)[t] }) : e)(function(e) {
7
+ if (typeof require < "u") return require.apply(this, arguments);
8
+ throw Error("Calling `require` for \"" + e + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
9
+ }), g = /* @__PURE__ */ m(((e) => {
10
+ var t = Symbol.for("react.transitional.element"), n = Symbol.for("react.fragment");
11
+ function r(e, n, r) {
12
+ var i = null;
13
+ if (r !== void 0 && (i = "" + r), n.key !== void 0 && (i = "" + n.key), "key" in n) for (var a in r = {}, n) a !== "key" && (r[a] = n[a]);
14
+ else r = n;
15
+ return n = r.ref, {
16
+ $$typeof: t,
17
+ type: e,
18
+ key: i,
19
+ ref: n === void 0 ? null : n,
20
+ props: r
21
+ };
22
+ }
23
+ e.Fragment = n, e.jsx = r, e.jsxs = r;
24
+ })), _ = /* @__PURE__ */ m(((e) => {
25
+ process.env.NODE_ENV !== "production" && (function() {
26
+ function t(e) {
27
+ if (e == null) return null;
28
+ if (typeof e == "function") return e.$$typeof === k ? null : e.displayName || e.name || null;
29
+ if (typeof e == "string") return e;
30
+ switch (e) {
31
+ case v: return "Fragment";
32
+ case b: return "Profiler";
33
+ case y: return "StrictMode";
34
+ case w: return "Suspense";
35
+ case T: return "SuspenseList";
36
+ case O: return "Activity";
37
+ }
38
+ if (typeof e == "object") switch (typeof e.tag == "number" && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), e.$$typeof) {
39
+ case _: return "Portal";
40
+ case S: return e.displayName || "Context";
41
+ case x: return (e._context.displayName || "Context") + ".Consumer";
42
+ case C:
43
+ var n = e.render;
44
+ return e = e.displayName, e ||= (e = n.displayName || n.name || "", e === "" ? "ForwardRef" : "ForwardRef(" + e + ")"), e;
45
+ case E: return n = e.displayName || null, n === null ? t(e.type) || "Memo" : n;
46
+ case D:
47
+ n = e._payload, e = e._init;
48
+ try {
49
+ return t(e(n));
50
+ } catch {}
51
+ }
52
+ return null;
53
+ }
54
+ function n(e) {
55
+ return "" + e;
56
+ }
57
+ function r(e) {
58
+ try {
59
+ n(e);
60
+ var t = !1;
61
+ } catch {
62
+ t = !0;
63
+ }
64
+ if (t) {
65
+ t = console;
66
+ var r = t.error, i = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
67
+ return r.call(t, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", i), n(e);
68
+ }
69
+ }
70
+ function i(e) {
71
+ if (e === v) return "<>";
72
+ if (typeof e == "object" && e && e.$$typeof === D) return "<...>";
73
+ try {
74
+ var n = t(e);
75
+ return n ? "<" + n + ">" : "<...>";
76
+ } catch {
77
+ return "<...>";
78
+ }
79
+ }
80
+ function a() {
81
+ var e = A.A;
82
+ return e === null ? null : e.getOwner();
83
+ }
84
+ function o() {
85
+ return Error("react-stack-top-frame");
86
+ }
87
+ function s(e) {
88
+ if (j.call(e, "key")) {
89
+ var t = Object.getOwnPropertyDescriptor(e, "key").get;
90
+ if (t && t.isReactWarning) return !1;
91
+ }
92
+ return e.key !== void 0;
93
+ }
94
+ function c(e, t) {
95
+ function n() {
96
+ P || (P = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", t));
97
+ }
98
+ n.isReactWarning = !0, Object.defineProperty(e, "key", {
99
+ get: n,
100
+ configurable: !0
101
+ });
102
+ }
103
+ function l() {
104
+ var e = t(this.type);
105
+ return F[e] || (F[e] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")), e = this.props.ref, e === void 0 ? null : e;
106
+ }
107
+ function u(e, t, n, r, i, a) {
108
+ var o = n.ref;
109
+ return e = {
110
+ $$typeof: g,
111
+ type: e,
112
+ key: t,
113
+ props: n,
114
+ _owner: r
115
+ }, (o === void 0 ? null : o) === null ? Object.defineProperty(e, "ref", {
116
+ enumerable: !1,
117
+ value: null
118
+ }) : Object.defineProperty(e, "ref", {
119
+ enumerable: !1,
120
+ get: l
121
+ }), e._store = {}, Object.defineProperty(e._store, "validated", {
122
+ configurable: !1,
123
+ enumerable: !1,
124
+ writable: !0,
125
+ value: 0
126
+ }), Object.defineProperty(e, "_debugInfo", {
127
+ configurable: !1,
128
+ enumerable: !1,
129
+ writable: !0,
130
+ value: null
131
+ }), Object.defineProperty(e, "_debugStack", {
132
+ configurable: !1,
133
+ enumerable: !1,
134
+ writable: !0,
135
+ value: i
136
+ }), Object.defineProperty(e, "_debugTask", {
137
+ configurable: !1,
138
+ enumerable: !1,
139
+ writable: !0,
140
+ value: a
141
+ }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
142
+ }
143
+ function d(e, n, i, o, l, d) {
144
+ var p = n.children;
145
+ if (p !== void 0) if (o) if (M(p)) {
146
+ for (o = 0; o < p.length; o++) f(p[o]);
147
+ Object.freeze && Object.freeze(p);
148
+ } else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
149
+ else f(p);
150
+ if (j.call(n, "key")) {
151
+ p = t(e);
152
+ var m = Object.keys(n).filter(function(e) {
153
+ return e !== "key";
154
+ });
155
+ o = 0 < m.length ? "{key: someKey, " + m.join(": ..., ") + ": ...}" : "{key: someKey}", R[p + o] || (m = 0 < m.length ? "{" + m.join(": ..., ") + ": ...}" : "{}", console.error("A props object containing a \"key\" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />", o, p, m, p), R[p + o] = !0);
156
+ }
157
+ if (p = null, i !== void 0 && (r(i), p = "" + i), s(n) && (r(n.key), p = "" + n.key), "key" in n) for (var h in i = {}, n) h !== "key" && (i[h] = n[h]);
158
+ else i = n;
159
+ return p && c(i, typeof e == "function" ? e.displayName || e.name || "Unknown" : e), u(e, p, i, a(), l, d);
160
+ }
161
+ function f(e) {
162
+ p(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e && e.$$typeof === D && (e._payload.status === "fulfilled" ? p(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
163
+ }
164
+ function p(e) {
165
+ return typeof e == "object" && !!e && e.$$typeof === g;
166
+ }
167
+ var m = h("react"), g = Symbol.for("react.transitional.element"), _ = Symbol.for("react.portal"), v = Symbol.for("react.fragment"), y = Symbol.for("react.strict_mode"), b = Symbol.for("react.profiler"), x = Symbol.for("react.consumer"), S = Symbol.for("react.context"), C = Symbol.for("react.forward_ref"), w = Symbol.for("react.suspense"), T = Symbol.for("react.suspense_list"), E = Symbol.for("react.memo"), D = Symbol.for("react.lazy"), O = Symbol.for("react.activity"), k = Symbol.for("react.client.reference"), A = m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, j = Object.prototype.hasOwnProperty, M = Array.isArray, N = console.createTask ? console.createTask : function() {
168
+ return null;
169
+ };
170
+ m = { react_stack_bottom_frame: function(e) {
171
+ return e();
172
+ } };
173
+ var P, F = {}, I = m.react_stack_bottom_frame.bind(m, o)(), L = N(i(o)), R = {};
174
+ e.Fragment = v, e.jsx = function(e, t, n) {
175
+ var r = 1e4 > A.recentlyCreatedOwnerStacks++;
176
+ return d(e, t, n, !1, r ? Error("react-stack-top-frame") : I, r ? N(i(e)) : L);
177
+ }, e.jsxs = function(e, t, n) {
178
+ var r = 1e4 > A.recentlyCreatedOwnerStacks++;
179
+ return d(e, t, n, !0, r ? Error("react-stack-top-frame") : I, r ? N(i(e)) : L);
180
+ };
181
+ })();
182
+ })), v = (/* @__PURE__ */ m(((e, t) => {
183
+ process.env.NODE_ENV === "production" ? t.exports = g() : t.exports = _();
184
+ })))(), y = s.divIcon({
185
+ className: "bg-transparent",
186
+ html: "<div class=\"l2-marker-container\">\n <div class=\"l2-marker-dest-icon-wrapper\">\n <div class=\"l2-marker-dest-icon\"></div>\n </div>\n <div class=\"l2-marker-label l2-marker-label-dest\">Target</div>\n </div>",
187
+ iconSize: [32, 32],
188
+ iconAnchor: [16, 16]
189
+ }), b = s.divIcon({
190
+ className: "bg-transparent",
191
+ html: "<div class=\"l2-marker-container\">\n <div class=\"l2-marker-origin-icon-wrapper\">\n <div class=\"l2-marker-origin-icon\"></div>\n </div>\n <div class=\"l2-marker-label l2-marker-label-origin\">You</div>\n </div>",
192
+ iconSize: [24, 24],
193
+ iconAnchor: [12, 12]
194
+ });
195
+ function x({ route: t, origin: n, destination: r }) {
196
+ let i = o();
197
+ return e(() => {
198
+ t.length > 0 ? i.fitBounds(s.latLngBounds(t), {
199
+ padding: [50, 50],
200
+ animate: !0,
201
+ duration: 1.5
202
+ }) : n && r ? i.fitBounds(s.latLngBounds([n, r]), {
203
+ padding: [50, 50],
204
+ animate: !0,
205
+ duration: 1.5
206
+ }) : n ? i.setView(n, 10, { animate: !0 }) : r ? i.setView(r, 10, { animate: !0 }) : i.setView([50, 10], 4, { animate: !0 });
207
+ }, [
208
+ t,
209
+ n,
210
+ r,
211
+ i
212
+ ]), null;
213
+ }
214
+ function S({ width: e = "100%", height: o = "100vh" }) {
215
+ let [s, m] = t(""), [h, g] = t(""), [_, S] = t(null), [C, w] = t(null), [T, E] = t([]), [D, O] = t(""), [k, A] = t(""), [j, M] = t(!1), [N, P] = t(""), [F, I] = t(!0), L = async (e, t) => {
216
+ let n = await (await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(e)}`)).json();
217
+ if (n && n.length > 0) return [parseFloat(n[0].lat), parseFloat(n[0].lon)];
218
+ throw Error(`${t} not found`);
219
+ }, R = async (e, t) => {
220
+ let n = await (await fetch(`https://router.project-osrm.org/route/v1/driving/${e[1]},${e[0]};${t[1]},${t[0]}?overview=full&geometries=geojson`)).json();
221
+ if (n.code === "Ok") {
222
+ let e = n.routes[0].geometry.coordinates.map((e) => [e[1], e[0]]), t = (n.routes[0].distance / 1e3).toFixed(1), r = Math.round(n.routes[0].duration / 60), i = r > 60 ? `${Math.floor(r / 60)} h ${r % 60} m` : `${r} m`;
223
+ return {
224
+ coords: e,
225
+ distance: `${t} km`,
226
+ duration: i
227
+ };
228
+ }
229
+ throw Error("Route not found");
230
+ };
231
+ return /* @__PURE__ */ (0, v.jsxs)("div", {
232
+ className: "map-wrapper",
233
+ style: {
234
+ width: e,
235
+ height: o
236
+ },
237
+ children: [
238
+ /* @__PURE__ */ (0, v.jsxs)(n, {
239
+ center: [50, 10],
240
+ zoom: 4,
241
+ zoomControl: !1,
242
+ attributionControl: !1,
243
+ className: "map-container",
244
+ children: [
245
+ /* @__PURE__ */ (0, v.jsx)(a, {
246
+ url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
247
+ attribution: "© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a>",
248
+ className: "fantasy-tiles"
249
+ }),
250
+ /* @__PURE__ */ (0, v.jsx)(x, {
251
+ route: T,
252
+ origin: _,
253
+ destination: C
254
+ }),
255
+ C && /* @__PURE__ */ (0, v.jsx)(r, {
256
+ position: C,
257
+ icon: y
258
+ }),
259
+ _ && /* @__PURE__ */ (0, v.jsx)(r, {
260
+ position: _,
261
+ icon: b
262
+ }),
263
+ T.length > 0 && /* @__PURE__ */ (0, v.jsx)(i, {
264
+ positions: T,
265
+ pathOptions: {
266
+ color: "#ffaa00",
267
+ weight: 4,
268
+ opacity: .9,
269
+ dashArray: "8, 8",
270
+ lineCap: "round",
271
+ className: "l2-route-line"
272
+ }
273
+ })
274
+ ]
275
+ }),
276
+ /* @__PURE__ */ (0, v.jsx)("div", { className: "parchment-overlay" }),
277
+ /* @__PURE__ */ (0, v.jsx)("div", { className: "burnt-edges" }),
278
+ /* @__PURE__ */ (0, v.jsx)("div", {
279
+ className: `l2-window ${F ? "" : "l2-window-collapsed"}`,
280
+ children: /* @__PURE__ */ (0, v.jsxs)("div", {
281
+ className: "l2-window-inner",
282
+ children: [
283
+ /* @__PURE__ */ (0, v.jsxs)("div", {
284
+ className: `l2-header ${F ? "" : "l2-header-collapsed"}`,
285
+ onClick: () => I(!F),
286
+ children: [/* @__PURE__ */ (0, v.jsxs)("div", {
287
+ className: "l2-header-left",
288
+ children: [/* @__PURE__ */ (0, v.jsx)(d, { className: "l2-header-icon" }), /* @__PURE__ */ (0, v.jsx)("h2", {
289
+ className: "l2-title",
290
+ children: "World Map"
291
+ })]
292
+ }), /* @__PURE__ */ (0, v.jsx)("button", {
293
+ className: "l2-toggle-btn",
294
+ type: "button",
295
+ children: F ? /* @__PURE__ */ (0, v.jsx)(l, { className: "w-5 h-5" }) : /* @__PURE__ */ (0, v.jsx)(c, { className: "w-5 h-5" })
296
+ })]
297
+ }),
298
+ !F && (s || h) && /* @__PURE__ */ (0, v.jsxs)("div", {
299
+ className: "l2-collapsed-summary",
300
+ onClick: () => I(!0),
301
+ children: [/* @__PURE__ */ (0, v.jsxs)("div", {
302
+ className: "l2-summary-route",
303
+ children: [
304
+ /* @__PURE__ */ (0, v.jsx)("span", {
305
+ className: "l2-summary-point",
306
+ title: s,
307
+ children: s || "..."
308
+ }),
309
+ /* @__PURE__ */ (0, v.jsx)("span", {
310
+ className: "l2-summary-arrow",
311
+ children: "→"
312
+ }),
313
+ /* @__PURE__ */ (0, v.jsx)("span", {
314
+ className: "l2-summary-point",
315
+ title: h,
316
+ children: h || "..."
317
+ })
318
+ ]
319
+ }), D && k && /* @__PURE__ */ (0, v.jsxs)("div", {
320
+ className: "l2-summary-stats",
321
+ children: [
322
+ D,
323
+ " • ",
324
+ k
325
+ ]
326
+ })]
327
+ }),
328
+ F && /* @__PURE__ */ (0, v.jsxs)("div", {
329
+ className: "l2-window-body",
330
+ children: [/* @__PURE__ */ (0, v.jsxs)("form", {
331
+ onSubmit: async (e) => {
332
+ if (e.preventDefault(), !(!s || !h)) {
333
+ M(!0), P("");
334
+ try {
335
+ let e = await L(s, "Origin"), t = await L(h, "Destination");
336
+ S(e), w(t);
337
+ let n = await R(e, t);
338
+ E(n.coords), O(n.distance), A(n.duration), I(!1);
339
+ } catch (e) {
340
+ console.error("Routing error:", e), P(e.message || "Failed to calculate route."), E([]);
341
+ } finally {
342
+ M(!1);
343
+ }
344
+ }
345
+ },
346
+ className: "l2-form",
347
+ children: [
348
+ /* @__PURE__ */ (0, v.jsxs)("div", {
349
+ className: "l2-form-group",
350
+ children: [/* @__PURE__ */ (0, v.jsx)("label", {
351
+ className: "l2-label",
352
+ children: "Current Location"
353
+ }), /* @__PURE__ */ (0, v.jsxs)("div", {
354
+ className: "l2-input-wrapper",
355
+ children: [/* @__PURE__ */ (0, v.jsx)(u, { className: "l2-input-icon l2-icon-blue" }), /* @__PURE__ */ (0, v.jsx)("input", {
356
+ type: "text",
357
+ value: s,
358
+ onChange: (e) => m(e.target.value),
359
+ placeholder: "Enter city...",
360
+ className: "l2-input"
361
+ })]
362
+ })]
363
+ }),
364
+ /* @__PURE__ */ (0, v.jsxs)("div", {
365
+ className: "l2-form-group",
366
+ children: [/* @__PURE__ */ (0, v.jsx)("label", {
367
+ className: "l2-label",
368
+ children: "Quest Target"
369
+ }), /* @__PURE__ */ (0, v.jsxs)("div", {
370
+ className: "l2-input-wrapper",
371
+ children: [/* @__PURE__ */ (0, v.jsx)(f, { className: "l2-input-icon l2-icon-red" }), /* @__PURE__ */ (0, v.jsx)("input", {
372
+ type: "text",
373
+ value: h,
374
+ onChange: (e) => g(e.target.value),
375
+ placeholder: "Enter destination...",
376
+ className: "l2-input"
377
+ })]
378
+ })]
379
+ }),
380
+ N && /* @__PURE__ */ (0, v.jsx)("div", {
381
+ className: "l2-error",
382
+ children: N
383
+ }),
384
+ /* @__PURE__ */ (0, v.jsxs)("div", {
385
+ className: "l2-button-group",
386
+ children: [/* @__PURE__ */ (0, v.jsxs)("button", {
387
+ type: "submit",
388
+ disabled: j || !s || !h,
389
+ className: "l2-button l2-button-primary",
390
+ children: [/* @__PURE__ */ (0, v.jsx)(p, { className: "l2-btn-icon" }), j ? "Searching..." : "Find Path"]
391
+ }), (T.length > 0 || _ || C) && /* @__PURE__ */ (0, v.jsx)("button", {
392
+ type: "button",
393
+ onClick: () => {
394
+ E([]), S(null), w(null), O(""), A(""), m(""), g(""), P("");
395
+ },
396
+ className: "l2-button l2-button-secondary",
397
+ children: "Clear"
398
+ })]
399
+ })
400
+ ]
401
+ }), T.length > 0 && /* @__PURE__ */ (0, v.jsxs)("div", {
402
+ className: "l2-route-info",
403
+ children: [/* @__PURE__ */ (0, v.jsxs)("div", {
404
+ className: "l2-route-stat-row",
405
+ children: [/* @__PURE__ */ (0, v.jsx)("span", {
406
+ className: "l2-stat-label",
407
+ children: "Distance:"
408
+ }), /* @__PURE__ */ (0, v.jsx)("span", {
409
+ className: "l2-stat-value",
410
+ children: D
411
+ })]
412
+ }), /* @__PURE__ */ (0, v.jsxs)("div", {
413
+ className: "l2-route-stat-row",
414
+ children: [/* @__PURE__ */ (0, v.jsx)("span", {
415
+ className: "l2-stat-label",
416
+ children: "Travel Time:"
417
+ }), /* @__PURE__ */ (0, v.jsx)("span", {
418
+ className: "l2-stat-value",
419
+ children: k
420
+ })]
421
+ })]
422
+ })]
423
+ })
424
+ ]
425
+ })
426
+ })
427
+ ]
428
+ });
429
+ }
430
+ //#endregion
431
+ //#region src/index.ts
432
+ var C = S;
433
+ //#endregion
434
+ export { S as FantasyMap, C as default };
@@ -0,0 +1,16 @@
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`),require(`react-leaflet`),require(`leaflet`),require(`lucide-react`)):typeof define==`function`&&define.amd?define([`exports`,`react`,`react-leaflet`,`leaflet`,`lucide-react`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.FantasyMap={},e.React,e.ReactLeaflet,e.L,e.lucide_react))})(this,function(e,t,n,r,i){Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var a=Object.create,o=Object.defineProperty,s=Object.getOwnPropertyDescriptor,c=Object.getOwnPropertyNames,l=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty,d=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),f=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=c(t),a=0,l=i.length,d;a<l;a++)d=i[a],!u.call(e,d)&&d!==n&&o(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=s(t,d))||r.enumerable});return e},p=(e,t,n)=>(n=e==null?{}:a(l(e)),f(t||!e||!e.__esModule?o(n,`default`,{value:e,enumerable:!0}):n,e));t=p(t),r=p(r);var m=d((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),h=d((e=>{process.env.NODE_ENV!==`production`&&(function(){function t(e){if(e==null)return null;if(typeof e==`function`)return e.$$typeof===O?null:e.displayName||e.name||null;if(typeof e==`string`)return e;switch(e){case _:return`Fragment`;case y:return`Profiler`;case v:return`StrictMode`;case C:return`Suspense`;case w:return`SuspenseList`;case D:return`Activity`}if(typeof e==`object`)switch(typeof e.tag==`number`&&console.error(`Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.`),e.$$typeof){case g:return`Portal`;case x:return e.displayName||`Context`;case b:return(e._context.displayName||`Context`)+`.Consumer`;case S:var n=e.render;return e=e.displayName,e||=(e=n.displayName||n.name||``,e===``?`ForwardRef`:`ForwardRef(`+e+`)`),e;case T:return n=e.displayName||null,n===null?t(e.type)||`Memo`:n;case E:n=e._payload,e=e._init;try{return t(e(n))}catch{}}return null}function n(e){return``+e}function r(e){try{n(e);var t=!1}catch{t=!0}if(t){t=console;var r=t.error,i=typeof Symbol==`function`&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||`Object`;return r.call(t,`The provided key is an unsupported type %s. This value must be coerced to a string before using it here.`,i),n(e)}}function i(e){if(e===_)return`<>`;if(typeof e==`object`&&e&&e.$$typeof===E)return`<...>`;try{var n=t(e);return n?`<`+n+`>`:`<...>`}catch{return`<...>`}}function a(){var e=k.A;return e===null?null:e.getOwner()}function o(){return Error(`react-stack-top-frame`)}function s(e){if(A.call(e,`key`)){var t=Object.getOwnPropertyDescriptor(e,`key`).get;if(t&&t.isReactWarning)return!1}return e.key!==void 0}function c(e,t){function n(){N||(N=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",t))}n.isReactWarning=!0,Object.defineProperty(e,`key`,{get:n,configurable:!0})}function l(){var e=t(this.type);return P[e]||(P[e]=!0,console.error(`Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.`)),e=this.props.ref,e===void 0?null:e}function u(e,t,n,r,i,a){var o=n.ref;return e={$$typeof:h,type:e,key:t,props:n,_owner:r},(o===void 0?null:o)===null?Object.defineProperty(e,`ref`,{enumerable:!1,value:null}):Object.defineProperty(e,`ref`,{enumerable:!1,get:l}),e._store={},Object.defineProperty(e._store,`validated`,{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,`_debugInfo`,{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,`_debugStack`,{configurable:!1,enumerable:!1,writable:!0,value:i}),Object.defineProperty(e,`_debugTask`,{configurable:!1,enumerable:!1,writable:!0,value:a}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function d(e,n,i,o,l,d){var p=n.children;if(p!==void 0)if(o)if(j(p)){for(o=0;o<p.length;o++)f(p[o]);Object.freeze&&Object.freeze(p)}else console.error(`React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.`);else f(p);if(A.call(n,`key`)){p=t(e);var m=Object.keys(n).filter(function(e){return e!==`key`});o=0<m.length?`{key: someKey, `+m.join(`: ..., `)+`: ...}`:`{key: someKey}`,L[p+o]||(m=0<m.length?`{`+m.join(`: ..., `)+`: ...}`:`{}`,console.error(`A props object containing a "key" prop is being spread into JSX:
2
+ let props = %s;
3
+ <%s {...props} />
4
+ React keys must be passed directly to JSX without using spread:
5
+ let props = %s;
6
+ <%s key={someKey} {...props} />`,o,p,m,p),L[p+o]=!0)}if(p=null,i!==void 0&&(r(i),p=``+i),s(n)&&(r(n.key),p=``+n.key),`key`in n)for(var h in i={},n)h!==`key`&&(i[h]=n[h]);else i=n;return p&&c(i,typeof e==`function`?e.displayName||e.name||`Unknown`:e),u(e,p,i,a(),l,d)}function f(e){p(e)?e._store&&(e._store.validated=1):typeof e==`object`&&e&&e.$$typeof===E&&(e._payload.status===`fulfilled`?p(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function p(e){return typeof e==`object`&&!!e&&e.$$typeof===h}var m=require(`react`),h=Symbol.for(`react.transitional.element`),g=Symbol.for(`react.portal`),_=Symbol.for(`react.fragment`),v=Symbol.for(`react.strict_mode`),y=Symbol.for(`react.profiler`),b=Symbol.for(`react.consumer`),x=Symbol.for(`react.context`),S=Symbol.for(`react.forward_ref`),C=Symbol.for(`react.suspense`),w=Symbol.for(`react.suspense_list`),T=Symbol.for(`react.memo`),E=Symbol.for(`react.lazy`),D=Symbol.for(`react.activity`),O=Symbol.for(`react.client.reference`),k=m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,A=Object.prototype.hasOwnProperty,j=Array.isArray,M=console.createTask?console.createTask:function(){return null};m={react_stack_bottom_frame:function(e){return e()}};var N,P={},F=m.react_stack_bottom_frame.bind(m,o)(),I=M(i(o)),L={};e.Fragment=_,e.jsx=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!1,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)},e.jsxs=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!0,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)}})()})),g=d(((e,t)=>{process.env.NODE_ENV===`production`?t.exports=m():t.exports=h()}))(),_=r.default.divIcon({className:`bg-transparent`,html:`<div class="l2-marker-container">
7
+ <div class="l2-marker-dest-icon-wrapper">
8
+ <div class="l2-marker-dest-icon"></div>
9
+ </div>
10
+ <div class="l2-marker-label l2-marker-label-dest">Target</div>
11
+ </div>`,iconSize:[32,32],iconAnchor:[16,16]}),v=r.default.divIcon({className:`bg-transparent`,html:`<div class="l2-marker-container">
12
+ <div class="l2-marker-origin-icon-wrapper">
13
+ <div class="l2-marker-origin-icon"></div>
14
+ </div>
15
+ <div class="l2-marker-label l2-marker-label-origin">You</div>
16
+ </div>`,iconSize:[24,24],iconAnchor:[12,12]});function y({route:e,origin:i,destination:a}){let o=(0,n.useMap)();return(0,t.useEffect)(()=>{e.length>0?o.fitBounds(r.default.latLngBounds(e),{padding:[50,50],animate:!0,duration:1.5}):i&&a?o.fitBounds(r.default.latLngBounds([i,a]),{padding:[50,50],animate:!0,duration:1.5}):i?o.setView(i,10,{animate:!0}):a?o.setView(a,10,{animate:!0}):o.setView([50,10],4,{animate:!0})},[e,i,a,o]),null}function b({width:e=`100%`,height:r=`100vh`}){let[a,o]=(0,t.useState)(``),[s,c]=(0,t.useState)(``),[l,u]=(0,t.useState)(null),[d,f]=(0,t.useState)(null),[p,m]=(0,t.useState)([]),[h,b]=(0,t.useState)(``),[x,S]=(0,t.useState)(``),[C,w]=(0,t.useState)(!1),[T,E]=(0,t.useState)(``),[D,O]=(0,t.useState)(!0),k=async(e,t)=>{let n=await(await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(e)}`)).json();if(n&&n.length>0)return[parseFloat(n[0].lat),parseFloat(n[0].lon)];throw Error(`${t} not found`)},A=async(e,t)=>{let n=await(await fetch(`https://router.project-osrm.org/route/v1/driving/${e[1]},${e[0]};${t[1]},${t[0]}?overview=full&geometries=geojson`)).json();if(n.code===`Ok`){let e=n.routes[0].geometry.coordinates.map(e=>[e[1],e[0]]),t=(n.routes[0].distance/1e3).toFixed(1),r=Math.round(n.routes[0].duration/60),i=r>60?`${Math.floor(r/60)} h ${r%60} m`:`${r} m`;return{coords:e,distance:`${t} km`,duration:i}}throw Error(`Route not found`)};return(0,g.jsxs)(`div`,{className:`map-wrapper`,style:{width:e,height:r},children:[(0,g.jsxs)(n.MapContainer,{center:[50,10],zoom:4,zoomControl:!1,attributionControl:!1,className:`map-container`,children:[(0,g.jsx)(n.TileLayer,{url:`https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`,attribution:`© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>`,className:`fantasy-tiles`}),(0,g.jsx)(y,{route:p,origin:l,destination:d}),d&&(0,g.jsx)(n.Marker,{position:d,icon:_}),l&&(0,g.jsx)(n.Marker,{position:l,icon:v}),p.length>0&&(0,g.jsx)(n.Polyline,{positions:p,pathOptions:{color:`#ffaa00`,weight:4,opacity:.9,dashArray:`8, 8`,lineCap:`round`,className:`l2-route-line`}})]}),(0,g.jsx)(`div`,{className:`parchment-overlay`}),(0,g.jsx)(`div`,{className:`burnt-edges`}),(0,g.jsx)(`div`,{className:`l2-window ${D?``:`l2-window-collapsed`}`,children:(0,g.jsxs)(`div`,{className:`l2-window-inner`,children:[(0,g.jsxs)(`div`,{className:`l2-header ${D?``:`l2-header-collapsed`}`,onClick:()=>O(!D),children:[(0,g.jsxs)(`div`,{className:`l2-header-left`,children:[(0,g.jsx)(i.Map,{className:`l2-header-icon`}),(0,g.jsx)(`h2`,{className:`l2-title`,children:`World Map`})]}),(0,g.jsx)(`button`,{className:`l2-toggle-btn`,type:`button`,children:D?(0,g.jsx)(i.ChevronUp,{className:`w-5 h-5`}):(0,g.jsx)(i.ChevronDown,{className:`w-5 h-5`})})]}),!D&&(a||s)&&(0,g.jsxs)(`div`,{className:`l2-collapsed-summary`,onClick:()=>O(!0),children:[(0,g.jsxs)(`div`,{className:`l2-summary-route`,children:[(0,g.jsx)(`span`,{className:`l2-summary-point`,title:a,children:a||`...`}),(0,g.jsx)(`span`,{className:`l2-summary-arrow`,children:`→`}),(0,g.jsx)(`span`,{className:`l2-summary-point`,title:s,children:s||`...`})]}),h&&x&&(0,g.jsxs)(`div`,{className:`l2-summary-stats`,children:[h,` • `,x]})]}),D&&(0,g.jsxs)(`div`,{className:`l2-window-body`,children:[(0,g.jsxs)(`form`,{onSubmit:async e=>{if(e.preventDefault(),!(!a||!s)){w(!0),E(``);try{let e=await k(a,`Origin`),t=await k(s,`Destination`);u(e),f(t);let n=await A(e,t);m(n.coords),b(n.distance),S(n.duration),O(!1)}catch(e){console.error(`Routing error:`,e),E(e.message||`Failed to calculate route.`),m([])}finally{w(!1)}}},className:`l2-form`,children:[(0,g.jsxs)(`div`,{className:`l2-form-group`,children:[(0,g.jsx)(`label`,{className:`l2-label`,children:`Current Location`}),(0,g.jsxs)(`div`,{className:`l2-input-wrapper`,children:[(0,g.jsx)(i.Crosshair,{className:`l2-input-icon l2-icon-blue`}),(0,g.jsx)(`input`,{type:`text`,value:a,onChange:e=>o(e.target.value),placeholder:`Enter city...`,className:`l2-input`})]})]}),(0,g.jsxs)(`div`,{className:`l2-form-group`,children:[(0,g.jsx)(`label`,{className:`l2-label`,children:`Quest Target`}),(0,g.jsxs)(`div`,{className:`l2-input-wrapper`,children:[(0,g.jsx)(i.MapPin,{className:`l2-input-icon l2-icon-red`}),(0,g.jsx)(`input`,{type:`text`,value:s,onChange:e=>c(e.target.value),placeholder:`Enter destination...`,className:`l2-input`})]})]}),T&&(0,g.jsx)(`div`,{className:`l2-error`,children:T}),(0,g.jsxs)(`div`,{className:`l2-button-group`,children:[(0,g.jsxs)(`button`,{type:`submit`,disabled:C||!a||!s,className:`l2-button l2-button-primary`,children:[(0,g.jsx)(i.Navigation,{className:`l2-btn-icon`}),C?`Searching...`:`Find Path`]}),(p.length>0||l||d)&&(0,g.jsx)(`button`,{type:`button`,onClick:()=>{m([]),u(null),f(null),b(``),S(``),o(``),c(``),E(``)},className:`l2-button l2-button-secondary`,children:`Clear`})]})]}),p.length>0&&(0,g.jsxs)(`div`,{className:`l2-route-info`,children:[(0,g.jsxs)(`div`,{className:`l2-route-stat-row`,children:[(0,g.jsx)(`span`,{className:`l2-stat-label`,children:`Distance:`}),(0,g.jsx)(`span`,{className:`l2-stat-value`,children:h})]}),(0,g.jsxs)(`div`,{className:`l2-route-stat-row`,children:[(0,g.jsx)(`span`,{className:`l2-stat-label`,children:`Travel Time:`}),(0,g.jsx)(`span`,{className:`l2-stat-value`,children:x})]})]})]})]})})]})}var x=b;e.FantasyMap=b,e.default=x});
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @license
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ export default function App(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ export interface FantasyMapProps {
2
+ width?: string | number;
3
+ height?: string | number;
4
+ }
5
+ export default function FantasyMap({ width, height }: FantasyMapProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import { default as FantasyMap, FantasyMapProps } from './components/FantasyMap';
2
+ export { FantasyMap, FantasyMapProps };
3
+ export default FantasyMap;
File without changes
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "fantasy-map-router",
3
+ "version": "1.0.0",
4
+ "description": "A Lineage II style fantasy map component for React",
5
+ "type": "module",
6
+ "main": "./dist/fantasy-map.umd.js",
7
+ "module": "./dist/fantasy-map.es.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/fantasy-map.es.js",
12
+ "require": "./dist/fantasy-map.umd.js"
13
+ },
14
+ "./style.css": "./dist/style.css"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc && vite build"
21
+ },
22
+ "peerDependencies": {
23
+ "leaflet": "^1.9.0",
24
+ "lucide-react": ">=0.546.0",
25
+ "react": "^18.0.0",
26
+ "react-dom": "^18.0.0",
27
+ "react-leaflet": "^4.0.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/express": "^4.17.21",
31
+ "@types/leaflet": "^1.9.21",
32
+ "@types/node": "^22.14.0",
33
+ "@types/react": "^19.2.14",
34
+ "@types/react-dom": "^19.2.3",
35
+ "@vitejs/plugin-react": "^6.0.1",
36
+ "autoprefixer": "^10.4.21",
37
+ "lucide-react": "^1.7.0",
38
+ "react-leaflet": "^5.0.0",
39
+ "tsx": "^4.21.0",
40
+ "typescript": "^6.0.2",
41
+ "vite": "^8.0.3",
42
+ "vite-plugin-dts": "^4.5.4"
43
+ }
44
+ }