eddev 2.0.0-beta.27 → 2.0.0-beta.29

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.
@@ -3,7 +3,7 @@ import { Suspense } from "react";
3
3
  import { QueryClientProvider } from "@tanstack/react-query";
4
4
  import { getQueryClient } from "../utils/query-client.js";
5
5
  import { SSRRouter } from "../lib/routing/components/SSRRouter.js";
6
- import { normalizeRoute } from "../lib/routing/utils.js";
6
+ import { getRouteMeta, normalizeRoute } from "../lib/routing/utils.js";
7
7
  import { MetaTags } from "./MetaTags.js";
8
8
  export function SSRRoot(props) {
9
9
  const loader = props.loader;
@@ -19,6 +19,6 @@ export function SSRRoot(props) {
19
19
  pathname: props.pathname,
20
20
  query: {},
21
21
  hash: "",
22
- meta: {},
22
+ meta: getRouteMeta(props.initialData),
23
23
  }) }) }) }) })] }));
24
24
  }
@@ -0,0 +1,39 @@
1
+ import { ReactNode } from "react";
2
+ import { RouteState } from "../types";
3
+ type BackButtonProps = {
4
+ /**
5
+ * An optional matching function, which will stop the render button from appearing unless the function returns true.
6
+ *
7
+ * The below example will only render a back button if the last route was a project archive.
8
+ *
9
+ * eg. `filter={(route) => route.view === 'archive-projects'}`
10
+ *
11
+ * @param route The last route in the history stack.
12
+ */
13
+ filter?: (route: RouteState) => boolean;
14
+ /**
15
+ * An optional href, which will be used if no back route is found.
16
+ *
17
+ * When used, the back button will always render.
18
+ */
19
+ fallbackHref?: string;
20
+ /**
21
+ * A function to render the back button, if one should be rendered.
22
+ *
23
+ * Receives a `route` prop to further inspect the route, and an `onClick` function to navigate back.
24
+ *
25
+ * @param props
26
+ * @returns
27
+ */
28
+ render: (props: {
29
+ route: RouteState;
30
+ onClick: (e?: any) => void;
31
+ }) => ReactNode;
32
+ };
33
+ /**
34
+ * Display a back button that will navigate to the previous page in the router's history.
35
+ *
36
+ * This will allow you to render a back button on the condition that the back button will not send the user to a different website.
37
+ */
38
+ export declare function BackButton(props: BackButtonProps): ReactNode;
39
+ export {};
@@ -0,0 +1,45 @@
1
+ import { useMemo } from "react";
2
+ import { useRouter } from "../hooks/useRouter";
3
+ import { useRouterState } from "../hooks/useRouterState";
4
+ import { getLinkHandlerMode } from "../utils";
5
+ import { useRoute } from "../hooks/useRoute";
6
+ /**
7
+ * Display a back button that will navigate to the previous page in the router's history.
8
+ *
9
+ * This will allow you to render a back button on the condition that the back button will not send the user to a different website.
10
+ */
11
+ export function BackButton(props) {
12
+ const router = useRouter();
13
+ const route = useRoute();
14
+ const prevRoute = useRouterState((state) => state.history[state.history.length - 2]);
15
+ const backAction = useMemo(() => {
16
+ if (prevRoute && (!props.filter || props.filter(prevRoute))) {
17
+ return (e) => {
18
+ const { mode } = getLinkHandlerMode(e, prevRoute.uri);
19
+ if (mode === "navigate") {
20
+ e.preventDefault();
21
+ history.back();
22
+ // history.length
23
+ }
24
+ else if (mode === "ignore") {
25
+ e.preventDefault();
26
+ }
27
+ };
28
+ }
29
+ else if (props.fallbackHref) {
30
+ return (e) => {
31
+ const { mode } = getLinkHandlerMode(e, props.fallbackHref);
32
+ if (mode === "navigate") {
33
+ e.preventDefault();
34
+ router.navigate(props.fallbackHref);
35
+ }
36
+ else if (mode === "ignore") {
37
+ e.preventDefault();
38
+ }
39
+ };
40
+ }
41
+ }, [route, props.filter, props.fallbackHref]);
42
+ if (backAction) {
43
+ return props.render ? props.render({ route: prevRoute, onClick: backAction }) : null;
44
+ }
45
+ }
@@ -24,10 +24,9 @@ if (env.client && !env.admin) {
24
24
  search: "",
25
25
  query: {},
26
26
  view: initialData.view,
27
- meta: {
28
- tags: initialData.meta?.head,
29
- },
27
+ meta: getRouteMeta(initialData),
30
28
  });
29
+ history.replaceState(historyStateForRoute(initialRoute), "", document.location.href);
31
30
  $routeMetaStore.data = getRouteMeta(initialData);
32
31
  }
33
32
  function parseHrefPath(url) {
@@ -120,6 +119,7 @@ export function BrowserRouter(props) {
120
119
  }
121
120
  internals.poppedState = (href, data) => {
122
121
  const stack = state.history;
122
+ console.log("Popped state", stack);
123
123
  // Is the route in our history stack? (going back)
124
124
  const index = stack.findIndex((item) => item.id === data.id);
125
125
  if (index >= 0) {
@@ -205,9 +205,7 @@ export function BrowserRouter(props) {
205
205
  props: data.viewData?.data ?? {},
206
206
  component: lazyComponent,
207
207
  returnState: args.restoreState ?? {},
208
- meta: {
209
- tags: data.meta?.head,
210
- },
208
+ meta: getRouteMeta(data),
211
209
  });
212
210
  setState({
213
211
  pendingRoute: route,
@@ -330,6 +328,39 @@ export function BrowserRouter(props) {
330
328
  }
331
329
  },
332
330
  emitEvent,
331
+ restoreRoute(route) {
332
+ const stack = state.history;
333
+ // Is the route in our history stack? (going back)
334
+ const index = stack.findIndex((item) => item.id === route.id);
335
+ if (index >= 0) {
336
+ return doRouteTransition({
337
+ url: route.uri,
338
+ route,
339
+ goingBack: true,
340
+ history: stack.slice(0, index),
341
+ restoreState: route.returnState,
342
+ shouldPush: false,
343
+ });
344
+ }
345
+ // Is the route in our history _cache_? (probably going forward)
346
+ if (historyCache.has(route.id)) {
347
+ return doRouteTransition({
348
+ url: route.uri,
349
+ route,
350
+ goingBack: false,
351
+ history: stack,
352
+ restoreState: route.returnState,
353
+ shouldPush: false,
354
+ });
355
+ }
356
+ return doRouteTransition({
357
+ url: route.uri,
358
+ goingBack: false,
359
+ history: stack,
360
+ restoreState: route.returnState,
361
+ shouldPush: false,
362
+ });
363
+ },
333
364
  };
334
365
  return {
335
366
  api,
@@ -358,6 +389,7 @@ export function BrowserRouter(props) {
358
389
  // Handle popState
359
390
  // const router = useRouterStore.getState()
360
391
  const onPopState = (e) => {
392
+ console.log("Popped", e.state);
361
393
  internals.poppedState?.(document.location.href, e.state ?? {});
362
394
  };
363
395
  window.addEventListener("popstate", onPopState);
@@ -29,6 +29,7 @@ export const RouterContext = createContext({
29
29
  getState() {
30
30
  return null;
31
31
  },
32
+ restoreRoute(route) { },
32
33
  });
33
34
  export const RouterStateContext = createContext({
34
35
  history: [NOOP_ROUTE],
@@ -3,6 +3,7 @@ export * from "./components/Link.js";
3
3
  export * from "./components/ScrollRestoration.js";
4
4
  export * from "./components/RouteRenderer.js";
5
5
  export * from "./components/ClientOnly.js";
6
+ export * from "./components/BackButton.js";
6
7
  export * from "./hooks/useRoute.js";
7
8
  export * from "./hooks/useRouteTransition.js";
8
9
  export * from "./hooks/useRouter.js";
@@ -3,6 +3,7 @@ export * from "./components/Link.js";
3
3
  export * from "./components/ScrollRestoration.js";
4
4
  export * from "./components/RouteRenderer.js";
5
5
  export * from "./components/ClientOnly.js";
6
+ export * from "./components/BackButton.js";
6
7
  export * from "./hooks/useRoute.js";
7
8
  export * from "./hooks/useRouteTransition.js";
8
9
  export * from "./hooks/useRouter.js";
@@ -111,6 +111,8 @@ export type RouterAPI = {
111
111
  emitEvent: (event: RouterEvent) => void;
112
112
  /** Returns the current RouterState */
113
113
  getState: () => RouterAPIState | null;
114
+ /** Go back to a previous route in the history stack, or push it onto the stack if it isn't currently on the stack. */
115
+ restoreRoute: (route: RouteState) => void;
114
116
  };
115
117
  export type TypedRouteState<T, TProps> = {
116
118
  /** A unique ID, representing this history item. */
@@ -139,6 +141,7 @@ export type TypedRouteState<T, TProps> = {
139
141
  meta: RouteMeta;
140
142
  };
141
143
  export type RouteMeta = {
144
+ title?: string;
142
145
  tags?: RouteMetaTag[];
143
146
  };
144
147
  export type RouteState = {
@@ -94,6 +94,7 @@ export function stringifyQuery(query) {
94
94
  }
95
95
  export function getRouteMeta(data) {
96
96
  return {
97
+ title: data.meta?.head.find((tag) => tag.tagName === "title")?.inner,
97
98
  tags: data.meta?.head ?? [],
98
99
  };
99
100
  }
@@ -1 +1 @@
1
- export declare const VERSION = "2.0.0-beta.27";
1
+ export declare const VERSION = "2.0.0-beta.29";
@@ -1 +1 @@
1
- export const VERSION = "2.0.0-beta.27";
1
+ export const VERSION = "2.0.0-beta.29";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eddev",
3
- "version": "2.0.0-beta.27",
3
+ "version": "2.0.0-beta.29",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",