efficient-web-builder 0.8.1 → 0.10.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +109 -1
  2. package/README.md +24 -5
  3. package/dist/chunks/{EditorPreviewCheckout-RALICX2M.js → EditorPreviewCheckout-5KOAA2SK.js} +3 -3
  4. package/dist/chunks/PreviewFooter-H6XJUR5S.js +1 -0
  5. package/dist/chunks/SectionEditorShell-EEZR7KFE.js +1 -0
  6. package/dist/chunks/{SiteEditorProvider-4NZYBEVE.js → SiteEditorProvider-ECGZVKLG.js} +1 -1
  7. package/dist/chunks/StorefrontEditorChrome-4TFS62GY.js +1 -0
  8. package/dist/chunks/chunk-6CP4D6VJ.js +1 -0
  9. package/dist/chunks/chunk-7QXLVNFD.js +1 -0
  10. package/dist/chunks/chunk-BJOS4Y35.js +15 -0
  11. package/dist/chunks/chunk-EIXUXJQ5.js +153 -0
  12. package/dist/chunks/chunk-H7O6ZYX6.js +1 -0
  13. package/dist/chunks/chunk-IFRGL3GL.js +1 -0
  14. package/dist/chunks/chunk-ML2AR222.js +1 -0
  15. package/dist/chunks/chunk-RRHBLOH4.js +1 -0
  16. package/dist/chunks/chunk-S6SXIMIG.js +2 -0
  17. package/dist/chunks/chunk-SNH7IFTZ.js +1 -0
  18. package/dist/chunks/chunk-Y4CZD2YY.js +230 -0
  19. package/dist/chunks/{chunk-6VNEBJKI.js → chunk-YVQUISDX.js} +1 -1
  20. package/dist/chunks/fitment-data-6NXSKODX.js +1 -0
  21. package/dist/chunks/render-client-YGYDU3K2.js +1 -0
  22. package/dist/editor.css +1 -1
  23. package/dist/index.d.ts +184 -4
  24. package/dist/index.js +920 -648
  25. package/dist/links.js +1 -1
  26. package/package.json +2 -2
  27. package/dist/chunks/PreviewFooter-SNJQZ6JZ.js +0 -1
  28. package/dist/chunks/SectionEditorShell-U5FUJW2M.js +0 -1
  29. package/dist/chunks/StorefrontEditorChrome-6OQOFCL6.js +0 -1
  30. package/dist/chunks/chunk-4MT74TMP.js +0 -1
  31. package/dist/chunks/chunk-764WH3TY.js +0 -11
  32. package/dist/chunks/chunk-CZ46NWN5.js +0 -230
  33. package/dist/chunks/chunk-DN65SLZM.js +0 -1
  34. package/dist/chunks/chunk-KZIT3J33.js +0 -1
  35. package/dist/chunks/chunk-RTCXXI5U.js +0 -143
  36. package/dist/chunks/chunk-TX7ND7AF.js +0 -1
  37. package/dist/chunks/chunk-WQ7W4AXL.js +0 -15
  38. package/dist/chunks/chunk-XMRSKZIR.js +0 -2
  39. package/dist/chunks/fitment-data-6EHBA26C.js +0 -1
  40. package/dist/chunks/render-client-ISZ5CGAI.js +0 -1
  41. /package/dist/chunks/{chunk-WQ7W4AXL.js.LEGAL.txt → chunk-BJOS4Y35.js.LEGAL.txt} +0 -0
  42. /package/dist/chunks/{chunk-RTCXXI5U.js.LEGAL.txt → chunk-EIXUXJQ5.js.LEGAL.txt} +0 -0
  43. /package/dist/chunks/{chunk-UBYBQ3KR.js → chunk-HVOO2GNE.js} +0 -0
package/dist/index.d.ts CHANGED
@@ -221,6 +221,22 @@ export type SaveExpectation = {
221
221
  };
222
222
 
223
223
  /** A set of pages: a website's, or one template's. */
224
+ /**
225
+ * A page a link can point at: enough to name it, and its layout — where its
226
+ * section anchors are read from, and how the editor tells which page holds a
227
+ * section a link may open in a particular state.
228
+ */
229
+ export interface LinkTargetPage {
230
+ id: string;
231
+ /** The page's handle. A link to the page is built from this. */
232
+ slug: string;
233
+ /** The page's name as a list shows it. */
234
+ label: string;
235
+ /** The page's layout, or null when the backend does not hand it out with the
236
+ * list. Without it the page is still a link target; its anchors are not. */
237
+ layout: PageLayout | null;
238
+ }
239
+
224
240
  export interface WebsitePages {
225
241
  /** The rows the page list navigates between. */
226
242
  list(scope?: SiteScope): Promise<EditorPageRow[]>;
@@ -244,6 +260,12 @@ export interface WebsitePages {
244
260
  create?(input: NewPageInput): Promise<EditorPageRow>;
245
261
  /** Delete a page from the page list. */
246
262
  remove?(id: string): Promise<void>;
263
+ /**
264
+ * Every page of the website a link may point at, each with its layout — in
265
+ * ONE call, for the link picker. Optional: without it the picker lists the
266
+ * rows of {@link list} and offers no section anchors.
267
+ */
268
+ linkTargets?(scope?: SiteScope): Promise<LinkTargetPage[]>;
247
269
  }
248
270
 
249
271
  /** The other operator, as the editor's notices describe them. */
@@ -310,6 +332,13 @@ export interface WebsiteMedia {
310
332
  /** RESERVED: upload a file dropped on a media field. 0.4.0 hands a dropped
311
333
  * file to the host's media panel or picker and does not call it. */
312
334
  upload?(file: File): Promise<HostPickedMedia>;
335
+ /**
336
+ * The largest file a media field takes, in bytes. A larger one is refused
337
+ * where it was dropped, with the reason, before it is handed to the host's
338
+ * media panel or picker. Without it the editor refuses no file for its size —
339
+ * the host's own picker has the say.
340
+ */
341
+ maxUploadBytes?: number;
313
342
  }
314
343
 
315
344
  /** One node of a page document: a section or a block, with its own props. */
@@ -358,13 +387,157 @@ export interface WebsitePreview {
358
387
  href(slug: string): string;
359
388
  }
360
389
 
390
+ /**
391
+ * A blog post, as the editor lists one: enough to name it, link to it and draw a
392
+ * card from it. Published posts only — a draft is not something a page links to.
393
+ */
394
+ export interface BlogPostRow {
395
+ /** The post's stable handle. A block that is linked to a post stores this. */
396
+ slug: string;
397
+ title: string;
398
+ /** The standfirst. Empty when the post has none. */
399
+ excerpt: string;
400
+ /** The post's editorial category, as its author typed it. Empty when none. */
401
+ category: string;
402
+ /** The cover picture's address, absolute — or "" when the post has none. */
403
+ coverImage: string;
404
+ /** When it was published (ISO 8601), or null. */
405
+ publishedAt: string | null;
406
+ /** Where the post lives on the website, as a path (`/journal/first-post`). */
407
+ href: string;
408
+ }
409
+
410
+ /**
411
+ * The website's blog. Optional: without it the editor lists no post — a block's
412
+ * "Blog post source" shows only what it is already linked to, and the link
413
+ * picker offers no "Blog post" (`EditorCapabilities.hasBlog`).
414
+ */
415
+ export interface WebsiteBlog {
416
+ /** The website's published posts, in the order the website lists them. */
417
+ posts(scope?: SiteScope): Promise<BlogPostRow[]>;
418
+ }
419
+
420
+ /** The website's live-chat bubble: whether it shows, and its three lines.
421
+ * A blank line means "the widget's own wording". */
422
+ export interface ChatSettings {
423
+ enabled: boolean;
424
+ title: string;
425
+ subtitle: string;
426
+ greeting: string;
427
+ }
428
+
429
+ /**
430
+ * The website's live chat. Optional: without it the editor's "Live chat" panel
431
+ * previews a change and saves nothing, and starts from the house default.
432
+ */
433
+ export interface WebsiteChat {
434
+ get(scope?: SiteScope): Promise<ChatSettings>;
435
+ /** Store the lines that changed; answer the settings as they now stand. */
436
+ update(patch: Partial<ChatSettings>, scope?: SiteScope): Promise<ChatSettings>;
437
+ }
438
+
439
+ /**
440
+ * A website's appearance as it is stored: its colour themes, type, corners,
441
+ * cards and widths — the row behind the Site styles panel. The keys are the
442
+ * stored ones. Every key but `id` and the first run is optional or nullable:
443
+ * absent and `null` both mean "not set", and the website draws the built-in
444
+ * look for it.
445
+ */
446
+ export interface SiteThemeRow {
447
+ id: string;
448
+ selected_preset: number;
449
+ theme_presets: {
450
+ text: string;
451
+ accent: string;
452
+ background?: string;
453
+ surface?: string;
454
+ line?: string;
455
+ muted?: string;
456
+ button?: string;
457
+ buttonInk?: string;
458
+ }[];
459
+ accent_color?: string | null;
460
+ heading_font: string;
461
+ body_font: string;
462
+ accent_font: string;
463
+ label_font: string;
464
+ default_mode: "light" | "dark" | "auto";
465
+ show_theme_switch: boolean;
466
+ heading_scale: number;
467
+ body_scale: number;
468
+ label_scale: number;
469
+ heading_size_large_px?: number | null;
470
+ heading_size_medium_px?: number | null;
471
+ heading_size_small_px?: number | null;
472
+ accent_size_px?: number | null;
473
+ body_size_px?: number | null;
474
+ label_size_px?: number | null;
475
+ corner_style: "square" | "small" | "large";
476
+ corner_radius_px?: number | null;
477
+ heading_compression: "normal" | "tight" | "compressed";
478
+ card_shadow?: "none" | "soft" | "lifted" | null;
479
+ shadow_color?: string | null;
480
+ card_gap: "tight" | "normal" | "roomy";
481
+ hover_effect?: "none" | "lift" | "highlight" | null;
482
+ heading_case?: "authored" | "sentence" | null;
483
+ heading_weight?: number | null;
484
+ heading_weight_strong?: number | null;
485
+ heading_2_weight?: number | null;
486
+ heading_3_weight?: number | null;
487
+ heading_2_case?: "authored" | "sentence" | null;
488
+ heading_3_case?: "authored" | "sentence" | null;
489
+ heading_max_px?: number | null;
490
+ site_width?: number | null;
491
+ site_gutter?: number | null;
492
+ block_gap?: number | null;
493
+ hero_background_follows_width?: boolean | null;
494
+ photography_grayscale?: boolean | null;
495
+ word_styles?: Partial<Record<string, Record<string, unknown> | null>> | null;
496
+ }
497
+
498
+ /** What may be written: any of a {@link SiteThemeRow} but its own id. */
499
+ export type SiteThemeRowPatch = Partial<Omit<SiteThemeRow, "id">>;
500
+
501
+ /**
502
+ * The website's appearance. Optional: without it the editor has no stored
503
+ * appearance to open on or save to — no Site styles — and a website is drawn
504
+ * in the built-in look.
505
+ */
506
+ export interface WebsiteTheme {
507
+ /** The row behind a website — its own, or the one it falls back to. Reading
508
+ * must not create one. */
509
+ get(scope?: SiteScope): Promise<SiteThemeRow>;
510
+ /** Store the keys that changed; answer the row as it now stands. */
511
+ update(patch: SiteThemeRowPatch, scope?: SiteScope): Promise<SiteThemeRow>;
512
+ }
513
+
514
+ /** The website's social profile links: one address per platform, under the
515
+ * platform's own name (`instagram`, `facebook`, …). "" where there is none. */
516
+ export type SocialLinkSettings = Record<string, string>;
517
+
518
+ /**
519
+ * The website's social links. Optional: without it the editor's Social links
520
+ * rows — and a footer's Social block — show no saved link and save none.
521
+ */
522
+ export interface WebsiteSocial {
523
+ get(scope?: SiteScope): Promise<SocialLinkSettings>;
524
+ /**
525
+ * Store the links named; answer every link as it now stands. Reject
526
+ * `invalid` with `fields` — the platform refused, and the reason to show
527
+ * beside its box — when an address is not one.
528
+ */
529
+ update(patch: SocialLinkSettings, scope?: SiteScope): Promise<SocialLinkSettings>;
530
+ }
531
+
361
532
  /**
362
533
  * Everything the editor asks a server for.
363
534
  *
364
535
  * Other groups the editor still reads from the EFFICIENT client directly — the
365
- * site's theme, header, social links and live chat, menus, blog, forms and the
366
- * catalog — join this interface as optional members when their call sites move.
367
- * Until then a backend other than EFFICIENT's gets the page editor without them.
536
+ * site's header, menus, forms and the catalog — join this interface as
537
+ * optional members when their call sites move. Until then a backend other than
538
+ * EFFICIENT's gets the page editor without them. The blog (`blog`), the live
539
+ * chat (`chat`), the social links (`social`) and the site's appearance
540
+ * (`theme`) have crossed.
368
541
  */
369
542
  export interface WebsiteBackend {
370
543
  pages: WebsitePages;
@@ -374,6 +547,10 @@ export interface WebsiteBackend {
374
547
  sectionTemplates?: WebsiteSectionTemplates;
375
548
  templates?: WebsiteTemplates;
376
549
  preview?: WebsitePreview;
550
+ blog?: WebsiteBlog;
551
+ chat?: WebsiteChat;
552
+ social?: WebsiteSocial;
553
+ theme?: WebsiteTheme;
377
554
  }
378
555
 
379
556
  /** Why a backend call failed, in the editor's own terms. */
@@ -405,10 +582,13 @@ export class WebsiteBackendError extends Error {
405
582
  readonly conflict?: SaveConflict;
406
583
  /** `lock-taken`: who holds the page. */
407
584
  readonly holder?: LockHolder;
585
+ /** `invalid`: the inputs that were refused, by name, each with the reason —
586
+ * when the backend can say which. The editor shows it beside that input. */
587
+ readonly fields?: Readonly<Record<string, string>>;
408
588
  constructor(
409
589
  kind: WebsiteBackendErrorKind,
410
590
  message?: string,
411
- detail?: { conflict?: SaveConflict; holder?: LockHolder; cause?: unknown },
591
+ detail?: { conflict?: SaveConflict; holder?: LockHolder; fields?: Readonly<Record<string, string>>; cause?: unknown },
412
592
  );
413
593
  }
414
594