npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@cniot/rn-swiper-code

v0.1.9

Published

@cniot/rn-swiper-code

Readme

React Native TripSwiper

一个用于展示和滑动切换行程信息的React Native组件,支持自定义内容、滑动切换和点击导航。

特性

  • 🎨 支持多个行程卡片的滑动切换
  • 📏 支持左右滑动和点击小圆点切换行程
  • 🔄 流畅的动画过渡效果
  • 🌐 完全可定制的UI样式
  • ⏳ 支持自定义渲染内容
  • 🎯 完全类型化的 TypeScript 支持
  • 📱 适配不同屏幕尺寸
  • 🔌 易于集成到现有项目中

安装

# 使用 npm
npm install @cniot/rn-swiper-code

# 使用 yarn
yarn add @cniot/rn-swiper-code

在线预览

您可以使用以下react-live代码在线预览TripSwiper组件的效果,预览界面会模拟iPhone 15的外观,让您能够直观地看到组件在移动设备上的显示效果。

// 引入必要的依赖
import React from 'react';
import { View, Text, StyleSheet, Image } from 'react-native';
import { RNTripSwiper } from '@cniot/rn-swiper-code';

// iPhone 15 样式容器
const IPhoneFrame = ({ children }) => (
  <div style={{
    width: 375,
    height: 812,
    margin: '0 auto',
    position: 'relative',
    overflow: 'hidden',
    borderRadius: 44,
    backgroundColor: 'white',
    boxShadow: '0 0 0 11px #1a1a1a, 0 0 0 13px #000, 0 0 34px rgba(0, 0, 0, 0.2)',
  }}>
    {/* 顶部刘海 */}
    <div style={{
      position: 'absolute',
      top: 0,
      left: '50%',
      transform: 'translateX(-50%)',
      width: 160,
      height: 34,
      backgroundColor: '#000',
      borderBottomLeftRadius: 18,
      borderBottomRightRadius: 18,
      zIndex: 10,
    }}></div>
    
    {/* 状态栏 */}
    <div style={{
      height: 44,
      width: '100%',
      backgroundColor: '#f8f8f8',
      display: 'flex',
      justifyContent: 'space-between',
      alignItems: 'center',
      padding: '0 20px',
      boxSizing: 'border-box',
      fontSize: 12,
      color: '#000',
      fontWeight: 'bold',
      zIndex: 5,
    }}>
      <span>9:41</span>
      <div style={{ display: 'flex', gap: 5 }}>
        <span>📶</span>
        <span>📡</span>
        <span>🔋</span>
      </div>
    </div>
    
    {/* 内容区域 */}
    <div style={{
      height: 'calc(100% - 44px)',
      width: '100%',
      overflow: 'hidden',
      backgroundColor: '#f8f8f8',
    }}>
      {children}
    </div>
  </div>
);

// 示例组件
const Example = () => {
  const tripData = [
    {
      title: '行程信息',
      items: [
        { label: '行程编号', value: 'TC-001' },
        { label: '计划出发时间', value: '8:00:00' },
        { label: '路线代码', value: 'TC-Route' },
      ],
    },
    {
      title: '行程信息',
      items: [
        { label: '行程编号', value: 'TC-002' },
        { label: '计划出发时间', value: '10:30:00' },
        { label: '路线代码', value: 'TC-Route' },
      ],
    },
  ];

  return (
    <IPhoneFrame>
      <View style={{ flex: 1, padding: 16 }}>
        <RNTripSwiper tripData={tripData} />
      </View>
    </IPhoneFrame>
  );
};

// 渲染示例
render(<Example />);

提示:在实际的react-live环境中,您可以左右滑动或点击底部的小圆点来切换不同的行程卡片。

必要依赖

本组件库依赖以下基础包,这些包通常在 React Native 项目中已经存在:

  • react (>=16.8.0)
  • react-native (>=0.60.0)
  • expo-status-bar (如果使用Expo)

注意:本组件使用了React Hooks,因此要求React版本不低于16.8.0。

使用指南

基本用法

import React from 'react';
import { View } from 'react-native';
import { RNTripSwiper } from '@cniot/rn-swiper-code';

const MyComponent = () => {
  return (
    <View style={{ padding: 16 }}>
      <RNTripSwiper
        tripData={[
          {
            title: '行程信息',
            items: [
              { label: '行程编号', value: 'TC-001' },
              { label: '计划出发时间', value: '8:00:00' },
              { label: '路线代码', value: 'TC-Route' },
            ],
          },
          {
            title: '行程信息',
            items: [
              { label: '行程编号', value: 'TC-002' },
              { label: '计划出发时间', value: '10:30:00' },
              { label: '路线代码', value: 'TC-Route' },
            ],
          }
        ]}
      />
    </View>
  );
};

export default MyComponent;

自定义渲染单个内容项

以下示例展示了如何自定义渲染单个内容项,并在iPhone 15模拟器中预览效果:

// 引入必要的依赖
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { RNTripSwiper } from '@cniot/rn-swiper-code';

// iPhone 15 样式容器
const IPhoneFrame = ({ children }) => (
  <div style={{
    width: 375,
    height: 812,
    margin: '0 auto',
    position: 'relative',
    overflow: 'hidden',
    borderRadius: 44,
    backgroundColor: 'white',
    boxShadow: '0 0 0 11px #1a1a1a, 0 0 0 13px #000, 0 0 34px rgba(0, 0, 0, 0.2)',
  }}>
    {/* 顶部刘海 */}
    <div style={{
      position: 'absolute',
      top: 0,
      left: '50%',
      transform: 'translateX(-50%)',
      width: 160,
      height: 34,
      backgroundColor: '#000',
      borderBottomLeftRadius: 18,
      borderBottomRightRadius: 18,
      zIndex: 10,
    }}></div>
    
    {/* 状态栏 */}
    <div style={{
      height: 44,
      width: '100%',
      backgroundColor: '#f8f8f8',
      display: 'flex',
      justifyContent: 'space-between',
      alignItems: 'center',
      padding: '0 20px',
      boxSizing: 'border-box',
      fontSize: 12,
      color: '#000',
      fontWeight: 'bold',
      zIndex: 5,
    }}>
      <span>9:41</span>
      <div style={{ display: 'flex', gap: 5 }}>
        <span>📶</span>
        <span>📡</span>
        <span>🔋</span>
      </div>
    </div>
    
    {/* 内容区域 */}
    <div style={{
      height: 'calc(100% - 44px)',
      width: '100%',
      overflow: 'hidden',
      backgroundColor: '#f8f8f8',
    }}>
      {children}
    </div>
  </div>
);

// 示例组件
const CustomItemExample = () => {
  // 自定义样式
  const styles = {
    customItem: {
      flexDirection: 'row',
      justifyContent: 'space-between',
      alignItems: 'center',
      width: '100%',
    },
    customLabel: {
      fontSize: 14,
      color: '#1A2138',
      fontWeight: '500',
    },
    customValueContainer: {
      flexDirection: 'row',
      alignItems: 'center',
    },
    customValue: {
      fontSize: 14,
      color: '#1A2138',
      fontWeight: 'bold',
      marginRight: 8,
    },
    badge: {
      backgroundColor: '#FF6B6B',
      paddingHorizontal: 6,
      paddingVertical: 2,
      borderRadius: 4,
    },
    badgeText: {
      color: 'white',
      fontSize: 10,
      fontWeight: 'bold',
    },
  };

  const tripData = [
    {
      title: '行程信息',
      items: [
        {
          label: '行程编号',
          value: 'TC-001',
          render: () => (
            <View style={styles.customItem}>
              <Text style={styles.customLabel}>行程编号</Text>
              <View style={styles.customValueContainer}>
                <Text style={styles.customValue}>TC-001</Text>
                <View style={styles.badge}>
                  <Text style={styles.badgeText}>VIP</Text>
                </View>
              </View>
            </View>
          ),
        },
        { label: '计划出发时间', value: '8:00:00' },
        { label: '路线代码', value: 'TC-Route' },
      ],
    },
    {
      title: '行程信息',
      items: [
        {
          label: '行程编号',
          value: 'TC-002',
          render: () => (
            <View style={styles.customItem}>
              <Text style={styles.customLabel}>行程编号</Text>
              <View style={styles.customValueContainer}>
                <Text style={styles.customValue}>TC-002</Text>
                <View style={styles.badge}>
                  <Text style={styles.badgeText}>普通</Text>
                </View>
              </View>
            </View>
          ),
        },
        { label: '计划出发时间', value: '10:30:00' },
        { label: '路线代码', value: 'TC-Route' },
      ],
    },
  ];

  return (
    <IPhoneFrame>
      <View style={{ flex: 1, padding: 16 }}>
        <RNTripSwiper tripData={tripData} />
      </View>
    </IPhoneFrame>
  );
};

// 渲染示例
render(<CustomItemExample />);

以下是常规代码示例,您可以复制到您的项目中:

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { RNTripSwiper } from '@cniot/rn-swiper-code';

const MyComponent = () => {
  const tripData = [
    {
      title: '行程信息',
      items: [
        {
          label: '行程编号',
          value: 'TC-001',
          render: () => (
            <View style={styles.customItem}>
              <Text style={styles.customLabel}>行程编号</Text>
              <View style={styles.customValueContainer}>
                <Text style={styles.customValue}>TC-001</Text>
                <View style={styles.badge}>
                  <Text style={styles.badgeText}>VIP</Text>
                </View>
              </View>
            </View>
          ),
        },
        { label: '计划出发时间', value: '8:00:00' },
        { label: '路线代码', value: 'TC-Route' },
      ],
    },
    // 更多行程...
  ];

  return (
    <View style={{ flex: 1 }}>
      <RNTripSwiper tripData={tripData} />
    </View>
  );
};

const styles = StyleSheet.create({
  customItem: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    width: '100%',
  },
  customLabel: {
    fontSize: 14,
    color: '#1A2138',
    fontWeight: '500',
  },
  customValueContainer: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  customValue: {
    fontSize: 14,
    color: '#1A2138',
    fontWeight: 'bold',
    marginRight: 8,
  },
  badge: {
    backgroundColor: '#FF6B6B',
    paddingHorizontal: 6,
    paddingVertical: 2,
    borderRadius: 4,
  },
  badgeText: {
    color: 'white',
    fontSize: 10,
    fontWeight: 'bold',
  },
});

export default MyComponent;

自定义整个内容区域

以下示例展示了如何自定义整个内容区域,并在iPhone 15模拟器中预览效果:

// 引入必要的依赖
import React from 'react';
import { View, Text, StyleSheet, Image } from 'react-native';
import { RNTripSwiper } from '@cniot/rn-swiper-code';

// iPhone 15 样式容器
const IPhoneFrame = ({ children }) => (
  <div style={{
    width: 375,
    height: 812,
    margin: '0 auto',
    position: 'relative',
    overflow: 'hidden',
    borderRadius: 44,
    backgroundColor: 'white',
    boxShadow: '0 0 0 11px #1a1a1a, 0 0 0 13px #000, 0 0 34px rgba(0, 0, 0, 0.2)',
  }}>
    {/* 顶部刘海 */}
    <div style={{
      position: 'absolute',
      top: 0,
      left: '50%',
      transform: 'translateX(-50%)',
      width: 160,
      height: 34,
      backgroundColor: '#000',
      borderBottomLeftRadius: 18,
      borderBottomRightRadius: 18,
      zIndex: 10,
    }}></div>
    
    {/* 状态栏 */}
    <div style={{
      height: 44,
      width: '100%',
      backgroundColor: '#f8f8f8',
      display: 'flex',
      justifyContent: 'space-between',
      alignItems: 'center',
      padding: '0 20px',
      boxSizing: 'border-box',
      fontSize: 12,
      color: '#000',
      fontWeight: 'bold',
      zIndex: 5,
    }}>
      <span>9:41</span>
      <div style={{ display: 'flex', gap: 5 }}>
        <span>📶</span>
        <span>📡</span>
        <span>🔋</span>
      </div>
    </div>
    
    {/* 内容区域 */}
    <div style={{
      height: 'calc(100% - 44px)',
      width: '100%',
      overflow: 'hidden',
      backgroundColor: '#f8f8f8',
    }}>
      {children}
    </div>
  </div>
);

// 示例组件
const CustomContentExample = () => {
  // 自定义样式
  const styles = {
    customContent: {
      backgroundColor: '#F5F7FA',
      borderRadius: 8,
      padding: 12,
    },
    customRow: {
      flexDirection: 'row',
      justifyContent: 'space-between',
      alignItems: 'center',
      paddingVertical: 10,
    },
    customRowLabel: {
      fontSize: 14,
      color: '#1A2138',
      fontWeight: '500',
    },
    customRowValue: {
      fontSize: 14,
      color: '#1A2138',
      fontWeight: 'bold',
    },
    divider: {
      height: 1,
      backgroundColor: '#E2E8F0',
      width: '100%',
    },
    transportContainer: {
      flexDirection: 'row',
      alignItems: 'center',
    },
    transportIcon: {
      width: 20,
      height: 20,
      marginRight: 8,
    },
  };

  const tripData = [
    {
      title: '行程信息',
      items: [
        { label: '行程编号', value: 'TC-001' },
        { label: '计划出发时间', value: '8:00:00' },
      ],
    },
    {
      title: '行程信息',
      renderContent: () => (
        <View style={styles.customContent}>
          <View style={styles.customRow}>
            <Text style={styles.customRowLabel}>目的地</Text>
            <Text style={styles.customRowValue}>上海</Text>
          </View>
          <View style={styles.divider} />
          <View style={styles.customRow}>
            <Text style={styles.customRowLabel}>出发时间</Text>
            <Text style={styles.customRowValue}>9:30:00</Text>
          </View>
          <View style={styles.divider} />
          <View style={styles.customRow}>
            <Text style={styles.customRowLabel}>交通方式</Text>
            <View style={styles.transportContainer}>
              <Image
                source={{ uri: 'https://via.placeholder.com/20' }}
                style={styles.transportIcon}
              />
              <Text style={styles.customRowValue}>高铁</Text>
            </View>
          </View>
        </View>
      ),
    },
  ];

  return (
    <IPhoneFrame>
      <View style={{ flex: 1, padding: 16 }}>
        <RNTripSwiper tripData={tripData} />
      </View>
    </IPhoneFrame>
  );
};

// 渲染示例
render(<CustomContentExample />);

以下是常规代码示例,您可以复制到您的项目中:

import React from 'react';
import { View, Text, StyleSheet, Image } from 'react-native';
import { RNTripSwiper } from '@cniot/rn-swiper-code';

const MyComponent = () => {
  const tripData = [
    {
      title: '行程信息',
      items: [
        { label: '行程编号', value: 'TC-001' },
        { label: '计划出发时间', value: '8:00:00' },
      ],
    },
    {
      title: '行程信息',
      renderContent: () => (
        <View style={styles.customContent}>
          <View style={styles.customRow}>
            <Text style={styles.customRowLabel}>目的地</Text>
            <Text style={styles.customRowValue}>上海</Text>
          </View>
          <View style={styles.divider} />
          <View style={styles.customRow}>
            <Text style={styles.customRowLabel}>出发时间</Text>
            <Text style={styles.customRowValue}>9:30:00</Text>
          </View>
          <View style={styles.divider} />
          <View style={styles.customRow}>
            <Text style={styles.customRowLabel}>交通方式</Text>
            <View style={styles.transportContainer}>
              <Image
                source={{ uri: 'https://via.placeholder.com/20' }}
                style={styles.transportIcon}
              />
              <Text style={styles.customRowValue}>高铁</Text>
            </View>
          </View>
        </View>
      ),
    },
    // 更多行程...
  ];

  return (
    <View style={{ flex: 1 }}>
      <RNTripSwiper tripData={tripData} />
    </View>
  );
};

const styles = StyleSheet.create({
  customContent: {
    backgroundColor: '#F5F7FA',
    borderRadius: 8,
    padding: 12,
  },
  customRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingVertical: 10,
  },
  customRowLabel: {
    fontSize: 14,
    color: '#1A2138',
    fontWeight: '500',
  },
  customRowValue: {
    fontSize: 14,
    color: '#1A2138',
    fontWeight: 'bold',
  },
  divider: {
    height: 1,
    backgroundColor: '#E2E8F0',
    width: '100%',
  },
  transportContainer: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  transportIcon: {
    width: 20,
    height: 20,
    marginRight: 8,
  },
});

export default MyComponent;

API 参考

RNTripSwiper Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | tripData | Array | 默认示例数据 | 行程数据数组 | | style | StyleProp | - | 应用于容器的自定义样式 |

TripData 类型

interface TripData {
  title: string;  // 行程卡片标题
  items?: TripItem[];  // 行程内容项数组
  renderContent?: () => React.ReactNode;  // 自定义渲染整个内容区域的函数
}

interface TripItem {
  label: string;  // 内容项的标签
  value: string;  // 内容项的值
  render?: () => React.ReactNode;  // 自定义渲染单个内容项的函数
}

注意事项

  • 组件内部使用了 PanResponder 来处理滑动手势,支持左右滑动切换行程
  • 滑动切换有阈值限制,需要足够的滑动距离才会触发切换
  • 在滑动动画进行中,组件会暂时禁用新的滑动操作,以避免动画冲突
  • 组件设计为只有内容区域轮播,标题和页码保持固定,但页码会随着翻页变化
  • 当提供 items 属性时,将忽略 tripCodeplanedStartTimerouteCode 属性
  • 组件内部的样式可以通过 style 属性进行覆盖
  • 在Android设备上,可能需要额外的配置来确保阴影效果正常显示
  • 当使用自定义渲染函数时,需要自行处理样式和布局
  • 组件默认不处理网络请求,如需动态加载数据,需要在父组件中实现
  • 在低端设备上,大量的动画效果可能会影响性能,建议适当减少动画效果
  • 组件使用了React Hooks,确保您的React版本支持Hooks功能

性能优化建议

  • 避免在渲染函数中创建新的函数或对象,应使用useCallback和useMemo
  • 对于大量数据的场景,考虑使用分页加载
  • 使用PureComponent或React.memo来避免不必要的重新渲染
  • 图片资源应进行适当的压缩和缓存处理
  • 避免在滑动动画过程中执行复杂的计算或渲染操作

许可证

MIT