@goodmanlabs/react-swipe-row 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ ![npm](https://img.shields.io/npm/v/@goodmanlabs/react-swipe-row)
2
+ ![CI](https://github.com/gpgoodman/react-swipe-row/actions/workflows/ci.yml/badge.svg)
3
+ ![license](https://img.shields.io/npm/l/@goodmanlabs/react-swipe-row)
4
+
1
5
  # react-swipe-row
2
6
 
3
7
  A native-feeling horizontal “card rail” for React — momentum scrolling + scroll-snap alignment, with optional desktop paging controls.
@@ -16,8 +20,70 @@ This was built to solve a common UI problem: you want a horizontally scrollable
16
20
  ## Install
17
21
 
18
22
  ```bash
19
- npm install react-swipe-row
23
+ npm install @goodmanlabs/react-swipe-row
20
24
  # or
21
- pnpm add react-swipe-row
25
+ pnpm add @goodmanlabs/react-swipe-row
22
26
  # or
23
- yarn add react-swipe-row
27
+ yarn add @goodmanlabs/react-swipe-row
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```tsx
33
+ import SwipeRow from '@goodmanlabs/react-swipe-row';
34
+ import '@goodmanlabs/react-swipe-row/style.css';
35
+
36
+ export default function Example() {
37
+ return (
38
+ <SwipeRow>
39
+ <div className="card">One</div>
40
+ <div className="card">Two</div>
41
+ <div className="card">Three</div>
42
+ </SwipeRow>
43
+ );
44
+ }
45
+ ```
46
+ > Note: You must import the provided CSS for base layout and snapping behavior.
47
+
48
+ ## Props
49
+
50
+ | Prop | Type | Default | Description |
51
+ |------|------|---------|-------------|
52
+ | `items` | `React.ReactNode[]` | — | Optional array of React nodes to render. If provided, it takes precedence over `children`. |
53
+ | `children` | `React.ReactNode` | — | Content to render if `items` is not provided. |
54
+ | `ariaLabel` | `string` | `"Scrollable content"` | Accessible label for the scroll region (`role="region"`). |
55
+ | `snap` | `boolean` | `true` | Enables/disables scroll-snap behavior (applies `rsr-snap` + `rsr-snap-item`). |
56
+ | `pageFactor` | `number` | `0.9` | How far the controls and keyboard paging move, as a fraction of the scroller’s `clientWidth`. |
57
+ | `showControls` | `"auto" \| "always" \| "never"` | `"auto"` | `auto` shows controls only on “desktop-like” pointers (`(hover: hover) and (pointer: fine)`), `always` forces them on, `never` hides them. |
58
+ | `id` | `string` | auto-generated | Optional stable id used for `aria-controls`. If omitted, a React `useId()` value is used. |
59
+ | `className` | `string` | — | Extra class(es) applied to the outer wrapper (`rsr-root`). |
60
+ | `gapClassName` | `string` | — | Optional spacing hook applied to the scroller (e.g. Tailwind `gap-*`, or any consumer-defined class). |
61
+ | `classNames` | `SwipeRowClassNames` | — | Optional granular class hooks for styling without targeting internals. |
62
+ | `scrollerStyle` | `React.CSSProperties` | — | Inline style passthrough for the scroller. Merged after defaults (so it can override). |
63
+
64
+ ### `SwipeRowClassNames`
65
+
66
+ ```ts
67
+ type SwipeRowClassNames = {
68
+ root?: string; // outer wrapper
69
+ scroller?: string; // the horizontal scroller element
70
+ item?: string; // wrapper around each item (snap target)
71
+ controlButton?: string; // shared class for both buttons
72
+ prevButton?: string; // prev button
73
+ nextButton?: string; // next button
74
+ };
75
+ ```
76
+
77
+ ## Accessibility & Behavior
78
+
79
+ - The scroll container is keyboard-focusable and supports left/right arrow key paging.
80
+ - Paging controls use semantic `<button>` elements with accessible labels.
81
+ - Scroll behavior relies on native browser momentum scrolling and `scroll-snap`, not JavaScript-driven carousels.
82
+ - On touch-first devices, paging controls are hidden by default to avoid interfering with native gestures.
83
+
84
+ ## License
85
+
86
+ MIT © Glenn Goodman
87
+
88
+
89
+
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  // src/SwipeRow.tsx
2
4
  import React, { useEffect, useId, useMemo, useRef, useState } from "react";
3
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/SwipeRow.tsx"],"sourcesContent":["import React, { useEffect, useId, useMemo, useRef, useState } from 'react';\n\nexport type ShowControlsMode = 'auto' | 'always' | 'never';\n\nexport type SwipeRowClassNames = {\n /** Outer wrapper around the scroller + controls */\n root?: string;\n /** The horizontal scroller element */\n scroller?: string;\n /** Wrapper around each item (the snap target) */\n item?: string;\n /** Shared class applied to both buttons */\n controlButton?: string;\n /** Prev button */\n prevButton?: string;\n /** Next button */\n nextButton?: string;\n};\n\nexport type SwipeRowProps = {\n /** Optional array of React nodes (alternative to children) */\n items?: React.ReactNode[];\n children?: React.ReactNode;\n\n ariaLabel?: string;\n\n /** Enable CSS scroll-snap */\n snap?: boolean;\n\n /** How far arrows / keyboard page (fraction of visible width) */\n pageFactor?: number;\n\n /** When to show left/right controls */\n showControls?: ShowControlsMode;\n\n /** Optional stable id for aria-controls */\n id?: string;\n\n /** Extra class on outer wrapper */\n className?: string;\n\n /**\n * Spacing between items.\n * This is a class hook (NOT Tailwind-specific). For non-Tailwind consumers,\n * they'll typically use the provided default CSS and ignore this.\n */\n gapClassName?: string;\n\n /** More granular class hooks */\n classNames?: SwipeRowClassNames;\n\n /**\n * Optional inline style passthrough for the scroller.\n * Useful for consumers that want scrollbarGutter, etc.\n */\n scrollerStyle?: React.CSSProperties;\n};\n\nfunction cx(...parts: Array<string | undefined | false | null>) {\n return parts.filter(Boolean).join(' ');\n}\n\nexport default function SwipeRow({\n items,\n children,\n ariaLabel = 'Scrollable content',\n className,\n gapClassName,\n snap = true,\n pageFactor = 0.9,\n showControls = 'auto',\n id,\n classNames,\n scrollerStyle,\n }: SwipeRowProps) {\n const scrollerRef = useRef<HTMLDivElement | null>(null);\n\n const [canLeft, setCanLeft] = useState(false);\n const [canRight, setCanRight] = useState(false);\n const [controlsOn, setControlsOn] = useState(showControls === 'always');\n\n const autoId = useId();\n const regionId = id ?? autoId;\n\n const content = useMemo(() => {\n if (items) return items;\n return React.Children.toArray(children);\n }, [items, children]);\n\n // Enable/disable arrows based on scroll position\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el) return;\n\n const update = () => {\n // tolerance: helps avoid off-by-1 due to subpixel rounding\n const max = el.scrollWidth - el.clientWidth - 1;\n setCanLeft(el.scrollLeft > 0);\n setCanRight(el.scrollLeft < max);\n };\n\n update();\n el.addEventListener('scroll', update, { passive: true });\n window.addEventListener('resize', update);\n\n return () => {\n el.removeEventListener('scroll', update);\n window.removeEventListener('resize', update);\n };\n }, []);\n\n // Decide when to show controls (desktop-ish)\n useEffect(() => {\n if (showControls !== 'auto') {\n setControlsOn(showControls === 'always');\n return;\n }\n\n const mq = window.matchMedia('(hover: hover) and (pointer: fine)');\n const set = () => setControlsOn(mq.matches);\n\n set();\n\n // Safari fallback\n if (mq.addEventListener) mq.addEventListener('change', set);\n // eslint-disable-next-line deprecation/deprecation\n else mq.addListener?.(set);\n\n return () => {\n if (mq.removeEventListener) mq.removeEventListener('change', set);\n // eslint-disable-next-line deprecation/deprecation\n else mq.removeListener?.(set);\n };\n }, [showControls]);\n\n const page = (dir: -1 | 1) => {\n const el = scrollerRef.current;\n if (!el) return;\n const step = Math.round(el.clientWidth * pageFactor);\n el.scrollBy({ left: dir * step, behavior: 'smooth' });\n };\n\n // Keyboard paging (a11y)\n const onKeyDown = (e: React.KeyboardEvent) => {\n const el = scrollerRef.current;\n if (!el) return;\n const step = Math.round(el.clientWidth * pageFactor);\n\n if (e.key === 'ArrowRight') {\n e.preventDefault();\n el.scrollBy({ left: step, behavior: 'smooth' });\n }\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n el.scrollBy({ left: -step, behavior: 'smooth' });\n }\n };\n\n return (\n <div className={cx('rsr-root', className, classNames?.root)}>\n <div\n ref={scrollerRef}\n role=\"region\"\n aria-label={ariaLabel}\n tabIndex={0}\n onKeyDown={onKeyDown}\n className={cx(\n 'rsr-scroller',\n snap && 'rsr-snap',\n gapClassName,\n classNames?.scroller\n )}\n style={{\n WebkitOverflowScrolling: 'touch',\n // matches your original (optional, but harmless)\n scrollbarGutter: 'stable both-edges',\n ...scrollerStyle,\n }}\n id={regionId}\n >\n {content.map((node, i) => (\n <div\n key={i}\n className={cx('rsr-item', snap && 'rsr-snap-item', classNames?.item)}\n >\n {node}\n </div>\n ))}\n </div>\n\n {controlsOn && (\n <>\n <button\n type=\"button\"\n onClick={() => page(-1)}\n disabled={!canLeft}\n aria-controls={regionId}\n aria-label=\"Scroll left\"\n className={cx(\n 'rsr-control',\n 'rsr-prev',\n classNames?.controlButton,\n classNames?.prevButton\n )}\n >\n ‹\n </button>\n\n <button\n type=\"button\"\n onClick={() => page(1)}\n disabled={!canRight}\n aria-controls={regionId}\n aria-label=\"Scroll right\"\n className={cx(\n 'rsr-control',\n 'rsr-next',\n classNames?.controlButton,\n classNames?.nextButton\n )}\n >\n ›\n </button>\n </>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["_a"]}
1
+ {"version":3,"sources":["../src/SwipeRow.tsx"],"sourcesContent":["'use client';\n\nimport React, { useEffect, useId, useMemo, useRef, useState } from 'react';\n\nexport type ShowControlsMode = 'auto' | 'always' | 'never';\n\nexport type SwipeRowClassNames = {\n /** Outer wrapper around the scroller + controls */\n root?: string;\n /** The horizontal scroller element */\n scroller?: string;\n /** Wrapper around each item (the snap target) */\n item?: string;\n /** Shared class applied to both buttons */\n controlButton?: string;\n /** Prev button */\n prevButton?: string;\n /** Next button */\n nextButton?: string;\n};\n\nexport type SwipeRowProps = {\n /** Optional array of React nodes (alternative to children) */\n items?: React.ReactNode[];\n children?: React.ReactNode;\n\n ariaLabel?: string;\n\n /** Enable CSS scroll-snap */\n snap?: boolean;\n\n /** How far arrows / keyboard page (fraction of visible width) */\n pageFactor?: number;\n\n /** When to show left/right controls */\n showControls?: ShowControlsMode;\n\n /** Optional stable id for aria-controls */\n id?: string;\n\n /** Extra class on outer wrapper */\n className?: string;\n\n /**\n * Spacing between items.\n * This is a class hook (NOT Tailwind-specific). For non-Tailwind consumers,\n * they'll typically use the provided default CSS and ignore this.\n */\n gapClassName?: string;\n\n /** More granular class hooks */\n classNames?: SwipeRowClassNames;\n\n /**\n * Optional inline style passthrough for the scroller.\n * Useful for consumers that want scrollbarGutter, etc.\n */\n scrollerStyle?: React.CSSProperties;\n};\n\nfunction cx(...parts: Array<string | undefined | false | null>) {\n return parts.filter(Boolean).join(' ');\n}\n\nexport default function SwipeRow({\n items,\n children,\n ariaLabel = 'Scrollable content',\n className,\n gapClassName,\n snap = true,\n pageFactor = 0.9,\n showControls = 'auto',\n id,\n classNames,\n scrollerStyle,\n }: SwipeRowProps) {\n const scrollerRef = useRef<HTMLDivElement | null>(null);\n\n const [canLeft, setCanLeft] = useState(false);\n const [canRight, setCanRight] = useState(false);\n const [controlsOn, setControlsOn] = useState(showControls === 'always');\n\n const autoId = useId();\n const regionId = id ?? autoId;\n\n const content = useMemo(() => {\n if (items) return items;\n return React.Children.toArray(children);\n }, [items, children]);\n\n // Enable/disable arrows based on scroll position\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el) return;\n\n const update = () => {\n // tolerance: helps avoid off-by-1 due to subpixel rounding\n const max = el.scrollWidth - el.clientWidth - 1;\n setCanLeft(el.scrollLeft > 0);\n setCanRight(el.scrollLeft < max);\n };\n\n update();\n el.addEventListener('scroll', update, { passive: true });\n window.addEventListener('resize', update);\n\n return () => {\n el.removeEventListener('scroll', update);\n window.removeEventListener('resize', update);\n };\n }, []);\n\n // Decide when to show controls (desktop-ish)\n useEffect(() => {\n if (showControls !== 'auto') {\n setControlsOn(showControls === 'always');\n return;\n }\n\n const mq = window.matchMedia('(hover: hover) and (pointer: fine)');\n const set = () => setControlsOn(mq.matches);\n\n set();\n\n // Safari fallback\n if (mq.addEventListener) mq.addEventListener('change', set);\n // eslint-disable-next-line deprecation/deprecation\n else mq.addListener?.(set);\n\n return () => {\n if (mq.removeEventListener) mq.removeEventListener('change', set);\n // eslint-disable-next-line deprecation/deprecation\n else mq.removeListener?.(set);\n };\n }, [showControls]);\n\n const page = (dir: -1 | 1) => {\n const el = scrollerRef.current;\n if (!el) return;\n const step = Math.round(el.clientWidth * pageFactor);\n el.scrollBy({ left: dir * step, behavior: 'smooth' });\n };\n\n // Keyboard paging (a11y)\n const onKeyDown = (e: React.KeyboardEvent) => {\n const el = scrollerRef.current;\n if (!el) return;\n const step = Math.round(el.clientWidth * pageFactor);\n\n if (e.key === 'ArrowRight') {\n e.preventDefault();\n el.scrollBy({ left: step, behavior: 'smooth' });\n }\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n el.scrollBy({ left: -step, behavior: 'smooth' });\n }\n };\n\n return (\n <div className={cx('rsr-root', className, classNames?.root)}>\n <div\n ref={scrollerRef}\n role=\"region\"\n aria-label={ariaLabel}\n tabIndex={0}\n onKeyDown={onKeyDown}\n className={cx(\n 'rsr-scroller',\n snap && 'rsr-snap',\n gapClassName,\n classNames?.scroller\n )}\n style={{\n WebkitOverflowScrolling: 'touch',\n // matches your original (optional, but harmless)\n scrollbarGutter: 'stable both-edges',\n ...scrollerStyle,\n }}\n id={regionId}\n >\n {content.map((node, i) => (\n <div\n key={i}\n className={cx('rsr-item', snap && 'rsr-snap-item', classNames?.item)}\n >\n {node}\n </div>\n ))}\n </div>\n\n {controlsOn && (\n <>\n <button\n type=\"button\"\n onClick={() => page(-1)}\n disabled={!canLeft}\n aria-controls={regionId}\n aria-label=\"Scroll left\"\n className={cx(\n 'rsr-control',\n 'rsr-prev',\n classNames?.controlButton,\n classNames?.prevButton\n )}\n >\n ‹\n </button>\n\n <button\n type=\"button\"\n onClick={() => page(1)}\n disabled={!canRight}\n aria-controls={regionId}\n aria-label=\"Scroll right\"\n className={cx(\n 'rsr-control',\n 'rsr-next',\n classNames?.controlButton,\n classNames?.nextButton\n )}\n >\n ›\n </button>\n </>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["_a"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodmanlabs/react-swipe-row",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "author": "Glenn Goodman",
5
5
  "description": "A native-feeling horizontal scroll-snap card rail for React",
6
6
  "license": "MIT",