feat: card fade-in delay and video mute toggle #41
@@ -52,22 +52,22 @@ jobs:
|
||||
REASON="Fix branches must target 'dev', not '${BASE}'"
|
||||
fi
|
||||
;;
|
||||
patch/*)
|
||||
if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ]; then
|
||||
ALLOWED=false
|
||||
REASON="Patch branches must target 'dev' or 'rc', not '${BASE}'"
|
||||
fi
|
||||
;;
|
||||
hotfix/*)
|
||||
if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then
|
||||
ALLOWED=false
|
||||
REASON="Hotfix branches can only target 'dev' or 'main', not '${BASE}'"
|
||||
fi
|
||||
;;
|
||||
alpha/*|beta/*)
|
||||
if [ "$BASE" != "dev" ]; then
|
||||
ALLOWED=false
|
||||
REASON="Pre-release branches must target 'dev', not '${BASE}'"
|
||||
fi
|
||||
;;
|
||||
rc/*)
|
||||
rc)
|
||||
if [ "$BASE" != "main" ]; then
|
||||
ALLOWED=false
|
||||
REASON="Release candidate branches must target 'main', not '${BASE}'"
|
||||
REASON="RC branch can only merge into 'main', not '${BASE}'"
|
||||
fi
|
||||
;;
|
||||
dev)
|
||||
@@ -183,6 +183,28 @@ jobs:
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: Check changelog has unreleased entry
|
||||
run: |
|
||||
if [ ! -f "CHANGELOG.md" ]; then
|
||||
echo "::warning::No CHANGELOG.md found"
|
||||
exit 0
|
||||
fi
|
||||
# Check for content under [Unreleased] section
|
||||
if ! grep -q "## \[Unreleased\]" CHANGELOG.md; then
|
||||
echo "::error::CHANGELOG.md missing [Unreleased] section"
|
||||
exit 1
|
||||
fi
|
||||
# Check there's at least one entry (Added/Changed/Fixed/Removed) under Unreleased
|
||||
UNRELEASED_CONTENT=$(sed -n '/## \[Unreleased\]/,/## \[/p' CHANGELOG.md | grep -cE '^\s*-\s' || true)
|
||||
if [ "$UNRELEASED_CONTENT" -eq 0 ]; then
|
||||
echo "::error::CHANGELOG.md [Unreleased] section has no entries. Add a changelog entry describing your changes."
|
||||
echo "## Changelog Check: Failed" >> $GITHUB_STEP_SUMMARY
|
||||
echo "The \`[Unreleased]\` section in CHANGELOG.md has no entries." >> $GITHUB_STEP_SUMMARY
|
||||
echo "Add a line like \`- Description of your change\` under a heading (\`### Added\`, \`### Changed\`, \`### Fixed\`, etc.)" >> $GITHUB_STEP_SUMMARY
|
||||
exit 1
|
||||
fi
|
||||
echo "Changelog: ${UNRELEASED_CONTENT} entry/entries in [Unreleased]"
|
||||
|
||||
- name: Verify package source
|
||||
run: |
|
||||
SOURCE_DIR="src"
|
||||
|
||||
@@ -7,6 +7,23 @@ Version format: `XX.YY.ZZ` (zero-padded semver).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Planned
|
||||
- Configurable card fade-in delay (#39)
|
||||
- Video audio mute/unmute option (#40)
|
||||
|
||||
## [01.01.00] - 2026-05-30
|
||||
|
||||
### Fixed
|
||||
- WebAsset registration: added `#style`/`#script` suffixes to preset dependencies (was causing `UnsatisfiedDependencyException`)
|
||||
- Asset URI resolution: use `extension/filename` pattern instead of `extension/folder/filename` (Joomla auto-inserts `css/`/`js/` folders)
|
||||
- iframe video cover: split CSS into `<video>` (`object-fit: cover`) and `<iframe>` (oversize + centre-crop) rules since `object-fit` doesn't apply to iframes
|
||||
- Card link styling: exclude `.btn` elements from `color: inherit` so buttons retain their own styles
|
||||
|
||||
### Added
|
||||
- Module title renders inside the hero card as `<h2>`, respecting Joomla's Show Title toggle
|
||||
- IntersectionObserver pauses/resumes videos when the hero scrolls out of/into the viewport (YouTube, Vimeo, and native `<video>`)
|
||||
- YouTube embeds include `enablejsapi=1` for postMessage playback control
|
||||
|
||||
### Changed
|
||||
- Migrated all workflow and template paths from `.github/` to `.mokogitea/`
|
||||
- Template source paths updated
|
||||
|
||||
@@ -36,6 +36,14 @@ MOD_MOKOJOOMHERO_SLIDE_INTERVAL_DESC="Time between slides in milliseconds (e.g.
|
||||
MOD_MOKOJOOMHERO_VIDEO_FILE_LABEL="Video URL"
|
||||
MOD_MOKOJOOMHERO_VIDEO_FILE_DESC="Local file path, YouTube URL, or Vimeo URL. Any format works — the module auto-detects the source."
|
||||
|
||||
; Card delay
|
||||
MOD_MOKOJOOMHERO_CARD_DELAY_LABEL="Card Fade-in Delay (ms)"
|
||||
MOD_MOKOJOOMHERO_CARD_DELAY_DESC="Delay in milliseconds before the content card fades in. Set to 0 for no delay."
|
||||
|
||||
; Mute toggle
|
||||
MOD_MOKOJOOMHERO_MUTE_TOGGLE_LABEL="Show Mute Toggle"
|
||||
MOD_MOKOJOOMHERO_MUTE_TOGGLE_DESC="Show a mute/unmute button on the hero video. Videos always start muted (required for autoplay)."
|
||||
|
||||
; Hero height
|
||||
MOD_MOKOJOOMHERO_HERO_HEIGHT_LABEL="Hero Height"
|
||||
MOD_MOKOJOOMHERO_HERO_HEIGHT_DESC="Height of the hero section. Use px for fixed pixels (e.g. 400px) or vh for viewport height (e.g. 60vh for 60%% of screen)."
|
||||
|
||||
@@ -41,6 +41,14 @@ MOD_MOKOJOOMHERO_HERO_HEIGHT_LABEL="Hero Height"
|
||||
MOD_MOKOJOOMHERO_HERO_HEIGHT_DESC="Height of the hero section. Use px for fixed pixels (e.g. 400px) or vh for viewport height (e.g. 60vh for 60% of screen)."
|
||||
MOD_MOKOJOOMHERO_HERO_HEIGHT_HINT="e.g. 60vh or 400px"
|
||||
|
||||
; Card delay
|
||||
MOD_MOKOJOOMHERO_CARD_DELAY_LABEL="Card Fade-in Delay (ms)"
|
||||
MOD_MOKOJOOMHERO_CARD_DELAY_DESC="Delay in milliseconds before the content card fades in. Set to 0 for no delay."
|
||||
|
||||
; Mute toggle
|
||||
MOD_MOKOJOOMHERO_MUTE_TOGGLE_LABEL="Show Mute Toggle"
|
||||
MOD_MOKOJOOMHERO_MUTE_TOGGLE_DESC="Show a mute/unmute button on the hero video. Videos always start muted (required for autoplay)."
|
||||
|
||||
; Overlay fieldset
|
||||
MOD_MOKOJOOMHERO_FIELDSET_OVERLAY="Overlay & Text"
|
||||
MOD_MOKOJOOMHERO_OVERLAY_COLOR_LABEL="Overlay Color"
|
||||
|
||||
@@ -126,6 +126,45 @@ iframe.mokojoomhero__video {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Card fade-in delay
|
||||
============================================================ */
|
||||
.mokojoomhero__card[data-card-delay] {
|
||||
opacity: 0;
|
||||
animation: mokojoomhero-fadein 0.6s ease forwards;
|
||||
}
|
||||
|
||||
@keyframes mokojoomhero-fadein {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Mute toggle
|
||||
============================================================ */
|
||||
.mokojoomhero__mute-toggle {
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
right: 1rem;
|
||||
z-index: 2;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.mokojoomhero__mute-toggle:hover {
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Responsive
|
||||
============================================================ */
|
||||
|
||||
@@ -85,4 +85,34 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
document.querySelectorAll('.mokojoomhero').forEach(function (hero) {
|
||||
observer.observe(hero);
|
||||
});
|
||||
|
||||
// ── Mute/unmute toggle ──
|
||||
document.querySelectorAll('.mokojoomhero__mute-toggle').forEach(function (btn) {
|
||||
var hero = btn.closest('.mokojoomhero');
|
||||
var video = hero.querySelector('video.mokojoomhero__video');
|
||||
var iframe = hero.querySelector('iframe.mokojoomhero__video');
|
||||
var icon = btn.querySelector('.mokojoomhero__mute-icon');
|
||||
|
||||
btn.addEventListener('click', function () {
|
||||
var muted = btn.getAttribute('data-muted') === 'true';
|
||||
|
||||
if (video) {
|
||||
video.muted = !muted;
|
||||
}
|
||||
if (iframe) {
|
||||
var src = iframe.src || '';
|
||||
if (src.indexOf('youtube') !== -1) {
|
||||
var func = muted ? 'unMute' : 'mute';
|
||||
iframe.contentWindow.postMessage('{"event":"command","func":"' + func + '","args":""}', '*');
|
||||
} else if (src.indexOf('vimeo') !== -1) {
|
||||
var vol = muted ? 1 : 0;
|
||||
iframe.contentWindow.postMessage('{"method":"setVolume","value":' + vol + '}', '*');
|
||||
}
|
||||
}
|
||||
|
||||
btn.setAttribute('data-muted', muted ? 'false' : 'true');
|
||||
btn.setAttribute('aria-label', muted ? 'Mute video' : 'Unmute video');
|
||||
icon.textContent = muted ? '\u{1F50A}' : '\u{1F507}';
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,6 +35,8 @@ $textAlign = $params->get('textAlign', 'center');
|
||||
$textColor = $params->get('textColor', '#ffffff');
|
||||
$heroContent = $params->get('heroContent', '');
|
||||
$showCard = (bool) $params->get('showCard', 1);
|
||||
$cardDelay = (int) $params->get('cardDelay', 0);
|
||||
$showMuteToggle = (bool) $params->get('showMuteToggle', 0);
|
||||
|
||||
// Collect hero images
|
||||
$heroImages = [];
|
||||
|
||||
@@ -104,6 +104,18 @@
|
||||
default="60vh"
|
||||
filter="string"
|
||||
/>
|
||||
<field
|
||||
name="showMuteToggle"
|
||||
type="radio"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
label="MOD_MOKOJOOMHERO_MUTE_TOGGLE_LABEL"
|
||||
description="MOD_MOKOJOOMHERO_MUTE_TOGGLE_DESC"
|
||||
default="0"
|
||||
showon="heroMode:video"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
<fieldset name="content"
|
||||
label="MOD_MOKOJOOMHERO_FIELDSET_CONTENT"
|
||||
@@ -128,6 +140,17 @@
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
<field
|
||||
name="cardDelay"
|
||||
type="number"
|
||||
label="MOD_MOKOJOOMHERO_CARD_DELAY_LABEL"
|
||||
description="MOD_MOKOJOOMHERO_CARD_DELAY_DESC"
|
||||
default="0"
|
||||
min="0"
|
||||
max="5000"
|
||||
step="250"
|
||||
showon="showCard:1"
|
||||
/>
|
||||
</fieldset>
|
||||
<fieldset name="advanced"
|
||||
label="MOD_MOKOJOOMHERO_FIELDSET_OVERLAY"
|
||||
|
||||
@@ -25,6 +25,8 @@ use Joomla\CMS\Language\Text;
|
||||
/** @var string $textColor */
|
||||
/** @var string $heroContent */
|
||||
/** @var bool $showCard */
|
||||
/** @var int $cardDelay */
|
||||
/** @var bool $showMuteToggle */
|
||||
/** @var string $content */
|
||||
|
||||
$moduleId = 'mod-mokojoomhero-' . $module->id;
|
||||
@@ -61,12 +63,18 @@ $heightAttr = htmlspecialchars($heroHeight, ENT_QUOTES, 'UTF-8');
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($heroMode === 'video' && $showMuteToggle) : ?>
|
||||
<button class="mokojoomhero__mute-toggle" type="button" aria-label="Unmute video" data-muted="true">
|
||||
<span class="mokojoomhero__mute-icon" aria-hidden="true">🔇</span>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php // Overlay + content ?>
|
||||
<div class="mokojoomhero__overlay" style="background-color: <?php echo $rgba; ?>;">
|
||||
<div class="mokojoomhero__content" style="text-align: <?php echo htmlspecialchars($textAlign, ENT_QUOTES, 'UTF-8'); ?>; color: <?php echo htmlspecialchars($textColor, ENT_QUOTES, 'UTF-8'); ?>;">
|
||||
<?php if ($heroContent || $module->showtitle) : ?>
|
||||
<?php if ($showCard) : ?>
|
||||
<div class="mokojoomhero__card">
|
||||
<div class="mokojoomhero__card"<?php if ($cardDelay) : ?> style="animation-delay: <?php echo $cardDelay; ?>ms;" data-card-delay="<?php echo $cardDelay; ?>"<?php endif; ?>>
|
||||
<?php if ($module->showtitle) : ?>
|
||||
<h2 class="mokojoomhero__title"><?php echo htmlspecialchars($module->title, ENT_QUOTES, 'UTF-8'); ?></h2>
|
||||
<?php endif; ?>
|
||||
|
||||
+82
-6
@@ -1,27 +1,103 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
VERSION: 01.00.20
|
||||
VERSION: 01.01.00
|
||||
-->
|
||||
|
||||
<updates>
|
||||
<update>
|
||||
<name>Module - MokoJoomHero</name>
|
||||
<description>Module - MokoJoomHero development build.</description>
|
||||
<description>Module - MokoJoomHero dev build.</description>
|
||||
<element>mod_mokojoomhero</element>
|
||||
<type>module</type>
|
||||
<client>site</client>
|
||||
<version>01.00.18-dev</version>
|
||||
<version>01.01.00-dev</version>
|
||||
<creationDate>2026-05-30</creationDate>
|
||||
<infourl title='Module - MokoJoomHero'>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/tag/development</infourl>
|
||||
<infourl title="Module - MokoJoomHero">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/tag/development</infourl>
|
||||
<downloads>
|
||||
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/download/development/mod_mokojoomhero-01.00.18-dev.zip</downloadurl>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/download/development/mod_mokojoomhero-01.01.00-dev.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>a629c54e31bcb6761d709a1b3c384c788172694365922dfad1b737fe502cf6c2</sha256>
|
||||
<sha256>f07dbfd79e507c3fb250cc34618940ef226bf58053b96b8d893cd9d33237717e</sha256>
|
||||
<tags><tag>dev</tag></tags>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*"/>
|
||||
</update>
|
||||
<update>
|
||||
<name>Module - MokoJoomHero</name>
|
||||
<description>Module - MokoJoomHero alpha build.</description>
|
||||
<element>mod_mokojoomhero</element>
|
||||
<type>module</type>
|
||||
<client>site</client>
|
||||
<version>01.01.00-alpha</version>
|
||||
<creationDate>2026-05-30</creationDate>
|
||||
<infourl title="Module - MokoJoomHero">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/tag/alpha</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/download/alpha/mod_mokojoomhero-01.01.00-alpha.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>f07dbfd79e507c3fb250cc34618940ef226bf58053b96b8d893cd9d33237717e</sha256>
|
||||
<tags><tag>alpha</tag></tags>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*"/>
|
||||
</update>
|
||||
<update>
|
||||
<name>Module - MokoJoomHero</name>
|
||||
<description>Module - MokoJoomHero beta build.</description>
|
||||
<element>mod_mokojoomhero</element>
|
||||
<type>module</type>
|
||||
<client>site</client>
|
||||
<version>01.01.00-beta</version>
|
||||
<creationDate>2026-05-30</creationDate>
|
||||
<infourl title="Module - MokoJoomHero">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/tag/beta</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/download/beta/mod_mokojoomhero-01.01.00-beta.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>f07dbfd79e507c3fb250cc34618940ef226bf58053b96b8d893cd9d33237717e</sha256>
|
||||
<tags><tag>beta</tag></tags>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*"/>
|
||||
</update>
|
||||
<update>
|
||||
<name>Module - MokoJoomHero</name>
|
||||
<description>Module - MokoJoomHero rc build.</description>
|
||||
<element>mod_mokojoomhero</element>
|
||||
<type>module</type>
|
||||
<client>site</client>
|
||||
<version>01.01.00-rc</version>
|
||||
<creationDate>2026-05-30</creationDate>
|
||||
<infourl title="Module - MokoJoomHero">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/tag/release-candidate</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/download/release-candidate/mod_mokojoomhero-01.01.00-rc.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>f07dbfd79e507c3fb250cc34618940ef226bf58053b96b8d893cd9d33237717e</sha256>
|
||||
<tags><tag>rc</tag></tags>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*"/>
|
||||
</update>
|
||||
<update>
|
||||
<name>Module - MokoJoomHero</name>
|
||||
<description>Module - MokoJoomHero stable build.</description>
|
||||
<element>mod_mokojoomhero</element>
|
||||
<type>module</type>
|
||||
<client>site</client>
|
||||
<version>01.01.00</version>
|
||||
<creationDate>2026-05-30</creationDate>
|
||||
<infourl title='Module - MokoJoomHero'>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/tag/stable</infourl>
|
||||
<downloads>
|
||||
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/releases/download/stable/mod_mokojoomhero-01.01.00.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>f07dbfd79e507c3fb250cc34618940ef226bf58053b96b8d893cd9d33237717e</sha256>
|
||||
<tags><tag>stable</tag></tags>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||
</update>
|
||||
</updates>
|
||||
|
||||
Reference in New Issue
Block a user