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 CHANGED
@@ -309,22 +309,63 @@ function Counter(
309
309
  }
310
310
  ```
311
311
 
312
- ### Using Computed Properties
312
+ ### Using App State
313
313
 
314
- You can use `this.computed` to create computed properties based on state. The computed property will automatically update when the state changes:
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 = 'Hello, world';
363
+ this.input = "Welcome to mono-jsx!";
319
364
  return (
320
365
  <div>
321
- <h1>{this.computed(() = this.input + "!")}</h1>
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 = "Hello, world";
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 = "Hello, world";
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
- <Dash />
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
- }