@stapel/listings-react 0.30.2 → 0.30.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # @stapel/listings-react
2
2
 
3
+ ## 0.30.3
4
+
5
+ ### Patch Changes
6
+
7
+ - bbb8454: A swipe advances exactly one photo, and only past a real threshold
8
+
9
+ The card gallery committed an advance after a fixed `SWIPE_MIN_PX = 32` of
10
+ travel, whatever the photo's size — 9.1% of a slide on a one-column phone card
11
+ and 18.8% on a two-column feed tile. Worse, the gesture's origin was reset on
12
+ every commit, so one continuous drag committed once per 32px travelled: a drag
13
+ across three slide widths advanced three photos, and a fling advanced as many
14
+ as there were. The middle photo flew past on a light gesture.
15
+
16
+ `swipeStep(dx, dy, slideWidth, velocity)` now commits on either:
17
+
18
+ - **distance** — at least `SWIPE_COMMIT_FRACTION` (0.3) of the SLIDE's own
19
+ measured width, via `measureSlideWidth()` (the first slide's box, taken once
20
+ at pointerdown; the media well is 8% too generous because of the carousel's
21
+ peek, and the viewport is not the geometry that matters), or
22
+ - **velocity** — at least `SWIPE_FLICK_VELOCITY` (0.5 px/ms) over a
23
+ `SWIPE_VELOCITY_WINDOW_MS` (100ms) moving window, so a gesture that crawls
24
+ and is then thrown is read as the throw the person meant.
25
+
26
+ It returns only `-1 | 0 | 1`, and a per-gesture latch means one press can never
27
+ move more than one photo. A horizontal gesture that falls short snaps back to
28
+ the active slide. `SWIPE_MIN_PX` stays as a tap-wobble floor and is documented
29
+ as a floor rather than as the price.
30
+
31
+ The detail gallery's strip is native scroll-snap; it gains
32
+ `scroll-snap-stop: always`, so a fling comes to rest on the next photograph
33
+ instead of flying past however many its momentum carried.
34
+
35
+ `measureSlideWidth` returns `0` when nothing is laid out, and `swipeStep` then
36
+ falls back to the pixel floor rather than inventing a width. The extra
37
+ parameters are additive, so an existing two-argument caller is unchanged.
38
+
3
39
  ## 0.30.2
4
40
 
5
41
  ### Patch Changes
@@ -8,13 +8,52 @@ export declare const CARD_GALLERY_STYLE_HREF = "stapel-listings-card-gallery";
8
8
  /** The environment a hover scrub is allowed in, and the only one. */
9
9
  export declare const SCRUB_MEDIA = "(hover: hover) and (pointer: fine)";
10
10
  /**
11
- * How far a finger travels before it has said "photo", in CSS pixels.
11
+ * How far a finger travels before it is a GESTURE at all, in CSS pixels.
12
12
  *
13
13
  * Under this, a drag is a tap that wobbled — and a tap on a card is a
14
14
  * navigation, so a low threshold does not change a photograph, it changes one
15
15
  * and then leaves the listing.
16
+ *
17
+ * This is the floor, not the price: what actually buys a photograph is
18
+ * {@link SWIPE_COMMIT_FRACTION} of the slide, or a flick above
19
+ * {@link SWIPE_FLICK_VELOCITY}. A pixel count cannot be the price, because
20
+ * the same 32px is a third of a card in a four-column desktop grid and a
21
+ * twelfth of one on a phone.
16
22
  */
17
23
  export declare const SWIPE_MIN_PX = 32;
24
+ /**
25
+ * How much of ONE PHOTOGRAPH a slow drag must cover to turn it, as a fraction
26
+ * of that photograph's own measured width.
27
+ *
28
+ * The owner's ruling, third pass: "maybe not 75, maybe 30 — right now it
29
+ * feels like 10%". 10% is what the old fixed 32px came to on a phone slide of
30
+ * ~350px, and it is why a middle photograph flew past on a gesture aimed at
31
+ * the feed. 0.3 is far enough that the drag is unmistakably a drag and short
32
+ * enough that a thumb can make it without crossing the whole card.
33
+ */
34
+ export declare const SWIPE_COMMIT_FRACTION = 0.3;
35
+ /**
36
+ * The speed, in CSS pixels per millisecond, at which a SHORT drag still turns
37
+ * the photograph.
38
+ *
39
+ * 0.5 px/ms — 500 px/s — is the owner's number and sits in the empty band
40
+ * between the two gestures it has to tell apart: a deliberate slow drag runs
41
+ * at 100–300 px/s (a thumb crossing a 350px card in one to three seconds),
42
+ * and a flick people expect to throw the strip runs at 800–2000 px/s. Nothing
43
+ * a person means as a careful drag arrives here, and nothing they mean as a
44
+ * flick falls under it.
45
+ */
46
+ export declare const SWIPE_FLICK_VELOCITY = 0.5;
47
+ /**
48
+ * The window the speed is measured over, in milliseconds.
49
+ *
50
+ * A flick is what the finger was doing AS IT LEFT, not the average of the
51
+ * whole gesture: a drag that crawls for a second and is then thrown would
52
+ * average out to a crawl, and the throw is the part the person meant. One
53
+ * moving window of roughly six frames is long enough to survive a single
54
+ * jittery sample and short enough to still be about the end of the gesture.
55
+ */
56
+ export declare const SWIPE_VELOCITY_WINDOW_MS = 100;
18
57
  /**
19
58
  * How much more horizontal than vertical a drag must be to count.
20
59
  *
@@ -32,12 +71,36 @@ export declare const SWIPE_AXIS_RATIO = 1.2;
32
71
  export declare function segmentIndex(offsetX: number, width: number, count: number): number;
33
72
  /**
34
73
  * A drag → the number of photographs it asks for: `1` forward, `-1` back, `0`
35
- * for a drag that has not declared horizontal intent.
74
+ * for a drag that has not earned one.
36
75
  *
37
76
  * Dragging LEFT advances, the direction the content moves under the finger —
38
- * the same mapping the native scroller has.
77
+ * the same mapping the native scroller has. The answer is never outside
78
+ * `-1…1`: a gesture is worth one photograph however far it travelled, which
79
+ * is what stops a fling crossing the whole strip.
80
+ *
81
+ * @param dx Horizontal travel from the press, signed, in CSS pixels.
82
+ * @param dy Vertical travel from the press, signed.
83
+ * @param slideWidth The measured width of ONE slide. `0` means it could not
84
+ * be measured (an unlaid-out strip, a server render) — and an unknown width
85
+ * has no fraction, so the decision falls back to {@link SWIPE_MIN_PX}
86
+ * alone rather than to an invented number.
87
+ * @param velocity The finger's recent speed in CSS pixels per millisecond.
88
+ */
89
+ export declare function swipeStep(dx: number, dy: number, slideWidth?: number, velocity?: number): -1 | 0 | 1;
90
+ /**
91
+ * The width of ONE slide inside this gallery's strip, in CSS pixels.
92
+ *
93
+ * Read off the SLIDE, which is the house rule (§83: geometry from the
94
+ * element's width, never the viewport's) and here also the only correct
95
+ * answer: a slide is the well less the carousel's peek, so the well's width
96
+ * is 8% too generous and a viewport-derived number is not about this card at
97
+ * all — the same card is full-bleed on a phone and a quarter of a row on a
98
+ * desktop grid.
99
+ *
100
+ * `0` when nothing can be measured. That is a refusal to guess, not a
101
+ * measurement: {@link swipeStep} falls back to the pixel floor for it.
39
102
  */
40
- export declare function swipeStep(dx: number, dy: number): -1 | 0 | 1;
103
+ export declare function measureSlideWidth(box: HTMLElement): number;
41
104
  /** Does this environment have a real pointer? `false` where there is no
42
105
  * `matchMedia` to ask (a server render, an old jsdom), which is the safe
43
106
  * side: a scrub that does not happen costs a hover, a scrub on a phone is a
@@ -1 +1 @@
1
- {"version":3,"file":"cardGallery.d.ts","sourceRoot":"","sources":["../../src/default/cardGallery.ts"],"names":[],"mappings":"AA+CA,OAAO,KAAK,EAAE,YAAY,IAAI,iBAAiB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG1E,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,2BAA2B,CAAC;AAC3D,yEAAyE;AACzE,eAAO,MAAM,0BAA0B,iCAAiC,CAAC;AACzE,oEAAoE;AACpE,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AAEtE,qEAAqE;AACrE,eAAO,MAAM,WAAW,uCAAuC,CAAC;AAEhE;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,KAAK,CAAC;AAE/B;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIlF;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAK5D;AAED;;;qDAGqD;AACrD,wBAAgB,cAAc,IAAI,OAAO,CAOxC;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,IAAI,OAAO,CA0BxC;AAED,yEAAyE;AACzE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC/C,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD;6DACyD;IACzD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IAC3E,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IAC3E,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IACzE,QAAQ,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IAC7E,QAAQ,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;CAC7E;AAoBD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAgIzD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CA2CvC"}
1
+ {"version":3,"file":"cardGallery.d.ts","sourceRoot":"","sources":["../../src/default/cardGallery.ts"],"names":[],"mappings":"AAwEA,OAAO,KAAK,EAAE,YAAY,IAAI,iBAAiB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG1E,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,2BAA2B,CAAC;AAC3D,yEAAyE;AACzE,eAAO,MAAM,0BAA0B,iCAAiC,CAAC;AACzE,oEAAoE;AACpE,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AAEtE,qEAAqE;AACrE,eAAO,MAAM,WAAW,uCAAuC,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,KAAK,CAAC;AAE/B;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIlF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,UAAU,SAAI,EACd,QAAQ,SAAI,GACX,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAWZ;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAM1D;AAED;;;qDAGqD;AACrD,wBAAgB,cAAc,IAAI,OAAO,CAOxC;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,IAAI,OAAO,CA0BxC;AAED,yEAAyE;AACzE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC/C,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD;6DACyD;IACzD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IAC3E,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IAC3E,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IACzE,QAAQ,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IAC7E,QAAQ,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;CAC7E;AA6ED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAsKzD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CA2CvC"}
@@ -34,6 +34,31 @@
34
34
  * {@link SWIPE_AXIS_RATIO}. A diagonal thumb scrolling the feed changes no
35
35
  * photograph.
36
36
  *
37
+ * ── HOW FAR IS FAR ENOUGH, and how many photographs that buys ────────────
38
+ *
39
+ * Intent is not a commit. A drag that has declared itself horizontal still
40
+ * has to EARN the photograph, and the price is a fraction of the photograph
41
+ * itself — {@link SWIPE_COMMIT_FRACTION} of the SLIDE's own measured width,
42
+ * never a pixel constant. The constant was the defect, and measurably so: a
43
+ * one-column search card on a 390px phone is a ~351px slide (the well less
44
+ * the carousel's 8% peek), so a fixed 32px priced a photograph at 9% of
45
+ * itself; the same 32px on the two-column home feed is 19% of a ~170px slide.
46
+ * One number, two different gestures, and the cheap one is the one the owner
47
+ * met — "it feels like 10%", and the middle photograph flying past.
48
+ *
49
+ * Two further rules, and both are about a gesture being ONE decision:
50
+ *
51
+ * - A flick is a choice too. Under the distance, a drag thrown faster than
52
+ * {@link SWIPE_FLICK_VELOCITY} still advances — the speed says the intent
53
+ * the distance did not.
54
+ * - ONE photograph per gesture, and one only. The old handler moved its own
55
+ * origin on each commit, so a drag across three slide widths advanced
56
+ * three photographs (and a fling across the card advanced ten). A gesture
57
+ * now commits at most once, and a second photograph costs a second press.
58
+ *
59
+ * Below the threshold the strip goes back to the picture it was showing —
60
+ * a refused gesture must leave the strip where it found it, not halfway.
61
+ *
37
62
  * ── What neither gesture touches ─────────────────────────────────────────
38
63
  *
39
64
  * The keyboard, and the card's single link target. The strip underneath is
@@ -55,13 +80,52 @@ export const CARD_GALLERY_STYLE_HREF = "stapel-listings-card-gallery";
55
80
  /** The environment a hover scrub is allowed in, and the only one. */
56
81
  export const SCRUB_MEDIA = "(hover: hover) and (pointer: fine)";
57
82
  /**
58
- * How far a finger travels before it has said "photo", in CSS pixels.
83
+ * How far a finger travels before it is a GESTURE at all, in CSS pixels.
59
84
  *
60
85
  * Under this, a drag is a tap that wobbled — and a tap on a card is a
61
86
  * navigation, so a low threshold does not change a photograph, it changes one
62
87
  * and then leaves the listing.
88
+ *
89
+ * This is the floor, not the price: what actually buys a photograph is
90
+ * {@link SWIPE_COMMIT_FRACTION} of the slide, or a flick above
91
+ * {@link SWIPE_FLICK_VELOCITY}. A pixel count cannot be the price, because
92
+ * the same 32px is a third of a card in a four-column desktop grid and a
93
+ * twelfth of one on a phone.
63
94
  */
64
95
  export const SWIPE_MIN_PX = 32;
96
+ /**
97
+ * How much of ONE PHOTOGRAPH a slow drag must cover to turn it, as a fraction
98
+ * of that photograph's own measured width.
99
+ *
100
+ * The owner's ruling, third pass: "maybe not 75, maybe 30 — right now it
101
+ * feels like 10%". 10% is what the old fixed 32px came to on a phone slide of
102
+ * ~350px, and it is why a middle photograph flew past on a gesture aimed at
103
+ * the feed. 0.3 is far enough that the drag is unmistakably a drag and short
104
+ * enough that a thumb can make it without crossing the whole card.
105
+ */
106
+ export const SWIPE_COMMIT_FRACTION = 0.3;
107
+ /**
108
+ * The speed, in CSS pixels per millisecond, at which a SHORT drag still turns
109
+ * the photograph.
110
+ *
111
+ * 0.5 px/ms — 500 px/s — is the owner's number and sits in the empty band
112
+ * between the two gestures it has to tell apart: a deliberate slow drag runs
113
+ * at 100–300 px/s (a thumb crossing a 350px card in one to three seconds),
114
+ * and a flick people expect to throw the strip runs at 800–2000 px/s. Nothing
115
+ * a person means as a careful drag arrives here, and nothing they mean as a
116
+ * flick falls under it.
117
+ */
118
+ export const SWIPE_FLICK_VELOCITY = 0.5;
119
+ /**
120
+ * The window the speed is measured over, in milliseconds.
121
+ *
122
+ * A flick is what the finger was doing AS IT LEFT, not the average of the
123
+ * whole gesture: a drag that crawls for a second and is then thrown would
124
+ * average out to a crawl, and the throw is the part the person meant. One
125
+ * moving window of roughly six frames is long enough to survive a single
126
+ * jittery sample and short enough to still be about the end of the gesture.
127
+ */
128
+ export const SWIPE_VELOCITY_WINDOW_MS = 100;
65
129
  /**
66
130
  * How much more horizontal than vertical a drag must be to count.
67
131
  *
@@ -84,19 +148,57 @@ export function segmentIndex(offsetX, width, count) {
84
148
  }
85
149
  /**
86
150
  * A drag → the number of photographs it asks for: `1` forward, `-1` back, `0`
87
- * for a drag that has not declared horizontal intent.
151
+ * for a drag that has not earned one.
88
152
  *
89
153
  * Dragging LEFT advances, the direction the content moves under the finger —
90
- * the same mapping the native scroller has.
154
+ * the same mapping the native scroller has. The answer is never outside
155
+ * `-1…1`: a gesture is worth one photograph however far it travelled, which
156
+ * is what stops a fling crossing the whole strip.
157
+ *
158
+ * @param dx Horizontal travel from the press, signed, in CSS pixels.
159
+ * @param dy Vertical travel from the press, signed.
160
+ * @param slideWidth The measured width of ONE slide. `0` means it could not
161
+ * be measured (an unlaid-out strip, a server render) — and an unknown width
162
+ * has no fraction, so the decision falls back to {@link SWIPE_MIN_PX}
163
+ * alone rather than to an invented number.
164
+ * @param velocity The finger's recent speed in CSS pixels per millisecond.
91
165
  */
92
- export function swipeStep(dx, dy) {
166
+ export function swipeStep(dx, dy, slideWidth = 0, velocity = 0) {
93
167
  const across = Math.abs(dx);
168
+ // Is this a gesture at all — past the tap wobble, and across rather than
169
+ // down the page.
94
170
  if (across < SWIPE_MIN_PX)
95
171
  return 0;
96
172
  if (across <= Math.abs(dy) * SWIPE_AXIS_RATIO)
97
173
  return 0;
174
+ // Has it earned a photograph: the distance rule, measured against THIS
175
+ // strip's slide, or the speed rule when the distance is short.
176
+ const far = slideWidth > 0 ? across >= slideWidth * SWIPE_COMMIT_FRACTION : true;
177
+ if (!far && velocity < SWIPE_FLICK_VELOCITY)
178
+ return 0;
98
179
  return dx < 0 ? 1 : -1;
99
180
  }
181
+ /**
182
+ * The width of ONE slide inside this gallery's strip, in CSS pixels.
183
+ *
184
+ * Read off the SLIDE, which is the house rule (§83: geometry from the
185
+ * element's width, never the viewport's) and here also the only correct
186
+ * answer: a slide is the well less the carousel's peek, so the well's width
187
+ * is 8% too generous and a viewport-derived number is not about this card at
188
+ * all — the same card is full-bleed on a phone and a quarter of a row on a
189
+ * desktop grid.
190
+ *
191
+ * `0` when nothing can be measured. That is a refusal to guess, not a
192
+ * measurement: {@link swipeStep} falls back to the pixel floor for it.
193
+ */
194
+ export function measureSlideWidth(box) {
195
+ const strip = box.querySelector("[data-stapel-carousel-strip]");
196
+ if (strip === null)
197
+ return 0;
198
+ const slide = strip.children.item(0);
199
+ const width = slide === null ? 0 : slide.getBoundingClientRect().width;
200
+ return width > 0 ? width : 0;
201
+ }
100
202
  /** Does this environment have a real pointer? `false` where there is no
101
203
  * `matchMedia` to ask (a server render, an old jsdom), which is the safe
102
204
  * side: a scrub that does not happen costs a hover, a scrub on a phone is a
@@ -168,6 +270,41 @@ function showSlide(box, index, instant) {
168
270
  strip.scrollLeft = left;
169
271
  }
170
272
  }
273
+ /** When this event happened, on whatever clock the environment has. A UA
274
+ * stamps every input event; the fallback is for a synthesised one. */
275
+ function stampOf(event) {
276
+ const stamp = event.timeStamp;
277
+ if (Number.isFinite(stamp) && stamp > 0)
278
+ return stamp;
279
+ return typeof performance === "object" && typeof performance.now === "function"
280
+ ? performance.now()
281
+ : Date.now();
282
+ }
283
+ /** Record a position, and forget the ones the speed window has passed. */
284
+ function sample(drag, x, t) {
285
+ drag.samples.push({ x, t });
286
+ // Drop the oldest only while the NEXT one is still inside the window, so
287
+ // the trail always spans at least one interval to divide by.
288
+ while (drag.samples.length > 2) {
289
+ const second = drag.samples[1];
290
+ if (second === undefined || t - second.t <= SWIPE_VELOCITY_WINDOW_MS)
291
+ break;
292
+ drag.samples.shift();
293
+ }
294
+ }
295
+ /** The finger's speed over the trail, in CSS pixels per millisecond. `0`
296
+ * where the environment gave no usable clock — an unknown speed is not a
297
+ * flick. */
298
+ function velocityOf(drag) {
299
+ const first = drag.samples[0];
300
+ const last = drag.samples[drag.samples.length - 1];
301
+ if (first === undefined || last === undefined)
302
+ return 0;
303
+ const elapsed = last.t - first.t;
304
+ if (elapsed <= 0)
305
+ return 0;
306
+ return Math.abs(last.x - first.x) / elapsed;
307
+ }
171
308
  /**
172
309
  * The gallery gestures for a media well holding `count` photographs.
173
310
  *
@@ -178,9 +315,9 @@ export function useCardGallery(count) {
178
315
  const ref = useRef(null);
179
316
  const [active, setActive] = useState(0);
180
317
  const [scrubbing, setScrubbing] = useState(false);
181
- // The origin of the drag in progress, or `null`. A ref rather than state:
182
- // it changes on every move and no render depends on it.
183
- const origin = useRef(null);
318
+ // The drag in progress, or `null`. A ref rather than state: it changes on
319
+ // every move and no render depends on it.
320
+ const drag = useRef(null);
184
321
  /**
185
322
  * THE INDEX THIS HOOK ASKED FOR, and the whole of the fix.
186
323
  *
@@ -243,28 +380,70 @@ export function useCardGallery(count) {
243
380
  request(segmentIndex(event.clientX - rect.left, rect.width, count));
244
381
  return;
245
382
  }
246
- const from = origin.current;
247
- if (from === null)
383
+ const current = drag.current;
384
+ if (current === null)
248
385
  return;
249
- const step = swipeStep(event.clientX - from.x, event.clientY - from.y);
386
+ sample(current, event.clientX, stampOf(event));
387
+ // ONE PHOTOGRAPH PER GESTURE. The trail keeps being recorded — a
388
+ // release still wants to know how the finger was moving — but the
389
+ // decision below is made once and the rest of the drag is scenery.
390
+ if (current.committed)
391
+ return;
392
+ const dx = event.clientX - current.x;
393
+ const dy = event.clientY - current.y;
394
+ if (Math.abs(dx) >= SWIPE_MIN_PX && Math.abs(dx) > Math.abs(dy) * SWIPE_AXIS_RATIO) {
395
+ current.crossed = true;
396
+ }
397
+ const step = swipeStep(dx, dy, current.width, velocityOf(current));
250
398
  if (step === 0)
251
399
  return;
252
- // The origin moves with the commit, so a long drag walks the strip one
253
- // photograph per threshold rather than one per gesture.
254
- origin.current = { x: event.clientX, y: event.clientY };
400
+ current.committed = true;
255
401
  setScrubbing(false);
256
- request((current) => Math.min(count - 1, Math.max(0, current + step)));
402
+ request((at) => Math.min(count - 1, Math.max(0, at + step)));
257
403
  }, [count, fine, many, request]);
258
404
  const onPointerDown = useCallback((event) => {
259
405
  if (!many || event.pointerType === "mouse")
260
406
  return;
261
- origin.current = { x: event.clientX, y: event.clientY };
407
+ const box = ref.current;
408
+ drag.current = {
409
+ x: event.clientX,
410
+ y: event.clientY,
411
+ // Measured here, from the slide itself, and held for the gesture.
412
+ width: box === null ? 0 : measureSlideWidth(box),
413
+ samples: [{ x: event.clientX, t: stampOf(event) }],
414
+ committed: false,
415
+ crossed: false,
416
+ };
262
417
  }, [many]);
418
+ /**
419
+ * The finger leaves.
420
+ *
421
+ * A gesture that earned its photograph already took it, mid-drag, the
422
+ * moment it crossed the threshold. What is left here is the REFUSED one: a
423
+ * drag that went sideways far enough to be read as a swipe and then stopped
424
+ * short. The strip goes back to the photograph it was showing, because a
425
+ * refused gesture that leaves the strip halfway is the defect wearing the
426
+ * other face.
427
+ *
428
+ * A release with no drag behind it touches nothing at all — that is the
429
+ * guard probe p23 bought: `pointerup` also arrives after a NATIVE scroll
430
+ * this hook never started, and scrolling "back" there means undoing the
431
+ * person's own swipe.
432
+ */
263
433
  const endDrag = useCallback(() => {
264
- origin.current = null;
265
- }, []);
434
+ const current = drag.current;
435
+ drag.current = null;
436
+ if (current === null || !many)
437
+ return;
438
+ if (current.committed || !current.crossed)
439
+ return;
440
+ const box = ref.current;
441
+ if (box === null)
442
+ return;
443
+ showSlide(box, active, false);
444
+ }, [active, many]);
266
445
  const onPointerLeave = useCallback((event) => {
267
- origin.current = null;
446
+ drag.current = null;
268
447
  if (!many)
269
448
  return;
270
449
  // THE REWIND IS A HOVER RULE, AND ONLY A HOVER RULE.
@@ -1 +1 @@
1
- {"version":3,"file":"cardGallery.js","sourceRoot":"","sources":["../../src/default/cardGallery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cardGallery.js","sourceRoot":"","sources":["../../src/default/cardGallery.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"detailGallery.d.ts","sourceRoot":"","sources":["../../src/default/detailGallery.ts"],"names":[],"mappings":"AA+DA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC,6DAA6D;AAC7D,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpD,yCAAyC;AACzC,eAAO,MAAM,sBAAsB,mCAAmC,CAAC;AAEvE,oEAAoE;AACpE,eAAO,MAAM,2BAA2B,mCAAmC,CAAC;AAE5E,oDAAoD;AACpD,eAAO,MAAM,8BAA8B,iCAAiC,CAAC;AAE7E;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,yCAAyC,CAAC;AAEnF;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,QAAQ,CAAC;AAElD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAc1D;AAED,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CACtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,CAyCpE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAkCzC"}
1
+ {"version":3,"file":"detailGallery.d.ts","sourceRoot":"","sources":["../../src/default/detailGallery.ts"],"names":[],"mappings":"AA+DA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC,6DAA6D;AAC7D,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpD,yCAAyC;AACzC,eAAO,MAAM,sBAAsB,mCAAmC,CAAC;AAEvE,oEAAoE;AACpE,eAAO,MAAM,2BAA2B,mCAAmC,CAAC;AAE5E,oDAAoD;AACpD,eAAO,MAAM,8BAA8B,iCAAiC,CAAC;AAE7E;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,yCAAyC,CAAC;AAEnF;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,QAAQ,CAAC;AAElD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAc1D;AAED,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CACtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,CAyCpE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CA2CzC"}
@@ -196,6 +196,15 @@ export function detailGalleryCss() {
196
196
  .${LISTINGS_GALLERY_CLASS}[data-gallery-layout="strip"] > * {
197
197
  flex: 0 0 ${LISTINGS_GALLERY_STRIP_BASIS};
198
198
  scroll-snap-align: start;
199
+ /* EVERY PHOTOGRAPH IS A DESTINATION, not a waypoint. A mandatory snap type
200
+ alone only promises the strip will COME TO REST on a snap point — a fling
201
+ with any momentum behind it still crosses two or three photographs on its
202
+ way there, which is the owner's "the middle photo flies past" in its
203
+ native form. "always" makes the scroller stop at the first snap point it
204
+ reaches, so one gesture is one photograph here for the same reason the
205
+ card's gesture layer clamps its own step to one. The same declaration
206
+ SkinCarousel already carries on its slides. */
207
+ scroll-snap-stop: always;
199
208
  }
200
209
  .${LISTINGS_GALLERY_FRAME_CLASS} {
201
210
  position: relative;
@@ -1 +1 @@
1
- {"version":3,"file":"detailGallery.js","sourceRoot":"","sources":["../../src/default/detailGallery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"detailGallery.js","sourceRoot":"","sources":["../../src/default/detailGallery.ts"],"names":[],"mappings":"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"}
@@ -63,7 +63,7 @@ export { ListingSpecColumns, ListingSpecList, SPEC_FOLD_MIN_HIDDEN, specListCss,
63
63
  export type { ListingSpecListProps } from "./ListingSpecList.js";
64
64
  export { CardBadges, CardSpecLine, CARD_SPEC_LINE_CLASS, CARD_SPEC_STYLE_HREF, CARD_SPEC_TEXT_CLASS, cardSpecLineCss, } from "./CardBadges.js";
65
65
  export type { CardBadgesProps } from "./CardBadges.js";
66
- export { SWIPE_AXIS_RATIO, SWIPE_MIN_PX, cardGalleryCss, hasFinePointer, segmentIndex, swipeStep, useCardGallery, } from "./cardGallery.js";
66
+ export { SWIPE_AXIS_RATIO, SWIPE_COMMIT_FRACTION, SWIPE_FLICK_VELOCITY, SWIPE_MIN_PX, SWIPE_VELOCITY_WINDOW_MS, cardGalleryCss, hasFinePointer, measureSlideWidth, segmentIndex, swipeStep, useCardGallery, } from "./cardGallery.js";
67
67
  export type { CardGallery } from "./cardGallery.js";
68
68
  export { ListingActions } from "./ListingActions.js";
69
69
  export type { ListingActionsConfig, ListingActionsProps, } from "./ListingActions.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"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"}
@@ -69,7 +69,7 @@ export { ListingPhoto, ListingPhotoStrip, LISTING_PHOTO_ASPECT, } from "./Listin
69
69
  export { ListingSpecColumns, ListingSpecList, SPEC_FOLD_MIN_HIDDEN, specListCss, } from "./ListingSpecList.js";
70
70
  export { CardBadges, CardSpecLine, CARD_SPEC_LINE_CLASS, CARD_SPEC_STYLE_HREF, CARD_SPEC_TEXT_CLASS, cardSpecLineCss, } from "./CardBadges.js";
71
71
  // ── the card gallery's two gestures ─────────────────────────────────────────
72
- export { SWIPE_AXIS_RATIO, SWIPE_MIN_PX, cardGalleryCss, hasFinePointer, segmentIndex, swipeStep, useCardGallery, } from "./cardGallery.js";
72
+ export { SWIPE_AXIS_RATIO, SWIPE_COMMIT_FRACTION, SWIPE_FLICK_VELOCITY, SWIPE_MIN_PX, SWIPE_VELOCITY_WINDOW_MS, cardGalleryCss, hasFinePointer, measureSlideWidth, segmentIndex, swipeStep, useCardGallery, } from "./cardGallery.js";
73
73
  // ── the reader's two actions: save it, or send it to somebody ───────────────
74
74
  export { ListingActions } from "./ListingActions.js";
75
75
  export { ShareAction } from "./ShareAction.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,EACL,WAAW;AACX,6EAA6E;AAC7E,6EAA6E;AAC7E,oBAAoB,EACpB,sBAAsB;AACtB,0EAA0E;AAC1E,4EAA4E;AAC5E,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAO1B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAMvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAKvD,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE5D,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,mBAAmB;AACnB,wEAAwE;AACxE,+DAA+D;AAC/D,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAKhC,8EAA8E;AAC9E,+EAA+E;AAC/E,oBAAoB;AACpB,OAAO,EACL,sBAAsB,EACtB,8BAA8B,EAC9B,4BAA4B,EAC5B,2BAA2B,EAC3B,4BAA4B,EAC5B,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAE5B,6EAA6E;AAC7E,qEAAqE;AACrE,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,8EAA8E;AAC9E,+EAA+E;AAC/E,8CAA8C;AAC9C,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,gEAAgE;AAChE,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAK7B,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,gBAAgB,EAChB,eAAe,GAChB,MAAM,0BAA0B,CAAC;AASlC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAOvE,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAG3B,gFAAgF;AAChF,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,UAAU,EACV,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAGzB,+EAA+E;AAC/E,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,cAAc,EACd,YAAY,EACZ,SAAS,EACT,cAAc,GACf,MAAM,kBAAkB,CAAC;AAE1B,+EAA+E;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAKrD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EACL,qBAAqB,EACrB,6BAA6B,EAC7B,0BAA0B,EAC1B,oBAAoB,EACpB,kBAAkB,EAClB,0BAA0B,EAC1B,0BAA0B,EAC1B,yBAAyB,EACzB,uBAAuB,EACvB,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"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"}
package/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # @stapel/listings-react 0.30.2
1
+ # @stapel/listings-react 0.30.3
2
2
 
3
3
  Headless React flow pair for stapel-listings (contract >=0.22 <0.23) — business + state, zero visual opinion.
4
4
  Built on @stapel/core: typed client + StapelApiError envelope, auth token refresh,
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$generated": "by scripts/gen-manifest.mjs — do not edit; drift-gated (pnpm gen:manifest:check)",
3
3
  "package": "@stapel/listings-react",
4
- "version": "0.30.2",
4
+ "version": "0.30.3",
5
5
  "backend": {
6
6
  "module": "stapel-listings",
7
7
  "contract": ">=0.22 <0.23"
package/nav-manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "@stapel/listings-react",
3
- "version": "0.30.2",
3
+ "version": "0.30.3",
4
4
  "entries": [
5
5
  {
6
6
  "id": "listings.detail",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stapel/listings-react",
3
- "version": "0.30.2",
3
+ "version": "0.30.3",
4
4
  "description": "Headless React pair for stapel-listings: a typed client over the draft twin, the composer that turns a category schema into a submittable listing, and the owner's dashboard. Two independent axes are rendered as two — lifecycle `status` decides visibility and `moderation_status` decides nothing about it, so an edit to a live listing stays live and says 'under review' instead of vanishing. Feature values are drawn and mirrored by @stapel/attributes-react; photos arrive as an injected upload bag whose `refs` ARE `images_draft` and whose `settled` gates the submit; a publish refusal is routed onto the control that caused it by slug. Zero visual opinion in the main entry; an opt-in /default subpath ships the antd skin.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -103,12 +103,12 @@
103
103
  "typescript": "^5.8.3",
104
104
  "vitest": "^3.2.4",
105
105
  "@stapel/attributes-react": "^0.17.0",
106
+ "@stapel/core": "^0.26.1",
106
107
  "@stapel/currencies-react": "^0.4.0",
107
108
  "@stapel/image": "^0.4.2",
108
109
  "@stapel/showcase": "^0.3.0",
109
110
  "@stapel/tokens": "^0.8.0",
110
- "@stapel/tokens-antd": "^0.18.0",
111
- "@stapel/core": "^0.26.1"
111
+ "@stapel/tokens-antd": "^0.18.1"
112
112
  },
113
113
  "engines": {
114
114
  "node": ">=22"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$generated": "by scripts/gen-events.mjs — do not edit; drift-gated (pnpm gen:events:check)",
3
3
  "package": "@stapel/listings-react",
4
- "version": "0.30.2",
4
+ "version": "0.30.3",
5
5
  "defined": [],
6
6
  "flows": []
7
7
  }
@@ -34,6 +34,31 @@
34
34
  * {@link SWIPE_AXIS_RATIO}. A diagonal thumb scrolling the feed changes no
35
35
  * photograph.
36
36
  *
37
+ * ── HOW FAR IS FAR ENOUGH, and how many photographs that buys ────────────
38
+ *
39
+ * Intent is not a commit. A drag that has declared itself horizontal still
40
+ * has to EARN the photograph, and the price is a fraction of the photograph
41
+ * itself — {@link SWIPE_COMMIT_FRACTION} of the SLIDE's own measured width,
42
+ * never a pixel constant. The constant was the defect, and measurably so: a
43
+ * one-column search card on a 390px phone is a ~351px slide (the well less
44
+ * the carousel's 8% peek), so a fixed 32px priced a photograph at 9% of
45
+ * itself; the same 32px on the two-column home feed is 19% of a ~170px slide.
46
+ * One number, two different gestures, and the cheap one is the one the owner
47
+ * met — "it feels like 10%", and the middle photograph flying past.
48
+ *
49
+ * Two further rules, and both are about a gesture being ONE decision:
50
+ *
51
+ * - A flick is a choice too. Under the distance, a drag thrown faster than
52
+ * {@link SWIPE_FLICK_VELOCITY} still advances — the speed says the intent
53
+ * the distance did not.
54
+ * - ONE photograph per gesture, and one only. The old handler moved its own
55
+ * origin on each commit, so a drag across three slide widths advanced
56
+ * three photographs (and a fling across the card advanced ten). A gesture
57
+ * now commits at most once, and a second photograph costs a second press.
58
+ *
59
+ * Below the threshold the strip goes back to the picture it was showing —
60
+ * a refused gesture must leave the strip where it found it, not halfway.
61
+ *
37
62
  * ── What neither gesture touches ─────────────────────────────────────────
38
63
  *
39
64
  * The keyboard, and the card's single link target. The strip underneath is
@@ -59,14 +84,56 @@ export const CARD_GALLERY_STYLE_HREF = "stapel-listings-card-gallery";
59
84
  export const SCRUB_MEDIA = "(hover: hover) and (pointer: fine)";
60
85
 
61
86
  /**
62
- * How far a finger travels before it has said "photo", in CSS pixels.
87
+ * How far a finger travels before it is a GESTURE at all, in CSS pixels.
63
88
  *
64
89
  * Under this, a drag is a tap that wobbled — and a tap on a card is a
65
90
  * navigation, so a low threshold does not change a photograph, it changes one
66
91
  * and then leaves the listing.
92
+ *
93
+ * This is the floor, not the price: what actually buys a photograph is
94
+ * {@link SWIPE_COMMIT_FRACTION} of the slide, or a flick above
95
+ * {@link SWIPE_FLICK_VELOCITY}. A pixel count cannot be the price, because
96
+ * the same 32px is a third of a card in a four-column desktop grid and a
97
+ * twelfth of one on a phone.
67
98
  */
68
99
  export const SWIPE_MIN_PX = 32;
69
100
 
101
+ /**
102
+ * How much of ONE PHOTOGRAPH a slow drag must cover to turn it, as a fraction
103
+ * of that photograph's own measured width.
104
+ *
105
+ * The owner's ruling, third pass: "maybe not 75, maybe 30 — right now it
106
+ * feels like 10%". 10% is what the old fixed 32px came to on a phone slide of
107
+ * ~350px, and it is why a middle photograph flew past on a gesture aimed at
108
+ * the feed. 0.3 is far enough that the drag is unmistakably a drag and short
109
+ * enough that a thumb can make it without crossing the whole card.
110
+ */
111
+ export const SWIPE_COMMIT_FRACTION = 0.3;
112
+
113
+ /**
114
+ * The speed, in CSS pixels per millisecond, at which a SHORT drag still turns
115
+ * the photograph.
116
+ *
117
+ * 0.5 px/ms — 500 px/s — is the owner's number and sits in the empty band
118
+ * between the two gestures it has to tell apart: a deliberate slow drag runs
119
+ * at 100–300 px/s (a thumb crossing a 350px card in one to three seconds),
120
+ * and a flick people expect to throw the strip runs at 800–2000 px/s. Nothing
121
+ * a person means as a careful drag arrives here, and nothing they mean as a
122
+ * flick falls under it.
123
+ */
124
+ export const SWIPE_FLICK_VELOCITY = 0.5;
125
+
126
+ /**
127
+ * The window the speed is measured over, in milliseconds.
128
+ *
129
+ * A flick is what the finger was doing AS IT LEFT, not the average of the
130
+ * whole gesture: a drag that crawls for a second and is then thrown would
131
+ * average out to a crawl, and the throw is the part the person meant. One
132
+ * moving window of roughly six frames is long enough to survive a single
133
+ * jittery sample and short enough to still be about the end of the gesture.
134
+ */
135
+ export const SWIPE_VELOCITY_WINDOW_MS = 100;
136
+
70
137
  /**
71
138
  * How much more horizontal than vertical a drag must be to count.
72
139
  *
@@ -90,18 +157,60 @@ export function segmentIndex(offsetX: number, width: number, count: number): num
90
157
 
91
158
  /**
92
159
  * A drag → the number of photographs it asks for: `1` forward, `-1` back, `0`
93
- * for a drag that has not declared horizontal intent.
160
+ * for a drag that has not earned one.
94
161
  *
95
162
  * Dragging LEFT advances, the direction the content moves under the finger —
96
- * the same mapping the native scroller has.
163
+ * the same mapping the native scroller has. The answer is never outside
164
+ * `-1…1`: a gesture is worth one photograph however far it travelled, which
165
+ * is what stops a fling crossing the whole strip.
166
+ *
167
+ * @param dx Horizontal travel from the press, signed, in CSS pixels.
168
+ * @param dy Vertical travel from the press, signed.
169
+ * @param slideWidth The measured width of ONE slide. `0` means it could not
170
+ * be measured (an unlaid-out strip, a server render) — and an unknown width
171
+ * has no fraction, so the decision falls back to {@link SWIPE_MIN_PX}
172
+ * alone rather than to an invented number.
173
+ * @param velocity The finger's recent speed in CSS pixels per millisecond.
97
174
  */
98
- export function swipeStep(dx: number, dy: number): -1 | 0 | 1 {
175
+ export function swipeStep(
176
+ dx: number,
177
+ dy: number,
178
+ slideWidth = 0,
179
+ velocity = 0
180
+ ): -1 | 0 | 1 {
99
181
  const across = Math.abs(dx);
182
+ // Is this a gesture at all — past the tap wobble, and across rather than
183
+ // down the page.
100
184
  if (across < SWIPE_MIN_PX) return 0;
101
185
  if (across <= Math.abs(dy) * SWIPE_AXIS_RATIO) return 0;
186
+ // Has it earned a photograph: the distance rule, measured against THIS
187
+ // strip's slide, or the speed rule when the distance is short.
188
+ const far = slideWidth > 0 ? across >= slideWidth * SWIPE_COMMIT_FRACTION : true;
189
+ if (!far && velocity < SWIPE_FLICK_VELOCITY) return 0;
102
190
  return dx < 0 ? 1 : -1;
103
191
  }
104
192
 
193
+ /**
194
+ * The width of ONE slide inside this gallery's strip, in CSS pixels.
195
+ *
196
+ * Read off the SLIDE, which is the house rule (§83: geometry from the
197
+ * element's width, never the viewport's) and here also the only correct
198
+ * answer: a slide is the well less the carousel's peek, so the well's width
199
+ * is 8% too generous and a viewport-derived number is not about this card at
200
+ * all — the same card is full-bleed on a phone and a quarter of a row on a
201
+ * desktop grid.
202
+ *
203
+ * `0` when nothing can be measured. That is a refusal to guess, not a
204
+ * measurement: {@link swipeStep} falls back to the pixel floor for it.
205
+ */
206
+ export function measureSlideWidth(box: HTMLElement): number {
207
+ const strip = box.querySelector<HTMLElement>("[data-stapel-carousel-strip]");
208
+ if (strip === null) return 0;
209
+ const slide = strip.children.item(0);
210
+ const width = slide === null ? 0 : slide.getBoundingClientRect().width;
211
+ return width > 0 ? width : 0;
212
+ }
213
+
105
214
  /** Does this environment have a real pointer? `false` where there is no
106
215
  * `matchMedia` to ask (a server render, an old jsdom), which is the safe
107
216
  * side: a scrub that does not happen costs a hover, a scrub on a phone is a
@@ -198,6 +307,63 @@ function showSlide(box: HTMLElement, index: number, instant: boolean): void {
198
307
  }
199
308
  }
200
309
 
310
+ /** One position of the finger, in time — the raw material of a flick. */
311
+ interface Sample {
312
+ readonly x: number;
313
+ readonly t: number;
314
+ }
315
+
316
+ /** The drag in progress. Everything a release has to decide on. */
317
+ interface Drag {
318
+ /** Where the finger went down. */
319
+ readonly x: number;
320
+ readonly y: number;
321
+ /** One slide's width, measured ONCE at the press: a strip whose geometry
322
+ * changed mid-gesture would move the goalposts under the finger. */
323
+ readonly width: number;
324
+ /** The recent trail, newest last — see {@link SWIPE_VELOCITY_WINDOW_MS}. */
325
+ samples: Sample[];
326
+ /** Has this gesture already spent its one photograph. */
327
+ committed: boolean;
328
+ /** Has it declared horizontal intent — the only kind of refused gesture
329
+ * that is worth snapping back from. */
330
+ crossed: boolean;
331
+ }
332
+
333
+ /** When this event happened, on whatever clock the environment has. A UA
334
+ * stamps every input event; the fallback is for a synthesised one. */
335
+ function stampOf(event: { timeStamp: number }): number {
336
+ const stamp = event.timeStamp;
337
+ if (Number.isFinite(stamp) && stamp > 0) return stamp;
338
+ return typeof performance === "object" && typeof performance.now === "function"
339
+ ? performance.now()
340
+ : Date.now();
341
+ }
342
+
343
+ /** Record a position, and forget the ones the speed window has passed. */
344
+ function sample(drag: Drag, x: number, t: number): void {
345
+ drag.samples.push({ x, t });
346
+ // Drop the oldest only while the NEXT one is still inside the window, so
347
+ // the trail always spans at least one interval to divide by.
348
+ while (drag.samples.length > 2) {
349
+ const second = drag.samples[1];
350
+ if (second === undefined || t - second.t <= SWIPE_VELOCITY_WINDOW_MS) break;
351
+ drag.samples.shift();
352
+ }
353
+ }
354
+
355
+ /** The finger's speed over the trail, in CSS pixels per millisecond. `0`
356
+ * where the environment gave no usable clock — an unknown speed is not a
357
+ * flick. */
358
+ function velocityOf(drag: Drag): number {
359
+ const first = drag.samples[0];
360
+ const last = drag.samples[drag.samples.length - 1];
361
+ if (first === undefined || last === undefined) return 0;
362
+ const elapsed = last.t - first.t;
363
+ if (elapsed <= 0) return 0;
364
+ return Math.abs(last.x - first.x) / elapsed;
365
+ }
366
+
201
367
  /**
202
368
  * The gallery gestures for a media well holding `count` photographs.
203
369
  *
@@ -208,9 +374,9 @@ export function useCardGallery(count: number): CardGallery {
208
374
  const ref = useRef<HTMLDivElement | null>(null);
209
375
  const [active, setActive] = useState(0);
210
376
  const [scrubbing, setScrubbing] = useState(false);
211
- // The origin of the drag in progress, or `null`. A ref rather than state:
212
- // it changes on every move and no render depends on it.
213
- const origin = useRef<{ x: number; y: number } | null>(null);
377
+ // The drag in progress, or `null`. A ref rather than state: it changes on
378
+ // every move and no render depends on it.
379
+ const drag = useRef<Drag | null>(null);
214
380
  /**
215
381
  * THE INDEX THIS HOOK ASKED FOR, and the whole of the fix.
216
382
  *
@@ -276,15 +442,23 @@ export function useCardGallery(count: number): CardGallery {
276
442
  request(segmentIndex(event.clientX - rect.left, rect.width, count));
277
443
  return;
278
444
  }
279
- const from = origin.current;
280
- if (from === null) return;
281
- const step = swipeStep(event.clientX - from.x, event.clientY - from.y);
445
+ const current = drag.current;
446
+ if (current === null) return;
447
+ sample(current, event.clientX, stampOf(event));
448
+ // ONE PHOTOGRAPH PER GESTURE. The trail keeps being recorded — a
449
+ // release still wants to know how the finger was moving — but the
450
+ // decision below is made once and the rest of the drag is scenery.
451
+ if (current.committed) return;
452
+ const dx = event.clientX - current.x;
453
+ const dy = event.clientY - current.y;
454
+ if (Math.abs(dx) >= SWIPE_MIN_PX && Math.abs(dx) > Math.abs(dy) * SWIPE_AXIS_RATIO) {
455
+ current.crossed = true;
456
+ }
457
+ const step = swipeStep(dx, dy, current.width, velocityOf(current));
282
458
  if (step === 0) return;
283
- // The origin moves with the commit, so a long drag walks the strip one
284
- // photograph per threshold rather than one per gesture.
285
- origin.current = { x: event.clientX, y: event.clientY };
459
+ current.committed = true;
286
460
  setScrubbing(false);
287
- request((current) => Math.min(count - 1, Math.max(0, current + step)));
461
+ request((at) => Math.min(count - 1, Math.max(0, at + step)));
288
462
  },
289
463
  [count, fine, many, request]
290
464
  );
@@ -292,18 +466,48 @@ export function useCardGallery(count: number): CardGallery {
292
466
  const onPointerDown = useCallback(
293
467
  (event: ReactPointerEvent<HTMLDivElement>): void => {
294
468
  if (!many || event.pointerType === "mouse") return;
295
- origin.current = { x: event.clientX, y: event.clientY };
469
+ const box = ref.current;
470
+ drag.current = {
471
+ x: event.clientX,
472
+ y: event.clientY,
473
+ // Measured here, from the slide itself, and held for the gesture.
474
+ width: box === null ? 0 : measureSlideWidth(box),
475
+ samples: [{ x: event.clientX, t: stampOf(event) }],
476
+ committed: false,
477
+ crossed: false,
478
+ };
296
479
  },
297
480
  [many]
298
481
  );
299
482
 
483
+ /**
484
+ * The finger leaves.
485
+ *
486
+ * A gesture that earned its photograph already took it, mid-drag, the
487
+ * moment it crossed the threshold. What is left here is the REFUSED one: a
488
+ * drag that went sideways far enough to be read as a swipe and then stopped
489
+ * short. The strip goes back to the photograph it was showing, because a
490
+ * refused gesture that leaves the strip halfway is the defect wearing the
491
+ * other face.
492
+ *
493
+ * A release with no drag behind it touches nothing at all — that is the
494
+ * guard probe p23 bought: `pointerup` also arrives after a NATIVE scroll
495
+ * this hook never started, and scrolling "back" there means undoing the
496
+ * person's own swipe.
497
+ */
300
498
  const endDrag = useCallback((): void => {
301
- origin.current = null;
302
- }, []);
499
+ const current = drag.current;
500
+ drag.current = null;
501
+ if (current === null || !many) return;
502
+ if (current.committed || !current.crossed) return;
503
+ const box = ref.current;
504
+ if (box === null) return;
505
+ showSlide(box, active, false);
506
+ }, [active, many]);
303
507
 
304
508
  const onPointerLeave = useCallback(
305
509
  (event: ReactPointerEvent<HTMLDivElement>): void => {
306
- origin.current = null;
510
+ drag.current = null;
307
511
  if (!many) return;
308
512
  // THE REWIND IS A HOVER RULE, AND ONLY A HOVER RULE.
309
513
  //
@@ -215,6 +215,15 @@ export function detailGalleryCss(): string {
215
215
  .${LISTINGS_GALLERY_CLASS}[data-gallery-layout="strip"] > * {
216
216
  flex: 0 0 ${LISTINGS_GALLERY_STRIP_BASIS};
217
217
  scroll-snap-align: start;
218
+ /* EVERY PHOTOGRAPH IS A DESTINATION, not a waypoint. A mandatory snap type
219
+ alone only promises the strip will COME TO REST on a snap point — a fling
220
+ with any momentum behind it still crosses two or three photographs on its
221
+ way there, which is the owner's "the middle photo flies past" in its
222
+ native form. "always" makes the scroller stop at the first snap point it
223
+ reaches, so one gesture is one photograph here for the same reason the
224
+ card's gesture layer clamps its own step to one. The same declaration
225
+ SkinCarousel already carries on its slides. */
226
+ scroll-snap-stop: always;
218
227
  }
219
228
  .${LISTINGS_GALLERY_FRAME_CLASS} {
220
229
  position: relative;
@@ -176,9 +176,13 @@ export type { CardBadgesProps } from "./CardBadges.js";
176
176
  // ── the card gallery's two gestures ─────────────────────────────────────────
177
177
  export {
178
178
  SWIPE_AXIS_RATIO,
179
+ SWIPE_COMMIT_FRACTION,
180
+ SWIPE_FLICK_VELOCITY,
179
181
  SWIPE_MIN_PX,
182
+ SWIPE_VELOCITY_WINDOW_MS,
180
183
  cardGalleryCss,
181
184
  hasFinePointer,
185
+ measureSlideWidth,
182
186
  segmentIndex,
183
187
  swipeStep,
184
188
  useCardGallery,