@storyblok/react
Advanced tools
Comparing version 3.0.15 to 4.0.0
@@ -0,1 +1,2 @@ | ||
"use client"; | ||
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("react"),b=require("./storyblok-js.js"),f=(e=null,o={})=>{const[u,s]=d.useState(e),r=(e==null?void 0:e.internalId)??(e==null?void 0:e.id)??0,t=typeof window<"u"&&typeof window.storyblokRegisterEvent<"u";return d.useEffect(()=>{s(e),!(!t||!e)&&b.registerStoryblokBridge(r,c=>s(c),o)},[e]),u};exports.useStoryblokState=f; |
@@ -1,1 +0,1 @@ | ||
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./bridge-loader.js"),o=require("./index2.js"),r=require("./story.js"),l=require("./storyblok-component.js"),e=require("./storyblok-js.js");exports.BridgeLoader=t;exports.StoryblokBridgeLoader=t;exports.getComponent=o.getComponent;exports.getCustomFallbackComponent=o.getCustomFallbackComponent;exports.getEnableFallbackComponent=o.getEnableFallbackComponent;exports.getStoryblokApi=o.useStoryblokApi;exports.setComponents=o.setComponents;exports.storyblokInit=o.storyblokInit;exports.useStoryblokApi=o.useStoryblokApi;exports.StoryblokStory=r;exports.StoryblokComponent=l;exports.RichTextResolver=e.RichTextResolver;exports.RichTextSchema=e.RichTextSchema;exports.apiPlugin=e.apiPlugin;exports.loadStoryblokBridge=e.loadStoryblokBridge;exports.registerStoryblokBridge=e.registerStoryblokBridge;exports.renderRichText=e.renderRichText;exports.storyblokEditable=e.storyblokEditable;exports.useStoryblokBridge=e.registerStoryblokBridge; | ||
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./common.js"),t=require("./story.js"),r=require("./server-component.js"),e=require("./storyblok-js.js");exports.getComponent=o.getComponent;exports.getCustomFallbackComponent=o.getCustomFallbackComponent;exports.getEnableFallbackComponent=o.getEnableFallbackComponent;exports.getStoryblokApi=o.useStoryblokApi;exports.setComponents=o.setComponents;exports.storyblokInit=o.storyblokInit;exports.useStoryblokApi=o.useStoryblokApi;exports.StoryblokStory=t;exports.StoryblokServerComponent=r;exports.RichTextResolver=e.RichTextResolver;exports.RichTextSchema=e.RichTextSchema;exports.apiPlugin=e.apiPlugin;exports.loadStoryblokBridge=e.loadStoryblokBridge;exports.registerStoryblokBridge=e.registerStoryblokBridge;exports.renderRichText=e.renderRichText;exports.storyblokEditable=e.storyblokEditable;exports.useStoryblokBridge=e.registerStoryblokBridge; |
@@ -1,2 +0,1 @@ | ||
"use client"; | ||
"use strict";const t=require("react"),c=require("./client.js"),i=require("./storyblok-component.js"),l=t.forwardRef(({story:e,bridgeOptions:n,...o},r)=>(typeof e.content=="string"&&(e.content=JSON.parse(e.content)),e=c.useStoryblokState(e,n),t.createElement(i,{ref:r,blok:e.content,...o})));module.exports=l; | ||
"use strict";const r=require("react");require("./common.js");const i=require("./live-editing.js"),l=require("./server-component.js"),a=r.forwardRef(({story:e,bridgeOptions:t,...n},o)=>{if(!e)return console.error("Please provide a 'story' property to the StoryblokServerComponent"),null;if(globalThis.storyCache.has(e.uuid)&&(e=globalThis.storyCache.get(e.uuid)),typeof e.content=="string")try{e.content=JSON.parse(e.content)}catch(c){console.error("An error occurred while trying to parse the story content",c),e.content={}}return r.createElement(r.Fragment,null,r.createElement(l,{ref:o,blok:e.content,...n}),r.createElement(i,{story:e,bridgeOptions:t}))});module.exports=a; |
@@ -1,4 +0,2 @@ | ||
export { default as BridgeLoader } from '../bridge-loader'; | ||
export { default as StoryblokBridgeLoader } from '../bridge-loader'; | ||
export * from '../common'; | ||
export { default as StoryblokStory } from '../story'; | ||
export * from './common'; | ||
export { default as StoryblokStory } from './story'; |
{ | ||
"name": "@storyblok/react", | ||
"version": "3.0.15", | ||
"version": "4.0.0", | ||
"description": "SDK to integrate Storyblok into your project using React.", | ||
@@ -60,3 +60,4 @@ "author": "Storyblok", | ||
"dependencies": { | ||
"@storyblok/js": "^3.1.1" | ||
"@storyblok/js": "^3.1.1", | ||
"next": "14.2.14" | ||
}, | ||
@@ -63,0 +64,0 @@ "devDependencies": { |
148
README.md
@@ -225,3 +225,3 @@ <div align="center"> | ||
## Next.js using App Router - Live Editing support | ||
## Next.js using App Router | ||
@@ -234,13 +234,27 @@ The components in the `app` directory are by default React Server Side Components, which limits the reactivity. You can enable Storyblok Visual Editor's live editing with React Server Components by rendering them inside a wrapper (`StoryblokPovider`) on the client. The SDK allows you to take full advantage of the Live Editing, but the use of Server Side Components is partial, which will be still better than the older Next.js approach performance-wise. The next section explains about how to use complete server side approach. | ||
In `app/layout.jsx`, call the `storyblokInit` function, but without loading the component list (we will do that on the client). Wrap your whole app using a `StoryblokProvider` component (this provider is created in the next step) : | ||
Create a new file `lib/storyblok.js` and initialize the SDK. Make sure you export the `getStoryblokApi` function, which is an instance of [storyblok-js-client](https://github.com/storyblok/storyblok-js-client) that is shared by client and server components. | ||
```js | ||
import { apiPlugin, storyblokInit } from '@storyblok/react/rsc' | ||
import StoryblokProvider from '../components/StoryblokProvider' | ||
// lib/storyblok.js | ||
import Page from '@/components/Page'; | ||
import Teaser from '@/components/Teaser'; | ||
import { apiPlugin, storyblokInit } from '@storyblok/react/rsc'; | ||
storyblokInit({ | ||
export const getStoryblokApi = storyblokInit({ | ||
accessToken: 'YOUR_ACCESS_TOKEN', | ||
use: [apiPlugin], | ||
}) | ||
components: { | ||
teaser: Teaser, | ||
page: Page, | ||
}, | ||
}); | ||
``` | ||
In `app/layout.jsx`, wrap your whole app using a `StoryblokProvider` component (this provider is created in the next step) : | ||
```js | ||
// app/layout.jsx | ||
import { apiPlugin, storyblokInit } from '@storyblok/react/rsc' | ||
import StoryblokProvider from '../components/StoryblokProvider' | ||
export default function RootLayout({ children }) { | ||
@@ -259,40 +273,27 @@ return ( | ||
Create the `components/StoryblokProvider.jsx` file. Re-initalize the connection with Storyblok (this time, on the client) using `storyblokInit`, and import your Storyblok components: | ||
Create the `components/StoryblokProvider.jsx` file. Re-initalize the connection with Storyblok (this time, on the client) using the `getStoryblokApi` function imported from the `lib/storyblok` file. This will enable the client-side compoenents to interact with the Storyblok API, including the Visual Editor. | ||
```js | ||
/** 1. Tag it as a client component */ | ||
'use client' | ||
import { apiPlugin, storyblokInit } from '@storyblok/react/rsc' | ||
// components/StoryblokProvider.jsx | ||
'use client'; | ||
/** 2. Import your components */ | ||
import Page from '../components/Page' | ||
import Teaser from '../components/Teaser' | ||
import { getStoryblokApi } from '@/lib/storyblok'; | ||
/** 3. Initialize it as usual */ | ||
storyblokInit({ | ||
accessToken: 'YOUR_ACCESS_TOKEN', | ||
use: [apiPlugin], | ||
components: { | ||
teaser: Teaser, | ||
page: Page, | ||
}, | ||
}) | ||
export default function StoryblokProvider({ children }) { | ||
return children | ||
getStoryblokApi(); | ||
return children; | ||
} | ||
``` | ||
> Note: it's necessary to re-initialize here as well, as to enable the live editing experience inside the Visual Editor you need to initialize the lib universally (client + server). | ||
### 3. Fetch Content and Render Components | ||
The `getStoryblokApi` function, which is an instance of [storyblok-js-client](https://github.com/storyblok/storyblok-js-client) can be used to fetch the data from the Storyblok API. This should be imported from `@storyblok/react/rsc`. | ||
You can render the content of your route with the `StoryblokStory` component, which will automatically handle the Visual Editor live events when editing the story. In `app/page.jsx`, use them as follows: | ||
The `getStoryblokApi` function can now be used inside your Story components to fetch the data from Storyblok. In `app/page.jsx`, use it as follows: | ||
```js | ||
import { getStoryblokApi, StoryblokStory } from '@storyblok/react/rsc' | ||
import { StoryblokClient, ISbStoriesParams } from '@storyblok/react'; | ||
import { StoryblokStory } from '@storyblok/react/rsc'; | ||
import { getStoryblokApi } from '@/lib/storyblok'; // Remember to import from the local file | ||
export default async function Home() { | ||
const { data } = await fetchData() | ||
const { data } = await fetchData(); | ||
@@ -303,8 +304,10 @@ return ( | ||
</div> | ||
) | ||
); | ||
} | ||
export async function fetchData() { | ||
const storyblokApi = getStoryblokApi() | ||
return storyblokApi.get(`cdn/stories/home`, { version: 'draft' }) | ||
let sbParams: ISbStoriesParams = { version: 'draft' }; | ||
const storyblokApi: StoryblokClient = getStoryblokApi(); | ||
return storyblokApi.get(`cdn/stories/home`, sbParams); | ||
} | ||
@@ -325,77 +328,2 @@ ``` | ||
## Next.js using App Router - Full React Server Components | ||
If you want to use the Next.js `app` directory approach, and React Server Components exclusively with everything on the server side, follow this approach. | ||
> The SDK has a special module for RSC. Always import `@storyblok/react/rsc` while using Server Components. | ||
**Limitation** - Real-time editing won't work if all the components are rendered on the server. Although, you can see the changes applied in the Visual Editor whenever you save or publish the changes applied to the story. | ||
### 1. Initialize and Import your Storyblok Components | ||
The initialzation remains the same here as well. Please refer to the above section about "Initialization" for more information about `storyblokInit` function. | ||
In `app/layout.jsx`, call the `storyblokInit` function and use the new `StoryblokBridgeLoader` component to set up the Storyblok bridge. This Bridge Loader can be imported from `@storyblok/react/bridge-loader`: | ||
```js | ||
import { storyblokInit, apiPlugin, StoryblokBridgeLoader } from "@storyblok/react/rsc"; | ||
import Page from "../components/Page"; | ||
import Teaser from "../components/Teaser"; | ||
storyblokInit({ | ||
accessToken: "YOUR_ACCESS_TOKEN", | ||
use: [apiPlugin], | ||
components: { | ||
teaser: Teaser, | ||
page: Page, | ||
}, | ||
}); | ||
export default RootLayout(({ children }) => { | ||
const bridgeOptions = { resolveRelations: ["article.author"] }; | ||
return ( | ||
<html lang="en"> | ||
<body>{children}</body> | ||
<StoryblokBridgeLoader options={bridgeOptions} /> | ||
</html> | ||
); | ||
} | ||
``` | ||
As the name says, `StoryblokBridgeLoader` loads the bridge on the client. It helps you see the dotted lines and allows you to still click on the components inside the Visual Editor to open their schema. You can pass the bridge options using the `options` prop. | ||
### 2. Fetch Content and Render Components | ||
The `getStoryblokApi` function, is an instance of [storyblok-js-client](https://github.com/storyblok/storyblok-js-client) can be used to fetch the data from the Storyblok API. This is imported from `@storyblok/react/rsc`. | ||
Go to the route you want to fetch data from and use it as follows: | ||
```js | ||
import { getStoryblokApi, StoryblokComponent } from '@storyblok/react/rsc' | ||
export default async function Home() { | ||
const { data } = await fetchData() | ||
return ( | ||
<div> | ||
<h1> | ||
Story: | ||
{data.story.id} | ||
</h1> | ||
<StoryblokComponent blok={data.story.content} /> | ||
</div> | ||
) | ||
} | ||
export async function fetchData() { | ||
const storyblokApi = getStoryblokApi() | ||
return storyblokApi.get(`cdn/stories/home`, { version: 'draft' }) | ||
} | ||
``` | ||
> Note: To use this approach (with `getStoryblokApi`), you need to include the `apiPlugin` module when calling `storyblokInit` function. If you don't use `apiPlugin`, you can use your preferred method or function to fetch your data. | ||
`StoryblokComponent` renders the route components dynamically, using the list of components loaded during the initialization inside the `storyblokInit` function. | ||
To try it, take a look at the [Next 13 RSC Playground](https://github.com/arorachakit/storyblok-react/tree/main/playground-next13-rsc) in this repo. | ||
## Next.js using Pages Router | ||
@@ -716,1 +644,5 @@ | ||
This project use [semantic-release](https://semantic-release.gitbook.io/semantic-release/) for generate new versions by using commit messages and we use the Angular Convention to naming the commits. Check [this question](https://semantic-release.gitbook.io/semantic-release/support/faq#how-can-i-change-the-type-of-commits-that-trigger-a-release) about it in semantic-release FAQ. | ||
## License | ||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 4 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
105693
35
1405
4
9
643
+ Addednext@14.2.14
+ Added@next/env@14.2.14(transitive)
+ Added@next/swc-darwin-arm64@14.2.14(transitive)
+ Added@next/swc-darwin-x64@14.2.14(transitive)
+ Added@next/swc-linux-arm64-gnu@14.2.14(transitive)
+ Added@next/swc-linux-arm64-musl@14.2.14(transitive)
+ Added@next/swc-linux-x64-gnu@14.2.14(transitive)
+ Added@next/swc-linux-x64-musl@14.2.14(transitive)
+ Added@next/swc-win32-arm64-msvc@14.2.14(transitive)
+ Added@next/swc-win32-ia32-msvc@14.2.14(transitive)
+ Added@next/swc-win32-x64-msvc@14.2.14(transitive)
+ Added@swc/counter@0.1.3(transitive)
+ Added@swc/helpers@0.5.5(transitive)
+ Addedbusboy@1.6.0(transitive)
+ Addedcaniuse-lite@1.0.30001687(transitive)
+ Addedclient-only@0.0.1(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addednanoid@3.3.8(transitive)
+ Addednext@14.2.14(transitive)
+ Addedpicocolors@1.1.1(transitive)
+ Addedpostcss@8.4.31(transitive)
+ Addedsource-map-js@1.2.1(transitive)
+ Addedstreamsearch@1.1.0(transitive)
+ Addedstyled-jsx@5.1.1(transitive)
+ Addedtslib@2.8.1(transitive)