@seliseblocks/mailcraft 0.2.2 → 0.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seliseblocks/mailcraft",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Framework-agnostic drag-and-drop email template editor, packaged as a zero-dependency Web Component.",
5
5
  "license": "MIT",
6
6
  "author": "SELISE Digital Platforms",
@@ -1500,11 +1500,16 @@ export class EditorCore {
1500
1500
  B.head('Content area'),
1501
1501
  B.color('Content area background color', 'contentBg', { transparent: true, solid: '#ffffff' }),
1502
1502
  B.range('Corner radius', 'radius', 0, 48, 1, 'px'),
1503
+ B.range('Border thickness', 'borderW', 0, 12, 1, 'px'),
1504
+ ].concat(this.state.doc.theme.borderW ? [
1505
+ B.sel('Border style', 'borderStyle', BORDER_STYLES),
1506
+ B.color('Border color', 'borderColor'),
1507
+ ] : []).concat([
1503
1508
  B.head('Type & color'),
1504
1509
  B.sel('Default font', 'font', this.fontOptions(false)),
1505
1510
  B.color('Text color', 'text'),
1506
1511
  B.color('Link color', 'link'),
1507
- ]);
1512
+ ]));
1508
1513
  }
1509
1514
 
1510
1515
  vars() { return varsFn(this.variablesRaw); }
@@ -156,6 +156,7 @@ export function buildHtml(state, root, boxCss) {
156
156
  const pagePad = (t.padY || t.padX) ? (t.padY || 0) + 'px ' + (t.padX || 0) + 'px' : '0';
157
157
  // `overflow:hidden` is what actually clips a row's own background to the
158
158
  // rounded corner; without it the first and last rows paint square over it.
159
- const contentShape = t.radius ? 'border-radius:' + t.radius + 'px;overflow:hidden;' : '';
159
+ const contentShape = (t.radius ? 'border-radius:' + t.radius + 'px;overflow:hidden;' : '')
160
+ + (t.borderW ? 'border:' + t.borderW + 'px ' + (t.borderStyle || 'solid') + ' ' + (t.borderColor || '#e2e2e5') + ';' : '');
160
161
  return '<!doctype html>\n<html lang="en">\n<head>\n<meta charset="utf-8">\n<meta name="viewport" content="width=device-width,initial-scale=1">\n<meta name="color-scheme" content="light dark">\n<title>' + 'Email' + '</title>\n</head>\n<body style="margin:0;padding:0;background:' + pageBg + ';font-family:' + t.font.replace(/"/g, "'") + ';color:' + t.text + ';-webkit-font-smoothing:antialiased;">\n<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="background:' + pageBg + ';">\n <tr><td align="center" style="padding:' + pagePad + ';">\n <table role="presentation" width="' + t.width + '" cellpadding="0" cellspacing="0" border="0" style="width:' + t.width + 'px;max-width:100%;background:' + (t.contentBg || 'transparent') + ';' + contentShape + '">\n' + rows + '\n </table>\n </td></tr>\n</table>\n</body>\n</html>';
161
162
  }
@@ -977,6 +977,15 @@ function themeFromParsedDoc(doc) {
977
977
  if (cbg) theme.contentBg = cbg;
978
978
  const r = PX(content.style && content.style.borderRadius);
979
979
  if (r > 0) theme.radius = r;
980
+ // The content column's full border, written by the exporter as a
981
+ // `border` shorthand on the same table -- read back so it survives the
982
+ // round trip like the radius above.
983
+ const bw = content.style ? PX(content.style.borderWidth) || PX(content.style.borderTopWidth) : 0;
984
+ if (bw > 0) {
985
+ theme.borderW = bw;
986
+ theme.borderStyle = borderStyleOf(content.style);
987
+ theme.borderColor = borderColorOf(content.style) || '';
988
+ }
980
989
  const cell = content.closest ? content.closest('td') : null;
981
990
  if (cell && cell.style) {
982
991
  const padY = PX(cell.style.paddingTop);
package/src/core/theme.js CHANGED
@@ -12,4 +12,4 @@
12
12
  * accept the literal `transparent` (and any rgba()/#rrggbbaa value) as well
13
13
  * as a hex colour.
14
14
  */
15
- export const THEME = () => ({ bg: '#eef2f7', contentBg: '#ffffff', width: 620, padY: 0, padX: 0, radius: 0, font: '"Helvetica Neue", Helvetica, Arial, sans-serif', text: '#172033', link: '#0065b3' });
15
+ export const THEME = () => ({ bg: '#eef2f7', contentBg: '#ffffff', width: 620, padY: 0, padX: 0, radius: 0, borderW: 0, borderStyle: 'solid', borderColor: '#e2e2e5', font: '"Helvetica Neue", Helvetica, Arial, sans-serif', text: '#172033', link: '#0065b3' });
@@ -176,12 +176,16 @@ export function renderDoc(core, live) {
176
176
  // flipped bidi punctuation and default alignment on the canvas and made it
177
177
  // disagree with the exported result.
178
178
  const radius = Number(theme.radius) || 0;
179
+ const borderW = Number(theme.borderW) || 0;
179
180
  const root = el('div', {
180
181
  width: width + 'px', maxWidth: '100%', background: theme.contentBg || 'transparent', color: theme.text, fontFamily: theme.font,
181
182
  // Only when the document actually asks for a shape: an unconditional
182
183
  // `0px` would override the editor chrome's own soft corner on the sheet
183
184
  // (style.js) and square off every template that never touched the field.
184
185
  borderRadius: radius ? radius + 'px' : '',
186
+ // Same contract for the full content-area border: set only when asked,
187
+ // so the chrome's own subtle frame keeps marking the sheet otherwise.
188
+ border: borderW ? borderW + 'px ' + (theme.borderStyle || 'solid') + ' ' + (theme.borderColor || '#e2e2e5') : '',
185
189
  // Clipping the rows to that corner is right for the sent email (export
186
190
  // emits `overflow:hidden` alongside the radius) and for the static
187
191
  // preview, but not for the editable canvas: the sheet is also what the