Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .git-report-tmp.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { execSync } from 'node:child_process';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const dir = path.dirname(fileURLToPath(import.meta.url));

function run(cmd) {
console.log(`\n=== ${cmd} ===\n`);
try {
console.log(
execSync(cmd, { cwd: dir, encoding: 'utf8', maxBuffer: 50 * 1024 * 1024 })
);
} catch (e) {
if (e.stdout) console.log(e.stdout);
if (e.stderr) console.error(e.stderr);
process.exitCode = e.status ?? 1;
}
}

run('git log --oneline 4c87ba85..HEAD');
run('git diff 4c87ba85...HEAD --stat');
run('git diff HEAD --stat');
run('git ls-files --others --exclude-standard');
run(
"git diff 4c87ba85...HEAD -- gutenberg/ docs/ tests/ classes/ '*.php' '*.js' '*.scss' '*.md' ':!build/**'"
);
2 changes: 1 addition & 1 deletion build/gutenberg/blocks/item-template/view.asset.php

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion build/gutenberg/blocks/item-template/view.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/gutenberg/index.asset.php

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 30 additions & 30 deletions build/gutenberg/index.js

Large diffs are not rendered by default.

32 changes: 28 additions & 4 deletions docs/gallery-loop-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,11 @@ editor uses for the width of any block — *None* is the content width, then
*Wide width*, *Full width* and *Custom*, whose width is typed in the menu.

The carousel panel of the item template carries the rest: *Effect*, *Autoplay*
and its delay, *Repeat*, *Peek*, *Slides per step* (zero
moves a whole screen at a time, and a swipe comes to rest on the same frames an
arrow does), *Slide height* and *Blocks fill the slide*,
*Fade the edges*, *Slide width from content* and *Free scrolling*.
with its mode (slide by slide, or a marquee with Pro) and its delay, *Repeat*,
*Peek*, *Slides per step* (zero moves a whole screen at a time, and a swipe
comes to rest on the same frames an arrow does), *Slide height* and *Blocks
fill the slide*, *Fade the edges*, *Slide width from content* and *Free
scrolling*.

**Controls.** Filter, sort and pagination are server-rendered links and forms.
With JavaScript they swap the gallery in place; without it they work as ordinary
Expand Down Expand Up @@ -786,6 +787,17 @@ stated in `cqw` rather than in a percentage of the list — a carousel that
repeats is padded by half its width at each end, and a percentage of what that
leaves is nothing.

### Carousel marquee

Autoplay has two modes. Slide by slide holds each slide for the delay. A
marquee moves the carousel on without stopping, and is Pro's: the free editor
offers it as a disabled "Marquee (Pro)" option of the *Mode* select, and the
free plugin has no code that runs one. Choosing it keeps `extensions.marquee`
on the item template, an object whose settings belong to the extension, turns
*Repeat* on, and puts `vpf.itemTemplateMarqueeControls` (`null`, `{ attributes,
setAttributes }`) where the delay was. The page runs it through the autoplay
events below.

### Sitemap

`vpf_parse_sitemap_images_from_blocks` filters the images a post contributes.
Expand Down Expand Up @@ -962,6 +974,8 @@ template:
|---|---|
| `vp-carousel-go-to` | `detail.index` — scroll to that slide |
| `vp-carousel-autoplay` | `detail.playing` — `false` holds autoplay, `true` releases it |
| `vp-carousel-place` | `detail.position` — a place on the loop of a repeating carousel, scrolled to at once and kept off the seam the way a step is; written back as the scroll it came to rest at |
| `vp-carousel-autoplay-take` | the autoplay stops moving the carousel and hands each frame to the script that took it |

And announces itself on the same element, bubbling, so that a script outside
the module can run beside a carousel for as long as it runs:
Expand All @@ -970,6 +984,16 @@ the module can run beside a carousel for as long as it runs:
|---|---|
| `vp-carousel-start` | the module has started the carousel, once per start — a Load More starts it again |
| `vp-carousel-stop` | the module is about to let go of it |
| `vp-carousel-travel-start` | the module has started drawing a step of a repeating carousel, snapping held off (not bubbling) |
| `vp-carousel-travel-end` | the step has arrived or was stopped, and the snap is back (not bubbling) |
| `vp-carousel-autoplay-frame` | a frame of a taken autoplay: `detail.elapsed` in milliseconds, `detail.held` (the visitor's stop, a script's hold, off the screen, the keyboard), `detail.pointer` and `detail.keyboard` (not bubbling) |

A script that takes the autoplay moves the carousel itself and keeps the rest:
the pauses, the play and pause button, and a visitor who asked for less
motion, for whom no frame ever comes. It takes it again on every
`vp-carousel-start`, since a Load More starts a new autoplay. Snapping is
switched by the list's `--snap-type` custom property, which the carousel
library reads; a step saves it and puts it back when it arrives.

Holding autoplay is not the same as stopping it: the pause a pointer or a focus
already applies keeps working underneath, and releasing the hold does not
Expand Down
114 changes: 109 additions & 5 deletions gutenberg/blocks/item-template/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import ProNote from '../../components/pro-note';
/**
* Internal dependencies
*/
import { ProLine } from '../../components/pro-teaser';
import { getProLabel, ProLine } from '../../components/pro-teaser';
import getBlockGapValue from '../../utils/block-gap';
import { CONTROL_BLOCKS } from '../../utils/carousel-controls';
import { useLoopOrphanWarning } from '../../utils/loop-orphan-warning';
Expand Down Expand Up @@ -307,6 +307,38 @@ function getRepeatHelp(attributes) {
);
}

/**
* What the autoplay mode does, or why it cannot be a marquee.
*
* @param {boolean} repeatable - whether the carousel can run round.
*
* @return {string|Element} Help of the mode control.
*/
function getAutoplayModeHelp(repeatable) {
if (!isProPlugin) {
return (
<ProLine campaign="teaser_carousel_marquee">
{__(
'A marquee moves the carousel on without stopping, at a steady speed.',
'visual-portfolio'
)}
</ProLine>
);
}

if (!repeatable) {
return __(
'A marquee runs round, and this carousel cannot, so it moves slide by slide.',
'visual-portfolio'
);
}

return __(
'Slide by slide holds each slide for the delay. A marquee moves on without stopping, and the arrows, dots and dragging still work.',
'visual-portfolio'
);
}

// The same question the view module asks: where the browser packs masonry
// itself, the stylesheet does the layout and no script should run over it.
const HAS_NATIVE_MASONRY = !!window.CSS?.supports?.('display', 'grid-lanes');
Expand Down Expand Up @@ -880,6 +912,14 @@ export default function BlockEdit({
// greyed, the way the container control is.
const repeatable = canRepeat(attributes);

// A marquee is Pro's. The choice of it lives here, beside the delay it
// replaces, and Pro draws its settings under it. The page runs one only
// where the carousel can run round, and steps by the delay elsewhere - so
// does the editor.
const { marquee, ...extensionsWithoutMarquee } =
attributes.extensions || {};
const runsMarquee = !!marquee && repeatable && isProPlugin;

// An effect that lays the slides out itself leaves no edge for the next
// one to show at, so its peek is greyed the same way, and not drawn.
const peekable = effectPeeks(carouselEffect);
Expand Down Expand Up @@ -1380,6 +1420,7 @@ export default function BlockEdit({
carouselRepeat: false,
carouselAutoplay: false,
carouselAutoplayDelay: 5,
extensions: extensionsWithoutMarquee,
carouselPeek: 0,
carouselEdgeFade: false,
carouselSlideHeight: '',
Expand Down Expand Up @@ -1432,6 +1473,7 @@ export default function BlockEdit({
setAttributes({
carouselAutoplay: false,
carouselAutoplayDelay: 5,
extensions: extensionsWithoutMarquee,
})
}
>
Expand All @@ -1444,10 +1486,65 @@ export default function BlockEdit({
)}
checked={carouselAutoplay}
onChange={(value) =>
setAttributes({ carouselAutoplay: value })
setAttributes({
carouselAutoplay: value,
...(value
? {}
: { extensions: extensionsWithoutMarquee }),
})
}
/>
{carouselAutoplay && (
<SelectControl
label={__('Mode', 'visual-portfolio')}
help={getAutoplayModeHelp(repeatable)}
value={marquee ? 'marquee' : 'step'}
options={[
{
label: __(
'Slide by slide',
'visual-portfolio'
),
value: 'step',
},
{
label: isProPlugin
? __('Marquee', 'visual-portfolio')
: getProLabel(
__(
'Marquee',
'visual-portfolio'
)
),
value: 'marquee',
disabled: !isProPlugin || !repeatable,
},
]}
onChange={(value) =>
setAttributes(
'marquee' === value
? {
extensions: {
...extensionsWithoutMarquee,
marquee: {},
},
carouselRepeat: true,
}
: {
extensions:
extensionsWithoutMarquee,
}
)
}
/>
)}
{carouselAutoplay &&
runsMarquee &&
applyFilters('vpf.itemTemplateMarqueeControls', null, {
attributes,
setAttributes,
})}
{carouselAutoplay && !runsMarquee && (
<RangeControl
label={__('Delay, seconds', 'visual-portfolio')}
help={__(
Expand Down Expand Up @@ -1478,9 +1575,16 @@ export default function BlockEdit({
effect. */}
<ToggleControl
label={__('Repeat', 'visual-portfolio')}
help={getRepeatHelp(attributes)}
checked={carouselRepeat && repeatable}
disabled={!repeatable}
help={
runsMarquee
? __(
'A marquee runs round, so the carousel repeats.',
'visual-portfolio'
)
: getRepeatHelp(attributes)
}
checked={(carouselRepeat || runsMarquee) && repeatable}
disabled={!repeatable || runsMarquee}
onChange={(value) =>
setAttributes({ carouselRepeat: value })
}
Expand Down
Loading
Loading