flipfolio 0.1.0 → 0.3.0
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/README.md +34 -7
- package/dist/{chunk-DT6YOBGV.js → chunk-RFBZ3WPG.js} +274 -75
- package/dist/chunk-RFBZ3WPG.js.map +1 -0
- package/dist/element.cjs +287 -59
- package/dist/element.cjs.map +1 -1
- package/dist/element.d.ts +6 -0
- package/dist/element.js +21 -2
- package/dist/element.js.map +1 -1
- package/dist/folder-gallery.css +66 -24
- package/dist/index.cjs +274 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +42 -1
- package/dist/index.js +3 -1
- package/dist/react.cjs +305 -94
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.ts +5 -1
- package/dist/react.js +39 -27
- package/dist/react.js.map +1 -1
- package/dist/vue.cjs +299 -62
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.ts +20 -4
- package/dist/vue.js +33 -5
- package/dist/vue.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-DT6YOBGV.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,22 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __defProp = Object.defineProperty;
|
|
3
2
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
4
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
-
var __spreadValues = (a, b) => {
|
|
10
|
-
for (var prop in b || (b = {}))
|
|
11
|
-
if (__hasOwnProp.call(b, prop))
|
|
12
|
-
__defNormalProp(a, prop, b[prop]);
|
|
13
|
-
if (__getOwnPropSymbols)
|
|
14
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
-
if (__propIsEnum.call(b, prop))
|
|
16
|
-
__defNormalProp(a, prop, b[prop]);
|
|
17
|
-
}
|
|
18
|
-
return a;
|
|
19
|
-
};
|
|
20
5
|
var __export = (target, all) => {
|
|
21
6
|
for (var name in all)
|
|
22
7
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -34,12 +19,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
34
19
|
// src/folder-gallery.js
|
|
35
20
|
var folder_gallery_exports = {};
|
|
36
21
|
__export(folder_gallery_exports, {
|
|
22
|
+
FOLDER_PATHS: () => FOLDER_PATHS,
|
|
37
23
|
createFolderGallery: () => createFolderGallery,
|
|
38
24
|
default: () => folder_gallery_default
|
|
39
25
|
});
|
|
40
26
|
module.exports = __toCommonJS(folder_gallery_exports);
|
|
41
27
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
42
28
|
var DEFAULT_FOLDER_PATH = "M 0 22 C 0 10 10 0 22 0 L 155 0 C 168 0 172 6 176 14 C 180 24 188 32 204 32 L 458 32 C 470 32 480 42 480 54 L 480 320 C 480 332 470 342 458 342 L 22 342 C 10 342 0 332 0 320 Z";
|
|
29
|
+
var FOLDER_PATHS = {
|
|
30
|
+
left: DEFAULT_FOLDER_PATH,
|
|
31
|
+
right: "M 480 22 C 480 10 470 0 458 0 L 325 0 C 312 0 308 6 304 14 C 300 24 292 32 276 32 L 22 32 C 10 32 0 42 0 54 L 0 320 C 0 332 10 342 22 342 L 458 342 C 470 342 480 332 480 320 Z",
|
|
32
|
+
tray: "M 0 22 C 0 10 10 0 22 0 L 458 0 C 470 0 480 10 480 22 L 480 320 C 480 332 470 342 458 342 L 22 342 C 10 342 0 332 0 320 Z"
|
|
33
|
+
};
|
|
43
34
|
var DEFAULTS = {
|
|
44
35
|
mode: "stack",
|
|
45
36
|
// 'stack' | 'grid' | 'carousel'
|
|
@@ -50,19 +41,27 @@ var DEFAULTS = {
|
|
|
50
41
|
// 'auto' | 'off' | 'force'
|
|
51
42
|
peek: "hover",
|
|
52
43
|
// 'hover' | 'always' | 'off'
|
|
44
|
+
drag: "fling",
|
|
45
|
+
// 'fling' | 'off' - grab the active folder and throw it (stack mode)
|
|
53
46
|
defaultActiveIndex: 0,
|
|
54
47
|
label: "Folder gallery"
|
|
55
48
|
};
|
|
56
49
|
var PEEK_MODES = /* @__PURE__ */ new Set(["hover", "always", "off"]);
|
|
50
|
+
var DRAG_MODES = /* @__PURE__ */ new Set(["fling", "off"]);
|
|
51
|
+
var INSTANCES = /* @__PURE__ */ new WeakMap();
|
|
57
52
|
var MODE_WIDTHS = { stack: 480, grid: 720, carousel: 720 };
|
|
58
53
|
var SCROLL_THRESHOLD = 30;
|
|
59
54
|
var SCROLL_COOLDOWN = { stack: 450, carousel: 300 };
|
|
60
55
|
function hexToRgb(hex) {
|
|
61
|
-
|
|
56
|
+
let h = String(hex).trim().replace(/^#/, "");
|
|
57
|
+
if (h.length === 3) h = h.replace(/./g, (c) => c + c);
|
|
58
|
+
if (!/^[0-9a-f]{6}$/i.test(h)) return null;
|
|
62
59
|
return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
|
|
63
60
|
}
|
|
64
61
|
function folderColors(hex) {
|
|
65
|
-
const
|
|
62
|
+
const rgb = hexToRgb(hex);
|
|
63
|
+
if (!rgb) return null;
|
|
64
|
+
const [r, g, b] = rgb;
|
|
66
65
|
const dn = (v) => Math.max(v - 30, 0);
|
|
67
66
|
const up = (v, o) => Math.min(v + o, 255);
|
|
68
67
|
const fr = up(r, 35);
|
|
@@ -76,6 +75,34 @@ function folderColors(hex) {
|
|
|
76
75
|
label: yiq >= 128 ? "#1c1c1a" : "#ffffff"
|
|
77
76
|
};
|
|
78
77
|
}
|
|
78
|
+
function paintFolder(card, hex) {
|
|
79
|
+
const c = folderColors(hex);
|
|
80
|
+
if (!c) return;
|
|
81
|
+
card.style.setProperty("--fg-folder-bg", hex);
|
|
82
|
+
card.style.setProperty("--fg-front", c.front);
|
|
83
|
+
card.style.setProperty("--fg-front-solid", c.frontSolid);
|
|
84
|
+
card.style.setProperty("--fg-label-on-color", c.label);
|
|
85
|
+
const path = card.querySelector(".fg-folder path");
|
|
86
|
+
if (path) path.setAttribute("fill", c.back);
|
|
87
|
+
}
|
|
88
|
+
function paintGradient(card, gradient) {
|
|
89
|
+
const front = card.querySelector(".fg-front");
|
|
90
|
+
if (!front) return;
|
|
91
|
+
let layer = front.querySelector(".fg-gradient");
|
|
92
|
+
if (!gradient) {
|
|
93
|
+
if (layer) layer.remove();
|
|
94
|
+
card.classList.remove("fg-card--gradient");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (!layer) {
|
|
98
|
+
layer = document.createElement("div");
|
|
99
|
+
layer.className = "fg-gradient";
|
|
100
|
+
layer.setAttribute("aria-hidden", "true");
|
|
101
|
+
front.insertBefore(layer, front.firstChild);
|
|
102
|
+
}
|
|
103
|
+
layer.style.background = gradient;
|
|
104
|
+
card.classList.add("fg-card--gradient");
|
|
105
|
+
}
|
|
79
106
|
function defaultContentRenderer(card, item) {
|
|
80
107
|
const wrap = document.createElement("div");
|
|
81
108
|
wrap.className = "fg-content";
|
|
@@ -95,12 +122,17 @@ function defaultContentRenderer(card, item) {
|
|
|
95
122
|
card.appendChild(wrap);
|
|
96
123
|
}
|
|
97
124
|
function createFolderGallery(root, options = {}) {
|
|
98
|
-
if (!root ||
|
|
99
|
-
const
|
|
125
|
+
if (!root || root.nodeType !== 1) throw new Error("createFolderGallery: a root element is required");
|
|
126
|
+
const prior = INSTANCES.get(root);
|
|
127
|
+
if (prior) prior();
|
|
128
|
+
const provided = {};
|
|
129
|
+
for (const k in options) if (options[k] !== void 0) provided[k] = options[k];
|
|
130
|
+
const opts = { ...DEFAULTS, ...provided };
|
|
100
131
|
const items = Array.isArray(opts.items) ? opts.items : [];
|
|
101
132
|
const n = items.length;
|
|
102
133
|
const renderContent = typeof opts.contentRenderer === "function" ? opts.contentRenderer : defaultContentRenderer;
|
|
103
|
-
const
|
|
134
|
+
const reducedQuery = opts.reducedMotion === "auto" && typeof matchMedia === "function" ? matchMedia("(prefers-reduced-motion: reduce)") : null;
|
|
135
|
+
let reduced = opts.reducedMotion === "force" || (reducedQuery ? reducedQuery.matches : false);
|
|
104
136
|
let mode = MODE_WIDTHS[opts.mode] ? opts.mode : "stack";
|
|
105
137
|
let active = Math.min(Math.max(opts.defaultActiveIndex | 0, 0), Math.max(n - 1, 0));
|
|
106
138
|
let scrollCooldown = false;
|
|
@@ -111,9 +143,29 @@ function createFolderGallery(root, options = {}) {
|
|
|
111
143
|
cleanups.push(() => el.removeEventListener(ev, fn, o));
|
|
112
144
|
};
|
|
113
145
|
const emit = (name, detail) => root.dispatchEvent(new CustomEvent(name, { detail, bubbles: true }));
|
|
146
|
+
let destroyed = false;
|
|
147
|
+
const timers = /* @__PURE__ */ new Set();
|
|
148
|
+
const rafs = /* @__PURE__ */ new Set();
|
|
149
|
+
const later = (fn, ms) => {
|
|
150
|
+
const id = setTimeout(() => {
|
|
151
|
+
timers.delete(id);
|
|
152
|
+
fn();
|
|
153
|
+
}, ms);
|
|
154
|
+
timers.add(id);
|
|
155
|
+
return id;
|
|
156
|
+
};
|
|
157
|
+
const frame = (fn) => {
|
|
158
|
+
const id = requestAnimationFrame(() => {
|
|
159
|
+
rafs.delete(id);
|
|
160
|
+
fn();
|
|
161
|
+
});
|
|
162
|
+
rafs.add(id);
|
|
163
|
+
return id;
|
|
164
|
+
};
|
|
114
165
|
root.classList.add("fg-root");
|
|
115
166
|
root.setAttribute("data-fg-mode", mode);
|
|
116
167
|
root.setAttribute("data-fg-peek", PEEK_MODES.has(opts.peek) ? opts.peek : "hover");
|
|
168
|
+
root.setAttribute("data-fg-drag", DRAG_MODES.has(opts.drag) ? opts.drag : "fling");
|
|
117
169
|
const scene = document.createElement("div");
|
|
118
170
|
scene.className = "fg-scene";
|
|
119
171
|
scene.setAttribute("role", "listbox");
|
|
@@ -128,26 +180,48 @@ function createFolderGallery(root, options = {}) {
|
|
|
128
180
|
live.setAttribute("aria-atomic", "true");
|
|
129
181
|
root.append(scene, dotsEl, live);
|
|
130
182
|
function teardown() {
|
|
183
|
+
if (destroyed) return;
|
|
184
|
+
destroyed = true;
|
|
185
|
+
timers.forEach(clearTimeout);
|
|
186
|
+
timers.clear();
|
|
187
|
+
rafs.forEach(cancelAnimationFrame);
|
|
188
|
+
rafs.clear();
|
|
131
189
|
cleanups.forEach((fn) => fn());
|
|
132
190
|
cleanups.length = 0;
|
|
133
191
|
root.replaceChildren();
|
|
134
192
|
root.classList.remove("fg-root");
|
|
135
193
|
root.removeAttribute("data-fg-mode");
|
|
136
194
|
root.removeAttribute("data-fg-peek");
|
|
195
|
+
root.removeAttribute("data-fg-drag");
|
|
196
|
+
INSTANCES.delete(root);
|
|
137
197
|
}
|
|
138
198
|
if (n === 0) {
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
199
|
+
const noop = () => {
|
|
200
|
+
};
|
|
201
|
+
INSTANCES.set(root, teardown);
|
|
202
|
+
return {
|
|
203
|
+
next: noop,
|
|
204
|
+
prev: noop,
|
|
205
|
+
goTo: noop,
|
|
206
|
+
setMode: noop,
|
|
207
|
+
setPeek: noop,
|
|
208
|
+
setColor: noop,
|
|
209
|
+
setGradient: noop,
|
|
210
|
+
getActiveIndex: () => -1,
|
|
211
|
+
getMode: () => mode,
|
|
212
|
+
getPeek: () => root.getAttribute("data-fg-peek"),
|
|
213
|
+
getColor: () => void 0,
|
|
214
|
+
getGradient: () => void 0,
|
|
215
|
+
getItems: () => [],
|
|
216
|
+
destroy: teardown
|
|
217
|
+
};
|
|
145
218
|
}
|
|
146
219
|
function setCardTransform(card, { x, y, z, rx, ry, s, zIndex, opacity, isActive }) {
|
|
147
|
-
card.
|
|
148
|
-
|
|
220
|
+
if (!card.classList.contains("fg-card--flung")) {
|
|
221
|
+
card.style.transform = `translate3d(${x}px,${y}px,${z}px) rotateX(${rx}deg) rotateY(${ry}deg) scale(${s})`;
|
|
222
|
+
card.style.opacity = String(opacity);
|
|
223
|
+
}
|
|
149
224
|
card.style.zIndex = String(zIndex);
|
|
150
|
-
card.style.opacity = String(opacity);
|
|
151
225
|
card.setAttribute("aria-selected", isActive ? "true" : "false");
|
|
152
226
|
card.classList.toggle("is-active", isActive);
|
|
153
227
|
}
|
|
@@ -157,13 +231,9 @@ function createFolderGallery(root, options = {}) {
|
|
|
157
231
|
card.tabIndex = i === active ? 0 : -1;
|
|
158
232
|
card.setAttribute("role", "option");
|
|
159
233
|
card.setAttribute("aria-label", item.label || `Item ${i + 1}`);
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
card.style.setProperty("--fg-front", c.front);
|
|
164
|
-
card.style.setProperty("--fg-front-solid", c.frontSolid);
|
|
165
|
-
card.style.setProperty("--fg-label-on-color", c.label);
|
|
166
|
-
}
|
|
234
|
+
card.setAttribute("aria-setsize", String(n));
|
|
235
|
+
card.setAttribute("aria-posinset", String(i + 1));
|
|
236
|
+
card.setAttribute("data-fg-index", String(i));
|
|
167
237
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
168
238
|
svg.setAttribute("class", "fg-folder");
|
|
169
239
|
svg.setAttribute("viewBox", "0 0 480 342");
|
|
@@ -171,7 +241,7 @@ function createFolderGallery(root, options = {}) {
|
|
|
171
241
|
svg.setAttribute("aria-hidden", "true");
|
|
172
242
|
const path = document.createElementNS(SVG_NS, "path");
|
|
173
243
|
path.setAttribute("d", opts.folderPath);
|
|
174
|
-
path.setAttribute("fill",
|
|
244
|
+
path.setAttribute("fill", "var(--fg-folder-bg)");
|
|
175
245
|
svg.appendChild(path);
|
|
176
246
|
card.appendChild(svg);
|
|
177
247
|
renderContent(card, item, i);
|
|
@@ -194,6 +264,8 @@ function createFolderGallery(root, options = {}) {
|
|
|
194
264
|
front.appendChild(label);
|
|
195
265
|
}
|
|
196
266
|
card.appendChild(front);
|
|
267
|
+
if (item.color) paintFolder(card, item.color);
|
|
268
|
+
if (item.gradient) paintGradient(card, item.gradient);
|
|
197
269
|
scene.appendChild(card);
|
|
198
270
|
return card;
|
|
199
271
|
});
|
|
@@ -207,9 +279,13 @@ function createFolderGallery(root, options = {}) {
|
|
|
207
279
|
dotsEl.appendChild(dot);
|
|
208
280
|
return dot;
|
|
209
281
|
});
|
|
282
|
+
const clearGridWidth = (card) => {
|
|
283
|
+
if (card.style.width) card.style.width = "";
|
|
284
|
+
};
|
|
210
285
|
function layoutStack() {
|
|
211
286
|
scene.style.height = "";
|
|
212
287
|
cardEls.forEach((card, i) => {
|
|
288
|
+
clearGridWidth(card);
|
|
213
289
|
const behind = (i - active + n) % n;
|
|
214
290
|
if (behind === 0) {
|
|
215
291
|
setCardTransform(card, { x: 0, y: 100, z: 20, rx: 0, ry: 0, s: 1, zIndex: n + 1, opacity: 1, isActive: true });
|
|
@@ -225,33 +301,31 @@ function createFolderGallery(root, options = {}) {
|
|
|
225
301
|
}
|
|
226
302
|
function layoutGrid() {
|
|
227
303
|
const sceneW = scene.clientWidth || MODE_WIDTHS.grid;
|
|
228
|
-
const
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
const
|
|
234
|
-
const scaledH = cardH * sc;
|
|
235
|
-
const tabScaled = 22 * sc;
|
|
304
|
+
const gap = Number.isFinite(opts.grid && opts.grid.gap) ? opts.grid.gap : 16;
|
|
305
|
+
const cols = Math.max(1, Math.round(
|
|
306
|
+
opts.grid && opts.grid.columns ? opts.grid.columns : sceneW < 520 ? 2 : n <= 4 ? 2 : 3
|
|
307
|
+
));
|
|
308
|
+
const cellW = (sceneW - (cols - 1) * gap) / cols;
|
|
309
|
+
const cellH = cellW * (2 / 3);
|
|
236
310
|
const rows = Math.ceil(n / cols);
|
|
237
311
|
cardEls.forEach((card, i) => {
|
|
238
312
|
const col = i % cols;
|
|
239
313
|
const row = Math.floor(i / cols);
|
|
240
314
|
const itemsInRow = Math.min(cols, n - row * cols);
|
|
241
|
-
const rowW = itemsInRow *
|
|
315
|
+
const rowW = itemsInRow * cellW + (itemsInRow - 1) * gap;
|
|
242
316
|
const rowStartX = (sceneW - rowW) / 2;
|
|
243
|
-
const
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
setCardTransform(card, { x: tx, y: ty, z: 0, rx: 0, ry: 0, s: sc, zIndex: i === active ? 2 : 1, opacity: 1, isActive: i === active });
|
|
317
|
+
const x = rowStartX + col * (cellW + gap);
|
|
318
|
+
const y = row * (cellH + gap);
|
|
319
|
+
card.style.width = cellW + "px";
|
|
320
|
+
setCardTransform(card, { x, y, z: 0, rx: 0, ry: 0, s: 1, zIndex: i === active ? 2 : 1, opacity: 1, isActive: i === active });
|
|
248
321
|
});
|
|
249
|
-
scene.style.height = rows *
|
|
322
|
+
scene.style.height = rows * cellH + (rows - 1) * gap + "px";
|
|
250
323
|
}
|
|
251
324
|
function layoutCarousel() {
|
|
252
325
|
const sceneW = scene.clientWidth || MODE_WIDTHS.carousel;
|
|
253
326
|
const cardW = sceneW;
|
|
254
327
|
const cardH = cardW * (2 / 3);
|
|
328
|
+
cardEls.forEach(clearGridWidth);
|
|
255
329
|
const activeSc = 0.62;
|
|
256
330
|
const activeW = cardW * activeSc;
|
|
257
331
|
const sceneH = Math.max(cardH * activeSc + 40, 180);
|
|
@@ -286,29 +360,39 @@ function createFolderGallery(root, options = {}) {
|
|
|
286
360
|
live.textContent = cur && cur.label ? `${active + 1} of ${n}: ${cur.label}` : `${active + 1} of ${n}`;
|
|
287
361
|
}
|
|
288
362
|
function goTo(i) {
|
|
289
|
-
|
|
363
|
+
if (destroyed) return;
|
|
364
|
+
const t = Number.isFinite(+i) ? Math.trunc(+i) : active;
|
|
365
|
+
const next = opts.loop ? (t % n + n) % n : Math.min(Math.max(t, 0), n - 1);
|
|
290
366
|
if (next === active) return;
|
|
291
367
|
active = next;
|
|
292
368
|
applyLayout();
|
|
293
369
|
emit("fg-activechange", { index: active, item: items[active] });
|
|
294
370
|
}
|
|
295
371
|
function select(i) {
|
|
372
|
+
if (destroyed) return;
|
|
296
373
|
emit("fg-select", { index: i, item: items[i] });
|
|
297
374
|
if (typeof opts.onSelect === "function") opts.onSelect(items[i], i);
|
|
298
375
|
}
|
|
299
376
|
function setMode(m) {
|
|
300
|
-
if (m === mode || !MODE_WIDTHS[m]) return;
|
|
377
|
+
if (destroyed || m === mode || !MODE_WIDTHS[m]) return;
|
|
301
378
|
mode = m;
|
|
302
379
|
root.setAttribute("data-fg-mode", mode);
|
|
303
380
|
applyLayout();
|
|
304
381
|
emit("fg-modechange", { mode });
|
|
305
382
|
}
|
|
306
383
|
function setPeek(p) {
|
|
307
|
-
if (!PEEK_MODES.has(p)) return;
|
|
384
|
+
if (destroyed || !PEEK_MODES.has(p) || p === root.getAttribute("data-fg-peek")) return;
|
|
308
385
|
root.setAttribute("data-fg-peek", p);
|
|
386
|
+
emit("fg-peekchange", { peek: p });
|
|
309
387
|
}
|
|
388
|
+
const dragEnabled = opts.drag !== "off";
|
|
389
|
+
let suppressClick = false;
|
|
310
390
|
cardEls.forEach((card, i) => {
|
|
311
391
|
on(card, "click", () => {
|
|
392
|
+
if (suppressClick) {
|
|
393
|
+
suppressClick = false;
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
312
396
|
i === active ? select(i) : goTo(i);
|
|
313
397
|
});
|
|
314
398
|
on(card, "keydown", (e) => {
|
|
@@ -374,7 +458,7 @@ function createFolderGallery(root, options = {}) {
|
|
|
374
458
|
scrollAccum = 0;
|
|
375
459
|
scrollCooldown = true;
|
|
376
460
|
goTo(active + dir);
|
|
377
|
-
|
|
461
|
+
later(() => {
|
|
378
462
|
scrollCooldown = false;
|
|
379
463
|
scrollAccum = 0;
|
|
380
464
|
}, SCROLL_COOLDOWN[mode] || 300);
|
|
@@ -388,6 +472,7 @@ function createFolderGallery(root, options = {}) {
|
|
|
388
472
|
touchStartY = e.touches[0].clientY;
|
|
389
473
|
}, { passive: true });
|
|
390
474
|
on(scene, "touchend", (e) => {
|
|
475
|
+
if (dragEnabled && mode === "stack") return;
|
|
391
476
|
const dx = touchStartX - e.changedTouches[0].clientX;
|
|
392
477
|
const dy = touchStartY - e.changedTouches[0].clientY;
|
|
393
478
|
const ax = Math.abs(dx);
|
|
@@ -396,26 +481,157 @@ function createFolderGallery(root, options = {}) {
|
|
|
396
481
|
const dir = ax > ay ? dx > 0 ? 1 : -1 : dy > 0 ? 1 : -1;
|
|
397
482
|
goTo(active + dir);
|
|
398
483
|
}, { passive: true });
|
|
484
|
+
if (dragEnabled) {
|
|
485
|
+
const DRAG_ROT = 0.04;
|
|
486
|
+
const FLING_DIST = 90;
|
|
487
|
+
const FLING_VEL = 0.5;
|
|
488
|
+
const TAP_SLOP = 6;
|
|
489
|
+
let dragCard = null;
|
|
490
|
+
let dragBase = "";
|
|
491
|
+
let startPX = 0, startPY = 0, dragDX = 0, dragDY = 0;
|
|
492
|
+
let lastX = 0, lastY = 0, lastT = 0, velX = 0, velY = 0;
|
|
493
|
+
on(scene, "pointerdown", (e) => {
|
|
494
|
+
if (mode !== "stack") return;
|
|
495
|
+
if (e.button !== void 0 && e.button !== 0) return;
|
|
496
|
+
const card = e.target && e.target.closest ? e.target.closest(".fg-card") : null;
|
|
497
|
+
if (!card || !card.classList.contains("is-active")) return;
|
|
498
|
+
dragCard = card;
|
|
499
|
+
dragBase = card.style.transform;
|
|
500
|
+
startPX = e.clientX;
|
|
501
|
+
startPY = e.clientY;
|
|
502
|
+
dragDX = 0;
|
|
503
|
+
dragDY = 0;
|
|
504
|
+
lastX = e.clientX;
|
|
505
|
+
lastY = e.clientY;
|
|
506
|
+
lastT = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
507
|
+
velX = 0;
|
|
508
|
+
velY = 0;
|
|
509
|
+
card.classList.add("fg-card--dragging");
|
|
510
|
+
if (card.setPointerCapture && e.pointerId !== void 0) {
|
|
511
|
+
try {
|
|
512
|
+
card.setPointerCapture(e.pointerId);
|
|
513
|
+
} catch (_) {
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
on(window, "pointermove", (e) => {
|
|
518
|
+
if (!dragCard) return;
|
|
519
|
+
dragDX = e.clientX - startPX;
|
|
520
|
+
dragDY = e.clientY - startPY;
|
|
521
|
+
const now = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
522
|
+
const dt = Math.max(now - lastT, 1);
|
|
523
|
+
velX = (e.clientX - lastX) / dt;
|
|
524
|
+
velY = (e.clientY - lastY) / dt;
|
|
525
|
+
lastX = e.clientX;
|
|
526
|
+
lastY = e.clientY;
|
|
527
|
+
lastT = now;
|
|
528
|
+
dragCard.style.transform = `${dragBase} translate3d(${dragDX}px, ${dragDY}px, 40px) rotate(${(dragDX * DRAG_ROT).toFixed(2)}deg)`;
|
|
529
|
+
});
|
|
530
|
+
const endDrag = () => {
|
|
531
|
+
if (!dragCard) return;
|
|
532
|
+
const card = dragCard;
|
|
533
|
+
dragCard = null;
|
|
534
|
+
card.classList.remove("fg-card--dragging");
|
|
535
|
+
const dist = Math.hypot(dragDX, dragDY);
|
|
536
|
+
if (dist < TAP_SLOP) {
|
|
537
|
+
card.style.transform = dragBase;
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
suppressClick = true;
|
|
541
|
+
const horizontal = Math.abs(dragDX) >= Math.abs(dragDY);
|
|
542
|
+
const flung = dist > FLING_DIST || Math.hypot(velX, velY) > FLING_VEL;
|
|
543
|
+
const dir = horizontal ? dragDX > 0 ? -1 : 1 : dragDY > 0 ? -1 : 1;
|
|
544
|
+
const target = active + dir;
|
|
545
|
+
const blocked = !opts.loop && (target < 0 || target > n - 1);
|
|
546
|
+
if (!flung || blocked) {
|
|
547
|
+
card.style.transform = dragBase;
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
const semantic = dir > 0 ? "next" : "prev";
|
|
551
|
+
emit("fg-flingstart", { index: active, direction: semantic });
|
|
552
|
+
if (reduced) {
|
|
553
|
+
goTo(target);
|
|
554
|
+
emit("fg-flingend", { index: target, direction: semantic });
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
const offX = horizontal ? Math.sign(dragDX) * Math.max(window.innerWidth * 0.7, 480) : dragDX * 3;
|
|
558
|
+
const offY = horizontal ? dragDY * 3 : Math.sign(dragDY) * Math.max(window.innerHeight * 0.7, 480);
|
|
559
|
+
card.classList.add("fg-card--flung");
|
|
560
|
+
card.style.transform = `${dragBase} translate3d(${offX}px, ${offY}px, 40px) rotate(${Math.sign(dragDX || 1) * 18}deg)`;
|
|
561
|
+
card.style.opacity = "0";
|
|
562
|
+
goTo(target);
|
|
563
|
+
later(() => {
|
|
564
|
+
card.classList.add("fg-card--snap");
|
|
565
|
+
card.classList.remove("fg-card--flung");
|
|
566
|
+
applyLayout();
|
|
567
|
+
const slot = card.style.transform;
|
|
568
|
+
const slotOpacity = card.style.opacity;
|
|
569
|
+
card.style.transform = `${slot} translate3d(0, -90px, 0)`;
|
|
570
|
+
card.style.opacity = "0";
|
|
571
|
+
frame(() => frame(() => {
|
|
572
|
+
card.classList.remove("fg-card--snap");
|
|
573
|
+
card.classList.add("fg-card--entering");
|
|
574
|
+
card.style.transform = slot;
|
|
575
|
+
card.style.opacity = slotOpacity;
|
|
576
|
+
later(() => {
|
|
577
|
+
card.classList.remove("fg-card--entering");
|
|
578
|
+
emit("fg-flingend", { index: target, direction: semantic });
|
|
579
|
+
}, 700);
|
|
580
|
+
}));
|
|
581
|
+
}, 400);
|
|
582
|
+
};
|
|
583
|
+
on(window, "pointerup", endDrag);
|
|
584
|
+
on(window, "pointercancel", endDrag);
|
|
585
|
+
}
|
|
399
586
|
let resizeTimer;
|
|
400
587
|
on(window, "resize", () => {
|
|
401
588
|
clearTimeout(resizeTimer);
|
|
402
|
-
resizeTimer =
|
|
589
|
+
resizeTimer = later(applyLayout, 150);
|
|
403
590
|
});
|
|
591
|
+
if (reducedQuery && reducedQuery.addEventListener) {
|
|
592
|
+
on(reducedQuery, "change", (e) => {
|
|
593
|
+
if (!destroyed) {
|
|
594
|
+
reduced = e.matches;
|
|
595
|
+
applyLayout();
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
}
|
|
404
599
|
applyLayout();
|
|
405
|
-
|
|
600
|
+
const handle = {
|
|
406
601
|
next: () => goTo(active + 1),
|
|
407
602
|
prev: () => goTo(active - 1),
|
|
408
603
|
goTo,
|
|
409
604
|
setMode,
|
|
410
605
|
setPeek,
|
|
606
|
+
setColor: (i, hex) => {
|
|
607
|
+
const card = cardEls[i];
|
|
608
|
+
if (card && !destroyed) paintFolder(card, hex);
|
|
609
|
+
},
|
|
610
|
+
setGradient: (i, gradient) => {
|
|
611
|
+
const card = cardEls[i];
|
|
612
|
+
if (card && !destroyed) paintGradient(card, gradient);
|
|
613
|
+
},
|
|
411
614
|
getActiveIndex: () => active,
|
|
412
615
|
getMode: () => mode,
|
|
616
|
+
getPeek: () => root.getAttribute("data-fg-peek"),
|
|
617
|
+
getColor: (i) => {
|
|
618
|
+
const card = cardEls[i];
|
|
619
|
+
return card ? card.style.getPropertyValue("--fg-folder-bg") || void 0 : void 0;
|
|
620
|
+
},
|
|
621
|
+
getGradient: (i) => {
|
|
622
|
+
const layer = cardEls[i] && cardEls[i].querySelector(".fg-gradient");
|
|
623
|
+
return layer ? layer.style.background || void 0 : void 0;
|
|
624
|
+
},
|
|
625
|
+
getItems: () => items.slice(),
|
|
413
626
|
destroy: teardown
|
|
414
627
|
};
|
|
628
|
+
INSTANCES.set(root, teardown);
|
|
629
|
+
return handle;
|
|
415
630
|
}
|
|
416
631
|
var folder_gallery_default = createFolderGallery;
|
|
417
632
|
// Annotate the CommonJS export names for ESM import in node:
|
|
418
633
|
0 && (module.exports = {
|
|
634
|
+
FOLDER_PATHS,
|
|
419
635
|
createFolderGallery
|
|
420
636
|
});
|
|
421
637
|
//# sourceMappingURL=index.cjs.map
|