fleuron-react 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 ADDED
@@ -0,0 +1,28 @@
1
+ # fleuron-react
2
+
3
+ The [fleuron](https://fleuron.typeworks.dev/) preview, as a
4
+ React component.
5
+
6
+ ```sh
7
+ npm install fleuron-react fleuron react
8
+ ```
9
+
10
+ ```jsx
11
+ import { Preview } from 'fleuron-react';
12
+
13
+ <Preview markdown={markdown} css={css} page={page} zoom={1.5} />;
14
+ ```
15
+
16
+ The manuscript and the stylesheet are props, so a keystroke is a
17
+ re-render and the engine is handed the one input that changed. A
18
+ render the reader has already typed past paints nothing.
19
+
20
+ `onMount` hands back the preview itself, for the page count, the
21
+ warnings and the PDF export.
22
+
23
+ There is no engine logic in here. This package hands `fleuron`'s
24
+ `Preview` an element and passes props along to it. React stays out of
25
+ the binding package, and deleting this one leaves a preview a plain
26
+ page can still mount.
27
+
28
+ MIT or Apache-2.0.
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The fleuron preview, as a React component.
3
+ *
4
+ * There is no engine logic in here and there is not meant to be:
5
+ * everything this file knows how to do is hand `fleuron`'s
6
+ * `Preview` an element and pass props along to it. React stays out
7
+ * of the binding package for the same reason, that a host which does
8
+ * not use it should not download it, and a host that deletes this one
9
+ * still has a preview a plain page can mount.
10
+ */
11
+ import { Preview as Mounted, type PreviewOptions } from 'fleuron';
12
+ import { type CSSProperties } from 'react';
13
+ /** What the component takes, over what a preview takes. */
14
+ export interface PreviewProps extends PreviewOptions {
15
+ /** The manuscript, as markdown. */
16
+ markdown?: string;
17
+ /** The author stylesheet, as CSS text. */
18
+ css?: string;
19
+ /** What the manuscript is called, which is what an edit replaces. */
20
+ name?: string;
21
+ /** The page to show, counting from 1. */
22
+ page?: number;
23
+ /** Points to CSS pixels. */
24
+ zoom?: number;
25
+ /**
26
+ * The images the manuscript refers to, by the url it names them
27
+ * by. One that arrives after the book does is registered when it
28
+ * arrives, and the pages are laid out again around it.
29
+ */
30
+ images?: Record<string, Uint8Array>;
31
+ /** Passed to the element the preview mounts into. */
32
+ className?: string;
33
+ /** The same. */
34
+ style?: CSSProperties;
35
+ /** The preview itself, once it is mounted. */
36
+ onMount?: (preview: Mounted) => void;
37
+ }
38
+ /**
39
+ * A book on screen. The manuscript and the stylesheet are props, so
40
+ * a keystroke is a re-render and the engine is handed the one input
41
+ * that changed.
42
+ */
43
+ export declare function Preview(props: PreviewProps): React.ReactElement;
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAExE,2DAA2D;AAC3D,MAAM,WAAW,YAAa,SAAQ,cAAc;IAClD,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACpC,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACtC;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,KAAK,CAAC,YAAY,CA6D/D"}
package/dist/index.js ADDED
@@ -0,0 +1,74 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * The fleuron preview, as a React component.
4
+ *
5
+ * There is no engine logic in here and there is not meant to be:
6
+ * everything this file knows how to do is hand `fleuron`'s
7
+ * `Preview` an element and pass props along to it. React stays out
8
+ * of the binding package for the same reason, that a host which does
9
+ * not use it should not download it, and a host that deletes this one
10
+ * still has a preview a plain page can mount.
11
+ */
12
+ import { Preview as Mounted } from 'fleuron';
13
+ import { useEffect, useRef, useState } from 'react';
14
+ /**
15
+ * A book on screen. The manuscript and the stylesheet are props, so
16
+ * a keystroke is a re-render and the engine is handed the one input
17
+ * that changed.
18
+ */
19
+ export function Preview(props) {
20
+ const { markdown, css, name, page, zoom, images, className, style, onMount, ...options } = props;
21
+ const element = useRef(null);
22
+ const [preview, setPreview] = useState(null);
23
+ // Mounted once. The options a preview is opened with are fixed for
24
+ // its life; everything that can change afterwards is a prop below.
25
+ useEffect(() => {
26
+ let wanted = true;
27
+ let opened = null;
28
+ void Mounted.mount(element.current, options).then((mounted) => {
29
+ opened = mounted;
30
+ if (!wanted) {
31
+ mounted.destroy();
32
+ return;
33
+ }
34
+ setPreview(mounted);
35
+ onMount?.(mounted);
36
+ });
37
+ return () => {
38
+ wanted = false;
39
+ opened?.destroy();
40
+ };
41
+ }, []);
42
+ useEffect(() => {
43
+ if (preview !== null && css !== undefined) {
44
+ void preview.setStyle(css);
45
+ }
46
+ }, [preview, css]);
47
+ useEffect(() => {
48
+ if (preview !== null && markdown !== undefined) {
49
+ void preview.setMarkdown(markdown, name);
50
+ }
51
+ }, [preview, markdown, name]);
52
+ useEffect(() => {
53
+ if (preview !== null && page !== undefined) {
54
+ preview.page = page;
55
+ }
56
+ }, [preview, page]);
57
+ useEffect(() => {
58
+ if (preview !== null && zoom !== undefined) {
59
+ preview.zoom = zoom;
60
+ }
61
+ }, [preview, zoom]);
62
+ // Images are registered rather than passed at mount, so one that
63
+ // arrives after the manuscript still reaches the page. A url the
64
+ // session already holds costs no layout.
65
+ useEffect(() => {
66
+ if (preview !== null && images !== undefined) {
67
+ for (const [url, bytes] of Object.entries(images)) {
68
+ void preview.addImage(url, bytes);
69
+ }
70
+ }
71
+ }, [preview, images]);
72
+ return _jsx("div", { ref: element, className: className, style: style });
73
+ }
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "fleuron-react",
3
+ "version": "0.1.0",
4
+ "description": "The fleuron preview as a React component, and nothing else",
5
+ "license": "MIT OR Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/zachhannum/fleuron.git",
9
+ "directory": "packages/react"
10
+ },
11
+ "homepage": "https://fleuron.typeworks.dev/",
12
+ "type": "module",
13
+ "sideEffects": false,
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "default": "./dist/index.js"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc -p tsconfig.json",
25
+ "test": "npm run build && node test/wrapper.mjs"
26
+ },
27
+ "peerDependencies": {
28
+ "fleuron": "0.1.0",
29
+ "react": ">=18"
30
+ },
31
+ "devDependencies": {
32
+ "fleuron": "file:../../crates/fleuron-wasm/npm",
33
+ "@types/react": "^19.2.2",
34
+ "react": "^19.2.0",
35
+ "typescript": "^5.9.2"
36
+ },
37
+ "engines": {
38
+ "node": ">=20"
39
+ }
40
+ }