@real-router/vue 0.0.1

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.
@@ -0,0 +1,116 @@
1
+ import { shouldNavigate, applyLinkA11y } from "dom-utils";
2
+
3
+ import type { Router, NavigationOptions, Params } from "@real-router/core";
4
+ import type { Directive } from "vue";
5
+
6
+ export interface LinkDirectiveValue {
7
+ name: string;
8
+ params?: Params;
9
+ options?: NavigationOptions;
10
+ }
11
+
12
+ let _router: Router | null = null;
13
+
14
+ export function setDirectiveRouter(router: Router): void {
15
+ _router = router;
16
+ }
17
+
18
+ export function getDirectiveRouter(): Router {
19
+ if (!_router) {
20
+ /* v8 ignore next 3 -- @preserve Defensive: router always initialized by RouterProvider */
21
+ throw new Error(
22
+ "v-link directive requires a RouterProvider ancestor. Make sure RouterProvider is mounted.",
23
+ );
24
+ }
25
+
26
+ return _router;
27
+ }
28
+
29
+ const clickHandlers = new WeakMap<HTMLElement, (evt: MouseEvent) => void>();
30
+ const keydownHandlers = new WeakMap<
31
+ HTMLElement,
32
+ (evt: KeyboardEvent) => void
33
+ >();
34
+
35
+ function createClickHandler(
36
+ router: Router,
37
+ value: LinkDirectiveValue,
38
+ ): (evt: MouseEvent) => void {
39
+ return (evt: MouseEvent) => {
40
+ if (!shouldNavigate(evt)) {
41
+ return;
42
+ }
43
+
44
+ evt.preventDefault();
45
+ router
46
+ .navigate(value.name, value.params ?? {}, value.options ?? {})
47
+ .catch(() => {});
48
+ };
49
+ }
50
+
51
+ function createKeydownHandler(
52
+ router: Router,
53
+ value: LinkDirectiveValue,
54
+ el: HTMLElement,
55
+ ): (evt: KeyboardEvent) => void {
56
+ return (evt: KeyboardEvent) => {
57
+ if (evt.key === "Enter" && !(el instanceof HTMLButtonElement)) {
58
+ router
59
+ .navigate(value.name, value.params ?? {}, value.options ?? {})
60
+ .catch(() => {});
61
+ }
62
+ };
63
+ }
64
+
65
+ function attachHandlers(
66
+ el: HTMLElement,
67
+ router: Router,
68
+ value: LinkDirectiveValue,
69
+ ): void {
70
+ const handleClick = createClickHandler(router, value);
71
+ const handleKeyDown = createKeydownHandler(router, value, el);
72
+
73
+ el.addEventListener("click", handleClick);
74
+ el.addEventListener("keydown", handleKeyDown);
75
+
76
+ clickHandlers.set(el, handleClick);
77
+ keydownHandlers.set(el, handleKeyDown);
78
+ }
79
+
80
+ function detachHandlers(el: HTMLElement): void {
81
+ const clickHandler = clickHandlers.get(el);
82
+ const keydownHandler = keydownHandlers.get(el);
83
+
84
+ if (clickHandler) {
85
+ el.removeEventListener("click", clickHandler);
86
+ }
87
+ if (keydownHandler) {
88
+ el.removeEventListener("keydown", keydownHandler);
89
+ }
90
+
91
+ clickHandlers.delete(el);
92
+ keydownHandlers.delete(el);
93
+ }
94
+
95
+ export const vLink: Directive<HTMLElement, LinkDirectiveValue> = {
96
+ mounted(el, binding) {
97
+ const router = getDirectiveRouter();
98
+
99
+ applyLinkA11y(el);
100
+
101
+ el.style.cursor = "pointer";
102
+
103
+ attachHandlers(el, router, binding.value);
104
+ },
105
+
106
+ updated(el, binding) {
107
+ const router = getDirectiveRouter();
108
+
109
+ detachHandlers(el);
110
+ attachHandlers(el, router, binding.value);
111
+ },
112
+
113
+ beforeUnmount(el) {
114
+ detachHandlers(el);
115
+ },
116
+ };
package/src/index.ts ADDED
@@ -0,0 +1,43 @@
1
+ // Components
2
+ export { RouteView } from "./components/RouteView";
3
+
4
+ export { Link } from "./components/Link";
5
+
6
+ // Directives
7
+ export { vLink } from "./directives/vLink";
8
+
9
+ // Composables
10
+ export { useRouter } from "./composables/useRouter";
11
+
12
+ export { useNavigator } from "./composables/useNavigator";
13
+
14
+ export { useRouteUtils } from "./composables/useRouteUtils";
15
+
16
+ export { useRoute } from "./composables/useRoute";
17
+
18
+ export { useRouteNode } from "./composables/useRouteNode";
19
+
20
+ export { useRouterTransition } from "./composables/useRouterTransition";
21
+
22
+ // Plugin
23
+ export { createRouterPlugin } from "./createRouterPlugin";
24
+
25
+ // Context
26
+ export { RouterProvider } from "./RouterProvider";
27
+
28
+ export { RouterKey, NavigatorKey, RouteKey } from "./context";
29
+
30
+ // Types
31
+ export type { LinkProps } from "./types";
32
+
33
+ export type { LinkDirectiveValue } from "./directives/vLink";
34
+
35
+ export type {
36
+ RouteViewProps,
37
+ RouteViewMatchProps,
38
+ RouteViewNotFoundProps,
39
+ } from "./components/RouteView";
40
+
41
+ export type { Navigator } from "@real-router/core";
42
+
43
+ export type { RouterTransitionSnapshot } from "@real-router/sources";
package/src/types.ts ADDED
@@ -0,0 +1,24 @@
1
+ import type {
2
+ NavigationOptions,
3
+ Params,
4
+ Navigator,
5
+ State,
6
+ } from "@real-router/core";
7
+ import type { ShallowRef } from "vue";
8
+
9
+ export interface RouteContext {
10
+ navigator: Navigator;
11
+ route: ShallowRef<State | undefined>;
12
+ previousRoute: ShallowRef<State | undefined>;
13
+ }
14
+
15
+ export interface LinkProps<P extends Params = Params> {
16
+ routeName: string;
17
+ routeParams?: P;
18
+ routeOptions?: NavigationOptions;
19
+ class?: string;
20
+ activeClassName?: string;
21
+ activeStrict?: boolean;
22
+ ignoreQueryParams?: boolean;
23
+ target?: string;
24
+ }
@@ -0,0 +1,16 @@
1
+ import { shallowRef, onScopeDispose } from "vue";
2
+
3
+ import type { RouterSource } from "@real-router/sources";
4
+ import type { ShallowRef } from "vue";
5
+
6
+ export function useRefFromSource<T>(source: RouterSource<T>): ShallowRef<T> {
7
+ const ref = shallowRef(source.getSnapshot());
8
+
9
+ const unsub = source.subscribe(() => {
10
+ ref.value = source.getSnapshot();
11
+ });
12
+
13
+ onScopeDispose(unsub);
14
+
15
+ return ref;
16
+ }