feat: VivesPOS landing on Winter CMS 1.2 — theme + plugin + Dockerfile
Some checks are pending
Module sub-split / Sub-split (push) Waiting to run
Some checks are pending
Module sub-split / Sub-split (push) Waiting to run
- Base: wintercms/winter branch 1.2 (full framework) - Theme vivespos: Canvas 7 + Bootstrap 5 CDN, custom CSS - Layout: deferred GTM/GA4 tracking, JSON-LD SoftwareApplication - Partials: hero (offline-first), features, modes (offline/nube toggle), screenshots, pricing (3 planes), comparison, FAQ, CTA - Plugin VivesPOS.Site with ContactForm - Dockerfile: PHP 8.2 Apache, port 80, healthcheck - Added winter/wn-pages, blog, sitemap, seo plugins - Active theme set to vivespos
This commit is contained in:
206
modules/system/assets/js/snowboard/extras/Transition.js
Normal file
206
modules/system/assets/js/snowboard/extras/Transition.js
Normal file
@@ -0,0 +1,206 @@
|
||||
import PluginBase from '../abstracts/PluginBase';
|
||||
|
||||
/**
|
||||
* Provides transition support for elements.
|
||||
*
|
||||
* Transition allows CSS transitions to be controlled and callbacks to be run once completed. It works similar to Vue
|
||||
* transitions with 3 stages of transition, and classes assigned to the element with the transition name suffixed with
|
||||
* the stage of transition:
|
||||
*
|
||||
* - `in`: A class assigned to the element for the first frame of the transition, removed afterwards. This should be
|
||||
* used to define the initial state of the transition.
|
||||
* - `active`: A class assigned to the element for the duration of the transition. This should be used to define the
|
||||
* transition itself.
|
||||
* - `out`: A class assigned to the element after the first frame of the transition and kept to the end of the
|
||||
* transition. This should define the end state of the transition.
|
||||
*
|
||||
* Usage:
|
||||
* Snowboard.transition(document.element, 'transition', () => {
|
||||
* console.log('Remove element after 7 seconds');
|
||||
* this.remove();
|
||||
* }, '7s');
|
||||
*
|
||||
* @copyright 2021 Winter.
|
||||
* @author Ben Thomson <git@alfreido.com>
|
||||
*/
|
||||
export default class Transition extends PluginBase {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param {HTMLElement} element The element to transition
|
||||
* @param {string} transition The name of the transition, this prefixes the stages of transition.
|
||||
* @param {Function} callback An optional callback to call when the transition ends.
|
||||
* @param {Number} duration An optional override on the transition duration. Must be specified as 's' (secs) or 'ms' (msecs).
|
||||
* @param {Boolean} trailTo If true, the "out" class will remain after the end of the transition.
|
||||
*/
|
||||
construct(element, transition, callback, duration, trailTo) {
|
||||
if (element instanceof HTMLElement === false) {
|
||||
throw new Error('A HTMLElement must be provided for transitioning');
|
||||
}
|
||||
this.element = element;
|
||||
|
||||
if (typeof transition !== 'string') {
|
||||
throw new Error('Transition name must be specified as a string');
|
||||
}
|
||||
this.transition = transition;
|
||||
|
||||
if (callback && typeof callback !== 'function') {
|
||||
throw new Error('Callback must be a valid function');
|
||||
}
|
||||
this.callback = callback;
|
||||
|
||||
if (duration) {
|
||||
this.duration = this.parseDuration(duration);
|
||||
} else {
|
||||
this.duration = null;
|
||||
}
|
||||
|
||||
this.trailTo = (trailTo === true);
|
||||
|
||||
this.doTransition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps event classes to the given transition state.
|
||||
*
|
||||
* @param {...any} args
|
||||
* @returns {Array}
|
||||
*/
|
||||
eventClasses(...args) {
|
||||
const eventClasses = {
|
||||
in: `${this.transition}-in`,
|
||||
active: `${this.transition}-active`,
|
||||
out: `${this.transition}-out`,
|
||||
};
|
||||
|
||||
if (args.length === 0) {
|
||||
return Object.values(eventClasses);
|
||||
}
|
||||
|
||||
const returnClasses = [];
|
||||
Object.entries(eventClasses).forEach((entry) => {
|
||||
const [key, value] = entry;
|
||||
|
||||
if (args.indexOf(key) !== -1) {
|
||||
returnClasses.push(value);
|
||||
}
|
||||
});
|
||||
|
||||
return returnClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the transition.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
doTransition() {
|
||||
// Add duration override
|
||||
if (this.duration !== null) {
|
||||
this.element.style.transitionDuration = this.duration;
|
||||
}
|
||||
|
||||
this.resetClasses();
|
||||
|
||||
// Start transition - show "in" and "active" classes
|
||||
this.eventClasses('in', 'active').forEach((eventClass) => {
|
||||
this.element.classList.add(eventClass);
|
||||
});
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
// Ensure a transition exists
|
||||
if (window.getComputedStyle(this.element)['transition-duration'] !== '0s') {
|
||||
// Listen for the transition to end
|
||||
this.element.addEventListener('transitionend', () => this.onTransitionEnd(), {
|
||||
once: true,
|
||||
});
|
||||
window.requestAnimationFrame(() => {
|
||||
this.element.classList.remove(this.eventClasses('in')[0]);
|
||||
this.element.classList.add(this.eventClasses('out')[0]);
|
||||
});
|
||||
} else {
|
||||
this.resetClasses();
|
||||
|
||||
if (this.callback) {
|
||||
this.callback.apply(this.element);
|
||||
}
|
||||
|
||||
this.destruct();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function when the transition ends.
|
||||
*
|
||||
* When a transition ends, the instance of the transition is automatically destructed.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
onTransitionEnd() {
|
||||
this.eventClasses('active', (!this.trailTo) ? 'out' : '').forEach((eventClass) => {
|
||||
this.element.classList.remove(eventClass);
|
||||
});
|
||||
|
||||
if (this.callback) {
|
||||
this.callback.apply(this.element);
|
||||
}
|
||||
|
||||
// Remove duration override
|
||||
if (this.duration !== null) {
|
||||
this.element.style.transitionDuration = null;
|
||||
}
|
||||
|
||||
this.destruct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a transition.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
cancel() {
|
||||
this.element.removeEventListener('transitionend', () => this.onTransitionEnd, {
|
||||
once: true,
|
||||
});
|
||||
|
||||
this.resetClasses();
|
||||
|
||||
// Remove duration override
|
||||
if (this.duration !== null) {
|
||||
this.element.style.transitionDuration = null;
|
||||
}
|
||||
|
||||
// Call destructor
|
||||
this.destruct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the classes, removing any transition classes.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
resetClasses() {
|
||||
this.eventClasses().forEach((eventClass) => {
|
||||
this.element.classList.remove(eventClass);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a given duration and converts it to a "ms" value.
|
||||
*
|
||||
* @param {String} duration
|
||||
* @returns {String}
|
||||
*/
|
||||
parseDuration(duration) {
|
||||
const parsed = /^([0-9]+(\.[0-9]+)?)(m?s)?$/.exec(duration);
|
||||
const amount = Number(parsed[1]);
|
||||
const unit = (parsed[3] === 's')
|
||||
? 'sec'
|
||||
: 'msec';
|
||||
|
||||
return (unit === 'sec')
|
||||
? `${amount * 1000}ms`
|
||||
: `${Math.floor(amount)}ms`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user