react-email-builder
Version:
A simple React drag and drop email builder.
170 lines (169 loc) • 8.42 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Block = void 0;
const clsx_1 = __importDefault(require("clsx"));
const react_1 = __importStar(require("react"));
const utils_1 = require("../../utils");
const hooks_1 = require("../../hooks");
const hooks_2 = require("../../controls/Popover/hooks");
const DropArea_1 = require("../DropArea");
const placeholder_1 = require("../../blocks/placeholder");
const hooks_3 = require("../../controls/Tooltip/hooks");
const Icon_1 = require("../Icon");
const Tooltip_1 = require("../../controls/Tooltip");
const Popover_1 = require("../../controls/Popover");
const Button_1 = require("../../controls/Button");
const Content = (0, react_1.memo)(function Content({ className, config, block }) {
let content = null;
if (block.type === 'placeholder') {
content = react_1.default.createElement(placeholder_1.Placeholder, { block: block });
}
else {
const Component = config.blocks.find((b) => b.type === block.type)?.blockComponent;
content = Component ? react_1.default.createElement(Component, { block: block }) : null;
}
return react_1.default.createElement("div", { className: className }, content);
});
const Toolbar = (0, react_1.memo)(function Toolbar() {
const css = useCss();
const { block, first, last } = (0, hooks_1.useSelectedBlock)();
const moveBlock = (0, hooks_1.useMoveBlock)();
const copyBlock = (0, hooks_1.useCopyBlock)();
return block ? (react_1.default.createElement("div", { className: css.toolbar },
react_1.default.createElement("div", { className: css.actions },
first ? null : (react_1.default.createElement(Action, { icon: "up", title: "Move up", onClick: () => {
moveBlock(block.id, -1);
} })),
last ? null : (react_1.default.createElement(Action, { icon: "down", title: "Move down", onClick: () => {
moveBlock(block.id, 1);
} })),
react_1.default.createElement(Action, { icon: "copy", title: "Copy", onClick: (e) => {
e.stopPropagation();
copyBlock(block.id);
} }),
block.type === 'placeholder' && first && last ? null : (react_1.default.createElement(Delete, { blockId: block.id }))))) : null;
});
const Delete = (0, react_1.memo)(function Delete({ blockId }) {
const css = useCss();
const tooltip = (0, hooks_3.useTooltip)({ showDelay: 500 });
const popover = (0, hooks_2.usePopover)({
placement: 'bottom-start',
offset: 8
});
const deleteBlock = (0, hooks_1.useDeleteBlock)();
return (react_1.default.createElement(react_1.default.Fragment, null,
react_1.default.createElement("div", { ref: (node) => {
tooltip.triggerRef(node);
popover.triggerRef(node);
}, className: (0, clsx_1.default)(css.action, {
[css.actionActive]: popover.open
}), onClick: () => {
popover.setOpen(true);
} },
react_1.default.createElement(Icon_1.Icon, { name: "delete" })),
popover.open ? null : (react_1.default.createElement(Tooltip_1.Tooltip, { open: tooltip.open, tooltipRef: tooltip.tooltipRef }, "Delete")),
react_1.default.createElement(Popover_1.Popover, { open: popover.open, popoverRef: popover.popoverRef, arrow: true },
react_1.default.createElement("div", { style: {
padding: 20,
minWidth: 300,
maxWidth: 400,
boxSizing: 'border-box'
} },
react_1.default.createElement("div", { style: { fontWeight: 'bold', marginBottom: 16 } }, "Delete block"),
react_1.default.createElement("div", null,
"Are you sure you want to delete this block?",
react_1.default.createElement("br", null),
"This action cannot be undone."),
react_1.default.createElement("div", { style: { textAlign: 'right', marginTop: 24 } },
react_1.default.createElement(Button_1.Button, { secondary: true, style: { marginRight: 12 }, onClick: () => {
popover.setOpen(false);
} }, "Cancel"),
react_1.default.createElement(Button_1.Button, { onClick: () => {
popover.setOpen(false);
deleteBlock(blockId);
} }, "Delete"))))));
});
function Block({ block, dragging, dragover, children, childrenSelected, role, selected, showDropArea }) {
const css = useCss();
const config = (0, hooks_1.useEmailBuilderConfig)();
const setState = (0, hooks_1.useSetEmailBuilderState)();
const onClickBlock = (0, react_1.useCallback)((e) => {
e.stopPropagation();
setState((prev) => {
return prev.selectedId === block.id
? prev
: {
...prev,
selectedId: block.id,
tab: 'settings'
};
});
}, [block, setState]);
return (react_1.default.createElement("div", { className: (0, clsx_1.default)(css.section, {
[css.full]: block.style.full !== 'no'
}), style: {
backgroundColor: block.style.sectionBgColor
} },
react_1.default.createElement("div", { onClick: onClickBlock, className: (0, clsx_1.default)(css.block, {
[css.dropArea]: dragging && showDropArea,
[css.dragover]: dragover,
[css.selected]: selected,
[css.active]: selected || childrenSelected,
[css.column]: role === 'column'
}) },
children ? (children) : (react_1.default.createElement(Content, { block: block, className: css.content, config: config })),
showDropArea ? (react_1.default.createElement(DropArea_1.DropArea, { block: block, dragover: dragover, role: role })) : null,
selected ? react_1.default.createElement(Toolbar, null) : null)));
}
exports.Block = Block;
function Action({ title, icon, onClick }) {
const css = useCss();
const tooltip = (0, hooks_3.useTooltip)({ showDelay: 500 });
return (react_1.default.createElement(react_1.default.Fragment, null,
react_1.default.createElement("div", { ref: tooltip.triggerRef, className: css.action, onClick: onClick },
react_1.default.createElement(Icon_1.Icon, { name: icon })),
title ? (react_1.default.createElement(Tooltip_1.Tooltip, { open: tooltip.open, tooltipRef: tooltip.tooltipRef }, title)) : null));
}
function useCss() {
return (0, utils_1.getCss)('Block', (ns) => ({
section: ns('section'),
full: ns('section-full'),
block: ns(),
dropArea: ns('drop-area'),
dragover: ns('dragover'),
selected: ns('selected'),
active: ns('active'),
column: ns('column'),
content: ns('content'),
toolbar: ns('toolbar'),
actions: ns('actions'),
action: ns('action'),
actionActive: ns('action-active')
}));
}