From f90f9844b200b2c52a8389ff4cda59d16e363043 Mon Sep 17 00:00:00 2001 From: Johannes Lindgren <14206504+johannes-lindgren@users.noreply.github.com> Date: Wed, 2 Oct 2024 17:03:17 +0200 Subject: [PATCH 01/11] feat: introduce usePortalModal to PluginLoadedMessage --- .../PluginLoadedMessage.test.ts | 100 ++++++++++++++++++ .../PluginLoadedMessage.ts | 7 +- 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts index 716303c8..4e04d78e 100644 --- a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts +++ b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts @@ -76,6 +76,94 @@ describe('PluginLoadedMessage', () => { ).toEqual(false) }) }) + describe('subscribeState', () => { + it('is optional', () => { + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: undefined, + }), + ).toEqual(true) + }) + it('is a boolean', () => { + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: true, + }), + ).toEqual(true) + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: false, + }), + ).toEqual(true) + const { subscribeState: _subscribeState, ...subWithoutSubscribeState } = stub + expect(isPluginLoadedMessage(subWithoutSubscribeState)).toEqual(true) + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: 'false', + }), + ).toEqual(false) + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: 123, + }), + ).toEqual(false) + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: null, + }), + ).toEqual(false) + }) + }) + describe('usePortalModal', () => { + it('is optional', () => { + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: undefined, + }), + ).toEqual(true) + }) + it('is a boolean', () => { + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: true, + }), + ).toEqual(true) + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: false, + }), + ).toEqual(true) + const { subscribeState: _subscribeState, ...subWithoutSubscribeState } = stub + expect(isPluginLoadedMessage(subWithoutSubscribeState)).toEqual(true) + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: 'false', + }), + ).toEqual(false) + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: 123, + }), + ).toEqual(false) + expect( + isPluginLoadedMessage({ + ...stub, + subscribeState: null, + }), + ).toEqual(false) + }) + }) }) describe('constructor', () => { it('includes the uid', () => { @@ -90,5 +178,17 @@ describe('PluginLoadedMessage', () => { true, ) }) + it('sets subscribeState to true', () => { + expect(pluginLoadedMessage({ uid, callbackId })).toHaveProperty( + 'subscribeState', + true, + ) + }) + it('sets usePortalModal to true', () => { + expect(pluginLoadedMessage({ uid, callbackId })).toHaveProperty( + 'usePortalModal', + true, + ) + }) }) }) diff --git a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts index e6fbd7cd..5e8f0a36 100644 --- a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts +++ b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts @@ -5,6 +5,7 @@ export type PluginLoadedMessage = MessageToContainer<'loaded'> & { // signals that the field plugin is responsible for its own scrolling in modal mode fullHeight?: boolean subscribeState?: boolean + usePortalModal?: boolean } export const isPluginLoadedMessage = ( obj: unknown, @@ -16,7 +17,10 @@ export const isPluginLoadedMessage = ( typeof obj.fullHeight === 'boolean') && (!hasKey(obj, 'subscribeState') || typeof obj.subscribeState === 'undefined' || - typeof obj.subscribeState === 'boolean') + typeof obj.subscribeState === 'boolean') && + (!hasKey(obj, 'usePortalModal') || + typeof obj.usePortalModal === 'undefined' || + typeof obj.usePortalModal === 'boolean') export const pluginLoadedMessage = ( options: Pick, @@ -25,5 +29,6 @@ export const pluginLoadedMessage = ( event: 'loaded', fullHeight: true, subscribeState: true, + usePortalModal: true, ...options, }) From 7ede7bf977f39d1f208cfc83d954723e9ddf4030 Mon Sep 17 00:00:00 2001 From: Johannes Lindgren <14206504+johannes-lindgren@users.noreply.github.com> Date: Thu, 3 Oct 2024 10:29:27 +0200 Subject: [PATCH 02/11] feat: modal in portal --- .../createFieldPlugin/createFieldPlugin.ts | 1 + .../PluginLoadedMessage.test.ts | 6 ++--- .../PluginLoadedMessage.ts | 10 ++++---- .../src/components/FieldPluginSandbox.tsx | 5 ++++ .../src/components/FieldTypePreview.tsx | 25 +++++++++++-------- 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts b/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts index 594f515c..9d6f14dc 100644 --- a/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts +++ b/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts @@ -12,6 +12,7 @@ export type CreateFieldPluginOptions = { onUpdateState: (state: FieldPluginResponse) => void validateContent?: ValidateContent targetOrigin?: string +// TODO add enablePortalModal } export type CreateFieldPlugin = ( diff --git a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts index 4e04d78e..5f926e26 100644 --- a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts +++ b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts @@ -120,7 +120,7 @@ describe('PluginLoadedMessage', () => { ).toEqual(false) }) }) - describe('usePortalModal', () => { + describe('enablePortalModal', () => { it('is optional', () => { expect( isPluginLoadedMessage({ @@ -184,9 +184,9 @@ describe('PluginLoadedMessage', () => { true, ) }) - it('sets usePortalModal to true', () => { + it('sets enablePortalModal to true', () => { expect(pluginLoadedMessage({ uid, callbackId })).toHaveProperty( - 'usePortalModal', + 'enablePortalModal', true, ) }) diff --git a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts index 5e8f0a36..0b82332c 100644 --- a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts +++ b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts @@ -5,7 +5,7 @@ export type PluginLoadedMessage = MessageToContainer<'loaded'> & { // signals that the field plugin is responsible for its own scrolling in modal mode fullHeight?: boolean subscribeState?: boolean - usePortalModal?: boolean + enablePortalModal?: boolean } export const isPluginLoadedMessage = ( obj: unknown, @@ -18,9 +18,9 @@ export const isPluginLoadedMessage = ( (!hasKey(obj, 'subscribeState') || typeof obj.subscribeState === 'undefined' || typeof obj.subscribeState === 'boolean') && - (!hasKey(obj, 'usePortalModal') || - typeof obj.usePortalModal === 'undefined' || - typeof obj.usePortalModal === 'boolean') + (!hasKey(obj, 'enablePortalModal') || + typeof obj.enablePortalModal === 'undefined' || + typeof obj.enablePortalModal === 'boolean') export const pluginLoadedMessage = ( options: Pick, @@ -29,6 +29,6 @@ export const pluginLoadedMessage = ( event: 'loaded', fullHeight: true, subscribeState: true, - usePortalModal: true, + enablePortalModal: true, ...options, }) diff --git a/packages/sandbox/src/components/FieldPluginSandbox.tsx b/packages/sandbox/src/components/FieldPluginSandbox.tsx index d2f00feb..e84af9b3 100644 --- a/packages/sandbox/src/components/FieldPluginSandbox.tsx +++ b/packages/sandbox/src/components/FieldPluginSandbox.tsx @@ -108,6 +108,7 @@ const useSandbox = ( const [isModalOpen, setModalOpen] = useState(false) const [height, setHeight] = useState(initialHeight) const [fullHeight, setFullHeight] = useState(false) + const [enablePortalModal, setEnablePortalModal] = useState(false) const [schema, setSchema] = useState({ field_type: 'preview', options: manifest.options, @@ -218,6 +219,7 @@ const useSandbox = ( (message: PluginLoadedMessage) => { setSubscribeState(Boolean(message.subscribeState)) setFullHeight(Boolean(message.fullHeight)) + setEnablePortalModal(Boolean(message.enablePortalModal)) dispatchLoadedChanged({ ...stateChangedData, action: 'loaded', @@ -309,6 +311,7 @@ const useSandbox = ( isModalOpen, height, fullHeight, + enablePortalModal, schema, url, fieldTypeIframe, @@ -332,6 +335,7 @@ export const FieldPluginSandbox: FunctionComponent = () => { language, isModalOpen, fullHeight, + enablePortalModal, height, schema, url, @@ -371,6 +375,7 @@ export const FieldPluginSandbox: FunctionComponent = () => { src={iframeSrc} height={height} isModal={isModalOpen} + enablePortalModal={enablePortalModal} fullHeight={fullHeight} ref={fieldTypeIframe} /> diff --git a/packages/sandbox/src/components/FieldTypePreview.tsx b/packages/sandbox/src/components/FieldTypePreview.tsx index ec560b31..40876a83 100644 --- a/packages/sandbox/src/components/FieldTypePreview.tsx +++ b/packages/sandbox/src/components/FieldTypePreview.tsx @@ -9,14 +9,14 @@ import { } from '@mui/material' import { DisableShieldsNotification } from './DisableShieldsNotification' -const FieldTypeModal: FunctionComponent< +const NonPortalModal: FunctionComponent< PropsWithChildren<{ - isModal: boolean + isNonPortalModalOpen: boolean }> > = (props) => ( > = (props) => ( {props.children} @@ -74,13 +74,18 @@ export const FieldTypePreview = forwardRef< src: string | undefined height: number isModal: boolean + enablePortalModal: boolean fullHeight: boolean // Allows the iframe to be refreshed iframeKey?: number sx?: SxProps } >(function FieldTypePreview(props, ref) { - const { height, isModal, fullHeight } = props + const { height, isModal, fullHeight, enablePortalModal } = props + + const isNonPortalModalOpen = !enablePortalModal && isModal + const isPortalModalOpen = enablePortalModal && isModal + return ( @@ -88,8 +93,8 @@ export const FieldTypePreview = forwardRef< open={props.isModal} sx={{ zIndex: ({ zIndex }) => zIndex.drawer }} /> - - + + {typeof props.src !== 'undefined' ? ( )} - + ) }) From c603fcbc2766f06b113be63020343c5652806b1b Mon Sep 17 00:00:00 2001 From: Johannes Lindgren <14206504+johannes-lindgren@users.noreply.github.com> Date: Thu, 3 Oct 2024 12:15:01 +0200 Subject: [PATCH 03/11] fix(sandbox): implementation for sandbox --- .../src/components/FieldTypePreview.tsx | 121 ++++++++++++++---- 1 file changed, 98 insertions(+), 23 deletions(-) diff --git a/packages/sandbox/src/components/FieldTypePreview.tsx b/packages/sandbox/src/components/FieldTypePreview.tsx index 40876a83..78208bfc 100644 --- a/packages/sandbox/src/components/FieldTypePreview.tsx +++ b/packages/sandbox/src/components/FieldTypePreview.tsx @@ -1,9 +1,15 @@ -import { forwardRef, FunctionComponent, PropsWithChildren } from 'react' +import { + ForwardedRef, + forwardRef, + FunctionComponent, + PropsWithChildren, +} from 'react' import { Alert, AlertTitle, Backdrop, Box, + Dialog, SxProps, Typography, } from '@mui/material' @@ -68,6 +74,57 @@ const FieldTypeSandbox: FunctionComponent< ) +const FieldPluginIframe = forwardRef< + HTMLIFrameElement, + { + src: string | undefined + fullHeight: boolean + modal: boolean + height: number + } +>(function FieldPluginIframe(props, ref) { + const { src, fullHeight, modal, height } = props + + if (typeof src === 'undefined') { + return ( + + Unable to Load Field Plugin + Please enter a valid URL. + + ) + } + + return ( + + ) +}) + +const setRef = (ref: ForwardedRef, value: T | null) => { + if (ref === null) { + return + } else if (typeof ref === 'function') { + ref(value) + } else { + ref.current = value + } +} + export const FieldTypePreview = forwardRef< HTMLIFrameElement, { @@ -86,39 +143,57 @@ export const FieldTypePreview = forwardRef< const isNonPortalModalOpen = !enablePortalModal && isModal const isPortalModalOpen = enablePortalModal && isModal + const setTeleported = (el: HTMLIFrameElement | null) => { + if (isPortalModalOpen) { + setRef(ref, el) + } + } + const setNonTeleported = (el: HTMLIFrameElement | null) => { + if (!isPortalModalOpen) { + setRef(ref, el) + } + } + return ( + + + zIndex.drawer }} /> - {typeof props.src !== 'undefined' ? ( - - ) : ( - - Unable to Load Field Plugin - Please enter a valid URL. - )} From c4f98a6fb0ed08cbb8b55487a177787a844739ae Mon Sep 17 00:00:00 2001 From: Johannes Lindgren <14206504+johannes-lindgren@users.noreply.github.com> Date: Thu, 3 Oct 2024 15:06:58 +0200 Subject: [PATCH 04/11] fix(sandbox): close modal from the parent app --- .../src/components/FieldPluginSandbox.tsx | 4 +++- .../src/components/FieldTypePreview.tsx | 24 ++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/sandbox/src/components/FieldPluginSandbox.tsx b/packages/sandbox/src/components/FieldPluginSandbox.tsx index e84af9b3..062d5d9f 100644 --- a/packages/sandbox/src/components/FieldPluginSandbox.tsx +++ b/packages/sandbox/src/components/FieldPluginSandbox.tsx @@ -323,6 +323,7 @@ const useSandbox = ( setSchema, setUrl, randomizeUid, + setModalOpen, }, ] as const } @@ -342,7 +343,7 @@ export const FieldPluginSandbox: FunctionComponent = () => { fieldTypeIframe, iframeSrc, }, - { setContent, setLanguage, setSchema, setUrl, randomizeUid }, + { setModalOpen, setContent, setLanguage, setSchema, setUrl, randomizeUid }, ] = useSandbox(error) return ( @@ -378,6 +379,7 @@ export const FieldPluginSandbox: FunctionComponent = () => { enablePortalModal={enablePortalModal} fullHeight={fullHeight} ref={fieldTypeIframe} + onModalChange={setModalOpen} /> diff --git a/packages/sandbox/src/components/FieldTypePreview.tsx b/packages/sandbox/src/components/FieldTypePreview.tsx index 78208bfc..26a6d192 100644 --- a/packages/sandbox/src/components/FieldTypePreview.tsx +++ b/packages/sandbox/src/components/FieldTypePreview.tsx @@ -10,10 +10,12 @@ import { Backdrop, Box, Dialog, + IconButton, SxProps, Typography, } from '@mui/material' import { DisableShieldsNotification } from './DisableShieldsNotification' +import { CloseIcon } from '@storyblok/mui' const NonPortalModal: FunctionComponent< PropsWithChildren<{ @@ -136,9 +138,11 @@ export const FieldTypePreview = forwardRef< // Allows the iframe to be refreshed iframeKey?: number sx?: SxProps + onModalChange: (isModal: boolean) => void } >(function FieldTypePreview(props, ref) { - const { height, isModal, fullHeight, enablePortalModal } = props + const { height, isModal, fullHeight, enablePortalModal, onModalChange } = + props const isNonPortalModalOpen = !enablePortalModal && isModal const isPortalModalOpen = enablePortalModal && isModal @@ -154,6 +158,10 @@ export const FieldTypePreview = forwardRef< } } + const handleClose = () => { + onModalChange(false) + } + return ( @@ -169,7 +177,21 @@ export const FieldTypePreview = forwardRef< overflow: 'hidden', }, }} + onClose={handleClose} > + + + + + Date: Fri, 4 Oct 2024 11:19:18 +0200 Subject: [PATCH 05/11] refactor(sandbox): better state management of modal --- .../createFieldPlugin/createFieldPlugin.ts | 1 - .../src/components/FieldPluginSandbox.tsx | 26 +++++-- .../src/components/FieldTypePreview.tsx | 67 ++++++++++--------- 3 files changed, 53 insertions(+), 41 deletions(-) diff --git a/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts b/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts index 9d6f14dc..594f515c 100644 --- a/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts +++ b/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts @@ -12,7 +12,6 @@ export type CreateFieldPluginOptions = { onUpdateState: (state: FieldPluginResponse) => void validateContent?: ValidateContent targetOrigin?: string -// TODO add enablePortalModal } export type CreateFieldPlugin = ( diff --git a/packages/sandbox/src/components/FieldPluginSandbox.tsx b/packages/sandbox/src/components/FieldPluginSandbox.tsx index 062d5d9f..184813d7 100644 --- a/packages/sandbox/src/components/FieldPluginSandbox.tsx +++ b/packages/sandbox/src/components/FieldPluginSandbox.tsx @@ -65,6 +65,11 @@ const defaultManifest = { options: [] } const urlQueryParam = withDefault(StringParam, defaultUrl) const manifestQueryParam = withDefault(JsonParam, defaultManifest) +export type ModalState = + | 'non-modal' + | 'modal-with-portal' + | 'modal-without-portal' + const useSandbox = ( onError: (message: { title: string; message?: string }) => void, ) => { @@ -304,14 +309,23 @@ const useSandbox = ( ], ) + const modalState = useMemo(() => { + if (!isModalOpen) { + return 'non-modal' + } else if (enablePortalModal) { + return 'modal-with-portal' + } else { + return 'modal-without-portal' + } + }, [isModalOpen, enablePortalModal]) + return [ { content, language, - isModalOpen, height, fullHeight, - enablePortalModal, + modalState, schema, url, fieldTypeIframe, @@ -334,9 +348,8 @@ export const FieldPluginSandbox: FunctionComponent = () => { { content, language, - isModalOpen, + modalState, fullHeight, - enablePortalModal, height, schema, url, @@ -375,8 +388,7 @@ export const FieldPluginSandbox: FunctionComponent = () => { { output={ { content, - isModalOpen, + isModalOpen: modalState !== 'non-modal', translatable: schema.translatable, storyLang: language, options: recordFromFieldPluginOptions(schema.options), diff --git a/packages/sandbox/src/components/FieldTypePreview.tsx b/packages/sandbox/src/components/FieldTypePreview.tsx index 26a6d192..2c02d50b 100644 --- a/packages/sandbox/src/components/FieldTypePreview.tsx +++ b/packages/sandbox/src/components/FieldTypePreview.tsx @@ -16,15 +16,16 @@ import { } from '@mui/material' import { DisableShieldsNotification } from './DisableShieldsNotification' import { CloseIcon } from '@storyblok/mui' +import { ModalState } from './FieldPluginSandbox' const NonPortalModal: FunctionComponent< PropsWithChildren<{ - isNonPortalModalOpen: boolean + isModal: boolean }> > = (props) => ( > = (props) => ( {props.children} @@ -132,8 +133,7 @@ export const FieldTypePreview = forwardRef< { src: string | undefined height: number - isModal: boolean - enablePortalModal: boolean + modalState: ModalState fullHeight: boolean // Allows the iframe to be refreshed iframeKey?: number @@ -141,19 +141,15 @@ export const FieldTypePreview = forwardRef< onModalChange: (isModal: boolean) => void } >(function FieldTypePreview(props, ref) { - const { height, isModal, fullHeight, enablePortalModal, onModalChange } = - props - - const isNonPortalModalOpen = !enablePortalModal && isModal - const isPortalModalOpen = enablePortalModal && isModal + const { height, fullHeight, modalState, onModalChange } = props const setTeleported = (el: HTMLIFrameElement | null) => { - if (isPortalModalOpen) { + if (modalState === 'modal-with-portal') { setRef(ref, el) } } const setNonTeleported = (el: HTMLIFrameElement | null) => { - if (!isPortalModalOpen) { + if (modalState !== 'modal-with-portal') { setRef(ref, el) } } @@ -166,7 +162,7 @@ export const FieldTypePreview = forwardRef< - zIndex.drawer }} - /> - - - {!isPortalModalOpen && ( - + zIndex.drawer }} /> - )} - - + + + + + + + ) + } ) }) From 6f591eac579028b568e9d45cde2eeaf4fa7f373e Mon Sep 17 00:00:00 2001 From: Johannes Lindgren <14206504+johannes-lindgren@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:03:06 +0200 Subject: [PATCH 06/11] feat: enablePortalModal option --- .../demo/src/components/FieldPluginDemo.tsx | 2 ++ .../createFieldPlugin/createFieldPlugin.ts | 3 +++ .../createPluginActions.ts | 6 ++++- .../PluginLoadedMessage.test.ts | 22 ++++++++++++++----- .../PluginLoadedMessage.ts | 6 +++-- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/packages/demo/src/components/FieldPluginDemo.tsx b/packages/demo/src/components/FieldPluginDemo.tsx index 1e9c1247..64628ca7 100644 --- a/packages/demo/src/components/FieldPluginDemo.tsx +++ b/packages/demo/src/components/FieldPluginDemo.tsx @@ -19,6 +19,8 @@ export type PluginComponent = FunctionComponent<{ export const FieldPluginDemo: FunctionComponent = () => { const { type, data, actions } = useFieldPlugin({ validateContent, + targetOrigin: 'http://localhost:7070', + enablePortalModal: true, }) if (type === 'loading') { diff --git a/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts b/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts index 594f515c..9cf30cfa 100644 --- a/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts +++ b/packages/field-plugin/src/createFieldPlugin/createFieldPlugin.ts @@ -12,6 +12,7 @@ export type CreateFieldPluginOptions = { onUpdateState: (state: FieldPluginResponse) => void validateContent?: ValidateContent targetOrigin?: string + enablePortalModal?: boolean } export type CreateFieldPlugin = ( @@ -25,6 +26,7 @@ export const createFieldPlugin: CreateFieldPlugin = ({ onUpdateState, validateContent, targetOrigin, + enablePortalModal, }) => { const isEmbedded = window.parent !== window @@ -107,6 +109,7 @@ export const createFieldPlugin: CreateFieldPlugin = ({ validateContent: validateContent || ((content) => ({ content: content as InferredContent })), + enablePortalModal, }) const cleanupHeightChangeListener = createHeightChangeListener(onHeightChange) diff --git a/packages/field-plugin/src/createFieldPlugin/createPluginActions/createPluginActions.ts b/packages/field-plugin/src/createFieldPlugin/createPluginActions/createPluginActions.ts index 23b790e7..fde67769 100644 --- a/packages/field-plugin/src/createFieldPlugin/createPluginActions/createPluginActions.ts +++ b/packages/field-plugin/src/createFieldPlugin/createPluginActions/createPluginActions.ts @@ -28,6 +28,7 @@ export type CreatePluginActions = (options: { postToContainer: (message: unknown) => void onUpdateState: (state: FieldPluginData) => void validateContent: ValidateContent + enablePortalModal: boolean | undefined }) => { // These functions are to be called by the field plugin when the user performs actions in the UI actions: FieldPluginActions @@ -46,6 +47,7 @@ export const createPluginActions: CreatePluginActions = ({ postToContainer, onUpdateState, validateContent, + enablePortalModal, }) => { const { pushCallback, popCallback } = callbackQueue() @@ -143,7 +145,9 @@ export const createPluginActions: CreatePluginActions = ({ resolve(pluginStateFromStateChangeMessage(message, validateContent)), ) // Request the initial state from the Visual Editor. - postToContainer(pluginLoadedMessage({ uid, callbackId })) + postToContainer( + pluginLoadedMessage({ uid, callbackId, enablePortalModal }), + ) }) }, } diff --git a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts index 5f926e26..2686d256 100644 --- a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts +++ b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts @@ -98,7 +98,8 @@ describe('PluginLoadedMessage', () => { subscribeState: false, }), ).toEqual(true) - const { subscribeState: _subscribeState, ...subWithoutSubscribeState } = stub + const { subscribeState: _subscribeState, ...subWithoutSubscribeState } = + stub expect(isPluginLoadedMessage(subWithoutSubscribeState)).toEqual(true) expect( isPluginLoadedMessage({ @@ -142,7 +143,8 @@ describe('PluginLoadedMessage', () => { subscribeState: false, }), ).toEqual(true) - const { subscribeState: _subscribeState, ...subWithoutSubscribeState } = stub + const { subscribeState: _subscribeState, ...subWithoutSubscribeState } = + stub expect(isPluginLoadedMessage(subWithoutSubscribeState)).toEqual(true) expect( isPluginLoadedMessage({ @@ -184,11 +186,21 @@ describe('PluginLoadedMessage', () => { true, ) }) - it('sets enablePortalModal to true', () => { - expect(pluginLoadedMessage({ uid, callbackId })).toHaveProperty( + it('does not define enablePortalModal by default', () => { + expect(pluginLoadedMessage({ uid, callbackId })).not.toHaveProperty( 'enablePortalModal', - true, ) }) + it('lets you define enablePortalModal', () => { + expect( + pluginLoadedMessage({ uid, callbackId, enablePortalModal: true }), + ).toHaveProperty('enablePortalModal', true) + expect( + pluginLoadedMessage({ uid, callbackId, enablePortalModal: false }), + ).toHaveProperty('enablePortalModal', false) + expect( + pluginLoadedMessage({ uid, callbackId, enablePortalModal: undefined }), + ).toHaveProperty('enablePortalModal', undefined) + }) }) }) diff --git a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts index 0b82332c..80d94a13 100644 --- a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts +++ b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.ts @@ -23,12 +23,14 @@ export const isPluginLoadedMessage = ( typeof obj.enablePortalModal === 'boolean') export const pluginLoadedMessage = ( - options: Pick, + options: Pick< + PluginLoadedMessage, + 'uid' | 'callbackId' | 'enablePortalModal' + >, ): PluginLoadedMessage => ({ action: 'plugin-changed', event: 'loaded', fullHeight: true, subscribeState: true, - enablePortalModal: true, ...options, }) From 381fd168af36c263905981cd100ace2ef9994161 Mon Sep 17 00:00:00 2001 From: Johannes Lindgren <14206504+johannes-lindgren@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:07:57 +0200 Subject: [PATCH 07/11] fix: ts errors --- .../createPluginActions/createPluginActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/field-plugin/src/createFieldPlugin/createPluginActions/createPluginActions.ts b/packages/field-plugin/src/createFieldPlugin/createPluginActions/createPluginActions.ts index fde67769..a830b2da 100644 --- a/packages/field-plugin/src/createFieldPlugin/createPluginActions/createPluginActions.ts +++ b/packages/field-plugin/src/createFieldPlugin/createPluginActions/createPluginActions.ts @@ -28,7 +28,7 @@ export type CreatePluginActions = (options: { postToContainer: (message: unknown) => void onUpdateState: (state: FieldPluginData) => void validateContent: ValidateContent - enablePortalModal: boolean | undefined + enablePortalModal?: boolean }) => { // These functions are to be called by the field plugin when the user performs actions in the UI actions: FieldPluginActions From 5bf71a7225af03f223ab0ec2109c035e9ff18a2e Mon Sep 17 00:00:00 2001 From: Johannes Lindgren <14206504+johannes-lindgren@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:17:06 +0200 Subject: [PATCH 08/11] feat: enable by default in templates --- packages/cli/templates/js/src/main.js | 1 + packages/cli/templates/react/src/components/FieldPlugin.tsx | 1 + packages/cli/templates/vue2/src/fieldPlugin.js | 1 + .../templates/vue3/src/components/FieldPluginExample/index.vue | 1 + 4 files changed, 4 insertions(+) diff --git a/packages/cli/templates/js/src/main.js b/packages/cli/templates/js/src/main.js index e8ddd8e4..5d54b82a 100644 --- a/packages/cli/templates/js/src/main.js +++ b/packages/cli/templates/js/src/main.js @@ -15,6 +15,7 @@ let previousType = 'loading' // Establish communication with the Visual Editor createFieldPlugin({ + enablePortalModal: true, validateContent: (content) => ({ content: typeof content === 'number' ? content : 0, }), diff --git a/packages/cli/templates/react/src/components/FieldPlugin.tsx b/packages/cli/templates/react/src/components/FieldPlugin.tsx index 66c07911..0e11db4b 100644 --- a/packages/cli/templates/react/src/components/FieldPlugin.tsx +++ b/packages/cli/templates/react/src/components/FieldPlugin.tsx @@ -3,6 +3,7 @@ import { useFieldPlugin } from '@storyblok/field-plugin/react' const FieldPlugin: FunctionComponent = () => { const plugin = useFieldPlugin({ + enablePortalModal: true, /* The `validateContent` parameter is optional. It allows you to - validate the content diff --git a/packages/cli/templates/vue2/src/fieldPlugin.js b/packages/cli/templates/vue2/src/fieldPlugin.js index 5ce69db0..f4cf2c24 100644 --- a/packages/cli/templates/vue2/src/fieldPlugin.js +++ b/packages/cli/templates/vue2/src/fieldPlugin.js @@ -4,6 +4,7 @@ import { createFieldPlugin } from '@storyblok/field-plugin' export const fieldPluginMixin = { created() { createFieldPlugin({ + enablePortalModal: true, validateContent: (content) => ({ content: typeof content === 'number' ? content : 0, }), diff --git a/packages/cli/templates/vue3/src/components/FieldPluginExample/index.vue b/packages/cli/templates/vue3/src/components/FieldPluginExample/index.vue index 324efd51..63df6e61 100644 --- a/packages/cli/templates/vue3/src/components/FieldPluginExample/index.vue +++ b/packages/cli/templates/vue3/src/components/FieldPluginExample/index.vue @@ -6,6 +6,7 @@ import AssetSelector from './AssetSelector.vue' import { useFieldPlugin } from '@storyblok/field-plugin/vue3' const plugin = useFieldPlugin({ + enablePortalModal: true, validateContent: (content: unknown) => ({ content: typeof content === 'number' ? content : 0, }), From 868873dd20bcafbb4c6e0c871c5804f69e290f67 Mon Sep 17 00:00:00 2001 From: Johannes Lindgren <14206504+johannes-lindgren@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:57:36 +0200 Subject: [PATCH 09/11] Update packages/demo/src/components/FieldPluginDemo.tsx --- packages/demo/src/components/FieldPluginDemo.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/demo/src/components/FieldPluginDemo.tsx b/packages/demo/src/components/FieldPluginDemo.tsx index 64628ca7..aeff0300 100644 --- a/packages/demo/src/components/FieldPluginDemo.tsx +++ b/packages/demo/src/components/FieldPluginDemo.tsx @@ -19,7 +19,6 @@ export type PluginComponent = FunctionComponent<{ export const FieldPluginDemo: FunctionComponent = () => { const { type, data, actions } = useFieldPlugin({ validateContent, - targetOrigin: 'http://localhost:7070', enablePortalModal: true, }) From 5be7b069d1330943829a7ec885abb55bbf486757 Mon Sep 17 00:00:00 2001 From: Johannes Lindgren <14206504+johannes-lindgren@users.noreply.github.com> Date: Thu, 10 Oct 2024 11:29:43 +0200 Subject: [PATCH 10/11] fix: templates --- .../templates/react/src/components/FieldPluginExample/index.tsx | 1 + packages/cli/templates/vue3/src/components/FieldPlugin.vue | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/cli/templates/react/src/components/FieldPluginExample/index.tsx b/packages/cli/templates/react/src/components/FieldPluginExample/index.tsx index 80cc3e3a..f99df789 100644 --- a/packages/cli/templates/react/src/components/FieldPluginExample/index.tsx +++ b/packages/cli/templates/react/src/components/FieldPluginExample/index.tsx @@ -7,6 +7,7 @@ import { useFieldPlugin } from '@storyblok/field-plugin/react' const FieldPlugin: FunctionComponent = () => { const { type, data, actions } = useFieldPlugin({ + enablePortalModal: true, validateContent: (content: unknown) => ({ content: typeof content === 'number' ? content : 0, }), diff --git a/packages/cli/templates/vue3/src/components/FieldPlugin.vue b/packages/cli/templates/vue3/src/components/FieldPlugin.vue index 268472a4..9bae6b85 100644 --- a/packages/cli/templates/vue3/src/components/FieldPlugin.vue +++ b/packages/cli/templates/vue3/src/components/FieldPlugin.vue @@ -2,6 +2,7 @@ import { useFieldPlugin } from '@storyblok/field-plugin/vue3' const plugin = useFieldPlugin({ + enablePortalModal: true, /* The `validateContent` parameter is optional. It allows you to - validate the content From b0d2b9aebdd0076c8cc4e2d98174060e7506d563 Mon Sep 17 00:00:00 2001 From: Johannes Lindgren <14206504+johannes-lindgren@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:22:36 +0200 Subject: [PATCH 11/11] fix: tests --- .../PluginLoadedMessage.test.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts index 2686d256..8d4427ed 100644 --- a/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts +++ b/packages/field-plugin/src/messaging/pluginMessage/pluginToContainerMessage/PluginLoadedMessage.test.ts @@ -126,7 +126,6 @@ describe('PluginLoadedMessage', () => { expect( isPluginLoadedMessage({ ...stub, - subscribeState: undefined, }), ).toEqual(true) }) @@ -134,34 +133,31 @@ describe('PluginLoadedMessage', () => { expect( isPluginLoadedMessage({ ...stub, - subscribeState: true, + enablePortalModal: true, }), ).toEqual(true) expect( isPluginLoadedMessage({ ...stub, - subscribeState: false, + enablePortalModal: false, }), ).toEqual(true) - const { subscribeState: _subscribeState, ...subWithoutSubscribeState } = - stub - expect(isPluginLoadedMessage(subWithoutSubscribeState)).toEqual(true) expect( isPluginLoadedMessage({ ...stub, - subscribeState: 'false', + enablePortalModal: 'false', }), ).toEqual(false) expect( isPluginLoadedMessage({ ...stub, - subscribeState: 123, + enablePortalModal: 123, }), ).toEqual(false) expect( isPluginLoadedMessage({ ...stub, - subscribeState: null, + enablePortalModal: null, }), ).toEqual(false) })