import React, { useContext, ComponentType, Fragment } from 'react'; import classnames from 'classnames'; import { useDebouncedCallback } from 'use-debounce'; import { Resizable } from 're-resizable'; import Frames from './Frames/Frames'; import WindowPortal from './WindowPortal'; import { Snippets } from '../../utils'; import componentsToHints from '../utils/componentsToHints'; import Toolbar from './Toolbar/Toolbar'; import ChevronIcon from './icons/ChevronIcon'; import { StatusMessage } from './StatusMessage/StatusMessage'; import { StoreContext, EditorPosition } from '../StoreContext/StoreContext'; // @ts-ignore import themeVars from '!!less-vars-loader?resolveVariables!./variables.less'; const getThemeVariable = (name: string) => { const resolvedVar = themeVars[name]; if (!resolvedVar) { throw new Error(`Cannot resolve "${name}" from variables`); } if (!(typeof resolvedVar === 'string' && /(px|[0-9])$/.test(resolvedVar))) { throw new Error( `Invalid characters "${resolvedVar}", must be a number of pixel value` ); } return parseInt(resolvedVar.replace(/px$/, ''), 10); }; const MIN_HEIGHT = getThemeVariable('toolbar-item-size') * getThemeVariable('toolbar-max-item-count'); const MIN_WIDTH = getThemeVariable('toolbar-open-size') + getThemeVariable('toolbar-closed-size') + 80; // @ts-ignore import { CodeEditor } from './CodeEditor/CodeEditor'; // @ts-ignore import styles from './Playroom.less'; const resizableConfig = (position: EditorPosition = 'bottom') => ({ top: position === 'bottom', right: false, bottom: false, left: position === 'right', topRight: false, bottomRight: false, bottomLeft: false, topLeft: false, }); const resolveDirection = ( editorPosition: EditorPosition, editorHidden: boolean ) => { if (editorPosition === 'right') { return editorHidden ? 'left' : 'right'; } return editorHidden ? 'up' : 'down'; }; export interface PlayroomProps { components: Record; themes: string[]; widths: number[]; snippets: Snippets; } export default ({ components, themes, widths, snippets }: PlayroomProps) => { const [ { editorPosition, editorHeight, editorWidth, editorHidden, visibleThemes, visibleWidths, code, previewRenderCode, previewEditorCode, ready, }, dispatch, ] = useContext(StoreContext); const [updateEditorSize] = useDebouncedCallback( ({ isVerticalEditor, offsetWidth, offsetHeight, }: { isVerticalEditor: boolean; offsetHeight: number; offsetWidth: number; }) => { dispatch({ type: isVerticalEditor ? 'updateEditorWidth' : 'updateEditorHeight', payload: { size: isVerticalEditor ? offsetWidth : offsetHeight }, }); }, 1 ); const [resetEditorPosition] = useDebouncedCallback(() => { if (editorPosition === 'undocked') { dispatch({ type: 'resetEditorPosition' }); } }, 1); if (!ready) { return null; } const codeEditor = (
dispatch({ type: 'updateCode', payload: { code: newCode } }) } previewCode={previewEditorCode} hints={componentsToHints(components)} />
); const isVerticalEditor = editorPosition === 'right'; const isHorizontalEditor = editorPosition === 'bottom'; const sizeStyles = { height: isHorizontalEditor ? `${editorHeight}px` : 'auto', // issue in ff & safari when not a string width: isVerticalEditor ? `${editorWidth}px` : 'auto', }; const editorContainer = editorPosition === 'undocked' ? ( {codeEditor} ) : ( { updateEditorSize({ isVerticalEditor, offsetWidth, offsetHeight }); }} enable={resizableConfig(editorPosition)} > {codeEditor} ); return (
0 ? visibleThemes : themes } widths={ visibleWidths && visibleWidths.length > 0 ? visibleWidths : widths } />
{editorContainer}
); };