@ktjs/router 0.14.4 → 0.14.5

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/dist/index.d.ts CHANGED
@@ -124,6 +124,10 @@ interface RouterConfig {
124
124
  * Default is `true`
125
125
  */
126
126
  asyncGuards?: boolean;
127
+ /**
128
+ * Router mode: 'history' uses HTML5 history API, 'hash' uses URL hash. Default is 'hash'.
129
+ */
130
+ mode?: 'history' | 'hash';
127
131
  }
128
132
 
129
133
  /**
@@ -169,6 +169,8 @@ var __ktjs_router__ = (function (exports) {
169
169
  const onNotFound = config.onNotFound ?? defaultHook;
170
170
  const onError = config.onError ?? defaultHook;
171
171
  const asyncGuards = config.asyncGuards ?? true;
172
+ // default to 'hash' mode
173
+ const mode = config.mode ?? 'hash';
172
174
  const baseUrl = config.baseUrl ?? '';
173
175
  // # private values
174
176
  const routes = [];
@@ -199,19 +201,37 @@ var __ktjs_router__ = (function (exports) {
199
201
  * Initialize current route from URL
200
202
  */
201
203
  const initCurrentRoute = () => {
202
- const hash = window.location.hash.slice(1); // Remove '#'
203
- if (!hash) {
204
- return (current = null);
204
+ if (mode === 'hash') {
205
+ const hash = window.location.hash.slice(1); // Remove '#'
206
+ if (!hash) {
207
+ return (current = null);
208
+ }
209
+ // Parse path and query
210
+ const [path, queryString] = hash.split('?');
211
+ const normalizedPath = normalizePath(path);
212
+ // Match route
213
+ const matched = match(normalizedPath);
214
+ if (!matched) {
215
+ return (current = null);
216
+ }
217
+ // Build route context
218
+ return (current = {
219
+ path: normalizedPath,
220
+ name: matched.route.name,
221
+ params: matched.params,
222
+ query: queryString ? parseQuery(queryString) : {},
223
+ meta: matched.route.meta ?? {},
224
+ matched: matched.result,
225
+ });
205
226
  }
206
- // Parse path and query
207
- const [path, queryString] = hash.split('?');
227
+ // history mode
228
+ const pathWithQuery = window.location.pathname + window.location.search;
229
+ const [path, queryString] = pathWithQuery.split('?');
208
230
  const normalizedPath = normalizePath(path);
209
- // Match route
210
231
  const matched = match(normalizedPath);
211
232
  if (!matched) {
212
233
  return (current = null);
213
234
  }
214
- // Build route context
215
235
  return (current = {
216
236
  path: normalizedPath,
217
237
  name: matched.route.name,
@@ -365,17 +385,38 @@ var __ktjs_router__ = (function (exports) {
365
385
  }
366
386
  return false;
367
387
  }
368
- // Update browser history
388
+ // Update browser history depending on mode
369
389
  const url = fullPath;
370
- if (replace) {
371
- window.history.replaceState({ path: to.path }, '', url);
390
+ if (mode === 'history') {
391
+ if (replace) {
392
+ window.history.replaceState({ path: to.path }, '', url);
393
+ }
394
+ else {
395
+ window.history.pushState({ path: to.path }, '', url);
396
+ }
372
397
  }
373
398
  else {
374
- window.history.pushState({ path: to.path }, '', url);
399
+ const hashUrl = '#' + fullPath;
400
+ if (replace) {
401
+ window.location.replace(hashUrl);
402
+ }
403
+ else {
404
+ window.location.hash = fullPath;
405
+ }
375
406
  }
376
- // Update current route
407
+ // Update current route in memory
377
408
  current = to;
378
- history.push(to);
409
+ if (replace) {
410
+ if (history.length > 0) {
411
+ history[history.length - 1] = to;
412
+ }
413
+ else {
414
+ history.push(to);
415
+ }
416
+ }
417
+ else {
418
+ history.push(to);
419
+ }
379
420
  // Render component if routerView exists
380
421
  if (routerView && to.matched.length > 0) {
381
422
  const route = to.matched[to.matched.length - 1];
@@ -424,14 +465,35 @@ var __ktjs_router__ = (function (exports) {
424
465
  }
425
466
  // ---- Guards passed ----
426
467
  const url = fullPath;
427
- if (replace) {
428
- window.history.replaceState({ path: to.path }, '', url);
468
+ if (mode === 'history') {
469
+ if (replace) {
470
+ window.history.replaceState({ path: to.path }, '', url);
471
+ }
472
+ else {
473
+ window.history.pushState({ path: to.path }, '', url);
474
+ }
429
475
  }
430
476
  else {
431
- window.history.pushState({ path: to.path }, '', url);
477
+ const hashUrl = '#' + fullPath;
478
+ if (replace) {
479
+ window.location.replace(hashUrl);
480
+ }
481
+ else {
482
+ window.location.hash = fullPath;
483
+ }
432
484
  }
433
485
  current = to;
434
- history.push(to);
486
+ if (replace) {
487
+ if (history.length > 0) {
488
+ history[history.length - 1] = to;
489
+ }
490
+ else {
491
+ history.push(to);
492
+ }
493
+ }
494
+ else {
495
+ history.push(to);
496
+ }
435
497
  // Render component if routerView exists
436
498
  if (routerView && to.matched.length > 0) {
437
499
  const route = to.matched[to.matched.length - 1];
@@ -475,12 +537,61 @@ var __ktjs_router__ = (function (exports) {
475
537
  return loc;
476
538
  };
477
539
  // # register events
478
- // Listen to browser back/forward
479
- window.addEventListener('popstate', (event) => {
480
- if (event.state?.path) {
481
- navigate({ path: event.state.path, guardLevel: 1 /* GuardLevel.Global */, replace: true });
482
- }
483
- });
540
+ if (mode === 'history') {
541
+ // Listen to browser back/forward for history mode
542
+ window.addEventListener('popstate', (event) => {
543
+ if (event.state?.path) {
544
+ // navigate without pushing new history entry
545
+ navigate({ path: event.state.path, guardLevel: 1 /* GuardLevel.Global */, replace: true });
546
+ }
547
+ });
548
+ }
549
+ else {
550
+ // hash mode: listen to hashchange
551
+ window.addEventListener('hashchange', () => {
552
+ const hash = window.location.hash.slice(1);
553
+ const [path] = hash.split('?');
554
+ const normalizedPath = normalizePath(path);
555
+ if (current && current.path === normalizedPath) {
556
+ return;
557
+ }
558
+ // render route for new hash without adding extra history entry
559
+ const matched = match(normalizedPath);
560
+ if (!matched) {
561
+ onNotFound(normalizedPath);
562
+ return;
563
+ }
564
+ const queryString = window.location.hash.slice(1).split('?')[1];
565
+ const to = {
566
+ path: normalizedPath,
567
+ name: matched.route.name,
568
+ params: matched.params,
569
+ query: queryString ? parseQuery(queryString) : {},
570
+ meta: matched.route.meta ?? {},
571
+ matched: matched.result,
572
+ };
573
+ // apply without modifying browser history
574
+ current = to;
575
+ history.push(to);
576
+ if (routerView && to.matched.length > 0) {
577
+ const route = to.matched[to.matched.length - 1];
578
+ if (route.component) {
579
+ const element = route.component();
580
+ if (element instanceof Promise) {
581
+ element.then((el) => {
582
+ routerView.innerHTML = '';
583
+ routerView.appendChild(el);
584
+ });
585
+ }
586
+ else {
587
+ routerView.innerHTML = '';
588
+ routerView.appendChild(element);
589
+ }
590
+ }
591
+ }
592
+ executeAfterHooksSync(to, history[history.length - 2] ?? null);
593
+ });
594
+ }
484
595
  // Router instance
485
596
  return {
486
597
  get current() {
@@ -253,14 +253,16 @@ var __ktjs_router__ = (function (exports) {
253
253
  * Create a new router instance
254
254
  */
255
255
  var createRouter = function (config) {
256
- var _a, _b, _c, _d, _e, _f;
256
+ var _a, _b, _c, _d, _e, _f, _g;
257
257
  // # default configs
258
258
  var beforeEach = (_a = config.beforeEach) !== null && _a !== void 0 ? _a : defaultHook;
259
259
  var afterEach = (_b = config.afterEach) !== null && _b !== void 0 ? _b : defaultHook;
260
260
  var onNotFound = (_c = config.onNotFound) !== null && _c !== void 0 ? _c : defaultHook;
261
261
  var onError = (_d = config.onError) !== null && _d !== void 0 ? _d : defaultHook;
262
262
  var asyncGuards = (_e = config.asyncGuards) !== null && _e !== void 0 ? _e : true;
263
- var baseUrl = (_f = config.baseUrl) !== null && _f !== void 0 ? _f : '';
263
+ // default to 'hash' mode
264
+ var mode = (_f = config.mode) !== null && _f !== void 0 ? _f : 'hash';
265
+ var baseUrl = (_g = config.baseUrl) !== null && _g !== void 0 ? _g : '';
264
266
  // # private values
265
267
  var routes = [];
266
268
  var routerView = null;
@@ -288,31 +290,49 @@ var __ktjs_router__ = (function (exports) {
288
290
  };
289
291
  // Normalize routes with default guards
290
292
  normalize(config.routes, '/');
291
- var _g = createMatcher(routes), findByName = _g.findByName, match = _g.match;
293
+ var _h = createMatcher(routes), findByName = _h.findByName, match = _h.match;
292
294
  /**
293
295
  * Initialize current route from URL
294
296
  */
295
297
  var initCurrentRoute = function () {
296
- var _a;
297
- var hash = window.location.hash.slice(1); // Remove '#'
298
- if (!hash) {
299
- return (current = null);
298
+ var _a, _b;
299
+ if (mode === 'hash') {
300
+ var hash = window.location.hash.slice(1); // Remove '#'
301
+ if (!hash) {
302
+ return (current = null);
303
+ }
304
+ // Parse path and query
305
+ var _c = hash.split('?'), path_1 = _c[0], queryString_1 = _c[1];
306
+ var normalizedPath_1 = normalizePath(path_1);
307
+ // Match route
308
+ var matched_1 = match(normalizedPath_1);
309
+ if (!matched_1) {
310
+ return (current = null);
311
+ }
312
+ // Build route context
313
+ return (current = {
314
+ path: normalizedPath_1,
315
+ name: matched_1.route.name,
316
+ params: matched_1.params,
317
+ query: queryString_1 ? parseQuery(queryString_1) : {},
318
+ meta: (_a = matched_1.route.meta) !== null && _a !== void 0 ? _a : {},
319
+ matched: matched_1.result,
320
+ });
300
321
  }
301
- // Parse path and query
302
- var _b = hash.split('?'), path = _b[0], queryString = _b[1];
322
+ // history mode
323
+ var pathWithQuery = window.location.pathname + window.location.search;
324
+ var _d = pathWithQuery.split('?'), path = _d[0], queryString = _d[1];
303
325
  var normalizedPath = normalizePath(path);
304
- // Match route
305
326
  var matched = match(normalizedPath);
306
327
  if (!matched) {
307
328
  return (current = null);
308
329
  }
309
- // Build route context
310
330
  return (current = {
311
331
  path: normalizedPath,
312
332
  name: matched.route.name,
313
333
  params: matched.params,
314
334
  query: queryString ? parseQuery(queryString) : {},
315
- meta: (_a = matched.route.meta) !== null && _a !== void 0 ? _a : {},
335
+ meta: (_b = matched.route.meta) !== null && _b !== void 0 ? _b : {},
316
336
  matched: matched.result,
317
337
  });
318
338
  };
@@ -474,17 +494,38 @@ var __ktjs_router__ = (function (exports) {
474
494
  }
475
495
  return false;
476
496
  }
477
- // Update browser history
497
+ // Update browser history depending on mode
478
498
  var url = fullPath;
479
- if (replace) {
480
- window.history.replaceState({ path: to.path }, '', url);
499
+ if (mode === 'history') {
500
+ if (replace) {
501
+ window.history.replaceState({ path: to.path }, '', url);
502
+ }
503
+ else {
504
+ window.history.pushState({ path: to.path }, '', url);
505
+ }
481
506
  }
482
507
  else {
483
- window.history.pushState({ path: to.path }, '', url);
508
+ var hashUrl = '#' + fullPath;
509
+ if (replace) {
510
+ window.location.replace(hashUrl);
511
+ }
512
+ else {
513
+ window.location.hash = fullPath;
514
+ }
484
515
  }
485
- // Update current route
516
+ // Update current route in memory
486
517
  current = to;
487
- history.push(to);
518
+ if (replace) {
519
+ if (history.length > 0) {
520
+ history[history.length - 1] = to;
521
+ }
522
+ else {
523
+ history.push(to);
524
+ }
525
+ }
526
+ else {
527
+ history.push(to);
528
+ }
488
529
  // Render component if routerView exists
489
530
  if (routerView && to.matched.length > 0) {
490
531
  var route = to.matched[to.matched.length - 1];
@@ -517,7 +558,7 @@ var __ktjs_router__ = (function (exports) {
517
558
  args_1[_i - 1] = arguments[_i];
518
559
  }
519
560
  return __awaiter(void 0, __spreadArray([options_1], args_1, true), void 0, function (options, redirectCount) {
520
- var prep, guardLevel, replace, to, fullPath, guardResult, url, route, element, error_2;
561
+ var prep, guardLevel, replace, to, fullPath, guardResult, url, hashUrl, route, element, error_2;
521
562
  var _a;
522
563
  if (redirectCount === void 0) { redirectCount = 0; }
523
564
  return __generator(this, function (_b) {
@@ -545,14 +586,35 @@ var __ktjs_router__ = (function (exports) {
545
586
  return [2 /*return*/, false];
546
587
  }
547
588
  url = fullPath;
548
- if (replace) {
549
- window.history.replaceState({ path: to.path }, '', url);
589
+ if (mode === 'history') {
590
+ if (replace) {
591
+ window.history.replaceState({ path: to.path }, '', url);
592
+ }
593
+ else {
594
+ window.history.pushState({ path: to.path }, '', url);
595
+ }
550
596
  }
551
597
  else {
552
- window.history.pushState({ path: to.path }, '', url);
598
+ hashUrl = '#' + fullPath;
599
+ if (replace) {
600
+ window.location.replace(hashUrl);
601
+ }
602
+ else {
603
+ window.location.hash = fullPath;
604
+ }
553
605
  }
554
606
  current = to;
555
- history.push(to);
607
+ if (replace) {
608
+ if (history.length > 0) {
609
+ history[history.length - 1] = to;
610
+ }
611
+ else {
612
+ history.push(to);
613
+ }
614
+ }
615
+ else {
616
+ history.push(to);
617
+ }
556
618
  if (!(routerView && to.matched.length > 0)) return [3 /*break*/, 3];
557
619
  route = to.matched[to.matched.length - 1];
558
620
  if (!route.component) return [3 /*break*/, 3];
@@ -611,13 +673,63 @@ var __ktjs_router__ = (function (exports) {
611
673
  return loc;
612
674
  };
613
675
  // # register events
614
- // Listen to browser back/forward
615
- window.addEventListener('popstate', function (event) {
616
- var _a;
617
- if ((_a = event.state) === null || _a === void 0 ? void 0 : _a.path) {
618
- navigate({ path: event.state.path, guardLevel: 1 /* GuardLevel.Global */, replace: true });
619
- }
620
- });
676
+ if (mode === 'history') {
677
+ // Listen to browser back/forward for history mode
678
+ window.addEventListener('popstate', function (event) {
679
+ var _a;
680
+ if ((_a = event.state) === null || _a === void 0 ? void 0 : _a.path) {
681
+ // navigate without pushing new history entry
682
+ navigate({ path: event.state.path, guardLevel: 1 /* GuardLevel.Global */, replace: true });
683
+ }
684
+ });
685
+ }
686
+ else {
687
+ // hash mode: listen to hashchange
688
+ window.addEventListener('hashchange', function () {
689
+ var _a, _b;
690
+ var hash = window.location.hash.slice(1);
691
+ var path = hash.split('?')[0];
692
+ var normalizedPath = normalizePath(path);
693
+ if (current && current.path === normalizedPath) {
694
+ return;
695
+ }
696
+ // render route for new hash without adding extra history entry
697
+ var matched = match(normalizedPath);
698
+ if (!matched) {
699
+ onNotFound(normalizedPath);
700
+ return;
701
+ }
702
+ var queryString = window.location.hash.slice(1).split('?')[1];
703
+ var to = {
704
+ path: normalizedPath,
705
+ name: matched.route.name,
706
+ params: matched.params,
707
+ query: queryString ? parseQuery(queryString) : {},
708
+ meta: (_a = matched.route.meta) !== null && _a !== void 0 ? _a : {},
709
+ matched: matched.result,
710
+ };
711
+ // apply without modifying browser history
712
+ current = to;
713
+ history.push(to);
714
+ if (routerView && to.matched.length > 0) {
715
+ var route = to.matched[to.matched.length - 1];
716
+ if (route.component) {
717
+ var element = route.component();
718
+ if (element instanceof Promise) {
719
+ element.then(function (el) {
720
+ routerView.innerHTML = '';
721
+ routerView.appendChild(el);
722
+ });
723
+ }
724
+ else {
725
+ routerView.innerHTML = '';
726
+ routerView.appendChild(element);
727
+ }
728
+ }
729
+ }
730
+ executeAfterHooksSync(to, (_b = history[history.length - 2]) !== null && _b !== void 0 ? _b : null);
731
+ });
732
+ }
621
733
  // Router instance
622
734
  return {
623
735
  get current() {
package/dist/index.mjs CHANGED
@@ -166,6 +166,8 @@ const createRouter = (config) => {
166
166
  const onNotFound = config.onNotFound ?? defaultHook;
167
167
  const onError = config.onError ?? defaultHook;
168
168
  const asyncGuards = config.asyncGuards ?? true;
169
+ // default to 'hash' mode
170
+ const mode = config.mode ?? 'hash';
169
171
  const baseUrl = config.baseUrl ?? '';
170
172
  // # private values
171
173
  const routes = [];
@@ -196,19 +198,37 @@ const createRouter = (config) => {
196
198
  * Initialize current route from URL
197
199
  */
198
200
  const initCurrentRoute = () => {
199
- const hash = window.location.hash.slice(1); // Remove '#'
200
- if (!hash) {
201
- return (current = null);
201
+ if (mode === 'hash') {
202
+ const hash = window.location.hash.slice(1); // Remove '#'
203
+ if (!hash) {
204
+ return (current = null);
205
+ }
206
+ // Parse path and query
207
+ const [path, queryString] = hash.split('?');
208
+ const normalizedPath = normalizePath(path);
209
+ // Match route
210
+ const matched = match(normalizedPath);
211
+ if (!matched) {
212
+ return (current = null);
213
+ }
214
+ // Build route context
215
+ return (current = {
216
+ path: normalizedPath,
217
+ name: matched.route.name,
218
+ params: matched.params,
219
+ query: queryString ? parseQuery(queryString) : {},
220
+ meta: matched.route.meta ?? {},
221
+ matched: matched.result,
222
+ });
202
223
  }
203
- // Parse path and query
204
- const [path, queryString] = hash.split('?');
224
+ // history mode
225
+ const pathWithQuery = window.location.pathname + window.location.search;
226
+ const [path, queryString] = pathWithQuery.split('?');
205
227
  const normalizedPath = normalizePath(path);
206
- // Match route
207
228
  const matched = match(normalizedPath);
208
229
  if (!matched) {
209
230
  return (current = null);
210
231
  }
211
- // Build route context
212
232
  return (current = {
213
233
  path: normalizedPath,
214
234
  name: matched.route.name,
@@ -362,17 +382,38 @@ const createRouter = (config) => {
362
382
  }
363
383
  return false;
364
384
  }
365
- // Update browser history
385
+ // Update browser history depending on mode
366
386
  const url = fullPath;
367
- if (replace) {
368
- window.history.replaceState({ path: to.path }, '', url);
387
+ if (mode === 'history') {
388
+ if (replace) {
389
+ window.history.replaceState({ path: to.path }, '', url);
390
+ }
391
+ else {
392
+ window.history.pushState({ path: to.path }, '', url);
393
+ }
369
394
  }
370
395
  else {
371
- window.history.pushState({ path: to.path }, '', url);
396
+ const hashUrl = '#' + fullPath;
397
+ if (replace) {
398
+ window.location.replace(hashUrl);
399
+ }
400
+ else {
401
+ window.location.hash = fullPath;
402
+ }
372
403
  }
373
- // Update current route
404
+ // Update current route in memory
374
405
  current = to;
375
- history.push(to);
406
+ if (replace) {
407
+ if (history.length > 0) {
408
+ history[history.length - 1] = to;
409
+ }
410
+ else {
411
+ history.push(to);
412
+ }
413
+ }
414
+ else {
415
+ history.push(to);
416
+ }
376
417
  // Render component if routerView exists
377
418
  if (routerView && to.matched.length > 0) {
378
419
  const route = to.matched[to.matched.length - 1];
@@ -421,14 +462,35 @@ const createRouter = (config) => {
421
462
  }
422
463
  // ---- Guards passed ----
423
464
  const url = fullPath;
424
- if (replace) {
425
- window.history.replaceState({ path: to.path }, '', url);
465
+ if (mode === 'history') {
466
+ if (replace) {
467
+ window.history.replaceState({ path: to.path }, '', url);
468
+ }
469
+ else {
470
+ window.history.pushState({ path: to.path }, '', url);
471
+ }
426
472
  }
427
473
  else {
428
- window.history.pushState({ path: to.path }, '', url);
474
+ const hashUrl = '#' + fullPath;
475
+ if (replace) {
476
+ window.location.replace(hashUrl);
477
+ }
478
+ else {
479
+ window.location.hash = fullPath;
480
+ }
429
481
  }
430
482
  current = to;
431
- history.push(to);
483
+ if (replace) {
484
+ if (history.length > 0) {
485
+ history[history.length - 1] = to;
486
+ }
487
+ else {
488
+ history.push(to);
489
+ }
490
+ }
491
+ else {
492
+ history.push(to);
493
+ }
432
494
  // Render component if routerView exists
433
495
  if (routerView && to.matched.length > 0) {
434
496
  const route = to.matched[to.matched.length - 1];
@@ -472,12 +534,61 @@ const createRouter = (config) => {
472
534
  return loc;
473
535
  };
474
536
  // # register events
475
- // Listen to browser back/forward
476
- window.addEventListener('popstate', (event) => {
477
- if (event.state?.path) {
478
- navigate({ path: event.state.path, guardLevel: 1 /* GuardLevel.Global */, replace: true });
479
- }
480
- });
537
+ if (mode === 'history') {
538
+ // Listen to browser back/forward for history mode
539
+ window.addEventListener('popstate', (event) => {
540
+ if (event.state?.path) {
541
+ // navigate without pushing new history entry
542
+ navigate({ path: event.state.path, guardLevel: 1 /* GuardLevel.Global */, replace: true });
543
+ }
544
+ });
545
+ }
546
+ else {
547
+ // hash mode: listen to hashchange
548
+ window.addEventListener('hashchange', () => {
549
+ const hash = window.location.hash.slice(1);
550
+ const [path] = hash.split('?');
551
+ const normalizedPath = normalizePath(path);
552
+ if (current && current.path === normalizedPath) {
553
+ return;
554
+ }
555
+ // render route for new hash without adding extra history entry
556
+ const matched = match(normalizedPath);
557
+ if (!matched) {
558
+ onNotFound(normalizedPath);
559
+ return;
560
+ }
561
+ const queryString = window.location.hash.slice(1).split('?')[1];
562
+ const to = {
563
+ path: normalizedPath,
564
+ name: matched.route.name,
565
+ params: matched.params,
566
+ query: queryString ? parseQuery(queryString) : {},
567
+ meta: matched.route.meta ?? {},
568
+ matched: matched.result,
569
+ };
570
+ // apply without modifying browser history
571
+ current = to;
572
+ history.push(to);
573
+ if (routerView && to.matched.length > 0) {
574
+ const route = to.matched[to.matched.length - 1];
575
+ if (route.component) {
576
+ const element = route.component();
577
+ if (element instanceof Promise) {
578
+ element.then((el) => {
579
+ routerView.innerHTML = '';
580
+ routerView.appendChild(el);
581
+ });
582
+ }
583
+ else {
584
+ routerView.innerHTML = '';
585
+ routerView.appendChild(element);
586
+ }
587
+ }
588
+ }
589
+ executeAfterHooksSync(to, history[history.length - 2] ?? null);
590
+ });
591
+ }
481
592
  // Router instance
482
593
  return {
483
594
  get current() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ktjs/router",
3
- "version": "0.14.4",
3
+ "version": "0.14.5",
4
4
  "description": "Router for kt.js - client-side routing with navigation guards",
5
5
  "type": "module",
6
6
  "module": "./dist/index.mjs",