Merge pull request #434 from webzard-io/feat/iframe

feat: add the iframe component
This commit is contained in:
tanbowensg 2022-06-08 14:19:13 +08:00 committed by GitHub
commit 00c5f345da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 143 additions and 2 deletions

View File

@ -1,4 +1,4 @@
import React, { useMemo, useRef, useState } from 'react';
import React, { useMemo, useRef, useState, useEffect, useCallback } from 'react';
import { EditorServices } from '../../types';
import { observer } from 'mobx-react-lite';
import { Box } from '@chakra-ui/react';
@ -66,6 +66,26 @@ export const EditorMaskWrapper: React.FC<Props> = observer(props => {
);
};
const onClickIframe = useCallback(() => {
if (document.activeElement?.tagName === 'IFRAME') {
setSelectedComponentId(document.activeElement?.getAttribute('title') || '');
setTimeout(() => {
window.focus();
});
}
}, [setSelectedComponentId]);
// can't capture the iframe click event
// use window's blur event to detect whether clicking the iframes
useEffect(() => {
window.focus();
window.addEventListener('blur', onClickIframe);
return () => {
window.removeEventListener('blur', onClickIframe);
};
}, [onClickIframe]);
const mousePositionWithOffset: [number, number] = [
mousePosition[0] + scrollOffset[0],
mousePosition[1] + scrollOffset[1],

View File

@ -0,0 +1,118 @@
import { implementRuntimeComponent } from '../../utils/buildKit';
import { Type } from '@sinclair/typebox';
import { CORE_VERSION, CoreComponentName, StringUnion } from '@sunmao-ui/shared';
import { css } from '@emotion/css';
import { useEffect } from 'react';
export default implementRuntimeComponent({
version: CORE_VERSION,
metadata: {
name: CoreComponentName.Iframe,
displayName: 'Iframe',
description: '',
isDraggable: false,
isResizable: false,
exampleProperties: {
src: 'https://www.openstreetmap.org/export/embed.html?bbox=-0.004017949104309083%2C51.47612752641776%2C0.00030577182769775396%2C51.478569861898606&layer=mapnik',
referrerpolicy: 'unset',
sandbox: 'unset',
fetchpriority: 'auto',
},
exampleSize: [1, 1],
annotations: {
category: 'Advance',
},
},
spec: {
properties: Type.Object({
src: Type.String({ title: 'Src' }),
referrerpolicy: StringUnion(
[
'unset',
'no-referrer',
'no-referrer-when-downgrade',
'origin',
'origin-when-cross-origin',
'same-origin',
'strict-origin',
'strict-origin-when-cross-origin',
'unsafe-url',
],
{
title: 'Referrer Policy',
description:
"Indicates which referrer to send when fetching the frame's resource.",
}
),
sandbox: StringUnion(
[
'unset',
'allow-forms',
'allow-modals',
'allow-orientation-lock',
'allow-pointer-lock',
'allow-popups',
'allow-popups-to-escape-sandbox',
'allow-presentation',
'allow-same-origin',
'allow-scripts',
'allow-top-navigation',
'allow-top-navigation-by-user-activation',
],
{
title: 'Sandbox',
description: 'Applies extra restrictions to the content in the frame.',
}
),
fetchpriority: StringUnion(['auto', 'low', 'high'], {
title: 'Fetch Priority',
description:
'Provides a hint of the relative priority to use when fetching the iframe document',
}),
}),
state: Type.Object({}),
methods: {
requestFullscreen: Type.Object({}),
},
slots: {},
styleSlots: ['content'],
events: [],
},
})(
({
component,
src,
referrerpolicy,
sandbox,
fetchpriority,
elementRef,
customStyle,
subscribeMethods,
}) => {
const iframeProps: Record<string, unknown> = {
title: component.id,
src,
fetchpriority,
};
if (referrerpolicy !== 'unset') {
iframeProps.referrerpolicy = referrerpolicy;
}
if (sandbox !== 'unset') {
iframeProps.sandbox = sandbox;
}
useEffect(() => {
subscribeMethods({
requestFullscreen() {
elementRef?.current.requestFullscreen();
},
});
}, [elementRef, subscribeMethods]);
return (
<iframe ref={elementRef} {...iframeProps} className={css(customStyle?.content)} />
);
}
);

View File

@ -8,6 +8,7 @@ import CoreDummy from '../components/core/Dummy';
import CoreModuleContainer from '../components/core/ModuleContainer';
import CoreStack from '../components/core/Stack';
import CoreFileInput from '../components/core/FileInput';
import CoreIframe from '../components/core/Iframe';
// traits
import CoreArrayState from '../traits/core/ArrayState';
@ -242,6 +243,7 @@ export function initRegistry(
registry.registerComponent(CoreModuleContainer);
registry.registerComponent(CoreStack);
registry.registerComponent(CoreFileInput);
registry.registerComponent(CoreIframe);
registry.registerTrait(CoreState);
registry.registerTrait(CoreArrayState);

View File

@ -28,7 +28,7 @@ export type ComponentImplProps<
> = ImplWrapperProps &
TraitResult<KStyleSlot, KEvent>['props'] &
RuntimeFunctions<TState, TMethods, TSlots> & {
elementRef?: React.Ref<any>;
elementRef?: React.MutableRefObject<any>;
getElement?: (ele: HTMLElement) => void;
};

View File

@ -6,6 +6,7 @@ export enum CoreComponentName {
ModuleContainer = 'moduleContainer',
GridLayout = 'grid_layout',
Text = 'text',
Iframe = 'iframe',
}
// core traits
export enum CoreTraitName {