@lit-pigeon/editor 0.1.3 → 0.3.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/dist/templates.js CHANGED
@@ -1,11 +1,270 @@
1
- import { LitElement as m, html as o, css as f } from "lit";
2
- import { property as c, state as s, customElement as g } from "lit/decorators.js";
3
- var h = Object.defineProperty, b = Object.getOwnPropertyDescriptor, r = (e, i, p, n) => {
4
- for (var a = n > 1 ? void 0 : n ? b(i, p) : i, l = e.length - 1, d; l >= 0; l--)
5
- (d = e[l]) && (a = (n ? d(i, p, a) : d(a)) || a);
6
- return n && a && h(i, p, a), a;
1
+ import { LitElement as u, html as l, css as v } from "lit";
2
+ import { property as g, state as p, customElement as f } from "lit/decorators.js";
3
+ const m = {
4
+ // toolbar
5
+ "toolbar.undo": "Undo",
6
+ "toolbar.redo": "Redo",
7
+ "toolbar.preview-device": "Preview device",
8
+ "toolbar.desktop-view": "Desktop view",
9
+ "toolbar.tablet-view-title": "Tablet view (768px)",
10
+ "toolbar.tablet-view": "Tablet view",
11
+ "toolbar.mobile-view-title": "Mobile view (375px)",
12
+ "toolbar.mobile-view": "Mobile view",
13
+ "toolbar.fullscreen": "Fullscreen",
14
+ "toolbar.exit-fullscreen": "Exit fullscreen",
15
+ "toolbar.enter-fullscreen": "Enter fullscreen",
16
+ "toolbar.templates": "Templates",
17
+ "toolbar.preview": "Preview",
18
+ "toolbar.export": "Export",
19
+ "toolbar.export-format": "Export format",
20
+ "toolbar.export-html": "Export HTML",
21
+ "toolbar.export-mjml": "Export MJML",
22
+ "toolbar.export-json": "Export JSON",
23
+ // palette
24
+ "palette.label": "Palette",
25
+ "palette.tab.content": "Content",
26
+ "palette.tab.layers": "Layers",
27
+ "palette.tab.brand": "Brand",
28
+ "palette.tab.saved": "Saved",
29
+ // palette — layout section
30
+ "palette.layout.section-content": "Content",
31
+ "palette.layout.section-layout": "Layout",
32
+ "palette.layout.1-col": "1 Column",
33
+ "palette.layout.2-col": "2 Columns",
34
+ "palette.layout.3-col": "3 Columns",
35
+ "palette.layout.4-col": "4 Columns",
36
+ // palette — brand tab
37
+ "palette.brand.colors": "Colors",
38
+ "palette.brand.fonts": "Fonts",
39
+ "palette.brand.logos": "Logos",
40
+ "palette.brand.add": "+ Add",
41
+ "palette.brand.no-colors": "No colors yet",
42
+ "palette.brand.no-fonts": "No fonts yet",
43
+ "palette.brand.no-logos": "No logos yet",
44
+ "palette.brand.color-name-label": "Color name",
45
+ "palette.brand.color-value-label": "Color value",
46
+ "palette.brand.delete-title": "Delete",
47
+ "palette.brand.insert-logo-title": "Insert logo",
48
+ // palette — saved tab
49
+ "palette.saved.empty": "No saved rows yet. Use the bookmark action on a row to save it here.",
50
+ "palette.saved.delete-title": "Delete",
51
+ // preview
52
+ "preview.heading": "Preview",
53
+ "preview.tab-group-label": "Preview format",
54
+ "preview.tab.preview": "Preview",
55
+ "preview.tab.html": "HTML",
56
+ "preview.tab.mjml": "MJML",
57
+ "preview.tab.json": "JSON",
58
+ "preview.device.desktop": "Desktop preview",
59
+ "preview.device.mobile": "Mobile preview",
60
+ "preview.close": "Close preview",
61
+ "preview.loading": "Rendering...",
62
+ // template picker
63
+ "template.heading": "Templates",
64
+ "template.close": "Close",
65
+ "template.section.choose": "Choose a template",
66
+ "template.empty": "No templates available yet.",
67
+ "template.section.save": "Save current as template",
68
+ "template.field.name": "Name",
69
+ "template.field.name-placeholder": "My template",
70
+ "template.field.category": "Category",
71
+ "template.field.description": "Description (optional)",
72
+ "template.field.description-placeholder": "What is this template for?",
73
+ "template.cancel": "Cancel",
74
+ "template.save": "Save template",
75
+ "template.error.name-required": "Name is required",
76
+ // asset manager
77
+ "asset.title": "Select asset",
78
+ "asset.title-upload": "Select image",
79
+ "asset.close": "Close",
80
+ "asset.tab.library": "Library",
81
+ "asset.tab.upload": "Upload",
82
+ "asset.folder.all": "All folders",
83
+ "asset.search": "Search assets",
84
+ "asset.tag-filter-label": "Filter by tag",
85
+ "asset.loading": "Loading…",
86
+ "asset.empty.filtered": "No assets match your filters.",
87
+ "asset.empty.no-assets": "No saved assets yet. Upload one to get started.",
88
+ "asset.drop-zone.label": "Drag & drop an image here",
89
+ "asset.drop-zone.hint": "or click to browse",
90
+ "asset.url.separator": "or enter URL",
91
+ "asset.url.placeholder": "https://example.com/image.jpg",
92
+ "asset.url.use": "Use URL",
93
+ // asset manager — stock tab
94
+ "asset.tab.stock": "Stock",
95
+ "asset.stock.search": "Search free photos…",
96
+ "asset.stock.idle": "Search Unsplash and Pexels for free photos.",
97
+ "asset.stock.empty": "No photos found. Try another search.",
98
+ "asset.stock.load-more": "Load more",
99
+ "asset.stock.photo-by": "Photo by",
100
+ "asset.stock.on": "on",
101
+ "asset.stock.error": "Couldn’t load photos. Check the API key or try again.",
102
+ "asset.stock.rate-limited": "Rate limit reached. Try again shortly.",
103
+ // property panels — shared (common) labels
104
+ "panel.common.backgroundColor": "Background Color",
105
+ "panel.common.padding": "Padding",
106
+ "panel.common.outerPadding": "Outer Padding",
107
+ "panel.common.innerPadding": "Inner Padding",
108
+ "panel.common.alignment": "Alignment",
109
+ "panel.common.fontSize": "Font Size",
110
+ "panel.common.borderRadius": "Border Radius",
111
+ "panel.common.linkUrl": "Link URL",
112
+ "panel.common.urlPlaceholder": "https://example.com",
113
+ "panel.common.contentHtml": "Content (HTML)",
114
+ "panel.common.insertMergeTag": "Insert merge tag",
115
+ "panel.common.tagBtn": "{ } Tag",
116
+ "panel.common.uploadImage": "Upload Image",
117
+ "panel.common.left": "Left",
118
+ "panel.common.center": "Center",
119
+ // property panels — body
120
+ "panel.body.title": "Email Body",
121
+ "panel.body.contentWidth": "Content Width",
122
+ "panel.body.fontFamily": "Font Family",
123
+ "panel.body.contentAlignment": "Content Alignment",
124
+ "panel.body.emailName": "Email Name",
125
+ "panel.body.previewText": "Preview Text",
126
+ "panel.body.previewTextPlaceholder": "Email preview text...",
127
+ // property panels — text
128
+ "panel.text.title": "Text Properties",
129
+ "panel.text.textAlign": "Text Align",
130
+ "panel.text.lineHeight": "Line Height",
131
+ // property panels — button
132
+ "panel.button.title": "Button Properties",
133
+ "panel.button.buttonText": "Button Text",
134
+ "panel.button.textColor": "Text Color",
135
+ "panel.button.fontWeight": "Font Weight",
136
+ "panel.button.fontWeight.normal": "Normal (400)",
137
+ "panel.button.fontWeight.medium": "Medium (500)",
138
+ "panel.button.fontWeight.semibold": "Semibold (600)",
139
+ "panel.button.fontWeight.bold": "Bold (700)",
140
+ "panel.button.fullWidth": "Full Width",
141
+ // property panels — image
142
+ "panel.image.title": "Image Properties",
143
+ "panel.image.imageUrl": "Image URL",
144
+ "panel.image.urlPlaceholder": "https://example.com/image.jpg",
145
+ "panel.image.altText": "Alt Text",
146
+ "panel.image.altPlaceholder": "Image description",
147
+ "panel.image.width": "Width (0 = auto)",
148
+ // property panels — hero
149
+ "panel.hero.title": "Hero Properties",
150
+ "panel.hero.backgroundUrl": "Background URL",
151
+ "panel.hero.backgroundUrlPlaceholder": "https://example.com/hero.jpg",
152
+ "panel.hero.backgroundPosition": "Background Position",
153
+ "panel.hero.mode": "Mode",
154
+ "panel.hero.modeFluidHeight": "Fluid Height",
155
+ "panel.hero.modeFixedHeight": "Fixed Height",
156
+ "panel.hero.height": "Height",
157
+ "panel.hero.width": "Width",
158
+ "panel.hero.verticalAlign": "Vertical Align",
159
+ "panel.hero.verticalAlignTop": "Top",
160
+ "panel.hero.verticalAlignMiddle": "Middle",
161
+ "panel.hero.verticalAlignBottom": "Bottom",
162
+ // property panels — navbar
163
+ "panel.navbar.title": "Navbar Properties",
164
+ "panel.navbar.links": "Links",
165
+ "panel.navbar.linkLabel": "Link",
166
+ "panel.navbar.removeLink": "Remove",
167
+ "panel.navbar.linkText": "Text",
168
+ "panel.navbar.url": "URL",
169
+ "panel.navbar.addLink": "+ Add Link",
170
+ "panel.navbar.hamburger": "Hamburger (mobile)",
171
+ "panel.navbar.hamburgerShow": "Show",
172
+ "panel.navbar.hamburgerHide": "Hide",
173
+ "panel.navbar.linkColor": "Link Color",
174
+ "panel.navbar.linkFontSize": "Link Font Size",
175
+ "panel.navbar.linkPadding": "Link Padding",
176
+ // property panels — divider
177
+ "panel.divider.title": "Divider Properties",
178
+ "panel.divider.style": "Style",
179
+ "panel.divider.styleSolid": "Solid",
180
+ "panel.divider.styleDashed": "Dashed",
181
+ "panel.divider.styleDotted": "Dotted",
182
+ "panel.divider.color": "Color",
183
+ "panel.divider.width": "Width",
184
+ "panel.divider.lineWidth": "Line Width",
185
+ // property panels — spacer
186
+ "panel.spacer.title": "Spacer Properties",
187
+ "panel.spacer.height": "Height",
188
+ // property panels — social
189
+ "panel.social.title": "Social Properties",
190
+ "panel.social.icons": "Icons",
191
+ "panel.social.iconLabel": "Icon",
192
+ "panel.social.removeIcon": "Remove",
193
+ "panel.social.network": "Network",
194
+ "panel.social.url": "URL",
195
+ "panel.social.iconUrl": "Icon URL",
196
+ "panel.social.altText": "Label (alt text)",
197
+ "panel.social.addIcon": "+ Add Icon",
198
+ "panel.social.iconSize": "Icon Size",
199
+ "panel.social.spacing": "Spacing",
200
+ // property panels — html
201
+ "panel.html.title": "HTML Properties",
202
+ "panel.html.rawHtml": "Raw HTML",
203
+ // property panels — row
204
+ "panel.row.title": "Row Properties",
205
+ "panel.row.columnLayout": "Column Layout",
206
+ "panel.row.layout1col": "1 Column",
207
+ "panel.row.layout2col": "2 Equal",
208
+ "panel.row.layout3col": "3 Equal",
209
+ "panel.row.layout4col": "4 Equal",
210
+ "panel.row.backgroundImageUrl": "Background Image URL",
211
+ "panel.row.fullWidth": "Full Width",
212
+ "panel.row.displayCondition": "Display condition",
213
+ // controls — color picker
214
+ "control.color.label": "Color",
215
+ // controls — font picker
216
+ "control.fontPicker.label": "Font Family",
217
+ // controls — link type picker
218
+ "control.linkType.ariaLabel": "Insert a special link",
219
+ "control.linkType.placeholder": "+ Special link",
220
+ "control.linkType.emailPrompt": "Email address",
221
+ "control.linkType.telPrompt": "Phone number",
222
+ // controls — spacing input
223
+ "control.spacing.top": "Top",
224
+ "control.spacing.right": "Right",
225
+ "control.spacing.bottom": "Bottom",
226
+ "control.spacing.left": "Left",
227
+ "control.spacing.topTitle": "Top (px)",
228
+ "control.spacing.rightTitle": "Right (px)",
229
+ "control.spacing.bottomTitle": "Bottom (px)",
230
+ "control.spacing.leftTitle": "Left (px)",
231
+ // controls — alignment picker
232
+ "control.alignment.left": "Align left",
233
+ "control.alignment.center": "Align center",
234
+ "control.alignment.right": "Align right",
235
+ // controls — merge tag picker
236
+ "control.mergeTag.searchPlaceholder": "Search tags...",
237
+ "control.mergeTag.noMatches": "No matching tags",
238
+ // rich text bubble toolbar
239
+ "richtext.bold": "Bold (Cmd+B)",
240
+ "richtext.italic": "Italic (Cmd+I)",
241
+ "richtext.underline": "Underline (Cmd+U)",
242
+ "richtext.strike": "Strike",
243
+ "richtext.code": "Code",
244
+ "richtext.link": "Link",
245
+ "richtext.apply": "Apply",
246
+ "richtext.removeLink": "Remove link",
247
+ "richtext.urlPlaceholder": "https://…"
248
+ }, x = /* @__PURE__ */ new Set(["ar", "he", "fa", "ur", "ps", "sd", "dv", "yi"]);
249
+ let h = "en", b = { en: m };
250
+ function L(e, t) {
251
+ h = e || "en", b = { en: m, ...t ?? {} };
252
+ }
253
+ function o(e) {
254
+ var t;
255
+ return ((t = b[h]) == null ? void 0 : t[e]) ?? m[e] ?? e;
256
+ }
257
+ function T(e, t) {
258
+ if (t) return t;
259
+ const n = (e || "en").toLowerCase().split(/[-_]/)[0];
260
+ return x.has(n) ? "rtl" : "ltr";
261
+ }
262
+ var y = Object.defineProperty, w = Object.getOwnPropertyDescriptor, r = (e, t, n, s) => {
263
+ for (var i = s > 1 ? void 0 : s ? w(t, n) : t, d = e.length - 1, c; d >= 0; d--)
264
+ (c = e[d]) && (i = (s ? c(t, n, i) : c(i)) || i);
265
+ return s && i && y(t, n, i), i;
7
266
  };
8
- const v = [
267
+ const k = [
9
268
  { v: "welcome", l: "Welcome" },
10
269
  { v: "newsletter", l: "Newsletter" },
11
270
  { v: "transactional", l: "Transactional" },
@@ -13,21 +272,21 @@ const v = [
13
272
  { v: "announcement", l: "Announcement" },
14
273
  { v: "other", l: "Other" }
15
274
  ];
16
- let t = class extends m {
275
+ let a = class extends u {
17
276
  constructor() {
18
277
  super(...arguments), this.open = !1, this._templates = [], this._name = "", this._description = "", this._category = "other", this._formError = "", this._close = () => {
19
278
  this.open = !1, this._formError = "";
20
279
  }, this._onSubmit = (e) => {
21
280
  e.preventDefault();
22
- const i = this._name.trim();
23
- if (!i) {
24
- this._formError = "Name is required";
281
+ const t = this._name.trim();
282
+ if (!t) {
283
+ this._formError = o("template.error.name-required");
25
284
  return;
26
285
  }
27
286
  this._formError = "", this.dispatchEvent(
28
287
  new CustomEvent("template-save", {
29
288
  detail: {
30
- name: i,
289
+ name: t,
31
290
  description: this._description.trim() || void 0,
32
291
  category: this._category
33
292
  },
@@ -53,61 +312,61 @@ let t = class extends m {
53
312
  }
54
313
  }
55
314
  render() {
56
- return o`
315
+ return l`
57
316
  <div class="overlay" @click=${this._close}></div>
58
317
  <div class="modal">
59
318
  <div class="header">
60
- <h3>Templates</h3>
61
- <button class="close-btn" title="Close" @click=${this._close}>&times;</button>
319
+ <h3>${o("template.heading")}</h3>
320
+ <button class="close-btn" title=${o("template.close")} @click=${this._close}>&times;</button>
62
321
  </div>
63
322
  <div class="body">
64
323
  <div>
65
- <h4 class="section-title">Choose a template</h4>
66
- ${this._templates.length === 0 ? o`<div class="empty">No templates available yet.</div>` : o`<div class="grid">${this._templates.map((e) => this._renderCard(e))}</div>`}
324
+ <h4 class="section-title">${o("template.section.choose")}</h4>
325
+ ${this._templates.length === 0 ? l`<div class="empty">${o("template.empty")}</div>` : l`<div class="grid">${this._templates.map((e) => this._renderCard(e))}</div>`}
67
326
  </div>
68
327
 
69
328
  <form class="save-form" @submit=${this._onSubmit}>
70
- <h4 class="section-title">Save current as template</h4>
329
+ <h4 class="section-title">${o("template.section.save")}</h4>
71
330
  <div class="save-row">
72
331
  <div class="field">
73
- <label for="template-name">Name</label>
332
+ <label for="template-name">${o("template.field.name")}</label>
74
333
  <input
75
334
  id="template-name"
76
335
  name="template-name"
77
336
  type="text"
78
- placeholder="My template"
337
+ placeholder=${o("template.field.name-placeholder")}
79
338
  .value=${this._name}
80
339
  @input=${(e) => this._name = e.target.value}
81
340
  />
82
341
  </div>
83
342
  <div class="field">
84
- <label for="template-category">Category</label>
343
+ <label for="template-category">${o("template.field.category")}</label>
85
344
  <select
86
345
  id="template-category"
87
346
  name="template-category"
88
347
  .value=${this._category}
89
348
  @change=${(e) => this._category = e.target.value}
90
349
  >
91
- ${v.map(
92
- (e) => o`<option value=${e.v} ?selected=${this._category === e.v}>${e.l}</option>`
350
+ ${k.map(
351
+ (e) => l`<option value=${e.v} ?selected=${this._category === e.v}>${e.l}</option>`
93
352
  )}
94
353
  </select>
95
354
  </div>
96
355
  </div>
97
356
  <div class="field">
98
- <label for="template-description">Description (optional)</label>
357
+ <label for="template-description">${o("template.field.description")}</label>
99
358
  <textarea
100
359
  id="template-description"
101
360
  name="template-description"
102
- placeholder="What is this template for?"
361
+ placeholder=${o("template.field.description-placeholder")}
103
362
  .value=${this._description}
104
363
  @input=${(e) => this._description = e.target.value}
105
364
  ></textarea>
106
365
  </div>
107
- ${this._formError ? o`<div class="error">${this._formError}</div>` : ""}
366
+ ${this._formError ? l`<div class="error">${this._formError}</div>` : ""}
108
367
  <div class="form-actions">
109
- <button type="button" class="secondary" @click=${this._close}>Cancel</button>
110
- <button type="submit">Save template</button>
368
+ <button type="button" class="secondary" @click=${this._close}>${o("template.cancel")}</button>
369
+ <button type="submit">${o("template.save")}</button>
111
370
  </div>
112
371
  </form>
113
372
  </div>
@@ -115,11 +374,11 @@ let t = class extends m {
115
374
  `;
116
375
  }
117
376
  _renderCard(e) {
118
- return o`
377
+ return l`
119
378
  <button class="template-card" @click=${() => this._onPick(e)} title="Load ${e.name}">
120
- ${e.thumbnail ? o`<img class="thumb" src=${e.thumbnail} alt="" />` : o`<div class="thumb-placeholder">${e.category ?? "template"}</div>`}
379
+ ${e.thumbnail ? l`<img class="thumb" src=${e.thumbnail} alt="" />` : l`<div class="thumb-placeholder">${e.category ?? "template"}</div>`}
121
380
  <span class="name">${e.name}</span>
122
- ${e.description ? o`<span class="description">${e.description}</span>` : ""}
381
+ ${e.description ? l`<span class="description">${e.description}</span>` : ""}
123
382
  </button>
124
383
  `;
125
384
  }
@@ -133,7 +392,7 @@ let t = class extends m {
133
392
  );
134
393
  }
135
394
  };
136
- t.styles = f`
395
+ a.styles = v`
137
396
  :host { display: none; }
138
397
  :host([open]) { display: block; position: fixed; inset: 0; z-index: 10000; }
139
398
  .overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.5); }
@@ -246,29 +505,39 @@ t.styles = f`
246
505
  .error { color: var(--pigeon-danger, #ef4444); font-size: 12px; }
247
506
  `;
248
507
  r([
249
- c({ attribute: !1 })
250
- ], t.prototype, "storage", 2);
508
+ g({ attribute: !1 })
509
+ ], a.prototype, "storage", 2);
251
510
  r([
252
- c({ type: Boolean, reflect: !0 })
253
- ], t.prototype, "open", 2);
511
+ g({ type: Boolean, reflect: !0 })
512
+ ], a.prototype, "open", 2);
254
513
  r([
255
- s()
256
- ], t.prototype, "_templates", 2);
514
+ p()
515
+ ], a.prototype, "_templates", 2);
257
516
  r([
258
- s()
259
- ], t.prototype, "_name", 2);
517
+ p()
518
+ ], a.prototype, "_name", 2);
260
519
  r([
261
- s()
262
- ], t.prototype, "_description", 2);
520
+ p()
521
+ ], a.prototype, "_description", 2);
263
522
  r([
264
- s()
265
- ], t.prototype, "_category", 2);
523
+ p()
524
+ ], a.prototype, "_category", 2);
266
525
  r([
267
- s()
268
- ], t.prototype, "_formError", 2);
269
- t = r([
270
- g("pigeon-template-picker")
271
- ], t);
526
+ p()
527
+ ], a.prototype, "_formError", 2);
528
+ a = r([
529
+ f("pigeon-template-picker")
530
+ ], a);
531
+ const C = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
532
+ __proto__: null,
533
+ get PigeonTemplatePicker() {
534
+ return a;
535
+ }
536
+ }, Symbol.toStringTag, { value: "Module" }));
272
537
  export {
273
- t as PigeonTemplatePicker
538
+ a as P,
539
+ L as c,
540
+ C as p,
541
+ T as r,
542
+ o as t
274
543
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lit-pigeon/editor",
3
- "version": "0.1.3",
3
+ "version": "0.3.0",
4
4
  "description": "Lit Web Components UI for the Pigeon email editor",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,7 +26,7 @@
26
26
  "@tiptap/pm": "^2.10.0",
27
27
  "@tiptap/starter-kit": "^2.10.0",
28
28
  "lit": "^3.1.0",
29
- "@lit-pigeon/core": "^0.1.2"
29
+ "@lit-pigeon/core": "^0.3.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "happy-dom": "^20.9.0",