mono-jsx 0.2.0 → 0.3.0
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 +58 -16
- package/bin/mono-jsx +1 -42
- package/jsx-runtime.mjs +135 -136
- package/package.json +3 -2
- package/setup.mjs +58 -0
- package/types/css.d.ts +1 -1
- package/types/html.d.ts +3 -2
- package/types/htmx.d.ts +791 -0
- package/types/mono.d.ts +6 -5
- package/types/render.d.ts +42 -1
package/README.md
CHANGED
|
@@ -309,22 +309,63 @@ function Counter(
|
|
|
309
309
|
}
|
|
310
310
|
```
|
|
311
311
|
|
|
312
|
-
### Using
|
|
312
|
+
### Using App State
|
|
313
313
|
|
|
314
|
-
You can
|
|
314
|
+
You can define app state by adding `appState` prop to the root `<html>` element. The app state is available in all components via `this.app.<stateKey>`. Changes to the app state will trigger re-renders in all components that use it:
|
|
315
|
+
|
|
316
|
+
```tsx
|
|
317
|
+
function Header(this: FC<{}, { title: string }>) {
|
|
318
|
+
return (
|
|
319
|
+
<header>
|
|
320
|
+
<h1>{this.app.title}</h1>
|
|
321
|
+
</header>
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function Footer(this: FC<{}, { title: string }>) {
|
|
326
|
+
return (
|
|
327
|
+
<footer>
|
|
328
|
+
<p>(c) 2025 {this.app.title}</p>
|
|
329
|
+
</footer>
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function Main(this: FC<{}, { title: string }>) {
|
|
334
|
+
return (
|
|
335
|
+
<main>
|
|
336
|
+
<h1>{this.app.title}</h1>
|
|
337
|
+
<h2>Changing the title</h2>
|
|
338
|
+
<input
|
|
339
|
+
onInput={(evt) => this.app.title = evt.target.value }
|
|
340
|
+
placeholder="Enter a new title"
|
|
341
|
+
/>
|
|
342
|
+
</main>
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export default {
|
|
347
|
+
fetch: (req) => (
|
|
348
|
+
<html appState={{ title: "Welcome to mono-jsx!" }}>
|
|
349
|
+
<Header />
|
|
350
|
+
<Main />
|
|
351
|
+
<Footer />
|
|
352
|
+
</html>
|
|
353
|
+
),
|
|
354
|
+
};
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Using Computed State
|
|
358
|
+
|
|
359
|
+
You can use `this.computed` to create computed state based on state. The computed state will automatically update when the state changes:
|
|
315
360
|
|
|
316
361
|
```tsx
|
|
317
362
|
function App(this: FC<{ input: string }>) {
|
|
318
|
-
this.input =
|
|
363
|
+
this.input = "Welcome to mono-jsx!";
|
|
319
364
|
return (
|
|
320
365
|
<div>
|
|
321
|
-
<h1>{this.computed(()
|
|
366
|
+
<h1>{this.computed(() => this.input + "!")}</h1>
|
|
322
367
|
|
|
323
|
-
<form
|
|
324
|
-
action={(data: FormData ) => {
|
|
325
|
-
this.input = data.get("input") as string;
|
|
326
|
-
}}
|
|
327
|
-
>
|
|
368
|
+
<form action={(fd) => this.input = fd.get("input") as string}>
|
|
328
369
|
<input type="text" name="input" value={this.input} />
|
|
329
370
|
<button type="submit">Submit</button>
|
|
330
371
|
</form>
|
|
@@ -366,7 +407,7 @@ function App(this: FC) {
|
|
|
366
407
|
```tsx
|
|
367
408
|
// ❌ Won't work - state updates won't refresh the view
|
|
368
409
|
function App(this: FC<{ message: string }>) {
|
|
369
|
-
this.message = "
|
|
410
|
+
this.message = "Welcome to mono-jsx!";
|
|
370
411
|
return (
|
|
371
412
|
<div>
|
|
372
413
|
<h1 title={this.message + "!"}>{this.message + "!"}</h1>
|
|
@@ -379,7 +420,7 @@ function App(this: FC<{ message: string }>) {
|
|
|
379
420
|
|
|
380
421
|
// ✅ Works correctly
|
|
381
422
|
function App(this: FC) {
|
|
382
|
-
this.message = "
|
|
423
|
+
this.message = "Welcome to mono-jsx!";
|
|
383
424
|
return (
|
|
384
425
|
<div>
|
|
385
426
|
<h1 title={this.computed(() => this.message + "!")}>{this.computed(() => this.message + "!")}</h1>
|
|
@@ -494,22 +535,23 @@ export default {
|
|
|
494
535
|
You can use the `context` property in `this` to access context values in your components. The context is defined on the root `<html>` element:
|
|
495
536
|
|
|
496
537
|
```tsx
|
|
497
|
-
function Dash(this: FC<{}, { auth: { uuid: string; name: string } }>) {
|
|
538
|
+
function Dash(this: FC<{}, {}, { auth: { uuid: string; name: string } }>) {
|
|
498
539
|
const { auth } = this.context;
|
|
499
540
|
return (
|
|
500
541
|
<div>
|
|
501
|
-
<h1>Welcome back, {auth.name}!</h1
|
|
542
|
+
<h1>Welcome back, {auth.name}!</h1>
|
|
502
543
|
<p>Your UUID is {auth.uuid}</p>
|
|
503
544
|
</div>
|
|
504
545
|
);
|
|
505
546
|
}
|
|
506
547
|
|
|
507
548
|
export default {
|
|
508
|
-
fetch: (req) => {
|
|
509
|
-
const auth = doAuth(req);
|
|
549
|
+
fetch: async (req) => {
|
|
550
|
+
const auth = await doAuth(req);
|
|
510
551
|
return (
|
|
511
552
|
<html context={{ auth }} request={req}>
|
|
512
|
-
<
|
|
553
|
+
{!auth && <p>Please Login</p>}
|
|
554
|
+
{auth && <Dash />}
|
|
513
555
|
</html>
|
|
514
556
|
);
|
|
515
557
|
},
|
package/bin/mono-jsx
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
4
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
5
3
|
import process from "node:process";
|
|
4
|
+
import { setup } from "../setup.mjs";
|
|
6
5
|
|
|
7
6
|
switch (process.argv[2]) {
|
|
8
7
|
case "setup":
|
|
@@ -11,43 +10,3 @@ switch (process.argv[2]) {
|
|
|
11
10
|
default:
|
|
12
11
|
process.exit(0);
|
|
13
12
|
}
|
|
14
|
-
|
|
15
|
-
async function setup() {
|
|
16
|
-
if (globalThis.Deno && existsSync("deno.jsonc")) {
|
|
17
|
-
console.log("Please add the following options to your deno.jsonc file:");
|
|
18
|
-
console.log(
|
|
19
|
-
[
|
|
20
|
-
`{`,
|
|
21
|
-
` "compilerOptions": {`,
|
|
22
|
-
` %c"jsx": "react-jsx",`,
|
|
23
|
-
` "jsxImportSource": "mono-jsx",%c`,
|
|
24
|
-
` }`,
|
|
25
|
-
`}`,
|
|
26
|
-
].join("\n"),
|
|
27
|
-
"color:green",
|
|
28
|
-
"",
|
|
29
|
-
);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
let tsConfigFilename = globalThis.Deno ? "deno.json" : "tsconfig.json";
|
|
33
|
-
let tsConfig = Object.create(null);
|
|
34
|
-
try {
|
|
35
|
-
const data = await readFile(tsConfigFilename, "utf8");
|
|
36
|
-
tsConfig = JSON.parse(data);
|
|
37
|
-
} catch {
|
|
38
|
-
// ignore
|
|
39
|
-
}
|
|
40
|
-
const compilerOptions = tsConfig.compilerOptions ?? (tsConfig.compilerOptions = {});
|
|
41
|
-
if (compilerOptions.jsx === "react-jsx" && compilerOptions.jsxImportSource === "mono-jsx") {
|
|
42
|
-
console.log("%cmono-jsx already setup.","color:grey");
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
if (!globalThis.Deno) {
|
|
46
|
-
compilerOptions.module ??= "es2022";
|
|
47
|
-
compilerOptions.moduleResolution ??= "bundler";
|
|
48
|
-
}
|
|
49
|
-
compilerOptions.jsx = "react-jsx";
|
|
50
|
-
compilerOptions.jsxImportSource = "mono-jsx";
|
|
51
|
-
await writeFile(tsConfigFilename, JSON.stringify(tsConfig, null, 2));
|
|
52
|
-
console.log("✅ mono-jsx setup complete.")
|
|
53
|
-
}
|