From 07de97586496683dd1a2efeeec29f67e26e0beaa Mon Sep 17 00:00:00 2001 From: cohitre Date: Mon, 4 Mar 2024 07:28:09 -0800 Subject: [PATCH] Consuming @usewaypoint/email-builder --- packages/editor-sample/package-lock.json | 23 ++++ packages/editor-sample/package.json | 1 + .../input-panels/ContainerSidebarPanel.tsx | 2 +- .../input-panels/EmailLayoutSidebarPanel.tsx | 17 ++- .../src/App/TemplatePanel/HtmlPanel.tsx | 27 ++-- .../src/App/TemplatePanel/index.tsx | 7 +- .../ColumnsContainerEditor.tsx | 49 +++++++ .../blocks/ColumnsContainer/index.tsx | 84 ------------ .../blocks/Container/ContainerEditor.tsx | 37 ++++++ .../blocks/Container/ContainerPropsSchema.tsx | 4 +- .../src/documents/blocks/Container/index.tsx | 57 --------- .../blocks/EmailLayout/EmailLayoutEditor.tsx | 96 ++++++++++++++ .../EmailLayout/EmailLayoutPropsSchema.tsx | 39 ++++-- .../documents/blocks/EmailLayout/index.tsx | 121 ------------------ .../helpers/EditorChildrenIds/index.tsx | 42 +++++- .../src/documents/editor/core.tsx | 20 ++- .../src/documents/reader/ReaderBlock.tsx | 21 --- .../src/documents/reader/ReaderContext.tsx | 17 --- .../src/documents/reader/core.tsx | 78 ----------- 19 files changed, 311 insertions(+), 431 deletions(-) create mode 100644 packages/editor-sample/src/documents/blocks/ColumnsContainer/ColumnsContainerEditor.tsx delete mode 100644 packages/editor-sample/src/documents/blocks/ColumnsContainer/index.tsx create mode 100644 packages/editor-sample/src/documents/blocks/Container/ContainerEditor.tsx delete mode 100644 packages/editor-sample/src/documents/blocks/Container/index.tsx create mode 100644 packages/editor-sample/src/documents/blocks/EmailLayout/EmailLayoutEditor.tsx delete mode 100644 packages/editor-sample/src/documents/blocks/EmailLayout/index.tsx delete mode 100644 packages/editor-sample/src/documents/reader/ReaderBlock.tsx delete mode 100644 packages/editor-sample/src/documents/reader/ReaderContext.tsx delete mode 100644 packages/editor-sample/src/documents/reader/core.tsx diff --git a/packages/editor-sample/package-lock.json b/packages/editor-sample/package-lock.json index 91a82ab..0b3111d 100644 --- a/packages/editor-sample/package-lock.json +++ b/packages/editor-sample/package-lock.json @@ -23,6 +23,7 @@ "@usewaypoint/block-spacer": "^0.0.2", "@usewaypoint/block-text": "^0.0.2", "@usewaypoint/document-core": "^0.0.4", + "@usewaypoint/email-builder": "^0.0.2", "codemirror": "^6.0.1", "highlight.js": "^11.9.0", "js-beautify": "^1.15.1", @@ -2110,6 +2111,28 @@ "zod": "^1 || ^2 || ^3" } }, + "node_modules/@usewaypoint/email-builder": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@usewaypoint/email-builder/-/email-builder-0.0.2.tgz", + "integrity": "sha512-d15dlfVsGzyNTuaqp72NYWjHTVRmlwqiDm9TnxeryBTbSptED1Pf+kLGKDepFR/cK7qTZREvF0m6f3RxhdD0AA==", + "dependencies": { + "@usewaypoint/block-avatar": "^0.0.1", + "@usewaypoint/block-button": "^0.0.2", + "@usewaypoint/block-columns-container": "^0.0.2", + "@usewaypoint/block-container": "^0.0.1", + "@usewaypoint/block-divider": "^0.0.3", + "@usewaypoint/block-heading": "^0.0.2", + "@usewaypoint/block-html": "^0.0.2", + "@usewaypoint/block-image": "^0.0.4", + "@usewaypoint/block-spacer": "^0.0.2", + "@usewaypoint/block-text": "^0.0.2", + "@usewaypoint/document-core": "^0.0.4" + }, + "peerDependencies": { + "react": "^16 || ^17 || ^18", + "zod": "^1 || ^2 || ^3" + } + }, "node_modules/@vitejs/plugin-react-swc": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.6.0.tgz", diff --git a/packages/editor-sample/package.json b/packages/editor-sample/package.json index a6b64b8..88c4f51 100644 --- a/packages/editor-sample/package.json +++ b/packages/editor-sample/package.json @@ -23,6 +23,7 @@ "@usewaypoint/block-spacer": "^0.0.2", "@usewaypoint/block-text": "^0.0.2", "@usewaypoint/document-core": "^0.0.4", + "@usewaypoint/email-builder": "^0.0.2", "codemirror": "^6.0.1", "highlight.js": "^11.9.0", "js-beautify": "^1.15.1", diff --git a/packages/editor-sample/src/App/InspectorDrawer/ConfigurationPanel/input-panels/ContainerSidebarPanel.tsx b/packages/editor-sample/src/App/InspectorDrawer/ConfigurationPanel/input-panels/ContainerSidebarPanel.tsx index b33c0a8..c947545 100644 --- a/packages/editor-sample/src/App/InspectorDrawer/ConfigurationPanel/input-panels/ContainerSidebarPanel.tsx +++ b/packages/editor-sample/src/App/InspectorDrawer/ConfigurationPanel/input-panels/ContainerSidebarPanel.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; -import { ContainerProps, ContainerPropsSchema } from '../../../../documents/blocks/Container/ContainerPropsSchema'; +import ContainerPropsSchema, { ContainerProps } from '../../../../documents/blocks/Container/ContainerPropsSchema'; import BaseSidebarPanel from './helpers/BaseSidebarPanel'; import MultiStylePropertyPanel from './helpers/style-inputs/MultiStylePropertyPanel'; diff --git a/packages/editor-sample/src/App/InspectorDrawer/ConfigurationPanel/input-panels/EmailLayoutSidebarPanel.tsx b/packages/editor-sample/src/App/InspectorDrawer/ConfigurationPanel/input-panels/EmailLayoutSidebarPanel.tsx index bf56e90..d915ff8 100644 --- a/packages/editor-sample/src/App/InspectorDrawer/ConfigurationPanel/input-panels/EmailLayoutSidebarPanel.tsx +++ b/packages/editor-sample/src/App/InspectorDrawer/ConfigurationPanel/input-panels/EmailLayoutSidebarPanel.tsx @@ -1,18 +1,17 @@ import React, { useState } from 'react'; -import { z } from 'zod'; import { Divider } from '@mui/material'; -import { EmailLayoutPropsSchema } from '../../../../documents/blocks/EmailLayout/EmailLayoutPropsSchema'; +import EmailLayoutPropsSchema, { + EmailLayoutProps, +} from '../../../../documents/blocks/EmailLayout/EmailLayoutPropsSchema'; import BaseSidebarPanel from './helpers/BaseSidebarPanel'; import ColorInput from './helpers/inputs/ColorInput'; -type EmailLayoutSidebarPanelProps = z.infer; - type EmailLayoutSidebarFieldsProps = { - data: EmailLayoutSidebarPanelProps; - setData: (v: EmailLayoutSidebarPanelProps) => void; + data: EmailLayoutProps; + setData: (v: EmailLayoutProps) => void; }; export default function EmailLayoutSidebarFields({ data, setData }: EmailLayoutSidebarFieldsProps) { const [, setErrors] = useState(null); @@ -31,18 +30,18 @@ export default function EmailLayoutSidebarFields({ data, setData }: EmailLayoutS updateData({ ...data, backdropColor })} /> updateData({ ...data, canvasColor })} /> updateData({ ...data, textColor })} /> diff --git a/packages/editor-sample/src/App/TemplatePanel/HtmlPanel.tsx b/packages/editor-sample/src/App/TemplatePanel/HtmlPanel.tsx index eba2c2e..6c38048 100644 --- a/packages/editor-sample/src/App/TemplatePanel/HtmlPanel.tsx +++ b/packages/editor-sample/src/App/TemplatePanel/HtmlPanel.tsx @@ -1,25 +1,26 @@ -import * as React from 'react'; +import React, { useMemo } from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; +import Reader from '@usewaypoint/email-builder/dist/Reader/core'; + import { useDocument } from '../../documents/editor/EditorContext'; -import ReaderBlock from '../../documents/reader/ReaderBlock'; -import { ReaderProvider } from '../../documents/reader/ReaderContext'; import TextEditorPanel from './helper/TextEditorPanel'; export default function HtmlPanel() { const document = useDocument(); - const string = React.useMemo(() => { - return renderToStaticMarkup( - - - - - - - - + const string = useMemo(() => { + return ( + '' + + renderToStaticMarkup( + + + + + + + ) ); }, [document]); diff --git a/packages/editor-sample/src/App/TemplatePanel/index.tsx b/packages/editor-sample/src/App/TemplatePanel/index.tsx index bf212fb..9c7b0df 100644 --- a/packages/editor-sample/src/App/TemplatePanel/index.tsx +++ b/packages/editor-sample/src/App/TemplatePanel/index.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { MonitorOutlined, PhoneIphoneOutlined } from '@mui/icons-material'; import { Box, Stack, SxProps, ToggleButton, ToggleButtonGroup, Tooltip } from '@mui/material'; +import Reader from '@usewaypoint/email-builder/dist/Reader/core'; import EditorBlock from '../../documents/editor/EditorBlock'; import { @@ -10,8 +11,6 @@ import { useSelectedMainTab, useSelectedScreenSize, } from '../../documents/editor/EditorContext'; -import ReaderBlock from '../../documents/reader/ReaderBlock'; -import { ReaderProvider } from '../../documents/reader/ReaderContext'; import ToggleInspectorPanelButton from '../InspectorDrawer/ToggleInspectorPanelButton'; import ToggleSamplesPanelButton from '../SamplesDrawer/ToggleSamplesPanelButton'; @@ -61,9 +60,7 @@ export default function TemplatePanel() { case 'preview': return ( - - - + ); case 'html': diff --git a/packages/editor-sample/src/documents/blocks/ColumnsContainer/ColumnsContainerEditor.tsx b/packages/editor-sample/src/documents/blocks/ColumnsContainer/ColumnsContainerEditor.tsx new file mode 100644 index 0000000..145cd8a --- /dev/null +++ b/packages/editor-sample/src/documents/blocks/ColumnsContainer/ColumnsContainerEditor.tsx @@ -0,0 +1,49 @@ +import React from 'react'; + +import { ColumnsContainer as BaseColumnsContainer } from '@usewaypoint/block-columns-container'; + +import { useCurrentBlockId } from '../../editor/EditorBlock'; +import { setDocument, setSelectedBlockId } from '../../editor/EditorContext'; +import EditorChildrenIds, { EditorChildrenChange } from '../helpers/EditorChildrenIds'; + +import ColumnsContainerPropsSchema, { ColumnsContainerProps } from './ColumnsContainerPropsSchema'; + +const EMPTY_COLUMNS = [{ childrenIds: [] }, { childrenIds: [] }, { childrenIds: [] }]; + +export default function ColumnsContainerEditor({ style, props }: ColumnsContainerProps) { + const currentBlockId = useCurrentBlockId(); + + const { columns, ...restProps } = props ?? {}; + const columnsValue = columns ?? EMPTY_COLUMNS; + + const updateColumn = (columnIndex: 0 | 1 | 2, { block, blockId, childrenIds }: EditorChildrenChange) => { + const nColumns = [...columnsValue]; + nColumns[columnIndex] = { childrenIds }; + setDocument({ + [blockId]: block, + [currentBlockId]: { + type: 'ColumnsContainer', + data: ColumnsContainerPropsSchema.parse({ + style, + props: { + ...restProps, + columns: nColumns, + }, + }), + }, + }); + setSelectedBlockId(blockId); + }; + + return ( + updateColumn(0, change)} />, + updateColumn(1, change)} />, + updateColumn(2, change)} />, + ]} + /> + ); +} diff --git a/packages/editor-sample/src/documents/blocks/ColumnsContainer/index.tsx b/packages/editor-sample/src/documents/blocks/ColumnsContainer/index.tsx deleted file mode 100644 index 777d596..0000000 --- a/packages/editor-sample/src/documents/blocks/ColumnsContainer/index.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import React from 'react'; - -import { ColumnsContainer as BaseColumnsContainer } from '@usewaypoint/block-columns-container'; - -import { TEditorBlock } from '../../editor/core'; -import { useCurrentBlockId } from '../../editor/EditorBlock'; -import { setDocument, setSelectedBlockId } from '../../editor/EditorContext'; -import ReaderBlock from '../../reader/ReaderBlock'; -import EditorChildrenIds from '../helpers/EditorChildrenIds'; - -import ColumnsContainerPropsSchema, { ColumnsContainerProps } from './ColumnsContainerPropsSchema'; - -export function ColumnsContainer({ style, props }: ColumnsContainerProps) { - const { columns, ...restProps } = props ?? {}; - let cols = undefined; - if (columns) { - cols = columns.map((col) => col.childrenIds.map((childId) => )); - } - - return ; -} - -const EMPTY_COLUMNS = [{ childrenIds: [] }, { childrenIds: [] }, { childrenIds: [] }]; - -export function EditorColumnsContainer({ style, props }: ColumnsContainerProps) { - const blockId = useCurrentBlockId(); - - const { columns, ...restProps } = props ?? {}; - const columnsValue = columns ?? EMPTY_COLUMNS; - - const renderColumn = (columnIndex: 0 | 1 | 2) => ( - { - insertBlock(columnIndex, block, index); - }} - /> - ); - - const insertBlock = (columnIndex: 0 | 1 | 2, blockConfiguration: TEditorBlock, i: number | null) => { - const id = `block-${Date.now()}`; - - const getColumns = () => { - const columnsCopy = [...columnsValue]; - if (i === null) { - columnsCopy[columnIndex] = { - childrenIds: [...columnsValue[columnIndex].childrenIds, id], - }; - return columnsCopy; - } - columnsCopy[columnIndex] = { - childrenIds: [ - ...columnsValue[columnIndex].childrenIds.slice(0, i), - id, - ...columnsValue[columnIndex].childrenIds.slice(i), - ], - }; - return columnsCopy; - }; - - setDocument({ - [id]: blockConfiguration, - [blockId]: { - type: 'ColumnsContainer', - data: ColumnsContainerPropsSchema.parse({ - style, - props: { - ...restProps, - columns: getColumns(), - }, - }), - }, - }); - setSelectedBlockId(id); - }; - - return ( - - ); -} diff --git a/packages/editor-sample/src/documents/blocks/Container/ContainerEditor.tsx b/packages/editor-sample/src/documents/blocks/Container/ContainerEditor.tsx new file mode 100644 index 0000000..6e027a9 --- /dev/null +++ b/packages/editor-sample/src/documents/blocks/Container/ContainerEditor.tsx @@ -0,0 +1,37 @@ +import React from 'react'; + +import { Container as BaseContainer } from '@usewaypoint/block-container'; + +import { useCurrentBlockId } from '../../editor/EditorBlock'; +import { setDocument, setSelectedBlockId, useDocument } from '../../editor/EditorContext'; +import EditorChildrenIds from '../helpers/EditorChildrenIds'; + +import { ContainerProps } from './ContainerPropsSchema'; + +export default function ContainerEditor({ style, props }: ContainerProps) { + const childrenIds = props?.childrenIds ?? []; + + const document = useDocument(); + const currentBlockId = useCurrentBlockId(); + + return ( + + { + setDocument({ + [blockId]: block, + [currentBlockId]: { + type: 'Container', + data: { + ...document[currentBlockId].data, + props: { childrenIds: childrenIds }, + }, + }, + }); + setSelectedBlockId(blockId); + }} + /> + + ); +} diff --git a/packages/editor-sample/src/documents/blocks/Container/ContainerPropsSchema.tsx b/packages/editor-sample/src/documents/blocks/Container/ContainerPropsSchema.tsx index 3e353df..a0188f6 100644 --- a/packages/editor-sample/src/documents/blocks/Container/ContainerPropsSchema.tsx +++ b/packages/editor-sample/src/documents/blocks/Container/ContainerPropsSchema.tsx @@ -2,7 +2,7 @@ import { z } from 'zod'; import { ContainerPropsSchema as BaseContainerPropsSchema } from '@usewaypoint/block-container'; -export const ContainerPropsSchema = z.object({ +const ContainerPropsSchema = z.object({ style: BaseContainerPropsSchema.shape.style, props: z .object({ @@ -12,4 +12,6 @@ export const ContainerPropsSchema = z.object({ .nullable(), }); +export default ContainerPropsSchema; + export type ContainerProps = z.infer; diff --git a/packages/editor-sample/src/documents/blocks/Container/index.tsx b/packages/editor-sample/src/documents/blocks/Container/index.tsx deleted file mode 100644 index 0a7dba9..0000000 --- a/packages/editor-sample/src/documents/blocks/Container/index.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react'; - -import { Container as BaseContainer } from '@usewaypoint/block-container'; - -import { TEditorBlock } from '../../editor/core'; -import { useCurrentBlockId } from '../../editor/EditorBlock'; -import { setDocument, setSelectedBlockId, useDocument } from '../../editor/EditorContext'; -import ReaderBlock from '../../reader/ReaderBlock'; -import EditorChildrenIds from '../helpers/EditorChildrenIds'; - -import { ContainerProps } from './ContainerPropsSchema'; - -export function Container({ style, props }: ContainerProps) { - const childrenIds = props?.childrenIds ?? []; - return ( - - {childrenIds.map((childId) => ( - - ))} - - ); -} - -export function EditorContainer({ style, props }: ContainerProps) { - const childrenIds = props?.childrenIds ?? []; - - const document = useDocument(); - const blockId = useCurrentBlockId(); - - const insertBlock = (blockConfiguration: TEditorBlock, i: number | null) => { - const id = `block-${Date.now()}`; - let nChildrenIds: string[]; - if (i === null) { - nChildrenIds = [...childrenIds, id]; - } else { - nChildrenIds = [...childrenIds.slice(0, i), id, ...childrenIds.slice(i)]; - } - - setDocument({ - [id]: blockConfiguration, - [blockId]: { - type: 'Container', - data: { - ...document[blockId].data, - props: { childrenIds: nChildrenIds }, - }, - }, - }); - setSelectedBlockId(id); - }; - - return ( - - - - ); -} diff --git a/packages/editor-sample/src/documents/blocks/EmailLayout/EmailLayoutEditor.tsx b/packages/editor-sample/src/documents/blocks/EmailLayout/EmailLayoutEditor.tsx new file mode 100644 index 0000000..f08b067 --- /dev/null +++ b/packages/editor-sample/src/documents/blocks/EmailLayout/EmailLayoutEditor.tsx @@ -0,0 +1,96 @@ +import React from 'react'; + +import { useCurrentBlockId } from '../../editor/EditorBlock'; +import { setDocument, setSelectedBlockId, useDocument } from '../../editor/EditorContext'; +import EditorChildrenIds from '../helpers/EditorChildrenIds'; + +import { EmailLayoutProps } from './EmailLayoutPropsSchema'; + +function getFontFamily(fontFamily: EmailLayoutProps['fontFamily']) { + const f = fontFamily ?? 'MODERN_SANS'; + switch (f) { + case 'MODERN_SANS': + return '"Helvetica Neue", "Arial Nova", "Nimbus Sans", Arial, sans-serif'; + case 'BOOK_SANS': + return 'Optima, Candara, "Noto Sans", source-sans-pro, sans-serif'; + case 'ORGANIC_SANS': + return 'Seravek, "Gill Sans Nova", Ubuntu, Calibri, "DejaVu Sans", source-sans-pro, sans-serif'; + case 'GEOMETRIC_SANS': + return 'Avenir, "Avenir Next LT Pro", Montserrat, Corbel, "URW Gothic", source-sans-pro, sans-serif'; + case 'HEAVY_SANS': + return 'Bahnschrift, "DIN Alternate", "Franklin Gothic Medium", "Nimbus Sans Narrow", sans-serif-condensed, sans-serif'; + case 'ROUNDED_SANS': + return 'ui-rounded, "Hiragino Maru Gothic ProN", Quicksand, Comfortaa, Manjari, "Arial Rounded MT Bold", Calibri, source-sans-pro, sans-serif'; + case 'MODERN_SERIF': + return 'Charter, "Bitstream Charter", "Sitka Text", Cambria, serif'; + case 'BOOK_SERIF': + return '"Iowan Old Style", "Palatino Linotype", "URW Palladio L", P052, serif'; + case 'MONOSPACE': + return '"Nimbus Mono PS", "Courier New", "Cutive Mono", monospace'; + } +} + +export default function EmailLayoutEditor(props: EmailLayoutProps) { + const childrenIds = props.childrenIds ?? []; + const document = useDocument(); + const currentBlockId = useCurrentBlockId(); + + return ( +
{ + setSelectedBlockId(null); + }} + style={{ + backgroundColor: props.backdropColor ?? '#EEEEEE', + color: props.textColor ?? '#242424', + fontFamily: getFontFamily(props.fontFamily), + fontSize: '16px', + fontWeight: '400', + letterSpacing: '0.15008px', + lineHeight: '1.5', + margin: '0', + padding: '32px 0', + minHeight: '100%', + width: '100%', + height: '100%', + }} + > + + + + + + +
+ { + setDocument({ + [blockId]: block, + [currentBlockId]: { + type: 'Container', + data: { + ...document[currentBlockId].data, + props: { childrenIds: childrenIds }, + }, + }, + }); + setSelectedBlockId(blockId); + }} + /> +
+
+ ); +} diff --git a/packages/editor-sample/src/documents/blocks/EmailLayout/EmailLayoutPropsSchema.tsx b/packages/editor-sample/src/documents/blocks/EmailLayout/EmailLayoutPropsSchema.tsx index d3e7fdf..5eef514 100644 --- a/packages/editor-sample/src/documents/blocks/EmailLayout/EmailLayoutPropsSchema.tsx +++ b/packages/editor-sample/src/documents/blocks/EmailLayout/EmailLayoutPropsSchema.tsx @@ -1,11 +1,34 @@ import { z } from 'zod'; -import { zColor, zFontFamily } from '../helpers/zod'; - -export const EmailLayoutPropsSchema = z.object({ - backdropColor: zColor(), - canvasColor: zColor(), - textColor: zColor(), - fontFamily: zFontFamily().default('MODERN_SANS'), - childrenIds: z.array(z.string()), +const COLOR_SCHEMA = z + .string() + .regex(/^#[0-9a-fA-F]{6}$/) + .nullable() + .optional(); + +const FONT_FAMILY_SCHEMA = z + .enum([ + 'MODERN_SANS', + 'BOOK_SANS', + 'ORGANIC_SANS', + 'GEOMETRIC_SANS', + 'HEAVY_SANS', + 'ROUNDED_SANS', + 'MODERN_SERIF', + 'BOOK_SERIF', + 'MONOSPACE', + ]) + .nullable() + .optional(); + +const EmailLayoutPropsSchema = z.object({ + backdropColor: COLOR_SCHEMA, + canvasColor: COLOR_SCHEMA, + textColor: COLOR_SCHEMA, + fontFamily: FONT_FAMILY_SCHEMA, + childrenIds: z.array(z.string()).optional().nullable(), }); + +export default EmailLayoutPropsSchema; + +export type EmailLayoutProps = z.infer; diff --git a/packages/editor-sample/src/documents/blocks/EmailLayout/index.tsx b/packages/editor-sample/src/documents/blocks/EmailLayout/index.tsx deleted file mode 100644 index 58c8074..0000000 --- a/packages/editor-sample/src/documents/blocks/EmailLayout/index.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import React, { CSSProperties } from 'react'; -import { z } from 'zod'; - -import { TEditorBlock } from '../../editor/core'; -import { useCurrentBlockId } from '../../editor/EditorBlock'; -import { setDocument, setSelectedBlockId, useDocument } from '../../editor/EditorContext'; -import ReaderBlock from '../../reader/ReaderBlock'; -import EditorChildrenIds from '../helpers/EditorChildrenIds'; - -import { EmailLayoutPropsSchema } from './EmailLayoutPropsSchema'; - -// Based on https://modernfontstacks.com/#font-stacks -const FONT_FAMILY_MAPPINGS = { - MODERN_SANS: '"Helvetica Neue", "Arial Nova", "Nimbus Sans", Arial, sans-serif', - BOOK_SANS: 'Optima, Candara, "Noto Sans", source-sans-pro, sans-serif', - ORGANIC_SANS: 'Seravek, "Gill Sans Nova", Ubuntu, Calibri, "DejaVu Sans", source-sans-pro, sans-serif', - GEOMETRIC_SANS: 'Avenir, "Avenir Next LT Pro", Montserrat, Corbel, "URW Gothic", source-sans-pro, sans-serif', - HEAVY_SANS: - 'Bahnschrift, "DIN Alternate", "Franklin Gothic Medium", "Nimbus Sans Narrow", sans-serif-condensed, sans-serif', - ROUNDED_SANS: - 'ui-rounded, "Hiragino Maru Gothic ProN", Quicksand, Comfortaa, Manjari, "Arial Rounded MT Bold", Calibri, source-sans-pro, sans-serif', - MODERN_SERIF: 'Charter, "Bitstream Charter", "Sitka Text", Cambria, serif', - BOOK_SERIF: '"Iowan Old Style", "Palatino Linotype", "URW Palladio L", P052, serif', - MONOSPACE: '"Nimbus Mono PS", "Courier New", "Cutive Mono", monospace', -}; - -export type EmailLayoutProps = z.infer; - -export function EmailLayout(props: EmailLayoutProps) { - return ( - - {props.childrenIds.map((childId) => ( - - ))} - - ); -} - -export function EditorEmailLayout(props: EmailLayoutProps) { - const document = useDocument(); - const blockId = useCurrentBlockId(); - const childrenIds = props.childrenIds; - - const insertBlock = (blockConfiguration: TEditorBlock, i: number | null) => { - const id = `block-${Date.now()}`; - const getChildrenIds = () => { - if (i === null) { - return [...childrenIds, id]; - } - return [...childrenIds.slice(0, i), id, ...childrenIds.slice(i)]; - }; - - setDocument({ - [id]: blockConfiguration, - [blockId]: { - type: 'EmailLayout', - data: { - ...document[blockId].data, - childrenIds: getChildrenIds(), - }, - } as TEditorBlock, - }); - setSelectedBlockId(id); - }; - - return ( -
{ - setSelectedBlockId(null); - }} - > - - - -
- ); -} - -type SharedLayoutProps = EmailLayoutProps & { - children: JSX.Element[] | JSX.Element; -}; -function SharedLayout({ children, fontFamily, backdropColor, textColor, canvasColor }: SharedLayoutProps) { - const backdropStyle: CSSProperties = { - backgroundColor: backdropColor, - color: textColor, - fontFamily: FONT_FAMILY_MAPPINGS[fontFamily], - fontSize: '16px', - fontWeight: '400', - letterSpacing: '0.15008px', - lineHeight: '1.5', - margin: '0', - padding: '32px 0', - minHeight: '100%', - width: '100%', - }; - const canvasStyle: CSSProperties = { - margin: '0 auto', - maxWidth: '600px', - backgroundColor: canvasColor, - }; - return ( -
- - - - - - -
{children}
-
- ); -} diff --git a/packages/editor-sample/src/documents/blocks/helpers/EditorChildrenIds/index.tsx b/packages/editor-sample/src/documents/blocks/helpers/EditorChildrenIds/index.tsx index fbee88c..a07c17d 100644 --- a/packages/editor-sample/src/documents/blocks/helpers/EditorChildrenIds/index.tsx +++ b/packages/editor-sample/src/documents/blocks/helpers/EditorChildrenIds/index.tsx @@ -5,11 +5,45 @@ import EditorBlock from '../../../editor/EditorBlock'; import AddBlockButton from './AddBlockMenu'; -type Props = { +export type EditorChildrenChange = { + blockId: string; + block: TEditorBlock; childrenIds: string[]; - insertBlock: (block: TEditorBlock, index: number | null) => void; }; -export default function EditorChildrenIds({ childrenIds, insertBlock }: Props) { + +function generateId() { + return `block-${Date.now()}`; +} + +export type EditorChildrenIdsProps = { + childrenIds: string[] | null | undefined; + onChange: (val: EditorChildrenChange) => void; +}; +export default function EditorChildrenIds({ childrenIds, onChange }: EditorChildrenIdsProps) { + const appendBlock = (block: TEditorBlock) => { + const blockId = generateId(); + return onChange({ + blockId, + block, + childrenIds: [...(childrenIds || []), blockId], + }); + }; + + const insertBlock = (block: TEditorBlock, index: number) => { + const blockId = generateId(); + const newChildrenIds = [...(childrenIds || [])]; + newChildrenIds.splice(index, 0, blockId); + return onChange({ + blockId, + block, + childrenIds: newChildrenIds, + }); + }; + + if (!childrenIds) { + return ; + } + return ( <> {childrenIds.map((childId, i) => ( @@ -18,7 +52,7 @@ export default function EditorChildrenIds({ childrenIds, insertBlock }: Props) { ))} - insertBlock(block, null)} /> + ); } diff --git a/packages/editor-sample/src/documents/editor/core.tsx b/packages/editor-sample/src/documents/editor/core.tsx index 056119d..4db26f1 100644 --- a/packages/editor-sample/src/documents/editor/core.tsx +++ b/packages/editor-sample/src/documents/editor/core.tsx @@ -15,12 +15,12 @@ import { buildBlockConfigurationSchema, } from '@usewaypoint/document-core'; -import { EditorColumnsContainer } from '../blocks/ColumnsContainer'; +import ColumnsContainerEditor from '../blocks/ColumnsContainer/ColumnsContainerEditor'; import ColumnsContainerPropsSchema from '../blocks/ColumnsContainer/ColumnsContainerPropsSchema'; -import { EditorContainer } from '../blocks/Container'; -import { ContainerPropsSchema } from '../blocks/Container/ContainerPropsSchema'; -import { EditorEmailLayout } from '../blocks/EmailLayout'; -import { EmailLayoutPropsSchema } from '../blocks/EmailLayout/EmailLayoutPropsSchema'; +import ContainerEditor from '../blocks/Container/ContainerEditor'; +import ContainerPropsSchema from '../blocks/Container/ContainerPropsSchema'; +import EmailLayoutEditor from '../blocks/EmailLayout/EmailLayoutEditor'; +import EmailLayoutPropsSchema from '../blocks/EmailLayout/EmailLayoutPropsSchema'; import EditorBlockWrapper from '../blocks/helpers/block-wrappers/EditorBlockWrapper'; const EDITOR_DICTIONARY = buildBlockConfigurationDictionary({ @@ -44,7 +44,7 @@ const EDITOR_DICTIONARY = buildBlockConfigurationDictionary({ schema: ContainerPropsSchema, Component: (props) => ( - + ), }, @@ -52,7 +52,7 @@ const EDITOR_DICTIONARY = buildBlockConfigurationDictionary({ schema: ColumnsContainerPropsSchema, Component: (props) => ( - + ), }, @@ -99,11 +99,7 @@ const EDITOR_DICTIONARY = buildBlockConfigurationDictionary({ }, EmailLayout: { schema: EmailLayoutPropsSchema, - Component: (p) => ( -
- -
- ), + Component: (p) => , }, Spacer: { schema: SpacerPropsSchema, diff --git a/packages/editor-sample/src/documents/reader/ReaderBlock.tsx b/packages/editor-sample/src/documents/reader/ReaderBlock.tsx deleted file mode 100644 index 494518a..0000000 --- a/packages/editor-sample/src/documents/reader/ReaderBlock.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; - -import { ReaderBlock as CoreReaderBlock } from './core'; -import { useReaderDocument } from './ReaderContext'; - -type ReaderBlockProps = { - id: string; -}; - -/** - * @param id - Block id - * @returns ReaderBlock component that loads data from the ReaderDocumentContext - */ -export default function ReaderBlock({ id }: ReaderBlockProps) { - const document = useReaderDocument(); - const block = document[id]; - if (!block) { - throw new Error('Could not find block'); - } - return ; -} diff --git a/packages/editor-sample/src/documents/reader/ReaderContext.tsx b/packages/editor-sample/src/documents/reader/ReaderContext.tsx deleted file mode 100644 index 6982c8f..0000000 --- a/packages/editor-sample/src/documents/reader/ReaderContext.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React, { createContext, useContext } from 'react'; - -import { TReaderDocument } from './core'; - -const ReaderContext = createContext({}); - -export function useReaderDocument() { - return useContext(ReaderContext); -} - -type ReaderProviderProps = { - value: TReaderDocument; - children: Parameters[0]['children']; -}; -export function ReaderProvider({ value, children }: ReaderProviderProps) { - return {children}; -} diff --git a/packages/editor-sample/src/documents/reader/core.tsx b/packages/editor-sample/src/documents/reader/core.tsx deleted file mode 100644 index f40582b..0000000 --- a/packages/editor-sample/src/documents/reader/core.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { z } from 'zod'; - -import { Avatar, AvatarPropsSchema } from '@usewaypoint/block-avatar'; -import { Button, ButtonPropsSchema } from '@usewaypoint/block-button'; -import { Divider, DividerPropsSchema } from '@usewaypoint/block-divider'; -import { Heading, HeadingPropsSchema } from '@usewaypoint/block-heading'; -import { Html, HtmlPropsSchema } from '@usewaypoint/block-html'; -import { Image, ImagePropsSchema } from '@usewaypoint/block-image'; -import { Spacer, SpacerPropsSchema } from '@usewaypoint/block-spacer'; -import { Text, TextPropsSchema } from '@usewaypoint/block-text'; -import { - buildBlockComponent, - buildBlockConfigurationDictionary, - buildBlockConfigurationSchema, -} from '@usewaypoint/document-core'; - -import { ColumnsContainer } from '../blocks/ColumnsContainer'; -import ColumnsContainerPropsSchema from '../blocks/ColumnsContainer/ColumnsContainerPropsSchema'; -import { Container } from '../blocks/Container'; -import { ContainerPropsSchema } from '../blocks/Container/ContainerPropsSchema'; -import { EmailLayout } from '../blocks/EmailLayout'; -import { EmailLayoutPropsSchema } from '../blocks/EmailLayout/EmailLayoutPropsSchema'; - -const READER_DICTIONARY = buildBlockConfigurationDictionary({ - Avatar: { - schema: AvatarPropsSchema, - Component: Avatar, - }, - Button: { - schema: ButtonPropsSchema, - Component: Button, - }, - ColumnsContainer: { - schema: ColumnsContainerPropsSchema, - Component: ColumnsContainer, - }, - Container: { - schema: ContainerPropsSchema, - Component: Container, - }, - Divider: { - schema: DividerPropsSchema, - Component: Divider, - }, - Heading: { - schema: HeadingPropsSchema, - Component: Heading, - }, - Html: { - schema: HtmlPropsSchema, - Component: Html, - }, - Image: { - schema: ImagePropsSchema, - Component: Image, - }, - Text: { - schema: TextPropsSchema, - Component: Text, - }, - EmailLayout: { - schema: EmailLayoutPropsSchema, - Component: EmailLayout, - }, - Spacer: { - schema: SpacerPropsSchema, - Component: Spacer, - }, -}); - -const ReaderBlockSchema = buildBlockConfigurationSchema(READER_DICTIONARY); -const ReaderDocumentSchema = z.record(z.string(), ReaderBlockSchema); - -export const ReaderBlock = buildBlockComponent(READER_DICTIONARY); - -export type TReaderDocument = Record>; - -export default ReaderDocumentSchema;