@objectifthunes/react-three-book 0.1.0 → 0.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 +214 -0
  2. package/package.json +2 -2
package/README.md ADDED
@@ -0,0 +1,214 @@
1
+ # @objectifthunes/react-three-book
2
+
3
+ A procedural, interactive 3D book for [React Three Fiber](https://docs.pmnd.rs/react-three-fiber) — drag pages to turn them, apply textures to every surface, and drop `<Book>` into your R3F scene like any other component.
4
+
5
+ <p align="center">
6
+ <img src="https://raw.githubusercontent.com/ObjectifThunes/react-three-book/main/docs/images/default.png" width="49%" alt="Closed book" />
7
+ <img src="https://raw.githubusercontent.com/ObjectifThunes/react-three-book/main/docs/images/open-half.png" width="49%" alt="Book opened halfway" />
8
+ </p>
9
+ <p align="center">
10
+ <img src="https://raw.githubusercontent.com/ObjectifThunes/react-three-book/main/docs/images/page-curl.png" width="49%" alt="Page mid-curl" />
11
+ <img src="https://raw.githubusercontent.com/ObjectifThunes/react-three-book/main/docs/images/demo-ui.png" width="49%" alt="Demo app with tweakable controls" />
12
+ </p>
13
+
14
+ ## Features
15
+
16
+ - **`<Book>` R3F component** — handles init / update / dispose automatically; rebuilds cleanly via React's `key` prop.
17
+ - **`<BookInteraction>`** — declarative pointer-drag wiring for interactive page turning; auto-discovers the book from context.
18
+ - **Hooks** — `useBookControls`, `useAutoTurn`, `useBookState`, `useBookContent`, `usePageTurning`.
19
+ - **BookContext** — child components access the book instance without prop-drilling.
20
+ - **Per-surface textures** — assign a `THREE.Texture` (or `null`) to each cover side and page side independently.
21
+ - **Configurable geometry** — page/cover width, height, thickness, stiffness, color.
22
+ - **Texture utilities** — `createPageTexture`, `drawImageWithFit`, `loadImage` included.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ npm install @objectifthunes/react-three-book three @react-three/fiber react react-dom
28
+ ```
29
+
30
+ ```bash
31
+ pnpm add @objectifthunes/react-three-book three @react-three/fiber react react-dom
32
+ ```
33
+
34
+ Peer dependencies: `three >= 0.150.0`, `react >= 18.0.0`, `@react-three/fiber >= 8.0.0`.
35
+
36
+ ## Quick Start
37
+
38
+ ```tsx
39
+ import { Canvas } from '@react-three/fiber';
40
+ import { OrbitControls } from '@react-three/drei';
41
+ import * as THREE from 'three';
42
+ import {
43
+ Book,
44
+ BookContent,
45
+ BookDirection,
46
+ BookInteraction,
47
+ StapleBookBinding,
48
+ useBookContent,
49
+ } from '@objectifthunes/react-three-book';
50
+
51
+ function Scene() {
52
+ const orbitRef = useRef(null);
53
+
54
+ const content = useBookContent(() => {
55
+ const c = new BookContent();
56
+ c.direction = BookDirection.LeftToRight;
57
+ c.covers.push(frontOuterTex, frontInnerTex, backInnerTex, backOuterTex);
58
+ c.pages.push(page1Tex, page2Tex, page3Tex, page4Tex);
59
+ return c;
60
+ }, []);
61
+
62
+ return (
63
+ <>
64
+ <OrbitControls ref={orbitRef} />
65
+ <Book
66
+ content={content}
67
+ binding={new StapleBookBinding()}
68
+ castShadows
69
+ alignToGround
70
+ pagePaperSetup={{ width: 2, height: 3, thickness: 0.02, stiffness: 0.2, color: new THREE.Color(1, 1, 1), material: null }}
71
+ coverPaperSetup={{ width: 2.1, height: 3.1, thickness: 0.04, stiffness: 0.5, color: new THREE.Color(1, 1, 1), material: null }}
72
+ >
73
+ <BookInteraction orbitControlsRef={orbitRef} />
74
+ </Book>
75
+ </>
76
+ );
77
+ }
78
+
79
+ export default function App() {
80
+ return (
81
+ <Canvas shadows camera={{ position: [0, 2, 5], fov: 45 }}>
82
+ <Scene />
83
+ </Canvas>
84
+ );
85
+ }
86
+ ```
87
+
88
+ ## Triggering a Rebuild
89
+
90
+ Change the `key` prop — React unmounts and remounts `<Book>`, which runs a clean dispose → init cycle:
91
+
92
+ ```tsx
93
+ <Book key={buildKey} content={content} binding={binding} ... />
94
+ ```
95
+
96
+ ## Imperative Access
97
+
98
+ Forward a ref to get the underlying `ThreeBook` instance:
99
+
100
+ ```tsx
101
+ const bookRef = useRef<ThreeBook>(null);
102
+ <Book ref={bookRef} ... />
103
+
104
+ bookRef.current?.setOpenProgress(0.5);
105
+ ```
106
+
107
+ ## Hooks
108
+
109
+ ### `useBookControls(bookRef?)`
110
+
111
+ ```tsx
112
+ const { setOpenProgress, setOpenProgressByIndex, stopTurning } = useBookControls();
113
+ ```
114
+
115
+ ### `useAutoTurn(bookRef?)`
116
+
117
+ ```tsx
118
+ const { turnNext, turnPrev, turnAll, startAutoTurning, cancelPendingAutoTurns } = useAutoTurn();
119
+
120
+ turnNext();
121
+ turnPrev();
122
+ turnAll(AutoTurnDirection.Next);
123
+ startAutoTurning(AutoTurnDirection.Next, settings, 5, 0.3);
124
+ ```
125
+
126
+ ### `useBookState(bookRef?)`
127
+
128
+ Reactive snapshot updated every frame — triggers re-renders only when something actually changes:
129
+
130
+ ```tsx
131
+ const { isTurning, isIdle, isAutoTurning, paperCount } = useBookState();
132
+ ```
133
+
134
+ ### `useBookContent(factory, deps)`
135
+
136
+ Creates a `BookContent` and disposes its `THREE.Texture`s automatically when `deps` change or the component unmounts:
137
+
138
+ ```tsx
139
+ const content = useBookContent(() => {
140
+ const c = new BookContent();
141
+ c.covers.push(myTexture);
142
+ c.pages.push(pageA, pageB);
143
+ return c;
144
+ }, [rebuildKey]);
145
+ ```
146
+
147
+ ## Context
148
+
149
+ Any component rendered inside `<Book>` can access the instance without a ref:
150
+
151
+ ```tsx
152
+ function PageButtons() {
153
+ const { turnNext, turnPrev } = useAutoTurn();
154
+ return (
155
+ <>
156
+ <button onClick={turnPrev}>◀</button>
157
+ <button onClick={turnNext}>▶</button>
158
+ </>
159
+ );
160
+ }
161
+
162
+ <Book ...>
163
+ <BookInteraction />
164
+ <PageButtons />
165
+ </Book>
166
+ ```
167
+
168
+ ## Texture Utilities
169
+
170
+ ```tsx
171
+ import { createPageTexture, drawImageWithFit, loadImage } from '@objectifthunes/react-three-book';
172
+
173
+ const tex = createPageTexture('#ff0000', 'Cover', myImage, 'cover', true);
174
+
175
+ const result = await loadImage(file); // { image, objectUrl } | null
176
+ ```
177
+
178
+ ## Content Model
179
+
180
+ **Covers** — 4 entries, one per surface:
181
+
182
+ | Index | Surface |
183
+ |-------|---------|
184
+ | 0 | Front outer |
185
+ | 1 | Front inner |
186
+ | 2 | Back inner |
187
+ | 3 | Back outer |
188
+
189
+ **Pages** — ordered list of page-side textures. Each entry can be a `THREE.Texture`, an `IPageContent` implementation, or `null` (renders the base paper color).
190
+
191
+ ## Auto Turn
192
+
193
+ ```tsx
194
+ import { AutoTurnDirection, AutoTurnMode, AutoTurnSettings } from '@objectifthunes/react-three-book';
195
+
196
+ const { startAutoTurning } = useAutoTurn();
197
+
198
+ const settings = new AutoTurnSettings();
199
+ settings.mode = AutoTurnMode.Edge;
200
+ startAutoTurning(AutoTurnDirection.Next, settings, 3);
201
+ ```
202
+
203
+ ## API Surface
204
+
205
+ | Category | Exports |
206
+ |----------|---------|
207
+ | Components | `Book`, `BookInteraction` |
208
+ | Context | `BookContext`, `useBook`, `useRequiredBook` |
209
+ | Hooks | `useBookRef`, `useBookContent`, `useBookControls`, `useAutoTurn`, `useBookState`, `usePageTurning` |
210
+ | Texture utils | `createPageTexture`, `drawImageWithFit`, `loadImage` |
211
+ | Core | `ThreeBook`, `BookContent`, `BookDirection`, `Paper`, `PaperSetup` |
212
+ | Binding | `BookBinding`, `StapleBookBinding`, `StapleBookBound`, `StapleSetup` |
213
+ | Content | `IPageContent`, `PageContent`, `SpritePageContent2` |
214
+ | Auto turn | `AutoTurnDirection`, `AutoTurnMode`, `AutoTurnSettings`, `AutoTurnSetting` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectifthunes/react-three-book",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -10,7 +10,7 @@
10
10
  "types": "./dist/index.d.ts"
11
11
  }
12
12
  },
13
- "files": ["dist"],
13
+ "files": ["dist", "README.md"],
14
14
  "scripts": {
15
15
  "build": "vite build",
16
16
  "typecheck": "tsc --noEmit",