@frybynite/image-cloud 0.9.6 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,9 +10,9 @@ A TypeScript library for creating interactive image clouds with animated scatter
10
10
  ## Features
11
11
 
12
12
  - ✨ Animated image layouts with smooth transitions
13
- - 🎯 Multiple layout algorithms (radial, grid, spiral, cluster, wave, random)
13
+ - 🎯 Multiple layout algorithms (radial, grid, spiral, cluster, wave, honeycomb, random)
14
14
  - 🎬 Rich entry animations (bounce, elastic, wave paths; spin, wobble rotations)
15
- - 🔍 Zoom/focus interactions with keyboard navigation
15
+ - 🔍 Zoom/focus interactions with keyboard, swipe, and mouse wheel navigation
16
16
  - 🎨 State-based image styling (borders, shadows, filters for default/hover/focused)
17
17
  - 📱 Responsive design with adaptive sizing
18
18
  - 🖼️ Multiple image sources (static URLs, JSON endpoints, Google Drive, composite loaders)
@@ -53,30 +53,29 @@ Replace `@latest` with a specific version (e.g., `@0.5.1`) to pin to that releas
53
53
  ### TypeScript/JavaScript (Programmatic API)
54
54
 
55
55
  ```typescript
56
- import { ImageCloud } from '@frybynite/image-cloud';
56
+ import { imageCloud } from '@frybynite/image-cloud';
57
57
  import '@frybynite/image-cloud/style.css';
58
58
 
59
- const cloud = new ImageCloud({
59
+ // Single-expression initialization imageCloud() constructs and calls init() for you
60
+ const cloud = await imageCloud({
60
61
  container: 'myCloud',
61
- loaders: [{
62
- static: {
63
- sources: [{
64
- urls: [
65
- 'https://images.pexels.com/photos/1261728/pexels-photo-1261728.jpeg?auto=compress&w=600',
66
- 'https://images.pexels.com/photos/3225517/pexels-photo-3225517.jpeg?auto=compress&w=600',
67
- 'https://images.pexels.com/photos/1402787/pexels-photo-1402787.jpeg?auto=compress&w=600'
68
- ]
69
- }]
70
- }
71
- }],
62
+ images: [
63
+ 'https://images.pexels.com/photos/1261728/pexels-photo-1261728.jpeg?auto=compress&w=600',
64
+ 'https://images.pexels.com/photos/3225517/pexels-photo-3225517.jpeg?auto=compress&w=600',
65
+ 'https://images.pexels.com/photos/1402787/pexels-photo-1402787.jpeg?auto=compress&w=600'
66
+ ],
72
67
  layout: {
73
68
  algorithm: 'radial'
74
69
  }
75
70
  });
76
-
77
- await cloud.init();
78
71
  ```
79
72
 
73
+ > For advanced lifecycle control (e.g. deferred init, re-use), the `ImageCloud` class is also exported and still works as before:
74
+ > ```typescript
75
+ > const cloud = new ImageCloud({ container: 'myCloud', images: [...] });
76
+ > await cloud.init();
77
+ > ```
78
+
80
79
  ### HTML (Auto-initialization)
81
80
 
82
81
  ```html
@@ -107,13 +106,13 @@ await cloud.init();
107
106
 
108
107
  ## Getting Started
109
108
 
110
- For detailed configuration, see the documentation in the `docs/` folder:
109
+ Full documentation is available at **[frybynite.github.io/image-cloud](https://frybynite.github.io/image-cloud/)**
111
110
 
112
- 1. **[Loaders](docs/LOADERS.md)** — Configure image sources (static URLs, JSON endpoints, local paths, Google Drive folders)
113
- 2. **[Layouts](docs/LAYOUTS.md)** — Choose and customize layout algorithms (radial, grid, spiral, cluster, random, wave)
114
- 3. **[Image Sizing](docs/IMAGE_SIZING.md)** — Control base sizes, variance, and responsive/adaptive behavior
115
- 4. **[Full Parameter Reference](docs/PARAMETERS.md)** — Complete configuration options for animation, interaction, styling, and more
116
- 5. **[API Reference](docs/api/README.md)** — TypeScript API documentation for the ImageCloud class, types, loaders, and layouts
111
+ - **[Loaders](https://frybynite.github.io/image-cloud/loaders/)** — Configure image sources (static URLs, JSON endpoints, Google Drive)
112
+ - **[Layouts](https://frybynite.github.io/image-cloud/layouts/)** — Layout algorithms (radial, grid, spiral, cluster, wave, honeycomb, random)
113
+ - **[Image Sizing](https://frybynite.github.io/image-cloud/image_sizing/)** — Base sizes, variance, and responsive/adaptive behavior
114
+ - **[Parameters](https://frybynite.github.io/image-cloud/parameters/)** — Complete configuration reference
115
+ - **[API Reference](https://frybynite.github.io/image-cloud/api/)** — TypeScript API documentation
117
116
 
118
117
  ### Using the Configurator
119
118
 
@@ -139,6 +138,10 @@ The Configurator lets you visually adjust all settings and exports a ready-to-us
139
138
  - **Enter / Space**: Focus hovered image
140
139
  - **Escape**: Unfocus current image
141
140
 
141
+ ### Touch
142
+
143
+ - **Swipe left / right**: Navigate between focused images
144
+
142
145
  ### Window
143
146
 
144
147
  - **Resize**: Responsive layout adjustment (debounced)
@@ -152,29 +155,31 @@ The Configurator lets you visually adjust all settings and exports a ready-to-us
152
155
 
153
156
  ## Examples
154
157
 
155
- Check out the `examples/` directory for various usage patterns:
156
- - `esm-example.html` - Modern ES module usage
157
- - `cdn-umd-example.html` - Traditional script tag / CDN usage
158
- - `auto-init-example.html` - HTML data attribute initialization
159
- - `static-loader-example.html` - Static image URLs
160
- - `static-urls-shorthand-example.html` - Simplest static loader: direct URL array shorthand
161
- - `static-json-source-example.html` - Load images from a JSON endpoint
162
- - `google-drive-loader-example.html` - Google Drive folder source
163
- - `layout-algorithms.html` - Compare all layout algorithms
164
- - `entry-animations.html` - Entry animation styles
165
- - `image-style-demo.html` - Borders, shadows, and filters
166
- - `typescript-example.ts` - TypeScript with React and Vue
167
- - See `examples/README.md` for detailed instructions
158
+ Live examples are published at [frybynite.github.io/image-cloud/examples/](https://frybynite.github.io/image-cloud/examples/):
159
+
160
+ - [Static URLs Shorthand](https://frybynite.github.io/image-cloud/examples/static-urls-shorthand-example.html) - Simplest setup: direct URL array
161
+ - [Static Loader](https://frybynite.github.io/image-cloud/examples/static-loader-example.html) - Static image URLs
162
+ - [Static JSON Source](https://frybynite.github.io/image-cloud/examples/static-json-source-example.html) - Load images from a JSON endpoint
163
+ - [Google Drive](https://frybynite.github.io/image-cloud/examples/google-drive-loader-example.html) - Google Drive folder source
164
+ - [Auto-Init](https://frybynite.github.io/image-cloud/examples/auto-init-example.html) - Zero-JS setup using data attributes
165
+ - [ESM Module](https://frybynite.github.io/image-cloud/examples/esm-example.html) - ES module usage
166
+ - [CDN/UMD](https://frybynite.github.io/image-cloud/examples/cdn-umd-example.html) - CDN script tag usage
167
+ - [Iframe Embed](https://frybynite.github.io/image-cloud/examples/iframe-example.html) - Embedded in an iframe
168
+ - [Layout Algorithms](https://frybynite.github.io/image-cloud/examples/layout-algorithms.html) - Compare all layout algorithms
169
+ - [Entry Animations](https://frybynite.github.io/image-cloud/examples/entry-animations.html) - Entry animation styles
170
+ - [Keyboard Navigation](https://frybynite.github.io/image-cloud/examples/keyboard-navigation-demo.html) - Per-container keyboard navigation
171
+ - [Image Style Demo](https://frybynite.github.io/image-cloud/examples/image-style-demo.html) - Borders, shadows, and filters
172
+ - [Detailed Styling](https://frybynite.github.io/image-cloud/examples/styling/index.html) - In-depth styling examples
168
173
 
169
174
  ## Changelog
170
175
 
171
- See [CHANGELOG.md](CHANGELOG.md) for a full list of changes across all versions.
176
+ See [Changelog](https://frybynite.github.io/image-cloud/changelog/) for a full list of changes across all versions.
172
177
 
173
178
  ## Contributing
174
179
 
175
180
  Contributions are welcome! Please feel free to submit a Pull Request.
176
181
 
177
- See [docs/DEVELOPER.md](docs/DEVELOPER.md) for build scripts, testing, and project structure.
182
+ See the [Developer Guide](https://frybynite.github.io/image-cloud/developer/) for build scripts, testing, and project structure.
178
183
 
179
184
  ## License
180
185
 
@@ -24,7 +24,7 @@ const Ut = ".fbn-ic-gallery{--fbn-ic-bg-primary: #05060F;--fbn-ic-bg-secondary:
24
24
  mode: "none"
25
25
  }), xt = Object.freeze({
26
26
  mode: "none"
27
- }), Ft = Object.freeze({
27
+ }), Mt = Object.freeze({
28
28
  default: Object.freeze({
29
29
  border: Object.freeze({
30
30
  width: 0,
@@ -82,7 +82,7 @@ const Ut = ".fbn-ic-gallery{--fbn-ic-bg-primary: #05060F;--fbn-ic-bg-secondary:
82
82
  min: -15,
83
83
  max: 15
84
84
  })
85
- }), Mt = Object.freeze({
85
+ }), Ft = Object.freeze({
86
86
  sizing: jt,
87
87
  rotation: Wt
88
88
  }), zt = Object.freeze({
@@ -103,7 +103,7 @@ const Ut = ".fbn-ic-gallery{--fbn-ic-bg-primary: #05060F;--fbn-ic-bg-secondary:
103
103
  debug: Ot
104
104
  }),
105
105
  // Image sizing and rotation configuration
106
- image: Mt,
106
+ image: Ft,
107
107
  // Pattern-based layout configuration
108
108
  layout: Object.freeze({
109
109
  algorithm: "radial",
@@ -186,7 +186,7 @@ const Ut = ".fbn-ic-gallery{--fbn-ic-bg-primary: #05060F;--fbn-ic-bg-secondary:
186
186
  showFocusOutline: !1
187
187
  }),
188
188
  // Image styling
189
- styling: Ft
189
+ styling: Mt
190
190
  });
191
191
  function Z(o, t) {
192
192
  if (!o) return t || {};
@@ -274,12 +274,12 @@ function Qt(o = {}) {
274
274
  }, s = {
275
275
  loaders: n,
276
276
  config: r,
277
- image: Vt(Mt, e),
277
+ image: Vt(Ft, e),
278
278
  layout: { ...C.layout },
279
279
  animation: { ...C.animation },
280
280
  interaction: { ...C.interaction },
281
281
  ui: { ...C.ui },
282
- styling: Jt(Ft, o.styling)
282
+ styling: Jt(Mt, o.styling)
283
283
  };
284
284
  o.layout && (s.layout = {
285
285
  ...C.layout,
@@ -653,10 +653,10 @@ function de(o) {
653
653
  };
654
654
  }
655
655
  const W = D.x - e.x, U = D.y - e.y;
656
- let F;
657
- m ? F = le(A, c, y) : f ? F = V(d, c, A) : F = c;
656
+ let M;
657
+ m ? M = le(A, c, y) : f ? M = V(d, c, A) : M = c;
658
658
  let R;
659
- S ? R = he(A, l, w) : v ? R = V(b, l, A) : R = l, t.style.transform = `translate(${L}px, ${_}px) translate(${W}px, ${U}px) rotate(${F}deg) scale(${R})`, A < 1 ? requestAnimationFrame(O) : (t.style.transform = `translate(${L}px, ${_}px) rotate(${c}deg) scale(${l})`, u && u());
659
+ S ? R = he(A, l, w) : v ? R = V(b, l, A) : R = l, t.style.transform = `translate(${L}px, ${_}px) translate(${W}px, ${U}px) rotate(${M}deg) scale(${R})`, A < 1 ? requestAnimationFrame(O) : (t.style.transform = `translate(${L}px, ${_}px) rotate(${c}deg) scale(${l})`, u && u());
660
660
  }
661
661
  requestAnimationFrame(O);
662
662
  }
@@ -1279,16 +1279,16 @@ class be {
1279
1279
  continue;
1280
1280
  }
1281
1281
  const W = 2 * Math.PI / D, U = I * (20 * Math.PI / 180);
1282
- for (let F = 0; F < D && w < t; F++) {
1283
- const R = F * W + U, k = g ? this.random(h, d) : 1, q = L * k, T = f * q;
1284
- let $ = m + Math.cos(R) * H, M = y + Math.sin(R) * O;
1282
+ for (let M = 0; M < D && w < t; M++) {
1283
+ const R = M * W + U, k = g ? this.random(h, d) : 1, q = L * k, T = f * q;
1284
+ let $ = m + Math.cos(R) * H, F = y + Math.sin(R) * O;
1285
1285
  const P = T * 1.5 / 2, B = T / 2;
1286
- $ - P < v ? $ = v + P : $ + P > a - v && ($ = a - v - P), M - B < v ? M = v + B : M + B > r - v && (M = r - v - B);
1286
+ $ - P < v ? $ = v + P : $ + P > a - v && ($ = a - v - P), F - B < v ? F = v + B : F + B > r - v && (F = r - v - B);
1287
1287
  const Y = c === "random" ? this.random(l, u) : 0;
1288
1288
  n.push({
1289
1289
  id: w,
1290
1290
  x: $,
1291
- y: M,
1291
+ y: F,
1292
1292
  rotation: Y,
1293
1293
  scale: q,
1294
1294
  baseSize: T,
@@ -1365,27 +1365,27 @@ class ve {
1365
1365
  p,
1366
1366
  l,
1367
1367
  s
1368
- ), y = s.stagger === "row", x = s.stagger === "column", v = y ? f + 0.5 : f, S = x ? m + 0.5 : m, w = (b - s.gap * (f - 1)) / v, I = (p - s.gap * (m - 1)) / S, z = y ? w / 2 : 0, L = x ? I / 2 : 0, _ = 1 + s.overlap, O = Math.min(w, I) * _, H = e.fixedHeight ? Math.min(e.fixedHeight, O) : O, N = f * w + (f - 1) * s.gap + z, A = m * I + (m - 1) * s.gap + L, D = c + (b - N) / 2, W = c + (p - A) / 2, U = f * m, F = s.columns !== "auto" && s.rows !== "auto", R = F && t > U;
1368
+ ), y = s.stagger === "row", x = s.stagger === "column", v = y ? f + 0.5 : f, S = x ? m + 0.5 : m, w = (b - s.gap * (f - 1)) / v, I = (p - s.gap * (m - 1)) / S, z = y ? w / 2 : 0, L = x ? I / 2 : 0, _ = 1 + s.overlap, O = Math.min(w, I) * _, H = e.fixedHeight ? Math.min(e.fixedHeight, O) : O, N = f * w + (f - 1) * s.gap + z, A = m * I + (m - 1) * s.gap + L, D = c + (b - N) / 2, W = c + (p - A) / 2, U = f * m, M = s.columns !== "auto" && s.rows !== "auto", R = M && t > U;
1369
1369
  typeof window < "u" && (window.__gridOverflowDebug = {
1370
1370
  gridConfigColumns: s.columns,
1371
1371
  gridConfigRows: s.rows,
1372
1372
  columns: f,
1373
1373
  rows: m,
1374
1374
  cellCount: U,
1375
- hasFixedGrid: F,
1375
+ hasFixedGrid: M,
1376
1376
  imageCount: t,
1377
1377
  isOverflowMode: R
1378
1378
  });
1379
1379
  const k = R ? new Array(U).fill(0) : [], q = Math.min(w, I) * s.overflowOffset;
1380
1380
  for (let T = 0; T < t; T++) {
1381
- let $, M, X = 0;
1381
+ let $, F, X = 0;
1382
1382
  if (R && T >= U) {
1383
1383
  const G = T - U, j = G % U;
1384
- X = Math.floor(G / U) + 1, k[j]++, s.fillDirection === "row" ? ($ = j % f, M = Math.floor(j / f)) : (M = j % m, $ = Math.floor(j / m));
1384
+ X = Math.floor(G / U) + 1, k[j]++, s.fillDirection === "row" ? ($ = j % f, F = Math.floor(j / f)) : (F = j % m, $ = Math.floor(j / m));
1385
1385
  } else
1386
- s.fillDirection === "row" ? ($ = T % f, M = Math.floor(T / f)) : (M = T % m, $ = Math.floor(T / m));
1387
- let P = D + $ * (w + s.gap) + w / 2, B = W + M * (I + s.gap) + I / 2;
1388
- if (s.stagger === "row" && M % 2 === 1 ? P += w / 2 : s.stagger === "column" && $ % 2 === 1 && (B += I / 2), X > 0) {
1386
+ s.fillDirection === "row" ? ($ = T % f, F = Math.floor(T / f)) : (F = T % m, $ = Math.floor(T / m));
1387
+ let P = D + $ * (w + s.gap) + w / 2, B = W + F * (I + s.gap) + I / 2;
1388
+ if (s.stagger === "row" && F % 2 === 1 ? P += w / 2 : s.stagger === "column" && $ % 2 === 1 && (B += I / 2), X > 0) {
1389
1389
  const G = (X - 1) % Rt.length, j = Rt[G];
1390
1390
  P += j.x * q, B += j.y * q;
1391
1391
  }
@@ -1396,7 +1396,7 @@ class ve {
1396
1396
  let Y = P, J = B;
1397
1397
  if (!R && s.fillDirection === "row") {
1398
1398
  const G = t % f || f;
1399
- if (M === Math.floor((t - 1) / f) && G < f) {
1399
+ if (F === Math.floor((t - 1) / f) && G < f) {
1400
1400
  const St = G * w + (G - 1) * s.gap;
1401
1401
  let gt = 0;
1402
1402
  s.alignment === "center" ? gt = (N - St) / 2 : s.alignment === "end" && (gt = N - St), Y += gt;
@@ -1481,18 +1481,18 @@ class Ee {
1481
1481
  const P = S * 0.3 * s.tightness;
1482
1482
  w = P * v + s.startAngle, I = this.calculateLogarithmicRadius(P, t, x, s.tightness);
1483
1483
  }
1484
- const z = m + Math.cos(w) * I, L = y + Math.sin(w) * I, _ = I / x, O = f > 0 ? 1 - _ * f * 0.5 : 1, H = p ? this.random(g, b) : 1, N = O * H, A = l * N, W = A * 1.5 / 2, U = A / 2, F = c + W, R = a - c - W, k = c + U, q = r - c - U, T = Math.max(F, Math.min(z, R)), $ = Math.max(k, Math.min(L, q));
1485
- let M = 0;
1484
+ const z = m + Math.cos(w) * I, L = y + Math.sin(w) * I, _ = I / x, O = f > 0 ? 1 - _ * f * 0.5 : 1, H = p ? this.random(g, b) : 1, N = O * H, A = l * N, W = A * 1.5 / 2, U = A / 2, M = c + W, R = a - c - W, k = c + U, q = r - c - U, T = Math.max(M, Math.min(z, R)), $ = Math.max(k, Math.min(L, q));
1485
+ let F = 0;
1486
1486
  if (u === "random") {
1487
1487
  const P = w * 180 / Math.PI % 360, B = this.random(h, d);
1488
- M = s.spiralType === "golden" ? B : P * 0.1 + B * 0.9;
1489
- } else u === "tangent" && (M = this.calculateSpiralTangent(w, I, s));
1488
+ F = s.spiralType === "golden" ? B : P * 0.1 + B * 0.9;
1489
+ } else u === "tangent" && (F = this.calculateSpiralTangent(w, I, s));
1490
1490
  const X = t - S;
1491
1491
  n.push({
1492
1492
  id: S,
1493
1493
  x: T,
1494
1494
  y: $,
1495
- rotation: M,
1495
+ rotation: F,
1496
1496
  scale: N,
1497
1497
  baseSize: A,
1498
1498
  zIndex: X
@@ -1591,15 +1591,15 @@ class Ie {
1591
1591
  if (s.distribution === "gaussian")
1592
1592
  z = this.gaussianRandom() * S.spread, L = this.gaussianRandom() * S.spread;
1593
1593
  else {
1594
- const M = this.random(0, Math.PI * 2), X = this.random(0, S.spread);
1595
- z = Math.cos(M) * X, L = Math.sin(M) * X;
1594
+ const F = this.random(0, Math.PI * 2), X = this.random(0, S.spread);
1595
+ z = Math.cos(F) * X, L = Math.sin(F) * X;
1596
1596
  }
1597
1597
  const _ = 1 + s.overlap * 0.5, O = 1 + s.overlap * 0.3;
1598
1598
  z /= _, L /= _;
1599
1599
  const H = p ? this.random(g, b) : 1, N = O * H, A = l * N;
1600
1600
  let D = S.x + z, W = S.y + L;
1601
- const F = A * 1.5 / 2, R = A / 2;
1602
- D = Math.max(c + F, Math.min(D, a - c - F)), W = Math.max(c + R, Math.min(W, r - c - R));
1601
+ const M = A * 1.5 / 2, R = A / 2;
1602
+ D = Math.max(c + M, Math.min(D, a - c - M)), W = Math.max(c + R, Math.min(W, r - c - R));
1603
1603
  const k = u === "random" ? this.random(h, d) : 0, T = Math.sqrt(z * z + L * L) / S.spread, $ = Math.round((1 - T) * 50) + 1;
1604
1604
  n.push({
1605
1605
  id: x,
@@ -1690,25 +1690,25 @@ class Ce {
1690
1690
  ...Nt,
1691
1691
  ...this.config.wave
1692
1692
  }, { rows: m, amplitude: y, frequency: x, phaseShift: v, synchronization: S } = f, w = Math.ceil(t / m), L = p * 1.5 / 2, _ = c + L, O = a - c - L, H = O - _, N = w > 1 ? H / (w - 1) : 0, A = c + y + p / 2, D = r - c - y - p / 2, W = D - A, U = m > 1 ? W / (m - 1) : 0;
1693
- let F = 0;
1694
- for (let R = 0; R < m && F < t; R++) {
1693
+ let M = 0;
1694
+ for (let R = 0; R < m && M < t; R++) {
1695
1695
  const k = m === 1 ? (A + D) / 2 : A + R * U;
1696
1696
  let q = 0;
1697
1697
  S === "offset" ? q = R * v : S === "alternating" && (q = R * Math.PI);
1698
- for (let T = 0; T < w && F < t; T++) {
1699
- const $ = w === 1 ? (_ + O) / 2 : _ + T * N, M = this.calculateWaveY($, a, y, x, q), X = $, P = k + M, B = b ? this.random(d, g) : 1, Y = p * B;
1698
+ for (let T = 0; T < w && M < t; T++) {
1699
+ const $ = w === 1 ? (_ + O) / 2 : _ + T * N, F = this.calculateWaveY($, a, y, x, q), X = $, P = k + F, B = b ? this.random(d, g) : 1, Y = p * B;
1700
1700
  let J = 0;
1701
1701
  l === "tangent" ? J = this.calculateRotation($, a, y, x, q) : l === "random" && (J = this.random(u, h));
1702
1702
  const K = Y * 1.5 / 2, lt = Y / 2, nt = c + K, ot = a - c - K, ht = c + lt, dt = r - c - lt;
1703
1703
  n.push({
1704
- id: F,
1704
+ id: M,
1705
1705
  x: Math.max(nt, Math.min(X, ot)),
1706
1706
  y: Math.max(ht, Math.min(P, dt)),
1707
1707
  rotation: J,
1708
1708
  scale: B,
1709
1709
  baseSize: Y,
1710
- zIndex: F + 1
1711
- }), F++;
1710
+ zIndex: M + 1
1711
+ }), M++;
1712
1712
  }
1713
1713
  }
1714
1714
  return n;
@@ -1778,7 +1778,7 @@ function Le(o, t, i, e, n, a) {
1778
1778
  py: n + a * (t + o / 2)
1779
1779
  };
1780
1780
  }
1781
- const Fe = [
1781
+ const Me = [
1782
1782
  [1, 0, -1],
1783
1783
  [0, 1, -1],
1784
1784
  [-1, 1, 0],
@@ -1786,11 +1786,11 @@ const Fe = [
1786
1786
  [0, -1, 1],
1787
1787
  [1, -1, 0]
1788
1788
  ];
1789
- function Me(o) {
1789
+ function Fe(o) {
1790
1790
  if (o === 0) return [[0, 0, 0]];
1791
1791
  const t = [];
1792
1792
  let [i, e, n] = [0, -o, o];
1793
- for (const [a, r, s] of Fe)
1793
+ for (const [a, r, s] of Me)
1794
1794
  for (let c = 0; c < o; c++)
1795
1795
  t.push([i, e, n]), i += a, e += r, n += s;
1796
1796
  return t;
@@ -1808,7 +1808,7 @@ class ze {
1808
1808
  }.spacing ?? 0, d = l + h;
1809
1809
  let g = 0, b = 0;
1810
1810
  for (; g < t; ) {
1811
- const p = Me(b);
1811
+ const p = Fe(b);
1812
1812
  for (const [f, m, y] of p) {
1813
1813
  if (g >= t) break;
1814
1814
  const { px: x, py: v } = Le(f, m, y, s, c, d);
@@ -3292,7 +3292,7 @@ class ti {
3292
3292
  createLoader() {
3293
3293
  const t = this.fullConfig.loaders, i = this.fullConfig.config.loaders ?? {};
3294
3294
  if (!t || t.length === 0)
3295
- throw new Error("No loaders configured. Provide `images`, `loaders`, or both.");
3295
+ throw new Error("No loaders configured. Provide `images`, `loaders`, or both.\n Example: imageCloud({ container: 'id', images: ['https://...'] })");
3296
3296
  const e = t.map((n) => this.createLoaderFromEntry(n, i));
3297
3297
  return e.length === 1 ? e[0] : new Ve({
3298
3298
  loaders: e,
@@ -3331,7 +3331,7 @@ class ti {
3331
3331
  if (Qe(), this.containerRef)
3332
3332
  this.containerEl = this.containerRef;
3333
3333
  else if (this.containerEl = document.getElementById(this.containerId), !this.containerEl)
3334
- throw new Error(`Container #${this.containerId} not found`);
3334
+ throw new Error(`Container "#${this.containerId}" not found. Ensure an element with id="${this.containerId}" exists in the DOM before calling imageCloud().`);
3335
3335
  this.containerEl.classList.add("fbn-ic-gallery"), this.containerEl.setAttribute("tabindex", "0"), this.fullConfig.interaction.navigation?.swipe !== !1 && (this.swipeEngine = new bt(this.containerEl, {
3336
3336
  onNext: () => this.navigateToNextImage(),
3337
3337
  onPrev: () => this.navigateToPreviousImage(),
@@ -3341,7 +3341,7 @@ class ti {
3341
3341
  }
3342
3342
  })), this.setupUI(), this.setupEventListeners(), this.logDebug("ImageCloud initialized"), await this.loadImages();
3343
3343
  } catch (t) {
3344
- console.error("Gallery initialization failed:", t), this.errorEl && t instanceof Error && this.showError("Gallery failed to initialize: " + t.message);
3344
+ console.error(`ImageCloud initialization failed (container: "${this.containerId ?? "element"}"):`, t), this.errorEl && t instanceof Error && this.showError("Gallery failed to initialize: " + t.message);
3345
3345
  }
3346
3346
  }
3347
3347
  setupUI() {
@@ -3695,7 +3695,8 @@ function ii() {
3695
3695
  return;
3696
3696
  }
3697
3697
  else {
3698
- console.error(`ImageCloud: Missing configuration for #${e.id}. Add data-config='{...}' attribute.`);
3698
+ console.error(`ImageCloud: Missing configuration for #${e.id}. Add data-config='{...}' attribute.
3699
+ Example: data-config='{"images":["https://..."]}'`);
3699
3700
  return;
3700
3701
  }
3701
3702
  new ti(a).init().catch((s) => {