efficient-web-builder 43.0.0 → 44.0.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 (65) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/editor/components/CanvasPartsBridge.d.ts +1 -0
  3. package/dist/editor/components/CanvasPartsBridge.js +1 -1
  4. package/dist/editor/components/PreviewPartAnchors.js +1 -1
  5. package/dist/editor/components/PreviewThemeFrame.d.ts +1 -1
  6. package/dist/editor/components/PreviewThemeFrame.js +3 -19
  7. package/dist/editor/components/SectionTextPartBridge.js +1 -1
  8. package/dist/editor/components/StandaloneSectionEditor.js +1 -1
  9. package/dist/editor/components/StorefrontEditor.js +1 -1
  10. package/dist/editor/components/storefront-editor.css +16 -77
  11. package/dist/editor/lib/document/MarkupToolbar.d.ts +6 -2
  12. package/dist/editor/lib/document/MarkupToolbar.js +1 -1
  13. package/dist/editor/lib/document/blocks/general/ButtonBlock/fields.js +1 -1
  14. package/dist/editor/lib/document/controls.d.ts +1 -0
  15. package/dist/editor/lib/document/controls.js +1 -1
  16. package/dist/editor/lib/document/field-groups.js +1 -1
  17. package/dist/editor/lib/document/overrides.js +1 -1
  18. package/dist/editor/lib/document/part-anchors.d.ts +7 -0
  19. package/dist/editor/lib/document/part-anchors.js +1 -1
  20. package/dist/format/lib/editor-words-catalogue.d.ts +0 -1
  21. package/dist/format/lib/editor-words-catalogue.js +1 -1
  22. package/dist/format/lib/markup.d.ts +1 -0
  23. package/dist/format/lib/markup.js +2 -2
  24. package/dist/format/lib/popup/rules.d.ts +1 -1
  25. package/dist/format/lib/popup/rules.js +1 -1
  26. package/dist/render/components/BlockFrame.d.ts +1 -1
  27. package/dist/render/components/Btn.js +1 -1
  28. package/dist/render/components/ButtonBlock.js +1 -1
  29. package/dist/render/components/ContactLocations.js +3 -45
  30. package/dist/render/components/Divider.d.ts +1 -1
  31. package/dist/render/components/Divider.js +1 -1
  32. package/dist/render/components/Flex.d.ts +3 -9
  33. package/dist/render/components/Flex.js +1 -1
  34. package/dist/render/components/Heading.d.ts +1 -1
  35. package/dist/render/components/HeroGroup.d.ts +3 -9
  36. package/dist/render/components/HeroGroup.js +1 -1
  37. package/dist/render/components/HeroSection.js +1 -11
  38. package/dist/render/components/HeroSingle.js +1 -11
  39. package/dist/render/components/PreviewTickerContext.d.ts +3 -0
  40. package/dist/render/components/PreviewTickerContext.js +1 -1
  41. package/dist/render/components/SiteGutterFrame.d.ts +1 -1
  42. package/dist/render/components/SiteGutterFrame.js +1 -1
  43. package/dist/render/components/Text.d.ts +1 -1
  44. package/dist/render/lib/content/button-look.js +1 -0
  45. package/dist/{format → render}/lib/content/section-padding.d.ts +23 -5
  46. package/dist/render/lib/content/section-padding.js +1 -0
  47. package/dist/render/lib/content/view-values.d.ts +10 -0
  48. package/dist/render/lib/content/view-values.js +1 -0
  49. package/dist/render/lib/document/blocks/general/Divider/render.js +1 -1
  50. package/dist/render/lib/document/blocks/general/Flex/render.js +1 -1
  51. package/dist/render/lib/document/blocks/general/Heading/render.js +1 -1
  52. package/dist/render/lib/document/blocks/general/HeroGroup/render.js +1 -1
  53. package/dist/render/lib/document/blocks/general/Text/render.js +1 -1
  54. package/dist/render/lib/document/blocks/general/section-to-box-row-parts.js +1 -1
  55. package/dist/render/lib/document/hero-media-parts.d.ts +2 -2
  56. package/dist/render/lib/document/part-styles.d.ts +0 -1
  57. package/dist/render/lib/document/part-styles.js +2 -2
  58. package/dist/render/lib/document/passes/section-padding.js +1 -1
  59. package/dist/render/lib/document/text-parts.d.ts +0 -2
  60. package/dist/render/lib/document/text-parts.js +1 -1
  61. package/dist/render/lib/text-styles/site-text-styles.js +2 -2
  62. package/package.json +1 -1
  63. package/dist/format/lib/content/button-look.js +0 -1
  64. package/dist/format/lib/content/section-padding.js +0 -1
  65. /package/dist/{format → render}/lib/content/button-look.d.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ ## 44.0.0 - 2026-10-28
4
+
5
+ **MAJOR for hosts.** Published paths and names go (harness CI-3: an export removed is a major); nothing saved changes. Found by comparing every `dist/**/*.d.ts` of npm 43.0.0 with this build:
6
+
7
+ - Removed paths (they move to the `render` side, #331): `format/lib/content/section-padding` → `render/lib/content/section-padding`; `format/lib/content/button-look` → `render/lib/content/button-look`.
8
+ - Removed names: `PART_SELECTED_ATTR` and `partOpenOn` (`lib/document/text-parts`, #310); `PART_PHONE_MAX_CSS` (`lib/document/part-styles`, #331: import `PHONE_MEDIA` from `render/lib/content/view-values`).
9
+ - Changed signatures (#331): `sectionPadAttrs` takes one `PadValues`; `padValuesOf(props, keys?, sides?)` reads the tablet keys; `components/Flex` and `components/HeroGroup` take one `pad` in place of eight padding props.
10
+
11
+ Peers are unchanged from 43.0.0 (`efficient-easel` `^23.0.0`, `efficient-shell` `^10.13.0`).
12
+
13
+ ### Changed (one box per text, #310)
14
+
15
+ - One box per text. The page no longer draws its own line on the words (CSS rules C, D, E and the portal focus ring are gone). The open part's box is the engine's: CanvasPartsBridge hands selectedPart(doc). PartAwareComponentOverlay and partOpenOn are removed. The Hero picture is an engine part too. Needs the efficient-easel release with CanvasParts.selectedPart.
16
+ - **BREAKING:** `PART_SELECTED_ATTR` and `partOpenOn` (`lib/document/text-parts`) are removed; no host imports them (efficient-storefront-blocks, efficient-storefront, efficient-admin-portal main, 2026-10-27).
17
+
18
+ ### Changed (one Clear formatting, #311)
19
+
20
+ - One Clear formatting. The copy field's bar uses the shell's Clear formatting button instead of its own. Selected words: those words. Nothing selected: the whole field. A link stays. The range rule is efficient-easel's clearRangeOf. Needs the efficient-easel release with clearRangeOf.
21
+
22
+ ### Fixed (C6: the scrolling bar and a city's picture are engine parts)
23
+
24
+ - **HeroSection's scrolling bar and ContactLocations' city picture and map have no box system of their own** (GG 2026-10-26, system duplicates C6). Each kept an outline stylesheet (`HERO_TICKER_PICK_CSS`, `.loc-part-pick::after`), a capture-phase click and a `data-selected` marker. They now carry a marker (`data-sf-hero-ticker`, `data-loc-pick`); `partOfBlockAt` finds them (with `whole`), `CanvasPartsBridge` routes their ids to the ticker and location bridges and hands their element, and efficient-easel picks them after their block (first click the block, the next the part) and draws their one box. `PreviewLocationPartProvider` now wraps `CanvasPartsBridge` in both editors so the bridge can read it. The reel, dots and arrows keep their click: they move the slideshow. Dead state (`puckId`, the selected flags, `rootRef`) is gone; `CANVAS_ACCENT` has no user here any more and stays for storefront-blocks.
25
+ - Guards: `scripts/test-picks-are-engine-parts.tsx` (red first); `scripts/test-locations-grid.ts` and `scripts/test-hero-swipe.tsx` follow the removed click and portal mark.
26
+
27
+ ### Added (a padding's tablet value; three-views plan 2026-10-23, PR 3a)
28
+
29
+ - **BREAKING: `lib/content/section-padding` moves from the `format` side to the `render` side**. It reads the per-view keys and rules from `efficient-easel/draw`, which a format module may not import. A host imports it as `efficient-web-builder/render/lib/content/section-padding` (efficient-storefront-blocks: three guard scripts).
30
+ - **BREAKING: `sectionPadAttrs` takes one `PadValues`** (four sides, each with its tablet and phone value) in place of its eight arguments (top, bottom, topPhone, bottomPhone, left, right, leftPhone, rightPhone).
31
+ - **BREAKING: `padValuesOf(props, keys?, sides?)`** reads `<key>Tablet` beside `<key>Phone`, from `SECTION_PAD_KEYS` by default; `keys` names another key set and `sides: false` reads top and bottom only. Its `PadValues` gains `topTablet`, `bottomTablet`, `leftTablet` and `rightTablet`.
32
+ - **BREAKING: `components/Flex` loses `padTop` … `padRightPhone`** (eight props): it takes one `pad` (`PadValues`).
33
+ - **BREAKING: `components/HeroGroup` loses `sectionPaddingTop` … `sectionPaddingRightPhone`** (eight props): it takes one `pad` (`PadValues`).
34
+ - **BREAKING: `format/lib/content/button-look` moves to `render/lib/content/button-look`** (it pads through `padSideAttrs` in section-padding). Host search: storefront-blocks 0 imports, storefront 0; admin-portal has no web-builder dependency.
35
+ - **BREAKING: `PART_PHONE_MAX_CSS` (`lib/document/part-styles`) is deleted.** It was a second name for the phone query: import `PHONE_MEDIA` from `efficient-web-builder/render/lib/content/view-values` (efficient-storefront-blocks: `components/ChatLauncher` and `scripts/test-chat-launcher-settings.tsx`).
36
+ - **`lib/content/view-values` (render): the one rule version and the one pair of media queries.** `RESPONSIVE_RULES` is `"v1"`: every page draws by easel's `FOLLOW_RULES` (an empty Tablet follows Desktop, an empty Phone follows Tablet), which is what every page draws today. The switch to `AUTO_RULES` is this one constant, for every site at once, after Lewis looks at the side-by-side page. `TABLET_MEDIA` and `PHONE_MEDIA` are built from easel's tier edges, and `PHONE_MEDIA` is the one phone query (the part styles and site text styles draw under it). `viewOverrides` is the one rule for when a view draws a value of its own: it is stored, or the rule set works out a value different from Desktop's.
37
+ - **Padding draws its tablet value.** `padValuesOf` reads `<key>Tablet` (easel's `tabletKey`) beside `<key>Phone`; `sectionPadAttrs` takes one `PadValues` (four sides, three views) and emits `.sf-pad-<side>-tablet` with `--sf-pad-<s>-tablet` for a side whose tablet value is drawn (the CSS is efficient-storefront-blocks #239). A stored tablet value with no phone value is drawn on the phone too: Phone's parent is Tablet. `padSideAttrs` (the one side / view builder the Button shares) takes an optional `tablet` and `desktop` beside `inline` and `phone`; a two-argument call draws what it drew. Box (`Flex`, now one `pad` prop), HeroGroup (one `pad` prop), the Divider (its own top and bottom now count a tablet value too) and the section padding pass hand the values over through `padValuesOf`.
38
+ - **No stored page changes.** No page has a tablet value; under v1 a node with no tablet value draws the bytes it drew before: `scripts/test-section-pad-bytes.tsx` holds 1282 outputs (576 value mixes through both padding doors, and page renders of Box, Box card, Text, Heading and HeroGroup), recorded on main before the change.
39
+ - `scripts/test-view-values-padding.tsx` (red first: the module did not exist).
40
+ - The Box card's padding defaults read the stored sides with `finiteNumber` (#328), so `components/Flex.tsx` has no number reader of its own and leaves `scripts/fixtures/finite-number.baseline.json` (8 to 0).
41
+ - Needs efficient-easel with `FOLLOW_RULES` (easel #365).
42
+
43
+ **REMOVALS (44.0.0):** `dist/format/lib/content/section-padding.js`, `.d.ts`, `dist/format/lib/content/button-look.js`, `.d.ts` — section-padding moves from format/ to render/ (it reads efficient-easel/draw, which a format module may not import); button-look follows it (it pads through `padSideAttrs`). The entry is in `scripts/verify-published-entries.mjs` (main's from #355, plus the 2 button-look files in 7a5d3c3a).
44
+
45
+ ### Added (a date row)
46
+ - **New panel row `date(label, icon?, hint?)`** (`lib/document/controls`): ONE calendar day, stored `YYYY-MM-DD`, the day the merchant picked, in any time zone. The picker is the shell's `DatePicker`. For a popup's Schedule (`Start date`, `End date`; popups and cart drawer plan, PR 8), which `lib/popup/rules` reads in the visitor's own day. `dateTime` stays the row for one instant (the Countdown's end): it stores UTC, so a Sydney midnight would store the day before.
47
+ - The day is read and written with efficient-shell/format `fromDateKey` / `toDateKey`; `lib/popup/rules` `localDay` is `toDateKey`.
48
+ - Two group labels are filed (`lib/document/field-groups` `LABEL_GROUP`): `Schedule` under Layout, beside `Behavior`; `Placement` under Position, beside `Nudge`. Neither heading is drawn. `test-panel-group-order`'s baseline lists both as blocks headings.
49
+ - Guard: new `scripts/test-date-row.tsx`, run in the Sydney zone.
50
+
3
51
  ## 43.0.0 - 2026-10-27
4
52
 
5
53
  **MAJOR for hosts.** Three peers and names move at once (Victor Mau, 2026-10-27: "cut web-builder 43.0.0 now"; #331, #282, #310 and #311 were not merged and go to the next release):
@@ -2,3 +2,4 @@ import { type ReactNode } from "react";
2
2
  export declare function CanvasPartsBridge({ children }: {
3
3
  children: ReactNode;
4
4
  }): import("react").JSX.Element;
5
+ export declare function openPartElement(doc: Pick<Document, "querySelectorAll">, partId: string | null): Element | null;
@@ -1 +1 @@
1
- "use client";import{jsx as a}from"react/jsx-runtime";import{useMemo as i,useRef as u}from"react";import{CanvasPartsContext as m}from"efficient-easel/easel";import{usePreviewParts as d}from"efficient-easel/draw/client";import{partOfBlockAt as l}from"../lib/document/part-anchors.js";import{decodePartId as f,encodePartId as p}from"../../render/lib/document/text-parts.js";function w({children:s}){const{selectedPartId:t,select:e}=d(),r=u(t);r.current=t;const c=i(()=>({partAt:l,selected:()=>r.current,select:o=>{if(o){e(o);return}const n=r.current?f(r.current)?.nodeId:null;n&&e(p(n,null))}}),[e]);return a(m.Provider,{value:c,children:s})}export{w as CanvasPartsBridge};
1
+ "use client";import{jsx as k}from"react/jsx-runtime";import{useMemo as v,useRef as O}from"react";import{CanvasPartsContext as _}from"efficient-easel/easel";import{usePreviewParts as w}from"efficient-easel/draw/client";import{isOnlyPart as x,partLabelOf as y,partOfBlockAt as C}from"../lib/document/part-anchors.js";import{say as H}from"../../format/lib/editor-words.js";import{decodePartId as T,encodePartId as L,PART_ATTR as b}from"../../render/lib/document/text-parts.js";import{HERO_PART_ATTR as h,readHeroPartId as p}from"../../render/lib/document/hero-media-parts.js";import{usePreviewHeroPart as q}from"../../render/components/PreviewHeroPartContext.js";import{TICKER_PART_ATTR as B,readTickerPartId as A,tickerPartId as E,usePreviewTicker as K}from"../../render/components/PreviewTickerContext.js";import{decodeLocationPartId as $,usePreviewLocationPart as g}from"../../render/components/PreviewLocationPartContext.js";import{LOCATION_PICK_ATTR as j}from"../lib/document/part-anchors.js";function X({children:m}){const{selectedPartId:o,select:l}=w(),{selectedHeroPart:P,select:u}=q(),{selectedHeroId:i,select:c}=K(),{selectedLocationPartId:a,select:f}=g(),r=P??(i?E(i):null)??a??o,t=O(r);t.current=r;const R=v(()=>({partAt:C,selected:()=>t.current,selectedPart:e=>{const n=t.current,s=I(e,n);if(!n||!s)return null;const d=y(s,n);return{id:n,element:s,whole:x(s,n),...d?{label:H(d)}:{}}},select:e=>{if(e&&$(e)){f(e);return}if(e&&p(e)){u(e);return}const n=A(e);if(n){c(n);return}if(e){l(e);return}const s=t.current?T(t.current)?.nodeId:null;s&&l(L(s,null))}}),[l,u,c,f,r]);return k(_.Provider,{value:R,children:m})}function I(m,o){if(!o||!T(o)?.propKey)return null;const l=r=>r.replace(/["\\]/g,"\\$&"),P=[...m.querySelectorAll(`[${b}="${l(o)}"]`)],u=P.find(r=>!P.some(t=>t!==r&&r.contains(t)));if(u)return u;const i=(r,t)=>[...m.querySelectorAll(`[data-easel-block="${l(r)}"] ${t}`)][0]??null,c=$(o);if(c)return i(c.nodeId,`[${j}="${c.index}:${c.part}"]`);const a=p(o);if(a)return i(a.nodeId,`[${h}="${a.part}"]`);const f=A(o);return f?i(f,`[${B}]`):null}export{X as CanvasPartsBridge,I as openPartElement};
@@ -1 +1 @@
1
- "use client";import{jsx as L}from"react/jsx-runtime";import{readInks as k}from"../../format/lib/document/part-inks.js";import{useEffect as F,useRef as J}from"react";import{markOverlayPortal as z}from"../../format/lib/document/overlay-portal.js";import{usePreviewParts as B}from"efficient-easel/draw/client";import{usePartStyle as Y}from"./PreviewPartStyleContext.js";import{usePreviewDevice as $}from"efficient-easel/draw/client";import{encodePartId as j}from"efficient-easel/draw";import{BLOCK_ATTR as G,engagePartAnchors as H}from"../lib/document/part-anchors.js";import{PART_ATTR as O,PART_SELECTED_ATTR as E,PART_STYLE_KIND_ATTR as w,PART_STYLE_OWNER_ATTR as M,partStyleOwnerOf as v}from"../../render/lib/document/text-parts.js";import{PART_STYLE_PROPERTIES as _,applyPartStyles as x,blockDrawsTextStyle as q,partFontKeyOf as V,partStyleBase as Q,partStyleSource as U}from"../../render/lib/document/part-styles.js";import{fontRoleOfClassName as X,styleRoleOfClassName as Z}from"../../format/lib/fonts.js";import{typeScaleGroupOfClassName as N}from"../../format/lib/theme.js";import{styleKeyForPart as ee}from"../../format/lib/sections/section-text-kinds.js";function te(a){let o=null,s=null;for(let t=a;t&&(o===null||s===null);t=t.parentElement){const c=t.getAttribute("class");o??=Z(c),s??=N(c)}return{faceRole:o??"body",sizeGroup:s}}function C(a){const o=a.style,s={};for(const r of _)s[r]=o[r]??"",o[r]="";const t=getComputedStyle(a),c=getComputedStyle(a.ownerDocument.documentElement),p=Q({fontSize:t.fontSize,fontWeight:t.fontWeight,lineHeight:t.lineHeight,letterSpacing:t.letterSpacing,textAlign:t.textAlign,textTransform:t.textTransform,paddingTop:t.paddingTop,maxWidth:t.maxWidth},V(t.fontFamily,r=>c.getPropertyValue(r)));for(const r of _)o[r]=s[r];return p}function re({needles:a,styles:o,type:s,children:t}){const c=J(null),{selectedPartId:p}=B(),{setPartStyle:r}=Y(),d=$()==="mobile",y=JSON.stringify(a),S=JSON.stringify(o);return F(()=>{const f=c.current;if(!f)return;const g=[],T=()=>f.parentElement,D=l=>{const n=T();if(!n)return null;const m=new MutationObserver(l);return m.observe(n,{attributes:!0,attributeFilter:[G]}),()=>m.disconnect()},W=l=>{const n=new MutationObserver(l);return n.observe(f,{childList:!0,subtree:!0,characterData:!0}),()=>n.disconnect()};let u=[];g.push(()=>{for(const l of u)l();u=[]});const I=JSON.parse(y),h=JSON.parse(S),K=H(f,I,T,D,(l,n,m)=>{for(const e of u)e();u=[];const b=[];for(const e of m){const i=e,R=z(i);R&&u.push(R),i.getAttribute(O)===p?(i.setAttribute(E,""),b.push(i)):i.removeAttribute(E)}const A=U(n,p,b,e=>X(e)!==null||N(e)!==null);if(A&&p){const e=A;r({partId:p,...te(e),base:C(e),inks:k(e),...(()=>{const i=v(e);return i?{styleOwner:i}:{}})()})}x(m.filter(e=>!v(e)).map(e=>({element:e,partId:e.getAttribute(O)??""})),h,e=>C(e),e=>ee(s,e),void 0,d,e=>q(s,e));const P=[...f.querySelectorAll(`[${M}="${CSS.escape(n)}"][${w}]`)];P.length&&x(P.map(e=>({element:e,partId:j(n,e.getAttribute(w)??"")})),h,void 0,e=>e,void 0,d)},W);return()=>{K();for(const l of g)l()}},[y,S,p,r,d]),L("div",{ref:c,"data-sf-part-host":"",style:{display:"contents"},children:t})}export{re as default,C as measureStyleBase,te as styleTagsOf};
1
+ "use client";import{jsx as K}from"react/jsx-runtime";import{readInks as k}from"../../format/lib/document/part-inks.js";import{useEffect as L,useRef as F}from"react";import{markOverlayPortal as J}from"../../format/lib/document/overlay-portal.js";import{usePreviewParts as z}from"efficient-easel/draw/client";import{usePartStyle as B}from"./PreviewPartStyleContext.js";import{usePreviewDevice as Y}from"efficient-easel/draw/client";import{encodePartId as $}from"efficient-easel/draw";import{BLOCK_ATTR as j,engagePartAnchors as G}from"../lib/document/part-anchors.js";import{PART_ATTR as R,PART_STYLE_KIND_ATTR as w,PART_STYLE_OWNER_ATTR as H,partStyleOwnerOf as E}from"../../render/lib/document/text-parts.js";import{PART_STYLE_PROPERTIES as v,applyPartStyles as x,blockDrawsTextStyle as M,partFontKeyOf as q,partStyleBase as V,partStyleSource as Q}from"../../render/lib/document/part-styles.js";import{fontRoleOfClassName as U,styleRoleOfClassName as X}from"../../format/lib/fonts.js";import{typeScaleGroupOfClassName as _}from"../../format/lib/theme.js";import{styleKeyForPart as Z}from"../../format/lib/sections/section-text-kinds.js";function ee(a){let o=null,s=null;for(let t=a;t&&(o===null||s===null);t=t.parentElement){const i=t.getAttribute("class");o??=X(i),s??=_(i)}return{faceRole:o??"body",sizeGroup:s}}function N(a){const o=a.style,s={};for(const r of v)s[r]=o[r]??"",o[r]="";const t=getComputedStyle(a),i=getComputedStyle(a.ownerDocument.documentElement),c=V({fontSize:t.fontSize,fontWeight:t.fontWeight,lineHeight:t.lineHeight,letterSpacing:t.letterSpacing,textAlign:t.textAlign,textTransform:t.textTransform,paddingTop:t.paddingTop,maxWidth:t.maxWidth},q(t.fontFamily,r=>i.getPropertyValue(r)));for(const r of v)o[r]=s[r];return c}function te({needles:a,styles:o,type:s,children:t}){const i=F(null),{selectedPartId:c}=z(),{setPartStyle:r}=B(),d=Y()==="mobile",y=JSON.stringify(a),S=JSON.stringify(o);return L(()=>{const f=i.current;if(!f)return;const g=[],h=()=>f.parentElement,C=l=>{const n=h();if(!n)return null;const m=new MutationObserver(l);return m.observe(n,{attributes:!0,attributeFilter:[j]}),()=>m.disconnect()},W=l=>{const n=new MutationObserver(l);return n.observe(f,{childList:!0,subtree:!0,characterData:!0}),()=>n.disconnect()};let u=[];g.push(()=>{for(const l of u)l();u=[]});const D=JSON.parse(y),T=JSON.parse(S),I=G(f,D,h,C,(l,n,m)=>{for(const e of u)e();u=[];const P=[];for(const e of m){const p=e,A=J(p);A&&u.push(A),p.getAttribute(R)===c&&P.push(p)}const b=Q(n,c,P,e=>U(e)!==null||_(e)!==null);if(b&&c){const e=b;r({partId:c,...ee(e),base:N(e),inks:k(e),...(()=>{const p=E(e);return p?{styleOwner:p}:{}})()})}x(m.filter(e=>!E(e)).map(e=>({element:e,partId:e.getAttribute(R)??""})),T,e=>N(e),e=>Z(s,e),void 0,d,e=>M(s,e));const O=[...f.querySelectorAll(`[${H}="${CSS.escape(n)}"][${w}]`)];O.length&&x(O.map(e=>({element:e,partId:$(n,e.getAttribute(w)??"")})),T,void 0,e=>e,void 0,d)},W);return()=>{I();for(const l of g)l()}},[y,S,c,r,d]),K("div",{ref:i,"data-sf-part-host":"",style:{display:"contents"},children:t})}export{te as default,N as measureStyleBase,ee as styleTagsOf};
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from "react";
2
- export declare const PART_PICK_CSS = "\n[data-sf-part][data-sf-part] { cursor: text; }\n[data-sf-part-selected][data-sf-part-selected][data-sf-part-selected] {\n outline: 1px solid var(--es-accent, #2563eb);\n outline-offset: 2px;\n}\n[data-sf-part-selected][data-sf-part-selected]:has([data-sf-part-selected]),\n[data-easel-overlay-portal][data-easel-overlay-portal]:has([data-sf-part-selected]) {\n outline: none;\n}\n[data-sf-part-selected][data-sf-part-selected][data-sf-part-selected][data-es-typing],\n[data-es-typing] [data-sf-part-selected][data-sf-part-selected][data-sf-part-selected] {\n outline: none;\n}\n[data-easel-overlay-portal][data-easel-overlay-portal][data-es-typing],\n[data-es-typing] [data-easel-overlay-portal][data-easel-overlay-portal] {\n outline: none;\n}\n";
2
+ export declare const PART_PICK_CSS = "\n[data-sf-part][data-sf-part] { cursor: text; }\n";
3
3
  export default function PreviewThemeFrame({ children, document: previewDocument, }: {
4
4
  children: ReactNode;
5
5
  document?: Document;
@@ -1,19 +1,3 @@
1
- "use client";import{jsx as s,Fragment as f,jsxs as d}from"react/jsx-runtime";import{useEffect as n,useLayoutEffect as h}from"react";import{usePreviewHeader as $}from"../../render/components/PreviewHeaderContext.js";import{CANVAS_ACCENT as p}from"../../format/lib/canvas-accent.js";import{PART_ATTR as l,PART_SELECTED_ATTR as e}from"../../render/lib/document/text-parts.js";import{syncPreviewSurfaces as u,syncPreviewTheme as y}from"../../format/lib/theme-dom.js";import{normalizeTheme as T}from"../../format/lib/theme.js";import{CanvasOwnStyles as x}from"../lib/editor-canvas-styles.js";import{runFitWordsIn as S}from"../../format/lib/fit-words.js";const _=`
2
- [${l}][${l}] { cursor: text; }
3
- [${e}][${e}][${e}] {
4
- outline: 1px solid ${p};
5
- outline-offset: 2px;
6
- }
7
- [${e}][${e}]:has([${e}]),
8
- [data-easel-overlay-portal][data-easel-overlay-portal]:has([${e}]) {
9
- outline: none;
10
- }
11
- [${e}][${e}][${e}][data-es-typing],
12
- [data-es-typing] [${e}][${e}][${e}] {
13
- outline: none;
14
- }
15
- [data-easel-overlay-portal][data-easel-overlay-portal][data-es-typing],
16
- [data-es-typing] [data-easel-overlay-portal][data-easel-overlay-portal] {
17
- outline: none;
18
- }
19
- `;function c({children:i,document:t}){const{theme:m,themeMode:r,themeSwitchShown:a}=$(),o=T(m);return n(()=>{if(t)return y(t,{mode:r,switchShown:a})},[t,r,a]),n(()=>{if(t)return u(t,o)},[t,o]),h(()=>{if(t)return S(t)},[t]),d(f,{children:[s(x,{}),s("style",{children:_}),i]})}export{_ as PART_PICK_CSS,c as default};
1
+ "use client";import{jsx as o,Fragment as h,jsxs as a}from"react/jsx-runtime";import{useEffect as m,useLayoutEffect as u}from"react";import{usePreviewHeader as d}from"../../render/components/PreviewHeaderContext.js";import{PART_ATTR as n}from"../../render/lib/document/text-parts.js";import{syncPreviewSurfaces as c,syncPreviewTheme as T}from"../../format/lib/theme-dom.js";import{normalizeTheme as l}from"../../format/lib/theme.js";import{CanvasOwnStyles as x}from"../lib/editor-canvas-styles.js";import{runFitWordsIn as P}from"../../format/lib/fit-words.js";const S=`
2
+ [${n}][${n}] { cursor: text; }
3
+ `;function _({children:f,document:r}){const{theme:i,themeMode:e,themeSwitchShown:t}=d(),s=l(i);return m(()=>{if(r)return T(r,{mode:e,switchShown:t})},[r,e,t]),m(()=>{if(r)return c(r,s)},[r,s]),u(()=>{if(r)return P(r)},[r]),a(h,{children:[o(x,{}),o("style",{children:S}),f]})}export{S as PART_PICK_CSS,_ as default};
@@ -1 +1 @@
1
- "use client";import{jsx as R}from"react/jsx-runtime";import{useEffect as d,useRef as g}from"react";import{markOverlayPortal as y}from"../../format/lib/document/overlay-portal.js";import{measureStyleBase as E,styleTagsOf as b}from"./PreviewPartAnchors.js";import{usePreviewParts as S}from"efficient-easel/draw/client";import{usePartStyle as _}from"./PreviewPartStyleContext.js";import{PART_SELECTED_ATTR as o,REGION_PART_ATTR as A,encodePartId as v}from"../../render/lib/document/text-parts.js";import{TEXT_REGION_ATTR as T,textRegionOfAttr as x,textRegionPartKey as O}from"../../format/lib/sections/text-regions.js";import{regionsForSection as h}from"../../format/lib/sections/section-text-regions.js";function I({nodeId:e,sectionType:s,children:P}){const i=g(null),{selectedPartId:n}=S(),{setPartStyle:f}=_();return d(()=>{const m=i.current,c=h(s);if(!m||!e||!c)return;const u=[],l=Array.from(m.querySelectorAll(`[${T}]`));for(const t of l){const a=x(c,t.getAttribute(T));if(!a)continue;const p=y(t);p&&u.push(p);const r=v(e,O(a));t.setAttribute(A,r),r===n?(t.setAttribute(o,""),f({partId:r,...b(t),base:E(t)})):t.removeAttribute(o)}return()=>{for(const t of u)t();for(const t of l)t.removeAttribute(o),t.removeAttribute(A)}},[e,s,n,f]),R("div",{ref:i,style:{display:"contents"},children:P})}export{I as default};
1
+ "use client";import{jsx as g}from"react/jsx-runtime";import{useEffect as y,useRef as A}from"react";import{markOverlayPortal as R}from"../../format/lib/document/overlay-portal.js";import{measureStyleBase as T,styleTagsOf as x}from"./PreviewPartAnchors.js";import{usePreviewParts as S}from"efficient-easel/draw/client";import{usePartStyle as E}from"./PreviewPartStyleContext.js";import{REGION_PART_ATTR as p,encodePartId as O}from"../../render/lib/document/text-parts.js";import{TEXT_REGION_ATTR as P,textRegionOfAttr as _,textRegionPartKey as b}from"../../format/lib/sections/text-regions.js";import{regionsForSection as h}from"../../format/lib/sections/section-text-regions.js";function v({nodeId:e,sectionType:o,children:d}){const s=A(null),{selectedPartId:i}=S(),{setPartStyle:n}=E();return y(()=>{const f=s.current,c=h(o);if(!f||!e||!c)return;const m=[],l=Array.from(f.querySelectorAll(`[${P}]`));for(const t of l){const a=_(c,t.getAttribute(P));if(!a)continue;const u=R(t);u&&m.push(u);const r=O(e,b(a));t.setAttribute(p,r),r===i&&n({partId:r,...x(t),base:T(t)})}return()=>{for(const t of m)t();for(const t of l)t.removeAttribute(p)}},[e,o,i,n]),g("div",{ref:s,style:{display:"contents"},children:d})}export{v as default};
@@ -1 +1 @@
1
- "use client";import{jsx as o}from"react/jsx-runtime";import{useCallback as H,useEffect as P,useMemo as l,useRef as V,useState as u}from"react";import x from"next/dynamic";import"efficient-easel/easel.css";import"efficient-easel/shell.css";import"efficient-easel/rail.css";import"efficient-easel/panel.css";import"efficient-easel/fields.css";import"efficient-easel/pick.css";import"efficient-easel/copy.css";import"efficient-easel/gold.css";import"efficient-easel/text-styles.css";import"efficient-easel/menu.css";import"efficient-easel/chrome.css";import"efficient-easel/tree.css";import"efficient-easel/screen.css";import"./storefront-editor.css";import{buildConfig as X}from"../lib/document/build-config.js";import{withTemplateMediaPlaceholders as Z}from"../../format/lib/document/templateFields.js";import{setEditorPageSlug as B}from"../../format/lib/document/editor-page-context.js";import{ScreenDocumentContext as $}from"efficient-easel/screen/components/ScreenDocumentContext";import{PreviewHeaderProvider as ee}from"../../render/components/PreviewHeaderContext.js";import{PreviewTickerProvider as te}from"../../render/components/PreviewTickerContext.js";import{PreviewHeroPartProvider as re}from"../../render/components/PreviewHeroPartContext.js";import{PreviewPartsProvider as oe}from"efficient-easel/draw/client";import{CanvasPartsBridge as ie}from"./CanvasPartsBridge.js";import{PreviewLocationPartProvider as ne}from"../../render/components/PreviewLocationPartContext.js";import{PreviewPartStyleProvider as se}from"./PreviewPartStyleContext.js";import{sectionTemplates as b}from"efficient-easel/screen/lib/section-templates";import{nodeToDoc as de,docToNode as R}from"efficient-easel/screen/lib/document/section-doc";import{newNodeId as ae}from"efficient-easel/draw";import{migrateRenamedProps as ce}from"../../format/lib/document/renamed-props.js";import{buildSlotSeedChildren as me}from"../../render/lib/document/slot-specs.js";import{FOOTER_TYPE as le,buildDefaultFooterBlocks as ue}from"../lib/document/footer-blocks.js";import{NO_BRIDGED_CAPABILITIES as fe,useAdminBridge as pe}from"efficient-easel/screen/lib/admin-bridge";import{useEaselHost as ve}from"efficient-easel/screen/lib/host";import{ChromeWrap as ge}from"efficient-easel/screen/lib/host-chrome";import{sessionRegistry as he}from"efficient-easel/screen/lib/session";import{useEaselSession as Pe}from"efficient-easel/screen/lib/session-context";import{say as F}from"../../format/lib/editor-words.js";import{retargetWhenSaved as Se}from"../../format/lib/section-retarget.js";import{routeSharedHostMessage as Ee}from"efficient-easel/screen/lib/host-inbound";import{routeWebsiteHostMessage as ye}from"../../format/lib/website-host-inbound.js";import{DEFAULT_THEME_MODE as S,THEME_MODE_KEY as Te}from"../../format/lib/theme.js";import{makeSitePageAdapter as L}from"../lib/editor-document-adapter.js";import{documentPermissions as we}from"efficient-easel/edit-lock";import{useAutosave as Ne}from"efficient-easel/autosave";import{saveStatusOf as Ce}from"efficient-easel/screen/lib/document-switch";import{blocksOf as ke}from"../lib/website-session.js";const Ae=x(()=>import("./SiteEditorProvider.js"),{ssr:!1}),Ie=x(()=>import("efficient-easel/screen/components/SectionScreenShell"),{ssr:!1}),U="HeroSingle",W="Untitled section";function be(i,E){const d=E.components,r=d[i]?i:U,y=d[r]?.defaultProps??{},n=me(r,f=>d[f]?.defaultProps??{}),s=r===le?{blocks:ue()}:null;return{type:r,props:{id:ae(r),...y,...n?{[n.slot]:n.children}:null,...s}}}function Me(){if(typeof window>"u")return S;try{const i=window.localStorage.getItem(Te);return i==="light"||i==="dark"||i==="auto"?i:S}catch{return S}}function Oe({id:i,initialType:E,initialName:d=W}){const[r,y]=u(i),n=V(r);P(()=>{n.current=r},[r]);const s=ve(),[f,Y]=u(E),[M,j]=u(d),[a,T]=u(void 0),[K,G]=u(S),{token:w,tokenRef:O}=pe({onMessage:e=>{if(ye(e)||Ee(e))return;const t=e;if(t?.type==="storefront-editor:navigate"&&t.target?.kind==="section"&&t.target.id){const I=t.target.id;if(I===n.current)return;const J=t.target.type,Q=t.target.name;Se(C,()=>{Y(J),j(Q||W),y(I),s.address.show({kind:"section",id:I})},()=>s.send("storefront-editor:save-failed"))}}}),N=Ne({save:e=>b.update(e.id,e.node).then(()=>{}),onFailure:(e,t)=>{t===0&&s.send("storefront-editor:save-failed")}}),{state:p,push:D,flush:C}=N;P(()=>G(Me()),[]);const c=Pe(),v=c.usesBridgedToken?!!w:!0,g=l(()=>X(he(c),ke(c)),[c]);P(()=>{if(!v)return;let e=!1;return T(void 0),b.ensure(r,M,be(f??U,g)).then(t=>!e&&T(t.node)).catch(()=>!e&&T(null)),()=>{e=!0}},[r,f,M,v,g]);const k=H(e=>{s.send("storefront-editor:dirty");const t=R(e);t&&D({id:n.current,node:t})},[D,s]),h=s.send,_=H(async e=>{try{return await e(O.current??""),!0}catch{return h("storefront-editor:save-failed"),!1}},[h]),q=l(()=>Z(g,!0),[g]);P(()=>(B(null),()=>B(null)),[]);const m=l(()=>a?ce(de(a)):null,[a]),A=l(()=>({target:{kind:"page",slug:""},adapter:L(void 0),capabilities:L(void 0).capabilities,templateId:null,currentSlug:"",currentKind:null,siteId:null,ready:v,token:w,tokenRef:O,notifyParent:h,runAuthed:_,docId:r,data:m,getLiveData:()=>m,error:null,redirecting:!1,saveStatus:Ce(p),saveState:p,autoSaveEnabled:!0,autoSaveStoppedByConflict:!1,hasUnsavedEdits:p.pending,toggleAutoSave:()=>{},retrySave:()=>{N.retryNow()},onChange:k,flushSave:C,onPublish:async e=>{const t=R(e);t&&await b.update(n.current,t)},bridgeCapabilities:fe,access:{kind:"editing"},readOnly:!1,takeOverEditing:()=>{},viewReadOnly:()=>{},saveConflict:null,reloadFromServer:()=>{},navigate:()=>{},pendingNav:null,cancelPendingNav:()=>{},discardAndNavigate:()=>{},saveAndNavigate:async()=>{}}),[r,v,w,h,_,m,p,k,C,N.retryNow]),z=l(()=>we(!A.readOnly),[A.readOnly]);return a===void 0?o("div",{className:"sf-msg",children:F("Loading…")}):a===null||!m?o("div",{className:"sf-msg sf-msg--error",children:F("Couldn’t open this section.")}):o($.Provider,{value:A,children:o(ee,{themeMode:K,chromePlaceholder:!0,children:o(ge,{wrap:c.chrome?.wrap,surface:"section",children:o(te,{children:o(re,{children:o(oe,{children:o(ie,{children:o(ne,{children:o(se,{children:o(Ae,{config:q,data:m,onChange:k,permissions:z,children:o(Ie,{})},r)})})})})})})})})})}export{Oe as default};
1
+ "use client";import{jsx as o}from"react/jsx-runtime";import{useCallback as H,useEffect as P,useMemo as l,useRef as V,useState as u}from"react";import x from"next/dynamic";import"efficient-easel/easel.css";import"efficient-easel/shell.css";import"efficient-easel/rail.css";import"efficient-easel/panel.css";import"efficient-easel/fields.css";import"efficient-easel/pick.css";import"efficient-easel/copy.css";import"efficient-easel/gold.css";import"efficient-easel/text-styles.css";import"efficient-easel/menu.css";import"efficient-easel/chrome.css";import"efficient-easel/tree.css";import"efficient-easel/screen.css";import"./storefront-editor.css";import{buildConfig as X}from"../lib/document/build-config.js";import{withTemplateMediaPlaceholders as Z}from"../../format/lib/document/templateFields.js";import{setEditorPageSlug as B}from"../../format/lib/document/editor-page-context.js";import{ScreenDocumentContext as $}from"efficient-easel/screen/components/ScreenDocumentContext";import{PreviewHeaderProvider as ee}from"../../render/components/PreviewHeaderContext.js";import{PreviewTickerProvider as te}from"../../render/components/PreviewTickerContext.js";import{PreviewHeroPartProvider as re}from"../../render/components/PreviewHeroPartContext.js";import{PreviewPartsProvider as oe}from"efficient-easel/draw/client";import{CanvasPartsBridge as ie}from"./CanvasPartsBridge.js";import{PreviewLocationPartProvider as ne}from"../../render/components/PreviewLocationPartContext.js";import{PreviewPartStyleProvider as se}from"./PreviewPartStyleContext.js";import{sectionTemplates as b}from"efficient-easel/screen/lib/section-templates";import{nodeToDoc as de,docToNode as R}from"efficient-easel/screen/lib/document/section-doc";import{newNodeId as ae}from"efficient-easel/draw";import{migrateRenamedProps as ce}from"../../format/lib/document/renamed-props.js";import{buildSlotSeedChildren as me}from"../../render/lib/document/slot-specs.js";import{FOOTER_TYPE as le,buildDefaultFooterBlocks as ue}from"../lib/document/footer-blocks.js";import{NO_BRIDGED_CAPABILITIES as fe,useAdminBridge as pe}from"efficient-easel/screen/lib/admin-bridge";import{useEaselHost as ve}from"efficient-easel/screen/lib/host";import{ChromeWrap as ge}from"efficient-easel/screen/lib/host-chrome";import{sessionRegistry as he}from"efficient-easel/screen/lib/session";import{useEaselSession as Pe}from"efficient-easel/screen/lib/session-context";import{say as F}from"../../format/lib/editor-words.js";import{retargetWhenSaved as Se}from"../../format/lib/section-retarget.js";import{routeSharedHostMessage as Ee}from"efficient-easel/screen/lib/host-inbound";import{routeWebsiteHostMessage as ye}from"../../format/lib/website-host-inbound.js";import{DEFAULT_THEME_MODE as S,THEME_MODE_KEY as Te}from"../../format/lib/theme.js";import{makeSitePageAdapter as L}from"../lib/editor-document-adapter.js";import{documentPermissions as we}from"efficient-easel/edit-lock";import{useAutosave as Ne}from"efficient-easel/autosave";import{saveStatusOf as Ce}from"efficient-easel/screen/lib/document-switch";import{blocksOf as ke}from"../lib/website-session.js";const Ae=x(()=>import("./SiteEditorProvider.js"),{ssr:!1}),Ie=x(()=>import("efficient-easel/screen/components/SectionScreenShell"),{ssr:!1}),U="HeroSingle",W="Untitled section";function be(i,E){const d=E.components,r=d[i]?i:U,y=d[r]?.defaultProps??{},n=me(r,f=>d[f]?.defaultProps??{}),s=r===le?{blocks:ue()}:null;return{type:r,props:{id:ae(r),...y,...n?{[n.slot]:n.children}:null,...s}}}function Me(){if(typeof window>"u")return S;try{const i=window.localStorage.getItem(Te);return i==="light"||i==="dark"||i==="auto"?i:S}catch{return S}}function Oe({id:i,initialType:E,initialName:d=W}){const[r,y]=u(i),n=V(r);P(()=>{n.current=r},[r]);const s=ve(),[f,Y]=u(E),[M,j]=u(d),[a,T]=u(void 0),[K,G]=u(S),{token:w,tokenRef:O}=pe({onMessage:e=>{if(ye(e)||Ee(e))return;const t=e;if(t?.type==="storefront-editor:navigate"&&t.target?.kind==="section"&&t.target.id){const I=t.target.id;if(I===n.current)return;const J=t.target.type,Q=t.target.name;Se(C,()=>{Y(J),j(Q||W),y(I),s.address.show({kind:"section",id:I})},()=>s.send("storefront-editor:save-failed"))}}}),N=Ne({save:e=>b.update(e.id,e.node).then(()=>{}),onFailure:(e,t)=>{t===0&&s.send("storefront-editor:save-failed")}}),{state:p,push:D,flush:C}=N;P(()=>G(Me()),[]);const c=Pe(),v=c.usesBridgedToken?!!w:!0,g=l(()=>X(he(c),ke(c)),[c]);P(()=>{if(!v)return;let e=!1;return T(void 0),b.ensure(r,M,be(f??U,g)).then(t=>!e&&T(t.node)).catch(()=>!e&&T(null)),()=>{e=!0}},[r,f,M,v,g]);const k=H(e=>{s.send("storefront-editor:dirty");const t=R(e);t&&D({id:n.current,node:t})},[D,s]),h=s.send,_=H(async e=>{try{return await e(O.current??""),!0}catch{return h("storefront-editor:save-failed"),!1}},[h]),q=l(()=>Z(g,!0),[g]);P(()=>(B(null),()=>B(null)),[]);const m=l(()=>a?ce(de(a)):null,[a]),A=l(()=>({target:{kind:"page",slug:""},adapter:L(void 0),capabilities:L(void 0).capabilities,templateId:null,currentSlug:"",currentKind:null,siteId:null,ready:v,token:w,tokenRef:O,notifyParent:h,runAuthed:_,docId:r,data:m,getLiveData:()=>m,error:null,redirecting:!1,saveStatus:Ce(p),saveState:p,autoSaveEnabled:!0,autoSaveStoppedByConflict:!1,hasUnsavedEdits:p.pending,toggleAutoSave:()=>{},retrySave:()=>{N.retryNow()},onChange:k,flushSave:C,onPublish:async e=>{const t=R(e);t&&await b.update(n.current,t)},bridgeCapabilities:fe,access:{kind:"editing"},readOnly:!1,takeOverEditing:()=>{},viewReadOnly:()=>{},saveConflict:null,reloadFromServer:()=>{},navigate:()=>{},pendingNav:null,cancelPendingNav:()=>{},discardAndNavigate:()=>{},saveAndNavigate:async()=>{}}),[r,v,w,h,_,m,p,k,C,N.retryNow]),z=l(()=>we(!A.readOnly),[A.readOnly]);return a===void 0?o("div",{className:"sf-msg",children:F("Loading…")}):a===null||!m?o("div",{className:"sf-msg sf-msg--error",children:F("Couldn’t open this section.")}):o($.Provider,{value:A,children:o(ee,{themeMode:K,chromePlaceholder:!0,children:o(ge,{wrap:c.chrome?.wrap,surface:"section",children:o(te,{children:o(re,{children:o(oe,{children:o(ne,{children:o(ie,{children:o(se,{children:o(Ae,{config:q,data:m,onChange:k,permissions:z,children:o(Ie,{})},r)})})})})})})})})})}export{Oe as default};
@@ -1 +1 @@
1
- "use client";import{jsx as c,jsxs as it}from"react/jsx-runtime";import{useCallback as n,useEffect as S,useMemo as oe,useRef as f,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 ct}from"../lib/document/build-config.js";import{ChromeWrap as st}from"efficient-easel/screen/lib/host-chrome";import{sessionRegistry as dt}from"efficient-easel/screen/lib/session";import{refreshSiteLiveState as ut}from"../lib/site-live-state.js";import{holdSiteWrites as ht}from"../../format/lib/site-writes.js";import{backendOf as W,blocksOf as lt}from"../lib/website-session.js";import{useEaselSession as mt}from"efficient-easel/screen/lib/session-context";import{withSiteBlockGapFields as pt}from"../../format/lib/document/site-gap-fields.js";import{withTemplateMediaPlaceholders as St}from"../../format/lib/document/templateFields.js";import{setEditorPage as ne}from"../../format/lib/document/editor-page-context.js";import{resolveSiteName as ft}from"../../format/lib/content/site-name.js";import{normalizeSiteGutter as gt,normalizeSiteWidth as wt}from"../../format/lib/content/page-width.js";import{normalizeSiteBackground as ae}from"../../format/lib/content/section-width.js";import{normalizeSiteBlockGap as Ct}from"../../format/lib/content/container-gap.js";import _t,{DocumentScreen as Tt}from"efficient-easel/screen/components/ScreenMount";import{useScreenDocument as Et}from"efficient-easel/screen/components/ScreenDocumentContext";import{PreviewHeaderProvider as yt}from"../../render/components/PreviewHeaderContext.js";import{PreviewFooterProvider as Pt}from"./PreviewFooterContext.js";import{PreviewChatProvider as vt,DEFAULT_CHAT_PREVIEW as Wt}from"./PreviewChatContext.js";import{PreviewSocialProvider as Ht}from"../../render/components/PreviewSocialContext.js";import{useSocialSettings as kt}from"./useSocialSettings.js";import{PreviewSurfaceProvider as Gt}from"./PreviewSurfaceContext.js";import{WEBSITE_ADDRESSING as Bt}from"../lib/website-document-addressing.js";import{PreviewTickerProvider as Rt}from"../../render/components/PreviewTickerContext.js";import{PreviewHeroPartProvider as It}from"../../render/components/PreviewHeroPartContext.js";import{PreviewPartsProvider as Ft}from"efficient-easel/draw/client";import{CanvasPartsBridge as Dt}from"./CanvasPartsBridge.js";import{PreviewLocationPartProvider as Mt}from"../../render/components/PreviewLocationPartContext.js";import{PreviewPartStyleProvider as xt}from"./PreviewPartStyleContext.js";import{CORNER_STYLE_TO_PX as Nt,DEFAULT_HEADING_COMPRESSION as Ot,DEFAULT_HEADING_TYPOGRAPHY as bt,DEFAULT_SWITCH_SHOWN as H,DEFAULT_SIZES as At,DEFAULT_THEME_MODE as _,normalizeCornerRadius as zt,normalizeCornerStyle as Lt,normalizeCardShadow as Yt,normalizeCardGap as Ut,normalizeHoverEffect as jt,normalizeShadowColor as Kt,IDENTITY_CARD_GAP as ie,IDENTITY_CARD_SHADOW as Vt,IDENTITY_HOVER_EFFECT as Xt,THEME_MODE_KEY as ce,THEME_STORAGE_KEY as Zt,THEME_SWITCH_HIDE as se,THEME_SWITCH_KEY as k}from"../../format/lib/theme.js";import{DEFAULT_FONTS as qt}from"../../format/lib/fonts.js";import{WEBSITE_SCREEN as Jt}from"./WebsiteScreenParts.js";import{routeWebsiteHostMessage as Qt}from"../../format/lib/website-host-inbound.js";import{siteTextFromRow as $t}from"../../render/lib/text-styles/site-text-styles.js";import{wordStylesFromRow as er}from"../../format/lib/word-styles.js";import{chatPreviewFrom as tr}from"./PreviewChatContext.js";const rr=()=>{if(typeof window>"u")return _;try{const i=window.localStorage.getItem(ce);return i==="light"||i==="dark"||i==="auto"?i:_}catch{return _}},de=i=>{if(!(typeof window>"u"))try{window.localStorage.setItem(ce,i)}catch{}},or=()=>{if(typeof window>"u")return H;try{return window.localStorage.getItem(k)!==se}catch{return H}},nr=()=>{if(!(typeof window>"u"))try{window.localStorage.removeItem(Zt)}catch{}},ue=i=>{if(!(typeof window>"u"))try{i?window.localStorage.removeItem(k):window.localStorage.setItem(k,se)}catch{}};function ar(){const{adapter:i,capabilities:d,templateId:G,ready:w,token:h,siteId:s,currentSlug:B,currentKind:R}=Et();S(()=>(ne(B,R),()=>ne(null,null)),[B,R]);const T=d.placeholderFrames,[he,I]=r(null),[le,F]=r("");S(()=>{const e=i.templateName;if(!w||!G||!e){F("");return}let a=!1;return e().then(l=>!a&&F(l??"")).catch(()=>{}),()=>{a=!0}},[w,h,G,i]);const[me,E]=r(_),[pe,y]=r(H),[Se,D]=r({selected:0,themes:[]}),[fe,M]=r(qt),[ge,x]=r(At),[we,N]=r(null),[Ce,O]=r(Ot),[_e,b]=r(null),[Te,A]=r(null),[Ee,z]=r(ie),[ye,L]=r(null),[Pe,Y]=r(null),[ve,U]=r(null),[P,j]=r(null),u=mt(),K=oe(()=>ct(dt(u),lt(u)),[u]),We=oe(()=>pt(St(K,T),P),[K,T,P]),[He,V]=r(bt),[ke,X]=r(null),[Ge,Z]=r(null),[Be,q]=r(null),[Re,J]=r(null),[Ie,Q]=r(null),$=f(null),o=f(!1);S(()=>{E(rr()),y(or())},[]);const Fe=n(e=>{o.current=!0,nr(),de(e),E(e)},[]),De=n(e=>{o.current=!0,ue(e),y(e)},[]),Me=n(e=>{o.current=!0,D(e)},[]),xe=n(e=>{o.current=!0,M(e)},[]),Ne=n(e=>{o.current=!0,x(e)},[]),Oe=n(e=>{o.current=!0,N(e)},[]),be=n(e=>{o.current=!0,O(e)},[]),Ae=n(e=>{o.current=!0,b(e)},[]),ze=n(e=>{o.current=!0,A(e)},[]),Le=n(e=>{o.current=!0,z(e)},[]),Ye=n(e=>{o.current=!0,L(e)},[]),Ue=n(e=>{o.current=!0,V(e)},[]),[je,ee]=r(null),[Ke,Ve]=r(null),Xe=n(e=>{o.current=!0,ee(e)},[]),Ze=n(e=>{o.current=!0,Y(e)},[]),qe=n(e=>{o.current=!0,U(e)},[]),Je=n(e=>{o.current=!0,j(e)},[]),Qe=n(e=>{o.current=!0,X(e)},[]),$e=n(e=>{o.current=!0,Z(e)},[]),et=n(e=>{o.current=!0,q(e)},[]),tt=n(e=>{o.current=!0,J(e)},[]),rt=n(e=>{o.current=!0,Q(e)},[]);S(()=>{const e=W(u).theme;if(!h||!d.hasSiteTheme||!e)return;const a=s??"";$.current!==a&&($.current=a,o.current=!1);let l=!1;return e.get(s?{siteId:s}:void 0).then(t=>{if(l||o.current)return;de(t.default_mode),ue(t.show_theme_switch),E(t.default_mode),y(t.show_theme_switch),D({selected:t.selected_preset,themes:t.theme_presets});const g=$t(t);M(g.fonts),x(g.sizes),N(t.corner_radius_px===void 0?Nt[Lt(t.corner_style)]:zt(t.corner_radius_px)),O(g.compression),b(t.card_shadow==null?Vt:Yt(t.card_shadow)),z(t.card_gap==null?ie:Ut(t.card_gap)),L(t.hover_effect==null?Xt:jt(t.hover_effect)),A(Kt(t.shadow_color)),Y(wt(t.site_width)),U(gt(t.site_gutter)),j(Ct(t.block_gap)),V(g.typography),ee(g.textStyles),Ve(er(t)),X(t.hero_background_follows_width===!0),Z(ae(t.section_background_width)),q(ae(t.section_content_width)),J(t.photography_grayscale===!0),Q(t.share_button_on_posts===!0)}).catch(()=>{}),()=>{l=!0}},[h,s,d.hasSiteTheme,u]);const ot=kt({token:h,siteId:s,enabled:d.hasSiteSettings}),[nt,te]=r(Wt),re=f(null),v=f(!1),m=f(null),p=f({}),C=n(async()=>{m.current&&clearTimeout(m.current),m.current=null;const e=p.current;p.current={};try{await W(u).chat?.update(e,s?{siteId:s}:void 0),ut()}catch(a){throw p.current={...e,...p.current},a}},[u,s]);S(()=>ht(()=>m.current||Object.keys(p.current).length>0?C():void 0),[C]);const at=n(e=>{v.current=!0,te(a=>({...a,...e})),!(!d.hasSiteSettings||!h)&&(p.current={...p.current,...e},m.current&&clearTimeout(m.current),m.current=setTimeout(()=>{C().catch(()=>{})},500))},[d.hasSiteSettings,h,C]);return S(()=>{if(!h||!d.hasSiteSettings)return;const e=s??"";re.current!==e&&(re.current=e,v.current=!1);let a=!1;const l=W(u).chat;if(l)return l.get(s?{siteId:s}:void 0).then(t=>{a||v.current||te(tr(t))}).catch(()=>{}),()=>{a=!0}},[h,s,d.hasSiteSettings,u]),S(()=>{const e=i.site;if(!w||!d.hasSiteRecord||!e){I(null);return}let a=!1;return e().then(l=>{a||I(ft(l.name))}).catch(()=>{}),()=>{a=!0}},[w,h,d.hasSiteRecord,s,i]),c(Tt,{config:We,parts:Jt,wrap:(e,a)=>c(yt,{websiteName:he,templateChrome:T,templateName:le||null,themeMode:me,onThemeModeChange:Fe,themeSwitchShown:pe,onThemeSwitchShownChange:De,theme:Se,onThemeChange:Me,fonts:fe,onFontsChange:xe,cornerRadiusPx:we,onCornerRadiusPxChange:Oe,cardShadow:_e,onCardShadowChange:Ae,shadowColor:Te,onShadowColorChange:ze,cardGap:Ee,onCardGapChange:Le,hoverEffect:ye,onHoverEffectChange:Ye,headingCompression:Ce,onHeadingCompressionChange:be,headingTypography:He,onHeadingTypographyChange:Ue,textStyles:je,onTextStylesChange:Xe,wordStyles:Ke,sizes:ge,onSizesChange:Ne,siteWidth:Pe,onSiteWidthChange:Ze,siteGutter:ve,onSiteGutterChange:qe,blockGap:P,onBlockGapChange:Je,heroBackgroundFollowsWidth:ke,onHeroBackgroundFollowsWidthChange:Qe,sectionBackgroundWidth:Ge,onSectionBackgroundWidthChange:$e,sectionContentWidth:Be,onSectionContentWidthChange:et,photographyGrayscale:Re,onPhotographyGrayscaleChange:tt,shareButtonOnPosts:Ie,onShareButtonOnPostsChange:rt,themeFromDocument:!d.hasSiteTheme,children:c(Pt,{children:c(st,{wrap:u.chrome?.wrap,surface:"page",children:c(Rt,{children:c(It,{children:c(Ft,{children:c(Dt,{children:c(Mt,{children:it(xt,{children:[c(vt,{chat:nt,onChatChange:at,children:c(Ht,{value:ot,children:c(Gt,{children:e})})}),a]})})})})})})})})})})}function ir({target:i}){return c(_t,{target:i,addressing:Bt,onHostMessage:Qt,children:c(ar,{})})}export{ir as default};
1
+ "use client";import{jsx as c,jsxs as it}from"react/jsx-runtime";import{useCallback as n,useEffect as S,useMemo as oe,useRef as f,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 ct}from"../lib/document/build-config.js";import{ChromeWrap as st}from"efficient-easel/screen/lib/host-chrome";import{sessionRegistry as dt}from"efficient-easel/screen/lib/session";import{refreshSiteLiveState as ut}from"../lib/site-live-state.js";import{holdSiteWrites as ht}from"../../format/lib/site-writes.js";import{backendOf as W,blocksOf as lt}from"../lib/website-session.js";import{useEaselSession as mt}from"efficient-easel/screen/lib/session-context";import{withSiteBlockGapFields as pt}from"../../format/lib/document/site-gap-fields.js";import{withTemplateMediaPlaceholders as St}from"../../format/lib/document/templateFields.js";import{setEditorPage as ne}from"../../format/lib/document/editor-page-context.js";import{resolveSiteName as ft}from"../../format/lib/content/site-name.js";import{normalizeSiteGutter as gt,normalizeSiteWidth as wt}from"../../format/lib/content/page-width.js";import{normalizeSiteBackground as ae}from"../../format/lib/content/section-width.js";import{normalizeSiteBlockGap as Ct}from"../../format/lib/content/container-gap.js";import _t,{DocumentScreen as Tt}from"efficient-easel/screen/components/ScreenMount";import{useScreenDocument as Et}from"efficient-easel/screen/components/ScreenDocumentContext";import{PreviewHeaderProvider as yt}from"../../render/components/PreviewHeaderContext.js";import{PreviewFooterProvider as Pt}from"./PreviewFooterContext.js";import{PreviewChatProvider as vt,DEFAULT_CHAT_PREVIEW as Wt}from"./PreviewChatContext.js";import{PreviewSocialProvider as Ht}from"../../render/components/PreviewSocialContext.js";import{useSocialSettings as kt}from"./useSocialSettings.js";import{PreviewSurfaceProvider as Gt}from"./PreviewSurfaceContext.js";import{WEBSITE_ADDRESSING as Bt}from"../lib/website-document-addressing.js";import{PreviewTickerProvider as Rt}from"../../render/components/PreviewTickerContext.js";import{PreviewHeroPartProvider as It}from"../../render/components/PreviewHeroPartContext.js";import{PreviewPartsProvider as Ft}from"efficient-easel/draw/client";import{CanvasPartsBridge as Dt}from"./CanvasPartsBridge.js";import{PreviewLocationPartProvider as Mt}from"../../render/components/PreviewLocationPartContext.js";import{PreviewPartStyleProvider as xt}from"./PreviewPartStyleContext.js";import{CORNER_STYLE_TO_PX as Nt,DEFAULT_HEADING_COMPRESSION as Ot,DEFAULT_HEADING_TYPOGRAPHY as bt,DEFAULT_SWITCH_SHOWN as H,DEFAULT_SIZES as At,DEFAULT_THEME_MODE as _,normalizeCornerRadius as zt,normalizeCornerStyle as Lt,normalizeCardShadow as Yt,normalizeCardGap as Ut,normalizeHoverEffect as jt,normalizeShadowColor as Kt,IDENTITY_CARD_GAP as ie,IDENTITY_CARD_SHADOW as Vt,IDENTITY_HOVER_EFFECT as Xt,THEME_MODE_KEY as ce,THEME_STORAGE_KEY as Zt,THEME_SWITCH_HIDE as se,THEME_SWITCH_KEY as k}from"../../format/lib/theme.js";import{DEFAULT_FONTS as qt}from"../../format/lib/fonts.js";import{WEBSITE_SCREEN as Jt}from"./WebsiteScreenParts.js";import{routeWebsiteHostMessage as Qt}from"../../format/lib/website-host-inbound.js";import{siteTextFromRow as $t}from"../../render/lib/text-styles/site-text-styles.js";import{wordStylesFromRow as er}from"../../format/lib/word-styles.js";import{chatPreviewFrom as tr}from"./PreviewChatContext.js";const rr=()=>{if(typeof window>"u")return _;try{const i=window.localStorage.getItem(ce);return i==="light"||i==="dark"||i==="auto"?i:_}catch{return _}},de=i=>{if(!(typeof window>"u"))try{window.localStorage.setItem(ce,i)}catch{}},or=()=>{if(typeof window>"u")return H;try{return window.localStorage.getItem(k)!==se}catch{return H}},nr=()=>{if(!(typeof window>"u"))try{window.localStorage.removeItem(Zt)}catch{}},ue=i=>{if(!(typeof window>"u"))try{i?window.localStorage.removeItem(k):window.localStorage.setItem(k,se)}catch{}};function ar(){const{adapter:i,capabilities:d,templateId:G,ready:w,token:h,siteId:s,currentSlug:B,currentKind:R}=Et();S(()=>(ne(B,R),()=>ne(null,null)),[B,R]);const T=d.placeholderFrames,[he,I]=r(null),[le,F]=r("");S(()=>{const e=i.templateName;if(!w||!G||!e){F("");return}let a=!1;return e().then(l=>!a&&F(l??"")).catch(()=>{}),()=>{a=!0}},[w,h,G,i]);const[me,E]=r(_),[pe,y]=r(H),[Se,D]=r({selected:0,themes:[]}),[fe,M]=r(qt),[ge,x]=r(At),[we,N]=r(null),[Ce,O]=r(Ot),[_e,b]=r(null),[Te,A]=r(null),[Ee,z]=r(ie),[ye,L]=r(null),[Pe,Y]=r(null),[ve,U]=r(null),[P,j]=r(null),u=mt(),K=oe(()=>ct(dt(u),lt(u)),[u]),We=oe(()=>pt(St(K,T),P),[K,T,P]),[He,V]=r(bt),[ke,X]=r(null),[Ge,Z]=r(null),[Be,q]=r(null),[Re,J]=r(null),[Ie,Q]=r(null),$=f(null),o=f(!1);S(()=>{E(rr()),y(or())},[]);const Fe=n(e=>{o.current=!0,nr(),de(e),E(e)},[]),De=n(e=>{o.current=!0,ue(e),y(e)},[]),Me=n(e=>{o.current=!0,D(e)},[]),xe=n(e=>{o.current=!0,M(e)},[]),Ne=n(e=>{o.current=!0,x(e)},[]),Oe=n(e=>{o.current=!0,N(e)},[]),be=n(e=>{o.current=!0,O(e)},[]),Ae=n(e=>{o.current=!0,b(e)},[]),ze=n(e=>{o.current=!0,A(e)},[]),Le=n(e=>{o.current=!0,z(e)},[]),Ye=n(e=>{o.current=!0,L(e)},[]),Ue=n(e=>{o.current=!0,V(e)},[]),[je,ee]=r(null),[Ke,Ve]=r(null),Xe=n(e=>{o.current=!0,ee(e)},[]),Ze=n(e=>{o.current=!0,Y(e)},[]),qe=n(e=>{o.current=!0,U(e)},[]),Je=n(e=>{o.current=!0,j(e)},[]),Qe=n(e=>{o.current=!0,X(e)},[]),$e=n(e=>{o.current=!0,Z(e)},[]),et=n(e=>{o.current=!0,q(e)},[]),tt=n(e=>{o.current=!0,J(e)},[]),rt=n(e=>{o.current=!0,Q(e)},[]);S(()=>{const e=W(u).theme;if(!h||!d.hasSiteTheme||!e)return;const a=s??"";$.current!==a&&($.current=a,o.current=!1);let l=!1;return e.get(s?{siteId:s}:void 0).then(t=>{if(l||o.current)return;de(t.default_mode),ue(t.show_theme_switch),E(t.default_mode),y(t.show_theme_switch),D({selected:t.selected_preset,themes:t.theme_presets});const g=$t(t);M(g.fonts),x(g.sizes),N(t.corner_radius_px===void 0?Nt[Lt(t.corner_style)]:zt(t.corner_radius_px)),O(g.compression),b(t.card_shadow==null?Vt:Yt(t.card_shadow)),z(t.card_gap==null?ie:Ut(t.card_gap)),L(t.hover_effect==null?Xt:jt(t.hover_effect)),A(Kt(t.shadow_color)),Y(wt(t.site_width)),U(gt(t.site_gutter)),j(Ct(t.block_gap)),V(g.typography),ee(g.textStyles),Ve(er(t)),X(t.hero_background_follows_width===!0),Z(ae(t.section_background_width)),q(ae(t.section_content_width)),J(t.photography_grayscale===!0),Q(t.share_button_on_posts===!0)}).catch(()=>{}),()=>{l=!0}},[h,s,d.hasSiteTheme,u]);const ot=kt({token:h,siteId:s,enabled:d.hasSiteSettings}),[nt,te]=r(Wt),re=f(null),v=f(!1),m=f(null),p=f({}),C=n(async()=>{m.current&&clearTimeout(m.current),m.current=null;const e=p.current;p.current={};try{await W(u).chat?.update(e,s?{siteId:s}:void 0),ut()}catch(a){throw p.current={...e,...p.current},a}},[u,s]);S(()=>ht(()=>m.current||Object.keys(p.current).length>0?C():void 0),[C]);const at=n(e=>{v.current=!0,te(a=>({...a,...e})),!(!d.hasSiteSettings||!h)&&(p.current={...p.current,...e},m.current&&clearTimeout(m.current),m.current=setTimeout(()=>{C().catch(()=>{})},500))},[d.hasSiteSettings,h,C]);return S(()=>{if(!h||!d.hasSiteSettings)return;const e=s??"";re.current!==e&&(re.current=e,v.current=!1);let a=!1;const l=W(u).chat;if(l)return l.get(s?{siteId:s}:void 0).then(t=>{a||v.current||te(tr(t))}).catch(()=>{}),()=>{a=!0}},[h,s,d.hasSiteSettings,u]),S(()=>{const e=i.site;if(!w||!d.hasSiteRecord||!e){I(null);return}let a=!1;return e().then(l=>{a||I(ft(l.name))}).catch(()=>{}),()=>{a=!0}},[w,h,d.hasSiteRecord,s,i]),c(Tt,{config:We,parts:Jt,wrap:(e,a)=>c(yt,{websiteName:he,templateChrome:T,templateName:le||null,themeMode:me,onThemeModeChange:Fe,themeSwitchShown:pe,onThemeSwitchShownChange:De,theme:Se,onThemeChange:Me,fonts:fe,onFontsChange:xe,cornerRadiusPx:we,onCornerRadiusPxChange:Oe,cardShadow:_e,onCardShadowChange:Ae,shadowColor:Te,onShadowColorChange:ze,cardGap:Ee,onCardGapChange:Le,hoverEffect:ye,onHoverEffectChange:Ye,headingCompression:Ce,onHeadingCompressionChange:be,headingTypography:He,onHeadingTypographyChange:Ue,textStyles:je,onTextStylesChange:Xe,wordStyles:Ke,sizes:ge,onSizesChange:Ne,siteWidth:Pe,onSiteWidthChange:Ze,siteGutter:ve,onSiteGutterChange:qe,blockGap:P,onBlockGapChange:Je,heroBackgroundFollowsWidth:ke,onHeroBackgroundFollowsWidthChange:Qe,sectionBackgroundWidth:Ge,onSectionBackgroundWidthChange:$e,sectionContentWidth:Be,onSectionContentWidthChange:et,photographyGrayscale:Re,onPhotographyGrayscaleChange:tt,shareButtonOnPosts:Ie,onShareButtonOnPostsChange:rt,themeFromDocument:!d.hasSiteTheme,children:c(Pt,{children:c(st,{wrap:u.chrome?.wrap,surface:"page",children:c(Rt,{children:c(It,{children:c(Ft,{children:c(Mt,{children:c(Dt,{children:it(xt,{children:[c(vt,{chat:nt,onChatChange:at,children:c(Ht,{value:ot,children:c(Gt,{children:e})})}),a]})})})})})})})})})})}function ir({target:i}){return c(_t,{target:i,addressing:Bt,onHostMessage:Qt,children:c(ar,{})})}export{ir as default};
@@ -659,7 +659,7 @@
659
659
 
660
660
  the zone whose owner you CLICKED --isAreaSelected_
661
661
  the deepest zone you are INSIDE --hoveringOverArea_:not(--isRootZone_)
662
- the block you are POINTING AT [data-easel-overlay-portal]:hover
662
+ the block you are POINTING AT [data-easel-overlay-portal]:hover (C, retired 2026-10-26)
663
663
 
664
664
  MEASURED, not inferred, by scripts/probe-hover-outline-count.mjs (retired
665
665
  with the old editor library in blueprint 6.3) against both stylesheets in the app's own import
@@ -732,86 +732,25 @@
732
732
  outline: 1px solid var(--es-accent-line, #bfdbfe);
733
733
  }
734
734
 
735
- /* C · the block you are pointing at: one line, solid, 1px, 2px off the words.
736
- the old editor library's own overlay-portal sheet drew it 2px dashed and this file narrowed it;
737
- since that sheet left with 5.5 the whole line is declared here.
738
- ITS COLOUR IS THE ENGINE'S HOVER COLOUR (2026-10-16): the accent at 60%, as
739
- `.es-canvas-outline.is-hover` draws it in efficient-easel easel.css, so a
740
- pointed-at word and a pointed-at block look the same. It was the old editor library's azure-09
741
- (#dbeafe), a tint of white: next to the engine's box it read as a second,
742
- lighter box, and once E below took that box away it was all but invisible
743
- on a light page. */
744
- [data-easel-overlay-portal]:hover {
745
- outline: 1px solid color-mix(in srgb, var(--es-accent, #2563eb) 60%, transparent);
746
- outline-offset: 2px;
747
- }
748
-
749
- /* …and the rest of what the old editor library's overlay-portal sheet (lib/overlay-portal/
750
- styles.css) gave a text-part anchor, carried here for the same reason: the
751
- anchor takes the pointer, and draws a ring while the caret is in it. The
752
- OPEN part's own hairline (PART_PICK_CSS, (0,3,0)) still outranks the ring
753
- (0,2,0) — one line, card 11103. */
735
+ /* C, D, E · RETIRED 2026-10-26: no line on the words, ever, and the engine's
736
+ box is never hidden. Lewis, on one Text block: "look how many boxes the text
737
+ has now; is this reasonable?" These rules drew a line on the part anchor itself (C), kept
738
+ only the innermost of those (D), and hid the engine's hover box while one
739
+ was hovered (E). An anchor is often an INLINE run, and an outline on an
740
+ inline run follows each line, so two lines of different length drew an
741
+ irregular shape; with E the engine's box was gone and its "⋮⋮ Text" handle
742
+ was left floating away from any line. The engine draws every box now, a
743
+ regular rectangle: the block, or the part the next click picks
744
+ (efficient-easel `PartHover`), or the open part (`selectedPart`, handed
745
+ by components/CanvasPartsBridge). `scripts/test-part-outline-hairline.tsx`
746
+ resolves the sheets and fails if a page element draws a line again.
747
+
748
+ The anchor still takes the pointer (the old editor library's overlay-portal sheet gave it
749
+ that, and the click on a part depends on it). */
754
750
  [data-easel-overlay-portal],
755
751
  [data-easel-overlay-portal] * {
756
752
  pointer-events: auto !important;
757
753
  }
758
- [data-easel-overlay-portal]:focus-within {
759
- outline: 2px solid var(--es-accent-line, #bfdbfe);
760
- outline-offset: 2px;
761
- }
762
-
763
- /* D · …and ONLY the innermost one.
764
- ⚠️ FOUND IN THE REAL EDITOR, NOT ON THE BOARD, AND IT IS THE HALF THE BOARD
765
- COULD NOT SEE. The old editor library nests an overlay per component, and `:hover` matches
766
- every ancestor in that chain — so pointing at the heading of a section put
767
- FOUR overlays in `:hover` at once. Measured at /edit/preview-footer with a
768
- real pointer: 4 hovered overlays, 4 painted lines. Rules A-C removed every
769
- dashed line and still left him four thin ones.
770
-
771
- The board modelled ONE overlay because that is what a nesting sketch needs;
772
- the editor stacks them because that is what a component tree does. Same
773
- family as measuring a component outside the container it ships in — the
774
- experiment was honest and the population was wrong.
775
-
776
- `:has()` reads "an overlay that contains another hovered overlay stands
777
- aside", which leaves exactly the deepest one — the thing under the cursor,
778
- which is the one you are actually reaching for. Re-measured with this rule
779
- live in the same editor: 4 hovered, 1 painted, 225x46, the heading itself.
780
-
781
- ⚠️ SETTLED BY THE OWNER, 2026-09-02: keep the innermost. He was shown the
782
- alternative and the reason the choice is not obvious — on a heading the
783
- innermost box hugs the text, which is right, but on the Subscribe button the
784
- innermost is the button's LABEL (63x16) rather than the button (97x38). He
785
- picked innermost anyway. DO NOT re-open this as "the button's box looks
786
- small": that is the known cost of the rule he chose.
787
-
788
- ⚠️ AND THIS ONLY HIDES THE LINE. The duplicate overlays are still in the DOM.
789
- Measured on /edit/preview-footer: TWELVE overlays carrying only FOUR distinct
790
- `data-sf-part` ids, and all EIGHT nested pairs share their ancestor's id — so
791
- the extra boxes were never separate things to select and never had settings
792
- of their own. Marking one element per part is a separate card touching
793
- several components; it is not this one. */
794
- [data-easel-overlay-portal]:hover:has([data-easel-overlay-portal]:hover) {
795
- outline: none;
796
- }
797
-
798
- /* E · …and the engine's hover box stands aside for it.
799
- Lewis, 2026-10-16, on the Hartes homepage hero: pointing at the "Ranger II"
800
- heading drew TWO lines again, the words' own (C) and a wider box round the
801
- Heading block. That box is the engine's (`.es-canvas-outline.is-hover`,
802
- efficient-easel easel.css), drawn on its outline layer over the block the
803
- next click would pick. It came with the engine in blueprint 5.5, after A-D
804
- were written, so nothing here answered it. But a click on a marked element
805
- never reaches the engine (PreviewPartAnchors and the hero / ticker / location
806
- bridges stop it and open their own thing), so over one the engine's box
807
- names the wrong target, and the innermost line D keeps is the true one.
808
- Off a marked element the engine's box is the only line, and stays. Led by
809
- `[data-easel-entry]`, the frame's root, as A is; (0,5,0) against the
810
- engine's (0,2,0). `scripts/test-part-outline-hairline.tsx` §3
811
- resolves both sheets. */
812
- [data-easel-entry]:has([data-easel-overlay-portal]:hover) .es-canvas-outline.is-hover {
813
- outline: none;
814
- }
815
754
 
816
755
  /* @tokens canvas-end */
817
756
 
@@ -1,8 +1,12 @@
1
1
  import { type RefObject } from "react";
2
2
  import { type SelectionSource } from "efficient-easel/copy";
3
- import { type MarkStyle } from "../../../format/lib/markup.js";
3
+ import { type MarkStyle, type WrapResult } from "../../../format/lib/markup.js";
4
4
  export type Selectable = SelectionSource;
5
- export declare function markSelection(value: string, style: MarkStyle, el: Selectable): import("efficient-shell/markup").WrapResult;
5
+ export declare function markSelection(value: string, style: MarkStyle, el: Selectable): WrapResult;
6
+ export declare function clearFormatting(value: string, sel: {
7
+ start: number;
8
+ end: number;
9
+ } | null): WrapResult | null;
6
10
  export declare function MarkupToolbar({ target, value, onChange, disabled, label, }: {
7
11
  target: RefObject<HTMLInputElement | HTMLTextAreaElement | null>;
8
12
  value: string;
@@ -1 +1 @@
1
- import{jsx as l}from"react/jsx-runtime";import{useEffect as E,useState as T}from"react";import{markSelection as x,useCaretEdit as y}from"efficient-easel/copy";import{RevertIcon as M}from"efficient-easel/icons";import{IconButton as b,TextToolbar as v,Tooltip as L}from"efficient-shell/ui";import{say as u}from"../../../format/lib/editor-words.js";import{applyShopMark as C,shopMarkedAt as D,shopMarkupTools as I,stripMarkup as g}from"../../../format/lib/markup.js";const S="Clear formatting";function j(t,n,o){return x(t,n,o,C)}function z(t){const[n,o]=T(null);return E(()=>{const r=t.current?.ownerDocument??(typeof document>"u"?null:document);if(!r)return;const i=()=>{const s=t.current;if(!s||r.activeElement!==s)return;const c=s.selectionStart??s.value.length,m=s.selectionEnd??c;o(a=>a&&a.start===c&&a.end===m?a:{start:c,end:m})};return r.addEventListener("selectionchange",i),()=>r.removeEventListener("selectionchange",i)},[t]),[n,o]}function A({target:t,value:n,onChange:o,disabled:r=!1,label:i="Formatting"}){const s=y({target:t,onChange:o}),[c,m]=z(t),a=e=>s(h=>{const p=j(n,e,h);return m({start:p.selectionStart,end:p.selectionEnd}),p}),d=I(),f={};if(c)for(const e of d)f[e.style]=D(n,c.start,c.end,e.style);const k=g(n);return l(v,{offered:new Set(d.map(e=>e.style)),onMark:e=>a(e),pressed:f,disabled:r,"aria-label":u(i),className:"sf-markup-bar",last:l("span",{className:"sf-markup-clear",children:l(L,{content:u(S),children:l(b,{size:"sm",onMouseDown:e=>e.preventDefault(),onClick:()=>o(k),disabled:r||k===n,"aria-label":u(S),children:l(M,{size:14})})})})})}var w=A;export{A as MarkupToolbar,w as default,j as markSelection};
1
+ import{jsx as x}from"react/jsx-runtime";import{useEffect as E,useState as h}from"react";import{clearRangeOf as k,markSelection as y,useCaretEdit as g}from"efficient-easel/copy";import{TextToolbar as M}from"efficient-shell/ui";import{say as T}from"../../../format/lib/editor-words.js";import{applyShopMark as b,clearShopStyle as j,shopMarkedAt as C,shopMarkupTools as D}from"../../../format/lib/markup.js";function F(e,n,r){return y(e,n,r,b)}function p(e,n){const r=k(n,e.length),o=j(e,r.start,r.end);return o.text===e?null:o}function L(e){const[n,r]=h(null);return E(()=>{const o=e.current?.ownerDocument??(typeof document>"u"?null:document);if(!o)return;const u=()=>{const s=e.current;if(!s||o.activeElement!==s)return;const c=s.selectionStart??s.value.length,i=s.selectionEnd??c;r(a=>a&&a.start===c&&a.end===i?a:{start:c,end:i})};return o.addEventListener("selectionchange",u),()=>o.removeEventListener("selectionchange",u)},[e]),[n,r]}function A({target:e,value:n,onChange:r,disabled:o=!1,label:u="Formatting"}){const s=g({target:e,onChange:r}),[c,i]=L(e),a=t=>s(d=>{const l=F(n,t,d);return i({start:l.selectionStart,end:l.selectionEnd}),l}),f=D(),m={};if(c)for(const t of f)m[t.style]=C(n,c.start,c.end,t.style);const S=o?null:p(n,c);return x(M,{offered:new Set(f.map(t=>t.style)),onMark:t=>a(t),pressed:m,disabled:o,"aria-label":T(u),className:"sf-markup-bar",clear:S?{onClear:()=>s(()=>{const t=e.current,d=t&&t.ownerDocument.activeElement===t?{start:t.selectionStart??0,end:t.selectionEnd??0}:null,l=p(n,d)??{text:n,selectionStart:d?.start??0,selectionEnd:d?.end??0};return i({start:l.selectionStart,end:l.selectionEnd}),l})}:void 0})}var v=A;export{A as MarkupToolbar,p as clearFormatting,v as default,F as markSelection};
@@ -1 +1 @@
1
- import{jsx as t,jsxs as I}from"react/jsx-runtime";import{ButtonIcon as F,ButtonIconIcon as g,GroundIcon as x,IconAfterTextIcon as T,IconBeforeTextIcon as y,TextColorIcon as C,WidthIcon as _}from"efficient-easel/icons";import*as B from"efficient-easel/icons";import{SettingsField as O}from"efficient-easel/panel";import{useSelectedFields as d}from"efficient-easel/easel";import{IconPicker as S,Segmented as k}from"efficient-shell/ui";import{StorefrontTextLinkField as w}from"../../../../../components/StorefrontLinkField.js";import{BUTTON_ICONS as L,buttonIconChoice as N,buttonIconSide as v,buttonWidth as W}from"../../../../../../format/lib/content/button-icon.js";import{BUTTON_PAD_BUILT_IN as z,BUTTON_PAD_KEYS as P,buttonLook as A}from"../../../../../../format/lib/content/button-look.js";import{say as n}from"../../../../../../format/lib/editor-words.js";import{FOLLOWS_SITE_BUTTON as U,FOLLOWS_SITE_BUTTON_INK as R,buttonBorderField as j,buttonWordsEntryField as E,colorInput as u,group as f,inOwnBox as D,linkField as K,plainText as G,section as m,segmented as Y,sidesPaddingFields as M}from"../../../controls.js";import{NoControlMark as V,noControlField as $}from"efficient-easel/screen/lib/document/panel-no-control-mark";import{alignField as q}from"../../shared-fields.js";import{CARD_ROW_FACTS as H,cardRowField as p,cardRowFields as J}from"../../../card-row-fields.js";import{consentWordsKept as Q,withConsentWordsRow as X}from"../../../consent-words-field.js";const c=o=>({...$({type:"custom",render:()=>t(V,{})},"always"),reachedBy:o});function h(o){const e=(o==="none"?"no-symbol":o).replace(/(^|-)([a-z])/g,(r,s,a)=>a.toUpperCase()),l=B[`${e}Icon`];return l?t(l,{size:16}):null}const Z=L.map(o=>({value:o,icon:h(o)}));function oo({value:o,onChange:i}){const e=d(),l=e.values.href,r=typeof o=="string"?o:o&&typeof o=="object"&&"text"in o?String(o.text??""):"";return t(w,{label:"Button",icon:t(F,{size:18}),text:r,onTextChange:i,link:typeof l=="string"?l:"",onLinkChange:s=>e.onChange("href",s)})}function to({value:o,onChange:i}){const e=d(),l=N(o,e.values.arrow),r=v(e.values.iconPosition),s=W(e.values.widthFit)==="fill",a=h("icon-at-end");return t(O,{label:n("Icon"),icon:t(g,{size:18}),children:I("div",{className:"flex items-center gap-2",children:[t(S,{label:n("Icon"),value:l,emptyValue:"none",options:Z,onChange:i}),l!=="none"&&t(k,{size:"sm",block:!0,label:n("Icon position"),value:r==="end"&&!s?"after":r,onChange:b=>e.onChange("iconPosition",b),options:[{value:"before",icon:t(y,{size:16}),label:t("span",{className:"sr-only",children:n("Icon before text")}),title:n("Icon before text")},{value:"after",icon:t(T,{size:16}),label:t("span",{className:"sr-only",children:n("Icon after text")}),title:n("Icon after text")},...s?[{value:"end",icon:a,label:t("span",{className:"sr-only",children:n("Icon at the far end")}),title:n("Icon at the far end")}]:[]]})]})})}const eo={key:"buttonFillOpacity",unsetFrom:"variant",unset:o=>A({variant:o}).fillOpacity},Fo={fields:{label:D(G("Button"),o=>t(oo,{value:o.value,onChange:o.onChange})),labelText:E("label"),href:{...K("Button link"),...c("label")},consentWords:Q("label"),_gButton:f("Button"),rowField:p("Shows","text"),rowLinkField:p("Link from","link"),_dSize:m("Size"),widthFit:Y("Width",t(_,{}),[{label:"Fit content",value:"fit"},{label:"Fill",value:"fill"}],"fit"),...M({keys:P,fallback:z,group:!1}),_gStyle:f("Style"),variant:c("buttonColor"),icon:{type:"custom",render:o=>t(to,{value:o.value,onChange:o.onChange})},iconPosition:c("icon"),arrow:c("icon"),buttonColor:u("Fill color",U,t(x,{}),eo),buttonFillOpacity:c("buttonColor"),buttonBorder:j(),buttonTextColor:u("Text color",R,t(C,{})),_dLayout:m("Layout"),align:q()},resolveFields:(o,i)=>X(J(i.fields,o,i),o.props,"label",["href"]),showWhenFacts:H};export{Fo as ButtonBlockFields};
1
+ import{jsx as t,jsxs as I}from"react/jsx-runtime";import{ButtonIcon as F,ButtonIconIcon as g,GroundIcon as x,IconAfterTextIcon as T,IconBeforeTextIcon as y,TextColorIcon as C,WidthIcon as _}from"efficient-easel/icons";import*as B from"efficient-easel/icons";import{SettingsField as O}from"efficient-easel/panel";import{useSelectedFields as d}from"efficient-easel/easel";import{IconPicker as S,Segmented as k}from"efficient-shell/ui";import{StorefrontTextLinkField as w}from"../../../../../components/StorefrontLinkField.js";import{BUTTON_ICONS as L,buttonIconChoice as N,buttonIconSide as v,buttonWidth as W}from"../../../../../../format/lib/content/button-icon.js";import{BUTTON_PAD_BUILT_IN as z,BUTTON_PAD_KEYS as P,buttonLook as A}from"../../../../../../render/lib/content/button-look.js";import{say as n}from"../../../../../../format/lib/editor-words.js";import{FOLLOWS_SITE_BUTTON as U,FOLLOWS_SITE_BUTTON_INK as R,buttonBorderField as j,buttonWordsEntryField as E,colorInput as u,group as f,inOwnBox as D,linkField as K,plainText as G,section as m,segmented as Y,sidesPaddingFields as M}from"../../../controls.js";import{NoControlMark as V,noControlField as $}from"efficient-easel/screen/lib/document/panel-no-control-mark";import{alignField as q}from"../../shared-fields.js";import{CARD_ROW_FACTS as H,cardRowField as p,cardRowFields as J}from"../../../card-row-fields.js";import{consentWordsKept as Q,withConsentWordsRow as X}from"../../../consent-words-field.js";const c=o=>({...$({type:"custom",render:()=>t(V,{})},"always"),reachedBy:o});function h(o){const e=(o==="none"?"no-symbol":o).replace(/(^|-)([a-z])/g,(r,s,a)=>a.toUpperCase()),l=B[`${e}Icon`];return l?t(l,{size:16}):null}const Z=L.map(o=>({value:o,icon:h(o)}));function oo({value:o,onChange:i}){const e=d(),l=e.values.href,r=typeof o=="string"?o:o&&typeof o=="object"&&"text"in o?String(o.text??""):"";return t(w,{label:"Button",icon:t(F,{size:18}),text:r,onTextChange:i,link:typeof l=="string"?l:"",onLinkChange:s=>e.onChange("href",s)})}function to({value:o,onChange:i}){const e=d(),l=N(o,e.values.arrow),r=v(e.values.iconPosition),s=W(e.values.widthFit)==="fill",a=h("icon-at-end");return t(O,{label:n("Icon"),icon:t(g,{size:18}),children:I("div",{className:"flex items-center gap-2",children:[t(S,{label:n("Icon"),value:l,emptyValue:"none",options:Z,onChange:i}),l!=="none"&&t(k,{size:"sm",block:!0,label:n("Icon position"),value:r==="end"&&!s?"after":r,onChange:b=>e.onChange("iconPosition",b),options:[{value:"before",icon:t(y,{size:16}),label:t("span",{className:"sr-only",children:n("Icon before text")}),title:n("Icon before text")},{value:"after",icon:t(T,{size:16}),label:t("span",{className:"sr-only",children:n("Icon after text")}),title:n("Icon after text")},...s?[{value:"end",icon:a,label:t("span",{className:"sr-only",children:n("Icon at the far end")}),title:n("Icon at the far end")}]:[]]})]})})}const eo={key:"buttonFillOpacity",unsetFrom:"variant",unset:o=>A({variant:o}).fillOpacity},Fo={fields:{label:D(G("Button"),o=>t(oo,{value:o.value,onChange:o.onChange})),labelText:E("label"),href:{...K("Button link"),...c("label")},consentWords:Q("label"),_gButton:f("Button"),rowField:p("Shows","text"),rowLinkField:p("Link from","link"),_dSize:m("Size"),widthFit:Y("Width",t(_,{}),[{label:"Fit content",value:"fit"},{label:"Fill",value:"fill"}],"fit"),...M({keys:P,fallback:z,group:!1}),_gStyle:f("Style"),variant:c("buttonColor"),icon:{type:"custom",render:o=>t(to,{value:o.value,onChange:o.onChange})},iconPosition:c("icon"),arrow:c("icon"),buttonColor:u("Fill color",U,t(x,{}),eo),buttonFillOpacity:c("buttonColor"),buttonBorder:j(),buttonTextColor:u("Text color",R,t(C,{})),_dLayout:m("Layout"),align:q()},resolveFields:(o,i)=>X(J(i.fields,o,i),o.props,"label",["href"]),showWhenFacts:H};export{Fo as ButtonBlockFields};
@@ -292,6 +292,7 @@ export declare function heightFields(): Record<string, CustomField<undefined> |
292
292
  export declare function stickFields(): Record<string, CustomField<undefined> | CustomField<boolean> | CustomField<number>>;
293
293
  export declare function anchorFields(): Record<string, CustomField<undefined> | CustomField<HidableValue>>;
294
294
  export declare function dateTime(label: string, icon?: ReactNode, hint?: string): CustomField<string>;
295
+ export declare function date(label: string, icon?: ReactNode, hint?: string): CustomField<string>;
295
296
  export declare function toggle(label: string, fallback: boolean, icon?: ReactNode): CustomField<boolean>;
296
297
  export declare function pageBackgroundField(): CustomField<string>;
297
298
  export declare function checkbox(label: string, fallback: boolean): CustomField<boolean>;