@haventmet/carousel 1.0.0 → 1.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 (72) hide show
  1. package/README.md +36 -43
  2. package/dist/carousel.css +1 -0
  3. package/dist/carousel.d.ts +17 -0
  4. package/dist/carousel.js +387 -0
  5. package/dist/carousel.umd.cjs +1 -0
  6. package/dist/index.d.ts +1 -0
  7. package/package.json +29 -17
  8. package/.mcp.json +0 -8
  9. package/CLAUDE.md +0 -177
  10. package/LICENSE +0 -21
  11. package/biome.json +0 -174
  12. package/packages/alpine/index.html +0 -50
  13. package/packages/alpine/package.json +0 -70
  14. package/packages/alpine/src/index.ts +0 -46
  15. package/packages/alpine/style.css +0 -76
  16. package/packages/alpine/tsconfig.json +0 -28
  17. package/packages/alpine/vite.config.ts +0 -28
  18. package/packages/core/README.md +0 -69
  19. package/packages/core/package.json +0 -45
  20. package/packages/core/src/carousel.ts +0 -842
  21. package/packages/core/src/index.ts +0 -2
  22. package/packages/core/src/style.css +0 -46
  23. package/packages/core/vite.config.js +0 -14
  24. package/packages/react/.vite/deps/_metadata.json +0 -25
  25. package/packages/react/.vite/deps/chunk-7CQ73C3Q.js +0 -1908
  26. package/packages/react/.vite/deps/chunk-7CQ73C3Q.js.map +0 -7
  27. package/packages/react/.vite/deps/package.json +0 -3
  28. package/packages/react/.vite/deps/react-dom_client.js +0 -21712
  29. package/packages/react/.vite/deps/react-dom_client.js.map +0 -7
  30. package/packages/react/.vite/deps/react.js +0 -4
  31. package/packages/react/.vite/deps/react.js.map +0 -7
  32. package/packages/react/README.md +0 -75
  33. package/packages/react/index.html +0 -12
  34. package/packages/react/package.json +0 -74
  35. package/packages/react/src/App.tsx +0 -38
  36. package/packages/react/src/BlossomCarousel.tsx +0 -77
  37. package/packages/react/src/index.ts +0 -2
  38. package/packages/react/src/main.jsx +0 -6
  39. package/packages/react/src/style.css +0 -50
  40. package/packages/react/tsconfig.json +0 -17
  41. package/packages/react/vite.config.js +0 -27
  42. package/packages/svelte/README.md +0 -58
  43. package/packages/svelte/index.html +0 -12
  44. package/packages/svelte/package.json +0 -71
  45. package/packages/svelte/src/App.svelte +0 -12
  46. package/packages/svelte/src/BlossomCarousel.svelte +0 -39
  47. package/packages/svelte/src/BlossomCarousel.svelte.d.ts +0 -8
  48. package/packages/svelte/src/index.ts +0 -2
  49. package/packages/svelte/src/main.js +0 -10
  50. package/packages/svelte/src/style.css +0 -52
  51. package/packages/svelte/tsconfig.json +0 -16
  52. package/packages/svelte/vite.config.js +0 -45
  53. package/packages/vue/README.md +0 -70
  54. package/packages/vue/index.html +0 -12
  55. package/packages/vue/package.json +0 -69
  56. package/packages/vue/src/App.vue +0 -82
  57. package/packages/vue/src/BlossomCarousel.vue +0 -52
  58. package/packages/vue/src/index.ts +0 -2
  59. package/packages/vue/src/main.js +0 -5
  60. package/packages/vue/src/style.css +0 -18
  61. package/packages/vue/vite.config.js +0 -25
  62. package/packages/web/README.md +0 -44
  63. package/packages/web/index.html +0 -29
  64. package/packages/web/package.json +0 -65
  65. package/packages/web/src/index.ts +0 -27
  66. package/packages/web/src/style.css +0 -53
  67. package/packages/web/style.css +0 -54
  68. package/packages/web/tsconfig.json +0 -18
  69. package/packages/web/vite.config.ts +0 -23
  70. package/pnpm-workspace.yaml +0 -8
  71. package/public/cover.jpg +0 -0
  72. package/turbo.json +0 -12
package/README.md CHANGED
@@ -1,69 +1,62 @@
1
- ![Blossom Carousel](./public/cover.jpg)
1
+ # Blossom Core
2
2
 
3
- # Blossom Carousel
4
-
5
- <p>
6
- <a href="https://www.npmjs.com/package/@numbered/carousel/core"><img src="https://img.shields.io/npm/v/@numbered/carousel/core.svg?color=%23c1a8e2"></a>
7
- <a href="https://bundlephobia.com/package/@numbered/carousel/core"><img src="https://img.shields.io/bundlephobia/minzip/@numbered/carousel/core?color=%238ab4f8&label=gzip%20size"></a>
8
- </p>
9
-
10
- The native-first carousel enhanced with drag support.
11
-
12
- ➥ [www.blossom-carousel.com](http://www.blossom-carousel.com)
13
-
14
- ## Why Blossom?
15
-
16
- <ul style="list-style: none; padding: 0;">
17
- <li>🥇 <strong>Native scrolling</strong>: Full performance and accessibility.</li>
18
- <li>🚀 <strong>Dragging</strong>: Custom physics-based dragging for all pointer types.</li>
19
- <li>✨ <strong>No abstraction</strong>: use all native web API's.</li>
20
- <li>💡 <strong>Configure with CSS</strong>: Works with native scroll-snap, position sticky and scroll-driven animations.</li>
21
- <li>🪶 <strong>0kb on touch devices</strong>: Blossom only loads when a fine pointer device is detected.</li>
22
- <li>🧱 <strong>Works with major frameworks</strong>: Components for React, Vue, Svelte and Web Components.</li>
23
- </ul>
3
+ A native-scroll-first carousel for the web.
24
4
 
25
5
  ## Installation
26
6
 
27
- ### React
28
-
29
- [React Docs](./packages/react)
7
+ Add the blossom-carousel package to your project.
30
8
 
31
9
  ```bash
32
- npm install @numbered/carousel/react
10
+ npm install @numbered/carousel/core
33
11
  ```
34
12
 
35
- ### Vue
13
+ Then, create a Blossom instance and initialize it.
36
14
 
37
- [Vue Docs](./packages/vue)
15
+ ```js
16
+ import { Blossom } from "@numbered/carousel/core";
17
+ import "@numbered/carousel/core/style.css";
38
18
 
39
- ```bash
40
- npm install @numbered/carousel/vue
19
+ const element = document.querySelector("#my-carousel-element");
20
+ // prepare the Blossom carousel
21
+ const blossom = Blossom(element);
22
+ // initialize whenever you want
23
+ blossom.init();
41
24
  ```
42
25
 
43
- ### Svelte
26
+ ## Lazy loading
44
27
 
45
- [Svelte Docs](./packages/svelte)
28
+ Load Blossom only when needed.
46
29
 
47
- ```bash
48
- npm install @numbered/carousel/svelte
49
- ```
30
+ ```js
31
+ const hasMouse = window.matchMedia(
32
+ "(hover: hover) and (pointer: fine)"
33
+ ).matches;
50
34
 
51
- ### Web Component
35
+ // We don't need Blossom's engine on touch devices
36
+ if (!hasMouse) return;
52
37
 
53
- [Web Component Docs](./packages/web)
38
+ const { Blossom } = await import("@numbered/carousel/core");
54
39
 
55
- ```bash
56
- npm install @numbered/carousel/web
40
+ const element = document.querySelector("#my-carousel-element");
41
+ const blossom = Blossom(element);
42
+ blossom.init();
57
43
  ```
58
44
 
59
- ### Core
45
+ ### Destroy
60
46
 
61
- [Core Docs](./packages/core)
47
+ Destroy the Blossom instance when you no longer need it to free up resources.
62
48
 
63
- ```bash
64
- npm install @numbered/carousel/core
49
+ ```js
50
+ blossom.destroy();
65
51
  ```
66
52
 
53
+ ### Get started in your favorite framework:
54
+
55
+ - [React](https://www.npmjs.com/package/@numbered/carousel/react)
56
+ - [Vue](https://www.npmjs.com/package/@numbered/carousel/vue)
57
+ - [Svelte](https://www.npmjs.com/package/@numbered/carousel/svelte)
58
+ - [Web Component](https://www.npmjs.com/package/@numbered/carousel/web)
59
+
67
60
  ## Examples
68
61
 
69
62
  - [Simple](https://www.blossom-carousel.com/docs/examples#simple)
@@ -0,0 +1 @@
1
+ [blossom-carousel]{display:inline-block;white-space:nowrap;overflow-x:auto;overflow-y:clip;scroll-behavior:smooth;overscroll-behavior-x:contain;list-style-type:none;inline-size:100%;max-inline-size:100vw;box-sizing:border-box}[blossom-carousel][has-repeat=true]{scroll-padding-inline:50%!important;padding-inline:50%!important}[blossom-carousel]>*{display:inline-block;white-space:initial;vertical-align:top}[blossom-carousel] *{-webkit-user-drag:none;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}[blossom-carousel].blossom-dragging>*{pointer-events:none}
@@ -0,0 +1,17 @@
1
+ interface HasOverflow {
2
+ x: boolean;
3
+ y: boolean;
4
+ }
5
+ export interface CarouselOptions {
6
+ repeat?: boolean;
7
+ }
8
+ export declare const Blossom: (scroller: HTMLElement, options: CarouselOptions) => {
9
+ init: () => void;
10
+ snap: boolean;
11
+ hasOverflow: HasOverflow;
12
+ currentIndex: () => number;
13
+ next: () => void;
14
+ prev: () => void;
15
+ destroy: () => void;
16
+ };
17
+ export {};
@@ -0,0 +1,387 @@
1
+ const $t = (i, r) => {
2
+ let U = !0;
3
+ const _ = { x: 0, y: 0 }, d = { x: 0, y: 0 }, m = { x: 0, y: 0 }, P = new Proxy(
4
+ { x: 0, y: 0 },
5
+ {
6
+ set(t, n, e) {
7
+ if (!X) {
8
+ if (t[n] === e) return !0;
9
+ t[n] = e, (t.x >= 10 || t.y >= 10) && E(!0);
10
+ }
11
+ return !0;
12
+ }
13
+ }
14
+ ), f = new Proxy(
15
+ { x: !1, y: !1 },
16
+ {
17
+ set(t, n, e) {
18
+ return t[n] === e || (t[n] = e, t.x || t.y ? (i.setAttribute("has-overflow", "true"), i.addEventListener("touchstart", F, { passive: !1 }), i.addEventListener("pointerdown", F, { passive: !1 }), i.addEventListener("wheel", ft, { passive: !1 })) : (i.removeAttribute("has-overflow"), i.removeEventListener("touchstart", F), i.removeEventListener("pointerdown", F), i.removeEventListener("wheel", ft))), !0;
19
+ }
20
+ }
21
+ ), p = new Proxy(
22
+ { value: 0, onChange: null },
23
+ {
24
+ set(t, n, e) {
25
+ if (t[n] === e) return !0;
26
+ if (t[n] = e, n === "value") {
27
+ const a = new CustomEvent("change", {
28
+ bubbles: !0,
29
+ detail: { index: e }
30
+ });
31
+ i == null || i.dispatchEvent(a);
32
+ }
33
+ return !0;
34
+ }
35
+ }
36
+ );
37
+ let K = 300, y = null, b = !1, A = 300, g = 300, st = 300, at = 300;
38
+ const rt = 0, V = { start: 0, end: 0 };
39
+ let J = 0, w = [], x = [], Q = [];
40
+ const S = [];
41
+ let B = [], I = null, T = null, lt = !1, ot = !1, X = !0, Y, c = 1;
42
+ function Pt() {
43
+ i == null || i.setAttribute("blossom-carousel", "true"), B = Array.from(i.children), window.addEventListener("keydown", dt), i.addEventListener("scroll", ut), c = i.closest('[dir="rtl"]') ? -1 : 1;
44
+ const { scrollSnapType: t } = window.getComputedStyle(i);
45
+ lt = t !== "none", i.style.setProperty("--snap-type", t), i.setAttribute("has-repeat", r != null && r.repeat ? "true" : "false"), ot = window.matchMedia("(hover: hover) and (pointer: fine)").matches, X = !ot && !(r != null && r.repeat), X || (i.style.scrollSnapType = "none"), Y = Dt((e) => {
46
+ (e === i || i.contains(e)) && E(!1);
47
+ }), I = new ResizeObserver(ct);
48
+ const n = i.parentElement;
49
+ n && i.clientWidth === n.clientWidth ? I.observe(n) : I.observe(i), T = new MutationObserver(Tt), T.observe(i, {
50
+ attributes: !1,
51
+ childList: !0,
52
+ subtree: !1
53
+ });
54
+ }
55
+ function At() {
56
+ i.removeAttribute("blossom-carousel"), I == null || I.disconnect(), T == null || T.disconnect(), y && cancelAnimationFrame(y), window.removeEventListener("keydown", dt), i.removeEventListener("scroll", ut), Y == null || Y();
57
+ }
58
+ function ct() {
59
+ if (!i) return;
60
+ E(!1);
61
+ for (let e = 0; e < x.length; e++) {
62
+ const s = x[e];
63
+ s.style.translate = "";
64
+ }
65
+ A = i.scrollWidth, g = i.clientWidth, st = i.scrollHeight, at = i.clientHeight;
66
+ const t = window.getComputedStyle(i);
67
+ f.x = // !hasTouch &&
68
+ A > g && ["auto", "scroll"].includes(t.getPropertyValue("overflow-x")), f.y = // !hasTouch &&
69
+ st > at && ["auto", "scroll"].includes(t.getPropertyValue("overflow-y")), Number.parseInt(t.paddingInlineStart, 10), Number.parseInt(t.paddingInlineEnd, 10), V.start = Number.parseInt(t.scrollPaddingInlineStart, 10) || 0, V.end = Number.parseInt(t.scrollPaddingInlineEnd, 10) || 0, c = i.closest('[dir="rtl"]') ? -1 : 1, J = Number.parseInt(t.gap, 10) || Number.parseInt(t.columnGap, 10) || 0, K = (A - g - rt + J) * c;
70
+ const n = lt ? kt(i) : { points: [], elements: [], alignments: [] };
71
+ w = n.points, x = n.elements, Q = n.alignments, d.x = l.x = w[p.value], i.scrollTo({ left: l.x, behavior: "instant" }), r != null && r.repeat && Z();
72
+ }
73
+ function Tt() {
74
+ ct();
75
+ }
76
+ function kt(t) {
77
+ const n = [];
78
+ let e = 0;
79
+ const s = (o) => {
80
+ if (e++, e > 100) return;
81
+ const z = window.getComputedStyle(o).scrollSnapAlign;
82
+ if (z !== "none") {
83
+ n.push({
84
+ align: z,
85
+ el: o
86
+ });
87
+ return;
88
+ }
89
+ const R = o.children;
90
+ if (R.length !== 0)
91
+ for (const D of R)
92
+ s(D);
93
+ };
94
+ s(t);
95
+ const a = t.getBoundingClientRect(), u = n.map(({ el: o, align: L }) => {
96
+ const z = o.getBoundingClientRect(), R = o.clientWidth, D = z.left - a.left + t.scrollLeft;
97
+ let G = null;
98
+ switch (L) {
99
+ case "start":
100
+ G = D - V.start;
101
+ break;
102
+ case "end":
103
+ G = D + R - g + V.end;
104
+ break;
105
+ case "center":
106
+ G = D + R * 0.5 - g / 2;
107
+ break;
108
+ }
109
+ return { position: G, element: o, align: L };
110
+ }), v = [], h = /* @__PURE__ */ new Set();
111
+ for (const o of u)
112
+ o.position !== null && !h.has(o.position) && (h.add(o.position), v.push({ position: o.position, element: o.element, align: o.align }));
113
+ return {
114
+ points: v.map((o) => o.position),
115
+ elements: v.map((o) => o.element),
116
+ alignments: v.map((o) => o.align)
117
+ };
118
+ }
119
+ function ut() {
120
+ if (b || !i) return;
121
+ if (C || (l.x = d.x = i.scrollLeft), r != null && r.repeat) {
122
+ Z(), it();
123
+ return;
124
+ }
125
+ const t = i.scrollLeft, n = Lt();
126
+ if (t < 0) {
127
+ const e = t * -1;
128
+ et(e);
129
+ } else if (t > n) {
130
+ const e = t * -1 + n;
131
+ et(e);
132
+ }
133
+ it();
134
+ }
135
+ const l = {
136
+ x: 0,
137
+ y: 0
138
+ };
139
+ function Ct() {
140
+ window.addEventListener("pointermove", H, { passive: !0 }), window.addEventListener("touchmove", H, { passive: !0 }), window.addEventListener("pointerup", O, { passive: !0 }), window.addEventListener("touchend", O, { passive: !0 });
141
+ }
142
+ function Wt() {
143
+ window.removeEventListener("pointermove", H), window.removeEventListener("touchmove", H), window.removeEventListener("pointerup", O), window.removeEventListener("touchend", O);
144
+ }
145
+ function F(t) {
146
+ var s, a;
147
+ if (!i) return;
148
+ const n = "touches" in t ? (s = t.touches[0]) == null ? void 0 : s.clientX : t.clientX, e = "touches" in t ? (a = t.touches[0]) == null ? void 0 : a.clientY : t.clientY;
149
+ f.x && wt("x", n), f.y && wt("y", e), P.x = 0, b = !0, Ct();
150
+ }
151
+ function H(t) {
152
+ var s, a;
153
+ const n = "touches" in t ? (s = t.touches[0]) == null ? void 0 : s.clientX : t.clientX, e = "touches" in t ? (a = t.touches[0]) == null ? void 0 : a.clientY : t.clientY;
154
+ f.x && xt("x", n), f.y && xt("y", e), (P.x > 2 || P.y > 2) && i.classList.add("blossom-dragging");
155
+ }
156
+ function O() {
157
+ Wt(), b = !1, i.classList.remove("blossom-dragging"), !(P.x <= 10) && (f.x && (m.x *= 2), f.y && (m.y *= 2), Nt());
158
+ }
159
+ function ft(t) {
160
+ if (Math.abs(t.deltaX) > Math.abs(t.deltaY)) {
161
+ if (E(!1), b || !i) return;
162
+ f.x && (l.x = i.scrollLeft), f.y && (l.y = i.scrollTop);
163
+ }
164
+ }
165
+ function dt(t) {
166
+ ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(t.key) && E(!1);
167
+ }
168
+ function Nt() {
169
+ let t;
170
+ if (r != null && r.repeat && x.length > 0) {
171
+ const n = w.length;
172
+ if (n >= 2) {
173
+ const e = (p.value % n + n) % n, s = m.x * c >= 0 ? 1 : -1, a = (e + s + n) % n;
174
+ t = Yt(a, s);
175
+ } else
176
+ t = yt({ axis: "x" });
177
+ } else if (!(r != null && r.repeat) && x.length) {
178
+ const n = St();
179
+ t = bt(yt({ axis: "x" }), n.min, n.max);
180
+ }
181
+ t !== void 0 && It(t);
182
+ }
183
+ const $ = [], j = /* @__PURE__ */ new Map();
184
+ function Z() {
185
+ if (!i) return;
186
+ const t = N();
187
+ if (t === 0) return;
188
+ l.x >= K ? (l.x -= t, d.x -= t, C || i.scrollTo({ left: l.x, behavior: "instant" })) : l.x <= rt && (l.x += t, d.x += t, C || i.scrollTo({ left: l.x, behavior: "instant" }));
189
+ const n = l.x;
190
+ j.clear(), $.length = w.length;
191
+ for (let e = 0; e < x.length; e++) {
192
+ const s = x[e], a = w[e] ?? 0, u = Q[e] ?? "start", v = u === "start" ? 0 : u === "end" ? (g - s.clientWidth) / 2 : (-g + s.clientWidth) / 2, h = (n - a + v) / t, L = Math.round(h + (m.x >= 0 ? 1e-3 : -1e-3)) * t;
193
+ s.style.translate = `${L}px 0`, j.set(s, L), $[e] = a + L;
194
+ }
195
+ for (let e = 0; e < B.length; e++) {
196
+ const s = B[e];
197
+ if (j.has(s)) continue;
198
+ let a = 0;
199
+ for (let u = e - 1; u >= 0; u--) {
200
+ const v = B[u], h = j.get(v);
201
+ if (h !== void 0) {
202
+ a = h;
203
+ break;
204
+ }
205
+ }
206
+ s.style.translate = `${a}px 0`;
207
+ }
208
+ S.length = 0;
209
+ for (let e = 0; e < $.length; e++) S.push($[e]);
210
+ }
211
+ const k = 0.72, ht = 0.12;
212
+ let C = !1;
213
+ function E(t) {
214
+ i && (t && !C ? (tt = performance.now(), f.x && (d.x = i.scrollLeft), f.y && (d.y = i.scrollTop), y || (y = requestAnimationFrame(mt))) : !t && y && (cancelAnimationFrame(y), y = null), C = t, U = !t, i.setAttribute("has-snap", U ? "true" : "false"));
215
+ }
216
+ let q = 0, tt = 0;
217
+ function mt(t) {
218
+ y = requestAnimationFrame(mt), q = t - tt, i && (f.x && pt("x"), f.y && pt("y"), r != null && r.repeat ? Z() : Rt(Et(l.x, 2)), W = !0, i.scrollTo({
219
+ left: l.x,
220
+ top: l.y,
221
+ behavior: "instant"
222
+ }), it(), tt = t);
223
+ }
224
+ let M = 0;
225
+ function Rt(t) {
226
+ if (!i) return;
227
+ const n = K;
228
+ let e = 0;
229
+ if (t * c <= 0 ? e = b ? t * -0.2 : 0 : t * c > n * c && (e = b ? (t - n) * -0.2 : 0), M = nt(M, e, b ? 0.8 : ht, q), Math.abs(M) > 0.01) {
230
+ if (et(M).defaultPrevented) return;
231
+ i.style.transform = `translateX(${Et(M, 3)}px)`;
232
+ return;
233
+ }
234
+ i.style.transform = "", M = 0;
235
+ }
236
+ function et(t) {
237
+ const n = new CustomEvent("overscroll", {
238
+ bubbles: !0,
239
+ cancelable: !0,
240
+ detail: { left: t }
241
+ });
242
+ return i == null || i.dispatchEvent(n), n;
243
+ }
244
+ let W = !1;
245
+ const vt = i.scrollTo.bind(i);
246
+ i.scrollTo = (t, n) => {
247
+ W === !0 || E(!1), W = !1, typeof t == "number" ? vt(t, n ?? 0) : vt(t);
248
+ };
249
+ const gt = i.scrollBy.bind(i);
250
+ i.scrollBy = (t, n) => {
251
+ W === !0 || E(!1), W = !1, typeof t == "number" ? gt(t, n ?? 0) : gt(t);
252
+ };
253
+ function Dt(t) {
254
+ const n = [], e = Element.prototype.scrollIntoView;
255
+ return e && (Element.prototype.scrollIntoView = function(s) {
256
+ t(this, "scrollIntoView", [s]), e.call(this, s);
257
+ }, n.push(() => {
258
+ Element.prototype.scrollIntoView = e;
259
+ })), () => n.forEach((s) => {
260
+ s();
261
+ });
262
+ }
263
+ function wt(t, n) {
264
+ const e = t === "x" ? "scrollLeft" : "scrollTop";
265
+ l[t] = i[e], d[t] = i[e], _[t] = n, m[t] = 0;
266
+ }
267
+ function xt(t, n) {
268
+ const e = _[t] - n;
269
+ d[t] += e, m[t] += e, _[t] = n, P[t] += Math.abs(e);
270
+ }
271
+ function pt(t) {
272
+ m[t] *= k, b ? l[t] = nt(l[t], d[t], k, q) : (d[t] += m[t], l[t] = nt(l[t], d[t], ht, q));
273
+ }
274
+ function Vt({ axis: t = "x" }) {
275
+ return d[t] + m[t] / (1 - k);
276
+ }
277
+ function yt({ axis: t = "x" }) {
278
+ const n = Vt({ axis: t });
279
+ return (S.length ? S : w).reduce((s, a) => Math.abs(a - n) < Math.abs(s - n) ? a : s);
280
+ }
281
+ function Bt(t, n, e) {
282
+ return (1 - e) * t + e * n;
283
+ }
284
+ function nt(t, n, e, s) {
285
+ return Bt(t, n, 1 - Math.exp(Math.log(1 - e) * (s / 16.666666666666668)));
286
+ }
287
+ function bt(t, n, e) {
288
+ return t < n ? n : t > e ? e : t;
289
+ }
290
+ function Et(t, n = 0) {
291
+ const e = 10 ** n;
292
+ return Math.round(t * e) / e;
293
+ }
294
+ function N() {
295
+ return A - g + J;
296
+ }
297
+ function Lt() {
298
+ return A - g;
299
+ }
300
+ function St() {
301
+ const t = Lt();
302
+ return {
303
+ min: Math.min(t * c, 0),
304
+ max: Math.max(t * c, 0)
305
+ };
306
+ }
307
+ function Xt(t, n) {
308
+ const e = N();
309
+ if (e <= 0) return t;
310
+ const s = Math.round((n - t) / e);
311
+ return t + s * e;
312
+ }
313
+ function It(t, n) {
314
+ if (t === void 0 || Number.isNaN(t)) return;
315
+ E(!0), d.x = l.x;
316
+ let e = t - l.x;
317
+ if (r != null && r.repeat) {
318
+ const a = N();
319
+ a > 0 && (e = e - Math.round(e / a) * a, n === 1 && e * c <= 0 && (e += a * c), n === -1 && e * c >= 0 && (e -= a * c));
320
+ }
321
+ const s = e * (1 - k) * (1 / k);
322
+ m.x = s;
323
+ }
324
+ function Yt(t, n) {
325
+ const e = w[t] ?? 0, s = Xt(e, l.x), a = N();
326
+ if (a <= 0) return s;
327
+ const u = s - l.x;
328
+ return n === 1 && u * c <= 0 ? s + a * c : n === -1 && u * c >= 0 ? s - a * c : s;
329
+ }
330
+ function Ft() {
331
+ const t = r != null && r.repeat && S.length ? S : w;
332
+ if (!t.length) return 0;
333
+ const n = i.scrollLeft;
334
+ let e = 0, s = Math.abs(t[0] - n);
335
+ for (let a = 1; a < t.length; a++) {
336
+ const u = Math.abs(t[a] - n);
337
+ u < s && (s = u, e = a);
338
+ }
339
+ return e;
340
+ }
341
+ function it() {
342
+ const t = Ft();
343
+ p.value !== t && (p.value = t);
344
+ }
345
+ function Mt(t) {
346
+ if (x.length <= 1) return;
347
+ const n = w, e = r != null && r.repeat ? (p.value + t + n.length) % n.length : t === 1 ? Math.min(p.value + 1, n.length - 1) : Math.max(p.value - 1, 0);
348
+ if (X) {
349
+ const a = Q[e] ?? "start";
350
+ x[e].scrollIntoView({
351
+ behavior: "smooth",
352
+ block: "nearest",
353
+ inline: a
354
+ });
355
+ return;
356
+ }
357
+ let s;
358
+ if (r != null && r.repeat && n.length >= 2) {
359
+ const a = N(), u = n[e], v = a > 0 ? Math.round((l.x - u) / a) : 0;
360
+ let h = u + v * a;
361
+ const o = h - l.x;
362
+ t === 1 && o * c <= 0 && (h += a * c), t === -1 && o * c >= 0 && (h -= a * c), s = h;
363
+ } else {
364
+ const a = St();
365
+ s = bt(n[e], a.min, a.max);
366
+ }
367
+ It(s, t);
368
+ }
369
+ function Ht() {
370
+ Mt(1);
371
+ }
372
+ function Ot() {
373
+ Mt(-1);
374
+ }
375
+ return {
376
+ init: Pt,
377
+ snap: U,
378
+ hasOverflow: f,
379
+ currentIndex: () => p.value,
380
+ next: Ht,
381
+ prev: Ot,
382
+ destroy: At
383
+ };
384
+ };
385
+ export {
386
+ $t as Blossom
387
+ };
@@ -0,0 +1 @@
1
+ (function(S,T){typeof exports=="object"&&typeof module<"u"?T(exports):typeof define=="function"&&define.amd?define(["exports"],T):(S=typeof globalThis<"u"?globalThis:S||self,T(S.BlossomCarousel={}))})(this,function(S){"use strict";const T=(i,o)=>{let K=!0;const J={x:0,y:0},d={x:0,y:0},m={x:0,y:0},A=new Proxy({x:0,y:0},{set(e,n,t){if(!F){if(e[n]===t)return!0;e[n]=t,(e.x>=10||e.y>=10)&&E(!0)}return!0}}),f=new Proxy({x:!1,y:!1},{set(e,n,t){return e[n]===t||(e[n]=t,e.x||e.y?(i.setAttribute("has-overflow","true"),i.addEventListener("touchstart",H,{passive:!1}),i.addEventListener("pointerdown",H,{passive:!1}),i.addEventListener("wheel",he,{passive:!1})):(i.removeAttribute("has-overflow"),i.removeEventListener("touchstart",H),i.removeEventListener("pointerdown",H),i.removeEventListener("wheel",he))),!0}}),x=new Proxy({value:0,onChange:null},{set(e,n,t){if(e[n]===t)return!0;if(e[n]=t,n==="value"){const a=new CustomEvent("change",{bubbles:!0,detail:{index:t}});i==null||i.dispatchEvent(a)}return!0}});let Q=300,y=null,b=!1,k=300,g=300,oe=300,le=300;const re=0,X={start:0,end:0};let Z=0,p=[],w=[],ee=[];const M=[];let Y=[],I=null,C=null,ce=!1,ue=!1,F=!0,j,c=1;function Ae(){i==null||i.setAttribute("blossom-carousel","true"),Y=Array.from(i.children),window.addEventListener("keydown",me),i.addEventListener("scroll",de),c=i.closest('[dir="rtl"]')?-1:1;const{scrollSnapType:e}=window.getComputedStyle(i);ce=e!=="none",i.style.setProperty("--snap-type",e),i.setAttribute("has-repeat",o!=null&&o.repeat?"true":"false"),ue=window.matchMedia("(hover: hover) and (pointer: fine)").matches,F=!ue&&!(o!=null&&o.repeat),F||(i.style.scrollSnapType="none"),j=Ve(t=>{(t===i||i.contains(t))&&E(!1)}),I=new ResizeObserver(fe);const n=i.parentElement;n&&i.clientWidth===n.clientWidth?I.observe(n):I.observe(i),C=new MutationObserver(Ce),C.observe(i,{attributes:!1,childList:!0,subtree:!1})}function ke(){i.removeAttribute("blossom-carousel"),I==null||I.disconnect(),C==null||C.disconnect(),y&&cancelAnimationFrame(y),window.removeEventListener("keydown",me),i.removeEventListener("scroll",de),j==null||j()}function fe(){if(!i)return;E(!1);for(let t=0;t<w.length;t++){const s=w[t];s.style.translate=""}k=i.scrollWidth,g=i.clientWidth,oe=i.scrollHeight,le=i.clientHeight;const e=window.getComputedStyle(i);f.x=k>g&&["auto","scroll"].includes(e.getPropertyValue("overflow-x")),f.y=oe>le&&["auto","scroll"].includes(e.getPropertyValue("overflow-y")),Number.parseInt(e.paddingInlineStart,10),Number.parseInt(e.paddingInlineEnd,10),X.start=Number.parseInt(e.scrollPaddingInlineStart,10)||0,X.end=Number.parseInt(e.scrollPaddingInlineEnd,10)||0,c=i.closest('[dir="rtl"]')?-1:1,Z=Number.parseInt(e.gap,10)||Number.parseInt(e.columnGap,10)||0,Q=(k-g-re+Z)*c;const n=ce?We(i):{points:[],elements:[],alignments:[]};p=n.points,w=n.elements,ee=n.alignments,d.x=l.x=p[x.value],i.scrollTo({left:l.x,behavior:"instant"}),o!=null&&o.repeat&&te()}function Ce(){fe()}function We(e){const n=[];let t=0;const s=r=>{if(t++,t>100)return;const U=window.getComputedStyle(r).scrollSnapAlign;if(U!=="none"){n.push({align:U,el:r});return}const D=r.children;if(D.length!==0)for(const V of D)s(V)};s(e);const a=e.getBoundingClientRect(),u=n.map(({el:r,align:L})=>{const U=r.getBoundingClientRect(),D=r.clientWidth,V=U.left-a.left+e.scrollLeft;let _=null;switch(L){case"start":_=V-X.start;break;case"end":_=V+D-g+X.end;break;case"center":_=V+D*.5-g/2;break}return{position:_,element:r,align:L}}),v=[],h=new Set;for(const r of u)r.position!==null&&!h.has(r.position)&&(h.add(r.position),v.push({position:r.position,element:r.element,align:r.align}));return{points:v.map(r=>r.position),elements:v.map(r=>r.element),alignments:v.map(r=>r.align)}}function de(){if(b||!i)return;if(B||(l.x=d.x=i.scrollLeft),o!=null&&o.repeat){te(),ae();return}const e=i.scrollLeft,n=Me();if(e<0){const t=e*-1;ie(t)}else if(e>n){const t=e*-1+n;ie(t)}ae()}const l={x:0,y:0};function Be(){window.addEventListener("pointermove",O,{passive:!0}),window.addEventListener("touchmove",O,{passive:!0}),window.addEventListener("pointerup",$,{passive:!0}),window.addEventListener("touchend",$,{passive:!0})}function Ne(){window.removeEventListener("pointermove",O),window.removeEventListener("touchmove",O),window.removeEventListener("pointerup",$),window.removeEventListener("touchend",$)}function H(e){var s,a;if(!i)return;const n="touches"in e?(s=e.touches[0])==null?void 0:s.clientX:e.clientX,t="touches"in e?(a=e.touches[0])==null?void 0:a.clientY:e.clientY;f.x&&xe("x",n),f.y&&xe("y",t),A.x=0,b=!0,Be()}function O(e){var s,a;const n="touches"in e?(s=e.touches[0])==null?void 0:s.clientX:e.clientX,t="touches"in e?(a=e.touches[0])==null?void 0:a.clientY:e.clientY;f.x&&ye("x",n),f.y&&ye("y",t),(A.x>2||A.y>2)&&i.classList.add("blossom-dragging")}function $(){Ne(),b=!1,i.classList.remove("blossom-dragging"),!(A.x<=10)&&(f.x&&(m.x*=2),f.y&&(m.y*=2),Re())}function he(e){if(Math.abs(e.deltaX)>Math.abs(e.deltaY)){if(E(!1),b||!i)return;f.x&&(l.x=i.scrollLeft),f.y&&(l.y=i.scrollTop)}}function me(e){["ArrowLeft","ArrowRight","ArrowUp","ArrowDown"].includes(e.key)&&E(!1)}function Re(){let e;if(o!=null&&o.repeat&&w.length>0){const n=p.length;if(n>=2){const t=(x.value%n+n)%n,s=m.x*c>=0?1:-1,a=(t+s+n)%n;e=je(a,s)}else e=Ee({axis:"x"})}else if(!(o!=null&&o.repeat)&&w.length){const n=Ie();e=Le(Ee({axis:"x"}),n.min,n.max)}e!==void 0&&Pe(e)}const q=[],z=new Map;function te(){if(!i)return;const e=R();if(e===0)return;l.x>=Q?(l.x-=e,d.x-=e,B||i.scrollTo({left:l.x,behavior:"instant"})):l.x<=re&&(l.x+=e,d.x+=e,B||i.scrollTo({left:l.x,behavior:"instant"}));const n=l.x;z.clear(),q.length=p.length;for(let t=0;t<w.length;t++){const s=w[t],a=p[t]??0,u=ee[t]??"start",v=u==="start"?0:u==="end"?(g-s.clientWidth)/2:(-g+s.clientWidth)/2,h=(n-a+v)/e,L=Math.round(h+(m.x>=0?.001:-.001))*e;s.style.translate=`${L}px 0`,z.set(s,L),q[t]=a+L}for(let t=0;t<Y.length;t++){const s=Y[t];if(z.has(s))continue;let a=0;for(let u=t-1;u>=0;u--){const v=Y[u],h=z.get(v);if(h!==void 0){a=h;break}}s.style.translate=`${a}px 0`}M.length=0;for(let t=0;t<q.length;t++)M.push(q[t])}const W=.72,ve=.12;let B=!1;function E(e){i&&(e&&!B?(ne=performance.now(),f.x&&(d.x=i.scrollLeft),f.y&&(d.y=i.scrollTop),y||(y=requestAnimationFrame(ge))):!e&&y&&(cancelAnimationFrame(y),y=null),B=e,K=!e,i.setAttribute("has-snap",K?"true":"false"))}let G=0,ne=0;function ge(e){y=requestAnimationFrame(ge),G=e-ne,i&&(f.x&&be("x"),f.y&&be("y"),o!=null&&o.repeat?te():De(Se(l.x,2)),N=!0,i.scrollTo({left:l.x,top:l.y,behavior:"instant"}),ae(),ne=e)}let P=0;function De(e){if(!i)return;const n=Q;let t=0;if(e*c<=0?t=b?e*-.2:0:e*c>n*c&&(t=b?(e-n)*-.2:0),P=se(P,t,b?.8:ve,G),Math.abs(P)>.01){if(ie(P).defaultPrevented)return;i.style.transform=`translateX(${Se(P,3)}px)`;return}i.style.transform="",P=0}function ie(e){const n=new CustomEvent("overscroll",{bubbles:!0,cancelable:!0,detail:{left:e}});return i==null||i.dispatchEvent(n),n}let N=!1;const pe=i.scrollTo.bind(i);i.scrollTo=(e,n)=>{N===!0||E(!1),N=!1,typeof e=="number"?pe(e,n??0):pe(e)};const we=i.scrollBy.bind(i);i.scrollBy=(e,n)=>{N===!0||E(!1),N=!1,typeof e=="number"?we(e,n??0):we(e)};function Ve(e){const n=[],t=Element.prototype.scrollIntoView;return t&&(Element.prototype.scrollIntoView=function(s){e(this,"scrollIntoView",[s]),t.call(this,s)},n.push(()=>{Element.prototype.scrollIntoView=t})),()=>n.forEach(s=>{s()})}function xe(e,n){const t=e==="x"?"scrollLeft":"scrollTop";l[e]=i[t],d[e]=i[t],J[e]=n,m[e]=0}function ye(e,n){const t=J[e]-n;d[e]+=t,m[e]+=t,J[e]=n,A[e]+=Math.abs(t)}function be(e){m[e]*=W,b?l[e]=se(l[e],d[e],W,G):(d[e]+=m[e],l[e]=se(l[e],d[e],ve,G))}function Xe({axis:e="x"}){return d[e]+m[e]/(1-W)}function Ee({axis:e="x"}){const n=Xe({axis:e});return(M.length?M:p).reduce((s,a)=>Math.abs(a-n)<Math.abs(s-n)?a:s)}function Ye(e,n,t){return(1-t)*e+t*n}function se(e,n,t,s){return Ye(e,n,1-Math.exp(Math.log(1-t)*(s/16.666666666666668)))}function Le(e,n,t){return e<n?n:e>t?t:e}function Se(e,n=0){const t=10**n;return Math.round(e*t)/t}function R(){return k-g+Z}function Me(){return k-g}function Ie(){const e=Me();return{min:Math.min(e*c,0),max:Math.max(e*c,0)}}function Fe(e,n){const t=R();if(t<=0)return e;const s=Math.round((n-e)/t);return e+s*t}function Pe(e,n){if(e===void 0||Number.isNaN(e))return;E(!0),d.x=l.x;let t=e-l.x;if(o!=null&&o.repeat){const a=R();a>0&&(t=t-Math.round(t/a)*a,n===1&&t*c<=0&&(t+=a*c),n===-1&&t*c>=0&&(t-=a*c))}const s=t*(1-W)*(1/W);m.x=s}function je(e,n){const t=p[e]??0,s=Fe(t,l.x),a=R();if(a<=0)return s;const u=s-l.x;return n===1&&u*c<=0?s+a*c:n===-1&&u*c>=0?s-a*c:s}function He(){const e=o!=null&&o.repeat&&M.length?M:p;if(!e.length)return 0;const n=i.scrollLeft;let t=0,s=Math.abs(e[0]-n);for(let a=1;a<e.length;a++){const u=Math.abs(e[a]-n);u<s&&(s=u,t=a)}return t}function ae(){const e=He();x.value!==e&&(x.value=e)}function Te(e){if(w.length<=1)return;const n=p,t=o!=null&&o.repeat?(x.value+e+n.length)%n.length:e===1?Math.min(x.value+1,n.length-1):Math.max(x.value-1,0);if(F){const a=ee[t]??"start";w[t].scrollIntoView({behavior:"smooth",block:"nearest",inline:a});return}let s;if(o!=null&&o.repeat&&n.length>=2){const a=R(),u=n[t],v=a>0?Math.round((l.x-u)/a):0;let h=u+v*a;const r=h-l.x;e===1&&r*c<=0&&(h+=a*c),e===-1&&r*c>=0&&(h-=a*c),s=h}else{const a=Ie();s=Le(n[t],a.min,a.max)}Pe(s,e)}function Oe(){Te(1)}function $e(){Te(-1)}return{init:Ae,snap:K,hasOverflow:f,currentIndex:()=>x.value,next:Oe,prev:$e,destroy:ke}};S.Blossom=T,Object.defineProperty(S,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1 @@
1
+ export { Blossom, type CarouselOptions } from './carousel';
package/package.json CHANGED
@@ -1,33 +1,45 @@
1
1
  {
2
2
  "name": "@haventmet/carousel",
3
- "version": "1.0.0",
4
- "private": false,
3
+ "version": "1.0.1",
5
4
  "author": "Loris",
6
5
  "license": "MIT",
7
6
  "description": "A native-scroll-first carousel component for the web.",
8
7
  "repository": {
9
8
  "type": "git",
10
- "url": "git+https://github.com/loris-numbered/carousel.git"
9
+ "url": "git+https://github.com/loris-numbered/carousel"
11
10
  },
12
11
  "bugs": {
13
12
  "url": "https://github.com/loris-numbered/carousel/issues"
14
13
  },
15
- "main": "index.js",
14
+ "homepage": "https://www.blossom-carousel.com",
15
+ "type": "module",
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "main": "dist/carousel.umd.cjs",
20
+ "module": "dist/carousel.js",
21
+ "types": "dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/carousel.js",
26
+ "require": "./dist/carousel.umd.cjs"
27
+ },
28
+ "./style.css": "./dist/carousel.css"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
16
33
  "scripts": {
17
- "test": "echo \"Error: no test specified\" && exit 1",
18
- "dev": "pnpm --filter @haventmet/carousel-dev dev",
19
- "dev:vue": "pnpm --filter @haventmet/carousel-vue dev",
20
- "dev:react": "pnpm --filter @haventmet/carousel-react dev",
21
- "dev:svelte": "pnpm --filter @haventmet/carousel-svelte dev",
22
- "dev:web": "pnpm --filter @haventmet/carousel-web dev",
23
- "dev:alpine": "pnpm --filter @haventmet/carousel-alpine dev"
34
+ "dev": "vite",
35
+ "build": "vite build",
36
+ "preview": "vite preview"
24
37
  },
25
- "workspaces": [
26
- "packages/*"
27
- ],
28
38
  "devDependencies": {
29
- "biome": "^0.3.3",
30
- "turbo": "^2.5.0"
39
+ "tsup": "^6.0.0"
31
40
  },
32
- "packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748"
41
+ "dependencies": {
42
+ "vite": "^6.3.3",
43
+ "vite-plugin-dts": "^4.5.3"
44
+ }
33
45
  }
package/.mcp.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "mcpServers": {
3
- "chrome-devtools": {
4
- "command": "bunx",
5
- "args": ["chrome-devtools-mcp@latest"]
6
- }
7
- }
8
- }