@limlabs/rex 0.0.1-test.1

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/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@limlabs/rex",
3
+ "version": "0.0.1-test.1",
4
+ "description": "Rex - Next.js Pages Router reimplemented in Rust",
5
+ "main": "src/index.js",
6
+ "exports": {
7
+ ".": "./src/index.js",
8
+ "./document": "./src/document.js",
9
+ "./link": "./src/link.js",
10
+ "./router": "./src/router.js"
11
+ },
12
+ "peerDependencies": {
13
+ "react": "^18.0.0",
14
+ "react-dom": "^18.0.0"
15
+ }
16
+ }
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+
3
+ /**
4
+ * rex/document exports
5
+ * These components are meaningful during SSR and provide structure for the HTML document.
6
+ * On the client side, they are essentially pass-throughs.
7
+ */
8
+
9
+ export function Html({ children, ...props }) {
10
+ return React.createElement('html', props, children);
11
+ }
12
+
13
+ export function Head({ children }) {
14
+ return React.createElement('head', null, children);
15
+ }
16
+
17
+ export function Main() {
18
+ // During SSR, this is replaced with the actual page content
19
+ return React.createElement('div', { id: '__rex' });
20
+ }
21
+
22
+ export function NextScript() {
23
+ // During SSR, this is replaced with the actual script tags
24
+ return null;
25
+ }
26
+
27
+ // Default document component
28
+ export default function Document() {
29
+ return React.createElement(
30
+ Html,
31
+ null,
32
+ React.createElement(Head, null),
33
+ React.createElement(
34
+ 'body',
35
+ null,
36
+ React.createElement(Main, null),
37
+ React.createElement(NextScript, null)
38
+ )
39
+ );
40
+ }
package/src/index.js ADDED
@@ -0,0 +1,4 @@
1
+ // Rex framework exports
2
+ export { Html, Head, Main, NextScript } from './document.js';
3
+ export { default as Link } from './link.js';
4
+ export { useRouter, navigateTo } from './router.js';
package/src/link.js ADDED
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { navigateTo } from './router.js';
3
+
4
+ /**
5
+ * rex/link - Client-side navigation link
6
+ * Renders an <a> tag that intercepts clicks for SPA navigation.
7
+ */
8
+ export default function Link({ href, children, target, rel, className, style, ...rest }) {
9
+ function handleClick(e) {
10
+ // Don't intercept if:
11
+ // - modifier key is held (user wants new tab)
12
+ // - target is set (external link behavior)
13
+ // - href is external
14
+ if (
15
+ e.metaKey ||
16
+ e.ctrlKey ||
17
+ e.shiftKey ||
18
+ e.altKey ||
19
+ target === '_blank' ||
20
+ (href && (href.startsWith('http://') || href.startsWith('https://')))
21
+ ) {
22
+ return;
23
+ }
24
+
25
+ e.preventDefault();
26
+ navigateTo(href);
27
+ }
28
+
29
+ return React.createElement(
30
+ 'a',
31
+ {
32
+ href: href,
33
+ onClick: handleClick,
34
+ target: target,
35
+ rel: rel,
36
+ className: className,
37
+ style: style,
38
+ ...rest,
39
+ },
40
+ children
41
+ );
42
+ }
package/src/router.js ADDED
@@ -0,0 +1,114 @@
1
+ /**
2
+ * rex/router - Client-side router
3
+ * Handles SPA navigation by fetching page data and re-rendering.
4
+ */
5
+
6
+ let _initialized = false;
7
+ let _currentPath = null;
8
+ let _buildId = null;
9
+
10
+ /**
11
+ * Initialize the client-side router.
12
+ * Called automatically on page load.
13
+ */
14
+ export function initializeRouter() {
15
+ if (_initialized) return;
16
+ _initialized = true;
17
+
18
+ _currentPath = window.location.pathname;
19
+ _buildId = window.__REX_BUILD_ID__ || '';
20
+
21
+ // Listen for browser back/forward
22
+ window.addEventListener('popstate', function(event) {
23
+ var path = window.location.pathname;
24
+ if (path !== _currentPath) {
25
+ _currentPath = path;
26
+ loadPage(path, false);
27
+ }
28
+ });
29
+ }
30
+
31
+ /**
32
+ * Navigate to a new path via client-side routing.
33
+ */
34
+ export function navigateTo(path) {
35
+ if (path === _currentPath) return;
36
+
37
+ _currentPath = path;
38
+ window.history.pushState(null, '', path);
39
+ loadPage(path, true);
40
+ }
41
+
42
+ /**
43
+ * Get the current route information (React hook style, but simplified).
44
+ */
45
+ export function useRouter() {
46
+ return {
47
+ pathname: window.location.pathname,
48
+ query: parseQuery(window.location.search),
49
+ push: navigateTo,
50
+ back: function() { window.history.back(); },
51
+ };
52
+ }
53
+
54
+ async function loadPage(path, isNavigation) {
55
+ try {
56
+ // Fetch page data
57
+ var dataPath = path === '/' ? '/index' : path;
58
+ var dataUrl = '/_rex/data/' + _buildId + dataPath + '.json';
59
+
60
+ var response = await fetch(dataUrl);
61
+
62
+ if (response.status === 404) {
63
+ // Build ID mismatch or route not found - full reload
64
+ window.location.href = path;
65
+ return;
66
+ }
67
+
68
+ if (!response.ok) {
69
+ throw new Error('Failed to fetch page data: ' + response.status);
70
+ }
71
+
72
+ var data = await response.json();
73
+
74
+ if (data.redirect) {
75
+ navigateTo(data.redirect.destination);
76
+ return;
77
+ }
78
+
79
+ if (data.notFound) {
80
+ // Show 404
81
+ window.location.href = path;
82
+ return;
83
+ }
84
+
85
+ // For the prototype, we do a full page reload
86
+ // A full implementation would dynamically import the page module
87
+ // and re-render using window.__REX_ROOT__.render()
88
+ window.location.href = path;
89
+
90
+ } catch (err) {
91
+ console.error('[Rex Router] Navigation error:', err);
92
+ window.location.href = path;
93
+ }
94
+ }
95
+
96
+ function parseQuery(search) {
97
+ var query = {};
98
+ if (!search || search.length <= 1) return query;
99
+ var pairs = search.substring(1).split('&');
100
+ for (var i = 0; i < pairs.length; i++) {
101
+ var pair = pairs[i].split('=');
102
+ query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
103
+ }
104
+ return query;
105
+ }
106
+
107
+ // Auto-initialize when loaded in browser
108
+ if (typeof window !== 'undefined') {
109
+ if (document.readyState === 'loading') {
110
+ document.addEventListener('DOMContentLoaded', initializeRouter);
111
+ } else {
112
+ initializeRouter();
113
+ }
114
+ }