efficient-web-builder 31.1.0 → 32.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/CHANGELOG.md +39 -0
- package/dist/editor/components/DuplicatePageDialog.d.ts +10 -0
- package/dist/editor/components/DuplicatePageDialog.js +1 -0
- package/dist/editor/components/PagesPanel.js +1 -1
- package/dist/editor/components/PreviewChatContext.d.ts +1 -1
- package/dist/editor/components/SectionEditor.js +1 -1
- package/dist/editor/components/StandaloneSectionEditor.js +1 -1
- package/dist/editor/components/StorefrontLinkField.d.ts +1 -1
- package/dist/editor/components/WebsitePreviewButton.d.ts +1 -1
- package/dist/editor/components/storefront-editor.css +13 -0
- package/dist/editor/components/usePinnedChromeSeed.js +1 -1
- package/dist/editor/components/useSocialSettings.js +1 -1
- package/dist/editor/components/useStorefrontBlogPosts.d.ts +1 -1
- package/dist/editor/lib/editor-document-adapter.d.ts +1 -1
- package/dist/editor/lib/page-copy.d.ts +6 -0
- package/dist/editor/lib/page-copy.js +1 -0
- package/dist/editor/lib/page-live-state.d.ts +1 -1
- package/dist/editor/lib/puck/add-palette.d.ts +0 -1
- package/dist/editor/lib/puck/add-palette.js +1 -1
- package/dist/editor/lib/puck/add-target.d.ts +0 -1
- package/dist/editor/lib/puck/blocks/general/HeroGroup/fields.js +1 -1
- package/dist/editor/lib/puck/controls.d.ts +14 -1
- package/dist/editor/lib/puck/controls.js +1 -1
- package/dist/editor/lib/puck/footer-blocks.d.ts +0 -1
- package/dist/editor/lib/puck/footer-blocks.js +1 -1
- package/dist/editor/lib/site-live-state.d.ts +1 -1
- package/dist/editor/lib/theme-row-persist.js +1 -1
- package/dist/editor/lib/website-session.d.ts +1 -1
- package/dist/format/lib/editor-words-catalogue.d.ts +6 -0
- package/dist/format/lib/editor-words-catalogue.js +2 -2
- package/dist/format/lib/puck/container-blocks.d.ts +1 -1
- package/dist/{editor → format}/lib/puck/pinned-seed-gate.d.ts +0 -1
- package/dist/format/lib/puck/pinned-seed-gate.js +1 -0
- package/dist/{editor → format}/lib/web-backend.d.ts +6 -3
- package/dist/format/lib/web-backend.js +0 -0
- package/dist/render/lib/puck/slot-specs.d.ts +0 -1
- package/package.json +3 -3
- package/dist/editor/lib/puck/pinned-seed-gate.js +0 -1
- package/dist/editor/lib/web-backend.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 32.1.0 - 2026-10-21
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Duplicate page** (Lewis, 2026-10-21: design final via GG). A merchant copies one Normal or Dynamic page into a new draft page with a new title and URL handle, from two places:
|
|
10
|
+
- the Pages panel: a hover action "Duplicate “name”" on each Normal / Dynamic row, before the pencil (not on a lightbox, the footer or a Shop row);
|
|
11
|
+
- the Page settings head: an icon button "Duplicate page", the same kind as the section head's "Duplicate section".
|
|
12
|
+
Both open ONE dialog, `components/DuplicatePageDialog` (the shell's `Dialog`, the same type as "Add a page"), with the admin page form's field names, Title and URL handle. It starts on "<title> copy" and the first free "<slug>-copy"; a URL handle another page uses blocks the button. After the copy, the editor opens it.
|
|
13
|
+
- `WebsitePages.duplicate?(id, {title, slug})` (`lib/web-backend`, with `DuplicatePageInput`): the backend makes the copy (efficient-backend `POST /storefront/pages/{id}/duplicate/`: working layout, type and folder; hidden, unpublished, no SEO strings). Optional: a backend without it shows no Duplicate action. A template's pages have none.
|
|
14
|
+
- `lib/page-copy`: which rows may be copied (`canDuplicatePage`), the suggestion (`copySuggestion`), and `usePageDuplicate`. It also holds the ONE "first free slug" rule (`uniqueSlug`): the Pages panel's add dialog had its own copy of it and of `slugify`, and now imports these.
|
|
15
|
+
|
|
16
|
+
### Guards
|
|
17
|
+
|
|
18
|
+
- `scripts/test-page-duplicate.ts` (red first): both entries, the one shell dialog and its words, the suggestion and the taken-handle block, the copy made by the backend and never in the browser, and no action without `duplicate`.
|
|
19
|
+
|
|
20
|
+
## 32.0.0 - 2026-10-21
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- **BREAKING: no builder module hands on an easel screen name** (SSOT, harness DUP-1; 31.0.0 kept six). A host imports each name from its easel subpath:
|
|
25
|
+
- `lib/web-backend` no longer exports `WebsiteBackendError`, `isBackendError`, `STATUS_UNREACHABLE`, `provideHostFailures`, `readHostFailure`, `hostLoadRefusalOf`, `hostUnreachableMessage`, `WebsiteBackendErrorKind`, `HostFailure`: take them from `efficient-easel/screen/lib/backend-error`.
|
|
26
|
+
- `lib/puck/slot-specs` no longer exports `NodeDefaults`, `SlotSectionSpec`: `efficient-easel/screen/lib/puck/slot-section-spec`.
|
|
27
|
+
- `lib/puck/add-palette` no longer exports `matchesQuery`, `PaletteSection`: `efficient-easel/screen/lib/puck/palette-sections`.
|
|
28
|
+
- `lib/puck/add-target` no longer exports `AddTarget`, `AddTargetSource`: `efficient-easel/screen/lib/puck/add-target-types`.
|
|
29
|
+
- `lib/puck/footer-blocks` no longer exports `blockRuns`, `BlockChoice`, `BlockChoiceRun`: `efficient-easel/screen/lib/puck/block-choice`.
|
|
30
|
+
- `lib/puck/pinned-seed-gate` no longer exports `resetForDocumentSwitch`, `saveStatusForNewDocument`, `saveStatusOf`, `DocumentSwitchSetters`, `SaveStatus`: `efficient-easel/screen/lib/document-switch`.
|
|
31
|
+
- **BREAKING: `lib/web-backend` and `lib/puck/pinned-seed-gate` are on the `format` side now.** With the easel re-exports gone they draw no React and import no editor package, so `scripts/entry-sides.mjs` classes them `format`, as it does every pure module (doc/adr/0005). A host imports `efficient-web-builder/format/lib/web-backend` and `efficient-web-builder/format/lib/puck/pinned-seed-gate`; the `editor/` paths are gone (`verify-published-entries`: 4 files moved). The path change goes in the host's own pull request that takes 32.0.0, because the `format/` paths exist only from this release: 5 files in efficient-storefront-blocks (`src/editor/lib/efficient-backend.ts`, `src/editor/lib/storefront-editor.ts`, `package/src/index.tsx`, `package/src/types.check.ts`, `scripts/test-template-editor-isolation.ts`) and 2 in efficient-storefront (`scripts/test-dynamic-page-own-slug-404.ts`, `scripts/test-editor-page-lock.ts`).
|
|
32
|
+
- Hosts: efficient-storefront-blocks moved in #145 (0.53.0). efficient-storefront moved 3 guard files in #1717; before it takes this release (it pins 30.1.1 now) it syncs its vendored blocks to 0.53.0 or later and moves one more line (`scripts/test-editor-page-lock.ts`, `resetForDocumentSwitch`). No admin, portal, easel, shell or CLI file named one. Each name is the same class, function or type as before. No stored value, page, setting or pixel changes.
|
|
33
|
+
- The builder's own 9 files that used them import easel directly.
|
|
34
|
+
- **The Box inside a Hero moves by two boxes, straight in its Position band** (Layered images v3, Lewis 2026-10-21: final, option 1). The two ±40px sliders `Sideways` and `Up and down` are gone. In their place: a left-and-right box and an up-and-down box (efficient-shell `PositionInput`, glyphs `nudge-x` and `nudge-y`), with no row name of their own, because the band already says Position. It is the same shell part the email designer's Layered images picture draws (there, in a panel with no Position band, the row is called `Position`). One edit writes both stored values in one write. The stored keys `nudgeX` / `nudgeY` do not move (N10.6): no page, setting or pixel changes.
|
|
35
|
+
- New builder `positionFields` (and `positionPatch`) in `lib/puck/controls`, for any part that moves by a nudge; `label: null` draws the boxes with no row.
|
|
36
|
+
- **BREAKING: the efficient-shell peer range narrows to `^8.13.0`** (peer and dev), the release with `PositionInput` and the `nudge-x` / `nudge-y` glyphs. A host on an older shell moves first.
|
|
37
|
+
|
|
38
|
+
### Guards
|
|
39
|
+
|
|
40
|
+
- `scripts/test-screen-in-easel.mjs` (red first): `PASS_THROUGH` is empty, so no file in `src/` re-exports `efficient-easel/screen` beside its own code. It failed on main with the six modules named.
|
|
41
|
+
- `scripts/test-shell-peer-range.ts`: the floor is 8.13.0.
|
|
42
|
+
- `scripts/test-hero-group-position-row.tsx` (red first): one row on `nudgeX` with both boxes in order and no slider left; `nudgeY` kept and reached by that row; one edit writes only what changed and a cleared box removes its key; a stored `nudgeX` / `nudgeY` still moves the Box.
|
|
43
|
+
|
|
5
44
|
## 31.1.0 - 2026-10-21
|
|
6
45
|
|
|
7
46
|
### Removed
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DuplicatePageInput, EditorPageRow } from "../../format/lib/web-backend.js";
|
|
2
|
+
interface Props {
|
|
3
|
+
source: EditorPageRow | null;
|
|
4
|
+
taken: ReadonlySet<string>;
|
|
5
|
+
duplicate: (row: EditorPageRow, input: DuplicatePageInput) => Promise<EditorPageRow>;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
onDuplicated: (copy: EditorPageRow) => void;
|
|
8
|
+
}
|
|
9
|
+
export default function DuplicatePageDialog({ source, taken, duplicate, onClose, onDuplicated }: Props): import("react").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as l,jsxs as S,Fragment as L}from"react/jsx-runtime";import{useId as C,useState as i}from"react";import{Button as F,Dialog as R,FormField as T,Input as k,Stack as U}from"efficient-shell/ui";import{copySuggestion as _,urlHandleTaken as K}from"../lib/page-copy.js";import{slugify as w}from"../../format/lib/slugify.js";import{say as n}from"../../format/lib/editor-words.js";function z({source:t,taken:h,duplicate:x,onClose:f,onDuplicated:I}){const g=C(),m=C(),[j,B]=i(null),[r,p]=i(""),[a,d]=i(""),[E,y]=i(!1),[o,v]=i(!1),[b,u]=i(null);if(t!==j&&(B(t),t)){const e=_(t,h);p(e.title),d(e.slug),y(!1),u(null)}const s=K(a,h),D=!!(t&&r.trim()&&a&&!s&&!o),c=async()=>{if(!(!t||!D)){v(!0),u(null);try{const e=await x(t,{title:r.trim(),slug:a});I(e)}catch{u(n("Couldn’t duplicate the page — please retry."))}finally{v(!1)}}};return l(R,{open:t!==null,onClose:()=>{o||f()},size:"sm",title:n("Duplicate “{name}”",{name:t?.label??""}),description:n("The copy is a draft and stays hidden until you publish it. It opens in the editor."),footer:S(L,{children:[l(F,{variant:"secondary",onClick:f,disabled:o,children:n("Cancel")}),l(F,{onClick:()=>{c()},disabled:!D,loading:o,children:n("Duplicate page")})]}),children:S(U,{gap:4,children:[l(T,{label:n("Title"),htmlFor:g,error:b??void 0,children:l(k,{id:g,value:r,invalid:!!b,onChange:e=>{p(e.target.value),E||d(w(e.target.value))},onKeyDown:e=>{e.key==="Enter"&&c()}})}),l(T,{label:n("URL handle"),htmlFor:m,hint:s?void 0:n("URL: /{slug}",{slug:a}),error:s?n("Another page uses this URL handle."):void 0,children:l(k,{id:m,value:a,invalid:s,onChange:e=>{y(!0),d(w(e.target.value))},onKeyDown:e=>{e.key==="Enter"&&c()}})})]})})}export{z as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as n,Fragment as
|
|
1
|
+
"use client";import{jsx as n,Fragment as J,jsxs as w}from"react/jsx-runtime";import{Fragment as be,useEffect as ye,useId as Pe,useMemo as Q,useState as c}from"react";import{useScreenDocument as ke}from"efficient-easel/screen/components/ScreenDocumentContext";import{UiIcon as S}from"efficient-easel/draw/client";import we from"efficient-easel/screen/components/SidePanelHead";import{useWebsiteName as Se}from"./WebsiteSettingsPanel.js";import{InspectorIconButton as Ce}from"efficient-easel/chrome";import{Button as V,Dialog as Ie,FormField as De,Input as X,toast as Z}from"efficient-shell/ui";import{LayersTree as Ae,TreeGroupLabel as Re,TreeRow as $,TreeRowAction as C}from"efficient-easel/tree";import{AddIcon as xe,DuplicateIcon as Ne,PageIcon as Ee}from"efficient-easel/icons";import{PagesIcon as ve}from"efficient-easel/rail";import{useEaselHost as Oe}from"efficient-easel/screen/lib/host";import{bucketEditorPageRows as Le,DYNAMIC_PAGES_GROUP_KEY as Fe,isDynamicPageRow as _e,MAIN_PAGES_GROUP as ze}from"../../format/lib/editor-page-rows.js";import{useEaselSession as Ge}from"efficient-easel/screen/lib/session-context";import{holdPageRow as F,usePageRows as Be}from"../lib/page-rows.js";import{say as t}from"../../format/lib/editor-words.js";import{canDuplicatePage as He,uniqueSlug as ee,usePageDuplicate as Me}from"../lib/page-copy.js";import Te from"./DuplicatePageDialog.js";const ne="sf-editor-pages-collapsed-groups";function Ue({onNavigate:u,onClose:te,activeSurface:_,onPreviewSurface:ae}){const h=Ge().chrome?.pageRows,z=Oe(),{adapter:I,capabilities:m,ready:G,currentSlug:B}=ke(),oe=Se(),{rows:r,reload:H,setRows:M,getRows:se}=Be(),[D,le]=c(""),[d,T]=c(!1),[b,y]=c(null),[U,P]=c(!1),[p,A]=c(""),W=Pe(),R=Me(),[ie,x]=c(null),[N,re]=c(()=>{if(typeof window>"u")return new Set;try{const e=window.localStorage.getItem(ne);return new Set(e?JSON.parse(e):[])}catch{return new Set}});ye(()=>{try{window.localStorage.setItem(ne,JSON.stringify([...N]))}catch{}},[N]);const ce=e=>re(o=>{const a=new Set(o);return a.has(e)?a.delete(e):a.add(e),a}),de=Q(()=>Le(r??[]),[r]),E=D.trim().toLowerCase(),j=e=>!E||e.toLowerCase().includes(E),ue=e=>E?!0:!N.has(e),v=Q(()=>new Set((r??[]).map(e=>e.slug)),[r]),me=()=>{if(m.pageCreationInAdminForm){z.send("storefront-editor:new-page");return}A(""),y(null),P(!0)},q=async()=>{const e=p.trim();if(!(!e||!G||d||!I.createPage)){T(!0),y(null);try{const o=await I.createPage({slug:ee(e,v),title:e,layout:{}});await H(),P(!1),A(""),u(o.slug)}catch{y(t("Couldn’t add the page — please retry."))}finally{T(!1)}}},pe=e=>{const o=r??[],a=I.deletePage;if(!G||d||!a||o.length<=1)return;const l=o.findIndex(s=>s.id===e.id),i=o.filter(s=>s.id!==e.id),g=e.slug===B;F(e.id,!0),M(i),y(null),g&&i[0]&&u(i[0].slug);const k=()=>{F(e.id,!1);const s=se()??[];if(s.some(he=>he.id===e.id))return;const f=[...s];f.splice(Math.max(0,Math.min(l,f.length)),0,e),M(f)};Z.undoable(t("Deleted “{name}”",{name:e.label}),{actionLabel:t("Undo"),commit:async s=>{await a(e.id,s),F(e.id,!1)},undo:()=>{k(),g&&u(e.slug)},onFail:()=>{k(),Z.error(t("Couldn’t delete the page — please retry."))}})},ge=e=>z.send("storefront-editor:open-page",{slug:e}),fe=e=>{if(!j(e.label))return null;const o=!_&&e.slug===B,a=m.canDeletePagesInline&&(r??[]).length>1,l=_e(e),i=e.kind==="lightbox",g=[...l?[{label:t("Dynamic"),tone:"info"}]:[],...i?[{label:t("Lightbox"),tone:"success"}]:[],...e.draft?[{label:t("draft"),tone:"draft"}]:[]],k=g.length>0?g:void 0,s=!!R&&He(e),f=s||m.pageCreationInAdminForm||a?w(J,{children:[s&&n(C,{kind:"plain",label:t("Duplicate “{name}”",{name:e.label}),disabled:d,onClick:()=>x(e),children:n(Ne,{size:13})}),m.pageCreationInAdminForm&&n(C,{kind:"plain",label:t("Edit “{name}” in {place}",{name:e.label,place:t("the admin")}),onClick:()=>ge(e.slug),children:n(S,{name:"pencil",size:13,strokeWidth:1.7,rounded:!0})}),a&&n(C,{kind:"delete",label:t("Delete “{name}”",{name:e.label}),disabled:d,onClick:()=>pe(e),children:n(S,{name:"trash",size:13,strokeWidth:1.7,rounded:!0})})]}):void 0;return n($,{icon:n(Ee,{size:14}),name:e.label,selected:o,onSelect:()=>u(e.slug),badge:k,actions:f,rowProps:{"data-page-slug":e.slug}},e.id)},O=(e,o,a)=>{const l=a.filter(Boolean);if(l.length===0)return null;const i=ue(e);return w(be,{children:[n(Re,{count:l.length,expanded:i,onToggle:()=>ce(e),children:o}),i&&l]},e)},K=(h?.rows??[]).filter(e=>j(e.label)).map(e=>{const o=_===e.key;return n($,{icon:e.icon,name:e.label,selected:o,onSelect:()=>ae(e.key),badge:{label:t("Preview"),tone:"warning"},actions:n(C,{kind:"plain",label:t("Open the {name} in a new tab",{name:e.label}),onClick:()=>window.open(e.href,"_blank","noopener,noreferrer"),children:n(S,{name:"external-link",size:13,strokeWidth:1.7,rounded:!0})}),rowProps:{"data-shop-surface":e.key}},e.key)}),Y=m.hasSiteSettings&&!!h,L=(()=>{if(r===null)return null;const e=[];let o=!1;for(const a of de){Y&&!o&&a.key.startsWith("system:")&&(e.push(O("shop",h.title,K)),o=!0);const l=a.key===Fe||a.label===ze?t(a.label):a.label;e.push(O(a.key,l,a.rows.map(fe)))}return Y&&!o&&e.push(O("shop",h.title,K)),e})();return w("div",{className:"sf-pages",children:[n(we,{icon:n(ve,{}),title:t("Pages"),context:oe,actions:n(Ce,{label:t("New page"),onClick:me,children:n(xe,{size:15})}),onHide:te}),n("div",{className:"sf-pages-find",children:n(X,{type:"search",leftIcon:n(S,{name:"search",size:14,rounded:!0}),placeholder:t("Search all pages…"),value:D,onChange:e=>le(e.target.value),"aria-label":t("Search all pages")})}),b&&!U&&n("div",{className:"sf-note sf-note--error",role:"alert",children:b}),L===null?n("div",{className:"sf-note",children:t("Loading…")}):L.some(Boolean)?n(Ae,{ariaLabel:t("Pages"),className:"sf-scroll",children:L}):n("div",{className:"sf-note",children:D.trim()?t("No pages match your search"):t("No pages yet. Add one with + above.")}),R&&n(Te,{source:ie,taken:v,duplicate:R,onClose:()=>x(null),onDuplicated:e=>{x(null),H(),u(e.slug)}}),n(Ie,{open:U,onClose:()=>P(!1),size:"sm",title:t("Add a page"),description:t("Give the new template page a name. It starts blank — add sections once it opens."),footer:w(J,{children:[n(V,{variant:"secondary",onClick:()=>P(!1),children:t("Cancel")}),n(V,{onClick:()=>{q()},disabled:d||!p.trim(),loading:d,children:t("Add page")})]}),children:n(De,{label:t("Page name"),htmlFor:W,hint:p.trim()?t("URL: /{slug}",{slug:ee(p,v)}):void 0,error:b??void 0,children:n(X,{id:W,value:p,invalid:!!b,onChange:e=>A(e.target.value),onKeyDown:e=>{e.key==="Enter"&&q()},placeholder:t("e.g. About")})})})]})}export{Ue as default};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import type { ChatSettings } from "
|
|
2
|
+
import type { ChatSettings } from "../../format/lib/web-backend.js";
|
|
3
3
|
import { type ChatLauncherPosition } from "../../format/lib/content/chat-launcher.js";
|
|
4
4
|
export type ChatPreview = {
|
|
5
5
|
enabled: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as n,jsxs as
|
|
1
|
+
"use client";import{jsx as n,jsxs as m,Fragment as k}from"react/jsx-runtime";import{useState as K}from"react";import{useEasel as Se}from"efficient-easel/easel";import{headWords as W,InspectorHead as be,InspectorIconButton as L}from"efficient-easel/chrome";import{DuplicateIcon as j,TrashIcon as ke}from"efficient-easel/icons";import{panelFieldsOf as Pe}from"efficient-easel/screen/lib/puck/panel-fields";import{TICKER_PART_LABEL as U}from"../../render/components/PreviewTickerContext.js";import ve from"./SectionIcon.js";import{PanelHideButton as O}from"efficient-easel/screen/components/SidePanelHead";import{useEaselSession as Ie}from"efficient-easel/screen/lib/session-context";import{say as o}from"../../format/lib/editor-words.js";import Ee,{HintsToggle as ye,SHOW_HINTS_DEFAULT as Le}from"./WebsiteSettingsPanel.js";import Oe from"./ChatSettingsPanel.js";import Ne from"./SocialLinksPanel.js";import Te from"./TickerSettingsPanel.js";import He,{PartSourceNote as De}from"./PartSettingsPanel.js";import _e from"./DuplicateToPageMenu.js";import Re from"./DuplicatePageDialog.js";import{canDuplicatePage as Ae,usePageDuplicate as Ce}from"../lib/page-copy.js";import{usePageRows as Fe}from"../lib/page-rows.js";import{useScreenDocument as xe}from"efficient-easel/screen/components/ScreenDocumentContext";import{usePreviewHeader as Be}from"../../render/components/PreviewHeaderContext.js";import{useSectionOps as Me}from"efficient-easel/screen/lib/puck/use-section-ops";import{SELECTION_MODE as ze}from"efficient-easel/screen/lib/screen-parts";import{usePreviewParts as Ke}from"efficient-easel/draw/client";import{entryPartsOf as We,SectionTextEntries as je}from"./SectionTextEntries.js";import{SectionTextSuppressProvider as Ue}from"../lib/puck/section-text-suppress.js";import{HEADER_TYPE as Ye,ROOT_ZONE as Y}from"efficient-easel/draw";import{websiteDuplicateBlocked as Ze}from"../lib/puck/every-page.js";import{FOOTER_TYPE as N}from"../lib/puck/footer-blocks.js";import $e from"./SwitchToBoxFooter.js";import{SiteFields as Z}from"./SiteFields.js";import qe from"./HeroPartPanel.js";import{HERO_MEDIA_PART_LABELS as Ge,HERO_PART_MODE as Je,heroPartLabel as Qe}from"../../render/lib/puck/hero-media-parts.js";import{SettingsSwitch as Ve}from"efficient-easel/panel";import{foldTopTier as Xe}from"../lib/puck/field-groups.js";import{FoldHeadingScope as et}from"../lib/puck/panel-heading-scope.js";import{partRowField as tt}from"../lib/puck/part-row-field.js";import{decodePartKey as nt,partRowHeadLabel as ot}from"../../render/lib/puck/part-rows.js";import{encodePartId as it,partHeadLabel as rt,partLabel as st,sectionTextParts as at}from"../../render/lib/puck/text-parts.js";import{partSourceOf as lt,sourceMenuIdOf as ct,sourceSlugOf as dt}from"../../format/lib/puck/source-bound-parts.js";const an=ze,ln={kind:"header"},cn={kind:"website"},dn={kind:"chat"},pn={kind:"social"},w="Part";function pt(e){return o("Part of {name}",{name:o(e)})}function mt(e,i,r){const l=e.describeNode(i);return{name:r,kindLabel:l?pt(l.label):o(w)}}function ut(e){switch(e){case"Header":return{title:o("Header settings belong to a website."),own:o("Each website created from this template sets its own header afterwards.")};case"Appearance":return{title:o("Appearance settings belong to a website."),own:o("Each website created from this template sets its own appearance afterwards.")};case"Live chat":return{title:o("Live chat settings belong to a website."),own:o("Each website created from this template sets its own live chat afterwards.")};case"Social link":return{title:o("Social link settings belong to a website."),own:o("Each website created from this template sets its own social link afterwards.")};default:return{title:o("{what} settings belong to a website.",{what:e}),own:o("Each website created from this template sets its own {what} afterwards.",{what:e.toLowerCase()})}}}function $({what:e}){const i=ut(e);return m("div",{className:"sf-note",children:[n("p",{children:n("strong",{children:i.title})}),m("p",{children:[o("A template is a blueprint — it has no website of its own, so there is nothing here to change.")," ",i.own]})]})}function T(e){const i=Je[e];return{name:Ge[e],kindLabel:w,icon:i,head:(r,l)=>{if(r.kind!==i)return null;const p=l.describeNode(r.nodeId);if(!p)return null;const u=W({name:o(Qe(e,p.props)),tier:"part",of:o(p.label)},{partOf:({name:d})=>o("Part of {name}",{name:d})});return{name:u.name,kindLabel:u.kind}},render:(r,l)=>r.kind===i?n(qe,{nodeId:r.nodeId,part:e,sectionName:l.describeNode(r.nodeId)?.label??"Hero",onUpToSection:()=>l.onSelectNode(r.nodeId)}):null}}const ft={header:{name:"Header",kindLabel:"Site settings",icon:"header",render:(e,i)=>{const r=i.hostPanels?.header;return r?n(r,{placeholderMode:i.capabilities.placeholderFrames,tokenRef:i.tokenRef,siteId:i.siteId,websiteName:i.websiteName,onOpenWebsiteSettings:i.onOpenWebsiteSettings,onAuthExpired:()=>i.notifyParent("storefront-editor:auth-expired")}):null}},website:{name:"Appearance",kindLabel:"Site settings",icon:"website",render:(e,i)=>n(Ee,{themeFromDocument:!i.capabilities.hasSiteTheme,tokenRef:i.tokenRef,siteId:i.siteId,onNotify:i.onNotify})},chat:{name:"Live chat",kindLabel:"Site settings",icon:"chat",render:()=>n(Oe,{})},social:{name:"Social links",kindLabel:"Site settings",icon:"social",render:()=>n(Ne,{unavailable:n($,{what:"Social link"})})},ticker:{name:U,kindLabel:w,icon:"ticker",head:(e,i)=>e.kind==="ticker"?mt(i,e.heroId,o(U)):null,render:e=>n(Te,{heroId:e.kind==="ticker"?e.heroId:""})},heroMedia:T("media"),heroImage:T("image"),heroImage2:T("image2"),part:{name:w,kindLabel:w,icon:"Text",head:(e,i)=>{if(e.kind!=="part")return null;const r=i.describeNode(e.nodeId);if(!r)return null;const{key:l,row:p}=nt(e.propKey),u=p?tt(r.fields[l],p):r.fields[l],d=ot(o(rt(st(u??{},l))),p),f=W({name:d,tier:"part",of:o(r.label)},{partOf:({name:S})=>o("Part of {name}",{name:S})});return{name:f.name,kindLabel:f.kind}},render:(e,i)=>e.kind==="part"?n(He,{nodeId:e.nodeId,propKey:e.propKey,onBack:()=>i.onSelectNode(e.nodeId),onEditStyle:i.onOpenSiteStyles}):null}},ht=new Set(["header","website","chat"]);function gt(e,i){if(e==="puck")return null;const r=ft[e];return ht.has(e)&&!i.hasSiteSettings?{...r,kindLabel:"Not part of a template",render:()=>n($,{what:r.name})}:r}function wt({mode:e,onOpenWebsiteSettings:i,onOpenSiteStyles:r,onSelectNode:l,hideNodeActions:p=!1,onNotify:u,onHidePanel:d}){const{capabilities:f,tokenRef:S,notifyParent:q,currentSlug:H,siteId:P,runAuthed:G,readOnly:J,navigate:Q}=xe(),v=Ce(),{rows:D,reload:V}=Fe(),I=D?.find(a=>a.slug===H)??null,[X,E]=K(null),{websiteName:ee}=Be(),b=Me({readOnly:J}),{select:te}=Ke(),{selectedItem:t,getItemById:ne,getSelectorForId:oe,config:h,appState:ie}=Se(a=>a),re=Pe(h,t?{type:t.type,props:t.props}:null),_=t?at(re??h.components[t.type]?.fields,t.props):[],se=a=>h.components[a]?.label??a,s=t?oe(t.props.id):void 0,c=gt(e.kind,f),ae=Ie(),R={capabilities:f,tokenRef:S,hostPanels:ae.chrome?.panels,describeNode:a=>{const g=ne(a);if(!g)return null;const z=h.components[g.type];return{type:g.type,label:z?.label??g.type,fields:z?.fields??{},props:g.props??{}}},siteId:P,websiteName:ee??null,notifyParent:q,onNotify:u,onOpenWebsiteSettings:i,onOpenSiteStyles:r,onSelectNode:l},A=c?.head?.(e,R)??null,le=A?.name??(c?o(c.name):t?o(se(t.type)):o("Page settings")),ce=A?.kindLabel??(c?o(c.kindLabel):t?s&&s.zone!==Y?o("Block"):o("Section"):o("Page")),de=c?c.icon:t?t.type:"page",C=c?null:t?h.components[t.type]?.fields??null:h.root?.fields??null,pe=C?Xe(C):2,F=e.kind==="puck"&&t?lt(t.type):null,me=!!t&&!!s&&s.zone===Y&&t.type!==N&&t.type!==Ye,y=Ze(ie?.data,t),ue=()=>{y||s&&b.duplicateComponent(s.zone,s.index)},fe=()=>{s&&(b.removeComponent(s.zone,s.index),b.select(null))},he=t?h.components[t.type]?.defaultProps?.previewHover:void 0,x=e.kind==="puck"&&!!t&&!!s&&he!==void 0,B=x&&t.props.previewHover===!0,ge=()=>{!t||!s||b.replaceComponent(s.zone,s.index,{...t,props:{...t.props,previewHover:!B}})},[M,we]=K(Le);return m("div",{className:`es-sidepanel es-sidepanel--right sf-panel sf-panel--right${M||!(!c&&!!t)?"":" sf-hints-folded"}`,children:[n(be,{icon:n(ve,{type:de,size:15}),name:le,kind:ce,actions:!p&&e.kind==="puck"&&t&&t.type!==N?m(k,{children:[n(L,{label:o("Duplicate section"),title:y??void 0,disabled:y!==null,onClick:ue,children:n(j,{size:15})}),me&&f.hasSiteSettings&&n(_e,{node:t,currentSlug:H,siteId:P??void 0,tokenRef:S,runAuthed:G,onNotify:u}),n(L,{label:o("Remove section"),danger:!0,onClick:fe,children:n(ke,{size:15})}),d?n(O,{side:"right",onHide:d,divider:!0}):null]}):!c&&!t&&e.kind==="puck"&&v&&I&&Ae(I)?m(k,{children:[n(L,{label:o("Duplicate page"),onClick:()=>E(I),children:n(j,{size:15})}),d?n(O,{side:"right",onHide:d,divider:!0}):null]}):d?n(O,{side:"right",onHide:d}):void 0}),v&&n(Re,{source:X,taken:new Set((D??[]).map(a=>a.slug)),duplicate:v,onClose:()=>E(null),onDuplicated:a=>{E(null),V(),Q({kind:"page",slug:a.slug,siteId:P??void 0})}}),x&&m("div",{className:"sf-preview-pin",children:[m("div",{className:"sf-preview-pin-text",children:[n("span",{className:"sf-preview-pin-label",children:o("Preview hover state")}),n("span",{className:"sf-preview-pin-hint",children:o("not shown live")})]}),n(Ve,{checked:B,onChange:ge,ariaLabel:o("Preview hover state")})]}),n(et,{tier:pe,children:n("div",{className:"sf-insp-body es-insp-body sf-scroll",children:c?c.render(e,R):t?m(k,{children:[t.type===N&&f.hasSiteSettings&&n($e,{}),n(Ue,{children:n(Z,{entries:n(je,{parts:_,heading:!1,onOpen:a=>te(it(t.props.id,a))}),entryCount:We(_).length})}),F&&n(De,{source:F,slug:dt(t?.props),menuId:ct(t?.props)}),n(ye,{shown:M,onChange:we})]}):n(k,{children:n(Z,{})})})})]})}export{dn as CHAT_MODE,ln as HEADER_MODE,an as PUCK_MODE,pn as SOCIAL_MODE,cn as WEBSITE_MODE,wt as default,gt as resolvePanel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as o}from"react/jsx-runtime";import{useCallback as H,useEffect as S,useMemo as l,useRef as V,useState as u}from"react";import x from"next/dynamic";import"efficient-easel/easel.css";import"efficient-easel/shell.css";import"efficient-easel/rail.css";import"efficient-easel/panel.css";import"efficient-easel/fields.css";import"efficient-easel/pick.css";import"efficient-easel/copy.css";import"efficient-easel/gold.css";import"efficient-easel/text-styles.css";import"efficient-easel/menu.css";import"efficient-easel/chrome.css";import"efficient-easel/tree.css";import"efficient-easel/screen.css";import"./storefront-editor.css";import{buildConfig as X}from"../lib/puck/build-config.js";import{withTemplateMediaPlaceholders as Z}from"../../format/lib/puck/templateFields.js";import{setEditorPageSlug as R}from"../../format/lib/puck/editor-page-context.js";import{ScreenDocumentContext as $}from"efficient-easel/screen/components/ScreenDocumentContext";import{PreviewHeaderProvider as ee}from"../../render/components/PreviewHeaderContext.js";import{PreviewTickerProvider as te}from"../../render/components/PreviewTickerContext.js";import{PreviewHeroPartProvider as re}from"../../render/components/PreviewHeroPartContext.js";import{PreviewPartsProvider as oe}from"efficient-easel/draw/client";import{PreviewLocationPartProvider as ie}from"../../render/components/PreviewLocationPartContext.js";import{PreviewPartStyleProvider as ne}from"./PreviewPartStyleContext.js";import{sectionTemplates as O}from"efficient-easel/screen/lib/section-templates";import{nodeToDoc as se,docToNode as B}from"efficient-easel/screen/lib/puck/section-doc";import{newNodeId as de}from"efficient-easel/draw";import{migrateRenamedProps as ae}from"../../format/lib/puck/renamed-props.js";import{buildSlotSeedChildren as ce}from"../../render/lib/puck/slot-specs.js";import{FOOTER_TYPE as me,buildDefaultFooterBlocks as le}from"../lib/puck/footer-blocks.js";import{NO_BRIDGED_CAPABILITIES as ue,useAdminBridge as fe}from"efficient-easel/screen/lib/admin-bridge";import{useEaselHost as pe}from"efficient-easel/screen/lib/host";import{ChromeWrap as ve}from"efficient-easel/screen/lib/host-chrome";import{sessionRegistry as ge}from"efficient-easel/screen/lib/session";import{useEaselSession as he}from"efficient-easel/screen/lib/session-context";import{say as F}from"../../format/lib/editor-words.js";import{retargetWhenSaved as Se}from"../../format/lib/section-retarget.js";import{routeSharedHostMessage as Pe}from"efficient-easel/screen/lib/host-inbound";import{routeWebsiteHostMessage as Ee}from"../../format/lib/website-host-inbound.js";import{DEFAULT_THEME_MODE as P,THEME_MODE_KEY as ye}from"../../format/lib/theme.js";import{makeSitePageAdapter as L}from"../lib/editor-document-adapter.js";import{documentPermissions as Te}from"efficient-easel/edit-lock";import{useAutosave as we}from"efficient-easel/autosave";import{saveStatusOf as Ne}from"
|
|
1
|
+
"use client";import{jsx as o}from"react/jsx-runtime";import{useCallback as H,useEffect as S,useMemo as l,useRef as V,useState as u}from"react";import x from"next/dynamic";import"efficient-easel/easel.css";import"efficient-easel/shell.css";import"efficient-easel/rail.css";import"efficient-easel/panel.css";import"efficient-easel/fields.css";import"efficient-easel/pick.css";import"efficient-easel/copy.css";import"efficient-easel/gold.css";import"efficient-easel/text-styles.css";import"efficient-easel/menu.css";import"efficient-easel/chrome.css";import"efficient-easel/tree.css";import"efficient-easel/screen.css";import"./storefront-editor.css";import{buildConfig as X}from"../lib/puck/build-config.js";import{withTemplateMediaPlaceholders as Z}from"../../format/lib/puck/templateFields.js";import{setEditorPageSlug as R}from"../../format/lib/puck/editor-page-context.js";import{ScreenDocumentContext as $}from"efficient-easel/screen/components/ScreenDocumentContext";import{PreviewHeaderProvider as ee}from"../../render/components/PreviewHeaderContext.js";import{PreviewTickerProvider as te}from"../../render/components/PreviewTickerContext.js";import{PreviewHeroPartProvider as re}from"../../render/components/PreviewHeroPartContext.js";import{PreviewPartsProvider as oe}from"efficient-easel/draw/client";import{PreviewLocationPartProvider as ie}from"../../render/components/PreviewLocationPartContext.js";import{PreviewPartStyleProvider as ne}from"./PreviewPartStyleContext.js";import{sectionTemplates as O}from"efficient-easel/screen/lib/section-templates";import{nodeToDoc as se,docToNode as B}from"efficient-easel/screen/lib/puck/section-doc";import{newNodeId as de}from"efficient-easel/draw";import{migrateRenamedProps as ae}from"../../format/lib/puck/renamed-props.js";import{buildSlotSeedChildren as ce}from"../../render/lib/puck/slot-specs.js";import{FOOTER_TYPE as me,buildDefaultFooterBlocks as le}from"../lib/puck/footer-blocks.js";import{NO_BRIDGED_CAPABILITIES as ue,useAdminBridge as fe}from"efficient-easel/screen/lib/admin-bridge";import{useEaselHost as pe}from"efficient-easel/screen/lib/host";import{ChromeWrap as ve}from"efficient-easel/screen/lib/host-chrome";import{sessionRegistry as ge}from"efficient-easel/screen/lib/session";import{useEaselSession as he}from"efficient-easel/screen/lib/session-context";import{say as F}from"../../format/lib/editor-words.js";import{retargetWhenSaved as Se}from"../../format/lib/section-retarget.js";import{routeSharedHostMessage as Pe}from"efficient-easel/screen/lib/host-inbound";import{routeWebsiteHostMessage as Ee}from"../../format/lib/website-host-inbound.js";import{DEFAULT_THEME_MODE as P,THEME_MODE_KEY as ye}from"../../format/lib/theme.js";import{makeSitePageAdapter as L}from"../lib/editor-document-adapter.js";import{documentPermissions as Te}from"efficient-easel/edit-lock";import{useAutosave as we}from"efficient-easel/autosave";import{saveStatusOf as Ne}from"efficient-easel/screen/lib/document-switch";import{blocksOf as ke}from"../lib/website-session.js";const Ce=x(()=>import("./SiteEditorProvider.js"),{ssr:!1}),Ae=x(()=>import("efficient-easel/screen/components/SectionScreenShell"),{ssr:!1}),U="HeroSingle",W="Untitled section";function Ie(i,E){const d=E.components,r=d[i]?i:U,y=d[r]?.defaultProps??{},n=ce(r,f=>d[f]?.defaultProps??{}),s=r===me?{blocks:le()}:null;return{type:r,props:{id:de(r),...y,...n?{[n.slot]:n.children}:null,...s}}}function Oe(){if(typeof window>"u")return P;try{const i=window.localStorage.getItem(ye);return i==="light"||i==="dark"||i==="auto"?i:P}catch{return P}}function be({id:i,initialType:E,initialName:d=W}){const[r,y]=u(i),n=V(r);S(()=>{n.current=r},[r]);const s=pe(),[f,Y]=u(E),[b,j]=u(d),[a,T]=u(void 0),[K,G]=u(P),{token:w,tokenRef:M}=fe({onMessage:e=>{if(Ee(e)||Pe(e))return;const t=e;if(t?.type==="storefront-editor:navigate"&&t.target?.kind==="section"&&t.target.id){const I=t.target.id;if(I===n.current)return;const J=t.target.type,Q=t.target.name;Se(k,()=>{Y(J),j(Q||W),y(I),s.address.show({kind:"section",id:I})},()=>s.send("storefront-editor:save-failed"))}}}),N=we({save:e=>O.update(e.id,e.node).then(()=>{}),onFailure:(e,t)=>{t===0&&s.send("storefront-editor:save-failed")}}),{state:p,push:D,flush:k}=N;S(()=>G(Oe()),[]);const c=he(),v=c.usesBridgedToken?!!w:!0,g=l(()=>X(ge(c),ke(c)),[c]);S(()=>{if(!v)return;let e=!1;return T(void 0),O.ensure(r,b,Ie(f??U,g)).then(t=>!e&&T(t.node)).catch(()=>!e&&T(null)),()=>{e=!0}},[r,f,b,v,g]);const C=H(e=>{s.send("storefront-editor:dirty");const t=B(e);t&&D({id:n.current,node:t})},[D,s]),h=s.send,_=H(async e=>{try{return await e(M.current??""),!0}catch{return h("storefront-editor:save-failed"),!1}},[h]),q=l(()=>Z(g,!0),[g]);S(()=>(R(null),()=>R(null)),[]);const m=l(()=>a?ae(se(a)):null,[a]),A=l(()=>({target:{kind:"page",slug:""},adapter:L(void 0),capabilities:L(void 0).capabilities,templateId:null,currentSlug:"",currentKind:null,siteId:null,ready:v,token:w,tokenRef:M,notifyParent:h,runAuthed:_,docId:r,data:m,getLiveData:()=>m,footerOriginSlug:null,error:null,redirecting:!1,saveStatus:Ne(p),saveState:p,autoSaveEnabled:!0,autoSaveStoppedByConflict:!1,hasUnsavedEdits:p.pending,toggleAutoSave:()=>{},retrySave:()=>{N.retryNow()},onChange:C,flushSave:k,onPublish:async e=>{const t=B(e);t&&await O.update(n.current,t)},bridgeCapabilities:ue,access:{kind:"editing"},readOnly:!1,takeOverEditing:()=>{},viewReadOnly:()=>{},saveConflict:null,reloadFromServer:()=>{},navigate:()=>{},pendingNav:null,cancelPendingNav:()=>{},discardAndNavigate:()=>{},saveAndNavigate:async()=>{}}),[r,v,w,h,_,m,p,C,k,N.retryNow]),z=l(()=>Te(!A.readOnly),[A.readOnly]);return a===void 0?o("div",{className:"sf-msg",children:F("Loading…")}):a===null||!m?o("div",{className:"sf-msg sf-msg--error",children:F("Couldn’t open this section.")}):o($.Provider,{value:A,children:o(ee,{themeMode:K,chromePlaceholder:!0,children:o(ve,{wrap:c.chrome?.wrap,surface:"section",children:o(te,{children:o(re,{children:o(oe,{children:o(ie,{children:o(ne,{children:o(Ce,{config:q,data:m,onChange:C,permissions:z,children:o(Ae,{})},r)})})})})})})})})}export{be as default};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type React from "react";
|
|
2
|
-
import type { BlogPostRow, LinkTargetPage } from "
|
|
2
|
+
import type { BlogPostRow, LinkTargetPage } from "../../format/lib/web-backend.js";
|
|
3
3
|
import { type LinkFilters, type LinkPickerSetupInput } from "../../format/lib/links/link-picker-setup.js";
|
|
4
4
|
export declare const loadPages: (key?: string) => Promise<LinkTargetPage[]>;
|
|
5
5
|
export declare const loadPosts: (key?: string) => Promise<BlogPostRow[]>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WebsitePreview } from "
|
|
1
|
+
import type { WebsitePreview } from "../../format/lib/web-backend.js";
|
|
2
2
|
type DraftLink = NonNullable<WebsitePreview["draftLink"]>;
|
|
3
3
|
type Opener = Pick<Window, "open">;
|
|
4
4
|
export declare function openDraftPreview({ pageId, liveHref, draftLink, win, }: {
|
|
@@ -1955,6 +1955,19 @@
|
|
|
1955
1955
|
white-space: nowrap;
|
|
1956
1956
|
}
|
|
1957
1957
|
|
|
1958
|
+
/* The Position boxes with no row of their own (the Hero Box, Lewis 2026-10-21):
|
|
1959
|
+
the two boxes, then the shared ↺ reset at the end of the same line — the
|
|
1960
|
+
band above already names them, so there is no label row to hold the reset. */
|
|
1961
|
+
.sf-position-line {
|
|
1962
|
+
display: flex;
|
|
1963
|
+
align-items: center;
|
|
1964
|
+
gap: 8px;
|
|
1965
|
+
}
|
|
1966
|
+
.sf-position-line > :first-child {
|
|
1967
|
+
flex: 1;
|
|
1968
|
+
min-width: 0;
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1958
1971
|
/* Text field with a visibility eye: leading type glyph · label · trailing eye.
|
|
1959
1972
|
The eye flips a stored `hidden` flag that drops the element from the slide
|
|
1960
1973
|
render — see controls.tsx. The input stays editable (dimmed) while hidden. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useEffect as G,useRef as L}from"react";import{createNode as x,newId as z}from"efficient-easel/data";import{useEaselApi as U}from"efficient-easel/easel";import{useScreenDocument as Z}from"efficient-easel/screen/components/ScreenDocumentContext";import{SITE_FOOTER_SLUG as H}from"../../format/lib/content/footer.js";import{boxFooterFromFooter as B}from"../../format/lib/puck/box-footer.js";import{ROOT_ZONE as l,missingPinnedTypes as j,pinnedDuplicateIds as D}from"efficient-easel/draw";import{FOOTER_TYPE as c,HEADER_TYPE as p,buildDefaultFooterBlocks as P,buildDefaultHeaderNode as E}from"../lib/puck/footer-blocks.js";import{canSeedPinnedChrome as q}from"
|
|
1
|
+
"use client";import{useEffect as G,useRef as L}from"react";import{createNode as x,newId as z}from"efficient-easel/data";import{useEaselApi as U}from"efficient-easel/easel";import{useScreenDocument as Z}from"efficient-easel/screen/components/ScreenDocumentContext";import{SITE_FOOTER_SLUG as H}from"../../format/lib/content/footer.js";import{boxFooterFromFooter as B}from"../../format/lib/puck/box-footer.js";import{ROOT_ZONE as l,missingPinnedTypes as j,pinnedDuplicateIds as D}from"efficient-easel/draw";import{FOOTER_TYPE as c,HEADER_TYPE as p,buildDefaultFooterBlocks as P,buildDefaultHeaderNode as E}from"../lib/puck/footer-blocks.js";import{canSeedPinnedChrome as q}from"../../format/lib/puck/pinned-seed-gate.js";import{siteFooterDocChrome as J,SITE_FOOTER_TYPE as f}from"../../format/lib/puck/section-groups.js";import{inPlaceSeedPlan as K}from"../lib/puck/pinned-in-place-seed.js";function se(t,F){const{adapter:k,capabilities:T,currentSlug:O,docId:u,data:y,saveStatus:I}=Z(),{hasSiteSettings:N,hasPinnedChrome:b}=T,C=!!T.editsPinnedInPlace&&O!==H,R=O===H,_=U().getState,v=L(null);G(()=>{if(!q({docId:u,saveStatus:I,seededDocId:v.current})||(v.current=u,!b))return;const m=_().appState.data,o=m.content,a=y?.content??[],d=(e,n)=>e.some(r=>r?.type===n);if(!N){const e=new Set(D(o)),n=e.size?o.filter(s=>!e.has(s.props.id)):o;e.size&&t.setDocument({...m,content:n});const r=j(n,a);if(r.includes(c)){const s=n.length,i=t.insertSection(c,s);t.replaceComponent(l,s,{type:c,props:{id:i,blocks:P()}})}r.includes(p)&&t.insertNode(l,0,E());return}if(R){const e=J(o);if(e!==o&&t.setDocument({...m,content:[...e]}),!e.find(r=>r.type===c)&&!d(a,c)&&!d(e,f)&&!d(a,f)){const r=(i,g)=>x(F,i,g),s={type:c,props:{blocks:P()}};t.insertNode(l,e.length,B(s,r,z(f)))}return}if(C){const e=!!k?.pinnedChrome?.state().docId,n=K(o,{hasChromeDoc:e}),r=new Set([...n.remove,...D(o.filter(i=>!n.remove.includes(String(i.props.id))))]),s=r.size?o.filter(i=>!r.has(String(i.props.id))):o;if(s.length!==o.length&&t.setDocument({...m,content:s}),n.seedFooter&&!d(a,c)&&!d(a,f)){const i=(Y,A)=>x(F,Y,A),g={type:c,props:{blocks:P()}};t.insertNode(l,s.length,B(g,i,z(f)))}if(n.seedHeader&&!d(a,p)){const i=s[0]?.type==="SiteHeader"?1:0;t.insertNode(l,i,E())}return}const h=o.filter(e=>e.type!==c),w=new Set(D(h)),S=w.size?h.filter(e=>!w.has(e.props.id)):h;S.length!==o.length&&t.setDocument({...m,content:S}),!d(S,p)&&!d(a,p)&&t.insertNode(l,0,E())},[u,I,y,_,t,N,b,R,C,k])}export{se as usePinnedChromeSeed};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useCallback as d,useEffect as p,useMemo as v,useRef as h,useState as A}from"react";import{EMPTY_SOCIAL_ROWS as L}from"../../render/components/PreviewSocialContext.js";import{SOCIAL_PLATFORMS as O,normalizeSocialLinks as C}from"../../format/lib/content/social-links.js";import{refreshSiteLiveState as w}from"../lib/site-live-state.js";import{backendOf as y}from"../lib/website-session.js";import{useEaselSession as _}from"efficient-easel/screen/lib/session-context";import{WebsiteBackendError as g}from"
|
|
1
|
+
"use client";import{useCallback as d,useEffect as p,useMemo as v,useRef as h,useState as A}from"react";import{EMPTY_SOCIAL_ROWS as L}from"../../render/components/PreviewSocialContext.js";import{SOCIAL_PLATFORMS as O,normalizeSocialLinks as C}from"../../format/lib/content/social-links.js";import{refreshSiteLiveState as w}from"../lib/site-live-state.js";import{backendOf as y}from"../lib/website-session.js";import{useEaselSession as _}from"efficient-easel/screen/lib/session-context";import{WebsiteBackendError as g}from"efficient-easel/screen/lib/backend-error";const F="Could not save this link. Check your connection and try again.";function R(n,e){if(!(n instanceof g)||n.kind!=="invalid")return null;const s=n.fields?.[e];return typeof s=="string"&&s.trim()?s:null}function T(n){return Object.fromEntries(O.map(e=>[e,{value:n[e]??"",error:null}]))}function D({token:n,siteId:e,enabled:s}){const[i,c]=A(L),m=h(null),a=h(!1),b=_(),t=y(b).social,o=s&&!!n&&!!e&&!!t;p(()=>{if(!o||!n||!e||!t)return;m.current!==e&&(m.current=e,a.current=!1,c(L));let r=!1;return t.get({siteId:e}).then(l=>{!r&&!a.current&&c(T(l))}).catch(()=>{}),()=>{r=!0}},[o,n,e,t]);const S=d(async(r,l)=>{if(!o||!n||!e||!t)return{ok:!1,error:"There is no website to save to."};try{const f=await t.update({[r]:l.trim()},{siteId:e});return a.current=!0,w(),c(u=>({...u,[r]:{value:f[r]??"",error:null}})),{ok:!0}}catch(f){const u=R(f,r)??F;return c(E=>({...E,[r]:{...E[r],error:u}})),{ok:!1,error:u}}},[o,n,e,t]),k=v(()=>C(Object.fromEntries(O.map(r=>[r,i[r].value]))),[i]);return v(()=>({links:k,rows:i,canSave:o,saveLink:S}),[k,i,o,S])}export{F as SOCIAL_SAVE_FAILED,R as socialFieldError,D as useSocialSettings};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { BlogPostRow } from "
|
|
1
|
+
import type { BlogPostRow } from "../../format/lib/web-backend.js";
|
|
2
2
|
export declare const loadStorefrontBlogPosts: (force?: boolean) => Promise<BlogPostRow[]>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { LockHolder, SaveConflict } from "efficient-easel/edit-lock";
|
|
2
2
|
import { type OfferedSets } from "./editor-blocks.js";
|
|
3
3
|
import type { EaselCapabilities as EditorCapabilities, EaselDocument as EditorDocument, EaselDocumentAdapter as EditorDocumentAdapter } from "efficient-easel/screen/lib/document-contract";
|
|
4
|
-
import type { EditorPageRow, SiteLiveState, WebsiteBackend } from "
|
|
4
|
+
import type { EditorPageRow, SiteLiveState, WebsiteBackend } from "../../format/lib/web-backend.js";
|
|
5
5
|
export type { EditorPageRow };
|
|
6
6
|
export type { EditorCapabilities, EditorDocument, EditorDocumentAdapter };
|
|
7
7
|
export type WebsiteCapabilities = EditorCapabilities & {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DuplicatePageInput, EditorPageRow } from "../../format/lib/web-backend.js";
|
|
2
|
+
export declare function canDuplicatePage(row: Pick<EditorPageRow, "kind">): boolean;
|
|
3
|
+
export declare function uniqueSlug(base: string, taken: ReadonlySet<string>): string;
|
|
4
|
+
export declare function urlHandleTaken(slug: string, taken: ReadonlySet<string>): boolean;
|
|
5
|
+
export declare function copySuggestion(row: Pick<EditorPageRow, "label" | "slug">, taken: ReadonlySet<string>): DuplicatePageInput;
|
|
6
|
+
export declare function usePageDuplicate(): ((row: EditorPageRow, input: DuplicatePageInput) => Promise<EditorPageRow>) | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{useEaselSession as i}from"efficient-easel/screen/lib/session-context";import{useScreenDocument as r}from"efficient-easel/screen/components/ScreenDocumentContext";import{slugify as c}from"../../format/lib/slugify.js";import{backendOf as a}from"./website-session.js";const l=new Set(["normal","dynamic"]);function S(e){return!e.kind||l.has(e.kind)}function p(e,t){const n=c(e)||"page";if(!t.has(n))return n;let s=2;for(;t.has(`${n}-${s}`);)s+=1;return`${n}-${s}`}function D(e,t){return t.has(e)}function $(e,t){return{title:`${e.label||e.slug} copy`,slug:p(`${e.slug}-copy`,t)}}function h(){const e=i(),{siteId:t,templateId:n}=r(),s=a(e).pages;if(!(!s.duplicate||n))return(u,o)=>s.duplicate(u.id,{...o,...t?{siteId:t}:{}})}export{S as canDuplicatePage,$ as copySuggestion,p as uniqueSlug,D as urlHandleTaken,h as usePageDuplicate};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ScreenMainAction } from "efficient-easel/screen/lib/screen-parts";
|
|
2
|
-
import type { PageLiveState, SiteChange } from "
|
|
2
|
+
import type { PageLiveState, SiteChange } from "../../format/lib/web-backend.js";
|
|
3
3
|
export type { PageLiveState };
|
|
4
4
|
export declare function noteLoaded(id: string, live: PageLiveState | undefined): void;
|
|
5
5
|
export declare function noteSaved(id: string, live: PageLiveState | undefined): void;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Config } from "efficient-easel/blocks";
|
|
2
2
|
import { type PaletteSection } from "efficient-easel/screen/lib/puck/palette-sections";
|
|
3
|
-
export { matchesQuery, type PaletteSection } from "efficient-easel/screen/lib/puck/palette-sections";
|
|
4
3
|
export declare const CATEGORY_META: Record<string, {
|
|
5
4
|
label: string;
|
|
6
5
|
icon: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{buildPaletteSections as
|
|
1
|
+
import{buildPaletteSections as l,categoryLabel as r,paletteWithoutPinned as i,pinnedSection as c}from"efficient-easel/screen/lib/puck/palette-sections";import{labelAtLevel as b,LEVEL_NAMED_TYPE as u}from"../../../format/lib/puck/section-catalog.js";const t={openers:{label:"Hero & intros",icon:"image"},shop:{label:"Shop & galleries",icon:"bag"},product:{label:"Product page",icon:"box"},checkout:{label:"Checkout & ordering",icon:"bag"},about:{label:"About & brand story",icon:"book"},content:{label:"Text & content",icon:"type"},proof:{label:"Stats & social proof",icon:"star"},promo:{label:"Promotions & sign-ups",icon:"sparkles"},blog:{label:"Blog & journal",icon:"newspaper"},navigation:{label:"Navigation & wayfinding",icon:"bookmark"},legal:{label:"Legal & documents",icon:"file"},contact:{label:"Contact, FAQ & forms",icon:"mail"},structure:{label:"Layout, structure & embeds",icon:"grid"}};function n(o){return t[o]?.label}function d(o,e={}){return l(o,{labelAtLevel:b,categoryLabel:n,descriptions:e})}function f(o,e){return r(o,e,n)}function m(o){return t[o]?.icon??"layers"}const a=u;function y(o){return c(o,a)}function x(o){return i(o,a)}export{t as CATEGORY_META,a as PINNED_SECTION_TYPE,d as buildPaletteSections,m as categoryIcon,f as categoryLabel,n as categoryShortLabel,x as paletteWithoutPinned,y as pinnedSection};
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import type { AddTarget } from "efficient-easel/screen/lib/puck/add-target-types";
|
|
2
|
-
export type { AddTarget, AddTargetSource } from "efficient-easel/screen/lib/puck/add-target-types";
|
|
3
2
|
export declare function canAddTo(nodeType: string, nestDepth?: number): AddTarget | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as
|
|
1
|
+
import{jsx as r}from"react/jsx-runtime";import{HERO_GROUP_NUDGE_LIMIT as n,HERO_GROUP_WIDTH_DEFAULT as u,HERO_GROUP_WIDTH_MAX as p,HERO_GROUP_WIDTH_MIN as d,HERO_GROUP_WIDTH_NESTED_DEFAULT as _,heroGroupNestDepth as g}from"../../../../../../format/lib/hero-group-placement.js";import{WidthIcon as l}from"efficient-easel/icons";import{boxAlignField as f,boxJustifyField as c,boxWrapField as H,directionField as h,gapField as x,group as e,placementField as F,plainText as G,positionFields as O,sidesPaddingFields as R,slider as s,withIdentifier as D,withOffPage as E,withPanelOnly as P}from"../../../controls.js";import{PH as I}from"../../../../../../format/lib/puck/blocks/placeholders.js";import{withRowRules as T}from"../../../../../../render/lib/puck/show-when.js";import{HeroGroupSlots as w}from"../../../../../../render/lib/puck/blocks/general/HeroGroup/render.js";const j={fields:T({_gContent:e("Content"),name:P(D(E(G("Box name",I.boxName)))),content:w.content,_gLayout:e("Layout"),placement:F("Placement",{stacking:!0}),width:s("Width",r(l,{}),d,p,5,u,"%"),direction:h("HeroGroup"),gap:x("HeroGroup"),justify:c(),align:f(),wrap:H(),_gNudge:e("Nudge"),...O({keys:{x:"nudgeX",y:"nudgeY"},min:-n,max:n,label:null}),...R()},[[["placement"],{context:"heroGroupDepth",is:0}]]),resolveFields:(o,{fields:t,appState:m})=>{const a=typeof o.props.id=="string"?o.props.id:"";if(g(m?.data,a)===0)return t;const i={...t};return i.width=s("Width",r(l,{}),d,p,5,_,"%"),i}};export{j as HeroGroupFields};
|
|
@@ -4,7 +4,7 @@ import { FOLD_FIELD_MARKER, LINK_FIELD_MARKER, MEDIA_FIELD_MARKER, SCAFFOLD_FIEL
|
|
|
4
4
|
import type { ShowWhenRule } from "../../../render/lib/puck/show-when.js";
|
|
5
5
|
import { type HeroGroupPlacement } from "../../../format/lib/hero-group-placement.js";
|
|
6
6
|
import { type SettingsSidesValue, type SettingsBorderValue } from "efficient-easel/panel";
|
|
7
|
-
import { type AlignmentPoint, FOCAL_DEFAULT } from "efficient-shell/ui";
|
|
7
|
+
import { type AlignmentPoint, FOCAL_DEFAULT, type PositionValue } from "efficient-shell/ui";
|
|
8
8
|
import type { GeocodeState } from "../../../format/lib/content/contact.js";
|
|
9
9
|
import { type DirectionContainer } from "../../../format/lib/content/container-direction.js";
|
|
10
10
|
import { GAP_FIELD_CONTAINER, type GapContainer } from "../../../format/lib/content/container-gap.js";
|
|
@@ -269,6 +269,19 @@ export type SidesPaddingOptions = {
|
|
|
269
269
|
step?: number;
|
|
270
270
|
};
|
|
271
271
|
export declare function sidesPaddingFields(opts?: SidesPaddingOptions): Record<string, CustomField<undefined> | CustomField<number>>;
|
|
272
|
+
type PositionKeys = {
|
|
273
|
+
x: string;
|
|
274
|
+
y: string;
|
|
275
|
+
};
|
|
276
|
+
export declare function positionPatch(keys: PositionKeys, before: PositionValue, next: PositionValue): Record<string, number | undefined>;
|
|
277
|
+
export type PositionOptions = {
|
|
278
|
+
keys: PositionKeys;
|
|
279
|
+
min: number;
|
|
280
|
+
max: number;
|
|
281
|
+
step?: number;
|
|
282
|
+
label?: string | null;
|
|
283
|
+
};
|
|
284
|
+
export declare function positionFields(o: PositionOptions): Record<string, CustomField<number>>;
|
|
272
285
|
export declare function widthField(defaultMode: WidthMode, modes?: readonly WidthMode[], inheritable?: boolean): Record<string, CustomField<undefined> | CustomField<string> | CustomField<number>>;
|
|
273
286
|
export declare function heightFields(): Record<string, CustomField<undefined> | CustomField<string> | CustomField<number>>;
|
|
274
287
|
export declare function stickFields(): Record<string, CustomField<undefined> | CustomField<boolean> | CustomField<number>>;
|