@seliseblocks/mailcraft 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +557 -0
- package/LICENSE +21 -0
- package/README.md +126 -0
- package/dist/mailcraft-editor.bundle.js +519 -0
- package/dist/mailcraft-editor.bundle.js.map +7 -0
- package/examples/templates/activate-your-account.html +54 -0
- package/examples/templates/back-in-stock.html +63 -0
- package/examples/templates/cart-left-behind.html +74 -0
- package/examples/templates/community-giveaway.html +81 -0
- package/examples/templates/frontend-futures-invite.html +69 -0
- package/examples/templates/give-25-get-25.html +69 -0
- package/examples/templates/invoice-paid.html +77 -0
- package/examples/templates/meet-nova-launch.html +69 -0
- package/examples/templates/mega-weekend-sale.html +57 -0
- package/examples/templates/order-confirmed.html +80 -0
- package/examples/templates/rate-your-headphones.html +71 -0
- package/examples/templates/reset-your-password.html +54 -0
- package/examples/templates/thankyou-promo-code.html +68 -0
- package/examples/templates/the-sunday-brief.html +47 -0
- package/examples/templates/welcome-to-your-workspace.html +62 -0
- package/examples/templates/your-order-shipped.html +74 -0
- package/examples/templates/your-password-was-changed.html +58 -0
- package/examples/templates/your-signin-code.html +58 -0
- package/examples/vanilla.html +1574 -0
- package/package.json +66 -0
- package/src/core/accent.js +194 -0
- package/src/core/assets.js +15 -0
- package/src/core/binder.js +119 -0
- package/src/core/blocks.js +256 -0
- package/src/core/css-cascade.js +117 -0
- package/src/core/editor-core.js +1492 -0
- package/src/core/export.js +58 -0
- package/src/core/footer.js +73 -0
- package/src/core/i18n/ar.js +177 -0
- package/src/core/i18n/bg.js +152 -0
- package/src/core/i18n/bn.js +176 -0
- package/src/core/i18n/ca.js +152 -0
- package/src/core/i18n/cs.js +152 -0
- package/src/core/i18n/da.js +152 -0
- package/src/core/i18n/de-CH.js +152 -0
- package/src/core/i18n/de.js +152 -0
- package/src/core/i18n/dz.js +179 -0
- package/src/core/i18n/el.js +152 -0
- package/src/core/i18n/en.js +269 -0
- package/src/core/i18n/es.js +152 -0
- package/src/core/i18n/et.js +152 -0
- package/src/core/i18n/fi.js +152 -0
- package/src/core/i18n/fr.js +152 -0
- package/src/core/i18n/hr.js +152 -0
- package/src/core/i18n/hu.js +152 -0
- package/src/core/i18n/index.js +83 -0
- package/src/core/i18n/it.js +152 -0
- package/src/core/i18n/lt.js +152 -0
- package/src/core/i18n/lv.js +152 -0
- package/src/core/i18n/nb.js +152 -0
- package/src/core/i18n/nl.js +152 -0
- package/src/core/i18n/pl.js +152 -0
- package/src/core/i18n/pt.js +152 -0
- package/src/core/i18n/ro.js +152 -0
- package/src/core/i18n/ru.js +152 -0
- package/src/core/i18n/sk.js +152 -0
- package/src/core/i18n/sl.js +152 -0
- package/src/core/i18n/sv.js +152 -0
- package/src/core/i18n/tables.js +50 -0
- package/src/core/i18n/tr.js +152 -0
- package/src/core/i18n/uk.js +152 -0
- package/src/core/icons.js +235 -0
- package/src/core/ids.js +1 -0
- package/src/core/import-html.js +959 -0
- package/src/core/layout-style.js +115 -0
- package/src/core/parse.js +10 -0
- package/src/core/placeholder.js +15 -0
- package/src/core/sanitize.js +141 -0
- package/src/core/storage-limits.js +184 -0
- package/src/core/storage.js +85 -0
- package/src/core/theme.js +1 -0
- package/src/core/toolbar.js +67 -0
- package/src/core/variables.js +11 -0
- package/src/create-editor.js +109 -0
- package/src/index.js +9 -0
- package/src/mailcraft-editor.js +1862 -0
- package/src/render/block-body.js +295 -0
- package/src/render/canvas.js +284 -0
- package/src/render/fields.js +609 -0
- package/src/render/focus-preserve.js +158 -0
- package/src/render/rte.js +212 -0
- package/src/render/screenshot.js +132 -0
- package/src/render/story.js +415 -0
- package/src/render/style.js +452 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mount-into-a-container API, for hosts that would rather call a function than
|
|
3
|
+
* write a tag -- the shape a JS widget usually ships with (`new Map(el, opts)`).
|
|
4
|
+
*
|
|
5
|
+
* const editor = createEditor('#mail', { html, toolbar: false });
|
|
6
|
+
* const out = editor.exportHtml();
|
|
7
|
+
* editor.destroy();
|
|
8
|
+
*
|
|
9
|
+
* This is a thin wrapper, not a second implementation: it creates the same
|
|
10
|
+
* `<mailcraft-editor>`, applies the options to it, and returns a handle whose
|
|
11
|
+
* methods forward to it. `editor.element` is the escape hatch to everything
|
|
12
|
+
* the wrapper does not surface, and markup usage stays exactly as it was.
|
|
13
|
+
*
|
|
14
|
+
* Options that are attributes on the element (`locale`, `theme`, ...) are set
|
|
15
|
+
* as attributes; the ones that carry objects or functions (`storageProvider`,
|
|
16
|
+
* `messages`, ...) are set as properties, because attributes hold strings.
|
|
17
|
+
* Callers do not have to know which is which.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { MailCraftEditor } from './mailcraft-editor.js';
|
|
21
|
+
|
|
22
|
+
/** Options that map 1:1 onto an attribute. `uiFont` is spelled `ui-font` in markup. */
|
|
23
|
+
const ATTRS = { variables: 'variables', locale: 'locale', dir: 'dir', theme: 'theme', uiFont: 'ui-font', accent: 'accent' };
|
|
24
|
+
|
|
25
|
+
/** Options that must be assigned as properties -- objects and functions cannot travel through an attribute. */
|
|
26
|
+
const PROPS = ['storageProvider', 'storageLimits', 'aiProvider', 'iconProvider', 'messages', 'footer'];
|
|
27
|
+
|
|
28
|
+
/** Methods forwarded verbatim onto the returned handle. */
|
|
29
|
+
const METHODS = ['exportHtml', 'importHtml', 'loadTemplate', 'undo', 'redo', 'screenshotPng', 'previewScreenshot', 'downloadScreenshot', 'copyScreenshot'];
|
|
30
|
+
|
|
31
|
+
function resolveTarget(target) {
|
|
32
|
+
const el = typeof target === 'string' ? document.querySelector(target) : target;
|
|
33
|
+
if (!el || el.nodeType !== 1) {
|
|
34
|
+
throw new Error('[mailcraft] createEditor: no element matched ' + JSON.stringify(target));
|
|
35
|
+
}
|
|
36
|
+
return el;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const px = (v) => (typeof v === 'number' ? v + 'px' : v);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Creates an editor inside `container`.
|
|
43
|
+
*
|
|
44
|
+
* @param {string|Element} target CSS selector or element to mount into.
|
|
45
|
+
* @param {Object} [options]
|
|
46
|
+
* @param {string} [options.html] initial email HTML, applied through the importer
|
|
47
|
+
* @param {string|string[]} [options.variables]
|
|
48
|
+
* @param {string} [options.locale] @param {string} [options.dir] @param {string} [options.theme] @param {string} [options.uiFont]
|
|
49
|
+
* @param {string} [options.accent] brand color for the editor chrome -- a CSS color, `var(--token)`, or `inherit`
|
|
50
|
+
* @param {boolean|Object} [options.toolbar] which parts of the top bar to show -- see core/toolbar.js
|
|
51
|
+
* @param {boolean|string|Object} [options.footer] the attribution strip: false to remove, a string to replace it, or { text, href } -- see core/footer.js
|
|
52
|
+
* @param {Object} [options.storageProvider] @param {Object} [options.storageLimits]
|
|
53
|
+
* @param {Function} [options.aiProvider] @param {Function} [options.iconProvider] @param {Object} [options.messages]
|
|
54
|
+
* @param {string|number} [options.height] sets the container's height; otherwise your CSS decides
|
|
55
|
+
* @param {boolean} [options.replace] empty the container first (default: append)
|
|
56
|
+
* @param {Function} [options.onChange] (doc) => void
|
|
57
|
+
* @param {Function} [options.onExport] (html) => void
|
|
58
|
+
* @returns {Object} handle with the editor's methods, `element`, and `destroy()`
|
|
59
|
+
*/
|
|
60
|
+
export function createEditor(target, options) {
|
|
61
|
+
const o = options || {};
|
|
62
|
+
const container = resolveTarget(target);
|
|
63
|
+
const el = document.createElement('mailcraft-editor');
|
|
64
|
+
|
|
65
|
+
Object.keys(ATTRS).forEach((key) => {
|
|
66
|
+
if (o[key] == null) return;
|
|
67
|
+
el.setAttribute(ATTRS[key], Array.isArray(o[key]) ? o[key].join(',') : String(o[key]));
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Before insertion: `toolbar` decides whether the header row is built at all,
|
|
71
|
+
// and the providers are wanted by the first render, not one frame after it.
|
|
72
|
+
if (o.toolbar !== undefined) el.toolbar = o.toolbar;
|
|
73
|
+
PROPS.forEach((key) => { if (o[key] !== undefined) el[key] = o[key]; });
|
|
74
|
+
|
|
75
|
+
const onChange = o.onChange ? (e) => o.onChange(e.detail) : null;
|
|
76
|
+
const onExport = o.onExport ? (e) => o.onExport(e.detail) : null;
|
|
77
|
+
if (onChange) el.addEventListener('change', onChange);
|
|
78
|
+
if (onExport) el.addEventListener('export', onExport);
|
|
79
|
+
|
|
80
|
+
// The element is `display: block; height: 100%`, so the container's height is
|
|
81
|
+
// the editor's height. Left to the host's CSS unless `height` says otherwise --
|
|
82
|
+
// guessing one here would silently override a layout that was already correct.
|
|
83
|
+
if (o.replace) container.textContent = '';
|
|
84
|
+
if (o.height) container.style.height = px(o.height);
|
|
85
|
+
container.appendChild(el);
|
|
86
|
+
|
|
87
|
+
// Applied last: this is an undoable edit, and it should land on an editor
|
|
88
|
+
// that is already mounted and configured.
|
|
89
|
+
if (typeof o.html === 'string' && o.html.trim()) el.loadTemplate({ name: o.name || '', html: o.html });
|
|
90
|
+
|
|
91
|
+
const handle = {
|
|
92
|
+
/** The underlying custom element -- everything the wrapper does not forward. */
|
|
93
|
+
element: el,
|
|
94
|
+
/** Removes the editor and detaches the listeners this call attached. Leaves anything else in the container alone. */
|
|
95
|
+
destroy() {
|
|
96
|
+
if (onChange) el.removeEventListener('change', onChange);
|
|
97
|
+
if (onExport) el.removeEventListener('export', onExport);
|
|
98
|
+
if (el.parentNode) el.parentNode.removeChild(el);
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
METHODS.forEach((name) => { handle[name] = (...args) => el[name](...args); });
|
|
102
|
+
|
|
103
|
+
return handle;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** True once the element is registered -- the import above is what registers it, so this is a sanity check for hosts loading scripts out of order. */
|
|
107
|
+
export function isReady() {
|
|
108
|
+
return typeof customElements !== 'undefined' && customElements.get('mailcraft-editor') === MailCraftEditor;
|
|
109
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { MailCraftEditor } from './mailcraft-editor.js';
|
|
2
|
+
export { createEditor, isReady } from './create-editor.js';
|
|
3
|
+
export { EditorCore } from './core/editor-core.js';
|
|
4
|
+
export { renderDoc } from './render/canvas.js';
|
|
5
|
+
export { BLOCKS, GROUPS, LAYOUTS, PALETTE } from './core/blocks.js';
|
|
6
|
+
export { createTranslator, defineMessages, missingKeys, LOCALES, isRtl, EN, MESSAGE_KEYS } from './core/i18n/index.js';
|
|
7
|
+
export { LOCALE_TABLES } from './core/i18n/tables.js';
|
|
8
|
+
export { ALL_FOLDER_ID, normalizeAsset, resolveLimits } from './core/storage.js';
|
|
9
|
+
export { validateFiles, sanitizeName, acceptAttribute, limitsProblem } from './core/storage-limits.js';
|