@muten/shadcn 0.2.5 → 0.2.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@muten/shadcn",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "shadcn-style component registry for muten - own-the-source parts you add with `muten add`.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -134,8 +134,13 @@ export function carouselBehavior(root, i, core) {
134
134
  track.tabIndex = 0;
135
135
  track.addEventListener('keydown', (e) => { if (e.key === 'ArrowRight') { e.preventDefault(); go(current() + 1); } if (e.key === 'ArrowLeft') { e.preventDefault(); go(current() - 1); } });
136
136
  let drag = null;
137
- track.addEventListener('pointerdown', (e) => { if (e.pointerType !== 'mouse' || e.button > 0) return; drag = { x: e.clientX, left: track.scrollLeft, moved: false }; track.classList.add('dragging'); });
138
- addEventListener('pointermove', (e) => { if (!drag) return; const dx = e.clientX - drag.x; if (Math.abs(dx) > 4) drag.moved = true; track.scrollLeft = drag.left - dx; });
137
+ // a track with nothing to scroll (only: "phone" on a wide screen) is not dragged at all
138
+ track.addEventListener('pointerdown', (e) => { if (e.pointerType !== 'mouse' || e.button > 0 || track.scrollWidth <= track.clientWidth + 1) return; drag = { x: e.clientX, left: track.scrollLeft, moved: false }; track.classList.add('dragging'); });
139
+ // A slide that is a link or a picture starts the browser's own drag: it ends in pointercancel, never pointerup, and the
140
+ // track went on following the mouse with the button already up. So the browser's drag is refused inside the track,
141
+ // and a move with no button down (released outside the window, or a lost pointerup) ends the drag too.
142
+ track.addEventListener('dragstart', (e) => e.preventDefault());
143
+ addEventListener('pointermove', (e) => { if (!drag) return; if (!(e.buttons & 1)) { release(); return; } const dx = e.clientX - drag.x; if (Math.abs(dx) > 4) drag.moved = true; track.scrollLeft = drag.left - dx; });
139
144
  // A drag lets go between two pages (snapping is off while dragging): settle on the nearest one, as a swipe does,
140
145
  // or the track rests half-way and the dots and arrows disagree about where it is.
141
146
  const nearest = () => {
@@ -143,7 +148,11 @@ export function carouselBehavior(root, i, core) {
143
148
  if (track.scrollLeft >= track.scrollWidth - track.clientWidth - 4) return pages() - 1;
144
149
  return Math.max(0, Math.min(pages() - 1, Math.round(track.scrollLeft / (step() * perPage()))));
145
150
  };
146
- addEventListener('pointerup', () => { if (!drag) return; const moved = drag.moved; drag = null; track.classList.remove('dragging'); if (moved) { go(nearest()); track.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); }, { capture: true, once: true }); } });
151
+ function release() { if (!drag) return; const moved = drag.moved; drag = null; track.classList.remove('dragging'); if (moved) { go(nearest()); swallowClick(); } }
152
+ // the click that ends a drag is not a tap on the slide; only that one: a drag that ended without a click (pointercancel)
153
+ // must not leave the next real tap swallowed
154
+ function swallowClick() { const eat = (e) => { e.preventDefault(); e.stopPropagation(); }; track.addEventListener('click', eat, { capture: true, once: true }); setTimeout(() => track.removeEventListener('click', eat, { capture: true }), 0); }
155
+ ['pointerup', 'pointercancel', 'blur'].forEach((type) => addEventListener(type, release));
147
156
  let playing = !!autoplay && !matchMedia('(prefers-reduced-motion: reduce)').matches, hold = false;
148
157
  if (autoplay) {
149
158
  if (!playing) { const b = $('[data-car="play"]', root); b.innerHTML = ui.icon('play'); b.setAttribute('aria-label', T('Play')); }