efficient-web-builder 32.1.0 → 32.2.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 +17 -0
- package/dist/editor/components/usePinnedChromeSeed.js +1 -1
- package/dist/editor/lib/editor-blocks.d.ts +16 -0
- package/dist/editor/lib/puck/pinned-in-place-seed.d.ts +1 -0
- package/dist/editor/lib/puck/pinned-in-place-seed.js +1 -1
- package/dist/format/lib/puck/new-site-header-seed.d.ts +17 -0
- package/dist/format/lib/puck/new-site-header-seed.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 32.2.0 - 2026-10-22
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **A new site starts on the Box header** (plan 2026-10-10 step B3; card [SWITCH] Every Site To The Box Header). A new site already started on the Box footer: its site-footer document is laid down empty, and the seed fills it. That same new site now also gets the header group, pinned first, built by the HOST from the site's own header row. A site on the old footer, or on the Box footer only, keeps its header: it switches by its own choice ("Switch to Box header"). No live site changes.
|
|
10
|
+
- `EditorBlocks.seeds` (`lib/editor-blocks`, with `EditorSeeds` and `EditorSeedContext`): `siteHeader({ make, id, siteId, token })` resolves the `SiteHeader` group, or null. Optional: a host without it keeps a new site on the old header, as before.
|
|
11
|
+
- A TEMPLATE's site-footer page gets no old Footer or Header seeded (`components/usePinnedChromeSeed`). A site made from the template takes that page as its site-footer document, so it stays empty and the new site's seed lays down both Box groups.
|
|
12
|
+
- `lib/puck/new-site-header-seed` (`seedNewSiteHeader`): asks the host, then writes the group only when the same document is still open, no header group arrived meanwhile, and the answer is a header group. `inPlaceSeedPlan` gains `seedSiteHeader`.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- The comments that said nothing creates a group (`components/usePinnedChromeSeed`, `lib/puck/section-groups`) say the two ways a group is created now. The stale notes on the footer focus's seams and `panels.chromePage` are gone (`components/SectionEditor`, `components/WebsiteScreenParts`).
|
|
17
|
+
|
|
18
|
+
### Guards
|
|
19
|
+
|
|
20
|
+
- `scripts/test-new-site-box-header.ts` (red first): which sites get the header group, the write and each case that writes nothing, the seed's call, and the template's empty site-footer page.
|
|
21
|
+
|
|
5
22
|
## 32.1.0 - 2026-10-21
|
|
6
23
|
|
|
7
24
|
### Added
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useEffect as
|
|
1
|
+
"use client";import{useEffect as j,useRef as q}from"react";import{createNode as T,newId as I}from"efficient-easel/data";import{useEaselApi as J}from"efficient-easel/easel";import{useScreenDocument as K}from"efficient-easel/screen/components/ScreenDocumentContext";import{useEaselSession as M}from"efficient-easel/screen/lib/session-context";import{SITE_FOOTER_SLUG as L}from"../../format/lib/content/footer.js";import{boxFooterFromFooter as U}from"../../format/lib/puck/box-footer.js";import{ROOT_ZONE as l,missingPinnedTypes as Q,pinnedDuplicateIds as O}from"efficient-easel/draw";import{FOOTER_TYPE as a,HEADER_TYPE as E,buildDefaultFooterBlocks as b,buildDefaultHeaderNode as N}from"../lib/puck/footer-blocks.js";import{canSeedPinnedChrome as V}from"../../format/lib/puck/pinned-seed-gate.js";import{siteFooterDocChrome as W,SITE_FOOTER_TYPE as f}from"../../format/lib/puck/section-groups.js";import{inPlaceSeedPlan as X}from"../lib/puck/pinned-in-place-seed.js";import{seedNewSiteHeader as $}from"../../format/lib/puck/new-site-header-seed.js";import{SITE_HEADER_TYPE as R}from"../../format/lib/puck/section-groups.js";import{blocksOf as ee}from"../lib/website-session.js";function he(t,D){const{adapter:_,capabilities:y,currentSlug:w,docId:S,data:C,saveStatus:H,siteId:v,tokenRef:x}=K(),z=M(),{hasSiteSettings:Y,hasPinnedChrome:A}=y,B=!!y.editsPinnedInPlace&&w!==L,g=w===L,h=J().getState,k=q(null);j(()=>{if(!V({docId:S,saveStatus:H,seededDocId:k.current})||(k.current=S,!A))return;const p=h().appState.data,n=p.content,d=C?.content??[],r=(e,s)=>e.some(i=>i?.type===s);if(!Y){const e=new Set(O(n)),s=e.size?n.filter(c=>!e.has(c.props.id)):n;if(e.size&&t.setDocument({...p,content:s}),g)return;const i=Q(s,d);if(i.includes(a)){const c=s.length,o=t.insertSection(a,c);t.replaceComponent(l,c,{type:a,props:{id:o,blocks:b()}})}i.includes(E)&&t.insertNode(l,0,N());return}if(g){const e=W(n);if(e!==n&&t.setDocument({...p,content:[...e]}),!e.find(i=>i.type===a)&&!r(d,a)&&!r(e,f)&&!r(d,f)){const i=(o,m)=>T(D,o,m),c={type:a,props:{blocks:b()}};t.insertNode(l,e.length,U(c,i,I(f)))}return}if(B){const e=!!_?.pinnedChrome?.state().docId,s=X(n,{hasChromeDoc:e}),i=new Set([...s.remove,...O(n.filter(o=>!s.remove.includes(String(o.props.id))))]),c=i.size?n.filter(o=>!i.has(String(o.props.id))):n;if(c.length!==n.length&&t.setDocument({...p,content:c}),s.seedFooter&&!r(d,a)&&!r(d,f)){const o=(u,Z)=>T(D,u,Z),m={type:a,props:{blocks:b()}};t.insertNode(l,c.length,U(m,o,I(f)))}if(s.seedHeader&&!r(d,E)){const o=c[0]?.type===R?1:0;t.insertNode(l,o,N())}if(s.seedSiteHeader&&!r(d,R)&&!r(d,a)&&!r(d,f)){const o=S;$({blocks:ee(z),make:(m,u)=>T(D,m,u),id:I(R),siteId:v??null,token:x.current,latest:()=>h().appState.data.content,stillOpen:()=>k.current===o,write:m=>{const u=h().appState.data;t.setDocument({...u,content:[...m]})}})}return}const P=n.filter(e=>e.type!==a),G=new Set(O(P)),F=G.size?P.filter(e=>!G.has(e.props.id)):P;F.length!==n.length&&t.setDocument({...p,content:F}),!r(F,E)&&!r(d,E)&&t.insertNode(l,0,N())},[S,H,C,h,t,Y,A,g,B,_,z,v,x])}export{he as usePinnedChromeSeed};
|
|
@@ -7,6 +7,21 @@ export interface EditorBlockCategory {
|
|
|
7
7
|
components: string[];
|
|
8
8
|
before?: string;
|
|
9
9
|
}
|
|
10
|
+
export interface EditorSeedContext {
|
|
11
|
+
make: (type: string, props?: Record<string, unknown>) => {
|
|
12
|
+
type: string;
|
|
13
|
+
props: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
id: string;
|
|
16
|
+
siteId: string | null;
|
|
17
|
+
token: string | null;
|
|
18
|
+
}
|
|
19
|
+
export interface EditorSeeds {
|
|
20
|
+
siteHeader?: (ctx: EditorSeedContext) => Promise<{
|
|
21
|
+
type: string;
|
|
22
|
+
props: Record<string, unknown>;
|
|
23
|
+
} | null>;
|
|
24
|
+
}
|
|
10
25
|
export interface EditorBlocks {
|
|
11
26
|
sets?: readonly BlockSet[];
|
|
12
27
|
allow?: readonly string[];
|
|
@@ -14,6 +29,7 @@ export interface EditorBlocks {
|
|
|
14
29
|
host?: Record<string, ComponentConfig>;
|
|
15
30
|
categories?: EditorBlockCategory[];
|
|
16
31
|
metadata?: Record<string, unknown>;
|
|
32
|
+
seeds?: EditorSeeds;
|
|
17
33
|
}
|
|
18
34
|
export type OfferedSets = Readonly<Record<BlockSet, boolean>>;
|
|
19
35
|
export declare function offeredSets(blocks: EditorBlocks | SessionBlocks | null | undefined): OfferedSets;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{FOOTER_TYPE as
|
|
1
|
+
import{FOOTER_TYPE as p,HEADER_TYPE as a}from"./footer-blocks.js";import{SITE_FOOTER_TYPE as c,SITE_HEADER_TYPE as T}from"../../../format/lib/puck/section-groups.js";function _(o,E){const t=o.some(e=>e?.type===c),r=o[o.length-1],s=!t&&r?.type===p?r:null,m=o.filter(e=>e?.type===p&&e!==s).map(e=>String(e.props?.id??"")).filter(Boolean),n=E.hasChromeDoc&&!t&&!s;return{remove:m,seedHeader:!o.some(e=>e?.type===a),seedFooter:n,seedSiteHeader:n&&!o.some(e=>e?.type===T)}}export{_ as inPlaceSeedPlan};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { EditorBlocks, EditorSeedContext } from "../../../editor/lib/editor-blocks.js";
|
|
2
|
+
type Node = {
|
|
3
|
+
type: string;
|
|
4
|
+
props: Record<string, unknown>;
|
|
5
|
+
};
|
|
6
|
+
export interface NewSiteHeaderSeed {
|
|
7
|
+
blocks: EditorBlocks | null | undefined;
|
|
8
|
+
make: EditorSeedContext["make"];
|
|
9
|
+
id: string;
|
|
10
|
+
siteId: string | null;
|
|
11
|
+
token: string | null;
|
|
12
|
+
latest: () => readonly Node[];
|
|
13
|
+
stillOpen: () => boolean;
|
|
14
|
+
write: (content: readonly Node[]) => void;
|
|
15
|
+
}
|
|
16
|
+
export declare function seedNewSiteHeader(seed: NewSiteHeaderSeed): Promise<boolean>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{SITE_HEADER_TYPE as n,withSectionGroup as o}from"./section-groups.js";async function l(t){const r=t.blocks?.seeds?.siteHeader;if(!r)return!1;let e;try{e=await r({make:t.make,id:t.id,siteId:t.siteId,token:t.token})}catch{return!1}if(!e||e.type!==n||!t.stillOpen())return!1;const i=t.latest();return i.some(a=>a?.type===n)?!1:(t.write(o(i,e)),!0)}export{l as seedNewSiteHeader};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "efficient-web-builder",
|
|
3
|
-
"version": "32.
|
|
3
|
+
"version": "32.2.0",
|
|
4
4
|
"description": "The EFFICIENT website builder: the website editor, the general sections and the renderer that draws them, compiled. Hostable by any EFFICIENT product; nothing here imports a host.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "Efficient Pty Ltd",
|