jops-core 1.1.0 → 1.1.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.
Files changed (2) hide show
  1. package/README.md +35 -24
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -54,7 +54,14 @@ The import map lets your app modules use `import { View } from "jops-core"`. The
54
54
 
55
55
  `App.js` is your entry point — a file you provide that instantiates your root `View` and mounts it to the page. Point `data-app` to wherever you place it.
56
56
 
57
- Replace `@latest` with a specific version (e.g. `@1.0.4`) to pin. No build step, no npm, no bundler.
57
+ Replace `@latest` with a specific version (e.g. `@1.1.1`) to pin. No build step, no npm, no bundler.
58
+
59
+ By default the app renders into `<body>`. To render it into an element instead (keeping the rest of the page), add `data-root` with the element's id:
60
+
61
+ ```html
62
+ <div id="app"></div>
63
+ <script type="module" src="https://cdn.jsdelivr.net/npm/jops-core@latest/lib/jops-core.min.js" data-app="./src/App.js" data-root="app"></script>
64
+ ```
58
65
 
59
66
  > **Note:** ES modules require an HTTP server — open your project with `npx serve` (or any static server) rather than double-clicking `index.html`. Browsers block `import` on `file://` URLs.
60
67
 
@@ -378,17 +385,33 @@ The root `<div>` has `position: relative`, which the Router's slide and fade ani
378
385
  - **Next.js owns the CSS.** `setStyle()` has no effect inside Next.js (a console message says so once). Tailwind CSS v4 also scans the files in `public/`, so Tailwind classes in JOPS layouts and views are generated by the Next.js build. Write class names as complete literal strings (`"bg-sky-50"`, never `` `bg-${color}-50` ``). Put other CSS in `globals.css` or a CSS file imported by the page, scoped under the app's root class (`.my-app table td { … }`), since it applies to the whole site.
379
386
  - **Backend calls:** `fetch("/api/…")` to Route Handlers on the same origin; the session cookie is sent automatically. A JOPS app can't call Server Actions.
380
387
  - **One JOPS app per page.** `Router`, `Store` and `EventBus` are page-wide singletons.
388
+ - **Always use `JopsApp` inside a Next.js page.** Don't add the jops-core `<script>` or an import map to a page or layout yourself: React doesn't run scripts it renders on soft navigation, and nothing would end the app when the page is left.
389
+
390
+ ### Deploying
391
+
392
+ The result is a standard Next.js app: `npm run build` produces `.next/`, and it runs on a Node.js server when it uses server features such as Route Handlers. Deploy it like any Next.js app (see the [Next.js deployment docs](https://nextjs.org/docs/app/getting-started/deploying)). Points specific to JOPS:
393
+
394
+ - **Deploy `public/` with the app**: the whole JOPS app and the library live there. With `output: "standalone"`, copy `public/` (and `.next/static/`) into `.next/standalone/` yourself.
395
+ - **Caching:** files in `public/` are not content-hashed, so a CDN or the browser may keep serving an old `jops-core.min.js` or view after a deploy. Use short cache headers for those paths, or versioned paths.
396
+ - **Library version:** run `npx jops-core update` after updating the package and before `npm run build`.
397
+
398
+ ---
399
+
400
+ ## Embedding JOPS in Other Pages (Hosted Mode)
381
401
 
382
- ### Without React: hosted mode
402
+ A JOPS app can run inside any page that is not a React component: a plain HTML page, or a page rendered by another server framework (PHP, ASP.NET, Rails, Django, …). This is the mechanism `JopsApp` uses in Next.js; **inside a Next.js page, use `JopsApp`** instead (see [Next.js Integration](#nextjs-integration)).
383
403
 
384
- `JopsApp` uses hosted mode, which any host page can use directly. Load the library with `data-host` and no `data-app`: nothing starts automatically, and `window.JOPS` exposes `mount()` and `unmount()` (a `jops:ready` event fires when it is available):
404
+ Load the library with `data-host` and no `data-app`: nothing starts automatically, and `window.JOPS` exposes `mount()` and `unmount()` (a `jops:ready` event fires when it is available). The import map and the script `src` must be the same URL, so the page has a single jops-core instance.
385
405
 
386
406
  ```html
387
- <script type="importmap">{ "imports": { "jops-core": "/lib/jops-core.min.js" } }</script>
388
- <script type="module" src="/lib/jops-core.min.js" data-host></script>
407
+ <script type="importmap">
408
+ { "imports": { "jops-core": "https://cdn.jsdelivr.net/npm/jops-core@latest/lib/jops-core.min.js" } }
409
+ </script>
410
+ <script type="module" src="https://cdn.jsdelivr.net/npm/jops-core@latest/lib/jops-core.min.js" data-host></script>
411
+
389
412
  <div id="app" style="position: relative"></div>
390
413
  <script type="module">
391
- const start = () => window.JOPS.mount({ app: "/my-app/App.js", root: document.getElementById("app") });
414
+ const start = () => window.JOPS.mount({ app: "./my-app/App.js", root: document.getElementById("app") });
392
415
  window.JOPS ? start() : window.addEventListener("jops:ready", start, { once: true });
393
416
  </script>
394
417
  ```
@@ -396,24 +419,12 @@ The root `<div>` has `position: relative`, which the Router's slide and fade ani
396
419
  | Function | Description |
397
420
  | --- | --- |
398
421
  | `mount({ app, root })` | Imports `app` and creates its default export; the root view renders into `root` (an `HTMLElement`) instead of `<body>`. Returns a promise of the App instance |
399
- | `unmount()` | Ends the app completely (see "App lifecycle" above). Safe to call more than once; `mount()` can start an app again afterwards |
400
-
401
- Both are also exported by the module (`import { mount, unmount } from "jops-core"`) for modules running on the same page. In hosted mode the Android back button integration is off.
402
-
403
- A **standalone** app (started by `data-app`) can render into an element instead of `<body>` with `data-root`:
404
-
405
- ```html
406
- <div id="app"></div>
407
- <script type="module" src="/lib/jops-core.min.js" data-app="./src/App.js" data-root="app"></script>
408
- ```
409
-
410
- ### Deploying
411
-
412
- The result is a standard Next.js app: `npm run build` produces `.next/`, and it runs on a Node.js server when it uses server features such as Route Handlers. Deploy it like any Next.js app (see the [Next.js deployment docs](https://nextjs.org/docs/app/getting-started/deploying)). Points specific to JOPS:
422
+ | `unmount()` | Ends the app completely: destroys the Router and every view, empties `root`, clears `Store` and `EventBus`, and restores the history methods JOPS wrapped. Safe to call more than once; `mount()` can start an app again afterwards |
413
423
 
414
- - **Deploy `public/` with the app**: the whole JOPS app and the library live there. With `output: "standalone"`, copy `public/` (and `.next/static/`) into `.next/standalone/` yourself.
415
- - **Caching:** files in `public/` are not content-hashed, so a CDN or the browser may keep serving an old `jops-core.min.js` or view after a deploy. Use short cache headers for those paths, or versioned paths.
416
- - **Library version:** run `npx jops-core update` after updating the package and before `npm run build`.
424
+ - **Paths depend on where the library comes from.** With the library from the CDN (as above), JOPS resolves paths relative to the **hosting page**: `./my-app/App.js` on `example.com/admin/users` means `example.com/admin/my-app/App.js`, and root-absolute `/my-app/...` paths are turned page-relative too. With a vendored library on the same origin (`/lib/jops-core.min.js` in both the import map and `src`), write root-absolute paths (`/my-app/App.js`, `src="/my-app/Users.js"`), which work on every page.
425
+ - **Ending the app:** a full page load ends it anyway. A host that removes the app's element without a page load, or navigates with `history.pushState()`, calls `unmount()`; when history moves to another path the Router also ends the app by itself.
426
+ - `mount` and `unmount` are also exported by the module (`import { mount, unmount } from "jops-core"`) for modules running on the same page.
427
+ - In hosted mode `setStyle()` has no effect (the host page provides the CSS) and the Android back button integration is off.
417
428
 
418
429
  ---
419
430
 
@@ -819,7 +830,7 @@ Prefer the owned form inside views. A global subscription made by a view keeps t
819
830
 
820
831
  ### `mount()` / `unmount()` — Functions
821
832
 
822
- Start and end an app in a host page (hosted mode). Used by `JopsApp` in Next.js; see [Without React: hosted mode](#without-react-hosted-mode). The page must load jops-core with `data-host` (otherwise it starts `data-app` / `./src/App.js` by itself); `window.JOPS.mount` / `window.JOPS.unmount` are the same functions.
833
+ Start and end an app in a host page (hosted mode). Used by `JopsApp` in Next.js; see [Embedding JOPS in Other Pages](#embedding-jops-in-other-pages-hosted-mode). The page must load jops-core with `data-host` (otherwise it starts `data-app` / `./src/App.js` by itself); `window.JOPS.mount` / `window.JOPS.unmount` are the same functions.
823
834
 
824
835
  ```js
825
836
  import { mount, unmount } from "jops-core";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jops-core",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "A no-bundler, OOP-first SPA framework with Android-style view composition",
5
5
  "type": "module",
6
6
  "exports": {