kdu-router 3.1.3 → 3.1.7

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,156 @@
1
+ /* @flow */
2
+
3
+ import type Router from '../index'
4
+ import { assert } from './warn'
5
+ import { getStateKey, setStateKey } from './state-key'
6
+ import { extend } from './misc'
7
+
8
+ const positionStore = Object.create(null)
9
+
10
+ export function setupScroll () {
11
+ // Fix for #1585 for Firefox
12
+ // Fix for #2195 Add optional third attribute to workaround a bug in safari https://bugs.webkit.org/show_bug.cgi?id=182678
13
+ // Fix for #2774 Support for apps loaded from Windows file shares not mapped to network drives: replaced location.origin with
14
+ // window.location.protocol + '//' + window.location.host
15
+ // location.host contains the port and location.hostname doesn't
16
+ const protocolAndPath = window.location.protocol + '//' + window.location.host
17
+ const absolutePath = window.location.href.replace(protocolAndPath, '')
18
+ // preserve existing history state as it could be overriden by the user
19
+ const stateCopy = extend({}, window.history.state)
20
+ stateCopy.key = getStateKey()
21
+ window.history.replaceState(stateCopy, '', absolutePath)
22
+ window.addEventListener('popstate', e => {
23
+ saveScrollPosition()
24
+ if (e.state && e.state.key) {
25
+ setStateKey(e.state.key)
26
+ }
27
+ })
28
+ }
29
+
30
+ export function handleScroll (
31
+ router: Router,
32
+ to: Route,
33
+ from: Route,
34
+ isPop: boolean
35
+ ) {
36
+ if (!router.app) {
37
+ return
38
+ }
39
+
40
+ const behavior = router.options.scrollBehavior
41
+ if (!behavior) {
42
+ return
43
+ }
44
+
45
+ if (process.env.NODE_ENV !== 'production') {
46
+ assert(typeof behavior === 'function', `scrollBehavior must be a function`)
47
+ }
48
+
49
+ // wait until re-render finishes before scrolling
50
+ router.app.$nextTick(() => {
51
+ const position = getScrollPosition()
52
+ const shouldScroll = behavior.call(
53
+ router,
54
+ to,
55
+ from,
56
+ isPop ? position : null
57
+ )
58
+
59
+ if (!shouldScroll) {
60
+ return
61
+ }
62
+
63
+ if (typeof shouldScroll.then === 'function') {
64
+ shouldScroll
65
+ .then(shouldScroll => {
66
+ scrollToPosition((shouldScroll: any), position)
67
+ })
68
+ .catch(err => {
69
+ if (process.env.NODE_ENV !== 'production') {
70
+ assert(false, err.toString())
71
+ }
72
+ })
73
+ } else {
74
+ scrollToPosition(shouldScroll, position)
75
+ }
76
+ })
77
+ }
78
+
79
+ export function saveScrollPosition () {
80
+ const key = getStateKey()
81
+ if (key) {
82
+ positionStore[key] = {
83
+ x: window.pageXOffset,
84
+ y: window.pageYOffset
85
+ }
86
+ }
87
+ }
88
+
89
+ function getScrollPosition (): ?Object {
90
+ const key = getStateKey()
91
+ if (key) {
92
+ return positionStore[key]
93
+ }
94
+ }
95
+
96
+ function getElementPosition (el: Element, offset: Object): Object {
97
+ const docEl: any = document.documentElement
98
+ const docRect = docEl.getBoundingClientRect()
99
+ const elRect = el.getBoundingClientRect()
100
+ return {
101
+ x: elRect.left - docRect.left - offset.x,
102
+ y: elRect.top - docRect.top - offset.y
103
+ }
104
+ }
105
+
106
+ function isValidPosition (obj: Object): boolean {
107
+ return isNumber(obj.x) || isNumber(obj.y)
108
+ }
109
+
110
+ function normalizePosition (obj: Object): Object {
111
+ return {
112
+ x: isNumber(obj.x) ? obj.x : window.pageXOffset,
113
+ y: isNumber(obj.y) ? obj.y : window.pageYOffset
114
+ }
115
+ }
116
+
117
+ function normalizeOffset (obj: Object): Object {
118
+ return {
119
+ x: isNumber(obj.x) ? obj.x : 0,
120
+ y: isNumber(obj.y) ? obj.y : 0
121
+ }
122
+ }
123
+
124
+ function isNumber (v: any): boolean {
125
+ return typeof v === 'number'
126
+ }
127
+
128
+ const hashStartsWithNumberRE = /^#\d/
129
+
130
+ function scrollToPosition (shouldScroll, position) {
131
+ const isObject = typeof shouldScroll === 'object'
132
+ if (isObject && typeof shouldScroll.selector === 'string') {
133
+ // getElementById would still fail if the selector contains a more complicated query like #main[data-attr]
134
+ // but at the same time, it doesn't make much sense to select an element with an id and an extra selector
135
+ const el = hashStartsWithNumberRE.test(shouldScroll.selector) // $flow-disable-line
136
+ ? document.getElementById(shouldScroll.selector.slice(1)) // $flow-disable-line
137
+ : document.querySelector(shouldScroll.selector)
138
+
139
+ if (el) {
140
+ let offset =
141
+ shouldScroll.offset && typeof shouldScroll.offset === 'object'
142
+ ? shouldScroll.offset
143
+ : {}
144
+ offset = normalizeOffset(offset)
145
+ position = getElementPosition(el, offset)
146
+ } else if (isValidPosition(shouldScroll)) {
147
+ position = normalizePosition(shouldScroll)
148
+ }
149
+ } else if (isObject && isValidPosition(shouldScroll)) {
150
+ position = normalizePosition(shouldScroll)
151
+ }
152
+
153
+ if (position) {
154
+ window.scrollTo(position.x, position.y)
155
+ }
156
+ }
@@ -0,0 +1,22 @@
1
+ /* @flow */
2
+ import { inBrowser } from './dom'
3
+
4
+ // use User Timing api (if present) for more accurate key precision
5
+ const Time =
6
+ inBrowser && window.performance && window.performance.now
7
+ ? window.performance
8
+ : Date
9
+
10
+ export function genStateKey (): string {
11
+ return Time.now().toFixed(3)
12
+ }
13
+
14
+ let _key: string = genStateKey()
15
+
16
+ export function getStateKey () {
17
+ return _key
18
+ }
19
+
20
+ export function setStateKey (key: string) {
21
+ return (_key = key)
22
+ }
@@ -0,0 +1,25 @@
1
+ /* @flow */
2
+
3
+ export function assert (condition: any, message: string) {
4
+ if (!condition) {
5
+ throw new Error(`[kdu-router] ${message}`)
6
+ }
7
+ }
8
+
9
+ export function warn (condition: any, message: string) {
10
+ if (process.env.NODE_ENV !== 'production' && !condition) {
11
+ typeof console !== 'undefined' && console.warn(`[kdu-router] ${message}`)
12
+ }
13
+ }
14
+
15
+ export function isError (err: any): boolean {
16
+ return Object.prototype.toString.call(err).indexOf('Error') > -1
17
+ }
18
+
19
+ export function isExtendedError (constructor: Function, err: any): boolean {
20
+ return (
21
+ err instanceof constructor ||
22
+ // _name is to support IE9 too
23
+ (err && (err.name === constructor.name || err._name === constructor._name))
24
+ )
25
+ }
package/types/index.d.ts CHANGED
@@ -1,16 +1,16 @@
1
- import './kdu'
2
- import { KduRouter } from './router'
3
-
4
- export default KduRouter
5
-
6
- export {
7
- RouterMode,
8
- RawLocation,
9
- RedirectOption,
10
- RouterOptions,
11
- RouteConfig,
12
- RouteRecord,
13
- Location,
14
- Route,
15
- NavigationGuard
16
- } from './router'
1
+ import './kdu'
2
+ import { KduRouter } from './router'
3
+
4
+ export default KduRouter
5
+
6
+ export {
7
+ RouterMode,
8
+ RawLocation,
9
+ RedirectOption,
10
+ RouterOptions,
11
+ RouteConfig,
12
+ RouteRecord,
13
+ Location,
14
+ Route,
15
+ NavigationGuard
16
+ } from './router'
package/types/kdu.d.ts CHANGED
@@ -1,22 +1,22 @@
1
- /**
2
- * Augment the typings of Kdu.js
3
- */
4
-
5
- import Kdu from 'kdu'
6
- import KduRouter, { Route, RawLocation, NavigationGuard } from './index'
7
-
8
- declare module 'kdu/types/kdu' {
9
- interface Kdu {
10
- $router: KduRouter
11
- $route: Route
12
- }
13
- }
14
-
15
- declare module 'kdu/types/options' {
16
- interface ComponentOptions<V extends Kdu> {
17
- router?: KduRouter
18
- beforeRouteEnter?: NavigationGuard<V>
19
- beforeRouteLeave?: NavigationGuard<V>
20
- beforeRouteUpdate?: NavigationGuard<V>
21
- }
22
- }
1
+ /**
2
+ * Augment the typings of Kdu.js
3
+ */
4
+
5
+ import Kdu from 'kdu'
6
+ import KduRouter, { Route, RawLocation, NavigationGuard } from './index'
7
+
8
+ declare module 'kdu/types/kdu' {
9
+ interface Kdu {
10
+ $router: KduRouter
11
+ $route: Route
12
+ }
13
+ }
14
+
15
+ declare module 'kdu/types/options' {
16
+ interface ComponentOptions<V extends Kdu> {
17
+ router?: KduRouter
18
+ beforeRouteEnter?: NavigationGuard<V>
19
+ beforeRouteLeave?: NavigationGuard<V>
20
+ beforeRouteUpdate?: NavigationGuard<V>
21
+ }
22
+ }
package/types/router.d.ts CHANGED
@@ -1,145 +1,145 @@
1
- import Kdu, { ComponentOptions, PluginFunction, AsyncComponent } from 'kdu'
2
-
3
- type Component = ComponentOptions<Kdu> | typeof Kdu | AsyncComponent
4
- type Dictionary < T > = { [key: string]: T }
5
- type ErrorHandler = (err: Error) => void
6
-
7
- export type RouterMode = 'hash' | 'history' | 'abstract'
8
- export type RawLocation = string | Location
9
- export type RedirectOption = RawLocation | ((to: Route) => RawLocation)
10
- export type NavigationGuard < V extends Kdu = Kdu > = (
11
- to: Route,
12
- from: Route,
13
- next: (to?: RawLocation | false | ((vm: V) => any) | void) => void
14
- ) => any
15
-
16
- export declare class KduRouter {
17
- constructor(options?: RouterOptions)
18
-
19
- app: Kdu
20
- mode: RouterMode
21
- currentRoute: Route
22
-
23
- beforeEach(guard: NavigationGuard): Function
24
- beforeResolve(guard: NavigationGuard): Function
25
- afterEach(hook: (to: Route, from: Route) => any): Function
26
- push(location: RawLocation): Promise<Route>
27
- replace(location: RawLocation): Promise<Route>
28
- push(
29
- location: RawLocation,
30
- onComplete?: Function,
31
- onAbort?: ErrorHandler
32
- ): void
33
- replace(
34
- location: RawLocation,
35
- onComplete?: Function,
36
- onAbort?: ErrorHandler
37
- ): void
38
- go(n: number): void
39
- back(): void
40
- forward(): void
41
- getMatchedComponents(to?: RawLocation | Route): Component[]
42
- onReady(cb: Function, errorCb?: ErrorHandler): void
43
- onError(cb: ErrorHandler): void
44
- addRoutes(routes: RouteConfig[]): void
45
- resolve(
46
- to: RawLocation,
47
- current?: Route,
48
- append?: boolean
49
- ): {
50
- location: Location
51
- route: Route
52
- href: string
53
- // backwards compat
54
- normalizedTo: Location
55
- resolved: Route
56
- }
57
-
58
- static install: PluginFunction<never>
59
- }
60
-
61
- type Position = { x: number; y: number }
62
- type PositionResult = Position | { selector: string; offset?: Position } | void
63
-
64
- export interface RouterOptions {
65
- routes?: RouteConfig[]
66
- mode?: RouterMode
67
- fallback?: boolean
68
- base?: string
69
- linkActiveClass?: string
70
- linkExactActiveClass?: string
71
- parseQuery?: (query: string) => Object
72
- stringifyQuery?: (query: Object) => string
73
- scrollBehavior?: (
74
- to: Route,
75
- from: Route,
76
- savedPosition: Position | void
77
- ) => PositionResult | Promise<PositionResult>
78
- }
79
-
80
- type RoutePropsFunction = (route: Route) => Object
81
-
82
- export interface PathToRegexpOptions {
83
- sensitive?: boolean
84
- strict?: boolean
85
- end?: boolean
86
- }
87
-
88
- export interface RouteConfig {
89
- path: string
90
- name?: string
91
- component?: Component
92
- components?: Dictionary<Component>
93
- redirect?: RedirectOption
94
- alias?: string | string[]
95
- children?: RouteConfig[]
96
- meta?: any
97
- beforeEnter?: NavigationGuard
98
- props?: boolean | Object | RoutePropsFunction
99
- caseSensitive?: boolean
100
- pathToRegexpOptions?: PathToRegexpOptions
101
- }
102
-
103
- export interface RouteRecord {
104
- path: string
105
- regex: RegExp
106
- components: Dictionary<Component>
107
- instances: Dictionary<Kdu>
108
- name?: string
109
- parent?: RouteRecord
110
- redirect?: RedirectOption
111
- matchAs?: string
112
- meta: any
113
- beforeEnter?: (
114
- route: Route,
115
- redirect: (location: RawLocation) => void,
116
- next: () => void
117
- ) => any
118
- props:
119
- | boolean
120
- | Object
121
- | RoutePropsFunction
122
- | Dictionary<boolean | Object | RoutePropsFunction>
123
- }
124
-
125
- export interface Location {
126
- name?: string
127
- path?: string
128
- hash?: string
129
- query?: Dictionary<string | (string | null)[] | null | undefined>
130
- params?: Dictionary<string>
131
- append?: boolean
132
- replace?: boolean
133
- }
134
-
135
- export interface Route {
136
- path: string
137
- name?: string
138
- hash: string
139
- query: Dictionary<string | (string | null)[]>
140
- params: Dictionary<string>
141
- fullPath: string
142
- matched: RouteRecord[]
143
- redirectedFrom?: string
144
- meta?: any
145
- }
1
+ import Kdu, { ComponentOptions, PluginFunction, AsyncComponent } from 'kdu'
2
+
3
+ type Component = ComponentOptions<Kdu> | typeof Kdu | AsyncComponent
4
+ type Dictionary < T > = { [key: string]: T }
5
+ type ErrorHandler = (err: Error) => void
6
+
7
+ export type RouterMode = 'hash' | 'history' | 'abstract'
8
+ export type RawLocation = string | Location
9
+ export type RedirectOption = RawLocation | ((to: Route) => RawLocation)
10
+ export type NavigationGuard < V extends Kdu = Kdu > = (
11
+ to: Route,
12
+ from: Route,
13
+ next: (to?: RawLocation | false | ((vm: V) => any) | void) => void
14
+ ) => any
15
+
16
+ export declare class KduRouter {
17
+ constructor(options?: RouterOptions)
18
+
19
+ app: Kdu
20
+ mode: RouterMode
21
+ currentRoute: Route
22
+
23
+ beforeEach(guard: NavigationGuard): Function
24
+ beforeResolve(guard: NavigationGuard): Function
25
+ afterEach(hook: (to: Route, from: Route) => any): Function
26
+ push(location: RawLocation): Promise<Route>
27
+ replace(location: RawLocation): Promise<Route>
28
+ push(
29
+ location: RawLocation,
30
+ onComplete?: Function,
31
+ onAbort?: ErrorHandler
32
+ ): void
33
+ replace(
34
+ location: RawLocation,
35
+ onComplete?: Function,
36
+ onAbort?: ErrorHandler
37
+ ): void
38
+ go(n: number): void
39
+ back(): void
40
+ forward(): void
41
+ getMatchedComponents(to?: RawLocation | Route): Component[]
42
+ onReady(cb: Function, errorCb?: ErrorHandler): void
43
+ onError(cb: ErrorHandler): void
44
+ addRoutes(routes: RouteConfig[]): void
45
+ resolve(
46
+ to: RawLocation,
47
+ current?: Route,
48
+ append?: boolean
49
+ ): {
50
+ location: Location
51
+ route: Route
52
+ href: string
53
+ // backwards compat
54
+ normalizedTo: Location
55
+ resolved: Route
56
+ }
57
+
58
+ static install: PluginFunction<never>
59
+ }
60
+
61
+ type Position = { x: number; y: number }
62
+ type PositionResult = Position | { selector: string; offset?: Position } | void
63
+
64
+ export interface RouterOptions {
65
+ routes?: RouteConfig[]
66
+ mode?: RouterMode
67
+ fallback?: boolean
68
+ base?: string
69
+ linkActiveClass?: string
70
+ linkExactActiveClass?: string
71
+ parseQuery?: (query: string) => Object
72
+ stringifyQuery?: (query: Object) => string
73
+ scrollBehavior?: (
74
+ to: Route,
75
+ from: Route,
76
+ savedPosition: Position | void
77
+ ) => PositionResult | Promise<PositionResult> | undefined | null
78
+ }
79
+
80
+ type RoutePropsFunction = (route: Route) => Object
81
+
82
+ export interface PathToRegexpOptions {
83
+ sensitive?: boolean
84
+ strict?: boolean
85
+ end?: boolean
86
+ }
87
+
88
+ export interface RouteConfig {
89
+ path: string
90
+ name?: string
91
+ component?: Component
92
+ components?: Dictionary<Component>
93
+ redirect?: RedirectOption
94
+ alias?: string | string[]
95
+ children?: RouteConfig[]
96
+ meta?: any
97
+ beforeEnter?: NavigationGuard
98
+ props?: boolean | Object | RoutePropsFunction
99
+ caseSensitive?: boolean
100
+ pathToRegexpOptions?: PathToRegexpOptions
101
+ }
102
+
103
+ export interface RouteRecord {
104
+ path: string
105
+ regex: RegExp
106
+ components: Dictionary<Component>
107
+ instances: Dictionary<Kdu>
108
+ name?: string
109
+ parent?: RouteRecord
110
+ redirect?: RedirectOption
111
+ matchAs?: string
112
+ meta: any
113
+ beforeEnter?: (
114
+ route: Route,
115
+ redirect: (location: RawLocation) => void,
116
+ next: () => void
117
+ ) => any
118
+ props:
119
+ | boolean
120
+ | Object
121
+ | RoutePropsFunction
122
+ | Dictionary<boolean | Object | RoutePropsFunction>
123
+ }
124
+
125
+ export interface Location {
126
+ name?: string
127
+ path?: string
128
+ hash?: string
129
+ query?: Dictionary<string | (string | null)[] | null | undefined>
130
+ params?: Dictionary<string>
131
+ append?: boolean
132
+ replace?: boolean
133
+ }
134
+
135
+ export interface Route {
136
+ path: string
137
+ name?: string | null
138
+ hash: string
139
+ query: Dictionary<string | (string | null)[]>
140
+ params: Dictionary<string>
141
+ fullPath: string
142
+ matched: RouteRecord[]
143
+ redirectedFrom?: string
144
+ meta?: any
145
+ }