@toonstrip/next 0.1.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 +56 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8 -0
- package/dist/server.d.ts +29 -0
- package/dist/server.js +10 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @toonstrip/next
|
|
2
|
+
|
|
3
|
+
`@toonstrip/react`'s `<ComicStrip>` behind an App-Router-safe `'use client'` boundary,
|
|
4
|
+
plus `@toonstrip/next/server`'s `renderPlaceholder` for a real SSR PNG placeholder — no
|
|
5
|
+
layout shift on hydration, and content visible with JavaScript disabled.
|
|
6
|
+
|
|
7
|
+
Part of [toonstrip](https://github.com/dkdev24/toonstrip), a
|
|
8
|
+
framework-embeddable comic-strip renderer. Docs, playground, and
|
|
9
|
+
changelog: [toonstrip.danielkimdev.com](https://toonstrip.danielkimdev.com).
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
npm install @toonstrip/next @toonstrip/cli @toonstrip/pack-comic-chat
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`@toonstrip/cli` must be your app's own direct dependency, not only reachable
|
|
18
|
+
transitively through `@toonstrip/next` — see
|
|
19
|
+
[`docs/next.md`](https://github.com/dkdev24/toonstrip/blob/main/docs/next.md#native-dependency)
|
|
20
|
+
for why, and for the `next.config.mjs` `serverExternalPackages` setting it also needs.
|
|
21
|
+
|
|
22
|
+
## Use
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
// app/page.tsx — a Server Component; no "use client" needed here
|
|
26
|
+
import { ComicStrip } from "@toonstrip/next";
|
|
27
|
+
import { renderPlaceholder } from "@toonstrip/next/server";
|
|
28
|
+
import doc from "./my-strip.json";
|
|
29
|
+
|
|
30
|
+
export default async function Page() {
|
|
31
|
+
const placeholder = await renderPlaceholder(doc, { width: 640 });
|
|
32
|
+
return (
|
|
33
|
+
<ComicStrip
|
|
34
|
+
document={doc}
|
|
35
|
+
packs={["/packs/comic-chat/"]}
|
|
36
|
+
placeholder={placeholder}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Same props as `@toonstrip/react`'s `<ComicStrip>`. `renderPlaceholder` is a separate
|
|
43
|
+
`@toonstrip/next/server` entry point (not the package root) because it pulls in
|
|
44
|
+
`@toonstrip/cli`'s native canvas dependency — call it only from a Server Component or
|
|
45
|
+
other server-only code.
|
|
46
|
+
|
|
47
|
+
## Worked example
|
|
48
|
+
|
|
49
|
+
See `examples/next-app` in the
|
|
50
|
+
[repo](https://github.com/dkdev24/toonstrip/tree/main/examples/next-app) for a complete,
|
|
51
|
+
runnable App Router app. Full field reference:
|
|
52
|
+
[`docs/next.md`](https://github.com/dkdev24/toonstrip/blob/main/docs/next.md).
|
|
53
|
+
|
|
54
|
+
## License
|
|
55
|
+
|
|
56
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
// The client-side, App-Router-safe boundary (dev plan §13.4): `@toonstrip/react`'s
|
|
3
|
+
// `<ComicStrip>` uses `useRef`/`useEffect`, so it must be marked a Client
|
|
4
|
+
// Component wherever a Server Component imports it. `packages/element`'s own
|
|
5
|
+
// SSR guards (customElements/HTMLElement) are what keep the *module* safe to
|
|
6
|
+
// import during the server render pass that still happens for a "use client"
|
|
7
|
+
// tree; this directive is the separate, RSC-protocol half of that story.
|
|
8
|
+
export { ComicStrip } from "@toonstrip/react";
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-only SSR placeholder helper (dev plan §13.4). Reuses §8's existing
|
|
3
|
+
* headless-canvas render path (`packages/cli`, already published) to produce
|
|
4
|
+
* a real PNG of the strip at request/build time, ready to hand to
|
|
5
|
+
* `<ComicStrip placeholder>` as the light-DOM image it shows until client JS
|
|
6
|
+
* hydrates and paints the live canvas.
|
|
7
|
+
*
|
|
8
|
+
* A separate entry point ("@toonstrip/next/server", not the package root):
|
|
9
|
+
* `@toonstrip/cli` pulls in `@napi-rs/canvas`, a native Node addon that must
|
|
10
|
+
* never end up in a client bundle. Only import this from a Server Component
|
|
11
|
+
* or other server-only code.
|
|
12
|
+
*
|
|
13
|
+
* `@toonstrip/cli` is imported dynamically with `webpackIgnore` rather than
|
|
14
|
+
* statically: Next's `serverExternalPackages` opt-out is meant to stop it
|
|
15
|
+
* being bundled, but a workspace package reached through a symlinked,
|
|
16
|
+
* non-`node_modules` local package (`@toonstrip/cli`, here) doesn't reliably
|
|
17
|
+
* hit that path, and webpack then tries to statically bundle
|
|
18
|
+
* `@napi-rs/canvas`'s platform-detection `require()`s for every OS/arch and
|
|
19
|
+
* fails on the binary `.node` files. `webpackIgnore` leaves this import
|
|
20
|
+
* completely alone, so Node resolves and loads it normally at request time —
|
|
21
|
+
* from the *bundled output file's* location, though, so the consuming app
|
|
22
|
+
* must list `@toonstrip/cli` as its own direct dependency (not only reachable
|
|
23
|
+
* transitively through `@toonstrip/next`) for that resolution to succeed
|
|
24
|
+
* under pnpm's default strict `node_modules` layout.
|
|
25
|
+
*/
|
|
26
|
+
import type { ComicStripPlaceholder } from "@toonstrip/react";
|
|
27
|
+
import type { ComicStripDocument } from "@toonstrip/schema";
|
|
28
|
+
import type { RenderOptions } from "@toonstrip/cli";
|
|
29
|
+
export declare function renderPlaceholder(doc: ComicStripDocument, options?: RenderOptions): Promise<ComicStripPlaceholder>;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export async function renderPlaceholder(doc, options = {}) {
|
|
2
|
+
const { renderDocument } = await import(/* webpackIgnore: true */ "@toonstrip/cli");
|
|
3
|
+
const { png, cssWidth, cssHeight } = await renderDocument(doc, options);
|
|
4
|
+
// The <img>'s width/height are CSS pixels (RenderResult.cssWidth/cssHeight),
|
|
5
|
+
// not the (possibly `scale`d-up) PNG's own pixel size — an `<img>` displays
|
|
6
|
+
// at its width/height attributes regardless of the file's actual pixel
|
|
7
|
+
// density, so using the PNG's raw pixel size here would render it 2x too
|
|
8
|
+
// large (the default `scale`) and shift layout on hydration.
|
|
9
|
+
return { src: `data:image/png;base64,${png.toString("base64")}`, width: cssWidth, height: cssHeight };
|
|
10
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@toonstrip/next",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "@toonstrip/react behind an App-Router-safe 'use client' boundary, plus a server-only SSR placeholder helper.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./server": {
|
|
15
|
+
"types": "./dist/server.d.ts",
|
|
16
|
+
"default": "./dist/server.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc -p tsconfig.json",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"lint": "tsc -p tsconfig.json --noEmit"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
29
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@toonstrip/cli": "workspace:*",
|
|
33
|
+
"@toonstrip/react": "workspace:*",
|
|
34
|
+
"@toonstrip/schema": "workspace:*"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/react": "^18.3.12",
|
|
38
|
+
"@types/react-dom": "^18.3.1",
|
|
39
|
+
"react": "^18.3.1",
|
|
40
|
+
"react-dom": "^18.3.1",
|
|
41
|
+
"typescript": "^5.6.3",
|
|
42
|
+
"vitest": "^2.1.4"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"keywords": [
|
|
48
|
+
"toonstrip",
|
|
49
|
+
"comic",
|
|
50
|
+
"next",
|
|
51
|
+
"nextjs",
|
|
52
|
+
"ssr"
|
|
53
|
+
],
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://github.com/dkdev24/toonstrip.git",
|
|
57
|
+
"directory": "packages/next"
|
|
58
|
+
},
|
|
59
|
+
"homepage": "https://github.com/dkdev24/toonstrip#readme",
|
|
60
|
+
"bugs": "https://github.com/dkdev24/toonstrip/issues"
|
|
61
|
+
}
|