@flight-framework/router 0.0.8 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,161 @@
1
+ import {
2
+ clearPrefetchCache,
3
+ findRoute,
4
+ generatePath,
5
+ getRouterContext,
6
+ initRouter,
7
+ isActive,
8
+ isPrefetched,
9
+ matchRoute,
10
+ navigate,
11
+ observeForPrefetch,
12
+ parseParams,
13
+ prefetch,
14
+ prefetchAll,
15
+ prefetchPages,
16
+ prefetchWhenIdle,
17
+ redirect,
18
+ setupIntentPrefetch,
19
+ subscribe
20
+ } from "../chunk-MO2HMSZH.js";
21
+
22
+ // src/svelte/Link.ts
23
+ var isBrowser = typeof window !== "undefined";
24
+ function isExternalUrl(href) {
25
+ if (!href) return false;
26
+ return href.startsWith("http://") || href.startsWith("https://") || href.startsWith("//") || href.startsWith("mailto:") || href.startsWith("tel:") || href.startsWith("javascript:") || href.startsWith("#");
27
+ }
28
+ function normalizePrefetchStrategy(prefetchProp) {
29
+ if (prefetchProp === true) return "intent";
30
+ if (prefetchProp === false || prefetchProp === void 0) return "none";
31
+ return prefetchProp;
32
+ }
33
+ function linkAction(node, options = {}) {
34
+ const { prefetch: prefetchProp = "none", replace = false, scroll = true } = options;
35
+ const href = node.getAttribute("href") || "";
36
+ const isExternal = isExternalUrl(href);
37
+ const prefetchStrategy = normalizePrefetchStrategy(prefetchProp);
38
+ let cleanup;
39
+ const handleClick = (e) => {
40
+ if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
41
+ if (e.button !== 0) return;
42
+ if (isExternal || node.target === "_blank") return;
43
+ e.preventDefault();
44
+ const { navigate: navigate2 } = getRouterContext();
45
+ navigate2(href, { replace, scroll });
46
+ };
47
+ node.addEventListener("click", handleClick);
48
+ if (!isExternal && prefetchStrategy !== "none" && isBrowser) {
49
+ switch (prefetchStrategy) {
50
+ case "render":
51
+ prefetch(href, { priority: "low" });
52
+ break;
53
+ case "viewport":
54
+ cleanup = observeForPrefetch(node, href);
55
+ break;
56
+ case "intent":
57
+ default:
58
+ cleanup = setupIntentPrefetch(node, href);
59
+ break;
60
+ }
61
+ }
62
+ return {
63
+ destroy() {
64
+ node.removeEventListener("click", handleClick);
65
+ cleanup?.();
66
+ }
67
+ };
68
+ }
69
+ function createLinkProps(href, options = {}) {
70
+ const { replace = false, scroll = true } = options;
71
+ const isExternal = isExternalUrl(href);
72
+ return {
73
+ href,
74
+ onclick: (e) => {
75
+ if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
76
+ if (e.button !== 0) return;
77
+ if (isExternal) return;
78
+ e.preventDefault();
79
+ const { navigate: navigate2 } = getRouterContext();
80
+ navigate2(href, { replace, scroll });
81
+ }
82
+ };
83
+ }
84
+ var Link = {
85
+ createProps: createLinkProps,
86
+ action: linkAction
87
+ };
88
+
89
+ // src/svelte/stores.ts
90
+ var isBrowser2 = typeof window !== "undefined";
91
+ function createStore(initialValue) {
92
+ let value = initialValue;
93
+ const subscribers = /* @__PURE__ */ new Set();
94
+ return {
95
+ subscribe(callback) {
96
+ subscribers.add(callback);
97
+ callback(value);
98
+ return () => subscribers.delete(callback);
99
+ },
100
+ set(newValue) {
101
+ value = newValue;
102
+ subscribers.forEach((cb) => cb(value));
103
+ },
104
+ get() {
105
+ return value;
106
+ }
107
+ };
108
+ }
109
+ var routerStore = createStore(getRouterContext());
110
+ var pathnameStore = createStore(
111
+ isBrowser2 ? window.location.pathname : "/"
112
+ );
113
+ var searchParamsStore = createStore(
114
+ isBrowser2 ? new URLSearchParams(window.location.search) : new URLSearchParams()
115
+ );
116
+ if (isBrowser2) {
117
+ subscribe((ctx) => {
118
+ routerStore.set(ctx);
119
+ pathnameStore.set(ctx.path);
120
+ searchParamsStore.set(ctx.searchParams);
121
+ });
122
+ window.addEventListener("popstate", () => {
123
+ pathnameStore.set(window.location.pathname);
124
+ searchParamsStore.set(new URLSearchParams(window.location.search));
125
+ });
126
+ }
127
+ function getRouter() {
128
+ return routerStore.get();
129
+ }
130
+ function getPathname() {
131
+ return pathnameStore.get();
132
+ }
133
+ function getSearchParams() {
134
+ return searchParamsStore.get();
135
+ }
136
+ export {
137
+ Link,
138
+ clearPrefetchCache,
139
+ findRoute,
140
+ generatePath,
141
+ getPathname,
142
+ getRouter,
143
+ getRouterContext,
144
+ getSearchParams,
145
+ initRouter,
146
+ isActive,
147
+ isPrefetched,
148
+ matchRoute,
149
+ navigate,
150
+ observeForPrefetch,
151
+ parseParams,
152
+ pathnameStore,
153
+ prefetch,
154
+ prefetchAll,
155
+ prefetchPages,
156
+ prefetchWhenIdle,
157
+ redirect,
158
+ routerStore,
159
+ setupIntentPrefetch,
160
+ subscribe
161
+ };
@@ -0,0 +1,147 @@
1
+ import { P as PrefetchStrategy, b as RouterProviderProps, a as RouterContextValue } from '../prefetch-CMmeei6-.js';
2
+ export { L as LinkProps, N as NavigateOptions, d as PrefetchOptions, c as PrefetchPriority, R as RouteParams, S as SearchParams, w as clearPrefetchCache, l as findRoute, o as generatePath, B as getRouterContext, D as initRouter, q as isActive, v as isPrefetched, m as matchRoute, n as navigate, x as observeForPrefetch, p as parseParams, s as prefetch, t as prefetchAll, z as prefetchPages, A as prefetchWhenIdle, r as redirect, y as setupIntentPrefetch, C as subscribe } from '../prefetch-CMmeei6-.js';
3
+ import * as vue from 'vue';
4
+ import { PropType, Ref } from 'vue';
5
+
6
+ /**
7
+ * Vue Link Component
8
+ *
9
+ * @example
10
+ * ```vue
11
+ * <template>
12
+ * <Link href="/docs" prefetch="intent">Documentation</Link>
13
+ * </template>
14
+ * ```
15
+ */
16
+ declare const Link: vue.DefineComponent<vue.ExtractPropTypes<{
17
+ href: {
18
+ type: StringConstructor;
19
+ required: true;
20
+ };
21
+ prefetch: {
22
+ type: PropType<boolean | PrefetchStrategy>;
23
+ default: string;
24
+ };
25
+ replace: {
26
+ type: BooleanConstructor;
27
+ default: boolean;
28
+ };
29
+ scroll: {
30
+ type: BooleanConstructor;
31
+ default: boolean;
32
+ };
33
+ class: {
34
+ type: StringConstructor;
35
+ default: undefined;
36
+ };
37
+ target: {
38
+ type: StringConstructor;
39
+ default: undefined;
40
+ };
41
+ rel: {
42
+ type: StringConstructor;
43
+ default: undefined;
44
+ };
45
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
46
+ [key: string]: any;
47
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
48
+ href: {
49
+ type: StringConstructor;
50
+ required: true;
51
+ };
52
+ prefetch: {
53
+ type: PropType<boolean | PrefetchStrategy>;
54
+ default: string;
55
+ };
56
+ replace: {
57
+ type: BooleanConstructor;
58
+ default: boolean;
59
+ };
60
+ scroll: {
61
+ type: BooleanConstructor;
62
+ default: boolean;
63
+ };
64
+ class: {
65
+ type: StringConstructor;
66
+ default: undefined;
67
+ };
68
+ target: {
69
+ type: StringConstructor;
70
+ default: undefined;
71
+ };
72
+ rel: {
73
+ type: StringConstructor;
74
+ default: undefined;
75
+ };
76
+ }>> & Readonly<{}>, {
77
+ replace: boolean;
78
+ scroll: boolean;
79
+ prefetch: boolean | PrefetchStrategy;
80
+ class: string;
81
+ target: string;
82
+ rel: string;
83
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
84
+
85
+ /**
86
+ * Vue Composables for Router
87
+ *
88
+ * Provides Vue 3 composition API composables for routing.
89
+ */
90
+
91
+ /**
92
+ * Vue RouterProvider component for composition API
93
+ *
94
+ * @example
95
+ * ```vue
96
+ * <script setup>
97
+ * import { RouterProvider } from '@flight-framework/router/vue';
98
+ * </script>
99
+ *
100
+ * <template>
101
+ * <RouterProvider initial-path="/">
102
+ * <App />
103
+ * </RouterProvider>
104
+ * </template>
105
+ * ```
106
+ */
107
+ declare function RouterProvider(props: RouterProviderProps, { slots }: {
108
+ slots: {
109
+ default?: () => unknown;
110
+ };
111
+ }): unknown;
112
+ /**
113
+ * Composable to access router functions
114
+ *
115
+ * @example
116
+ * ```vue
117
+ * <script setup>
118
+ * import { useRouter } from '@flight-framework/router/vue';
119
+ *
120
+ * const { navigate, back, forward } = useRouter();
121
+ * </script>
122
+ * ```
123
+ */
124
+ declare function useRouter(): RouterContextValue;
125
+ /**
126
+ * Composable to get current pathname
127
+ *
128
+ * @example
129
+ * ```vue
130
+ * <script setup>
131
+ * import { usePathname } from '@flight-framework/router/vue';
132
+ *
133
+ * const pathname = usePathname();
134
+ * </script>
135
+ * ```
136
+ */
137
+ declare function usePathname(): Ref<string>;
138
+ /**
139
+ * Composable to get current search params
140
+ */
141
+ declare function useSearchParams(): Ref<URLSearchParams>;
142
+ /**
143
+ * Composable to get route params
144
+ */
145
+ declare function useParams(): Ref<Record<string, string>>;
146
+
147
+ export { Link, PrefetchStrategy, RouterContextValue, RouterProvider, RouterProviderProps, useParams, usePathname, useRouter, useSearchParams };
@@ -0,0 +1,224 @@
1
+ import {
2
+ clearPrefetchCache,
3
+ findRoute,
4
+ generatePath,
5
+ getRouterContext,
6
+ initRouter,
7
+ isActive,
8
+ isPrefetched,
9
+ matchRoute,
10
+ navigate,
11
+ observeForPrefetch,
12
+ parseParams,
13
+ prefetch,
14
+ prefetchAll,
15
+ prefetchPages,
16
+ prefetchWhenIdle,
17
+ redirect,
18
+ setupIntentPrefetch,
19
+ subscribe
20
+ } from "../chunk-MO2HMSZH.js";
21
+
22
+ // src/vue/Link.ts
23
+ import { defineComponent, ref, onMounted, onUnmounted, h } from "vue";
24
+ var isBrowser = typeof window !== "undefined";
25
+ function isExternalUrl(href) {
26
+ if (!href) return false;
27
+ return href.startsWith("http://") || href.startsWith("https://") || href.startsWith("//") || href.startsWith("mailto:") || href.startsWith("tel:") || href.startsWith("javascript:") || href.startsWith("#");
28
+ }
29
+ function normalizePrefetchStrategy(prefetchProp) {
30
+ if (prefetchProp === true) return "intent";
31
+ if (prefetchProp === false || prefetchProp === void 0) return "none";
32
+ return prefetchProp;
33
+ }
34
+ var Link = defineComponent({
35
+ name: "FlightLink",
36
+ props: {
37
+ href: {
38
+ type: String,
39
+ required: true
40
+ },
41
+ prefetch: {
42
+ type: [Boolean, String],
43
+ default: "none"
44
+ },
45
+ replace: {
46
+ type: Boolean,
47
+ default: false
48
+ },
49
+ scroll: {
50
+ type: Boolean,
51
+ default: true
52
+ },
53
+ class: {
54
+ type: String,
55
+ default: void 0
56
+ },
57
+ target: {
58
+ type: String,
59
+ default: void 0
60
+ },
61
+ rel: {
62
+ type: String,
63
+ default: void 0
64
+ }
65
+ },
66
+ setup(props, { slots }) {
67
+ const linkRef = ref(null);
68
+ const isExternal = isExternalUrl(props.href);
69
+ const prefetchStrategy = normalizePrefetchStrategy(props.prefetch);
70
+ let cleanup;
71
+ onMounted(() => {
72
+ if (isExternal || !isBrowser || prefetchStrategy === "none") {
73
+ return;
74
+ }
75
+ const link = linkRef.value;
76
+ if (!link) return;
77
+ switch (prefetchStrategy) {
78
+ case "render":
79
+ prefetch(props.href, { priority: "low" });
80
+ break;
81
+ case "viewport":
82
+ cleanup = observeForPrefetch(link, props.href);
83
+ break;
84
+ case "intent":
85
+ default:
86
+ cleanup = setupIntentPrefetch(link, props.href);
87
+ break;
88
+ }
89
+ });
90
+ onUnmounted(() => {
91
+ cleanup?.();
92
+ });
93
+ const handleClick = (e) => {
94
+ if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
95
+ return;
96
+ }
97
+ if (e.button !== 0) {
98
+ return;
99
+ }
100
+ if (isExternal || props.target === "_blank") {
101
+ return;
102
+ }
103
+ e.preventDefault();
104
+ const { navigate: navigate2 } = getRouterContext();
105
+ navigate2(props.href, { replace: props.replace, scroll: props.scroll });
106
+ };
107
+ const computedRel = isExternal && props.target === "_blank" ? props.rel || "noopener noreferrer" : props.rel;
108
+ return () => h("a", {
109
+ ref: linkRef,
110
+ href: props.href,
111
+ class: props.class,
112
+ target: props.target,
113
+ rel: computedRel,
114
+ onClick: handleClick
115
+ }, slots.default?.());
116
+ }
117
+ });
118
+
119
+ // src/vue/composables.ts
120
+ import { ref as ref2, provide, inject, onMounted as onMounted2, onUnmounted as onUnmounted2 } from "vue";
121
+ var isBrowser2 = typeof window !== "undefined";
122
+ var RouterKey = /* @__PURE__ */ Symbol("FlightRouter");
123
+ function navigateTo(to, options = {}) {
124
+ if (!isBrowser2) return;
125
+ const { replace = false, scroll = true, state } = options;
126
+ if (replace) {
127
+ window.history.replaceState(state ?? null, "", to);
128
+ } else {
129
+ window.history.pushState(state ?? null, "", to);
130
+ }
131
+ if (scroll) {
132
+ window.scrollTo({ top: 0, left: 0, behavior: "instant" });
133
+ }
134
+ }
135
+ function RouterProvider(props, { slots }) {
136
+ const path = ref2(isBrowser2 ? window.location.pathname : props.initialPath || "/");
137
+ const searchParams = ref2(isBrowser2 ? new URLSearchParams(window.location.search) : new URLSearchParams());
138
+ const routerState = ref2({
139
+ path: path.value,
140
+ searchParams: searchParams.value,
141
+ navigate: navigateTo,
142
+ back: () => isBrowser2 && window.history.back(),
143
+ forward: () => isBrowser2 && window.history.forward()
144
+ });
145
+ provide(RouterKey, routerState);
146
+ if (isBrowser2) {
147
+ onMounted2(() => {
148
+ const handlePopState = () => {
149
+ path.value = window.location.pathname;
150
+ searchParams.value = new URLSearchParams(window.location.search);
151
+ routerState.value = {
152
+ ...routerState.value,
153
+ path: path.value,
154
+ searchParams: searchParams.value
155
+ };
156
+ };
157
+ window.addEventListener("popstate", handlePopState);
158
+ const unsubscribe = subscribe((ctx) => {
159
+ path.value = ctx.path;
160
+ searchParams.value = ctx.searchParams;
161
+ routerState.value = {
162
+ ...routerState.value,
163
+ path: ctx.path,
164
+ searchParams: ctx.searchParams
165
+ };
166
+ });
167
+ onUnmounted2(() => {
168
+ window.removeEventListener("popstate", handlePopState);
169
+ unsubscribe();
170
+ });
171
+ });
172
+ }
173
+ return slots.default?.();
174
+ }
175
+ function useRouter() {
176
+ const routerState = inject(RouterKey);
177
+ if (routerState) {
178
+ return routerState.value;
179
+ }
180
+ return getRouterContext();
181
+ }
182
+ function usePathname() {
183
+ const routerState = inject(RouterKey);
184
+ if (routerState) {
185
+ return ref2(routerState.value.path);
186
+ }
187
+ return ref2(isBrowser2 ? window.location.pathname : "/");
188
+ }
189
+ function useSearchParams() {
190
+ const routerState = inject(RouterKey);
191
+ if (routerState) {
192
+ return ref2(routerState.value.searchParams);
193
+ }
194
+ return ref2(isBrowser2 ? new URLSearchParams(window.location.search) : new URLSearchParams());
195
+ }
196
+ function useParams() {
197
+ return ref2({});
198
+ }
199
+ export {
200
+ Link,
201
+ RouterProvider,
202
+ clearPrefetchCache,
203
+ findRoute,
204
+ generatePath,
205
+ getRouterContext,
206
+ initRouter,
207
+ isActive,
208
+ isPrefetched,
209
+ matchRoute,
210
+ navigate,
211
+ observeForPrefetch,
212
+ parseParams,
213
+ prefetch,
214
+ prefetchAll,
215
+ prefetchPages,
216
+ prefetchWhenIdle,
217
+ redirect,
218
+ setupIntentPrefetch,
219
+ subscribe,
220
+ useParams,
221
+ usePathname,
222
+ useRouter,
223
+ useSearchParams
224
+ };
package/package.json CHANGED
@@ -1,53 +1,93 @@
1
- {
2
- "name": "@flight-framework/router",
3
- "version": "0.0.8",
4
- "description": "Agnostic client-side routing primitives for Flight Framework",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "module": "./dist/index.js",
8
- "types": "./dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js"
13
- },
14
- "./react": {
15
- "types": "./dist/react/index.d.ts",
16
- "import": "./dist/react/index.js"
17
- }
18
- },
19
- "files": [
20
- "dist"
21
- ],
22
- "scripts": {
23
- "build": "tsup src/index.ts src/react/index.ts --format esm --dts --clean",
24
- "dev": "tsup src/index.ts src/react/index.ts --format esm --dts --watch"
25
- },
26
- "keywords": [
27
- "flight",
28
- "router",
29
- "spa",
30
- "navigation",
31
- "ssr"
32
- ],
33
- "author": "Flight Framework",
34
- "license": "MIT",
35
- "repository": {
36
- "type": "git",
37
- "url": "https://github.com/EliosLT/Flight-framework",
38
- "directory": "packages/router"
39
- },
40
- "devDependencies": {
41
- "@types/react": "^19.0.0",
42
- "tsup": "^8.0.0",
43
- "typescript": "^5.3.0"
44
- },
45
- "peerDependencies": {
46
- "react": ">=18.0.0"
47
- },
48
- "peerDependenciesMeta": {
49
- "react": {
50
- "optional": true
51
- }
52
- }
1
+ {
2
+ "name": "@flight-framework/router",
3
+ "version": "0.2.0",
4
+ "description": "Agnostic client-side routing primitives for Flight Framework",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./react": {
15
+ "types": "./dist/react/index.d.ts",
16
+ "import": "./dist/react/index.js"
17
+ },
18
+ "./vue": {
19
+ "types": "./dist/vue/index.d.ts",
20
+ "import": "./dist/vue/index.js"
21
+ },
22
+ "./svelte": {
23
+ "types": "./dist/svelte/index.d.ts",
24
+ "import": "./dist/svelte/index.js"
25
+ },
26
+ "./solid": {
27
+ "types": "./dist/solid/index.d.ts",
28
+ "import": "./dist/solid/index.js"
29
+ },
30
+ "./preact": {
31
+ "types": "./dist/preact/index.d.ts",
32
+ "import": "./dist/preact/index.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "keywords": [
39
+ "flight",
40
+ "router",
41
+ "spa",
42
+ "navigation",
43
+ "ssr",
44
+ "react",
45
+ "vue",
46
+ "svelte",
47
+ "solid",
48
+ "preact"
49
+ ],
50
+ "author": "Flight Framework",
51
+ "license": "MIT",
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "https://github.com/EliosLT/Flight-framework",
55
+ "directory": "packages/router"
56
+ },
57
+ "devDependencies": {
58
+ "@types/react": "^19.0.0",
59
+ "preact": "^10.19.0",
60
+ "solid-js": "^1.8.0",
61
+ "tsup": "^8.0.0",
62
+ "typescript": "^5.3.0",
63
+ "vue": "^3.4.0"
64
+ },
65
+ "peerDependencies": {
66
+ "preact": ">=10.0.0",
67
+ "react": ">=18.0.0",
68
+ "solid-js": ">=1.0.0",
69
+ "svelte": ">=4.0.0",
70
+ "vue": ">=3.0.0"
71
+ },
72
+ "peerDependenciesMeta": {
73
+ "react": {
74
+ "optional": true
75
+ },
76
+ "vue": {
77
+ "optional": true
78
+ },
79
+ "svelte": {
80
+ "optional": true
81
+ },
82
+ "solid-js": {
83
+ "optional": true
84
+ },
85
+ "preact": {
86
+ "optional": true
87
+ }
88
+ },
89
+ "scripts": {
90
+ "build": "tsup src/index.ts src/react/index.ts src/vue/index.ts src/svelte/index.ts src/solid/index.ts src/preact/index.ts --format esm --dts --clean",
91
+ "dev": "tsup src/index.ts src/react/index.ts src/vue/index.ts src/svelte/index.ts src/solid/index.ts src/preact/index.ts --format esm --dts --watch"
92
+ }
53
93
  }