@yoamigo.com/core 0.3.7 → 0.3.8

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/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1, { ReactNode, CSSProperties } from 'react';
3
3
  export { C as ContentStoreProviderProd, g as EmbedFieldValue, h as EmbedType, d as MarkdownText, e as MarkdownTextProps, P as PageInfo, b as StaticImage, c as StaticImageProps, M as StaticText, S as StaticTextProps, Y as YaEmbed, f as YaEmbedProps, i as YaLink, j as YaLinkProps, p as parseEmbedUrl, s as serializeEmbedValue, u as useContentStoreProd } from './MarkdownText-DHJo0ofY.js';
4
- export { Link, LinkProps, NavigateFunction, Router, RouterProps, useNavigate } from './router.js';
4
+ export { Link, LinkProps, NavigateFunction, Router, RouterProps, ScrollRestoration, useNavigate } from './router.js';
5
5
  export { Route, Switch, useParams } from 'wouter';
6
6
  export { A as AssetResolverFn, C as ContentRegistry, c as contentRegistry, a as getAllContent, g as getContent, h as hasContent, r as registerContent, b as resolveAssetUrl, s as setAssetResolver } from './asset-resolver-BnIvDkVv.js';
7
7
  export { i as initBuilderSelection } from './builder-selection-CYP91nRu.js';
package/dist/index.js CHANGED
@@ -5909,6 +5909,102 @@ function Router({ children, base }) {
5909
5909
  return /* @__PURE__ */ jsx21(WouterRouter, { base: basename, children });
5910
5910
  }
5911
5911
 
5912
+ // src/router/ScrollRestoration.tsx
5913
+ import { useEffect as useEffect15, useRef as useRef15 } from "react";
5914
+ import { useLocation as useLocation3 } from "wouter";
5915
+ var SCROLL_POSITIONS_KEY = "yoamigo-scroll-positions";
5916
+ var HISTORY_INDEX_KEY = "yoamigo-history-index";
5917
+ function getScrollPositions() {
5918
+ if (typeof sessionStorage === "undefined") return {};
5919
+ try {
5920
+ const stored = sessionStorage.getItem(SCROLL_POSITIONS_KEY);
5921
+ return stored ? JSON.parse(stored) : {};
5922
+ } catch {
5923
+ return {};
5924
+ }
5925
+ }
5926
+ function saveScrollPositions(positions) {
5927
+ if (typeof sessionStorage === "undefined") return;
5928
+ try {
5929
+ sessionStorage.setItem(SCROLL_POSITIONS_KEY, JSON.stringify(positions));
5930
+ } catch {
5931
+ }
5932
+ }
5933
+ function getHistoryIndex() {
5934
+ if (typeof history === "undefined") return 0;
5935
+ const state = history.state;
5936
+ if (state && typeof state[HISTORY_INDEX_KEY] === "number") {
5937
+ return state[HISTORY_INDEX_KEY];
5938
+ }
5939
+ return 0;
5940
+ }
5941
+ function setHistoryIndex(index) {
5942
+ if (typeof history === "undefined") return;
5943
+ const newState = { ...history.state, [HISTORY_INDEX_KEY]: index };
5944
+ history.replaceState(newState, "");
5945
+ }
5946
+ var globalHistoryIndex = 0;
5947
+ function ScrollRestoration() {
5948
+ const [location] = useLocation3();
5949
+ const previousLocation = useRef15(location);
5950
+ const isPopState = useRef15(false);
5951
+ const scrollPositionsRef = useRef15({});
5952
+ useEffect15(() => {
5953
+ if (typeof history !== "undefined" && "scrollRestoration" in history) {
5954
+ history.scrollRestoration = "manual";
5955
+ }
5956
+ scrollPositionsRef.current = getScrollPositions();
5957
+ const existingIndex = getHistoryIndex();
5958
+ if (existingIndex === 0 && !history.state?.[HISTORY_INDEX_KEY]) {
5959
+ globalHistoryIndex = 1;
5960
+ setHistoryIndex(globalHistoryIndex);
5961
+ } else {
5962
+ globalHistoryIndex = existingIndex;
5963
+ }
5964
+ const handlePopState = () => {
5965
+ isPopState.current = true;
5966
+ };
5967
+ window.addEventListener("popstate", handlePopState);
5968
+ return () => window.removeEventListener("popstate", handlePopState);
5969
+ }, []);
5970
+ useEffect15(() => {
5971
+ if (previousLocation.current === location) return;
5972
+ const prevHistoryIndex = globalHistoryIndex;
5973
+ const currentScrollY = window.scrollY;
5974
+ if (isPopState.current) {
5975
+ isPopState.current = false;
5976
+ globalHistoryIndex = getHistoryIndex() || globalHistoryIndex;
5977
+ const savedScroll = scrollPositionsRef.current[`${globalHistoryIndex}-${location}`];
5978
+ requestAnimationFrame(() => {
5979
+ window.scrollTo({ top: savedScroll ?? 0, behavior: "instant" });
5980
+ });
5981
+ } else {
5982
+ scrollPositionsRef.current[`${prevHistoryIndex}-${previousLocation.current}`] = currentScrollY;
5983
+ saveScrollPositions(scrollPositionsRef.current);
5984
+ globalHistoryIndex = prevHistoryIndex + 1;
5985
+ setHistoryIndex(globalHistoryIndex);
5986
+ window.scrollTo({ top: 0, behavior: "instant" });
5987
+ }
5988
+ previousLocation.current = location;
5989
+ }, [location]);
5990
+ useEffect15(() => {
5991
+ let timeoutId;
5992
+ const handleScroll = () => {
5993
+ clearTimeout(timeoutId);
5994
+ timeoutId = setTimeout(() => {
5995
+ scrollPositionsRef.current[`${globalHistoryIndex}-${location}`] = window.scrollY;
5996
+ saveScrollPositions(scrollPositionsRef.current);
5997
+ }, 100);
5998
+ };
5999
+ window.addEventListener("scroll", handleScroll, { passive: true });
6000
+ return () => {
6001
+ clearTimeout(timeoutId);
6002
+ window.removeEventListener("scroll", handleScroll);
6003
+ };
6004
+ }, [location]);
6005
+ return null;
6006
+ }
6007
+
5912
6008
  // src/router/index.ts
5913
6009
  import { Route, Switch, useParams } from "wouter";
5914
6010
  export {
@@ -5921,6 +6017,7 @@ export {
5921
6017
  Router,
5922
6018
  SafeHtml,
5923
6019
  SafeTriangleBelow,
6020
+ ScrollRestoration,
5924
6021
  MpImage as StaticImage,
5925
6022
  MpText as StaticText,
5926
6023
  Switch,
package/dist/prod.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { a as ContentStore, E as ContentStoreMode, C as ContentStoreProvider, d as MarkdownText, e as MarkdownTextProps, P as PageInfo, b as StaticImage, c as StaticImageProps, M as StaticText, S as StaticTextProps, b as YaImage, c as YaImageProps, M as YaText, S as YaTextProps, p as parseEmbedUrl, u as useContentStore } from './MarkdownText-DHJo0ofY.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import React, { CSSProperties, ReactNode } from 'react';
4
- export { Link, LinkProps, NavigateFunction, Router, RouterProps, useNavigate } from './router.js';
4
+ export { Link, LinkProps, NavigateFunction, Router, RouterProps, ScrollRestoration, useNavigate } from './router.js';
5
5
  export { Route, Switch, useParams } from 'wouter';
6
6
  export { A as AssetResolverFn, C as ContentRegistry, c as contentRegistry, a as getAllContent, g as getContent, h as hasContent, r as registerContent, b as resolveAssetUrl, s as setAssetResolver } from './asset-resolver-BnIvDkVv.js';
7
7
 
package/dist/prod.js CHANGED
@@ -953,6 +953,102 @@ function Router({ children, base }) {
953
953
  return /* @__PURE__ */ jsx12(WouterRouter, { base: basename, children });
954
954
  }
955
955
 
956
+ // src/router/ScrollRestoration.tsx
957
+ import { useEffect as useEffect4, useRef as useRef4 } from "react";
958
+ import { useLocation as useLocation3 } from "wouter";
959
+ var SCROLL_POSITIONS_KEY = "yoamigo-scroll-positions";
960
+ var HISTORY_INDEX_KEY = "yoamigo-history-index";
961
+ function getScrollPositions() {
962
+ if (typeof sessionStorage === "undefined") return {};
963
+ try {
964
+ const stored = sessionStorage.getItem(SCROLL_POSITIONS_KEY);
965
+ return stored ? JSON.parse(stored) : {};
966
+ } catch {
967
+ return {};
968
+ }
969
+ }
970
+ function saveScrollPositions(positions) {
971
+ if (typeof sessionStorage === "undefined") return;
972
+ try {
973
+ sessionStorage.setItem(SCROLL_POSITIONS_KEY, JSON.stringify(positions));
974
+ } catch {
975
+ }
976
+ }
977
+ function getHistoryIndex() {
978
+ if (typeof history === "undefined") return 0;
979
+ const state = history.state;
980
+ if (state && typeof state[HISTORY_INDEX_KEY] === "number") {
981
+ return state[HISTORY_INDEX_KEY];
982
+ }
983
+ return 0;
984
+ }
985
+ function setHistoryIndex(index) {
986
+ if (typeof history === "undefined") return;
987
+ const newState = { ...history.state, [HISTORY_INDEX_KEY]: index };
988
+ history.replaceState(newState, "");
989
+ }
990
+ var globalHistoryIndex = 0;
991
+ function ScrollRestoration() {
992
+ const [location] = useLocation3();
993
+ const previousLocation = useRef4(location);
994
+ const isPopState = useRef4(false);
995
+ const scrollPositionsRef = useRef4({});
996
+ useEffect4(() => {
997
+ if (typeof history !== "undefined" && "scrollRestoration" in history) {
998
+ history.scrollRestoration = "manual";
999
+ }
1000
+ scrollPositionsRef.current = getScrollPositions();
1001
+ const existingIndex = getHistoryIndex();
1002
+ if (existingIndex === 0 && !history.state?.[HISTORY_INDEX_KEY]) {
1003
+ globalHistoryIndex = 1;
1004
+ setHistoryIndex(globalHistoryIndex);
1005
+ } else {
1006
+ globalHistoryIndex = existingIndex;
1007
+ }
1008
+ const handlePopState = () => {
1009
+ isPopState.current = true;
1010
+ };
1011
+ window.addEventListener("popstate", handlePopState);
1012
+ return () => window.removeEventListener("popstate", handlePopState);
1013
+ }, []);
1014
+ useEffect4(() => {
1015
+ if (previousLocation.current === location) return;
1016
+ const prevHistoryIndex = globalHistoryIndex;
1017
+ const currentScrollY = window.scrollY;
1018
+ if (isPopState.current) {
1019
+ isPopState.current = false;
1020
+ globalHistoryIndex = getHistoryIndex() || globalHistoryIndex;
1021
+ const savedScroll = scrollPositionsRef.current[`${globalHistoryIndex}-${location}`];
1022
+ requestAnimationFrame(() => {
1023
+ window.scrollTo({ top: savedScroll ?? 0, behavior: "instant" });
1024
+ });
1025
+ } else {
1026
+ scrollPositionsRef.current[`${prevHistoryIndex}-${previousLocation.current}`] = currentScrollY;
1027
+ saveScrollPositions(scrollPositionsRef.current);
1028
+ globalHistoryIndex = prevHistoryIndex + 1;
1029
+ setHistoryIndex(globalHistoryIndex);
1030
+ window.scrollTo({ top: 0, behavior: "instant" });
1031
+ }
1032
+ previousLocation.current = location;
1033
+ }, [location]);
1034
+ useEffect4(() => {
1035
+ let timeoutId;
1036
+ const handleScroll = () => {
1037
+ clearTimeout(timeoutId);
1038
+ timeoutId = setTimeout(() => {
1039
+ scrollPositionsRef.current[`${globalHistoryIndex}-${location}`] = window.scrollY;
1040
+ saveScrollPositions(scrollPositionsRef.current);
1041
+ }, 100);
1042
+ };
1043
+ window.addEventListener("scroll", handleScroll, { passive: true });
1044
+ return () => {
1045
+ clearTimeout(timeoutId);
1046
+ window.removeEventListener("scroll", handleScroll);
1047
+ };
1048
+ }, [location]);
1049
+ return null;
1050
+ }
1051
+
956
1052
  // src/router/index.ts
957
1053
  import { Route, Switch, useParams } from "wouter";
958
1054
  export {
@@ -962,6 +1058,7 @@ export {
962
1058
  Route,
963
1059
  Router,
964
1060
  SafeHtml,
1061
+ ScrollRestoration,
965
1062
  StaticContainer,
966
1063
  StaticEmbed,
967
1064
  MpImage as StaticImage,
package/dist/router.d.ts CHANGED
@@ -44,4 +44,15 @@ interface RouterProps {
44
44
  }
45
45
  declare function Router({ children, base }: RouterProps): react_jsx_runtime.JSX.Element;
46
46
 
47
- export { Link, type LinkProps, type NavigateFunction, Router, type RouterProps$1 as RouterProps, useNavigate };
47
+ /**
48
+ * ScrollRestoration Component
49
+ *
50
+ * Handles scroll position management for SPA navigation:
51
+ * - Forward navigation (link clicks) → instantly at top (no scroll animation)
52
+ * - Back navigation (browser back) → restore previous scroll position
53
+ *
54
+ * Uses sessionStorage to persist scroll positions across page refreshes.
55
+ */
56
+ declare function ScrollRestoration(): null;
57
+
58
+ export { Link, type LinkProps, type NavigateFunction, Router, type RouterProps$1 as RouterProps, ScrollRestoration, useNavigate };
package/dist/router.js CHANGED
@@ -40,12 +40,109 @@ function Router({ children, base }) {
40
40
  return /* @__PURE__ */ jsx2(WouterRouter, { base: basename, children });
41
41
  }
42
42
 
43
+ // src/router/ScrollRestoration.tsx
44
+ import { useEffect, useRef } from "react";
45
+ import { useLocation as useLocation2 } from "wouter";
46
+ var SCROLL_POSITIONS_KEY = "yoamigo-scroll-positions";
47
+ var HISTORY_INDEX_KEY = "yoamigo-history-index";
48
+ function getScrollPositions() {
49
+ if (typeof sessionStorage === "undefined") return {};
50
+ try {
51
+ const stored = sessionStorage.getItem(SCROLL_POSITIONS_KEY);
52
+ return stored ? JSON.parse(stored) : {};
53
+ } catch {
54
+ return {};
55
+ }
56
+ }
57
+ function saveScrollPositions(positions) {
58
+ if (typeof sessionStorage === "undefined") return;
59
+ try {
60
+ sessionStorage.setItem(SCROLL_POSITIONS_KEY, JSON.stringify(positions));
61
+ } catch {
62
+ }
63
+ }
64
+ function getHistoryIndex() {
65
+ if (typeof history === "undefined") return 0;
66
+ const state = history.state;
67
+ if (state && typeof state[HISTORY_INDEX_KEY] === "number") {
68
+ return state[HISTORY_INDEX_KEY];
69
+ }
70
+ return 0;
71
+ }
72
+ function setHistoryIndex(index) {
73
+ if (typeof history === "undefined") return;
74
+ const newState = { ...history.state, [HISTORY_INDEX_KEY]: index };
75
+ history.replaceState(newState, "");
76
+ }
77
+ var globalHistoryIndex = 0;
78
+ function ScrollRestoration() {
79
+ const [location] = useLocation2();
80
+ const previousLocation = useRef(location);
81
+ const isPopState = useRef(false);
82
+ const scrollPositionsRef = useRef({});
83
+ useEffect(() => {
84
+ if (typeof history !== "undefined" && "scrollRestoration" in history) {
85
+ history.scrollRestoration = "manual";
86
+ }
87
+ scrollPositionsRef.current = getScrollPositions();
88
+ const existingIndex = getHistoryIndex();
89
+ if (existingIndex === 0 && !history.state?.[HISTORY_INDEX_KEY]) {
90
+ globalHistoryIndex = 1;
91
+ setHistoryIndex(globalHistoryIndex);
92
+ } else {
93
+ globalHistoryIndex = existingIndex;
94
+ }
95
+ const handlePopState = () => {
96
+ isPopState.current = true;
97
+ };
98
+ window.addEventListener("popstate", handlePopState);
99
+ return () => window.removeEventListener("popstate", handlePopState);
100
+ }, []);
101
+ useEffect(() => {
102
+ if (previousLocation.current === location) return;
103
+ const prevHistoryIndex = globalHistoryIndex;
104
+ const currentScrollY = window.scrollY;
105
+ if (isPopState.current) {
106
+ isPopState.current = false;
107
+ globalHistoryIndex = getHistoryIndex() || globalHistoryIndex;
108
+ const savedScroll = scrollPositionsRef.current[`${globalHistoryIndex}-${location}`];
109
+ requestAnimationFrame(() => {
110
+ window.scrollTo({ top: savedScroll ?? 0, behavior: "instant" });
111
+ });
112
+ } else {
113
+ scrollPositionsRef.current[`${prevHistoryIndex}-${previousLocation.current}`] = currentScrollY;
114
+ saveScrollPositions(scrollPositionsRef.current);
115
+ globalHistoryIndex = prevHistoryIndex + 1;
116
+ setHistoryIndex(globalHistoryIndex);
117
+ window.scrollTo({ top: 0, behavior: "instant" });
118
+ }
119
+ previousLocation.current = location;
120
+ }, [location]);
121
+ useEffect(() => {
122
+ let timeoutId;
123
+ const handleScroll = () => {
124
+ clearTimeout(timeoutId);
125
+ timeoutId = setTimeout(() => {
126
+ scrollPositionsRef.current[`${globalHistoryIndex}-${location}`] = window.scrollY;
127
+ saveScrollPositions(scrollPositionsRef.current);
128
+ }, 100);
129
+ };
130
+ window.addEventListener("scroll", handleScroll, { passive: true });
131
+ return () => {
132
+ clearTimeout(timeoutId);
133
+ window.removeEventListener("scroll", handleScroll);
134
+ };
135
+ }, [location]);
136
+ return null;
137
+ }
138
+
43
139
  // src/router/index.ts
44
140
  import { Route, Switch, useParams } from "wouter";
45
141
  export {
46
142
  Link,
47
143
  Route,
48
144
  Router,
145
+ ScrollRestoration,
49
146
  Switch,
50
147
  useNavigate,
51
148
  useParams
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yoamigo.com/core",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "Core components, router, and utilities for YoAmigo templates",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",