@akinon/pz-theme 2.0.134-rc.0 → 2.0.135-beta.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 CHANGED
@@ -1,40 +1,20 @@
1
1
  # @akinon/pz-theme
2
2
 
3
- ## 2.0.134-rc.0
4
-
5
- ### Patch Changes
6
-
7
- - Updated dependencies [86187b1c2]
8
- - Updated dependencies [0cf9ea239]
9
- - Updated dependencies [324f97d55]
10
- - Updated dependencies [51ea06888]
11
- - Updated dependencies
12
- - Updated dependencies [2fea41430]
13
- - Updated dependencies [b55acb768]
14
- - Updated dependencies [760258c1c]
15
- - Updated dependencies [143be2b9d]
16
- - Updated dependencies [7889b08fe]
17
- - Updated dependencies [9f8cd3bc5]
18
- - Updated dependencies [bfafa3f49]
19
- - Updated dependencies [57d7eb305]
20
- - Updated dependencies [d99a6a7d5]
21
- - Updated dependencies [9db81a714]
22
- - Updated dependencies [591e345e1]
23
- - Updated dependencies [4de5303c5]
24
- - Updated dependencies [95b139dc1]
25
- - Updated dependencies [1d00f2d06]
26
- - Updated dependencies [4ac7b2a1e]
27
- - Updated dependencies [e9598c71d]
28
- - Updated dependencies [4998a9631]
29
- - Updated dependencies [804d2bd6c]
30
- - Updated dependencies [3909d3224]
31
- - Updated dependencies [6a3d8a631]
32
- - Updated dependencies [e18836b20]
33
- - Updated dependencies [b1111d7b1]
34
- - Updated dependencies [1595d458]
35
- - Updated dependencies [dca12811]
36
- - @akinon/next@2.0.134-rc.0
37
- - @akinon/theme-contract@2.0.134-rc.0
3
+ ## 2.0.135-beta.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [cbbbfd757]
8
+ - @akinon/next@2.0.135-beta.0
9
+ - @akinon/theme-contract@2.0.135-beta.0
10
+
11
+ ## 2.0.134
12
+
13
+ ### Patch Changes
14
+
15
+ - f03a0af: ZERO-5165: Announce what the storefront can report to the theme editor
16
+ - @akinon/next@2.0.134
17
+ - @akinon/theme-contract@2.0.134
38
18
 
39
19
  ## 2.0.133
40
20
 
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@akinon/pz-theme",
3
3
  "description": "Theme package for Project Zero Next — ThemePlaceholder system and theme editor infrastructure",
4
- "version": "2.0.134-rc.0",
4
+ "version": "2.0.135-beta.0",
5
5
  "license": "MIT",
6
6
  "main": "src/index.ts",
7
7
  "scripts": {
8
8
  "test": "jest"
9
9
  },
10
10
  "peerDependencies": {
11
- "@akinon/next": "2.0.134-rc.0",
11
+ "@akinon/next": "2.0.135-beta.0",
12
12
  "react": "^18.0.0 || ^19.0.0",
13
13
  "react-dom": "^18.0.0 || ^19.0.0"
14
14
  },
15
15
  "dependencies": {
16
- "@akinon/theme-contract": "2.0.134-rc.0",
16
+ "@akinon/theme-contract": "2.0.135-beta.0",
17
17
  "clsx": "2.1.1",
18
18
  "lottie-web": "^5.13.0",
19
19
  "react-multi-carousel": "2.8.4",
@@ -21,7 +21,7 @@
21
21
  "zod": "4.4.1"
22
22
  },
23
23
  "devDependencies": {
24
- "@akinon/next": "2.0.134-rc.0",
24
+ "@akinon/next": "2.0.135-beta.0",
25
25
  "@testing-library/jest-dom": "5.16.4",
26
26
  "@testing-library/react": "16.3.2",
27
27
  "@testing-library/user-event": "14.1.1",
@@ -381,6 +381,20 @@ describe('PLACEHOLDERS_AVAILABLE announce', () => {
381
381
  ]);
382
382
  });
383
383
 
384
+ it('announces what this build can report, on the same terms', () => {
385
+ const { registry } = load();
386
+
387
+ registry.registerPlaceholder('header');
388
+ jest.advanceTimersByTime(100);
389
+
390
+ // Literal rather than the constant, like the action list above: the editor
391
+ // matches by name and drops a name it does not know, so a rename here has
392
+ // to be a visible change on both sides rather than a silent narrowing.
393
+ // Without this field the editor offers no tracking panel at all, which is
394
+ // the correct reading of every renderer built before it existed.
395
+ expect(frames()[0].signalCapabilities).toEqual(['section-seen']);
396
+ });
397
+
384
398
  it('keeps the action capability on the designer re-announce too', () => {
385
399
  const { registry, register } = load();
386
400
 
@@ -407,6 +421,14 @@ describe('PLACEHOLDERS_AVAILABLE announce', () => {
407
421
  ['add-to-cart-after-add', 'localized-video'],
408
422
  ['add-to-cart-after-add', 'localized-video']
409
423
  ]);
424
+
425
+ // The reporting list rides every frame for the same reason: the editor
426
+ // replaces what it holds, so a later frame without it would take the
427
+ // merchant's tracking panel away halfway through a session.
428
+ expect(frames().map((frame) => frame.signalCapabilities)).toEqual([
429
+ ['section-seen'],
430
+ ['section-seen']
431
+ ]);
410
432
  });
411
433
 
412
434
  it('sends the whole catalog every time, so a re-announce replaces', () => {
@@ -5,6 +5,10 @@ import {
5
5
  ACTION_CAPABILITIES,
6
6
  type ActionCapability
7
7
  } from './action-capabilities';
8
+ import {
9
+ SIGNAL_CAPABILITIES,
10
+ type SignalCapability
11
+ } from './signal-capabilities';
8
12
  import {
9
13
  STATE_PIN_CAPABILITIES,
10
14
  type StatePinCapability
@@ -107,6 +111,14 @@ interface PlaceholdersAvailablePayload {
107
111
  * out before the designer flag arrived (see `handleEditorMessage`).
108
112
  */
109
113
  actionCapabilities?: readonly ActionCapability[];
114
+ /**
115
+ * Which moments this build can report.
116
+ *
117
+ * Same terms as `actionCapabilities` above and on every frame for the same
118
+ * reason: the editor replaces what it holds with each frame, so a frame
119
+ * without the field would put it back to reporting nothing.
120
+ */
121
+ signalCapabilities?: readonly SignalCapability[];
110
122
  }
111
123
 
112
124
  const isFramed = (): boolean =>
@@ -147,7 +159,11 @@ const flush = () => {
147
159
  // withhold. Gated, it would be lost for the life of the document on a slow
148
160
  // handshake: the designer re-announce only fires for a build that
149
161
  // registers a custom catalog, and most brands register none.
150
- actionCapabilities: ACTION_CAPABILITIES
162
+ actionCapabilities: ACTION_CAPABILITIES,
163
+ // Outside the designer gate for the same reason, and for one more: the
164
+ // panel it gates is the merchant's, so a slow handshake must not be the
165
+ // difference between a section being trackable and not.
166
+ signalCapabilities: SIGNAL_CAPABILITIES
151
167
  };
152
168
 
153
169
  // Omitted entirely when nothing is registered: a build with no brand pages
@@ -0,0 +1,39 @@
1
+ /**
2
+ * What this build can REPORT, announced to the editor (ZERO-5165).
3
+ *
4
+ * The sibling of `action-capabilities.ts`, for the other half of the same
5
+ * problem. That one says what a stored action will do; this one says which
6
+ * moments the renderer is able to observe and emit at all.
7
+ *
8
+ * The editor is one deployment serving channels whose storefronts pin their
9
+ * own pz-theme version, so it cannot assume that what the repo can do is what
10
+ * the storefront in front of it can do. Without this, a tracking panel would
11
+ * be authorable on every brand and dead on every brand below the line: the
12
+ * merchant types a name, saves, and nothing ever happens, with no error
13
+ * anywhere. That is the failure this ecosystem keeps producing, and a name
14
+ * list is what stops it.
15
+ *
16
+ * - `section-seen` the renderer observes composed sections and emits
17
+ * `section.seen` when one crosses the middle of the
18
+ * viewport and stays there. The editor reads it to decide
19
+ * whether to offer the section tracking panel at all.
20
+ *
21
+ * Names rather than a version number, for the reason the action capabilities
22
+ * are: the editor must not have to know which release added what. A build that
23
+ * does not send the list is read as reporting nothing, which is exactly what
24
+ * every renderer shipped before this one did.
25
+ *
26
+ * The editor matches these strings exactly and silently drops one it does not
27
+ * know, so a rename here narrows the editor back to its baseline instead of
28
+ * failing anywhere. Change one only together with `StorefrontSignalCapability`
29
+ * in pz-dynamic-widget, which has a parity test against this file.
30
+ *
31
+ * Its own module rather than a constant beside the hook that implements it:
32
+ * the placeholder registry announces this, and it must not have to pull a
33
+ * client component in to say one list of strings.
34
+ */
35
+ export type SignalCapability = 'section-seen';
36
+
37
+ export const SIGNAL_CAPABILITIES: readonly SignalCapability[] = [
38
+ 'section-seen'
39
+ ];