From 63835c3374fb6db58b1e923763186bedb2cbac9a Mon Sep 17 00:00:00 2001 From: Luv Kapur Date: Thu, 11 Apr 2024 15:28:08 -0400 Subject: [PATCH 1/2] notify parent from iframe when preview is not available --- .bitmap | 21 +++++ .../ui/pages/preview-not-found/image-icon.tsx | 12 +++ .../ui/pages/preview-not-found/index.ts | 2 + .../preview-not-found/preview-not-found.tsx | 32 +++++++ components/ui/pages/static-error/index.ts | 1 + .../ui/pages/static-error/render-page.tsx | 14 +++ .../pages/static-error/static-error-pages.tsx | 56 ++++++++++++ components/ui/rendering/html/dev-tools.tsx | 10 +++ .../ui/rendering/html/full-height-style.tsx | 6 ++ components/ui/rendering/html/html.tsx | 87 +++++++++++++++++++ components/ui/rendering/html/index.ts | 4 + components/ui/rendering/html/mount-point.tsx | 13 +++ components/ui/rendering/html/ssr-styles.tsx | 15 ++++ .../ui/rendering/html/stored-assets.tsx | 30 +++++++ .../preview/ui/component-preview/preview.tsx | 13 +++ workspace.jsonc | 3 - 16 files changed, 316 insertions(+), 3 deletions(-) create mode 100644 components/ui/pages/preview-not-found/image-icon.tsx create mode 100644 components/ui/pages/preview-not-found/index.ts create mode 100644 components/ui/pages/preview-not-found/preview-not-found.tsx create mode 100644 components/ui/pages/static-error/index.ts create mode 100644 components/ui/pages/static-error/render-page.tsx create mode 100644 components/ui/pages/static-error/static-error-pages.tsx create mode 100644 components/ui/rendering/html/dev-tools.tsx create mode 100644 components/ui/rendering/html/full-height-style.tsx create mode 100644 components/ui/rendering/html/html.tsx create mode 100644 components/ui/rendering/html/index.ts create mode 100644 components/ui/rendering/html/mount-point.tsx create mode 100644 components/ui/rendering/html/ssr-styles.tsx create mode 100644 components/ui/rendering/html/stored-assets.tsx diff --git a/.bitmap b/.bitmap index 4a7eb1678855..aca57a9f44d4 100644 --- a/.bitmap +++ b/.bitmap @@ -1766,6 +1766,20 @@ "mainFile": "index.ts", "rootDir": "components/ui/navigation/lane-switcher" }, + "ui/pages/preview-not-found": { + "name": "ui/pages/preview-not-found", + "scope": "teambit.ui-foundation", + "version": "0.0.84", + "mainFile": "index.ts", + "rootDir": "components/ui/pages/preview-not-found" + }, + "ui/pages/static-error": { + "name": "ui/pages/static-error", + "scope": "teambit.ui-foundation", + "version": "0.0.92", + "mainFile": "index.ts", + "rootDir": "components/ui/pages/static-error" + }, "ui/preview-placeholder": { "name": "ui/preview-placeholder", "scope": "teambit.preview", @@ -1787,6 +1801,13 @@ "mainFile": "index.ts", "rootDir": "components/ui/react-router/slot-router" }, + "ui/rendering/html": { + "name": "ui/rendering/html", + "scope": "teambit.ui-foundation", + "version": "0.0.85", + "mainFile": "index.ts", + "rootDir": "components/ui/rendering/html" + }, "ui/test-compare": { "name": "ui/test-compare", "scope": "teambit.defender", diff --git a/components/ui/pages/preview-not-found/image-icon.tsx b/components/ui/pages/preview-not-found/image-icon.tsx new file mode 100644 index 000000000000..5b03871187d1 --- /dev/null +++ b/components/ui/pages/preview-not-found/image-icon.tsx @@ -0,0 +1,12 @@ +import React, { SVGProps } from 'react'; + +export function ImageIcon(props: SVGProps) { + return ( + + + + ); +} diff --git a/components/ui/pages/preview-not-found/index.ts b/components/ui/pages/preview-not-found/index.ts new file mode 100644 index 000000000000..81af1d5daa91 --- /dev/null +++ b/components/ui/pages/preview-not-found/index.ts @@ -0,0 +1,2 @@ +export { PreviewNotFoundPage } from './preview-not-found'; +export type { PreviewNotFoundPageProps } from './preview-not-found'; diff --git a/components/ui/pages/preview-not-found/preview-not-found.tsx b/components/ui/pages/preview-not-found/preview-not-found.tsx new file mode 100644 index 000000000000..27cd5d5c1852 --- /dev/null +++ b/components/ui/pages/preview-not-found/preview-not-found.tsx @@ -0,0 +1,32 @@ +import React, { CSSProperties } from 'react'; +import { ImageIcon } from './image-icon'; + +const styles: Record = { + container: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + + height: '100%', + }, + image: { + width: '2.6em', + marginBottom: '1em', + }, + message: { + fontSize: '1em', + textAlign: 'center', + }, +}; + +export type PreviewNotFoundPageProps = React.HTMLAttributes; + +export function PreviewNotFoundPage(props: PreviewNotFoundPageProps) { + return ( +
+ +
No preview available
+
+ ); +} diff --git a/components/ui/pages/static-error/index.ts b/components/ui/pages/static-error/index.ts new file mode 100644 index 000000000000..67cc00eb2406 --- /dev/null +++ b/components/ui/pages/static-error/index.ts @@ -0,0 +1 @@ +export { noPreview, notFound, serverError } from './static-error-pages'; diff --git a/components/ui/pages/static-error/render-page.tsx b/components/ui/pages/static-error/render-page.tsx new file mode 100644 index 000000000000..5ec12d6b2f15 --- /dev/null +++ b/components/ui/pages/static-error/render-page.tsx @@ -0,0 +1,14 @@ +import React, { ReactNode } from 'react'; +import { renderToStaticMarkup } from 'react-dom/server'; +import { Html, Assets } from '@teambit/ui-foundation.ui.rendering.html'; + +export function fullPageToStaticString(content: ReactNode, assets?: Assets) { + const html = ( + + {content} + + ); + const stringified = renderToStaticMarkup(html); + + return stringified; +} diff --git a/components/ui/pages/static-error/static-error-pages.tsx b/components/ui/pages/static-error/static-error-pages.tsx new file mode 100644 index 000000000000..7be830065063 --- /dev/null +++ b/components/ui/pages/static-error/static-error-pages.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { staticBookFontClass, staticBookFontUrl } from '@teambit/base-ui.theme.fonts.book'; +import { NotFoundPage } from '@teambit/design.ui.pages.not-found'; +import { ServerErrorPage } from '@teambit/design.ui.pages.server-error'; +import { PreviewNotFoundPage } from '@teambit/ui-foundation.ui.pages.preview-not-found'; + +import { fullPageToStaticString } from './render-page'; + +const center = ` + body { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + + font-family: sans-serif; + } +`; + +const sizing = ` + body { + font-size: 18px; + color: #878c9a; + width: 100% !important; + height: 500px; + } + + @media screen and (max-width: 250px) { + body { + font-size: 14px; + color: #c7c7c7; + } + } +`; + +const assets = { + style: [center], + css: [staticBookFontUrl], +}; + +const noPreviewAssets = { + style: [center, sizing], + css: [staticBookFontUrl], +}; + +export function notFound(): string { + return fullPageToStaticString(, assets); +} + +export function serverError(): string { + return fullPageToStaticString(, assets); +} + +export function noPreview(): string { + return fullPageToStaticString(, noPreviewAssets); +} diff --git a/components/ui/rendering/html/dev-tools.tsx b/components/ui/rendering/html/dev-tools.tsx new file mode 100644 index 000000000000..1fbf0020817a --- /dev/null +++ b/components/ui/rendering/html/dev-tools.tsx @@ -0,0 +1,10 @@ +import React from 'react'; + +export function CrossIframeDevTools() { + return ( + + ); +} diff --git a/components/ui/rendering/html/full-height-style.tsx b/components/ui/rendering/html/full-height-style.tsx new file mode 100644 index 000000000000..09b207617d8d --- /dev/null +++ b/components/ui/rendering/html/full-height-style.tsx @@ -0,0 +1,6 @@ +import React from 'react'; + +export function FullHeightStyle() { + // return ; + return ; +} diff --git a/components/ui/rendering/html/html.tsx b/components/ui/rendering/html/html.tsx new file mode 100644 index 000000000000..803e4c50443b --- /dev/null +++ b/components/ui/rendering/html/html.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { CrossIframeDevTools } from './dev-tools'; +import { MountPoint, fillMountPoint } from './mount-point'; +import { popAssets, StoredAssets } from './stored-assets'; +import { SsrStyles, removeSsrStyles } from './ssr-styles'; +import { FullHeightStyle } from './full-height-style'; + +export type Assets = Partial<{ + /** page title */ + title: string; + /** js files to load */ + js: string[]; + /** css files to load */ + css: string[]; + /** raw css styles */ + style: string[]; + /** raw data to be stored in the dom. Use Html.popAssets to retrieve it from the dom */ + json: Record; +}>; + +export interface HtmlProps extends React.HtmlHTMLAttributes { + withDevTools?: boolean; + fullHeight?: boolean; + assets?: Assets; + ssr?: boolean; +} + +const NotifyParentScript = () => ( + +); + +/** html template for the main UI, when ssr is active */ +export function Html({ + assets = {}, + withDevTools = false, + fullHeight, + ssr, + children = , + ...rest +}: HtmlProps) { + return ( + + + {assets.title || 'bit scope'} + + + + {ssr && } + {fullHeight && } + {withDevTools && } + + {assets.style?.map((x, idx) => ( + + ))} + {assets.css?.map((x, idx) => ( + + ))} + + + + {children} + {assets.json && } + {/* load scripts after showing the the whole html */} + {assets.js?.map((x, idx) => ( + @@ -46,6 +50,7 @@ export function Html({ fullHeight, ssr, children = , + notifyParentOnLoad = true, ...rest }: HtmlProps) { return ( @@ -65,7 +70,7 @@ export function Html({ {assets.css?.map((x, idx) => ( ))} - + {notifyParentOnLoad && } {children} diff --git a/components/ui/rendering/html/index.ts b/components/ui/rendering/html/index.ts index 1dcee848baee..d189bfa8f6b2 100644 --- a/components/ui/rendering/html/index.ts +++ b/components/ui/rendering/html/index.ts @@ -1,4 +1,4 @@ -export { Html, ssrCleanup } from './html'; +export { Html, ssrCleanup, LOAD_EVENT } from './html'; export { MountPoint, mountPointId } from './mount-point'; export { popAssets } from './stored-assets'; export type { HtmlProps, Assets } from './html'; diff --git a/scopes/preview/ui/component-preview/preview.tsx b/scopes/preview/ui/component-preview/preview.tsx index 9e5ac4c9e652..5f8dea584d5b 100644 --- a/scopes/preview/ui/component-preview/preview.tsx +++ b/scopes/preview/ui/component-preview/preview.tsx @@ -4,6 +4,7 @@ import { compact } from 'lodash'; import { connectToChild } from 'penpal'; import { usePubSubIframe } from '@teambit/pubsub'; import { ComponentModel } from '@teambit/component'; +import { LOAD_EVENT } from '@teambit/ui-foundation.ui.rendering.html'; import { toPreviewUrl } from './urls'; import { computePreviewScale } from './compute-preview-scale'; import { useIframeContentHeight } from './use-iframe-content-height'; @@ -111,7 +112,7 @@ export function ComponentPreview({ useEffect(() => { const handleLoad = (event) => { - if (event.data && event.data.event === 'loaded') { + if (event.data && event.data.event === LOAD_EVENT) { onLoad && onLoad(event); } };