@mhmo91/schmancy 0.4.79 → 0.4.80

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.
Files changed (37) hide show
  1. package/ai/area.md +223 -11
  2. package/dist/ai/area.md +223 -11
  3. package/dist/area.cjs +1 -1
  4. package/dist/area.js +13 -12
  5. package/dist/{avatar-Cxu7EOku.cjs → avatar-Bws6p1iq.cjs} +2 -2
  6. package/dist/{avatar-Cxu7EOku.cjs.map → avatar-Bws6p1iq.cjs.map} +1 -1
  7. package/dist/{avatar-CokwBO2O.js → avatar-kpFZmTl5.js} +2 -2
  8. package/dist/{avatar-CokwBO2O.js.map → avatar-kpFZmTl5.js.map} +1 -1
  9. package/dist/badge.cjs +1 -1
  10. package/dist/badge.js +1 -1
  11. package/dist/content-drawer.cjs +1 -1
  12. package/dist/content-drawer.js +1 -1
  13. package/dist/index.cjs +1 -1
  14. package/dist/index.js +192 -191
  15. package/dist/{utils-C9nzOWpR.cjs → lazy-DObpkuL6.cjs} +2 -2
  16. package/dist/lazy-DObpkuL6.cjs.map +1 -0
  17. package/dist/{utils-03Coa8AW.js → lazy-E2LCDm7n.js} +37 -23
  18. package/dist/lazy-E2LCDm7n.js.map +1 -0
  19. package/dist/nav-drawer.cjs +1 -1
  20. package/dist/nav-drawer.js +1 -1
  21. package/dist/route.component-5LuJ2r6W.js +311 -0
  22. package/dist/route.component-5LuJ2r6W.js.map +1 -0
  23. package/dist/route.component-DR82kcmu.cjs +12 -0
  24. package/dist/route.component-DR82kcmu.cjs.map +1 -0
  25. package/dist/teleport.cjs +1 -1
  26. package/dist/teleport.js +1 -1
  27. package/package.json +1 -1
  28. package/types/src/area/area.component.d.ts +6 -36
  29. package/types/src/area/index.d.ts +1 -0
  30. package/types/src/area/lazy.d.ts +44 -0
  31. package/types/src/area/router.types.d.ts +3 -1
  32. package/dist/route.component-BMRfUQ9O.cjs +0 -12
  33. package/dist/route.component-BMRfUQ9O.cjs.map +0 -1
  34. package/dist/route.component-D2BflZS9.js +0 -341
  35. package/dist/route.component-D2BflZS9.js.map +0 -1
  36. package/dist/utils-03Coa8AW.js.map +0 -1
  37. package/dist/utils-C9nzOWpR.cjs.map +0 -1
@@ -1,341 +0,0 @@
1
- import { Subject as q, ReplaySubject as v, distinctUntilChanged as y, shareReplay as N, skip as L, map as c, filter as d, catchError as l, EMPTY as p, zip as I, fromEvent as P, of as h, bufferTime as T, tap as J, timeout as B, from as $, switchMap as O, startWith as F, combineLatest as A, take as D, merge as _, debounceTime as z, takeUntil as Q } from "rxjs";
2
- import "lit/directives/class-map.js";
3
- import "lit/directives/style-map.js";
4
- import { property as w, queryAssignedElements as Y, customElement as M } from "lit/decorators.js";
5
- import "./tailwind.mixin-NLG6hsRk.js";
6
- import { $ as U } from "./litElement.mixin-Cs2vwcM4.js";
7
- import { css as k, html as H } from "lit";
8
- const x = new q(), W = "FINDING_MORTIES", G = "HERE_RICKY", C = /* @__PURE__ */ new WeakMap();
9
- class b {
10
- constructor() {
11
- this.prettyURL = !1, this.mode = "HISTORY", this.request = new v(1), this.current = /* @__PURE__ */ new Map(), this.$current = new v(1), this.enableHistoryMode = !0, this.findingMortiesEvent = new CustomEvent(W), this.disposed = !1, this.isProcessingPopstate = !1, this.$current.next(this.current), this.$current.subscribe((t) => {
12
- this.disposed || t.forEach((e, r) => {
13
- this.getOrCreateAreaSubject(r).next(e);
14
- });
15
- }), this.initializeFromBrowserState();
16
- }
17
- get areaSubjects() {
18
- let t = C.get(this);
19
- return t || (t = /* @__PURE__ */ new Map(), C.set(this, t)), t;
20
- }
21
- initializeFromBrowserState() {
22
- try {
23
- const t = history.state;
24
- t && t.schmancyAreas && (Object.entries(t.schmancyAreas).forEach(([e, r]) => {
25
- this.current.set(e, r);
26
- }), this.$current.next(this.current));
27
- } catch {
28
- }
29
- }
30
- getOrCreateAreaSubject(t) {
31
- let e = this.areaSubjects.get(t);
32
- if (!e || e.closed) {
33
- e = new v(1), this.areaSubjects.set(t, e);
34
- const r = this.current.get(t);
35
- r && e.next({ ...r, state: r.state || {}, params: r.params || {}, props: r.props || {} });
36
- }
37
- return e;
38
- }
39
- on(t, e = !1) {
40
- if (!t) throw new Error("Area name is required");
41
- const r = this.getOrCreateAreaSubject(t).asObservable().pipe(y((o, n) => o.component === n.component && JSON.stringify(o.state) === JSON.stringify(n.state) && JSON.stringify(o.params) === JSON.stringify(n.params)), N(1));
42
- return e ? r.pipe(L(1)) : r;
43
- }
44
- all(t = !1) {
45
- const e = this.$current.asObservable().pipe(N(1));
46
- return t ? e.pipe(L(1)) : e;
47
- }
48
- getState(t) {
49
- if (!t) throw new Error("Area name is required");
50
- return this.on(t).pipe(c((e) => e.state), d((e) => e != null), y((e, r) => JSON.stringify(e) === JSON.stringify(r)), c((e) => e), l((e) => p));
51
- }
52
- params(t) {
53
- if (!t) throw new Error("Area name is required");
54
- return this.on(t).pipe(c((e) => e.params), d((e) => e != null), y((e, r) => JSON.stringify(e) === JSON.stringify(r)), c((e) => e), l((e) => p));
55
- }
56
- param(t, e) {
57
- if (!t || !e) throw new Error("Area name and key are required");
58
- return this.params(t).pipe(c((r) => r[e]), d((r) => r !== void 0), y(), c((r) => r), l((r) => p));
59
- }
60
- props(t) {
61
- if (!t) throw new Error("Area name is required");
62
- return this.on(t).pipe(c((e) => e.props), d((e) => e != null), y((e, r) => JSON.stringify(e) === JSON.stringify(r)), c((e) => e), l((e) => p));
63
- }
64
- prop(t, e) {
65
- if (!t || !e) throw new Error("Area name and key are required");
66
- return this.props(t).pipe(c((r) => r[e]), d((r) => r !== void 0), y(), c((r) => r), l((r) => p));
67
- }
68
- find() {
69
- return I([P(window, G).pipe(c((t) => t.detail), T(0)), h(1).pipe(J(() => window.dispatchEvent(this.findingMortiesEvent)))]).pipe(c(([t]) => t), B(1), l(() => p));
70
- }
71
- push(t) {
72
- if (!t.area) throw new Error("Area is required for route action");
73
- if (this.isProcessingPopstate) return;
74
- const e = { ...t, state: t.state || {}, params: t.params || {}, props: t.props || {}, _source: "programmatic" };
75
- this.enableHistoryMode && x.next(e), this.request.next(e), this.dispatchAreaEvent(e.area, e);
76
- }
77
- _updateFromBrowser(t) {
78
- const e = { ...t, state: t.state || {}, params: t.params || {}, props: t.props || {}, _source: "browser" };
79
- this.isProcessingPopstate = !0, this.request.next(e), this.isProcessingPopstate = !1;
80
- }
81
- _updateBrowserHistory(t, e, r, o) {
82
- if (this.enableHistoryMode) try {
83
- const n = history.state || {}, s = n.schmancyAreas || {}, i = { component: e.component, area: e.area };
84
- e.state && Object.keys(e.state).length > 0 && (i.state = e.state), e.params && Object.keys(e.params).length > 0 && (i.params = e.params), e.props && Object.keys(e.props).length > 0 && (i.props = e.props), s[t] = i;
85
- const m = { ...n, schmancyAreas: s }, u = this.createCleanURL(s, o);
86
- r === "replace" || r === "pop" ? history.replaceState(m, "", u) : r !== "push" && r || history.pushState(m, "", u);
87
- } catch {
88
- }
89
- }
90
- createCleanURL(t, e) {
91
- let r = "";
92
- if (e !== !0) {
93
- const o = new URLSearchParams(location.search);
94
- Array.isArray(e) && e.forEach((n) => o.delete(n)), r = o.toString(), r = r ? `?${r}` : "";
95
- }
96
- if (this.prettyURL) {
97
- const o = t.main;
98
- if (o) {
99
- let n = `/${o.component}`;
100
- const s = new URLSearchParams(r);
101
- o.params && Object.entries(o.params).forEach(([m, u]) => {
102
- typeof u != "string" && typeof u != "number" || s.set(m, String(u));
103
- });
104
- const i = s.toString();
105
- return n + (i ? `?${i}` : "");
106
- }
107
- }
108
- try {
109
- const o = {};
110
- return Object.entries(t).forEach(([n, s]) => {
111
- const i = { component: s.component };
112
- s.state && Object.keys(s.state).length > 0 && (i.state = s.state), s.params && Object.keys(s.params).length > 0 && (i.params = s.params), s.props && Object.keys(s.props).length > 0 && (i.props = s.props), o[n] = i;
113
- }), Object.keys(o).length === 0 ? r ? `/${r}` : "/" : `/${encodeURIComponent(JSON.stringify(o))}${r}`;
114
- } catch {
115
- return location.pathname;
116
- }
117
- }
118
- restoreFromBrowserState(t) {
119
- try {
120
- if (t && t.schmancyAreas) return t.schmancyAreas;
121
- } catch {
122
- }
123
- return this.parseStateFromURL();
124
- }
125
- parseStateFromURL() {
126
- const t = location.pathname.split("/").pop();
127
- if (!t) return {};
128
- try {
129
- const e = decodeURIComponent(t), r = JSON.parse(e);
130
- if (typeof r == "object" && r !== null) return r;
131
- } catch {
132
- }
133
- return {};
134
- }
135
- dispatchAreaEvent(t, e) {
136
- const r = new CustomEvent(`schmancy-area-${t}-changed`, { detail: { area: t, component: e.component, state: e.state, params: e.params, props: e.props, historyStrategy: e.historyStrategy }, bubbles: !0, composed: !0 });
137
- window.dispatchEvent(r);
138
- }
139
- pop(t) {
140
- if (!t) throw new Error("Area name is required");
141
- const e = this.areaSubjects.get(t);
142
- if (e && !e.closed && e.next({ component: null, state: {}, area: t, params: {}, props: {} }), this.request.next({ area: t, component: null, state: {}, params: {}, props: {}, historyStrategy: "silent", _source: "programmatic" }), this.current.delete(t), this.$current.next(this.current), this.enableHistoryMode) try {
143
- const r = history.state || {}, o = { ...r.schmancyAreas || {} };
144
- delete o[t];
145
- const n = { ...r, schmancyAreas: o }, s = this.createCleanURL(o);
146
- history.replaceState(n, "", s);
147
- } catch {
148
- }
149
- }
150
- clear() {
151
- this.areaSubjects.forEach((t) => t.complete()), this.areaSubjects.clear(), this.current.clear(), this.$current.next(this.current), this.enableHistoryMode && history.replaceState({ schmancyAreas: {} }, "", `/${location.search}`);
152
- }
153
- dispose() {
154
- this.disposed || (this.disposed = !0, this.areaSubjects.forEach((t) => t.complete()), this.areaSubjects.clear(), this.request.complete(), this.$current.complete(), x.complete(), this.current.clear(), C.delete(this));
155
- }
156
- static getInstance() {
157
- return b.instance || (b.instance = new b()), b.instance;
158
- }
159
- get state() {
160
- try {
161
- const t = history.state;
162
- if (t && t.schmancyAreas) return t.schmancyAreas;
163
- } catch {
164
- }
165
- return this.parseStateFromURL();
166
- }
167
- hasArea(t) {
168
- return this.current.has(t);
169
- }
170
- getActiveAreas() {
171
- return Array.from(this.current.keys());
172
- }
173
- getRoute(t) {
174
- return this.current.get(t);
175
- }
176
- }
177
- const f = b.getInstance();
178
- typeof window < "u" && window.addEventListener("unload", () => {
179
- f.dispose();
180
- });
181
- var S = ((a) => (a.push = "push", a.replace = "replace", a.pop = "pop", a.silent = "silent", a))(S || {}), K = Object.defineProperty, V = Object.getOwnPropertyDescriptor, j = (a, t, e, r) => {
182
- for (var o, n = r > 1 ? void 0 : r ? V(t, e) : t, s = a.length - 1; s >= 0; s--) (o = a[s]) && (n = (r ? o(t, e, n) : o(n)) || n);
183
- return r && n && K(t, e, n), n;
184
- };
185
- let E = class extends U(k`
186
- :host {
187
- position: relative;
188
- display: block;
189
- inset: 0;
190
- }
191
- `) {
192
- resolveRoute(a, t, e = S.silent, r = []) {
193
- switch (a) {
194
- case "initial":
195
- case "popstate": {
196
- if (a === "popstate" && t && typeof t == "object" && "state" in t) {
197
- const n = t, s = n.state?.schmancyAreas?.[this.name];
198
- if (s) return h({ area: this.name, component: s.component, state: s.state || {}, params: s.params || {}, historyStrategy: S.silent });
199
- }
200
- const o = typeof t == "string" ? t : location.pathname;
201
- return this.matchSegmentToRoute(o, e, r);
202
- }
203
- case "navigation":
204
- return t && typeof t == "object" && "component" in t ? h(t) : p;
205
- default:
206
- return p;
207
- }
208
- }
209
- matchSegmentToRoute(a, t, e) {
210
- const r = a.split("/").pop() || "";
211
- if (r && (r.includes("{") || r.includes("%7B"))) try {
212
- const o = decodeURIComponent(r), n = JSON.parse(o);
213
- if (n[this.name]) return h({ area: this.name, component: n[this.name].component, state: n[this.name].state || {}, params: n[this.name].params || {}, historyStrategy: t });
214
- } catch {
215
- }
216
- if (e && e.length > 0) {
217
- const o = a.split("/").filter(Boolean)[0] || "";
218
- for (const n of e)
219
- if (n.when === o) return n.guard ? $(Promise.resolve(n.guard())).pipe(O((s) => s === !0 ? h({ area: this.name, component: n.component, state: {}, params: {}, historyStrategy: t }) : s === !1 ? this.default ? h({ area: this.name, component: this.default, state: {}, params: {}, historyStrategy: t }) : p : typeof s == "string" ? this.matchSegmentToRoute(s, t, e) : typeof s == "object" && s.redirect ? this.matchSegmentToRoute(s.redirect, t, e) : this.default ? h({ area: this.name, component: this.default, state: {}, params: {}, historyStrategy: t }) : p), l((s) => this.default ? h({ area: this.name, component: this.default, state: {}, params: {}, historyStrategy: t }) : p)) : h({ area: this.name, component: n.component, state: {}, params: {}, historyStrategy: t });
220
- }
221
- return this.default ? h({ area: this.name, component: this.default, state: {}, params: {}, historyStrategy: t }) : p;
222
- }
223
- async resolveComponent(a) {
224
- if (!a || a === "") return { element: null };
225
- if (typeof a == "string") try {
226
- return { element: document.createElement(a) };
227
- } catch {
228
- return this.default && typeof this.default == "string" ? { element: document.createElement(this.default) } : { element: null };
229
- }
230
- if (a instanceof HTMLElement) return { element: a };
231
- if (typeof a == "function" && !("then" in a)) try {
232
- return { element: new a() };
233
- } catch {
234
- return { element: null };
235
- }
236
- if (typeof a == "function") try {
237
- const t = (await a()).default;
238
- return { element: new t() };
239
- } catch {
240
- return { element: null };
241
- }
242
- if (a instanceof Promise) try {
243
- const t = (await a).default;
244
- return { element: new t() };
245
- } catch {
246
- return { element: null };
247
- }
248
- return { element: null };
249
- }
250
- firstUpdated() {
251
- if (!this.name) throw new Error("Area name is required");
252
- this.routingSubscription?.unsubscribe();
253
- const a = this.shadowRoot?.querySelector("slot"), t = a ? P(a, "slotchange").pipe(F(null), c(() => this.routes || [])) : h([]), e = A([h(location.pathname), t]).pipe(D(1), O(([s, i]) => this.resolveRoute("initial", s, S.silent, i))), r = A([f.request.pipe(d(({ area: s }) => s === this.name)), t]).pipe(O(([s, i]) => this.resolveRoute("navigation", s, S.silent, i))), o = A([P(window, "popstate"), t]).pipe(O(([s, i]) => this.resolveRoute("popstate", s, S.silent, i))), n = _(e, r, o);
254
- this.routingSubscription = n.pipe(z(0), d((s) => s.component !== void 0), y((s, i) => this.isSameRoute(s, i)), N(1), O((s) => $(this.resolveComponent(s.component)).pipe(c((i) => ({ ...i, route: s })))), c(({ element: s, route: i }) => (s && (i.params && Object.entries(i.params).forEach(([m, u]) => {
255
- s[m] = u;
256
- }), i.props && Object.entries(i.props).forEach(([m, u]) => {
257
- s[m] = u;
258
- }), i.state && (s.state = i.state)), { element: s, route: i })), J(({ element: s, route: i }) => {
259
- this.updateDOM(s), s && this.updateInternalState(i, s), this.updateBrowserHistory(i, s);
260
- }), l((s) => p), Q(this.disconnecting)).subscribe({ error: (s) => {
261
- } });
262
- }
263
- isSameRoute(a, t) {
264
- if (a.component === null && t.component === null) return !0;
265
- if (a.component === null || t.component === null) return !1;
266
- let e = "", r = "";
267
- typeof a.component == "function" ? e = a.component.name || a.component.toString() : typeof a.component == "string" ? e = a.component : a.component instanceof HTMLElement && (e = a.component.tagName.toLowerCase()), typeof t.component == "function" ? r = t.component.name || t.component.toString() : typeof t.component == "string" ? r = t.component : t.component instanceof HTMLElement && (r = t.component.tagName.toLowerCase());
268
- const o = (m) => m?.replaceAll("-", "").toLowerCase(), n = o(e) === o(r), s = JSON.stringify(a.params || {}) === JSON.stringify(t.params || {}), i = JSON.stringify(a.state || {}) === JSON.stringify(t.state || {});
269
- return n && s && i;
270
- }
271
- updateDOM(a) {
272
- const t = this.shadowRoot?.children[0], e = !!t;
273
- t && t.remove(), a && (this.shadowRoot?.append(a), this.shadowRoot?.contains(a) && (a.animate([{ opacity: 0 }, { opacity: 1 }], { duration: e ? 150 : 100, easing: "cubic-bezier(0.25, 0.8, 0.25, 1)", fill: "forwards" }).onfinish = () => {
274
- a.style.opacity = "1";
275
- }));
276
- }
277
- updateInternalState(a, t) {
278
- if (!t) return;
279
- const e = { component: t.tagName.toLowerCase(), state: a.state || {}, area: this.name, params: a.params || {} };
280
- f.current.set(this.name, e), f.$current.next(f.current);
281
- }
282
- updateBrowserHistory(a, t) {
283
- if (!f.enableHistoryMode || !t) return;
284
- const e = { component: t.tagName.toLowerCase(), state: a.state || {}, area: this.name, params: a.params || {} };
285
- f._updateBrowserHistory(this.name, e, a.historyStrategy, a.clearQueryParams);
286
- }
287
- newPath(a, t) {
288
- const e = location.pathname.split("/").pop();
289
- let r = {};
290
- try {
291
- r = e ? JSON.parse(decodeURIComponent(e)) : {};
292
- } catch {
293
- r = {};
294
- }
295
- t.state = t.state ?? {};
296
- const o = t.clearQueryParams ? this.queryParamClear(t.clearQueryParams) : document.location.search;
297
- return encodeURIComponent(JSON.stringify({ ...r, [this.name]: { component: a.toLowerCase(), state: t.state, params: t.params } })).concat(`${o}`);
298
- }
299
- queryParamClear(a) {
300
- if (!a) return "";
301
- const t = new URLSearchParams(location.search);
302
- return a === !0 ? "" : (a.forEach((e) => t.delete(e)), t.toString() === "" ? "" : `?${t.toString()}`);
303
- }
304
- disconnectedCallback() {
305
- super.disconnectedCallback(), this.routingSubscription && (this.routingSubscription.unsubscribe(), this.routingSubscription = void 0);
306
- }
307
- render() {
308
- return H` <slot> </slot> `;
309
- }
310
- };
311
- j([w()], E.prototype, "name", 2), j([w()], E.prototype, "default", 2), j([Y({ selector: "schmancy-route" })], E.prototype, "routes", 2), E = j([M("schmancy-area")], E);
312
- var X = Object.defineProperty, Z = Object.getOwnPropertyDescriptor, R = (a, t, e, r) => {
313
- for (var o, n = r > 1 ? void 0 : r ? Z(t, e) : t, s = a.length - 1; s >= 0; s--) (o = a[s]) && (n = (r ? o(t, e, n) : o(n)) || n);
314
- return r && n && X(t, e, n), n;
315
- };
316
- let g = class extends U(k`
317
- :host {
318
- display: none;
319
- }
320
- `) {
321
- constructor() {
322
- super(...arguments), this.exact = !1;
323
- }
324
- getConfig() {
325
- return { when: this.when, component: this.component, exact: this.exact, guard: this.guard };
326
- }
327
- render() {
328
- return H``;
329
- }
330
- };
331
- R([w({ type: String })], g.prototype, "when", 2), R([w({ type: Object })], g.prototype, "component", 2), R([w({ type: Boolean })], g.prototype, "exact", 2), R([w({ type: Object })], g.prototype, "guard", 2), g = R([M("schmancy-route")], g);
332
- export {
333
- W as F,
334
- G as H,
335
- E as S,
336
- g as a,
337
- f as b,
338
- S as c,
339
- x as r
340
- };
341
- //# sourceMappingURL=route.component-D2BflZS9.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"route.component-D2BflZS9.js","sources":["../src/area/area.service.ts","../src/area/router.types.ts","../src/area/area.component.ts","../src/area/route.component.ts"],"sourcesContent":["import { \n\tObservable, \n\tReplaySubject, \n\tSubject, \n\tbufferTime, \n\tfilter, \n\tfromEvent, \n\tmap, \n\tof, \n\tskip, \n\ttap, \n\ttimeout, \n\tzip,\n\tshareReplay,\n\tdistinctUntilChanged,\n\tcatchError,\n\tEMPTY\n} from 'rxjs'\nimport { SchmancyTeleportation } from '../teleport'\nimport { ActiveRoute, AreaSubscription, RouteAction } from './router.types'\n\nexport const routerHistory = new Subject<RouteAction>()\n\nexport const FINDING_MORTIES = 'FINDING_MORTIES'\nexport const HERE_RICKY = 'HERE_RICKY'\nexport type HERE_RICKY_EVENT = CustomEvent<{\n\tcomponent: SchmancyTeleportation\n}>\nexport type FINDING_MORTIES_EVENT = CustomEvent<{\n\tcomponent: SchmancyTeleportation\n}>\n\n// WeakMap for better memory management of area subjects\nconst areaSubjectsCache = new WeakMap<AreaService, Map<string, ReplaySubject<ActiveRoute>>>()\n\n// Track navigation source to prevent history conflicts\ntype NavigationSource = 'programmatic' | 'browser' | 'initial'\n\nclass AreaService implements AreaSubscription {\n\tprivate static instance: AreaService\n\tpublic prettyURL = false\n\tpublic mode: 'SILENT' | 'HISTORY' = 'HISTORY'\n\tpublic request = new ReplaySubject<RouteAction>(1)\n\tpublic current = new Map<string, ActiveRoute>()\n\tpublic $current = new ReplaySubject<Map<string, ActiveRoute>>(1)\n\t\n\t// Create a dictionary of ReplaySubjects for area-specific subscriptions\n\tprivate get areaSubjects(): Map<string, ReplaySubject<ActiveRoute>> {\n\t\tlet subjects = areaSubjectsCache.get(this)\n\t\tif (!subjects) {\n\t\t\tsubjects = new Map()\n\t\t\tareaSubjectsCache.set(this, subjects)\n\t\t}\n\t\treturn subjects\n\t}\n\t\n\tpublic enableHistoryMode = true\n\tprivate findingMortiesEvent = new CustomEvent<FINDING_MORTIES_EVENT['detail']>(FINDING_MORTIES)\n\tprivate disposed = false\n\tpublic isProcessingPopstate = false\n\n\tconstructor() {\n\t\tthis.$current.next(this.current)\n\t\t\n\t\t// Subscribe to current changes to update area-specific subjects\n\t\tthis.$current.subscribe(currentAreas => {\n\t\t\tif (this.disposed) return\n\t\t\t\n\t\t\t// For each area in the current map\n\t\t\tcurrentAreas.forEach((route, areaName) => {\n\t\t\t\t// Get or create a subject for this area\n\t\t\t\tconst areaSubject = this.getOrCreateAreaSubject(areaName)\n\t\t\t\t// Emit the updated route to area-specific subscribers\n\t\t\t\tareaSubject.next(route)\n\t\t\t})\n\t\t})\n\n\t\t// Initialize from browser state if available\n\t\tthis.initializeFromBrowserState()\n\t}\n\n\t/**\n\t * Initialize router state from browser history state\n\t */\n\tprivate initializeFromBrowserState() {\n\t\ttry {\n\t\t\tconst browserState = history.state\n\t\t\tif (browserState && browserState.schmancyAreas) {\n\t\t\t\tObject.entries(browserState.schmancyAreas).forEach(([areaName, route]) => {\n\t\t\t\t\tthis.current.set(areaName, route as ActiveRoute)\n\t\t\t\t})\n\t\t\t\tthis.$current.next(this.current)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.warn('Failed to initialize from browser state:', error)\n\t\t}\n\t}\n\n\t/**\n\t * Get or create a ReplaySubject for a specific area with proper cleanup\n\t */\n\tprivate getOrCreateAreaSubject(areaName: string): ReplaySubject<ActiveRoute> {\n\t\tlet subject = this.areaSubjects.get(areaName)\n\t\t\n\t\tif (!subject || subject.closed) {\n\t\t\tsubject = new ReplaySubject<ActiveRoute>(1)\n\t\t\tthis.areaSubjects.set(areaName, subject)\n\t\t\t\n\t\t\t// If the area already exists in current, emit it immediately\n\t\t\tconst currentRoute = this.current.get(areaName)\n\t\t\tif (currentRoute) {\n\t\t\t\tsubject.next({\n\t\t\t\t\t...currentRoute,\n\t\t\t\t\t// Ensure state, params and props are initialized if undefined\n\t\t\t\t\tstate: currentRoute.state || {},\n\t\t\t\t\tparams: currentRoute.params || {},\n\t\t\t\t\tprops: currentRoute.props || {}\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn subject\n\t}\n\n\t/**\n\t * Subscribe to a specific area with caching\n\t */\n\ton(areaName: string, skipCurrent = false): Observable<ActiveRoute> {\n\t\tif (!areaName) {\n\t\t\tthrow new Error('Area name is required')\n\t\t}\n\t\t\n\t\tconst areaSubject = this.getOrCreateAreaSubject(areaName)\n\t\tconst observable = areaSubject.asObservable().pipe(\n\t\t\t// Add distinct to prevent duplicate emissions - now includes state\n\t\t\tdistinctUntilChanged((a, b) => \n\t\t\t\ta.component === b.component &&\n\t\t\t\tJSON.stringify(a.state) === JSON.stringify(b.state) &&\n\t\t\t\tJSON.stringify(a.params) === JSON.stringify(b.params)\n\t\t\t),\n\t\t\t// Share the subscription\n\t\t\tshareReplay(1)\n\t\t)\n\t\t\n\t\treturn skipCurrent ? observable.pipe(skip(1)) : observable\n\t}\n\t\n\t/**\n\t * Subscribe to all areas\n\t */\n\tall(skipCurrent = false): Observable<Map<string, ActiveRoute>> {\n\t\tconst observable = this.$current.asObservable().pipe(\n\t\t\tshareReplay(1)\n\t\t)\n\t\treturn skipCurrent ? observable.pipe(skip(1)) : observable\n\t}\n\t\n\t/**\n\t * Get state from an area with type safety\n\t */\n\tgetState<T = unknown>(areaName: string): Observable<T> {\n\t\tif (!areaName) {\n\t\t\tthrow new Error('Area name is required')\n\t\t}\n\t\t\n\t\treturn this.on(areaName).pipe(\n\t\t\tmap(route => route.state),\n\t\t\tfilter((state): state is NonNullable<Record<string, unknown>> => \n\t\t\t\tstate !== undefined && state !== null\n\t\t\t),\n\t\t\tdistinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),\n\t\t\tmap(state => state as T),\n\t\t\tcatchError(err => {\n\t\t\t\tconsole.error(`Error getting state for area \"${areaName}\":`, err)\n\t\t\t\treturn EMPTY\n\t\t\t})\n\t\t)\n\t}\n\t\n\t/**\n\t * Get params from an area with type safety\n\t */\n\tparams<T extends Record<string, unknown> = Record<string, unknown>>(areaName: string): Observable<T> {\n\t\tif (!areaName) {\n\t\t\tthrow new Error('Area name is required')\n\t\t}\n\t\t\n\t\treturn this.on(areaName).pipe(\n\t\t\tmap(route => route.params),\n\t\t\tfilter((params): params is NonNullable<Record<string, unknown>> => \n\t\t\t\tparams !== undefined && params !== null\n\t\t\t),\n\t\t\tdistinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),\n\t\t\tmap(params => params as T),\n\t\t\tcatchError(err => {\n\t\t\t\tconsole.error(`Error getting params for area \"${areaName}\":`, err)\n\t\t\t\treturn EMPTY\n\t\t\t})\n\t\t)\n\t}\n\t\n\t/**\n\t * Get a specific param from an area with null safety\n\t */\n\tparam<T = unknown>(areaName: string, key: string): Observable<T> {\n\t\tif (!areaName || !key) {\n\t\t\tthrow new Error('Area name and key are required')\n\t\t}\n\t\t\n\t\treturn this.params<Record<string, unknown>>(areaName).pipe(\n\t\t\tmap(params => params[key]),\n\t\t\tfilter((value): value is NonNullable<unknown> => value !== undefined),\n\t\t\tdistinctUntilChanged(),\n\t\t\tmap(value => value as T),\n\t\t\tcatchError(err => {\n\t\t\t\tconsole.error(`Error getting param \"${key}\" for area \"${areaName}\":`, err)\n\t\t\t\treturn EMPTY\n\t\t\t})\n\t\t)\n\t}\n\t\n\t/**\n\t * Get props from an area with type safety\n\t */\n\tprops<T extends Record<string, unknown> = Record<string, unknown>>(areaName: string): Observable<T> {\n\t\tif (!areaName) {\n\t\t\tthrow new Error('Area name is required')\n\t\t}\n\t\t\n\t\treturn this.on(areaName).pipe(\n\t\t\tmap(route => route.props),\n\t\t\tfilter((props): props is NonNullable<Record<string, unknown>> => \n\t\t\t\tprops !== undefined && props !== null\n\t\t\t),\n\t\t\tdistinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),\n\t\t\tmap(props => props as T),\n\t\t\tcatchError(err => {\n\t\t\t\tconsole.error(`Error getting props for area \"${areaName}\":`, err)\n\t\t\t\treturn EMPTY\n\t\t\t})\n\t\t)\n\t}\n\t\n\t/**\n\t * Get a specific prop from an area with null safety\n\t */\n\tprop<T = unknown>(areaName: string, key: string): Observable<T> {\n\t\tif (!areaName || !key) {\n\t\t\tthrow new Error('Area name and key are required')\n\t\t}\n\t\t\n\t\treturn this.props<Record<string, unknown>>(areaName).pipe(\n\t\t\tmap(props => props[key]),\n\t\t\tfilter((value): value is NonNullable<unknown> => value !== undefined),\n\t\t\tdistinctUntilChanged(),\n\t\t\tmap(value => value as T),\n\t\t\tcatchError(err => {\n\t\t\t\tconsole.error(`Error getting prop \"${key}\" for area \"${areaName}\":`, err)\n\t\t\t\treturn EMPTY\n\t\t\t})\n\t\t)\n\t}\n\n\t/**\n\t * Find teleportation components\n\t */\n\tfind() {\n\t\treturn zip([\n\t\t\tfromEvent<HERE_RICKY_EVENT>(window, HERE_RICKY).pipe(\n\t\t\t\tmap(e => e.detail),\n\t\t\t\tbufferTime(0),\n\t\t\t),\n\t\t\tof(1).pipe(tap(() => window.dispatchEvent(this.findingMortiesEvent))),\n\t\t]).pipe(\n\t\t\tmap(([component]) => component),\n\t\t\ttimeout(1),\n\t\t\tcatchError(() => EMPTY)\n\t\t)\n\t}\n\n\t/**\n\t * Push a new route action with validation\n\t */\n\tpush(r: RouteAction) {\n\t\tif (!r.area) {\n\t\t\tthrow new Error('Area is required for route action')\n\t\t}\n\t\t\n\t\t// Prevent processing during popstate handling\n\t\tif (this.isProcessingPopstate) {\n\t\t\treturn\n\t\t}\n\t\t\n\t\t// Ensure state, params and props are initialized\n\t\tconst routeAction: RouteAction = {\n\t\t\t...r,\n\t\t\tstate: r.state || {},\n\t\t\tparams: r.params || {},\n\t\t\tprops: r.props || {},\n\t\t\t_source: 'programmatic' as NavigationSource\n\t\t}\n\t\t\n\t\t// Add to history if enabled\n\t\tif (this.enableHistoryMode) {\n\t\t\trouterHistory.next(routeAction)\n\t\t}\n\t\t\n\t\tthis.request.next(routeAction)\n\t\t// Emit an area-specific event for those who want to listen directly to DOM events\n\t\tthis.dispatchAreaEvent(routeAction.area, routeAction)\n\t}\n\n\t/**\n\t * Internal method to update route from browser navigation\n\t * This should only be called by area components during popstate handling\n\t */\n\t_updateFromBrowser(routeAction: RouteAction) {\n\t\tconst enhancedRoute: RouteAction = {\n\t\t\t...routeAction,\n\t\t\tstate: routeAction.state || {},\n\t\t\tparams: routeAction.params || {},\n\t\t\tprops: routeAction.props || {},\n\t\t\t_source: 'browser' as NavigationSource\n\t\t}\n\t\t\n\t\tthis.isProcessingPopstate = true\n\t\tthis.request.next(enhancedRoute)\n\t\tthis.isProcessingPopstate = false\n\t}\n\n\t/**\n\t * Update browser history state (called by area components)\n\t */\n\t_updateBrowserHistory(areaName: string, route: ActiveRoute, historyStrategy?: string, clearQueryParams?: string[] | boolean | null) {\n\t\tif (!this.enableHistoryMode) return\n\t\t\n\t\ttry {\n\t\t\t// Get current browser state or create new one\n\t\t\tconst currentState = history.state || {}\n\t\t\tconst schmancyAreas = currentState.schmancyAreas || {}\n\t\t\t\n\t\t\t// Update the specific area - only include non-empty state/params/props\n\t\t\tconst areaData: any = {\n\t\t\t\tcomponent: route.component,\n\t\t\t\tarea: route.area\n\t\t\t}\n\t\t\t\n\t\t\t// Only include state if it has content\n\t\t\tif (route.state && Object.keys(route.state).length > 0) {\n\t\t\t\tareaData.state = route.state\n\t\t\t}\n\t\t\t\n\t\t\t// Only include params if it has content\n\t\t\tif (route.params && Object.keys(route.params).length > 0) {\n\t\t\t\tareaData.params = route.params\n\t\t\t}\n\t\t\t\n\t\t\t// Only include props if it has content\n\t\t\tif (route.props && Object.keys(route.props).length > 0) {\n\t\t\t\tareaData.props = route.props\n\t\t\t}\n\t\t\t\n\t\t\tschmancyAreas[areaName] = areaData\n\t\t\t\n\t\t\tconst newState = {\n\t\t\t\t...currentState,\n\t\t\t\tschmancyAreas\n\t\t\t}\n\t\t\t\n\t\t\t// Create clean URL\n\t\t\tconst url = this.createCleanURL(schmancyAreas, clearQueryParams)\n\t\t\t\n\t\t\t// Update browser history\n\t\t\tif (historyStrategy === 'replace' || historyStrategy === 'pop') {\n\t\t\t\thistory.replaceState(newState, '', url)\n\t\t\t} else if (historyStrategy === 'push' || !historyStrategy) {\n\t\t\t\thistory.pushState(newState, '', url)\n\t\t\t}\n\t\t\t// 'silent' strategy doesn't update browser history\n\t\t\t\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to update browser history:', error)\n\t\t}\n\t}\n\n\t/**\n\t * Create a clean URL from area states\n\t */\n\tprivate createCleanURL(areas: Record<string, ActiveRoute>, clearQueryParams?: string[] | boolean | null): string {\n\t\t// Handle query parameters\n\t\tlet queryString = ''\n\t\t\n\t\tif (clearQueryParams !== true) {\n\t\t\t// Get current query params\n\t\t\tconst urlParams = new URLSearchParams(location.search)\n\t\t\t\n\t\t\t// Clear specific params if provided\n\t\t\tif (Array.isArray(clearQueryParams)) {\n\t\t\t\tclearQueryParams.forEach(param => urlParams.delete(param))\n\t\t\t}\n\t\t\t\n\t\t\t// Convert back to string\n\t\t\tqueryString = urlParams.toString()\n\t\t\tqueryString = queryString ? `?${queryString}` : ''\n\t\t}\n\t\t// If clearQueryParams === true, queryString remains empty (all params cleared)\n\t\t\n\t\tif (this.prettyURL) {\n\t\t\t// Create pretty URLs - customize this based on your routing needs\n\t\t\tconst mainArea = areas.main\n\t\t\tif (mainArea) {\n\t\t\t\tlet path = `/${mainArea.component}`\n\t\t\t\t\n\t\t\t\t// Add simple params to URL\n\t\t\t\tconst searchParams = new URLSearchParams(queryString)\n\t\t\t\tif (mainArea.params) {\n\t\t\t\t\tObject.entries(mainArea.params).forEach(([key, value]) => {\n\t\t\t\t\t\tif (typeof value === 'string' || typeof value === 'number') {\n\t\t\t\t\t\t\tsearchParams.set(key, String(value))\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tconst query = searchParams.toString()\n\t\t\t\treturn path + (query ? `?${query}` : '')\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Fallback to encoded state in URL (original behavior)\n\t\ttry {\n\t\t\t// Clean up empty objects before encoding\n\t\t\tconst cleanedAreas: Record<string, any> = {}\n\t\t\tObject.entries(areas).forEach(([areaName, route]) => {\n\t\t\t\tconst cleanRoute: any = { component: route.component }\n\n\t\t\t\t// Only include state if it has content\n\t\t\t\tif (route.state && Object.keys(route.state).length > 0) {\n\t\t\t\t\tcleanRoute.state = route.state\n\t\t\t\t}\n\n\t\t\t\t// Only include params if it has content\n\t\t\t\tif (route.params && Object.keys(route.params).length > 0) {\n\t\t\t\t\tcleanRoute.params = route.params\n\t\t\t\t}\n\n\t\t\t\t// Only include props if it has content\n\t\t\t\tif (route.props && Object.keys(route.props).length > 0) {\n\t\t\t\t\tcleanRoute.props = route.props\n\t\t\t\t}\n\n\t\t\t\tcleanedAreas[areaName] = cleanRoute\n\t\t\t})\n\n\t\t\t// If cleanedAreas is empty, return a clean URL without encoded empty object\n\t\t\tif (Object.keys(cleanedAreas).length === 0) {\n\t\t\t\treturn queryString ? `/${queryString}` : '/'\n\t\t\t}\n\n\t\t\tconst encoded = encodeURIComponent(JSON.stringify(cleanedAreas))\n\t\t\treturn `/${encoded}${queryString}`\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to encode URL state:', error)\n\t\t\treturn location.pathname\n\t\t}\n\t}\n\n\t/**\n\t * Restore state from browser history state\n\t */\n\trestoreFromBrowserState(browserState: any): Record<string, ActiveRoute> {\n\t\ttry {\n\t\t\tif (browserState && browserState.schmancyAreas) {\n\t\t\t\treturn browserState.schmancyAreas\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to restore from browser state:', error)\n\t\t}\n\t\t\n\t\t// Fallback to URL parsing (original behavior)\n\t\treturn this.parseStateFromURL()\n\t}\n\n\t/**\n\t * Parse state from URL (fallback method)\n\t */\n\tprivate parseStateFromURL(): Record<string, ActiveRoute> {\n\t\tconst pathname = location.pathname.split('/').pop()\n\t\tif (!pathname) return {}\n\t\t\n\t\ttry {\n\t\t\tconst decoded = decodeURIComponent(pathname)\n\t\t\tconst parsed = JSON.parse(decoded)\n\t\t\t\n\t\t\tif (typeof parsed === 'object' && parsed !== null) {\n\t\t\t\treturn parsed\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore parse errors\n\t\t}\n\t\t\n\t\treturn {}\n\t}\n\t\n\t/**\n\t * Dispatch a DOM event for a specific area change\n\t */\n\tprivate dispatchAreaEvent(areaName: string, routeAction: RouteAction) {\n\t\tconst eventName = `schmancy-area-${areaName}-changed`\n\t\tconst event = new CustomEvent(eventName, { \n\t\t\tdetail: { \n\t\t\t\tarea: areaName,\n\t\t\t\tcomponent: routeAction.component,\n\t\t\t\tstate: routeAction.state,\n\t\t\t\tparams: routeAction.params,\n\t\t\t\tprops: routeAction.props,\n\t\t\t\thistoryStrategy: routeAction.historyStrategy\n\t\t\t},\n\t\t\tbubbles: true,\n\t\t\tcomposed: true\n\t\t})\n\t\twindow.dispatchEvent(event)\n\t}\n\n\t/**\n\t * Remove an area from the current state\n\t */\n\tpop(name: string) {\n\t\tif (!name) {\n\t\t\tthrow new Error('Area name is required')\n\t\t}\n\n\t\t// Before removing from current map, emit a clearing signal to the area's subject\n\t\t// This notifies the area component to clear itself\n\t\tconst areaSubject = this.areaSubjects.get(name)\n\t\tif (areaSubject && !areaSubject.closed) {\n\t\t\t// Send a route with null component to signal clearing\n\t\t\tareaSubject.next({\n\t\t\t\tcomponent: null as any,\n\t\t\t\tstate: {},\n\t\t\t\tarea: name,\n\t\t\t\tparams: {},\n\t\t\t\tprops: {}\n\t\t\t})\n\t\t}\n\n\t\t// Send a clearing signal through the request pipeline\n\t\t// This ensures the area component receives the signal to clear\n\t\tthis.request.next({\n\t\t\tarea: name,\n\t\t\tcomponent: null as any,\n\t\t\tstate: {},\n\t\t\tparams: {},\n\t\t\tprops: {},\n\t\t\thistoryStrategy: 'silent' as any,\n\t\t\t_source: 'programmatic' as NavigationSource\n\t\t})\n\n\t\t// Remove from current map\n\t\tthis.current.delete(name)\n\t\tthis.$current.next(this.current)\n\n\t\t// Update browser history\n\t\tif (this.enableHistoryMode) {\n\t\t\ttry {\n\t\t\t\tconst currentState = history.state || {}\n\t\t\t\tconst schmancyAreas = { ...(currentState.schmancyAreas || {}) }\n\t\t\t\tdelete schmancyAreas[name]\n\n\t\t\t\tconst newState = {\n\t\t\t\t\t...currentState,\n\t\t\t\t\tschmancyAreas\n\t\t\t\t}\n\n\t\t\t\tconst url = this.createCleanURL(schmancyAreas)\n\t\t\t\thistory.replaceState(newState, '', url)\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('Failed to update history after pop:', error)\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/**\n\t * Clear all areas\n\t */\n\tclear() {\n\t\t// Complete all area subjects\n\t\tthis.areaSubjects.forEach(subject => subject.complete())\n\t\tthis.areaSubjects.clear()\n\t\t\n\t\t// Clear current state\n\t\tthis.current.clear()\n\t\tthis.$current.next(this.current)\n\t\t\n\t\t// Update URL\n\t\tif (this.enableHistoryMode) {\n\t\t\thistory.replaceState({ schmancyAreas: {} }, '', `/${location.search}`)\n\t\t}\n\t}\n\t\n\t/**\n\t * Dispose of the service and clean up resources\n\t */\n\tdispose() {\n\t\tif (this.disposed) return\n\t\t\n\t\tthis.disposed = true\n\t\t\n\t\t// Complete all subjects\n\t\tthis.areaSubjects.forEach(subject => subject.complete())\n\t\tthis.areaSubjects.clear()\n\t\t\n\t\tthis.request.complete()\n\t\tthis.$current.complete()\n\t\trouterHistory.complete()\n\t\t\n\t\t// Clear references\n\t\tthis.current.clear()\n\t\tareaSubjectsCache.delete(this)\n\t}\n\t\n\t/**\n\t * Get singleton instance\n\t */\n\tstatic getInstance() {\n\t\tif (!AreaService.instance) {\n\t\t\tAreaService.instance = new AreaService()\n\t\t}\n\t\treturn AreaService.instance\n\t}\n\n\t/**\n\t * Get current state from URL (deprecated - use browser state instead)\n\t */\n\tget state(): Record<string, unknown> {\n\t\t// Try browser state first\n\t\ttry {\n\t\t\tconst browserState = history.state\n\t\t\tif (browserState && browserState.schmancyAreas) {\n\t\t\t\treturn browserState.schmancyAreas\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fallback to URL parsing\n\t\t}\n\t\t\n\t\t// Fallback to URL parsing (original behavior)\n\t\treturn this.parseStateFromURL()\n\t}\n\t\n\t/**\n\t * Check if an area exists in current state\n\t */\n\thasArea(areaName: string): boolean {\n\t\treturn this.current.has(areaName)\n\t}\n\t\n\t/**\n\t * Get all active area names\n\t */\n\tgetActiveAreas(): string[] {\n\t\treturn Array.from(this.current.keys())\n\t}\n\t\n\t/**\n\t * Get route for a specific area synchronously\n\t */\n\tgetRoute(areaName: string): ActiveRoute | undefined {\n\t\treturn this.current.get(areaName)\n\t}\n}\n\nexport const area = AreaService.getInstance()\nexport default area\n\n// Cleanup on page unload\nif (typeof window !== 'undefined') {\n\twindow.addEventListener('unload', () => {\n\t\tarea.dispose()\n\t})\n}","export type RouteAction = {\n\tcomponent: CustomElementConstructor | string | HTMLElement | Promise<any>\n\tarea: string\n\tstate?: Record<string, unknown>\n\tparams?: Record<string, unknown>\n\tprops?: Record<string, unknown> // Alias for params\n\thistoryStrategy?: THistoryStrategy\n\tclearQueryParams?: string[] | boolean | null\n\t_source?: 'programmatic' | 'browser' | 'initial' // Internal use only\n}\n\nexport type ActiveRoute = {\n\tcomponent: string\n\tarea: string\n\tstate?: Record<string, unknown>\n\tparams?: Record<string, unknown>\n\tprops?: Record<string, unknown>\n}\n\n/**\n * Interface for subscribing to area changes\n */\nexport interface AreaSubscription {\n\t/**\n\t * Subscribe to a specific area\n\t * @param areaName Name of the area to subscribe to\n\t * @param skipCurrent Whether to skip the current value\n\t * @returns Observable of the active route for the specified area\n\t */\n\ton(areaName: string, skipCurrent?: boolean): import('rxjs').Observable<ActiveRoute>\n\t\n\t/**\n\t * Subscribe to all areas\n\t * @param skipCurrent Whether to skip the current value\n\t * @returns Observable of all active routes\n\t */\n\tall(skipCurrent?: boolean): import('rxjs').Observable<Map<string, ActiveRoute>>\n\t\n\t/**\n\t * Get state from an area\n\t * @param areaName Name of the area to subscribe to\n\t * @returns Observable of the area's state\n\t */\n\tgetState<T = unknown>(areaName: string): import('rxjs').Observable<T>\n\t\n\t/**\n\t * Get params from an area\n\t * @param areaName Name of the area to subscribe to\n\t * @returns Observable of the area's params\n\t */\n\tparams<T extends Record<string, unknown> = Record<string, unknown>>(areaName: string): import('rxjs').Observable<T>\n\t\n\t/**\n\t * Get a specific param from an area\n\t * @param areaName Name of the area to subscribe to\n\t * @param key Key of the param to select\n\t * @returns Observable of the param value\n\t */\n\tparam<T = unknown>(areaName: string, key: string): import('rxjs').Observable<T>\n\t\n\t/**\n\t * Get props from an area\n\t * @param areaName Name of the area to subscribe to\n\t * @returns Observable of the area's props\n\t */\n\tprops<T extends Record<string, unknown> = Record<string, unknown>>(areaName: string): import('rxjs').Observable<T>\n\t\n\t/**\n\t * Get a specific prop from an area\n\t * @param areaName Name of the area to subscribe to\n\t * @param key Key of the prop to select\n\t * @returns Observable of the prop value\n\t */\n\tprop<T = unknown>(areaName: string, key: string): import('rxjs').Observable<T>\n}\n\nexport type THistoryStrategy = 'push' | 'replace' | 'pop' | 'silent'\n\nexport enum HISTORY_STRATEGY {\n\tpush = 'push',\n\treplace = 'replace',\n\tpop = 'pop',\n\tsilent = 'silent',\n}\n\n/**\n * Browser history state structure used by Schmancy Area\n */\nexport interface SchmancyHistoryState {\n\tschmancyAreas: Record<string, ActiveRoute>\n\t[key: string]: any // Allow other apps to store additional state\n}","import { $LitElement } from '@mixins/index'\nimport { TemplateResult, css, html } from 'lit'\nimport { customElement, property, queryAssignedElements } from 'lit/decorators.js'\nimport {\n\tEMPTY,\n\tObservable,\n\tSubscription,\n\tcatchError,\n\tcombineLatest,\n\tdebounceTime,\n\tdistinctUntilChanged,\n\tfilter,\n\tfrom,\n\tfromEvent,\n\tmap,\n\tmerge,\n\tof,\n\tshareReplay,\n\tstartWith,\n\tswitchMap,\n\ttake,\n\ttakeUntil,\n\ttap\n} from 'rxjs'\nimport area from './area.service'\nimport { SchmancyRoute } from './route.component'\nimport { ActiveRoute, HISTORY_STRATEGY, RouteAction } from './router.types'\n\n// Component types that can be passed to area\ntype ComponentInput =\n\t| string // Tag name or path\n\t| CustomElementConstructor // Constructor function\n\t| HTMLElement // Existing element\n\t| TemplateResult<1> // Lit template\n\t| (() => Promise<{ default: CustomElementConstructor }>) // Lazy loader\n\t| Promise<{ default: CustomElementConstructor }> // Dynamic import\n\n// Resolved component after processing\ntype ResolvedComponent = {\n\telement: HTMLElement | null\n}\n\n// Route source for debugging\ntype RouteSource = 'initial' | 'navigation' | 'popstate'\n\n\n@customElement('schmancy-area')\nexport class SchmancyArea extends $LitElement(css`\n\t:host {\n\t\tposition: relative;\n\t\tdisplay: block;\n\t\tinset: 0;\n\t}\n`) {\n\t/**\n\t * The name of the router outlet\n\t * @attr\n\t * @type {string}\n\t * @public\n\t * @required\n\t */\n\t@property() name!: string\n\n\t@property() default!: string | CustomElementConstructor | TemplateResult<1>\n\n\t/**\n\t * Query for assigned route elements in the slot\n\t * This will automatically update when slot content changes\n\t */\n\t@queryAssignedElements({ selector: 'schmancy-route' })\n\tprivate routes!: SchmancyRoute[]\n\n\t/**\n\t * Subscription to the routing pipeline\n\t */\n\tprivate routingSubscription?: Subscription\n\n\n\t/**\n\t * Unified route resolver that handles all routing scenarios\n\t * This is the single source of truth for resolving routes\n\t */\n\tprivate resolveRoute(\n\t\tsource: RouteSource,\n\t\tdata?: string | PopStateEvent | RouteAction | null,\n\t\thistoryStrategy: HISTORY_STRATEGY = HISTORY_STRATEGY.silent,\n\t\troutes: SchmancyRoute[] = []\n\t): Observable<RouteAction> {\n\n\t\tswitch (source) {\n\t\t\tcase 'initial':\n\t\t\tcase 'popstate': {\n\t\t\t\t// Handle initial load or popstate event\n\t\t\t\tif (source === 'popstate' && data && typeof data === 'object' && 'state' in data) {\n\t\t\t\t\t// Try to get from browser state first\n\t\t\t\t\tconst event = data as PopStateEvent\n\t\t\t\t\tconst state = event.state?.schmancyAreas?.[this.name]\n\t\t\t\t\tif (state) {\n\t\t\t\t\t\treturn of({\n\t\t\t\t\t\t\tarea: this.name,\n\t\t\t\t\t\t\tcomponent: state.component,\n\t\t\t\t\t\t\tstate: state.state || {},\n\t\t\t\t\t\t\tparams: state.params || {},\n\t\t\t\t\t\t\thistoryStrategy: HISTORY_STRATEGY.silent\n\t\t\t\t\t\t} as RouteAction)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fall back to segment matching\n\t\t\t\tconst pathname = typeof data === 'string' ? data : location.pathname\n\t\t\t\treturn this.matchSegmentToRoute(pathname, historyStrategy, routes)\n\t\t\t}\n\n\t\t\tcase 'navigation': {\n\t\t\t\t// Direct navigation request\n\t\t\t\tif (!data || typeof data !== 'object' || !('component' in data)) {\n\t\t\t\t\treturn EMPTY\n\t\t\t\t}\n\t\t\t\treturn of(data as RouteAction)\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\treturn EMPTY\n\t\t}\n\t}\n\n\t/**\n\t * Match URL to route using both JSON-based (core) and segment-based (enhancement) routing\n\t * This method is pure and reactive - it ALWAYS emits something (matched route, default, or EMPTY)\n\t */\n\tprivate matchSegmentToRoute(pathname: string, historyStrategy: HISTORY_STRATEGY, routes: SchmancyRoute[]): Observable<RouteAction> {\n\n\t\t// 1. CORE LOGIC: Try JSON-based routing first (this is the primary routing mechanism)\n\t\t// JSON routing allows for complete state and component configuration via URL\n\t\tconst lastSegment = pathname.split('/').pop() || ''\n\n\t\tif (lastSegment && (lastSegment.includes('{') || lastSegment.includes('%7B'))) {\n\t\t\ttry {\n\t\t\t\tconst decoded = decodeURIComponent(lastSegment)\n\t\t\t\tconst parsed = JSON.parse(decoded)\n\n\t\t\t\t// If JSON has an entry for this area, use it\n\t\t\t\tif (parsed[this.name]) {\n\t\t\t\t\treturn of({\n\t\t\t\t\t\tarea: this.name,\n\t\t\t\t\t\tcomponent: parsed[this.name].component,\n\t\t\t\t\t\tstate: parsed[this.name].state || {},\n\t\t\t\t\t\tparams: parsed[this.name].params || {},\n\t\t\t\t\t\thistoryStrategy\n\t\t\t\t\t} as RouteAction)\n\t\t\t\t}\n\t\t\t\t// Otherwise continue to segment matching and defaults\n\t\t\t} catch (e) {\n\t\t\t\t// Not valid JSON, continue to segment matching\n\t\t\t}\n\t\t}\n\n\t\t// 2. ENHANCEMENT: Try segment-based routing (new feature - only if routes are configured)\n\t\t// Segment routing provides clean URLs for defined routes\n\t\tif (routes && routes.length > 0) {\n\t\t\t// Extract the first segment from the pathname\n\t\t\tconst segments = pathname.split('/').filter(Boolean)\n\t\t\tconst currentSegment = segments[0] || ''\n\n\t\t\t// Find matching route by when attribute\n\t\t\tfor (const route of routes) {\n\t\t\t\tconst routeWhen = route.when\n\n\t\t\t\tif (routeWhen === currentSegment) {\n\n\t\t\t\t\t// Check guard if present\n\t\t\t\t\tif (route.guard) {\n\t\t\t\t\t\treturn from(Promise.resolve(route.guard())).pipe(\n\t\t\t\t\t\t\tswitchMap(guardResult => {\n\n\t\t\t\t\t\t\t\t// Handle guard result\n\t\t\t\t\t\t\t\tif (guardResult === true) {\n\t\t\t\t\t\t\t\t\t// Guard passed, proceed with the route\n\t\t\t\t\t\t\t\t\treturn of({\n\t\t\t\t\t\t\t\t\t\tarea: this.name,\n\t\t\t\t\t\t\t\t\t\tcomponent: route.component,\n\t\t\t\t\t\t\t\t\t\tstate: {},\n\t\t\t\t\t\t\t\t\t\tparams: {},\n\t\t\t\t\t\t\t\t\t\thistoryStrategy\n\t\t\t\t\t\t\t\t\t} as RouteAction)\n\t\t\t\t\t\t\t\t} else if (guardResult === false) {\n\t\t\t\t\t\t\t\t\t// Guard failed, check for default\n\t\t\t\t\t\t\t\t\tif (this.default) {\n\t\t\t\t\t\t\t\t\t\treturn of({\n\t\t\t\t\t\t\t\t\t\t\tarea: this.name,\n\t\t\t\t\t\t\t\t\t\t\tcomponent: this.default,\n\t\t\t\t\t\t\t\t\t\t\tstate: {},\n\t\t\t\t\t\t\t\t\t\t\tparams: {},\n\t\t\t\t\t\t\t\t\t\t\thistoryStrategy\n\t\t\t\t\t\t\t\t\t\t} as RouteAction)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn EMPTY\n\t\t\t\t\t\t\t\t} else if (typeof guardResult === 'string') {\n\t\t\t\t\t\t\t\t\t// Redirect to string path\n\t\t\t\t\t\t\t\t\treturn this.matchSegmentToRoute(guardResult, historyStrategy, routes)\n\t\t\t\t\t\t\t\t} else if (typeof guardResult === 'object' && guardResult.redirect) {\n\t\t\t\t\t\t\t\t\t// Redirect to path in object\n\t\t\t\t\t\t\t\t\treturn this.matchSegmentToRoute(guardResult.redirect, historyStrategy, routes)\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// Invalid guard result\n\t\t\t\t\t\t\t\t\tconsole.error(`[${this.name}] Invalid guard result:`, guardResult)\n\t\t\t\t\t\t\t\t\t// Fall back to default if available\n\t\t\t\t\t\t\t\t\tif (this.default) {\n\t\t\t\t\t\t\t\t\t\treturn of({\n\t\t\t\t\t\t\t\t\t\t\tarea: this.name,\n\t\t\t\t\t\t\t\t\t\t\tcomponent: this.default,\n\t\t\t\t\t\t\t\t\t\t\tstate: {},\n\t\t\t\t\t\t\t\t\t\t\tparams: {},\n\t\t\t\t\t\t\t\t\t\t\thistoryStrategy\n\t\t\t\t\t\t\t\t\t\t} as RouteAction)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn EMPTY\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tcatchError(err => {\n\t\t\t\t\t\t\t\tconsole.error(`[${this.name}] Guard error:`, err)\n\t\t\t\t\t\t\t\t// On guard error, fall back to default if available\n\t\t\t\t\t\t\t\tif (this.default) {\n\t\t\t\t\t\t\t\t\treturn of({\n\t\t\t\t\t\t\t\t\t\tarea: this.name,\n\t\t\t\t\t\t\t\t\t\tcomponent: this.default,\n\t\t\t\t\t\t\t\t\t\tstate: {},\n\t\t\t\t\t\t\t\t\t\tparams: {},\n\t\t\t\t\t\t\t\t\t\thistoryStrategy\n\t\t\t\t\t\t\t\t\t} as RouteAction)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn EMPTY\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\n\t\t\t\t\t// No guard, proceed with the route\n\t\t\t\t\treturn of({\n\t\t\t\t\t\tarea: this.name,\n\t\t\t\t\t\tcomponent: route.component,\n\t\t\t\t\t\tstate: {},\n\t\t\t\t\t\tparams: {},\n\t\t\t\t\t\thistoryStrategy\n\t\t\t\t\t} as RouteAction)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 3. Nothing matched - emit default if defined, otherwise EMPTY\n\t\tif (this.default) {\n\t\t\treturn of({\n\t\t\t\tarea: this.name,\n\t\t\t\tcomponent: this.default,\n\t\t\t\tstate: {},\n\t\t\t\tparams: {},\n\t\t\t\thistoryStrategy\n\t\t\t} as RouteAction)\n\t\t}\n\n\t\t// No routes matched and no default defined\n\t\treturn EMPTY\n\t}\n\n\n\t/**\n\t * Resolve component input to HTMLElement\n\t * Handles strings, constructors, promises, lazy loading, etc.\n\t */\n\tprivate async resolveComponent(component: ComponentInput): Promise<ResolvedComponent> {\n\n\t\t// Handle empty/null cases\n\t\tif (!component || component === '') {\n\t\t\treturn { element: null }\n\t\t}\n\n\t\t// Handle string (tag name)\n\t\tif (typeof component === 'string') {\n\t\t\ttry {\n\t\t\t\tconst element = document.createElement(component)\n\t\t\t\treturn { element }\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`[${this.name}] Failed to create element:`, component, error)\n\t\t\t\tif (this.default && typeof this.default === 'string') {\n\t\t\t\t\tconst element = document.createElement(this.default)\n\t\t\t\t\treturn { element }\n\t\t\t\t}\n\t\t\t\treturn { element: null }\n\t\t\t}\n\t\t}\n\n\t\t// Handle HTMLElement\n\t\tif (component instanceof HTMLElement) {\n\t\t\treturn { element: component }\n\t\t}\n\n\t\t// Handle constructor function\n\t\tif (typeof component === 'function' && !('then' in component)) {\n\t\t\ttry {\n\t\t\t\tconst element = new (component as CustomElementConstructor)()\n\t\t\t\treturn { element }\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`[${this.name}] Failed to instantiate component:`, error)\n\t\t\t\treturn { element: null }\n\t\t\t}\n\t\t}\n\n\t\t// Handle lazy loading function\n\t\tif (typeof component === 'function') {\n\t\t\ttry {\n\t\t\t\tconst module = await (component as () => Promise<{ default: CustomElementConstructor }>)()\n\t\t\t\tconst Constructor = module.default\n\t\t\t\tconst element = new Constructor()\n\t\t\t\treturn { element }\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`[${this.name}] Failed to load dynamic component:`, error)\n\t\t\t\treturn { element: null }\n\t\t\t}\n\t\t}\n\n\t\t// Handle Promise (dynamic import)\n\t\tif (component instanceof Promise) {\n\t\t\ttry {\n\t\t\t\tconst module = await component\n\t\t\t\tconst Constructor = module.default\n\t\t\t\tconst element = new Constructor()\n\t\t\t\treturn { element }\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`[${this.name}] Failed to load promise component:`, error)\n\t\t\t\treturn { element: null }\n\t\t\t}\n\t\t}\n\n\t\t// Fallback for unknown types\n\t\tconsole.warn(`[${this.name}] Unknown component type:`, typeof component, component)\n\t\treturn { element: null }\n\t}\n\n\tprotected firstUpdated(): void {\n\t\tif (!this.name) {\n\t\t\tthrow new Error('Area name is required')\n\t\t}\n\n\t\t// Clean up any existing subscription before creating a new one\n\t\tthis.routingSubscription?.unsubscribe()\n\n\t\t// Create a reactive stream from slot changes\n\t\tconst slot = this.shadowRoot?.querySelector('slot') as HTMLSlotElement\n\t\tconst slotChanges$ = slot ? fromEvent(slot, 'slotchange').pipe(\n\t\t\tstartWith(null), // Emit immediately to capture initial state\n\t\t\tmap(() => this.routes || []), // Use queryAssignedElements result\n\t\t) : of([])\n\n\t\t// Create navigation event streams that will be combined with routes\n\t\tconst initialLoad$ = combineLatest([\n\t\t\tof(location.pathname),\n\t\t\tslotChanges$\n\t\t]).pipe(\n\t\t\ttake(1),\n\t\t\tswitchMap(([pathname, routes]) => this.resolveRoute('initial', pathname, HISTORY_STRATEGY.silent, routes)),\n\t\t)\n\n\t\tconst navigation$ = combineLatest([\n\t\t\tarea.request.pipe(filter(({ area }) => area === this.name)),\n\t\t\tslotChanges$\n\t\t]).pipe(\n\t\t\tswitchMap(([route, routes]) => this.resolveRoute('navigation', route, HISTORY_STRATEGY.silent, routes)),\n\t\t)\n\n\t\tconst popstate$ = combineLatest([\n\t\t\tfromEvent<PopStateEvent>(window, 'popstate'),\n\t\t\tslotChanges$\n\t\t]).pipe(\n\t\t\tswitchMap(([event, routes]) => this.resolveRoute('popstate', event, HISTORY_STRATEGY.silent, routes)),\n\t\t)\n\n\t\t// Create the base routing stream - matchSegmentToRoute now handles defaults\n\t\tconst baseRouting$ = merge(initialLoad$, navigation$, popstate$)\n\n\t\t// Create the routing pipeline directly from baseRouting$\n\t\tthis.routingSubscription = baseRouting$.pipe(\n\t\t\t// Add debounceTime to coalesce rapid emissions (especially during initialization)\n\t\t\tdebounceTime(0),\n\n\t\t\t// Filter out invalid routes (but allow null for clearing)\n\t\t\tfilter(route => {\n\t\t\t\t// Allow null component as a signal to clear the area\n\t\t\t\tconst valid = route.component !== undefined\n\t\t\t\treturn valid\n\t\t\t}),\n\n\t\t\t// Prevent duplicate navigations using deep comparison\n\t\t\tdistinctUntilChanged((a, b) => {\n\t\t\t\tconst same = this.isSameRoute(a, b)\n\t\t\t\treturn same\n\t\t\t}),\n\n\t\t\t// Share the resolved route state across subscribers\n\t\t\tshareReplay(1),\n\n\t\t\t// Resolve component to HTMLElement\n\t\t\tswitchMap(route => {\n\t\t\t\treturn from(this.resolveComponent(route.component as ComponentInput)).pipe(\n\t\t\t\t\tmap(resolved => ({ ...resolved, route }))\n\t\t\t\t)\n\t\t\t}),\n\n\t\t\t// Apply props, params, and state to element\n\t\t\tmap(({ element, route }) => {\n\t\t\t\tif (element) {\n\t\t\t\t\t// Apply params\n\t\t\t\t\tif (route.params) {\n\t\t\t\t\t\tObject.entries(route.params).forEach(([key, value]) => {\n\t\t\t\t\t\t\t(element as any)[key] = value\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply props\n\t\t\t\t\tif (route.props) {\n\t\t\t\t\t\tObject.entries(route.props).forEach(([key, value]) => {\n\t\t\t\t\t\t\t(element as any)[key] = value\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply state\n\t\t\t\t\tif (route.state) {\n\t\t\t\t\t\t(element as any).state = route.state\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn { element, route }\n\t\t\t}),\n\n\t\t\t// Update DOM and handle side effects\n\t\t\ttap(({ element, route }) => {\n\t\t\t\t// Update DOM\n\t\t\t\tthis.updateDOM(element)\n\n\t\t\t\t// Update internal state\n\t\t\t\tif (element) {\n\t\t\t\t\tthis.updateInternalState(route, element)\n\t\t\t\t}\n\n\t\t\t\t// Handle browser history\n\t\t\t\tthis.updateBrowserHistory(route, element)\n\t\t\t}),\n\n\t\t\t// Error handling\n\t\t\tcatchError(error => {\n\t\t\t\tconsole.error(`[${this.name}] Navigation error:`, error)\n\t\t\t\treturn EMPTY\n\t\t\t}),\n\n\t\t\ttakeUntil(this.disconnecting)\n\t\t).subscribe({\n\t\t\terror: (error) => {\n\t\t\t\tconsole.error(`[${this.name}] Subscription error:`, error)\n\t\t\t}\n\t\t})\n\t}\n\n\n\t/**\n\t * Check if two routes are the same (for duplicate prevention)\n\t */\n\tprivate isSameRoute(a: RouteAction, b: RouteAction): boolean {\n\t\t// Handle null components (clearing signals)\n\t\tif (a.component === null && b.component === null) {\n\t\t\treturn true // Both are clearing signals\n\t\t}\n\t\tif (a.component === null || b.component === null) {\n\t\t\treturn false // One is clearing, one is not\n\t\t}\n\n\t\tlet aComponent = '', bComponent = ''\n\n\t\t// Extract component identifiers\n\t\tif (typeof a.component === 'function') {\n\t\t\taComponent = (a.component as any).name || a.component.toString()\n\t\t} else if (typeof a.component === 'string') {\n\t\t\taComponent = a.component\n\t\t} else if (a.component instanceof HTMLElement) {\n\t\t\taComponent = a.component.tagName.toLowerCase()\n\t\t}\n\n\t\tif (typeof b.component === 'function') {\n\t\t\tbComponent = (b.component as any).name || b.component.toString()\n\t\t} else if (typeof b.component === 'string') {\n\t\t\tbComponent = b.component\n\t\t} else if (b.component instanceof HTMLElement) {\n\t\t\tbComponent = b.component.tagName.toLowerCase()\n\t\t}\n\n\t\t// Normalize and compare\n\t\tconst normalizeComponent = (c: string) => c?.replaceAll('-', '').toLowerCase()\n\t\tconst sameComponent = normalizeComponent(aComponent) === normalizeComponent(bComponent)\n\t\tconst sameParams = JSON.stringify(a.params || {}) === JSON.stringify(b.params || {})\n\t\tconst sameState = JSON.stringify(a.state || {}) === JSON.stringify(b.state || {})\n\n\t\tconst result = sameComponent && sameParams && sameState\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Update the DOM with the new component\n\t */\n\tprivate updateDOM(component: HTMLElement | null) {\n\n\t\tconst oldView = this.shadowRoot?.children[0]\n\t\tconst oldViewExists = !!oldView\n\n\t\t// Remove the old view (if any)\n\t\tif (oldView) {\n\t\t\toldView.remove()\n\t\t}\n\n\t\t// If component is null, we're clearing the area\n\t\tif (!component) {\n\t\t\treturn\n\t\t}\n\n\t\t// Add new component with animation\n\n\t\t// Append the component first\n\t\tthis.shadowRoot?.append(component)\n\n\n\t\t// Check if component was actually appended\n\t\tif (!this.shadowRoot?.contains(component)) {\n\t\t\tconsole.error(`[${this.name}] CRITICAL: Component was not appended to shadowRoot!`)\n\t\t\tconsole.error(`[${this.name}] ShadowRoot:`, this.shadowRoot)\n\t\t\tconsole.error(`[${this.name}] Component:`, component)\n\t\t\treturn\n\t\t}\n\n\t\t// Animate in without opacity class - use Web Animations API directly\n\t\tconst animation = component.animate([{ opacity: 0 }, { opacity: 1 }], {\n\t\t\tduration: oldViewExists ? 150 : 100,\n\t\t\teasing: 'cubic-bezier(0.25, 0.8, 0.25, 1)',\n\t\t\tfill: 'forwards',\n\t\t})\n\n\t\tanimation.onfinish = () => {\n\t\t\t// Ensure opacity is set to 1 after animation\n\t\t\tcomponent.style.opacity = '1'\n\t\t}\n\t}\n\n\t/**\n\t * Update internal router state\n\t */\n\tprivate updateInternalState(route: RouteAction, component: HTMLElement | null) {\n\t\t// If component is null, we're clearing\n\t\tif (!component) {\n\t\t\t// Don't update state - it's already been cleared by the service\n\t\t\treturn\n\t\t}\n\t\t\n\t\tconst activeRoute: ActiveRoute = {\n\t\t\tcomponent: component.tagName.toLowerCase(),\n\t\t\tstate: route.state || {},\n\t\t\tarea: this.name,\n\t\t\tparams: route.params || {},\n\t\t}\n\n\t\tarea.current.set(this.name, activeRoute)\n\t\tarea.$current.next(area.current)\n\t}\n\n\t/**\n\t * Update browser history (only for programmatic navigation)\n\t */\n\tprivate updateBrowserHistory(route: RouteAction, component: HTMLElement | null) {\n\t\tif (!area.enableHistoryMode) return\n\n\t\t// If clearing, don't update history (already handled by service)\n\t\tif (!component) {\n\t\t\treturn\n\t\t}\n\n\t\tconst activeRoute: ActiveRoute = {\n\t\t\tcomponent: component.tagName.toLowerCase(),\n\t\t\tstate: route.state || {},\n\t\t\tarea: this.name,\n\t\t\tparams: route.params || {},\n\t\t}\n\n\t\t// Use the service method to update browser history\n\t\tarea._updateBrowserHistory(this.name, activeRoute, route.historyStrategy, route.clearQueryParams)\n\t}\n\n\n\t/**\n\t * Create URL path for the route (legacy method, now handled by service)\n\t */\n\tnewPath(tag: string, route: RouteAction) {\n\t\tconst oldPathname = location.pathname.split('/').pop()\n\t\tlet oldAreaState = {}\n\t\ttry {\n\t\t\toldAreaState = oldPathname ? JSON.parse(decodeURIComponent(oldPathname)) : {}\n\t\t} catch {\n\t\t\toldAreaState = {}\n\t\t}\n\t\troute.state = route.state ?? {}\n\t\tconst queryParams = route.clearQueryParams ? this.queryParamClear(route.clearQueryParams) : document.location.search\n\n\t\treturn encodeURIComponent(\n\t\t\tJSON.stringify({\n\t\t\t\t...oldAreaState,\n\t\t\t\t[this.name]: { component: tag.toLowerCase(), state: route.state, params: route.params },\n\t\t\t}),\n\t\t).concat(`${queryParams}`)\n\t}\n\n\t/**\n\t * Clear query parameters\n\t */\n\tqueryParamClear(params?: string[] | boolean) {\n\t\tif (!params) {\n\t\t\treturn ''\n\t\t}\n\t\t// get query params from url\n\t\tconst urlParams = new URLSearchParams(location.search)\n\t\t\n\t\tif (params === true) {\n\t\t\t// Clear all query params\n\t\t\treturn ''\n\t\t} else {\n\t\t\t// Clear specific query params\n\t\t\tparams.forEach(param => urlParams.delete(param))\n\t\t\t// update url\n\t\t\tif (urlParams.toString() === '') return ''\n\t\t\treturn `?${urlParams.toString()}`\n\t\t}\n\t}\n\n\tdisconnectedCallback() {\n\t\tsuper.disconnectedCallback()\n\t\t// Clean up the routing subscription\n\t\tif (this.routingSubscription) {\n\t\t\tthis.routingSubscription.unsubscribe()\n\t\t\tthis.routingSubscription = undefined\n\t\t}\n\t}\n\n\trender() {\n\t\treturn html` <slot> </slot> `\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-area': SchmancyArea\n\t}\n}","import { html, css, TemplateResult } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { $LitElement } from '@mixins/index';\n\nexport type GuardResult = boolean | string | { redirect: string };\n\n// Component types that can be passed to routes\nexport type RouteComponent =\n | string // Tag name\n | CustomElementConstructor // Constructor function\n | HTMLElement // Existing element\n | TemplateResult<1> // Lit template\n | (() => Promise<{ default: CustomElementConstructor }>) // Lazy loader\n | Promise<{ default: CustomElementConstructor }>; // Dynamic import\n\nexport interface RouteConfig {\n when: string;\n component: RouteComponent;\n exact?: boolean;\n guard?: () => GuardResult | Promise<GuardResult>;\n}\n\n/**\n * A marker component that holds route configuration.\n * This component doesn't render anything - it's used by schmancy-area\n * to configure routing via slot change detection.\n *\n * @example\n * ```html\n * <schmancy-area>\n * <schmancy-route\n * when=\"users\"\n * .component=${UserComponent}\n * exact\n * ></schmancy-route>\n * </schmancy-area>\n * ```\n */\n@customElement('schmancy-route')\nexport class SchmancyRoute extends $LitElement(css`\n :host {\n display: none;\n }\n`) {\n @property({ type: String })\n when!: string;\n\n @property({ type: Object })\n component!: RouteComponent;\n\n @property({ type: Boolean })\n exact?: boolean = false;\n\n @property({ type: Object })\n guard?: () => GuardResult | Promise<GuardResult>;\n\n /**\n * Returns the route configuration object\n */\n getConfig(): RouteConfig {\n return {\n when: this.when,\n component: this.component,\n exact: this.exact,\n guard: this.guard\n };\n }\n\n render() {\n // This is a marker component - no visual output\n return html``;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'schmancy-route': SchmancyRoute;\n }\n}"],"names":["routerHistory","Subject","FINDING_MORTIES","HERE_RICKY","areaSubjectsCache","WeakMap","AreaService","constructor","this","prettyURL","mode","request","ReplaySubject","current","Map","$current","enableHistoryMode","findingMortiesEvent","CustomEvent","disposed","isProcessingPopstate","next","subscribe","currentAreas","forEach","route","areaName","getOrCreateAreaSubject","initializeFromBrowserState","areaSubjects","subjects","get","set","browserState","history","state","schmancyAreas","Object","entries","error","subject","closed","currentRoute","params","props","skipCurrent","Error","observable","asObservable","pipe","distinctUntilChanged","a","b","component","JSON","stringify","shareReplay","skip","on","map","filter","catchError","err","EMPTY","key","value","zip","fromEvent","window","e","detail","bufferTime","of","tap","dispatchEvent","timeout","r","area","routeAction","_source","dispatchAreaEvent","enhancedRoute","historyStrategy","clearQueryParams","currentState","areaData","keys","length","newState","url","createCleanURL","replaceState","pushState","areas","queryString","urlParams","URLSearchParams","location","search","Array","isArray","param","delete","toString","mainArea","main","path","searchParams","String","query","cleanedAreas","cleanRoute","encodeURIComponent","pathname","parseStateFromURL","split","pop","decoded","decodeURIComponent","parsed","parse","event","bubbles","composed","name","areaSubject","clear","complete","dispose","getInstance","instance","has","from","addEventListener","HISTORY_STRATEGY","SchmancyArea","$LitElement","css","source","data","silent","routes","matchSegmentToRoute","lastSegment","includes","currentSegment","Boolean","when","guard","Promise","resolve","switchMap","guardResult","default","redirect","element","document","createElement","HTMLElement","Constructor","firstUpdated","routingSubscription","unsubscribe","slot","shadowRoot","querySelector","slotChanges$","startWith","initialLoad$","combineLatest","take","resolveRoute","navigation$","popstate$","baseRouting$","merge","debounceTime","isSameRoute","resolveComponent","resolved","updateDOM","updateInternalState","updateBrowserHistory","takeUntil","disconnecting","aComponent","bComponent","tagName","toLowerCase","normalizeComponent","c","replaceAll","sameComponent","sameParams","sameState","oldView","children","oldViewExists","remove","append","contains","animate","opacity","duration","easing","fill","onfinish","style","activeRoute","_updateBrowserHistory","tag","oldPathname","oldAreaState","queryParams","queryParamClear","concat","disconnectedCallback","super","render","html","__decorateClass","property","prototype","queryAssignedElements","selector","customElement","SchmancyRoute","arguments","exact","getConfig","type"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils-03Coa8AW.js","sources":["../src/area/utils.ts"],"sourcesContent":["import { RouteAction, ActiveRoute } from './router.types'\n\n/**\n * Compare two custom element constructors for equality\n * @param constructor1 First constructor to compare\n * @param constructor2 Second constructor to compare\n * @returns true if constructors are functionally equivalent\n */\nexport function compareCustomElementConstructors(\n\tconstructor1: CustomElementConstructor | Function,\n\tconstructor2: CustomElementConstructor | Function\n): boolean {\n\t// Quick reference check\n\tif (constructor1 === constructor2) {\n\t\treturn true\n\t}\n\n\t// Check if both are functions\n\tif (typeof constructor1 !== 'function' || typeof constructor2 !== 'function') {\n\t\treturn false\n\t}\n\n\t// Compare by name (handles minification)\n\tif (constructor1.name && constructor2.name && constructor1.name === constructor2.name) {\n\t\treturn true\n\t}\n\n\t// Compare observed attributes if available\n\tconst obs1 = (constructor1 as any).observedAttributes\n\tconst obs2 = (constructor2 as any).observedAttributes\n\t\n\tif (obs1 && obs2) {\n\t\tif (Array.isArray(obs1) && Array.isArray(obs2)) {\n\t\t\tif (obs1.length !== obs2.length) return false\n\t\t\treturn obs1.every((attr, i) => attr === obs2[i])\n\t\t}\n\t}\n\n\t// Try to compare prototypes\n\ttry {\n\t\tconst proto1 = constructor1.prototype\n\t\tconst proto2 = constructor2.prototype\n\t\t\n\t\t// Check if they have the same prototype chain\n\t\tif (Object.getPrototypeOf(proto1) === Object.getPrototypeOf(proto2)) {\n\t\t\t// Check if they have the same property names\n\t\t\tconst keys1 = Object.getOwnPropertyNames(proto1).sort()\n\t\t\tconst keys2 = Object.getOwnPropertyNames(proto2).sort()\n\t\t\t\n\t\t\treturn keys1.length === keys2.length && \n\t\t\t\t keys1.every((key, i) => key === keys2[i])\n\t\t}\n\t} catch {\n\t\t// Ignore prototype access errors\n\t}\n\n\treturn false\n}\n\n/**\n * Normalize a component tag name for comparison\n * @param tagName Tag name to normalize\n * @returns Normalized tag name\n */\nexport function normalizeTagName(tagName: string): string {\n\treturn tagName\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]/g, '') // Remove all non-alphanumeric characters\n}\n\n/**\n * Get tag name from a component\n * @param component Component to get tag name from\n * @returns Tag name or null if unable to determine\n */\nexport function getTagName(component: any): string | null {\n\tif (typeof component === 'string') {\n\t\treturn component.toLowerCase()\n\t}\n\t\n\tif (component instanceof HTMLElement) {\n\t\treturn component.tagName.toLowerCase()\n\t}\n\t\n\tif (typeof component === 'function') {\n\t\t// Try to get custom element name from constructor\n\t\tconst name = component.name\n\t\tif (name) {\n\t\t\t// Convert PascalCase to kebab-case\n\t\t\treturn name\n\t\t\t\t.replace(/([A-Z])/g, '-$1')\n\t\t\t\t.toLowerCase()\n\t\t\t\t.replace(/^-/, '')\n\t\t}\n\t}\n\t\n\treturn null\n}\n\n/**\n * Deep merge two objects\n * @param target Target object\n * @param source Source object to merge\n * @returns Merged object\n */\nexport function deepMerge<T extends Record<string, any>>(\n\ttarget: T,\n\tsource: Partial<T>\n): T {\n\tconst output = { ...target }\n\t\n\tfor (const key in source) {\n\t\tif (source.hasOwnProperty(key)) {\n\t\t\tconst sourceValue = source[key]\n\t\t\tconst targetValue = output[key]\n\t\t\t\n\t\t\tif (isObject(sourceValue) && isObject(targetValue)) {\n\t\t\t\toutput[key] = deepMerge(targetValue, sourceValue)\n\t\t\t} else {\n\t\t\t\toutput[key] = sourceValue as T[Extract<keyof T, string>]\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn output\n}\n\n/**\n * Check if value is a plain object\n * @param obj Value to check\n * @returns true if value is a plain object\n */\nexport function isObject(obj: any): obj is Record<string, any> {\n\treturn obj !== null && \n\t\t typeof obj === 'object' && \n\t\t obj.constructor === Object &&\n\t\t Object.prototype.toString.call(obj) === '[object Object]'\n}\n\n/**\n * Debounce a function\n * @param func Function to debounce\n * @param wait Wait time in milliseconds\n * @returns Debounced function\n */\nexport function debounce<T extends (...args: any[]) => any>(\n\tfunc: T,\n\twait: number\n): (...args: Parameters<T>) => void {\n\tlet timeout: ReturnType<typeof setTimeout> | null = null\n\t\n\treturn function (this: any, ...args: Parameters<T>) {\n\t\tconst context = this\n\t\t\n\t\tif (timeout !== null) {\n\t\t\tclearTimeout(timeout)\n\t\t}\n\t\t\n\t\ttimeout = setTimeout(() => {\n\t\t\tfunc.apply(context, args)\n\t\t\ttimeout = null\n\t\t}, wait)\n\t}\n}\n\n/**\n * Create a URL-safe string from route state\n * @param state Route state object\n * @returns URL-safe encoded string\n */\nexport function encodeRouteState(state: Record<string, unknown>): string {\n\ttry {\n\t\tconst json = JSON.stringify(state)\n\t\treturn encodeURIComponent(json)\n\t} catch (error) {\n\t\tconsole.error('Failed to encode route state:', error)\n\t\treturn ''\n\t}\n}\n\n/**\n * Decode a URL-safe string to route state\n * @param encoded Encoded string\n * @returns Decoded route state or empty object\n */\nexport function decodeRouteState(encoded: string): Record<string, unknown> {\n\tif (!encoded) return {}\n\t\n\ttry {\n\t\tconst decoded = decodeURIComponent(encoded)\n\t\tconst parsed = JSON.parse(decoded)\n\t\t\n\t\tif (isObject(parsed)) {\n\t\t\treturn parsed\n\t\t}\n\t} catch (error) {\n\t\tconsole.error('Failed to decode route state:', error)\n\t}\n\t\n\treturn {}\n}\n\n/**\n * Compare two route actions for equality\n * @param a First route action\n * @param b Second route action\n * @returns true if route actions are equal\n */\nexport function compareRouteActions(a: RouteAction, b: RouteAction): boolean {\n\t// Compare areas\n\tif (a.area !== b.area) return false\n\t\n\t// Compare components\n\tif (typeof a.component !== typeof b.component) return false\n\t\n\tif (typeof a.component === 'string' && typeof b.component === 'string') {\n\t\tif (normalizeTagName(a.component) !== normalizeTagName(b.component)) {\n\t\t\treturn false\n\t\t}\n\t} else if (typeof a.component === 'function' && typeof b.component === 'function') {\n\t\tif (!compareCustomElementConstructors(a.component, b.component)) {\n\t\t\treturn false\n\t\t}\n\t} else if (a.component !== b.component) {\n\t\treturn false\n\t}\n\t\n\t// Compare state\n\tif (JSON.stringify(a.state || {}) !== JSON.stringify(b.state || {})) {\n\t\treturn false\n\t}\n\t\n\t// Compare params\n\tif (JSON.stringify(a.params || {}) !== JSON.stringify(b.params || {})) {\n\t\treturn false\n\t}\n\t\n\treturn true\n}\n\n/**\n * Compare two active routes for equality\n * @param a First active route\n * @param b Second active route\n * @returns true if active routes are equal\n */\nexport function compareActiveRoutes(a: ActiveRoute, b: ActiveRoute): boolean {\n\treturn a.area === b.area &&\n\t\t a.component === b.component &&\n\t\t JSON.stringify(a.state || {}) === JSON.stringify(b.state || {}) &&\n\t\t JSON.stringify(a.params || {}) === JSON.stringify(b.params || {})\n}\n\n/**\n * Create a cache key from a route action\n * @param route Route action\n * @returns Cache key string\n */\nexport function createRouteCacheKey(route: RouteAction): string {\n\tconst tagName = getTagName(route.component) || 'unknown'\n\tconst stateHash = simpleHash(JSON.stringify(route.state || {}))\n\tconst paramsHash = simpleHash(JSON.stringify(route.params || {}))\n\t\n\treturn `${route.area}:${tagName}:${stateHash}:${paramsHash}`\n}\n\n/**\n * Simple hash function for creating cache keys\n * @param str String to hash\n * @returns Hash string\n */\nfunction simpleHash(str: string): string {\n\tlet hash = 0\n\t\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst char = str.charCodeAt(i)\n\t\thash = ((hash << 5) - hash) + char\n\t\thash = hash & hash // Convert to 32-bit integer\n\t}\n\t\n\treturn Math.abs(hash).toString(36)\n}\n\n/**\n * Sanitize route state to remove sensitive data\n * @param state Route state\n * @param keysToRemove Keys to remove from state\n * @returns Sanitized state\n */\nexport function sanitizeRouteState(\n\tstate: Record<string, unknown>,\n\tkeysToRemove: string[] = ['password', 'token', 'secret', 'apiKey']\n): Record<string, unknown> {\n\tconst sanitized: Record<string, unknown> = {}\n\t\n\tfor (const key in state) {\n\t\tif (state.hasOwnProperty(key) && !keysToRemove.includes(key)) {\n\t\t\tconst value = state[key]\n\t\t\t\n\t\t\tif (isObject(value)) {\n\t\t\t\tsanitized[key] = sanitizeRouteState(value, keysToRemove)\n\t\t\t} else if (Array.isArray(value)) {\n\t\t\t\tsanitized[key] = value.map(item => \n\t\t\t\t\tisObject(item) ? sanitizeRouteState(item, keysToRemove) : item\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tsanitized[key] = value\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn sanitized\n}\n\n/**\n * Extract query parameters from URL\n * @param url URL string or URLSearchParams\n * @returns Object with query parameters\n */\nexport function extractQueryParams(url?: string | URLSearchParams): Record<string, string> {\n\tconst params: Record<string, string> = {}\n\t\n\tlet searchParams: URLSearchParams\n\t\n\tif (url instanceof URLSearchParams) {\n\t\tsearchParams = url\n\t} else if (typeof url === 'string') {\n\t\tconst urlObj = new URL(url, window.location.origin)\n\t\tsearchParams = urlObj.searchParams\n\t} else {\n\t\tsearchParams = new URLSearchParams(window.location.search)\n\t}\n\t\n\tsearchParams.forEach((value, key) => {\n\t\tparams[key] = value\n\t})\n\t\n\treturn params\n}\n\n/**\n * Build query string from parameters object\n * @param params Parameters object\n * @returns Query string with leading '?'\n */\nexport function buildQueryString(params: Record<string, string | number | boolean>): string {\n\tconst searchParams = new URLSearchParams()\n\t\n\tfor (const key in params) {\n\t\tif (params.hasOwnProperty(key)) {\n\t\t\tconst value = params[key]\n\t\t\tif (value !== undefined && value !== null && value !== '') {\n\t\t\t\tsearchParams.set(key, String(value))\n\t\t\t}\n\t\t}\n\t}\n\t\n\tconst queryString = searchParams.toString()\n\treturn queryString ? `?${queryString}` : ''\n}"],"names":["compareCustomElementConstructors","constructor1","constructor2","name","obs1","observedAttributes","obs2","Array","isArray","length","every","attr","i","proto1","prototype","proto2","Object","getPrototypeOf","keys1","getOwnPropertyNames","sort","keys2","key","normalizeTagName","tagName","toLowerCase","replace","getTagName","component","HTMLElement","deepMerge","target","source","output","hasOwnProperty","sourceValue","targetValue","isObject","obj","constructor","toString","call","debounce","func","wait","timeout","args","context","this","clearTimeout","setTimeout","apply","encodeRouteState","state","json","JSON","stringify","encodeURIComponent","error","decodeRouteState","encoded","decoded","decodeURIComponent","parsed","parse","compareRouteActions","a","b","area","params","compareActiveRoutes","createRouteCacheKey","route","stateHash","simpleHash","paramsHash","str","hash","charCodeAt","Math","abs","sanitizeRouteState","keysToRemove","sanitized","includes","value","map","item","extractQueryParams","url","searchParams","URLSearchParams","URL","window","location","origin","search","forEach","buildQueryString","set","String","queryString"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils-C9nzOWpR.cjs","sources":["../src/area/utils.ts"],"sourcesContent":["import { RouteAction, ActiveRoute } from './router.types'\n\n/**\n * Compare two custom element constructors for equality\n * @param constructor1 First constructor to compare\n * @param constructor2 Second constructor to compare\n * @returns true if constructors are functionally equivalent\n */\nexport function compareCustomElementConstructors(\n\tconstructor1: CustomElementConstructor | Function,\n\tconstructor2: CustomElementConstructor | Function\n): boolean {\n\t// Quick reference check\n\tif (constructor1 === constructor2) {\n\t\treturn true\n\t}\n\n\t// Check if both are functions\n\tif (typeof constructor1 !== 'function' || typeof constructor2 !== 'function') {\n\t\treturn false\n\t}\n\n\t// Compare by name (handles minification)\n\tif (constructor1.name && constructor2.name && constructor1.name === constructor2.name) {\n\t\treturn true\n\t}\n\n\t// Compare observed attributes if available\n\tconst obs1 = (constructor1 as any).observedAttributes\n\tconst obs2 = (constructor2 as any).observedAttributes\n\t\n\tif (obs1 && obs2) {\n\t\tif (Array.isArray(obs1) && Array.isArray(obs2)) {\n\t\t\tif (obs1.length !== obs2.length) return false\n\t\t\treturn obs1.every((attr, i) => attr === obs2[i])\n\t\t}\n\t}\n\n\t// Try to compare prototypes\n\ttry {\n\t\tconst proto1 = constructor1.prototype\n\t\tconst proto2 = constructor2.prototype\n\t\t\n\t\t// Check if they have the same prototype chain\n\t\tif (Object.getPrototypeOf(proto1) === Object.getPrototypeOf(proto2)) {\n\t\t\t// Check if they have the same property names\n\t\t\tconst keys1 = Object.getOwnPropertyNames(proto1).sort()\n\t\t\tconst keys2 = Object.getOwnPropertyNames(proto2).sort()\n\t\t\t\n\t\t\treturn keys1.length === keys2.length && \n\t\t\t\t keys1.every((key, i) => key === keys2[i])\n\t\t}\n\t} catch {\n\t\t// Ignore prototype access errors\n\t}\n\n\treturn false\n}\n\n/**\n * Normalize a component tag name for comparison\n * @param tagName Tag name to normalize\n * @returns Normalized tag name\n */\nexport function normalizeTagName(tagName: string): string {\n\treturn tagName\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]/g, '') // Remove all non-alphanumeric characters\n}\n\n/**\n * Get tag name from a component\n * @param component Component to get tag name from\n * @returns Tag name or null if unable to determine\n */\nexport function getTagName(component: any): string | null {\n\tif (typeof component === 'string') {\n\t\treturn component.toLowerCase()\n\t}\n\t\n\tif (component instanceof HTMLElement) {\n\t\treturn component.tagName.toLowerCase()\n\t}\n\t\n\tif (typeof component === 'function') {\n\t\t// Try to get custom element name from constructor\n\t\tconst name = component.name\n\t\tif (name) {\n\t\t\t// Convert PascalCase to kebab-case\n\t\t\treturn name\n\t\t\t\t.replace(/([A-Z])/g, '-$1')\n\t\t\t\t.toLowerCase()\n\t\t\t\t.replace(/^-/, '')\n\t\t}\n\t}\n\t\n\treturn null\n}\n\n/**\n * Deep merge two objects\n * @param target Target object\n * @param source Source object to merge\n * @returns Merged object\n */\nexport function deepMerge<T extends Record<string, any>>(\n\ttarget: T,\n\tsource: Partial<T>\n): T {\n\tconst output = { ...target }\n\t\n\tfor (const key in source) {\n\t\tif (source.hasOwnProperty(key)) {\n\t\t\tconst sourceValue = source[key]\n\t\t\tconst targetValue = output[key]\n\t\t\t\n\t\t\tif (isObject(sourceValue) && isObject(targetValue)) {\n\t\t\t\toutput[key] = deepMerge(targetValue, sourceValue)\n\t\t\t} else {\n\t\t\t\toutput[key] = sourceValue as T[Extract<keyof T, string>]\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn output\n}\n\n/**\n * Check if value is a plain object\n * @param obj Value to check\n * @returns true if value is a plain object\n */\nexport function isObject(obj: any): obj is Record<string, any> {\n\treturn obj !== null && \n\t\t typeof obj === 'object' && \n\t\t obj.constructor === Object &&\n\t\t Object.prototype.toString.call(obj) === '[object Object]'\n}\n\n/**\n * Debounce a function\n * @param func Function to debounce\n * @param wait Wait time in milliseconds\n * @returns Debounced function\n */\nexport function debounce<T extends (...args: any[]) => any>(\n\tfunc: T,\n\twait: number\n): (...args: Parameters<T>) => void {\n\tlet timeout: ReturnType<typeof setTimeout> | null = null\n\t\n\treturn function (this: any, ...args: Parameters<T>) {\n\t\tconst context = this\n\t\t\n\t\tif (timeout !== null) {\n\t\t\tclearTimeout(timeout)\n\t\t}\n\t\t\n\t\ttimeout = setTimeout(() => {\n\t\t\tfunc.apply(context, args)\n\t\t\ttimeout = null\n\t\t}, wait)\n\t}\n}\n\n/**\n * Create a URL-safe string from route state\n * @param state Route state object\n * @returns URL-safe encoded string\n */\nexport function encodeRouteState(state: Record<string, unknown>): string {\n\ttry {\n\t\tconst json = JSON.stringify(state)\n\t\treturn encodeURIComponent(json)\n\t} catch (error) {\n\t\tconsole.error('Failed to encode route state:', error)\n\t\treturn ''\n\t}\n}\n\n/**\n * Decode a URL-safe string to route state\n * @param encoded Encoded string\n * @returns Decoded route state or empty object\n */\nexport function decodeRouteState(encoded: string): Record<string, unknown> {\n\tif (!encoded) return {}\n\t\n\ttry {\n\t\tconst decoded = decodeURIComponent(encoded)\n\t\tconst parsed = JSON.parse(decoded)\n\t\t\n\t\tif (isObject(parsed)) {\n\t\t\treturn parsed\n\t\t}\n\t} catch (error) {\n\t\tconsole.error('Failed to decode route state:', error)\n\t}\n\t\n\treturn {}\n}\n\n/**\n * Compare two route actions for equality\n * @param a First route action\n * @param b Second route action\n * @returns true if route actions are equal\n */\nexport function compareRouteActions(a: RouteAction, b: RouteAction): boolean {\n\t// Compare areas\n\tif (a.area !== b.area) return false\n\t\n\t// Compare components\n\tif (typeof a.component !== typeof b.component) return false\n\t\n\tif (typeof a.component === 'string' && typeof b.component === 'string') {\n\t\tif (normalizeTagName(a.component) !== normalizeTagName(b.component)) {\n\t\t\treturn false\n\t\t}\n\t} else if (typeof a.component === 'function' && typeof b.component === 'function') {\n\t\tif (!compareCustomElementConstructors(a.component, b.component)) {\n\t\t\treturn false\n\t\t}\n\t} else if (a.component !== b.component) {\n\t\treturn false\n\t}\n\t\n\t// Compare state\n\tif (JSON.stringify(a.state || {}) !== JSON.stringify(b.state || {})) {\n\t\treturn false\n\t}\n\t\n\t// Compare params\n\tif (JSON.stringify(a.params || {}) !== JSON.stringify(b.params || {})) {\n\t\treturn false\n\t}\n\t\n\treturn true\n}\n\n/**\n * Compare two active routes for equality\n * @param a First active route\n * @param b Second active route\n * @returns true if active routes are equal\n */\nexport function compareActiveRoutes(a: ActiveRoute, b: ActiveRoute): boolean {\n\treturn a.area === b.area &&\n\t\t a.component === b.component &&\n\t\t JSON.stringify(a.state || {}) === JSON.stringify(b.state || {}) &&\n\t\t JSON.stringify(a.params || {}) === JSON.stringify(b.params || {})\n}\n\n/**\n * Create a cache key from a route action\n * @param route Route action\n * @returns Cache key string\n */\nexport function createRouteCacheKey(route: RouteAction): string {\n\tconst tagName = getTagName(route.component) || 'unknown'\n\tconst stateHash = simpleHash(JSON.stringify(route.state || {}))\n\tconst paramsHash = simpleHash(JSON.stringify(route.params || {}))\n\t\n\treturn `${route.area}:${tagName}:${stateHash}:${paramsHash}`\n}\n\n/**\n * Simple hash function for creating cache keys\n * @param str String to hash\n * @returns Hash string\n */\nfunction simpleHash(str: string): string {\n\tlet hash = 0\n\t\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst char = str.charCodeAt(i)\n\t\thash = ((hash << 5) - hash) + char\n\t\thash = hash & hash // Convert to 32-bit integer\n\t}\n\t\n\treturn Math.abs(hash).toString(36)\n}\n\n/**\n * Sanitize route state to remove sensitive data\n * @param state Route state\n * @param keysToRemove Keys to remove from state\n * @returns Sanitized state\n */\nexport function sanitizeRouteState(\n\tstate: Record<string, unknown>,\n\tkeysToRemove: string[] = ['password', 'token', 'secret', 'apiKey']\n): Record<string, unknown> {\n\tconst sanitized: Record<string, unknown> = {}\n\t\n\tfor (const key in state) {\n\t\tif (state.hasOwnProperty(key) && !keysToRemove.includes(key)) {\n\t\t\tconst value = state[key]\n\t\t\t\n\t\t\tif (isObject(value)) {\n\t\t\t\tsanitized[key] = sanitizeRouteState(value, keysToRemove)\n\t\t\t} else if (Array.isArray(value)) {\n\t\t\t\tsanitized[key] = value.map(item => \n\t\t\t\t\tisObject(item) ? sanitizeRouteState(item, keysToRemove) : item\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tsanitized[key] = value\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn sanitized\n}\n\n/**\n * Extract query parameters from URL\n * @param url URL string or URLSearchParams\n * @returns Object with query parameters\n */\nexport function extractQueryParams(url?: string | URLSearchParams): Record<string, string> {\n\tconst params: Record<string, string> = {}\n\t\n\tlet searchParams: URLSearchParams\n\t\n\tif (url instanceof URLSearchParams) {\n\t\tsearchParams = url\n\t} else if (typeof url === 'string') {\n\t\tconst urlObj = new URL(url, window.location.origin)\n\t\tsearchParams = urlObj.searchParams\n\t} else {\n\t\tsearchParams = new URLSearchParams(window.location.search)\n\t}\n\t\n\tsearchParams.forEach((value, key) => {\n\t\tparams[key] = value\n\t})\n\t\n\treturn params\n}\n\n/**\n * Build query string from parameters object\n * @param params Parameters object\n * @returns Query string with leading '?'\n */\nexport function buildQueryString(params: Record<string, string | number | boolean>): string {\n\tconst searchParams = new URLSearchParams()\n\t\n\tfor (const key in params) {\n\t\tif (params.hasOwnProperty(key)) {\n\t\t\tconst value = params[key]\n\t\t\tif (value !== undefined && value !== null && value !== '') {\n\t\t\t\tsearchParams.set(key, String(value))\n\t\t\t}\n\t\t}\n\t}\n\t\n\tconst queryString = searchParams.toString()\n\treturn queryString ? `?${queryString}` : ''\n}"],"names":["compareCustomElementConstructors","constructor1","constructor2","name","obs1","observedAttributes","obs2","Array","isArray","length","every","attr","i","proto1","prototype","proto2","Object","getPrototypeOf","keys1","getOwnPropertyNames","sort","keys2","key","normalizeTagName","tagName","toLowerCase","replace","getTagName","component","HTMLElement","isObject","obj","constructor","toString","call","simpleHash","str","hash","charCodeAt","Math","abs","params","searchParams","URLSearchParams","hasOwnProperty","value","set","String","queryString","a","b","area","JSON","stringify","state","route","stateHash","paramsHash","func","wait","timeout","args","context","this","clearTimeout","setTimeout","apply","encoded","decoded","decodeURIComponent","parsed","parse","error","deepMerge","target","source","output","sourceValue","targetValue","json","encodeURIComponent","url","URL","window","location","origin","search","forEach","sanitizeRouteState","keysToRemove","sanitized","includes","map","item"],"mappings":"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"}