@storyblok/react 5.0.0 → 5.0.2-rc.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 +147 -88
- package/dist/index.d.ts +1 -1
- package/dist/richtext.mjs +4 -4
- package/dist/storyblok-js.js +1 -1
- package/dist/storyblok-js.mjs +260 -247
- package/package.json +32 -51
package/README.md
CHANGED
|
@@ -31,12 +31,15 @@
|
|
|
31
31
|
</p>
|
|
32
32
|
|
|
33
33
|
## Kickstart a new project
|
|
34
|
+
|
|
34
35
|
Are you eager to dive into coding? **[Follow these steps to kickstart a new project with Storyblok and React](https://www.storyblok.com/technologies?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react#react)**, and get started in just a few minutes!
|
|
35
36
|
|
|
36
37
|
## 5-minute Tutorial
|
|
38
|
+
|
|
37
39
|
Are you looking for a hands-on, step-by-step tutorial? The **[React 5-minute Tutorial](https://www.storyblok.com/tp/headless-cms-react?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react)** has you covered! It provides comprehensive instructions on how to set up a Storyblok space and connect it to your React project.
|
|
38
40
|
|
|
39
41
|
## Ultimate Tutorial
|
|
42
|
+
|
|
40
43
|
Are you looking for a hands-on, step-by-step tutorial? The **[Next.js Ultimate Tutorial](https://www.storyblok.com/tp/nextjs-headless-cms-ultimate-tutorial?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react)** has you covered! It provides comprehensive instructions on building a complete, multilingual website using Storyblok and Next.js from start to finish.
|
|
41
44
|
|
|
42
45
|
## Installation
|
|
@@ -63,15 +66,15 @@ Install the file from the CDN:
|
|
|
63
66
|
Register the plugin on your application and add the [access token](https://www.storyblok.com/docs/api/content-delivery/v2/getting-started/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
67
|
|
|
65
68
|
```js
|
|
66
|
-
import { apiPlugin, storyblokInit } from
|
|
69
|
+
import { apiPlugin, storyblokInit } from "@storyblok/react";
|
|
67
70
|
|
|
68
71
|
/** Import your components */
|
|
69
|
-
import Page from
|
|
70
|
-
import Teaser from
|
|
72
|
+
import Page from "./components/Page";
|
|
73
|
+
import Teaser from "./components/Teaser";
|
|
71
74
|
// import FallbackComponent from "./components/FallbackComponent";
|
|
72
75
|
|
|
73
76
|
storyblokInit({
|
|
74
|
-
accessToken:
|
|
77
|
+
accessToken: "YOUR_ACCESS_TOKEN",
|
|
75
78
|
use: [apiPlugin],
|
|
76
79
|
components: {
|
|
77
80
|
page: Page,
|
|
@@ -82,7 +85,7 @@ storyblokInit({
|
|
|
82
85
|
// richText: {},
|
|
83
86
|
// enableFallbackComponent: false,
|
|
84
87
|
// customFallbackComponent: FallbackComponent,
|
|
85
|
-
})
|
|
88
|
+
});
|
|
86
89
|
```
|
|
87
90
|
|
|
88
91
|
> 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 +109,16 @@ Possible values:
|
|
|
106
109
|
Full example for a space created in the US:
|
|
107
110
|
|
|
108
111
|
```js
|
|
109
|
-
import { apiPlugin, storyblokInit } from
|
|
112
|
+
import { apiPlugin, storyblokInit } from "@storyblok/react";
|
|
110
113
|
|
|
111
114
|
storyblokInit({
|
|
112
|
-
accessToken:
|
|
115
|
+
accessToken: "YOUR_ACCESS_TOKEN",
|
|
113
116
|
use: [apiPlugin],
|
|
114
117
|
apiOptions: {
|
|
115
|
-
region:
|
|
118
|
+
region: "us",
|
|
116
119
|
},
|
|
117
120
|
components: {},
|
|
118
|
-
})
|
|
121
|
+
});
|
|
119
122
|
```
|
|
120
123
|
|
|
121
124
|
> Note: For spaces created in the United States or China, the `region` parameter **must** be specified.
|
|
@@ -129,7 +132,7 @@ storyblokInit({
|
|
|
129
132
|
For every component you've defined in your Storyblok space, call the `storyblokEditable` function with the blok content:
|
|
130
133
|
|
|
131
134
|
```js
|
|
132
|
-
import { storyblokEditable } from
|
|
135
|
+
import { storyblokEditable } from "@storyblok/react";
|
|
133
136
|
|
|
134
137
|
const Feature = ({ blok }) => {
|
|
135
138
|
return (
|
|
@@ -139,10 +142,10 @@ const Feature = ({ blok }) => {
|
|
|
139
142
|
<p>{blok.description}</p>
|
|
140
143
|
</div>
|
|
141
144
|
</div>
|
|
142
|
-
)
|
|
143
|
-
}
|
|
145
|
+
);
|
|
146
|
+
};
|
|
144
147
|
|
|
145
|
-
export default Feature
|
|
148
|
+
export default Feature;
|
|
146
149
|
```
|
|
147
150
|
|
|
148
151
|
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 +167,19 @@ The initalization remains the same when you work with React. You can intialze th
|
|
|
164
167
|
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
168
|
|
|
166
169
|
```js
|
|
167
|
-
import { StoryblokComponent, useStoryblok } from
|
|
170
|
+
import { StoryblokComponent, useStoryblok } from "@storyblok/react";
|
|
168
171
|
|
|
169
172
|
function App() {
|
|
170
|
-
const story = useStoryblok(
|
|
173
|
+
const story = useStoryblok("react", { version: "draft" });
|
|
171
174
|
|
|
172
175
|
if (!story?.content) {
|
|
173
|
-
return <div>Loading...</div
|
|
176
|
+
return <div>Loading...</div>;
|
|
174
177
|
}
|
|
175
178
|
|
|
176
|
-
return <StoryblokComponent blok={story.content}
|
|
179
|
+
return <StoryblokComponent blok={story.content} />;
|
|
177
180
|
}
|
|
178
181
|
|
|
179
|
-
export default App
|
|
182
|
+
export default App;
|
|
180
183
|
```
|
|
181
184
|
|
|
182
185
|
`StoryblokComponent` renders the route components dynamically, using the list of components loaded during the initialization inside the `storyblokInit` function.
|
|
@@ -186,13 +189,13 @@ This is how you can pass the Bridge options as a third parameter to `useStoryblo
|
|
|
186
189
|
```js
|
|
187
190
|
useStoryblok(
|
|
188
191
|
story.id,
|
|
189
|
-
{ version:
|
|
192
|
+
{ version: "draft", resolveRelations: ["Article.author"] },
|
|
190
193
|
{
|
|
191
|
-
resolveRelations: [
|
|
192
|
-
resolveLinks:
|
|
194
|
+
resolveRelations: ["Article.author"],
|
|
195
|
+
resolveLinks: "url",
|
|
193
196
|
preventClicks: true,
|
|
194
|
-
}
|
|
195
|
-
)
|
|
197
|
+
},
|
|
198
|
+
);
|
|
196
199
|
```
|
|
197
200
|
|
|
198
201
|
**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)**
|
|
@@ -212,13 +215,13 @@ Here's how you can fetch data from Storyblok with `cache: "no-store"`:
|
|
|
212
215
|
|
|
213
216
|
```typescript
|
|
214
217
|
export async function fetchData() {
|
|
215
|
-
const sbParams: ISbStoriesParams = { version:
|
|
218
|
+
const sbParams: ISbStoriesParams = { version: "draft" };
|
|
216
219
|
|
|
217
|
-
const storyblokApi: StoryblokClient = getStoryblokApi()
|
|
220
|
+
const storyblokApi: StoryblokClient = getStoryblokApi();
|
|
218
221
|
|
|
219
222
|
return storyblokApi.get(`cdn/stories/home`, sbParams, {
|
|
220
|
-
cache:
|
|
221
|
-
})
|
|
223
|
+
cache: "no-store", // This prevents Next.js 13, 14 default caching behaviour
|
|
224
|
+
});
|
|
222
225
|
}
|
|
223
226
|
```
|
|
224
227
|
|
|
@@ -234,12 +237,12 @@ Create a new file `lib/storyblok.js` and initialize the SDK. Make sure you expor
|
|
|
234
237
|
|
|
235
238
|
```js
|
|
236
239
|
// lib/storyblok.js
|
|
237
|
-
import Page from
|
|
238
|
-
import Teaser from
|
|
239
|
-
import { apiPlugin, storyblokInit } from
|
|
240
|
+
import Page from "@/components/Page";
|
|
241
|
+
import Teaser from "@/components/Teaser";
|
|
242
|
+
import { apiPlugin, storyblokInit } from "@storyblok/react/rsc";
|
|
240
243
|
|
|
241
244
|
export const getStoryblokApi = storyblokInit({
|
|
242
|
-
accessToken:
|
|
245
|
+
accessToken: "YOUR_ACCESS_TOKEN",
|
|
243
246
|
use: [apiPlugin],
|
|
244
247
|
components: {
|
|
245
248
|
teaser: Teaser,
|
|
@@ -252,8 +255,8 @@ In `app/layout.jsx`, wrap your whole app using a `StoryblokProvider` component (
|
|
|
252
255
|
|
|
253
256
|
```js
|
|
254
257
|
// app/layout.jsx
|
|
255
|
-
import { apiPlugin, storyblokInit } from
|
|
256
|
-
import StoryblokProvider from
|
|
258
|
+
import { apiPlugin, storyblokInit } from "@storyblok/react/rsc";
|
|
259
|
+
import StoryblokProvider from "../components/StoryblokProvider";
|
|
257
260
|
|
|
258
261
|
export default function RootLayout({ children }) {
|
|
259
262
|
return (
|
|
@@ -262,7 +265,7 @@ export default function RootLayout({ children }) {
|
|
|
262
265
|
<body>{children}</body>
|
|
263
266
|
</html>
|
|
264
267
|
</StoryblokProvider>
|
|
265
|
-
)
|
|
268
|
+
);
|
|
266
269
|
}
|
|
267
270
|
```
|
|
268
271
|
|
|
@@ -272,9 +275,9 @@ Create the `components/StoryblokProvider.jsx` file. Re-initalize the connection
|
|
|
272
275
|
|
|
273
276
|
```js
|
|
274
277
|
// components/StoryblokProvider.jsx
|
|
275
|
-
|
|
278
|
+
"use client";
|
|
276
279
|
|
|
277
|
-
import { getStoryblokApi } from
|
|
280
|
+
import { getStoryblokApi } from "@/lib/storyblok";
|
|
278
281
|
|
|
279
282
|
export default function StoryblokProvider({ children }) {
|
|
280
283
|
getStoryblokApi();
|
|
@@ -321,11 +324,14 @@ const bridgeOptions = { resolveRelations: ['article.author'] }
|
|
|
321
324
|
> When you render components, you must use `StoryblokServerComponent` exported from `@storyblok/react/rsc` instead of `StoryblokComponent`, even when you declare a client component with `"use client"`. This is because the components are always rendered on the server side.
|
|
322
325
|
|
|
323
326
|
```jsx
|
|
324
|
-
import {
|
|
327
|
+
import {
|
|
328
|
+
storyblokEditable,
|
|
329
|
+
StoryblokServerComponent,
|
|
330
|
+
} from "@storyblok/react/rsc";
|
|
325
331
|
|
|
326
332
|
const Page = ({ blok }) => (
|
|
327
333
|
<main {...storyblokEditable(blok)}>
|
|
328
|
-
{blok.body.map(nestedBlok => (
|
|
334
|
+
{blok.body.map((nestedBlok) => (
|
|
329
335
|
<StoryblokServerComponent blok={nestedBlok} key={nestedBlok._uid} />
|
|
330
336
|
))}
|
|
331
337
|
</main>
|
|
@@ -350,11 +356,11 @@ The initalization remains the same when you work with Next.js. You can intialze
|
|
|
350
356
|
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.
|
|
351
357
|
|
|
352
358
|
```js
|
|
353
|
-
import { getStoryblokApi } from
|
|
359
|
+
import { getStoryblokApi } from "@storyblok/react";
|
|
354
360
|
|
|
355
361
|
// At the required place
|
|
356
|
-
const storyblokApi = getStoryblokApi()
|
|
357
|
-
const { data } = await storyblokApi.get(
|
|
362
|
+
const storyblokApi = getStoryblokApi();
|
|
363
|
+
const { data } = await storyblokApi.get("cdn/stories", { version: "draft" });
|
|
358
364
|
```
|
|
359
365
|
|
|
360
366
|
> 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.
|
|
@@ -364,16 +370,16 @@ const { data } = await storyblokApi.get('cdn/stories', { version: 'draft' })
|
|
|
364
370
|
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.
|
|
365
371
|
|
|
366
372
|
```js
|
|
367
|
-
import { StoryblokComponent, useStoryblokState } from
|
|
373
|
+
import { StoryblokComponent, useStoryblokState } from "@storyblok/react";
|
|
368
374
|
|
|
369
375
|
export default function Home({ story: initialStory }) {
|
|
370
|
-
const story = useStoryblokState(initialStory)
|
|
376
|
+
const story = useStoryblokState(initialStory);
|
|
371
377
|
|
|
372
378
|
if (!story.content) {
|
|
373
|
-
return <div>Loading...</div
|
|
379
|
+
return <div>Loading...</div>;
|
|
374
380
|
}
|
|
375
381
|
|
|
376
|
-
return <StoryblokComponent blok={story.content}
|
|
382
|
+
return <StoryblokComponent blok={story.content} />;
|
|
377
383
|
}
|
|
378
384
|
```
|
|
379
385
|
|
|
@@ -384,23 +390,23 @@ import {
|
|
|
384
390
|
getStoryblokApi,
|
|
385
391
|
StoryblokComponent,
|
|
386
392
|
useStoryblokState,
|
|
387
|
-
} from
|
|
393
|
+
} from "@storyblok/react";
|
|
388
394
|
|
|
389
395
|
export default function Home({ story: initialStory }) {
|
|
390
|
-
const story = useStoryblokState(initialStory)
|
|
396
|
+
const story = useStoryblokState(initialStory);
|
|
391
397
|
|
|
392
398
|
if (!story.content) {
|
|
393
|
-
return <div>Loading...</div
|
|
399
|
+
return <div>Loading...</div>;
|
|
394
400
|
}
|
|
395
401
|
|
|
396
|
-
return <StoryblokComponent blok={story.content}
|
|
402
|
+
return <StoryblokComponent blok={story.content} />;
|
|
397
403
|
}
|
|
398
404
|
|
|
399
405
|
export async function getStaticProps({ preview = false }) {
|
|
400
|
-
const storyblokApi = getStoryblokApi()
|
|
406
|
+
const storyblokApi = getStoryblokApi();
|
|
401
407
|
const { data } = await storyblokApi.get(`cdn/stories/react`, {
|
|
402
|
-
version:
|
|
403
|
-
})
|
|
408
|
+
version: "draft",
|
|
409
|
+
});
|
|
404
410
|
|
|
405
411
|
return {
|
|
406
412
|
props: {
|
|
@@ -408,7 +414,7 @@ export async function getStaticProps({ preview = false }) {
|
|
|
408
414
|
preview,
|
|
409
415
|
},
|
|
410
416
|
revalidate: 3600, // revalidate every hour
|
|
411
|
-
}
|
|
417
|
+
};
|
|
412
418
|
}
|
|
413
419
|
```
|
|
414
420
|
|
|
@@ -489,10 +495,10 @@ You can use an `apiOptions` object. This is passed down to the [storyblok-js-cli
|
|
|
489
495
|
|
|
490
496
|
```js
|
|
491
497
|
storyblokInit({
|
|
492
|
-
accessToken:
|
|
498
|
+
accessToken: "YOUR_ACCESS_TOKEN",
|
|
493
499
|
apiOptions: {
|
|
494
500
|
// storyblok-js-client config object
|
|
495
|
-
cache: { type:
|
|
501
|
+
cache: { type: "memory" },
|
|
496
502
|
},
|
|
497
503
|
use: [apiPlugin],
|
|
498
504
|
components: {
|
|
@@ -501,13 +507,13 @@ storyblokInit({
|
|
|
501
507
|
grid: Grid,
|
|
502
508
|
feature: Feature,
|
|
503
509
|
},
|
|
504
|
-
})
|
|
510
|
+
});
|
|
505
511
|
```
|
|
506
512
|
|
|
507
513
|
If you prefer to use your own fetch method, just remove the `apiPlugin` and `storyblok-js-client` won't be added to your application.
|
|
508
514
|
|
|
509
515
|
```js
|
|
510
|
-
storyblokInit({})
|
|
516
|
+
storyblokInit({});
|
|
511
517
|
```
|
|
512
518
|
|
|
513
519
|
### Storyblok Bridge
|
|
@@ -515,14 +521,14 @@ storyblokInit({})
|
|
|
515
521
|
If you don't use `registerStoryblokBridge`, you still have access to the raw `window.StoryblokBridge`:
|
|
516
522
|
|
|
517
523
|
```js
|
|
518
|
-
const sbBridge = new window.StoryblokBridge(options)
|
|
524
|
+
const sbBridge = new window.StoryblokBridge(options);
|
|
519
525
|
|
|
520
|
-
sbBridge.on([
|
|
526
|
+
sbBridge.on(["input", "published", "change"], (event) => {
|
|
521
527
|
// ...
|
|
522
|
-
})
|
|
528
|
+
});
|
|
523
529
|
```
|
|
524
530
|
|
|
525
|
-
## Rendering Rich Text
|
|
531
|
+
## Rendering Rich Text
|
|
526
532
|
|
|
527
533
|
> [!WARNING]
|
|
528
534
|
> We have identified issues with richtext and Types on React 19 and Next.js 15. As a temporary measure, we advise you to continue using React 18 and Next.js 14 until we have fully resolved the issues.
|
|
@@ -607,25 +613,84 @@ function App() {
|
|
|
607
613
|
</a>
|
|
608
614
|
);
|
|
609
615
|
},
|
|
610
|
-
[BlockTypes.CODE_BLOCK]: (node) =>
|
|
611
|
-
<CodeBlock
|
|
616
|
+
[BlockTypes.CODE_BLOCK]: (node) =>
|
|
617
|
+
<CodeBlock
|
|
612
618
|
class={node?.attrs?.class}
|
|
613
619
|
>
|
|
614
|
-
{node.children}
|
|
620
|
+
{node.children}
|
|
615
621
|
</CodeBlock>;
|
|
616
622
|
}
|
|
617
623
|
|
|
618
624
|
return (
|
|
619
625
|
<div>
|
|
620
|
-
<StoryblokRichText
|
|
626
|
+
<StoryblokRichText
|
|
621
627
|
doc={story.content.richText}
|
|
622
|
-
resolvers={resolvers}
|
|
628
|
+
resolvers={resolvers}
|
|
623
629
|
/>
|
|
624
630
|
</div>
|
|
625
631
|
);
|
|
626
632
|
}
|
|
627
633
|
```
|
|
628
634
|
|
|
635
|
+
### Legacy Rich Text Resolver
|
|
636
|
+
|
|
637
|
+
> [!WARNING]
|
|
638
|
+
> The legacy `renderRichText` is soon to be deprecated. We recommend migrating to the new approach described above instead.
|
|
639
|
+
|
|
640
|
+
You can easily render rich text by using the `renderRichText` function that comes with `@storyblok/react`:
|
|
641
|
+
|
|
642
|
+
```js
|
|
643
|
+
import { renderRichText } from "@storyblok/react";
|
|
644
|
+
|
|
645
|
+
const renderedRichText = renderRichText(blok.richtext);
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
You can set a **custom Schema and component resolver globally** at init time by using the `richText` init option:
|
|
649
|
+
|
|
650
|
+
```js
|
|
651
|
+
import { RichTextSchema, storyblokInit } from "@storyblok/react";
|
|
652
|
+
import cloneDeep from "clone-deep";
|
|
653
|
+
|
|
654
|
+
const mySchema = cloneDeep(RichTextSchema); // you can make a copy of the default RichTextSchema
|
|
655
|
+
// ... and edit the nodes and marks, or add your own.
|
|
656
|
+
// Check the base RichTextSchema source here https://github.com/storyblok/storyblok-js-client/blob/main/src/schema.ts
|
|
657
|
+
|
|
658
|
+
storyblokInit({
|
|
659
|
+
accessToken: "<your-token>",
|
|
660
|
+
richText: {
|
|
661
|
+
schema: mySchema,
|
|
662
|
+
resolver: (component, blok) => {
|
|
663
|
+
switch (component) {
|
|
664
|
+
case "my-custom-component":
|
|
665
|
+
return `<div class="my-component-class">${blok.text}</div>`;
|
|
666
|
+
default:
|
|
667
|
+
return "Resolver not defined";
|
|
668
|
+
}
|
|
669
|
+
},
|
|
670
|
+
},
|
|
671
|
+
});
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
You can also set a **custom Schema and component resolver only once** by passing the options as the second parameter to `renderRichText` function:
|
|
675
|
+
|
|
676
|
+
```js
|
|
677
|
+
import { renderRichText } from "@storyblok/react";
|
|
678
|
+
|
|
679
|
+
renderRichText(blok.richTextField, {
|
|
680
|
+
schema: mySchema,
|
|
681
|
+
resolver: (component, blok) => {
|
|
682
|
+
switch (component) {
|
|
683
|
+
case "my-custom-component":
|
|
684
|
+
return `<div class="my-component-class">${blok.text}</div>`;
|
|
685
|
+
default:
|
|
686
|
+
return `Component ${component} not found`;
|
|
687
|
+
}
|
|
688
|
+
},
|
|
689
|
+
});
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
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.
|
|
693
|
+
|
|
629
694
|
### Using fallback components
|
|
630
695
|
|
|
631
696
|
By default, `@storyblok/react` returns an empty `<div>` if a component is not implemented. Setting `enableFallbackComponent` to `true` when calling `storyblokInit` bypasses that behavior, rendering a fallback component in the frontend instead. You can use the default fallback component, or create a custom React fallback component in your project and use it by setting `customFallbackComponent: [YourFallbackComponent]`.
|
|
@@ -641,7 +706,7 @@ storyblokInit({
|
|
|
641
706
|
components: {
|
|
642
707
|
// all your React components
|
|
643
708
|
},
|
|
644
|
-
})
|
|
709
|
+
});
|
|
645
710
|
```
|
|
646
711
|
|
|
647
712
|
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.
|
|
@@ -654,24 +719,24 @@ Storyblok's React SDK automatically renders these predefined components based on
|
|
|
654
719
|
2. **React's `react.lazy`**:
|
|
655
720
|
React offers a built-in solution called `react.lazy` for code splitting. Instead of directly importing components, you can do the following:
|
|
656
721
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
722
|
+
```javascript
|
|
723
|
+
"use client";
|
|
724
|
+
import { apiPlugin, storyblokInit } from "@storyblok/react/rsc";
|
|
725
|
+
import { lazy } from "react";
|
|
661
726
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
727
|
+
const lazyComponents = {
|
|
728
|
+
page: lazy(() => import("./components/Page")),
|
|
729
|
+
// other lazy-loaded components
|
|
730
|
+
};
|
|
666
731
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
732
|
+
storyblokInit({
|
|
733
|
+
accessToken,
|
|
734
|
+
use: [apiPlugin],
|
|
735
|
+
components: lazyComponents,
|
|
736
|
+
});
|
|
737
|
+
```
|
|
673
738
|
|
|
674
|
-
|
|
739
|
+
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).
|
|
675
740
|
|
|
676
741
|
3. **Using `@loadable/component`**:
|
|
677
742
|
For cases where SSR is needed, or in general, you can use the `@loadable/component` library, which offers similar functionality and better SSR support. This library is framework-agnostic and can be used with any React framework. [Loadable Components Documentation](https://loadable-components.com/docs/getting-started/)
|
|
@@ -703,12 +768,6 @@ By using these techniques, you can ensure that only the necessary components and
|
|
|
703
768
|
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?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-react#code-of-conduct).
|
|
704
769
|
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.
|
|
705
770
|
|
|
706
|
-
Please run `simple-git-hooks` after cloning the repository to enable the pre-commit hooks.
|
|
707
|
-
|
|
708
|
-
```bash
|
|
709
|
-
pnpm simple-git-hook
|
|
710
|
-
```
|
|
711
|
-
|
|
712
771
|
## License
|
|
713
772
|
|
|
714
773
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ISbStoriesParams, ISbStoryData, StoryblokBridgeConfigV2 } from './types';
|
|
2
2
|
import { useStoryblokRichText } from './richtext';
|
|
3
|
-
export declare const useStoryblok: (slug: string, apiOptions?: ISbStoriesParams, bridgeOptions?: StoryblokBridgeConfigV2) => ISbStoryData<import('
|
|
3
|
+
export declare const useStoryblok: (slug: string, apiOptions?: ISbStoriesParams, bridgeOptions?: StoryblokBridgeConfigV2) => ISbStoryData<import('storyblok-js-client').ISbComponentType<string> & {
|
|
4
4
|
[index: string]: any;
|
|
5
5
|
}>;
|
|
6
6
|
export * from './common/client';
|
package/dist/richtext.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import o from "react";
|
|
2
2
|
import n from "./storyblok-component.mjs";
|
|
3
|
-
import { BlockTypes as
|
|
4
|
-
function
|
|
3
|
+
import { BlockTypes as a, richTextResolver as m } from "./storyblok-js.mjs";
|
|
4
|
+
function i(e) {
|
|
5
5
|
var t, s;
|
|
6
6
|
const r = (t = e == null ? void 0 : e.attrs) == null ? void 0 : t.body;
|
|
7
7
|
return o.createElement(n, {
|
|
@@ -16,7 +16,7 @@ function p(e) {
|
|
|
16
16
|
key: Math.random().toString(36).substring(2, 15)
|
|
17
17
|
}, t),
|
|
18
18
|
resolvers: {
|
|
19
|
-
[
|
|
19
|
+
[a.COMPONENT]: i,
|
|
20
20
|
...e.resolvers
|
|
21
21
|
},
|
|
22
22
|
keyedResolvers: !0
|
|
@@ -24,6 +24,6 @@ function p(e) {
|
|
|
24
24
|
return m(r);
|
|
25
25
|
}
|
|
26
26
|
export {
|
|
27
|
-
|
|
27
|
+
i as componentResolver,
|
|
28
28
|
p as useStoryblokRichText
|
|
29
29
|
};
|
package/dist/storyblok-js.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function re(n,e){if(!e)return{src:n,attrs:{}};let t=0,r=0;const s={},o=[];function l(c,h,f,y,$){typeof c!="number"||c<=h||c>=f?console.warn(`[StoryblokRichText] - ${y.charAt(0).toUpperCase()+y.slice(1)} value must be a number between ${h} and ${f} (inclusive)`):$.push(`${y}(${c})`)}if(typeof e=="object"){if(typeof e.width=="number"&&e.width>0?(s.width=e.width,t=e.width):console.warn("[StoryblokRichText] - Width value must be a number greater than 0"),e.height&&typeof e.height=="number"&&e.height>0?(s.height=e.height,r=e.height):console.warn("[StoryblokRichText] - Height value must be a number greater than 0"),e.loading&&["lazy","eager"].includes(e.loading)&&(s.loading=e.loading),e.class&&(s.class=e.class),e.filters){const{filters:c}=e||{},{blur:h,brightness:f,fill:y,format:$,grayscale:A,quality:R,rotate:S}=c||{};h&&l(h,0,100,"blur",o),R&&l(R,0,100,"quality",o),f&&l(f,0,100,"brightness",o),y&&o.push(`fill(${y})`),A&&o.push("grayscale()"),S&&[0,90,180,270].includes(e.filters.rotate||0)&&o.push(`rotate(${S})`),$&&["webp","png","jpeg"].includes($)&&o.push(`format(${$})`)}e.srcset&&(s.srcset=e.srcset.map(c=>{if(typeof c=="number")return`${n}/m/${c}x0/${o.length>0?`filters:${o.join(":")}`:""} ${c}w`;if(Array.isArray(c)&&c.length===2){const[h,f]=c;return`${n}/m/${h}x${f}/${o.length>0?`filters:${o.join(":")}`:""} ${h}w`}else{console.warn("[StoryblokRichText] - srcset entry must be a number or a tuple of two numbers");return}}).join(", ")),e.sizes&&(s.sizes=e.sizes.join(", "))}let a=`${n}/m/`;return t>0&&r>0&&(a=`${a}${t}x${r}/`),o.length>0&&(a=`${a}filters:${o.join(":")}`),{src:a,attrs:s}}var b=(n=>(n.DOCUMENT="doc",n.HEADING="heading",n.PARAGRAPH="paragraph",n.QUOTE="blockquote",n.OL_LIST="ordered_list",n.UL_LIST="bullet_list",n.LIST_ITEM="list_item",n.CODE_BLOCK="code_block",n.HR="horizontal_rule",n.BR="hard_break",n.IMAGE="image",n.EMOJI="emoji",n.COMPONENT="blok",n.TABLE="table",n.TABLE_ROW="tableRow",n.TABLE_CELL="tableCell",n.TABLE_HEADER="tableHeader",n))(b||{}),_=(n=>(n.BOLD="bold",n.STRONG="strong",n.STRIKE="strike",n.UNDERLINE="underline",n.ITALIC="italic",n.CODE="code",n.LINK="link",n.ANCHOR="anchor",n.STYLED="styled",n.SUPERSCRIPT="superscript",n.SUBSCRIPT="subscript",n.TEXT_STYLE="textStyle",n.HIGHLIGHT="highlight",n))(_||{}),N=(n=>(n.TEXT="text",n))(N||{}),I=(n=>(n.URL="url",n.STORY="story",n.ASSET="asset",n.EMAIL="email",n))(I||{});const ne=["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"],oe=(n={})=>Object.keys(n).map(e=>`${e}="${n[e]}"`).join(" "),ie=(n={})=>Object.keys(n).map(e=>`${e}: ${n[e]}`).join("; ");function ae(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}const O=n=>Object.fromEntries(Object.entries(n).filter(([e,t])=>t!==void 0));function B(n,e={},t){const r=oe(e),s=r?`${n} ${r}`:n,o=Array.isArray(t)?t.join(""):t||"";if(n){if(ne.includes(n))return`<${s}>`}else return o;return`<${s}>${o}</${n}>`}function G(n={}){const e=new Map,{renderFn:t=B,textFn:r=ae,resolvers:s={},optimizeImages:o=!1,keyedResolvers:l=!1}=n,a=t!==B,c=()=>({render:(i,u={},d)=>{if(l&&i){const p=e.get(i)||0;e.set(i,p+1),u.key=`${i}-${p}`}return t(i,u,d)}}),h=i=>(u,d)=>{const p=u.attrs||{};return d.render(i,p,u.children||null)},f=(i,u)=>{const{src:d,alt:p,title:m,srcset:w,sizes:v}=i.attrs||{};let k=d,T={};if(o){const{src:te,attrs:se}=re(d,o);k=te,T=se}const ee={src:k,alt:p,title:m,srcset:w,sizes:v,...T};return u.render("img",O(ee))},y=(i,u)=>{const{level:d,...p}=i.attrs||{};return u.render(`h${d}`,p,i.children)},$=(i,u)=>{var d,p,m,w;const v=u.render("img",{src:(d=i.attrs)==null?void 0:d.fallbackImage,alt:(p=i.attrs)==null?void 0:p.alt,style:"width: 1.25em; height: 1.25em; vertical-align: text-top",draggable:"false",loading:"lazy"});return u.render("span",{"data-type":"emoji","data-name":(m=i.attrs)==null?void 0:m.name,"data-emoji":(w=i.attrs)==null?void 0:w.emoji},v)},A=(i,u)=>u.render("pre",i.attrs||{},u.render("code",{},i.children||"")),R=(i,u=!1)=>({text:d,attrs:p},m)=>{const{class:w,id:v,...k}=p||{},T=u?{class:w,id:v,style:ie(k)||void 0}:p||{};return m.render(i,O(T),d)},S=i=>C(i),J=i=>{const{marks:u,...d}=i;if("text"in i){if(u)return u.reduce((m,w)=>S({...w,text:m}),S({...d,children:d.children}));const p=i.attrs||{};if(l){const m=e.get("txt")||0;e.set("txt",m+1),p.key=`txt-${m}`}return r(d.text,p)}return""},U=(i,u)=>{const{linktype:d,href:p,anchor:m,...w}=i.attrs||{};let v="";switch(d){case I.ASSET:case I.URL:v=p;break;case I.EMAIL:v=`mailto:${p}`;break;case I.STORY:v=p,m&&(v=`${v}#${m}`);break;default:v=p;break}const k={...w};return v&&(k.href=v),u.render("a",k,i.text)},Y=(i,u)=>{var d,p;return console.warn("[StoryblokRichtText] - BLOK resolver is not available for vanilla usage"),u.render("span",{blok:(d=i==null?void 0:i.attrs)==null?void 0:d.body[0],id:(p=i.attrs)==null?void 0:p.id,style:"display: none"})},K=(i,u)=>{const d={},p=u.render("tbody",{},i.children);return u.render("table",d,p)},W=(i,u)=>{const d={};return u.render("tr",d,i.children)},X=(i,u)=>{const{colspan:d,rowspan:p,colwidth:m,backgroundColor:w,...v}=i.attrs||{},k={...v};d>1&&(k.colspan=d),p>1&&(k.rowspan=p);const T=[];return m&&T.push(`width: ${m}px;`),w&&T.push(`background-color: ${w};`),T.length>0&&(k.style=T.join(" ")),u.render("td",O(k),i.children)},Q=(i,u)=>{const{colspan:d,rowspan:p,colwidth:m,backgroundColor:w,...v}=i.attrs||{},k={...v};d>1&&(k.colspan=d),p>1&&(k.rowspan=p);const T=[];return m&&T.push(`width: ${m}px;`),w&&T.push(`background-color: ${w};`),T.length>0&&(k.style=T.join(" ")),u.render("th",O(k),i.children)},Z=new Map([[b.DOCUMENT,h("")],[b.HEADING,y],[b.PARAGRAPH,h("p")],[b.UL_LIST,h("ul")],[b.OL_LIST,h("ol")],[b.LIST_ITEM,h("li")],[b.IMAGE,f],[b.EMOJI,$],[b.CODE_BLOCK,A],[b.HR,h("hr")],[b.BR,h("br")],[b.QUOTE,h("blockquote")],[b.COMPONENT,Y],[N.TEXT,J],[_.LINK,U],[_.ANCHOR,U],[_.STYLED,R("span",!0)],[_.BOLD,R("strong")],[_.TEXT_STYLE,R("span",!0)],[_.ITALIC,R("em")],[_.UNDERLINE,R("u")],[_.STRIKE,R("s")],[_.CODE,R("code")],[_.SUPERSCRIPT,R("sup")],[_.SUBSCRIPT,R("sub")],[_.HIGHLIGHT,R("mark")],[b.TABLE,K],[b.TABLE_ROW,W],[b.TABLE_CELL,X],[b.TABLE_HEADER,Q],...Object.entries(s).map(([i,u])=>[i,u])]);function L(i){const u=Z.get(i.type);if(!u)return console.error("<Storyblok>",`No resolver found for node type ${i.type}`),"";const d=c();if(i.type==="text")return u(i,d);const p=i.content?i.content.map(C):void 0;return u({...i,children:p},d)}function C(i){return i.type==="doc"?a?i.content.map(L):i.content.map(L).join(""):Array.isArray(i)?i.map(L):L(i)}return{render:C}}let D=!1;const M=[],V=n=>new Promise((e,t)=>{if(typeof window>"u"||(window.storyblokRegisterEvent=s=>{if(window.location===window.parent.location){console.warn("You are not in Draft Mode or in the Visual Editor.");return}D?s():M.push(s)},document.getElementById("storyblok-javascript-bridge")))return;const r=document.createElement("script");r.async=!0,r.src=n,r.id="storyblok-javascript-bridge",r.onerror=s=>t(s),r.onload=s=>{M.forEach(o=>o()),D=!0,e(s)},document.getElementsByTagName("head")[0].appendChild(r)});var le=Object.defineProperty,ce=(n,e,t)=>e in n?le(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,g=(n,e,t)=>ce(n,typeof e!="symbol"?e+"":e,t);class he extends Error{constructor(e){super(e),this.name="AbortError"}}function ue(n,e,t){if(!Number.isFinite(e))throw new TypeError("Expected `limit` to be a finite number");if(!Number.isFinite(t))throw new TypeError("Expected `interval` to be a finite number");const r=[];let s=[],o=0,l=!1;const a=async()=>{o++;const h=r.shift();if(h)try{const y=await n(...h.args);h.resolve(y)}catch(y){h.reject(y)}const f=setTimeout(()=>{o--,r.length>0&&a(),s=s.filter(y=>y!==f)},t);s.includes(f)||s.push(f)},c=(...h)=>l?Promise.reject(new Error("Throttled function is already aborted and not accepting new promises")):new Promise((f,y)=>{r.push({resolve:f,reject:y,args:h}),o<e&&a()});return c.abort=()=>{l=!0,s.forEach(clearTimeout),s=[],r.forEach(h=>h.reject(()=>new he("Throttle function aborted"))),r.length=0},c}const de=(n="")=>n.includes("/cdn/"),pe=(n,e=25,t=1)=>({...n,per_page:e,page:t}),fe=n=>new Promise(e=>setTimeout(e,n)),ye=(n=0,e)=>Array.from({length:n},e),ge=(n=0,e=n)=>{const t=Math.abs(e-n)||0,r=n<e?1:-1;return ye(t,(s,o)=>o*r+n)},me=async(n,e)=>Promise.all(n.map(e)),be=(n=[],e)=>n.map(e).reduce((t,r)=>[...t,...r],[]),H=(n,e,t)=>{const r=[];for(const s in n){if(!Object.prototype.hasOwnProperty.call(n,s))continue;const o=n[s];if(o==null)continue;const l=t?"":encodeURIComponent(s);let a;typeof o=="object"?a=H(o,e?e+encodeURIComponent(`[${l}]`):l,Array.isArray(o)):a=`${e?e+encodeURIComponent(`[${l}]`):l}=${encodeURIComponent(o)}`,r.push(a)}return r.join("&")},z=n=>{const e={eu:"api.storyblok.com",us:"api-us.storyblok.com",cn:"app.storyblokchina.cn",ap:"api-ap.storyblok.com",ca:"api-ca.storyblok.com"};return e[n]??e.eu};class ve{constructor(e){g(this,"baseURL"),g(this,"timeout"),g(this,"headers"),g(this,"responseInterceptor"),g(this,"fetch"),g(this,"ejectInterceptor"),g(this,"url"),g(this,"parameters"),g(this,"fetchOptions"),this.baseURL=e.baseURL,this.headers=e.headers||new Headers,this.timeout=e!=null&&e.timeout?e.timeout*1e3:0,this.responseInterceptor=e.responseInterceptor,this.fetch=(...t)=>e.fetch?e.fetch(...t):fetch(...t),this.ejectInterceptor=!1,this.url="",this.parameters={},this.fetchOptions={}}get(e,t){return this.url=e,this.parameters=t,this._methodHandler("get")}post(e,t){return this.url=e,this.parameters=t,this._methodHandler("post")}put(e,t){return this.url=e,this.parameters=t,this._methodHandler("put")}delete(e,t){return this.url=e,this.parameters=t??{},this._methodHandler("delete")}async _responseHandler(e){const t=[],r={data:{},headers:{},status:0,statusText:""};e.status!==204&&await e.json().then(s=>{r.data=s});for(const s of e.headers.entries())t[s[0]]=s[1];return r.headers={...t},r.status=e.status,r.statusText=e.statusText,r}async _methodHandler(e){let t=`${this.baseURL}${this.url}`,r=null;e==="get"?t=`${this.baseURL}${this.url}?${H(this.parameters)}`:r=JSON.stringify(this.parameters);const s=new URL(t),o=new AbortController,{signal:l}=o;let a;this.timeout&&(a=setTimeout(()=>o.abort(),this.timeout));try{const c=await this.fetch(`${s}`,{method:e,headers:this.headers,body:r,signal:l,...this.fetchOptions});this.timeout&&clearTimeout(a);const h=await this._responseHandler(c);return this.responseInterceptor&&!this.ejectInterceptor?this._statusHandler(this.responseInterceptor(h)):this._statusHandler(h)}catch(c){return{message:c}}}setFetchOptions(e={}){Object.keys(e).length>0&&"method"in e&&delete e.method,this.fetchOptions={...e}}eject(){this.ejectInterceptor=!0}_normalizeErrorMessage(e){if(Array.isArray(e))return e[0]||"Unknown error";if(e&&typeof e=="object"){if(e.error)return e.error;for(const t in e){if(Array.isArray(e[t]))return`${t}: ${e[t][0]}`;if(typeof e[t]=="string")return`${t}: ${e[t]}`}if(e.slug)return e.slug}return"Unknown error"}_statusHandler(e){const t=/20[0-6]/g;return new Promise((r,s)=>{if(t.test(`${e.status}`))return r(e);const o={message:this._normalizeErrorMessage(e.data),status:e.status,response:e};s(o)})}}const F="SB-Agent",P={defaultAgentName:"SB-JS-CLIENT",defaultAgentVersion:"SB-Agent-Version",packageVersion:"6.0.0"},ke={DRAFT:"draft"};let j={};const E={};class we{constructor(e,t){g(this,"client"),g(this,"maxRetries"),g(this,"retriesDelay"),g(this,"throttle"),g(this,"accessToken"),g(this,"cache"),g(this,"resolveCounter"),g(this,"relations"),g(this,"links"),g(this,"version"),g(this,"richTextResolver"),g(this,"resolveNestedRelations"),g(this,"stringifiedStoriesCache"),g(this,"inlineAssets");let r=e.endpoint||t;if(!r){const l=e.https===!1?"http":"https";e.oauthToken?r=`${l}://${z(e.region)}/v1`:r=`${l}://${z(e.region)}/v2`}const s=new Headers;s.set("Content-Type","application/json"),s.set("Accept","application/json"),e.headers&&(e.headers.constructor.name==="Headers"?e.headers.entries().toArray():Object.entries(e.headers)).forEach(([l,a])=>{s.set(l,a)}),s.has(F)||(s.set(F,P.defaultAgentName),s.set(P.defaultAgentVersion,P.packageVersion));let o=5;e.oauthToken&&(s.set("Authorization",e.oauthToken),o=3),e.rateLimit&&(o=e.rateLimit),this.maxRetries=e.maxRetries||10,this.retriesDelay=300,this.throttle=ue(this.throttledRequest.bind(this),o,1e3),this.accessToken=e.accessToken||"",this.relations={},this.links={},this.cache=e.cache||{clear:"manual"},this.resolveCounter=0,this.resolveNestedRelations=e.resolveNestedRelations||!0,this.stringifiedStoriesCache={},this.version=e.version||ke.DRAFT,this.inlineAssets=e.inlineAssets||!1,this.client=new ve({baseURL:r,timeout:e.timeout||0,headers:s,responseInterceptor:e.responseInterceptor,fetch:e.fetch})}parseParams(e){return e.token||(e.token=this.getToken()),e.cv||(e.cv=E[e.token]),Array.isArray(e.resolve_relations)&&(e.resolve_relations=e.resolve_relations.join(",")),typeof e.resolve_relations<"u"&&(e.resolve_level=2),e}factoryParamOptions(e,t){return de(e)?this.parseParams(t):t}makeRequest(e,t,r,s,o){const l=this.factoryParamOptions(e,pe(t,r,s));return this.cacheResponse(e,l,void 0,o)}get(e,t={},r){t||(t={});const s=`/${e}`;t.version=t.version||this.version;const o=this.factoryParamOptions(s,t);return this.cacheResponse(s,o,void 0,r)}async getAll(e,t={},r,s){const o=(t==null?void 0:t.per_page)||25,l=`/${e}`.replace(/\/$/,""),a=r??l.substring(l.lastIndexOf("/")+1);t.version=t.version||this.version;const c=1,h=await this.makeRequest(l,t,o,c,s),f=h.total?Math.ceil(h.total/o):1,y=await me(ge(c,f),$=>this.makeRequest(l,t,o,$+1,s));return be([h,...y],$=>Object.values($.data[a]))}post(e,t={},r){const s=`/${e}`;return this.throttle("post",s,t,r)}put(e,t={},r){const s=`/${e}`;return this.throttle("put",s,t,r)}delete(e,t={},r){t||(t={});const s=`/${e}`;return this.throttle("delete",s,t,r)}getStories(e={},t){return this._addResolveLevel(e),this.get("cdn/stories",e,t)}getStory(e,t={},r){return this._addResolveLevel(t),this.get(`cdn/stories/${e}`,t,r)}getToken(){return this.accessToken}ejectInterceptor(){this.client.eject()}_addResolveLevel(e){typeof e.resolve_relations<"u"&&(e.resolve_level=2)}_cleanCopy(e){return JSON.parse(JSON.stringify(e))}_insertLinks(e,t,r){const s=e[t];s&&s.fieldtype==="multilink"&&s.linktype==="story"&&typeof s.id=="string"&&this.links[r][s.id]?s.story=this._cleanCopy(this.links[r][s.id]):s&&s.linktype==="story"&&typeof s.uuid=="string"&&this.links[r][s.uuid]&&(s.story=this._cleanCopy(this.links[r][s.uuid]))}getStoryReference(e,t){return this.relations[e][t]?JSON.parse(this.stringifiedStoriesCache[t]||JSON.stringify(this.relations[e][t])):t}_resolveField(e,t,r){const s=e[t];typeof s=="string"?e[t]=this.getStoryReference(r,s):Array.isArray(s)&&(e[t]=s.map(o=>this.getStoryReference(r,o)).filter(Boolean))}_insertRelations(e,t,r,s){if(Array.isArray(r)?r.find(l=>l.endsWith(`.${t}`)):r.endsWith(`.${t}`)){this._resolveField(e,t,s);return}const o=e.component?`${e.component}.${t}`:t;(Array.isArray(r)?r.includes(o):r===o)&&this._resolveField(e,t,s)}iterateTree(e,t,r){const s=(o,l="")=>{if(!(!o||o._stopResolving)){if(Array.isArray(o))o.forEach((a,c)=>s(a,`${l}[${c}]`));else if(typeof o=="object")for(const a in o){const c=l?`${l}.${a}`:a;(o.component&&o._uid||o.type==="link")&&(this._insertRelations(o,a,t,r),this._insertLinks(o,a,r)),s(o[a],c)}}};s(e.content)}async resolveLinks(e,t,r){let s=[];if(e.link_uuids){const o=e.link_uuids.length,l=[],a=50;for(let c=0;c<o;c+=a){const h=Math.min(o,c+a);l.push(e.link_uuids.slice(c,h))}for(let c=0;c<l.length;c++)(await this.getStories({per_page:a,language:t.language,version:t.version,starts_with:t.starts_with,by_uuids:l[c].join(",")})).data.stories.forEach(h=>{s.push(h)})}else s=e.links;s.forEach(o=>{this.links[r][o.uuid]={...o,_stopResolving:!0}})}async resolveRelations(e,t,r){let s=[];if(e.rel_uuids){const o=e.rel_uuids.length,l=[],a=50;for(let c=0;c<o;c+=a){const h=Math.min(o,c+a);l.push(e.rel_uuids.slice(c,h))}for(let c=0;c<l.length;c++)(await this.getStories({per_page:a,language:t.language,version:t.version,starts_with:t.starts_with,by_uuids:l[c].join(","),excluding_fields:t.excluding_fields})).data.stories.forEach(h=>{s.push(h)});s.length>0&&(e.rels=s,delete e.rel_uuids)}else s=e.rels;s&&s.length>0&&s.forEach(o=>{this.relations[r][o.uuid]={...o,_stopResolving:!0}})}async resolveStories(e,t,r){var s,o;let l=[];if(this.links[r]={},this.relations[r]={},typeof t.resolve_relations<"u"&&t.resolve_relations.length>0&&(typeof t.resolve_relations=="string"&&(l=t.resolve_relations.split(",")),await this.resolveRelations(e,t,r)),t.resolve_links&&["1","story","url","link"].includes(t.resolve_links)&&((s=e.links)!=null&&s.length||(o=e.link_uuids)!=null&&o.length)&&await this.resolveLinks(e,t,r),this.resolveNestedRelations)for(const a in this.relations[r])this.iterateTree(this.relations[r][a],l,r);e.story?this.iterateTree(e.story,l,r):e.stories.forEach(a=>{this.iterateTree(a,l,r)}),this.stringifiedStoriesCache={},delete this.links[r],delete this.relations[r]}async cacheResponse(e,t,r,s){const o=H({url:e,params:t}),l=this.cacheProvider();if(t.version==="published"&&e!=="/cdn/spaces/me"){const a=await l.get(o);if(a)return Promise.resolve(a)}return new Promise(async(a,c)=>{var h;try{const f=await this.throttle("get",e,t,s);if(f.status!==200)return c(f);let y={data:f.data,headers:f.headers};if((h=f.headers)!=null&&h["per-page"]&&(y=Object.assign({},y,{perPage:f.headers["per-page"]?Number.parseInt(f.headers["per-page"]):0,total:f.headers["per-page"]?Number.parseInt(f.headers.total):0})),y.data.story||y.data.stories){const A=this.resolveCounter=++this.resolveCounter%1e3;await this.resolveStories(y.data,t,`${A}`),y=await this.processInlineAssets(y)}t.version==="published"&&e!=="/cdn/spaces/me"&&await l.set(o,y);const $=this.cache.clear==="onpreview"&&t.version==="draft"||this.cache.clear==="auto";return t.token&&y.data.cv&&($&&E[t.token]&&E[t.token]!==y.data.cv&&await this.flushCache(),E[t.token]=y.data.cv),a(y)}catch(f){if(f.response&&f.status===429&&(r=typeof r>"u"?0:r+1,r<this.maxRetries))return console.log(`Hit rate limit. Retrying in ${this.retriesDelay/1e3} seconds.`),await fe(this.retriesDelay),this.cacheResponse(e,t,r).then(a).catch(c);c(f)}})}throttledRequest(e,t,r,s){return this.client.setFetchOptions(s),this.client[e](t,r)}cacheVersions(){return E}cacheVersion(){return E[this.accessToken]}setCacheVersion(e){this.accessToken&&(E[this.accessToken]=e)}clearCacheVersion(){this.accessToken&&(E[this.accessToken]=0)}cacheProvider(){switch(this.cache.type){case"memory":return{get(e){return Promise.resolve(j[e])},getAll(){return Promise.resolve(j)},set(e,t){return j[e]=t,Promise.resolve(void 0)},flush(){return j={},Promise.resolve(void 0)}};case"custom":if(this.cache.custom)return this.cache.custom;default:return{get(){return Promise.resolve()},getAll(){return Promise.resolve(void 0)},set(){return Promise.resolve(void 0)},flush(){return Promise.resolve(void 0)}}}}async flushCache(){return await this.cacheProvider().flush(),this.clearCacheVersion(),this}async processInlineAssets(e){if(!this.inlineAssets)return e;const t=r=>{if(!r||typeof r!="object")return r;if(Array.isArray(r))return r.map(o=>t(o));let s={...r};s.fieldtype==="asset"&&Array.isArray(e.data.assets)&&(s={...s,...e.data.assets.find(o=>o.id===s.id)});for(const o in s)typeof s[o]=="object"&&(s[o]=t(s[o]));return s};return e.data.story&&(e.data.story.content=t(e.data.story.content)),e.data.stories&&(e.data.stories=e.data.stories.map(r=>(r.content=t(r.content),r))),e}}const Te=(n={})=>{const{apiOptions:e}=n;if(!e||!e.accessToken){console.error("You need to provide an access token to interact with Storyblok API. Read https://www.storyblok.com/docs/api/content-delivery#topics/authentication");return}return{storyblokApi:new we(e)}},_e=n=>{if(typeof n!="object"||typeof n._editable>"u")return{};try{const e=JSON.parse(n._editable.replace(/^<!--#storyblok#/,"").replace(/-->$/,""));return e?{"data-blok-c":JSON.stringify(e),"data-blok-uid":`${e.id}-${e.uid}`}:{}}catch{return{}}};let x="https://app.storyblok.com/f/storyblok-v2-latest.js";const q=(n,e,t={})=>{var r;const s=!(typeof window>"u")&&typeof window.storyblokRegisterEvent<"u",o=new URL((r=window.location)==null?void 0:r.href).searchParams.get("_storyblok"),l=o!==null&&+o===n;if(!(!s||!l)){if(!n){console.warn("Story ID is not defined. Please provide a valid ID.");return}window.storyblokRegisterEvent(()=>{new window.StoryblokBridge(t).on(["input","published","change"],a=>{var c;a&&(a.action==="input"&&((c=a.story)==null?void 0:c.id)===n?e(a.story):(a.action==="change"||a.action==="published")&&a.storyId===n&&window.location.reload())})})}},$e=(n={})=>{var e,t;const{bridge:r,accessToken:s,use:o=[],apiOptions:l={},bridgeUrl:a}=n;l.accessToken=l.accessToken||s;const c={bridge:r,apiOptions:l};let h={};o.forEach(y=>{h={...h,...y(c)}}),a&&(x=a);const f=!(typeof window>"u")&&((t=(e=window.location)==null?void 0:e.search)==null?void 0:t.includes("_storyblok_tk"));return r!==!1&&f&&V(x),h};function Re(n,e){return G(e).render(n)}const Ee=()=>V(x);exports.BlockTypes=b;exports.MarkTypes=_;exports.TextTypes=N;exports.apiPlugin=Te;exports.loadStoryblokBridge=Ee;exports.registerStoryblokBridge=q;exports.renderRichText=Re;exports.richTextResolver=G;exports.storyblokEditable=_e;exports.storyblokInit=$e;exports.useStoryblokBridge=q;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function ne(n,e){if(!e)return{src:n,attrs:{}};let t=0,r=0;const s={},o=[];function c(i,h,f,y,$){typeof i!="number"||i<=h||i>=f?console.warn(`[StoryblokRichText] - ${y.charAt(0).toUpperCase()+y.slice(1)} value must be a number between ${h} and ${f} (inclusive)`):$.push(`${y}(${i})`)}if(typeof e=="object"){if(typeof e.width=="number"&&e.width>0?(s.width=e.width,t=e.width):console.warn("[StoryblokRichText] - Width value must be a number greater than 0"),e.height&&typeof e.height=="number"&&e.height>0?(s.height=e.height,r=e.height):console.warn("[StoryblokRichText] - Height value must be a number greater than 0"),e.loading&&["lazy","eager"].includes(e.loading)&&(s.loading=e.loading),e.class&&(s.class=e.class),e.filters){const{filters:i}=e||{},{blur:h,brightness:f,fill:y,format:$,grayscale:T,quality:A,rotate:I}=i||{};h&&c(h,0,100,"blur",o),A&&c(A,0,100,"quality",o),f&&c(f,0,100,"brightness",o),y&&o.push(`fill(${y})`),T&&o.push("grayscale()"),I&&[0,90,180,270].includes(e.filters.rotate||0)&&o.push(`rotate(${I})`),$&&["webp","png","jpeg"].includes($)&&o.push(`format(${$})`)}e.srcset&&(s.srcset=e.srcset.map(i=>{if(typeof i=="number")return`${n}/m/${i}x0/${o.length>0?`filters:${o.join(":")}`:""} ${i}w`;if(Array.isArray(i)&&i.length===2){const[h,f]=i;return`${n}/m/${h}x${f}/${o.length>0?`filters:${o.join(":")}`:""} ${h}w`}else{console.warn("[StoryblokRichText] - srcset entry must be a number or a tuple of two numbers");return}}).join(", ")),e.sizes&&(s.sizes=e.sizes.join(", "))}let l=`${n}/m/`;return t>0&&r>0&&(l=`${l}${t}x${r}/`),o.length>0&&(l=`${l}filters:${o.join(":")}`),{src:l,attrs:s}}var b=(n=>(n.DOCUMENT="doc",n.HEADING="heading",n.PARAGRAPH="paragraph",n.QUOTE="blockquote",n.OL_LIST="ordered_list",n.UL_LIST="bullet_list",n.LIST_ITEM="list_item",n.CODE_BLOCK="code_block",n.HR="horizontal_rule",n.BR="hard_break",n.IMAGE="image",n.EMOJI="emoji",n.COMPONENT="blok",n.TABLE="table",n.TABLE_ROW="tableRow",n.TABLE_CELL="tableCell",n.TABLE_HEADER="tableHeader",n))(b||{}),_=(n=>(n.BOLD="bold",n.STRONG="strong",n.STRIKE="strike",n.UNDERLINE="underline",n.ITALIC="italic",n.CODE="code",n.LINK="link",n.ANCHOR="anchor",n.STYLED="styled",n.SUPERSCRIPT="superscript",n.SUBSCRIPT="subscript",n.TEXT_STYLE="textStyle",n.HIGHLIGHT="highlight",n))(_||{}),N=(n=>(n.TEXT="text",n))(N||{}),S=(n=>(n.URL="url",n.STORY="story",n.ASSET="asset",n.EMAIL="email",n))(S||{});const oe=["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"],ie=(n={})=>Object.keys(n).map(e=>`${e}="${n[e]}"`).join(" "),ae=(n={})=>Object.keys(n).map(e=>`${e}: ${n[e]}`).join("; ");function le(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}const O=n=>Object.fromEntries(Object.entries(n).filter(([e,t])=>t!==void 0));function M(n,e={},t){const r=ie(e),s=r?`${n} ${r}`:n,o=Array.isArray(t)?t.join(""):t||"";if(n){if(oe.includes(n))return`<${s}>`}else return o;return`<${s}>${o}</${n}>`}function q(n={}){const e=new Map,{renderFn:t=M,textFn:r=le,resolvers:s={},optimizeImages:o=!1,keyedResolvers:c=!1}=n,l=t!==M,i=a=>(u,d)=>{const p=u.attrs||{};return d.render(a,p,u.children||null)},h=(a,u)=>{const{src:d,alt:p,title:m,srcset:w,sizes:v}=a.attrs||{};let k=d,R={};if(o){const{src:se,attrs:re}=ne(d,o);k=se,R=re}const te={src:k,alt:p,title:m,srcset:w,sizes:v,...R};return u.render("img",O(te))},f=(a,u)=>{const{level:d,...p}=a.attrs||{};return u.render(`h${d}`,p,a.children)},y=(a,u)=>{var d,p,m,w;const v=u.render("img",{src:(d=a.attrs)==null?void 0:d.fallbackImage,alt:(p=a.attrs)==null?void 0:p.alt,style:"width: 1.25em; height: 1.25em; vertical-align: text-top",draggable:"false",loading:"lazy"});return u.render("span",{"data-type":"emoji","data-name":(m=a.attrs)==null?void 0:m.name,"data-emoji":(w=a.attrs)==null?void 0:w.emoji},v)},$=(a,u)=>u.render("pre",a.attrs||{},u.render("code",{},a.children||"")),T=(a,u=!1)=>({text:d,attrs:p},m)=>{const{class:w,id:v,...k}=p||{},R=u?{class:w,id:v,style:ae(k)||void 0}:p||{};return m.render(a,O(R),d)},A=a=>C(a),I=a=>{const{marks:u,...d}=a;if("text"in a){if(u)return u.reduce((m,w)=>A({...w,text:m}),A({...d,children:d.children}));const p=a.attrs||{};if(c){const m=e.get("txt")||0;e.set("txt",m+1),p.key=`txt-${m}`}return r(d.text,p)}return""},U=(a,u)=>{const{linktype:d,href:p,anchor:m,...w}=a.attrs||{};let v="";switch(d){case S.ASSET:case S.URL:v=p;break;case S.EMAIL:v=`mailto:${p}`;break;case S.STORY:v=p,m&&(v=`${v}#${m}`);break;default:v=p;break}const k={...w};return v&&(k.href=v),u.render("a",k,a.text)},K=(a,u)=>{var d,p;return console.warn("[StoryblokRichtText] - BLOK resolver is not available for vanilla usage"),u.render("span",{blok:(d=a==null?void 0:a.attrs)==null?void 0:d.body[0],id:(p=a.attrs)==null?void 0:p.id,style:"display: none"})},W=(a,u)=>{const d={},p=u.render("tbody",{},a.children);return u.render("table",d,p)},X=(a,u)=>{const d={};return u.render("tr",d,a.children)},Q=(a,u)=>{const{colspan:d,rowspan:p,colwidth:m,backgroundColor:w,...v}=a.attrs||{},k={...v};d>1&&(k.colspan=d),p>1&&(k.rowspan=p);const R=[];return m&&R.push(`width: ${m}px;`),w&&R.push(`background-color: ${w};`),R.length>0&&(k.style=R.join(" ")),u.render("td",O(k),a.children)},Z=(a,u)=>{const{colspan:d,rowspan:p,colwidth:m,backgroundColor:w,...v}=a.attrs||{},k={...v};d>1&&(k.colspan=d),p>1&&(k.rowspan=p);const R=[];return m&&R.push(`width: ${m}px;`),w&&R.push(`background-color: ${w};`),R.length>0&&(k.style=R.join(" ")),u.render("th",O(k),a.children)},B=new Map([[b.DOCUMENT,i("")],[b.HEADING,f],[b.PARAGRAPH,i("p")],[b.UL_LIST,i("ul")],[b.OL_LIST,i("ol")],[b.LIST_ITEM,i("li")],[b.IMAGE,h],[b.EMOJI,y],[b.CODE_BLOCK,$],[b.HR,i("hr")],[b.BR,i("br")],[b.QUOTE,i("blockquote")],[b.COMPONENT,K],[N.TEXT,I],[_.LINK,U],[_.ANCHOR,U],[_.STYLED,T("span",!0)],[_.BOLD,T("strong")],[_.TEXT_STYLE,T("span",!0)],[_.ITALIC,T("em")],[_.UNDERLINE,T("u")],[_.STRIKE,T("s")],[_.CODE,T("code")],[_.SUPERSCRIPT,T("sup")],[_.SUBSCRIPT,T("sub")],[_.HIGHLIGHT,T("mark")],[b.TABLE,W],[b.TABLE_ROW,X],[b.TABLE_CELL,Q],[b.TABLE_HEADER,Z]]),D=new Map([...B,...Object.entries(s).map(([a,u])=>[a,u])]),ee=()=>({render:(a,u={},d)=>{if(c&&a){const p=e.get(a)||0;e.set(a,p+1),u.key=`${a}-${p}`}return t(a,u,d)},originalResolvers:B,mergedResolvers:D});function L(a){const u=D.get(a.type);if(!u)return console.error("<Storyblok>",`No resolver found for node type ${a.type}`),"";const d=ee();if(a.type==="text")return u(a,d);const p=a.content?a.content.map(C):void 0;return u({...a,children:p},d)}function C(a){return a.type==="doc"?l?a.content.map(L):a.content.map(L).join(""):Array.isArray(a)?a.map(L):L(a)}return{render:C}}let z=!1;const F=[],J=n=>new Promise((e,t)=>{if(typeof window>"u"){t(new Error("Cannot load Storyblok bridge: window is undefined (server-side environment)"));return}if(window.storyblokRegisterEvent=s=>{if(window.location===window.parent.location){console.warn("You are not in Draft Mode or in the Visual Editor.");return}z?s():F.push(s)},document.getElementById("storyblok-javascript-bridge")){e(void 0);return}const r=document.createElement("script");r.async=!0,r.src=n,r.id="storyblok-javascript-bridge",r.onerror=s=>t(s),r.onload=s=>{F.forEach(o=>o()),z=!0,e(s)},document.getElementsByTagName("head")[0].appendChild(r)});var ce=Object.defineProperty,he=(n,e,t)=>e in n?ce(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,g=(n,e,t)=>he(n,typeof e!="symbol"?e+"":e,t);class ue extends Error{constructor(e){super(e),this.name="AbortError"}}function de(n,e,t){if(!Number.isFinite(e))throw new TypeError("Expected `limit` to be a finite number");if(!Number.isFinite(t))throw new TypeError("Expected `interval` to be a finite number");const r=[];let s=[],o=0,c=!1;const l=async()=>{o++;const h=r.shift();if(h)try{const y=await n(...h.args);h.resolve(y)}catch(y){h.reject(y)}const f=setTimeout(()=>{o--,r.length>0&&l(),s=s.filter(y=>y!==f)},t);s.includes(f)||s.push(f)},i=(...h)=>c?Promise.reject(new Error("Throttled function is already aborted and not accepting new promises")):new Promise((f,y)=>{r.push({resolve:f,reject:y,args:h}),o<e&&l()});return i.abort=()=>{c=!0,s.forEach(clearTimeout),s=[],r.forEach(h=>h.reject(()=>new ue("Throttle function aborted"))),r.length=0},i}const pe=(n="")=>n.includes("/cdn/"),fe=(n,e=25,t=1)=>({...n,per_page:e,page:t}),ye=n=>new Promise(e=>setTimeout(e,n)),ge=(n=0,e)=>Array.from({length:n},e),me=(n=0,e=n)=>{const t=Math.abs(e-n)||0,r=n<e?1:-1;return ge(t,(s,o)=>o*r+n)},be=async(n,e)=>Promise.all(n.map(e)),ve=(n=[],e)=>n.map(e).reduce((t,r)=>[...t,...r],[]),H=(n,e,t)=>{const r=[];for(const s in n){if(!Object.prototype.hasOwnProperty.call(n,s))continue;const o=n[s];if(o==null)continue;const c=t?"":encodeURIComponent(s);let l;typeof o=="object"?l=H(o,e?e+encodeURIComponent(`[${c}]`):c,Array.isArray(o)):l=`${e?e+encodeURIComponent(`[${c}]`):c}=${encodeURIComponent(o)}`,r.push(l)}return r.join("&")},G=n=>{const e={eu:"api.storyblok.com",us:"api-us.storyblok.com",cn:"app.storyblokchina.cn",ap:"api-ap.storyblok.com",ca:"api-ca.storyblok.com"};return e[n]??e.eu};class ke{constructor(e){g(this,"baseURL"),g(this,"timeout"),g(this,"headers"),g(this,"responseInterceptor"),g(this,"fetch"),g(this,"ejectInterceptor"),g(this,"url"),g(this,"parameters"),g(this,"fetchOptions"),this.baseURL=e.baseURL,this.headers=e.headers||new Headers,this.timeout=e!=null&&e.timeout?e.timeout*1e3:0,this.responseInterceptor=e.responseInterceptor,this.fetch=(...t)=>e.fetch?e.fetch(...t):fetch(...t),this.ejectInterceptor=!1,this.url="",this.parameters={},this.fetchOptions={}}get(e,t){return this.url=e,this.parameters=t,this._methodHandler("get")}post(e,t){return this.url=e,this.parameters=t,this._methodHandler("post")}put(e,t){return this.url=e,this.parameters=t,this._methodHandler("put")}delete(e,t){return this.url=e,this.parameters=t??{},this._methodHandler("delete")}async _responseHandler(e){const t=[],r={data:{},headers:{},status:0,statusText:""};e.status!==204&&await e.json().then(s=>{r.data=s});for(const s of e.headers.entries())t[s[0]]=s[1];return r.headers={...t},r.status=e.status,r.statusText=e.statusText,r}async _methodHandler(e){let t=`${this.baseURL}${this.url}`,r=null;e==="get"?t=`${this.baseURL}${this.url}?${H(this.parameters)}`:r=JSON.stringify(this.parameters);const s=new URL(t),o=new AbortController,{signal:c}=o;let l;this.timeout&&(l=setTimeout(()=>o.abort(),this.timeout));try{const i=await this.fetch(`${s}`,{method:e,headers:this.headers,body:r,signal:c,...this.fetchOptions});this.timeout&&clearTimeout(l);const h=await this._responseHandler(i);return this.responseInterceptor&&!this.ejectInterceptor?this._statusHandler(this.responseInterceptor(h)):this._statusHandler(h)}catch(i){return{message:i}}}setFetchOptions(e={}){Object.keys(e).length>0&&"method"in e&&delete e.method,this.fetchOptions={...e}}eject(){this.ejectInterceptor=!0}_normalizeErrorMessage(e){if(Array.isArray(e))return e[0]||"Unknown error";if(e&&typeof e=="object"){if(e.error)return e.error;for(const t in e){if(Array.isArray(e[t]))return`${t}: ${e[t][0]}`;if(typeof e[t]=="string")return`${t}: ${e[t]}`}if(e.slug)return e.slug}return"Unknown error"}_statusHandler(e){const t=/20[0-6]/g;return new Promise((r,s)=>{if(t.test(`${e.status}`))return r(e);const o={message:this._normalizeErrorMessage(e.data),status:e.status,response:e};s(o)})}}const V="SB-Agent",P={defaultAgentName:"SB-JS-CLIENT",defaultAgentVersion:"SB-Agent-Version",packageVersion:"6.0.0"},we={DRAFT:"draft"};let j={};const E={};class Te{constructor(e,t){g(this,"client"),g(this,"maxRetries"),g(this,"retriesDelay"),g(this,"throttle"),g(this,"accessToken"),g(this,"cache"),g(this,"resolveCounter"),g(this,"relations"),g(this,"links"),g(this,"version"),g(this,"richTextResolver"),g(this,"resolveNestedRelations"),g(this,"stringifiedStoriesCache"),g(this,"inlineAssets");let r=e.endpoint||t;if(!r){const c=e.https===!1?"http":"https";e.oauthToken?r=`${c}://${G(e.region)}/v1`:r=`${c}://${G(e.region)}/v2`}const s=new Headers;s.set("Content-Type","application/json"),s.set("Accept","application/json"),e.headers&&(e.headers.constructor.name==="Headers"?e.headers.entries().toArray():Object.entries(e.headers)).forEach(([c,l])=>{s.set(c,l)}),s.has(V)||(s.set(V,P.defaultAgentName),s.set(P.defaultAgentVersion,P.packageVersion));let o=5;e.oauthToken&&(s.set("Authorization",e.oauthToken),o=3),e.rateLimit&&(o=e.rateLimit),this.maxRetries=e.maxRetries||10,this.retriesDelay=300,this.throttle=de(this.throttledRequest.bind(this),o,1e3),this.accessToken=e.accessToken||"",this.relations={},this.links={},this.cache=e.cache||{clear:"manual"},this.resolveCounter=0,this.resolveNestedRelations=e.resolveNestedRelations||!0,this.stringifiedStoriesCache={},this.version=e.version||we.DRAFT,this.inlineAssets=e.inlineAssets||!1,this.client=new ke({baseURL:r,timeout:e.timeout||0,headers:s,responseInterceptor:e.responseInterceptor,fetch:e.fetch})}parseParams(e){return e.token||(e.token=this.getToken()),e.cv||(e.cv=E[e.token]),Array.isArray(e.resolve_relations)&&(e.resolve_relations=e.resolve_relations.join(",")),typeof e.resolve_relations<"u"&&(e.resolve_level=2),e}factoryParamOptions(e,t){return pe(e)?this.parseParams(t):t}makeRequest(e,t,r,s,o){const c=this.factoryParamOptions(e,fe(t,r,s));return this.cacheResponse(e,c,void 0,o)}get(e,t={},r){t||(t={});const s=`/${e}`;t.version=t.version||this.version;const o=this.factoryParamOptions(s,t);return this.cacheResponse(s,o,void 0,r)}async getAll(e,t={},r,s){const o=(t==null?void 0:t.per_page)||25,c=`/${e}`.replace(/\/$/,""),l=r??c.substring(c.lastIndexOf("/")+1);t.version=t.version||this.version;const i=1,h=await this.makeRequest(c,t,o,i,s),f=h.total?Math.ceil(h.total/o):1,y=await be(me(i,f),$=>this.makeRequest(c,t,o,$+1,s));return ve([h,...y],$=>Object.values($.data[l]))}post(e,t={},r){const s=`/${e}`;return this.throttle("post",s,t,r)}put(e,t={},r){const s=`/${e}`;return this.throttle("put",s,t,r)}delete(e,t={},r){t||(t={});const s=`/${e}`;return this.throttle("delete",s,t,r)}getStories(e={},t){return this._addResolveLevel(e),this.get("cdn/stories",e,t)}getStory(e,t={},r){return this._addResolveLevel(t),this.get(`cdn/stories/${e}`,t,r)}getToken(){return this.accessToken}ejectInterceptor(){this.client.eject()}_addResolveLevel(e){typeof e.resolve_relations<"u"&&(e.resolve_level=2)}_cleanCopy(e){return JSON.parse(JSON.stringify(e))}_insertLinks(e,t,r){const s=e[t];s&&s.fieldtype==="multilink"&&s.linktype==="story"&&typeof s.id=="string"&&this.links[r][s.id]?s.story=this._cleanCopy(this.links[r][s.id]):s&&s.linktype==="story"&&typeof s.uuid=="string"&&this.links[r][s.uuid]&&(s.story=this._cleanCopy(this.links[r][s.uuid]))}getStoryReference(e,t){return this.relations[e][t]?JSON.parse(this.stringifiedStoriesCache[t]||JSON.stringify(this.relations[e][t])):t}_resolveField(e,t,r){const s=e[t];typeof s=="string"?e[t]=this.getStoryReference(r,s):Array.isArray(s)&&(e[t]=s.map(o=>this.getStoryReference(r,o)).filter(Boolean))}_insertRelations(e,t,r,s){if(Array.isArray(r)?r.find(c=>c.endsWith(`.${t}`)):r.endsWith(`.${t}`)){this._resolveField(e,t,s);return}const o=e.component?`${e.component}.${t}`:t;(Array.isArray(r)?r.includes(o):r===o)&&this._resolveField(e,t,s)}iterateTree(e,t,r){const s=(o,c="")=>{if(!(!o||o._stopResolving)){if(Array.isArray(o))o.forEach((l,i)=>s(l,`${c}[${i}]`));else if(typeof o=="object")for(const l in o){const i=c?`${c}.${l}`:l;(o.component&&o._uid||o.type==="link")&&(this._insertRelations(o,l,t,r),this._insertLinks(o,l,r)),s(o[l],i)}}};s(e.content)}async resolveLinks(e,t,r){let s=[];if(e.link_uuids){const o=e.link_uuids.length,c=[],l=50;for(let i=0;i<o;i+=l){const h=Math.min(o,i+l);c.push(e.link_uuids.slice(i,h))}for(let i=0;i<c.length;i++)(await this.getStories({per_page:l,language:t.language,version:t.version,starts_with:t.starts_with,by_uuids:c[i].join(",")})).data.stories.forEach(h=>{s.push(h)})}else s=e.links;s.forEach(o=>{this.links[r][o.uuid]={...o,_stopResolving:!0}})}async resolveRelations(e,t,r){let s=[];if(e.rel_uuids){const o=e.rel_uuids.length,c=[],l=50;for(let i=0;i<o;i+=l){const h=Math.min(o,i+l);c.push(e.rel_uuids.slice(i,h))}for(let i=0;i<c.length;i++)(await this.getStories({per_page:l,language:t.language,version:t.version,starts_with:t.starts_with,by_uuids:c[i].join(","),excluding_fields:t.excluding_fields})).data.stories.forEach(h=>{s.push(h)});s.length>0&&(e.rels=s,delete e.rel_uuids)}else s=e.rels;s&&s.length>0&&s.forEach(o=>{this.relations[r][o.uuid]={...o,_stopResolving:!0}})}async resolveStories(e,t,r){var s,o;let c=[];if(this.links[r]={},this.relations[r]={},typeof t.resolve_relations<"u"&&t.resolve_relations.length>0&&(typeof t.resolve_relations=="string"&&(c=t.resolve_relations.split(",")),await this.resolveRelations(e,t,r)),t.resolve_links&&["1","story","url","link"].includes(t.resolve_links)&&((s=e.links)!=null&&s.length||(o=e.link_uuids)!=null&&o.length)&&await this.resolveLinks(e,t,r),this.resolveNestedRelations)for(const l in this.relations[r])this.iterateTree(this.relations[r][l],c,r);e.story?this.iterateTree(e.story,c,r):e.stories.forEach(l=>{this.iterateTree(l,c,r)}),this.stringifiedStoriesCache={},delete this.links[r],delete this.relations[r]}async cacheResponse(e,t,r,s){const o=H({url:e,params:t}),c=this.cacheProvider();if(t.version==="published"&&e!=="/cdn/spaces/me"){const l=await c.get(o);if(l)return Promise.resolve(l)}return new Promise(async(l,i)=>{var h;try{const f=await this.throttle("get",e,t,s);if(f.status!==200)return i(f);let y={data:f.data,headers:f.headers};if((h=f.headers)!=null&&h["per-page"]&&(y=Object.assign({},y,{perPage:f.headers["per-page"]?Number.parseInt(f.headers["per-page"]):0,total:f.headers["per-page"]?Number.parseInt(f.headers.total):0})),y.data.story||y.data.stories){const T=this.resolveCounter=++this.resolveCounter%1e3;await this.resolveStories(y.data,t,`${T}`),y=await this.processInlineAssets(y)}t.version==="published"&&e!=="/cdn/spaces/me"&&await c.set(o,y);const $=this.cache.clear==="onpreview"&&t.version==="draft"||this.cache.clear==="auto";return t.token&&y.data.cv&&($&&E[t.token]&&E[t.token]!==y.data.cv&&await this.flushCache(),E[t.token]=y.data.cv),l(y)}catch(f){if(f.response&&f.status===429&&(r=typeof r>"u"?0:r+1,r<this.maxRetries))return console.log(`Hit rate limit. Retrying in ${this.retriesDelay/1e3} seconds.`),await ye(this.retriesDelay),this.cacheResponse(e,t,r).then(l).catch(i);i(f)}})}throttledRequest(e,t,r,s){return this.client.setFetchOptions(s),this.client[e](t,r)}cacheVersions(){return E}cacheVersion(){return E[this.accessToken]}setCacheVersion(e){this.accessToken&&(E[this.accessToken]=e)}clearCacheVersion(){this.accessToken&&(E[this.accessToken]=0)}cacheProvider(){switch(this.cache.type){case"memory":return{get(e){return Promise.resolve(j[e])},getAll(){return Promise.resolve(j)},set(e,t){return j[e]=t,Promise.resolve(void 0)},flush(){return j={},Promise.resolve(void 0)}};case"custom":if(this.cache.custom)return this.cache.custom;default:return{get(){return Promise.resolve()},getAll(){return Promise.resolve(void 0)},set(){return Promise.resolve(void 0)},flush(){return Promise.resolve(void 0)}}}}async flushCache(){return await this.cacheProvider().flush(),this.clearCacheVersion(),this}async processInlineAssets(e){if(!this.inlineAssets)return e;const t=r=>{if(!r||typeof r!="object")return r;if(Array.isArray(r))return r.map(o=>t(o));let s={...r};s.fieldtype==="asset"&&Array.isArray(e.data.assets)&&(s={...s,...e.data.assets.find(o=>o.id===s.id)});for(const o in s)typeof s[o]=="object"&&(s[o]=t(s[o]));return s};return e.data.story&&(e.data.story.content=t(e.data.story.content)),e.data.stories&&(e.data.stories=e.data.stories.map(r=>(r.content=t(r.content),r))),e}}const Re=(n={})=>{const{apiOptions:e}=n;if(!e||!e.accessToken){console.error("You need to provide an access token to interact with Storyblok API. Read https://www.storyblok.com/docs/api/content-delivery#topics/authentication");return}return{storyblokApi:new Te(e)}},_e=n=>{if(typeof n!="object"||typeof n._editable>"u")return{};try{const e=JSON.parse(n._editable.replace(/^<!--#storyblok#/,"").replace(/-->$/,""));return e?{"data-blok-c":JSON.stringify(e),"data-blok-uid":`${e.id}-${e.uid}`}:{}}catch{return{}}};let x="https://app.storyblok.com/f/storyblok-v2-latest.js";const Y=(n,e,t={})=>{var r;const s=!(typeof window>"u")&&typeof window.storyblokRegisterEvent<"u",o=new URL((r=window.location)==null?void 0:r.href).searchParams.get("_storyblok"),c=o!==null&&+o===n;if(!(!s||!c)){if(!n){console.warn("Story ID is not defined. Please provide a valid ID.");return}window.storyblokRegisterEvent(()=>{new window.StoryblokBridge(t).on(["input","published","change"],l=>{var i;l&&(l.action==="input"&&((i=l.story)==null?void 0:i.id)===n?e(l.story):(l.action==="change"||l.action==="published")&&l.storyId===n&&window.location.reload())})})}},$e=(n={})=>{var e,t;const{bridge:r,accessToken:s,use:o=[],apiOptions:c={},bridgeUrl:l}=n;c.accessToken=c.accessToken||s;const i={bridge:r,apiOptions:c};let h={};o.forEach(y=>{h={...h,...y(i)}}),l&&(x=l);const f=!(typeof window>"u")&&((t=(e=window.location)==null?void 0:e.search)==null?void 0:t.includes("_storyblok_tk"));return r!==!1&&f&&J(x),h};function Ee(n,e){return q(e).render(n)}const Ae=()=>J(x);exports.BlockTypes=b;exports.MarkTypes=_;exports.TextTypes=N;exports.apiPlugin=Re;exports.loadStoryblokBridge=Ae;exports.registerStoryblokBridge=Y;exports.renderRichText=Ee;exports.richTextResolver=q;exports.storyblokEditable=_e;exports.storyblokInit=$e;exports.useStoryblokBridge=Y;
|