@enigmax/primitives 0.1.1 → 0.1.2

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.
@@ -88,13 +88,19 @@ function createMarquee(lane, track, options = {}) {
88
88
  }
89
89
  function measure() {
90
90
  if (destroyed) return;
91
- const measured = readPeriod();
92
- const needed = requiredCopies(measured);
91
+ const cloning = opts.copies === "clone";
92
+ if (cloning && track.children.length < 2) syncClones(2);
93
+ let measured = readPeriod();
94
+ let needed = requiredCopies(measured);
95
+ if (cloning && track.children.length !== needed) {
96
+ syncClones(needed);
97
+ measured = readPeriod();
98
+ needed = requiredCopies(measured);
99
+ }
93
100
  const changed = measured !== period || needed !== copyCount;
94
101
  period = measured;
95
102
  if (needed !== copyCount) {
96
103
  copyCount = needed;
97
- if (opts.copies === "clone") syncClones(needed);
98
104
  opts.onCopyCountChange?.(needed);
99
105
  }
100
106
  if (period > 0) offset = wrap(offset);
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export { createMarquee } from './chunk-QDGZANPT.js';
1
+ export { createMarquee } from './chunk-55J5JEWX.js';
@@ -1,4 +1,4 @@
1
- import { createMarquee } from '../chunk-QDGZANPT.js';
1
+ import { createMarquee } from '../chunk-55J5JEWX.js';
2
2
  import { useRef, useState, useEffect, useLayoutEffect } from 'react';
3
3
 
4
4
  var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enigmax/primitives",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Headless interaction primitives: the behaviour, the timing and the accessibility of components like a draggable infinite marquee, with no styles of their own. Framework-agnostic core plus thin adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -205,13 +205,30 @@ export function createMarquee(lane: HTMLElement, track: HTMLElement, options: Ma
205
205
 
206
206
  function measure(): void {
207
207
  if (destroyed) return;
208
- const measured = readPeriod();
209
- const needed = requiredCopies(measured);
208
+ const cloning = opts.copies === "clone";
209
+
210
+ // The lap can only be READ from the step between two copies, so the second one
211
+ // has to exist before the number is worth anything. Without this, markup that
212
+ // ships a single copy is measured by that copy's own width instead.
213
+ if (cloning && track.children.length < 2) syncClones(2);
214
+
215
+ let measured = readPeriod();
216
+ let needed = requiredCopies(measured);
217
+
218
+ // Reconcile against the DOM, not against the previous count. `copyCount` starts
219
+ // optimistically at 2 while the markup carries one copy, so keying the clone on
220
+ // "the count changed" left a row that needs exactly 2 copies with only its
221
+ // original - and a visible gap once the lap scrolled past the lane.
222
+ if (cloning && track.children.length !== needed) {
223
+ syncClones(needed);
224
+ measured = readPeriod();
225
+ needed = requiredCopies(measured);
226
+ }
227
+
210
228
  const changed = measured !== period || needed !== copyCount;
211
229
  period = measured;
212
230
  if (needed !== copyCount) {
213
231
  copyCount = needed;
214
- if (opts.copies === "clone") syncClones(needed);
215
232
  opts.onCopyCountChange?.(needed);
216
233
  }
217
234
  if (period > 0) offset = wrap(offset);