@chidchanun/bcp 0.1.1 → 0.1.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable framework changes are tracked here before release.
4
4
 
5
+ ## 0.1.2 - SSR Link hotfix
6
+
7
+ ### Client routing
8
+
9
+ - Export `Link` through an SSR-safe implementation that uses `React.createElement` semantics without relying on a global `React` binding.
10
+ - Avoid the `ReferenceError: React is not defined` failure when a published BCP package is executed through `tsx` from `node_modules` during server-side rendering.
11
+ - Added an SSR regression test that renders the public `Link` component with `react-dom/server`.
12
+
5
13
  ## 0.1.1 - Packaging hotfix
6
14
 
7
15
  ### Packaging and release recovery
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chidchanun/bcp",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "BCP Framework - a React full-stack framework with file-based routing, SSR, APIs, middleware, islands, caching and standalone production builds.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,14 +1,17 @@
1
1
  import "./persistent-layout-runtime.js";
2
2
 
3
3
  export {
4
- Link,
5
4
  navigate,
6
5
  useRouter,
7
- type LinkProps,
8
6
  type NavigationOptions,
9
7
  type Router,
10
8
  } from "./router-v2.js";
11
9
 
10
+ export {
11
+ Link,
12
+ type LinkProps,
13
+ } from "./link.js";
14
+
12
15
  export {
13
16
  useNavigation,
14
17
  type NavigationState,
@@ -0,0 +1,123 @@
1
+ import {
2
+ createElement,
3
+ type MouseEvent,
4
+ } from "react";
5
+
6
+ import {
7
+ navigate,
8
+ useRouter,
9
+ type LinkProps,
10
+ } from "./router-v2.js";
11
+
12
+ export type {
13
+ LinkProps,
14
+ } from "./router-v2.js";
15
+
16
+ export function Link({
17
+ href,
18
+ replace = false,
19
+ scroll = true,
20
+ onClick,
21
+ ...props
22
+ }: LinkProps) {
23
+ useRouter();
24
+
25
+ function handleClick(
26
+ event: MouseEvent<HTMLAnchorElement>
27
+ ) {
28
+ onClick?.(event);
29
+
30
+ if (
31
+ event.defaultPrevented ||
32
+ !shouldInterceptClick(
33
+ event
34
+ )
35
+ ) {
36
+ return;
37
+ }
38
+
39
+ event.preventDefault();
40
+
41
+ void navigate(
42
+ href,
43
+ {
44
+ replace,
45
+ scroll,
46
+ }
47
+ ).catch(
48
+ (error) => {
49
+ if (isAbortError(error)) {
50
+ return;
51
+ }
52
+
53
+ console.error(
54
+ "[BCP Router] navigation failed:",
55
+ error
56
+ );
57
+ window.location.assign(
58
+ href
59
+ );
60
+ }
61
+ );
62
+ }
63
+
64
+ return createElement(
65
+ "a",
66
+ {
67
+ ...props,
68
+ href,
69
+ onClick:
70
+ handleClick,
71
+ }
72
+ );
73
+ }
74
+
75
+ function shouldInterceptClick(
76
+ event: MouseEvent<HTMLAnchorElement>
77
+ ): boolean {
78
+ if (
79
+ event.defaultPrevented ||
80
+ event.button !== 0 ||
81
+ event.metaKey ||
82
+ event.ctrlKey ||
83
+ event.shiftKey ||
84
+ event.altKey
85
+ ) {
86
+ return false;
87
+ }
88
+
89
+ const anchor =
90
+ event.currentTarget;
91
+
92
+ if (
93
+ anchor.target &&
94
+ anchor.target !== "_self"
95
+ ) {
96
+ return false;
97
+ }
98
+
99
+ if (
100
+ anchor.hasAttribute(
101
+ "download"
102
+ )
103
+ ) {
104
+ return false;
105
+ }
106
+
107
+ return (
108
+ new URL(
109
+ anchor.href,
110
+ window.location.href
111
+ ).origin ===
112
+ window.location.origin
113
+ );
114
+ }
115
+
116
+ function isAbortError(
117
+ error: unknown
118
+ ): boolean {
119
+ return (
120
+ error instanceof DOMException &&
121
+ error.name === "AbortError"
122
+ );
123
+ }
@@ -1 +1,11 @@
1
- export * from "./router-v2.js";
1
+ export {
2
+ navigate,
3
+ useRouter,
4
+ type NavigationOptions,
5
+ type Router,
6
+ } from "./router-v2.js";
7
+
8
+ export {
9
+ Link,
10
+ type LinkProps,
11
+ } from "./link.js";