akanjs 2.0.0-beta.8 → 2.0.0-beta.9

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.
@@ -45,11 +45,11 @@ export const HMR_CLIENT_SCRIPT = `(function(){
45
45
  return;
46
46
  }
47
47
  if (msg.type === "rsc-refresh") {
48
- refreshRsc(msg);
48
+ reloadForHmr(msg);
49
49
  return;
50
50
  }
51
51
  if (msg.type === "client-refresh") {
52
- refreshClient(msg);
52
+ reloadForHmr(msg);
53
53
  return;
54
54
  }
55
55
  if (msg.type === "css-update") {
@@ -73,6 +73,12 @@ export const HMR_CLIENT_SCRIPT = `(function(){
73
73
  setTimeout(connect, delay);
74
74
  }
75
75
 
76
+ function reloadForHmr(msg){
77
+ try { self.__AKAN_RSC_CLEAR_CACHE__ && self.__AKAN_RSC_CLEAR_CACHE__(); } catch(e){}
78
+ if (msg && msg.buildId != null) lastBuildId = msg.buildId;
79
+ location.reload();
80
+ }
81
+
76
82
  function ensureOverlay(){
77
83
  if (overlayEl && overlayLabelEl) return overlayEl;
78
84
  if (!overlayStyleEl) {
@@ -303,8 +309,5 @@ export const HMR_CLIENT_SCRIPT = `(function(){
303
309
  return cssAssets[""] && cssAssets[""].cssUrl ? cssAssets[""].cssUrl : null;
304
310
  }
305
311
 
306
- ensureRefreshRuntime().catch(function(err){
307
- console.warn("[akan-hmr] React Refresh runtime preload failed", err);
308
- });
309
312
  connect();
310
313
  })();`;
package/ui/Portal.tsx CHANGED
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { createPortal } from "react-dom";
2
4
 
3
5
  interface PortalProps {
package/ui/System/CSR.tsx CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  import { st } from "akanjs/store";
16
16
  import { animated } from "akanjs/ui";
17
17
  import { useFetch, usePushNoti } from "akanjs/webkit";
18
- import { memo, type ReactNode, useEffect, useRef } from "react";
18
+ import { createElement, memo, type ReactNode, useEffect, useRef } from "react";
19
19
  import { createPortal } from "react-dom";
20
20
 
21
21
  import { FontFace } from "../FontFace";
@@ -305,9 +305,7 @@ const CSRPageContainer = ({ pathRoute, prefix, layoutStyle }: CSRPageContainerPr
305
305
  <animated.div
306
306
  id={`pageContainer-${pathRoute.path}`}
307
307
  style={{ ...(page?.containerStyle ?? {}), zIndex }}
308
- className={clsx("absolute top-0 left-0 isolate", {
309
- "w-full": layoutStyle === "web",
310
- "w-screen": layoutStyle === "mobile",
308
+ className={clsx("absolute top-0 left-0 isolate w-screen", {
311
309
  absolute: pageType !== "current",
312
310
  hidden: pageType === "cached",
313
311
  "pointer-events-none": pageType === "prev",
@@ -398,11 +396,14 @@ const RenderLayer = memo(({ renders, index, params, searchParams }: RenderLayerP
398
396
  <RenderLayer renders={renders} index={index + 1} params={params} searchParams={searchParams} />
399
397
  );
400
398
  const routeRender = renders[index];
399
+ const isAsyncRender = routeRender?.render.constructor.name === "AsyncFunction";
401
400
  const resultRef = useRef<ReactNode | Promise<ReactNode> | null>(null);
402
- if (resultRef.current === null) {
401
+ if (isAsyncRender && resultRef.current === null) {
403
402
  resultRef.current = routeRender?.render({ children, params, searchParams } as never) ?? null;
404
403
  }
405
404
  const { fulfilled, value: Component } = useFetch(resultRef.current);
405
+ if (!routeRender) return null;
406
+ if (!isAsyncRender) return createElement(routeRender.render as never, { children, params, searchParams } as never);
406
407
  if (!fulfilled || !Component) return <>{composeLoadingFallback(renders.slice(index), params)}</>;
407
408
  return <>{Component}</>;
408
409
  });
package/ui/System/SSR.tsx CHANGED
@@ -115,11 +115,11 @@ const SSRWrapper = ({
115
115
  <div key="frame-root" id="frameRoot" className={className}>
116
116
  <ClientPathWrapper layoutStyle={layoutStyle} prefix={prefix}>
117
117
  <div key="top-safe-area" id="topSafeArea" className={clsx("fixed inset-x-0 top-0 bg-base-100")} />
118
- <div key="page-containers" id="pageContainers" className={clsx("isolate")}>
118
+ <div key="page-containers" id="pageContainers" className={clsx("isolate bg-red-500")}>
119
119
  <div id="pageContainer">
120
120
  <div
121
121
  id="pageContent"
122
- className={clsx("relative isolate bg-base-100", {
122
+ className={clsx("relative isolate", {
123
123
  "w-full": layoutStyle === "web",
124
124
  "left-1/2 h-screen w-[600px] -translate-x-1/2": layoutStyle === "mobile",
125
125
  })}
@@ -23,7 +23,7 @@ import {
23
23
  parseRouteModuleKey,
24
24
  routeSegmentToTreePath,
25
25
  } from "akanjs/common";
26
- import { memo, type ReactNode, useRef } from "react";
26
+ import { createElement, memo, type ReactNode, useRef } from "react";
27
27
  import * as ReactDOM from "react-dom/client";
28
28
  import { useCsrValues } from "./useCsrValues";
29
29
  import { useFetch } from "./useFetch";
@@ -48,11 +48,14 @@ const RootRenderLayer = memo(({ renders, index, params, searchParams }: RootRend
48
48
  <RootRenderLayer renders={renders} index={index + 1} params={params} searchParams={searchParams} />
49
49
  );
50
50
  const routeRender = renders[index];
51
+ const isAsyncRender = routeRender?.render.constructor.name === "AsyncFunction";
51
52
  const resultRef = useRef<ReactNode | Promise<ReactNode> | null>(null);
52
- if (resultRef.current === null) {
53
+ if (isAsyncRender && resultRef.current === null) {
53
54
  resultRef.current = routeRender?.render({ children, params, searchParams } as never) ?? null;
54
55
  }
55
56
  const { fulfilled, value: Layout } = useFetch(resultRef.current);
57
+ if (!routeRender) return null;
58
+ if (!isAsyncRender) return createElement(routeRender.render as never, { children, params, searchParams } as never);
56
59
  if (!fulfilled || !Layout) return <>{composeLoadingFallback(renders.slice(index), params)}</>;
57
60
  return Layout;
58
61
  });
@@ -101,7 +104,7 @@ export const bootCsr = async (context: Record<string, () => Promise<RouteModule>
101
104
  if (pageContent.default) pages[key] = pageContent;
102
105
  }),
103
106
  );
104
- const getPageState = (csrConfig?: PageConfig) => {
107
+ const getPageState = (PageConfig?: PageConfig) => {
105
108
  const {
106
109
  transition,
107
110
  safeArea,
@@ -111,7 +114,7 @@ export const bootCsr = async (context: Record<string, () => Promise<RouteModule>
111
114
  cache,
112
115
  topSafeAreaColor,
113
116
  bottomSafeAreaColor,
114
- }: PageConfig = csrConfig ?? {};
117
+ }: PageConfig = PageConfig ?? {};
115
118
  const pageState: PageState = {
116
119
  transition: transition ?? "none",
117
120
  topSafeArea:
@@ -159,7 +162,7 @@ export const bootCsr = async (context: Record<string, () => Promise<RouteModule>
159
162
  pageIncludesOwnLayout: parsed.leaf === "_index",
160
163
  isSpecialRoute: parsed.isSpecialRoute,
161
164
  pageState: getPageState((page as RouteModuleWithConfig).pageConfig),
162
- csrConfig: (page as RouteModuleWithConfig).pageConfig,
165
+ PageConfig: (page as RouteModuleWithConfig).pageConfig,
163
166
  }),
164
167
  } as Route);
165
168
  }
@@ -1,12 +0,0 @@
1
- import type { AppInfo, LibInfo } from "akanjs/devkit";
2
-
3
- interface Dict {
4
- appName: string;
5
- }
6
- export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict) {
7
- return `
8
-
9
- export const someCommonLogic = () => {
10
- };
11
- `;
12
- }
@@ -1,10 +0,0 @@
1
- import type { AppInfo, LibInfo } from "akanjs/devkit";
2
-
3
- interface Dict {
4
- [key: string]: string;
5
- }
6
- export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict = {}) {
7
- return `
8
- export * from "./commonLogic";
9
- `;
10
- }
@@ -1,12 +0,0 @@
1
- import type { AppInfo, LibInfo } from "akanjs/devkit";
2
-
3
- interface Dict {
4
- appName: string;
5
- }
6
- export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict) {
7
- return `
8
-
9
- export const someBackendLogic = () => {
10
- };
11
- `;
12
- }
@@ -1,10 +0,0 @@
1
- import type { AppInfo, LibInfo } from "akanjs/devkit";
2
-
3
- interface Dict {
4
- [key: string]: string;
5
- }
6
- export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict = {}) {
7
- return `
8
- export * from "./backendLogic";
9
- `;
10
- }
@@ -1,16 +0,0 @@
1
- import type { AppInfo, LibInfo } from "akanjs/devkit";
2
-
3
- interface Dict {
4
- appName: string;
5
- }
6
- export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict) {
7
- return {
8
- filename: "UiComponent.tsx",
9
- content: `
10
-
11
- export const UiComponent = () => {
12
- return <div>UiComponent</div>;
13
- };
14
- `,
15
- };
16
- }
@@ -1,10 +0,0 @@
1
- import type { AppInfo, LibInfo } from "akanjs/devkit";
2
-
3
- interface Dict {
4
- [key: string]: string;
5
- }
6
- export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict = {}) {
7
- return `
8
- export { UiComponent } from "./UiComponent";
9
- `;
10
- }
@@ -1,12 +0,0 @@
1
- import type { AppInfo, LibInfo } from "akanjs/devkit";
2
-
3
- interface Dict {
4
- appName: string;
5
- }
6
- export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict) {
7
- return `
8
-
9
- export const someFrontendLogic = () => {
10
- };
11
- `;
12
- }
@@ -1,10 +0,0 @@
1
- import type { AppInfo, LibInfo } from "akanjs/devkit";
2
-
3
- interface Dict {
4
- [key: string]: string;
5
- }
6
- export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict = {}) {
7
- return `
8
- export * from "./frontendLogic";
9
- `;
10
- }
@@ -1,44 +0,0 @@
1
- import type { AppInfo, LibInfo } from "akanjs/devkit";
2
-
3
- interface Dict {
4
- Model: string;
5
- model: string;
6
- appName: string;
7
- }
8
- export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict) {
9
- return {
10
- filename: "index.tsx",
11
- content: `
12
- import { Signal } from "akanjs/ui";
13
- import { AiOutlineDatabase } from "react-icons/ai";
14
-
15
- import * as Template from "./${dict.Model}.Template";
16
- import * as Unit from "./${dict.Model}.Unit";
17
- import * as Util from "./${dict.Model}.Util";
18
- import * as View from "./${dict.Model}.View";
19
- import * as Zone from "./${dict.Model}.Zone";
20
-
21
- export const ${dict.Model} = {
22
- Menu: {
23
- Admin: {
24
- key: "${dict.model}",
25
- label: "${dict.Model}",
26
- icon: <AiOutlineDatabase />,
27
- render: () => <Zone.Admin />,
28
- },
29
- Doc: {
30
- key: "${dict.model}",
31
- label: "${dict.Model}",
32
- icon: <AiOutlineDatabase />,
33
- render: () => <Signal.Doc.Zone refName="${dict.model}" />,
34
- },
35
- },
36
- Template,
37
- Unit,
38
- Util,
39
- View,
40
- Zone,
41
- };
42
- `,
43
- };
44
- }