Skip to content

Commit

Permalink
[core] Make inline canvas the default (#3370)
Browse files Browse the repository at this point in the history
  • Loading branch information
Janpot authored Apr 9, 2024
1 parent 97b5eab commit 79e83ff
Show file tree
Hide file tree
Showing 22 changed files with 226 additions and 889 deletions.
2 changes: 1 addition & 1 deletion packages/toolpad-studio/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ interface EditorOptions {
}

async function editorCommand({ dev: toolpadDevMode, ...args }: EditorOptions) {
await runEditor(args.url, { toolpadDevMode, ...args });
await runEditor(args.url);
}

interface BuildOptions {
Expand Down
1 change: 0 additions & 1 deletion packages/toolpad-studio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"lint": "prettier --check .",
"fix": "prettier --write .",
"build:cli": "tsup",
"build:editor": "vite build ./src/toolpad",
"build:typings": "tsx ./scripts/typings.mts",
"dev:cli": "tsup --watch",
"dev:typings": "pnpm build:typings",
Expand Down
15 changes: 0 additions & 15 deletions packages/toolpad-studio/src/canvas/ToolpadBridge.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import { Emitter } from '@toolpad/utils/events';
import type { RuntimeEvents } from '@toolpad/studio-runtime';
import { TOOLPAD_BRIDGE_GLOBAL } from '../constants';
import type { AppCanvasState, PageViewState } from '../types';

declare global {
interface Window {
[TOOLPAD_BRIDGE_GLOBAL]?: ToolpadBridge | ((bridge: ToolpadBridge) => void);
}
}

const COMMAND_HANDLERS = Symbol('hidden property to hold the command handlers');

type Commands<T extends Record<string, Function>> = T & {
Expand Down Expand Up @@ -98,12 +91,4 @@ bridge?.canvasEvents.on('ready', () => {
canvasIsReady = true;
});

if (bridge) {
if (typeof window[TOOLPAD_BRIDGE_GLOBAL] === 'function') {
window[TOOLPAD_BRIDGE_GLOBAL](bridge);
}

window[TOOLPAD_BRIDGE_GLOBAL] = bridge;
}

export { bridge };
3 changes: 0 additions & 3 deletions packages/toolpad-studio/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export const WINDOW_PROP_TOOLPAD_APP_RENDER_PARAMS = '__TOOLPAD_APP_RENDER_PARAMS__';
export const RUNTIME_CONFIG_WINDOW_PROPERTY = '__TOOLPAD_RUNTIME_CONFIG__';
export const APP_URL_WINDOW_PROPERTY = '__TOOLPAD_APP_URL__';
export const INITIAL_STATE_WINDOW_PROPERTY = '__initialToolpadState__';

export const TOOLPAD_TARGET_CE = 'CE';
Expand All @@ -15,8 +14,6 @@ export const ROADMAP_URL = 'https://github.com/orgs/mui/projects/9';
export const SCHEDULE_DEMO_URL = 'https://calendly.com/prakhar-mui/toolpad';
export const UPGRADE_URL = 'https://mui.com/toolpad/studio/getting-started/roadmap/#paid-plan';

export const TOOLPAD_BRIDGE_GLOBAL = '__TOOLPAD_BRIDGE__';

export const VERSION_CHECK_INTERVAL = 1000 * 60 * 10;

// TODO: Remove once global functions UI is ready
Expand Down
187 changes: 8 additions & 179 deletions packages/toolpad-studio/src/runtime/PreviewHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,111 +1,11 @@
import * as React from 'react';
import {
Button,
Typography,
Box,
useTheme,
Alert,
ButtonProps,
Popover,
styled,
IconButton,
Tooltip,
Snackbar,
IconButtonProps,
popoverClasses,
} from '@mui/material';
import { Button, Typography, Box, useTheme, Alert, ButtonProps } from '@mui/material';
import EditIcon from '@mui/icons-material/Edit';
import { Link, useMatch } from 'react-router-dom';
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
import { useNonNullableContext } from '@toolpad/utils/react';
import { PREVIEW_HEADER_HEIGHT } from './constants';
import { AppHostContext } from './AppHostContext';

interface CopyToClipboardButtonProps extends IconButtonProps {
content: string;
}

function CopyToClipboardButton({ content, onClick, ...props }: CopyToClipboardButtonProps) {
const [confirmSnackbarOpen, setConfirmSnackbarOpen] = React.useState(false);

const handleClick = React.useCallback(
(event: React.MouseEvent<HTMLButtonElement>) => {
window.navigator.clipboard.writeText(content);
setConfirmSnackbarOpen(true);
onClick?.(event);
},
[content, onClick],
);

const handleCopySnackbarClose = React.useCallback(() => setConfirmSnackbarOpen(false), []);

return (
<React.Fragment>
<Tooltip title="Copy to clipboard">
<IconButton {...props} onClick={handleClick}>
<ContentCopyIcon fontSize="inherit" />
</IconButton>
</Tooltip>

<Snackbar
open={confirmSnackbarOpen}
autoHideDuration={3000}
onClose={handleCopySnackbarClose}
message="Copied to clipboard"
/>
</React.Fragment>
);
}

interface CodeViewProps {
children?: string;
}

const classes = {
copyToClipboardButton: 'Toolpad_CodeView_CopyToClipboardButton',
hasCopyToClipboardButton: 'Toolpad_CodeView_hasCopyToClipboardButton',
};

const CodeViewRoot = styled('pre')(({ theme }) => ({
position: 'relative',
border: `1px solid ${theme.palette.divider}`,
padding: theme.spacing(2),
paddingRight: theme.spacing(5),
borderRadius: theme.shape.borderRadius,

fontFamily: theme.fontFamilyMonospaced,

overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',

[`& .${classes.copyToClipboardButton}`]: {
position: 'absolute',
top: 0,
right: 0,
marginTop: theme.spacing(1),
marginRight: theme.spacing(1),
},
}));

function CodeView({ children }: CodeViewProps) {
return (
<CodeViewRoot>
<Typography noWrap component="code" fontFamily="inherit">
{children}
</Typography>

{children ? (
<CopyToClipboardButton
size="small"
content={children}
className={classes.copyToClipboardButton}
/>
) : null}
</CodeViewRoot>
);
}

function OpenInEditorButton<C extends React.ElementType>({
children = 'Open in editor',
...props
Expand All @@ -117,67 +17,7 @@ function OpenInEditorButton<C extends React.ElementType>({
);
}

interface CustomServerInstructionsProps {
basename: string;
}

function CustomServerInstructions({ basename }: CustomServerInstructionsProps) {
const id = React.useId();
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null);

const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};

const handleClose = () => {
setAnchorEl(null);
};

const open = Boolean(anchorEl);

const appUrl = React.useMemo(() => {
return new URL(basename, window.location.origin).href;
}, [basename]);

return (
<React.Fragment>
<OpenInEditorButton aria-describedby={id} onClick={handleClick} />
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'right',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
sx={{
[`& .${popoverClasses.paper}`]: {
maxWidth: 700,
},
}}
>
<Box sx={{ p: 2 }}>
<Typography>
This application is running under a custom server. Run the standalone Toolpad Studio
editor to make changes to this application.
</Typography>
<CodeView>{`npx @toolpad/studio editor ${appUrl}`}</CodeView>
</Box>
</Popover>
</React.Fragment>
);
}

export interface PreviewHeaderProps {
basename: string;
}

export default function PreviewHeader({ basename }: PreviewHeaderProps) {
export default function PreviewHeader() {
const pageMatch = useMatch('/pages/:slug');
const activePage = pageMatch?.params.slug;

Expand All @@ -187,23 +27,12 @@ export default function PreviewHeader({ basename }: PreviewHeaderProps) {

let action: React.ReactNode = null;

if (process.env.EXPERIMENTAL_INLINE_CANVAS) {
action = (
<OpenInEditorButton
component={Link}
to={activePage ? `/editor/app/pages/${activePage}` : '/editor/app'}
/>
);
} else if (appContext) {
action = appContext.isCustomServer ? (
<CustomServerInstructions basename={basename} />
) : (
<OpenInEditorButton
component="a"
href={activePage ? `/_toolpad/app/pages/${activePage}` : '/_toolpad/app'}
/>
);
}
action = (
<OpenInEditorButton
component={Link}
to={activePage ? `/editor/app/pages/${activePage}` : '/editor/app'}
/>
);

return appContext ? (
<Box
Expand Down
6 changes: 3 additions & 3 deletions packages/toolpad-studio/src/runtime/ToolpadApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ import evalJsBindings, {
EvaluatedBinding,
ParsedBinding,
} from './evalJsBindings';
import { HTML_ID_EDITOR_OVERLAY, PREVIEW_HEADER_HEIGHT } from './constants';
import { PREVIEW_HEADER_HEIGHT } from './constants';
import { layoutBoxArgTypes } from './toolpadComponents/layoutBox';
import { useDataQuery, UseFetch } from './useDataQuery';
import { CanvasHooksContext, NavigateToPage } from './CanvasHooksContext';
Expand Down Expand Up @@ -1676,7 +1676,7 @@ export function ToolpadAppProvider({
<ResetNodeErrorsKeyProvider value={resetNodeErrorsKey}>
<AppThemeProvider dom={dom}>
<CssBaseline enableColorScheme />
{showPreviewHeader ? <PreviewHeader basename={basename} /> : null}
{showPreviewHeader ? <PreviewHeader /> : null}
<AppRoot
ref={rootRef}
sx={{
Expand All @@ -1686,7 +1686,7 @@ export function ToolpadAppProvider({
<ErrorBoundary FallbackComponent={AppError}>
<React.Suspense fallback={<AppLoading />}>{children}</React.Suspense>
</ErrorBoundary>
<EditorOverlay ref={canvasHooks.overlayRef} id={HTML_ID_EDITOR_OVERLAY} />
<EditorOverlay ref={canvasHooks.overlayRef} />
</AppRoot>
</AppThemeProvider>
</ResetNodeErrorsKeyProvider>
Expand Down
1 change: 0 additions & 1 deletion packages/toolpad-studio/src/runtime/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export const HTML_ID_EDITOR_OVERLAY = 'editor-overlay';
export const PREVIEW_HEADER_HEIGHT = 52;
6 changes: 2 additions & 4 deletions packages/toolpad-studio/src/server/appServerWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import invariant from 'invariant';
import type { Plugin } from 'vite';
import { createRpcClient } from '@toolpad/utils/workerRpc';
import type * as appDom from '@toolpad/studio-runtime/appDom';
import { createViteConfig, getAppHtmlContent, getEditorHtmlContent } from './toolpadAppBuilder';
import { createViteConfig, getEditorHtmlContent } from './toolpadAppBuilder';
import type { RuntimeConfig } from '../types';
import type { ComponentEntry, PagesManifest } from './localMode';
import createRuntimeState from '../runtime/createRuntimeState';
Expand Down Expand Up @@ -46,9 +46,7 @@ function devServerPlugin({ config }: ToolpadAppDevServerParams): Plugin {
try {
const dom = await loadDom();

const template = process.env.EXPERIMENTAL_INLINE_CANVAS
? getEditorHtmlContent()
: getAppHtmlContent();
const template = getEditorHtmlContent();

let html = await viteServer.transformIndexHtml(req.url, template);

Expand Down
Loading

0 comments on commit 79e83ff

Please sign in to comment.