efficient-storefront-blocks 0.0.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,429 @@
1
+ # Changelog
2
+
3
+ ## 0.12.0 — 2026-10-08
4
+
5
+ ⚠️ **For hosts, before you upgrade:** the peer dependency is `efficient-easel` ^0.102.0, and the editor's screen comes from it. A host that loads `components/storefront-editor.css` itself also loads `efficient-easel/screen.css` before it.
6
+
7
+ - **The editor's screen comes from efficient-easel.** The website editor's
8
+ frame, panels, Layers tree, Add panel, inspector and load-and-save are
9
+ `efficient-easel/screen` (0.102.0) now, which the builder's modules re-export
10
+ (efficient-web-builder ADR 0004). The peer dependency is `efficient-easel`
11
+ ^0.102.0. A host that loads `components/storefront-editor.css` itself loads
12
+ `efficient-easel/screen.css` before it.
13
+ - **The editor's Link row is the shared link picker.** Every `linkField()` row
14
+ (button, card, header and footnote links) now draws efficient-easel's
15
+ `LinkPicker`, the same control as the admin's menu item: a type, then which
16
+ one, and on the product listing a Filter and a Value. The listing page is
17
+ called "Products" in the Page list. Any field the listing filters on can be a
18
+ link's filter (`/wheels?size=20`), with only the values in this site's
19
+ catalogue, and a field the merchant took out of the listing's filter rail in
20
+ Product Types is not offered. An unsafe address (`javascript:`) is refused.
21
+ The separate "Product type" row under the Link row is gone; the type is now
22
+ one of the Filters. Saved links do not change.
23
+ - **`linkPickerSetup`** in `efficient-storefront-blocks/links`: a host's pages,
24
+ posts, products, catalogue and Product Types answers → what the shared picker
25
+ is handed (the kinds with their options, the URL rules, the filters a listing
26
+ link may carry). The editor's Link row draws the same answer. Types
27
+ `LinkPickerSetupInput`, `LinkPickerSetup`, `LinkPickerKind`,
28
+ `LinkPickerTarget`, `LinkPickerOption`, `LinkPickerRules`.
29
+ - **`fieldUsageFromAdminRows`** in `efficient-storefront-blocks/links`: the
30
+ admin's field-usage rows (`GET /api/storefront/field-usage/?site=`, which
31
+ carries the backend's own `kind`) → the answers the Filter list reads. A row
32
+ with no kind is left out; an unanswered place stays absent. `LinkFieldUsage`
33
+ and `AdminFieldUsageRow` are its types.
34
+
35
+ ## 0.11.0 — 2026-10-07
36
+
37
+ - **Renamed: `efficient-web-builder` is now `efficient-storefront-blocks`.**
38
+ This package is the website builder assembled with the storefront's own
39
+ sections and EFFICIENT's backend, built from the storefront repository. The
40
+ name `efficient-web-builder` goes to the builder alone, published from its
41
+ own repository (doc/adr/0002, *Names and end state*). Nothing else moved:
42
+ the entries (`.`, `./contract`, `./links`, `./editor.css`), every export and
43
+ the `storefront-editor:*` messages are what 0.10.0 published.
44
+
45
+ To migrate, install `efficient-storefront-blocks@^0.11.0`, remove
46
+ `efficient-web-builder`, and change the module name in each import:
47
+
48
+ ```diff
49
+ -import "efficient-web-builder/editor.css";
50
+ -import { WebsiteEditor, createEditorHost } from "efficient-web-builder";
51
+ +import "efficient-storefront-blocks/editor.css";
52
+ +import { WebsiteEditor, createEditorHost } from "efficient-storefront-blocks";
53
+ ```
54
+
55
+ `efficient-web-builder` 0.10.0 and earlier stay on the registry as they
56
+ were published. Do not alias the old name to this package: a host that later
57
+ installs the builder itself needs that name free.
58
+
59
+ - **Needs `efficient-easel` 0.101.0 or later** (peer `^0.101.0`, was
60
+ `^0.100.0`). Every list in the editor is efficient-easel's one list, which
61
+ 0.101 ships.
62
+
63
+ ## 0.10.0 — 2026-10-07
64
+
65
+ - **The preview has square corners.** The canvas's desktop frame had a rounded
66
+ corner where the page meets the toolbar and the panel, and the tablet and
67
+ phone frames were drawn with a device's rounded edge. All three clipped the
68
+ corners of the website inside. They are square; the tablet and phone frames
69
+ are still told apart from the well by their width and outline.
70
+ - **A website that has not set Corners is drawn square.** In Site styles ▸
71
+ Corners, "Not set" used to leave small built-in rounded corners on inputs,
72
+ panels and some pictures. The canvas now draws such a site square, as the
73
+ live storefront does; a site that chose a value keeps it. The Mockup
74
+ section's address bar and stat chips and the integrations chips, which were
75
+ pill-shaped on every site, follow the site's Corners too.
76
+
77
+ - **The part panel takes the final text box.** Clicking a run of text opens
78
+ efficient-easel's final text box: a two-row toolbar (Bold, Italic, Underline,
79
+ Strikethrough, Color, Link, Superscript, Subscript, Undo / Left, Center,
80
+ Right, Justify, lists, Aa AA aa) and six number cells — Font size, Line
81
+ spacing (%), Letter spacing (px), Paragraph spacing, Padding and Width. The
82
+ Style section below holds the style card, Font (easel's one dropdown) and a
83
+ Color row of the section's theme colours plus Any color. The Weight row is
84
+ gone (B is the bold); a weight already stored still draws. The bundle now also imports
85
+ `efficient-easel/gold.css` and `efficient-easel/text-styles.css`, which the
86
+ host's bundler resolves from its own efficient-easel.
87
+ - **Old part settings draw the same.** A stored line or letter nudge is read
88
+ as the number the published page has always drawn for it and is never
89
+ rewritten. The editor canvas now draws a nudged part exactly as the live
90
+ page does.
91
+
92
+ ## 0.9.0 — 2026-10-07
93
+
94
+ - **The Product Grid title keeps its words in the canvas.** When the head row
95
+ is crowded (in the editor, an empty supporting line and link draw their
96
+ placeholders), the supporting line now truncates first, and the title, "View
97
+ all" and the count stay whole. Before, the title split inside its words at
98
+ 912 wide. Published heads that are not crowded are unchanged.
99
+
100
+ - **Needs `efficient-easel` 0.100.0 or later** (peer `^0.100.0`, was
101
+ `^0.99.2`). 0.100 removes the deprecated `Editor…` names, which this package
102
+ no longer uses. The copy box's bar no longer draws the ◆ Emphasis button
103
+ (E5a), and the "press the highlighter" hint under four copy rows is gone with
104
+ it. Saved `==words==` still shows in the theme colour.
105
+
106
+ - **`backend.media.maxUploadBytes` — the media field's size cap is the
107
+ backend's.** An optional number on the `media` group: the largest file a
108
+ media field takes before handing it to the host's panel or picker. Without it
109
+ the editor refuses no file for its size. It was EFFICIENT's published cap,
110
+ applied to every host.
111
+
112
+ - **`backend.social` — the social links join the backend contract.** A new
113
+ optional group on `WebsiteBackend`: `social.get(scope?)` and
114
+ `social.update(patch, scope?)` over `SocialLinkSettings` — one address per
115
+ platform, under the platform's name. The editor's Social links rows read and
116
+ save through it and no longer call EFFICIENT's client.
117
+ - **`WebsiteBackendError.fields`.** An `invalid` rejection may name the inputs
118
+ it refused, each with the reason (`{ instagram: "Enter a valid URL." }`); the
119
+ editor shows it beside that input. `social.update` is the first to use it.
120
+
121
+ - **`backend.chat` — the live chat joins the backend contract.** A new optional
122
+ group on `WebsiteBackend`: `chat.get(scope?)` and `chat.update(patch, scope?)`
123
+ over `ChatSettings` (enabled, title, subtitle, greeting). The editor's Live
124
+ chat panel reads and saves through it and no longer calls EFFICIENT's client.
125
+ Under EFFICIENT's backend nothing changes.
126
+
127
+ - **`backend.pages.linkTargets` — the link picker's pages join the backend
128
+ contract.** A new optional method on the `pages` group: every page a link
129
+ may point at, as `LinkTargetPage`s (id, slug, the page's name, and its
130
+ layout), in one call. The link picker reads it for its "Page" and "Anchor"
131
+ targets and no longer calls EFFICIENT's client. A host's backend without it
132
+ still has its pages listed — from `pages.list` — with no section anchors.
133
+ Under EFFICIENT's backend nothing changes.
134
+
135
+ - **`backend.blog` — the website's blog joins the backend contract.** A new
136
+ optional group on `WebsiteBackend`: `blog.posts(scope?)` answers the
137
+ website's published posts as `BlogPostRow`s (slug, title, excerpt, category,
138
+ an absolute cover address, the publish date, and the post's own path). The
139
+ editor reads it in two places — a section's "Blog post source", and the link
140
+ picker's "Blog post" target — and no longer calls EFFICIENT's client for
141
+ either. A host that passes its own `backend` with a `blog` gets both; one
142
+ without gets what it had before: a block already linked to a post says so and
143
+ can only be unlinked, and the link picker offers no "Blog post". Under
144
+ EFFICIENT's backend (no `backend` passed, or `createEfficientBackend()`)
145
+ nothing changes.
146
+
147
+ - **The Visual sitemap is out of the editor.** The rail's "Visual sitemap"
148
+ button and the page-card overlay it opened are removed. A host that wants a
149
+ bird's-eye view of a website's pages draws its own, outside the editor:
150
+ EFFICIENT's admin shows it as the Sitemap section of its Storefront Console.
151
+ Nothing else in the rail moves, and no prop or host message changes
152
+ (`storefront-editor:open-page` and `storefront-editor:new-page` are still
153
+ sent by the Pages panel).
154
+
155
+ - **`backend.theme` — a website's appearance joins the backend contract.** A
156
+ new optional group on `WebsiteBackend`: `theme.get(scope?)` and
157
+ `theme.update(patch, scope?)` over `SiteThemeRow` — the row behind Site
158
+ styles, key for key as it is stored. The editor seeds its appearance and
159
+ saves every Site styles change through it and no longer calls EFFICIENT's
160
+ client. Site styles is now offered to ANY backend that has the group
161
+ (`hasSiteTheme` was EFFICIENT-only); one without it is unchanged.
162
+
163
+ ## 0.8.1 — 2026-10-07
164
+
165
+ - **The held hero frame stays on screen.** A hero slide with a video and no
166
+ poster holds on the video's first frame (0.8.0). That frame was a paused,
167
+ never-played `<video>`, and the browser does not always paint one: it could
168
+ go blank, for example after the editor window was resized, leaving the pale
169
+ surface under the slide's white words. The frame is now drawn once onto a
170
+ canvas, and the source video is dropped as soon as it is drawn.
171
+
172
+ A patch cut from 0.8.0 with this one fix (branch `release/web-builder-0.8.1`),
173
+ so it did not carry the 0.9.0 changes above. The fix is on `main` too
174
+ (#1582), so 0.9.0 has it.
175
+
176
+ ## 0.8.0 — 2026-10-06
177
+
178
+ - **A hero slide with a video and no poster shows in the canvas.** A hero's
179
+ video is held in the editor until "Play video" is pressed. A held slide that
180
+ has no poster drew nothing, so the canvas showed a pale blank under white
181
+ words where the published page plays the video. It now shows the video's
182
+ first frame as a still: nothing plays, and only the start of the file is
183
+ fetched. A slide that has a poster mounts no video while held, as before.
184
+
185
+ - **`efficient-web-builder/links` — the link rules, for a host's own link picker.**
186
+ A new light entry (one file, no imports, like `/contract`): the link kinds,
187
+ each thing's live URL, a saved link read back to its kind, the product
188
+ listing read off a page's layout, the ONE filter a listing link may carry
189
+ (any field the listing filters on, in the listing's own query param), the
190
+ filters and catalogue values a listing link may offer, and the addresses
191
+ that are refused. Built from the file the editor's own Link field reads, so
192
+ the admin's menu picker writes links by the same rules. The editor itself is
193
+ unchanged.
194
+
195
+ ## 0.7.1 — 2026-10-06
196
+
197
+ - **The Fitment Finder and the gallery builds load in a host's editor.** Their
198
+ calls to the website's own public routes (`/api/v1/fitment/*`,
199
+ `/api/v1/gallery-builds`) carried an `X-Portal-Audience` header. Those routes
200
+ answer a cross-origin caller with open CORS that allows only `Accept` and
201
+ `Content-Type`, so the browser's preflight refused the call: the Fitment
202
+ Finder showed "Vehicle list unavailable" and the gallery came back empty.
203
+ These calls now send no audience; every other call is unchanged.
204
+
205
+ - **The engine peer is `efficient-easel ^0.99.2`** (it was `^0.99.0`). This
206
+ package now imports the engine by its Easel names (`createEasel`,
207
+ `useEasel`, `EaselProvider`, `efficient-easel/easel`), which 0.99.2 added.
208
+ The engine still exports the old names, so a host's own code does not have
209
+ to change; a host only needs 0.99.2 or later installed. Nothing an operator
210
+ sees changes.
211
+
212
+ - **One media panel head for both editors.** The Media panel's head is
213
+ efficient-easel's `MediaPanelHead`, the same head the campaign designer
214
+ draws over the same library (owner ruling 2026-10-06: a part exists once, in
215
+ efficient-easel). Nothing it says or does changed; the Cancel button's sides
216
+ are 12px (were 10px), on the spacing scale. Needs the efficient-easel release
217
+ that ships `MediaPanelHead`.
218
+
219
+ - **Grid cells fill their height in the canvas.** A block in a Grid cell now
220
+ stretches to the cell's height in the editor, as it does on the published
221
+ page. The canvas sheet (built from the storefront's `app/globals.css`) makes
222
+ the editor's drag wrapper in a Grid a one-column grid, so the block inside it
223
+ stretches. Published pages are unchanged.
224
+ - **Box rows fill their height in the canvas.** The same fix for a Box laid out
225
+ in one row and a Slide box set to One row: when the row stretches (Align
226
+ Stretch, or not set), the drag wrapper is a one-column grid, so the block
227
+ inside it is the row's height as on the published page. Start, Center and End
228
+ rows and Stacked boxes are unchanged. Published pages are unchanged.
229
+
230
+ - **The editor opens a page with its live prices.** Under the EFFICIENT
231
+ backend, `pages.load` by slug now only finds the page, then reads it by id.
232
+ Only that read re-prices the wheel copy a linked Product Grid or Product
233
+ Hero keeps in the page, the same way the published page does. Before, a
234
+ stale copy (USD 0) drew "Price on request" on cards the live page priced.
235
+ An embedder's own backend is not affected.
236
+
237
+ - **The canvas gets the live page's head.** The editor's canvas frame now runs
238
+ the same fit-words boot the published `<body>` runs (`lib/fit-words.ts`), so
239
+ a heading word wider than its box shrinks to fit instead of breaking inside
240
+ the word ("THE UNPAVE / D", "Monoblo / ck"). It runs in the frame's own
241
+ document; the embedder's page is never touched.
242
+ - **The canvas fonts fall back as the live page's do.** Each `--font-*`
243
+ variable is bound to next/font's stack (`'Family', 'Family Fallback'`) and
244
+ the canvas sheet declares next/font's metric-matched `"<Family> Fallback"`
245
+ faces, so a glyph outside a web font's subset (→, ″) and text drawn before
246
+ the web font arrives take the widths the live page gives them. The faces are
247
+ local fonts: an editor over an embedder's own backend (no Google Fonts sheet)
248
+ gets them too.
249
+ - **The Mobile canvas is 390px wide** (it was 388: the device frame's 1px
250
+ border sat inside its width), and Tablet is 800 (was 798). The device edge
251
+ is now an outline that takes no width.
252
+ - **An empty slot no longer covers the picture behind it.** The editor sheet
253
+ (`dist/editor.css`) no longer paints its own solid fill on efficient-easel's
254
+ empty-slot cell, so the slot looks as easel 0.99.1 draws it: nothing at
255
+ rest, so a hero's picture or video shows; the outline and "+ Add block" on
256
+ hover or focus. Published pages are unchanged.
257
+
258
+ ## 0.7.0 — 2026-10-05
259
+
260
+ - **Renamed: `efficient-web` is now `efficient-web-builder`.** 0.7.0 is the
261
+ first release under this name, and `efficient-web` stops at 0.3.0. 0.4.0,
262
+ 0.5.0 and 0.6.0 below were never published under either name, so an embedder
263
+ moving from `efficient-web` 0.3.0 takes all four sets of changes together.
264
+ - **To migrate:** change the dependency name (`"efficient-web": "^0.3.0"`
265
+ becomes `"efficient-web-builder": "^0.7.0"`) and the import specifiers:
266
+ `efficient-web` becomes `efficient-web-builder`, and
267
+ `efficient-web/editor.css` becomes `efficient-web-builder/editor.css`. An
268
+ install that lists the package by name (pnpm's `minimumReleaseAgeExclude`)
269
+ renames that entry too.
270
+ - The messages the package logs or throws now open with
271
+ `efficient-web-builder:` instead of `efficient-web:`.
272
+ - **A host chooses which blocks its editor offers.** `WebsiteEditor` and
273
+ `WebsiteSectionEditor` take an optional `blocks`: the `sets` offered
274
+ (`general`, `commerce`, `service`), an `allow` and a `deny` list, the host's
275
+ own blocks (`host`, each an `efficient-easel/blocks` `ComponentConfig`), the
276
+ Add-panel group each stands in (`categories`), and live `metadata` every
277
+ block receives as `puck.metadata`. See the README.
278
+ - **Without `blocks` nothing changes.** The editor is given the same block
279
+ registry, the same object, and offers every block it has. An embedder that
280
+ passes nothing compiles and behaves as in 0.6.0.
281
+ - **Every block has a set.** `general` blocks draw from their own props and
282
+ what the host hands them; `commerce` blocks are the shop; `service` blocks
283
+ need one of the EFFICIENT backend's site services (forms, bookings, reviews,
284
+ the newsletter, the blog, menus). 105 blocks: 53 general, 27 commerce, 25
285
+ service.
286
+ - **Offered, not registered.** A block a host leaves out is in no Add-panel
287
+ group, no slot's menu and no drop target, and no section is seeded with it. A
288
+ page that already holds one still draws it and it can be deleted.
289
+ - **A section is offered only with the blocks it is built from.** A Hero is not
290
+ offered where its slides are not; a section that is merely wrapped in a Box
291
+ when it is added lands whole instead.
292
+ - **With a set left out, the controls that need it are not drawn**: a link has
293
+ no "Blog post" or "Product" target, a section's optional "Blog post source"
294
+ is hidden, the Form picker is inert, and the pinned Header and Footer are
295
+ not seeded.
296
+ - **`blocks.metadata` is live.** Change the object and the blocks in the canvas
297
+ redraw in place; it is never written to the page or the undo history. The
298
+ rest of `blocks` is read once, when the editor mounts.
299
+ - **A host's own block gets none of the rows the editor adds to its own
300
+ sections** (padding, width, anchor, theme, animation). It is drawn by its own
301
+ `render`, edited with the fields it declares, added from the Add panel, and
302
+ hidden by the Layers tree's eye.
303
+ - **New entry: `efficient-web-builder/contract`.** One small file with no imports, for
304
+ a host's server: `BLOCK_SETS`, `GENERAL_BLOCKS`, `COMMERCE_BLOCKS`,
305
+ `SERVICE_BLOCKS`, `blockSetOf(type)` and `blockTypesIn(layout)` — every block
306
+ type a saved page uses, including inside slots. Hiding a block in the editor
307
+ is not a security boundary; checking the saved page is.
308
+ - New types: `WebsiteEditorBlocks`, `WebsiteBlockCategory`, `WebsiteBlockSet`.
309
+ `ComponentConfig` is the engine's (`efficient-easel/blocks`).
310
+
311
+ ## 0.6.0 — 2026-10-05
312
+
313
+ - **The engine peer is `efficient-easel`.** The engine is called Efficient
314
+ Easel, and its package was renamed from `efficient-editor` at 0.96.0. This
315
+ package now imports `efficient-easel/*` and asks for `efficient-easel`
316
+ `^0.96.0` in place of `efficient-editor` `^0.94.1`. A host moves the two
317
+ together: install `efficient-easel` and import its sheets from
318
+ `efficient-easel/*.css`.
319
+ - The engine's sheets inside `efficient-web/editor.css` are 0.96.0's. That
320
+ release is 0.95.0 under the new name: no class, variable or rendered byte
321
+ differs, and the `es-` classes keep their names.
322
+
323
+ ## 0.5.0 — 2026-10-04
324
+
325
+ - **Built on efficient-editor 0.94.1.** The peer range moves from `^0.93.0` to
326
+ `^0.94.1`, and the engine's sheets inside `efficient-web/editor.css` are
327
+ 0.94.1's. Install the two together: the formatting bar above a copy box is
328
+ drawn by the engine and styled by this package's sheet, so 0.94's bar on
329
+ 0.93's sheet would not match.
330
+ - The formatting bar's buttons take the engine's 0.94 look: 32px, 6px corners,
331
+ and a pressed button that stays tinted under the pointer. Their tooltips are
332
+ the engine's: Strong, Italic, Strikethrough and Emphasis, each with the mark
333
+ it writes.
334
+ - **Two word styles are renamed on the bar: Emphasis is now Highlight, and
335
+ Strong is now Bold**, because the engine's own buttons took those two words.
336
+ The stored keys (`highlight`, `strong`) and the marks (`@@`, `++`) do not move.
337
+
338
+ ## 0.4.0 — 2026-10-04
339
+
340
+ - **The editor can run on a backend that is not EFFICIENT's.** `WebsiteEditor`
341
+ and `WebsiteSectionEditor` take an optional `backend`: the embedder's own
342
+ implementation of `WebsiteBackend` — pages (list, load, save, version,
343
+ publish, create, remove), the edit lock, the site record, media, section
344
+ templates, website templates, the Preview link. `pages`, `site.get` and
345
+ `media.resolve` are required; every other group or method is optional, and
346
+ the editor draws no control for one that is missing. See the README and
347
+ `doc/adr/0002`.
348
+ - **Without `backend` nothing changes.** It is `createEfficientBackend()`:
349
+ `/api/storefront/*`, authorised by the token the host delivers with
350
+ `storefront-editor:auth`, with `auth-expired` on a 401 — as in 0.3.0. An
351
+ embedder that passes nothing compiles and behaves as before.
352
+ - **Failures are kinds, not HTTP bodies.** A backend rejects with
353
+ `WebsiteBackendError` (`unauthorized`, `changed-elsewhere`, `lock-taken`,
354
+ `not-found`, `invalid`, `unavailable`); a refused save carries who saved, a
355
+ taken page who holds it.
356
+ - **`PageBundle`** — a page is saved as `{ layout, translations?, seo? }`.
357
+ 0.4.0 edits `layout`; `translations` and `seo` are reserved for per-language
358
+ content, so a host's storage is shaped once.
359
+ - **Under an embedder's backend the package makes no request of its own**: no
360
+ token is waited for (`ready` is announced once), its own HTTP client is
361
+ closed, the canvas loads no remote font sheet, and stored media is resolved
362
+ by `backend.media.resolve`.
363
+ - **One session per mounted editor.** The token, the website being edited and
364
+ the editor's caches belong to the mount, so a re-mount for another website
365
+ starts from nothing (one editor at a time is still the rule).
366
+ - New exports: `createEfficientBackend`, `WebsiteBackendError`, and the types
367
+ `WebsiteBackend`, `WebsitePages`, `WebsiteEditLock`, `WebsiteSite`,
368
+ `WebsiteMedia`, `WebsiteSectionTemplates`, `WebsiteTemplates`,
369
+ `WebsitePreview`, `PageBundle`, `PageDocument`, `PageLayout`, `PageRef`,
370
+ `SiteScope`, `NewPageInput`, `SaveExpectation`, `EditorPageRow`, `SiteRecord`,
371
+ `SiteRecordPatch`, `SaveConflict`, `LockHolder`, `SectionNode`,
372
+ `SectionTemplate`, `SectionTemplateRecord`, `WebsiteBackendErrorKind`,
373
+ `EfficientBackendOptions`.
374
+ - Not behind the interface yet (unchanged under EFFICIENT's backend, absent
375
+ under another): site styles, the pinned header and footer, live chat, social
376
+ links, menus, blog, forms, the catalog, the sitemap panel and "duplicate to
377
+ page". A Form section's picker (0.3.0) is inert under another backend: no
378
+ list, no "New form", no `storefront-editor:open-form`.
379
+
380
+ ## 0.3.0 — 2026-10-04
381
+
382
+ - **Editing a form waits for nothing.** A Form picker's "Edit form" sends
383
+ `storefront-editor:open-form` with `mode: "edit"` and **no `requestId`**, and
384
+ does not wait for an answer: the embedder's form builder is a window the
385
+ merchant works in beside the editor, not a question the picker asked. The
386
+ picker's buttons are no longer disabled while the builder is open.
387
+ `requestId` is now optional on the message type.
388
+ - **A block follows a renamed form by id.** When a forms re-read no longer
389
+ explains a block's stored slug but still holds the form that slug last
390
+ resolved to, the block is re-pointed at the form's new slug. This replaces
391
+ following the slug on the reply to an edit request, and also covers a rename
392
+ made outside the editor. A deleted form is never replaced by another.
393
+ - **"New form" still asks and waits** (`mode: "create"`, with a `requestId`,
394
+ answered by `form-saved` / `form-closed`). An embedder is expected to answer
395
+ it quickly, for example with a popup that names and creates the form; one
396
+ that answers with its whole form builder still works, and the fifteen-minute
397
+ reply backstop stays for it.
398
+ - An embedder that answered an edit request with `form-closed` keeps working:
399
+ the reply is for a request nobody is waiting on, and is ignored.
400
+
401
+ ## 0.2.0 — 2026-10-04
402
+
403
+ - **The media library is a panel of the editor.** `WebsiteEditor` and
404
+ `WebsiteSectionEditor` take an optional `mediaPanel`: the embedder's media
405
+ library, as a component the editor draws in its own left panel. The rail's
406
+ Media button opens it as a view beside Pages, Layers and Site styles, and
407
+ every image field opens it in pick mode ("Choose image · Background image"),
408
+ so the field's choice is made in the editor instead of in a second window.
409
+ New types: `MediaPanelComponent`, `MediaPanelProps`, `MediaPickRequest`.
410
+ - Without `mediaPanel` nothing changes: fields ask the host to open its picker
411
+ window with `storefront-editor:open-media-picker`, as in 0.1.0.
412
+ - **One head for every side panel, on both sides.** Pages, Layers, Site styles,
413
+ the Media library, Add, Choose image and the right-hand settings panel all
414
+ wear the engine's `InspectorHead`: a glyph, the name, what it is about, the
415
+ panel's own buttons, then **Hide panel**, now on the right panel too. No ✕ in a panel head any
416
+ more: Add leaves with **Done**, choosing an image with **Cancel**, and Layers'
417
+ collapse-all glyph no longer reads as a second ✕.
418
+ - **No panel toggles in the top bar.** They duplicated the heads' Hide panel
419
+ button. A hidden panel leaves a 40px strip at its edge with **Show panel**
420
+ (the same picture), the way back for both sides.
421
+
422
+ ## 0.1.0 — 2026-10-03
423
+
424
+ - **First release.** The storefront website editor (page and template editor,
425
+ standalone section editor) for an app that mounts it in its own page: an
426
+ in-process host (`createEditorHost`) in place of the shop's postMessage
427
+ bridge, the shop's sections with Next.js replaced at the module boundary, and
428
+ the canvas styled from the storefront's own compiled stylesheet inside its
429
+ frame.
package/LICENSE ADDED
@@ -0,0 +1,10 @@
1
+ Copyright (c) 2026 Efficient Pty Ltd. All rights reserved.
2
+
3
+ This software and its documentation are proprietary to Efficient Pty Ltd and
4
+ are confidential. No licence is granted to use, copy, modify, merge, publish,
5
+ distribute, sublicense or sell this software, in whole or in part, except
6
+ under a written agreement with Efficient Pty Ltd.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.