swipe-row 1.0.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 ADDED
@@ -0,0 +1,143 @@
1
+ # React Swipe Row Component 🚀
2
+
3
+ A highly customizable, iOS-style swipeable row component for React applications. Built with `framer-motion` for buttery-smooth spring physics animations. Perfect for creating lists with interactive hidden actions like "Archive", "Delete", or "Reply".
4
+
5
+ ![npm version](https://img.shields.io/npm/v/swipe-row)
6
+ ![React](https://img.shields.io/badge/react-%5E18.2.0-blue)
7
+ ![TypeScript](https://img.shields.io/badge/TypeScript-%5E5.2.2-blue)
8
+ ![License](https://img.shields.io/badge/license-MIT-green)
9
+
10
+ ---
11
+
12
+ ## ✨ Features
13
+
14
+ - **Fluid Animations:** Powered by [Framer Motion](https://www.framer.com/motion/) with native-feeling spring physics.
15
+ - **Dynamic Actions:** Pass an unlimited number of custom action buttons (Edit, Delete, Archive, etc.).
16
+ - **Automatic Styling:** Built-in basic styling with CSS Modules so it just works out of the box without polluting global scopes.
17
+ - **Dark Mode Support:** Automatically detects system preferences and adjusts action background colors.
18
+ - **Fully Typed:** Written in TypeScript for excellent Developer Experience and IntelliSense.
19
+ - **Zero Config:** Auto-calculates swipe distances based on your button widths.
20
+
21
+ ---
22
+
23
+ ## 📦 Installation
24
+
25
+ ```bash
26
+ npm install swipe-row framer-motion
27
+ # or
28
+ yarn add swipe-row framer-motion
29
+ # or
30
+ pnpm add swipe-row framer-motion
31
+ ```
32
+
33
+ *Note: `framer-motion` is required as a peer dependency for animations.*
34
+
35
+ ---
36
+
37
+ ## 💻 Usage
38
+
39
+ First, import the component and the necessary CSS styles into your React file:
40
+
41
+ ```tsx
42
+ import { SwipeRow } from 'swipe-row';
43
+ import 'swipe-row/style.css'; // Important for default styling!
44
+ ```
45
+
46
+ ### Basic Example (Single Action)
47
+
48
+ ```tsx
49
+ function BasicList() {
50
+ return (
51
+ <SwipeRow
52
+ actions={[
53
+ {
54
+ label: 'Delete',
55
+ onClick: () => console.log('Deleted!'),
56
+ backgroundColor: '#ef4444', // Tailwind red-500
57
+ }
58
+ ]}
59
+ >
60
+ <div style={{ padding: '16px' }}>
61
+ Swipe me to the left!
62
+ </div>
63
+ </SwipeRow>
64
+ );
65
+ }
66
+ ```
67
+
68
+ ### Advanced Example (Multiple Actions)
69
+
70
+ You can pass multiple action objects. The component will automatically calculate how far the user needs to swipe.
71
+
72
+ ```tsx
73
+ function EmailList() {
74
+ const handleArchive = () => alert('Archived');
75
+ const handleReply = () => alert('Replying...');
76
+
77
+ return (
78
+ <SwipeRow
79
+ actions={[
80
+ {
81
+ label: 'Reply',
82
+ onClick: handleReply,
83
+ backgroundColor: '#3b82f6', // Tailwind blue-500
84
+ width: 80, // Default is 80px
85
+ },
86
+ {
87
+ label: 'Archive',
88
+ onClick: handleArchive,
89
+ backgroundColor: '#f59e0b', // Tailwind amber-500
90
+ width: 90,
91
+ }
92
+ ]}
93
+ >
94
+ <div style={{ padding: '20px', borderBottom: '1px solid #eee' }}>
95
+ <h4>Job Application Updates</h4>
96
+ <p>You have successfully submitted your resume...</p>
97
+ </div>
98
+ </SwipeRow>
99
+ );
100
+ }
101
+ ```
102
+
103
+ ---
104
+
105
+ ## 🛠 Props
106
+
107
+ ### `SwipeRow`
108
+
109
+ | Prop | Type | Default | Description |
110
+ |---|---|---|---|
111
+ | `children` | `React.ReactNode` | **Required** | The main visible content of your row. |
112
+ | `actions` | `SwipeAction[]` | **Required** | Array of action configurations to be revealed on swipe. |
113
+ | `maxSwipe` | `number` | `undefined` | Override the automatic swipe width calculation (px). |
114
+
115
+ ### `SwipeAction` Object
116
+
117
+ Configure each button in the `actions` array:
118
+
119
+ | Property | Type | Default | Description |
120
+ |---|---|---|---|
121
+ | `label` | `React.ReactNode` | **Required** | The text or icon to show inside the button. |
122
+ | `onClick` | `() => void` | **Required** | Function to call when clicked. |
123
+ | `backgroundColor` | `string` | `'#64748b'` | CSS background color for the button. |
124
+ | `color` | `string` | `'white'` | CSS text color. |
125
+ | `width` | `number` | `80` | Width of the button in pixels. Used for auto element calculation. |
126
+ | `className` | `string` | `undefined` | Custom CSS class applied to the button element. |
127
+ | `ariaLabel` | `string` | `label` string value | For screen readers. |
128
+
129
+ ---
130
+
131
+ ## 🧪 Local Development
132
+
133
+ 1. Clone the repository
134
+ 2. Install dependencies: `npm install`
135
+ 3. Start the Vite playground: `npm run dev`
136
+ 4. Run unit tests: `npm run test`
137
+ 5. Build the library: `npm run build`
138
+
139
+ ---
140
+
141
+ ## 📄 License
142
+
143
+ MIT © nahkar - Feel free to use in personal and commercial projects!
@@ -0,0 +1,29 @@
1
+ export type SwipeAction = {
2
+ /** The visual content of the button (e.g. text or icon) */
3
+ label: React.ReactNode;
4
+ /** Callback triggered when this action is clicked */
5
+ onClick: () => void;
6
+ /** Background color for this action button */
7
+ backgroundColor?: string;
8
+ /** Text color for this action button */
9
+ color?: string;
10
+ /** Width of the button. Defaults to 80px */
11
+ width?: number;
12
+ /** Additional CSS class for the button */
13
+ className?: string;
14
+ /** Accessibility label. Defaults to label if it is a string a fallback string */
15
+ ariaLabel?: string;
16
+ };
17
+ export type SwipeRowProps = {
18
+ /** The content to be displayed in the row */
19
+ children: React.ReactNode;
20
+ /** An array of action objects to render behind the row */
21
+ actions: SwipeAction[];
22
+ /** Optional custom swipe threshold. Computed automatically if not provided. */
23
+ maxSwipe?: number;
24
+ };
25
+ /**
26
+ * SwipeRow creates an iOS style swipeable row element that reveals generic actions behind it.
27
+ * Highly configurable and built for generic use across various projects.
28
+ */
29
+ export declare function SwipeRow({ children, actions, maxSwipe }: SwipeRowProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export { SwipeRow } from './SwipeRow';
2
+ export type { SwipeRowProps } from './SwipeRow';
@@ -0,0 +1 @@
1
+ export * from './SwipeRow';
@@ -0,0 +1 @@
1
+ export * from './components';
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ ._container_1y7jq_1{position:relative;overflow:hidden;border-radius:12px;background-color:#f3f4f6;touch-action:pan-y;-webkit-user-select:none;user-select:none;box-shadow:0 2px 8px #0000000d}._actionsBackground_1y7jq_11{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;justify-content:flex-end;background-color:#f3f4f6}._actionButton_1y7jq_19{display:flex;align-items:center;justify-content:center;border:none;font-family:inherit;font-size:14px;font-weight:500;cursor:pointer;transition:filter .2s}._actionButton_1y7jq_19:hover{filter:brightness(.9)}._foreground_1y7jq_35{position:relative;background-color:#fff;padding:16px;width:100%;box-sizing:border-box;border-radius:12px;box-shadow:-2px 0 10px #00000008}@media (prefers-color-scheme: dark){._container_1y7jq_1,._actionsBackground_1y7jq_11{background-color:#171717}._foreground_1y7jq_35{background-color:#262626;color:#fff}}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),e=require("framer-motion"),u=require("react"),b="_container_1y7jq_1",p="_actionsBackground_1y7jq_11",_="_actionButton_1y7jq_19",j="_foreground_1y7jq_35",s={container:b,actionsBackground:p,actionButton:_,foreground:j};function h({children:l,actions:c,maxSwipe:i}){const o=e.useMotionValue(0),d=u.useRef(null),g=u.useMemo(()=>-c.reduce((n,r)=>n+(r.width||80),0),[c]),t=i!==void 0?i:g,f=e.useTransform(o,[t/2,0],[1,0]),m=()=>{o.get()<t/2?e.animate(o,t,{type:"spring",bounce:0,duration:.3}):e.animate(o,0,{type:"spring",bounce:0,duration:.3})};return a.jsxs("div",{ref:d,className:s.container,children:[a.jsx(e.motion.div,{style:{opacity:f},className:s.actionsBackground,children:c.map((n,r)=>{const y=typeof n.label=="string"?n.label:`Action ${r}`;return a.jsx("button",{onClick:n.onClick,className:`${s.actionButton} ${n.className||""}`.trim(),style:{width:n.width||80,backgroundColor:n.backgroundColor||"#64748b",color:n.color||"white"},"aria-label":n.ariaLabel||y,children:n.label},r)})}),a.jsx(e.motion.div,{drag:"x",dragConstraints:{left:t,right:0},dragElastic:.1,style:{x:o},onDragEnd:m,className:s.foreground,children:l})]})}exports.SwipeRow=h;
2
+ //# sourceMappingURL=swipe-row.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swipe-row.cjs.js","sources":["../src/components/SwipeRow/SwipeRow.tsx"],"sourcesContent":["import { motion, useMotionValue, useTransform, animate } from 'framer-motion';\nimport { useRef, useMemo } from 'react';\nimport styles from './SwipeRow.module.css';\n\nexport type SwipeAction = {\n /** The visual content of the button (e.g. text or icon) */\n label: React.ReactNode;\n /** Callback triggered when this action is clicked */\n onClick: () => void;\n /** Background color for this action button */\n backgroundColor?: string;\n /** Text color for this action button */\n color?: string;\n /** Width of the button. Defaults to 80px */\n width?: number;\n /** Additional CSS class for the button */\n className?: string;\n /** Accessibility label. Defaults to label if it is a string a fallback string */\n ariaLabel?: string;\n};\n\nexport type SwipeRowProps = {\n /** The content to be displayed in the row */\n children: React.ReactNode;\n /** An array of action objects to render behind the row */\n actions: SwipeAction[];\n /** Optional custom swipe threshold. Computed automatically if not provided. */\n maxSwipe?: number;\n};\n\n/**\n * SwipeRow creates an iOS style swipeable row element that reveals generic actions behind it.\n * Highly configurable and built for generic use across various projects.\n */\nexport function SwipeRow({ children, actions, maxSwipe }: SwipeRowProps) {\n const x = useMotionValue(0);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const calculatedMaxSwipe = useMemo(() => {\n return -actions.reduce((acc, action) => acc + (action.width || 80), 0);\n }, [actions]);\n\n const swipeDistance = maxSwipe !== undefined ? maxSwipe : calculatedMaxSwipe;\n\n const backgroundOpacity = useTransform(x, [swipeDistance / 2, 0], [1, 0]);\n\n const handleDragEnd = () => {\n const current = x.get();\n\n // Swipe threshold to snap open\n if (current < swipeDistance / 2) {\n animate(x, swipeDistance, { type: 'spring', bounce: 0, duration: 0.3 });\n } else {\n animate(x, 0, { type: 'spring', bounce: 0, duration: 0.3 });\n }\n };\n\n return (\n <div ref={containerRef} className={styles.container}>\n {/* ACTIONS BACKGROUND */}\n <motion.div\n style={{ opacity: backgroundOpacity }}\n className={styles.actionsBackground}\n >\n {actions.map((action, index) => {\n const defaultAria = typeof action.label === 'string' ? action.label : `Action ${index}`;\n return (\n <button\n key={index}\n onClick={action.onClick}\n className={`${styles.actionButton} ${action.className || ''}`.trim()}\n style={{\n width: action.width || 80,\n backgroundColor: action.backgroundColor || '#64748b', // Slate\n color: action.color || 'white',\n }}\n aria-label={action.ariaLabel || defaultAria}\n >\n {action.label}\n </button>\n );\n })}\n </motion.div>\n\n {/* FOREGROUND */}\n <motion.div\n drag=\"x\"\n dragConstraints={{ left: swipeDistance, right: 0 }}\n dragElastic={0.1}\n style={{ x }}\n onDragEnd={handleDragEnd}\n className={styles.foreground}\n >\n {children}\n </motion.div>\n </div>\n );\n}\n"],"names":["SwipeRow","children","actions","maxSwipe","x","useMotionValue","containerRef","useRef","calculatedMaxSwipe","useMemo","acc","action","swipeDistance","backgroundOpacity","useTransform","handleDragEnd","animate","styles","jsx","motion","index","defaultAria"],"mappings":"8UAkCO,SAASA,EAAS,CAAE,SAAAC,EAAU,QAAAC,EAAS,SAAAC,GAA2B,CACvE,MAAMC,EAAIC,EAAAA,eAAe,CAAC,EACpBC,EAAeC,EAAAA,OAAuB,IAAI,EAE1CC,EAAqBC,EAAAA,QAAQ,IAC1B,CAACP,EAAQ,OAAO,CAACQ,EAAKC,IAAWD,GAAOC,EAAO,OAAS,IAAK,CAAC,EACpE,CAACT,CAAO,CAAC,EAENU,EAAgBT,IAAa,OAAYA,EAAWK,EAEpDK,EAAoBC,EAAAA,aAAaV,EAAG,CAACQ,EAAgB,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,CAAC,EAElEG,EAAgB,IAAM,CACVX,EAAE,IAAA,EAGJQ,EAAgB,EAC5BI,UAAQZ,EAAGQ,EAAe,CAAE,KAAM,SAAU,OAAQ,EAAG,SAAU,GAAK,EAEtEI,UAAQZ,EAAG,EAAG,CAAE,KAAM,SAAU,OAAQ,EAAG,SAAU,GAAK,CAE9D,EAEA,cACG,MAAA,CAAI,IAAKE,EAAc,UAAWW,EAAO,UAExC,SAAA,CAAAC,EAAAA,IAACC,EAAAA,OAAO,IAAP,CACC,MAAO,CAAE,QAASN,CAAA,EAClB,UAAWI,EAAO,kBAEjB,SAAAf,EAAQ,IAAI,CAACS,EAAQS,IAAU,CAC9B,MAAMC,EAAc,OAAOV,EAAO,OAAU,SAAWA,EAAO,MAAQ,UAAUS,CAAK,GACrF,OACEF,EAAAA,IAAC,SAAA,CAEC,QAASP,EAAO,QAChB,UAAW,GAAGM,EAAO,YAAY,IAAIN,EAAO,WAAa,EAAE,GAAG,KAAA,EAC9D,MAAO,CACL,MAAOA,EAAO,OAAS,GACvB,gBAAiBA,EAAO,iBAAmB,UAC3C,MAAOA,EAAO,OAAS,OAAA,EAEzB,aAAYA,EAAO,WAAaU,EAE/B,SAAAV,EAAO,KAAA,EAVHS,CAAA,CAaX,CAAC,CAAA,CAAA,EAIHF,EAAAA,IAACC,EAAAA,OAAO,IAAP,CACC,KAAK,IACL,gBAAiB,CAAE,KAAMP,EAAe,MAAO,CAAA,EAC/C,YAAa,GACb,MAAO,CAAE,EAAAR,CAAA,EACT,UAAWW,EACX,UAAWE,EAAO,WAEjB,SAAAhB,CAAA,CAAA,CACH,EACF,CAEJ"}
@@ -0,0 +1,58 @@
1
+ import { jsxs as y, jsx as c } from "react/jsx-runtime";
2
+ import { useMotionValue as b, useTransform as _, motion as i, animate as l } from "framer-motion";
3
+ import { useRef as h, useMemo as k } from "react";
4
+ const B = "_container_1y7jq_1", w = "_actionsBackground_1y7jq_11", j = "_actionButton_1y7jq_19", C = "_foreground_1y7jq_35", e = {
5
+ container: B,
6
+ actionsBackground: w,
7
+ actionButton: j,
8
+ foreground: C
9
+ };
10
+ function x({ children: u, actions: a, maxSwipe: s }) {
11
+ const n = b(0), d = h(null), g = k(() => -a.reduce((o, r) => o + (r.width || 80), 0), [a]), t = s !== void 0 ? s : g, f = _(n, [t / 2, 0], [1, 0]), m = () => {
12
+ n.get() < t / 2 ? l(n, t, { type: "spring", bounce: 0, duration: 0.3 }) : l(n, 0, { type: "spring", bounce: 0, duration: 0.3 });
13
+ };
14
+ return /* @__PURE__ */ y("div", { ref: d, className: e.container, children: [
15
+ /* @__PURE__ */ c(
16
+ i.div,
17
+ {
18
+ style: { opacity: f },
19
+ className: e.actionsBackground,
20
+ children: a.map((o, r) => {
21
+ const p = typeof o.label == "string" ? o.label : `Action ${r}`;
22
+ return /* @__PURE__ */ c(
23
+ "button",
24
+ {
25
+ onClick: o.onClick,
26
+ className: `${e.actionButton} ${o.className || ""}`.trim(),
27
+ style: {
28
+ width: o.width || 80,
29
+ backgroundColor: o.backgroundColor || "#64748b",
30
+ // Slate
31
+ color: o.color || "white"
32
+ },
33
+ "aria-label": o.ariaLabel || p,
34
+ children: o.label
35
+ },
36
+ r
37
+ );
38
+ })
39
+ }
40
+ ),
41
+ /* @__PURE__ */ c(
42
+ i.div,
43
+ {
44
+ drag: "x",
45
+ dragConstraints: { left: t, right: 0 },
46
+ dragElastic: 0.1,
47
+ style: { x: n },
48
+ onDragEnd: m,
49
+ className: e.foreground,
50
+ children: u
51
+ }
52
+ )
53
+ ] });
54
+ }
55
+ export {
56
+ x as SwipeRow
57
+ };
58
+ //# sourceMappingURL=swipe-row.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swipe-row.es.js","sources":["../src/components/SwipeRow/SwipeRow.tsx"],"sourcesContent":["import { motion, useMotionValue, useTransform, animate } from 'framer-motion';\nimport { useRef, useMemo } from 'react';\nimport styles from './SwipeRow.module.css';\n\nexport type SwipeAction = {\n /** The visual content of the button (e.g. text or icon) */\n label: React.ReactNode;\n /** Callback triggered when this action is clicked */\n onClick: () => void;\n /** Background color for this action button */\n backgroundColor?: string;\n /** Text color for this action button */\n color?: string;\n /** Width of the button. Defaults to 80px */\n width?: number;\n /** Additional CSS class for the button */\n className?: string;\n /** Accessibility label. Defaults to label if it is a string a fallback string */\n ariaLabel?: string;\n};\n\nexport type SwipeRowProps = {\n /** The content to be displayed in the row */\n children: React.ReactNode;\n /** An array of action objects to render behind the row */\n actions: SwipeAction[];\n /** Optional custom swipe threshold. Computed automatically if not provided. */\n maxSwipe?: number;\n};\n\n/**\n * SwipeRow creates an iOS style swipeable row element that reveals generic actions behind it.\n * Highly configurable and built for generic use across various projects.\n */\nexport function SwipeRow({ children, actions, maxSwipe }: SwipeRowProps) {\n const x = useMotionValue(0);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const calculatedMaxSwipe = useMemo(() => {\n return -actions.reduce((acc, action) => acc + (action.width || 80), 0);\n }, [actions]);\n\n const swipeDistance = maxSwipe !== undefined ? maxSwipe : calculatedMaxSwipe;\n\n const backgroundOpacity = useTransform(x, [swipeDistance / 2, 0], [1, 0]);\n\n const handleDragEnd = () => {\n const current = x.get();\n\n // Swipe threshold to snap open\n if (current < swipeDistance / 2) {\n animate(x, swipeDistance, { type: 'spring', bounce: 0, duration: 0.3 });\n } else {\n animate(x, 0, { type: 'spring', bounce: 0, duration: 0.3 });\n }\n };\n\n return (\n <div ref={containerRef} className={styles.container}>\n {/* ACTIONS BACKGROUND */}\n <motion.div\n style={{ opacity: backgroundOpacity }}\n className={styles.actionsBackground}\n >\n {actions.map((action, index) => {\n const defaultAria = typeof action.label === 'string' ? action.label : `Action ${index}`;\n return (\n <button\n key={index}\n onClick={action.onClick}\n className={`${styles.actionButton} ${action.className || ''}`.trim()}\n style={{\n width: action.width || 80,\n backgroundColor: action.backgroundColor || '#64748b', // Slate\n color: action.color || 'white',\n }}\n aria-label={action.ariaLabel || defaultAria}\n >\n {action.label}\n </button>\n );\n })}\n </motion.div>\n\n {/* FOREGROUND */}\n <motion.div\n drag=\"x\"\n dragConstraints={{ left: swipeDistance, right: 0 }}\n dragElastic={0.1}\n style={{ x }}\n onDragEnd={handleDragEnd}\n className={styles.foreground}\n >\n {children}\n </motion.div>\n </div>\n );\n}\n"],"names":["SwipeRow","children","actions","maxSwipe","x","useMotionValue","containerRef","useRef","calculatedMaxSwipe","useMemo","acc","action","swipeDistance","backgroundOpacity","useTransform","handleDragEnd","animate","styles","jsx","motion","index","defaultAria"],"mappings":";;;;;;;;;AAkCO,SAASA,EAAS,EAAE,UAAAC,GAAU,SAAAC,GAAS,UAAAC,KAA2B;AACvE,QAAMC,IAAIC,EAAe,CAAC,GACpBC,IAAeC,EAAuB,IAAI,GAE1CC,IAAqBC,EAAQ,MAC1B,CAACP,EAAQ,OAAO,CAACQ,GAAKC,MAAWD,KAAOC,EAAO,SAAS,KAAK,CAAC,GACpE,CAACT,CAAO,CAAC,GAENU,IAAgBT,MAAa,SAAYA,IAAWK,GAEpDK,IAAoBC,EAAaV,GAAG,CAACQ,IAAgB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAElEG,IAAgB,MAAM;AAI1B,IAHgBX,EAAE,IAAA,IAGJQ,IAAgB,IAC5BI,EAAQZ,GAAGQ,GAAe,EAAE,MAAM,UAAU,QAAQ,GAAG,UAAU,KAAK,IAEtEI,EAAQZ,GAAG,GAAG,EAAE,MAAM,UAAU,QAAQ,GAAG,UAAU,KAAK;AAAA,EAE9D;AAEA,2BACG,OAAA,EAAI,KAAKE,GAAc,WAAWW,EAAO,WAExC,UAAA;AAAA,IAAA,gBAAAC;AAAA,MAACC,EAAO;AAAA,MAAP;AAAA,QACC,OAAO,EAAE,SAASN,EAAA;AAAA,QAClB,WAAWI,EAAO;AAAA,QAEjB,UAAAf,EAAQ,IAAI,CAACS,GAAQS,MAAU;AAC9B,gBAAMC,IAAc,OAAOV,EAAO,SAAU,WAAWA,EAAO,QAAQ,UAAUS,CAAK;AACrF,iBACE,gBAAAF;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,SAASP,EAAO;AAAA,cAChB,WAAW,GAAGM,EAAO,YAAY,IAAIN,EAAO,aAAa,EAAE,GAAG,KAAA;AAAA,cAC9D,OAAO;AAAA,gBACL,OAAOA,EAAO,SAAS;AAAA,gBACvB,iBAAiBA,EAAO,mBAAmB;AAAA;AAAA,gBAC3C,OAAOA,EAAO,SAAS;AAAA,cAAA;AAAA,cAEzB,cAAYA,EAAO,aAAaU;AAAA,cAE/B,UAAAV,EAAO;AAAA,YAAA;AAAA,YAVHS;AAAA,UAAA;AAAA,QAaX,CAAC;AAAA,MAAA;AAAA,IAAA;AAAA,IAIH,gBAAAF;AAAA,MAACC,EAAO;AAAA,MAAP;AAAA,QACC,MAAK;AAAA,QACL,iBAAiB,EAAE,MAAMP,GAAe,OAAO,EAAA;AAAA,QAC/C,aAAa;AAAA,QACb,OAAO,EAAE,GAAAR,EAAA;AAAA,QACT,WAAWW;AAAA,QACX,WAAWE,EAAO;AAAA,QAEjB,UAAAhB;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GACF;AAEJ;"}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "swipe-row",
3
+ "version": "1.0.0",
4
+ "description": "A highly customizable, iOS-style swipeable row component for React applications.",
5
+ "type": "module",
6
+ "main": "./dist/swipe-row.cjs.js",
7
+ "module": "./dist/swipe-row.es.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/swipe-row.es.js",
12
+ "require": "./dist/swipe-row.cjs.js",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./style.css": "./dist/style.css"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "dev": "vite",
22
+ "build": "tsc && vite build",
23
+ "test": "vitest run",
24
+ "test:ui": "vitest --ui"
25
+ },
26
+ "peerDependencies": {
27
+ "react": ">=18.2.0",
28
+ "react-dom": ">=18.2.0"
29
+ },
30
+ "devDependencies": {
31
+ "@testing-library/dom": "^10.4.1",
32
+ "@testing-library/jest-dom": "^6.9.1",
33
+ "@testing-library/react": "^16.3.2",
34
+ "@types/node": "^25.3.0",
35
+ "@types/react": "^18.2.0",
36
+ "@types/react-dom": "^18.2.0",
37
+ "@vitejs/plugin-react": "^4.2.0",
38
+ "@vitest/ui": "^3.2.4",
39
+ "jsdom": "^27.0.1",
40
+ "typescript": "^5.2.2",
41
+ "vite": "^5.0.0",
42
+ "vite-plugin-dts": "^3.9.0",
43
+ "vitest": "^3.2.4"
44
+ },
45
+ "keywords": [
46
+ "react",
47
+ "framer-motion",
48
+ "swipe",
49
+ "swipeable",
50
+ "list",
51
+ "row",
52
+ "ios",
53
+ "gesture",
54
+ "components"
55
+ ],
56
+ "author": "nahkar",
57
+ "repository": {
58
+ "type": "git",
59
+ "url": "https://github.com/nahkar/swipe-row.git"
60
+ },
61
+ "bugs": {
62
+ "url": "https://github.com/nahkar/swipe-row/issues"
63
+ },
64
+ "homepage": "https://github.com/nahkar/swipe-row#readme",
65
+ "license": "MIT",
66
+ "dependencies": {
67
+ "framer-motion": "^12.34.3"
68
+ }
69
+ }