@storyblok/react 3.0.14 → 4.0.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 +124 -190
- package/dist/client.js +1 -0
- package/dist/client.mjs +1 -0
- package/dist/common.js +1 -0
- package/dist/common.mjs +35 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -2
- package/dist/live-edit-update-action.js +2 -0
- package/dist/live-edit-update-action.mjs +15 -0
- package/dist/live-editing.js +2 -0
- package/dist/live-editing.mjs +19 -0
- package/dist/rsc.js +1 -1
- package/dist/rsc.mjs +16 -19
- package/dist/server-component.js +1 -0
- package/dist/server-component.mjs +23 -0
- package/dist/story.js +1 -2
- package/dist/story.mjs +22 -7
- package/dist/types/common/client.d.ts +1 -1
- package/dist/types/common/index.d.ts +4 -4
- package/dist/types/common/storyblok-component.d.ts +2 -2
- package/dist/types/index.d.ts +3 -3
- package/dist/types/rsc/common.d.ts +11 -0
- package/dist/types/rsc/index.d.ts +2 -4
- package/dist/types/rsc/live-edit-update-action.d.ts +4 -0
- package/dist/types/rsc/live-editing.d.ts +5 -0
- package/dist/types/rsc/server-component.d.ts +8 -0
- package/dist/types/{story.d.ts → rsc/story.d.ts} +2 -2
- package/dist/types/types.d.ts +3 -4
- package/package.json +26 -25
- package/dist/bridge-loader.js +0 -2
- package/dist/bridge-loader.mjs +0 -11
- package/dist/types/bridge-loader.d.ts +0 -8
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
<a href="https://www.storyblok.com?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react" align="center">
|
|
3
|
+
<img src="https://a.storyblok.com/f/88751/1776x360/ccc1c50c67/sb-react.png" alt="Storyblok Logo">
|
|
4
|
+
</a>
|
|
5
|
+
<h1 align="center">@storyblok/react</h1>
|
|
6
6
|
<p align="center">
|
|
7
7
|
The React plugin you need to interact with <a href="http://www.storyblok.com?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react" target="_blank">Storyblok API</a> and enable the <a href="https://www.storyblok.com/docs/guide/essentials/visual-editor?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react" target="_blank">Real-time Visual Editing Experience</a>. This package helps you integrate Storyblok with React along with all types of React based frameworks like Next.js, Remix etc. This SDK also includes the support for React Server Side Components.
|
|
8
8
|
</p>
|
|
@@ -63,15 +63,15 @@ Install the file from the CDN:
|
|
|
63
63
|
Register the plugin on your application and add the [access token](https://www.storyblok.com/docs/api/content-delivery#topics/authentication?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react) of your Storyblok space. You can also add the `apiPlugin` in case that you want to use the Storyblok API Client:
|
|
64
64
|
|
|
65
65
|
```js
|
|
66
|
-
import {
|
|
66
|
+
import { apiPlugin, storyblokInit } from '@storyblok/react'
|
|
67
67
|
|
|
68
68
|
/** Import your components */
|
|
69
|
-
import Page from
|
|
70
|
-
import Teaser from
|
|
69
|
+
import Page from './components/Page'
|
|
70
|
+
import Teaser from './components/Teaser'
|
|
71
71
|
// import FallbackComponent from "./components/FallbackComponent";
|
|
72
72
|
|
|
73
73
|
storyblokInit({
|
|
74
|
-
accessToken:
|
|
74
|
+
accessToken: 'YOUR_ACCESS_TOKEN',
|
|
75
75
|
use: [apiPlugin],
|
|
76
76
|
components: {
|
|
77
77
|
page: Page,
|
|
@@ -82,7 +82,7 @@ storyblokInit({
|
|
|
82
82
|
// richText: {},
|
|
83
83
|
// enableFallbackComponent: false,
|
|
84
84
|
// customFallbackComponent: FallbackComponent,
|
|
85
|
-
})
|
|
85
|
+
})
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
> Note: This is the general way for initalizing the SDK, the initialization might be a little different depending upon the framework. You can see how everything works according to the framework in their respective sections below.
|
|
@@ -106,16 +106,16 @@ Possible values:
|
|
|
106
106
|
Full example for a space created in the US:
|
|
107
107
|
|
|
108
108
|
```js
|
|
109
|
-
import {
|
|
109
|
+
import { apiPlugin, storyblokInit } from '@storyblok/react'
|
|
110
110
|
|
|
111
111
|
storyblokInit({
|
|
112
|
-
accessToken:
|
|
112
|
+
accessToken: 'YOUR_ACCESS_TOKEN',
|
|
113
113
|
use: [apiPlugin],
|
|
114
114
|
apiOptions: {
|
|
115
|
-
region:
|
|
115
|
+
region: 'us',
|
|
116
116
|
},
|
|
117
117
|
components: {},
|
|
118
|
-
})
|
|
118
|
+
})
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
> Note: For spaces created in the United States or China, the `region` parameter **must** be specified.
|
|
@@ -129,7 +129,7 @@ storyblokInit({
|
|
|
129
129
|
For every component you've defined in your Storyblok space, call the `storyblokEditable` function with the blok content:
|
|
130
130
|
|
|
131
131
|
```js
|
|
132
|
-
import { storyblokEditable } from
|
|
132
|
+
import { storyblokEditable } from '@storyblok/react'
|
|
133
133
|
|
|
134
134
|
const Feature = ({ blok }) => {
|
|
135
135
|
return (
|
|
@@ -139,10 +139,10 @@ const Feature = ({ blok }) => {
|
|
|
139
139
|
<p>{blok.description}</p>
|
|
140
140
|
</div>
|
|
141
141
|
</div>
|
|
142
|
-
)
|
|
143
|
-
}
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
144
|
|
|
145
|
-
export default Feature
|
|
145
|
+
export default Feature
|
|
146
146
|
```
|
|
147
147
|
|
|
148
148
|
Where `blok` is the actual blok data coming from [Storyblok's Content Delivery API](https://www.storyblok.com/docs/api/content-delivery?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react).
|
|
@@ -164,19 +164,19 @@ The initalization remains the same when you work with React. You can intialze th
|
|
|
164
164
|
Use `useStoryblok` to fetch the content as well as enable live editing. You need to pass the `slug` as the first parameter, `apiOptions` as the second parameter, and `bridgeOptions` as the third parameter, which is optional if you want to set the options for the bridge by yourself. Check the available [apiOptions](https://github.com/storyblok/storyblok-js-client#class-storyblok) (passed to `storyblok-js-client`) and [bridgeOptions](https://www.storyblok.com/docs/Guides/storyblok-latest-js?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-nuxt) (passed to the Storyblok Bridge).
|
|
165
165
|
|
|
166
166
|
```js
|
|
167
|
-
import {
|
|
167
|
+
import { StoryblokComponent, useStoryblok } from '@storyblok/react'
|
|
168
168
|
|
|
169
169
|
function App() {
|
|
170
|
-
const story = useStoryblok(
|
|
170
|
+
const story = useStoryblok('react', { version: 'draft' })
|
|
171
171
|
|
|
172
172
|
if (!story?.content) {
|
|
173
|
-
return <div>Loading...</div
|
|
173
|
+
return <div>Loading...</div>
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
return <StoryblokComponent blok={story.content}
|
|
176
|
+
return <StoryblokComponent blok={story.content} />
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
export default App
|
|
179
|
+
export default App
|
|
180
180
|
```
|
|
181
181
|
|
|
182
182
|
`StoryblokComponent` renders the route components dynamically, using the list of components loaded during the initialization inside the `storyblokInit` function.
|
|
@@ -186,13 +186,13 @@ This is how you can pass the Bridge options as a third parameter to `useStoryblo
|
|
|
186
186
|
```js
|
|
187
187
|
useStoryblok(
|
|
188
188
|
story.id,
|
|
189
|
-
{ version:
|
|
189
|
+
{ version: 'draft', resolveRelations: ['Article.author'] },
|
|
190
190
|
{
|
|
191
|
-
resolveRelations: [
|
|
192
|
-
resolveLinks:
|
|
191
|
+
resolveRelations: ['Article.author'],
|
|
192
|
+
resolveLinks: 'url',
|
|
193
193
|
preventClicks: true,
|
|
194
194
|
}
|
|
195
|
-
)
|
|
195
|
+
)
|
|
196
196
|
```
|
|
197
197
|
|
|
198
198
|
**Check out our React Boilerplate [here](https://github.com/storyblok/storyblok-react-boilerplate), or read on how to add Storyblok to React in 5 mins [here](https://www.storyblok.com/tp/headless-cms-react)**
|
|
@@ -210,19 +210,19 @@ For more details, refer to the Next.js documentation on [opting out of caching](
|
|
|
210
210
|
|
|
211
211
|
Here's how you can fetch data from Storyblok with `cache: "no-store"`:
|
|
212
212
|
|
|
213
|
-
```
|
|
213
|
+
```typescript
|
|
214
214
|
export async function fetchData() {
|
|
215
|
-
|
|
215
|
+
const sbParams: ISbStoriesParams = { version: 'draft' }
|
|
216
216
|
|
|
217
|
-
const storyblokApi: StoryblokClient = getStoryblokApi()
|
|
217
|
+
const storyblokApi: StoryblokClient = getStoryblokApi()
|
|
218
218
|
|
|
219
219
|
return storyblokApi.get(`cdn/stories/home`, sbParams, {
|
|
220
|
-
cache:
|
|
221
|
-
})
|
|
220
|
+
cache: 'no-store', // This prevents Next.js 13, 14 default caching behaviour
|
|
221
|
+
})
|
|
222
222
|
}
|
|
223
223
|
```
|
|
224
224
|
|
|
225
|
-
## Next.js using App Router
|
|
225
|
+
## Next.js using App Router
|
|
226
226
|
|
|
227
227
|
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.
|
|
228
228
|
|
|
@@ -230,16 +230,30 @@ The components in the `app` directory are by default React Server Side Component
|
|
|
230
230
|
|
|
231
231
|
### 1. Initialize
|
|
232
232
|
|
|
233
|
-
|
|
233
|
+
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.
|
|
234
234
|
|
|
235
235
|
```js
|
|
236
|
-
|
|
237
|
-
import
|
|
236
|
+
// lib/storyblok.js
|
|
237
|
+
import Page from '@/components/Page';
|
|
238
|
+
import Teaser from '@/components/Teaser';
|
|
239
|
+
import { apiPlugin, storyblokInit } from '@storyblok/react/rsc';
|
|
238
240
|
|
|
239
|
-
storyblokInit({
|
|
240
|
-
accessToken:
|
|
241
|
+
export const getStoryblokApi = storyblokInit({
|
|
242
|
+
accessToken: 'YOUR_ACCESS_TOKEN',
|
|
241
243
|
use: [apiPlugin],
|
|
244
|
+
components: {
|
|
245
|
+
teaser: Teaser,
|
|
246
|
+
page: Page,
|
|
247
|
+
},
|
|
242
248
|
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
In `app/layout.jsx`, wrap your whole app using a `StoryblokProvider` component (this provider is created in the next step) :
|
|
252
|
+
|
|
253
|
+
```js
|
|
254
|
+
// app/layout.jsx
|
|
255
|
+
import { apiPlugin, storyblokInit } from '@storyblok/react/rsc'
|
|
256
|
+
import StoryblokProvider from '../components/StoryblokProvider'
|
|
243
257
|
|
|
244
258
|
export default function RootLayout({ children }) {
|
|
245
259
|
return (
|
|
@@ -248,47 +262,34 @@ export default function RootLayout({ children }) {
|
|
|
248
262
|
<body>{children}</body>
|
|
249
263
|
</html>
|
|
250
264
|
</StoryblokProvider>
|
|
251
|
-
)
|
|
265
|
+
)
|
|
252
266
|
}
|
|
253
267
|
```
|
|
254
268
|
|
|
255
269
|
### 2. Create StoryblokProvider and Import your Storyblok Components
|
|
256
270
|
|
|
257
|
-
Create the `components/StoryblokProvider.jsx` file. Re-initalize the connection with Storyblok (this time, on the client) using `
|
|
271
|
+
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.
|
|
258
272
|
|
|
259
273
|
```js
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
import { storyblokInit, apiPlugin } from "@storyblok/react/rsc";
|
|
274
|
+
// components/StoryblokProvider.jsx
|
|
275
|
+
'use client';
|
|
263
276
|
|
|
264
|
-
|
|
265
|
-
import Page from "../components/Page";
|
|
266
|
-
import Teaser from "../components/Teaser";
|
|
267
|
-
|
|
268
|
-
/** 3. Initialize it as usual */
|
|
269
|
-
storyblokInit({
|
|
270
|
-
accessToken: "YOUR_ACCESS_TOKEN",
|
|
271
|
-
use: [apiPlugin],
|
|
272
|
-
components: {
|
|
273
|
-
teaser: Teaser,
|
|
274
|
-
page: Page,
|
|
275
|
-
},
|
|
276
|
-
});
|
|
277
|
+
import { getStoryblokApi } from '@/lib/storyblok';
|
|
277
278
|
|
|
278
279
|
export default function StoryblokProvider({ children }) {
|
|
280
|
+
getStoryblokApi();
|
|
279
281
|
return children;
|
|
280
282
|
}
|
|
281
283
|
```
|
|
282
284
|
|
|
283
|
-
> 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).
|
|
284
|
-
|
|
285
285
|
### 3. Fetch Content and Render Components
|
|
286
286
|
|
|
287
|
-
The `getStoryblokApi` function
|
|
288
|
-
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:
|
|
287
|
+
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:
|
|
289
288
|
|
|
290
289
|
```js
|
|
291
|
-
import {
|
|
290
|
+
import { StoryblokClient, ISbStoriesParams } from '@storyblok/react';
|
|
291
|
+
import { StoryblokStory } from '@storyblok/react/rsc';
|
|
292
|
+
import { getStoryblokApi } from '@/lib/storyblok'; // Remember to import from the local file
|
|
292
293
|
|
|
293
294
|
export default async function Home() {
|
|
294
295
|
const { data } = await fetchData();
|
|
@@ -301,95 +302,25 @@ export default async function Home() {
|
|
|
301
302
|
}
|
|
302
303
|
|
|
303
304
|
export async function fetchData() {
|
|
304
|
-
|
|
305
|
-
|
|
305
|
+
let sbParams: ISbStoriesParams = { version: 'draft' };
|
|
306
|
+
|
|
307
|
+
const storyblokApi: StoryblokClient = getStoryblokApi();
|
|
308
|
+
return storyblokApi.get(`cdn/stories/home`, sbParams);
|
|
306
309
|
}
|
|
307
310
|
```
|
|
308
311
|
|
|
309
312
|
`StoryblokStory` keeps the state for thet story behind the scenes and uses `StoryblokComponent` to render the route components dynamically, using the list of components loaded during the initialization inside the `storyblokInit` function. You can use the `StoryblokComponent` inside the components to render the nested components dynamically. You can also pass bridge options to `StoryblokStory` using the prop `bridgeOptions`.
|
|
310
313
|
|
|
311
|
-
```
|
|
312
|
-
const bridgeOptions = { resolveRelations: [
|
|
314
|
+
```jsx
|
|
315
|
+
const bridgeOptions = { resolveRelations: ['article.author'] }
|
|
313
316
|
|
|
314
|
-
<StoryblokStory story={data.story} bridgeOptions={bridgeOptions}
|
|
317
|
+
<StoryblokStory story={data.story} bridgeOptions={bridgeOptions} />
|
|
315
318
|
```
|
|
316
319
|
|
|
317
320
|
> 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.
|
|
318
321
|
|
|
319
322
|
To try this setup, take a look at the [Next 13 Live Editing Playground](https://github.com/arorachakit/storyblok-react/tree/main/playground-next13-live-editing) in this repo.
|
|
320
323
|
|
|
321
|
-
## Next.js using App Router - Full React Server Components
|
|
322
|
-
|
|
323
|
-
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.
|
|
324
|
-
|
|
325
|
-
> The SDK has a special module for RSC. Always import `@storyblok/react/rsc` while using Server Components.
|
|
326
|
-
|
|
327
|
-
**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.
|
|
328
|
-
|
|
329
|
-
### 1. Initialize and Import your Storyblok Components
|
|
330
|
-
|
|
331
|
-
The initialzation remains the same here as well. Please refer to the above section about "Initialization" for more information about `storyblokInit` function.
|
|
332
|
-
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`:
|
|
333
|
-
|
|
334
|
-
```js
|
|
335
|
-
import { storyblokInit, apiPlugin, StoryblokBridgeLoader } from "@storyblok/react/rsc";
|
|
336
|
-
|
|
337
|
-
import Page from "../components/Page";
|
|
338
|
-
import Teaser from "../components/Teaser";
|
|
339
|
-
|
|
340
|
-
storyblokInit({
|
|
341
|
-
accessToken: "YOUR_ACCESS_TOKEN",
|
|
342
|
-
use: [apiPlugin],
|
|
343
|
-
components: {
|
|
344
|
-
teaser: Teaser,
|
|
345
|
-
page: Page,
|
|
346
|
-
},
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
export default RootLayout({ children }) =>{
|
|
350
|
-
const bridgeOptions = { resolveRelations: ["article.author"] };
|
|
351
|
-
|
|
352
|
-
return (
|
|
353
|
-
<html lang="en">
|
|
354
|
-
<body>{children}</body>
|
|
355
|
-
<StoryblokBridgeLoader options={bridgeOptions} />
|
|
356
|
-
</html>
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
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.
|
|
362
|
-
|
|
363
|
-
### 2. Fetch Content and Render Components
|
|
364
|
-
|
|
365
|
-
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`.
|
|
366
|
-
Go to the route you want to fetch data from and use it as follows:
|
|
367
|
-
|
|
368
|
-
```js
|
|
369
|
-
import { getStoryblokApi, StoryblokComponent } from "@storyblok/react/rsc";
|
|
370
|
-
|
|
371
|
-
export default async function Home() {
|
|
372
|
-
const { data } = await fetchData();
|
|
373
|
-
|
|
374
|
-
return (
|
|
375
|
-
<div>
|
|
376
|
-
<h1>Story: {data.story.id}</h1>
|
|
377
|
-
<StoryblokComponent blok={data.story.content} />
|
|
378
|
-
</div>
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
export async function fetchData() {
|
|
383
|
-
const storyblokApi = getStoryblokApi();
|
|
384
|
-
return storyblokApi.get(`cdn/stories/home`, { version: "draft" });
|
|
385
|
-
}
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
> 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.
|
|
389
|
-
|
|
390
|
-
`StoryblokComponent` renders the route components dynamically, using the list of components loaded during the initialization inside the `storyblokInit` function.
|
|
391
|
-
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.
|
|
392
|
-
|
|
393
324
|
## Next.js using Pages Router
|
|
394
325
|
|
|
395
326
|
In this section, we'll see how to use the React SDK with the `pages` directory approach.
|
|
@@ -401,11 +332,11 @@ The initalization remains the same when you work with Next.js. You can intialze
|
|
|
401
332
|
The SDK provides a `getStoryblokApi` object in your app, which is an instance of [storyblok-js-client](https://github.com/storyblok/storyblok-js-client). This can be used to fetch the content from Storyblok. You can use it in functions like `getStaticProps`, `getStaticPaths`, `getServerSideProps` etc.
|
|
402
333
|
|
|
403
334
|
```js
|
|
404
|
-
import { getStoryblokApi } from
|
|
335
|
+
import { getStoryblokApi } from '@storyblok/react'
|
|
405
336
|
|
|
406
337
|
// At the required place
|
|
407
|
-
const storyblokApi = getStoryblokApi()
|
|
408
|
-
const { data } = await storyblokApi.get(
|
|
338
|
+
const storyblokApi = getStoryblokApi()
|
|
339
|
+
const { data } = await storyblokApi.get('cdn/stories', { version: 'draft' })
|
|
409
340
|
```
|
|
410
341
|
|
|
411
342
|
> Note: To use this approach, 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.
|
|
@@ -415,16 +346,16 @@ const { data } = await storyblokApi.get("cdn/stories", { version: "draft" });
|
|
|
415
346
|
The SDK also provides you with the `useStoryblokState` hook. It works similarly to `useStoryblok` for live editing, but it doesn't fetch the content. Instead, it receives a story object as the first parameter. You can also pass the Bridge Options as the second parameter.
|
|
416
347
|
|
|
417
348
|
```js
|
|
418
|
-
import {
|
|
349
|
+
import { StoryblokComponent, useStoryblokState } from '@storyblok/react'
|
|
419
350
|
|
|
420
351
|
export default function Home({ story: initialStory }) {
|
|
421
|
-
const story = useStoryblokState(initialStory)
|
|
352
|
+
const story = useStoryblokState(initialStory)
|
|
422
353
|
|
|
423
354
|
if (!story.content) {
|
|
424
|
-
return <div>Loading...</div
|
|
355
|
+
return <div>Loading...</div>
|
|
425
356
|
}
|
|
426
357
|
|
|
427
|
-
return <StoryblokComponent blok={story.content}
|
|
358
|
+
return <StoryblokComponent blok={story.content} />
|
|
428
359
|
}
|
|
429
360
|
```
|
|
430
361
|
|
|
@@ -432,26 +363,26 @@ In this case, the story is being passed as a prop that can be coming from where
|
|
|
432
363
|
|
|
433
364
|
```js
|
|
434
365
|
import {
|
|
435
|
-
useStoryblokState,
|
|
436
366
|
getStoryblokApi,
|
|
437
367
|
StoryblokComponent,
|
|
438
|
-
|
|
368
|
+
useStoryblokState,
|
|
369
|
+
} from '@storyblok/react'
|
|
439
370
|
|
|
440
371
|
export default function Home({ story: initialStory }) {
|
|
441
|
-
const story = useStoryblokState(initialStory)
|
|
372
|
+
const story = useStoryblokState(initialStory)
|
|
442
373
|
|
|
443
374
|
if (!story.content) {
|
|
444
|
-
return <div>Loading...</div
|
|
375
|
+
return <div>Loading...</div>
|
|
445
376
|
}
|
|
446
377
|
|
|
447
|
-
return <StoryblokComponent blok={story.content}
|
|
378
|
+
return <StoryblokComponent blok={story.content} />
|
|
448
379
|
}
|
|
449
380
|
|
|
450
381
|
export async function getStaticProps({ preview = false }) {
|
|
451
|
-
const storyblokApi = getStoryblokApi()
|
|
452
|
-
|
|
453
|
-
version:
|
|
454
|
-
})
|
|
382
|
+
const storyblokApi = getStoryblokApi()
|
|
383
|
+
const { data } = await storyblokApi.get(`cdn/stories/react`, {
|
|
384
|
+
version: 'draft',
|
|
385
|
+
})
|
|
455
386
|
|
|
456
387
|
return {
|
|
457
388
|
props: {
|
|
@@ -459,7 +390,7 @@ export async function getStaticProps({ preview = false }) {
|
|
|
459
390
|
preview,
|
|
460
391
|
},
|
|
461
392
|
revalidate: 3600, // revalidate every hour
|
|
462
|
-
}
|
|
393
|
+
}
|
|
463
394
|
}
|
|
464
395
|
```
|
|
465
396
|
|
|
@@ -540,10 +471,10 @@ You can use an `apiOptions` object. This is passed down to the [storyblok-js-cli
|
|
|
540
471
|
|
|
541
472
|
```js
|
|
542
473
|
storyblokInit({
|
|
543
|
-
accessToken:
|
|
474
|
+
accessToken: 'YOUR_ACCESS_TOKEN',
|
|
544
475
|
apiOptions: {
|
|
545
476
|
// storyblok-js-client config object
|
|
546
|
-
cache: { type:
|
|
477
|
+
cache: { type: 'memory' },
|
|
547
478
|
},
|
|
548
479
|
use: [apiPlugin],
|
|
549
480
|
components: {
|
|
@@ -552,13 +483,13 @@ storyblokInit({
|
|
|
552
483
|
grid: Grid,
|
|
553
484
|
feature: Feature,
|
|
554
485
|
},
|
|
555
|
-
})
|
|
486
|
+
})
|
|
556
487
|
```
|
|
557
488
|
|
|
558
489
|
If you prefer to use your own fetch method, just remove the `apiPlugin` and `storyblok-js-client` won't be added to your application.
|
|
559
490
|
|
|
560
491
|
```js
|
|
561
|
-
storyblokInit({})
|
|
492
|
+
storyblokInit({})
|
|
562
493
|
```
|
|
563
494
|
|
|
564
495
|
### Storyblok Bridge
|
|
@@ -566,11 +497,11 @@ storyblokInit({});
|
|
|
566
497
|
If you don't use `registerStoryblokBridge`, you still have access to the raw `window.StoryblokBridge`:
|
|
567
498
|
|
|
568
499
|
```js
|
|
569
|
-
const sbBridge = new window.StoryblokBridge(options)
|
|
500
|
+
const sbBridge = new window.StoryblokBridge(options)
|
|
570
501
|
|
|
571
|
-
sbBridge.on([
|
|
502
|
+
sbBridge.on(['input', 'published', 'change'], (event) => {
|
|
572
503
|
// ...
|
|
573
|
-
})
|
|
504
|
+
})
|
|
574
505
|
```
|
|
575
506
|
|
|
576
507
|
### Rendering Rich Text
|
|
@@ -578,54 +509,53 @@ sbBridge.on(["input", "published", "change"], (event) => {
|
|
|
578
509
|
You can easily render rich text by using the `renderRichText` function that comes with `@storyblok/react`:
|
|
579
510
|
|
|
580
511
|
```js
|
|
581
|
-
import { renderRichText } from
|
|
512
|
+
import { renderRichText } from '@storyblok/react'
|
|
582
513
|
|
|
583
|
-
const renderedRichText = renderRichText(blok.richtext)
|
|
514
|
+
const renderedRichText = renderRichText(blok.richtext)
|
|
584
515
|
```
|
|
585
516
|
|
|
586
517
|
You can set a **custom Schema and component resolver globally** at init time by using the `richText` init option:
|
|
587
518
|
|
|
588
519
|
```js
|
|
589
|
-
import { RichTextSchema, storyblokInit } from
|
|
590
|
-
import cloneDeep from
|
|
520
|
+
import { RichTextSchema, storyblokInit } from '@storyblok/react'
|
|
521
|
+
import cloneDeep from 'clone-deep'
|
|
591
522
|
|
|
592
|
-
const mySchema = cloneDeep(RichTextSchema)
|
|
523
|
+
const mySchema = cloneDeep(RichTextSchema) // you can make a copy of the default RichTextSchema
|
|
593
524
|
// ... and edit the nodes and marks, or add your own.
|
|
594
525
|
// Check the base RichTextSchema source here https://github.com/storyblok/storyblok-js-client/blob/main/src/schema.ts
|
|
595
526
|
|
|
596
527
|
storyblokInit({
|
|
597
|
-
accessToken:
|
|
528
|
+
accessToken: '<your-token>',
|
|
598
529
|
richText: {
|
|
599
530
|
schema: mySchema,
|
|
600
531
|
resolver: (component, blok) => {
|
|
601
532
|
switch (component) {
|
|
602
|
-
case
|
|
603
|
-
return `<div class="my-component-class">${blok.text}</div
|
|
533
|
+
case 'my-custom-component':
|
|
534
|
+
return `<div class="my-component-class">${blok.text}</div>`
|
|
604
535
|
default:
|
|
605
|
-
return
|
|
536
|
+
return 'Resolver not defined'
|
|
606
537
|
}
|
|
607
538
|
},
|
|
608
539
|
},
|
|
609
|
-
})
|
|
540
|
+
})
|
|
610
541
|
```
|
|
611
542
|
|
|
612
543
|
You can also set a **custom Schema and component resolver only once** by passing the options as the second parameter to `renderRichText` function:
|
|
613
544
|
|
|
614
545
|
```js
|
|
615
|
-
import { renderRichText } from
|
|
546
|
+
import { renderRichText } from '@storyblok/react'
|
|
616
547
|
|
|
617
548
|
renderRichText(blok.richTextField, {
|
|
618
549
|
schema: mySchema,
|
|
619
550
|
resolver: (component, blok) => {
|
|
620
551
|
switch (component) {
|
|
621
|
-
case
|
|
622
|
-
return `<div class="my-component-class">${blok.text}</div
|
|
623
|
-
break;
|
|
552
|
+
case 'my-custom-component':
|
|
553
|
+
return `<div class="my-component-class">${blok.text}</div>`
|
|
624
554
|
default:
|
|
625
|
-
return `Component ${component} not found
|
|
555
|
+
return `Component ${component} not found`
|
|
626
556
|
}
|
|
627
557
|
},
|
|
628
|
-
})
|
|
558
|
+
})
|
|
629
559
|
```
|
|
630
560
|
|
|
631
561
|
We also recommend using the [Storyblok Rich Text Renderer for React by Claus](https://github.com/claus/storyblok-rich-text-react-renderer) for rendering your Storyblok rich text content to React elements and Next.js applications.
|
|
@@ -645,36 +575,36 @@ storyblokInit({
|
|
|
645
575
|
components: {
|
|
646
576
|
// all your React components
|
|
647
577
|
},
|
|
648
|
-
})
|
|
578
|
+
})
|
|
649
579
|
```
|
|
650
580
|
|
|
651
581
|
Storyblok's React SDK automatically renders these predefined components based on your page content. While this is convenient, it can lead to larger bundle sizes and slower page speeds, especially for larger sites or when using heavy JavaScript libraries that are only needed on specific pages or a specific component.
|
|
652
582
|
|
|
653
583
|
### Solutions
|
|
654
584
|
|
|
655
|
-
1. **Storyblok's `setComponents` Function**:
|
|
585
|
+
1. **Storyblok's `setComponents` Function**:
|
|
656
586
|
Storyblok SDK provides a function called `setComponents` that allows you to load only the components needed for each route instead of defining all components during initialization. This approach is useful but might not be practical if you use a catch-all route, which is common in many React frameworks.
|
|
657
587
|
|
|
658
|
-
2. **React's `react.lazy`**:
|
|
588
|
+
2. **React's `react.lazy`**:
|
|
659
589
|
React offers a built-in solution called `react.lazy` for code splitting. Instead of directly importing components, you can do the following:
|
|
660
|
-
|
|
590
|
+
|
|
661
591
|
```javascript
|
|
662
|
-
|
|
663
|
-
import {
|
|
664
|
-
import { lazy } from
|
|
665
|
-
|
|
592
|
+
'use client'
|
|
593
|
+
import { apiPlugin, storyblokInit } from '@storyblok/react/rsc'
|
|
594
|
+
import { lazy } from 'react'
|
|
595
|
+
|
|
666
596
|
const lazyComponents = {
|
|
667
|
-
page: lazy(() => import(
|
|
597
|
+
page: lazy(() => import('./components/Page')),
|
|
668
598
|
// other lazy-loaded components
|
|
669
|
-
}
|
|
670
|
-
|
|
599
|
+
}
|
|
600
|
+
|
|
671
601
|
storyblokInit({
|
|
672
602
|
accessToken,
|
|
673
603
|
use: [apiPlugin],
|
|
674
604
|
components: lazyComponents,
|
|
675
|
-
})
|
|
605
|
+
})
|
|
676
606
|
```
|
|
677
|
-
|
|
607
|
+
|
|
678
608
|
This approach enables automatic code splitting and loads only the necessary JavaScript for each page. However, `react.lazy` has some limitations when used with SSR (Server-Side Rendering).
|
|
679
609
|
|
|
680
610
|
3. **Using `@loadable/component`**:
|
|
@@ -706,3 +636,7 @@ By using these techniques, you can ensure that only the necessary components and
|
|
|
706
636
|
|
|
707
637
|
Please see our [contributing guidelines](https://github.com/storyblok/.github/blob/master/contributing.md) and our [code of conduct](https://www.storyblok.com/trust-center#code-of-conduct?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react).
|
|
708
638
|
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.
|
|
639
|
+
|
|
640
|
+
## License
|
|
641
|
+
|
|
642
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
package/dist/client.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
"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;
|
package/dist/client.mjs
CHANGED
package/dist/common.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./storyblok-js.js"),b=require("./server-component.js");let t=null;const n=new Map;let l=!1,s=null;globalThis.storyCache=new Map;const a=()=>(t||console.error("You can't use getStoryblokApi if you're not loading apiPlugin."),t),c=e=>(Object.entries(e).forEach(([r,i])=>{n.set(r,i)}),n),k=e=>n.has(e)?n.get(e):(console.error(`Component ${e} doesn't exist.`),!1),m=()=>l,u=()=>s,g=(e={})=>{if(t)return()=>t;const{storyblokApi:r}=o.storyblokInit(e);return t=r,e.components&&c(e.components),l=e.enableFallbackComponent,s=e.customFallbackComponent,()=>r};exports.RichTextResolver=o.RichTextResolver;exports.RichTextSchema=o.RichTextSchema;exports.apiPlugin=o.apiPlugin;exports.loadStoryblokBridge=o.loadStoryblokBridge;exports.registerStoryblokBridge=o.registerStoryblokBridge;exports.renderRichText=o.renderRichText;exports.storyblokEditable=o.storyblokEditable;exports.useStoryblokBridge=o.registerStoryblokBridge;exports.StoryblokServerComponent=b;exports.getComponent=k;exports.getCustomFallbackComponent=u;exports.getEnableFallbackComponent=m;exports.getStoryblokApi=a;exports.setComponents=c;exports.storyblokInit=g;exports.useStoryblokApi=a;
|
package/dist/common.mjs
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { storyblokInit as a } from "./storyblok-js.mjs";
|
|
2
|
+
import { RichTextResolver as g, RichTextSchema as C, apiPlugin as d, loadStoryblokBridge as S, registerStoryblokBridge as h, renderRichText as x, storyblokEditable as F, registerStoryblokBridge as A } from "./storyblok-js.mjs";
|
|
3
|
+
import { default as M } from "./server-component.mjs";
|
|
4
|
+
let e = null;
|
|
5
|
+
const r = /* @__PURE__ */ new Map();
|
|
6
|
+
let n = !1, l = null;
|
|
7
|
+
globalThis.storyCache = /* @__PURE__ */ new Map();
|
|
8
|
+
const i = () => (e || console.error(
|
|
9
|
+
"You can't use getStoryblokApi if you're not loading apiPlugin."
|
|
10
|
+
), e), c = (o) => (Object.entries(o).forEach(([t, s]) => {
|
|
11
|
+
r.set(t, s);
|
|
12
|
+
}), r), k = (o) => r.has(o) ? r.get(o) : (console.error(`Component ${o} doesn't exist.`), !1), m = () => n, p = () => l, u = (o = {}) => {
|
|
13
|
+
if (e)
|
|
14
|
+
return () => e;
|
|
15
|
+
const { storyblokApi: t } = a(o);
|
|
16
|
+
return e = t, o.components && c(o.components), n = o.enableFallbackComponent, l = o.customFallbackComponent, () => t;
|
|
17
|
+
};
|
|
18
|
+
export {
|
|
19
|
+
g as RichTextResolver,
|
|
20
|
+
C as RichTextSchema,
|
|
21
|
+
M as StoryblokServerComponent,
|
|
22
|
+
d as apiPlugin,
|
|
23
|
+
k as getComponent,
|
|
24
|
+
p as getCustomFallbackComponent,
|
|
25
|
+
m as getEnableFallbackComponent,
|
|
26
|
+
i as getStoryblokApi,
|
|
27
|
+
S as loadStoryblokBridge,
|
|
28
|
+
h as registerStoryblokBridge,
|
|
29
|
+
x as renderRichText,
|
|
30
|
+
c as setComponents,
|
|
31
|
+
F as storyblokEditable,
|
|
32
|
+
u as storyblokInit,
|
|
33
|
+
i as useStoryblokApi,
|
|
34
|
+
A as useStoryblokBridge
|
|
35
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("react"),e=require("./storyblok-js.js"),o=require("./index2.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("react"),e=require("./storyblok-js.js"),o=require("./index2.js"),k=require("./client.js"),S=require("./storyblok-component.js"),d=(s,r={},t={})=>{const[a,i]=y.useState({}),u=typeof window<"u"&&typeof window.storyblokRegisterEvent<"u",n=o.useStoryblokApi();return y.useEffect(()=>{if(!n){console.error("You can't use useStoryblok if you're not loading apiPlugin.");return}async function b(){const{data:l}=await n.get(`cdn/stories/${s}`,r);i(l.story),u&&l.story.id&&e.registerStoryblokBridge(l.story.id,c=>i(c),t)}b()},[s,JSON.stringify(r),n]),n?(t.resolveRelations=t.resolveRelations??r.resolve_relations,t.resolveLinks=t.resolveLinks??r.resolve_links,a):null};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;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.useStoryblokState=k.useStoryblokState;exports.StoryblokComponent=S;exports.useStoryblok=d;
|
package/dist/index.mjs
CHANGED
|
@@ -6,8 +6,7 @@ import { getComponent as h, getCustomFallbackComponent as A, getEnableFallbackCo
|
|
|
6
6
|
import { useStoryblokState as N } from "./client.mjs";
|
|
7
7
|
import { default as _ } from "./storyblok-component.mjs";
|
|
8
8
|
const b = (s, e = {}, o = {}) => {
|
|
9
|
-
|
|
10
|
-
const i = typeof window < "u" && typeof window.storyblokRegisterEvent < "u", t = c();
|
|
9
|
+
const [l, n] = f({}), i = typeof window < "u" && typeof window.storyblokRegisterEvent < "u", t = c();
|
|
11
10
|
return u(() => {
|
|
12
11
|
if (!t) {
|
|
13
12
|
console.error(
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
"use strict";var n=Object.create;var a=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var l=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty;var p=(e,t,i,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of d(t))!s.call(e,r)&&r!==i&&a(e,r,{get:()=>t[r],enumerable:!(o=c(t,r))||o.enumerable});return e};var v=(e,t,i)=>(i=e!=null?n(l(e)):{},p(t||!e||!e.__esModule?a(i,"default",{value:e,enumerable:!0}):i,e));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});async function u({story:e,pathToRevalidate:t}){if(!e||!t)return console.error("liveEditUpdateAction: story or pathToRevalidate is not provided");if(globalThis.storyCache.set(e.uuid,e),process.env.NEXT_RUNTIME)try{const{revalidatePath:i}=await import("next/cache");i(t)}catch(i){console.error("liveEditUpdateAction: error while revalidating path",i)}}exports.liveEditUpdateAction=u;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
async function r({ story: e, pathToRevalidate: i }) {
|
|
3
|
+
if (!e || !i)
|
|
4
|
+
return console.error("liveEditUpdateAction: story or pathToRevalidate is not provided");
|
|
5
|
+
if (globalThis.storyCache.set(e.uuid, e), process.env.NEXT_RUNTIME)
|
|
6
|
+
try {
|
|
7
|
+
const { revalidatePath: t } = await import("next/cache");
|
|
8
|
+
t(i);
|
|
9
|
+
} catch (t) {
|
|
10
|
+
console.error("liveEditUpdateAction: error while revalidating path", t);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
r as liveEditUpdateAction
|
|
15
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";const r=require("./storyblok-js.js"),t=require("react"),o=require("./live-edit-update-action.js"),a=({story:e=null,bridgeOptions:i={}})=>{if(typeof window>"u")return null;const d=n=>{n&&t.startTransition(()=>{o.liveEditUpdateAction({story:n,pathToRevalidate:window.location.pathname})})},l=(e==null?void 0:e.internalId)??(e==null?void 0:e.id)??0;return t.useEffect(()=>{r.registerStoryblokBridge(l,n=>d(n),i)},[]),null};module.exports=a;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { registerStoryblokBridge as d } from "./storyblok-js.mjs";
|
|
3
|
+
import { useEffect as l, startTransition as o } from "react";
|
|
4
|
+
import { liveEditUpdateAction as r } from "./live-edit-update-action.mjs";
|
|
5
|
+
const m = ({ story: n = null, bridgeOptions: i = {} }) => {
|
|
6
|
+
if (typeof window > "u")
|
|
7
|
+
return null;
|
|
8
|
+
const t = (e) => {
|
|
9
|
+
e && o(() => {
|
|
10
|
+
r({ story: e, pathToRevalidate: window.location.pathname });
|
|
11
|
+
});
|
|
12
|
+
}, a = (n == null ? void 0 : n.internalId) ?? (n == null ? void 0 : n.id) ?? 0;
|
|
13
|
+
return l(() => {
|
|
14
|
+
d(a, (e) => t(e), i);
|
|
15
|
+
}, []), null;
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
m as default
|
|
19
|
+
};
|
package/dist/rsc.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./
|
|
1
|
+
"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;
|
package/dist/rsc.mjs
CHANGED
|
@@ -1,26 +1,23 @@
|
|
|
1
|
-
import { getComponent as t, getCustomFallbackComponent as r, getEnableFallbackComponent as l, useStoryblokApi as
|
|
1
|
+
import { getComponent as t, getCustomFallbackComponent as r, getEnableFallbackComponent as l, useStoryblokApi as i, setComponents as a, storyblokInit as b, useStoryblokApi as s } from "./common.mjs";
|
|
2
2
|
import { default as k } from "./story.mjs";
|
|
3
|
-
import { default as
|
|
4
|
-
import {
|
|
5
|
-
import { RichTextResolver as f, RichTextSchema as u, apiPlugin as x, loadStoryblokBridge as c, registerStoryblokBridge as B, renderRichText as C, storyblokEditable as h, registerStoryblokBridge as R } from "./storyblok-js.mjs";
|
|
3
|
+
import { default as y } from "./server-component.mjs";
|
|
4
|
+
import { RichTextResolver as g, RichTextSchema as m, apiPlugin as d, loadStoryblokBridge as u, registerStoryblokBridge as x, renderRichText as c, storyblokEditable as f, registerStoryblokBridge as C } from "./storyblok-js.mjs";
|
|
6
5
|
export {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
g as StoryblokBridgeLoader,
|
|
11
|
-
m as StoryblokComponent,
|
|
6
|
+
g as RichTextResolver,
|
|
7
|
+
m as RichTextSchema,
|
|
8
|
+
y as StoryblokServerComponent,
|
|
12
9
|
k as StoryblokStory,
|
|
13
|
-
|
|
10
|
+
d as apiPlugin,
|
|
14
11
|
t as getComponent,
|
|
15
12
|
r as getCustomFallbackComponent,
|
|
16
13
|
l as getEnableFallbackComponent,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
i as getStoryblokApi,
|
|
15
|
+
u as loadStoryblokBridge,
|
|
16
|
+
x as registerStoryblokBridge,
|
|
17
|
+
c as renderRichText,
|
|
18
|
+
a as setComponents,
|
|
19
|
+
f as storyblokEditable,
|
|
20
|
+
b as storyblokInit,
|
|
21
|
+
s as useStoryblokApi,
|
|
22
|
+
C as useStoryblokBridge
|
|
26
23
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const e=require("react"),o=require("./common.js");require("./story.js");const c=e.forwardRef(({blok:t,...n},m)=>{if(!t)return console.error("Please provide a 'blok' property to the StoryblokComponent"),e.createElement("div",null,"Please provide a blok property to the StoryblokComponent");const r=o.getComponent(t.component);if(r)return e.createElement(r,{ref:m,blok:t,...n});if(o.getEnableFallbackComponent()){const l=o.getCustomFallbackComponent();return l?e.createElement(l,{blok:t,...n}):e.createElement(e.Fragment,null,e.createElement("p",null,"Component could not be found for blok"," ",e.createElement("strong",null,t.component),"! Is it configured correctly?"))}return e.createElement("div",null)});c.displayName="StoryblokComponent";module.exports=c;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import e, { forwardRef as m } from "react";
|
|
2
|
+
import { getComponent as a, getEnableFallbackComponent as p, getCustomFallbackComponent as c } from "./common.mjs";
|
|
3
|
+
import "./story.mjs";
|
|
4
|
+
const u = m(
|
|
5
|
+
({ blok: t, ...o }, l) => {
|
|
6
|
+
if (!t)
|
|
7
|
+
return console.error(
|
|
8
|
+
"Please provide a 'blok' property to the StoryblokComponent"
|
|
9
|
+
), /* @__PURE__ */ e.createElement("div", null, "Please provide a blok property to the StoryblokComponent");
|
|
10
|
+
const n = a(t.component);
|
|
11
|
+
if (n)
|
|
12
|
+
return /* @__PURE__ */ e.createElement(n, { ref: l, blok: t, ...o });
|
|
13
|
+
if (p()) {
|
|
14
|
+
const r = c();
|
|
15
|
+
return r ? /* @__PURE__ */ e.createElement(r, { blok: t, ...o }) : /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement("p", null, "Component could not be found for blok", " ", /* @__PURE__ */ e.createElement("strong", null, t.component), "! Is it configured correctly?"));
|
|
16
|
+
}
|
|
17
|
+
return /* @__PURE__ */ e.createElement("div", null);
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
u.displayName = "StoryblokComponent";
|
|
21
|
+
export {
|
|
22
|
+
u as default
|
|
23
|
+
};
|
package/dist/story.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
"use
|
|
2
|
-
"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;
|
|
1
|
+
"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;
|
package/dist/story.mjs
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
const
|
|
6
|
-
({ story:
|
|
1
|
+
import r, { forwardRef as c } from "react";
|
|
2
|
+
import "./common.mjs";
|
|
3
|
+
import a from "./live-editing.mjs";
|
|
4
|
+
import i from "./server-component.mjs";
|
|
5
|
+
const h = c(
|
|
6
|
+
({ story: e, bridgeOptions: t, ...o }, n) => {
|
|
7
|
+
if (!e)
|
|
8
|
+
return console.error(
|
|
9
|
+
"Please provide a 'story' property to the StoryblokServerComponent"
|
|
10
|
+
), null;
|
|
11
|
+
if (globalThis.storyCache.has(e.uuid) && (e = globalThis.storyCache.get(e.uuid)), typeof e.content == "string")
|
|
12
|
+
try {
|
|
13
|
+
e.content = JSON.parse(e.content);
|
|
14
|
+
} catch (l) {
|
|
15
|
+
console.error(
|
|
16
|
+
"An error occurred while trying to parse the story content",
|
|
17
|
+
l
|
|
18
|
+
), e.content = {};
|
|
19
|
+
}
|
|
20
|
+
return /* @__PURE__ */ r.createElement(r.Fragment, null, /* @__PURE__ */ r.createElement(i, { ref: n, blok: e.content, ...o }), /* @__PURE__ */ r.createElement(a, { story: e, bridgeOptions: t }));
|
|
21
|
+
}
|
|
7
22
|
);
|
|
8
23
|
export {
|
|
9
|
-
|
|
24
|
+
h as default
|
|
10
25
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { TUseStoryblokState } from
|
|
1
|
+
import type { TUseStoryblokState } from '../types';
|
|
2
2
|
export declare const useStoryblokState: TUseStoryblokState;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { SbReactComponentsMap, SbReactSDKOptions, StoryblokClient } from
|
|
1
|
+
import type { SbReactComponentsMap, SbReactSDKOptions, StoryblokClient } from '../types';
|
|
2
2
|
export declare const useStoryblokApi: () => StoryblokClient;
|
|
3
3
|
export declare const setComponents: (newComponentsMap: SbReactComponentsMap) => SbReactComponentsMap;
|
|
4
4
|
export declare const getComponent: (componentKey: string) => false | import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements>;
|
|
5
5
|
export declare const getEnableFallbackComponent: () => boolean;
|
|
6
6
|
export declare const getCustomFallbackComponent: () => import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements>;
|
|
7
7
|
export declare const storyblokInit: (pluginOptions?: SbReactSDKOptions) => void;
|
|
8
|
-
export
|
|
8
|
+
export * from '../types';
|
|
9
9
|
export { useStoryblokApi as getStoryblokApi };
|
|
10
|
-
export {
|
|
11
|
-
export
|
|
10
|
+
export { default as StoryblokComponent } from './storyblok-component';
|
|
11
|
+
export { apiPlugin, loadStoryblokBridge, registerStoryblokBridge, renderRichText, RichTextResolver, RichTextSchema, storyblokEditable, useStoryblokBridge, } from '@storyblok/js';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ISbStoriesParams,
|
|
1
|
+
import type { ISbStoriesParams, ISbStoryData, StoryblokBridgeConfigV2 } from './types';
|
|
2
2
|
export declare const useStoryblok: (slug: string, apiOptions?: ISbStoriesParams, bridgeOptions?: StoryblokBridgeConfigV2) => ISbStoryData<import("@storyblok/js").StoryblokComponentType<string> & {
|
|
3
3
|
[index: string]: any;
|
|
4
4
|
}>;
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
5
|
+
export * from './common';
|
|
6
|
+
export * from './common/client';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SbReactComponentsMap, SbReactSDKOptions, StoryblokClient } from '../types';
|
|
2
|
+
export declare const useStoryblokApi: () => StoryblokClient;
|
|
3
|
+
export declare const setComponents: (newComponentsMap: SbReactComponentsMap) => Map<string, import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements>>;
|
|
4
|
+
export declare const getComponent: (componentKey: string) => React.ElementType | false;
|
|
5
|
+
export declare const getEnableFallbackComponent: () => boolean;
|
|
6
|
+
export declare const getCustomFallbackComponent: () => import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements>;
|
|
7
|
+
export declare const storyblokInit: (pluginOptions?: SbReactSDKOptions) => (() => StoryblokClient);
|
|
8
|
+
export * from '../types';
|
|
9
|
+
export { useStoryblokApi as getStoryblokApi };
|
|
10
|
+
export { default as StoryblokServerComponent } from './server-component';
|
|
11
|
+
export { apiPlugin, loadStoryblokBridge, registerStoryblokBridge, renderRichText, RichTextResolver, RichTextSchema, storyblokEditable, useStoryblokBridge, } from '@storyblok/js';
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export { default as StoryblokStory } from
|
|
3
|
-
export { default as BridgeLoader } from "../bridge-loader";
|
|
4
|
-
export { default as StoryblokBridgeLoader } from "../bridge-loader";
|
|
1
|
+
export * from './common';
|
|
2
|
+
export { default as StoryblokStory } from './story';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SbBlokData } from '../types';
|
|
3
|
+
interface SbServerComponentProps {
|
|
4
|
+
blok: SbBlokData;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
declare const StoryblokServerComponent: React.ForwardRefExoticComponent<Omit<SbServerComponentProps, "ref"> & React.RefAttributes<HTMLElement>>;
|
|
8
|
+
export default StoryblokServerComponent;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { ISbStoryData, StoryblokBridgeConfigV2 } from
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ISbStoryData, StoryblokBridgeConfigV2 } from '../types';
|
|
3
3
|
interface StoryblokStoryProps {
|
|
4
4
|
story: ISbStoryData;
|
|
5
5
|
bridgeOptions: StoryblokBridgeConfigV2;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { SbSDKOptions } from
|
|
3
|
-
import type { ISbStoryData, StoryblokBridgeConfigV2 } from "@storyblok/js";
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { ISbStoryData, SbSDKOptions, StoryblokBridgeConfigV2 } from '@storyblok/js';
|
|
4
3
|
export interface SbReactComponentsMap {
|
|
5
4
|
[key: string]: React.ElementType;
|
|
6
5
|
}
|
|
@@ -10,4 +9,4 @@ export interface SbReactSDKOptions extends SbSDKOptions {
|
|
|
10
9
|
customFallbackComponent?: React.ElementType;
|
|
11
10
|
}
|
|
12
11
|
export type TUseStoryblokState = <T = void>(initialStory: ISbStoryData<T> | null, bridgeOptions?: StoryblokBridgeConfigV2) => ISbStoryData<T> | null;
|
|
13
|
-
export type {
|
|
12
|
+
export type { ArrayFn, AsyncFn, ISbAlternateObject, ISbCache, ISbConfig, ISbContentMangmntAPI, ISbDimensions, ISbError, ISbManagmentApiResult, ISbNode, ISbResponse, ISbResult, ISbRichtext, ISbSchema, ISbStories, ISbStoriesParams, ISbStory, ISbStoryData, ISbStoryParams, SbBlokData, SbBlokKeyDataTypes, SbRichTextOptions, SbSDKOptions, StoryblokBridgeConfigV2, StoryblokBridgeV2, StoryblokClient, StoryblokComponentType, ThrottleFn, useStoryblokBridge, } from '@storyblok/js';
|
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storyblok/react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "SDK to integrate Storyblok into your project using React.",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
|
|
5
|
+
"author": "Storyblok",
|
|
6
|
+
"homepage": "https://github.com/storyblok/storyblok-react",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/storyblok/storyblok-react"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/storyblok/storyblok-react/issues"
|
|
13
|
+
},
|
|
11
14
|
"exports": {
|
|
12
15
|
".": {
|
|
13
16
|
"types": "./dist/types/index.d.ts",
|
|
@@ -30,6 +33,12 @@
|
|
|
30
33
|
"require": "./dist/story.js"
|
|
31
34
|
}
|
|
32
35
|
},
|
|
36
|
+
"main": "./dist/index.js",
|
|
37
|
+
"module": "./dist/index.mjs",
|
|
38
|
+
"types": "./dist/types/index.d.ts",
|
|
39
|
+
"files": [
|
|
40
|
+
"dist"
|
|
41
|
+
],
|
|
33
42
|
"scripts": {
|
|
34
43
|
"dev": "vite build --watch",
|
|
35
44
|
"build": "vite build && tsc --project tsconfig.json",
|
|
@@ -43,31 +52,32 @@
|
|
|
43
52
|
"test:comp": "cypress run-ct",
|
|
44
53
|
"prepublishOnly": "npm run build && cp ../README.md ./"
|
|
45
54
|
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"react": "^17.0.0 || ^18.0.0",
|
|
57
|
+
"react-dom": "^17.0.0 || ^18.0.0"
|
|
58
|
+
},
|
|
46
59
|
"dependencies": {
|
|
47
|
-
"@storyblok/js": "^3.1.1"
|
|
60
|
+
"@storyblok/js": "^3.1.1",
|
|
61
|
+
"next": "14.2.14"
|
|
48
62
|
},
|
|
49
63
|
"devDependencies": {
|
|
50
64
|
"@babel/core": "^7.25.2",
|
|
51
65
|
"@babel/preset-env": "^7.25.4",
|
|
52
66
|
"@cypress/react": "^8.0.2",
|
|
53
|
-
"@cypress/vite-dev-server": "^5.
|
|
67
|
+
"@cypress/vite-dev-server": "^5.2.0",
|
|
54
68
|
"@tsconfig/recommended": "^1.0.7",
|
|
55
69
|
"@types/react": "18.3.4",
|
|
56
70
|
"@vitejs/plugin-react": "^4.3.1",
|
|
57
71
|
"babel-jest": "^29.7.0",
|
|
58
|
-
"cypress": "^13.
|
|
72
|
+
"cypress": "^13.14.2",
|
|
59
73
|
"eslint-plugin-cypress": "^3.5.0",
|
|
60
|
-
"eslint-plugin-jest": "^28.8.
|
|
74
|
+
"eslint-plugin-jest": "^28.8.3",
|
|
61
75
|
"jest": "^29.7.0",
|
|
62
76
|
"react": "^18.3.1",
|
|
63
77
|
"react-dom": "^18.3.1",
|
|
64
78
|
"rollup-plugin-preserve-directives": "^0.4.0",
|
|
65
79
|
"start-server-and-test": "^2.0.5",
|
|
66
|
-
"vite": "^5.4.
|
|
67
|
-
},
|
|
68
|
-
"peerDependencies": {
|
|
69
|
-
"react": "^17.0.0 || ^18.0.0",
|
|
70
|
-
"react-dom": "^17.0.0 || ^18.0.0"
|
|
80
|
+
"vite": "^5.4.3"
|
|
71
81
|
},
|
|
72
82
|
"babel": {
|
|
73
83
|
"presets": [
|
|
@@ -95,15 +105,6 @@
|
|
|
95
105
|
"main"
|
|
96
106
|
]
|
|
97
107
|
},
|
|
98
|
-
"repository": {
|
|
99
|
-
"type": "git",
|
|
100
|
-
"url": "https://github.com/storyblok/storyblok-react"
|
|
101
|
-
},
|
|
102
|
-
"author": "Storyblok",
|
|
103
|
-
"bugs": {
|
|
104
|
-
"url": "https://github.com/storyblok/storyblok-react/issues"
|
|
105
|
-
},
|
|
106
|
-
"homepage": "https://github.com/storyblok/storyblok-react",
|
|
107
108
|
"publishConfig": {
|
|
108
109
|
"access": "public"
|
|
109
110
|
}
|
package/dist/bridge-loader.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
"use strict";const o=require("react"),r=require("./storyblok-js.js"),t=async e=>{await r.loadStoryblokBridge(),new window.StoryblokBridge(e).on(["published","change"],()=>{window.location.reload()})},n=({options:e})=>(t(e),o.createElement(o.Fragment,null));module.exports=n;
|
package/dist/bridge-loader.mjs
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import o from "react";
|
|
3
|
-
import { loadStoryblokBridge as r } from "./storyblok-js.mjs";
|
|
4
|
-
const t = async (e) => {
|
|
5
|
-
await r(), new window.StoryblokBridge(e).on(["published", "change"], () => {
|
|
6
|
-
window.location.reload();
|
|
7
|
-
});
|
|
8
|
-
}, i = ({ options: e }) => (t(e), /* @__PURE__ */ o.createElement(o.Fragment, null));
|
|
9
|
-
export {
|
|
10
|
-
i as default
|
|
11
|
-
};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { StoryblokBridgeConfigV2 } from "./types";
|
|
3
|
-
interface StoryblokBridgeLoaderProps {
|
|
4
|
-
options: StoryblokBridgeConfigV2;
|
|
5
|
-
[key: string]: unknown;
|
|
6
|
-
}
|
|
7
|
-
declare const StoryblokBridgeLoader: ({ options }: StoryblokBridgeLoaderProps) => React.JSX.Element;
|
|
8
|
-
export default StoryblokBridgeLoader;
|