Skip to content

Commit fd44aa0

Browse files
committed
move core functional to a custom hook
1 parent ee8d602 commit fd44aa0

10 files changed

Lines changed: 530 additions & 470 deletions

File tree

README.md

Lines changed: 76 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,50 +26,92 @@ Earlier releases exposed a **class** component. The default export is now a **fu
2626
| Area | Notes |
2727
|------|--------|
2828
| **React versions** | Supported as **peer** dependencies: **React 18** and **React 19** (with matching `react-dom`). |
29-
| **Import** | Same as before: `import ReactPannellum from "react-pannellum"`. |
30-
| **Static / imperative API** | Methods such as `ReactPannellum.getPitch()`, `loadScene`, `addHotSpot`, etc. remain on the **default export** object (same call pattern as the old class statics). |
31-
| **Props** | Same props; **`prop-types` was removed** from this package — TypeScript users get exported types (`ReactPannellumProps`, etc.); plain JS apps do not get runtime prop validation from the library. |
32-
| **Children** | Pass **`children` as normal JSX children** inside `<ReactPannellum>…</ReactPannellum>` (a root `<div>` wraps them). |
29+
| **Import** | `import ReactPannellum, { usePannellum } from "react-pannellum"` (default export is the viewer component; **`usePannellum`** is the imperative API). |
30+
| **Imperative API** | Use the **`usePannellum()`** hook from a component rendered **inside** `<ReactPannellum>...</ReactPannellum>`. It returns an object with all viewer methods (`getPitch`, `setYaw`, `loadScene`, …). **Static methods on the component and named exports such as `getConfig` are removed** — migrate to the hook. |
31+
| **Props** | Same props; **`prop-types` was removed** from this package — TypeScript users get exported types (`ReactPannellumProps`, `PannellumViewerApi`, etc.); plain JS apps do not get runtime prop validation from the library. |
32+
| **Children** | **Required for `usePannellum`:** render a child (or descendants) that calls the hook. Pass **`children` as normal JSX children** inside `<ReactPannellum>` (a root `<div>` wraps them). |
3333
| **TypeScript** | Types ship with the package (`"types"` in `package.json`). |
3434
| **Build output** | The library is compiled to **ESM** in `dist/` (no CommonJS bundle). |
3535

3636
Internals (hooks, cleanup, listener registration) changed; if you relied on undocumented behavior or private APIs, re-test after upgrading.
3737

3838
## Usage
3939

40-
1. [Config props](#config)
41-
2. [API Events](#apiEvents)
42-
3. [API Event Listeners](#apiEventListeners)
40+
1. [`usePannellum` hook](#usePannellum)
41+
2. [Config props](#config)
42+
3. [Imperative API](#apiEvents)
43+
4. [Event listener props](#apiEventListeners)
44+
45+
### <a id="usePannellum"></a> `usePannellum()`
46+
47+
Call **`usePannellum()`** from any **descendant** of `<ReactPannellum>` (for example a child component). It returns a stable object of imperative methods for **that** viewer instance (`PannellumViewerApi` in TypeScript).
4348

4449
```tsx
4550
import { useCallback } from "react";
46-
import ReactPannellum, { getConfig } from "react-pannellum";
51+
import ReactPannellum, { usePannellum } from "react-pannellum";
52+
53+
function Toolbar() {
54+
const p = usePannellum();
4755

48-
export function Example() {
4956
const showConfig = useCallback(() => {
50-
console.log(getConfig());
51-
}, []);
57+
console.log(p.getConfig());
58+
}, [p]);
59+
60+
return (
61+
<button type="button" onClick={showConfig}>
62+
Log config
63+
</button>
64+
);
65+
}
5266

67+
export function Example() {
5368
const config = {
5469
autoRotate: -2,
5570
};
5671

5772
return (
58-
<div>
59-
<ReactPannellum
60-
id="1"
61-
sceneId="firstScene"
62-
imageSource="https://pannellum.org/images/alma.jpg"
63-
config={config}
64-
/>
65-
<button type="button" onClick={showConfig}>
66-
Log config
67-
</button>
68-
</div>
73+
<ReactPannellum
74+
id="1"
75+
sceneId="firstScene"
76+
imageSource="https://pannellum.org/images/alma.jpg"
77+
config={config}
78+
>
79+
<Toolbar />
80+
</ReactPannellum>
6981
);
7082
}
7183
```
7284

85+
Calling `usePannellum()` **outside** `<ReactPannellum>` (e.g. a sibling in the tree) throws — the hook reads from React context supplied by the viewer.
86+
87+
```tsx
88+
import ReactPannellum, { usePannellum } from "react-pannellum";
89+
90+
export function Example() {
91+
const p = usePannellum(); // Error: no provider above this component
92+
return <ReactPannellum id="x" sceneId="y" imageSource="" />;
93+
}
94+
```
95+
96+
### Full example (inline)
97+
98+
```tsx
99+
import ReactPannellum, { usePannellum } from "react-pannellum";
100+
101+
export function Example() {
102+
return (
103+
<ReactPannellum id="1" sceneId="firstScene" imageSource="https://pannellum.org/images/alma.jpg">
104+
<Inner />
105+
</ReactPannellum>
106+
);
107+
}
108+
109+
function Inner() {
110+
const p = usePannellum();
111+
return <button type="button" onClick={() => console.log(p.getPitch())}>Pitch</button>;
112+
}
113+
```
114+
73115
## <a id="config" ></a> Config props
74116

75117
### sceneId (required): string
@@ -391,11 +433,19 @@ Specifies an array containing RGB values [0, 1] that sets the background color f
391433

392434
If set to `true`, prevent displaying out-of-range areas of a partial panorama by constraining the yaw and the field-of-view. Even at the corners and edges of the canvas only areas actually belonging to the image (i.e., within [`minYaw`, `maxYaw`] and [`minPitch`, `maxPitch`]) are shown, thus setting the `backgroundColor` option is not needed if this option is set. Defaults to `false`.
393435

394-
## <a id="apiEvents" ></a> API Events
436+
## <a id="apiEvents" ></a> Imperative API (`usePannellum`)
437+
438+
The Pannellum **instance** is created **after mount** (inside a `useEffect`). Methods on the object returned by **`usePannellum()`** read the **current** viewer ref when invoked, so you can call them from callbacks (e.g. button clicks) even before the panorama has finished loading — many calls simply no-op or return `undefined` until the native viewer exists.
395439

396-
The viewer is created **after mount** (inside a `useEffect` in the implementation). **Do not call** the static imperative methods above **in the same synchronous turn as the first render** — the internal viewer may not exist yet, so you can get `undefined` / no-ops.
440+
Prefer **`onPanoramaLoaded`** when you need to run code exactly once after the panorama is ready.
441+
442+
In the reference below, assume:
443+
444+
```ts
445+
const p = usePannellum();
446+
```
397447

398-
Use **`onPanoramaLoaded`**, or a **`useEffect`** with an empty dependency array (runs after paint) so the component has mounted and the Pannellum instance exists.
448+
Then use **`p.isLoaded()`**, **`p.getPitch()`**, etc. (same names as before, without the old `ReactPannellum.` prefix or top-level `getPitch` imports).
399449

400450
> ### isLoaded
401451
>
@@ -568,7 +618,7 @@ Parameters:
568618

569619
> ### getCurrentScene
570620
>
571-
> Returns `object` with sceneId and current scene config.
621+
> Returns the **current scene id** (`string`), same as Pannellum’s `getScene()`. For the full config object, use **`getConfig()`**.
572622
573623
> ### getAllScenes
574624
>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-pannellum",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "A library show panorama image for react",
55
"author": "hoaiduyit",
66
"license": "MIT",

0 commit comments

Comments
 (0)