-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: refactor React Server Components support
- Loading branch information
Showing
22 changed files
with
553 additions
and
173 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,76 @@ | ||
import { storyblokInit as sbInit } from "@storyblok/js"; | ||
|
||
import { | ||
import { storyblokInit as sbInit } from '@storyblok/js'; | ||
import type { | ||
ISbStoryData, | ||
SbReactComponentsMap, | ||
SbReactSDKOptions, | ||
StoryblokClient, | ||
} from "../types"; | ||
} from '../types'; | ||
|
||
let storyblokApiInstance: StoryblokClient = null; | ||
let componentsMap: SbReactComponentsMap = {}; | ||
const componentsMap: Map<string, React.ElementType> = new Map<string, React.ElementType>(); | ||
let enableFallbackComponent: boolean = false; | ||
let customFallbackComponent: React.ElementType = null; | ||
|
||
// Cache for storyblok stories to allow for live editing | ||
globalThis.storyCache = new Map<string, ISbStoryData>(); | ||
|
||
export const useStoryblokApi = (): StoryblokClient => { | ||
if (!storyblokApiInstance) { | ||
console.error( | ||
"You can't use getStoryblokApi if you're not loading apiPlugin." | ||
'You can\'t use getStoryblokApi if you\'re not loading apiPlugin.', | ||
); | ||
} | ||
|
||
return storyblokApiInstance; | ||
}; | ||
|
||
export const setComponents = (newComponentsMap: SbReactComponentsMap) => { | ||
componentsMap = newComponentsMap; | ||
Object.entries(newComponentsMap).forEach(([key, value]) => { | ||
componentsMap.set(key, value); | ||
}); | ||
return componentsMap; | ||
}; | ||
|
||
export const getComponent = (componentKey: string) => { | ||
if (!componentsMap[componentKey]) { | ||
export const getComponent = (componentKey: string): React.ElementType | false => { | ||
if (!componentsMap.has(componentKey)) { | ||
console.error(`Component ${componentKey} doesn't exist.`); | ||
return false; | ||
} | ||
|
||
return componentsMap[componentKey]; | ||
return componentsMap.get(componentKey); | ||
}; | ||
|
||
export const getEnableFallbackComponent = () => enableFallbackComponent; | ||
export const getCustomFallbackComponent = () => customFallbackComponent; | ||
|
||
export const storyblokInit = ( | ||
pluginOptions: SbReactSDKOptions = {} | ||
): (() => StoryblokClient) => { | ||
export const storyblokInit = (pluginOptions: SbReactSDKOptions = {},): (() => StoryblokClient) => { | ||
if (storyblokApiInstance) { | ||
return () => storyblokApiInstance; | ||
} | ||
|
||
const { storyblokApi } = sbInit(pluginOptions); | ||
storyblokApiInstance = storyblokApi; | ||
|
||
componentsMap = pluginOptions.components; | ||
if (pluginOptions.components) { | ||
setComponents(pluginOptions.components); | ||
} | ||
enableFallbackComponent = pluginOptions.enableFallbackComponent; | ||
customFallbackComponent = pluginOptions.customFallbackComponent; | ||
|
||
return () => storyblokApi; | ||
}; | ||
|
||
export { default as StoryblokComponent } from "./storyblok-component"; | ||
export * from '../types'; | ||
export { useStoryblokApi as getStoryblokApi }; | ||
export { default as SbServerComponent } from './storyblok-server-component'; | ||
|
||
export { | ||
storyblokEditable, | ||
apiPlugin, | ||
loadStoryblokBridge, | ||
useStoryblokBridge, | ||
registerStoryblokBridge, | ||
renderRichText, | ||
RichTextResolver, | ||
RichTextSchema, | ||
} from "@storyblok/js"; | ||
|
||
export * from "../types"; | ||
storyblokEditable, | ||
useStoryblokBridge, | ||
} from '@storyblok/js'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
export * from "./common"; | ||
export { default as StoryblokStory } from "./story"; | ||
export { default as BridgeLoader } from "../bridge-loader"; | ||
export { default as StoryblokBridgeLoader } from "../bridge-loader"; | ||
export { default as BridgeLoader } from '../bridge-loader'; | ||
export { default as StoryblokBridgeLoader } from '../bridge-loader'; | ||
export * from './common'; | ||
export { default as SbStoryServerComponent } from './story-server-component'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
'use server'; | ||
|
||
export async function liveEditUpdateAction({ story, pathToRevalidate }) { | ||
if (!story || !pathToRevalidate) { | ||
console.error('liveEditUpdateAction: story or pathToRevalidate is not provided'); | ||
return; | ||
} | ||
|
||
globalThis.storyCache.set(story.uuid, story); | ||
|
||
if (process.env.NEXT_RUNTIME) { | ||
import('next/cache').then(({ revalidatePath }) => { | ||
console.log('Revalidating path:', pathToRevalidate); | ||
revalidatePath(pathToRevalidate); | ||
}).catch((error) => { | ||
console.error('liveEditUpdateAction: error while revalidating path', error); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import React, { forwardRef } from 'react'; | ||
import type { ISbStoryData, StoryblokBridgeConfigV2 } from '../types'; | ||
import { SbServerComponent } from './common'; | ||
import StoryblokLiveEditing from './storyblok-live-editing'; | ||
|
||
interface SbStoryServerComponentProps { | ||
story: ISbStoryData; | ||
bridgeOptions: StoryblokBridgeConfigV2; | ||
[key: string]: unknown; | ||
} | ||
|
||
const SbStoryServerComponent = forwardRef<HTMLElement, SbStoryServerComponentProps>( | ||
({ story, bridgeOptions, ...restProps }, ref) => { | ||
if (!story) { | ||
console.error( | ||
'Please provide a \'story\' property to the SbStoryServerComponent', | ||
); | ||
return null; | ||
} | ||
|
||
if (!globalThis.storyCache.has(story.uuid)) { | ||
globalThis.storyCache.set(story.uuid, story); | ||
} else { | ||
story = globalThis.storyCache.get(story.uuid); | ||
} | ||
if (typeof story.content === 'string') { | ||
story.content = JSON.parse(story.content); | ||
} | ||
|
||
return ( | ||
<> | ||
<SbServerComponent ref={ref} blok={story.content} {...restProps} /> | ||
<StoryblokLiveEditing story={story} bridgeOptions={bridgeOptions} /> | ||
</> | ||
); | ||
}, | ||
); | ||
|
||
export default SbStoryServerComponent; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
"use client"; | ||
|
||
import { registerStoryblokBridge } from "@storyblok/js"; | ||
import { useEffect, startTransition } from "react"; | ||
import { liveEditUpdateAction } from "./live-edit-update-action"; | ||
|
||
const StoryblokLiveEditing = ({ story = null, bridgeOptions = {} }) => { | ||
if (typeof window === 'undefined') { | ||
return null; | ||
} | ||
|
||
const handleInput = (story) => { | ||
if (!story) { | ||
return; | ||
} | ||
startTransition(() => { | ||
liveEditUpdateAction({ story, pathToRevalidate: window.location.pathname }); | ||
}); | ||
}; | ||
|
||
const storyId = story?.internalId ?? story?.id ?? 0; | ||
useEffect(() => { | ||
registerStoryblokBridge(storyId, (newStory) => handleInput(newStory), bridgeOptions); | ||
}, []); | ||
|
||
return null; | ||
}; | ||
|
||
export default StoryblokLiveEditing; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.