Skip to content

Commit ee8d602

Browse files
committed
Breaking Changes: Upgrade to react hooks, remove outdated package, support typescript
1 parent 177c468 commit ee8d602

19 files changed

Lines changed: 3798 additions & 25686 deletions

.babelrc

Lines changed: 0 additions & 8 deletions
This file was deleted.

.eslintrc

Lines changed: 0 additions & 32 deletions
This file was deleted.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11

22
# See https://help.github.com/ignore-files/ for more about ignoring files.
33

4+
# local Vite sample (npm link to parent); keep untracked
5+
sample/
6+
47
# dependencies
58
node_modules
69

README.md

Lines changed: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,72 @@
11
# react-pannellum
22

3-
> A library show panorama image for react
3+
> A React library for embedding [Pannellum](https://pannellum.org/) panorama viewers.
44
5-
> This library use source from [https://pannellum.org/](https://pannellum.org/)
5+
> This library bundles source derived from [pannellum.org](https://pannellum.org/).
66
7-
[![NPM](https://img.shields.io/npm/v/react-pannellum.svg)](https://www.npmjs.com/package/react-pannellum) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
7+
[![NPM](https://img.shields.io/npm/v/react-pannellum.svg)](https://www.npmjs.com/package/react-pannellum) ![TypeScript](https://img.shields.io/badge/TypeScript-5-blue)
88

99
## Install
1010

1111
```bash
12-
npm install --save react-pannellum
12+
npm install react-pannellum
1313
```
1414

15+
Peer dependencies **`react`** and **`react-dom`** (versions **^18** or **^19**) must be installed in your application.
16+
17+
## Requirements
18+
19+
- **React 18+** or **React 19** (with matching **React DOM**)
20+
- An **ESM** toolchain (Vite, webpack, Next.js, etc.). The published package uses [`"type": "module"`](https://nodejs.org/api/packages.html#type); **`require('react-pannellum')` is not supported** — use `import` (or dynamic `import()`).
21+
22+
## Migration (class component → hooks implementation)
23+
24+
Earlier releases exposed a **class** component. The default export is now a **function component** built with React hooks, but **the public API is intentionally stable**:
25+
26+
| Area | Notes |
27+
|------|--------|
28+
| **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). |
33+
| **TypeScript** | Types ship with the package (`"types"` in `package.json`). |
34+
| **Build output** | The library is compiled to **ESM** in `dist/` (no CommonJS bundle). |
35+
36+
Internals (hooks, cleanup, listener registration) changed; if you relied on undocumented behavior or private APIs, re-test after upgrading.
37+
1538
## Usage
1639

1740
1. [Config props](#config)
1841
2. [API Events](#apiEvents)
1942
3. [API Event Listeners](#apiEventListeners)
2043

21-
```jsx
22-
import React from "react";
44+
```tsx
45+
import { useCallback } from "react";
2346
import ReactPannellum, { getConfig } from "react-pannellum";
2447

25-
class Example extends React.Component {
26-
click() {
48+
export function Example() {
49+
const showConfig = useCallback(() => {
2750
console.log(getConfig());
28-
}
29-
30-
render() {
31-
const config = {
32-
autoRotate: -2,
33-
};
34-
return (
35-
<div>
36-
<ReactPannellum
37-
id="1"
38-
sceneId="firstScene"
39-
imageSource="https://pannellum.org/images/alma.jpg"
40-
config={config}
41-
/>
42-
<div onClick={this.click}>Click me</div>
43-
</div>
44-
);
45-
}
51+
}, []);
52+
53+
const config = {
54+
autoRotate: -2,
55+
};
56+
57+
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>
69+
);
4670
}
4771
```
4872

@@ -369,7 +393,9 @@ If set to `true`, prevent displaying out-of-range areas of a partial panorama by
369393

370394
## <a id="apiEvents" ></a> API Events
371395

372-
### Do not call API event in `componentDidMount` or API event will return undefined.
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.
397+
398+
Use **`onPanoramaLoaded`**, or a **`useEffect`** with an empty dependency array (runs after paint) so the component has mounted and the Pannellum instance exists.
373399

374400
> ### isLoaded
375401
>
@@ -468,7 +494,7 @@ Parameters:
468494
- `hfov` [number] Target hfov.
469495
- `animated` [(boolean | number)] Animation duration in milliseconds or false for no animation (optional, default 1000).
470496
- `callback` [function] Function to call when animation finishes.
471-
- `callbackArg`s [object] Arguments to pass to callback function.
497+
- `callbackArgs` [object] Arguments to pass to callback function.
472498

473499
> ### getNorthOffset
474500
>
@@ -645,11 +671,19 @@ Returns `true` if active, else `false`.
645671
>
646672
> Destructor.
647673
648-
## <a id="apiEventListeners" ></a> Api Event Listeners
674+
## <a id="apiEventListeners"></a> API event listeners (props)
649675

650-
> ### onPanoramaLoaded
651-
>
652-
> Will be triggered when panorama is loaded
676+
### onPanoramaLoaded (optional): `() => void`
677+
678+
Called when the panorama has finished loading (forwarded to Pannellum’s `load` event).
679+
680+
### onPanoramaMouseDown (optional): `(event: unknown) => void`
681+
682+
Called on viewer `mousedown`.
683+
684+
### onPanoramaMouseUp (optional): `(event: unknown) => void`
685+
686+
Called on viewer `mouseup`.
653687

654688
## License
655689

eslint.config.mjs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import js from "@eslint/js";
2+
import globals from "globals";
3+
import reactPlugin from "eslint-plugin-react";
4+
import reactHooks from "eslint-plugin-react-hooks";
5+
import tseslint from "typescript-eslint";
6+
7+
export default tseslint.config(
8+
{ ignores: ["dist/**", "src/libs/**"] },
9+
js.configs.recommended,
10+
...tseslint.configs.recommended,
11+
{
12+
files: ["src/**/*.{ts,tsx}"],
13+
...reactPlugin.configs.flat.recommended,
14+
plugins: {
15+
"react-hooks": reactHooks,
16+
},
17+
languageOptions: {
18+
globals: { ...globals.browser },
19+
parserOptions: {
20+
ecmaFeatures: { jsx: true },
21+
},
22+
},
23+
rules: {
24+
...reactHooks.configs.recommended.rules,
25+
"react/react-in-jsx-scope": "off",
26+
"react/no-children-prop": "off",
27+
"react/prop-types": "off",
28+
"@typescript-eslint/no-unused-vars": [
29+
"warn",
30+
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
31+
],
32+
"no-console": "off",
33+
},
34+
settings: {
35+
react: { version: "detect" },
36+
},
37+
}
38+
);

0 commit comments

Comments
 (0)