efficient-web-builder 37.1.0 → 37.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.
Files changed (29) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/editor/components/AnchorField.d.ts +8 -0
  3. package/dist/editor/components/AnchorField.js +1 -0
  4. package/dist/editor/components/PartSettingsPanel.js +1 -1
  5. package/dist/editor/components/StylesPanel.js +1 -1
  6. package/dist/editor/components/WebsiteScreenParts.js +1 -1
  7. package/dist/editor/components/WebsiteSettingsPanel.js +1 -1
  8. package/dist/editor/components/storefront-editor.css +27 -4
  9. package/dist/editor/lib/puck/blocks/general/Footprint/fields.d.ts +1 -0
  10. package/dist/editor/lib/puck/blocks/general/Footprint/fields.js +1 -1
  11. package/dist/editor/lib/puck/controls.d.ts +0 -1
  12. package/dist/editor/lib/puck/controls.js +1 -1
  13. package/dist/editor/lib/puck/section-width-fields.js +1 -1
  14. package/dist/format/lib/content/footprint.d.ts +3 -0
  15. package/dist/format/lib/content/footprint.js +1 -1
  16. package/dist/format/lib/content/subscribe.d.ts +2 -18
  17. package/dist/format/lib/content/subscribe.js +2 -2
  18. package/dist/format/lib/editor-words-catalogue.d.ts +9 -9
  19. package/dist/format/lib/editor-words-catalogue.js +4 -4
  20. package/dist/format/lib/popup/behavior.d.ts +43 -0
  21. package/dist/format/lib/popup/behavior.js +1 -0
  22. package/dist/format/lib/popup/look.d.ts +28 -0
  23. package/dist/format/lib/popup/look.js +1 -0
  24. package/dist/format/lib/popup/rules.d.ts +35 -0
  25. package/dist/format/lib/popup/rules.js +1 -0
  26. package/dist/format/lib/source-rules/panel-no-divider-lines.js +1 -1
  27. package/dist/render/components/Footprint.js +1 -1
  28. package/dist/render/lib/puck/blocks/general/Footprint/render.js +2 -2
  29. package/package.json +1 -1
@@ -0,0 +1,43 @@
1
+ export declare const POPUP_TRIGGERS: readonly ["delay", "scroll", "exit"];
2
+ export type PopupTrigger = (typeof POPUP_TRIGGERS)[number];
3
+ export declare const POPUP_SHOW_ON: readonly ["all", "chosen", "except"];
4
+ export type PopupShowOn = (typeof POPUP_SHOW_ON)[number];
5
+ export declare const POPUP_HIDE_AFTER: readonly ["visit", "days", "never", "once"];
6
+ export type PopupHideAfter = (typeof POPUP_HIDE_AFTER)[number];
7
+ export declare const POPUP_DEVICES: readonly ["all", "desktop", "phone"];
8
+ export type PopupDevices = (typeof POPUP_DEVICES)[number];
9
+ export declare const POPUP_AFTER_SUBMIT: readonly ["stop", "continue"];
10
+ export type PopupAfterSubmit = (typeof POPUP_AFTER_SUBMIT)[number];
11
+ export declare const POPUP_DELAY_RANGE: {
12
+ readonly min: 0;
13
+ readonly max: 60;
14
+ };
15
+ export declare const POPUP_SCROLL_RANGE: {
16
+ readonly min: 10;
17
+ readonly max: 90;
18
+ };
19
+ export declare const POPUP_DAYS_RANGE: {
20
+ readonly min: 1;
21
+ readonly max: 90;
22
+ };
23
+ export interface PopupBehavior {
24
+ autoOpen: boolean;
25
+ trigger: PopupTrigger;
26
+ autoOpenDelaySec: number;
27
+ scrollPercent: number;
28
+ showOn: PopupShowOn;
29
+ showOnPages: string[];
30
+ devices: PopupDevices;
31
+ hideAfter: PopupHideAfter;
32
+ hideDays: number;
33
+ afterSubmit: PopupAfterSubmit;
34
+ startDate: string | null;
35
+ endDate: string | null;
36
+ }
37
+ export declare const POPUP_BEHAVIOR_DEFAULTS: PopupBehavior;
38
+ export declare function oneOf<T extends string>(list: readonly T[], v: unknown, fallback: T): T;
39
+ export declare function inRange(v: unknown, range: {
40
+ min: number;
41
+ max: number;
42
+ }, fallback: number): number;
43
+ export declare function resolvePopupBehavior(rootProps: Record<string, unknown> | undefined | null): PopupBehavior;
@@ -0,0 +1 @@
1
+ import{authoredBoolean as c,authoredNumber as u}from"../content/authored-props.js";const l=["delay","scroll","exit"],P=["all","chosen","except"],d=["visit","days","never","once"],f=["all","desktop","phone"],p=["stop","continue"],O={min:0,max:60},h={min:10,max:90},m={min:1,max:90},o={autoOpen:!1,trigger:"delay",autoOpenDelaySec:15,scrollPercent:50,showOn:"all",showOnPages:[],devices:"all",hideAfter:"days",hideDays:7,afterSubmit:"stop",startDate:null,endDate:null};function r(t,e,n){return typeof e=="string"&&t.includes(e)?e:n}function s(t,e,n){const i=u(t,n);return Math.min(e.max,Math.max(e.min,Math.round(i)))}function y(t){return typeof t.hideAfter=="string"?r(d,t.hideAfter,o.hideAfter):t.oncePerSession===!0?"visit":t.oncePerSession===!1?"never":o.hideAfter}function x(t){return Array.isArray(t)?t.map(e=>typeof e=="string"?e.trim():"").filter(Boolean).map(e=>e.startsWith("/")?e:`/${e}`):[]}function a(t){if(typeof t!="string")return null;const e=t.trim();return/^\d{4}-\d{2}-\d{2}$/.test(e)?e:null}function A(t){const e=t??{},n=o;return{autoOpen:c(e.autoOpen,n.autoOpen),trigger:r(l,e.trigger,n.trigger),autoOpenDelaySec:s(e.autoOpenDelaySec,O,n.autoOpenDelaySec),scrollPercent:s(e.scrollPercent,h,n.scrollPercent),showOn:r(P,e.showOn,n.showOn),showOnPages:x(e.showOnPages),devices:r(f,e.devices,n.devices),hideAfter:y(e),hideDays:s(e.hideDays,m,n.hideDays),afterSubmit:r(p,e.afterSubmit,n.afterSubmit),startDate:a(e.startDate),endDate:a(e.endDate)}}export{p as POPUP_AFTER_SUBMIT,o as POPUP_BEHAVIOR_DEFAULTS,m as POPUP_DAYS_RANGE,O as POPUP_DELAY_RANGE,f as POPUP_DEVICES,d as POPUP_HIDE_AFTER,h as POPUP_SCROLL_RANGE,P as POPUP_SHOW_ON,l as POPUP_TRIGGERS,s as inRange,r as oneOf,A as resolvePopupBehavior};
@@ -0,0 +1,28 @@
1
+ import { type HeroGroupPlacement } from "../hero-group-placement.js";
2
+ export declare const POPUP_PAGE_KIND = "popup";
3
+ export declare const POPUP_PLACEMENTS: readonly ["top-left", "top-center", "top-right", "left", "center", "right", "bottom-left", "bottom-center", "bottom-right"];
4
+ export type PopupPlacement = HeroGroupPlacement;
5
+ export declare const POPUP_HEIGHTS: readonly ["auto", "full"];
6
+ export type PopupHeight = (typeof POPUP_HEIGHTS)[number];
7
+ export declare const POPUP_CLOSE_BUTTONS: readonly ["inside", "outside", "none"];
8
+ export type PopupCloseButton = (typeof POPUP_CLOSE_BUTTONS)[number];
9
+ export declare const POPUP_WIDTH_RANGE: {
10
+ readonly min: 240;
11
+ readonly max: 1440;
12
+ };
13
+ export declare const POPUP_TINT_OPACITY_RANGE: {
14
+ readonly min: 0;
15
+ readonly max: 100;
16
+ };
17
+ export interface PopupLook {
18
+ placement: PopupPlacement;
19
+ fullWidth: boolean;
20
+ width: number;
21
+ height: PopupHeight;
22
+ tintColor: string;
23
+ tintOpacity: number;
24
+ outsideClick: boolean;
25
+ closeButton: PopupCloseButton;
26
+ }
27
+ export declare const POPUP_LOOK_DEFAULTS: PopupLook;
28
+ export declare function resolvePopupLook(rootProps: Record<string, unknown> | undefined | null): PopupLook;
@@ -0,0 +1 @@
1
+ import{HERO_GROUP_PLACEMENTS as r}from"../hero-group-placement.js";import{authoredBoolean as n}from"../content/authored-props.js";import{inRange as l,oneOf as e}from"./behavior.js";const f="popup",c=r,P=["auto","full"],p=["inside","outside","none"],s={min:240,max:1440},u={min:0,max:100},O={placement:"center",fullWidth:!1,width:720,height:"auto",tintColor:"#000000",tintOpacity:60,outsideClick:!0,closeButton:"inside"};function h(i,t){return typeof i=="string"&&/^#[0-9a-fA-F]{6}$/.test(i.trim())?i.trim():t}function _(i){const t=i??{},o=O;return{placement:e(c,t.placement,o.placement),fullWidth:n(t.fullWidth,o.fullWidth),width:l(t.width,s,o.width),height:e(P,t.height,o.height),tintColor:h(t.tintColor,o.tintColor),tintOpacity:l(t.tintOpacity,u,o.tintOpacity),outsideClick:n(t.outsideClick,o.outsideClick),closeButton:e(p,t.closeButton,o.closeButton)}}export{p as POPUP_CLOSE_BUTTONS,P as POPUP_HEIGHTS,O as POPUP_LOOK_DEFAULTS,f as POPUP_PAGE_KIND,c as POPUP_PLACEMENTS,u as POPUP_TINT_OPACITY_RANGE,s as POPUP_WIDTH_RANGE,_ as resolvePopupLook};
@@ -0,0 +1,35 @@
1
+ import { type StorageLike } from "../safe-storage.js";
2
+ import type { PopupBehavior, PopupDevices, PopupShowOn, PopupTrigger } from "./behavior.js";
3
+ export declare const POPUP_NEVER_ON: readonly string[];
4
+ export interface PopupStores {
5
+ session: StorageLike;
6
+ local: StorageLike;
7
+ }
8
+ export interface PopupStorageKeys {
9
+ seen: string;
10
+ closedAt: string;
11
+ sentAt: string;
12
+ }
13
+ export declare function popupStorageKeys(popupId: string): PopupStorageKeys;
14
+ export interface PopupContext {
15
+ path: string;
16
+ isPhone: boolean;
17
+ today: string;
18
+ inEditor: boolean;
19
+ }
20
+ export declare function normalizePath(path: string): string;
21
+ export declare function popupAllowedOnPath(path: string, showOn: PopupShowOn, showOnPages: readonly string[]): boolean;
22
+ export declare function popupAllowedOnDevice(devices: PopupDevices, isPhone: boolean): boolean;
23
+ export declare function popupInSchedule(startDate: string | null, endDate: string | null, today: string): boolean;
24
+ export declare function popupHidden(popupId: string, b: PopupBehavior, stores: PopupStores, now: number): boolean;
25
+ export declare function markPopupClosed(popupId: string, stores: PopupStores, now: number): void;
26
+ export declare function markPopupSent(popupId: string, stores: PopupStores, now: number): void;
27
+ export declare function mayAutoOpen(popupId: string, b: PopupBehavior, ctx: PopupContext, stores: PopupStores, now: number): boolean;
28
+ export interface ListedPopup {
29
+ id: string;
30
+ behavior: PopupBehavior;
31
+ }
32
+ export declare function pickAutoPopup<T extends ListedPopup>(popups: readonly T[], ctx: PopupContext, stores: PopupStores, now: number): T | null;
33
+ export declare function effectiveTrigger(trigger: PopupTrigger, hasHoverPointer: boolean): PopupTrigger;
34
+ export declare function scrolledPercent(scrollY: number, viewportH: number, pageH: number): number;
35
+ export declare function localDay(now: Date): string;
@@ -0,0 +1 @@
1
+ import{SUBSCRIBE_POPUP_SLUG as a}from"../content/subscribe.js";import{canPersist as i}from"../safe-storage.js";const c=1440*60*1e3,p=["/checkout","/cart"];function u(t){return t===a?{seen:"storefront-subscribe-seen",closedAt:"storefront-popup-closed-at",sentAt:"storefront-popup-sent-at"}:{seen:`storefront-popup:${t}:seen`,closedAt:`storefront-popup:${t}:closed-at`,sentAt:`storefront-popup:${t}:sent-at`}}function f(t){const e=t.split(/[?#]/)[0]||"/",r=e.startsWith("/")?e:`/${e}`;return r.length>1?r.replace(/\/+$/,"")||"/":r}function d(t,e,r){const n=f(t);if(p.some(s=>n===s||n.startsWith(`${s}/`)))return!1;if(e==="all")return!0;const o=r.some(s=>f(s)===n);return e==="chosen"?o:!o}function m(t,e){return t==="all"?!0:t==="phone"?e:!e}function h(t,e,r){return!(t&&r<t||e&&r>e)}function l(t,e){const r=Number(t.getItem(e));return Number.isFinite(r)&&r>0?r:null}function A(t,e,r,n){const o=u(t);if(e.afterSubmit==="stop"&&l(r.local,o.sentAt)!==null)return!0;if(e.hideAfter==="never")return!1;if(r.session.getItem(o.seen)==="1")return!0;if(e.hideAfter==="visit")return!1;const s=l(r.local,o.closedAt);return s===null?!1:e.hideAfter==="once"?!0:n-s<e.hideDays*c}function S(t,e,r){const n=u(t);e.session.setItem(n.seen,"1"),e.local.setItem(n.closedAt,String(r))}function y(t,e,r){S(t,e,r),e.local.setItem(u(t).sentAt,String(r))}function P(t,e,r,n,o){return!e.autoOpen||r.inEditor||!d(r.path,e.showOn,e.showOnPages)||!m(e.devices,r.isPhone)||!h(e.startDate,e.endDate,r.today)||(e.hideAfter!=="never"||e.afterSubmit==="stop")&&(!i(n.session)||!i(n.local))?!1:!A(t,e,n,o)}function $(t,e,r,n){return t.find(o=>P(o.id,o.behavior,e,r,n))??null}function O(t,e){return t==="exit"&&!e?"delay":t}function k(t,e,r){const n=r-e;return n<=0?100:Math.min(100,Math.max(0,t/n*100))}function v(t){const e=t.getFullYear(),r=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0");return`${e}-${r}-${n}`}export{p as POPUP_NEVER_ON,O as effectiveTrigger,v as localDay,S as markPopupClosed,y as markPopupSent,P as mayAutoOpen,f as normalizePath,$ as pickAutoPopup,m as popupAllowedOnDevice,d as popupAllowedOnPath,A as popupHidden,h as popupInSchedule,u as popupStorageKeys,k as scrolledPercent};
@@ -1,7 +1,7 @@
1
1
  import{ruleChecks as O}from"./rule.js";function j(r){const s=r.split(`
2
2
  `),n=[];return s.forEach((g,a)=>{if(!/border-(top|bottom|left|right)[a-z-]*\s*:[^;]*\bsolid\b/.test(g))return;let $=0,c="?";for(let i=a-1;i>=0;i-=1)if($+=(s[i].match(/\}/g)??[]).length-(s[i].match(/\{/g)??[]).length,$<0){c=s[i].split("{")[0].trim();let h=i-1;for(;h>=0&&s[h].trim().endsWith(",");)c=`${s[h].trim()} ${c}`,h-=1;break}n.push({line:a+1,selector:c,decl:g.trim()})}),n}const y=r=>r.split(/[\s,+>~]/)[0].trim(),k=(r,s)=>s in r||y(s)in r,L=/\bzinc-|--sf-line\b|--sf-divider\b|--sf-input-border\b|--sf-chip-bg\b|--es-line\b|--es-divider\b|--sf-text-secondary\b/,S=[["utility",/(^|["'`\s])border-(t|b|l|r)($|["'`\s])/],["style object",/border(Top|Bottom|Left|Right)\s*:/],["css in a string",/border-(top|bottom|left|right)\s*:/]];function E(r){return/radius/i.test(r)||!L.test(r)?null:S.find(([,s])=>s.test(r))?.[0]??null}function T(r,s){const{check:n,report:g}=O("panel divider lines"),a=s.allowed??{},$=s.pendingElsewhere??{},c=s.allowedTsx??[];{const e=u=>["border",u].join("-"),t=[".a,",".b + .c {",` ${e("top")}: 1px solid red;`,"}",`.d { ${e("radius")}: 4px; }`].join(`
3
3
  `),l=j(t);n("the census finds a directional solid border, with its whole multi-line selector",l.length===1&&l[0].selector===".a, .b + .c"&&y(l[0].selector)===".a",JSON.stringify(l));const d=["zinc","200"].join("-"),f=[["a utility",`<div className="${e("t")} border-${d}" />`,"utility"],["a style object",`style={{ ${["border","Top"].join("")}: "1px solid var(--sf-line)" }}`,"style object"],["CSS in a string",`const s = "${e("left")}: 1px solid var(--es-divider)";`,"css in a string"],["a border in the storefront's own ink",`<div className="${e("t")} border-line" />`,null],["a radius",`<div className="${e("t")} border-${d} rounded" style={{ borderRadius: 4 }} />`,null]];for(const[u,o,p]of f)n(`the sweep reads ${u} as ${p??"no hairline"}`,E(o)===p,o)}const i=[];for(const e of s.panelSheets??[]){const t=r.find(o=>o.path===e)?.text??"",l=j(t);n(`${e} was read and parsed`,t.length>1e4&&l.length>0,`${t.length} bytes, ${l.length} directional border(s)`),i.push(...l.map(o=>({...o,sheet:e})));const f=(t.replace(/\/\*[\s\S]*?\*\//g,"").match(/\[class\*="_PuckFields[^"]*"\][^{]*\{/g)??[]).length;n(`${e} reaches for no Puck field wrapper`,f===0,`${f} rule(s) still select \`[class*="_PuckFields…"]\` — the rows are \`.es-insp-row\` now`);const u=t.replace(/,\s*\n\s*/g,", ");for(const o of s.fullBleed??[]){if(!(o in a))continue;const p=u.indexOf(`
4
- ${o} {`);if(!n(`the allowed full-bleed rule is still in ${e}`,p>=0,o))continue;const v=u.slice(p,u.indexOf("}",p));for(const[w,x]of[["left","--es-insp-pad-x"],["right","--sf-insp-pad-end"]])n(`the full-bleed rule cancels the panel's ${w} padding, so it reaches the edge`,new RegExp(`margin-${w}:\\s*calc\\(var\\(${x}\\)\\s*\\*\\s*-1\\)`).test(v),"inset, this is the line the owner rejected — full bleed is the exemption"),n(`…and puts that ${w} padding back inside, so the words stay on the rows' edge`,new RegExp(`padding-${w}:\\s*var\\(${x}\\)`).test(v))}}for(const e of s.fullBleed??[])n(`the full-bleed selector is an ALLOWED entry: ${e}`,e in a);if(s.panelSheets?.length){const e=i.filter(t=>!k(a,t.selector)&&!k($,t.selector));n(`no unlisted directional border survives in a panel stylesheet (${i.length} censused)`,e.length===0,`${e.length} neither removed, allowed, nor owed to another card — delete it and let the rhythm tokens separate, or add it to the allow-list with a reason if it is a control edge:
4
+ ${o} {`);if(!n(`the allowed full-bleed rule is still in ${e}`,p>=0,o))continue;const v=u.slice(p,u.indexOf("}",p));for(const[w,x]of[["left","--es-insp-pad-x"],["right","--es-insp-pad-end"]])n(`the full-bleed rule cancels the panel's ${w} padding, so it reaches the edge`,new RegExp(`margin-${w}:\\s*calc\\(var\\(${x}\\)\\s*\\*\\s*-1\\)`).test(v),"inset, this is the line the owner rejected — full bleed is the exemption"),n(`…and puts that ${w} padding back inside, so the words stay on the rows' edge`,new RegExp(`padding-${w}:\\s*var\\(${x}\\)`).test(v))}}for(const e of s.fullBleed??[])n(`the full-bleed selector is an ALLOWED entry: ${e}`,e in a);if(s.panelSheets?.length){const e=i.filter(t=>!k(a,t.selector)&&!k($,t.selector));n(`no unlisted directional border survives in a panel stylesheet (${i.length} censused)`,e.length===0,`${e.length} neither removed, allowed, nor owed to another card — delete it and let the rhythm tokens separate, or add it to the allow-list with a reason if it is a control edge:
5
5
  `+e.map(t=>`${t.sheet}:${t.line} ${t.selector} — ${t.decl}`).join(`
6
6
  `))}const h=e=>i.some(t=>t.selector===e||y(t.selector)===e);for(const[e,t]of Object.entries(a))n(`ALLOWED entry ${e} still names a real rule (${t.slice(0,48)}…)`,h(e),"the rule is gone: delete this entry with it");for(const[e,t]of Object.entries($))n(`PENDING entry ${e} is still owed — ${t}`,h(e),"that card has landed and the rule is gone: delete this entry");const b=r.filter(e=>/\.tsx?$/.test(e.path));n(`the repository's own TS/TSX files were swept (${b.length}, at least ${s.minFiles})`,b.length>=s.minFiles);const m=[];for(const e of b)e.text.split(`
7
7
  `).forEach((t,l)=>{const d=E(t);d&&(c.some(f=>f.file===e.path&&t.includes(f.util))||m.push(`${e.path}:${l+1} (${d}) ${t.trim().slice(0,80)}`))});n("no editor panel file draws an unlisted directional border",m.length===0,`${m.length} found:
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as m}from"react/jsx-runtime";import{useEffect as w,useMemo as z,useState as $}from"react";import{footprintPins as E}from"../../format/lib/content/footprint.js";import{bucketByGroup as F,groupColsClass as A}from"../../format/lib/locations-grid.js";import G from"./EditorialSectionHead.js";import{LocationGroupHeader as B}from"./LocationGroupHeader.js";import{renderGold as K,renderHeadline as P}from"./goldPhrases.js";import q from"./PartStyledText.js";import{say as L}from"../../format/lib/editor-words.js";import{parseFootprintSource as D}from"../lib/dealer-source.js";import Q from"./DealerFinder.js";import I from"./SiteMap.js";const a={bodySmall:"text-[length:var(--size-body,10px)]",bodyLarge:"text-[length:var(--size-body,18px)]",labelSmall:"text-[length:var(--size-label,11px)]",labelLarge:"text-[length:var(--size-label,12px)]"};function O({sectionNumber:o="",heading:s="",tagline:x="",offices:l=[],mapTheme:f="auto",padTop:g,padBottom:p,editing:d,omitHead:h=!1,source:i,search:u=!1,searchHint:n="",noMatchText:y="",listPosition:c="below",showDistance:M=!0}){const b=D(i)==="dealers",j=typeof g=="number"?g:120,C=typeof p=="number"?p:120,[k,v]=$(null),H=l.length===0&&!b&&!o&&!s&&!x;if(w(()=>{v(t=>t!==null&&t>=l.length?null:t)},[l]),H&&!d)return null;const T=F(l,t=>String(t.group??""),()=>"");return e("section",{className:"relative z-[2] bg-bg",children:m("div",{className:"mx-auto max-w-[var(--sf-site-width,1600px)] border-b border-line px-[var(--sf-site-gutter,40px)] max-[1100px]:px-[min(24px,var(--sf-site-gutter,40px))] max-[800px]:px-[min(20px,var(--sf-site-gutter,40px))]",style:{paddingTop:j,paddingBottom:C},children:[!h&&(o||s||x)&&e(G,{num:o,title:s?P(s):void 0,desc:x||void 0,spaceBelow:"mb-12"}),b?e(Q,{mapLabel:s.replace(/[=*]/g,"").replace(/\s+/g," ").trim(),mapTheme:f,search:u,searchHint:n,noMatchText:y,listPosition:c,showDistance:M,editing:d}):e(W,{offices:l,mapLabel:s.replace(/[=*]/g,"").replace(/\s+/g," ").trim(),mapTheme:f,activeIndex:k,onSelect:v,editing:d}),!b&&l.length>0&&e("div",{className:"mt-12 flex flex-col gap-8",children:T.map((t,_)=>m("div",{children:[t.key&&e(B,{groupKey:t.key,count:t.items.length}),e("div",{className:["grid gap-[2px] bg-bg",A(t.items.length),t.items.length>2?"max-[1100px]:grid-cols-2 max-[700px]:grid-cols-1":t.items.length===2?"max-[700px]:grid-cols-1":""].join(" "),children:t.items.map(({item:r,index:N})=>{const S=k===N;return m("button",{type:"button",onClick:()=>v(N),"aria-pressed":S,className:["flex flex-col gap-1.5 bg-bg px-6 py-5 text-left transition-colors outline outline-1 -outline-offset-1",S?"outline-accent":"outline-transparent hover:outline-line"].join(" "),children:[m("span",{className:`flex items-center gap-2.5 font-mono ${a.labelSmall} uppercase tracking-[0.28em]`,children:[r.hq&&e("span",{className:`border border-accent bg-accent px-1.5 py-0.5 ${a.bodySmall} text-bg`,children:"HQ"}),r.role&&e("span",{className:"text-accent",children:r.role})]}),r.city&&e("span",{className:`font-display ${a.bodyLarge} font-medium leading-[1.2] tracking-[-0.01em] text-fg`,children:e(q,{value:r.city,children:r.city})}),r.country&&e("span",{className:`font-mono ${a.labelSmall} uppercase tracking-[0.2em] text-fg-dim`,children:r.country}),r.address&&e("span",{className:`font-mono ${a.labelSmall} uppercase tracking-[0.2em] text-fg-dim`,children:K(r.address)})]},N)})})]},t.key?`g:${t.key}`:`ungrouped:${_}`))}),!b&&l.length===0&&d&&e("p",{className:`mt-8 font-mono ${a.labelLarge} uppercase tracking-[0.24em] text-fg-dim`,children:L("Add an office in the inspector")})]})})}function W({offices:o,mapLabel:s,mapTheme:x,activeIndex:l,onSelect:f,editing:g}){const p=z(()=>E(o),[o]),[d,h]=$(null),i=l===null?null:String(l),u=i!==null&&p.some(c=>c.key===i);if(w(()=>{i!==null&&u&&h(c=>({key:i,n:(c?.n??0)+1}))},[i,u]),p.length===0)return g?e("div",{className:"relative flex aspect-[16/9] w-full items-center justify-center overflow-hidden border border-line bg-bg px-6 text-center max-[720px]:aspect-[4/5]",children:e("span",{className:`font-mono ${a.labelLarge} uppercase tracking-[0.24em] text-fg-dim`,children:L("Add office coordinates to plot the map")})}):null;const n=u&&l!==null?o[l]:null,y=n?m("div",{className:"flex items-start gap-3 border border-line bg-bg px-3.5 py-2.5 text-fg shadow-[0_8px_24px_rgba(0,0,0,.4)]",children:[m("div",{className:"min-w-0 flex-1",children:[m("div",{className:`flex items-center gap-2 font-mono ${a.labelSmall} uppercase tracking-[0.28em]`,children:[n.hq&&e("span",{className:`bg-accent px-1.5 py-px ${a.bodySmall} text-bg`,children:"HQ"}),n.role&&e("span",{className:"text-accent",children:n.role})]}),n.city&&e("div",{className:`mt-1.5 font-display ${a.bodyLarge} font-medium leading-[1.2] text-fg`,children:n.city}),n.country&&e("div",{className:`mt-1 font-mono ${a.labelSmall} uppercase tracking-[0.2em] text-fg-dim`,children:n.country})]}),e("button",{type:"button",onClick:()=>f(null),"aria-label":"Close",className:"-mr-1 grid h-6 w-6 shrink-0 place-items-center text-fg-dim hover:text-fg",children:e("svg",{"aria-hidden":!0,width:"12",height:"12",viewBox:"0 0 12 12",fill:"none",stroke:"currentColor",strokeWidth:"1.5",children:e("path",{d:"M2 2l8 8M10 2l-8 8"})})})]}):null;return e(I,{pins:p,mapTheme:x,ariaLabel:s||"Offices",className:"sf-card relative aspect-[16/9] w-full overflow-hidden border border-line max-[720px]:aspect-[4/5]",selectedKey:u?i:null,focus:d,onSelect:c=>f(Number(c)),card:y})}export{O as default};
1
+ "use client";import{jsx as e,jsxs as o}from"react/jsx-runtime";import{useEffect as L,useMemo as F,useState as M}from"react";import{footprintPins as A}from"../../format/lib/content/footprint.js";import{bucketByGroup as B,groupColsClass as G}from"../../format/lib/locations-grid.js";import K from"./EditorialSectionHead.js";import{LocationGroupHeader as P}from"./LocationGroupHeader.js";import{renderGold as q,renderHeadline as D}from"./goldPhrases.js";import Q from"./PartStyledText.js";import{say as j}from"../../format/lib/editor-words.js";import{parseFootprintSource as I}from"../lib/dealer-source.js";import O from"./DealerFinder.js";import W from"./SiteMap.js";const n={bodySmall:"text-[length:var(--size-body,10px)]",bodyLarge:"text-[length:var(--size-body,18px)]",labelSmall:"text-[length:var(--size-label,11px)]",labelLarge:"text-[length:var(--size-label,12px)]"};function X({sectionNumber:c="",heading:i="",tagline:f="",offices:a=[],mapTheme:x="auto",padTop:b,padBottom:p,editing:d,omitHead:v=!1,source:s,search:u=!1,searchHint:r="",noMatchText:k="",listPosition:m="below",showDistance:C=!0}){const h=I(s)==="dealers",H=typeof b=="number"?b:120,T=typeof p=="number"?p:120,[S,N]=M(null),_=a.length===0&&!h&&!c&&!i&&!f;if(L(()=>{N(t=>t!==null&&t>=a.length?null:t)},[a]),_&&!d)return null;const z=B(a,t=>String(t.group??""),()=>"");return e("section",{className:"relative z-[2] bg-bg",children:o("div",{className:"mx-auto max-w-[var(--sf-site-width,1600px)] border-b border-line px-[var(--sf-site-gutter,40px)] max-[1100px]:px-[min(24px,var(--sf-site-gutter,40px))] max-[800px]:px-[min(20px,var(--sf-site-gutter,40px))]",style:{paddingTop:H,paddingBottom:T},children:[!v&&(c||i||f)&&e(K,{num:c,title:i?D(i):void 0,desc:f||void 0,spaceBelow:"mb-12"}),h?e(O,{mapLabel:i.replace(/[=*]/g,"").replace(/\s+/g," ").trim(),mapTheme:x,search:u,searchHint:r,noMatchText:k,listPosition:m,showDistance:C,editing:d}):e(Z,{offices:a,mapLabel:i.replace(/[=*]/g,"").replace(/\s+/g," ").trim(),mapTheme:x,activeIndex:S,onSelect:N,editing:d}),!h&&a.length>0&&e("div",{className:"mt-12 flex flex-col gap-8",children:z.map((t,E)=>o("div",{children:[t.key&&e(P,{groupKey:t.key,count:t.items.length}),e("div",{className:["grid gap-[2px] bg-bg",G(t.items.length),t.items.length>2?"max-[1100px]:grid-cols-2 max-[700px]:grid-cols-1":t.items.length===2?"max-[700px]:grid-cols-1":""].join(" "),children:t.items.map(({item:l,index:y})=>{const w=S===y,g=l.href&&l.linkLabel?{href:l.href,label:l.linkLabel}:null,$=o("button",{type:"button",onClick:()=>N(y),"aria-pressed":w,className:["flex flex-col gap-1.5 bg-bg px-6 py-5 text-left transition-colors outline outline-1 -outline-offset-1",w?"outline-accent":"outline-transparent hover:outline-line",g?"w-full pb-11":""].filter(Boolean).join(" "),children:[o("span",{className:`flex items-center gap-2.5 font-mono ${n.labelSmall} uppercase tracking-[0.28em]`,children:[l.hq&&e("span",{className:`border border-accent bg-accent px-1.5 py-0.5 ${n.bodySmall} text-bg`,children:"HQ"}),l.role&&e("span",{className:"text-accent",children:l.role})]}),l.city&&e("span",{className:`font-display ${n.bodyLarge} font-medium leading-[1.2] tracking-[-0.01em] text-fg`,children:e(Q,{value:l.city,children:l.city})}),l.country&&e("span",{className:`font-mono ${n.labelSmall} uppercase tracking-[0.2em] text-fg-dim`,children:l.country}),l.address&&e("span",{className:`font-mono ${n.labelSmall} uppercase tracking-[0.2em] text-fg-dim`,children:q(l.address)})]},g?void 0:y);return g?o("div",{className:"relative flex",children:[$,e("a",{href:g.href,className:`absolute bottom-5 left-6 font-mono ${n.labelSmall} uppercase tracking-[0.24em] text-accent hover:underline`,children:`→ ${g.label}`})]},y):$})})]},t.key?`g:${t.key}`:`ungrouped:${E}`))}),!h&&a.length===0&&d&&e("p",{className:`mt-8 font-mono ${n.labelLarge} uppercase tracking-[0.24em] text-fg-dim`,children:j("Add an office in the inspector")})]})})}function Z({offices:c,mapLabel:i,mapTheme:f,activeIndex:a,onSelect:x,editing:b}){const p=F(()=>A(c),[c]),[d,v]=M(null),s=a===null?null:String(a),u=s!==null&&p.some(m=>m.key===s);if(L(()=>{s!==null&&u&&v(m=>({key:s,n:(m?.n??0)+1}))},[s,u]),p.length===0)return b?e("div",{className:"relative flex aspect-[16/9] w-full items-center justify-center overflow-hidden border border-line bg-bg px-6 text-center max-[720px]:aspect-[4/5]",children:e("span",{className:`font-mono ${n.labelLarge} uppercase tracking-[0.24em] text-fg-dim`,children:j("Add office coordinates to plot the map")})}):null;const r=u&&a!==null?c[a]:null,k=r?o("div",{className:"flex items-start gap-3 border border-line bg-bg px-3.5 py-2.5 text-fg shadow-[0_8px_24px_rgba(0,0,0,.4)]",children:[o("div",{className:"min-w-0 flex-1",children:[o("div",{className:`flex items-center gap-2 font-mono ${n.labelSmall} uppercase tracking-[0.28em]`,children:[r.hq&&e("span",{className:`bg-accent px-1.5 py-px ${n.bodySmall} text-bg`,children:"HQ"}),r.role&&e("span",{className:"text-accent",children:r.role})]}),r.city&&e("div",{className:`mt-1.5 font-display ${n.bodyLarge} font-medium leading-[1.2] text-fg`,children:r.city}),r.country&&e("div",{className:`mt-1 font-mono ${n.labelSmall} uppercase tracking-[0.2em] text-fg-dim`,children:r.country})]}),e("button",{type:"button",onClick:()=>x(null),"aria-label":"Close",className:"-mr-1 grid h-6 w-6 shrink-0 place-items-center text-fg-dim hover:text-fg",children:e("svg",{"aria-hidden":!0,width:"12",height:"12",viewBox:"0 0 12 12",fill:"none",stroke:"currentColor",strokeWidth:"1.5",children:e("path",{d:"M2 2l8 8M10 2l-8 8"})})})]}):null;return e(W,{pins:p,mapTheme:f,ariaLabel:i||"Offices",className:"sf-card relative aspect-[16/9] w-full overflow-hidden border border-line max-[720px]:aspect-[4/5]",selectedKey:u?s:null,focus:d,onSelect:m=>x(Number(m)),card:k})}export{X as default};
@@ -1,2 +1,2 @@
1
- import{jsx as d}from"react/jsx-runtime";import h from"../../../../../components/Footprint.js";import{FOOTPRINT_DEFAULTS as c}from"../../../../../../format/lib/content/footprint.js";import{parseDealerListPosition as f,parseFootprintSource as u}from"../../../../dealer-source.js";import{hidableText as m}from"efficient-easel/draw";import{parseSectionHeadPlacement as l}from"../../../../../../format/lib/sections/section-head-placement.js";import{PH as o}from"../../../../../../format/lib/puck/blocks/placeholders.js";import{phRows as T,phHide as n}from"../../scaffold.js";import{say as t}from"../../../../../../format/lib/editor-words.js";const r={sectionNumber:o.sectionNumber,heading:`${o.heading}
2
- *${o.accent}*`,tagline:o.body},g=()=>[{role:t("Headquarters"),city:t("City"),country:t("Country"),address:t("Street address"),lat:0,lng:0,hq:!0},{role:t("Office"),city:t("City"),country:t("Country"),address:t("Street address"),lat:0,lng:0,hq:!1}],O={label:"Locations Map",defaultProps:{sectionNumber:"",heading:"",tagline:"",offices:[],mapTheme:c.mapTheme,padTop:120,padBottom:120,source:"typed",search:!1,searchHint:"",noMatchText:"",listPosition:"below",showDistance:!0},render:e=>{const i=l(e.headPlacement)==="own-box",a=s=>i?void 0:s;return d(h,{sectionNumber:a(n(e.sectionNumber,r.sectionNumber,e.puck)),heading:a(n(e.heading,r.heading,e.puck)),tagline:a(n(e.tagline,r.tagline,e.puck)),omitHead:i,offices:T(e.offices,g(),e.puck),mapTheme:e.mapTheme??c.mapTheme,padTop:i?0:typeof e.padTop=="number"?e.padTop:120,padBottom:typeof e.padBottom=="number"?e.padBottom:120,editing:e.puck?.isEditing,source:u(e.source),search:e.search===!0,searchHint:m(e.searchHint),noMatchText:m(e.noMatchText),listPosition:f(e.listPosition),showDistance:e.showDistance!==!1})}};export{r as FOOTPRINT_PH,O as FootprintRender};
1
+ import{jsx as f}from"react/jsx-runtime";import u from"../../../../../components/Footprint.js";import{FOOTPRINT_DEFAULTS as s,footprintOfficeOfRow as l}from"../../../../../../format/lib/content/footprint.js";import{declaredBlockSource as d,sourcedRows as h}from"../../../../../../format/lib/content/block-sources.js";import{parseDealerListPosition as y,parseFootprintSource as g}from"../../../../dealer-source.js";import{hidableText as m}from"efficient-easel/draw";import{parseSectionHeadPlacement as T}from"../../../../../../format/lib/sections/section-head-placement.js";import{PH as r}from"../../../../../../format/lib/puck/blocks/placeholders.js";import{phRows as b,phHide as a}from"../../scaffold.js";import{say as t}from"../../../../../../format/lib/editor-words.js";const c={sectionNumber:r.sectionNumber,heading:`${r.heading}
2
+ *${r.accent}*`,tagline:r.body},w=()=>[{role:t("Headquarters"),city:t("City"),country:t("Country"),address:t("Street address"),lat:0,lng:0,hq:!0},{role:t("Office"),city:t("City"),country:t("Country"),address:t("Street address"),lat:0,lng:0,hq:!1}],P=()=>[{role:t("Headquarters"),city:t("City"),country:t("Country"),address:t("Street address"),hq:"true"},{role:t("Office"),city:t("City"),country:t("Country"),address:t("Street address")}];function S(e){const o=()=>b(e.offices,w(),e.puck);if(!d(e))return o();const i=e.puck?.isEditing===!0,n=h(e,i,P());return!n.sample&&!n.rows.length?o():n.rows.map(l)}const q={label:"Locations Map",defaultProps:{sectionNumber:"",heading:"",tagline:"",offices:[],mapTheme:s.mapTheme,padTop:120,padBottom:120,source:"typed",search:!1,searchHint:"",noMatchText:"",listPosition:"below",showDistance:!0},render:e=>{const o=T(e.headPlacement)==="own-box",i=n=>o?void 0:n;return f(u,{sectionNumber:i(a(e.sectionNumber,c.sectionNumber,e.puck)),heading:i(a(e.heading,c.heading,e.puck)),tagline:i(a(e.tagline,c.tagline,e.puck)),omitHead:o,offices:S(e),mapTheme:e.mapTheme??s.mapTheme,padTop:o?0:typeof e.padTop=="number"?e.padTop:120,padBottom:typeof e.padBottom=="number"?e.padBottom:120,editing:e.puck?.isEditing,source:d(e)?"typed":g(e.source),search:e.search===!0,searchHint:m(e.searchHint),noMatchText:m(e.noMatchText),listPosition:y(e.listPosition),showDistance:e.showDistance!==!1})}};export{c as FOOTPRINT_PH,q as FootprintRender};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "efficient-web-builder",
3
- "version": "37.1.0",
3
+ "version": "37.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",