@tramvai/module-autoscroll 6.80.26 → 6.81.11

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/README.md CHANGED
@@ -1,8 +1,12 @@
1
1
  # Autoscroll
2
2
 
3
- React component that implements autoscroll to page start or to the anchor on page on SPA-navigations
3
+ Module emulates native browser scroll behavior on SPA-navigations:
4
4
 
5
- The behaviour is similar to the [react-router](https://reacttraining.com/react-router/web/guides/scroll-restoration/scroll-to-tops)
5
+ - scroll to top of the page if there is no hash in the URL
6
+ - scroll to the element with id that equals to the hash in the URL if it exists
7
+ - restore scroll position on back/forward navigations
8
+
9
+ The behaviour is similar to the [react-router](https://reactrouter.com/api/components/ScrollRestoration)
6
10
 
7
11
  ## Installation
8
12
 
@@ -12,15 +16,15 @@ First install `@tramvai/module-autoscroll`:
12
16
  yarn add @tramvai/module-autoscroll
13
17
  ```
14
18
 
15
- And add `AutoscrollModule` to the modules list:
19
+ And add `ScrollRestorationModule` to the modules list:
16
20
 
17
21
  ```tsx
18
22
  import { createApp } from '@tramvai/core';
19
- import { AutoscrollModule } from '@tramvai/module-autoscroll';
23
+ import { ScrollRestorationModule } from '@tramvai/module-autoscroll';
20
24
 
21
25
  createApp({
22
26
  name: 'tincoin',
23
- modules: [AutoscrollModule],
27
+ modules: [ScrollRestorationModule],
24
28
  });
25
29
  ```
26
30
 
@@ -30,7 +34,11 @@ createApp({
30
34
 
31
35
  `behavior: smooth` is not supported by every browser (e.g. doesn't work in Safari). In this case you can use polyfill `smoothscroll-polyfill` that you should add to your app.
32
36
 
33
- Browser scroll restoration is disabled when autoscroll is enabled (`window.history.scrollRestoration = 'manual'`).
37
+ ### Scroll restoration
38
+
39
+ Native browser scroll restoration is disabled when autoscroll is enabled (`window.history.scrollRestoration = 'manual'`, depending on the `navigateState.disableAutoscroll` parameter or `AUTOSCROLL_DISABLED_TOKEN` token).
40
+
41
+ Module saves scroll position on every navigation and restores it on back/forward navigations. Scroll position is saved in `sessionStorage` by navigation index (`history.state.index`).
34
42
 
35
43
  ## How to
36
44
 
@@ -51,6 +59,53 @@ function Component() {
51
59
  }
52
60
  ```
53
61
 
62
+ ### Disable autoscroll for custom conditions
63
+
64
+ By default, autoscroll is disabled, when `navigateState.disableAutoscroll` is `true`.
65
+
66
+ For example, if you want to disable it for all `updateCurrentRoute` calls, you can provide `AUTOSCROLL_DISABLED_TOKEN` token:
67
+
68
+ ```tsx
69
+ import { AUTOSCROLL_DISABLED_TOKEN } from '@tramvai/module-autoscroll';
70
+ import { provide } from '@tramvai/core';
71
+
72
+ const providers = [
73
+ // ...,
74
+ provide({
75
+ provide: AUTOSCROLL_DISABLED_TOKEN,
76
+ useFactory:
77
+ ({ router }) =>
78
+ () => {
79
+ // disable autoscroll for navigation with query `?autoscroll_disabled=true`
80
+ if (router.getCurrentUrl().query.autoscroll_disabled === 'true') {
81
+ return true;
82
+ }
83
+ // return nothing to use default behavior
84
+ },
85
+ deps: {
86
+ router: ROUTER_TOKEN,
87
+ },
88
+ }),
89
+ ];
90
+ ```
91
+
92
+ ### Use autoscroll with View Transitions
93
+
94
+ To avoid inconsistent animations when using View Transition API (e.g. X and Y axis movements in the same time), recommended to set autoscroll behavior to `instant`:
95
+
96
+ ```tsx
97
+ import { AUTOSCROLL_BEHAVIOR_MODE_TOKEN } from '@tramvai/module-autoscroll';
98
+ import { provide } from '@tramvai/core';
99
+
100
+ const providers = [
101
+ // ...,
102
+ provide({
103
+ provide: AUTOSCROLL_BEHAVIOR_MODE_TOKEN,
104
+ useValue: (defaultBehavior) => 'instant', // default is 'smooth' for autoscroll in new pages or anchors and 'instant' for scroll restoration
105
+ }),
106
+ ];
107
+ ```
108
+
54
109
  ### Scroll behavior change
55
110
 
56
111
  #### Global
@@ -63,7 +118,7 @@ const providers = [
63
118
  // ...,
64
119
  provide({
65
120
  provide: AUTOSCROLL_BEHAVIOR_MODE_TOKEN,
66
- useValue: 'auto', // default is 'smooth'
121
+ useValue: (defaultBehavior) => 'auto', // default is 'smooth' for autoscroll in new pages or anchors and 'instant' for scroll restoration
67
122
  }),
68
123
  ];
69
124
  ```
@@ -83,7 +138,7 @@ function Component() {
83
138
  }
84
139
  ```
85
140
 
86
- ### ScrollTo top change
141
+ ### Scroll top change
87
142
 
88
143
  #### Global
89
144
 
@@ -112,7 +167,8 @@ const providers = [
112
167
  // ...,
113
168
  provide({
114
169
  provide: AUTOSCROLL_SCROLL_TOP_TOKEN,
115
- useValue: () => {
170
+ // if `isRestoredValue` is `true`, it means that `defaultScrollTop` is resolved previous position for auto scroll restoration
171
+ useValue: (defaultScrollTop, isRestoredValue) => {
116
172
  try {
117
173
  const savedScrollTop = JSON.parse(sessionStorage.get('scrollTop'));
118
174
  // for example, if you save scroll position by navigation index
@@ -1,5 +1,5 @@
1
1
  import { memo, useMemo, useRef } from 'react';
2
- import { useRoute, useUrl, useViewTransition } from '@tramvai/module-router';
2
+ import { useRoute, useUrl } from '@tramvai/module-router';
3
3
  import { optional } from '@tinkoff/dippy';
4
4
  import { useDi } from '@tramvai/react';
5
5
  import { LOGGER_TOKEN } from '@tramvai/tokens-common';
@@ -32,7 +32,6 @@ const scrollToAnchor = (anchor, behavior) => {
32
32
  const Autoscroll = memo(() => {
33
33
  const route = useRoute();
34
34
  const url = useUrl();
35
- const { isTransitioning } = useViewTransition(url.pathname);
36
35
  const scrollBehaviorFactory = useDi(optional(AUTOSCROLL_BEHAVIOR_MODE_TOKEN)) ?? DEFAULT_AUTOSCROLL_BEHAVIOR;
37
36
  const scrollTopFactory = useDi(optional(AUTOSCROLL_SCROLL_TOP_TOKEN)) ?? DEFAULT_AUTOSCROLL_SCROLL_TOP;
38
37
  const logger = useDi(LOGGER_TOKEN);
@@ -48,11 +47,6 @@ const Autoscroll = memo(() => {
48
47
  if (!shouldScroll.current) {
49
48
  return;
50
49
  }
51
- // when VT is enabled, we will have a two re-renderw with `isTransitioning: true` (with current and next url),
52
- // and only after that `isTransitioning` will be false and url will be updated to the next one.
53
- if (isTransitioning) {
54
- return;
55
- }
56
50
  // disable autoscroll for current page if `disableAutoscroll` is set in route history state
57
51
  if (route.navigateState?.disableAutoscroll) {
58
52
  previousUrl.current = url;
@@ -64,9 +58,11 @@ const Autoscroll = memo(() => {
64
58
  shouldScroll.current = false;
65
59
  const scrollBehavior = route.navigateState?.autoscrollBehavior ??
66
60
  (typeof scrollBehaviorFactory === 'function'
67
- ? scrollBehaviorFactory()
61
+ ? scrollBehaviorFactory(DEFAULT_AUTOSCROLL_BEHAVIOR)
68
62
  : scrollBehaviorFactory);
69
- const scrollTop = typeof scrollTopFactory === 'function' ? scrollTopFactory() : scrollTopFactory;
63
+ const scrollTop = typeof scrollTopFactory === 'function'
64
+ ? scrollTopFactory(DEFAULT_AUTOSCROLL_SCROLL_TOP, false)
65
+ : scrollTopFactory;
70
66
  function scroll() {
71
67
  if (!url.hash) {
72
68
  log.debug(`Scrolling to top ${scrollTop}px with behavior: ${scrollBehavior}`);
@@ -79,7 +75,7 @@ const Autoscroll = memo(() => {
79
75
  }
80
76
  scroll();
81
77
  // eslint-disable-next-line react-hooks/exhaustive-deps
82
- }, [route, url, isTransitioning]);
78
+ }, [route, url]);
83
79
  return null;
84
80
  });
85
81
 
@@ -36,7 +36,6 @@ const scrollToAnchor = (anchor, behavior) => {
36
36
  const Autoscroll = react.memo(() => {
37
37
  const route = moduleRouter.useRoute();
38
38
  const url = moduleRouter.useUrl();
39
- const { isTransitioning } = moduleRouter.useViewTransition(url.pathname);
40
39
  const scrollBehaviorFactory = react$1.useDi(dippy.optional(tokens.AUTOSCROLL_BEHAVIOR_MODE_TOKEN)) ?? DEFAULT_AUTOSCROLL_BEHAVIOR;
41
40
  const scrollTopFactory = react$1.useDi(dippy.optional(tokens.AUTOSCROLL_SCROLL_TOP_TOKEN)) ?? DEFAULT_AUTOSCROLL_SCROLL_TOP;
42
41
  const logger = react$1.useDi(tokensCommon.LOGGER_TOKEN);
@@ -52,11 +51,6 @@ const Autoscroll = react.memo(() => {
52
51
  if (!shouldScroll.current) {
53
52
  return;
54
53
  }
55
- // when VT is enabled, we will have a two re-renderw with `isTransitioning: true` (with current and next url),
56
- // and only after that `isTransitioning` will be false and url will be updated to the next one.
57
- if (isTransitioning) {
58
- return;
59
- }
60
54
  // disable autoscroll for current page if `disableAutoscroll` is set in route history state
61
55
  if (route.navigateState?.disableAutoscroll) {
62
56
  previousUrl.current = url;
@@ -68,9 +62,11 @@ const Autoscroll = react.memo(() => {
68
62
  shouldScroll.current = false;
69
63
  const scrollBehavior = route.navigateState?.autoscrollBehavior ??
70
64
  (typeof scrollBehaviorFactory === 'function'
71
- ? scrollBehaviorFactory()
65
+ ? scrollBehaviorFactory(DEFAULT_AUTOSCROLL_BEHAVIOR)
72
66
  : scrollBehaviorFactory);
73
- const scrollTop = typeof scrollTopFactory === 'function' ? scrollTopFactory() : scrollTopFactory;
67
+ const scrollTop = typeof scrollTopFactory === 'function'
68
+ ? scrollTopFactory(DEFAULT_AUTOSCROLL_SCROLL_TOP, false)
69
+ : scrollTopFactory;
74
70
  function scroll() {
75
71
  if (!url.hash) {
76
72
  log.debug(`Scrolling to top ${scrollTop}px with behavior: ${scrollBehavior}`);
@@ -83,7 +79,7 @@ const Autoscroll = react.memo(() => {
83
79
  }
84
80
  scroll();
85
81
  // eslint-disable-next-line react-hooks/exhaustive-deps
86
- }, [route, url, isTransitioning]);
82
+ }, [route, url]);
87
83
  return null;
88
84
  });
89
85
 
@@ -0,0 +1,2 @@
1
+ export declare const ScrollRestoration: import("react").MemoExoticComponent<() => null>;
2
+ //# sourceMappingURL=ScrollRestoration.d.ts.map
@@ -0,0 +1,127 @@
1
+ import { memo, useMemo, useRef } from 'react';
2
+ import { useRouter, useRoute, useUrl } from '@tramvai/module-router';
3
+ import { optional } from '@tinkoff/dippy';
4
+ import { useDi } from '@tramvai/react';
5
+ import { LOGGER_TOKEN } from '@tramvai/tokens-common';
6
+ import { useIsomorphicLayoutEffect } from '@tinkoff/react-hooks';
7
+ import { AUTOSCROLL_BEHAVIOR_MODE_TOKEN, AUTOSCROLL_SCROLL_TOP_TOKEN, AUTOSCROLL_DISABLED_TOKEN, AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN } from '../tokens.es.js';
8
+
9
+ const DEFAULT_AUTOSCROLL_BEHAVIOR = process.env.__TRAMVAI_REACT_TRANSITIONS === 'true' ? 'instant' : 'smooth';
10
+ const DEFAULT_SCROLL_RESTORATION_BEHAVIOR = 'instant';
11
+ const DEFAULT_AUTOSCROLL_SCROLL_TOP = 0;
12
+ const scrollToTop = (behavior, top) => {
13
+ // cross-browser `window.scrollTo` parameters
14
+ try {
15
+ window.scrollTo({ top, left: 0, behavior });
16
+ }
17
+ catch (error) {
18
+ window.scrollTo(0, top);
19
+ }
20
+ };
21
+ const scrollToAnchor = (anchor, behavior) => {
22
+ try {
23
+ document.querySelector(anchor)?.scrollIntoView({
24
+ behavior,
25
+ });
26
+ return true;
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ };
32
+ // @reference https://reacttraining.com/react-router/web/guides/scroll-restoration/scroll-to-top
33
+ const ScrollRestoration = memo(() => {
34
+ const router = useRouter();
35
+ const route = useRoute();
36
+ const url = useUrl();
37
+ const scrollBehaviorFactory = useDi(optional(AUTOSCROLL_BEHAVIOR_MODE_TOKEN));
38
+ const scrollTopFactory = useDi(optional(AUTOSCROLL_SCROLL_TOP_TOKEN));
39
+ const autoscrollDisabledFactory = useDi(optional(AUTOSCROLL_DISABLED_TOKEN));
40
+ const appliedNavigations = useDi(AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN);
41
+ const logger = useDi(LOGGER_TOKEN);
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ const log = useMemo(() => logger('autoscroll'), []);
44
+ const previousUrl = useRef(url);
45
+ const shouldScroll = useRef(true);
46
+ // workaround to restore scroll position on page reload instantly
47
+ const initialScrollRestoration = useRef(true);
48
+ // eslint-disable-next-line max-statements
49
+ useIsomorphicLayoutEffect(() => {
50
+ if (url.pathname !== previousUrl.current.pathname ||
51
+ url.hash !== previousUrl.current.hash ||
52
+ url.search !== previousUrl.current.search) {
53
+ shouldScroll.current = true;
54
+ }
55
+ // skip unnecessary checks, if url has not changed and shouldScroll.current set to false - we don't need to scroll
56
+ if (!shouldScroll.current) {
57
+ return;
58
+ }
59
+ const autoscrollDisabled = typeof autoscrollDisabledFactory === 'function'
60
+ ? autoscrollDisabledFactory()
61
+ : autoscrollDisabledFactory;
62
+ // disable autoscroll for current page if `disableAutoscroll` is set in route history state
63
+ if (autoscrollDisabled ?? route.navigateState?.disableAutoscroll) {
64
+ previousUrl.current = url;
65
+ shouldScroll.current = false;
66
+ if (typeof autoscrollDisabled === 'boolean') {
67
+ log.debug('Skipping autoscroll because "AUTOSCROLL_DISABLED_TOKEN" is return true');
68
+ }
69
+ else {
70
+ log.debug('Skipping autoscroll because "disableAutoscroll" is set in navigation state');
71
+ }
72
+ log.debug('Enable browser scroll restoration to handle scroll position automatically');
73
+ window.history.scrollRestoration = 'auto';
74
+ return;
75
+ }
76
+ log.debug('Disabling browser scroll restoration to handle scroll position manually');
77
+ window.history.scrollRestoration = 'manual';
78
+ previousUrl.current = url;
79
+ shouldScroll.current = false;
80
+ const navigationIndex = router.history.getCurrentState()?.index;
81
+ const scrollRestoredPosition = appliedNavigations.has(navigationIndex) &&
82
+ // if url was changed with replace: true navigation
83
+ appliedNavigations.get(navigationIndex).href === url.href &&
84
+ appliedNavigations.get(navigationIndex).scrollTop;
85
+ const isRestoredScrollPosition = typeof scrollRestoredPosition === 'number';
86
+ const scrollTopDefault = isRestoredScrollPosition
87
+ ? scrollRestoredPosition
88
+ : DEFAULT_AUTOSCROLL_SCROLL_TOP;
89
+ const scrollTopFromFactory = typeof scrollTopFactory === 'function'
90
+ ? scrollTopFactory(scrollTopDefault, isRestoredScrollPosition)
91
+ : scrollTopFactory;
92
+ const scrollTop = scrollTopFromFactory ?? scrollTopDefault;
93
+ const scrollBehaviorDefault = initialScrollRestoration.current || isRestoredScrollPosition
94
+ ? DEFAULT_SCROLL_RESTORATION_BEHAVIOR
95
+ : DEFAULT_AUTOSCROLL_BEHAVIOR;
96
+ const scrollBehaviorFromFactory = typeof scrollBehaviorFactory === 'function'
97
+ ? scrollBehaviorFactory(scrollBehaviorDefault)
98
+ : scrollBehaviorFactory;
99
+ const scrollBehavior = scrollBehaviorFromFactory ?? scrollBehaviorDefault;
100
+ if (isRestoredScrollPosition) {
101
+ if (initialScrollRestoration.current) {
102
+ log.debug(`Restoring scroll position ${scrollRestoredPosition}px with instant behavior due to page reload`);
103
+ }
104
+ else {
105
+ log.debug(`Restoring scroll position ${scrollRestoredPosition}px for navigation index ${navigationIndex}`);
106
+ }
107
+ }
108
+ if (initialScrollRestoration.current) {
109
+ initialScrollRestoration.current = false;
110
+ }
111
+ function scroll() {
112
+ if (!url.hash) {
113
+ log.debug(`Scrolling to top ${scrollTop}px with behavior: ${scrollBehavior}`);
114
+ scrollToTop(scrollBehavior, scrollTop);
115
+ }
116
+ else {
117
+ log.debug(`Scrolling to anchor ${url.hash} with behavior: ${scrollBehavior}`);
118
+ scrollToAnchor(url.hash, scrollBehavior);
119
+ }
120
+ }
121
+ scroll();
122
+ // eslint-disable-next-line react-hooks/exhaustive-deps
123
+ }, [router, route, url]);
124
+ return null;
125
+ });
126
+
127
+ export { ScrollRestoration };
@@ -0,0 +1,131 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var react = require('react');
6
+ var moduleRouter = require('@tramvai/module-router');
7
+ var dippy = require('@tinkoff/dippy');
8
+ var react$1 = require('@tramvai/react');
9
+ var tokensCommon = require('@tramvai/tokens-common');
10
+ var reactHooks = require('@tinkoff/react-hooks');
11
+ var tokens = require('../tokens.js');
12
+
13
+ const DEFAULT_AUTOSCROLL_BEHAVIOR = process.env.__TRAMVAI_REACT_TRANSITIONS === 'true' ? 'instant' : 'smooth';
14
+ const DEFAULT_SCROLL_RESTORATION_BEHAVIOR = 'instant';
15
+ const DEFAULT_AUTOSCROLL_SCROLL_TOP = 0;
16
+ const scrollToTop = (behavior, top) => {
17
+ // cross-browser `window.scrollTo` parameters
18
+ try {
19
+ window.scrollTo({ top, left: 0, behavior });
20
+ }
21
+ catch (error) {
22
+ window.scrollTo(0, top);
23
+ }
24
+ };
25
+ const scrollToAnchor = (anchor, behavior) => {
26
+ try {
27
+ document.querySelector(anchor)?.scrollIntoView({
28
+ behavior,
29
+ });
30
+ return true;
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ };
36
+ // @reference https://reacttraining.com/react-router/web/guides/scroll-restoration/scroll-to-top
37
+ const ScrollRestoration = react.memo(() => {
38
+ const router = moduleRouter.useRouter();
39
+ const route = moduleRouter.useRoute();
40
+ const url = moduleRouter.useUrl();
41
+ const scrollBehaviorFactory = react$1.useDi(dippy.optional(tokens.AUTOSCROLL_BEHAVIOR_MODE_TOKEN));
42
+ const scrollTopFactory = react$1.useDi(dippy.optional(tokens.AUTOSCROLL_SCROLL_TOP_TOKEN));
43
+ const autoscrollDisabledFactory = react$1.useDi(dippy.optional(tokens.AUTOSCROLL_DISABLED_TOKEN));
44
+ const appliedNavigations = react$1.useDi(tokens.AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN);
45
+ const logger = react$1.useDi(tokensCommon.LOGGER_TOKEN);
46
+ // eslint-disable-next-line react-hooks/exhaustive-deps
47
+ const log = react.useMemo(() => logger('autoscroll'), []);
48
+ const previousUrl = react.useRef(url);
49
+ const shouldScroll = react.useRef(true);
50
+ // workaround to restore scroll position on page reload instantly
51
+ const initialScrollRestoration = react.useRef(true);
52
+ // eslint-disable-next-line max-statements
53
+ reactHooks.useIsomorphicLayoutEffect(() => {
54
+ if (url.pathname !== previousUrl.current.pathname ||
55
+ url.hash !== previousUrl.current.hash ||
56
+ url.search !== previousUrl.current.search) {
57
+ shouldScroll.current = true;
58
+ }
59
+ // skip unnecessary checks, if url has not changed and shouldScroll.current set to false - we don't need to scroll
60
+ if (!shouldScroll.current) {
61
+ return;
62
+ }
63
+ const autoscrollDisabled = typeof autoscrollDisabledFactory === 'function'
64
+ ? autoscrollDisabledFactory()
65
+ : autoscrollDisabledFactory;
66
+ // disable autoscroll for current page if `disableAutoscroll` is set in route history state
67
+ if (autoscrollDisabled ?? route.navigateState?.disableAutoscroll) {
68
+ previousUrl.current = url;
69
+ shouldScroll.current = false;
70
+ if (typeof autoscrollDisabled === 'boolean') {
71
+ log.debug('Skipping autoscroll because "AUTOSCROLL_DISABLED_TOKEN" is return true');
72
+ }
73
+ else {
74
+ log.debug('Skipping autoscroll because "disableAutoscroll" is set in navigation state');
75
+ }
76
+ log.debug('Enable browser scroll restoration to handle scroll position automatically');
77
+ window.history.scrollRestoration = 'auto';
78
+ return;
79
+ }
80
+ log.debug('Disabling browser scroll restoration to handle scroll position manually');
81
+ window.history.scrollRestoration = 'manual';
82
+ previousUrl.current = url;
83
+ shouldScroll.current = false;
84
+ const navigationIndex = router.history.getCurrentState()?.index;
85
+ const scrollRestoredPosition = appliedNavigations.has(navigationIndex) &&
86
+ // if url was changed with replace: true navigation
87
+ appliedNavigations.get(navigationIndex).href === url.href &&
88
+ appliedNavigations.get(navigationIndex).scrollTop;
89
+ const isRestoredScrollPosition = typeof scrollRestoredPosition === 'number';
90
+ const scrollTopDefault = isRestoredScrollPosition
91
+ ? scrollRestoredPosition
92
+ : DEFAULT_AUTOSCROLL_SCROLL_TOP;
93
+ const scrollTopFromFactory = typeof scrollTopFactory === 'function'
94
+ ? scrollTopFactory(scrollTopDefault, isRestoredScrollPosition)
95
+ : scrollTopFactory;
96
+ const scrollTop = scrollTopFromFactory ?? scrollTopDefault;
97
+ const scrollBehaviorDefault = initialScrollRestoration.current || isRestoredScrollPosition
98
+ ? DEFAULT_SCROLL_RESTORATION_BEHAVIOR
99
+ : DEFAULT_AUTOSCROLL_BEHAVIOR;
100
+ const scrollBehaviorFromFactory = typeof scrollBehaviorFactory === 'function'
101
+ ? scrollBehaviorFactory(scrollBehaviorDefault)
102
+ : scrollBehaviorFactory;
103
+ const scrollBehavior = scrollBehaviorFromFactory ?? scrollBehaviorDefault;
104
+ if (isRestoredScrollPosition) {
105
+ if (initialScrollRestoration.current) {
106
+ log.debug(`Restoring scroll position ${scrollRestoredPosition}px with instant behavior due to page reload`);
107
+ }
108
+ else {
109
+ log.debug(`Restoring scroll position ${scrollRestoredPosition}px for navigation index ${navigationIndex}`);
110
+ }
111
+ }
112
+ if (initialScrollRestoration.current) {
113
+ initialScrollRestoration.current = false;
114
+ }
115
+ function scroll() {
116
+ if (!url.hash) {
117
+ log.debug(`Scrolling to top ${scrollTop}px with behavior: ${scrollBehavior}`);
118
+ scrollToTop(scrollBehavior, scrollTop);
119
+ }
120
+ else {
121
+ log.debug(`Scrolling to anchor ${url.hash} with behavior: ${scrollBehavior}`);
122
+ scrollToAnchor(url.hash, scrollBehavior);
123
+ }
124
+ }
125
+ scroll();
126
+ // eslint-disable-next-line react-hooks/exhaustive-deps
127
+ }, [router, route, url]);
128
+ return null;
129
+ });
130
+
131
+ exports.ScrollRestoration = ScrollRestoration;
package/lib/index.d.ts CHANGED
@@ -1,6 +1,14 @@
1
1
  import { Autoscroll } from './components/Autoscroll';
2
+ import { ScrollRestoration } from './components/ScrollRestoration';
2
3
  export * from './tokens';
3
- export { Autoscroll };
4
- export declare class AutoscrollModule {
5
- }
4
+ export { Autoscroll, ScrollRestoration };
5
+ /**
6
+ * @deprecated use ScrollRestorationModule instead, which includes autoscroll and compatible with View Transitions
7
+ */
8
+ export declare const AutoscrollModule: import("@tinkoff/dippy/lib/modules/module.h").ModuleClass & Partial<import("@tinkoff/dippy/lib/modules/module.h").ModuleSecretParameters> & {
9
+ [x: string]: (...args: any[]) => import("@tramvai/core").ModuleType;
10
+ };
11
+ export declare const ScrollRestorationModule: import("@tinkoff/dippy/lib/modules/module.h").ModuleClass & Partial<import("@tinkoff/dippy/lib/modules/module.h").ModuleSecretParameters> & {
12
+ [x: string]: (...args: any[]) => import("@tramvai/core").ModuleType;
13
+ };
6
14
  //# sourceMappingURL=index.d.ts.map
package/lib/index.es.js CHANGED
@@ -1,67 +1,192 @@
1
- import { __decorate } from 'tslib';
2
- import { Module, provide, commandLineListTokens } from '@tramvai/core';
1
+ import noop from '@tinkoff/utils/function/noop';
2
+ import { createToken, declareModule, provide, optional, commandLineListTokens } from '@tramvai/core';
3
3
  import { LAYOUT_OPTIONS } from '@tramvai/tokens-render';
4
4
  import { ROUTER_TOKEN } from '@tramvai/module-router';
5
5
  import { LOGGER_TOKEN } from '@tramvai/tokens-common';
6
6
  import { Autoscroll } from './components/Autoscroll.es.js';
7
7
  export { Autoscroll } from './components/Autoscroll.es.js';
8
- export { AUTOSCROLL_BEHAVIOR_MODE_TOKEN, AUTOSCROLL_SCROLL_TOP_TOKEN } from './tokens.es.js';
8
+ import { ScrollRestoration } from './components/ScrollRestoration.es.js';
9
+ export { ScrollRestoration } from './components/ScrollRestoration.es.js';
10
+ import { AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN } from './tokens.es.js';
11
+ export { AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN, AUTOSCROLL_BEHAVIOR_MODE_TOKEN, AUTOSCROLL_DISABLED_TOKEN, AUTOSCROLL_SCROLL_TOP_TOKEN } from './tokens.es.js';
9
12
 
10
- let AutoscrollModule = class AutoscrollModule {
11
- };
12
- AutoscrollModule = __decorate([
13
- Module({
14
- providers: [
15
- provide({
16
- provide: LAYOUT_OPTIONS,
17
- useValue: {
13
+ const APPLIED_NAVIGATIONS_KEY = '_t_autoscroll_applied_navigations';
14
+ const NEW_SCROLL_RESTORATION_IS_USED = createToken('tramvai autoscroll new scroll restoration');
15
+ /**
16
+ * @deprecated use ScrollRestorationModule instead, which includes autoscroll and compatible with View Transitions
17
+ */
18
+ const AutoscrollModule = declareModule({
19
+ name: 'AutoscrollModule',
20
+ providers: [
21
+ provide({
22
+ provide: LAYOUT_OPTIONS,
23
+ useFactory: ({ newScrollRestoration }) => newScrollRestoration
24
+ ? {}
25
+ : {
18
26
  components: {
19
27
  autoscroll: Autoscroll,
20
28
  },
21
29
  },
22
- multi: true,
23
- }),
24
- ...(typeof window !== 'undefined'
25
- ? [
26
- provide({
27
- provide: commandLineListTokens.customerStart,
28
- useFactory: ({ logger, router }) => {
29
- const log = logger('autoscroll');
30
- // disable browser scroll restoration, to avoid conflicts with autoscroll
31
- const disableBrowserScrollRestoration = () => {
32
- log.debug('Disabling browser scroll restoration, autoscroll will be applied for this history entry');
33
- window.history.scrollRestoration = 'manual';
34
- };
35
- // enable browser scroll restoration, if autoscroll was disabled
36
- const enableBrowserScrollRestoration = () => {
37
- log.debug('Enable browser scroll restoration, autoscroll was disabled for this history entry');
38
- window.history.scrollRestoration = 'auto';
39
- };
40
- return () => {
41
- // for initial page load
42
- if (!window.history.state?.navigateState?.disableAutoscroll) {
30
+ multi: true,
31
+ deps: {
32
+ newScrollRestoration: optional(NEW_SCROLL_RESTORATION_IS_USED),
33
+ },
34
+ }),
35
+ ...(typeof window !== 'undefined'
36
+ ? [
37
+ provide({
38
+ provide: commandLineListTokens.customerStart,
39
+ useFactory: ({ logger, router, newScrollRestoration }) => {
40
+ const log = logger('autoscroll');
41
+ if (newScrollRestoration) {
42
+ return noop;
43
+ }
44
+ // disable browser scroll restoration, to avoid conflicts with autoscroll
45
+ const disableBrowserScrollRestoration = () => {
46
+ log.debug('Disabling browser scroll restoration, autoscroll will be applied for this history entry');
47
+ window.history.scrollRestoration = 'manual';
48
+ };
49
+ // enable browser scroll restoration, if autoscroll was disabled
50
+ const enableBrowserScrollRestoration = () => {
51
+ log.debug('Enable browser scroll restoration, autoscroll was disabled for this history entry');
52
+ window.history.scrollRestoration = 'auto';
53
+ };
54
+ return () => {
55
+ // for initial page load
56
+ if (!window.history.state?.navigateState?.disableAutoscroll) {
57
+ disableBrowserScrollRestoration();
58
+ }
59
+ // for sequent navigations
60
+ router.registerSyncHook('change', async (navigation) => {
61
+ if (!navigation.navigateState?.disableAutoscroll) {
43
62
  disableBrowserScrollRestoration();
44
63
  }
45
- // for sequent navigations
46
- router.registerSyncHook('change', async (navigation) => {
47
- if (!navigation.navigateState?.disableAutoscroll) {
48
- disableBrowserScrollRestoration();
49
- }
50
- else {
51
- enableBrowserScrollRestoration();
64
+ else {
65
+ enableBrowserScrollRestoration();
66
+ }
67
+ });
68
+ };
69
+ },
70
+ deps: {
71
+ logger: LOGGER_TOKEN,
72
+ router: ROUTER_TOKEN,
73
+ newScrollRestoration: optional(NEW_SCROLL_RESTORATION_IS_USED),
74
+ },
75
+ }),
76
+ ]
77
+ : []),
78
+ ],
79
+ });
80
+ const ScrollRestorationModule = declareModule({
81
+ name: 'ScrollRestorationModule',
82
+ providers: [
83
+ provide({
84
+ provide: NEW_SCROLL_RESTORATION_IS_USED,
85
+ useValue: true,
86
+ }),
87
+ provide({
88
+ provide: LAYOUT_OPTIONS,
89
+ useValue: {
90
+ components: {
91
+ autoscroll: ScrollRestoration,
92
+ },
93
+ },
94
+ multi: true,
95
+ }),
96
+ provide({
97
+ provide: AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN,
98
+ useFactory: () => new Map(),
99
+ }),
100
+ ...(typeof window !== 'undefined'
101
+ ? [
102
+ provide({
103
+ provide: commandLineListTokens.customerStart,
104
+ useFactory: ({ logger, router, appliedNavigations }) => {
105
+ const log = logger('autoscroll');
106
+ return () => {
107
+ try {
108
+ log.debug('Restoring applied navigations from sessionStorage');
109
+ const valueFromStorage = sessionStorage.getItem(APPLIED_NAVIGATIONS_KEY);
110
+ if (valueFromStorage !== null) {
111
+ const parsedValue = JSON.parse(valueFromStorage);
112
+ Object.entries(parsedValue).forEach(([key, value]) => {
113
+ appliedNavigations.set(Number.parseInt(key, 10), value);
114
+ });
115
+ }
116
+ else {
117
+ log.debug('No applied navigations found in sessionStorage');
118
+ }
119
+ }
120
+ catch (error) { }
121
+ window.addEventListener('pagehide', () => {
122
+ // to correct scroll restoration for current page in case of reload,
123
+ // both enable automatic scroll restoration and save scroll position
124
+ window.history.scrollRestoration = 'auto';
125
+ const state = router.history.getCurrentState();
126
+ appliedNavigations.set(state.index, {
127
+ href: router.getCurrentUrl()?.href || window.location.href,
128
+ scrollTop: window.scrollY,
129
+ });
130
+ try {
131
+ log.debug('Saving applied navigations to sessionStorage');
132
+ const valueToSave = {};
133
+ for (const [key, value] of appliedNavigations) {
134
+ valueToSave[key] = value;
52
135
  }
136
+ sessionStorage.setItem(APPLIED_NAVIGATIONS_KEY, JSON.stringify(valueToSave));
137
+ }
138
+ catch (error) { }
139
+ });
140
+ // case for browser back/forward buttons and router.go/back/forward navigations,
141
+ // here `history.getCurrentState()` and `router.getCurrentUrl()` will return leaving page values,
142
+ // so we can save scroll position for correct page index
143
+ window.addEventListener('popstate', (event) => {
144
+ const state = router.history.getCurrentState();
145
+ appliedNavigations.set(state.index, {
146
+ href: router.getCurrentUrl()?.href || window.location.href,
147
+ scrollTop: window.scrollY,
53
148
  });
54
- };
55
- },
56
- deps: {
57
- logger: LOGGER_TOKEN,
58
- router: ROUTER_TOKEN,
59
- },
60
- }),
61
- ]
62
- : []),
63
- ],
64
- })
65
- ], AutoscrollModule);
149
+ log.debug(`Save scroll position on history change, index: ${state.index}, scrollTop: ${window.scrollY}, url: ${router.getCurrentUrl()?.href || window.location.href}`);
150
+ });
151
+ // case for router.navigate navigation
152
+ router.registerHook('beforeNavigate', async (navigation) => {
153
+ if (!navigation.history) {
154
+ const state = router.history.getCurrentState();
155
+ appliedNavigations.set(state.index, {
156
+ href: navigation.fromUrl?.href || window.location.href,
157
+ scrollTop: window.scrollY,
158
+ });
159
+ log.debug(`Save scroll position on router.navigate, index: ${state.index}, scrollTop: ${window.scrollY}, url: ${navigation.fromUrl?.href || window.location.href}`);
160
+ // browser invalidates forward history on pushState, prune stale entries
161
+ for (const key of appliedNavigations.keys()) {
162
+ if (key > state.index) {
163
+ appliedNavigations.delete(key);
164
+ }
165
+ }
166
+ }
167
+ });
168
+ // case for router.updateCurrentRoute navigation
169
+ router.registerHook('beforeUpdateCurrent', async (navigation) => {
170
+ if (!navigation.history) {
171
+ const state = router.history.getCurrentState();
172
+ appliedNavigations.set(state.index, {
173
+ href: navigation.fromUrl?.href || window.location.href,
174
+ scrollTop: window.scrollY,
175
+ });
176
+ log.debug(`Save scroll position on router.updateCurrentRoute, index: ${state.index}, scrollTop: ${window.scrollY}, url: ${navigation.fromUrl?.href || window.location.href}`);
177
+ }
178
+ });
179
+ };
180
+ },
181
+ deps: {
182
+ logger: LOGGER_TOKEN,
183
+ router: ROUTER_TOKEN,
184
+ appliedNavigations: AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN,
185
+ },
186
+ }),
187
+ ]
188
+ : []),
189
+ ],
190
+ });
66
191
 
67
- export { AutoscrollModule };
192
+ export { AutoscrollModule, ScrollRestorationModule };
package/lib/index.js CHANGED
@@ -2,71 +2,203 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var tslib = require('tslib');
5
+ var noop = require('@tinkoff/utils/function/noop');
6
6
  var core = require('@tramvai/core');
7
7
  var tokensRender = require('@tramvai/tokens-render');
8
8
  var moduleRouter = require('@tramvai/module-router');
9
9
  var tokensCommon = require('@tramvai/tokens-common');
10
10
  var Autoscroll = require('./components/Autoscroll.js');
11
+ var ScrollRestoration = require('./components/ScrollRestoration.js');
11
12
  var tokens = require('./tokens.js');
12
13
 
13
- exports.AutoscrollModule = class AutoscrollModule {
14
- };
15
- exports.AutoscrollModule = tslib.__decorate([
16
- core.Module({
17
- providers: [
18
- core.provide({
19
- provide: tokensRender.LAYOUT_OPTIONS,
20
- useValue: {
14
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
15
+
16
+ var noop__default = /*#__PURE__*/_interopDefaultLegacy(noop);
17
+
18
+ const APPLIED_NAVIGATIONS_KEY = '_t_autoscroll_applied_navigations';
19
+ const NEW_SCROLL_RESTORATION_IS_USED = core.createToken('tramvai autoscroll new scroll restoration');
20
+ /**
21
+ * @deprecated use ScrollRestorationModule instead, which includes autoscroll and compatible with View Transitions
22
+ */
23
+ const AutoscrollModule = core.declareModule({
24
+ name: 'AutoscrollModule',
25
+ providers: [
26
+ core.provide({
27
+ provide: tokensRender.LAYOUT_OPTIONS,
28
+ useFactory: ({ newScrollRestoration }) => newScrollRestoration
29
+ ? {}
30
+ : {
21
31
  components: {
22
32
  autoscroll: Autoscroll.Autoscroll,
23
33
  },
24
34
  },
25
- multi: true,
26
- }),
27
- ...(typeof window !== 'undefined'
28
- ? [
29
- core.provide({
30
- provide: core.commandLineListTokens.customerStart,
31
- useFactory: ({ logger, router }) => {
32
- const log = logger('autoscroll');
33
- // disable browser scroll restoration, to avoid conflicts with autoscroll
34
- const disableBrowserScrollRestoration = () => {
35
- log.debug('Disabling browser scroll restoration, autoscroll will be applied for this history entry');
36
- window.history.scrollRestoration = 'manual';
37
- };
38
- // enable browser scroll restoration, if autoscroll was disabled
39
- const enableBrowserScrollRestoration = () => {
40
- log.debug('Enable browser scroll restoration, autoscroll was disabled for this history entry');
41
- window.history.scrollRestoration = 'auto';
42
- };
43
- return () => {
44
- // for initial page load
45
- if (!window.history.state?.navigateState?.disableAutoscroll) {
35
+ multi: true,
36
+ deps: {
37
+ newScrollRestoration: core.optional(NEW_SCROLL_RESTORATION_IS_USED),
38
+ },
39
+ }),
40
+ ...(typeof window !== 'undefined'
41
+ ? [
42
+ core.provide({
43
+ provide: core.commandLineListTokens.customerStart,
44
+ useFactory: ({ logger, router, newScrollRestoration }) => {
45
+ const log = logger('autoscroll');
46
+ if (newScrollRestoration) {
47
+ return noop__default["default"];
48
+ }
49
+ // disable browser scroll restoration, to avoid conflicts with autoscroll
50
+ const disableBrowserScrollRestoration = () => {
51
+ log.debug('Disabling browser scroll restoration, autoscroll will be applied for this history entry');
52
+ window.history.scrollRestoration = 'manual';
53
+ };
54
+ // enable browser scroll restoration, if autoscroll was disabled
55
+ const enableBrowserScrollRestoration = () => {
56
+ log.debug('Enable browser scroll restoration, autoscroll was disabled for this history entry');
57
+ window.history.scrollRestoration = 'auto';
58
+ };
59
+ return () => {
60
+ // for initial page load
61
+ if (!window.history.state?.navigateState?.disableAutoscroll) {
62
+ disableBrowserScrollRestoration();
63
+ }
64
+ // for sequent navigations
65
+ router.registerSyncHook('change', async (navigation) => {
66
+ if (!navigation.navigateState?.disableAutoscroll) {
46
67
  disableBrowserScrollRestoration();
47
68
  }
48
- // for sequent navigations
49
- router.registerSyncHook('change', async (navigation) => {
50
- if (!navigation.navigateState?.disableAutoscroll) {
51
- disableBrowserScrollRestoration();
52
- }
53
- else {
54
- enableBrowserScrollRestoration();
69
+ else {
70
+ enableBrowserScrollRestoration();
71
+ }
72
+ });
73
+ };
74
+ },
75
+ deps: {
76
+ logger: tokensCommon.LOGGER_TOKEN,
77
+ router: moduleRouter.ROUTER_TOKEN,
78
+ newScrollRestoration: core.optional(NEW_SCROLL_RESTORATION_IS_USED),
79
+ },
80
+ }),
81
+ ]
82
+ : []),
83
+ ],
84
+ });
85
+ const ScrollRestorationModule = core.declareModule({
86
+ name: 'ScrollRestorationModule',
87
+ providers: [
88
+ core.provide({
89
+ provide: NEW_SCROLL_RESTORATION_IS_USED,
90
+ useValue: true,
91
+ }),
92
+ core.provide({
93
+ provide: tokensRender.LAYOUT_OPTIONS,
94
+ useValue: {
95
+ components: {
96
+ autoscroll: ScrollRestoration.ScrollRestoration,
97
+ },
98
+ },
99
+ multi: true,
100
+ }),
101
+ core.provide({
102
+ provide: tokens.AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN,
103
+ useFactory: () => new Map(),
104
+ }),
105
+ ...(typeof window !== 'undefined'
106
+ ? [
107
+ core.provide({
108
+ provide: core.commandLineListTokens.customerStart,
109
+ useFactory: ({ logger, router, appliedNavigations }) => {
110
+ const log = logger('autoscroll');
111
+ return () => {
112
+ try {
113
+ log.debug('Restoring applied navigations from sessionStorage');
114
+ const valueFromStorage = sessionStorage.getItem(APPLIED_NAVIGATIONS_KEY);
115
+ if (valueFromStorage !== null) {
116
+ const parsedValue = JSON.parse(valueFromStorage);
117
+ Object.entries(parsedValue).forEach(([key, value]) => {
118
+ appliedNavigations.set(Number.parseInt(key, 10), value);
119
+ });
120
+ }
121
+ else {
122
+ log.debug('No applied navigations found in sessionStorage');
123
+ }
124
+ }
125
+ catch (error) { }
126
+ window.addEventListener('pagehide', () => {
127
+ // to correct scroll restoration for current page in case of reload,
128
+ // both enable automatic scroll restoration and save scroll position
129
+ window.history.scrollRestoration = 'auto';
130
+ const state = router.history.getCurrentState();
131
+ appliedNavigations.set(state.index, {
132
+ href: router.getCurrentUrl()?.href || window.location.href,
133
+ scrollTop: window.scrollY,
134
+ });
135
+ try {
136
+ log.debug('Saving applied navigations to sessionStorage');
137
+ const valueToSave = {};
138
+ for (const [key, value] of appliedNavigations) {
139
+ valueToSave[key] = value;
55
140
  }
141
+ sessionStorage.setItem(APPLIED_NAVIGATIONS_KEY, JSON.stringify(valueToSave));
142
+ }
143
+ catch (error) { }
144
+ });
145
+ // case for browser back/forward buttons and router.go/back/forward navigations,
146
+ // here `history.getCurrentState()` and `router.getCurrentUrl()` will return leaving page values,
147
+ // so we can save scroll position for correct page index
148
+ window.addEventListener('popstate', (event) => {
149
+ const state = router.history.getCurrentState();
150
+ appliedNavigations.set(state.index, {
151
+ href: router.getCurrentUrl()?.href || window.location.href,
152
+ scrollTop: window.scrollY,
56
153
  });
57
- };
58
- },
59
- deps: {
60
- logger: tokensCommon.LOGGER_TOKEN,
61
- router: moduleRouter.ROUTER_TOKEN,
62
- },
63
- }),
64
- ]
65
- : []),
66
- ],
67
- })
68
- ], exports.AutoscrollModule);
154
+ log.debug(`Save scroll position on history change, index: ${state.index}, scrollTop: ${window.scrollY}, url: ${router.getCurrentUrl()?.href || window.location.href}`);
155
+ });
156
+ // case for router.navigate navigation
157
+ router.registerHook('beforeNavigate', async (navigation) => {
158
+ if (!navigation.history) {
159
+ const state = router.history.getCurrentState();
160
+ appliedNavigations.set(state.index, {
161
+ href: navigation.fromUrl?.href || window.location.href,
162
+ scrollTop: window.scrollY,
163
+ });
164
+ log.debug(`Save scroll position on router.navigate, index: ${state.index}, scrollTop: ${window.scrollY}, url: ${navigation.fromUrl?.href || window.location.href}`);
165
+ // browser invalidates forward history on pushState, prune stale entries
166
+ for (const key of appliedNavigations.keys()) {
167
+ if (key > state.index) {
168
+ appliedNavigations.delete(key);
169
+ }
170
+ }
171
+ }
172
+ });
173
+ // case for router.updateCurrentRoute navigation
174
+ router.registerHook('beforeUpdateCurrent', async (navigation) => {
175
+ if (!navigation.history) {
176
+ const state = router.history.getCurrentState();
177
+ appliedNavigations.set(state.index, {
178
+ href: navigation.fromUrl?.href || window.location.href,
179
+ scrollTop: window.scrollY,
180
+ });
181
+ log.debug(`Save scroll position on router.updateCurrentRoute, index: ${state.index}, scrollTop: ${window.scrollY}, url: ${navigation.fromUrl?.href || window.location.href}`);
182
+ }
183
+ });
184
+ };
185
+ },
186
+ deps: {
187
+ logger: tokensCommon.LOGGER_TOKEN,
188
+ router: moduleRouter.ROUTER_TOKEN,
189
+ appliedNavigations: tokens.AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN,
190
+ },
191
+ }),
192
+ ]
193
+ : []),
194
+ ],
195
+ });
69
196
 
70
197
  exports.Autoscroll = Autoscroll.Autoscroll;
198
+ exports.ScrollRestoration = ScrollRestoration.ScrollRestoration;
199
+ exports.AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN = tokens.AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN;
71
200
  exports.AUTOSCROLL_BEHAVIOR_MODE_TOKEN = tokens.AUTOSCROLL_BEHAVIOR_MODE_TOKEN;
201
+ exports.AUTOSCROLL_DISABLED_TOKEN = tokens.AUTOSCROLL_DISABLED_TOKEN;
72
202
  exports.AUTOSCROLL_SCROLL_TOP_TOKEN = tokens.AUTOSCROLL_SCROLL_TOP_TOKEN;
203
+ exports.AutoscrollModule = AutoscrollModule;
204
+ exports.ScrollRestorationModule = ScrollRestorationModule;
package/lib/tokens.d.ts CHANGED
@@ -1,14 +1,25 @@
1
- export type AutoscrollBehavior = 'smooth' | 'auto';
1
+ export type AutoscrollBehavior = 'smooth' | 'instant' | 'auto';
2
2
  export declare const AUTOSCROLL_BEHAVIOR_MODE_TOKEN: ("smooth" & {
3
3
  __type?: "base token" | undefined;
4
+ }) | ("instant" & {
5
+ __type?: "base token" | undefined;
4
6
  }) | ("auto" & {
5
7
  __type?: "base token" | undefined;
6
- }) | ((() => AutoscrollBehavior) & {
8
+ }) | (((defaultBehavior: AutoscrollBehavior) => AutoscrollBehavior) & {
7
9
  __type?: "base token" | undefined;
8
10
  });
9
11
  export declare const AUTOSCROLL_SCROLL_TOP_TOKEN: (number & {
10
12
  __type?: "base token" | undefined;
11
- }) | ((() => number) & {
13
+ }) | (((defaultScrollTop: number, isRestoredValue: boolean) => number) & {
12
14
  __type?: "base token" | undefined;
13
15
  });
16
+ export declare const AUTOSCROLL_DISABLED_TOKEN: (() => boolean | undefined) & {
17
+ __type?: "base token" | undefined;
18
+ };
19
+ export declare const AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN: Map<number, {
20
+ href: string;
21
+ scrollTop: number;
22
+ }> & {
23
+ __type?: "base token" | undefined;
24
+ };
14
25
  //# sourceMappingURL=tokens.d.ts.map
package/lib/tokens.es.js CHANGED
@@ -2,5 +2,7 @@ import { createToken } from '@tinkoff/dippy';
2
2
 
3
3
  const AUTOSCROLL_BEHAVIOR_MODE_TOKEN = createToken('autoscroll behavior');
4
4
  const AUTOSCROLL_SCROLL_TOP_TOKEN = createToken('autoscroll scroll top');
5
+ const AUTOSCROLL_DISABLED_TOKEN = createToken('autoscroll disabled');
6
+ const AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN = createToken('autoscroll applied navigations');
5
7
 
6
- export { AUTOSCROLL_BEHAVIOR_MODE_TOKEN, AUTOSCROLL_SCROLL_TOP_TOKEN };
8
+ export { AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN, AUTOSCROLL_BEHAVIOR_MODE_TOKEN, AUTOSCROLL_DISABLED_TOKEN, AUTOSCROLL_SCROLL_TOP_TOKEN };
package/lib/tokens.js CHANGED
@@ -6,6 +6,10 @@ var dippy = require('@tinkoff/dippy');
6
6
 
7
7
  const AUTOSCROLL_BEHAVIOR_MODE_TOKEN = dippy.createToken('autoscroll behavior');
8
8
  const AUTOSCROLL_SCROLL_TOP_TOKEN = dippy.createToken('autoscroll scroll top');
9
+ const AUTOSCROLL_DISABLED_TOKEN = dippy.createToken('autoscroll disabled');
10
+ const AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN = dippy.createToken('autoscroll applied navigations');
9
11
 
12
+ exports.AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN = AUTOSCROLL_APPPLIED_NAVIGATIONS_TOKEN;
10
13
  exports.AUTOSCROLL_BEHAVIOR_MODE_TOKEN = AUTOSCROLL_BEHAVIOR_MODE_TOKEN;
14
+ exports.AUTOSCROLL_DISABLED_TOKEN = AUTOSCROLL_DISABLED_TOKEN;
11
15
  exports.AUTOSCROLL_SCROLL_TOP_TOKEN = AUTOSCROLL_SCROLL_TOP_TOKEN;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tramvai/module-autoscroll",
3
- "version": "6.80.26",
3
+ "version": "6.81.11",
4
4
  "description": "Компонент с автопрокруткой к началу страницы",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -17,16 +17,17 @@
17
17
  "watch": "tsc -w"
18
18
  },
19
19
  "dependencies": {
20
+ "@tinkoff/utils": "^2.1.3",
20
21
  "tslib": "^2.4.0"
21
22
  },
22
23
  "peerDependencies": {
23
24
  "@tinkoff/dippy": "^1.0.0",
24
25
  "@tinkoff/react-hooks": "0.5.4",
25
- "@tramvai/core": "6.80.26",
26
- "@tramvai/module-router": "6.80.26",
27
- "@tramvai/react": "6.80.26",
28
- "@tramvai/tokens-common": "6.80.26",
29
- "@tramvai/tokens-render": "6.80.26",
26
+ "@tramvai/core": "6.81.11",
27
+ "@tramvai/module-router": "6.81.11",
28
+ "@tramvai/react": "6.81.11",
29
+ "@tramvai/tokens-common": "6.81.11",
30
+ "@tramvai/tokens-render": "6.81.11",
30
31
  "react": ">=16.14.0"
31
32
  },
32
33
  "module": "lib/index.es.js",