neutronium 3.3.6 → 3.3.8

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/README.md CHANGED
@@ -1,18 +1,21 @@
1
- # ⚛️ Neutronium v3.0
1
+ # ⚛️ Neutronium v3.3.8
2
2
 
3
3
  **Ultra-dense JavaScript framework – maximum performance, minimal overhead**
4
4
 
5
- [![NPM Downloads](https://img.shields.io/npm/dw/neutronium?style=flat-square)](https://www.npmjs.com/package/neutronium)
5
+ [![npm](https://img.shields.io/badge/Downloads-3.2k-CB3837?logo=npm&logoColor=CB3837&style=flat-square)](https://www.npmjs.com/package/neutronium)
6
6
  [![License: MIT](https://img.shields.io/npm/l/neutronium?style=flat-square)](https://opensource.org/licenses/MIT)
7
7
  [![Version](https://img.shields.io/npm/v/neutronium?style=flat-square)](https://www.npmjs.com/package/neutronium)
8
-
8
+ [![Website](https://img.shields.io/badge/Neutronium_Website-online-0bff03?logo=GoogleChrome&logoColor=d4d2d2&style=flat-square)](https://neutronium-website.onrender.com)
9
+ [![Playground](https://img.shields.io/badge/Online_Playground-0368ff?logo=stackblitz&style=flat-square)](https://neutronium-website.onrender.com/Playground/)
10
+ [![Documentation](https://img.shields.io/badge/Documentation-3d3c3b?logo=readthedocs&style=flat-square)](https://neutronium-website.onrender.com/Docuemntation/)
9
11
  ---
10
12
 
11
13
  ## 🎉 What's new?
12
14
  - ⚡ Faster compilation for complex projects
13
15
  - ✨ useState, and useEffect
14
16
  - ⚛️ React like syntax for easier switching
15
-
17
+ - 🌐 browser-safe Neutronium code compilation using /sandbox.mjs
18
+ - 🖼️ Apply favicon to your site
16
19
  ---
17
20
 
18
21
  ## ℹ️ About
@@ -28,7 +31,7 @@
28
31
  - ⚡️ **Blazing fast rendering**
29
32
  - 🧠 **Simple component logic**
30
33
  - 🔌 **No dependencies or virtual DOM**
31
- - 📦 **Small size (~139kB unpacked)**
34
+ - 📦 **Small size (~184kB unpacked)**
32
35
  - 🛠️ **Works out of the box**
33
36
  - 🔁 **Easy JSX-style structure**
34
37
 
@@ -78,8 +81,9 @@ createApp(App).mount('body');
78
81
 
79
82
  ## NPM Packages using Neutronium
80
83
  ### [@neuhq/alert](https://www.npmjs.com/package/@neuhq/alert)
84
+ ### [neutronium-alert](https://npmjs.org/package/neutronium-alert)
81
85
 
82
86
  ---
83
87
 
84
88
  ## Found a bug or a problem?
85
- ### Report [here.](https://github.com/PFMCODES/neutronium/issues/new)
89
+ ### Report [here.](https://github.com/PFMCODES/neutronium/issues/new)
@@ -7,7 +7,6 @@ const chokidar = require('chokidar');
7
7
  const http = require('http');
8
8
  const { default: Mime } = require('mime');
9
9
  const WebSocket = require('ws');
10
- const { default: open } = require('open');
11
10
  const { execSync } = require('child_process');
12
11
 
13
12
  async function compileProject(projectDir = process.cwd()) {
@@ -203,7 +202,7 @@ function serveProject(projectDir = process.cwd(), port = 3000) {
203
202
  reqPath = reqPath.replace('/node_modules', '');
204
203
  reqPath = "/node_modules/" + reqPath;
205
204
  }
206
- else if (!reqPath.startsWith('/dist/')) {
205
+ else if (!reqPath.startsWith('/dist/') && !reqPath.startsWith('node_modules')) {
207
206
  reqPath = '/dist' + reqPath;
208
207
  }
209
208
 
@@ -1,3 +1,15 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ let favicon;
4
+ const faviconPath = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'))).favicon
5
+
6
+ if (faviconPath) {
7
+ favicon = `<link rel="icon" type="image/x-icon" href="${faviconPath}">`;
8
+ }
9
+ else {
10
+ favicon = '';
11
+ }
12
+
1
13
  function baseHtml(script) {
2
14
  return `
3
15
  <!DOCTYPE html>
@@ -5,6 +17,7 @@ function baseHtml(script) {
5
17
  <head>
6
18
  <meta charset="UTF-8">
7
19
  <title>Neutronium App</title>
20
+ ${favicon}
8
21
  </head>
9
22
  <body>
10
23
  ${script}
package/neutronium.ico ADDED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neutronium",
3
- "version": "3.3.6",
3
+ "version": "3.3.8",
4
4
  "description": "Ultra-dense JavaScript framework – maximum performance, minimal overhead",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -31,16 +31,11 @@
31
31
  "homepage": "https://github.com/pfmcodes/neutronium#readme",
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
- "@babel/core": "^7.28.0",
34
+ "@babel/core": "^7.28.6",
35
35
  "@babel/plugin-transform-react-jsx": "^7.28.6",
36
- "@babel/preset-env": "^7.28.0",
37
- "@babel/preset-react": "^7.27.1",
38
- "@babel/standalone": "^7.28.6",
39
- "@pfmcodes/lexius-api": "^1.0.2",
40
36
  "chokidar": "^4.0.3",
41
37
  "inquirer": "^12.7.0",
42
38
  "mime": "^4.0.7",
43
- "open": "^10.2.0",
44
39
  "ws": "^8.18.3"
45
40
  }
46
41
  }
package/sandbox.mjs CHANGED
@@ -16,7 +16,7 @@ export function compileAndReturnOutput(source) {
16
16
  ]]
17
17
  });
18
18
 
19
- const CDN = "https://esm.sh/neutronium@3.1.8/es2022/neutronium.mjs";
19
+ const CDN = "https://esm.sh/neutronium@3.3.8/es2022/neutronium.mjs";
20
20
  let compiledCode = result.code
21
21
  // import { x } from "neutronium"
22
22
  .replace(
@@ -1,38 +1,38 @@
1
1
  // src/index.ts
2
2
 
3
- type EffectFn = () => void;
4
- type Setter<T> = (value: T) => void;
5
- type Getter<T> = () => T;
6
- type StateTuple<T> = [Getter<T>, Setter<T>];
3
+ type EffectFunction = () => void;
4
+ type StateGetter<T> = () => T;
5
+ type StateSetter<T> = (newVal: T) => void;
6
+ type StateEntry<T> = [StateGetter<T>, StateSetter<T>];
7
7
 
8
- let globalState: Array<StateTuple<any>> = [];
8
+ let globalState: StateEntry<any>[] = [];
9
9
  let stateIndex = 0;
10
10
 
11
11
  function resetStateIndex(): void {
12
12
  stateIndex = 0;
13
13
  }
14
14
 
15
- let currentEffect: EffectFn | null = null;
15
+ let currentEffect: EffectFunction | null = null;
16
16
 
17
- function useEffect(fn: EffectFn): void {
17
+ function useEffect(fn: EffectFunction): void {
18
18
  currentEffect = fn;
19
19
  fn(); // run once to collect dependencies
20
20
  currentEffect = null;
21
21
  }
22
22
 
23
- function useState<T>(initialValue: T): StateTuple<T> {
23
+ function useState<T>(initialValue: T): StateEntry<T> {
24
24
  const index = stateIndex;
25
25
 
26
26
  if (!globalState[index]) {
27
27
  let value = initialValue;
28
- const subs = new Set<EffectFn>();
28
+ const subs = new Set<EffectFunction>();
29
29
 
30
- const get: Getter<T> = () => {
30
+ function get(): T {
31
31
  if (currentEffect) subs.add(currentEffect);
32
32
  return value;
33
- };
33
+ }
34
34
 
35
- const set: Setter<T> = (newVal: T) => {
35
+ function set(newVal: T): void {
36
36
  if (value !== newVal) {
37
37
  value = newVal;
38
38
  subs.forEach(fn => fn()); // re-run effects
@@ -40,23 +40,34 @@ function useState<T>(initialValue: T): StateTuple<T> {
40
40
  (window as any).__NEUTRONIUM_RENDER_FN__();
41
41
  }
42
42
  }
43
- };
43
+ }
44
44
 
45
45
  globalState[index] = [get, set];
46
46
  }
47
47
 
48
- const result = globalState[index] as StateTuple<T>;
48
+ const result = globalState[index] as StateEntry<T>;
49
49
  stateIndex++;
50
50
  return result;
51
51
  }
52
52
 
53
- type Props = {
53
+ type VNode = Node;
54
+ type Child = VNode | string | number | null | undefined;
55
+ type Children = Child | Child[];
56
+
57
+ interface Props {
58
+ children?: Children;
59
+ ref?: (el: HTMLElement) => void;
54
60
  [key: string]: any;
55
- children?: any;
56
- };
61
+ }
62
+
63
+ type ComponentFunction = (props: Props) => VNode;
64
+ type ElementType = string | ComponentFunction;
57
65
 
58
- function h(type: string | ((props: Props) => Node), props: Props = {}, ...children: any[]): Node {
59
- props.children = (props.children || []).concat(children).flat();
66
+ function h(type: ElementType, props: Props | null = {}, ...children: Child[]): VNode {
67
+ props = props || {};
68
+ props.children = (props.children ? (Array.isArray(props.children) ? props.children : [props.children]) : [])
69
+ .concat(children)
70
+ .flat();
60
71
 
61
72
  if (typeof type === 'function') {
62
73
  return type(props);
@@ -64,35 +75,36 @@ function h(type: string | ((props: Props) => Node), props: Props = {}, ...childr
64
75
 
65
76
  const el = document.createElement(type);
66
77
 
67
- for (const [key, value] of Object.entries(props)) {
68
- if (key === 'children') continue;
78
+ for (const [key, value] of Object.entries(props || {})) {
79
+ if (key === 'children') continue; // skip
69
80
  if (key.startsWith('on') && typeof value === 'function') {
70
81
  el.addEventListener(key.slice(2).toLowerCase(), value);
71
82
  } else if (key === 'ref' && typeof value === 'function') {
72
83
  value(el);
73
84
  } else {
74
- el.setAttribute(key, value);
85
+ el.setAttribute(key, String(value));
75
86
  }
76
87
  }
77
88
 
78
- for (const child of props.children) {
89
+ props.children.forEach((child: Child) => {
79
90
  if (typeof child === 'string' || typeof child === 'number') {
80
91
  el.appendChild(document.createTextNode(String(child)));
81
92
  } else if (child instanceof Node) {
82
93
  el.appendChild(child);
83
94
  }
84
- }
95
+ });
85
96
 
86
97
  return el;
87
98
  }
88
99
 
89
- function createApp(component: () => Node) {
90
- return {
91
- mount(selector: string | Element): Element | null {
92
- const root = typeof selector === 'string'
93
- ? document.querySelector(selector)
94
- : selector;
100
+ interface App {
101
+ mount(selector: string | HTMLElement): HTMLElement | null;
102
+ }
95
103
 
104
+ function createApp(component: () => VNode): App {
105
+ return {
106
+ mount(selector: string | HTMLElement): HTMLElement | null {
107
+ const root = typeof selector === 'string' ? document.querySelector<HTMLElement>(selector) : selector;
96
108
  if (!root) {
97
109
  console.error(`❌ Root element '${selector}' not found`);
98
110
  return null;
@@ -100,7 +112,7 @@ function createApp(component: () => Node) {
100
112
 
101
113
  (window as any).__NEUTRONIUM_ROOT__ = root;
102
114
 
103
- function render() {
115
+ function render(): void {
104
116
  resetStateIndex();
105
117
  const vnode = component();
106
118
  root.innerHTML = '';
@@ -119,24 +131,16 @@ function Fragment(props: Props = {}): DocumentFragment {
119
131
  const frag = document.createDocumentFragment();
120
132
  const children = props.children || [];
121
133
 
122
- const childArray = Array.isArray(children) ? children : [children];
123
-
124
- for (const child of childArray) {
134
+ (Array.isArray(children) ? children : [children]).forEach((child: Child) => {
125
135
  if (typeof child === 'string' || typeof child === 'number') {
126
136
  frag.appendChild(document.createTextNode(String(child)));
127
137
  } else if (child instanceof Node) {
128
138
  frag.appendChild(child);
129
139
  }
130
- }
140
+ });
131
141
 
132
142
  return frag;
133
143
  }
134
144
 
135
- export {
136
- h,
137
- createApp,
138
- Fragment,
139
- useState,
140
- useEffect,
141
- resetStateIndex
142
- };
145
+ export { h, createApp, Fragment, useState, useEffect, resetStateIndex };
146
+ export type { Props, VNode, Child, Children, ComponentFunction, ElementType, StateEntry, EffectFunction };