@simhub2/justflipit 3.2.2 → 4.0.1

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +21 -0
  3. package/README.md +258 -91
  4. package/dist/agent.cjs +63 -0
  5. package/dist/agent.cjs.map +7 -0
  6. package/dist/agent.d.cts +4 -0
  7. package/dist/agent.d.mts +4 -0
  8. package/dist/agent.d.ts +4 -0
  9. package/dist/agent.mjs +43 -0
  10. package/dist/agent.mjs.map +7 -0
  11. package/dist/justFlipIt-combined.js +295 -0
  12. package/dist/justFlipIt-combined.min.js +23 -0
  13. package/dist/justFlipIt-modern.js +271 -476
  14. package/dist/justFlipIt-modern.min.js +23 -1
  15. package/dist/justFlipIt-vanilla.js +272 -343
  16. package/dist/justFlipIt-vanilla.min.js +23 -1
  17. package/dist/justFlipIt.cjs +293 -0
  18. package/dist/justFlipIt.cjs.map +7 -0
  19. package/dist/justFlipIt.d.cts +4 -0
  20. package/dist/justFlipIt.d.mts +38 -0
  21. package/dist/justFlipIt.d.ts +38 -0
  22. package/dist/justFlipIt.js +269 -391
  23. package/dist/justFlipIt.js.map +7 -0
  24. package/dist/justFlipIt.min.js +23 -1
  25. package/dist/justFlipIt.min.js.map +7 -0
  26. package/dist/justFlipIt.mjs +272 -0
  27. package/dist/justFlipIt.mjs.map +7 -0
  28. package/dist/react.cjs +55 -0
  29. package/dist/react.cjs.map +7 -0
  30. package/dist/react.d.cts +3 -0
  31. package/dist/react.d.mts +3 -0
  32. package/dist/react.d.ts +3 -0
  33. package/dist/react.mjs +25 -0
  34. package/dist/react.mjs.map +7 -0
  35. package/dist/svelte.cjs +45 -0
  36. package/dist/svelte.cjs.map +7 -0
  37. package/dist/svelte.d.cts +3 -0
  38. package/dist/svelte.d.mts +3 -0
  39. package/dist/svelte.d.ts +3 -0
  40. package/dist/svelte.mjs +15 -0
  41. package/dist/svelte.mjs.map +7 -0
  42. package/dist/types/justFlipIt.d.ts +36 -59
  43. package/dist/vue.cjs +49 -0
  44. package/dist/vue.cjs.map +7 -0
  45. package/dist/vue.d.cts +3 -0
  46. package/dist/vue.d.mts +3 -0
  47. package/dist/vue.d.ts +3 -0
  48. package/dist/vue.mjs +19 -0
  49. package/dist/vue.mjs.map +7 -0
  50. package/package.json +117 -50
  51. package/src/justFlipIt-combined.js +0 -417
  52. package/src/justFlipIt-combined.min.js +0 -1
  53. package/src/justFlipIt-modern.js +0 -500
  54. package/src/justFlipIt-modern.min.js +0 -1
  55. package/src/justFlipIt-vanilla.js +0 -366
  56. package/src/justFlipIt-vanilla.min.js +0 -1
  57. package/src/justFlipIt.d.ts +0 -61
@@ -1,500 +0,0 @@
1
- /*!
2
- * justFlipIt v3.1.0
3
- * https://github.com/SimHub/justFlipIt
4
- *
5
- * Copyright SimHub
6
- * Released under the MIT license
7
- *
8
- * Date: 2025
9
- */
10
-
11
- (function (root, factory) {
12
- if (typeof define === "function" && define.amd) {
13
- define([], factory);
14
- } else if (typeof module === "object" && module.exports) {
15
- module.exports = factory();
16
- } else {
17
- root.justFlipIt = factory();
18
- }
19
- })(typeof self !== "undefined" ? self : this, function () {
20
- "use strict";
21
-
22
- // Feature detection
23
- const supportsGrid = typeof CSS !== "undefined" &&
24
- CSS.supports &&
25
- CSS.supports("display", "grid");
26
- const supportsWebAnimations = typeof Element !== "undefined" &&
27
- "animate" in Element.prototype;
28
- const supportsCustomProperties = window.CSS && CSS.supports &&
29
- CSS.supports("color", "var(--test)");
30
-
31
- // Style generation based on browser support
32
- function generateStyles() {
33
- // Base styles that work everywhere
34
- let baseStyles =
35
- "._justFlipIt_panel {perspective:1000px;-webkit-perspective:1000px;-moz-perspective:1000px;position:relative;}" +
36
- "._justFlipIt_panel .front{height:inherit;width:inherit;position:absolute;top:0;z-index:900;transform-style:preserve-3d;backface-visibility:hidden;transition:transform .4s ease-in-out;}" +
37
- "._justFlipIt_panel .back, ._justFlipIt_panel .backY{height:inherit;width:inherit;position:absolute;top:0;z-index:1000;transform-style:preserve-3d;backface-visibility:hidden;transition:transform .4s ease-in-out;}";
38
-
39
- // Add prefixed versions for older browsers
40
- let prefixedStyles =
41
- "._justFlipIt_panel .front{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-webkit-transition:transform .4s ease-in-out;-moz-transition:transform .4s ease-in-out;}" +
42
- "._justFlipIt_panel .back, ._justFlipIt_panel .backY{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-webkit-transition:transform .4s ease-in-out;-moz-transition:transform .4s ease-in-out;}";
43
-
44
- // X-axis rotations
45
- let xAxisStyles =
46
- "._justFlipIt_panel .back{transform:rotateX(-180deg);-webkit-transform:rotateX(-180deg);-moz-transform:rotateX(-180deg);}" +
47
- "._justFlipIt_panel._flip_ .front{transform:rotateX(180deg);-webkit-transform:rotateX(180deg);-moz-transform:rotateX(180deg);}" +
48
- "._justFlipIt_panel._flip_ .back{transform:rotateX(0);-webkit-transform:rotateX(0);-moz-transform:rotateX(0);}";
49
-
50
- // Y-axis rotations
51
- let yAxisStyles =
52
- "._justFlipIt_panel .backY{transform:rotateY(-180deg);-webkit-transform:rotateY(-180deg);-moz-transform:rotateY(-180deg);}" +
53
- "._justFlipIt_panel._flipY_ .front{transform:rotateY(180deg);-webkit-transform:rotateY(180deg);-moz-transform:rotateY(180deg);}" +
54
- "._justFlipIt_panel._flipY_ .backY{transform:rotateY(0);-webkit-transform:rotateY(0);-moz-transform:rotateY(0);}";
55
-
56
- // PATCH: Transparency-Style
57
- let transparentStyle =
58
- "._justFlipIt_panel {background: transparent !important; box-shadow: none !important;}" +
59
- "._justFlipIt_panel > * {box-sizing: border-box;}";
60
-
61
- return (
62
- baseStyles + prefixedStyles + xAxisStyles + yAxisStyles + transparentStyle
63
- );
64
- }
65
-
66
- // Add styles to document head
67
- function addStyles() {
68
- if (document.querySelector('[data-justflipitstyle="justFlipIt"]')) {
69
- return; // Styles already added
70
- }
71
-
72
- const styleElement = document.createElement("style");
73
- styleElement.setAttribute("data-justflipitstyle", "justFlipIt");
74
- styleElement.textContent = generateStyles();
75
-
76
- document.head.appendChild(styleElement);
77
- }
78
-
79
- // Helper functions to replace jQuery
80
- function getStyle(element, property) {
81
- return window.getComputedStyle(element, null).getPropertyValue(property);
82
- }
83
-
84
- function addClass(element, className) {
85
- if (element.classList) {
86
- element.classList.add(className);
87
- } else {
88
- element.className += " " + className;
89
- }
90
- }
91
-
92
- function removeClass(element, className) {
93
- if (element.classList) {
94
- element.classList.remove(className);
95
- } else {
96
- element.className = element.className.replace(
97
- new RegExp(
98
- "(^|\\b)" + className.split(" ").join("|") + "(\\b|$)",
99
- "gi",
100
- ),
101
- " ",
102
- );
103
- }
104
- }
105
-
106
- function toggleClass(element, className) {
107
- if (element.classList) {
108
- element.classList.toggle(className);
109
- } else {
110
- var classes = element.className.split(" ");
111
- var existingIndex = classes.indexOf(className);
112
-
113
- if (existingIndex >= 0) {
114
- classes.splice(existingIndex, 1);
115
- } else {
116
- classes.push(className);
117
- }
118
-
119
- element.className = classes.join(" ");
120
- }
121
- }
122
-
123
- function hasClass(element, className) {
124
- if (element.classList) {
125
- return element.classList.contains(className);
126
- } else {
127
- return new RegExp("(^| )" + className + "( |$)", "gi").test(
128
- element.className,
129
- );
130
- }
131
- }
132
-
133
- // NEU: Funktion zur Anwendung der benutzerdefinierten Animationseinstellungen
134
- function applyAnimationSettings(element, duration, easing) {
135
- const transitionValue = `transform ${duration / 1000}s ${easing}`;
136
- element.style.transition = transitionValue;
137
- element.style.WebkitTransition = transitionValue;
138
- element.style.MozTransition = transitionValue;
139
- }
140
-
141
- // PATCH: Verbesserte Style-Kopierfunktion
142
- function copyStyles(src, dest) {
143
- const computed = window.getComputedStyle(src);
144
- // Kopiere alle visuellen Eigenschaften
145
- const properties = [
146
- "background",
147
- "backgroundColor",
148
- "backgroundImage",
149
- "backgroundPosition",
150
- "backgroundRepeat",
151
- "backgroundSize",
152
- "borderRadius",
153
- "borderTopLeftRadius",
154
- "borderTopRightRadius",
155
- "borderBottomLeftRadius",
156
- "borderBottomRightRadius",
157
- "border",
158
- "borderTop",
159
- "borderRight",
160
- "borderBottom",
161
- "borderLeft",
162
- "boxShadow",
163
- "color",
164
- "opacity",
165
- ];
166
- properties.forEach((prop) => {
167
- if (
168
- computed[prop] &&
169
- computed[prop] !== "none" &&
170
- computed[prop] !== "initial" &&
171
- computed[prop] !== ""
172
- ) {
173
- dest.style[prop] = computed[prop];
174
- }
175
- });
176
- }
177
-
178
- // Modern animation with fallback
179
- function animateFlip(element, start, end, duration, easing = "ease-in-out") {
180
- if (supportsWebAnimations) {
181
- // Use Web Animations API
182
- const keyframes = [{ transform: start }, { transform: end }];
183
-
184
- const options = {
185
- duration: duration,
186
- easing: easing,
187
- fill: "forwards",
188
- };
189
-
190
- return element.animate(keyframes, options);
191
- } else {
192
- // Fallback to CSS transitions (already set in the CSS)
193
- element.style.transform = end;
194
- element.style.webkitTransform = end;
195
- element.style.mozTransform = end;
196
- return null;
197
- }
198
- }
199
-
200
- // Store for instances
201
- const instanceMap = new WeakMap();
202
-
203
- // Main justFlipIt class
204
- class JustFlipIt {
205
- constructor(element, options = {}) {
206
- // Make sure styles are added
207
- addStyles();
208
-
209
- this.element = element;
210
- this.settings = Object.assign(
211
- {},
212
- {
213
- Template: "", // Template for back side
214
- Click: false, // Click behavior
215
- FlipX: false, // Flip direction
216
- Style: [], // Custom styles
217
- Duration: 400, // Animation duration in ms
218
- Easing: "ease-in-out", // Animation easing function
219
- preserveClasses: true, // NEU
220
- preserveStyles: true, // NEU
221
- },
222
- options,
223
- );
224
-
225
- this.elementWidth = getStyle(element, "width");
226
- this.elementHeight = getStyle(element, "height");
227
- this.elementBackgroundColor = getStyle(element, "background-color");
228
- this.originalClassName = element.className;
229
- this.originalTagName = element.tagName.toLowerCase();
230
- this.originalId = element.id || "";
231
-
232
- // Set flip direction
233
- if (this.settings.FlipX === true) {
234
- this.flipClass = "_flip_";
235
- this.backClass = "back";
236
- this.rotateStart = "rotateX(0deg)";
237
- this.rotateFront = "rotateX(180deg)";
238
- this.rotateBack = "rotateX(-180deg)";
239
- this.rotateReset = "rotateX(0deg)";
240
- } else {
241
- this.flipClass = "_flipY_";
242
- this.backClass = "backY";
243
- this.rotateStart = "rotateY(0deg)";
244
- this.rotateFront = "rotateY(180deg)";
245
- this.rotateBack = "rotateY(-180deg)";
246
- this.rotateReset = "rotateY(0deg)";
247
- }
248
-
249
- // Initialize flip
250
- this._init();
251
-
252
- if (this.settings.Tilt) {
253
- this._setupTilt();
254
- }
255
-
256
- // Store instance
257
- instanceMap.set(element, this);
258
- }
259
-
260
- _init() {
261
- const originalElement = this.element;
262
- const originalClassName = this.originalClassName;
263
-
264
- // Panel-Struktur erzeugen
265
- const hoverPanel = document.createElement(this.originalTagName);
266
- addClass(hoverPanel, "hover");
267
- addClass(hoverPanel, "_justFlipIt_panel");
268
- const frontWrapper = document.createElement("div");
269
- addClass(frontWrapper, "front");
270
- const backWrapper = document.createElement("div");
271
- addClass(backWrapper, this.backClass);
272
-
273
- // NEU: Klassen übernehmen (Panel, .front, .backY)
274
- if (this.settings.preserveClasses && originalElement.classList.length) {
275
- originalElement.classList.forEach((cls) => {
276
- if (!hoverPanel.classList.contains(cls)) {
277
- hoverPanel.classList.add(cls);
278
- }
279
- if (frontWrapper && !frontWrapper.classList.contains(cls)) {
280
- frontWrapper.classList.add(cls);
281
- }
282
- if (backWrapper && !backWrapper.classList.contains(cls)) {
283
- backWrapper.classList.add(cls);
284
- }
285
- });
286
- }
287
-
288
- // NEU: Inline-Styles übernehmen (nur auf Panel)
289
- if (
290
- this.settings.preserveStyles && originalElement.getAttribute("style")
291
- ) {
292
- hoverPanel.setAttribute(
293
- "style",
294
- (hoverPanel.getAttribute("style") || "") +
295
- ";" + originalElement.getAttribute("style"),
296
- );
297
- }
298
-
299
- // Nur den INHALT übernehmen!
300
- frontWrapper.innerHTML = originalElement.innerHTML;
301
-
302
- if (this.settings.Template) {
303
- backWrapper.innerHTML = this.settings.Template;
304
- } else {
305
- backWrapper.innerHTML = originalElement.innerHTML;
306
- }
307
-
308
- // Panel einfügen und Original entfernen
309
- originalElement.parentNode.insertBefore(hoverPanel, originalElement);
310
- hoverPanel.appendChild(frontWrapper);
311
- hoverPanel.appendChild(backWrapper);
312
- originalElement.parentNode.removeChild(originalElement);
313
-
314
- // Panel-Größe und Styles übernehmen
315
- hoverPanel.style.width = this.elementWidth;
316
- hoverPanel.style.height = this.elementHeight;
317
-
318
- // Custom Styles aus Option anwenden
319
- if (this.settings.Style && this.settings.Style.length) {
320
- this.settings.Style.forEach((styleObj) => {
321
- if (styleObj.el) {
322
- if (styleObj.el.toLowerCase() === "self") {
323
- Object.assign(hoverPanel.style, styleObj.style);
324
- } else {
325
- const targetElements = hoverPanel.querySelectorAll(styleObj.el);
326
- targetElements.forEach((el) => {
327
- Object.assign(el.style, styleObj.style);
328
- });
329
- }
330
- }
331
- });
332
- }
333
-
334
- // Events setzen
335
- this._setupEvents(hoverPanel);
336
-
337
- // Referenzen speichern
338
- this.hoverPanel = hoverPanel;
339
- this.frontWrapper = frontWrapper;
340
- this.backWrapper = backWrapper;
341
- }
342
-
343
- _setupTilt() {
344
- const handleMove = (e) => {
345
- const rect = this.hoverPanel.getBoundingClientRect();
346
- const x = (e.touches ? e.touches[0].clientX : e.clientX) - rect.left;
347
- const y = (e.touches ? e.touches[0].clientY : e.clientY) - rect.top;
348
- const centerX = rect.width / 2;
349
- const centerY = rect.height / 2;
350
- const rotateX = ((y - centerY) / centerY) * 10;
351
- const rotateY = (-(x - centerX) / centerX) * 10;
352
- this.hoverPanel.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.05, 1.05, 1.05)`;
353
- };
354
-
355
- const handleEnter = () => {
356
- this.hoverPanel.style.transition = "all 0.2s ease-out";
357
- };
358
-
359
- const handleLeave = () => {
360
- this.hoverPanel.style.transform = `perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)`;
361
- this.hoverPanel.style.transition = "all 0.5s ease-in-out";
362
- };
363
-
364
- this.hoverPanel.addEventListener("mousemove", handleMove);
365
- this.hoverPanel.addEventListener("touchmove", handleMove);
366
- this.hoverPanel.addEventListener("mouseenter", handleEnter);
367
- this.hoverPanel.addEventListener("touchstart", handleEnter);
368
- this.hoverPanel.addEventListener("mouseleave", handleLeave);
369
- this.hoverPanel.addEventListener("touchend", handleLeave);
370
- }
371
-
372
- _setupEvents(hoverPanel) {
373
- if (this.settings.Tilt === 'only') return;
374
- if (this.settings.Click === true) {
375
- hoverPanel.addEventListener("click", (e) => {
376
- e.preventDefault();
377
- this._toggleFlip();
378
- });
379
- } else if (typeof this.settings.Click === "string") {
380
- const clickElements = hoverPanel.querySelectorAll(this.settings.Click);
381
- clickElements.forEach((el) => {
382
- el.addEventListener("click", () => {
383
- this._toggleFlip();
384
- });
385
- });
386
- } else {
387
- // Default hover behavior
388
- hoverPanel.addEventListener("mouseenter", () => {
389
- this._flip(true);
390
- });
391
- hoverPanel.addEventListener("mouseleave", () => {
392
- this._flip(false);
393
- });
394
- }
395
- }
396
-
397
- _toggleFlip() {
398
- const isFlipped = hasClass(this.hoverPanel, this.flipClass);
399
- this._flip(!isFlipped);
400
- }
401
-
402
- _flip(shouldFlip) {
403
- if (shouldFlip) {
404
- addClass(this.hoverPanel, this.flipClass);
405
- if (supportsWebAnimations) {
406
- animateFlip(
407
- this.frontWrapper,
408
- this.rotateStart,
409
- this.rotateFront,
410
- this.settings.Duration,
411
- this.settings.Easing,
412
- );
413
- animateFlip(
414
- this.backWrapper,
415
- this.rotateBack,
416
- this.rotateReset,
417
- this.settings.Duration,
418
- this.settings.Easing,
419
- );
420
- }
421
- } else {
422
- removeClass(this.hoverPanel, this.flipClass);
423
- if (supportsWebAnimations) {
424
- animateFlip(
425
- this.frontWrapper,
426
- this.rotateFront,
427
- this.rotateStart,
428
- this.settings.Duration,
429
- this.settings.Easing,
430
- );
431
- animateFlip(
432
- this.backWrapper,
433
- this.rotateReset,
434
- this.rotateBack,
435
- this.settings.Duration,
436
- this.settings.Easing,
437
- );
438
- }
439
- }
440
- }
441
-
442
- destroy() {
443
- const hoverPanel = this.hoverPanel;
444
- const originalElement = hoverPanel.querySelector(".front > *");
445
-
446
- // Restore original classes
447
- originalElement.className = this.originalClassName;
448
-
449
- // Put the original element back in its place
450
- hoverPanel.parentNode.insertBefore(originalElement, hoverPanel);
451
- hoverPanel.parentNode.removeChild(hoverPanel);
452
-
453
- // Remove from instance map
454
- instanceMap.delete(this.element);
455
- }
456
- }
457
-
458
- // Main function to initialize justFlipIt
459
- function justFlipIt(selector, options = {}) {
460
- if (typeof selector === "string") {
461
- // If selector is a string, find all matching elements
462
- const elements = document.querySelectorAll(selector);
463
- return Array.from(elements).map((el) => {
464
- return new JustFlipIt(el, options);
465
- });
466
- } else if (selector instanceof Element) {
467
- // If selector is a DOM element
468
- return new JustFlipIt(selector, options);
469
- } else if (selector.length) {
470
- // If selector is array-like (NodeList, HTMLCollection, etc.)
471
- return Array.from(selector).map((el) => {
472
- return new JustFlipIt(el, options);
473
- });
474
- }
475
- }
476
-
477
- // Destroy method
478
- justFlipIt.destroy = function (selector) {
479
- if (typeof selector === "string") {
480
- // If selector is a string, find all matching elements
481
- const elements = document.querySelectorAll(selector);
482
- Array.from(elements).forEach((el) => {
483
- const instance = instanceMap.get(el);
484
- if (instance) instance.destroy();
485
- });
486
- } else if (selector instanceof Element) {
487
- // If selector is a DOM element
488
- const instance = instanceMap.get(selector);
489
- if (instance) instance.destroy();
490
- } else if (selector.length) {
491
- // If selector is array-like (NodeList, HTMLCollection, etc.)
492
- Array.from(selector).forEach((el) => {
493
- const instance = instanceMap.get(el);
494
- if (instance) instance.destroy();
495
- });
496
- }
497
- };
498
-
499
- return justFlipIt;
500
- });
@@ -1 +0,0 @@
1
- (function(root,factory){if(typeof define==="function"&&define.amd){define([],factory)}else if(typeof module==="object"&&module.exports){module.exports=factory()}else{root.justFlipIt=factory()}})(typeof self!=="undefined"?self:this,function(){"use strict";const supportsGrid=typeof CSS!=="undefined"&&CSS.supports&&CSS.supports("display","grid");const supportsWebAnimations=typeof Element!=="undefined"&&"animate"in Element.prototype;const supportsCustomProperties=window.CSS&&CSS.supports&&CSS.supports("color","var(--test)");function generateStyles(){let baseStyles="._justFlipIt_panel {perspective:1000px;-webkit-perspective:1000px;-moz-perspective:1000px;position:relative;}"+"._justFlipIt_panel .front{height:inherit;width:inherit;position:absolute;top:0;z-index:900;transform-style:preserve-3d;backface-visibility:hidden;transition:transform .4s ease-in-out;}"+"._justFlipIt_panel .back, ._justFlipIt_panel .backY{height:inherit;width:inherit;position:absolute;top:0;z-index:1000;transform-style:preserve-3d;backface-visibility:hidden;transition:transform .4s ease-in-out;}";let prefixedStyles="._justFlipIt_panel .front{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-webkit-transition:transform .4s ease-in-out;-moz-transition:transform .4s ease-in-out;}"+"._justFlipIt_panel .back, ._justFlipIt_panel .backY{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-webkit-transition:transform .4s ease-in-out;-moz-transition:transform .4s ease-in-out;}";let xAxisStyles="._justFlipIt_panel .back{transform:rotateX(-180deg);-webkit-transform:rotateX(-180deg);-moz-transform:rotateX(-180deg);}"+"._justFlipIt_panel._flip_ .front{transform:rotateX(180deg);-webkit-transform:rotateX(180deg);-moz-transform:rotateX(180deg);}"+"._justFlipIt_panel._flip_ .back{transform:rotateX(0);-webkit-transform:rotateX(0);-moz-transform:rotateX(0);}";let yAxisStyles="._justFlipIt_panel .backY{transform:rotateY(-180deg);-webkit-transform:rotateY(-180deg);-moz-transform:rotateY(-180deg);}"+"._justFlipIt_panel._flipY_ .front{transform:rotateY(180deg);-webkit-transform:rotateY(180deg);-moz-transform:rotateY(180deg);}"+"._justFlipIt_panel._flipY_ .backY{transform:rotateY(0);-webkit-transform:rotateY(0);-moz-transform:rotateY(0);}";let transparentStyle="._justFlipIt_panel {background: transparent !important; box-shadow: none !important;}"+"._justFlipIt_panel > * {box-sizing: border-box;}";return baseStyles+prefixedStyles+xAxisStyles+yAxisStyles+transparentStyle}function addStyles(){if(document.querySelector('[data-justflipitstyle="justFlipIt"]')){return}const styleElement=document.createElement("style");styleElement.setAttribute("data-justflipitstyle","justFlipIt");styleElement.textContent=generateStyles();document.head.appendChild(styleElement)}function getStyle(element,property){return window.getComputedStyle(element,null).getPropertyValue(property)}function addClass(element,className){if(element.classList){element.classList.add(className)}else{element.className+=" "+className}}function removeClass(element,className){if(element.classList){element.classList.remove(className)}else{element.className=element.className.replace(new RegExp("(^|\\b)"+className.split(" ").join("|")+"(\\b|$)","gi")," ")}}function toggleClass(element,className){if(element.classList){element.classList.toggle(className)}else{var classes=element.className.split(" ");var existingIndex=classes.indexOf(className);if(existingIndex>=0){classes.splice(existingIndex,1)}else{classes.push(className)}element.className=classes.join(" ")}}function hasClass(element,className){if(element.classList){return element.classList.contains(className)}else{return new RegExp("(^| )"+className+"( |$)","gi").test(element.className)}}function applyAnimationSettings(element,duration,easing){const transitionValue=`transform ${duration/1e3}s ${easing}`;element.style.transition=transitionValue;element.style.WebkitTransition=transitionValue;element.style.MozTransition=transitionValue}function copyStyles(src,dest){const computed=window.getComputedStyle(src);const properties=["background","backgroundColor","backgroundImage","backgroundPosition","backgroundRepeat","backgroundSize","borderRadius","borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius","border","borderTop","borderRight","borderBottom","borderLeft","boxShadow","color","opacity"];properties.forEach(prop=>{if(computed[prop]&&computed[prop]!=="none"&&computed[prop]!=="initial"&&computed[prop]!==""){dest.style[prop]=computed[prop]}})}function animateFlip(element,start,end,duration,easing="ease-in-out"){if(supportsWebAnimations){const keyframes=[{transform:start},{transform:end}];const options={duration:duration,easing:easing,fill:"forwards"};return element.animate(keyframes,options)}else{element.style.transform=end;element.style.webkitTransform=end;element.style.mozTransform=end;return null}}const instanceMap=new WeakMap;class JustFlipIt{constructor(element,options={}){addStyles();this.element=element;this.settings=Object.assign({},{Template:"",Click:false,FlipX:false,Style:[],Duration:400,Easing:"ease-in-out",preserveClasses:true,preserveStyles:true},options);this.elementWidth=getStyle(element,"width");this.elementHeight=getStyle(element,"height");this.elementBackgroundColor=getStyle(element,"background-color");this.originalClassName=element.className;this.originalTagName=element.tagName.toLowerCase();this.originalId=element.id||"";if(this.settings.FlipX===true){this.flipClass="_flip_";this.backClass="back";this.rotateStart="rotateX(0deg)";this.rotateFront="rotateX(180deg)";this.rotateBack="rotateX(-180deg)";this.rotateReset="rotateX(0deg)"}else{this.flipClass="_flipY_";this.backClass="backY";this.rotateStart="rotateY(0deg)";this.rotateFront="rotateY(180deg)";this.rotateBack="rotateY(-180deg)";this.rotateReset="rotateY(0deg)"}this._init();if(this.settings.Tilt){this._setupTilt()}instanceMap.set(element,this)}_init(){const originalElement=this.element;const originalClassName=this.originalClassName;const hoverPanel=document.createElement(this.originalTagName);addClass(hoverPanel,"hover");addClass(hoverPanel,"_justFlipIt_panel");const frontWrapper=document.createElement("div");addClass(frontWrapper,"front");const backWrapper=document.createElement("div");addClass(backWrapper,this.backClass);if(this.settings.preserveClasses&&originalElement.classList.length){originalElement.classList.forEach(cls=>{if(!hoverPanel.classList.contains(cls)){hoverPanel.classList.add(cls)}if(frontWrapper&&!frontWrapper.classList.contains(cls)){frontWrapper.classList.add(cls)}if(backWrapper&&!backWrapper.classList.contains(cls)){backWrapper.classList.add(cls)}})}if(this.settings.preserveStyles&&originalElement.getAttribute("style")){hoverPanel.setAttribute("style",(hoverPanel.getAttribute("style")||"")+";"+originalElement.getAttribute("style"))}frontWrapper.innerHTML=originalElement.innerHTML;if(this.settings.Template){backWrapper.innerHTML=this.settings.Template}else{backWrapper.innerHTML=originalElement.innerHTML}originalElement.parentNode.insertBefore(hoverPanel,originalElement);hoverPanel.appendChild(frontWrapper);hoverPanel.appendChild(backWrapper);originalElement.parentNode.removeChild(originalElement);hoverPanel.style.width=this.elementWidth;hoverPanel.style.height=this.elementHeight;if(this.settings.Style&&this.settings.Style.length){this.settings.Style.forEach(styleObj=>{if(styleObj.el){if(styleObj.el.toLowerCase()==="self"){Object.assign(hoverPanel.style,styleObj.style)}else{const targetElements=hoverPanel.querySelectorAll(styleObj.el);targetElements.forEach(el=>{Object.assign(el.style,styleObj.style)})}}})}this._setupEvents(hoverPanel);this.hoverPanel=hoverPanel;this.frontWrapper=frontWrapper;this.backWrapper=backWrapper}_setupTilt(){const handleMove=e=>{const rect=this.hoverPanel.getBoundingClientRect();const x=(e.touches?e.touches[0].clientX:e.clientX)-rect.left;const y=(e.touches?e.touches[0].clientY:e.clientY)-rect.top;const centerX=rect.width/2;const centerY=rect.height/2;const rotateX=(y-centerY)/centerY*10;const rotateY=-(x-centerX)/centerX*10;this.hoverPanel.style.transform=`perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.05, 1.05, 1.05)`};const handleEnter=()=>{this.hoverPanel.style.transition="all 0.2s ease-out"};const handleLeave=()=>{this.hoverPanel.style.transform=`perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)`;this.hoverPanel.style.transition="all 0.5s ease-in-out"};this.hoverPanel.addEventListener("mousemove",handleMove);this.hoverPanel.addEventListener("touchmove",handleMove);this.hoverPanel.addEventListener("mouseenter",handleEnter);this.hoverPanel.addEventListener("touchstart",handleEnter);this.hoverPanel.addEventListener("mouseleave",handleLeave);this.hoverPanel.addEventListener("touchend",handleLeave)}_setupEvents(hoverPanel){if(this.settings.Tilt==="only")return;if(this.settings.Click===true){hoverPanel.addEventListener("click",e=>{e.preventDefault();this._toggleFlip()})}else if(typeof this.settings.Click==="string"){const clickElements=hoverPanel.querySelectorAll(this.settings.Click);clickElements.forEach(el=>{el.addEventListener("click",()=>{this._toggleFlip()})})}else{hoverPanel.addEventListener("mouseenter",()=>{this._flip(true)});hoverPanel.addEventListener("mouseleave",()=>{this._flip(false)})}}_toggleFlip(){const isFlipped=hasClass(this.hoverPanel,this.flipClass);this._flip(!isFlipped)}_flip(shouldFlip){if(shouldFlip){addClass(this.hoverPanel,this.flipClass);if(supportsWebAnimations){animateFlip(this.frontWrapper,this.rotateStart,this.rotateFront,this.settings.Duration,this.settings.Easing);animateFlip(this.backWrapper,this.rotateBack,this.rotateReset,this.settings.Duration,this.settings.Easing)}}else{removeClass(this.hoverPanel,this.flipClass);if(supportsWebAnimations){animateFlip(this.frontWrapper,this.rotateFront,this.rotateStart,this.settings.Duration,this.settings.Easing);animateFlip(this.backWrapper,this.rotateReset,this.rotateBack,this.settings.Duration,this.settings.Easing)}}}destroy(){const hoverPanel=this.hoverPanel;const originalElement=hoverPanel.querySelector(".front > *");originalElement.className=this.originalClassName;hoverPanel.parentNode.insertBefore(originalElement,hoverPanel);hoverPanel.parentNode.removeChild(hoverPanel);instanceMap.delete(this.element)}}function justFlipIt(selector,options={}){if(typeof selector==="string"){const elements=document.querySelectorAll(selector);return Array.from(elements).map(el=>{return new JustFlipIt(el,options)})}else if(selector instanceof Element){return new JustFlipIt(selector,options)}else if(selector.length){return Array.from(selector).map(el=>{return new JustFlipIt(el,options)})}}justFlipIt.destroy=function(selector){if(typeof selector==="string"){const elements=document.querySelectorAll(selector);Array.from(elements).forEach(el=>{const instance=instanceMap.get(el);if(instance)instance.destroy()})}else if(selector instanceof Element){const instance=instanceMap.get(selector);if(instance)instance.destroy()}else if(selector.length){Array.from(selector).forEach(el=>{const instance=instanceMap.get(el);if(instance)instance.destroy()})}};return justFlipIt});