melina 1.1.0 → 1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "melina",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "A lightweight, islands-architecture web framework for Bun with Next.js-style routing.",
5
5
  "module": "./src/web.ts",
6
6
  "main": "./src/web.ts",
package/src/client.ts CHANGED
@@ -1204,10 +1204,15 @@ async function loadComponent(name: string): Promise<Component<any> | null> {
1204
1204
 
1205
1205
  /**
1206
1206
  * Hydrate all islands in the current DOM
1207
+ * Uses ReactDOM.createRoot for React-based components
1207
1208
  */
1208
1209
  export async function hydrateIslands(): Promise<void> {
1209
1210
  initHangar();
1210
1211
 
1212
+ // Dynamic import of React and ReactDOM for island hydration
1213
+ const React = await import('react');
1214
+ const ReactDOM = await import('react-dom/client');
1215
+
1211
1216
  const placeholders = document.querySelectorAll('[data-melina-island]');
1212
1217
  const seenIds = new Set<string>();
1213
1218
 
@@ -1239,19 +1244,22 @@ export async function hydrateIslands(): Promise<void> {
1239
1244
  storageNode.setAttribute('data-storage', instanceId);
1240
1245
  el.appendChild(storageNode);
1241
1246
 
1242
- // Render component into storage node
1243
- const vnode = createElement(Component, props);
1244
- const fiber = render(vnode, storageNode);
1247
+ // Render component using ReactDOM.createRoot for proper React hydration
1248
+ const root = ReactDOM.createRoot(storageNode);
1249
+ root.render(React.createElement(Component as any, props));
1250
+
1251
+ // Store root for cleanup and re-rendering
1252
+ (storageNode as any).__reactRoot = root;
1245
1253
 
1246
1254
  islandRegistry.set(instanceId, {
1247
1255
  name,
1248
1256
  Component,
1249
1257
  props,
1250
- fiber,
1258
+ fiber: null as any, // Not using fiber for React components
1251
1259
  storageNode,
1252
1260
  });
1253
1261
 
1254
- console.log('[Melina Client] Created island:', instanceId);
1262
+ console.log('[Melina Client] Created React island:', instanceId);
1255
1263
  }
1256
1264
  }
1257
1265
  }
package/src/web.ts CHANGED
@@ -445,9 +445,9 @@ let cachedRuntimePath: string | null = null;
445
445
 
446
446
  /**
447
447
  * Build the Melina client runtime from TypeScript source
448
- * This bundles src/runtime/navigation.tsx and serves it from memory
448
+ * This bundles src/client.ts and serves it from memory
449
449
  *
450
- * The client runtime is React-based - it uses html-react-parser for VDOM reconciliation.
450
+ * The client runtime handles island hydration using React.
451
451
  * SSR uses React on the server, and the browser uses React for hydration.
452
452
  */
453
453
  async function buildRuntime(): Promise<string> {
@@ -457,7 +457,7 @@ async function buildRuntime(): Promise<string> {
457
457
  }
458
458
 
459
459
  // Find the runtime source file (in the package, not the user's app)
460
- const runtimePath = path.resolve(__dirname, './runtime/navigation.tsx');
460
+ const runtimePath = path.resolve(__dirname, './client.ts');
461
461
 
462
462
  if (!existsSync(runtimePath)) {
463
463
  throw new Error(`Melina runtime not found at: ${runtimePath}`);