@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,366 +1,295 @@
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
- function addStyles() {
23
- if (document.querySelector('[data-justflipitstyle="justFlipIt_One"]')) {
24
- return;
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 });
25
15
  }
26
- const styleX = document.createElement("style");
27
- styleX.setAttribute("data-justflipitstyle", "justFlipIt_One");
28
- styleX.textContent =
29
- "._justFlipIt_panel {perspective:1000px;-webkit-perspective:1000px;-moz-perspective:1000px;}" +
30
- "._justFlipIt_panel .front{height:inherit;width:inherit;position:absolute;top:0;z-index:900;-webkit-transform:rotateX(0) rotateX(0);-moz-transform:rotateX(0) rotateX(0);-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-webkit-transition:all .4s ease-in-out;-moz-transition:all .4s ease-in-out;-ms-transition:all .4s ease-in-out;-o-transition:all .4s ease-in-out;transition:all .4s ease-in-out}" +
31
- "._justFlipIt_panel .back{height:inherit;width:inherit;position:absolute;top:0;z-index:1000;-webkit-transform:rotateX(-180deg);-moz-transform:rotateX(-180deg);-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-webkit-transition:all .4s ease-in-out;-moz-transition:all .4s ease-in-out;-ms-transition:all .4s ease-in-out;-o-transition:all .4s ease-in-out;transition:all .4s ease-in-out}" +
32
- "._justFlipIt_panel._flip_ .front{z-index:900;-webkit-transform:rotateX(180deg);-moz-transform:rotateX(180deg)}" +
33
- "._justFlipIt_panel._flip_ .back{z-index:1000;-webkit-transform:rotateX(0) rotateX(0);-moz-transform:rotateX(0) rotateX(0)}";
34
- const styleY = document.createElement("style");
35
- styleY.setAttribute("data-justflipitstyle", "justFlipIt_Two");
36
- styleY.textContent =
37
- "._justFlipIt_panel .backY{height:inherit;width:inherit;position:absolute;top:0;z-index:1000;-webkit-transform:rotateY(-180deg);-moz-transform:rotateY(-180deg);-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-webkit-transition:all .4s ease-in-out;-moz-transition:all .4s ease-in-out;-ms-transition:all .4s ease-in-out;-o-transition:all .4s ease-in-out;transition:all .4s ease-in-out}" +
38
- "._justFlipIt_panel._flipY_ .front{z-index:900;-webkit-transform:rotateY(180deg);-moz-transform:rotateY(180deg)}" +
39
- "._justFlipIt_panel._flipY_ .backY{z-index:1000;-webkit-transform:rotateX(0) rotateY(0);-moz-transform:rotateX(0) rotateY(0)}";
40
-
41
- // PATCH: Füge Transparency-Style hinzu
42
- const styleTransparent = document.createElement("style");
43
- styleTransparent.setAttribute(
44
- "data-justflipitstyle",
45
- "justFlipIt_Transparent",
46
- );
47
- styleTransparent.textContent =
48
- "._justFlipIt_panel {background: transparent !important; box-shadow: none !important;}" +
49
- "._justFlipIt_panel > * {box-sizing: border-box;}";
50
-
51
- document.head.appendChild(styleX);
52
- document.head.appendChild(styleY);
53
- document.head.appendChild(styleTransparent);
54
- }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
55
19
 
56
- function getStyle(element, property) {
57
- return window.getComputedStyle(element, null).getPropertyValue(property);
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);
58
55
  }
59
- function addClass(element, className) {
60
- if (element.classList) {
61
- element.classList.add(className);
62
- } else {
63
- element.className += " " + className;
64
- }
65
- }
66
- function removeClass(element, className) {
67
- if (element.classList) {
68
- element.classList.remove(className);
69
- } else {
70
- element.className = element.className.replace(
71
- new RegExp(
72
- "(^|\\b)" + className.split(" ").join("|") + "(\\b|$)",
73
- "gi",
74
- ),
75
- " ",
76
- );
77
- }
78
- }
79
- function toggleClass(element, className) {
80
- if (element.classList) {
81
- element.classList.toggle(className);
82
- } else {
83
- var classes = element.className.split(" ");
84
- var existingIndex = classes.indexOf(className);
85
- if (existingIndex >= 0) {
86
- classes.splice(existingIndex, 1);
87
- } else {
88
- classes.push(className);
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}`);
89
62
  }
90
- element.className = classes.join(" ");
91
63
  }
92
64
  }
93
- function hasClass(element, className) {
94
- if (element.classList) {
95
- return element.classList.contains(className);
96
- } else {
97
- return new RegExp("(^| )" + className + "( |$)", "gi").test(
98
- element.className,
99
- );
100
- }
101
- }
102
-
103
- // PATCH: Verbesserte Style-Kopierfunktion
104
- function copyStyles(src, dest) {
105
- const computed = window.getComputedStyle(src);
106
- // Kopiere alle visuellen Eigenschaften
107
- const properties = [
108
- "background",
109
- "backgroundColor",
110
- "backgroundImage",
111
- "backgroundPosition",
112
- "backgroundRepeat",
113
- "backgroundSize",
114
- "borderRadius",
115
- "borderTopLeftRadius",
116
- "borderTopRightRadius",
117
- "borderBottomLeftRadius",
118
- "borderBottomRightRadius",
119
- "border",
120
- "borderTop",
121
- "borderRight",
122
- "borderBottom",
123
- "borderLeft",
124
- "boxShadow",
125
- "color",
126
- "opacity",
127
- ];
128
- properties.forEach((prop) => {
129
- if (
130
- computed[prop] &&
131
- computed[prop] !== "none" &&
132
- computed[prop] !== "initial" &&
133
- computed[prop] !== ""
134
- ) {
135
- dest.style[prop] = computed[prop];
136
- }
137
- });
138
- }
139
-
140
- // NEU: Funktion zur Anwendung der benutzerdefinierten Animationseinstellungen
141
- function applyAnimationSettings(element, duration, easing) {
142
- const transitionValue = `all ${duration / 1000}s ${easing}`;
143
- element.style.transition = transitionValue;
144
- element.style.WebkitTransition = transitionValue;
145
- element.style.MozTransition = transitionValue;
146
- element.style.msTransition = transitionValue;
147
- element.style.OTransition = transitionValue;
148
- }
149
-
150
- const instanceMap = new WeakMap();
151
-
152
- class JustFlipIt {
65
+ var FlipController = class {
153
66
  constructor(element, options = {}) {
154
- addStyles();
67
+ validate(options);
68
+ if (!element || element.nodeType !== 1) throw new TypeError("Expected an HTML element");
155
69
  this.element = element;
156
- this.settings = Object.assign(
157
- {},
158
- {
159
- Template: "",
160
- Click: false,
161
- FlipX: false,
162
- Style: [],
163
- Duration: 400,
164
- Easing: "ease-in-out",
165
- preserveClasses: true, // NEU
166
- preserveStyles: true, // NEU
167
- },
168
- options,
169
- );
170
- this.elementWidth = getStyle(element, "width");
171
- this.elementHeight = getStyle(element, "height");
172
- this.elementBackgroundColor = getStyle(element, "background-color");
173
- this.originalClassName = element.className;
174
- this.originalTagName = element.tagName.toLowerCase();
175
- this.originalId = element.id || "";
176
- if (this.settings.FlipX === true) {
177
- this.flipClass = "_flip_";
178
- this.backClass = "back";
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");
179
84
  } else {
180
- this.flipClass = "_flipY_";
181
- this.backClass = "backY";
182
- }
183
- this._init();
184
- if (this.settings.Tilt) {
185
- this._setupTilt();
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
+ }
186
101
  }
187
- instanceMap.set(element, this);
188
- }
189
-
190
- _init() {
191
- const originalElement = this.element;
192
- const originalClassName = this.originalClassName;
193
-
194
- // Panel-Struktur erzeugen
195
- const hoverPanel = document.createElement(this.originalTagName);
196
- addClass(hoverPanel, "hover");
197
- addClass(hoverPanel, "_justFlipIt_panel");
198
- const frontWrapper = document.createElement("div");
199
- addClass(frontWrapper, "front");
200
- const backWrapper = document.createElement("div");
201
- addClass(backWrapper, this.backClass);
202
-
203
- // NEU: Klassen übernehmen (Panel, .front, .backY)
204
- if (this.settings.preserveClasses && originalElement.classList.length) {
205
- originalElement.classList.forEach((cls) => {
206
- if (!hoverPanel.classList.contains(cls)) {
207
- hoverPanel.classList.add(cls);
208
- }
209
- if (frontWrapper && !frontWrapper.classList.contains(cls)) {
210
- frontWrapper.classList.add(cls);
211
- }
212
- if (backWrapper && !backWrapper.classList.contains(cls)) {
213
- backWrapper.classList.add(cls);
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);
214
112
  }
215
113
  });
216
114
  }
217
-
218
- // NEU: Inline-Styles übernehmen (nur auf Panel)
219
- if (
220
- this.settings.preserveStyles && originalElement.getAttribute("style")
221
- ) {
222
- hoverPanel.setAttribute(
223
- "style",
224
- (hoverPanel.getAttribute("style") || "") +
225
- ";" + originalElement.getAttribute("style"),
226
- );
227
- }
228
-
229
- // Nur den INHALT übernehmen!
230
- frontWrapper.innerHTML = originalElement.innerHTML;
231
-
232
- if (this.settings.Template) {
233
- backWrapper.innerHTML = this.settings.Template;
234
- } else {
235
- backWrapper.innerHTML = originalElement.innerHTML;
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();
122
+ };
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);
130
+ }
131
+ listen(type, handler, options) {
132
+ this.hoverPanel.addEventListener(type, handler, options);
133
+ this.cleanups.push(() => this.hoverPanel.removeEventListener(type, handler, options));
134
+ }
135
+ get reduced() {
136
+ return this.settings.ReducedMotion !== false && !!this.motion?.matches;
137
+ }
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));
236
148
  }
237
-
238
- // Panel einfügen und Original entfernen
239
- originalElement.parentNode.insertBefore(hoverPanel, originalElement);
240
- hoverPanel.appendChild(frontWrapper);
241
- hoverPanel.appendChild(backWrapper);
242
- originalElement.parentNode.removeChild(originalElement);
243
-
244
- // Panel-Größe und Styles übernehmen
245
- hoverPanel.style.width = this.elementWidth;
246
- hoverPanel.style.height = this.elementHeight;
247
-
248
- // Custom Styles aus Option anwenden
249
- if (this.settings.Style && this.settings.Style.length) {
250
- this.settings.Style.forEach((styleObj) => {
251
- if (styleObj.el) {
252
- if (styleObj.el.toLowerCase() === "self") {
253
- Object.assign(hoverPanel.style, styleObj.style);
254
- } else {
255
- const targetElements = hoverPanel.querySelectorAll(styleObj.el);
256
- targetElements.forEach((el) => {
257
- Object.assign(el.style, styleObj.style);
258
- });
259
- }
260
- }
261
- });
149
+ if (s.Tilt !== "only" && !p.hasAttribute("tabindex")) p.tabIndex = 0;
150
+ }
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();
156
+ });
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);
164
+ });
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();
193
+ });
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})`;
223
+ });
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;
262
236
  }
263
-
264
- // Events setzen
265
- this._setupEvents(hoverPanel);
266
-
267
- // Referenzen speichern
268
- this.hoverPanel = hoverPanel;
269
- this.frontWrapper = frontWrapper;
270
- this.backWrapper = backWrapper;
271
237
  }
272
-
273
- _setupTilt() {
274
- const handleMove = (e) => {
275
- const rect = this.hoverPanel.getBoundingClientRect();
276
- const x = (e.touches ? e.touches[0].clientX : e.clientX) - rect.left;
277
- const y = (e.touches ? e.touches[0].clientY : e.clientY) - rect.top;
278
- const centerX = rect.width / 2;
279
- const centerY = rect.height / 2;
280
- const rotateX = ((y - centerY) / centerY) * 10;
281
- const rotateY = (-(x - centerX) / centerX) * 10;
282
- this.hoverPanel.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.05, 1.05, 1.05)`;
283
- };
284
-
285
- const handleEnter = () => {
286
- this.hoverPanel.style.transition = "all 0.2s ease-out";
287
- };
288
-
289
- const handleLeave = () => {
290
- this.hoverPanel.style.transform = `perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)`;
291
- this.hoverPanel.style.transition = "all 0.5s ease-in-out";
292
- };
293
-
294
- this.hoverPanel.addEventListener("mousemove", handleMove);
295
- this.hoverPanel.addEventListener("touchmove", handleMove);
296
- this.hoverPanel.addEventListener("mouseenter", handleEnter);
297
- this.hoverPanel.addEventListener("touchstart", handleEnter);
298
- this.hoverPanel.addEventListener("mouseleave", handleLeave);
299
- this.hoverPanel.addEventListener("touchend", handleLeave);
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;
300
246
  }
301
-
302
- _setupEvents(hoverPanel) {
303
- if (this.settings.Tilt === 'only') return;
304
- if (this.settings.Click === true) {
305
- hoverPanel.addEventListener("click", (e) => {
306
- e.preventDefault();
307
- toggleClass(hoverPanel, this.flipClass);
308
- });
309
- } else if (typeof this.settings.Click === "string") {
310
- const clickElements = hoverPanel.querySelectorAll(this.settings.Click);
311
- clickElements.forEach((el) => {
312
- el.addEventListener("click", () => {
313
- toggleClass(hoverPanel, this.flipClass);
314
- });
315
- });
316
- } else {
317
- hoverPanel.addEventListener("mouseenter", () => {
318
- addClass(hoverPanel, this.flipClass);
319
- });
320
- hoverPanel.addEventListener("mouseleave", () => {
321
- removeClass(hoverPanel, this.flipClass);
322
- });
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;
323
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 };
324
267
  }
325
-
326
268
  destroy() {
327
- const hoverPanel = this.hoverPanel;
328
- const originalElement = hoverPanel.querySelector(".front > *");
329
- originalElement.className = this.originalClassName;
330
- hoverPanel.parentNode.insertBefore(originalElement, hoverPanel);
331
- hoverPanel.parentNode.removeChild(hoverPanel);
332
- instanceMap.delete(this.element);
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;
333
279
  }
280
+ };
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) : [];
334
285
  }
335
-
336
- function justFlipIt(selector, options = {}) {
337
- if (typeof selector === "string") {
338
- const elements = document.querySelectorAll(selector);
339
- return Array.from(elements).map((el) => new JustFlipIt(el, options));
340
- } else if (selector instanceof Element) {
341
- return new JustFlipIt(selector, options);
342
- } else if (selector.length) {
343
- return Array.from(selector).map((el) => new JustFlipIt(el, options));
344
- }
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;
345
289
  }
346
-
347
- justFlipIt.destroy = function (selector) {
348
- if (typeof selector === "string") {
349
- const elements = document.querySelectorAll(selector);
350
- Array.from(elements).forEach((el) => {
351
- const instance = instanceMap.get(el);
352
- if (instance) instance.destroy();
353
- });
354
- } else if (selector instanceof Element) {
355
- const instance = instanceMap.get(selector);
356
- if (instance) instance.destroy();
357
- } else if (selector.length) {
358
- Array.from(selector).forEach((el) => {
359
- const instance = instanceMap.get(el);
360
- if (instance) instance.destroy();
361
- });
362
- }
363
- };
364
-
365
- return justFlipIt;
366
- });
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