@simhub2/justflipit 4.0.0 → 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.
@@ -4,14 +4,16 @@ var defaults = { Click: false, FlipX: false, Duration: 400, Easing: "cubic-bezie
4
4
  var css = `
5
5
  ._justFlipIt_panel{position:relative;display:grid;perspective:var(--jfi-perspective,1000px);isolation:isolate}
6
6
  ._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}
7
- ._justFlipIt_panel>[data-jfi-face=front]{transform:rotateY(0deg)}
8
- ._justFlipIt_panel>[data-jfi-face=back]{transform:rotateY(-180deg);pointer-events:none}
9
- ._justFlipIt_panel[data-jfi-flipped=true]>[data-jfi-face=front]{transform:rotateY(180deg);pointer-events:none}
10
- ._justFlipIt_panel[data-jfi-flipped=true]>[data-jfi-face=back]{transform:rotateY(0deg);pointer-events:auto}
11
- ._justFlipIt_panel[data-jfi-axis=x]>[data-jfi-face=back]{transform:rotateX(-180deg)}
12
- ._justFlipIt_panel[data-jfi-axis=x][data-jfi-flipped=true]>[data-jfi-face=front]{transform:rotateX(180deg)}
13
- ._justFlipIt_panel[data-jfi-axis=x][data-jfi-flipped=true]>[data-jfi-face=back]{transform:rotateX(0deg)}
14
- ._justFlipIt_panel[data-jfi-effect=fade]>[data-jfi-face],._justFlipIt_panel[data-jfi-effect=scale]>[data-jfi-face]{transform:none}
7
+ ._justFlipIt_panel>[data-jfi-face=back],._justFlipIt_panel[data-jfi-flipped=true]>[data-jfi-face=front]{pointer-events:none}
8
+ ._justFlipIt_panel[data-jfi-flipped=true]>[data-jfi-face=back]{pointer-events:auto}
9
+ ._justFlipIt_panel[data-jfi-effect=flip]>[data-jfi-face=front]{transform:rotateY(0deg)}
10
+ ._justFlipIt_panel[data-jfi-effect=flip]>[data-jfi-face=back]{transform:rotateY(-180deg)}
11
+ ._justFlipIt_panel[data-jfi-effect=flip][data-jfi-flipped=true]>[data-jfi-face=front]{transform:rotateY(180deg)}
12
+ ._justFlipIt_panel[data-jfi-effect=flip][data-jfi-flipped=true]>[data-jfi-face=back]{transform:rotateY(0deg)}
13
+ ._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x]>[data-jfi-face=front]{transform:rotateX(0deg)}
14
+ ._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x]>[data-jfi-face=back]{transform:rotateX(-180deg)}
15
+ ._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x][data-jfi-flipped=true]>[data-jfi-face=front]{transform:rotateX(180deg)}
16
+ ._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x][data-jfi-flipped=true]>[data-jfi-face=back]{transform:rotateX(0deg)}
15
17
  ._justFlipIt_panel[data-jfi-effect=fade]>[data-jfi-face=back],._justFlipIt_panel[data-jfi-effect=scale]>[data-jfi-face=back]{opacity:0}
16
18
  ._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}
17
19
  ._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}
@@ -139,33 +141,63 @@ var FlipController = class {
139
141
  this.listen("pointerenter", (event) => {
140
142
  if (!this.settings.Click && this.settings.Tilt !== "only" && event.pointerType !== "touch") this.flip(true);
141
143
  });
142
- this.listen("pointerleave", () => {
144
+ this.listen("pointerleave", (event) => {
145
+ if (event.pointerType === "touch") return;
143
146
  this.resetTilt();
144
147
  if (!this.settings.Click && this.settings.Tilt !== "only") this.flip(false);
145
148
  });
146
- this.listen("pointercancel", () => this.resetTilt());
147
- this.listen("pointerup", (event) => {
148
- if (event.pointerType === "touch") {
149
- this.resetTilt();
150
- if (!this.settings.Click && this.settings.Tilt !== "only") this.toggle();
151
- }
152
- });
149
+ this.listen("pointerdown", (event) => {
150
+ if (event.pointerType !== "touch" || event.isPrimary === false || this.touch) return;
151
+ this.resetTilt();
152
+ this.touch = { id: event.pointerId, x: event.clientX, y: event.clientY, moved: false };
153
+ this.queueTilt(event, this.touch);
154
+ }, { passive: true });
153
155
  this.listen("pointermove", (event) => {
154
- if (!this.settings.Tilt || this.reduced || event.pointerType === "touch") return;
155
- this.point = [event.clientX, event.clientY];
156
- if (this.frame) return;
157
- this.frame = this.win.requestAnimationFrame(() => {
158
- this.frame = 0;
159
- const rect = this.hoverPanel.getBoundingClientRect();
160
- if (!rect.width || !rect.height) return;
161
- const t = { max: 10, perspective: 1e3, scale: 1.03, ...typeof this.settings.Tilt === "object" ? this.settings.Tilt : {} };
162
- const x = Math.max(-1, Math.min(1, (this.point[0] - rect.left) / rect.width * 2 - 1));
163
- const y = Math.max(-1, Math.min(1, (this.point[1] - rect.top) / rect.height * 2 - 1));
164
- this.hoverPanel.style.transform = `perspective(${t.perspective}px) rotateX(${-y * t.max}deg) rotateY(${x * t.max}deg) scale(${t.scale})`;
165
- });
156
+ if (event.pointerType !== "touch") {
157
+ if (!this.touch) this.queueTilt(event);
158
+ return;
159
+ }
160
+ const touch = this.touch;
161
+ if (!touch || touch.id !== event.pointerId) return;
162
+ touch.moved || (touch.moved = this.touchMoved(event, touch));
163
+ this.queueTilt(event, touch);
166
164
  }, { passive: true });
165
+ this.listen("pointerup", (event) => {
166
+ const touch = this.finishTouch(event);
167
+ if (!touch || touch.moved || this.touchMoved(event, touch)) return;
168
+ if (!this.settings.Click && this.settings.Tilt !== "only") this.toggle();
169
+ });
170
+ this.listen("pointercancel", (event) => {
171
+ if (event.pointerType === "touch") this.finishTouch(event);
172
+ else this.resetTilt();
173
+ });
174
+ this.listen("lostpointercapture", (event) => this.finishTouch(event));
167
175
  this.baseTransform = this.hoverPanel.style.transform;
168
176
  }
177
+ touchMoved(event, touch) {
178
+ return Math.hypot(event.clientX - touch.x, event.clientY - touch.y) > 10;
179
+ }
180
+ finishTouch(event) {
181
+ const touch = this.touch;
182
+ if (event.pointerType !== "touch" || !touch || touch.id !== event.pointerId) return;
183
+ this.touch = null;
184
+ this.resetTilt();
185
+ return touch;
186
+ }
187
+ queueTilt(event, touch) {
188
+ if (!this.settings.Tilt || this.reduced) return;
189
+ this.point = [event.clientX, event.clientY];
190
+ if (this.frame) return;
191
+ this.frame = this.win.requestAnimationFrame(() => {
192
+ this.frame = 0;
193
+ const rect = touch ? touch.rect ?? (touch.rect = this.hoverPanel.getBoundingClientRect()) : this.hoverPanel.getBoundingClientRect();
194
+ if (!rect.width || !rect.height) return;
195
+ const { max = 10, perspective = 1e3, scale = 1.03 } = this.settings.Tilt;
196
+ const x = Math.max(-1, Math.min(1, (this.point[0] - rect.left) / rect.width * 2 - 1));
197
+ const y = Math.max(-1, Math.min(1, (this.point[1] - rect.top) / rect.height * 2 - 1));
198
+ this.hoverPanel.style.transform = `perspective(${perspective}px) rotateX(${-y * max}deg) rotateY(${x * max}deg) scale(${scale})`;
199
+ });
200
+ }
169
201
  resetTilt() {
170
202
  if (this.frame) this.win.cancelAnimationFrame(this.frame);
171
203
  this.frame = 0;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/core.js"],
4
- "sourcesContent": ["const instances = new WeakMap();\nconst 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: [] };\nconst css = `\n._justFlipIt_panel{position:relative;display:grid;perspective:var(--jfi-perspective,1000px);isolation:isolate}\n._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}\n._justFlipIt_panel>[data-jfi-face=front]{transform:rotateY(0deg)}\n._justFlipIt_panel>[data-jfi-face=back]{transform:rotateY(-180deg);pointer-events:none}\n._justFlipIt_panel[data-jfi-flipped=true]>[data-jfi-face=front]{transform:rotateY(180deg);pointer-events:none}\n._justFlipIt_panel[data-jfi-flipped=true]>[data-jfi-face=back]{transform:rotateY(0deg);pointer-events:auto}\n._justFlipIt_panel[data-jfi-axis=x]>[data-jfi-face=back]{transform:rotateX(-180deg)}\n._justFlipIt_panel[data-jfi-axis=x][data-jfi-flipped=true]>[data-jfi-face=front]{transform:rotateX(180deg)}\n._justFlipIt_panel[data-jfi-axis=x][data-jfi-flipped=true]>[data-jfi-face=back]{transform:rotateX(0deg)}\n._justFlipIt_panel[data-jfi-effect=fade]>[data-jfi-face],._justFlipIt_panel[data-jfi-effect=scale]>[data-jfi-face]{transform:none}\n._justFlipIt_panel[data-jfi-effect=fade]>[data-jfi-face=back],._justFlipIt_panel[data-jfi-effect=scale]>[data-jfi-face=back]{opacity:0}\n._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}\n._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}\n._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)}\n._justFlipIt_panel[data-jfi-effect=scale][data-jfi-flipped=true]>[data-jfi-face=back]{transform:scale(1)}\n._justFlipIt_panel[data-jfi-reduced=true]>[data-jfi-face]{transition:none!important}\n@media(prefers-reduced-motion:reduce){._justFlipIt_panel:not([data-jfi-motion=allow])>[data-jfi-face]{transition:none!important}}\n`;\nfunction styles(doc) {\n if (doc.querySelector('style[data-justflipitstyle=\"v4\"]')) return;\n const style = doc.createElement('style');\n style.dataset.justflipitstyle = 'v4'; style.textContent = css; doc.head.append(style);\n}\nfunction validate(options) {\n if (options.Duration !== undefined && (!Number.isFinite(options.Duration) || options.Duration < 0)) throw new TypeError('Duration must be a non-negative finite number');\n if (options.Effect !== undefined && !['flip', 'fade', 'scale'].includes(options.Effect)) throw new TypeError('Unknown Effect');\n if (options.Tilt && typeof options.Tilt === 'object') {\n for (const key of ['max', 'perspective', 'scale']) {\n if (options.Tilt[key] !== undefined && (!Number.isFinite(options.Tilt[key]) || options.Tilt[key] < 0)) throw new TypeError(`Invalid Tilt.${key}`);\n }\n }\n}\nexport class FlipController {\n constructor(element, options = {}) {\n validate(options);\n if (!element || element.nodeType !== 1) throw new TypeError('Expected an HTML element');\n this.element = element; this.settings = { ...defaults, ...options }; this.flipped = false; this.destroyed = false;\n this.cleanups = []; this.restores = []; this.win = element.ownerDocument.defaultView;\n const doc = element.ownerDocument; styles(doc);\n this.managed = !!options.Faces;\n if (this.managed) {\n this.hoverPanel = element;\n this.frontWrapper = element.querySelector(options.Faces.front);\n this.backWrapper = element.querySelector(options.Faces.back);\n 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');\n } else {\n if (!element.parentNode) throw new TypeError('Element must have a parent');\n this.hoverPanel = doc.createElement('div');\n this.frontWrapper = doc.createElement('div'); this.backWrapper = doc.createElement('div');\n if (this.settings.preserveClasses) this.hoverPanel.className = element.className;\n if (this.settings.preserveStyles) this.hoverPanel.style.cssText = element.style.cssText;\n element.before(this.hoverPanel); this.hoverPanel.append(this.frontWrapper, this.backWrapper);\n this.frontWrapper.append(element);\n if (options.Template !== undefined) this.backWrapper.innerHTML = options.Template;\n else {\n const clone = element.cloneNode(true);\n clone.removeAttribute('id'); clone.querySelectorAll('[id]').forEach(node => node.removeAttribute('id'));\n this.backWrapper.append(clone);\n }\n }\n const panel = this.hoverPanel;\n for (const node of [panel, this.frontWrapper, this.backWrapper]) {\n 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'];\n const attrs = owned.map(name => [name, node.getAttribute(name)]);\n const inert = node.inert || false;\n this.restores.push(() => { node.inert = inert; for (const [name, value] of attrs) { if (value === null) node.removeAttribute(name); else node.setAttribute(name, value); } });\n }\n panel.classList.add('_justFlipIt_panel');\n this.frontWrapper.dataset.jfiFace = 'front'; this.backWrapper.dataset.jfiFace = 'back';\n this.motion = this.win.matchMedia?.('(prefers-reduced-motion: reduce)');\n const motionChange = () => { this.resetTilt(); this.render(); };\n this.motion?.addEventListener('change', motionChange);\n this.cleanups.push(() => this.motion?.removeEventListener('change', motionChange));\n this.configure(); this.events(); this.render();\n instances.set(element, this); instances.set(panel, this);\n }\n listen(type, handler, options) { this.hoverPanel.addEventListener(type, handler, options); this.cleanups.push(() => this.hoverPanel.removeEventListener(type, handler, options)); }\n get reduced() { return this.settings.ReducedMotion !== false && !!this.motion?.matches; }\n configure() {\n const s = this.settings, p = this.hoverPanel;\n p.style.setProperty('--jfi-duration', `${s.Duration}ms`); p.style.setProperty('--jfi-easing', s.Easing);\n p.dataset.jfiAxis = s.FlipX ? 'x' : 'y'; p.dataset.jfiEffect = s.Effect;\n p.dataset.jfiMotion = s.ReducedMotion === false ? 'allow' : 'respect';\n for (const item of s.Style || []) {\n const targets = item.el === 'self' ? [p] : p.querySelectorAll(item.el);\n targets.forEach(node => Object.assign(node.style, item.style));\n }\n // A generic keyboard focus target avoids button roles around interactive children.\n if (s.Tilt !== 'only' && !p.hasAttribute('tabindex')) p.tabIndex = 0;\n }\n events() {\n this.listen('click', event => {\n if (this.settings.Tilt === 'only') return;\n const trigger = this.settings.Click;\n if (trigger === true || (trigger && [].concat(trigger).some(selector => event.target.closest?.(selector) && this.hoverPanel.contains(event.target.closest(selector))))) this.toggle();\n });\n this.listen('keydown', event => {\n if (event.target !== this.hoverPanel || this.settings.Tilt === 'only') return;\n if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.toggle(); }\n if (event.key === 'Escape') this.flip(false);\n });\n this.listen('pointerenter', event => { if (!this.settings.Click && this.settings.Tilt !== 'only' && event.pointerType !== 'touch') this.flip(true); });\n this.listen('pointerleave', () => { this.resetTilt(); if (!this.settings.Click && this.settings.Tilt !== 'only') this.flip(false); });\n this.listen('pointercancel', () => this.resetTilt());\n this.listen('pointerup', event => { if (event.pointerType === 'touch') { this.resetTilt(); if (!this.settings.Click && this.settings.Tilt !== 'only') this.toggle(); } });\n this.listen('pointermove', event => {\n if (!this.settings.Tilt || this.reduced || event.pointerType === 'touch') return;\n this.point = [event.clientX, event.clientY];\n if (this.frame) return;\n this.frame = this.win.requestAnimationFrame(() => {\n this.frame = 0;\n const rect = this.hoverPanel.getBoundingClientRect();\n if (!rect.width || !rect.height) return;\n const t = { max: 10, perspective: 1000, scale: 1.03, ...(typeof this.settings.Tilt === 'object' ? this.settings.Tilt : {}) };\n const x = Math.max(-1, Math.min(1, (this.point[0] - rect.left) / rect.width * 2 - 1));\n const y = Math.max(-1, Math.min(1, (this.point[1] - rect.top) / rect.height * 2 - 1));\n this.hoverPanel.style.transform = `perspective(${t.perspective}px) rotateX(${-y * t.max}deg) rotateY(${x * t.max}deg) scale(${t.scale})`;\n });\n }, { passive: true });\n this.baseTransform = this.hoverPanel.style.transform;\n }\n resetTilt() { if (this.frame) this.win.cancelAnimationFrame(this.frame); this.frame = 0; this.hoverPanel.style.transform = this.baseTransform || ''; }\n render() {\n this.hoverPanel.dataset.jfiFlipped = String(this.flipped); this.hoverPanel.dataset.jfiReduced = String(this.reduced);\n for (const [node, hidden] of [[this.frontWrapper, this.flipped], [this.backWrapper, !this.flipped]]) { node.setAttribute('aria-hidden', String(hidden)); node.inert = hidden; }\n }\n flip(value = true) {\n if (this.destroyed || this.flipped === !!value) return this;\n const active = this.element.ownerDocument.activeElement;\n if ((value ? this.frontWrapper : this.backWrapper).contains(active)) this.hoverPanel.focus({ preventScroll: true });\n this.flipped = !!value; this.render();\n this.hoverPanel.dispatchEvent(new this.win.CustomEvent('justflipit:change', { bubbles: true, detail: this.getState() }));\n return this;\n }\n toggle() { return this.flip(!this.flipped); }\n update(options = {}) {\n if (this.destroyed) return this;\n if ('Faces' in options) throw new TypeError('Faces cannot change after initialization');\n validate(options);\n if (this.managed && 'Template' in options) throw new TypeError('Render framework face content with the framework');\n this.settings = { ...this.settings, ...options };\n if ('Template' in options) {\n if (this.managed) throw new TypeError('Render framework face content with the framework');\n this.backWrapper.innerHTML = options.Template;\n }\n this.resetTilt(); this.configure(); this.render(); return this;\n }\n getState() { return { flipped: this.flipped, destroyed: this.destroyed, effect: this.settings.Effect }; }\n destroy() {\n if (this.destroyed) return;\n this.resetTilt(); this.cleanups.forEach(fn => fn());\n this.restores.forEach(fn => fn());\n if (!this.managed) { this.hoverPanel.replaceWith(this.element); }\n instances.delete(this.element); instances.delete(this.hoverPanel); this.destroyed = true;\n }\n}\nfunction elements(target) {\n if (typeof target === 'string') return typeof document === 'undefined' ? [] : Array.from(document.querySelectorAll(target));\n if (target?.nodeType === 1) return [target];\n return target ? Array.from(target) : [];\n}\nexport default function justFlipIt(target, options) {\n const result = elements(target).map(element => instances.get(element) || new FlipController(element, options));\n return target?.nodeType === 1 ? result[0] : result;\n}\njustFlipIt.destroy = target => elements(target).forEach(element => instances.get(element)?.destroy());\njustFlipIt.get = element => instances.get(element);\n"],
5
- "mappings": ";AAAA,IAAM,YAAY,oBAAI,QAAQ;AAC9B,IAAM,WAAW,EAAE,OAAO,OAAO,OAAO,OAAO,UAAU,KAAK,QAAQ,+BAA+B,MAAM,OAAO,QAAQ,QAAQ,eAAe,MAAM,iBAAiB,MAAM,gBAAgB,MAAM,OAAO,CAAC,EAAE;AAC9M,IAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBZ,SAAS,OAAO,KAAK;AACnB,MAAI,IAAI,cAAc,kCAAkC,EAAG;AAC3D,QAAM,QAAQ,IAAI,cAAc,OAAO;AACvC,QAAM,QAAQ,kBAAkB;AAAM,QAAM,cAAc;AAAK,MAAI,KAAK,OAAO,KAAK;AACtF;AACA,SAAS,SAAS,SAAS;AACzB,MAAI,QAAQ,aAAa,WAAc,CAAC,OAAO,SAAS,QAAQ,QAAQ,KAAK,QAAQ,WAAW,GAAI,OAAM,IAAI,UAAU,+CAA+C;AACvK,MAAI,QAAQ,WAAW,UAAa,CAAC,CAAC,QAAQ,QAAQ,OAAO,EAAE,SAAS,QAAQ,MAAM,EAAG,OAAM,IAAI,UAAU,gBAAgB;AAC7H,MAAI,QAAQ,QAAQ,OAAO,QAAQ,SAAS,UAAU;AACpD,eAAW,OAAO,CAAC,OAAO,eAAe,OAAO,GAAG;AACjD,UAAI,QAAQ,KAAK,GAAG,MAAM,WAAc,CAAC,OAAO,SAAS,QAAQ,KAAK,GAAG,CAAC,KAAK,QAAQ,KAAK,GAAG,IAAI,GAAI,OAAM,IAAI,UAAU,gBAAgB,GAAG,EAAE;AAAA,IAClJ;AAAA,EACF;AACF;AACO,IAAM,iBAAN,MAAqB;AAAA,EAC1B,YAAY,SAAS,UAAU,CAAC,GAAG;AACjC,aAAS,OAAO;AAChB,QAAI,CAAC,WAAW,QAAQ,aAAa,EAAG,OAAM,IAAI,UAAU,0BAA0B;AACtF,SAAK,UAAU;AAAS,SAAK,WAAW,EAAE,GAAG,UAAU,GAAG,QAAQ;AAAG,SAAK,UAAU;AAAO,SAAK,YAAY;AAC5G,SAAK,WAAW,CAAC;AAAG,SAAK,WAAW,CAAC;AAAG,SAAK,MAAM,QAAQ,cAAc;AACzE,UAAM,MAAM,QAAQ;AAAe,WAAO,GAAG;AAC7C,SAAK,UAAU,CAAC,CAAC,QAAQ;AACzB,QAAI,KAAK,SAAS;AAChB,WAAK,aAAa;AAClB,WAAK,eAAe,QAAQ,cAAc,QAAQ,MAAM,KAAK;AAC7D,WAAK,cAAc,QAAQ,cAAc,QAAQ,MAAM,IAAI;AAC3D,UAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,eAAe,KAAK,iBAAiB,KAAK,eAAe,KAAK,aAAa,eAAe,WAAW,KAAK,YAAY,eAAe,QAAS,OAAM,IAAI,UAAU,gDAAgD;AAAA,IACpP,OAAO;AACL,UAAI,CAAC,QAAQ,WAAY,OAAM,IAAI,UAAU,4BAA4B;AACzE,WAAK,aAAa,IAAI,cAAc,KAAK;AACzC,WAAK,eAAe,IAAI,cAAc,KAAK;AAAG,WAAK,cAAc,IAAI,cAAc,KAAK;AACxF,UAAI,KAAK,SAAS,gBAAiB,MAAK,WAAW,YAAY,QAAQ;AACvE,UAAI,KAAK,SAAS,eAAgB,MAAK,WAAW,MAAM,UAAU,QAAQ,MAAM;AAChF,cAAQ,OAAO,KAAK,UAAU;AAAG,WAAK,WAAW,OAAO,KAAK,cAAc,KAAK,WAAW;AAC3F,WAAK,aAAa,OAAO,OAAO;AAChC,UAAI,QAAQ,aAAa,OAAW,MAAK,YAAY,YAAY,QAAQ;AAAA,WACpE;AACH,cAAM,QAAQ,QAAQ,UAAU,IAAI;AACpC,cAAM,gBAAgB,IAAI;AAAG,cAAM,iBAAiB,MAAM,EAAE,QAAQ,UAAQ,KAAK,gBAAgB,IAAI,CAAC;AACtG,aAAK,YAAY,OAAO,KAAK;AAAA,MAC/B;AAAA,IACF;AACA,UAAM,QAAQ,KAAK;AACnB,eAAW,QAAQ,CAAC,OAAO,KAAK,cAAc,KAAK,WAAW,GAAG;AAC/D,YAAM,QAAQ,SAAS,QAAQ,CAAC,SAAS,SAAS,YAAY,iBAAiB,mBAAmB,mBAAmB,oBAAoB,kBAAkB,IAAI,CAAC,SAAS,iBAAiB,eAAe,OAAO;AAChN,YAAM,QAAQ,MAAM,IAAI,UAAQ,CAAC,MAAM,KAAK,aAAa,IAAI,CAAC,CAAC;AAC/D,YAAM,QAAQ,KAAK,SAAS;AAC5B,WAAK,SAAS,KAAK,MAAM;AAAE,aAAK,QAAQ;AAAO,mBAAW,CAAC,MAAM,KAAK,KAAK,OAAO;AAAE,cAAI,UAAU,KAAM,MAAK,gBAAgB,IAAI;AAAA,cAAQ,MAAK,aAAa,MAAM,KAAK;AAAA,QAAG;AAAA,MAAE,CAAC;AAAA,IAC9K;AACA,UAAM,UAAU,IAAI,mBAAmB;AACvC,SAAK,aAAa,QAAQ,UAAU;AAAS,SAAK,YAAY,QAAQ,UAAU;AAChF,SAAK,SAAS,KAAK,IAAI,aAAa,kCAAkC;AACtE,UAAM,eAAe,MAAM;AAAE,WAAK,UAAU;AAAG,WAAK,OAAO;AAAA,IAAG;AAC9D,SAAK,QAAQ,iBAAiB,UAAU,YAAY;AACpD,SAAK,SAAS,KAAK,MAAM,KAAK,QAAQ,oBAAoB,UAAU,YAAY,CAAC;AACjF,SAAK,UAAU;AAAG,SAAK,OAAO;AAAG,SAAK,OAAO;AAC7C,cAAU,IAAI,SAAS,IAAI;AAAG,cAAU,IAAI,OAAO,IAAI;AAAA,EACzD;AAAA,EACA,OAAO,MAAM,SAAS,SAAS;AAAE,SAAK,WAAW,iBAAiB,MAAM,SAAS,OAAO;AAAG,SAAK,SAAS,KAAK,MAAM,KAAK,WAAW,oBAAoB,MAAM,SAAS,OAAO,CAAC;AAAA,EAAG;AAAA,EAClL,IAAI,UAAU;AAAE,WAAO,KAAK,SAAS,kBAAkB,SAAS,CAAC,CAAC,KAAK,QAAQ;AAAA,EAAS;AAAA,EACxF,YAAY;AACV,UAAM,IAAI,KAAK,UAAU,IAAI,KAAK;AAClC,MAAE,MAAM,YAAY,kBAAkB,GAAG,EAAE,QAAQ,IAAI;AAAG,MAAE,MAAM,YAAY,gBAAgB,EAAE,MAAM;AACtG,MAAE,QAAQ,UAAU,EAAE,QAAQ,MAAM;AAAK,MAAE,QAAQ,YAAY,EAAE;AACjE,MAAE,QAAQ,YAAY,EAAE,kBAAkB,QAAQ,UAAU;AAC5D,eAAW,QAAQ,EAAE,SAAS,CAAC,GAAG;AAChC,YAAM,UAAU,KAAK,OAAO,SAAS,CAAC,CAAC,IAAI,EAAE,iBAAiB,KAAK,EAAE;AACrE,cAAQ,QAAQ,UAAQ,OAAO,OAAO,KAAK,OAAO,KAAK,KAAK,CAAC;AAAA,IAC/D;AAEA,QAAI,EAAE,SAAS,UAAU,CAAC,EAAE,aAAa,UAAU,EAAG,GAAE,WAAW;AAAA,EACrE;AAAA,EACA,SAAS;AACP,SAAK,OAAO,SAAS,WAAS;AAC5B,UAAI,KAAK,SAAS,SAAS,OAAQ;AACnC,YAAM,UAAU,KAAK,SAAS;AAC9B,UAAI,YAAY,QAAS,WAAW,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,cAAY,MAAM,OAAO,UAAU,QAAQ,KAAK,KAAK,WAAW,SAAS,MAAM,OAAO,QAAQ,QAAQ,CAAC,CAAC,EAAI,MAAK,OAAO;AAAA,IACtL,CAAC;AACD,SAAK,OAAO,WAAW,WAAS;AAC9B,UAAI,MAAM,WAAW,KAAK,cAAc,KAAK,SAAS,SAAS,OAAQ;AACvE,UAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;AAAE,cAAM,eAAe;AAAG,aAAK,OAAO;AAAA,MAAG;AACzF,UAAI,MAAM,QAAQ,SAAU,MAAK,KAAK,KAAK;AAAA,IAC7C,CAAC;AACD,SAAK,OAAO,gBAAgB,WAAS;AAAE,UAAI,CAAC,KAAK,SAAS,SAAS,KAAK,SAAS,SAAS,UAAU,MAAM,gBAAgB,QAAS,MAAK,KAAK,IAAI;AAAA,IAAG,CAAC;AACrJ,SAAK,OAAO,gBAAgB,MAAM;AAAE,WAAK,UAAU;AAAG,UAAI,CAAC,KAAK,SAAS,SAAS,KAAK,SAAS,SAAS,OAAQ,MAAK,KAAK,KAAK;AAAA,IAAG,CAAC;AACpI,SAAK,OAAO,iBAAiB,MAAM,KAAK,UAAU,CAAC;AACnD,SAAK,OAAO,aAAa,WAAS;AAAE,UAAI,MAAM,gBAAgB,SAAS;AAAE,aAAK,UAAU;AAAG,YAAI,CAAC,KAAK,SAAS,SAAS,KAAK,SAAS,SAAS,OAAQ,MAAK,OAAO;AAAA,MAAG;AAAA,IAAE,CAAC;AACxK,SAAK,OAAO,eAAe,WAAS;AAClC,UAAI,CAAC,KAAK,SAAS,QAAQ,KAAK,WAAW,MAAM,gBAAgB,QAAS;AAC1E,WAAK,QAAQ,CAAC,MAAM,SAAS,MAAM,OAAO;AAC1C,UAAI,KAAK,MAAO;AAChB,WAAK,QAAQ,KAAK,IAAI,sBAAsB,MAAM;AAChD,aAAK,QAAQ;AACb,cAAM,OAAO,KAAK,WAAW,sBAAsB;AACnD,YAAI,CAAC,KAAK,SAAS,CAAC,KAAK,OAAQ;AACjC,cAAM,IAAI,EAAE,KAAK,IAAI,aAAa,KAAM,OAAO,MAAM,GAAI,OAAO,KAAK,SAAS,SAAS,WAAW,KAAK,SAAS,OAAO,CAAC,EAAG;AAC3H,cAAM,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,MAAM,CAAC,IAAI,KAAK,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC;AACpF,cAAM,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,MAAM,CAAC,IAAI,KAAK,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC;AACpF,aAAK,WAAW,MAAM,YAAY,eAAe,EAAE,WAAW,eAAe,CAAC,IAAI,EAAE,GAAG,gBAAgB,IAAI,EAAE,GAAG,cAAc,EAAE,KAAK;AAAA,MACvI,CAAC;AAAA,IACH,GAAG,EAAE,SAAS,KAAK,CAAC;AACpB,SAAK,gBAAgB,KAAK,WAAW,MAAM;AAAA,EAC7C;AAAA,EACA,YAAY;AAAE,QAAI,KAAK,MAAO,MAAK,IAAI,qBAAqB,KAAK,KAAK;AAAG,SAAK,QAAQ;AAAG,SAAK,WAAW,MAAM,YAAY,KAAK,iBAAiB;AAAA,EAAI;AAAA,EACrJ,SAAS;AACP,SAAK,WAAW,QAAQ,aAAa,OAAO,KAAK,OAAO;AAAG,SAAK,WAAW,QAAQ,aAAa,OAAO,KAAK,OAAO;AACnH,eAAW,CAAC,MAAM,MAAM,KAAK,CAAC,CAAC,KAAK,cAAc,KAAK,OAAO,GAAG,CAAC,KAAK,aAAa,CAAC,KAAK,OAAO,CAAC,GAAG;AAAE,WAAK,aAAa,eAAe,OAAO,MAAM,CAAC;AAAG,WAAK,QAAQ;AAAA,IAAQ;AAAA,EAChL;AAAA,EACA,KAAK,QAAQ,MAAM;AACjB,QAAI,KAAK,aAAa,KAAK,YAAY,CAAC,CAAC,MAAO,QAAO;AACvD,UAAM,SAAS,KAAK,QAAQ,cAAc;AAC1C,SAAK,QAAQ,KAAK,eAAe,KAAK,aAAa,SAAS,MAAM,EAAG,MAAK,WAAW,MAAM,EAAE,eAAe,KAAK,CAAC;AAClH,SAAK,UAAU,CAAC,CAAC;AAAO,SAAK,OAAO;AACpC,SAAK,WAAW,cAAc,IAAI,KAAK,IAAI,YAAY,qBAAqB,EAAE,SAAS,MAAM,QAAQ,KAAK,SAAS,EAAE,CAAC,CAAC;AACvH,WAAO;AAAA,EACT;AAAA,EACA,SAAS;AAAE,WAAO,KAAK,KAAK,CAAC,KAAK,OAAO;AAAA,EAAG;AAAA,EAC5C,OAAO,UAAU,CAAC,GAAG;AACnB,QAAI,KAAK,UAAW,QAAO;AAC3B,QAAI,WAAW,QAAS,OAAM,IAAI,UAAU,0CAA0C;AACtF,aAAS,OAAO;AAChB,QAAI,KAAK,WAAW,cAAc,QAAS,OAAM,IAAI,UAAU,kDAAkD;AACjH,SAAK,WAAW,EAAE,GAAG,KAAK,UAAU,GAAG,QAAQ;AAC/C,QAAI,cAAc,SAAS;AACzB,UAAI,KAAK,QAAS,OAAM,IAAI,UAAU,kDAAkD;AACxF,WAAK,YAAY,YAAY,QAAQ;AAAA,IACvC;AACA,SAAK,UAAU;AAAG,SAAK,UAAU;AAAG,SAAK,OAAO;AAAG,WAAO;AAAA,EAC5D;AAAA,EACA,WAAW;AAAE,WAAO,EAAE,SAAS,KAAK,SAAS,WAAW,KAAK,WAAW,QAAQ,KAAK,SAAS,OAAO;AAAA,EAAG;AAAA,EACxG,UAAU;AACR,QAAI,KAAK,UAAW;AACpB,SAAK,UAAU;AAAG,SAAK,SAAS,QAAQ,QAAM,GAAG,CAAC;AAClD,SAAK,SAAS,QAAQ,QAAM,GAAG,CAAC;AAChC,QAAI,CAAC,KAAK,SAAS;AAAE,WAAK,WAAW,YAAY,KAAK,OAAO;AAAA,IAAG;AAChE,cAAU,OAAO,KAAK,OAAO;AAAG,cAAU,OAAO,KAAK,UAAU;AAAG,SAAK,YAAY;AAAA,EACtF;AACF;AACA,SAAS,SAAS,QAAQ;AACxB,MAAI,OAAO,WAAW,SAAU,QAAO,OAAO,aAAa,cAAc,CAAC,IAAI,MAAM,KAAK,SAAS,iBAAiB,MAAM,CAAC;AAC1H,MAAI,QAAQ,aAAa,EAAG,QAAO,CAAC,MAAM;AAC1C,SAAO,SAAS,MAAM,KAAK,MAAM,IAAI,CAAC;AACxC;AACe,SAAR,WAA4B,QAAQ,SAAS;AAClD,QAAM,SAAS,SAAS,MAAM,EAAE,IAAI,aAAW,UAAU,IAAI,OAAO,KAAK,IAAI,eAAe,SAAS,OAAO,CAAC;AAC7G,SAAO,QAAQ,aAAa,IAAI,OAAO,CAAC,IAAI;AAC9C;AACA,WAAW,UAAU,YAAU,SAAS,MAAM,EAAE,QAAQ,aAAW,UAAU,IAAI,OAAO,GAAG,QAAQ,CAAC;AACpG,WAAW,MAAM,aAAW,UAAU,IAAI,OAAO;",
4
+ "sourcesContent": ["const instances = new WeakMap();\nconst 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: [] };\nconst css = `\n._justFlipIt_panel{position:relative;display:grid;perspective:var(--jfi-perspective,1000px);isolation:isolate}\n._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}\n._justFlipIt_panel>[data-jfi-face=back],._justFlipIt_panel[data-jfi-flipped=true]>[data-jfi-face=front]{pointer-events:none}\n._justFlipIt_panel[data-jfi-flipped=true]>[data-jfi-face=back]{pointer-events:auto}\n._justFlipIt_panel[data-jfi-effect=flip]>[data-jfi-face=front]{transform:rotateY(0deg)}\n._justFlipIt_panel[data-jfi-effect=flip]>[data-jfi-face=back]{transform:rotateY(-180deg)}\n._justFlipIt_panel[data-jfi-effect=flip][data-jfi-flipped=true]>[data-jfi-face=front]{transform:rotateY(180deg)}\n._justFlipIt_panel[data-jfi-effect=flip][data-jfi-flipped=true]>[data-jfi-face=back]{transform:rotateY(0deg)}\n._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x]>[data-jfi-face=front]{transform:rotateX(0deg)}\n._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x]>[data-jfi-face=back]{transform:rotateX(-180deg)}\n._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x][data-jfi-flipped=true]>[data-jfi-face=front]{transform:rotateX(180deg)}\n._justFlipIt_panel[data-jfi-effect=flip][data-jfi-axis=x][data-jfi-flipped=true]>[data-jfi-face=back]{transform:rotateX(0deg)}\n._justFlipIt_panel[data-jfi-effect=fade]>[data-jfi-face=back],._justFlipIt_panel[data-jfi-effect=scale]>[data-jfi-face=back]{opacity:0}\n._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}\n._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}\n._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)}\n._justFlipIt_panel[data-jfi-effect=scale][data-jfi-flipped=true]>[data-jfi-face=back]{transform:scale(1)}\n._justFlipIt_panel[data-jfi-reduced=true]>[data-jfi-face]{transition:none!important}\n@media(prefers-reduced-motion:reduce){._justFlipIt_panel:not([data-jfi-motion=allow])>[data-jfi-face]{transition:none!important}}\n`;\nfunction styles(doc) {\n if (doc.querySelector('style[data-justflipitstyle=\"v4\"]')) return;\n const style = doc.createElement('style');\n style.dataset.justflipitstyle = 'v4'; style.textContent = css; doc.head.append(style);\n}\nfunction validate(options) {\n if (options.Duration !== undefined && (!Number.isFinite(options.Duration) || options.Duration < 0)) throw new TypeError('Duration must be a non-negative finite number');\n if (options.Effect !== undefined && !['flip', 'fade', 'scale'].includes(options.Effect)) throw new TypeError('Unknown Effect');\n if (options.Tilt && typeof options.Tilt === 'object') {\n for (const key of ['max', 'perspective', 'scale']) {\n if (options.Tilt[key] !== undefined && (!Number.isFinite(options.Tilt[key]) || options.Tilt[key] < 0)) throw new TypeError(`Invalid Tilt.${key}`);\n }\n }\n}\nexport class FlipController {\n constructor(element, options = {}) {\n validate(options);\n if (!element || element.nodeType !== 1) throw new TypeError('Expected an HTML element');\n this.element = element; this.settings = { ...defaults, ...options }; this.flipped = false; this.destroyed = false;\n this.cleanups = []; this.restores = []; this.win = element.ownerDocument.defaultView;\n const doc = element.ownerDocument; styles(doc);\n this.managed = !!options.Faces;\n if (this.managed) {\n this.hoverPanel = element;\n this.frontWrapper = element.querySelector(options.Faces.front);\n this.backWrapper = element.querySelector(options.Faces.back);\n 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');\n } else {\n if (!element.parentNode) throw new TypeError('Element must have a parent');\n this.hoverPanel = doc.createElement('div');\n this.frontWrapper = doc.createElement('div'); this.backWrapper = doc.createElement('div');\n if (this.settings.preserveClasses) this.hoverPanel.className = element.className;\n if (this.settings.preserveStyles) this.hoverPanel.style.cssText = element.style.cssText;\n element.before(this.hoverPanel); this.hoverPanel.append(this.frontWrapper, this.backWrapper);\n this.frontWrapper.append(element);\n if (options.Template !== undefined) this.backWrapper.innerHTML = options.Template;\n else {\n const clone = element.cloneNode(true);\n clone.removeAttribute('id'); clone.querySelectorAll('[id]').forEach(node => node.removeAttribute('id'));\n this.backWrapper.append(clone);\n }\n }\n const panel = this.hoverPanel;\n for (const node of [panel, this.frontWrapper, this.backWrapper]) {\n 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'];\n const attrs = owned.map(name => [name, node.getAttribute(name)]);\n const inert = node.inert || false;\n this.restores.push(() => { node.inert = inert; for (const [name, value] of attrs) { if (value === null) node.removeAttribute(name); else node.setAttribute(name, value); } });\n }\n panel.classList.add('_justFlipIt_panel');\n this.frontWrapper.dataset.jfiFace = 'front'; this.backWrapper.dataset.jfiFace = 'back';\n this.motion = this.win.matchMedia?.('(prefers-reduced-motion: reduce)');\n const motionChange = () => { this.resetTilt(); this.render(); };\n this.motion?.addEventListener('change', motionChange);\n this.cleanups.push(() => this.motion?.removeEventListener('change', motionChange));\n this.configure(); this.events(); this.render();\n instances.set(element, this); instances.set(panel, this);\n }\n listen(type, handler, options) { this.hoverPanel.addEventListener(type, handler, options); this.cleanups.push(() => this.hoverPanel.removeEventListener(type, handler, options)); }\n get reduced() { return this.settings.ReducedMotion !== false && !!this.motion?.matches; }\n configure() {\n const s = this.settings, p = this.hoverPanel;\n p.style.setProperty('--jfi-duration', `${s.Duration}ms`); p.style.setProperty('--jfi-easing', s.Easing);\n p.dataset.jfiAxis = s.FlipX ? 'x' : 'y'; p.dataset.jfiEffect = s.Effect;\n p.dataset.jfiMotion = s.ReducedMotion === false ? 'allow' : 'respect';\n for (const item of s.Style || []) {\n const targets = item.el === 'self' ? [p] : p.querySelectorAll(item.el);\n targets.forEach(node => Object.assign(node.style, item.style));\n }\n // A generic keyboard focus target avoids button roles around interactive children.\n if (s.Tilt !== 'only' && !p.hasAttribute('tabindex')) p.tabIndex = 0;\n }\n events() {\n this.listen('click', event => {\n if (this.settings.Tilt === 'only') return;\n const trigger = this.settings.Click;\n if (trigger === true || (trigger && [].concat(trigger).some(selector => event.target.closest?.(selector) && this.hoverPanel.contains(event.target.closest(selector))))) this.toggle();\n });\n this.listen('keydown', event => {\n if (event.target !== this.hoverPanel || this.settings.Tilt === 'only') return;\n if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.toggle(); }\n if (event.key === 'Escape') this.flip(false);\n });\n this.listen('pointerenter', event => { if (!this.settings.Click && this.settings.Tilt !== 'only' && event.pointerType !== 'touch') this.flip(true); });\n this.listen('pointerleave', event => {\n // Touch release also emits pointerleave. The tap must survive it.\n if (event.pointerType === 'touch') return;\n this.resetTilt();\n if (!this.settings.Click && this.settings.Tilt !== 'only') this.flip(false);\n });\n this.listen('pointerdown', event => {\n if (event.pointerType !== 'touch' || event.isPrimary === false || this.touch) return;\n this.resetTilt();\n this.touch = { id: event.pointerId, x: event.clientX, y: event.clientY, moved: false };\n this.queueTilt(event, this.touch);\n }, { passive: true });\n this.listen('pointermove', event => {\n if (event.pointerType !== 'touch') {\n if (!this.touch) this.queueTilt(event);\n return;\n }\n const touch = this.touch;\n if (!touch || touch.id !== event.pointerId) return;\n touch.moved ||= this.touchMoved(event, touch);\n this.queueTilt(event, touch);\n }, { passive: true });\n this.listen('pointerup', event => {\n const touch = this.finishTouch(event);\n if (!touch || touch.moved || this.touchMoved(event, touch)) return;\n // Explicit click triggers continue to use the browser's click event.\n if (!this.settings.Click && this.settings.Tilt !== 'only') this.toggle();\n });\n this.listen('pointercancel', event => {\n if (event.pointerType === 'touch') this.finishTouch(event);\n else this.resetTilt();\n });\n this.listen('lostpointercapture', event => this.finishTouch(event));\n this.baseTransform = this.hoverPanel.style.transform;\n }\n touchMoved(event, touch) {\n return Math.hypot(event.clientX - touch.x, event.clientY - touch.y) > 10;\n }\n finishTouch(event) {\n const touch = this.touch;\n if (event.pointerType !== 'touch' || !touch || touch.id !== event.pointerId) return;\n this.touch = null;\n this.resetTilt();\n return touch;\n }\n queueTilt(event, touch) {\n if (!this.settings.Tilt || this.reduced) return;\n this.point = [event.clientX, event.clientY];\n if (this.frame) return;\n this.frame = this.win.requestAnimationFrame(() => {\n this.frame = 0;\n // Keep the touch reference box stable as the panel rotates.\n const rect = touch\n ? (touch.rect ??= this.hoverPanel.getBoundingClientRect())\n : this.hoverPanel.getBoundingClientRect();\n if (!rect.width || !rect.height) return;\n const { max = 10, perspective = 1000, scale = 1.03 } = this.settings.Tilt;\n const x = Math.max(-1, Math.min(1, (this.point[0] - rect.left) / rect.width * 2 - 1));\n const y = Math.max(-1, Math.min(1, (this.point[1] - rect.top) / rect.height * 2 - 1));\n this.hoverPanel.style.transform = `perspective(${perspective}px) rotateX(${-y * max}deg) rotateY(${x * max}deg) scale(${scale})`;\n });\n }\n resetTilt() { if (this.frame) this.win.cancelAnimationFrame(this.frame); this.frame = 0; this.hoverPanel.style.transform = this.baseTransform || ''; }\n render() {\n this.hoverPanel.dataset.jfiFlipped = String(this.flipped); this.hoverPanel.dataset.jfiReduced = String(this.reduced);\n for (const [node, hidden] of [[this.frontWrapper, this.flipped], [this.backWrapper, !this.flipped]]) { node.setAttribute('aria-hidden', String(hidden)); node.inert = hidden; }\n }\n flip(value = true) {\n if (this.destroyed || this.flipped === !!value) return this;\n const active = this.element.ownerDocument.activeElement;\n if ((value ? this.frontWrapper : this.backWrapper).contains(active)) this.hoverPanel.focus({ preventScroll: true });\n this.flipped = !!value; this.render();\n this.hoverPanel.dispatchEvent(new this.win.CustomEvent('justflipit:change', { bubbles: true, detail: this.getState() }));\n return this;\n }\n toggle() { return this.flip(!this.flipped); }\n update(options = {}) {\n if (this.destroyed) return this;\n if ('Faces' in options) throw new TypeError('Faces cannot change after initialization');\n validate(options);\n if (this.managed && 'Template' in options) throw new TypeError('Render framework face content with the framework');\n this.settings = { ...this.settings, ...options };\n if ('Template' in options) {\n if (this.managed) throw new TypeError('Render framework face content with the framework');\n this.backWrapper.innerHTML = options.Template;\n }\n this.resetTilt(); this.configure(); this.render(); return this;\n }\n getState() { return { flipped: this.flipped, destroyed: this.destroyed, effect: this.settings.Effect }; }\n destroy() {\n if (this.destroyed) return;\n this.resetTilt(); this.cleanups.forEach(fn => fn());\n this.restores.forEach(fn => fn());\n if (!this.managed) { this.hoverPanel.replaceWith(this.element); }\n instances.delete(this.element); instances.delete(this.hoverPanel); this.destroyed = true;\n }\n}\nfunction elements(target) {\n if (typeof target === 'string') return typeof document === 'undefined' ? [] : Array.from(document.querySelectorAll(target));\n if (target?.nodeType === 1) return [target];\n return target ? Array.from(target) : [];\n}\nexport default function justFlipIt(target, options) {\n const result = elements(target).map(element => instances.get(element) || new FlipController(element, options));\n return target?.nodeType === 1 ? result[0] : result;\n}\njustFlipIt.destroy = target => elements(target).forEach(element => instances.get(element)?.destroy());\njustFlipIt.get = element => instances.get(element);\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simhub2/justflipit",
3
- "version": "4.0.0",
3
+ "version": "4.0.1",
4
4
  "description": "Responsive flip and tilt animations with React, Vue, Svelte and agent tool adapters",
5
5
  "main": "./dist/justFlipIt.cjs",
6
6
  "module": "./dist/justFlipIt.mjs",