@present-day/reveal-row 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,9 +8,9 @@
8
8
  [![types](https://img.shields.io/npm/types/@present-day/reveal-row)](https://www.npmjs.com/package/@present-day/reveal-row)
9
9
  [![license](https://img.shields.io/npm/l/@present-day/reveal-row)](./LICENSE)
10
10
 
11
- The swipe-to-delete pattern everyone knows from iOS Mail — as a headless React component. Swipe (or drag, or scroll) a row horizontally to reveal action buttons on the **right**, the **left**, or **both** sides, with three crisp snap positions: left · center · right.
11
+ The swipe-to-reveal pattern every mobile inbox and to-do list has made second nature — as a headless React component. Swipe (or drag, or scroll) a row horizontally to reveal action buttons on the **right**, the **left**, or **both** sides, with three crisp snap positions: left · center · right.
12
12
 
13
- **[▶ Try the live playground](https://present-day.github.io/reveal-row/)**
13
+ **[▶ Try it in Storybook](https://present-day.github.io/reveal-row/)**
14
14
 
15
15
  <img width="295" height="640" alt="RevealRow demo — swiping a list row to reveal actions" src="https://github.com/user-attachments/assets/932021d4-5224-479f-9df9-c7045bf12afb" />
16
16
 
@@ -59,7 +59,7 @@ import { RevealRow } from '@present-day/reveal-row'
59
59
 
60
60
  ## Multiple actions per side
61
61
 
62
- A side slot is a single column that **auto-sizes to its content** (with an 88px floor) — to show several buttons (iOS Mail-style Delete + Pin), lay them out with flex and give each button its own width. No math required:
62
+ A side slot is a single column that **auto-sizes to its content** (with an 88px floor) — to show several buttons side by side (say, Delete + Pin), lay them out with flex and give each button its own width. No math required:
63
63
 
64
64
  ```tsx
65
65
  <RevealRow
@@ -76,7 +76,7 @@ A side slot is a single column that **auto-sizes to its content** (with an 88px
76
76
 
77
77
  Passing `actionWidthLeft`/`actionWidthRight` a number still gives you a fixed-width column, exactly as before.
78
78
 
79
- **[▶ See it live in the playground](https://present-day.github.io/reveal-row/)** under "Multiple actions".
79
+ **[▶ See it live in Storybook](https://present-day.github.io/reveal-row/?path=/story/revealrow--multiple-actions)** under "Multiple Actions".
80
80
 
81
81
  ## Accessibility
82
82
 
@@ -84,6 +84,7 @@ Passing `actionWidthLeft`/`actionWidthRight` a number still gives you a fixed-wi
84
84
  - **Reduced motion** — preset animations become instant under `prefers-reduced-motion: reduce`. An explicit `animationConfig` is treated as an intentional override and left untouched.
85
85
  - **State hooks for styling and testing** — the root carries `data-reveal-position="left | center | right"` (settled position) alongside `data-reveal-mode`.
86
86
  - **Screen readers** — the drag handle is decorative (`aria-hidden`) with a configurable sr-only description (`handleAriaLabel`).
87
+ - **Discoverable gesture** — tapping or clicking the handle briefly peeks the actions and springs back (released before the snap point), teaching the swipe without committing to a revealed state. Disable with `peekOnHandleTap={false}`; it's skipped automatically under reduced motion or `animationPreset="none"`.
87
88
 
88
89
  ## Modes
89
90
 
@@ -111,6 +112,7 @@ Omit `mode` and it's inferred: both slots → `both`, only `left` → `left`, ot
111
112
  | `handlePosition` | `'start' \| 'end'` | `'start'` in left mode, `'end'` otherwise | Where the handle strip sits in the row |
112
113
  | `handleTitle` | `string` | `'Drag horizontally…'` | Tooltip on the default handle |
113
114
  | `handleAriaLabel` | `string` | `'Drag horizontally…'` | Screen-reader text on the default handle |
115
+ | `peekOnHandleTap` | `boolean` | `true` | Tapping the handle briefly peeks the actions and springs back, hinting at the swipe gesture |
114
116
  | `onRevealChange` | `(pos: RevealPosition) => void` | — | Fires when the settled position changes (debounced) |
115
117
  | `onScroll` | `UIEventHandler` | — | Raw scroll events |
116
118
  | `disabled` | `boolean` | `false` | Disables swiping |
@@ -176,7 +178,7 @@ All sub-elements accept class names, so styling is entirely yours:
176
178
  .list > :last-child [data-reveal-row-left] button:first-child { border-bottom-left-radius: var(--row-radius); }
177
179
  ```
178
180
 
179
- The playground implements the same idea with an index-aware helper (`edgeCorners` in `playground/src/PlaygroundApp.tsx`).
181
+ The stories implement the same idea with an index-aware helper (`edgeCorners` in `stories/demo.tsx`).
180
182
 
181
183
  ## CSS tokens
182
184
 
@@ -186,7 +188,17 @@ The component is headless, but its one built-in dimension is themeable via a CSS
186
188
  | ----- | ------- | ------ |
187
189
  | `--reveal-row-action-min-width` | `88px` | Minimum width of an auto-sized action column (the floor under content-based sizing) |
188
190
 
189
- Set it on `:root` or any ancestor: `[data-reveal-mode] { --reveal-row-action-min-width: 72px; }`. Explicit `actionWidthLeft`/`actionWidthRight` props bypass the token. The playground layers its own tokens on top (`--row-radius`, `--action-width`) in `playground/index.html` — retheme everything from one place.
191
+ Set it on `:root` or any ancestor: `[data-reveal-mode] { --reveal-row-action-min-width: 72px; }`. Explicit `actionWidthLeft`/`actionWidthRight` props bypass the token. The stories layer their own tokens on top (`--row-radius`, `--action-width`) in `stories/demo.css` — retheme everything from one place.
192
+
193
+ ## Development
194
+
195
+ ```bash
196
+ bun run storybook # http://localhost:6006 (toolbar: Theme)
197
+ bun run test
198
+ bun run build
199
+ ```
200
+
201
+ **Testing on a phone** — swipe gestures are easiest to judge without the Storybook manager UI around the story. Open a story's standalone iframe instead, e.g. `http://<your-lan-ip>:6006/iframe.html?id=revealrow--multiple-actions` locally, or [the deployed one](https://present-day.github.io/reveal-row/iframe.html?id=revealrow--multiple-actions). Every story shows its own event log at the bottom of the screen.
190
202
 
191
203
  ## Publishing (maintainers)
192
204
 
package/dist/index.d.mts CHANGED
@@ -96,6 +96,14 @@ type RevealRowProps = {
96
96
  handleTitle?: string;
97
97
  /** Shown in screen-reader text when using the default drag handle. */
98
98
  handleAriaLabel?: string;
99
+ /**
100
+ * Tapping/clicking the drag handle briefly peeks the actions and springs
101
+ * back before the snap point, hinting at the swipe gesture. Skipped when
102
+ * the row's default animation resolves to instant (`animationPreset="none"`
103
+ * or the OS prefers-reduced-motion setting).
104
+ * @default true
105
+ */
106
+ peekOnHandleTap?: boolean;
99
107
  /** Fires when the settled position changes. */
100
108
  onRevealChange?: (position: RevealPosition) => void;
101
109
  onScroll?: (event: UIEvent<HTMLElement>) => void;
package/dist/index.d.ts CHANGED
@@ -96,6 +96,14 @@ type RevealRowProps = {
96
96
  handleTitle?: string;
97
97
  /** Shown in screen-reader text when using the default drag handle. */
98
98
  handleAriaLabel?: string;
99
+ /**
100
+ * Tapping/clicking the drag handle briefly peeks the actions and springs
101
+ * back before the snap point, hinting at the swipe gesture. Skipped when
102
+ * the row's default animation resolves to instant (`animationPreset="none"`
103
+ * or the OS prefers-reduced-motion setting).
104
+ * @default true
105
+ */
106
+ peekOnHandleTap?: boolean;
99
107
  /** Fires when the settled position changes. */
100
108
  onRevealChange?: (position: RevealPosition) => void;
101
109
  onScroll?: (event: UIEvent<HTMLElement>) => void;
package/dist/index.js CHANGED
@@ -164,6 +164,16 @@ function resolveAnimationConfig(animated, defaultPreset, customConfig) {
164
164
  }
165
165
  var SCROLL_REVEAL_DEBOUNCE_MS = 64;
166
166
  var restEpsilon = 2;
167
+ var PEEK_FRACTION = 0.35;
168
+ var PEEK_OUT_ANIMATION = {
169
+ duration: 120,
170
+ easing: "ease-out"
171
+ };
172
+ var PEEK_RETURN_ANIMATION = {
173
+ duration: 180,
174
+ easing: "ease-out"
175
+ };
176
+ var PEEK_SETTLE_BUFFER_MS = 120;
167
177
  var rootScrollStyle = {
168
178
  display: "grid",
169
179
  overflowX: "auto",
@@ -197,6 +207,7 @@ function RevealRowInner({
197
207
  handlePosition: handlePositionProp,
198
208
  handleTitle = "Drag horizontally to show actions",
199
209
  handleAriaLabel = "Drag horizontally to show actions",
210
+ peekOnHandleTap = true,
200
211
  onRevealChange,
201
212
  onScroll: onScrollProp,
202
213
  resetWhenDisabled = true,
@@ -215,6 +226,8 @@ function RevealRowInner({
215
226
  const containerRef = (0, import_react.useRef)(null);
216
227
  const leftRef = (0, import_react.useRef)(null);
217
228
  const rightRef = (0, import_react.useRef)(null);
229
+ const handleStripRef = (0, import_react.useRef)(null);
230
+ const peekTimerRef = (0, import_react.useRef)(null);
218
231
  const lastEmitted = (0, import_react.useRef)(null);
219
232
  const swipedRef = (0, import_react.useRef)(false);
220
233
  const focusRevealedRef = (0, import_react.useRef)(false);
@@ -335,6 +348,45 @@ function RevealRowInner({
335
348
  },
336
349
  []
337
350
  );
351
+ const peekActions = (0, import_react.useCallback)(() => {
352
+ const el = containerRef.current;
353
+ if (!el || disabled) return false;
354
+ if (isAnimatingRef.current || peekTimerRef.current !== null) return false;
355
+ const defaultConfig = resolveAnimationConfig(
356
+ void 0,
357
+ animationPreset,
358
+ animationConfig
359
+ );
360
+ if (defaultConfig.duration === 0) return false;
361
+ const m = getMaxScroll(el);
362
+ const wL = getWL();
363
+ const wR = getWR();
364
+ const closed = getScrollClosed(wL, wR, m, mode);
365
+ if (Math.abs(el.scrollLeft - closed) > restEpsilon) return false;
366
+ const peekRight = handlePosition === REVEAL_HANDLE_POSITION.end ? hasR : !hasL;
367
+ const target = peekRight ? Math.min(m, closed + wR * PEEK_FRACTION) : Math.max(0, closed - wL * PEEK_FRACTION);
368
+ if (target === closed) return false;
369
+ scrollToPosition(target, PEEK_OUT_ANIMATION);
370
+ peekTimerRef.current = setTimeout(() => {
371
+ scrollToPosition(closed, PEEK_RETURN_ANIMATION);
372
+ peekTimerRef.current = setTimeout(() => {
373
+ peekTimerRef.current = null;
374
+ swipedRef.current = false;
375
+ }, PEEK_RETURN_ANIMATION.duration + PEEK_SETTLE_BUFFER_MS);
376
+ }, PEEK_OUT_ANIMATION.duration);
377
+ return true;
378
+ }, [
379
+ animationConfig,
380
+ animationPreset,
381
+ disabled,
382
+ getWL,
383
+ getWR,
384
+ handlePosition,
385
+ hasL,
386
+ hasR,
387
+ mode,
388
+ scrollToPosition
389
+ ]);
338
390
  const closeRow = (0, import_react.useCallback)(
339
391
  (animated) => {
340
392
  const el = containerRef.current;
@@ -477,6 +529,9 @@ function RevealRowInner({
477
529
  if (finalizeTimerRef.current !== null) {
478
530
  clearTimeout(finalizeTimerRef.current);
479
531
  }
532
+ if (peekTimerRef.current !== null) {
533
+ clearTimeout(peekTimerRef.current);
534
+ }
480
535
  },
481
536
  []
482
537
  );
@@ -503,19 +558,27 @@ function RevealRowInner({
503
558
  },
504
559
  [emitReveal, getWL, getWR, mode, onScrollProp]
505
560
  );
506
- const onClickCapture = (0, import_react.useCallback)((e) => {
507
- const t = e.target;
508
- if (t) {
509
- if (leftRef.current?.contains(t) || rightRef.current?.contains(t)) {
561
+ const onClickCapture = (0, import_react.useCallback)(
562
+ (e) => {
563
+ const t = e.target;
564
+ if (t) {
565
+ if (leftRef.current?.contains(t) || rightRef.current?.contains(t)) {
566
+ return;
567
+ }
568
+ }
569
+ if (swipedRef.current) {
570
+ e.preventDefault();
571
+ e.stopPropagation();
572
+ swipedRef.current = false;
510
573
  return;
511
574
  }
512
- }
513
- if (swipedRef.current) {
514
- e.preventDefault();
515
- e.stopPropagation();
516
- swipedRef.current = false;
517
- }
518
- }, []);
575
+ if (peekOnHandleTap && t && handleStripRef.current?.contains(t) && peekActions()) {
576
+ e.preventDefault();
577
+ e.stopPropagation();
578
+ }
579
+ },
580
+ [peekActions, peekOnHandleTap]
581
+ );
519
582
  const trackL = wLIn != null ? `${wLIn}px` : "max-content";
520
583
  const trackR = wRIn != null ? `${wRIn}px` : "max-content";
521
584
  const gridTemplateColumns = mode === REVEAL_MODE.right ? `100% ${trackR}` : mode === REVEAL_MODE.left ? `${trackL} 100%` : `${trackL} 100% ${trackR}`;
@@ -542,6 +605,7 @@ function RevealRowInner({
542
605
  const handleStrip = showHandle ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
543
606
  "div",
544
607
  {
608
+ ref: handleStripRef,
545
609
  role: "presentation",
546
610
  className: classNames.handleContainer,
547
611
  "data-reveal-row-handle": true,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/getRevealFromScroll.ts","../src/RevealRow.tsx","../src/DefaultHandleIcon.tsx"],"sourcesContent":["export { getRevealFromScroll, getScrollClosed } from './getRevealFromScroll'\nexport { RevealRow } from './RevealRow'\nexport type {\n AnimationConfig,\n AnimationPreset,\n RevealHandlePosition,\n RevealMode,\n RevealPosition,\n RevealRowClassNames,\n RevealRowElement,\n RevealRowHandle,\n RevealRowProps,\n} from './types'\nexport {\n ANIMATION_PRESET,\n ANIMATION_PRESETS,\n REVEAL_HANDLE_POSITION,\n REVEAL_MODE,\n REVEAL_POSITION,\n REVEAL_ROW_ELEMENTS,\n} from './types'\n","import type { CSSProperties, ReactNode, UIEvent } from 'react'\n\nexport const REVEAL_MODE = {\n left: 'left',\n right: 'right',\n both: 'both',\n} as const\n\nexport type RevealMode = (typeof REVEAL_MODE)[keyof typeof REVEAL_MODE]\n\nexport const REVEAL_POSITION = {\n left: 'left',\n center: 'center',\n right: 'right',\n} as const\n\nexport type RevealPosition =\n (typeof REVEAL_POSITION)[keyof typeof REVEAL_POSITION]\n\nexport const REVEAL_HANDLE_POSITION = {\n start: 'start',\n end: 'end',\n} as const\n\nexport type RevealHandlePosition =\n (typeof REVEAL_HANDLE_POSITION)[keyof typeof REVEAL_HANDLE_POSITION]\n\nexport const REVEAL_ROW_ELEMENTS = {\n div: 'div',\n section: 'section',\n article: 'article',\n main: 'main',\n aside: 'aside',\n header: 'header',\n footer: 'footer',\n nav: 'nav',\n li: 'li',\n} as const\n\nexport type RevealRowElement =\n (typeof REVEAL_ROW_ELEMENTS)[keyof typeof REVEAL_ROW_ELEMENTS]\n\nexport const ANIMATION_PRESET = {\n none: 'none',\n quick: 'quick',\n smooth: 'smooth',\n} as const\n\nexport type AnimationPreset =\n (typeof ANIMATION_PRESET)[keyof typeof ANIMATION_PRESET]\n\nexport type AnimationConfig = {\n duration: number\n easing: string\n}\n\nexport const ANIMATION_PRESETS: Record<AnimationPreset, AnimationConfig> = {\n [ANIMATION_PRESET.none]: { duration: 0, easing: 'linear' },\n [ANIMATION_PRESET.quick]: { duration: 200, easing: 'ease-out' },\n [ANIMATION_PRESET.smooth]: { duration: 400, easing: 'ease-in-out' },\n}\n\nexport type RevealRowClassNames = {\n root?: string\n main?: string\n mainInner?: string\n left?: string\n right?: string\n handleContainer?: string\n handleIcon?: string\n}\n\nexport type RevealRowHandle = {\n close: (animated?: boolean | AnimationPreset | AnimationConfig) => void\n reveal: (\n position: RevealPosition,\n animated?: boolean | AnimationPreset | AnimationConfig,\n ) => void\n}\n\nexport type RevealRowProps = {\n /** Primary row content (e.g. title, subtitle). */\n children: ReactNode\n /** Optional leading action column (e.g. delete). Omitted in `right` mode. */\n left?: ReactNode\n /**\n * Trailing action column (e.g. add). Omitted in `left` mode.\n */\n right?: ReactNode\n /**\n * The HTML element to use for the root container.\n * @default 'div'\n */\n as?: RevealRowElement\n /**\n * If both `left` and `right` are set, defaults to `both`. If only one side,\n * mode is derived unless overridden.\n */\n mode?: RevealMode\n /**\n * Fixed width (px) of the left action column. Omit to size the column to\n * its content with an 88px floor (`minmax(88px, max-content)`).\n */\n actionWidthLeft?: number\n /**\n * Fixed width (px) of the right action column. Omit to size the column to\n * its content with an 88px floor (`minmax(88px, max-content)`).\n */\n actionWidthRight?: number\n classNames?: RevealRowClassNames\n /** @default true */\n showHandle?: boolean\n /** Replaces the built-in drag affordance. */\n handle?: ReactNode\n /**\n * Where the handle sits in the main row. Default: `start` in `left` mode,\n * `end` otherwise.\n */\n handlePosition?: RevealHandlePosition\n handleTitle?: string\n /** Shown in screen-reader text when using the default drag handle. */\n handleAriaLabel?: string\n /** Fires when the settled position changes. */\n onRevealChange?: (position: RevealPosition) => void\n onScroll?: (event: UIEvent<HTMLElement>) => void\n /** Resets to closed; default true. */\n resetWhenDisabled?: boolean\n disabled?: boolean\n /**\n * When true, snaps back to the closed position (e.g. row became active/selected\n * elsewhere in the list).\n */\n isActive?: boolean\n className?: string\n style?: CSSProperties\n /**\n * Default animation preset for close/reveal animations when action buttons are clicked.\n * @default 'quick'\n */\n animationPreset?: AnimationPreset\n /**\n * Custom animation configuration overriding the preset.\n */\n animationConfig?: AnimationConfig\n}\n","import {\n REVEAL_MODE,\n REVEAL_POSITION,\n type RevealMode,\n type RevealPosition,\n} from './types'\n\n/**\n * Map horizontal scroll position to a logical \"revealed\" state.\n * `wL` / `wR` are the fixed action column widths; `maxScroll` is\n * `Math.max(0, scrollWidth - clientWidth)`.\n */\nexport function getRevealFromScroll(\n scrollLeft: number,\n maxScroll: number,\n wL: number,\n wR: number,\n mode: RevealMode,\n): RevealPosition {\n if (mode === REVEAL_MODE.right) {\n if (maxScroll <= 0) return REVEAL_POSITION.center\n return scrollLeft < wR / 2 ? REVEAL_POSITION.center : REVEAL_POSITION.right\n }\n if (mode === REVEAL_MODE.left) {\n if (maxScroll <= 0) return REVEAL_POSITION.center\n return scrollLeft < wL / 2 ? REVEAL_POSITION.left : REVEAL_POSITION.center\n }\n if (maxScroll <= 0) return REVEAL_POSITION.center\n if (scrollLeft < wL / 2) return REVEAL_POSITION.left\n if (scrollLeft > maxScroll - wR / 2) return REVEAL_POSITION.right\n return REVEAL_POSITION.center\n}\n\n/** \"Closed\" / resting scrollLeft for a mode (main panel only). */\nexport function getScrollClosed(\n wL: number,\n _wR: number,\n _maxScroll: number,\n mode: RevealMode,\n): number {\n if (mode === REVEAL_MODE.right) return 0\n return wL\n}\n","'use client'\n\nimport type {\n CSSProperties,\n FocusEvent,\n ForwardedRef,\n MouseEvent,\n UIEvent,\n} from 'react'\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react'\n\nimport { DefaultHandleIcon } from './DefaultHandleIcon'\nimport { getRevealFromScroll, getScrollClosed } from './getRevealFromScroll'\nimport {\n ANIMATION_PRESET,\n ANIMATION_PRESETS,\n type AnimationConfig,\n type AnimationPreset,\n REVEAL_HANDLE_POSITION,\n REVEAL_MODE,\n REVEAL_POSITION,\n type RevealHandlePosition,\n type RevealMode,\n type RevealPosition,\n type RevealRowClassNames,\n type RevealRowHandle,\n type RevealRowProps,\n} from './types'\n\nfunction cx(...parts: (string | undefined)[]) {\n return parts.filter(Boolean).join(' ')\n}\n\nfunction getMaxScroll(el: HTMLElement) {\n return Math.max(0, el.scrollWidth - el.clientWidth)\n}\n\nfunction resolveMode(\n left: RevealRowProps['left'],\n right: RevealRowProps['right'],\n mode: RevealMode | undefined,\n): RevealMode {\n if (mode) return mode\n if (left != null && right != null) return REVEAL_MODE.both\n if (left != null) return REVEAL_MODE.left\n return REVEAL_MODE.right\n}\n\nfunction prefersReducedMotion(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n )\n}\n\nfunction resolveAnimationConfig(\n animated: boolean | AnimationPreset | AnimationConfig | undefined,\n defaultPreset: AnimationPreset,\n customConfig?: AnimationConfig,\n): AnimationConfig {\n let config: AnimationConfig\n // An explicit AnimationConfig object is an intentional override and is not\n // reduced; booleans and presets defer to the OS reduced-motion setting.\n let explicit = false\n\n if (animated === false) {\n config = ANIMATION_PRESETS[ANIMATION_PRESET.none]\n } else if (animated === true || animated === undefined) {\n if (customConfig) {\n config = customConfig\n explicit = true\n } else {\n config = ANIMATION_PRESETS[defaultPreset]\n }\n } else if (typeof animated === 'string') {\n config = ANIMATION_PRESETS[animated]\n } else {\n config = animated\n explicit = true\n }\n\n if (!explicit && prefersReducedMotion()) {\n return { ...config, duration: 0 }\n }\n\n // Validate and clamp duration to be >= 0\n return {\n ...config,\n duration: Math.max(\n 0,\n Number.isFinite(config.duration) ? config.duration : 0,\n ),\n }\n}\n\nconst SCROLL_REVEAL_DEBOUNCE_MS = 64\nconst restEpsilon = 2\n\nconst rootScrollStyle: CSSProperties = {\n display: 'grid',\n overflowX: 'auto',\n // `overflow-x: auto` would otherwise force `overflow-y` to compute to\n // `auto` — pin it so rows only ever scroll on one axis.\n overflowY: 'hidden',\n scrollSnapType: 'x mandatory',\n scrollbarWidth: 'none',\n WebkitOverflowScrolling: 'touch',\n overscrollBehaviorX: 'contain',\n touchAction: 'pan-x pan-y',\n}\n\nconst rootScrollStyleDisabled: CSSProperties = {\n ...rootScrollStyle,\n overflowX: 'hidden',\n touchAction: 'pan-y',\n}\n\nconst snapStart: CSSProperties = { scrollSnapAlign: 'start' }\nconst snapEnd: CSSProperties = { scrollSnapAlign: 'end' }\n\ntype InnerProps = RevealRowProps & {\n forwardedRef: ForwardedRef<RevealRowHandle>\n}\n\nfunction RevealRowInner({\n children,\n left,\n right,\n as: Element = 'div',\n mode: modeProp,\n actionWidthLeft: wLIn,\n actionWidthRight: wRIn,\n classNames = {} as RevealRowClassNames,\n showHandle = true,\n handle: handleOverride,\n handlePosition: handlePositionProp,\n handleTitle = 'Drag horizontally to show actions',\n handleAriaLabel = 'Drag horizontally to show actions',\n onRevealChange,\n onScroll: onScrollProp,\n resetWhenDisabled = true,\n disabled = false,\n isActive = false,\n className,\n style,\n animationPreset = ANIMATION_PRESET.quick,\n animationConfig,\n forwardedRef,\n}: InnerProps) {\n const mode = resolveMode(left, right, modeProp)\n const hasL = mode === REVEAL_MODE.left || mode === REVEAL_MODE.both\n const hasR = mode === REVEAL_MODE.right || mode === REVEAL_MODE.both\n\n const handlePosition: RevealHandlePosition =\n handlePositionProp ??\n (mode === REVEAL_MODE.left\n ? REVEAL_HANDLE_POSITION.start\n : REVEAL_HANDLE_POSITION.end)\n\n const containerRef = useRef<HTMLElement>(null)\n const leftRef = useRef<HTMLDivElement>(null)\n const rightRef = useRef<HTMLDivElement>(null)\n const lastEmitted = useRef<RevealPosition | null>(null)\n const swipedRef = useRef(false)\n const focusRevealedRef = useRef(false)\n const [settledPosition, setSettledPosition] = useState<RevealPosition>(\n REVEAL_POSITION.center,\n )\n\n // Effective action-column widths. With an explicit prop this is a constant;\n // without one the column is content-sized (minmax(88px, max-content) track)\n // and the rendered width is read live — only ever inside handlers that\n // already read layout, so no extra reflow cost. `|| 88` covers pre-mount\n // and environments without layout.\n const getWL = useCallback(\n () => (hasL ? (wLIn ?? (leftRef.current?.offsetWidth || 88)) : 0),\n [hasL, wLIn],\n )\n const getWR = useCallback(\n () => (hasR ? (wRIn ?? (rightRef.current?.offsetWidth || 88)) : 0),\n [hasR, wRIn],\n )\n const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n const hasAppliedInitialScroll = useRef(false)\n const isAnimatingRef = useRef(false)\n const rafIdRef = useRef<number | null>(null)\n const settleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const finalizeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const originalSnapRef = useRef('')\n\n const readPosition = useCallback((): RevealPosition => {\n const el = containerRef.current\n if (!el) return REVEAL_POSITION.center\n return getRevealFromScroll(\n el.scrollLeft,\n getMaxScroll(el),\n getWL(),\n getWR(),\n mode,\n )\n }, [getWL, getWR, mode])\n\n const emitReveal = useCallback(\n (position: RevealPosition) => {\n setSettledPosition(position)\n if (lastEmitted.current === position) return\n lastEmitted.current = position\n onRevealChange?.(position)\n },\n [onRevealChange],\n )\n\n const scrollToClosed = useCallback(() => {\n const el = containerRef.current\n if (!el) return\n const m = getMaxScroll(el)\n const closed = getScrollClosed(getWL(), getWR(), m, mode)\n\n // For immediate scroll, we can use the default behavior\n // CSS scroll snap will handle the final positioning\n el.scrollLeft = closed\n }, [getWL, getWR, mode])\n\n const scrollToPosition = useCallback(\n (targetScrollLeft: number, animationOptions: AnimationConfig) => {\n const el = containerRef.current\n if (!el) return\n\n const { duration, easing } = animationOptions\n\n if (duration === 0) {\n el.scrollLeft = targetScrollLeft\n return\n }\n\n // Cancel any existing animation\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n rafIdRef.current = null\n }\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n settleTimerRef.current = null\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n finalizeTimerRef.current = null\n }\n\n // Disable scroll snap during animation. Only capture the original value\n // when no animation is in flight — mid-animation it reads back our own\n // 'none' and would get restored permanently.\n if (!isAnimatingRef.current) {\n originalSnapRef.current = el.style.scrollSnapType\n }\n isAnimatingRef.current = true\n el.style.scrollSnapType = 'none'\n\n const finish = () => {\n el.scrollLeft = targetScrollLeft\n el.style.scrollSnapType = originalSnapRef.current || 'x mandatory'\n isAnimatingRef.current = false\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n rafIdRef.current = null\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n finalizeTimerRef.current = null\n }\n }\n\n // rAF is frozen on hidden/occluded pages — guarantee the animation\n // completes (and snap is restored) via a timer fallback.\n finalizeTimerRef.current = setTimeout(finish, duration + 100)\n\n const startScrollLeft = el.scrollLeft\n const distance = targetScrollLeft - startScrollLeft\n const startTime = performance.now()\n\n const animate = (currentTime: number) => {\n const elapsed = currentTime - startTime\n const progress = Math.min(elapsed / duration, 1)\n\n let easedProgress = progress\n if (easing === 'ease-out') {\n easedProgress = 1 - (1 - progress) ** 2\n } else if (easing === 'ease-in-out') {\n easedProgress =\n progress < 0.5\n ? 2 * progress * progress\n : 1 - (-2 * progress + 2) ** 2 / 2\n } else if (easing.startsWith('cubic-bezier')) {\n // For the bounce effect, we'll use a simplified approximation\n easedProgress = progress * progress * (3 - 2 * progress)\n if (easing.includes('-0.55')) {\n // Bounce effect approximation\n easedProgress =\n progress < 0.5\n ? 4 * progress * progress * progress\n : 1 - (-2 * progress + 2) ** 3 / 2\n // Add overshoot for bounce\n if (progress > 0.7 && progress < 1) {\n easedProgress +=\n Math.sin((progress - 0.7) * Math.PI * 10) * 0.1 * (1 - progress)\n }\n }\n }\n\n el.scrollLeft = startScrollLeft + distance * easedProgress\n\n if (progress < 1) {\n rafIdRef.current = requestAnimationFrame(animate)\n } else {\n rafIdRef.current = null\n finish()\n }\n }\n\n rafIdRef.current = requestAnimationFrame(animate)\n },\n [],\n )\n\n const closeRow = useCallback(\n (animated?: boolean | AnimationPreset | AnimationConfig) => {\n const el = containerRef.current\n if (!el) return\n\n const m = getMaxScroll(el)\n const closed = getScrollClosed(getWL(), getWR(), m, mode)\n const animConfig = resolveAnimationConfig(\n animated,\n animationPreset,\n animationConfig,\n )\n\n scrollToPosition(closed, animConfig)\n\n // Update position after animation or immediately if no animation\n const delay = animConfig.duration > 0 ? animConfig.duration : 0\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n settleTimerRef.current = setTimeout(() => {\n emitReveal(readPosition())\n settleTimerRef.current = null\n }, delay)\n },\n [\n animationConfig,\n animationPreset,\n emitReveal,\n getWL,\n getWR,\n mode,\n readPosition,\n scrollToPosition,\n ],\n )\n\n const revealRow = useCallback(\n (\n position: RevealPosition,\n animated?: boolean | AnimationPreset | AnimationConfig,\n ) => {\n const el = containerRef.current\n if (!el) return\n const max = getMaxScroll(el)\n const wL = getWL()\n const wR = getWR()\n\n let targetScroll: number\n if (position === REVEAL_POSITION.center) {\n targetScroll = getScrollClosed(wL, wR, max, mode)\n } else if (\n position === REVEAL_POSITION.left &&\n (mode === REVEAL_MODE.left || mode === REVEAL_MODE.both)\n ) {\n targetScroll = 0\n } else if (\n position === REVEAL_POSITION.right &&\n (mode === REVEAL_MODE.right || mode === REVEAL_MODE.both)\n ) {\n targetScroll = max\n } else {\n return\n }\n\n const animConfig = resolveAnimationConfig(\n animated,\n animationPreset,\n animationConfig,\n )\n scrollToPosition(targetScroll, animConfig)\n\n // Update position after animation or immediately if no animation\n const delay = animConfig.duration > 0 ? animConfig.duration : 0\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n settleTimerRef.current = setTimeout(() => {\n emitReveal(getRevealFromScroll(targetScroll, max, wL, wR, mode))\n settleTimerRef.current = null\n }, delay)\n },\n [\n animationConfig,\n animationPreset,\n emitReveal,\n getWL,\n getWR,\n mode,\n scrollToPosition,\n ],\n )\n\n useImperativeHandle(\n forwardedRef,\n () => ({ close: closeRow, reveal: revealRow }),\n [closeRow, revealRow],\n )\n\n // Keyboard support: tabbing into an off-screen action column snaps it\n // cleanly into view (instead of the browser's un-snapped scroll-into-view),\n // and a focus-initiated reveal closes again once focus leaves the row.\n // Swipe-opened rows are untouched by focus loss.\n const handleRootFocus = useCallback(\n (e: FocusEvent<HTMLElement>) => {\n const t = e.target as Node | null\n if (!t) return\n if (leftRef.current?.contains(t)) {\n focusRevealedRef.current = true\n revealRow(REVEAL_POSITION.left)\n } else if (rightRef.current?.contains(t)) {\n focusRevealedRef.current = true\n revealRow(REVEAL_POSITION.right)\n }\n },\n [revealRow],\n )\n\n const handleRootBlur = useCallback(\n (e: FocusEvent<HTMLElement>) => {\n if (!focusRevealedRef.current) return\n const next = e.relatedTarget as Node | null\n if (next && containerRef.current?.contains(next)) return\n focusRevealedRef.current = false\n closeRow()\n },\n [closeRow],\n )\n\n useLayoutEffect(() => {\n if (mode === REVEAL_MODE.right) {\n return\n }\n const el = containerRef.current\n if (!el) return\n if (!hasAppliedInitialScroll.current) {\n el.scrollLeft = getWL()\n hasAppliedInitialScroll.current = true\n }\n }, [mode, getWL])\n\n useEffect(() => {\n if (disabled && resetWhenDisabled) {\n hasAppliedInitialScroll.current = true\n scrollToClosed()\n emitReveal(readPosition())\n }\n }, [disabled, emitReveal, readPosition, resetWhenDisabled, scrollToClosed])\n\n useEffect(() => {\n if (isActive) {\n hasAppliedInitialScroll.current = true\n scrollToClosed()\n emitReveal(readPosition())\n }\n }, [emitReveal, isActive, readPosition, scrollToClosed])\n\n useEffect(\n () => () => {\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current)\n }\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n }\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n }\n },\n [],\n )\n\n const handleScroll = useCallback(\n (e: UIEvent<HTMLElement>) => {\n onScrollProp?.(e)\n const el = containerRef.current\n if (!el) return\n const m = getMaxScroll(el)\n const wL = getWL()\n const wR = getWR()\n const pos = getRevealFromScroll(el.scrollLeft, m, wL, wR, mode)\n const closed = getScrollClosed(wL, wR, m, mode)\n if (Math.abs(el.scrollLeft - closed) > restEpsilon) {\n swipedRef.current = true\n }\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current)\n }\n debounceTimer.current = setTimeout(() => {\n debounceTimer.current = null\n emitReveal(pos)\n }, SCROLL_REVEAL_DEBOUNCE_MS)\n },\n [emitReveal, getWL, getWR, mode, onScrollProp],\n )\n\n const onClickCapture = useCallback((e: MouseEvent) => {\n const t = e.target as Node | null\n if (t) {\n if (leftRef.current?.contains(t) || rightRef.current?.contains(t)) {\n return\n }\n }\n if (swipedRef.current) {\n e.preventDefault()\n e.stopPropagation()\n swipedRef.current = false\n }\n }, [])\n\n // `100%` for the main track (not `1fr`) so total row width > viewport: otherwise both\n // columns can shrink to fit with no overflow and the action stays visible.\n // Without an explicit width the column is content-sized via a `max-content`\n // track — `minmax(88px, max-content)` would never grow, because the `100%`\n // main track leaves no free space for minmax growth. The 88px floor for\n // stretchy content lives on the column element's `minWidth` instead, which\n // floors its sizing contribution to the track.\n const trackL = wLIn != null ? `${wLIn}px` : 'max-content'\n const trackR = wRIn != null ? `${wRIn}px` : 'max-content'\n const gridTemplateColumns =\n mode === REVEAL_MODE.right\n ? `100% ${trackR}`\n : mode === REVEAL_MODE.left\n ? `${trackL} 100%`\n : `${trackL} 100% ${trackR}`\n\n const handleContent = showHandle ? (\n handleOverride !== undefined ? (\n handleOverride\n ) : (\n <>\n <span\n className=\"sr-only\"\n style={{\n position: 'absolute',\n width: 1,\n height: 1,\n padding: 0,\n margin: -1,\n overflow: 'hidden',\n clip: 'rect(0,0,0,0)',\n border: 0,\n }}\n >\n {handleAriaLabel}\n </span>\n <span className={classNames.handleIcon} aria-hidden>\n <DefaultHandleIcon />\n </span>\n </>\n )\n ) : null\n\n const handleStrip = showHandle ? (\n <div\n role=\"presentation\"\n className={classNames.handleContainer}\n data-reveal-row-handle\n style={{\n flexShrink: 0,\n alignSelf: 'stretch',\n display: 'flex',\n alignItems: 'center',\n }}\n title={handleOverride === undefined ? handleTitle : undefined}\n >\n {handleContent}\n </div>\n ) : null\n\n const mainColumn = (\n <div\n className={classNames.main}\n data-reveal-row-main\n style={{\n ...snapStart,\n minWidth: 0,\n width: '100%',\n maxWidth: '100%',\n boxSizing: 'border-box',\n }}\n >\n <div\n className={classNames.mainInner}\n style={{\n display: 'flex',\n minWidth: 0,\n width: '100%',\n alignItems: 'flex-start',\n }}\n >\n {handlePosition === REVEAL_HANDLE_POSITION.start && handleStrip}\n <div style={{ minWidth: 0, flex: 1, flexBasis: 0 }}>{children}</div>\n {handlePosition === REVEAL_HANDLE_POSITION.end && handleStrip}\n </div>\n </div>\n )\n\n return (\n <Element\n // biome-ignore lint/suspicious/noExplicitAny: Required for polymorphic ref compatibility\n ref={containerRef as any}\n data-reveal-mode={mode}\n data-reveal-position={settledPosition}\n className={cx(classNames.root, className)}\n onScroll={handleScroll}\n onClickCapture={onClickCapture}\n onFocus={handleRootFocus}\n onBlur={handleRootBlur}\n style={{\n ...(disabled ? rootScrollStyleDisabled : rootScrollStyle),\n ...style,\n gridTemplateColumns,\n }}\n >\n {hasL ? (\n <div\n ref={leftRef}\n className={classNames.left}\n data-reveal-row-left\n style={{\n ...snapStart,\n ...(wLIn != null\n ? { minWidth: 0, width: wLIn }\n : { minWidth: 'var(--reveal-row-action-min-width, 88px)' }),\n }}\n >\n {left}\n </div>\n ) : null}\n {mainColumn}\n {hasR ? (\n <div\n ref={rightRef}\n className={classNames.right}\n data-reveal-row-right\n style={{\n ...snapEnd,\n ...(wRIn != null\n ? { minWidth: 0, width: wRIn }\n : { minWidth: 'var(--reveal-row-action-min-width, 88px)' }),\n }}\n >\n {right}\n </div>\n ) : null}\n </Element>\n )\n}\n\nexport const RevealRow = forwardRef<RevealRowHandle, RevealRowProps>(\n function RevealRow(props, ref) {\n return <RevealRowInner {...props} forwardedRef={ref} />\n },\n)\n","/** Minimal 6-dot grip, no icon library dependency. */\nexport function DefaultHandleIcon() {\n return (\n <svg\n width={16}\n height={16}\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n aria-hidden\n >\n <title>Drag handle</title>\n <circle cx=\"6\" cy=\"4\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"4\" r=\"1.2\" />\n <circle cx=\"6\" cy=\"8\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"8\" r=\"1.2\" />\n <circle cx=\"6\" cy=\"12\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"12\" r=\"1.2\" />\n </svg>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,cAAc;AAAA,EACzB,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AACR;AAIO,IAAM,kBAAkB;AAAA,EAC7B,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AACT;AAKO,IAAM,yBAAyB;AAAA,EACpC,OAAO;AAAA,EACP,KAAK;AACP;AAKO,IAAM,sBAAsB;AAAA,EACjC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,IAAI;AACN;AAKO,IAAM,mBAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AACV;AAUO,IAAM,oBAA8D;AAAA,EACzE,CAAC,iBAAiB,IAAI,GAAG,EAAE,UAAU,GAAG,QAAQ,SAAS;AAAA,EACzD,CAAC,iBAAiB,KAAK,GAAG,EAAE,UAAU,KAAK,QAAQ,WAAW;AAAA,EAC9D,CAAC,iBAAiB,MAAM,GAAG,EAAE,UAAU,KAAK,QAAQ,cAAc;AACpE;;;AChDO,SAAS,oBACd,YACA,WACA,IACA,IACA,MACgB;AAChB,MAAI,SAAS,YAAY,OAAO;AAC9B,QAAI,aAAa,EAAG,QAAO,gBAAgB;AAC3C,WAAO,aAAa,KAAK,IAAI,gBAAgB,SAAS,gBAAgB;AAAA,EACxE;AACA,MAAI,SAAS,YAAY,MAAM;AAC7B,QAAI,aAAa,EAAG,QAAO,gBAAgB;AAC3C,WAAO,aAAa,KAAK,IAAI,gBAAgB,OAAO,gBAAgB;AAAA,EACtE;AACA,MAAI,aAAa,EAAG,QAAO,gBAAgB;AAC3C,MAAI,aAAa,KAAK,EAAG,QAAO,gBAAgB;AAChD,MAAI,aAAa,YAAY,KAAK,EAAG,QAAO,gBAAgB;AAC5D,SAAO,gBAAgB;AACzB;AAGO,SAAS,gBACd,IACA,KACA,YACA,MACQ;AACR,MAAI,SAAS,YAAY,MAAO,QAAO;AACvC,SAAO;AACT;;;ACjCA,mBAQO;;;ACdH;AAFG,SAAS,oBAAoB;AAClC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,eAAW;AAAA,MAEX;AAAA,oDAAC,WAAM,yBAAW;AAAA,QAClB,4CAAC,YAAO,IAAG,KAAI,IAAG,KAAI,GAAE,OAAM;AAAA,QAC9B,4CAAC,YAAO,IAAG,MAAK,IAAG,KAAI,GAAE,OAAM;AAAA,QAC/B,4CAAC,YAAO,IAAG,KAAI,IAAG,KAAI,GAAE,OAAM;AAAA,QAC9B,4CAAC,YAAO,IAAG,MAAK,IAAG,KAAI,GAAE,OAAM;AAAA,QAC/B,4CAAC,YAAO,IAAG,KAAI,IAAG,MAAK,GAAE,OAAM;AAAA,QAC/B,4CAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,OAAM;AAAA;AAAA;AAAA,EAClC;AAEJ;;;ADmiBM,IAAAA,sBAAA;AAjhBN,SAAS,MAAM,OAA+B;AAC5C,SAAO,MAAM,OAAO,OAAO,EAAE,KAAK,GAAG;AACvC;AAEA,SAAS,aAAa,IAAiB;AACrC,SAAO,KAAK,IAAI,GAAG,GAAG,cAAc,GAAG,WAAW;AACpD;AAEA,SAAS,YACP,MACA,OACA,MACY;AACZ,MAAI,KAAM,QAAO;AACjB,MAAI,QAAQ,QAAQ,SAAS,KAAM,QAAO,YAAY;AACtD,MAAI,QAAQ,KAAM,QAAO,YAAY;AACrC,SAAO,YAAY;AACrB;AAEA,SAAS,uBAAgC;AACvC,SACE,OAAO,WAAW,eAClB,OAAO,OAAO,eAAe,cAC7B,OAAO,WAAW,kCAAkC,EAAE;AAE1D;AAEA,SAAS,uBACP,UACA,eACA,cACiB;AACjB,MAAI;AAGJ,MAAI,WAAW;AAEf,MAAI,aAAa,OAAO;AACtB,aAAS,kBAAkB,iBAAiB,IAAI;AAAA,EAClD,WAAW,aAAa,QAAQ,aAAa,QAAW;AACtD,QAAI,cAAc;AAChB,eAAS;AACT,iBAAW;AAAA,IACb,OAAO;AACL,eAAS,kBAAkB,aAAa;AAAA,IAC1C;AAAA,EACF,WAAW,OAAO,aAAa,UAAU;AACvC,aAAS,kBAAkB,QAAQ;AAAA,EACrC,OAAO;AACL,aAAS;AACT,eAAW;AAAA,EACb;AAEA,MAAI,CAAC,YAAY,qBAAqB,GAAG;AACvC,WAAO,EAAE,GAAG,QAAQ,UAAU,EAAE;AAAA,EAClC;AAGA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU,KAAK;AAAA,MACb;AAAA,MACA,OAAO,SAAS,OAAO,QAAQ,IAAI,OAAO,WAAW;AAAA,IACvD;AAAA,EACF;AACF;AAEA,IAAM,4BAA4B;AAClC,IAAM,cAAc;AAEpB,IAAM,kBAAiC;AAAA,EACrC,SAAS;AAAA,EACT,WAAW;AAAA;AAAA;AAAA,EAGX,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,yBAAyB;AAAA,EACzB,qBAAqB;AAAA,EACrB,aAAa;AACf;AAEA,IAAM,0BAAyC;AAAA,EAC7C,GAAG;AAAA,EACH,WAAW;AAAA,EACX,aAAa;AACf;AAEA,IAAM,YAA2B,EAAE,iBAAiB,QAAQ;AAC5D,IAAM,UAAyB,EAAE,iBAAiB,MAAM;AAMxD,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA,IAAI,UAAU;AAAA,EACd,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,aAAa,CAAC;AAAA,EACd,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB;AAAA,EACA,UAAU;AAAA,EACV,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,kBAAkB,iBAAiB;AAAA,EACnC;AAAA,EACA;AACF,GAAe;AACb,QAAM,OAAO,YAAY,MAAM,OAAO,QAAQ;AAC9C,QAAM,OAAO,SAAS,YAAY,QAAQ,SAAS,YAAY;AAC/D,QAAM,OAAO,SAAS,YAAY,SAAS,SAAS,YAAY;AAEhE,QAAM,iBACJ,uBACC,SAAS,YAAY,OAClB,uBAAuB,QACvB,uBAAuB;AAE7B,QAAM,mBAAe,qBAAoB,IAAI;AAC7C,QAAM,cAAU,qBAAuB,IAAI;AAC3C,QAAM,eAAW,qBAAuB,IAAI;AAC5C,QAAM,kBAAc,qBAA8B,IAAI;AACtD,QAAM,gBAAY,qBAAO,KAAK;AAC9B,QAAM,uBAAmB,qBAAO,KAAK;AACrC,QAAM,CAAC,iBAAiB,kBAAkB,QAAI;AAAA,IAC5C,gBAAgB;AAAA,EAClB;AAOA,QAAM,YAAQ;AAAA,IACZ,MAAO,OAAQ,SAAS,QAAQ,SAAS,eAAe,MAAO;AAAA,IAC/D,CAAC,MAAM,IAAI;AAAA,EACb;AACA,QAAM,YAAQ;AAAA,IACZ,MAAO,OAAQ,SAAS,SAAS,SAAS,eAAe,MAAO;AAAA,IAChE,CAAC,MAAM,IAAI;AAAA,EACb;AACA,QAAM,oBAAgB,qBAA6C,IAAI;AACvE,QAAM,8BAA0B,qBAAO,KAAK;AAC5C,QAAM,qBAAiB,qBAAO,KAAK;AACnC,QAAM,eAAW,qBAAsB,IAAI;AAC3C,QAAM,qBAAiB,qBAA6C,IAAI;AACxE,QAAM,uBAAmB,qBAA6C,IAAI;AAC1E,QAAM,sBAAkB,qBAAO,EAAE;AAEjC,QAAM,mBAAe,0BAAY,MAAsB;AACrD,UAAM,KAAK,aAAa;AACxB,QAAI,CAAC,GAAI,QAAO,gBAAgB;AAChC,WAAO;AAAA,MACL,GAAG;AAAA,MACH,aAAa,EAAE;AAAA,MACf,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAO,OAAO,IAAI,CAAC;AAEvB,QAAM,iBAAa;AAAA,IACjB,CAAC,aAA6B;AAC5B,yBAAmB,QAAQ;AAC3B,UAAI,YAAY,YAAY,SAAU;AACtC,kBAAY,UAAU;AACtB,uBAAiB,QAAQ;AAAA,IAC3B;AAAA,IACA,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,qBAAiB,0BAAY,MAAM;AACvC,UAAM,KAAK,aAAa;AACxB,QAAI,CAAC,GAAI;AACT,UAAM,IAAI,aAAa,EAAE;AACzB,UAAM,SAAS,gBAAgB,MAAM,GAAG,MAAM,GAAG,GAAG,IAAI;AAIxD,OAAG,aAAa;AAAA,EAClB,GAAG,CAAC,OAAO,OAAO,IAAI,CAAC;AAEvB,QAAM,uBAAmB;AAAA,IACvB,CAAC,kBAA0B,qBAAsC;AAC/D,YAAM,KAAK,aAAa;AACxB,UAAI,CAAC,GAAI;AAET,YAAM,EAAE,UAAU,OAAO,IAAI;AAE7B,UAAI,aAAa,GAAG;AAClB,WAAG,aAAa;AAChB;AAAA,MACF;AAGA,UAAI,SAAS,YAAY,MAAM;AAC7B,6BAAqB,SAAS,OAAO;AACrC,iBAAS,UAAU;AAAA,MACrB;AACA,UAAI,eAAe,YAAY,MAAM;AACnC,qBAAa,eAAe,OAAO;AACnC,uBAAe,UAAU;AAAA,MAC3B;AACA,UAAI,iBAAiB,YAAY,MAAM;AACrC,qBAAa,iBAAiB,OAAO;AACrC,yBAAiB,UAAU;AAAA,MAC7B;AAKA,UAAI,CAAC,eAAe,SAAS;AAC3B,wBAAgB,UAAU,GAAG,MAAM;AAAA,MACrC;AACA,qBAAe,UAAU;AACzB,SAAG,MAAM,iBAAiB;AAE1B,YAAM,SAAS,MAAM;AACnB,WAAG,aAAa;AAChB,WAAG,MAAM,iBAAiB,gBAAgB,WAAW;AACrD,uBAAe,UAAU;AACzB,YAAI,SAAS,YAAY,MAAM;AAC7B,+BAAqB,SAAS,OAAO;AACrC,mBAAS,UAAU;AAAA,QACrB;AACA,YAAI,iBAAiB,YAAY,MAAM;AACrC,uBAAa,iBAAiB,OAAO;AACrC,2BAAiB,UAAU;AAAA,QAC7B;AAAA,MACF;AAIA,uBAAiB,UAAU,WAAW,QAAQ,WAAW,GAAG;AAE5D,YAAM,kBAAkB,GAAG;AAC3B,YAAM,WAAW,mBAAmB;AACpC,YAAM,YAAY,YAAY,IAAI;AAElC,YAAM,UAAU,CAAC,gBAAwB;AACvC,cAAM,UAAU,cAAc;AAC9B,cAAM,WAAW,KAAK,IAAI,UAAU,UAAU,CAAC;AAE/C,YAAI,gBAAgB;AACpB,YAAI,WAAW,YAAY;AACzB,0BAAgB,KAAK,IAAI,aAAa;AAAA,QACxC,WAAW,WAAW,eAAe;AACnC,0BACE,WAAW,MACP,IAAI,WAAW,WACf,KAAK,KAAK,WAAW,MAAM,IAAI;AAAA,QACvC,WAAW,OAAO,WAAW,cAAc,GAAG;AAE5C,0BAAgB,WAAW,YAAY,IAAI,IAAI;AAC/C,cAAI,OAAO,SAAS,OAAO,GAAG;AAE5B,4BACE,WAAW,MACP,IAAI,WAAW,WAAW,WAC1B,KAAK,KAAK,WAAW,MAAM,IAAI;AAErC,gBAAI,WAAW,OAAO,WAAW,GAAG;AAClC,+BACE,KAAK,KAAK,WAAW,OAAO,KAAK,KAAK,EAAE,IAAI,OAAO,IAAI;AAAA,YAC3D;AAAA,UACF;AAAA,QACF;AAEA,WAAG,aAAa,kBAAkB,WAAW;AAE7C,YAAI,WAAW,GAAG;AAChB,mBAAS,UAAU,sBAAsB,OAAO;AAAA,QAClD,OAAO;AACL,mBAAS,UAAU;AACnB,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,eAAS,UAAU,sBAAsB,OAAO;AAAA,IAClD;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,eAAW;AAAA,IACf,CAAC,aAA2D;AAC1D,YAAM,KAAK,aAAa;AACxB,UAAI,CAAC,GAAI;AAET,YAAM,IAAI,aAAa,EAAE;AACzB,YAAM,SAAS,gBAAgB,MAAM,GAAG,MAAM,GAAG,GAAG,IAAI;AACxD,YAAM,aAAa;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,uBAAiB,QAAQ,UAAU;AAGnC,YAAM,QAAQ,WAAW,WAAW,IAAI,WAAW,WAAW;AAC9D,UAAI,eAAe,YAAY,MAAM;AACnC,qBAAa,eAAe,OAAO;AAAA,MACrC;AACA,qBAAe,UAAU,WAAW,MAAM;AACxC,mBAAW,aAAa,CAAC;AACzB,uBAAe,UAAU;AAAA,MAC3B,GAAG,KAAK;AAAA,IACV;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,gBAAY;AAAA,IAChB,CACE,UACA,aACG;AACH,YAAM,KAAK,aAAa;AACxB,UAAI,CAAC,GAAI;AACT,YAAM,MAAM,aAAa,EAAE;AAC3B,YAAM,KAAK,MAAM;AACjB,YAAM,KAAK,MAAM;AAEjB,UAAI;AACJ,UAAI,aAAa,gBAAgB,QAAQ;AACvC,uBAAe,gBAAgB,IAAI,IAAI,KAAK,IAAI;AAAA,MAClD,WACE,aAAa,gBAAgB,SAC5B,SAAS,YAAY,QAAQ,SAAS,YAAY,OACnD;AACA,uBAAe;AAAA,MACjB,WACE,aAAa,gBAAgB,UAC5B,SAAS,YAAY,SAAS,SAAS,YAAY,OACpD;AACA,uBAAe;AAAA,MACjB,OAAO;AACL;AAAA,MACF;AAEA,YAAM,aAAa;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,uBAAiB,cAAc,UAAU;AAGzC,YAAM,QAAQ,WAAW,WAAW,IAAI,WAAW,WAAW;AAC9D,UAAI,eAAe,YAAY,MAAM;AACnC,qBAAa,eAAe,OAAO;AAAA,MACrC;AACA,qBAAe,UAAU,WAAW,MAAM;AACxC,mBAAW,oBAAoB,cAAc,KAAK,IAAI,IAAI,IAAI,CAAC;AAC/D,uBAAe,UAAU;AAAA,MAC3B,GAAG,KAAK;AAAA,IACV;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA;AAAA,IACE;AAAA,IACA,OAAO,EAAE,OAAO,UAAU,QAAQ,UAAU;AAAA,IAC5C,CAAC,UAAU,SAAS;AAAA,EACtB;AAMA,QAAM,sBAAkB;AAAA,IACtB,CAAC,MAA+B;AAC9B,YAAM,IAAI,EAAE;AACZ,UAAI,CAAC,EAAG;AACR,UAAI,QAAQ,SAAS,SAAS,CAAC,GAAG;AAChC,yBAAiB,UAAU;AAC3B,kBAAU,gBAAgB,IAAI;AAAA,MAChC,WAAW,SAAS,SAAS,SAAS,CAAC,GAAG;AACxC,yBAAiB,UAAU;AAC3B,kBAAU,gBAAgB,KAAK;AAAA,MACjC;AAAA,IACF;AAAA,IACA,CAAC,SAAS;AAAA,EACZ;AAEA,QAAM,qBAAiB;AAAA,IACrB,CAAC,MAA+B;AAC9B,UAAI,CAAC,iBAAiB,QAAS;AAC/B,YAAM,OAAO,EAAE;AACf,UAAI,QAAQ,aAAa,SAAS,SAAS,IAAI,EAAG;AAClD,uBAAiB,UAAU;AAC3B,eAAS;AAAA,IACX;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,oCAAgB,MAAM;AACpB,QAAI,SAAS,YAAY,OAAO;AAC9B;AAAA,IACF;AACA,UAAM,KAAK,aAAa;AACxB,QAAI,CAAC,GAAI;AACT,QAAI,CAAC,wBAAwB,SAAS;AACpC,SAAG,aAAa,MAAM;AACtB,8BAAwB,UAAU;AAAA,IACpC;AAAA,EACF,GAAG,CAAC,MAAM,KAAK,CAAC;AAEhB,8BAAU,MAAM;AACd,QAAI,YAAY,mBAAmB;AACjC,8BAAwB,UAAU;AAClC,qBAAe;AACf,iBAAW,aAAa,CAAC;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,UAAU,YAAY,cAAc,mBAAmB,cAAc,CAAC;AAE1E,8BAAU,MAAM;AACd,QAAI,UAAU;AACZ,8BAAwB,UAAU;AAClC,qBAAe;AACf,iBAAW,aAAa,CAAC;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,YAAY,UAAU,cAAc,cAAc,CAAC;AAEvD;AAAA,IACE,MAAM,MAAM;AACV,UAAI,cAAc,SAAS;AACzB,qBAAa,cAAc,OAAO;AAAA,MACpC;AACA,UAAI,SAAS,YAAY,MAAM;AAC7B,6BAAqB,SAAS,OAAO;AAAA,MACvC;AACA,UAAI,eAAe,YAAY,MAAM;AACnC,qBAAa,eAAe,OAAO;AAAA,MACrC;AACA,UAAI,iBAAiB,YAAY,MAAM;AACrC,qBAAa,iBAAiB,OAAO;AAAA,MACvC;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,mBAAe;AAAA,IACnB,CAAC,MAA4B;AAC3B,qBAAe,CAAC;AAChB,YAAM,KAAK,aAAa;AACxB,UAAI,CAAC,GAAI;AACT,YAAM,IAAI,aAAa,EAAE;AACzB,YAAM,KAAK,MAAM;AACjB,YAAM,KAAK,MAAM;AACjB,YAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,IAAI,IAAI,IAAI;AAC9D,YAAM,SAAS,gBAAgB,IAAI,IAAI,GAAG,IAAI;AAC9C,UAAI,KAAK,IAAI,GAAG,aAAa,MAAM,IAAI,aAAa;AAClD,kBAAU,UAAU;AAAA,MACtB;AACA,UAAI,cAAc,SAAS;AACzB,qBAAa,cAAc,OAAO;AAAA,MACpC;AACA,oBAAc,UAAU,WAAW,MAAM;AACvC,sBAAc,UAAU;AACxB,mBAAW,GAAG;AAAA,MAChB,GAAG,yBAAyB;AAAA,IAC9B;AAAA,IACA,CAAC,YAAY,OAAO,OAAO,MAAM,YAAY;AAAA,EAC/C;AAEA,QAAM,qBAAiB,0BAAY,CAAC,MAAkB;AACpD,UAAM,IAAI,EAAE;AACZ,QAAI,GAAG;AACL,UAAI,QAAQ,SAAS,SAAS,CAAC,KAAK,SAAS,SAAS,SAAS,CAAC,GAAG;AACjE;AAAA,MACF;AAAA,IACF;AACA,QAAI,UAAU,SAAS;AACrB,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,gBAAU,UAAU;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,CAAC;AASL,QAAM,SAAS,QAAQ,OAAO,GAAG,IAAI,OAAO;AAC5C,QAAM,SAAS,QAAQ,OAAO,GAAG,IAAI,OAAO;AAC5C,QAAM,sBACJ,SAAS,YAAY,QACjB,QAAQ,MAAM,KACd,SAAS,YAAY,OACnB,GAAG,MAAM,UACT,GAAG,MAAM,SAAS,MAAM;AAEhC,QAAM,gBAAgB,aACpB,mBAAmB,SACjB,iBAEA,8EACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ;AAAA,QACV;AAAA,QAEC;AAAA;AAAA,IACH;AAAA,IACA,6CAAC,UAAK,WAAW,WAAW,YAAY,eAAW,MACjD,uDAAC,qBAAkB,GACrB;AAAA,KACF,IAEA;AAEJ,QAAM,cAAc,aAClB;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAW,WAAW;AAAA,MACtB,0BAAsB;AAAA,MACtB,OAAO;AAAA,QACL,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,SAAS;AAAA,QACT,YAAY;AAAA,MACd;AAAA,MACA,OAAO,mBAAmB,SAAY,cAAc;AAAA,MAEnD;AAAA;AAAA,EACH,IACE;AAEJ,QAAM,aACJ;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,WAAW;AAAA,MACtB,wBAAoB;AAAA,MACpB,OAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU;AAAA,QACV,OAAO;AAAA,QACP,UAAU;AAAA,QACV,WAAW;AAAA,MACb;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,WAAW;AAAA,UACtB,OAAO;AAAA,YACL,SAAS;AAAA,YACT,UAAU;AAAA,YACV,OAAO;AAAA,YACP,YAAY;AAAA,UACd;AAAA,UAEC;AAAA,+BAAmB,uBAAuB,SAAS;AAAA,YACpD,6CAAC,SAAI,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,WAAW,EAAE,GAAI,UAAS;AAAA,YAC7D,mBAAmB,uBAAuB,OAAO;AAAA;AAAA;AAAA,MACpD;AAAA;AAAA,EACF;AAGF,SACE;AAAA,IAAC;AAAA;AAAA,MAEC,KAAK;AAAA,MACL,oBAAkB;AAAA,MAClB,wBAAsB;AAAA,MACtB,WAAW,GAAG,WAAW,MAAM,SAAS;AAAA,MACxC,UAAU;AAAA,MACV;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,OAAO;AAAA,QACL,GAAI,WAAW,0BAA0B;AAAA,QACzC,GAAG;AAAA,QACH;AAAA,MACF;AAAA,MAEC;AAAA,eACC;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,WAAW,WAAW;AAAA,YACtB,wBAAoB;AAAA,YACpB,OAAO;AAAA,cACL,GAAG;AAAA,cACH,GAAI,QAAQ,OACR,EAAE,UAAU,GAAG,OAAO,KAAK,IAC3B,EAAE,UAAU,2CAA2C;AAAA,YAC7D;AAAA,YAEC;AAAA;AAAA,QACH,IACE;AAAA,QACH;AAAA,QACA,OACC;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,WAAW,WAAW;AAAA,YACtB,yBAAqB;AAAA,YACrB,OAAO;AAAA,cACL,GAAG;AAAA,cACH,GAAI,QAAQ,OACR,EAAE,UAAU,GAAG,OAAO,KAAK,IAC3B,EAAE,UAAU,2CAA2C;AAAA,YAC7D;AAAA,YAEC;AAAA;AAAA,QACH,IACE;AAAA;AAAA;AAAA,EACN;AAEJ;AAEO,IAAM,gBAAY;AAAA,EACvB,SAASC,WAAU,OAAO,KAAK;AAC7B,WAAO,6CAAC,kBAAgB,GAAG,OAAO,cAAc,KAAK;AAAA,EACvD;AACF;","names":["import_jsx_runtime","RevealRow"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/getRevealFromScroll.ts","../src/RevealRow.tsx","../src/DefaultHandleIcon.tsx"],"sourcesContent":["export { getRevealFromScroll, getScrollClosed } from './getRevealFromScroll'\nexport { RevealRow } from './RevealRow'\nexport type {\n AnimationConfig,\n AnimationPreset,\n RevealHandlePosition,\n RevealMode,\n RevealPosition,\n RevealRowClassNames,\n RevealRowElement,\n RevealRowHandle,\n RevealRowProps,\n} from './types'\nexport {\n ANIMATION_PRESET,\n ANIMATION_PRESETS,\n REVEAL_HANDLE_POSITION,\n REVEAL_MODE,\n REVEAL_POSITION,\n REVEAL_ROW_ELEMENTS,\n} from './types'\n","import type { CSSProperties, ReactNode, UIEvent } from 'react'\n\nexport const REVEAL_MODE = {\n left: 'left',\n right: 'right',\n both: 'both',\n} as const\n\nexport type RevealMode = (typeof REVEAL_MODE)[keyof typeof REVEAL_MODE]\n\nexport const REVEAL_POSITION = {\n left: 'left',\n center: 'center',\n right: 'right',\n} as const\n\nexport type RevealPosition =\n (typeof REVEAL_POSITION)[keyof typeof REVEAL_POSITION]\n\nexport const REVEAL_HANDLE_POSITION = {\n start: 'start',\n end: 'end',\n} as const\n\nexport type RevealHandlePosition =\n (typeof REVEAL_HANDLE_POSITION)[keyof typeof REVEAL_HANDLE_POSITION]\n\nexport const REVEAL_ROW_ELEMENTS = {\n div: 'div',\n section: 'section',\n article: 'article',\n main: 'main',\n aside: 'aside',\n header: 'header',\n footer: 'footer',\n nav: 'nav',\n li: 'li',\n} as const\n\nexport type RevealRowElement =\n (typeof REVEAL_ROW_ELEMENTS)[keyof typeof REVEAL_ROW_ELEMENTS]\n\nexport const ANIMATION_PRESET = {\n none: 'none',\n quick: 'quick',\n smooth: 'smooth',\n} as const\n\nexport type AnimationPreset =\n (typeof ANIMATION_PRESET)[keyof typeof ANIMATION_PRESET]\n\nexport type AnimationConfig = {\n duration: number\n easing: string\n}\n\nexport const ANIMATION_PRESETS: Record<AnimationPreset, AnimationConfig> = {\n [ANIMATION_PRESET.none]: { duration: 0, easing: 'linear' },\n [ANIMATION_PRESET.quick]: { duration: 200, easing: 'ease-out' },\n [ANIMATION_PRESET.smooth]: { duration: 400, easing: 'ease-in-out' },\n}\n\nexport type RevealRowClassNames = {\n root?: string\n main?: string\n mainInner?: string\n left?: string\n right?: string\n handleContainer?: string\n handleIcon?: string\n}\n\nexport type RevealRowHandle = {\n close: (animated?: boolean | AnimationPreset | AnimationConfig) => void\n reveal: (\n position: RevealPosition,\n animated?: boolean | AnimationPreset | AnimationConfig,\n ) => void\n}\n\nexport type RevealRowProps = {\n /** Primary row content (e.g. title, subtitle). */\n children: ReactNode\n /** Optional leading action column (e.g. delete). Omitted in `right` mode. */\n left?: ReactNode\n /**\n * Trailing action column (e.g. add). Omitted in `left` mode.\n */\n right?: ReactNode\n /**\n * The HTML element to use for the root container.\n * @default 'div'\n */\n as?: RevealRowElement\n /**\n * If both `left` and `right` are set, defaults to `both`. If only one side,\n * mode is derived unless overridden.\n */\n mode?: RevealMode\n /**\n * Fixed width (px) of the left action column. Omit to size the column to\n * its content with an 88px floor (`minmax(88px, max-content)`).\n */\n actionWidthLeft?: number\n /**\n * Fixed width (px) of the right action column. Omit to size the column to\n * its content with an 88px floor (`minmax(88px, max-content)`).\n */\n actionWidthRight?: number\n classNames?: RevealRowClassNames\n /** @default true */\n showHandle?: boolean\n /** Replaces the built-in drag affordance. */\n handle?: ReactNode\n /**\n * Where the handle sits in the main row. Default: `start` in `left` mode,\n * `end` otherwise.\n */\n handlePosition?: RevealHandlePosition\n handleTitle?: string\n /** Shown in screen-reader text when using the default drag handle. */\n handleAriaLabel?: string\n /**\n * Tapping/clicking the drag handle briefly peeks the actions and springs\n * back before the snap point, hinting at the swipe gesture. Skipped when\n * the row's default animation resolves to instant (`animationPreset=\"none\"`\n * or the OS prefers-reduced-motion setting).\n * @default true\n */\n peekOnHandleTap?: boolean\n /** Fires when the settled position changes. */\n onRevealChange?: (position: RevealPosition) => void\n onScroll?: (event: UIEvent<HTMLElement>) => void\n /** Resets to closed; default true. */\n resetWhenDisabled?: boolean\n disabled?: boolean\n /**\n * When true, snaps back to the closed position (e.g. row became active/selected\n * elsewhere in the list).\n */\n isActive?: boolean\n className?: string\n style?: CSSProperties\n /**\n * Default animation preset for close/reveal animations when action buttons are clicked.\n * @default 'quick'\n */\n animationPreset?: AnimationPreset\n /**\n * Custom animation configuration overriding the preset.\n */\n animationConfig?: AnimationConfig\n}\n","import {\n REVEAL_MODE,\n REVEAL_POSITION,\n type RevealMode,\n type RevealPosition,\n} from './types'\n\n/**\n * Map horizontal scroll position to a logical \"revealed\" state.\n * `wL` / `wR` are the fixed action column widths; `maxScroll` is\n * `Math.max(0, scrollWidth - clientWidth)`.\n */\nexport function getRevealFromScroll(\n scrollLeft: number,\n maxScroll: number,\n wL: number,\n wR: number,\n mode: RevealMode,\n): RevealPosition {\n if (mode === REVEAL_MODE.right) {\n if (maxScroll <= 0) return REVEAL_POSITION.center\n return scrollLeft < wR / 2 ? REVEAL_POSITION.center : REVEAL_POSITION.right\n }\n if (mode === REVEAL_MODE.left) {\n if (maxScroll <= 0) return REVEAL_POSITION.center\n return scrollLeft < wL / 2 ? REVEAL_POSITION.left : REVEAL_POSITION.center\n }\n if (maxScroll <= 0) return REVEAL_POSITION.center\n if (scrollLeft < wL / 2) return REVEAL_POSITION.left\n if (scrollLeft > maxScroll - wR / 2) return REVEAL_POSITION.right\n return REVEAL_POSITION.center\n}\n\n/** \"Closed\" / resting scrollLeft for a mode (main panel only). */\nexport function getScrollClosed(\n wL: number,\n _wR: number,\n _maxScroll: number,\n mode: RevealMode,\n): number {\n if (mode === REVEAL_MODE.right) return 0\n return wL\n}\n","'use client'\n\nimport type {\n CSSProperties,\n FocusEvent,\n ForwardedRef,\n MouseEvent,\n UIEvent,\n} from 'react'\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react'\n\nimport { DefaultHandleIcon } from './DefaultHandleIcon'\nimport { getRevealFromScroll, getScrollClosed } from './getRevealFromScroll'\nimport {\n ANIMATION_PRESET,\n ANIMATION_PRESETS,\n type AnimationConfig,\n type AnimationPreset,\n REVEAL_HANDLE_POSITION,\n REVEAL_MODE,\n REVEAL_POSITION,\n type RevealHandlePosition,\n type RevealMode,\n type RevealPosition,\n type RevealRowClassNames,\n type RevealRowHandle,\n type RevealRowProps,\n} from './types'\n\nfunction cx(...parts: (string | undefined)[]) {\n return parts.filter(Boolean).join(' ')\n}\n\nfunction getMaxScroll(el: HTMLElement) {\n return Math.max(0, el.scrollWidth - el.clientWidth)\n}\n\nfunction resolveMode(\n left: RevealRowProps['left'],\n right: RevealRowProps['right'],\n mode: RevealMode | undefined,\n): RevealMode {\n if (mode) return mode\n if (left != null && right != null) return REVEAL_MODE.both\n if (left != null) return REVEAL_MODE.left\n return REVEAL_MODE.right\n}\n\nfunction prefersReducedMotion(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n )\n}\n\nfunction resolveAnimationConfig(\n animated: boolean | AnimationPreset | AnimationConfig | undefined,\n defaultPreset: AnimationPreset,\n customConfig?: AnimationConfig,\n): AnimationConfig {\n let config: AnimationConfig\n // An explicit AnimationConfig object is an intentional override and is not\n // reduced; booleans and presets defer to the OS reduced-motion setting.\n let explicit = false\n\n if (animated === false) {\n config = ANIMATION_PRESETS[ANIMATION_PRESET.none]\n } else if (animated === true || animated === undefined) {\n if (customConfig) {\n config = customConfig\n explicit = true\n } else {\n config = ANIMATION_PRESETS[defaultPreset]\n }\n } else if (typeof animated === 'string') {\n config = ANIMATION_PRESETS[animated]\n } else {\n config = animated\n explicit = true\n }\n\n if (!explicit && prefersReducedMotion()) {\n return { ...config, duration: 0 }\n }\n\n // Validate and clamp duration to be >= 0\n return {\n ...config,\n duration: Math.max(\n 0,\n Number.isFinite(config.duration) ? config.duration : 0,\n ),\n }\n}\n\nconst SCROLL_REVEAL_DEBOUNCE_MS = 64\nconst restEpsilon = 2\n\n// Handle-tap peek: how far into the action column to scroll (kept well under\n// the wR/2 snap threshold) and the out/return micro-animation timings.\nconst PEEK_FRACTION = 0.35\nconst PEEK_OUT_ANIMATION: AnimationConfig = {\n duration: 120,\n easing: 'ease-out',\n}\nconst PEEK_RETURN_ANIMATION: AnimationConfig = {\n duration: 180,\n easing: 'ease-out',\n}\n// Past the return animation's finalize fallback (duration + 100ms), so snap is\n// restored and trailing scroll events have flushed before suppression clears.\nconst PEEK_SETTLE_BUFFER_MS = 120\n\nconst rootScrollStyle: CSSProperties = {\n display: 'grid',\n overflowX: 'auto',\n // `overflow-x: auto` would otherwise force `overflow-y` to compute to\n // `auto` — pin it so rows only ever scroll on one axis.\n overflowY: 'hidden',\n scrollSnapType: 'x mandatory',\n scrollbarWidth: 'none',\n WebkitOverflowScrolling: 'touch',\n overscrollBehaviorX: 'contain',\n touchAction: 'pan-x pan-y',\n}\n\nconst rootScrollStyleDisabled: CSSProperties = {\n ...rootScrollStyle,\n overflowX: 'hidden',\n touchAction: 'pan-y',\n}\n\nconst snapStart: CSSProperties = { scrollSnapAlign: 'start' }\nconst snapEnd: CSSProperties = { scrollSnapAlign: 'end' }\n\ntype InnerProps = RevealRowProps & {\n forwardedRef: ForwardedRef<RevealRowHandle>\n}\n\nfunction RevealRowInner({\n children,\n left,\n right,\n as: Element = 'div',\n mode: modeProp,\n actionWidthLeft: wLIn,\n actionWidthRight: wRIn,\n classNames = {} as RevealRowClassNames,\n showHandle = true,\n handle: handleOverride,\n handlePosition: handlePositionProp,\n handleTitle = 'Drag horizontally to show actions',\n handleAriaLabel = 'Drag horizontally to show actions',\n peekOnHandleTap = true,\n onRevealChange,\n onScroll: onScrollProp,\n resetWhenDisabled = true,\n disabled = false,\n isActive = false,\n className,\n style,\n animationPreset = ANIMATION_PRESET.quick,\n animationConfig,\n forwardedRef,\n}: InnerProps) {\n const mode = resolveMode(left, right, modeProp)\n const hasL = mode === REVEAL_MODE.left || mode === REVEAL_MODE.both\n const hasR = mode === REVEAL_MODE.right || mode === REVEAL_MODE.both\n\n const handlePosition: RevealHandlePosition =\n handlePositionProp ??\n (mode === REVEAL_MODE.left\n ? REVEAL_HANDLE_POSITION.start\n : REVEAL_HANDLE_POSITION.end)\n\n const containerRef = useRef<HTMLElement>(null)\n const leftRef = useRef<HTMLDivElement>(null)\n const rightRef = useRef<HTMLDivElement>(null)\n const handleStripRef = useRef<HTMLDivElement>(null)\n const peekTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const lastEmitted = useRef<RevealPosition | null>(null)\n const swipedRef = useRef(false)\n const focusRevealedRef = useRef(false)\n const [settledPosition, setSettledPosition] = useState<RevealPosition>(\n REVEAL_POSITION.center,\n )\n\n // Effective action-column widths. With an explicit prop this is a constant;\n // without one the column is content-sized (minmax(88px, max-content) track)\n // and the rendered width is read live — only ever inside handlers that\n // already read layout, so no extra reflow cost. `|| 88` covers pre-mount\n // and environments without layout.\n const getWL = useCallback(\n () => (hasL ? (wLIn ?? (leftRef.current?.offsetWidth || 88)) : 0),\n [hasL, wLIn],\n )\n const getWR = useCallback(\n () => (hasR ? (wRIn ?? (rightRef.current?.offsetWidth || 88)) : 0),\n [hasR, wRIn],\n )\n const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n const hasAppliedInitialScroll = useRef(false)\n const isAnimatingRef = useRef(false)\n const rafIdRef = useRef<number | null>(null)\n const settleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const finalizeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const originalSnapRef = useRef('')\n\n const readPosition = useCallback((): RevealPosition => {\n const el = containerRef.current\n if (!el) return REVEAL_POSITION.center\n return getRevealFromScroll(\n el.scrollLeft,\n getMaxScroll(el),\n getWL(),\n getWR(),\n mode,\n )\n }, [getWL, getWR, mode])\n\n const emitReveal = useCallback(\n (position: RevealPosition) => {\n setSettledPosition(position)\n if (lastEmitted.current === position) return\n lastEmitted.current = position\n onRevealChange?.(position)\n },\n [onRevealChange],\n )\n\n const scrollToClosed = useCallback(() => {\n const el = containerRef.current\n if (!el) return\n const m = getMaxScroll(el)\n const closed = getScrollClosed(getWL(), getWR(), m, mode)\n\n // For immediate scroll, we can use the default behavior\n // CSS scroll snap will handle the final positioning\n el.scrollLeft = closed\n }, [getWL, getWR, mode])\n\n const scrollToPosition = useCallback(\n (targetScrollLeft: number, animationOptions: AnimationConfig) => {\n const el = containerRef.current\n if (!el) return\n\n const { duration, easing } = animationOptions\n\n if (duration === 0) {\n el.scrollLeft = targetScrollLeft\n return\n }\n\n // Cancel any existing animation\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n rafIdRef.current = null\n }\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n settleTimerRef.current = null\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n finalizeTimerRef.current = null\n }\n\n // Disable scroll snap during animation. Only capture the original value\n // when no animation is in flight — mid-animation it reads back our own\n // 'none' and would get restored permanently.\n if (!isAnimatingRef.current) {\n originalSnapRef.current = el.style.scrollSnapType\n }\n isAnimatingRef.current = true\n el.style.scrollSnapType = 'none'\n\n const finish = () => {\n el.scrollLeft = targetScrollLeft\n el.style.scrollSnapType = originalSnapRef.current || 'x mandatory'\n isAnimatingRef.current = false\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n rafIdRef.current = null\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n finalizeTimerRef.current = null\n }\n }\n\n // rAF is frozen on hidden/occluded pages — guarantee the animation\n // completes (and snap is restored) via a timer fallback.\n finalizeTimerRef.current = setTimeout(finish, duration + 100)\n\n const startScrollLeft = el.scrollLeft\n const distance = targetScrollLeft - startScrollLeft\n const startTime = performance.now()\n\n const animate = (currentTime: number) => {\n const elapsed = currentTime - startTime\n const progress = Math.min(elapsed / duration, 1)\n\n let easedProgress = progress\n if (easing === 'ease-out') {\n easedProgress = 1 - (1 - progress) ** 2\n } else if (easing === 'ease-in-out') {\n easedProgress =\n progress < 0.5\n ? 2 * progress * progress\n : 1 - (-2 * progress + 2) ** 2 / 2\n } else if (easing.startsWith('cubic-bezier')) {\n // For the bounce effect, we'll use a simplified approximation\n easedProgress = progress * progress * (3 - 2 * progress)\n if (easing.includes('-0.55')) {\n // Bounce effect approximation\n easedProgress =\n progress < 0.5\n ? 4 * progress * progress * progress\n : 1 - (-2 * progress + 2) ** 3 / 2\n // Add overshoot for bounce\n if (progress > 0.7 && progress < 1) {\n easedProgress +=\n Math.sin((progress - 0.7) * Math.PI * 10) * 0.1 * (1 - progress)\n }\n }\n }\n\n el.scrollLeft = startScrollLeft + distance * easedProgress\n\n if (progress < 1) {\n rafIdRef.current = requestAnimationFrame(animate)\n } else {\n rafIdRef.current = null\n finish()\n }\n }\n\n rafIdRef.current = requestAnimationFrame(animate)\n },\n [],\n )\n\n // Briefly scroll partway into an action column and spring back, teaching\n // the swipe affordance without committing to a revealed state. Returns\n // whether a peek actually started, so the caller can consume the click.\n const peekActions = useCallback((): boolean => {\n const el = containerRef.current\n if (!el || disabled) return false\n if (isAnimatingRef.current || peekTimerRef.current !== null) return false\n const defaultConfig = resolveAnimationConfig(\n undefined,\n animationPreset,\n animationConfig,\n )\n if (defaultConfig.duration === 0) return false\n\n const m = getMaxScroll(el)\n const wL = getWL()\n const wR = getWR()\n const closed = getScrollClosed(wL, wR, m, mode)\n if (Math.abs(el.scrollLeft - closed) > restEpsilon) return false\n\n // Peek toward the handle's side when that side has actions, otherwise\n // toward whichever side exists.\n const peekRight =\n handlePosition === REVEAL_HANDLE_POSITION.end ? hasR : !hasL\n const target = peekRight\n ? Math.min(m, closed + wR * PEEK_FRACTION)\n : Math.max(0, closed - wL * PEEK_FRACTION)\n if (target === closed) return false\n\n scrollToPosition(target, PEEK_OUT_ANIMATION)\n peekTimerRef.current = setTimeout(() => {\n scrollToPosition(closed, PEEK_RETURN_ANIMATION)\n peekTimerRef.current = setTimeout(() => {\n peekTimerRef.current = null\n // The peek's own scrolling flags the row as swiped; the row is back\n // at rest, so don't let that eat the user's next click.\n swipedRef.current = false\n }, PEEK_RETURN_ANIMATION.duration + PEEK_SETTLE_BUFFER_MS)\n }, PEEK_OUT_ANIMATION.duration)\n return true\n }, [\n animationConfig,\n animationPreset,\n disabled,\n getWL,\n getWR,\n handlePosition,\n hasL,\n hasR,\n mode,\n scrollToPosition,\n ])\n\n const closeRow = useCallback(\n (animated?: boolean | AnimationPreset | AnimationConfig) => {\n const el = containerRef.current\n if (!el) return\n\n const m = getMaxScroll(el)\n const closed = getScrollClosed(getWL(), getWR(), m, mode)\n const animConfig = resolveAnimationConfig(\n animated,\n animationPreset,\n animationConfig,\n )\n\n scrollToPosition(closed, animConfig)\n\n // Update position after animation or immediately if no animation\n const delay = animConfig.duration > 0 ? animConfig.duration : 0\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n settleTimerRef.current = setTimeout(() => {\n emitReveal(readPosition())\n settleTimerRef.current = null\n }, delay)\n },\n [\n animationConfig,\n animationPreset,\n emitReveal,\n getWL,\n getWR,\n mode,\n readPosition,\n scrollToPosition,\n ],\n )\n\n const revealRow = useCallback(\n (\n position: RevealPosition,\n animated?: boolean | AnimationPreset | AnimationConfig,\n ) => {\n const el = containerRef.current\n if (!el) return\n const max = getMaxScroll(el)\n const wL = getWL()\n const wR = getWR()\n\n let targetScroll: number\n if (position === REVEAL_POSITION.center) {\n targetScroll = getScrollClosed(wL, wR, max, mode)\n } else if (\n position === REVEAL_POSITION.left &&\n (mode === REVEAL_MODE.left || mode === REVEAL_MODE.both)\n ) {\n targetScroll = 0\n } else if (\n position === REVEAL_POSITION.right &&\n (mode === REVEAL_MODE.right || mode === REVEAL_MODE.both)\n ) {\n targetScroll = max\n } else {\n return\n }\n\n const animConfig = resolveAnimationConfig(\n animated,\n animationPreset,\n animationConfig,\n )\n scrollToPosition(targetScroll, animConfig)\n\n // Update position after animation or immediately if no animation\n const delay = animConfig.duration > 0 ? animConfig.duration : 0\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n settleTimerRef.current = setTimeout(() => {\n emitReveal(getRevealFromScroll(targetScroll, max, wL, wR, mode))\n settleTimerRef.current = null\n }, delay)\n },\n [\n animationConfig,\n animationPreset,\n emitReveal,\n getWL,\n getWR,\n mode,\n scrollToPosition,\n ],\n )\n\n useImperativeHandle(\n forwardedRef,\n () => ({ close: closeRow, reveal: revealRow }),\n [closeRow, revealRow],\n )\n\n // Keyboard support: tabbing into an off-screen action column snaps it\n // cleanly into view (instead of the browser's un-snapped scroll-into-view),\n // and a focus-initiated reveal closes again once focus leaves the row.\n // Swipe-opened rows are untouched by focus loss.\n const handleRootFocus = useCallback(\n (e: FocusEvent<HTMLElement>) => {\n const t = e.target as Node | null\n if (!t) return\n if (leftRef.current?.contains(t)) {\n focusRevealedRef.current = true\n revealRow(REVEAL_POSITION.left)\n } else if (rightRef.current?.contains(t)) {\n focusRevealedRef.current = true\n revealRow(REVEAL_POSITION.right)\n }\n },\n [revealRow],\n )\n\n const handleRootBlur = useCallback(\n (e: FocusEvent<HTMLElement>) => {\n if (!focusRevealedRef.current) return\n const next = e.relatedTarget as Node | null\n if (next && containerRef.current?.contains(next)) return\n focusRevealedRef.current = false\n closeRow()\n },\n [closeRow],\n )\n\n useLayoutEffect(() => {\n if (mode === REVEAL_MODE.right) {\n return\n }\n const el = containerRef.current\n if (!el) return\n if (!hasAppliedInitialScroll.current) {\n el.scrollLeft = getWL()\n hasAppliedInitialScroll.current = true\n }\n }, [mode, getWL])\n\n useEffect(() => {\n if (disabled && resetWhenDisabled) {\n hasAppliedInitialScroll.current = true\n scrollToClosed()\n emitReveal(readPosition())\n }\n }, [disabled, emitReveal, readPosition, resetWhenDisabled, scrollToClosed])\n\n useEffect(() => {\n if (isActive) {\n hasAppliedInitialScroll.current = true\n scrollToClosed()\n emitReveal(readPosition())\n }\n }, [emitReveal, isActive, readPosition, scrollToClosed])\n\n useEffect(\n () => () => {\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current)\n }\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n }\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n }\n if (peekTimerRef.current !== null) {\n clearTimeout(peekTimerRef.current)\n }\n },\n [],\n )\n\n const handleScroll = useCallback(\n (e: UIEvent<HTMLElement>) => {\n onScrollProp?.(e)\n const el = containerRef.current\n if (!el) return\n const m = getMaxScroll(el)\n const wL = getWL()\n const wR = getWR()\n const pos = getRevealFromScroll(el.scrollLeft, m, wL, wR, mode)\n const closed = getScrollClosed(wL, wR, m, mode)\n if (Math.abs(el.scrollLeft - closed) > restEpsilon) {\n swipedRef.current = true\n }\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current)\n }\n debounceTimer.current = setTimeout(() => {\n debounceTimer.current = null\n emitReveal(pos)\n }, SCROLL_REVEAL_DEBOUNCE_MS)\n },\n [emitReveal, getWL, getWR, mode, onScrollProp],\n )\n\n const onClickCapture = useCallback(\n (e: MouseEvent) => {\n const t = e.target as Node | null\n if (t) {\n if (leftRef.current?.contains(t) || rightRef.current?.contains(t)) {\n return\n }\n }\n if (swipedRef.current) {\n e.preventDefault()\n e.stopPropagation()\n swipedRef.current = false\n return\n }\n if (\n peekOnHandleTap &&\n t &&\n handleStripRef.current?.contains(t) &&\n peekActions()\n ) {\n // The tap was aimed at the handle, not the row content.\n e.preventDefault()\n e.stopPropagation()\n }\n },\n [peekActions, peekOnHandleTap],\n )\n\n // `100%` for the main track (not `1fr`) so total row width > viewport: otherwise both\n // columns can shrink to fit with no overflow and the action stays visible.\n // Without an explicit width the column is content-sized via a `max-content`\n // track — `minmax(88px, max-content)` would never grow, because the `100%`\n // main track leaves no free space for minmax growth. The 88px floor for\n // stretchy content lives on the column element's `minWidth` instead, which\n // floors its sizing contribution to the track.\n const trackL = wLIn != null ? `${wLIn}px` : 'max-content'\n const trackR = wRIn != null ? `${wRIn}px` : 'max-content'\n const gridTemplateColumns =\n mode === REVEAL_MODE.right\n ? `100% ${trackR}`\n : mode === REVEAL_MODE.left\n ? `${trackL} 100%`\n : `${trackL} 100% ${trackR}`\n\n const handleContent = showHandle ? (\n handleOverride !== undefined ? (\n handleOverride\n ) : (\n <>\n <span\n className=\"sr-only\"\n style={{\n position: 'absolute',\n width: 1,\n height: 1,\n padding: 0,\n margin: -1,\n overflow: 'hidden',\n clip: 'rect(0,0,0,0)',\n border: 0,\n }}\n >\n {handleAriaLabel}\n </span>\n <span className={classNames.handleIcon} aria-hidden>\n <DefaultHandleIcon />\n </span>\n </>\n )\n ) : null\n\n const handleStrip = showHandle ? (\n <div\n ref={handleStripRef}\n role=\"presentation\"\n className={classNames.handleContainer}\n data-reveal-row-handle\n style={{\n flexShrink: 0,\n alignSelf: 'stretch',\n display: 'flex',\n alignItems: 'center',\n }}\n title={handleOverride === undefined ? handleTitle : undefined}\n >\n {handleContent}\n </div>\n ) : null\n\n const mainColumn = (\n <div\n className={classNames.main}\n data-reveal-row-main\n style={{\n ...snapStart,\n minWidth: 0,\n width: '100%',\n maxWidth: '100%',\n boxSizing: 'border-box',\n }}\n >\n <div\n className={classNames.mainInner}\n style={{\n display: 'flex',\n minWidth: 0,\n width: '100%',\n alignItems: 'flex-start',\n }}\n >\n {handlePosition === REVEAL_HANDLE_POSITION.start && handleStrip}\n <div style={{ minWidth: 0, flex: 1, flexBasis: 0 }}>{children}</div>\n {handlePosition === REVEAL_HANDLE_POSITION.end && handleStrip}\n </div>\n </div>\n )\n\n return (\n <Element\n // biome-ignore lint/suspicious/noExplicitAny: Required for polymorphic ref compatibility\n ref={containerRef as any}\n data-reveal-mode={mode}\n data-reveal-position={settledPosition}\n className={cx(classNames.root, className)}\n onScroll={handleScroll}\n onClickCapture={onClickCapture}\n onFocus={handleRootFocus}\n onBlur={handleRootBlur}\n style={{\n ...(disabled ? rootScrollStyleDisabled : rootScrollStyle),\n ...style,\n gridTemplateColumns,\n }}\n >\n {hasL ? (\n <div\n ref={leftRef}\n className={classNames.left}\n data-reveal-row-left\n style={{\n ...snapStart,\n ...(wLIn != null\n ? { minWidth: 0, width: wLIn }\n : { minWidth: 'var(--reveal-row-action-min-width, 88px)' }),\n }}\n >\n {left}\n </div>\n ) : null}\n {mainColumn}\n {hasR ? (\n <div\n ref={rightRef}\n className={classNames.right}\n data-reveal-row-right\n style={{\n ...snapEnd,\n ...(wRIn != null\n ? { minWidth: 0, width: wRIn }\n : { minWidth: 'var(--reveal-row-action-min-width, 88px)' }),\n }}\n >\n {right}\n </div>\n ) : null}\n </Element>\n )\n}\n\nexport const RevealRow = forwardRef<RevealRowHandle, RevealRowProps>(\n function RevealRow(props, ref) {\n return <RevealRowInner {...props} forwardedRef={ref} />\n },\n)\n","/** Minimal 6-dot grip, no icon library dependency. */\nexport function DefaultHandleIcon() {\n return (\n <svg\n width={16}\n height={16}\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n aria-hidden\n >\n <title>Drag handle</title>\n <circle cx=\"6\" cy=\"4\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"4\" r=\"1.2\" />\n <circle cx=\"6\" cy=\"8\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"8\" r=\"1.2\" />\n <circle cx=\"6\" cy=\"12\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"12\" r=\"1.2\" />\n </svg>\n )\n}\n"],"mappings":"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","names":["import_jsx_runtime","RevealRow"]}
package/dist/index.mjs CHANGED
@@ -138,6 +138,16 @@ function resolveAnimationConfig(animated, defaultPreset, customConfig) {
138
138
  }
139
139
  var SCROLL_REVEAL_DEBOUNCE_MS = 64;
140
140
  var restEpsilon = 2;
141
+ var PEEK_FRACTION = 0.35;
142
+ var PEEK_OUT_ANIMATION = {
143
+ duration: 120,
144
+ easing: "ease-out"
145
+ };
146
+ var PEEK_RETURN_ANIMATION = {
147
+ duration: 180,
148
+ easing: "ease-out"
149
+ };
150
+ var PEEK_SETTLE_BUFFER_MS = 120;
141
151
  var rootScrollStyle = {
142
152
  display: "grid",
143
153
  overflowX: "auto",
@@ -171,6 +181,7 @@ function RevealRowInner({
171
181
  handlePosition: handlePositionProp,
172
182
  handleTitle = "Drag horizontally to show actions",
173
183
  handleAriaLabel = "Drag horizontally to show actions",
184
+ peekOnHandleTap = true,
174
185
  onRevealChange,
175
186
  onScroll: onScrollProp,
176
187
  resetWhenDisabled = true,
@@ -189,6 +200,8 @@ function RevealRowInner({
189
200
  const containerRef = useRef(null);
190
201
  const leftRef = useRef(null);
191
202
  const rightRef = useRef(null);
203
+ const handleStripRef = useRef(null);
204
+ const peekTimerRef = useRef(null);
192
205
  const lastEmitted = useRef(null);
193
206
  const swipedRef = useRef(false);
194
207
  const focusRevealedRef = useRef(false);
@@ -309,6 +322,45 @@ function RevealRowInner({
309
322
  },
310
323
  []
311
324
  );
325
+ const peekActions = useCallback(() => {
326
+ const el = containerRef.current;
327
+ if (!el || disabled) return false;
328
+ if (isAnimatingRef.current || peekTimerRef.current !== null) return false;
329
+ const defaultConfig = resolveAnimationConfig(
330
+ void 0,
331
+ animationPreset,
332
+ animationConfig
333
+ );
334
+ if (defaultConfig.duration === 0) return false;
335
+ const m = getMaxScroll(el);
336
+ const wL = getWL();
337
+ const wR = getWR();
338
+ const closed = getScrollClosed(wL, wR, m, mode);
339
+ if (Math.abs(el.scrollLeft - closed) > restEpsilon) return false;
340
+ const peekRight = handlePosition === REVEAL_HANDLE_POSITION.end ? hasR : !hasL;
341
+ const target = peekRight ? Math.min(m, closed + wR * PEEK_FRACTION) : Math.max(0, closed - wL * PEEK_FRACTION);
342
+ if (target === closed) return false;
343
+ scrollToPosition(target, PEEK_OUT_ANIMATION);
344
+ peekTimerRef.current = setTimeout(() => {
345
+ scrollToPosition(closed, PEEK_RETURN_ANIMATION);
346
+ peekTimerRef.current = setTimeout(() => {
347
+ peekTimerRef.current = null;
348
+ swipedRef.current = false;
349
+ }, PEEK_RETURN_ANIMATION.duration + PEEK_SETTLE_BUFFER_MS);
350
+ }, PEEK_OUT_ANIMATION.duration);
351
+ return true;
352
+ }, [
353
+ animationConfig,
354
+ animationPreset,
355
+ disabled,
356
+ getWL,
357
+ getWR,
358
+ handlePosition,
359
+ hasL,
360
+ hasR,
361
+ mode,
362
+ scrollToPosition
363
+ ]);
312
364
  const closeRow = useCallback(
313
365
  (animated) => {
314
366
  const el = containerRef.current;
@@ -451,6 +503,9 @@ function RevealRowInner({
451
503
  if (finalizeTimerRef.current !== null) {
452
504
  clearTimeout(finalizeTimerRef.current);
453
505
  }
506
+ if (peekTimerRef.current !== null) {
507
+ clearTimeout(peekTimerRef.current);
508
+ }
454
509
  },
455
510
  []
456
511
  );
@@ -477,19 +532,27 @@ function RevealRowInner({
477
532
  },
478
533
  [emitReveal, getWL, getWR, mode, onScrollProp]
479
534
  );
480
- const onClickCapture = useCallback((e) => {
481
- const t = e.target;
482
- if (t) {
483
- if (leftRef.current?.contains(t) || rightRef.current?.contains(t)) {
535
+ const onClickCapture = useCallback(
536
+ (e) => {
537
+ const t = e.target;
538
+ if (t) {
539
+ if (leftRef.current?.contains(t) || rightRef.current?.contains(t)) {
540
+ return;
541
+ }
542
+ }
543
+ if (swipedRef.current) {
544
+ e.preventDefault();
545
+ e.stopPropagation();
546
+ swipedRef.current = false;
484
547
  return;
485
548
  }
486
- }
487
- if (swipedRef.current) {
488
- e.preventDefault();
489
- e.stopPropagation();
490
- swipedRef.current = false;
491
- }
492
- }, []);
549
+ if (peekOnHandleTap && t && handleStripRef.current?.contains(t) && peekActions()) {
550
+ e.preventDefault();
551
+ e.stopPropagation();
552
+ }
553
+ },
554
+ [peekActions, peekOnHandleTap]
555
+ );
493
556
  const trackL = wLIn != null ? `${wLIn}px` : "max-content";
494
557
  const trackR = wRIn != null ? `${wRIn}px` : "max-content";
495
558
  const gridTemplateColumns = mode === REVEAL_MODE.right ? `100% ${trackR}` : mode === REVEAL_MODE.left ? `${trackL} 100%` : `${trackL} 100% ${trackR}`;
@@ -516,6 +579,7 @@ function RevealRowInner({
516
579
  const handleStrip = showHandle ? /* @__PURE__ */ jsx2(
517
580
  "div",
518
581
  {
582
+ ref: handleStripRef,
519
583
  role: "presentation",
520
584
  className: classNames.handleContainer,
521
585
  "data-reveal-row-handle": true,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/getRevealFromScroll.ts","../src/RevealRow.tsx","../src/DefaultHandleIcon.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode, UIEvent } from 'react'\n\nexport const REVEAL_MODE = {\n left: 'left',\n right: 'right',\n both: 'both',\n} as const\n\nexport type RevealMode = (typeof REVEAL_MODE)[keyof typeof REVEAL_MODE]\n\nexport const REVEAL_POSITION = {\n left: 'left',\n center: 'center',\n right: 'right',\n} as const\n\nexport type RevealPosition =\n (typeof REVEAL_POSITION)[keyof typeof REVEAL_POSITION]\n\nexport const REVEAL_HANDLE_POSITION = {\n start: 'start',\n end: 'end',\n} as const\n\nexport type RevealHandlePosition =\n (typeof REVEAL_HANDLE_POSITION)[keyof typeof REVEAL_HANDLE_POSITION]\n\nexport const REVEAL_ROW_ELEMENTS = {\n div: 'div',\n section: 'section',\n article: 'article',\n main: 'main',\n aside: 'aside',\n header: 'header',\n footer: 'footer',\n nav: 'nav',\n li: 'li',\n} as const\n\nexport type RevealRowElement =\n (typeof REVEAL_ROW_ELEMENTS)[keyof typeof REVEAL_ROW_ELEMENTS]\n\nexport const ANIMATION_PRESET = {\n none: 'none',\n quick: 'quick',\n smooth: 'smooth',\n} as const\n\nexport type AnimationPreset =\n (typeof ANIMATION_PRESET)[keyof typeof ANIMATION_PRESET]\n\nexport type AnimationConfig = {\n duration: number\n easing: string\n}\n\nexport const ANIMATION_PRESETS: Record<AnimationPreset, AnimationConfig> = {\n [ANIMATION_PRESET.none]: { duration: 0, easing: 'linear' },\n [ANIMATION_PRESET.quick]: { duration: 200, easing: 'ease-out' },\n [ANIMATION_PRESET.smooth]: { duration: 400, easing: 'ease-in-out' },\n}\n\nexport type RevealRowClassNames = {\n root?: string\n main?: string\n mainInner?: string\n left?: string\n right?: string\n handleContainer?: string\n handleIcon?: string\n}\n\nexport type RevealRowHandle = {\n close: (animated?: boolean | AnimationPreset | AnimationConfig) => void\n reveal: (\n position: RevealPosition,\n animated?: boolean | AnimationPreset | AnimationConfig,\n ) => void\n}\n\nexport type RevealRowProps = {\n /** Primary row content (e.g. title, subtitle). */\n children: ReactNode\n /** Optional leading action column (e.g. delete). Omitted in `right` mode. */\n left?: ReactNode\n /**\n * Trailing action column (e.g. add). Omitted in `left` mode.\n */\n right?: ReactNode\n /**\n * The HTML element to use for the root container.\n * @default 'div'\n */\n as?: RevealRowElement\n /**\n * If both `left` and `right` are set, defaults to `both`. If only one side,\n * mode is derived unless overridden.\n */\n mode?: RevealMode\n /**\n * Fixed width (px) of the left action column. Omit to size the column to\n * its content with an 88px floor (`minmax(88px, max-content)`).\n */\n actionWidthLeft?: number\n /**\n * Fixed width (px) of the right action column. Omit to size the column to\n * its content with an 88px floor (`minmax(88px, max-content)`).\n */\n actionWidthRight?: number\n classNames?: RevealRowClassNames\n /** @default true */\n showHandle?: boolean\n /** Replaces the built-in drag affordance. */\n handle?: ReactNode\n /**\n * Where the handle sits in the main row. Default: `start` in `left` mode,\n * `end` otherwise.\n */\n handlePosition?: RevealHandlePosition\n handleTitle?: string\n /** Shown in screen-reader text when using the default drag handle. */\n handleAriaLabel?: string\n /** Fires when the settled position changes. */\n onRevealChange?: (position: RevealPosition) => void\n onScroll?: (event: UIEvent<HTMLElement>) => void\n /** Resets to closed; default true. */\n resetWhenDisabled?: boolean\n disabled?: boolean\n /**\n * When true, snaps back to the closed position (e.g. row became active/selected\n * elsewhere in the list).\n */\n isActive?: boolean\n className?: string\n style?: CSSProperties\n /**\n * Default animation preset for close/reveal animations when action buttons are clicked.\n * @default 'quick'\n */\n animationPreset?: AnimationPreset\n /**\n * Custom animation configuration overriding the preset.\n */\n animationConfig?: AnimationConfig\n}\n","import {\n REVEAL_MODE,\n REVEAL_POSITION,\n type RevealMode,\n type RevealPosition,\n} from './types'\n\n/**\n * Map horizontal scroll position to a logical \"revealed\" state.\n * `wL` / `wR` are the fixed action column widths; `maxScroll` is\n * `Math.max(0, scrollWidth - clientWidth)`.\n */\nexport function getRevealFromScroll(\n scrollLeft: number,\n maxScroll: number,\n wL: number,\n wR: number,\n mode: RevealMode,\n): RevealPosition {\n if (mode === REVEAL_MODE.right) {\n if (maxScroll <= 0) return REVEAL_POSITION.center\n return scrollLeft < wR / 2 ? REVEAL_POSITION.center : REVEAL_POSITION.right\n }\n if (mode === REVEAL_MODE.left) {\n if (maxScroll <= 0) return REVEAL_POSITION.center\n return scrollLeft < wL / 2 ? REVEAL_POSITION.left : REVEAL_POSITION.center\n }\n if (maxScroll <= 0) return REVEAL_POSITION.center\n if (scrollLeft < wL / 2) return REVEAL_POSITION.left\n if (scrollLeft > maxScroll - wR / 2) return REVEAL_POSITION.right\n return REVEAL_POSITION.center\n}\n\n/** \"Closed\" / resting scrollLeft for a mode (main panel only). */\nexport function getScrollClosed(\n wL: number,\n _wR: number,\n _maxScroll: number,\n mode: RevealMode,\n): number {\n if (mode === REVEAL_MODE.right) return 0\n return wL\n}\n","'use client'\n\nimport type {\n CSSProperties,\n FocusEvent,\n ForwardedRef,\n MouseEvent,\n UIEvent,\n} from 'react'\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react'\n\nimport { DefaultHandleIcon } from './DefaultHandleIcon'\nimport { getRevealFromScroll, getScrollClosed } from './getRevealFromScroll'\nimport {\n ANIMATION_PRESET,\n ANIMATION_PRESETS,\n type AnimationConfig,\n type AnimationPreset,\n REVEAL_HANDLE_POSITION,\n REVEAL_MODE,\n REVEAL_POSITION,\n type RevealHandlePosition,\n type RevealMode,\n type RevealPosition,\n type RevealRowClassNames,\n type RevealRowHandle,\n type RevealRowProps,\n} from './types'\n\nfunction cx(...parts: (string | undefined)[]) {\n return parts.filter(Boolean).join(' ')\n}\n\nfunction getMaxScroll(el: HTMLElement) {\n return Math.max(0, el.scrollWidth - el.clientWidth)\n}\n\nfunction resolveMode(\n left: RevealRowProps['left'],\n right: RevealRowProps['right'],\n mode: RevealMode | undefined,\n): RevealMode {\n if (mode) return mode\n if (left != null && right != null) return REVEAL_MODE.both\n if (left != null) return REVEAL_MODE.left\n return REVEAL_MODE.right\n}\n\nfunction prefersReducedMotion(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n )\n}\n\nfunction resolveAnimationConfig(\n animated: boolean | AnimationPreset | AnimationConfig | undefined,\n defaultPreset: AnimationPreset,\n customConfig?: AnimationConfig,\n): AnimationConfig {\n let config: AnimationConfig\n // An explicit AnimationConfig object is an intentional override and is not\n // reduced; booleans and presets defer to the OS reduced-motion setting.\n let explicit = false\n\n if (animated === false) {\n config = ANIMATION_PRESETS[ANIMATION_PRESET.none]\n } else if (animated === true || animated === undefined) {\n if (customConfig) {\n config = customConfig\n explicit = true\n } else {\n config = ANIMATION_PRESETS[defaultPreset]\n }\n } else if (typeof animated === 'string') {\n config = ANIMATION_PRESETS[animated]\n } else {\n config = animated\n explicit = true\n }\n\n if (!explicit && prefersReducedMotion()) {\n return { ...config, duration: 0 }\n }\n\n // Validate and clamp duration to be >= 0\n return {\n ...config,\n duration: Math.max(\n 0,\n Number.isFinite(config.duration) ? config.duration : 0,\n ),\n }\n}\n\nconst SCROLL_REVEAL_DEBOUNCE_MS = 64\nconst restEpsilon = 2\n\nconst rootScrollStyle: CSSProperties = {\n display: 'grid',\n overflowX: 'auto',\n // `overflow-x: auto` would otherwise force `overflow-y` to compute to\n // `auto` — pin it so rows only ever scroll on one axis.\n overflowY: 'hidden',\n scrollSnapType: 'x mandatory',\n scrollbarWidth: 'none',\n WebkitOverflowScrolling: 'touch',\n overscrollBehaviorX: 'contain',\n touchAction: 'pan-x pan-y',\n}\n\nconst rootScrollStyleDisabled: CSSProperties = {\n ...rootScrollStyle,\n overflowX: 'hidden',\n touchAction: 'pan-y',\n}\n\nconst snapStart: CSSProperties = { scrollSnapAlign: 'start' }\nconst snapEnd: CSSProperties = { scrollSnapAlign: 'end' }\n\ntype InnerProps = RevealRowProps & {\n forwardedRef: ForwardedRef<RevealRowHandle>\n}\n\nfunction RevealRowInner({\n children,\n left,\n right,\n as: Element = 'div',\n mode: modeProp,\n actionWidthLeft: wLIn,\n actionWidthRight: wRIn,\n classNames = {} as RevealRowClassNames,\n showHandle = true,\n handle: handleOverride,\n handlePosition: handlePositionProp,\n handleTitle = 'Drag horizontally to show actions',\n handleAriaLabel = 'Drag horizontally to show actions',\n onRevealChange,\n onScroll: onScrollProp,\n resetWhenDisabled = true,\n disabled = false,\n isActive = false,\n className,\n style,\n animationPreset = ANIMATION_PRESET.quick,\n animationConfig,\n forwardedRef,\n}: InnerProps) {\n const mode = resolveMode(left, right, modeProp)\n const hasL = mode === REVEAL_MODE.left || mode === REVEAL_MODE.both\n const hasR = mode === REVEAL_MODE.right || mode === REVEAL_MODE.both\n\n const handlePosition: RevealHandlePosition =\n handlePositionProp ??\n (mode === REVEAL_MODE.left\n ? REVEAL_HANDLE_POSITION.start\n : REVEAL_HANDLE_POSITION.end)\n\n const containerRef = useRef<HTMLElement>(null)\n const leftRef = useRef<HTMLDivElement>(null)\n const rightRef = useRef<HTMLDivElement>(null)\n const lastEmitted = useRef<RevealPosition | null>(null)\n const swipedRef = useRef(false)\n const focusRevealedRef = useRef(false)\n const [settledPosition, setSettledPosition] = useState<RevealPosition>(\n REVEAL_POSITION.center,\n )\n\n // Effective action-column widths. With an explicit prop this is a constant;\n // without one the column is content-sized (minmax(88px, max-content) track)\n // and the rendered width is read live — only ever inside handlers that\n // already read layout, so no extra reflow cost. `|| 88` covers pre-mount\n // and environments without layout.\n const getWL = useCallback(\n () => (hasL ? (wLIn ?? (leftRef.current?.offsetWidth || 88)) : 0),\n [hasL, wLIn],\n )\n const getWR = useCallback(\n () => (hasR ? (wRIn ?? (rightRef.current?.offsetWidth || 88)) : 0),\n [hasR, wRIn],\n )\n const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n const hasAppliedInitialScroll = useRef(false)\n const isAnimatingRef = useRef(false)\n const rafIdRef = useRef<number | null>(null)\n const settleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const finalizeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const originalSnapRef = useRef('')\n\n const readPosition = useCallback((): RevealPosition => {\n const el = containerRef.current\n if (!el) return REVEAL_POSITION.center\n return getRevealFromScroll(\n el.scrollLeft,\n getMaxScroll(el),\n getWL(),\n getWR(),\n mode,\n )\n }, [getWL, getWR, mode])\n\n const emitReveal = useCallback(\n (position: RevealPosition) => {\n setSettledPosition(position)\n if (lastEmitted.current === position) return\n lastEmitted.current = position\n onRevealChange?.(position)\n },\n [onRevealChange],\n )\n\n const scrollToClosed = useCallback(() => {\n const el = containerRef.current\n if (!el) return\n const m = getMaxScroll(el)\n const closed = getScrollClosed(getWL(), getWR(), m, mode)\n\n // For immediate scroll, we can use the default behavior\n // CSS scroll snap will handle the final positioning\n el.scrollLeft = closed\n }, [getWL, getWR, mode])\n\n const scrollToPosition = useCallback(\n (targetScrollLeft: number, animationOptions: AnimationConfig) => {\n const el = containerRef.current\n if (!el) return\n\n const { duration, easing } = animationOptions\n\n if (duration === 0) {\n el.scrollLeft = targetScrollLeft\n return\n }\n\n // Cancel any existing animation\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n rafIdRef.current = null\n }\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n settleTimerRef.current = null\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n finalizeTimerRef.current = null\n }\n\n // Disable scroll snap during animation. Only capture the original value\n // when no animation is in flight — mid-animation it reads back our own\n // 'none' and would get restored permanently.\n if (!isAnimatingRef.current) {\n originalSnapRef.current = el.style.scrollSnapType\n }\n isAnimatingRef.current = true\n el.style.scrollSnapType = 'none'\n\n const finish = () => {\n el.scrollLeft = targetScrollLeft\n el.style.scrollSnapType = originalSnapRef.current || 'x mandatory'\n isAnimatingRef.current = false\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n rafIdRef.current = null\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n finalizeTimerRef.current = null\n }\n }\n\n // rAF is frozen on hidden/occluded pages — guarantee the animation\n // completes (and snap is restored) via a timer fallback.\n finalizeTimerRef.current = setTimeout(finish, duration + 100)\n\n const startScrollLeft = el.scrollLeft\n const distance = targetScrollLeft - startScrollLeft\n const startTime = performance.now()\n\n const animate = (currentTime: number) => {\n const elapsed = currentTime - startTime\n const progress = Math.min(elapsed / duration, 1)\n\n let easedProgress = progress\n if (easing === 'ease-out') {\n easedProgress = 1 - (1 - progress) ** 2\n } else if (easing === 'ease-in-out') {\n easedProgress =\n progress < 0.5\n ? 2 * progress * progress\n : 1 - (-2 * progress + 2) ** 2 / 2\n } else if (easing.startsWith('cubic-bezier')) {\n // For the bounce effect, we'll use a simplified approximation\n easedProgress = progress * progress * (3 - 2 * progress)\n if (easing.includes('-0.55')) {\n // Bounce effect approximation\n easedProgress =\n progress < 0.5\n ? 4 * progress * progress * progress\n : 1 - (-2 * progress + 2) ** 3 / 2\n // Add overshoot for bounce\n if (progress > 0.7 && progress < 1) {\n easedProgress +=\n Math.sin((progress - 0.7) * Math.PI * 10) * 0.1 * (1 - progress)\n }\n }\n }\n\n el.scrollLeft = startScrollLeft + distance * easedProgress\n\n if (progress < 1) {\n rafIdRef.current = requestAnimationFrame(animate)\n } else {\n rafIdRef.current = null\n finish()\n }\n }\n\n rafIdRef.current = requestAnimationFrame(animate)\n },\n [],\n )\n\n const closeRow = useCallback(\n (animated?: boolean | AnimationPreset | AnimationConfig) => {\n const el = containerRef.current\n if (!el) return\n\n const m = getMaxScroll(el)\n const closed = getScrollClosed(getWL(), getWR(), m, mode)\n const animConfig = resolveAnimationConfig(\n animated,\n animationPreset,\n animationConfig,\n )\n\n scrollToPosition(closed, animConfig)\n\n // Update position after animation or immediately if no animation\n const delay = animConfig.duration > 0 ? animConfig.duration : 0\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n settleTimerRef.current = setTimeout(() => {\n emitReveal(readPosition())\n settleTimerRef.current = null\n }, delay)\n },\n [\n animationConfig,\n animationPreset,\n emitReveal,\n getWL,\n getWR,\n mode,\n readPosition,\n scrollToPosition,\n ],\n )\n\n const revealRow = useCallback(\n (\n position: RevealPosition,\n animated?: boolean | AnimationPreset | AnimationConfig,\n ) => {\n const el = containerRef.current\n if (!el) return\n const max = getMaxScroll(el)\n const wL = getWL()\n const wR = getWR()\n\n let targetScroll: number\n if (position === REVEAL_POSITION.center) {\n targetScroll = getScrollClosed(wL, wR, max, mode)\n } else if (\n position === REVEAL_POSITION.left &&\n (mode === REVEAL_MODE.left || mode === REVEAL_MODE.both)\n ) {\n targetScroll = 0\n } else if (\n position === REVEAL_POSITION.right &&\n (mode === REVEAL_MODE.right || mode === REVEAL_MODE.both)\n ) {\n targetScroll = max\n } else {\n return\n }\n\n const animConfig = resolveAnimationConfig(\n animated,\n animationPreset,\n animationConfig,\n )\n scrollToPosition(targetScroll, animConfig)\n\n // Update position after animation or immediately if no animation\n const delay = animConfig.duration > 0 ? animConfig.duration : 0\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n settleTimerRef.current = setTimeout(() => {\n emitReveal(getRevealFromScroll(targetScroll, max, wL, wR, mode))\n settleTimerRef.current = null\n }, delay)\n },\n [\n animationConfig,\n animationPreset,\n emitReveal,\n getWL,\n getWR,\n mode,\n scrollToPosition,\n ],\n )\n\n useImperativeHandle(\n forwardedRef,\n () => ({ close: closeRow, reveal: revealRow }),\n [closeRow, revealRow],\n )\n\n // Keyboard support: tabbing into an off-screen action column snaps it\n // cleanly into view (instead of the browser's un-snapped scroll-into-view),\n // and a focus-initiated reveal closes again once focus leaves the row.\n // Swipe-opened rows are untouched by focus loss.\n const handleRootFocus = useCallback(\n (e: FocusEvent<HTMLElement>) => {\n const t = e.target as Node | null\n if (!t) return\n if (leftRef.current?.contains(t)) {\n focusRevealedRef.current = true\n revealRow(REVEAL_POSITION.left)\n } else if (rightRef.current?.contains(t)) {\n focusRevealedRef.current = true\n revealRow(REVEAL_POSITION.right)\n }\n },\n [revealRow],\n )\n\n const handleRootBlur = useCallback(\n (e: FocusEvent<HTMLElement>) => {\n if (!focusRevealedRef.current) return\n const next = e.relatedTarget as Node | null\n if (next && containerRef.current?.contains(next)) return\n focusRevealedRef.current = false\n closeRow()\n },\n [closeRow],\n )\n\n useLayoutEffect(() => {\n if (mode === REVEAL_MODE.right) {\n return\n }\n const el = containerRef.current\n if (!el) return\n if (!hasAppliedInitialScroll.current) {\n el.scrollLeft = getWL()\n hasAppliedInitialScroll.current = true\n }\n }, [mode, getWL])\n\n useEffect(() => {\n if (disabled && resetWhenDisabled) {\n hasAppliedInitialScroll.current = true\n scrollToClosed()\n emitReveal(readPosition())\n }\n }, [disabled, emitReveal, readPosition, resetWhenDisabled, scrollToClosed])\n\n useEffect(() => {\n if (isActive) {\n hasAppliedInitialScroll.current = true\n scrollToClosed()\n emitReveal(readPosition())\n }\n }, [emitReveal, isActive, readPosition, scrollToClosed])\n\n useEffect(\n () => () => {\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current)\n }\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n }\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n }\n },\n [],\n )\n\n const handleScroll = useCallback(\n (e: UIEvent<HTMLElement>) => {\n onScrollProp?.(e)\n const el = containerRef.current\n if (!el) return\n const m = getMaxScroll(el)\n const wL = getWL()\n const wR = getWR()\n const pos = getRevealFromScroll(el.scrollLeft, m, wL, wR, mode)\n const closed = getScrollClosed(wL, wR, m, mode)\n if (Math.abs(el.scrollLeft - closed) > restEpsilon) {\n swipedRef.current = true\n }\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current)\n }\n debounceTimer.current = setTimeout(() => {\n debounceTimer.current = null\n emitReveal(pos)\n }, SCROLL_REVEAL_DEBOUNCE_MS)\n },\n [emitReveal, getWL, getWR, mode, onScrollProp],\n )\n\n const onClickCapture = useCallback((e: MouseEvent) => {\n const t = e.target as Node | null\n if (t) {\n if (leftRef.current?.contains(t) || rightRef.current?.contains(t)) {\n return\n }\n }\n if (swipedRef.current) {\n e.preventDefault()\n e.stopPropagation()\n swipedRef.current = false\n }\n }, [])\n\n // `100%` for the main track (not `1fr`) so total row width > viewport: otherwise both\n // columns can shrink to fit with no overflow and the action stays visible.\n // Without an explicit width the column is content-sized via a `max-content`\n // track — `minmax(88px, max-content)` would never grow, because the `100%`\n // main track leaves no free space for minmax growth. The 88px floor for\n // stretchy content lives on the column element's `minWidth` instead, which\n // floors its sizing contribution to the track.\n const trackL = wLIn != null ? `${wLIn}px` : 'max-content'\n const trackR = wRIn != null ? `${wRIn}px` : 'max-content'\n const gridTemplateColumns =\n mode === REVEAL_MODE.right\n ? `100% ${trackR}`\n : mode === REVEAL_MODE.left\n ? `${trackL} 100%`\n : `${trackL} 100% ${trackR}`\n\n const handleContent = showHandle ? (\n handleOverride !== undefined ? (\n handleOverride\n ) : (\n <>\n <span\n className=\"sr-only\"\n style={{\n position: 'absolute',\n width: 1,\n height: 1,\n padding: 0,\n margin: -1,\n overflow: 'hidden',\n clip: 'rect(0,0,0,0)',\n border: 0,\n }}\n >\n {handleAriaLabel}\n </span>\n <span className={classNames.handleIcon} aria-hidden>\n <DefaultHandleIcon />\n </span>\n </>\n )\n ) : null\n\n const handleStrip = showHandle ? (\n <div\n role=\"presentation\"\n className={classNames.handleContainer}\n data-reveal-row-handle\n style={{\n flexShrink: 0,\n alignSelf: 'stretch',\n display: 'flex',\n alignItems: 'center',\n }}\n title={handleOverride === undefined ? handleTitle : undefined}\n >\n {handleContent}\n </div>\n ) : null\n\n const mainColumn = (\n <div\n className={classNames.main}\n data-reveal-row-main\n style={{\n ...snapStart,\n minWidth: 0,\n width: '100%',\n maxWidth: '100%',\n boxSizing: 'border-box',\n }}\n >\n <div\n className={classNames.mainInner}\n style={{\n display: 'flex',\n minWidth: 0,\n width: '100%',\n alignItems: 'flex-start',\n }}\n >\n {handlePosition === REVEAL_HANDLE_POSITION.start && handleStrip}\n <div style={{ minWidth: 0, flex: 1, flexBasis: 0 }}>{children}</div>\n {handlePosition === REVEAL_HANDLE_POSITION.end && handleStrip}\n </div>\n </div>\n )\n\n return (\n <Element\n // biome-ignore lint/suspicious/noExplicitAny: Required for polymorphic ref compatibility\n ref={containerRef as any}\n data-reveal-mode={mode}\n data-reveal-position={settledPosition}\n className={cx(classNames.root, className)}\n onScroll={handleScroll}\n onClickCapture={onClickCapture}\n onFocus={handleRootFocus}\n onBlur={handleRootBlur}\n style={{\n ...(disabled ? rootScrollStyleDisabled : rootScrollStyle),\n ...style,\n gridTemplateColumns,\n }}\n >\n {hasL ? (\n <div\n ref={leftRef}\n className={classNames.left}\n data-reveal-row-left\n style={{\n ...snapStart,\n ...(wLIn != null\n ? { minWidth: 0, width: wLIn }\n : { minWidth: 'var(--reveal-row-action-min-width, 88px)' }),\n }}\n >\n {left}\n </div>\n ) : null}\n {mainColumn}\n {hasR ? (\n <div\n ref={rightRef}\n className={classNames.right}\n data-reveal-row-right\n style={{\n ...snapEnd,\n ...(wRIn != null\n ? { minWidth: 0, width: wRIn }\n : { minWidth: 'var(--reveal-row-action-min-width, 88px)' }),\n }}\n >\n {right}\n </div>\n ) : null}\n </Element>\n )\n}\n\nexport const RevealRow = forwardRef<RevealRowHandle, RevealRowProps>(\n function RevealRow(props, ref) {\n return <RevealRowInner {...props} forwardedRef={ref} />\n },\n)\n","/** Minimal 6-dot grip, no icon library dependency. */\nexport function DefaultHandleIcon() {\n return (\n <svg\n width={16}\n height={16}\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n aria-hidden\n >\n <title>Drag handle</title>\n <circle cx=\"6\" cy=\"4\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"4\" r=\"1.2\" />\n <circle cx=\"6\" cy=\"8\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"8\" r=\"1.2\" />\n <circle cx=\"6\" cy=\"12\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"12\" r=\"1.2\" />\n </svg>\n )\n}\n"],"mappings":"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","names":["jsx","jsxs","RevealRow"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/getRevealFromScroll.ts","../src/RevealRow.tsx","../src/DefaultHandleIcon.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode, UIEvent } from 'react'\n\nexport const REVEAL_MODE = {\n left: 'left',\n right: 'right',\n both: 'both',\n} as const\n\nexport type RevealMode = (typeof REVEAL_MODE)[keyof typeof REVEAL_MODE]\n\nexport const REVEAL_POSITION = {\n left: 'left',\n center: 'center',\n right: 'right',\n} as const\n\nexport type RevealPosition =\n (typeof REVEAL_POSITION)[keyof typeof REVEAL_POSITION]\n\nexport const REVEAL_HANDLE_POSITION = {\n start: 'start',\n end: 'end',\n} as const\n\nexport type RevealHandlePosition =\n (typeof REVEAL_HANDLE_POSITION)[keyof typeof REVEAL_HANDLE_POSITION]\n\nexport const REVEAL_ROW_ELEMENTS = {\n div: 'div',\n section: 'section',\n article: 'article',\n main: 'main',\n aside: 'aside',\n header: 'header',\n footer: 'footer',\n nav: 'nav',\n li: 'li',\n} as const\n\nexport type RevealRowElement =\n (typeof REVEAL_ROW_ELEMENTS)[keyof typeof REVEAL_ROW_ELEMENTS]\n\nexport const ANIMATION_PRESET = {\n none: 'none',\n quick: 'quick',\n smooth: 'smooth',\n} as const\n\nexport type AnimationPreset =\n (typeof ANIMATION_PRESET)[keyof typeof ANIMATION_PRESET]\n\nexport type AnimationConfig = {\n duration: number\n easing: string\n}\n\nexport const ANIMATION_PRESETS: Record<AnimationPreset, AnimationConfig> = {\n [ANIMATION_PRESET.none]: { duration: 0, easing: 'linear' },\n [ANIMATION_PRESET.quick]: { duration: 200, easing: 'ease-out' },\n [ANIMATION_PRESET.smooth]: { duration: 400, easing: 'ease-in-out' },\n}\n\nexport type RevealRowClassNames = {\n root?: string\n main?: string\n mainInner?: string\n left?: string\n right?: string\n handleContainer?: string\n handleIcon?: string\n}\n\nexport type RevealRowHandle = {\n close: (animated?: boolean | AnimationPreset | AnimationConfig) => void\n reveal: (\n position: RevealPosition,\n animated?: boolean | AnimationPreset | AnimationConfig,\n ) => void\n}\n\nexport type RevealRowProps = {\n /** Primary row content (e.g. title, subtitle). */\n children: ReactNode\n /** Optional leading action column (e.g. delete). Omitted in `right` mode. */\n left?: ReactNode\n /**\n * Trailing action column (e.g. add). Omitted in `left` mode.\n */\n right?: ReactNode\n /**\n * The HTML element to use for the root container.\n * @default 'div'\n */\n as?: RevealRowElement\n /**\n * If both `left` and `right` are set, defaults to `both`. If only one side,\n * mode is derived unless overridden.\n */\n mode?: RevealMode\n /**\n * Fixed width (px) of the left action column. Omit to size the column to\n * its content with an 88px floor (`minmax(88px, max-content)`).\n */\n actionWidthLeft?: number\n /**\n * Fixed width (px) of the right action column. Omit to size the column to\n * its content with an 88px floor (`minmax(88px, max-content)`).\n */\n actionWidthRight?: number\n classNames?: RevealRowClassNames\n /** @default true */\n showHandle?: boolean\n /** Replaces the built-in drag affordance. */\n handle?: ReactNode\n /**\n * Where the handle sits in the main row. Default: `start` in `left` mode,\n * `end` otherwise.\n */\n handlePosition?: RevealHandlePosition\n handleTitle?: string\n /** Shown in screen-reader text when using the default drag handle. */\n handleAriaLabel?: string\n /**\n * Tapping/clicking the drag handle briefly peeks the actions and springs\n * back before the snap point, hinting at the swipe gesture. Skipped when\n * the row's default animation resolves to instant (`animationPreset=\"none\"`\n * or the OS prefers-reduced-motion setting).\n * @default true\n */\n peekOnHandleTap?: boolean\n /** Fires when the settled position changes. */\n onRevealChange?: (position: RevealPosition) => void\n onScroll?: (event: UIEvent<HTMLElement>) => void\n /** Resets to closed; default true. */\n resetWhenDisabled?: boolean\n disabled?: boolean\n /**\n * When true, snaps back to the closed position (e.g. row became active/selected\n * elsewhere in the list).\n */\n isActive?: boolean\n className?: string\n style?: CSSProperties\n /**\n * Default animation preset for close/reveal animations when action buttons are clicked.\n * @default 'quick'\n */\n animationPreset?: AnimationPreset\n /**\n * Custom animation configuration overriding the preset.\n */\n animationConfig?: AnimationConfig\n}\n","import {\n REVEAL_MODE,\n REVEAL_POSITION,\n type RevealMode,\n type RevealPosition,\n} from './types'\n\n/**\n * Map horizontal scroll position to a logical \"revealed\" state.\n * `wL` / `wR` are the fixed action column widths; `maxScroll` is\n * `Math.max(0, scrollWidth - clientWidth)`.\n */\nexport function getRevealFromScroll(\n scrollLeft: number,\n maxScroll: number,\n wL: number,\n wR: number,\n mode: RevealMode,\n): RevealPosition {\n if (mode === REVEAL_MODE.right) {\n if (maxScroll <= 0) return REVEAL_POSITION.center\n return scrollLeft < wR / 2 ? REVEAL_POSITION.center : REVEAL_POSITION.right\n }\n if (mode === REVEAL_MODE.left) {\n if (maxScroll <= 0) return REVEAL_POSITION.center\n return scrollLeft < wL / 2 ? REVEAL_POSITION.left : REVEAL_POSITION.center\n }\n if (maxScroll <= 0) return REVEAL_POSITION.center\n if (scrollLeft < wL / 2) return REVEAL_POSITION.left\n if (scrollLeft > maxScroll - wR / 2) return REVEAL_POSITION.right\n return REVEAL_POSITION.center\n}\n\n/** \"Closed\" / resting scrollLeft for a mode (main panel only). */\nexport function getScrollClosed(\n wL: number,\n _wR: number,\n _maxScroll: number,\n mode: RevealMode,\n): number {\n if (mode === REVEAL_MODE.right) return 0\n return wL\n}\n","'use client'\n\nimport type {\n CSSProperties,\n FocusEvent,\n ForwardedRef,\n MouseEvent,\n UIEvent,\n} from 'react'\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react'\n\nimport { DefaultHandleIcon } from './DefaultHandleIcon'\nimport { getRevealFromScroll, getScrollClosed } from './getRevealFromScroll'\nimport {\n ANIMATION_PRESET,\n ANIMATION_PRESETS,\n type AnimationConfig,\n type AnimationPreset,\n REVEAL_HANDLE_POSITION,\n REVEAL_MODE,\n REVEAL_POSITION,\n type RevealHandlePosition,\n type RevealMode,\n type RevealPosition,\n type RevealRowClassNames,\n type RevealRowHandle,\n type RevealRowProps,\n} from './types'\n\nfunction cx(...parts: (string | undefined)[]) {\n return parts.filter(Boolean).join(' ')\n}\n\nfunction getMaxScroll(el: HTMLElement) {\n return Math.max(0, el.scrollWidth - el.clientWidth)\n}\n\nfunction resolveMode(\n left: RevealRowProps['left'],\n right: RevealRowProps['right'],\n mode: RevealMode | undefined,\n): RevealMode {\n if (mode) return mode\n if (left != null && right != null) return REVEAL_MODE.both\n if (left != null) return REVEAL_MODE.left\n return REVEAL_MODE.right\n}\n\nfunction prefersReducedMotion(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n )\n}\n\nfunction resolveAnimationConfig(\n animated: boolean | AnimationPreset | AnimationConfig | undefined,\n defaultPreset: AnimationPreset,\n customConfig?: AnimationConfig,\n): AnimationConfig {\n let config: AnimationConfig\n // An explicit AnimationConfig object is an intentional override and is not\n // reduced; booleans and presets defer to the OS reduced-motion setting.\n let explicit = false\n\n if (animated === false) {\n config = ANIMATION_PRESETS[ANIMATION_PRESET.none]\n } else if (animated === true || animated === undefined) {\n if (customConfig) {\n config = customConfig\n explicit = true\n } else {\n config = ANIMATION_PRESETS[defaultPreset]\n }\n } else if (typeof animated === 'string') {\n config = ANIMATION_PRESETS[animated]\n } else {\n config = animated\n explicit = true\n }\n\n if (!explicit && prefersReducedMotion()) {\n return { ...config, duration: 0 }\n }\n\n // Validate and clamp duration to be >= 0\n return {\n ...config,\n duration: Math.max(\n 0,\n Number.isFinite(config.duration) ? config.duration : 0,\n ),\n }\n}\n\nconst SCROLL_REVEAL_DEBOUNCE_MS = 64\nconst restEpsilon = 2\n\n// Handle-tap peek: how far into the action column to scroll (kept well under\n// the wR/2 snap threshold) and the out/return micro-animation timings.\nconst PEEK_FRACTION = 0.35\nconst PEEK_OUT_ANIMATION: AnimationConfig = {\n duration: 120,\n easing: 'ease-out',\n}\nconst PEEK_RETURN_ANIMATION: AnimationConfig = {\n duration: 180,\n easing: 'ease-out',\n}\n// Past the return animation's finalize fallback (duration + 100ms), so snap is\n// restored and trailing scroll events have flushed before suppression clears.\nconst PEEK_SETTLE_BUFFER_MS = 120\n\nconst rootScrollStyle: CSSProperties = {\n display: 'grid',\n overflowX: 'auto',\n // `overflow-x: auto` would otherwise force `overflow-y` to compute to\n // `auto` — pin it so rows only ever scroll on one axis.\n overflowY: 'hidden',\n scrollSnapType: 'x mandatory',\n scrollbarWidth: 'none',\n WebkitOverflowScrolling: 'touch',\n overscrollBehaviorX: 'contain',\n touchAction: 'pan-x pan-y',\n}\n\nconst rootScrollStyleDisabled: CSSProperties = {\n ...rootScrollStyle,\n overflowX: 'hidden',\n touchAction: 'pan-y',\n}\n\nconst snapStart: CSSProperties = { scrollSnapAlign: 'start' }\nconst snapEnd: CSSProperties = { scrollSnapAlign: 'end' }\n\ntype InnerProps = RevealRowProps & {\n forwardedRef: ForwardedRef<RevealRowHandle>\n}\n\nfunction RevealRowInner({\n children,\n left,\n right,\n as: Element = 'div',\n mode: modeProp,\n actionWidthLeft: wLIn,\n actionWidthRight: wRIn,\n classNames = {} as RevealRowClassNames,\n showHandle = true,\n handle: handleOverride,\n handlePosition: handlePositionProp,\n handleTitle = 'Drag horizontally to show actions',\n handleAriaLabel = 'Drag horizontally to show actions',\n peekOnHandleTap = true,\n onRevealChange,\n onScroll: onScrollProp,\n resetWhenDisabled = true,\n disabled = false,\n isActive = false,\n className,\n style,\n animationPreset = ANIMATION_PRESET.quick,\n animationConfig,\n forwardedRef,\n}: InnerProps) {\n const mode = resolveMode(left, right, modeProp)\n const hasL = mode === REVEAL_MODE.left || mode === REVEAL_MODE.both\n const hasR = mode === REVEAL_MODE.right || mode === REVEAL_MODE.both\n\n const handlePosition: RevealHandlePosition =\n handlePositionProp ??\n (mode === REVEAL_MODE.left\n ? REVEAL_HANDLE_POSITION.start\n : REVEAL_HANDLE_POSITION.end)\n\n const containerRef = useRef<HTMLElement>(null)\n const leftRef = useRef<HTMLDivElement>(null)\n const rightRef = useRef<HTMLDivElement>(null)\n const handleStripRef = useRef<HTMLDivElement>(null)\n const peekTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const lastEmitted = useRef<RevealPosition | null>(null)\n const swipedRef = useRef(false)\n const focusRevealedRef = useRef(false)\n const [settledPosition, setSettledPosition] = useState<RevealPosition>(\n REVEAL_POSITION.center,\n )\n\n // Effective action-column widths. With an explicit prop this is a constant;\n // without one the column is content-sized (minmax(88px, max-content) track)\n // and the rendered width is read live — only ever inside handlers that\n // already read layout, so no extra reflow cost. `|| 88` covers pre-mount\n // and environments without layout.\n const getWL = useCallback(\n () => (hasL ? (wLIn ?? (leftRef.current?.offsetWidth || 88)) : 0),\n [hasL, wLIn],\n )\n const getWR = useCallback(\n () => (hasR ? (wRIn ?? (rightRef.current?.offsetWidth || 88)) : 0),\n [hasR, wRIn],\n )\n const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n const hasAppliedInitialScroll = useRef(false)\n const isAnimatingRef = useRef(false)\n const rafIdRef = useRef<number | null>(null)\n const settleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const finalizeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const originalSnapRef = useRef('')\n\n const readPosition = useCallback((): RevealPosition => {\n const el = containerRef.current\n if (!el) return REVEAL_POSITION.center\n return getRevealFromScroll(\n el.scrollLeft,\n getMaxScroll(el),\n getWL(),\n getWR(),\n mode,\n )\n }, [getWL, getWR, mode])\n\n const emitReveal = useCallback(\n (position: RevealPosition) => {\n setSettledPosition(position)\n if (lastEmitted.current === position) return\n lastEmitted.current = position\n onRevealChange?.(position)\n },\n [onRevealChange],\n )\n\n const scrollToClosed = useCallback(() => {\n const el = containerRef.current\n if (!el) return\n const m = getMaxScroll(el)\n const closed = getScrollClosed(getWL(), getWR(), m, mode)\n\n // For immediate scroll, we can use the default behavior\n // CSS scroll snap will handle the final positioning\n el.scrollLeft = closed\n }, [getWL, getWR, mode])\n\n const scrollToPosition = useCallback(\n (targetScrollLeft: number, animationOptions: AnimationConfig) => {\n const el = containerRef.current\n if (!el) return\n\n const { duration, easing } = animationOptions\n\n if (duration === 0) {\n el.scrollLeft = targetScrollLeft\n return\n }\n\n // Cancel any existing animation\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n rafIdRef.current = null\n }\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n settleTimerRef.current = null\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n finalizeTimerRef.current = null\n }\n\n // Disable scroll snap during animation. Only capture the original value\n // when no animation is in flight — mid-animation it reads back our own\n // 'none' and would get restored permanently.\n if (!isAnimatingRef.current) {\n originalSnapRef.current = el.style.scrollSnapType\n }\n isAnimatingRef.current = true\n el.style.scrollSnapType = 'none'\n\n const finish = () => {\n el.scrollLeft = targetScrollLeft\n el.style.scrollSnapType = originalSnapRef.current || 'x mandatory'\n isAnimatingRef.current = false\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n rafIdRef.current = null\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n finalizeTimerRef.current = null\n }\n }\n\n // rAF is frozen on hidden/occluded pages — guarantee the animation\n // completes (and snap is restored) via a timer fallback.\n finalizeTimerRef.current = setTimeout(finish, duration + 100)\n\n const startScrollLeft = el.scrollLeft\n const distance = targetScrollLeft - startScrollLeft\n const startTime = performance.now()\n\n const animate = (currentTime: number) => {\n const elapsed = currentTime - startTime\n const progress = Math.min(elapsed / duration, 1)\n\n let easedProgress = progress\n if (easing === 'ease-out') {\n easedProgress = 1 - (1 - progress) ** 2\n } else if (easing === 'ease-in-out') {\n easedProgress =\n progress < 0.5\n ? 2 * progress * progress\n : 1 - (-2 * progress + 2) ** 2 / 2\n } else if (easing.startsWith('cubic-bezier')) {\n // For the bounce effect, we'll use a simplified approximation\n easedProgress = progress * progress * (3 - 2 * progress)\n if (easing.includes('-0.55')) {\n // Bounce effect approximation\n easedProgress =\n progress < 0.5\n ? 4 * progress * progress * progress\n : 1 - (-2 * progress + 2) ** 3 / 2\n // Add overshoot for bounce\n if (progress > 0.7 && progress < 1) {\n easedProgress +=\n Math.sin((progress - 0.7) * Math.PI * 10) * 0.1 * (1 - progress)\n }\n }\n }\n\n el.scrollLeft = startScrollLeft + distance * easedProgress\n\n if (progress < 1) {\n rafIdRef.current = requestAnimationFrame(animate)\n } else {\n rafIdRef.current = null\n finish()\n }\n }\n\n rafIdRef.current = requestAnimationFrame(animate)\n },\n [],\n )\n\n // Briefly scroll partway into an action column and spring back, teaching\n // the swipe affordance without committing to a revealed state. Returns\n // whether a peek actually started, so the caller can consume the click.\n const peekActions = useCallback((): boolean => {\n const el = containerRef.current\n if (!el || disabled) return false\n if (isAnimatingRef.current || peekTimerRef.current !== null) return false\n const defaultConfig = resolveAnimationConfig(\n undefined,\n animationPreset,\n animationConfig,\n )\n if (defaultConfig.duration === 0) return false\n\n const m = getMaxScroll(el)\n const wL = getWL()\n const wR = getWR()\n const closed = getScrollClosed(wL, wR, m, mode)\n if (Math.abs(el.scrollLeft - closed) > restEpsilon) return false\n\n // Peek toward the handle's side when that side has actions, otherwise\n // toward whichever side exists.\n const peekRight =\n handlePosition === REVEAL_HANDLE_POSITION.end ? hasR : !hasL\n const target = peekRight\n ? Math.min(m, closed + wR * PEEK_FRACTION)\n : Math.max(0, closed - wL * PEEK_FRACTION)\n if (target === closed) return false\n\n scrollToPosition(target, PEEK_OUT_ANIMATION)\n peekTimerRef.current = setTimeout(() => {\n scrollToPosition(closed, PEEK_RETURN_ANIMATION)\n peekTimerRef.current = setTimeout(() => {\n peekTimerRef.current = null\n // The peek's own scrolling flags the row as swiped; the row is back\n // at rest, so don't let that eat the user's next click.\n swipedRef.current = false\n }, PEEK_RETURN_ANIMATION.duration + PEEK_SETTLE_BUFFER_MS)\n }, PEEK_OUT_ANIMATION.duration)\n return true\n }, [\n animationConfig,\n animationPreset,\n disabled,\n getWL,\n getWR,\n handlePosition,\n hasL,\n hasR,\n mode,\n scrollToPosition,\n ])\n\n const closeRow = useCallback(\n (animated?: boolean | AnimationPreset | AnimationConfig) => {\n const el = containerRef.current\n if (!el) return\n\n const m = getMaxScroll(el)\n const closed = getScrollClosed(getWL(), getWR(), m, mode)\n const animConfig = resolveAnimationConfig(\n animated,\n animationPreset,\n animationConfig,\n )\n\n scrollToPosition(closed, animConfig)\n\n // Update position after animation or immediately if no animation\n const delay = animConfig.duration > 0 ? animConfig.duration : 0\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n settleTimerRef.current = setTimeout(() => {\n emitReveal(readPosition())\n settleTimerRef.current = null\n }, delay)\n },\n [\n animationConfig,\n animationPreset,\n emitReveal,\n getWL,\n getWR,\n mode,\n readPosition,\n scrollToPosition,\n ],\n )\n\n const revealRow = useCallback(\n (\n position: RevealPosition,\n animated?: boolean | AnimationPreset | AnimationConfig,\n ) => {\n const el = containerRef.current\n if (!el) return\n const max = getMaxScroll(el)\n const wL = getWL()\n const wR = getWR()\n\n let targetScroll: number\n if (position === REVEAL_POSITION.center) {\n targetScroll = getScrollClosed(wL, wR, max, mode)\n } else if (\n position === REVEAL_POSITION.left &&\n (mode === REVEAL_MODE.left || mode === REVEAL_MODE.both)\n ) {\n targetScroll = 0\n } else if (\n position === REVEAL_POSITION.right &&\n (mode === REVEAL_MODE.right || mode === REVEAL_MODE.both)\n ) {\n targetScroll = max\n } else {\n return\n }\n\n const animConfig = resolveAnimationConfig(\n animated,\n animationPreset,\n animationConfig,\n )\n scrollToPosition(targetScroll, animConfig)\n\n // Update position after animation or immediately if no animation\n const delay = animConfig.duration > 0 ? animConfig.duration : 0\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n settleTimerRef.current = setTimeout(() => {\n emitReveal(getRevealFromScroll(targetScroll, max, wL, wR, mode))\n settleTimerRef.current = null\n }, delay)\n },\n [\n animationConfig,\n animationPreset,\n emitReveal,\n getWL,\n getWR,\n mode,\n scrollToPosition,\n ],\n )\n\n useImperativeHandle(\n forwardedRef,\n () => ({ close: closeRow, reveal: revealRow }),\n [closeRow, revealRow],\n )\n\n // Keyboard support: tabbing into an off-screen action column snaps it\n // cleanly into view (instead of the browser's un-snapped scroll-into-view),\n // and a focus-initiated reveal closes again once focus leaves the row.\n // Swipe-opened rows are untouched by focus loss.\n const handleRootFocus = useCallback(\n (e: FocusEvent<HTMLElement>) => {\n const t = e.target as Node | null\n if (!t) return\n if (leftRef.current?.contains(t)) {\n focusRevealedRef.current = true\n revealRow(REVEAL_POSITION.left)\n } else if (rightRef.current?.contains(t)) {\n focusRevealedRef.current = true\n revealRow(REVEAL_POSITION.right)\n }\n },\n [revealRow],\n )\n\n const handleRootBlur = useCallback(\n (e: FocusEvent<HTMLElement>) => {\n if (!focusRevealedRef.current) return\n const next = e.relatedTarget as Node | null\n if (next && containerRef.current?.contains(next)) return\n focusRevealedRef.current = false\n closeRow()\n },\n [closeRow],\n )\n\n useLayoutEffect(() => {\n if (mode === REVEAL_MODE.right) {\n return\n }\n const el = containerRef.current\n if (!el) return\n if (!hasAppliedInitialScroll.current) {\n el.scrollLeft = getWL()\n hasAppliedInitialScroll.current = true\n }\n }, [mode, getWL])\n\n useEffect(() => {\n if (disabled && resetWhenDisabled) {\n hasAppliedInitialScroll.current = true\n scrollToClosed()\n emitReveal(readPosition())\n }\n }, [disabled, emitReveal, readPosition, resetWhenDisabled, scrollToClosed])\n\n useEffect(() => {\n if (isActive) {\n hasAppliedInitialScroll.current = true\n scrollToClosed()\n emitReveal(readPosition())\n }\n }, [emitReveal, isActive, readPosition, scrollToClosed])\n\n useEffect(\n () => () => {\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current)\n }\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current)\n }\n if (settleTimerRef.current !== null) {\n clearTimeout(settleTimerRef.current)\n }\n if (finalizeTimerRef.current !== null) {\n clearTimeout(finalizeTimerRef.current)\n }\n if (peekTimerRef.current !== null) {\n clearTimeout(peekTimerRef.current)\n }\n },\n [],\n )\n\n const handleScroll = useCallback(\n (e: UIEvent<HTMLElement>) => {\n onScrollProp?.(e)\n const el = containerRef.current\n if (!el) return\n const m = getMaxScroll(el)\n const wL = getWL()\n const wR = getWR()\n const pos = getRevealFromScroll(el.scrollLeft, m, wL, wR, mode)\n const closed = getScrollClosed(wL, wR, m, mode)\n if (Math.abs(el.scrollLeft - closed) > restEpsilon) {\n swipedRef.current = true\n }\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current)\n }\n debounceTimer.current = setTimeout(() => {\n debounceTimer.current = null\n emitReveal(pos)\n }, SCROLL_REVEAL_DEBOUNCE_MS)\n },\n [emitReveal, getWL, getWR, mode, onScrollProp],\n )\n\n const onClickCapture = useCallback(\n (e: MouseEvent) => {\n const t = e.target as Node | null\n if (t) {\n if (leftRef.current?.contains(t) || rightRef.current?.contains(t)) {\n return\n }\n }\n if (swipedRef.current) {\n e.preventDefault()\n e.stopPropagation()\n swipedRef.current = false\n return\n }\n if (\n peekOnHandleTap &&\n t &&\n handleStripRef.current?.contains(t) &&\n peekActions()\n ) {\n // The tap was aimed at the handle, not the row content.\n e.preventDefault()\n e.stopPropagation()\n }\n },\n [peekActions, peekOnHandleTap],\n )\n\n // `100%` for the main track (not `1fr`) so total row width > viewport: otherwise both\n // columns can shrink to fit with no overflow and the action stays visible.\n // Without an explicit width the column is content-sized via a `max-content`\n // track — `minmax(88px, max-content)` would never grow, because the `100%`\n // main track leaves no free space for minmax growth. The 88px floor for\n // stretchy content lives on the column element's `minWidth` instead, which\n // floors its sizing contribution to the track.\n const trackL = wLIn != null ? `${wLIn}px` : 'max-content'\n const trackR = wRIn != null ? `${wRIn}px` : 'max-content'\n const gridTemplateColumns =\n mode === REVEAL_MODE.right\n ? `100% ${trackR}`\n : mode === REVEAL_MODE.left\n ? `${trackL} 100%`\n : `${trackL} 100% ${trackR}`\n\n const handleContent = showHandle ? (\n handleOverride !== undefined ? (\n handleOverride\n ) : (\n <>\n <span\n className=\"sr-only\"\n style={{\n position: 'absolute',\n width: 1,\n height: 1,\n padding: 0,\n margin: -1,\n overflow: 'hidden',\n clip: 'rect(0,0,0,0)',\n border: 0,\n }}\n >\n {handleAriaLabel}\n </span>\n <span className={classNames.handleIcon} aria-hidden>\n <DefaultHandleIcon />\n </span>\n </>\n )\n ) : null\n\n const handleStrip = showHandle ? (\n <div\n ref={handleStripRef}\n role=\"presentation\"\n className={classNames.handleContainer}\n data-reveal-row-handle\n style={{\n flexShrink: 0,\n alignSelf: 'stretch',\n display: 'flex',\n alignItems: 'center',\n }}\n title={handleOverride === undefined ? handleTitle : undefined}\n >\n {handleContent}\n </div>\n ) : null\n\n const mainColumn = (\n <div\n className={classNames.main}\n data-reveal-row-main\n style={{\n ...snapStart,\n minWidth: 0,\n width: '100%',\n maxWidth: '100%',\n boxSizing: 'border-box',\n }}\n >\n <div\n className={classNames.mainInner}\n style={{\n display: 'flex',\n minWidth: 0,\n width: '100%',\n alignItems: 'flex-start',\n }}\n >\n {handlePosition === REVEAL_HANDLE_POSITION.start && handleStrip}\n <div style={{ minWidth: 0, flex: 1, flexBasis: 0 }}>{children}</div>\n {handlePosition === REVEAL_HANDLE_POSITION.end && handleStrip}\n </div>\n </div>\n )\n\n return (\n <Element\n // biome-ignore lint/suspicious/noExplicitAny: Required for polymorphic ref compatibility\n ref={containerRef as any}\n data-reveal-mode={mode}\n data-reveal-position={settledPosition}\n className={cx(classNames.root, className)}\n onScroll={handleScroll}\n onClickCapture={onClickCapture}\n onFocus={handleRootFocus}\n onBlur={handleRootBlur}\n style={{\n ...(disabled ? rootScrollStyleDisabled : rootScrollStyle),\n ...style,\n gridTemplateColumns,\n }}\n >\n {hasL ? (\n <div\n ref={leftRef}\n className={classNames.left}\n data-reveal-row-left\n style={{\n ...snapStart,\n ...(wLIn != null\n ? { minWidth: 0, width: wLIn }\n : { minWidth: 'var(--reveal-row-action-min-width, 88px)' }),\n }}\n >\n {left}\n </div>\n ) : null}\n {mainColumn}\n {hasR ? (\n <div\n ref={rightRef}\n className={classNames.right}\n data-reveal-row-right\n style={{\n ...snapEnd,\n ...(wRIn != null\n ? { minWidth: 0, width: wRIn }\n : { minWidth: 'var(--reveal-row-action-min-width, 88px)' }),\n }}\n >\n {right}\n </div>\n ) : null}\n </Element>\n )\n}\n\nexport const RevealRow = forwardRef<RevealRowHandle, RevealRowProps>(\n function RevealRow(props, ref) {\n return <RevealRowInner {...props} forwardedRef={ref} />\n },\n)\n","/** Minimal 6-dot grip, no icon library dependency. */\nexport function DefaultHandleIcon() {\n return (\n <svg\n width={16}\n height={16}\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n aria-hidden\n >\n <title>Drag handle</title>\n <circle cx=\"6\" cy=\"4\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"4\" r=\"1.2\" />\n <circle cx=\"6\" cy=\"8\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"8\" r=\"1.2\" />\n <circle cx=\"6\" cy=\"12\" r=\"1.2\" />\n <circle cx=\"10\" cy=\"12\" r=\"1.2\" />\n </svg>\n )\n}\n"],"mappings":"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","names":["jsx","jsxs","RevealRow"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@present-day/reveal-row",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Horizontal scroll-to-reveal row for actions on the left, right, or both sides",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -16,11 +16,10 @@
16
16
  "dist"
17
17
  ],
18
18
  "sideEffects": false,
19
- "packageManager": "bun@1.1.42",
19
+ "packageManager": "bun@1.3.13",
20
20
  "scripts": {
21
- "playground": "vite --config playground/vite.config.ts",
22
- "playground:build": "vite build --config playground/vite.config.ts",
23
- "playground:preview": "vite preview --config playground/vite.config.ts",
21
+ "storybook": "storybook dev -p 6006",
22
+ "storybook:build": "storybook build",
24
23
  "build": "tsup",
25
24
  "dev": "tsup --watch",
26
25
  "lint": "biome check .",
@@ -57,20 +56,24 @@
57
56
  "react-dom": ">=18.0.0"
58
57
  },
59
58
  "devDependencies": {
60
- "@biomejs/biome": "2.5.5",
61
- "@testing-library/jest-dom": "7.0.0",
59
+ "@biomejs/biome": "2.5.14",
60
+ "@storybook/addon-a11y": "^10.6.0",
61
+ "@storybook/react-vite": "^10.6.0",
62
+ "@tailwindcss/vite": "^4.3.3",
63
+ "@testing-library/jest-dom": "7.0.1",
62
64
  "@testing-library/react": "^16.3.2",
63
65
  "@testing-library/user-event": "^14.6.1",
64
- "@types/react": "^19.2.14",
65
- "@types/react-dom": "^19.2.3",
66
- "@vitejs/plugin-react": "6.0.4",
67
- "@vitest/coverage-istanbul": "^4.1.5",
68
- "jsdom": "^29.0.2",
69
- "react": "19.2.8",
70
- "react-dom": "19.2.8",
66
+ "@types/react": "19.3.0",
67
+ "@types/react-dom": "19.3.0",
68
+ "@vitest/coverage-istanbul": "^5.0.1",
69
+ "jsdom": "^30.0.1",
70
+ "react": "19.3.0",
71
+ "react-dom": "19.3.0",
72
+ "storybook": "^10.6.0",
73
+ "tailwindcss": "^4.3.3",
71
74
  "tsup": "^8.5.1",
72
75
  "typescript": "^6.0.3",
73
- "vite": "^8.0.10",
74
- "vitest": "4.1.10"
76
+ "vite": "8.3.0",
77
+ "vitest": "5.0.1"
75
78
  }
76
79
  }