@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.
- package/CHANGELOG.md +21 -0
- package/LICENSE +21 -0
- package/README.md +258 -91
- package/dist/agent.cjs +63 -0
- package/dist/agent.cjs.map +7 -0
- package/dist/agent.d.cts +4 -0
- package/dist/agent.d.mts +4 -0
- package/dist/agent.d.ts +4 -0
- package/dist/agent.mjs +43 -0
- package/dist/agent.mjs.map +7 -0
- package/dist/justFlipIt-combined.js +295 -0
- package/dist/justFlipIt-combined.min.js +23 -0
- package/dist/justFlipIt-modern.js +271 -476
- package/dist/justFlipIt-modern.min.js +23 -1
- package/dist/justFlipIt-vanilla.js +272 -343
- package/dist/justFlipIt-vanilla.min.js +23 -1
- package/dist/justFlipIt.cjs +293 -0
- package/dist/justFlipIt.cjs.map +7 -0
- package/dist/justFlipIt.d.cts +4 -0
- package/dist/justFlipIt.d.mts +38 -0
- package/dist/justFlipIt.d.ts +38 -0
- package/dist/justFlipIt.js +269 -391
- package/dist/justFlipIt.js.map +7 -0
- package/dist/justFlipIt.min.js +23 -1
- package/dist/justFlipIt.min.js.map +7 -0
- package/dist/justFlipIt.mjs +272 -0
- package/dist/justFlipIt.mjs.map +7 -0
- package/dist/react.cjs +55 -0
- package/dist/react.cjs.map +7 -0
- package/dist/react.d.cts +3 -0
- package/dist/react.d.mts +3 -0
- package/dist/react.d.ts +3 -0
- package/dist/react.mjs +25 -0
- package/dist/react.mjs.map +7 -0
- package/dist/svelte.cjs +45 -0
- package/dist/svelte.cjs.map +7 -0
- package/dist/svelte.d.cts +3 -0
- package/dist/svelte.d.mts +3 -0
- package/dist/svelte.d.ts +3 -0
- package/dist/svelte.mjs +15 -0
- package/dist/svelte.mjs.map +7 -0
- package/dist/types/justFlipIt.d.ts +36 -59
- package/dist/vue.cjs +49 -0
- package/dist/vue.cjs.map +7 -0
- package/dist/vue.d.cts +3 -0
- package/dist/vue.d.mts +3 -0
- package/dist/vue.d.ts +3 -0
- package/dist/vue.mjs +19 -0
- package/dist/vue.mjs.map +7 -0
- package/package.json +117 -50
- package/src/justFlipIt-combined.js +0 -417
- package/src/justFlipIt-combined.min.js +0 -1
- package/src/justFlipIt-modern.js +0 -500
- package/src/justFlipIt-modern.min.js +0 -1
- package/src/justFlipIt-vanilla.js +0 -366
- package/src/justFlipIt-vanilla.min.js +0 -1
- package/src/justFlipIt.d.ts +0 -61
|
@@ -1,500 +1,295 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
);
|
|
1
|
+
var JustFlipItModule = (() => {
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
130
15
|
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/core.js
|
|
21
|
+
var core_exports = {};
|
|
22
|
+
__export(core_exports, {
|
|
23
|
+
FlipController: () => FlipController,
|
|
24
|
+
default: () => justFlipIt
|
|
25
|
+
});
|
|
26
|
+
var instances = /* @__PURE__ */ new WeakMap();
|
|
27
|
+
var defaults = { Click: false, FlipX: false, Duration: 400, Easing: "cubic-bezier(.22,.61,.36,1)", Tilt: false, Effect: "flip", ReducedMotion: true, preserveClasses: true, preserveStyles: true, Style: [] };
|
|
28
|
+
var css = `
|
|
29
|
+
._justFlipIt_panel{position:relative;display:grid;perspective:var(--jfi-perspective,1000px);isolation:isolate}
|
|
30
|
+
._justFlipIt_panel>[data-jfi-face]{grid-area:1/1;min-width:0;backface-visibility:hidden;-webkit-backface-visibility:hidden;transition:transform var(--jfi-duration) var(--jfi-easing),opacity var(--jfi-duration) var(--jfi-easing);transform-origin:center}
|
|
31
|
+
._justFlipIt_panel>[data-jfi-face=back],._justFlipIt_panel[data-jfi-flipped=true]>[data-jfi-face=front]{pointer-events:none}
|
|
32
|
+
._justFlipIt_panel[data-jfi-flipped=true]>[data-jfi-face=back]{pointer-events:auto}
|
|
33
|
+
._justFlipIt_panel[data-jfi-effect=flip]>[data-jfi-face=front]{transform:rotateY(0deg)}
|
|
34
|
+
._justFlipIt_panel[data-jfi-effect=flip]>[data-jfi-face=back]{transform:rotateY(-180deg)}
|
|
35
|
+
._justFlipIt_panel[data-jfi-effect=flip][data-jfi-flipped=true]>[data-jfi-face=front]{transform:rotateY(180deg)}
|
|
36
|
+
._justFlipIt_panel[data-jfi-effect=flip][data-jfi-flipped=true]>[data-jfi-face=back]{transform:rotateY(0deg)}
|
|
37
|
+
._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x]>[data-jfi-face=front]{transform:rotateX(0deg)}
|
|
38
|
+
._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x]>[data-jfi-face=back]{transform:rotateX(-180deg)}
|
|
39
|
+
._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x][data-jfi-flipped=true]>[data-jfi-face=front]{transform:rotateX(180deg)}
|
|
40
|
+
._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x][data-jfi-flipped=true]>[data-jfi-face=back]{transform:rotateX(0deg)}
|
|
41
|
+
._justFlipIt_panel[data-jfi-effect=fade]>[data-jfi-face=back],._justFlipIt_panel[data-jfi-effect=scale]>[data-jfi-face=back]{opacity:0}
|
|
42
|
+
._justFlipIt_panel[data-jfi-effect=fade][data-jfi-flipped=true]>[data-jfi-face=front],._justFlipIt_panel[data-jfi-effect=scale][data-jfi-flipped=true]>[data-jfi-face=front]{opacity:0}
|
|
43
|
+
._justFlipIt_panel[data-jfi-effect=fade][data-jfi-flipped=true]>[data-jfi-face=back],._justFlipIt_panel[data-jfi-effect=scale][data-jfi-flipped=true]>[data-jfi-face=back]{opacity:1}
|
|
44
|
+
._justFlipIt_panel[data-jfi-effect=scale]>[data-jfi-face=back],._justFlipIt_panel[data-jfi-effect=scale][data-jfi-flipped=true]>[data-jfi-face=front]{transform:scale(.94)}
|
|
45
|
+
._justFlipIt_panel[data-jfi-effect=scale][data-jfi-flipped=true]>[data-jfi-face=back]{transform:scale(1)}
|
|
46
|
+
._justFlipIt_panel[data-jfi-reduced=true]>[data-jfi-face]{transition:none!important}
|
|
47
|
+
@media(prefers-reduced-motion:reduce){._justFlipIt_panel:not([data-jfi-motion=allow])>[data-jfi-face]{transition:none!important}}
|
|
48
|
+
`;
|
|
49
|
+
function styles(doc) {
|
|
50
|
+
if (doc.querySelector('style[data-justflipitstyle="v4"]')) return;
|
|
51
|
+
const style = doc.createElement("style");
|
|
52
|
+
style.dataset.justflipitstyle = "v4";
|
|
53
|
+
style.textContent = css;
|
|
54
|
+
doc.head.append(style);
|
|
131
55
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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];
|
|
56
|
+
function validate(options) {
|
|
57
|
+
if (options.Duration !== void 0 && (!Number.isFinite(options.Duration) || options.Duration < 0)) throw new TypeError("Duration must be a non-negative finite number");
|
|
58
|
+
if (options.Effect !== void 0 && !["flip", "fade", "scale"].includes(options.Effect)) throw new TypeError("Unknown Effect");
|
|
59
|
+
if (options.Tilt && typeof options.Tilt === "object") {
|
|
60
|
+
for (const key of ["max", "perspective", "scale"]) {
|
|
61
|
+
if (options.Tilt[key] !== void 0 && (!Number.isFinite(options.Tilt[key]) || options.Tilt[key] < 0)) throw new TypeError(`Invalid Tilt.${key}`);
|
|
174
62
|
}
|
|
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
63
|
}
|
|
198
64
|
}
|
|
199
|
-
|
|
200
|
-
// Store for instances
|
|
201
|
-
const instanceMap = new WeakMap();
|
|
202
|
-
|
|
203
|
-
// Main justFlipIt class
|
|
204
|
-
class JustFlipIt {
|
|
65
|
+
var FlipController = class {
|
|
205
66
|
constructor(element, options = {}) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
67
|
+
validate(options);
|
|
68
|
+
if (!element || element.nodeType !== 1) throw new TypeError("Expected an HTML element");
|
|
209
69
|
this.element = element;
|
|
210
|
-
this.settings =
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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)";
|
|
70
|
+
this.settings = { ...defaults, ...options };
|
|
71
|
+
this.flipped = false;
|
|
72
|
+
this.destroyed = false;
|
|
73
|
+
this.cleanups = [];
|
|
74
|
+
this.restores = [];
|
|
75
|
+
this.win = element.ownerDocument.defaultView;
|
|
76
|
+
const doc = element.ownerDocument;
|
|
77
|
+
styles(doc);
|
|
78
|
+
this.managed = !!options.Faces;
|
|
79
|
+
if (this.managed) {
|
|
80
|
+
this.hoverPanel = element;
|
|
81
|
+
this.frontWrapper = element.querySelector(options.Faces.front);
|
|
82
|
+
this.backWrapper = element.querySelector(options.Faces.back);
|
|
83
|
+
if (!this.frontWrapper || !this.backWrapper || this.frontWrapper === this.backWrapper || this.frontWrapper.parentNode !== element || this.backWrapper.parentNode !== element) throw new TypeError("Faces must select two distinct direct children");
|
|
240
84
|
} else {
|
|
241
|
-
|
|
242
|
-
this.
|
|
243
|
-
this.
|
|
244
|
-
this.
|
|
245
|
-
this.
|
|
246
|
-
this.
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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;
|
|
85
|
+
if (!element.parentNode) throw new TypeError("Element must have a parent");
|
|
86
|
+
this.hoverPanel = doc.createElement("div");
|
|
87
|
+
this.frontWrapper = doc.createElement("div");
|
|
88
|
+
this.backWrapper = doc.createElement("div");
|
|
89
|
+
if (this.settings.preserveClasses) this.hoverPanel.className = element.className;
|
|
90
|
+
if (this.settings.preserveStyles) this.hoverPanel.style.cssText = element.style.cssText;
|
|
91
|
+
element.before(this.hoverPanel);
|
|
92
|
+
this.hoverPanel.append(this.frontWrapper, this.backWrapper);
|
|
93
|
+
this.frontWrapper.append(element);
|
|
94
|
+
if (options.Template !== void 0) this.backWrapper.innerHTML = options.Template;
|
|
95
|
+
else {
|
|
96
|
+
const clone = element.cloneNode(true);
|
|
97
|
+
clone.removeAttribute("id");
|
|
98
|
+
clone.querySelectorAll("[id]").forEach((node) => node.removeAttribute("id"));
|
|
99
|
+
this.backWrapper.append(clone);
|
|
100
|
+
}
|
|
306
101
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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
|
-
}
|
|
102
|
+
const panel = this.hoverPanel;
|
|
103
|
+
for (const node of [panel, this.frontWrapper, this.backWrapper]) {
|
|
104
|
+
const owned = node === panel ? ["class", "style", "tabindex", "data-jfi-axis", "data-jfi-effect", "data-jfi-motion", "data-jfi-flipped", "data-jfi-reduced"] : ["style", "data-jfi-face", "aria-hidden", "inert"];
|
|
105
|
+
const attrs = owned.map((name) => [name, node.getAttribute(name)]);
|
|
106
|
+
const inert = node.inert || false;
|
|
107
|
+
this.restores.push(() => {
|
|
108
|
+
node.inert = inert;
|
|
109
|
+
for (const [name, value] of attrs) {
|
|
110
|
+
if (value === null) node.removeAttribute(name);
|
|
111
|
+
else node.setAttribute(name, value);
|
|
330
112
|
}
|
|
331
113
|
});
|
|
332
114
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
this.
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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";
|
|
115
|
+
panel.classList.add("_justFlipIt_panel");
|
|
116
|
+
this.frontWrapper.dataset.jfiFace = "front";
|
|
117
|
+
this.backWrapper.dataset.jfiFace = "back";
|
|
118
|
+
this.motion = this.win.matchMedia?.("(prefers-reduced-motion: reduce)");
|
|
119
|
+
const motionChange = () => {
|
|
120
|
+
this.resetTilt();
|
|
121
|
+
this.render();
|
|
362
122
|
};
|
|
363
|
-
|
|
364
|
-
this.
|
|
365
|
-
this.
|
|
366
|
-
this.
|
|
367
|
-
this.
|
|
368
|
-
|
|
369
|
-
|
|
123
|
+
this.motion?.addEventListener("change", motionChange);
|
|
124
|
+
this.cleanups.push(() => this.motion?.removeEventListener("change", motionChange));
|
|
125
|
+
this.configure();
|
|
126
|
+
this.events();
|
|
127
|
+
this.render();
|
|
128
|
+
instances.set(element, this);
|
|
129
|
+
instances.set(panel, this);
|
|
370
130
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
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
|
-
}
|
|
131
|
+
listen(type, handler, options) {
|
|
132
|
+
this.hoverPanel.addEventListener(type, handler, options);
|
|
133
|
+
this.cleanups.push(() => this.hoverPanel.removeEventListener(type, handler, options));
|
|
395
134
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
const isFlipped = hasClass(this.hoverPanel, this.flipClass);
|
|
399
|
-
this._flip(!isFlipped);
|
|
135
|
+
get reduced() {
|
|
136
|
+
return this.settings.ReducedMotion !== false && !!this.motion?.matches;
|
|
400
137
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
-
}
|
|
138
|
+
configure() {
|
|
139
|
+
const s = this.settings, p = this.hoverPanel;
|
|
140
|
+
p.style.setProperty("--jfi-duration", `${s.Duration}ms`);
|
|
141
|
+
p.style.setProperty("--jfi-easing", s.Easing);
|
|
142
|
+
p.dataset.jfiAxis = s.FlipX ? "x" : "y";
|
|
143
|
+
p.dataset.jfiEffect = s.Effect;
|
|
144
|
+
p.dataset.jfiMotion = s.ReducedMotion === false ? "allow" : "respect";
|
|
145
|
+
for (const item of s.Style || []) {
|
|
146
|
+
const targets = item.el === "self" ? [p] : p.querySelectorAll(item.el);
|
|
147
|
+
targets.forEach((node) => Object.assign(node.style, item.style));
|
|
439
148
|
}
|
|
149
|
+
if (s.Tilt !== "only" && !p.hasAttribute("tabindex")) p.tabIndex = 0;
|
|
440
150
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
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);
|
|
151
|
+
events() {
|
|
152
|
+
this.listen("click", (event) => {
|
|
153
|
+
if (this.settings.Tilt === "only") return;
|
|
154
|
+
const trigger = this.settings.Click;
|
|
155
|
+
if (trigger === true || trigger && [].concat(trigger).some((selector) => event.target.closest?.(selector) && this.hoverPanel.contains(event.target.closest(selector)))) this.toggle();
|
|
465
156
|
});
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
157
|
+
this.listen("keydown", (event) => {
|
|
158
|
+
if (event.target !== this.hoverPanel || this.settings.Tilt === "only") return;
|
|
159
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
this.toggle();
|
|
162
|
+
}
|
|
163
|
+
if (event.key === "Escape") this.flip(false);
|
|
473
164
|
});
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
165
|
+
this.listen("pointerenter", (event) => {
|
|
166
|
+
if (!this.settings.Click && this.settings.Tilt !== "only" && event.pointerType !== "touch") this.flip(true);
|
|
167
|
+
});
|
|
168
|
+
this.listen("pointerleave", (event) => {
|
|
169
|
+
if (event.pointerType === "touch") return;
|
|
170
|
+
this.resetTilt();
|
|
171
|
+
if (!this.settings.Click && this.settings.Tilt !== "only") this.flip(false);
|
|
172
|
+
});
|
|
173
|
+
this.listen("pointerdown", (event) => {
|
|
174
|
+
if (event.pointerType !== "touch" || event.isPrimary === false || this.touch) return;
|
|
175
|
+
this.resetTilt();
|
|
176
|
+
this.touch = { id: event.pointerId, x: event.clientX, y: event.clientY, moved: false };
|
|
177
|
+
this.queueTilt(event, this.touch);
|
|
178
|
+
}, { passive: true });
|
|
179
|
+
this.listen("pointermove", (event) => {
|
|
180
|
+
if (event.pointerType !== "touch") {
|
|
181
|
+
if (!this.touch) this.queueTilt(event);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const touch = this.touch;
|
|
185
|
+
if (!touch || touch.id !== event.pointerId) return;
|
|
186
|
+
touch.moved || (touch.moved = this.touchMoved(event, touch));
|
|
187
|
+
this.queueTilt(event, touch);
|
|
188
|
+
}, { passive: true });
|
|
189
|
+
this.listen("pointerup", (event) => {
|
|
190
|
+
const touch = this.finishTouch(event);
|
|
191
|
+
if (!touch || touch.moved || this.touchMoved(event, touch)) return;
|
|
192
|
+
if (!this.settings.Click && this.settings.Tilt !== "only") this.toggle();
|
|
485
193
|
});
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
194
|
+
this.listen("pointercancel", (event) => {
|
|
195
|
+
if (event.pointerType === "touch") this.finishTouch(event);
|
|
196
|
+
else this.resetTilt();
|
|
197
|
+
});
|
|
198
|
+
this.listen("lostpointercapture", (event) => this.finishTouch(event));
|
|
199
|
+
this.baseTransform = this.hoverPanel.style.transform;
|
|
200
|
+
}
|
|
201
|
+
touchMoved(event, touch) {
|
|
202
|
+
return Math.hypot(event.clientX - touch.x, event.clientY - touch.y) > 10;
|
|
203
|
+
}
|
|
204
|
+
finishTouch(event) {
|
|
205
|
+
const touch = this.touch;
|
|
206
|
+
if (event.pointerType !== "touch" || !touch || touch.id !== event.pointerId) return;
|
|
207
|
+
this.touch = null;
|
|
208
|
+
this.resetTilt();
|
|
209
|
+
return touch;
|
|
210
|
+
}
|
|
211
|
+
queueTilt(event, touch) {
|
|
212
|
+
if (!this.settings.Tilt || this.reduced) return;
|
|
213
|
+
this.point = [event.clientX, event.clientY];
|
|
214
|
+
if (this.frame) return;
|
|
215
|
+
this.frame = this.win.requestAnimationFrame(() => {
|
|
216
|
+
this.frame = 0;
|
|
217
|
+
const rect = touch ? touch.rect ?? (touch.rect = this.hoverPanel.getBoundingClientRect()) : this.hoverPanel.getBoundingClientRect();
|
|
218
|
+
if (!rect.width || !rect.height) return;
|
|
219
|
+
const { max = 10, perspective = 1e3, scale = 1.03 } = this.settings.Tilt;
|
|
220
|
+
const x = Math.max(-1, Math.min(1, (this.point[0] - rect.left) / rect.width * 2 - 1));
|
|
221
|
+
const y = Math.max(-1, Math.min(1, (this.point[1] - rect.top) / rect.height * 2 - 1));
|
|
222
|
+
this.hoverPanel.style.transform = `perspective(${perspective}px) rotateX(${-y * max}deg) rotateY(${x * max}deg) scale(${scale})`;
|
|
495
223
|
});
|
|
496
224
|
}
|
|
225
|
+
resetTilt() {
|
|
226
|
+
if (this.frame) this.win.cancelAnimationFrame(this.frame);
|
|
227
|
+
this.frame = 0;
|
|
228
|
+
this.hoverPanel.style.transform = this.baseTransform || "";
|
|
229
|
+
}
|
|
230
|
+
render() {
|
|
231
|
+
this.hoverPanel.dataset.jfiFlipped = String(this.flipped);
|
|
232
|
+
this.hoverPanel.dataset.jfiReduced = String(this.reduced);
|
|
233
|
+
for (const [node, hidden] of [[this.frontWrapper, this.flipped], [this.backWrapper, !this.flipped]]) {
|
|
234
|
+
node.setAttribute("aria-hidden", String(hidden));
|
|
235
|
+
node.inert = hidden;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
flip(value = true) {
|
|
239
|
+
if (this.destroyed || this.flipped === !!value) return this;
|
|
240
|
+
const active = this.element.ownerDocument.activeElement;
|
|
241
|
+
if ((value ? this.frontWrapper : this.backWrapper).contains(active)) this.hoverPanel.focus({ preventScroll: true });
|
|
242
|
+
this.flipped = !!value;
|
|
243
|
+
this.render();
|
|
244
|
+
this.hoverPanel.dispatchEvent(new this.win.CustomEvent("justflipit:change", { bubbles: true, detail: this.getState() }));
|
|
245
|
+
return this;
|
|
246
|
+
}
|
|
247
|
+
toggle() {
|
|
248
|
+
return this.flip(!this.flipped);
|
|
249
|
+
}
|
|
250
|
+
update(options = {}) {
|
|
251
|
+
if (this.destroyed) return this;
|
|
252
|
+
if ("Faces" in options) throw new TypeError("Faces cannot change after initialization");
|
|
253
|
+
validate(options);
|
|
254
|
+
if (this.managed && "Template" in options) throw new TypeError("Render framework face content with the framework");
|
|
255
|
+
this.settings = { ...this.settings, ...options };
|
|
256
|
+
if ("Template" in options) {
|
|
257
|
+
if (this.managed) throw new TypeError("Render framework face content with the framework");
|
|
258
|
+
this.backWrapper.innerHTML = options.Template;
|
|
259
|
+
}
|
|
260
|
+
this.resetTilt();
|
|
261
|
+
this.configure();
|
|
262
|
+
this.render();
|
|
263
|
+
return this;
|
|
264
|
+
}
|
|
265
|
+
getState() {
|
|
266
|
+
return { flipped: this.flipped, destroyed: this.destroyed, effect: this.settings.Effect };
|
|
267
|
+
}
|
|
268
|
+
destroy() {
|
|
269
|
+
if (this.destroyed) return;
|
|
270
|
+
this.resetTilt();
|
|
271
|
+
this.cleanups.forEach((fn) => fn());
|
|
272
|
+
this.restores.forEach((fn) => fn());
|
|
273
|
+
if (!this.managed) {
|
|
274
|
+
this.hoverPanel.replaceWith(this.element);
|
|
275
|
+
}
|
|
276
|
+
instances.delete(this.element);
|
|
277
|
+
instances.delete(this.hoverPanel);
|
|
278
|
+
this.destroyed = true;
|
|
279
|
+
}
|
|
497
280
|
};
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
281
|
+
function elements(target) {
|
|
282
|
+
if (typeof target === "string") return typeof document === "undefined" ? [] : Array.from(document.querySelectorAll(target));
|
|
283
|
+
if (target?.nodeType === 1) return [target];
|
|
284
|
+
return target ? Array.from(target) : [];
|
|
285
|
+
}
|
|
286
|
+
function justFlipIt(target, options) {
|
|
287
|
+
const result = elements(target).map((element) => instances.get(element) || new FlipController(element, options));
|
|
288
|
+
return target?.nodeType === 1 ? result[0] : result;
|
|
289
|
+
}
|
|
290
|
+
justFlipIt.destroy = (target) => elements(target).forEach((element) => instances.get(element)?.destroy());
|
|
291
|
+
justFlipIt.get = (element) => instances.get(element);
|
|
292
|
+
return __toCommonJS(core_exports);
|
|
293
|
+
})();
|
|
294
|
+
globalThis.justFlipIt = JustFlipItModule.default;
|
|
295
|
+
//# sourceMappingURL=justFlipIt.js.map
|