Skip to content

Commit cdbcbec

Browse files
committed
feat: merge new features from 'feat' branch
1 parent cd40d88 commit cdbcbec

File tree

3 files changed

+175
-45
lines changed

3 files changed

+175
-45
lines changed

js-css-animations/animate.js

Lines changed: 113 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,62 @@ import {
1919

2020
import { setParentMaxMeasures } from './measurements.js';
2121

22+
/**
23+
* Contains the default value for each custom option.
24+
* Those values can be overwritten by the user by calling jsCssAnimations.config()
25+
* and passing new default values for all the animations.
26+
* @type {Object.<string,any>}
27+
*/
28+
const configurations = {
29+
default: Object.freeze({
30+
trigger: `.${CLASS_NAMES.trigger}`,
31+
targetSelector: undefined,
32+
staggerDelay: undefined,
33+
start: undefined,
34+
complete: undefined,
35+
keepSpace: false,
36+
dimensionsTransition: true,
37+
widthTransition: undefined,
38+
heightTransition: undefined,
39+
overflowHidden: true,
40+
}),
41+
};
42+
43+
/**
44+
* ProxyHandler passed to the 'CONFIG' object to ensure that
45+
* if an option is not customized by the user, the default value set
46+
* in 'configurations.default' will be returned instead.
47+
* @see {@link CONFIG}
48+
* @see {@link configurations}
49+
*/
50+
const configHandler = {
51+
/**
52+
* @param {Object.<string, Function>} configurations - Contains the configuration options
53+
* @param {string} option - Key name of the configuration option
54+
*/
55+
get(configurations, option) {
56+
if (!(option in configurations)) return configurations.default[option];
57+
else return configurations[option];
58+
},
59+
/**
60+
* @param {Object.<string, Function>} configurations - Contains the configuration options
61+
* @param {string} option - Key name of the configuration option
62+
* @param {any} value - Configuration option value
63+
*/
64+
set(configurations, option, value) {
65+
configurations[option] = value;
66+
return true;
67+
},
68+
};
69+
70+
/**
71+
* Object that handles configurations, either customized by the user
72+
* or default values defined in 'configurations.default' object
73+
* @type {Object.<string,any>}
74+
* @see {@link configurations}
75+
*/
76+
const CONFIG = new Proxy(configurations, configHandler);
77+
2278
/** Matches duration or delay CSS properties values */
2379
const DURATION_REGEX = Object.freeze(new RegExp(/(\d?\.\d+|\d+)(ms|s)?/));
2480

@@ -40,14 +96,14 @@ const CALLBACK_TRACKER = Object.freeze({
4096
* Initiates the tracker
4197
* @param {string} trigger - A CSS selector representing the element which triggered the animation
4298
*/
43-
init: function(trigger) {
99+
init: function (trigger) {
44100
CALLBACK_TRACKER.executing[trigger] = {};
45101
},
46102
/**
47103
* Removes 'trigger' from the tracker
48104
* @param {string} trigger - A CSS selector representing the element which triggered the animation
49105
*/
50-
remove: function(trigger) {
106+
remove: function (trigger) {
51107
delete this.executing[trigger];
52108
},
53109
});
@@ -64,15 +120,15 @@ const TARGETS_STACK = {
64120
* @param {HTMLElement} elem - Element being animated
65121
* @param {string} trigger - CSS selector for the element that triggered the animation
66122
*/
67-
add: function(elem, trigger) {
123+
add: function (elem, trigger) {
68124
if (!(trigger in this.stack)) this.stack[trigger] = [];
69125
this.stack[trigger].push(elem);
70126
},
71127
/**
72128
* Removes from the stack all the elements animated by the same trigger button
73129
* @param {string} trigger - CSS selector for the element that triggered the animation
74130
*/
75-
remove: function(trigger) {
131+
remove: function (trigger) {
76132
if (!(trigger in this.stack)) return;
77133
delete this.stack[trigger];
78134
},
@@ -81,7 +137,7 @@ const TARGETS_STACK = {
81137
* @param {string} trigger - CSS selector for the element that triggered the animation
82138
* @returns An array of elements that have been animated by the same trigger button
83139
*/
84-
get: function(trigger) {
140+
get: function (trigger) {
85141
if (!(trigger in this.stack)) return;
86142
return this.stack[trigger];
87143
},
@@ -98,6 +154,31 @@ export const removeCustomCssProperties = element => {
98154
});
99155
};
100156

157+
/**
158+
* Customize the default animations configurations by overwriting
159+
* the 'CONFIG' values
160+
* @param {Object} opts - All the options customized by the user
161+
* @see {@link CONFIG}
162+
*/
163+
const updateDefaultConfig = opts => {
164+
for (let option in CONFIG.default) {
165+
if (opts[option] !== undefined) {
166+
CONFIG[option] = opts[option];
167+
}
168+
}
169+
};
170+
171+
/**
172+
* Reset the configurations to its default values
173+
* by removing from 'CONFIG' all options customized by the user
174+
* @see {@link CONFIG}
175+
*/
176+
const resetDefaultConfig = () => {
177+
for (let option in CONFIG.default) {
178+
delete CONFIG[option];
179+
}
180+
};
181+
101182
/**
102183
* Sets an inline CSS property
103184
* @param {HTMLElement} element - The DOM element which will receive the property
@@ -116,7 +197,7 @@ export const setCssProperty = (element, property, value) => {
116197
*/
117198
const updateCssProperties = (element, opts) => {
118199
removeCustomCssProperties(element);
119-
removeInlineTransition(element);
200+
if (element !== document.documentElement) removeInlineTransition(element);
120201
CUSTOM_CSS_PROPERTIES.forEach(prop => {
121202
if (typeof opts[prop] === 'string' || typeof opts[prop] === 'number') {
122203
if (typeof opts[prop] === 'number') {
@@ -328,13 +409,15 @@ const animate = (element, action, id, opts = {}) => {
328409
const {
329410
animType,
330411
trigger,
331-
start,
332-
complete,
333-
keepSpace,
334-
dimensionsTransition = keepSpace || isMotion(animType) ? false : true,
335-
widthTransition = dimensionsTransition,
336-
heightTransition = dimensionsTransition,
337-
overflowHidden = true,
412+
start = CONFIG.start,
413+
complete = CONFIG.complete,
414+
keepSpace = CONFIG.keepSpace,
415+
dimensionsTransition = keepSpace || isMotion(animType)
416+
? false
417+
: CONFIG.dimensionsTransition,
418+
widthTransition = CONFIG.widthTransition ?? dimensionsTransition,
419+
heightTransition = CONFIG.heightTransition ?? dimensionsTransition,
420+
overflowHidden = CONFIG.overflowHidden,
338421
} = opts;
339422
const { duration, delay } = getTotalAnimTime(element);
340423
const OPPOSITE_ACTION = Object.freeze({
@@ -487,7 +570,9 @@ const preset = (el, args) => {
487570
*/
488571
const eventHandler = (el, animationId, opts) => {
489572
return (/** @type {Event} */ e) => {
490-
e.stopPropagation();
573+
const { stopPropagation = true, preventDefault = true } = opts;
574+
if (stopPropagation) e.stopPropagation();
575+
if (preventDefault) e.preventDefault();
491576

492577
const action = getAction(el, opts.animType);
493578
if (!action)
@@ -513,7 +598,11 @@ const eventHandler = (el, animationId, opts) => {
513598
* @see {@link module:globals.MOTION_ANIMS_ID}
514599
*/
515600
const init = (animationId, opts = {}, eventType = 'click') => {
516-
const { trigger = `.${CLASS_NAMES.trigger}`, targetSelector, cursor } = opts;
601+
const {
602+
trigger = CONFIG.trigger,
603+
targetSelector = CONFIG.targetSelector,
604+
cursor,
605+
} = opts;
517606

518607
document.querySelectorAll(trigger).forEach(btn => {
519608
btn.classList.add(CLASS_NAMES.btnCursor);
@@ -540,4 +629,12 @@ const init = (animationId, opts = {}, eventType = 'click') => {
540629
});
541630
};
542631

543-
export { init, animate, preset, isEnabled };
632+
export {
633+
init,
634+
animate,
635+
preset,
636+
isEnabled,
637+
updateCssProperties,
638+
updateDefaultConfig,
639+
resetDefaultConfig,
640+
};

js-css-animations/js-animations.css

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,17 @@
158158
}
159159

160160
:root {
161+
--js-css-animation--cursor: pointer;
161162
--js-css-animation--duration: 800ms;
162163
--js-css-animation--timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955);
163164
--js-css-animation--delay: 0ms;
164165
--js-css-animation--fill-mode: both;
165166
--js-css-animation--blur: 0.5px;
166167
--js-css-animation--direction: normal;
167168
--js-css-animation--iteration: 1;
169+
--js-css-animation--transf-origin: 'center';
170+
--js-css-animation--initial-scale: 1;
171+
--js-css-animation--final-scale: 1;
168172
}
169173

170174
.js-anim--dimensions-transitions {
@@ -216,7 +220,6 @@
216220
.js-anim--rotate-left,
217221
.js-anim--rotate-left__ccw,
218222
.js-anim--rotate {
219-
--js-css-animation--transf-origin: 'center';
220223
transform: rotate(var(--js-css-animation--rotation-angle));
221224
transform-origin: var(--js-css-animation--transf-origin);
222225
transition-property: transform;
@@ -272,15 +275,11 @@
272275
--js-css-animation--rotation-angle: 0deg;
273276
--js-css-animation--iteration: infinite;
274277
--js-css-animation--direction: alternate;
275-
--js-css-animation--transf-origin: 'center';
276278
animation-name: js-anim--rotation-loop;
277279
}
278280

279281
.js-anim--scale,
280282
.js-anim--scale__back {
281-
--js-css-animation--transf-origin: 'center';
282-
--js-css-animation--initial-scale: 1;
283-
--js-css-animation--final-scale: 1;
284283
transform-origin: var(--js-css-animation--transf-origin);
285284
}
286285

@@ -354,7 +353,6 @@
354353
}
355354

356355
.js-anim--btn-cursor {
357-
--js-css-animation--cursor: pointer;
358356
cursor: var(--js-css-animation--cursor);
359357
}
360358

js-css-animations/js-css-animations.js

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,17 @@
22
* Builds the animation API that will be exported to the final user
33
* @module js-css-animations
44
*/
5-
import { init, animate, preset, isEnabled } from './animate.js';
5+
import {
6+
init,
7+
animate,
8+
preset,
9+
isEnabled,
10+
updateCssProperties,
11+
setCssProperty,
12+
updateDefaultConfig,
13+
resetDefaultConfig,
14+
} from './animate.js';
15+
616
import { VISIBILITY_ANIMS_ID, MOTION_ANIMS_ID } from './globals.js';
717

818
/**
@@ -51,6 +61,29 @@ const getTargets = selector => {
5161
: selectAllElements(selector);
5262
};
5363

64+
/**
65+
* Default values used by all animations are set by the user by
66+
* overriding default animations properties and options
67+
* @param {Object} opts - All custom animation properties and options.
68+
* @see {@link module:globals.PROPERTY_NAMES}
69+
* @see {@link module:animate.configurations.default}
70+
*/
71+
const config = opts => {
72+
updateDefaultConfig(opts);
73+
updateCssProperties(document.documentElement, opts);
74+
if (opts.cursor)
75+
setCssProperty(document.documentElement, 'cursor', opts.cursor);
76+
};
77+
78+
/**
79+
* Resets default animations values by
80+
* removing default values customized by the user
81+
*/
82+
const reset = () => {
83+
config({});
84+
resetDefaultConfig();
85+
};
86+
5487
/**
5588
* Toggles between two animations.
5689
*
@@ -134,7 +167,7 @@ const toggle = (selector, animA, animB, opts = {}) => {
134167
* @see {@link module:globals.MOTION_ANIMS_ID}
135168
* @type {Object}
136169
*/
137-
const animationFunctions = (function() {
170+
const animationFunctions = (function () {
138171
const handlers = {};
139172
['show', 'hide', 'move'].forEach(action => {
140173
const { animIds, animType } =
@@ -176,6 +209,23 @@ const animationFunctions = (function() {
176209
}
177210
}
178211
});
212+
const blink = (target, opts = {}) => {
213+
jsCssAnimations.show.fade(target, {
214+
iteration: 'infinite',
215+
direction: 'alternate',
216+
...opts,
217+
});
218+
};
219+
const pulsate = (target, opts = {}) => {
220+
jsCssAnimations.scale(target, {
221+
finalScale: '1.2',
222+
iteration: 'infinite',
223+
direction: 'alternate',
224+
...opts,
225+
});
226+
};
227+
handlers.blink = blink;
228+
handlers.pulsate = pulsate;
179229
return handlers;
180230
})();
181231

@@ -212,7 +262,7 @@ const eventBoundAnimations = (() => {
212262
* @param {HTMLElement|string} selector - An element or a valid CSS selector corresponding to the element
213263
* @returns True if the element was rotated from its original orientation. False if it maintains the original orientation.
214264
*/
215-
const checkTransform = selector => {
265+
const isTransformed = selector => {
216266
const el = selectElement(selector);
217267
const transform = getComputedStyle(el).transform;
218268
return transform !== 'none' && transform !== 'matrix(1, 0, 0, 1, 0, 0)';
@@ -259,7 +309,7 @@ const verifyAnimationName = {
259309
* isTransformed(), isVisible() and isHidden()
260310
* @type {Object.<string, Function|Object>}
261311
*/
262-
const jsCssAnimations = (function() {
312+
const jsCssAnimations = (function () {
263313
/**
264314
* Encapsulates eventBoundAnimations(), adding animation name validation
265315
* @see eventBoundAnimations
@@ -285,29 +335,14 @@ const jsCssAnimations = (function() {
285335
verifyAnimationName
286336
);
287337
const animationsHandler = Object.freeze({
338+
config,
339+
reset,
288340
init: eventAnimations,
289341
...animationFunctions,
290342
show: showVisibilityAnim,
291343
hide: hideVisibilityAnim,
292-
toggle: toggle,
293-
blink: (target, opts = {}) => {
294-
jsCssAnimations.show.fade(target, {
295-
duration: '1s',
296-
iteration: 'infinite',
297-
direction: 'alternate',
298-
...opts,
299-
});
300-
},
301-
pulsate: (target, opts = {}) => {
302-
jsCssAnimations.scale(target, {
303-
finalScale: '1.5',
304-
duration: '1s',
305-
iteration: 'infinite',
306-
direction: 'reverse',
307-
...opts,
308-
});
309-
},
310-
isTransformed: checkTransform,
344+
toggle,
345+
isTransformed,
311346
/**
312347
* @param {Element|string} selector - Dom element or a valid CSS selector
313348
* @returns True if the element is visible, False otherwise

0 commit comments

Comments
 (0)