-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add shared state * refactor(presentation): improve preview header component types
- Loading branch information
Showing
18 changed files
with
473 additions
and
130 deletions.
There are no files selected for viewing
25 changes: 25 additions & 0 deletions
25
apps/page-builder-demo/src/components/overlays/OverlayHighlight.tsx
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,25 @@ | ||
import {useSharedState} from '@sanity/visual-editing' | ||
import {FunctionComponent} from 'react' | ||
|
||
export const OverlayHighlight: FunctionComponent = () => { | ||
const overlayEnabled = useSharedState<boolean>('overlay-enabled') | ||
|
||
if (!overlayEnabled) { | ||
return null | ||
} | ||
|
||
return ( | ||
<div | ||
style={{ | ||
position: 'absolute', | ||
inset: 0, | ||
width: '100%', | ||
height: '100%', | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
backgroundColor: 'rgba(0, 0, 255, 0.25)', | ||
}} | ||
/> | ||
) | ||
} |
34 changes: 26 additions & 8 deletions
34
apps/page-builder-demo/src/components/overlays/resolver.ts
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,29 +1,47 @@ | ||
'use client' | ||
|
||
import {OverlayComponentResolver} from '@sanity/visual-editing' | ||
import {OverlayComponent, OverlayComponentResolver, useSharedState} from '@sanity/visual-editing' | ||
import { | ||
defineOverlayComponent, | ||
UnionInsertMenuOverlay, | ||
} from '@sanity/visual-editing/unstable_overlay-components' | ||
import {ExcitingTitleControl} from './ExcitingTitleControl' | ||
import {OverlayHighlight} from './OverlayHighlight' | ||
import {ProductModelRotationControl} from './ProductModelRotationControl' | ||
|
||
export const components: OverlayComponentResolver = (props) => { | ||
const {type, node, parent} = props | ||
const {element, type, node, parent} = props | ||
|
||
const components: Array< | ||
| OverlayComponent<Record<string, unknown>, any> | ||
| { | ||
component: OverlayComponent<Record<string, unknown>, any> | ||
props?: Record<string, unknown> | ||
} | ||
> = [OverlayHighlight] | ||
|
||
if (type === 'string' && node.path === 'title') { | ||
return ExcitingTitleControl | ||
components.push(ExcitingTitleControl) | ||
} | ||
|
||
if (type === 'object' && node.path.endsWith('rotations')) { | ||
return defineOverlayComponent(ProductModelRotationControl) | ||
components.push(ProductModelRotationControl) | ||
} | ||
|
||
if (parent?.type === 'union') { | ||
return defineOverlayComponent(UnionInsertMenuOverlay, { | ||
direction: 'vertical', | ||
}) | ||
const parentDataset = element.parentElement?.dataset || {} | ||
|
||
const direction = (parentDataset.direction ?? 'vertical') as 'vertical' | 'horizontal' | ||
|
||
const hoverAreaExtent = parentDataset.hoverExtent || 48 | ||
|
||
components.push( | ||
defineOverlayComponent(UnionInsertMenuOverlay, { | ||
direction, | ||
hoverAreaExtent, | ||
}), | ||
) | ||
} | ||
|
||
return undefined | ||
return components | ||
} |
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,41 @@ | ||
import {CheckmarkIcon, CloseIcon, EllipsisVerticalIcon} from '@sanity/icons' | ||
import {useSharedState} from '@sanity/presentation' | ||
import type {PreviewHeaderProps} from '@sanity/presentation' | ||
import {Button, Menu, MenuButton, MenuItem} from '@sanity/ui' | ||
import {useState, type FunctionComponent} from 'react' | ||
|
||
export const CustomHeader: FunctionComponent<PreviewHeaderProps> = (props) => { | ||
const [enabled, setEnabled] = useState(false) | ||
|
||
useSharedState('overlay-enabled', enabled) | ||
|
||
return ( | ||
<> | ||
{props.renderDefault(props)} | ||
<MenuButton | ||
button={ | ||
<Button fontSize={1} icon={EllipsisVerticalIcon} mode="bleed" padding={2} space={2} /> | ||
} | ||
id="custom-menu" | ||
menu={ | ||
<Menu style={{maxWidth: 240}}> | ||
<MenuItem | ||
fontSize={1} | ||
icon={enabled ? CloseIcon : CheckmarkIcon} | ||
onClick={() => setEnabled((enabled) => !enabled)} | ||
padding={3} | ||
tone={enabled ? 'caution' : 'positive'} | ||
text={enabled ? 'Disable Highlighting' : 'Enable Highlighting'} | ||
/> | ||
</Menu> | ||
} | ||
popover={{ | ||
animate: true, | ||
constrainSize: true, | ||
placement: 'bottom', | ||
portal: true, | ||
}} | ||
/> | ||
</> | ||
) | ||
} |
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
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,9 @@ | ||
import type {Serializable} from '@repo/visual-editing-helpers' | ||
import {createContext} from 'react' | ||
|
||
export interface SharedStateContextValue { | ||
removeValue: (key: string) => void | ||
setValue: (key: string, value: Serializable) => void | ||
} | ||
|
||
export const SharedStateContext = createContext<SharedStateContextValue | null>(null) |
50 changes: 50 additions & 0 deletions
50
packages/presentation/src/overlays/SharedStateProvider.tsx
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,50 @@ | ||
import type {Serializable, SerializableObject} from '@repo/visual-editing-helpers' | ||
import { | ||
useCallback, | ||
useEffect, | ||
useMemo, | ||
useRef, | ||
type FunctionComponent, | ||
type PropsWithChildren, | ||
} from 'react' | ||
import type {VisualEditingConnection} from '../types' | ||
import {SharedStateContext, type SharedStateContextValue} from './SharedStateContext' | ||
|
||
export const SharedStateProvider: FunctionComponent< | ||
PropsWithChildren<{ | ||
comlink: VisualEditingConnection | null | ||
}> | ||
> = function (props) { | ||
const {comlink, children} = props | ||
|
||
const sharedState = useRef<SerializableObject>({}) | ||
|
||
useEffect(() => { | ||
return comlink?.on('visual-editing/shared-state', () => { | ||
return {state: sharedState.current} | ||
}) | ||
}, [comlink]) | ||
|
||
const setValue = useCallback( | ||
(key: string, value: Serializable) => { | ||
sharedState.current[key] = value | ||
comlink?.post({type: 'presentation/shared-state', data: {key, value}}) | ||
}, | ||
[comlink], | ||
) | ||
|
||
const removeValue = useCallback( | ||
(key: string) => { | ||
comlink?.post({type: 'presentation/shared-state', data: {key}}) | ||
delete sharedState.current[key] | ||
}, | ||
[comlink], | ||
) | ||
|
||
const context = useMemo<SharedStateContextValue>( | ||
() => ({removeValue, setValue}), | ||
[removeValue, setValue], | ||
) | ||
|
||
return <SharedStateContext.Provider value={context}>{children}</SharedStateContext.Provider> | ||
} |
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,25 @@ | ||
import type {Serializable} from '@repo/visual-editing-helpers' | ||
import {useContext, useEffect} from 'react' | ||
import {SharedStateContext} from './SharedStateContext' | ||
|
||
export const useSharedState = (key: string, value: Serializable): undefined => { | ||
const context = useContext(SharedStateContext) | ||
|
||
if (!context) { | ||
throw new Error('Preview Snapshots context is missing') | ||
} | ||
|
||
const {removeValue, setValue} = context | ||
|
||
useEffect(() => { | ||
setValue(key, value) | ||
}, [key, value, setValue]) | ||
|
||
useEffect(() => { | ||
return () => { | ||
removeValue(key) | ||
} | ||
}, [key, removeValue]) | ||
|
||
return undefined | ||
} |
Oops, something went wrong.