@esmx/router-vue 3.0.0-rc.25 → 3.0.0-rc.26
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/router-link.d.ts +56 -2
- package/dist/router-link.mjs +72 -16
- package/package.json +4 -4
- package/src/router-link.ts +86 -20
package/dist/router-link.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export declare const RouterLink: import("vue").DefineComponent<import("vue").Ext
|
|
|
70
70
|
};
|
|
71
71
|
/**
|
|
72
72
|
* @deprecated Use 'type="replace"' instead
|
|
73
|
-
* @example replace={true} → type="replace"
|
|
73
|
+
* @example :replace={true} → type="replace"
|
|
74
74
|
*/
|
|
75
75
|
replace: {
|
|
76
76
|
type: BooleanConstructor;
|
|
@@ -120,6 +120,33 @@ export declare const RouterLink: import("vue").DefineComponent<import("vue").Ext
|
|
|
120
120
|
layerOptions: {
|
|
121
121
|
type: PropType<RouteLayerOptions>;
|
|
122
122
|
};
|
|
123
|
+
/**
|
|
124
|
+
* Custom event handler to control navigation behavior.
|
|
125
|
+
* Should return `true` to allow router to navigate, otherwise to prevent it.
|
|
126
|
+
*
|
|
127
|
+
* @Note you need to call `e.preventDefault()` to prevent default browser navigation.
|
|
128
|
+
* @default
|
|
129
|
+
*
|
|
130
|
+
* (event: Event & Partial<MouseEvent>): boolean => {
|
|
131
|
+
* // don't redirect with control keys
|
|
132
|
+
* if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return false;
|
|
133
|
+
* // don't redirect when preventDefault called
|
|
134
|
+
* if (e.defaultPrevented) return false;
|
|
135
|
+
* // don't redirect on right click
|
|
136
|
+
* if (e.button !== undefined && e.button !== 0) return false;
|
|
137
|
+
* // don't redirect if `target="_blank"`
|
|
138
|
+
* const target = e.currentTarget?.getAttribute?.('target') ?? '';
|
|
139
|
+
* if (/\b_blank\b/i.test(target)) return false;
|
|
140
|
+
* // Prevent default browser navigation to enable SPA routing
|
|
141
|
+
* // Note: this may be a Weex event which doesn't have this method
|
|
142
|
+
* if (e.preventDefault) e.preventDefault();
|
|
143
|
+
*
|
|
144
|
+
* return true;
|
|
145
|
+
* }
|
|
146
|
+
*/
|
|
147
|
+
eventHandler: {
|
|
148
|
+
type: PropType<(event: Event) => boolean | undefined | void>;
|
|
149
|
+
};
|
|
123
150
|
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
124
151
|
[key: string]: any;
|
|
125
152
|
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
@@ -143,7 +170,7 @@ export declare const RouterLink: import("vue").DefineComponent<import("vue").Ext
|
|
|
143
170
|
};
|
|
144
171
|
/**
|
|
145
172
|
* @deprecated Use 'type="replace"' instead
|
|
146
|
-
* @example replace={true} → type="replace"
|
|
173
|
+
* @example :replace={true} → type="replace"
|
|
147
174
|
*/
|
|
148
175
|
replace: {
|
|
149
176
|
type: BooleanConstructor;
|
|
@@ -193,6 +220,33 @@ export declare const RouterLink: import("vue").DefineComponent<import("vue").Ext
|
|
|
193
220
|
layerOptions: {
|
|
194
221
|
type: PropType<RouteLayerOptions>;
|
|
195
222
|
};
|
|
223
|
+
/**
|
|
224
|
+
* Custom event handler to control navigation behavior.
|
|
225
|
+
* Should return `true` to allow router to navigate, otherwise to prevent it.
|
|
226
|
+
*
|
|
227
|
+
* @Note you need to call `e.preventDefault()` to prevent default browser navigation.
|
|
228
|
+
* @default
|
|
229
|
+
*
|
|
230
|
+
* (event: Event & Partial<MouseEvent>): boolean => {
|
|
231
|
+
* // don't redirect with control keys
|
|
232
|
+
* if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return false;
|
|
233
|
+
* // don't redirect when preventDefault called
|
|
234
|
+
* if (e.defaultPrevented) return false;
|
|
235
|
+
* // don't redirect on right click
|
|
236
|
+
* if (e.button !== undefined && e.button !== 0) return false;
|
|
237
|
+
* // don't redirect if `target="_blank"`
|
|
238
|
+
* const target = e.currentTarget?.getAttribute?.('target') ?? '';
|
|
239
|
+
* if (/\b_blank\b/i.test(target)) return false;
|
|
240
|
+
* // Prevent default browser navigation to enable SPA routing
|
|
241
|
+
* // Note: this may be a Weex event which doesn't have this method
|
|
242
|
+
* if (e.preventDefault) e.preventDefault();
|
|
243
|
+
*
|
|
244
|
+
* return true;
|
|
245
|
+
* }
|
|
246
|
+
*/
|
|
247
|
+
eventHandler: {
|
|
248
|
+
type: PropType<(event: Event) => boolean | undefined | void>;
|
|
249
|
+
};
|
|
196
250
|
}>> & Readonly<{}>, {
|
|
197
251
|
type: RouterLinkType;
|
|
198
252
|
replace: boolean;
|
package/dist/router-link.mjs
CHANGED
|
@@ -21,7 +21,7 @@ export const RouterLink = defineComponent({
|
|
|
21
21
|
type: { type: String, default: "push" },
|
|
22
22
|
/**
|
|
23
23
|
* @deprecated Use 'type="replace"' instead
|
|
24
|
-
* @example replace={true} → type="replace"
|
|
24
|
+
* @example :replace={true} → type="replace"
|
|
25
25
|
*/
|
|
26
26
|
replace: { type: Boolean, default: false },
|
|
27
27
|
/**
|
|
@@ -57,28 +57,84 @@ export const RouterLink = defineComponent({
|
|
|
57
57
|
* Only used when type='pushLayer'.
|
|
58
58
|
* @example { zIndex: 1000, autoPush: false, routerOptions: { mode: 'memory' } }
|
|
59
59
|
*/
|
|
60
|
-
layerOptions: { type: Object }
|
|
60
|
+
layerOptions: { type: Object },
|
|
61
|
+
/**
|
|
62
|
+
* Custom event handler to control navigation behavior.
|
|
63
|
+
* Should return `true` to allow router to navigate, otherwise to prevent it.
|
|
64
|
+
*
|
|
65
|
+
* @Note you need to call `e.preventDefault()` to prevent default browser navigation.
|
|
66
|
+
* @default
|
|
67
|
+
*
|
|
68
|
+
* (event: Event & Partial<MouseEvent>): boolean => {
|
|
69
|
+
* // don't redirect with control keys
|
|
70
|
+
* if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return false;
|
|
71
|
+
* // don't redirect when preventDefault called
|
|
72
|
+
* if (e.defaultPrevented) return false;
|
|
73
|
+
* // don't redirect on right click
|
|
74
|
+
* if (e.button !== undefined && e.button !== 0) return false;
|
|
75
|
+
* // don't redirect if `target="_blank"`
|
|
76
|
+
* const target = e.currentTarget?.getAttribute?.('target') ?? '';
|
|
77
|
+
* if (/\b_blank\b/i.test(target)) return false;
|
|
78
|
+
* // Prevent default browser navigation to enable SPA routing
|
|
79
|
+
* // Note: this may be a Weex event which doesn't have this method
|
|
80
|
+
* if (e.preventDefault) e.preventDefault();
|
|
81
|
+
*
|
|
82
|
+
* return true;
|
|
83
|
+
* }
|
|
84
|
+
*/
|
|
85
|
+
eventHandler: {
|
|
86
|
+
type: Function
|
|
87
|
+
}
|
|
61
88
|
},
|
|
62
|
-
setup(props,
|
|
89
|
+
setup(props, context) {
|
|
90
|
+
const { slots, attrs } = context;
|
|
63
91
|
const link = useLink(props);
|
|
64
|
-
|
|
92
|
+
const wrapHandler = (externalHandler, internalHandler) => !internalHandler ? externalHandler : async (e) => {
|
|
93
|
+
try {
|
|
94
|
+
await externalHandler(e);
|
|
95
|
+
} finally {
|
|
96
|
+
await internalHandler(e);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const vue3renderer = () => {
|
|
65
100
|
var _a;
|
|
66
101
|
const data = link.value;
|
|
67
|
-
const
|
|
68
|
-
|
|
102
|
+
const genEventName = (name) => "on".concat(name.charAt(0).toUpperCase()).concat(name.slice(1));
|
|
103
|
+
const eventHandlers = data.getEventHandlers(genEventName);
|
|
104
|
+
Object.entries(attrs).forEach(([key, listener]) => {
|
|
105
|
+
if (!key.startsWith("on") || typeof listener !== "function")
|
|
106
|
+
return;
|
|
107
|
+
eventHandlers[key] = wrapHandler(listener, eventHandlers[key]);
|
|
108
|
+
});
|
|
109
|
+
return h(
|
|
110
|
+
data.tag,
|
|
111
|
+
{
|
|
112
|
+
...data.attributes,
|
|
113
|
+
...eventHandlers
|
|
114
|
+
},
|
|
115
|
+
(_a = slots.default) == null ? void 0 : _a.call(slots)
|
|
69
116
|
);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
117
|
+
};
|
|
118
|
+
const vue2renderer = () => {
|
|
119
|
+
var _a;
|
|
120
|
+
const data = link.value;
|
|
121
|
+
const eventHandlers = data.getEventHandlers();
|
|
122
|
+
const $listeners = context.listeners || {};
|
|
123
|
+
Object.entries($listeners).forEach(([key, listener]) => {
|
|
124
|
+
if (typeof listener !== "function") return;
|
|
125
|
+
eventHandlers[key] = wrapHandler(listener, eventHandlers[key]);
|
|
126
|
+
});
|
|
127
|
+
const { class: className, ...attrs2 } = data.attributes;
|
|
128
|
+
return h(
|
|
129
|
+
data.tag,
|
|
130
|
+
{
|
|
131
|
+
attrs: attrs2,
|
|
77
132
|
class: className,
|
|
78
133
|
on: eventHandlers
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
134
|
+
},
|
|
135
|
+
(_a = slots.default) == null ? void 0 : _a.call(slots)
|
|
136
|
+
);
|
|
82
137
|
};
|
|
138
|
+
return isVue3 ? vue3renderer : vue2renderer;
|
|
83
139
|
}
|
|
84
140
|
});
|
package/package.json
CHANGED
|
@@ -50,11 +50,11 @@
|
|
|
50
50
|
"vue": "^3.5.0 || ^2.7.0"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@esmx/router": "3.0.0-rc.
|
|
53
|
+
"@esmx/router": "3.0.0-rc.26"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@biomejs/biome": "1.9.4",
|
|
57
|
-
"@esmx/lint": "3.0.0-rc.
|
|
57
|
+
"@esmx/lint": "3.0.0-rc.26",
|
|
58
58
|
"@types/node": "^24.0.10",
|
|
59
59
|
"@vitest/coverage-v8": "3.2.4",
|
|
60
60
|
"stylelint": "16.21.0",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"vue": "3.5.13",
|
|
65
65
|
"vue2": "npm:vue@2.7.16"
|
|
66
66
|
},
|
|
67
|
-
"version": "3.0.0-rc.
|
|
67
|
+
"version": "3.0.0-rc.26",
|
|
68
68
|
"type": "module",
|
|
69
69
|
"private": false,
|
|
70
70
|
"exports": {
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"template",
|
|
84
84
|
"public"
|
|
85
85
|
],
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "2f52f94c8ac27aca32ef3148afd109d0f0470d52"
|
|
87
87
|
}
|
package/src/router-link.ts
CHANGED
|
@@ -77,7 +77,7 @@ export const RouterLink = defineComponent({
|
|
|
77
77
|
type: { type: String as PropType<RouterLinkType>, default: 'push' },
|
|
78
78
|
/**
|
|
79
79
|
* @deprecated Use 'type="replace"' instead
|
|
80
|
-
* @example replace={true} → type="replace"
|
|
80
|
+
* @example :replace={true} → type="replace"
|
|
81
81
|
*/
|
|
82
82
|
replace: { type: Boolean, default: false },
|
|
83
83
|
/**
|
|
@@ -113,36 +113,102 @@ export const RouterLink = defineComponent({
|
|
|
113
113
|
* Only used when type='pushLayer'.
|
|
114
114
|
* @example { zIndex: 1000, autoPush: false, routerOptions: { mode: 'memory' } }
|
|
115
115
|
*/
|
|
116
|
-
layerOptions: { type: Object as PropType<RouteLayerOptions> }
|
|
116
|
+
layerOptions: { type: Object as PropType<RouteLayerOptions> },
|
|
117
|
+
/**
|
|
118
|
+
* Custom event handler to control navigation behavior.
|
|
119
|
+
* Should return `true` to allow router to navigate, otherwise to prevent it.
|
|
120
|
+
*
|
|
121
|
+
* @Note you need to call `e.preventDefault()` to prevent default browser navigation.
|
|
122
|
+
* @default
|
|
123
|
+
*
|
|
124
|
+
* (event: Event & Partial<MouseEvent>): boolean => {
|
|
125
|
+
* // don't redirect with control keys
|
|
126
|
+
* if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return false;
|
|
127
|
+
* // don't redirect when preventDefault called
|
|
128
|
+
* if (e.defaultPrevented) return false;
|
|
129
|
+
* // don't redirect on right click
|
|
130
|
+
* if (e.button !== undefined && e.button !== 0) return false;
|
|
131
|
+
* // don't redirect if `target="_blank"`
|
|
132
|
+
* const target = e.currentTarget?.getAttribute?.('target') ?? '';
|
|
133
|
+
* if (/\b_blank\b/i.test(target)) return false;
|
|
134
|
+
* // Prevent default browser navigation to enable SPA routing
|
|
135
|
+
* // Note: this may be a Weex event which doesn't have this method
|
|
136
|
+
* if (e.preventDefault) e.preventDefault();
|
|
137
|
+
*
|
|
138
|
+
* return true;
|
|
139
|
+
* }
|
|
140
|
+
*/
|
|
141
|
+
eventHandler: {
|
|
142
|
+
type: Function as PropType<
|
|
143
|
+
(event: Event) => boolean | undefined | void
|
|
144
|
+
>
|
|
145
|
+
}
|
|
117
146
|
},
|
|
118
147
|
|
|
119
|
-
setup(props,
|
|
148
|
+
setup(props, context) {
|
|
149
|
+
const { slots, attrs } = context;
|
|
120
150
|
const link = useLink(props);
|
|
121
151
|
|
|
122
|
-
|
|
152
|
+
const wrapHandler = (
|
|
153
|
+
externalHandler: Function,
|
|
154
|
+
internalHandler: Function | undefined
|
|
155
|
+
) =>
|
|
156
|
+
!internalHandler
|
|
157
|
+
? (externalHandler as (e: Event) => Promise<void>)
|
|
158
|
+
: async (e: Event) => {
|
|
159
|
+
try {
|
|
160
|
+
await externalHandler(e);
|
|
161
|
+
} finally {
|
|
162
|
+
await internalHandler(e);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const vue3renderer = () => {
|
|
123
167
|
const data = link.value;
|
|
168
|
+
const genEventName = (name: string): string =>
|
|
169
|
+
`on${name.charAt(0).toUpperCase()}${name.slice(1)}`;
|
|
124
170
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
171
|
+
const eventHandlers = data.getEventHandlers(genEventName);
|
|
172
|
+
Object.entries(attrs).forEach(([key, listener]) => {
|
|
173
|
+
// In Vue 3, external event handlers are in attrs with 'on' prefix
|
|
174
|
+
if (!key.startsWith('on') || typeof listener !== 'function')
|
|
175
|
+
return;
|
|
176
|
+
eventHandlers[key] = wrapHandler(listener, eventHandlers[key]);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
return h(
|
|
180
|
+
data.tag,
|
|
181
|
+
{
|
|
182
|
+
...data.attributes,
|
|
183
|
+
...eventHandlers
|
|
184
|
+
},
|
|
185
|
+
slots.default?.()
|
|
131
186
|
);
|
|
187
|
+
};
|
|
132
188
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
189
|
+
const vue2renderer = () => {
|
|
190
|
+
const data = link.value;
|
|
191
|
+
|
|
192
|
+
const eventHandlers = data.getEventHandlers();
|
|
193
|
+
// Vue 2: get external listeners from context
|
|
194
|
+
const $listeners = (context as any).listeners || {};
|
|
195
|
+
Object.entries($listeners).forEach(([key, listener]) => {
|
|
196
|
+
if (typeof listener !== 'function') return;
|
|
197
|
+
eventHandlers[key] = wrapHandler(listener, eventHandlers[key]);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
const { class: className, ...attrs } = data.attributes;
|
|
201
|
+
return h(
|
|
202
|
+
data.tag,
|
|
203
|
+
{
|
|
139
204
|
attrs,
|
|
140
205
|
class: className,
|
|
141
206
|
on: eventHandlers
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return h(data.tag, props, slots.default?.());
|
|
207
|
+
},
|
|
208
|
+
slots.default?.()
|
|
209
|
+
);
|
|
146
210
|
};
|
|
211
|
+
|
|
212
|
+
return isVue3 ? vue3renderer : vue2renderer;
|
|
147
213
|
}
|
|
148
214
|
});
|