efficient-web-builder 5.0.2 → 5.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/CHANGELOG.md +34 -0
- package/dist/components/PhoneMenuTools.d.ts +3 -1
- package/dist/components/PhoneMenuTools.js +1 -1
- package/dist/components/PreviewHeaderContext.d.ts +5 -1
- package/dist/components/PreviewHeaderContext.js +1 -1
- package/dist/components/StorefrontEditor.js +1 -1
- package/dist/lib/puck/page-root.js +1 -1
- package/dist/lib/puck/section-catalog.js +1 -1
- package/dist/lib/site-text-styles.d.ts +41 -0
- package/dist/lib/site-text-styles.js +2 -0
- package/dist/lib/site-theme-row.d.ts +6 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.3.0 - 2026-10-12
|
|
4
|
+
|
|
5
|
+
- **The efficient-shell peer range takes 5.** efficient-shell 5.0.0
|
|
6
|
+
(Efficient-Pty-Ltd/efficient-shell#371) renames one prop, `SettingRow`'s
|
|
7
|
+
`name` to `label`, and the builder does not use `SettingRow`. Every host is
|
|
8
|
+
moving to `^5`; with the range stopping at `^4` each would warn about the
|
|
9
|
+
builder on every install. Peer range: `efficient-shell ^4.171.0 || ^5.0.0`.
|
|
10
|
+
Nothing else changes.
|
|
11
|
+
|
|
12
|
+
## 5.2.0 - 2026-10-12
|
|
13
|
+
|
|
14
|
+
- **The site header's phone menu can hold Account and Theme.**
|
|
15
|
+
`PhoneMenuTool` adds `"account"` and `"theme"` to `"search"` and
|
|
16
|
+
`"region"`, and `usePhoneMenuTools()` reports all four, so an Account block
|
|
17
|
+
and a Theme switch block in the header group can offer the old header's
|
|
18
|
+
"Account" and "Theme" rows to the one-row Menu's panel. Additive: a host
|
|
19
|
+
that reads only `search` and `region` is unchanged.
|
|
20
|
+
- **`AccountBlock` and `ThemeSwitchBlock` have a block set.** The catalogue's
|
|
21
|
+
list of unlisted blocks names the two new header tool blocks of
|
|
22
|
+
efficient-storefront-blocks as `commerce`, with the Header and its other
|
|
23
|
+
tools, so a host that registers them can say which set they travel in.
|
|
24
|
+
|
|
25
|
+
## 5.1.0 - 2026-10-12
|
|
26
|
+
|
|
27
|
+
- **The site's text styles reach the page.** The editor canvas reads the
|
|
28
|
+
theme's saved `text_styles` (Heading 1-7, Body 1-7) and paints each value a
|
|
29
|
+
merchant set on that style's face class (`textStylesCss`); hosts get
|
|
30
|
+
`themeWithTextStyles` and `storedTextStyles` to do the same on the live
|
|
31
|
+
page. A site that has not saved the list renders exactly as before: the old
|
|
32
|
+
six font roles are read into Heading 1-3, Body 1 and Body 5 (Labels), and
|
|
33
|
+
nothing is written.
|
|
34
|
+
- **`eyebrowStyleId`** is the one place that picks the style an eyebrow
|
|
35
|
+
follows: Body 7 when the site has it, otherwise its smallest Body.
|
|
36
|
+
|
|
3
37
|
## 5.0.2 - 2026-10-12
|
|
4
38
|
|
|
5
39
|
- **The copy box bar no longer offers the three word styles.** Highlight,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
export type PhoneMenuTool = "search" | "region";
|
|
2
|
+
export type PhoneMenuTool = "search" | "region" | "account" | "theme";
|
|
3
3
|
export interface PhoneMenuTools {
|
|
4
4
|
search: boolean;
|
|
5
5
|
region: boolean;
|
|
6
|
+
account: boolean;
|
|
7
|
+
theme: boolean;
|
|
6
8
|
}
|
|
7
9
|
export declare function PhoneMenuToolsProvider({ children }: {
|
|
8
10
|
children: ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as f}from"react/jsx-runtime";import{createContext as l,useContext as s,useEffect as d,useState as a,useSyncExternalStore as
|
|
1
|
+
"use client";import{jsx as f}from"react/jsx-runtime";import{createContext as l,useContext as s,useEffect as d,useState as a,useSyncExternalStore as h}from"react";const u=[];function x(){let e=u;const n=new Set,c=r=>{e=r;for(const t of n)t()};return{offer:r=>(c([...e,r]),()=>{const t=e.indexOf(r);t>=0&&c([...e.slice(0,t),...e.slice(t+1)])}),subscribe:r=>(n.add(r),()=>n.delete(r)),offered:()=>e}}const o=l(null);function P({children:e}){const[n]=a(x);return f(o.Provider,{value:n,children:e})}const S=()=>s(o)!==null;function b(e){const n=s(o);d(()=>{if(!(!n||!e))return n.offer(e)},[n,e])}const g=()=>()=>{},i=()=>u;function y(){const e=s(o),n=h(e?.subscribe??g,e?.offered??i,i);return e?{search:n.includes("search"),region:n.includes("region"),account:n.includes("account"),theme:n.includes("theme")}:null}export{P as PhoneMenuToolsProvider,S as useInSiteHeader,b as useOfferToPhoneMenu,y as usePhoneMenuTools};
|
|
@@ -35,6 +35,8 @@ type Ctx = {
|
|
|
35
35
|
setHeadingCompression: (v: HeadingCompression) => void;
|
|
36
36
|
headingTypography: ResolvedHeadingTypography;
|
|
37
37
|
setHeadingTypography: (v: ResolvedHeadingTypography) => void;
|
|
38
|
+
textStyles: unknown;
|
|
39
|
+
setTextStyles: (v: unknown) => void;
|
|
38
40
|
siteWidth: number | null;
|
|
39
41
|
setSiteWidth: (v: number | null) => void;
|
|
40
42
|
siteGutter: number | null;
|
|
@@ -52,7 +54,7 @@ type Ctx = {
|
|
|
52
54
|
setSelectHandler: (fn: () => void) => void;
|
|
53
55
|
};
|
|
54
56
|
export declare const PreviewHeaderContext: import("react").Context<Ctx>;
|
|
55
|
-
export declare function PreviewHeaderProvider({ children, websiteName, templateChrome, templateName, chromePlaceholder, themeMode, onThemeModeChange, themeSwitchShown, onThemeSwitchShownChange, theme, onThemeChange, fonts, onFontsChange, sizes, onSizesChange, cornerRadiusPx, onCornerRadiusPxChange, cardShadow, onCardShadowChange, shadowColor, onShadowColorChange, cardGap, onCardGapChange, hoverEffect, onHoverEffectChange, headingCompression, onHeadingCompressionChange, siteWidth, onSiteWidthChange, siteGutter, blockGap, onSiteGutterChange, onBlockGapChange, headingTypography, onHeadingTypographyChange, heroBackgroundFollowsWidth, onHeroBackgroundFollowsWidthChange, photographyGrayscale, onPhotographyGrayscaleChange, themeFromDocument, }: {
|
|
57
|
+
export declare function PreviewHeaderProvider({ children, websiteName, templateChrome, templateName, chromePlaceholder, themeMode, onThemeModeChange, themeSwitchShown, onThemeSwitchShownChange, theme, onThemeChange, fonts, onFontsChange, sizes, onSizesChange, cornerRadiusPx, onCornerRadiusPxChange, cardShadow, onCardShadowChange, shadowColor, onShadowColorChange, cardGap, onCardGapChange, hoverEffect, onHoverEffectChange, headingCompression, onHeadingCompressionChange, siteWidth, onSiteWidthChange, siteGutter, blockGap, onSiteGutterChange, onBlockGapChange, headingTypography, onHeadingTypographyChange, textStyles, onTextStylesChange, heroBackgroundFollowsWidth, onHeroBackgroundFollowsWidthChange, photographyGrayscale, onPhotographyGrayscaleChange, themeFromDocument, }: {
|
|
56
58
|
children: ReactNode;
|
|
57
59
|
websiteName?: string | null;
|
|
58
60
|
templateChrome?: boolean;
|
|
@@ -86,6 +88,8 @@ export declare function PreviewHeaderProvider({ children, websiteName, templateC
|
|
|
86
88
|
onSiteGutterChange?: (v: number | null) => void;
|
|
87
89
|
onBlockGapChange?: (v: number | null) => void;
|
|
88
90
|
onSiteWidthChange?: (v: number | null) => void;
|
|
91
|
+
textStyles?: unknown;
|
|
92
|
+
onTextStylesChange?: (v: unknown) => void;
|
|
89
93
|
headingTypography?: ResolvedHeadingTypography;
|
|
90
94
|
onHeadingTypographyChange?: (v: ResolvedHeadingTypography) => void;
|
|
91
95
|
heroBackgroundFollowsWidth?: boolean | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as
|
|
1
|
+
"use client";import{jsx as k}from"react/jsx-runtime";import{createContext as Le,useCallback as t,useContext as Ue,useMemo as ge,useState as y}from"react";import{EditorSiteLogoContext as Me}from"./SiteLogoContext.js";import{useSelectHandler as Re}from"../lib/puck/preview-selection-context.js";import{IDENTITY_CARD_GAP as L,DEFAULT_HEADING_COMPRESSION as U,DEFAULT_HEADING_TYPOGRAPHY as g,DEFAULT_SIZES as M,DEFAULT_SWITCH_SHOWN as R,DEFAULT_THEME_MODE as O,DEFAULT_THEME_VALUE as W}from"../lib/theme.js";import{DEFAULT_FONTS as N}from"../lib/fonts.js";const B=Le({settings:null,setSettings:()=>{},primeSettings:()=>{},websiteName:null,templateChrome:!1,templateName:null,chromePlaceholder:!1,themeMode:O,setThemeMode:()=>{},themeSwitchShown:R,setThemeSwitchShown:()=>{},theme:W,setTheme:()=>{},fonts:N,setFonts:()=>{},sizes:M,setSizes:()=>{},cornerRadiusPx:null,setCornerRadiusPx:()=>{},cardShadow:null,setCardShadow:()=>{},shadowColor:null,setShadowColor:()=>{},cardGap:L,setCardGap:()=>{},hoverEffect:null,setHoverEffect:()=>{},headingCompression:U,setHeadingCompression:()=>{},siteWidth:null,setSiteWidth:()=>{},siteGutter:null,blockGap:null,setSiteGutter:()=>{},setBlockGap:()=>{},headingTypography:g,setHeadingTypography:()=>{},textStyles:null,setTextStyles:()=>{},heroBackgroundFollowsWidth:null,setHeroBackgroundFollowsWidth:()=>{},photographyGrayscale:null,setPhotographyGrayscale:()=>{},themeFromDocument:!1,selected:!1,setSelected:()=>{},select:()=>{},setSelectHandler:()=>{}});function ze({children:Y,websiteName:o=null,templateChrome:l=!1,templateName:r=null,chromePlaceholder:n=!1,themeMode:j=O,onThemeModeChange:c,themeSwitchShown:z=R,onThemeSwitchShownChange:i,theme:b=W,onThemeChange:u,fonts:V=N,onFontsChange:d,sizes:Z=M,onSizesChange:S,cornerRadiusPx:q=null,onCornerRadiusPxChange:a,cardShadow:J=null,onCardShadowChange:p,shadowColor:K=null,onShadowColorChange:E,cardGap:Q=L,onCardGapChange:f,hoverEffect:X=null,onHoverEffectChange:T,headingCompression:$=U,onHeadingCompressionChange:m,siteWidth:C=null,onSiteWidthChange:H,siteGutter:ee=null,blockGap:te=null,onSiteGutterChange:D,onBlockGapChange:_,headingTypography:se=g,onHeadingTypographyChange:w,textStyles:le=null,onTextStylesChange:x,heroBackgroundFollowsWidth:oe=null,onHeroBackgroundFollowsWidthChange:A,photographyGrayscale:re=null,onPhotographyGrayscaleChange:v,themeFromDocument:ne=!1}){const[s,F]=y(null),ce=t(e=>F(ye=>ye??e),[]),[ie,ue]=y(!1),de=t(e=>c?.(e),[c]),Se=t(e=>i?.(e),[i]),ae=t(e=>u?.(e),[u]),pe=t(e=>d?.(e),[d]),Ee=t(e=>S?.(e),[S]),fe=t(e=>H?.(e),[H]),Te=t(e=>D?.(e),[D]),me=t(e=>_?.(e),[_]),He=t(e=>A?.(e),[A]),De=t(e=>v?.(e),[v]),_e=t(e=>a?.(e),[a]),we=t(e=>p?.(e),[p]),xe=t(e=>E?.(e),[E]),Ae=t(e=>f?.(e),[f]),ve=t(e=>T?.(e),[T]),Fe=t(e=>m?.(e),[m]),Ge=t(e=>w?.(e),[w]),Pe=t(e=>x?.(e),[x]),{select:he,setSelectHandler:Ie}=Re(),G=s?.logoUrl,P=s?.logoReversed,h=s?.logoInkIsDark,I=s!==null,ke=ge(()=>({logo:I?{logoUrl:G,logoReversed:P,logoInkIsDark:h}:null,placeholder:l||n,wordmark:l?r:o}),[I,G,P,h,l,n,r,o]);return k(Me.Provider,{value:ke,children:k(B.Provider,{value:{settings:s,setSettings:F,primeSettings:ce,websiteName:o,templateChrome:l,templateName:r,chromePlaceholder:n,themeMode:j,setThemeMode:de,themeSwitchShown:z,setThemeSwitchShown:Se,theme:b,setTheme:ae,fonts:V,setFonts:pe,sizes:Z,setSizes:Ee,cornerRadiusPx:q,setCornerRadiusPx:_e,cardShadow:J,setCardShadow:we,shadowColor:K,setShadowColor:xe,cardGap:Q,setCardGap:Ae,hoverEffect:X,setHoverEffect:ve,headingCompression:$,setHeadingCompression:Fe,siteWidth:C,setSiteWidth:fe,siteGutter:ee,blockGap:te,setSiteGutter:Te,setBlockGap:me,headingTypography:se,setHeadingTypography:Ge,textStyles:le,setTextStyles:Pe,heroBackgroundFollowsWidth:oe,setHeroBackgroundFollowsWidth:He,photographyGrayscale:re,setPhotographyGrayscale:De,themeFromDocument:ne,selected:ie,setSelected:ue,select:he,setSelectHandler:Ie},children:Y})})}const be=()=>Ue(B);export{B as PreviewHeaderContext,ze as PreviewHeaderProvider,be as usePreviewHeader};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as
|
|
1
|
+
"use client";import{jsx as s,jsxs as pt}from"react/jsx-runtime";import{useCallback as n,useEffect as p,useMemo as D,useRef as m,useState as r}from"react";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/drag.css";import"efficient-easel/screen.css";import"./storefront-editor.css";import{buildConfig as ft}from"../lib/puck/build-config.js";import{ChromeWrap as St}from"../lib/editor-chrome.js";import{sessionRegistry as gt}from"../lib/editor-session.js";import{backendOf as A,blocksOf as _t}from"../lib/website-session.js";import{useEditorSession as wt}from"../lib/editor-session-context.js";import{withSiteBlockGapFields as yt}from"../lib/puck/site-gap-fields.js";import{withTemplateMediaPlaceholders as Tt}from"../lib/puck/templateFields.js";import{setEditorPage as fe}from"../lib/puck/editor-page-context.js";import{resolveSiteName as Ct}from"../lib/content/site-name.js";import{normalizeSiteGutter as Et,normalizeSiteWidth as Pt}from"../lib/content/page-width.js";import{normalizeSiteBlockGap as vt}from"../lib/content/container-gap.js";import xt,{DocumentScreen as bt}from"./EditorScreenMount.js";import{useStorefrontDocument as It}from"./StorefrontDocumentContext.js";import{PreviewHeaderProvider as Ht}from"./PreviewHeaderContext.js";import{PreviewFooterProvider as Mt}from"./PreviewFooterContext.js";import{PreviewChatProvider as Rt,DEFAULT_CHAT_PREVIEW as Ft}from"./PreviewChatContext.js";import{PreviewSocialProvider as Gt}from"./PreviewSocialContext.js";import{useSocialSettings as zt}from"./useSocialSettings.js";import{PreviewSurfaceProvider as kt}from"./PreviewSurfaceContext.js";import{PreviewFocusProvider as Dt}from"./PreviewFocusContext.js";import{SITE_FOOTER_SLUG as At}from"../lib/content/footer.js";import{markFooterReturn as Wt}from"../lib/puck/footer-return.js";import{WEBSITE_ADDRESSING as Nt}from"../lib/website-document-addressing.js";import{PreviewTickerProvider as Ot}from"./PreviewTickerContext.js";import{PreviewPartsProvider as Bt}from"./PreviewPartsContext.js";import{PreviewLocationPartProvider as Kt}from"./PreviewLocationPartContext.js";import{PreviewPartStyleProvider as Lt}from"./PreviewPartStyleContext.js";import{SiteMapsProvider as Yt,readSiteMapsKey as Ut,writeSiteMapsKey as Se,readSiteMapId as jt,writeSiteMapId as Vt}from"../lib/maps-config.js";import{CORNER_STYLE_TO_PX as Xt,DEFAULT_HEADING_COMPRESSION as Zt,DEFAULT_HEADING_TYPOGRAPHY as qt,DEFAULT_SWITCH_SHOWN as W,DEFAULT_SIZES as Jt,DEFAULT_THEME_MODE as E,normalizeCornerRadius as Qt,normalizeCornerStyle as $t,normalizeCardShadow as er,normalizeCardGap as tr,normalizeHoverEffect as rr,normalizeShadowColor as or,IDENTITY_CARD_GAP as ge,IDENTITY_CARD_SHADOW as nr,IDENTITY_HOVER_EFFECT as ar,headingTypographyFromRow as _e,normalizeHeadingCompression as N,normalizeSizes as we,THEME_MODE_KEY as ye,THEME_STORAGE_KEY as ir,THEME_SWITCH_HIDE as Te,THEME_SWITCH_KEY as O}from"../lib/theme.js";import{DEFAULT_FONTS as cr,normalizeFonts as B}from"../lib/fonts.js";import{WEBSITE_SCREEN as sr}from"./WebsiteScreenParts.js";import{routeWebsiteHostMessage as dr}from"../lib/website-host-inbound.js";import{resolveTextStyles as lr,textStylesToOld as ur}from"../lib/site-text-styles.js";const hr=()=>{if(typeof window>"u")return E;try{const c=window.localStorage.getItem(ye);return c==="light"||c==="dark"||c==="auto"?c:E}catch{return E}},Ce=c=>{if(!(typeof window>"u"))try{window.localStorage.setItem(ye,c)}catch{}},mr=()=>{if(typeof window>"u")return W;try{return window.localStorage.getItem(O)!==Te}catch{return W}},pr=()=>{if(!(typeof window>"u"))try{window.localStorage.removeItem(ir)}catch{}},Ee=c=>{if(!(typeof window>"u"))try{c?window.localStorage.removeItem(O):window.localStorage.setItem(O,Te)}catch{}};function fr(){const{adapter:c,capabilities:d,templateId:K,ready:S,token:h,siteId:i,currentSlug:g,currentKind:L,data:Y,getLiveData:U,footerOriginSlug:_,navigate:y}=It();p(()=>(fe(g,L),()=>fe(null,null)),[g,L]);const P=d.placeholderFrames,[Pe,j]=r(null),[ve,V]=r("");p(()=>{const e=c.templateName;if(!S||!K||!e){V("");return}let o=!1;return e().then(l=>!o&&V(l??"")).catch(()=>{}),()=>{o=!0}},[S,h,K,c]);const[xe,v]=r(E),[be,x]=r(W),[Ie,X]=r({selected:0,themes:[]}),[He,b]=r(cr),[Me,I]=r(Jt),[Re,Z]=r(null),[Fe,H]=r(Zt),[Ge,q]=r(null),[ze,J]=r(null),[ke,Q]=r(ge),[De,$]=r(null),[Ae,ee]=r(null),[We,te]=r(null),[M,re]=r(null),u=wt(),oe=D(()=>ft(gt(u),_t(u)),[u]),Ne=D(()=>yt(Tt(oe,P),M),[oe,P,M]),[Oe,R]=r(qt),[Be,ne]=r(null),[Ke,ae]=r(null),ie=m(null),a=m(!1);p(()=>{v(hr()),x(mr())},[]);const Le=n(e=>{a.current=!0,pr(),Ce(e),v(e)},[]),Ye=n(e=>{a.current=!0,Ee(e),x(e)},[]),Ue=n(e=>{a.current=!0,X(e)},[]),je=n(e=>{a.current=!0,b(e)},[]),Ve=n(e=>{a.current=!0,I(e)},[]),Xe=n(e=>{a.current=!0,Z(e)},[]),Ze=n(e=>{a.current=!0,H(e)},[]),qe=n(e=>{a.current=!0,q(e)},[]),Je=n(e=>{a.current=!0,J(e)},[]),Qe=n(e=>{a.current=!0,Q(e)},[]),$e=n(e=>{a.current=!0,$(e)},[]),et=n(e=>{a.current=!0,R(e)},[]),[tt,ce]=r(null),rt=n(e=>{a.current=!0,ce(e)},[]),ot=n(e=>{a.current=!0,ee(e)},[]),nt=n(e=>{a.current=!0,te(e)},[]),at=n(e=>{a.current=!0,re(e)},[]),it=n(e=>{a.current=!0,ne(e)},[]),ct=n(e=>{a.current=!0,ae(e)},[]);p(()=>{const e=A(u).theme;if(!h||!d.hasSiteTheme||!e)return;const o=i??"";ie.current!==o&&(ie.current=o,a.current=!1);let l=!1;return e.get(i?{siteId:i}:void 0).then(t=>{if(!(l||a.current)){if(Ce(t.default_mode),Ee(t.show_theme_switch),v(t.default_mode),x(t.show_theme_switch),X({selected:t.selected_preset,themes:t.theme_presets}),b(B({heading:t.heading_font,body:t.body_font,accent:t.accent_font,label:t.label_font})),I(we({headingLarge:t.heading_size_large_px,headingMedium:t.heading_size_medium_px,headingSmall:t.heading_size_small_px,body:t.body_size_px,label:t.label_size_px})),Z(t.corner_radius_px===void 0?Xt[$t(t.corner_style)]:Qt(t.corner_radius_px)),H(N(t.heading_compression)),q(t.card_shadow==null?nr:er(t.card_shadow)),Q(t.card_gap==null?ge:tr(t.card_gap)),$(t.hover_effect==null?ar:rr(t.hover_effect)),J(or(t.shadow_color)),ee(Pt(t.site_width)),te(Et(t.site_gutter)),re(vt(t.block_gap)),R(_e(t)),ce(t.text_styles??null),Array.isArray(t.text_styles)){const w={fonts:B({heading:t.heading_font,body:t.body_font,accent:t.accent_font,label:t.label_font}),sizes:we({headingLarge:t.heading_size_large_px,headingMedium:t.heading_size_medium_px,headingSmall:t.heading_size_small_px,body:t.body_size_px,label:t.label_size_px}),compression:N(t.heading_compression),typography:_e(t)},f=ur(lr(t.text_styles,w),w);b(B(f.fonts)),I(f.sizes),H(N(f.compression)),R(f.typography)}ne(t.hero_background_follows_width===!0),ae(t.photography_grayscale===!0)}}).catch(()=>{}),()=>{l=!0}},[h,i,d.hasSiteTheme,u]);const st=zt({token:h,siteId:i,enabled:d.hasSiteSettings}),[dt,se]=r(Ft),de=m(null),F=m(!1),G=m(null),T=m({}),lt=n(e=>{F.current=!0,se(o=>({...o,...e})),!(!d.hasSiteSettings||!h)&&(T.current={...T.current,...e},G.current&&clearTimeout(G.current),G.current=setTimeout(()=>{const o=T.current;T.current={},A(u).chat?.update(o,i?{siteId:i}:void 0).catch(()=>{})},500))},[d.hasSiteSettings,h,i,u]);p(()=>{if(!h||!d.hasSiteSettings)return;const e=i??"";de.current!==e&&(de.current=e,F.current=!1);let o=!1;const l=A(u).chat;if(l)return l.get(i?{siteId:i}:void 0).then(t=>{o||F.current||se({enabled:t.enabled,title:t.title,subtitle:t.subtitle,greeting:t.greeting})}).catch(()=>{}),()=>{o=!0}},[h,i,d.hasSiteSettings,u]);const[C,z]=r(""),le=m(null),k=m(!1);p(()=>z(Ut()),[]);const ue=n(e=>{const o=e.trim();if(o===C)return;k.current=!0,Se(o),z(o);const l=c.updateSite;!d.canEditSiteRecord||!S||!l||l({mapsApiKey:o}).catch(()=>{})},[C,d.canEditSiteRecord,S,c]),[he,me]=r("");p(()=>me(jt()),[]),p(()=>{const e=c.site;if(!S||!d.hasSiteRecord||!e){j(null);return}const o=i??"";le.current!==o&&(le.current=o,k.current=!1);let l=!1;return e().then(t=>{if(l||(j(Ct(t.name)),k.current))return;const w=t.mapsApiKey??"";Se(w),z(w);const f=t.mapsMapId??"";Vt(f),me(f)}).catch(()=>{}),()=>{l=!0}},[S,h,d.hasSiteRecord,i,c]);const ut=D(()=>({apiKey:C,setApiKey:ue,mapId:he}),[C,ue,he]),pe=m(null),ht=n(()=>{pe.current=U()??Y??null,Wt(g),y({kind:"page",slug:At,siteId:i??void 0,originSlug:g})},[U,Y,g,y,i]),mt=n(()=>{_&&y({kind:"page",slug:_,siteId:i??void 0})},[_,y,i]);return s(bt,{config:Ne,parts:sr,wrap:(e,o)=>s(Ht,{websiteName:Pe,templateChrome:P,templateName:ve||null,themeMode:xe,onThemeModeChange:Le,themeSwitchShown:be,onThemeSwitchShownChange:Ye,theme:Ie,onThemeChange:Ue,fonts:He,onFontsChange:je,cornerRadiusPx:Re,onCornerRadiusPxChange:Xe,cardShadow:Ge,onCardShadowChange:qe,shadowColor:ze,onShadowColorChange:Je,cardGap:ke,onCardGapChange:Qe,hoverEffect:De,onHoverEffectChange:$e,headingCompression:Fe,onHeadingCompressionChange:Ze,headingTypography:Oe,onHeadingTypographyChange:et,textStyles:tt,onTextStylesChange:rt,sizes:Me,onSizesChange:Ve,siteWidth:Ae,onSiteWidthChange:ot,siteGutter:We,onSiteGutterChange:nt,blockGap:M,onBlockGapChange:at,heroBackgroundFollowsWidth:Be,onHeroBackgroundFollowsWidthChange:it,photographyGrayscale:Ke,onPhotographyGrayscaleChange:ct,themeFromDocument:!d.hasSiteTheme,children:s(Dt,{originData:_?pe.current:null,originSlug:_,exitFocus:mt,children:s(Mt,{editFooter:ht,children:s(St,{wrap:u.chrome?.wrap,surface:"page",children:s(Ot,{children:s(Bt,{children:s(Kt,{children:s(Lt,{children:pt(Yt,{value:ut,children:[s(Rt,{chat:dt,onChatChange:lt,children:s(Gt,{value:st,children:s(kt,{children:e})})}),o]})})})})})})})})})})}function Sr({target:c}){return s(xt,{target:c,addressing:Nt,onHostMessage:dr,children:s(fr,{})})}export{Sr as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as
|
|
1
|
+
import{jsx as r,jsxs as k}from"react/jsx-runtime";import{storedTextStyles as K,textStylesCss as Y}from"../site-text-styles.js";import{pageWidthMarker as q,PAGE_WIDTH_ATTR as J,SITE_WIDTH_CAP as Q,siteWidthTokens as U,siteGutterTokens as Z,heroBackgroundTokens as ee}from"../content/page-width.js";import{siteBlockGapTokens as te}from"../content/container-gap.js";import{siteCardRadiusTokens as oe}from"../content/card-corners.js";import{usePreviewHeader as ne}from"../../components/PreviewHeaderContext.js";import{SitePhotographyProvider as re}from"../../components/SitePhotographyContext.js";import{CORNER_STYLE_TO_PX as se,normalizeCornerStyle as ae,normalizeCornerRadius as de,themeColorStyle as ie,typeSizesStyle as ce,headingTypographyStyle as le,themeAccentStyle as he,themeButtonStyle as pe,themePresetAccentVars as fe,themeSurfaceStyle as me,siteCornerRadiusTokens as A,shadowColorTokens as ue,headingCompressionAttr as ge,cardShadowAttr as ye,cardGapAttr as Se,hoverEffectAttr as xe}from"../theme.js";import{fontRoleStyle as Te}from"../fonts.js";import{isStandaloneSectionDocument as Ce,pageHasHeaderSection as v,pageTakesTopSpace as ke,topSpaceMarker as Ae,TOP_SPACE_ATTR as ve,HEADER_CLEARANCE_CLASS as Ee}from"./header-clearance.js";import{leadSectionInk as _e,HEADER_INK_ATTR as Pe}from"./header-ink.js";import{useEasel as we}from"efficient-easel/easel";import{pageBackgroundVars as E}from"../content/page-background.js";const Re="color-mix(in oklab, var(--bg) 40%, #ffffff)",He="12vh";function We({style:t,frameClass:o,children:s}){const{appState:n}=we(g=>g),a=n.data.content,d=n.data.root;if(Ce(a))return r("div",{className:`sf-themed-content${o?` ${o}`:""}`,style:{...t,background:Re,minHeight:"100vh",paddingBottom:He},children:r("div",{style:{background:"var(--bg)"},children:s})});const c=v(a)&&ke(d,a),l=v(a)?Ae(d,a):null,f=l?{[ve]:l}:null,h=q(d?.widthChoice),m=h?{[J]:h}:null,p=c?null:_e(a),u=p?{[Pe]:p}:null;return r("div",{className:`sf-themed-content${c?` ${Ee}`:""}${o?` ${o}`:""}`,style:t,...u,...f,...m,children:r("div",{style:{background:"var(--bg)",minHeight:"100%"},children:s})})}function _(t){return{frameClass:void 0,style:{"--sf-page-width":Q}}}function Ie({w:t,children:o}){const{frameClass:s,style:n}=_(t);return r("div",{className:s,style:n,children:o})}function Xe({propsTheme:t,propsFonts:o,propsCornerStyle:s,propsCornerRadiusPx:n,propsHeadingCompression:a,propsHeadingTypography:d,widthMode:c,fullWidth:l,pageWidth:f,pageBackground:h,chromeInheritsSiteBackground:m,suppressPreviewNav:p,footer:u,overlay:g,children:P}){const{theme:w,fonts:R,sizes:H,cornerRadiusPx:W,cardShadow:y,shadowColor:I,cardGap:G,hoverEffect:S,headingCompression:N,siteWidth:b,siteGutter:B,blockGap:D,headingTypography:z,heroBackgroundFollowsWidth:V,photographyGrayscale:$,textStyles:F,themeFromDocument:e}=ne(),i=e?t:w,L=e?o:R,O=e?void 0:H,x=e?n===void 0?se[ae(s)]:de(n):W,j=e?a:N,T=Y(K(e?void 0:F)),M=e?d:z,C=_({widthMode:c,fullWidth:l,pageWidth:f}),X={...ie(i),...ce(O),...le(M),...C.style,...m?{}:E(h)};return k("div",{className:"sf-theme-surfaces sf-theme-accent",style:{...Te(L),...he(i),...pe(i),...fe(i),...me(i),...A(x),...oe(A(x)),...ue(e?void 0:y,e?void 0:I,e?void 0:S),...U(e?void 0:b),...Z(e?void 0:B),...te(e?void 0:D),...ee(e?void 0:V)},"data-sf-headings":ge(j),"data-sf-card-shadow":e?void 0:ye(y),"data-sf-card-gap":e?void 0:Se(G),"data-sf-card-hover":e?void 0:xe(S),onClickCapture:p,children:[T?r("style",{"data-sf-text-styles":"",dangerouslySetInnerHTML:{__html:T}}):null,k(re,{grayscale:e?void 0:$,children:[r(We,{style:X,frameClass:C.frameClass,children:P}),u,g]})]})}const Ke=t=>{t.target?.closest?.("a")&&t.preventDefault()};function Ye({pageBackground:t,inheritBackground:o=!1,w:s,children:n}){return r("div",{style:{...o?{}:E(t),background:"var(--bg)",minHeight:"100%",overflowX:"clip"},children:r(Ie,{w:s,children:n})})}export{We as EditorPageBody,Xe as EditorThemedBody,Ie as PageWidthWrapper,Ye as PublishedPageFrame,Re as SECTION_PREVIEW_CANVAS,He as SECTION_PREVIEW_CANVAS_TAIL,_ as pageWidthTokens,Ke as suppressPreviewNav};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const p=["general","commerce","service"],o=[{key:"openers",title:"Hero & intros",defaultExpanded:!0,templateable:!0,sections:[{type:"Hero",label:"Hero Slideshow",set:"general"},{type:"HeroSingle",label:"Hero",set:"general"},{type:"IntroBleed",label:"Scroll-Over Text",set:"general"}]},{key:"shop",title:"Shop & galleries",templateable:!0,sections:[{type:"Collections",label:"Collections",set:"commerce"},{type:"BrandStrip",label:"Brand Strip",set:"commerce"},{type:"AlloyWheelsListing",label:"List",set:"commerce"},{type:"CatalogFilterBar",label:"Catalog Filter Bar",set:"commerce"},{type:"ProductGrid",label:"Product Grid",set:"commerce"},{type:"FitmentFinder",label:"Fitment Form",set:"commerce"},{type:"Gallery",label:"Tabbed Gallery",set:"commerce"},{type:"GalleryB",label:"Customer Photo Grid",set:"commerce"},{type:"SpecStrip",label:"Spec Strip",set:"general"}]},{key:"product",title:"Product page",templateable:!0,sections:[{type:"ProductHero",label:"Product Hero",set:"commerce"},{type:"SpecTable",label:"Spec Table",set:"commerce"},{type:"ProcessSteps",label:"Image & Text Columns",set:"general"},{type:"DetailRows",label:"Feature Rows",set:"commerce"},{type:"FitmentTable",label:"Fitment Table",set:"commerce"},{type:"TyreSizes",label:"Tyre Sizes",set:"commerce"},{type:"TyreFitment",label:"Tyre Fitment Form",set:"commerce"},{type:"EuTyreLabel",label:"EU Tyre Label",set:"commerce"},{type:"RelatedProducts",label:"Related Products",set:"commerce"},{type:"BundleOffer",label:"Bundle Products",set:"commerce"}]},{key:"checkout",title:"Checkout & ordering",templateable:!0,sections:[{type:"OrderSummary",label:"Order Table",set:"general"},{type:"DeliveryOptions",label:"Delivery Options",set:"commerce"},{type:"PaymentBadges",label:"Payment Methods",set:"general"},{type:"CheckoutCTA",label:"Ready-to-Order Banner",set:"commerce"}]},{key:"about",title:"About & brand story",templateable:!0,sections:[{type:"Manifesto",label:"Brand Text",set:"general"},{type:"Timeline",label:"Story Timeline",set:"general"},{type:"TimelineTrack",label:"Milestone Timeline",set:"general"},{type:"Footprint",label:"Locations Map",set:"general"}]},{key:"content",title:"Text & content",templateable:!0,sections:[{type:"Prose",label:"Editorial Text",set:"general"},{type:"ParagraphsA",label:"Lead Text",set:"general"},{type:"Split",label:"Image & Text Split",set:"general"},{type:"Cards",label:"Cards",set:"general"},{type:"KeyFeatures",label:"Key Features",set:"general"}]},{key:"proof",title:"Stats & social proof",templateable:!0,sections:[{type:"Stats",label:"Stats",set:"general"},{type:"StatsParagraph",label:"Stats with Text",set:"general"},{type:"Chart",label:"Chart",set:"general"},{type:"Mockup",label:"Mockup Card",set:"general"},{type:"Testimonials",label:"Testimonials",set:"general"},{type:"Reviews",label:"Reviews",set:"service"},{type:"Logos",label:"Logos",set:"general"}]},{key:"promo",title:"Promotions & sign-ups",templateable:!0,sections:[{type:"Banner",label:"Banner",set:"general"},{type:"TitleWithButtons",label:"Call-to-Action Heading",set:"general"},{type:"Ticker",label:"Scrolling Bar",set:"general"},{type:"Subscribe",label:"Signup Form",set:"service"}]},{key:"blog",title:"Blog & journal",templateable:!0,sections:[{type:"Masthead",label:"Issue Header",set:"general"},{type:"FeaturedCover",label:"Feature Banner",set:"general"},{type:"LongRead",label:"Article Text",set:"general"},{type:"Series",label:"Recurring Columns",set:"general"},{type:"Events",label:"Latest Posts",set:"service"}]},{key:"navigation",title:"Navigation & wayfinding",templateable:!0,sections:[{type:"Breadcrumb",label:"Breadcrumb",set:"general"},{type:"CategoryBar",label:"Category Bar",set:"general"},{type:"DocTabs",label:"Document Tabs",set:"general"}]},{key:"legal",title:"Legal & documents",templateable:!0,sections:[{type:"DocMasthead",label:"Document Header",set:"general"},{type:"DocBody",label:"Document Text",set:"general"},{type:"DocMetaCards",label:"Document Detail Cards",set:"general"}]},{key:"contact",title:"Contact, FAQ & forms",templateable:!0,sections:[{type:"FAQ",label:"Q&A",set:"general"},{type:"ContactRouting",label:"Contact Form",set:"service"},{type:"ContactLocations",label:"Contact / Locations",set:"general"},{type:"SubmitBuild",label:"Photo Submission Form",set:"service"},{type:"ReviewForm",label:"Review Form",set:"service"},{type:"Form",label:"Form",set:"service"},{type:"AppointmentBooking",label:"Booking Form",set:"service"}]},{key:"structure",title:"Layout, structure & embeds",templateable:!1,sections:[{type:"SectionHeader",label:"Section Header",set:"general"},{type:"Flex",label:"Box",set:"general"},{type:"Spacer",label:"Spacer",set:"general"},{type:"Divider",label:"Divider",set:"general"},{type:"CustomHTML",label:"Custom HTML",set:"general"}]}];function h(){return Object.fromEntries(o.map(e=>[e.key,{title:e.title,components:e.sections.map(t=>t.type),...e.defaultExpanded?{defaultExpanded:!0}:{}}]))}const l={Grid:'Lewis, 2026-09-14: Box and Grid duplicate each other and it feels confusing. 2026-09-15 he chose the order: give Box uneven widths FIRST, then merge Grid into Box. Shown three ways to pick the widths (mockup "Uneven Box Widths"), he chose A — shape pictures on the Box\'s `Block widths` row, the same "a row is a shape, pick a picture of it" rule he set for the photo wall on 2026-09-07.\n\nWHAT REPLACES IT: a Box set to One row, with `Block widths` at Equal or a shape (Big left, Big right, Bigger left, Bigger right) and its own `Columns on phone`. Measured on PRODUCTION 2026-09-16 ~09:28 AEST (database `efficient-system`, all 10 tenant schemas, 128 storefront pages, both `layout` and `published_layout` — 256 documents): 2 Grid nodes, and they are ONE Grid counted twice — the 9DIEM homepage on 9diem.com (`xtreme_mudder` schema), once as draft and once as published. It is top-level, holds three `ImageBlock`s at `columns` 3 — equal thirds — and NO block sets `Positions`. A Box draws that with `Block widths` at Equal.\n\n⚠️ THE COUNT MOVES; THE RULE MUST NOT DEPEND ON IT. This entry has already carried three different readings. A local-clone snapshot said no Grid used `Positions`. A PRODUCTION reading on 2026-09-15 ~13:15 AEST found 6 nodes on two sites, 4 of them spanned — hartesmetal.com.au homepage and about, 4 columns, spans 1 + 3. That one was TRUE when it was taken and stopped being true the same day: those two pages were rebuilt on Box (`Block widths: Bigger right`), and on 2026-09-16 they hold zero Grid nodes and are built from `Flex`. ⛔ So the rule is NOT "there are still N spanned Grids". NEVER delete the Grid component or its `gridSpan` handling, whatever a census says — Grid still renders, still edits, still drags, and a merchant may rebuild a page either way on any day. Re-run the census on production before anyone PROPOSES deleting either, and read any number written here as the reading of its own day, not as the state of the world.\n\nWHAT A MERCHANT LOSES: a new Grid, and with it a fixed "N per row" that wraps by itself past three across, and the per-block `Positions` number. Box wraps with `Wrap`, but by content width, not by a fixed count.\n\nTHE TYPE KEY STAYS AND SO DOES THE COMPONENT. Every page holding a Grid still renders through it and can still be edited, dragged and added to; no document is rewritten and NO MIGRATION RUNS — the owner redoes live sections himself.\n\n⚠️ AND IT STAYS DROPPABLE WHERE IT LIVES. The drop rule in lib/puck/config.tsx read the nestable containers off the catalogue\'s `structure` row, so leaving the catalogue would have made every open slot — a Box included — refuse a Grid already stored inside one. `scripts/test-retired-grid-stays-editable.tsx` §3 pins it.',CompatibleTyres:'Lewis, 2026-09-09: "Do not bother counting. Delete Compatible Tyres and use the new one. The new one needs complete settings — it must have every setting our cards have." Shown three ways to finish it, he chose C: retire from the menu now, and take styling the card text as its own card.\n\nWHAT REPLACES IT: `RelatedProducts` with its `Show` dropdown set to "Tyres that fit this product". That block is the GENERIC relationship section from card 1128 — it knows nothing about wheels or tyres, it asks the registry for a relationship by name. The two have rendered through the SAME renderer (`DynamicRelatedProducts`) since that card; this one is the pre-registry one-off that was never removed.\n\n⚠️ THE SWAP WAS NOT SAFE UNTIL #1305, AND SAYING SO IS THE POINT. The first old-versus-new table put in front of the owner was WRONG. `DynamicRelatedProducts` returns EARLY on a tyre answer and draws this component, so the seven card settings, the head split and the Width control all stopped at that call — nine settings, measured NO EFFECT, on precisely the relationship that replaces this block. #1283 gave the new block the card settings, #1299 the head split and its own Width, #1305 carried all of it onto the tyre branch. Only then was the claim true.\n\nWHAT WAS MEASURED BEFORE RETIRING, four ways, because the premise decides the card:\n • settable text kinds (SECTION_TEXT_KINDS): both blocks ABSENT — the map holds only TimelineTrack and Footprint, both AUTHORED lists\n • read-only text regions: neither `components/CompatibleTyres` nor `components/TyreCard` stamps one\n • panel rows through resolveFields: this block 31, `RelatedProducts` 42. This block\'s only style-ish key is `_sStyle`, the bucket HEADER, not a control\n • head text (num/title/description) is authored on both, so `_partStyles` reaches it identically\nSo on the CARD runs the two are zero against zero — neither can style them — and everywhere else the new block is ahead. Styling those runs needs a section-level prop family and a paint path for DERIVED text, which no section has yet: a part is anchored by matching an AUTHORED prop\'s string against the DOM, and `lib/puck/source-bound-parts` keeps hydrated copy unreachable on purpose so a merchant cannot type into a copy of a product name and lose it at the next sync. That is its own card, and `lib/sections/text-regions` is the read-only half that already ships.\n\nTHE TYPE KEY STAYS AND SO DOES THE COMPONENT, the same contract Subscribe, Split and SubscribeBlogs have. Every page holding a `CompatibleTyres` still renders through it, no published document is rewritten, and NO MIGRATION RUNS — the owner\'s standing ruling of 2026-09-05: he redoes live sections himself and deletes the old ones when he does. He also said explicitly not to count them first.\n\n⚠️ AND THIS COMPONENT IS LOAD-BEARING FOR ITS OWN REPLACEMENT: `DynamicRelatedProducts` draws it for EVERY tyre answer. Deleting it would blank the block that replaces it, not just the pages still holding this one.',SubscribeBlogs:"card 66396 — folded into `Subscribe`, which now chooses its rail's content with a `Type` control (the newsletter's own issues, or live blog posts). The two shared 21 of their fields and rendered THE SAME BYTES from equivalent rows, so offering both asked a merchant to choose between two names for one section. The type key stays because it is stored on published pages, and the component stays because those pages still render through it."},m=["Grid"],y=Array.from(new Set([...o.flatMap(e=>e.sections.map(t=>t.type)),...Object.keys(l)])),u=Object.fromEntries(o.flatMap(e=>e.sections.map(t=>[t.type,t.label]))),i={Heading:"general",Text:"general",Eyebrow:"general",ImageBlock:"general",LogoBlock:"general",ButtonBlock:"general",PostCard:"general",HeroSlide:"general",HeroGroup:"general",Integrations:"general",Grid:"general",CollectionCard:"commerce",GalleryItem:"commerce",ProductRef:"commerce",CompatibleTyres:"commerce",Header:"commerce",SearchBlock:"commerce",CartBlock:"commerce",CountrySwitchBlock:"commerce",SubmitBox:"service",BookingBox:"service",SubscribeBlogs:"service",Footer:"service",FooterLogo:"service",FooterMenu:"service",FooterDivider:"service",FooterGroup:"service",FooterText:"service",FooterEmailSignup:"service",FooterSocial:"service",MenuBlock:"service",EmailFormBlock:"service",SocialLogosBlock:"service",LegalLineBlock:"service",SiteHeader:"service",SiteFooter:"service"},a={...i,...Object.fromEntries(o.flatMap(e=>e.sections.map(t=>[t.type,t.set])))};function b(e){return Object.prototype.hasOwnProperty.call(a,e)?a[e]:void 0}function r(e){return Object.keys(a).filter(t=>a[t]===e).sort()}const g=r("general"),T=r("commerce"),S=r("service"),c="Flex",s="Box",E=`${s}es`;function d(e){return e==="section"?"Blank section":s}function w(e,t,n){return e===c?d(t):n}export{y as ALL_SECTION_TYPES,p as BLOCK_SETS,s as BOX_LABEL,E as BOX_LABEL_PLURAL,T as COMMERCE_BLOCKS,g as GENERAL_BLOCKS,c as LEVEL_NAMED_TYPE,m as RETIRED_NESTABLE_SECTIONS,l as RETIRED_SECTIONS,o as SECTION_CATALOG,u as SECTION_LABELS,S as SERVICE_BLOCKS,i as UNLISTED_BLOCK_SETS,b as blockSetOf,r as blocksInSet,h as buildPuckCategories,w as labelAtLevel,d as labelForFlex};
|
|
1
|
+
const p=["general","commerce","service"],o=[{key:"openers",title:"Hero & intros",defaultExpanded:!0,templateable:!0,sections:[{type:"Hero",label:"Hero Slideshow",set:"general"},{type:"HeroSingle",label:"Hero",set:"general"},{type:"IntroBleed",label:"Scroll-Over Text",set:"general"}]},{key:"shop",title:"Shop & galleries",templateable:!0,sections:[{type:"Collections",label:"Collections",set:"commerce"},{type:"BrandStrip",label:"Brand Strip",set:"commerce"},{type:"AlloyWheelsListing",label:"List",set:"commerce"},{type:"CatalogFilterBar",label:"Catalog Filter Bar",set:"commerce"},{type:"ProductGrid",label:"Product Grid",set:"commerce"},{type:"FitmentFinder",label:"Fitment Form",set:"commerce"},{type:"Gallery",label:"Tabbed Gallery",set:"commerce"},{type:"GalleryB",label:"Customer Photo Grid",set:"commerce"},{type:"SpecStrip",label:"Spec Strip",set:"general"}]},{key:"product",title:"Product page",templateable:!0,sections:[{type:"ProductHero",label:"Product Hero",set:"commerce"},{type:"SpecTable",label:"Spec Table",set:"commerce"},{type:"ProcessSteps",label:"Image & Text Columns",set:"general"},{type:"DetailRows",label:"Feature Rows",set:"commerce"},{type:"FitmentTable",label:"Fitment Table",set:"commerce"},{type:"TyreSizes",label:"Tyre Sizes",set:"commerce"},{type:"TyreFitment",label:"Tyre Fitment Form",set:"commerce"},{type:"EuTyreLabel",label:"EU Tyre Label",set:"commerce"},{type:"RelatedProducts",label:"Related Products",set:"commerce"},{type:"BundleOffer",label:"Bundle Products",set:"commerce"}]},{key:"checkout",title:"Checkout & ordering",templateable:!0,sections:[{type:"OrderSummary",label:"Order Table",set:"general"},{type:"DeliveryOptions",label:"Delivery Options",set:"commerce"},{type:"PaymentBadges",label:"Payment Methods",set:"general"},{type:"CheckoutCTA",label:"Ready-to-Order Banner",set:"commerce"}]},{key:"about",title:"About & brand story",templateable:!0,sections:[{type:"Manifesto",label:"Brand Text",set:"general"},{type:"Timeline",label:"Story Timeline",set:"general"},{type:"TimelineTrack",label:"Milestone Timeline",set:"general"},{type:"Footprint",label:"Locations Map",set:"general"}]},{key:"content",title:"Text & content",templateable:!0,sections:[{type:"Prose",label:"Editorial Text",set:"general"},{type:"ParagraphsA",label:"Lead Text",set:"general"},{type:"Split",label:"Image & Text Split",set:"general"},{type:"Cards",label:"Cards",set:"general"},{type:"KeyFeatures",label:"Key Features",set:"general"}]},{key:"proof",title:"Stats & social proof",templateable:!0,sections:[{type:"Stats",label:"Stats",set:"general"},{type:"StatsParagraph",label:"Stats with Text",set:"general"},{type:"Chart",label:"Chart",set:"general"},{type:"Mockup",label:"Mockup Card",set:"general"},{type:"Testimonials",label:"Testimonials",set:"general"},{type:"Reviews",label:"Reviews",set:"service"},{type:"Logos",label:"Logos",set:"general"}]},{key:"promo",title:"Promotions & sign-ups",templateable:!0,sections:[{type:"Banner",label:"Banner",set:"general"},{type:"TitleWithButtons",label:"Call-to-Action Heading",set:"general"},{type:"Ticker",label:"Scrolling Bar",set:"general"},{type:"Subscribe",label:"Signup Form",set:"service"}]},{key:"blog",title:"Blog & journal",templateable:!0,sections:[{type:"Masthead",label:"Issue Header",set:"general"},{type:"FeaturedCover",label:"Feature Banner",set:"general"},{type:"LongRead",label:"Article Text",set:"general"},{type:"Series",label:"Recurring Columns",set:"general"},{type:"Events",label:"Latest Posts",set:"service"}]},{key:"navigation",title:"Navigation & wayfinding",templateable:!0,sections:[{type:"Breadcrumb",label:"Breadcrumb",set:"general"},{type:"CategoryBar",label:"Category Bar",set:"general"},{type:"DocTabs",label:"Document Tabs",set:"general"}]},{key:"legal",title:"Legal & documents",templateable:!0,sections:[{type:"DocMasthead",label:"Document Header",set:"general"},{type:"DocBody",label:"Document Text",set:"general"},{type:"DocMetaCards",label:"Document Detail Cards",set:"general"}]},{key:"contact",title:"Contact, FAQ & forms",templateable:!0,sections:[{type:"FAQ",label:"Q&A",set:"general"},{type:"ContactRouting",label:"Contact Form",set:"service"},{type:"ContactLocations",label:"Contact / Locations",set:"general"},{type:"SubmitBuild",label:"Photo Submission Form",set:"service"},{type:"ReviewForm",label:"Review Form",set:"service"},{type:"Form",label:"Form",set:"service"},{type:"AppointmentBooking",label:"Booking Form",set:"service"}]},{key:"structure",title:"Layout, structure & embeds",templateable:!1,sections:[{type:"SectionHeader",label:"Section Header",set:"general"},{type:"Flex",label:"Box",set:"general"},{type:"Spacer",label:"Spacer",set:"general"},{type:"Divider",label:"Divider",set:"general"},{type:"CustomHTML",label:"Custom HTML",set:"general"}]}];function h(){return Object.fromEntries(o.map(e=>[e.key,{title:e.title,components:e.sections.map(t=>t.type),...e.defaultExpanded?{defaultExpanded:!0}:{}}]))}const l={Grid:'Lewis, 2026-09-14: Box and Grid duplicate each other and it feels confusing. 2026-09-15 he chose the order: give Box uneven widths FIRST, then merge Grid into Box. Shown three ways to pick the widths (mockup "Uneven Box Widths"), he chose A — shape pictures on the Box\'s `Block widths` row, the same "a row is a shape, pick a picture of it" rule he set for the photo wall on 2026-09-07.\n\nWHAT REPLACES IT: a Box set to One row, with `Block widths` at Equal or a shape (Big left, Big right, Bigger left, Bigger right) and its own `Columns on phone`. Measured on PRODUCTION 2026-09-16 ~09:28 AEST (database `efficient-system`, all 10 tenant schemas, 128 storefront pages, both `layout` and `published_layout` — 256 documents): 2 Grid nodes, and they are ONE Grid counted twice — the 9DIEM homepage on 9diem.com (`xtreme_mudder` schema), once as draft and once as published. It is top-level, holds three `ImageBlock`s at `columns` 3 — equal thirds — and NO block sets `Positions`. A Box draws that with `Block widths` at Equal.\n\n⚠️ THE COUNT MOVES; THE RULE MUST NOT DEPEND ON IT. This entry has already carried three different readings. A local-clone snapshot said no Grid used `Positions`. A PRODUCTION reading on 2026-09-15 ~13:15 AEST found 6 nodes on two sites, 4 of them spanned — hartesmetal.com.au homepage and about, 4 columns, spans 1 + 3. That one was TRUE when it was taken and stopped being true the same day: those two pages were rebuilt on Box (`Block widths: Bigger right`), and on 2026-09-16 they hold zero Grid nodes and are built from `Flex`. ⛔ So the rule is NOT "there are still N spanned Grids". NEVER delete the Grid component or its `gridSpan` handling, whatever a census says — Grid still renders, still edits, still drags, and a merchant may rebuild a page either way on any day. Re-run the census on production before anyone PROPOSES deleting either, and read any number written here as the reading of its own day, not as the state of the world.\n\nWHAT A MERCHANT LOSES: a new Grid, and with it a fixed "N per row" that wraps by itself past three across, and the per-block `Positions` number. Box wraps with `Wrap`, but by content width, not by a fixed count.\n\nTHE TYPE KEY STAYS AND SO DOES THE COMPONENT. Every page holding a Grid still renders through it and can still be edited, dragged and added to; no document is rewritten and NO MIGRATION RUNS — the owner redoes live sections himself.\n\n⚠️ AND IT STAYS DROPPABLE WHERE IT LIVES. The drop rule in lib/puck/config.tsx read the nestable containers off the catalogue\'s `structure` row, so leaving the catalogue would have made every open slot — a Box included — refuse a Grid already stored inside one. `scripts/test-retired-grid-stays-editable.tsx` §3 pins it.',CompatibleTyres:'Lewis, 2026-09-09: "Do not bother counting. Delete Compatible Tyres and use the new one. The new one needs complete settings — it must have every setting our cards have." Shown three ways to finish it, he chose C: retire from the menu now, and take styling the card text as its own card.\n\nWHAT REPLACES IT: `RelatedProducts` with its `Show` dropdown set to "Tyres that fit this product". That block is the GENERIC relationship section from card 1128 — it knows nothing about wheels or tyres, it asks the registry for a relationship by name. The two have rendered through the SAME renderer (`DynamicRelatedProducts`) since that card; this one is the pre-registry one-off that was never removed.\n\n⚠️ THE SWAP WAS NOT SAFE UNTIL #1305, AND SAYING SO IS THE POINT. The first old-versus-new table put in front of the owner was WRONG. `DynamicRelatedProducts` returns EARLY on a tyre answer and draws this component, so the seven card settings, the head split and the Width control all stopped at that call — nine settings, measured NO EFFECT, on precisely the relationship that replaces this block. #1283 gave the new block the card settings, #1299 the head split and its own Width, #1305 carried all of it onto the tyre branch. Only then was the claim true.\n\nWHAT WAS MEASURED BEFORE RETIRING, four ways, because the premise decides the card:\n • settable text kinds (SECTION_TEXT_KINDS): both blocks ABSENT — the map holds only TimelineTrack and Footprint, both AUTHORED lists\n • read-only text regions: neither `components/CompatibleTyres` nor `components/TyreCard` stamps one\n • panel rows through resolveFields: this block 31, `RelatedProducts` 42. This block\'s only style-ish key is `_sStyle`, the bucket HEADER, not a control\n • head text (num/title/description) is authored on both, so `_partStyles` reaches it identically\nSo on the CARD runs the two are zero against zero — neither can style them — and everywhere else the new block is ahead. Styling those runs needs a section-level prop family and a paint path for DERIVED text, which no section has yet: a part is anchored by matching an AUTHORED prop\'s string against the DOM, and `lib/puck/source-bound-parts` keeps hydrated copy unreachable on purpose so a merchant cannot type into a copy of a product name and lose it at the next sync. That is its own card, and `lib/sections/text-regions` is the read-only half that already ships.\n\nTHE TYPE KEY STAYS AND SO DOES THE COMPONENT, the same contract Subscribe, Split and SubscribeBlogs have. Every page holding a `CompatibleTyres` still renders through it, no published document is rewritten, and NO MIGRATION RUNS — the owner\'s standing ruling of 2026-09-05: he redoes live sections himself and deletes the old ones when he does. He also said explicitly not to count them first.\n\n⚠️ AND THIS COMPONENT IS LOAD-BEARING FOR ITS OWN REPLACEMENT: `DynamicRelatedProducts` draws it for EVERY tyre answer. Deleting it would blank the block that replaces it, not just the pages still holding this one.',SubscribeBlogs:"card 66396 — folded into `Subscribe`, which now chooses its rail's content with a `Type` control (the newsletter's own issues, or live blog posts). The two shared 21 of their fields and rendered THE SAME BYTES from equivalent rows, so offering both asked a merchant to choose between two names for one section. The type key stays because it is stored on published pages, and the component stays because those pages still render through it."},m=["Grid"],y=Array.from(new Set([...o.flatMap(e=>e.sections.map(t=>t.type)),...Object.keys(l)])),u=Object.fromEntries(o.flatMap(e=>e.sections.map(t=>[t.type,t.label]))),i={Heading:"general",Text:"general",Eyebrow:"general",ImageBlock:"general",LogoBlock:"general",ButtonBlock:"general",PostCard:"general",HeroSlide:"general",HeroGroup:"general",Integrations:"general",Grid:"general",CollectionCard:"commerce",GalleryItem:"commerce",ProductRef:"commerce",CompatibleTyres:"commerce",Header:"commerce",SearchBlock:"commerce",CartBlock:"commerce",CountrySwitchBlock:"commerce",AccountBlock:"commerce",ThemeSwitchBlock:"commerce",SubmitBox:"service",BookingBox:"service",SubscribeBlogs:"service",Footer:"service",FooterLogo:"service",FooterMenu:"service",FooterDivider:"service",FooterGroup:"service",FooterText:"service",FooterEmailSignup:"service",FooterSocial:"service",MenuBlock:"service",EmailFormBlock:"service",SocialLogosBlock:"service",LegalLineBlock:"service",SiteHeader:"service",SiteFooter:"service"},a={...i,...Object.fromEntries(o.flatMap(e=>e.sections.map(t=>[t.type,t.set])))};function b(e){return Object.prototype.hasOwnProperty.call(a,e)?a[e]:void 0}function r(e){return Object.keys(a).filter(t=>a[t]===e).sort()}const g=r("general"),T=r("commerce"),S=r("service"),c="Flex",s="Box",E=`${s}es`;function d(e){return e==="section"?"Blank section":s}function w(e,t,n){return e===c?d(t):n}export{y as ALL_SECTION_TYPES,p as BLOCK_SETS,s as BOX_LABEL,E as BOX_LABEL_PLURAL,T as COMMERCE_BLOCKS,g as GENERAL_BLOCKS,c as LEVEL_NAMED_TYPE,m as RETIRED_NESTABLE_SECTIONS,l as RETIRED_SECTIONS,o as SECTION_CATALOG,u as SECTION_LABELS,S as SERVICE_BLOCKS,i as UNLISTED_BLOCK_SETS,b as blockSetOf,r as blocksInSet,h as buildPuckCategories,w as labelAtLevel,d as labelForFlex};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { TextStyleCase } from "efficient-easel/text-styles";
|
|
2
|
+
import { type FontsValue } from "./fonts.js";
|
|
3
|
+
import { type ResolvedHeadingTypography, type SizesValue } from "./theme.js";
|
|
4
|
+
export type StoredTextStyleValues = {
|
|
5
|
+
font?: string;
|
|
6
|
+
color?: string;
|
|
7
|
+
size?: number;
|
|
8
|
+
weight?: number;
|
|
9
|
+
italic?: boolean;
|
|
10
|
+
lineHeight?: number;
|
|
11
|
+
letterSpacing?: number;
|
|
12
|
+
paragraphSpacing?: number;
|
|
13
|
+
letterCase?: TextStyleCase;
|
|
14
|
+
largestSize?: number;
|
|
15
|
+
};
|
|
16
|
+
export type StoredTextStyle = {
|
|
17
|
+
id: string;
|
|
18
|
+
kind: "heading" | "body";
|
|
19
|
+
name: string;
|
|
20
|
+
values: StoredTextStyleValues;
|
|
21
|
+
};
|
|
22
|
+
export type OldSiteText = {
|
|
23
|
+
fonts: Partial<FontsValue> | Record<string, string>;
|
|
24
|
+
sizes: Partial<SizesValue> | Record<string, number | null>;
|
|
25
|
+
compression: string;
|
|
26
|
+
typography: Partial<ResolvedHeadingTypography> | Record<string, unknown>;
|
|
27
|
+
};
|
|
28
|
+
export declare function textStylesFromOld(old: OldSiteText): StoredTextStyle[];
|
|
29
|
+
export declare function storedTextStyles(value: unknown): StoredTextStyle[];
|
|
30
|
+
export declare function resolveTextStyles(saved: unknown, old: OldSiteText): StoredTextStyle[];
|
|
31
|
+
export declare function textStylesToOld(list: readonly StoredTextStyle[], prev: OldSiteText): OldSiteText;
|
|
32
|
+
export declare function themeWithTextStyles<T extends {
|
|
33
|
+
fonts?: unknown;
|
|
34
|
+
sizes?: unknown;
|
|
35
|
+
headingCompression?: unknown;
|
|
36
|
+
headingTypography?: unknown;
|
|
37
|
+
textStyles?: unknown;
|
|
38
|
+
}>(theme: T): T;
|
|
39
|
+
export declare function faceClassOf(style: Pick<StoredTextStyle, "id">): string;
|
|
40
|
+
export declare function textStylesCss(list: readonly StoredTextStyle[]): string;
|
|
41
|
+
export declare function eyebrowStyleId(list: readonly Pick<StoredTextStyle, "id" | "kind">[]): string;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{FONT_OPTIONS as S}from"./fonts.js";import{compressionMetrics as z}from"./theme.js";const h=e=>e==="sentence"?"none":void 0,d=e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,g=e=>typeof e=="string"&&e?e:void 0,$=["font","color","size","weight","italic","lineHeight","letterSpacing","paragraphSpacing","letterCase","largestSize"];function c(e){const i={};for(const t of $)e[t]!==void 0&&(i[t]=e[t]);return i}function x(e){const i=e.fonts,t=e.sizes,n=e.typography,o=z(e.compression),s=(l,a)=>({id:`heading-${l}`,kind:"heading",name:`Heading ${l}`,values:c(a)}),r=(l,a={})=>({id:`body-${l}`,kind:"body",name:`Body ${l}`,values:c(a)});return[s(1,{font:g(i.heading),size:d(t.headingLarge),weight:d(n.weight),lineHeight:o.lineHeight,letterSpacing:o.letterSpacing,letterCase:h(n.case),largestSize:d(n.maxPx)}),s(2,{font:g(i.heading2),size:d(t.headingMedium),weight:d(n.weight2),lineHeight:o.lineHeight,letterSpacing:o.letterSpacing,letterCase:h(n.case2)}),s(3,{font:g(i.heading3),size:d(t.headingSmall),weight:d(n.weight3),lineHeight:o.lineHeight,letterSpacing:o.letterSpacing,letterCase:h(n.case3)}),r(1,{font:g(i.body),size:d(t.body)}),r(2),r(3),r(4),r(5,{font:g(i.label),size:d(t.label)})]}function y(e){return Array.isArray(e)&&e.every(t=>t&&typeof t=="object"&&typeof t.id=="string"&&(t.kind==="heading"||t.kind==="body")&&typeof t.name=="string")?e.map(t=>({...t,values:c(t.values??{})})):null}function M(e){return y(e)??[]}function w(e,i){const t=x(i),n=y(e);return n?n.map(o=>({...o,values:c({...C(t,o.id),...o.values})})):t}const C=(e,i)=>e.find(t=>t.id===i)?.values??{};function k(e,i){const t=p=>e.find(m=>m.id===p)?.values??{},n=t("heading-1"),o=t("heading-2"),s=t("heading-3"),r=t("body-1"),l=t("body-5"),a=i.fonts,f=i.sizes,b=i.typography,u=p=>p==="none"?"sentence":"authored";return{fonts:{...a,heading:n.font??a.heading,heading2:o.font??n.font??a.heading2,heading3:s.font??n.font??a.heading3,body:r.font??a.body,label:l.font??a.label},sizes:{...f,headingLarge:n.size??null,headingMedium:o.size??null,headingSmall:s.size??null,body:r.size??null,label:l.size??null},compression:i.compression,typography:{...b,case:u(n.letterCase),weight:n.weight??null,maxPx:n.largestSize??null,weight2:o.weight??null,weight3:s.weight??null,case2:u(o.letterCase),case3:u(s.letterCase)}}}function N(e){const i=y(e.textStyles);if(!i||i.every(o=>Object.keys(o.values).length===0))return e;const t={fonts:e.fonts??{},sizes:e.sizes??{},compression:String(e.headingCompression??"normal"),typography:e.headingTypography??{}},n=k(w(i,t),t);return{...e,fonts:n.fonts,sizes:n.sizes,headingCompression:n.compression,headingTypography:n.typography}}function v(e){switch(e.id){case"heading-1":return"font-display";case"heading-2":return"font-heading2";case"heading-3":return"font-heading3";case"body-1":return"font-body";case"body-5":return"font-mono";default:return`font-${e.id}`}}function H(e){return e==="accent"?"var(--accent)":e==="text"?"var(--fg)":e==="labels"?"var(--fg-dim)":/^#[0-9a-f]{6}$/i.test(e)?e:null}function O(e){const i=":is([data-sf-bullet], [data-sf-number])";return[`${e} br:not(br + br) { display: block; content: ""; margin-top: var(--sf-part-para) }`,`${e} ${i}:not(:first-child) { margin-top: var(--sf-part-para) }`,`${e} ${i}:not(:last-child) { margin-bottom: var(--sf-part-para) }`]}function F(e){const i=[];for(const t of e){const n=t.values,o=`.${v(t)}`,s=[],r=n.font!==void 0?S.find(f=>f.key===n.font)?.cssVar:void 0;if(r&&s.push(`font-family: var(${r})`),n.size!==void 0){const f=n.largestSize!==void 0?Math.min(n.size,n.largestSize):n.size;s.push(`font-size: ${f}px`)}const l=n.color!==void 0?H(n.color):null;l&&s.push(`color: ${l}`),n.italic===!0&&s.push("font-style: italic"),n.weight!==void 0&&s.push(`font-weight: ${n.weight}`);const a=[];n.lineHeight!==void 0&&a.push(`line-height: ${n.lineHeight}`),n.letterSpacing!==void 0&&a.push(`letter-spacing: ${n.letterSpacing}em`),t.kind==="body"&&s.push(...a),n.letterCase!==void 0&&s.push(`text-transform: ${n.letterCase==="upper"?"uppercase":n.letterCase==="lower"?"lowercase":"none"}`),n.paragraphSpacing&&s.push(`--sf-part-para: ${n.paragraphSpacing}px`),s.length&&i.push(`${o} { ${s.join("; ")} }`),t.kind==="heading"&&a.length&&i.push(`${o}, ${o}:is(h1, h2, h3, h4) { ${a.join("; ")} }`),n.paragraphSpacing&&i.push(...O(o))}return i.join(`
|
|
2
|
+
`)}function L(e){const i=e.filter(t=>t.kind==="body").map(t=>Number(/^body-(\d+)$/.exec(t.id)?.[1])).filter(t=>Number.isInteger(t)&&t>0);return i.length?`body-${Math.max(...i)}`:"body-1"}export{L as eyebrowStyleId,v as faceClassOf,w as resolveTextStyles,M as storedTextStyles,F as textStylesCss,x as textStylesFromOld,k as textStylesToOld,N as themeWithTextStyles};
|
|
@@ -48,5 +48,11 @@ export interface SiteThemeRow {
|
|
|
48
48
|
hero_background_follows_width?: boolean | null;
|
|
49
49
|
photography_grayscale?: boolean | null;
|
|
50
50
|
word_styles?: Partial<Record<string, Record<string, unknown> | null>> | null;
|
|
51
|
+
text_styles?: {
|
|
52
|
+
id: string;
|
|
53
|
+
kind: "heading" | "body";
|
|
54
|
+
name: string;
|
|
55
|
+
values: Record<string, unknown>;
|
|
56
|
+
}[] | null;
|
|
51
57
|
}
|
|
52
58
|
export type SiteThemeRowPatch = Partial<Omit<SiteThemeRow, "id">>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "efficient-web-builder",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.3.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",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@tabler/icons-react": "^3.46.0",
|
|
42
42
|
"efficient-easel": "^2.0.0",
|
|
43
|
-
"efficient-shell": "^4.171.0",
|
|
43
|
+
"efficient-shell": "^4.171.0 || ^5.0.0",
|
|
44
44
|
"isomorphic-dompurify": "^3.18.0",
|
|
45
45
|
"next": ">=16",
|
|
46
46
|
"react": ">=19",
|