@akinon/pz-theme 2.0.112-rc.0 → 2.0.113-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 +15 -35
- package/package.json +4 -4
- package/src/blocks/__tests__/video-block.test.tsx +45 -0
- package/src/blocks/video-block.tsx +38 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,40 +1,20 @@
|
|
|
1
1
|
# @akinon/pz-theme
|
|
2
2
|
|
|
3
|
-
## 2.0.
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- Updated dependencies [
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
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 [1595d45]
|
|
35
|
-
- Updated dependencies [dca1281]
|
|
36
|
-
- @akinon/next@2.0.112-rc.0
|
|
37
|
-
- @akinon/theme-contract@2.0.112-rc.0
|
|
3
|
+
## 2.0.113-beta.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [cbbbfd757]
|
|
8
|
+
- @akinon/next@2.0.113-beta.0
|
|
9
|
+
- @akinon/theme-contract@2.0.113-beta.0
|
|
10
|
+
|
|
11
|
+
## 2.0.112
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 4abc0fe: ZERO-5086: Read the video source type through the breakpoint and give a tablet the mobile video
|
|
16
|
+
- @akinon/next@2.0.112
|
|
17
|
+
- @akinon/theme-contract@2.0.112
|
|
38
18
|
|
|
39
19
|
## 2.0.111
|
|
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.
|
|
4
|
+
"version": "2.0.113-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.
|
|
11
|
+
"@akinon/next": "2.0.113-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.
|
|
16
|
+
"@akinon/theme-contract": "2.0.113-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.
|
|
24
|
+
"@akinon/next": "2.0.113-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",
|
|
@@ -316,6 +316,17 @@ describe('VideoBlock', () => {
|
|
|
316
316
|
expect(container.querySelector('video')).toHaveAttribute('src', url);
|
|
317
317
|
});
|
|
318
318
|
|
|
319
|
+
it('plays an extensionless URL when the editor said so per breakpoint', () => {
|
|
320
|
+
// What the editor ACTUALLY writes for that dropdown: a property stored
|
|
321
|
+
// per breakpoint, never a bare string. Compared raw, the escape hatch
|
|
322
|
+
// never fired for a single composition authored in the editor.
|
|
323
|
+
const url = 'https://cdn.example.com/asset/9f2a';
|
|
324
|
+
const { container } = renderBlock(url, {
|
|
325
|
+
sourceType: { desktop: 'file' }
|
|
326
|
+
});
|
|
327
|
+
expect(container.querySelector('video')).toHaveAttribute('src', url);
|
|
328
|
+
});
|
|
329
|
+
|
|
319
330
|
it('refuses the same URL when they have not', () => {
|
|
320
331
|
renderBlock('https://cdn.example.com/asset/9f2a');
|
|
321
332
|
expect(screen.getByText('Invalid video URL')).toBeInTheDocument();
|
|
@@ -522,6 +533,40 @@ describe('VideoBlock', () => {
|
|
|
522
533
|
).toBe('https://cdn.example.com/mobile.mp4');
|
|
523
534
|
});
|
|
524
535
|
|
|
536
|
+
it('plays the mobile file on a tablet too, the way the CSS already does', () => {
|
|
537
|
+
// The mobile media query is max-width: 1023px, so at 800px every style
|
|
538
|
+
// around this player is already the mobile one. Reading the source with
|
|
539
|
+
// `=== 'mobile'` left the tablet on the landscape clip inside a layout
|
|
540
|
+
// that had gone vertical.
|
|
541
|
+
const { container } = renderAt(
|
|
542
|
+
'https://cdn.example.com/desktop.mp4',
|
|
543
|
+
{
|
|
544
|
+
useDifferentMobileVideo: true,
|
|
545
|
+
mobileUrl: 'https://cdn.example.com/mobile.mp4'
|
|
546
|
+
},
|
|
547
|
+
'tablet'
|
|
548
|
+
);
|
|
549
|
+
expect((container.querySelector('video') as HTMLVideoElement).src).toBe(
|
|
550
|
+
'https://cdn.example.com/mobile.mp4'
|
|
551
|
+
);
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
it('takes the mobile poster on a tablet for the same reason', () => {
|
|
555
|
+
const { container } = renderAt(
|
|
556
|
+
'https://cdn.example.com/desktop.mp4',
|
|
557
|
+
{
|
|
558
|
+
useDifferentMobileVideo: true,
|
|
559
|
+
mobilePoster: 'https://cdn.example.com/mobile.jpg',
|
|
560
|
+
poster: 'https://cdn.example.com/desktop.jpg'
|
|
561
|
+
},
|
|
562
|
+
'tablet'
|
|
563
|
+
);
|
|
564
|
+
expect(container.querySelector('video')).toHaveAttribute(
|
|
565
|
+
'poster',
|
|
566
|
+
'https://cdn.example.com/mobile.jpg'
|
|
567
|
+
);
|
|
568
|
+
});
|
|
569
|
+
|
|
525
570
|
it('still plays the desktop file on desktop even when a mobile override is set', () => {
|
|
526
571
|
const { container } = renderAt(
|
|
527
572
|
'https://cdn.example.com/desktop.mp4',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import React, { useRef, useState } from 'react';
|
|
4
|
-
import { getResponsiveValue } from '../utils';
|
|
4
|
+
import { getResponsiveValue, isNarrowBreakpoint } from '../utils';
|
|
5
5
|
import { BlockRendererProps } from './block-renderer-registry';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -194,7 +194,25 @@ const VideoBlock = ({
|
|
|
194
194
|
const desktopUrl = block.value as string;
|
|
195
195
|
const properties = (block.properties || {}) as VideoProperties;
|
|
196
196
|
|
|
197
|
-
|
|
197
|
+
/**
|
|
198
|
+
* "Narrower than desktop", not "is the phone".
|
|
199
|
+
*
|
|
200
|
+
* `=== 'mobile'` left the 768-1023 band on the DESKTOP video while every
|
|
201
|
+
* style around it was the mobile one — `MOBILE_MEDIA_QUERY` is
|
|
202
|
+
* `max-width: 1023px`, so a tablet reads the mobile rule unless a tablet rule
|
|
203
|
+
* narrows it, but `breakpointForWidth(800)` answers `'tablet'` and this
|
|
204
|
+
* comparison said no. A merchant who uploaded a portrait clip for phones got
|
|
205
|
+
* the landscape one on an iPad, inside a layout that had already gone
|
|
206
|
+
* vertical.
|
|
207
|
+
*
|
|
208
|
+
* `isNarrowBreakpoint` is the predicate written for exactly these call sites
|
|
209
|
+
* — the ones that asked `=== 'mobile'` back when mobile was the only other
|
|
210
|
+
* value — and it is what `hover-showcase-section.tsx` and
|
|
211
|
+
* `order-tracking-lookup-section.tsx` already use for their own `isMobile`.
|
|
212
|
+
* This also moves the custom play/pause button to its mobile corner on a
|
|
213
|
+
* tablet, which is the same inheritance every other mobile treatment has.
|
|
214
|
+
*/
|
|
215
|
+
const isMobile = isNarrowBreakpoint(currentBreakpoint);
|
|
198
216
|
const useDifferentMobileVideo = !!getResponsiveValue(
|
|
199
217
|
properties.useDifferentMobileVideo,
|
|
200
218
|
currentBreakpoint,
|
|
@@ -211,7 +229,24 @@ const VideoBlock = ({
|
|
|
211
229
|
// `properties` handed over RAW, not resolved: `buildEmbedParams` reads
|
|
212
230
|
// `autoplay`/`loop`/`muted`/`controls` the same way the native `<video>`
|
|
213
231
|
// below deliberately still does — see the note there.
|
|
214
|
-
|
|
232
|
+
//
|
|
233
|
+
// `sourceType` is the one exception, and it is the same defect that note
|
|
234
|
+
// records for `controls` and `poster`: the editor stores `{ desktop: 'file' }`,
|
|
235
|
+
// so `properties?.sourceType === 'file'` inside `parseVideoSource` has been
|
|
236
|
+
// comparing an OBJECT to a string and the escape hatch has never once fired
|
|
237
|
+
// for anything authored in the editor. An uploaded clip whose address carries
|
|
238
|
+
// no extension — the ordinary shape of a signed CDN link — therefore had no
|
|
239
|
+
// remedy at all. `getResponsiveValue` passes a plain string straight through,
|
|
240
|
+
// so reading it here handles both shapes and repairs what is already
|
|
241
|
+
// published. Unlike autoplay/loop/muted, reading this one correctly can only
|
|
242
|
+
// turn a dead "Invalid video URL" into a playing video.
|
|
243
|
+
const sourceType = getResponsiveValue(
|
|
244
|
+
properties.sourceType,
|
|
245
|
+
currentBreakpoint,
|
|
246
|
+
'auto'
|
|
247
|
+
) as string;
|
|
248
|
+
|
|
249
|
+
const parsed = parseVideoSource(videoUrl, { ...properties, sourceType });
|
|
215
250
|
|
|
216
251
|
/**
|
|
217
252
|
* Read through the breakpoint, the way `aspect-ratio` already is.
|